@sema-agent/server 7.136.0 → 7.138.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 (327) hide show
  1. package/MIGRATION.md +501 -139
  2. package/README.md +1 -0
  3. package/README.zh-CN.md +1 -0
  4. package/USAGE.md +149 -34
  5. package/deploy/sema-up/README.md +14 -0
  6. package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +7 -1
  7. package/deploy/sema-up/stack/sema-stack-cluster.yaml +7 -1
  8. package/dist/approval-card.d.ts +21 -14
  9. package/dist/approval-card.js +1 -0
  10. package/dist/approval-content-kind.d.ts +6 -0
  11. package/dist/approval-content-kind.js +7 -0
  12. package/dist/approval-gate-currency.d.ts +48 -6
  13. package/dist/approval-gate-currency.js +16 -9
  14. package/dist/approval-hmac.d.ts +13 -1
  15. package/dist/approval-hmac.js +1 -1
  16. package/dist/approval.js +3 -3
  17. package/dist/audit.js +1 -0
  18. package/dist/auth-bridge.js +2 -2
  19. package/dist/background-agent-name.d.ts +5 -0
  20. package/dist/background-agent-name.js +5 -0
  21. package/dist/boot/budget-tracing.d.ts +1 -12
  22. package/dist/boot/deployment-mods.d.ts +46 -16
  23. package/dist/boot/deployment-mods.js +82 -6
  24. package/dist/boot/execution-env.d.ts +24 -1
  25. package/dist/boot/execution-env.js +69 -6
  26. package/dist/boot/governance-seams.d.ts +10 -17
  27. package/dist/boot/governance-seams.js +5 -17
  28. package/dist/boot/leader.d.ts +3 -0
  29. package/dist/boot/leader.js +1 -0
  30. package/dist/boot/org-delivery.js +15 -2
  31. package/dist/boot/reapers.d.ts +3 -0
  32. package/dist/boot/reapers.js +15 -1
  33. package/dist/boot/resolve-spec.d.ts +7 -0
  34. package/dist/boot/resolve-spec.js +36 -26
  35. package/dist/boot/retention-lane.d.ts +11 -5
  36. package/dist/boot/retention-lane.js +2 -2
  37. package/dist/boot/runner-deps.d.ts +7 -3
  38. package/dist/boot/runner-deps.js +1 -0
  39. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  40. package/dist/boot/stage-04-stores.d.ts +2 -13
  41. package/dist/boot/stage-05-execution-env.d.ts +6 -13
  42. package/dist/boot/stage-05-execution-env.js +17 -5
  43. package/dist/boot/stage-06-runners.d.ts +6 -13
  44. package/dist/boot/stage-06-runners.js +10 -3
  45. package/dist/boot/stage-07-capability-layer.d.ts +7 -13
  46. package/dist/boot/stage-07-capability-layer.js +3 -3
  47. package/dist/boot/stage-08-reapers.d.ts +7 -13
  48. package/dist/boot/stage-08-reapers.js +2 -1
  49. package/dist/boot/stage-09-leader.d.ts +7 -13
  50. package/dist/boot/stage-09-leader.js +2 -2
  51. package/dist/boot/stage-10-http-server.d.ts +7 -13
  52. package/dist/boot/stage-10-http-server.js +6 -3
  53. package/dist/boot/stores.d.ts +1 -1
  54. package/dist/boot/web-admin.d.ts +5 -2
  55. package/dist/boot/web-admin.js +3 -3
  56. package/dist/brain.js +5 -5
  57. package/dist/broker/broker.d.ts +89 -0
  58. package/dist/broker/broker.js +287 -0
  59. package/dist/broker/constants.d.ts +39 -0
  60. package/dist/broker/constants.js +15 -0
  61. package/dist/broker/http1.d.ts +111 -0
  62. package/dist/broker/http1.js +256 -0
  63. package/dist/broker/lease-book.d.ts +87 -0
  64. package/dist/broker/lease-book.js +142 -0
  65. package/dist/broker/lease-file.d.ts +60 -0
  66. package/dist/broker/lease-file.js +127 -0
  67. package/dist/broker/main.d.ts +2 -0
  68. package/dist/broker/main.js +20 -0
  69. package/dist/budget.d.ts +17 -15
  70. package/dist/budget.js +2 -2
  71. package/dist/capabilities/composite-members.d.ts +2 -1
  72. package/dist/capabilities/composite-members.js +2 -1
  73. package/dist/capabilities/engine-capabilities.js +1 -0
  74. package/dist/capabilities/mcp-probe.d.ts +36 -11
  75. package/dist/capabilities/mcp-probe.js +44 -5
  76. package/dist/capabilities/scenarios.d.ts +23 -8
  77. package/dist/capabilities/scenarios.js +13 -8
  78. package/dist/capabilities/skills.d.ts +28 -5
  79. package/dist/capabilities/skills.js +8 -0
  80. package/dist/capability-facts.d.ts +6 -0
  81. package/dist/capability-facts.js +5 -0
  82. package/dist/center-credential-renewer.js +5 -1
  83. package/dist/checkpoint-ctx-seal-m28.d.ts +3 -10
  84. package/dist/checkpoint-ctx-seal-m28.js +1 -1
  85. package/dist/checkpoint-identity.d.ts +13 -6
  86. package/dist/config-catalog.js +16 -7
  87. package/dist/config-types.d.ts +24 -7
  88. package/dist/config.d.ts +1 -1
  89. package/dist/config.js +42 -13
  90. package/dist/deployment-governance.d.ts +2 -2
  91. package/dist/deployment-governance.js +7 -9
  92. package/dist/deployment-shape.d.ts +6 -6
  93. package/dist/device-ws-protocol.d.ts +1 -0
  94. package/dist/device-ws-protocol.js +2 -1
  95. package/dist/file-history-disclosure.d.ts +4 -2
  96. package/dist/file-history-disclosure.js +2 -0
  97. package/dist/gate-settlement.d.ts +71 -0
  98. package/dist/gate-settlement.js +40 -0
  99. package/dist/hooks/classic-stations.d.ts +12 -54
  100. package/dist/hooks/classic-stations.js +1 -0
  101. package/dist/hooks/command-spawn.d.ts +2 -2
  102. package/dist/hooks/hook-runner.js +14 -14
  103. package/dist/http/admission.js +14 -9
  104. package/dist/http/approval-sweeps.js +4 -3
  105. package/dist/http/caller-trust.d.ts +2 -1
  106. package/dist/http/caller-trust.js +1 -3
  107. package/dist/http/checkpoint-ctx.d.ts +48 -7
  108. package/dist/http/checkpoint-ctx.js +40 -0
  109. package/dist/http/dispatch.d.ts +4 -0
  110. package/dist/http/dispatch.js +18 -10
  111. package/dist/http/durable-run-leg.d.ts +5 -1
  112. package/dist/http/durable-run-leg.js +5 -3
  113. package/dist/http/health-self-report.d.ts +2 -2
  114. package/dist/http/memory-compliance-failure-reply.js +3 -0
  115. package/dist/http/principal-gate.d.ts +15 -10
  116. package/dist/http/principal-gate.js +48 -9
  117. package/dist/http/resume-legs.d.ts +7 -31
  118. package/dist/http/resume-legs.js +185 -126
  119. package/dist/http/route-ctx.d.ts +38 -53
  120. package/dist/http/route-ctx.js +2 -5
  121. package/dist/http/routes/a2a-serve.js +10 -4
  122. package/dist/http/routes/agents-roster.d.ts +1 -1
  123. package/dist/http/routes/agents-roster.js +5 -1
  124. package/dist/http/routes/approvals-assistant.js +24 -10
  125. package/dist/http/routes/capabilities.js +23 -11
  126. package/dist/http/routes/mcp-reconnect.d.ts +3 -2
  127. package/dist/http/routes/mcp-reconnect.js +7 -7
  128. package/dist/http/routes/memory-consolidation.d.ts +1 -1
  129. package/dist/http/routes/memory-origin.d.ts +1 -1
  130. package/dist/http/routes/rules.js +3 -3
  131. package/dist/http/routes/runs.js +13 -8
  132. package/dist/http/routes/session-sync.js +42 -6
  133. package/dist/http/routes/sessions.js +6 -3
  134. package/dist/http/routes/side-query.js +2 -3
  135. package/dist/http/routes/tasks.js +794 -780
  136. package/dist/http/server.d.ts +35 -25
  137. package/dist/http/stored-body-replay.d.ts +3 -3
  138. package/dist/http/stored-body-replay.js +6 -1
  139. package/dist/http/wire-types.d.ts +66 -33
  140. package/dist/identity-source.d.ts +65 -0
  141. package/dist/identity-source.js +45 -0
  142. package/dist/index.d.ts +2 -0
  143. package/dist/index.js +1 -0
  144. package/dist/leader/wire.d.ts +7 -0
  145. package/dist/leader/wire.js +5 -4
  146. package/dist/mcp-assertion-header.d.ts +51 -40
  147. package/dist/mcp-assertion-header.js +10 -11
  148. package/dist/mcp-authorization-face.d.ts +27 -0
  149. package/dist/mcp-authorization-face.js +15 -0
  150. package/dist/memory-operator-faces.d.ts +13 -4
  151. package/dist/memory-operator-faces.js +1 -17
  152. package/dist/memory-store-refusal.d.ts +3 -3
  153. package/dist/memory-sync-client.js +72 -57
  154. package/dist/memory-sync.d.ts +1 -1
  155. package/dist/model-entry-refusal.d.ts +2 -0
  156. package/dist/model-entry-refusal.js +11 -0
  157. package/dist/model-route-gap.d.ts +6 -22
  158. package/dist/model-route-gap.js +7 -5
  159. package/dist/model-select.d.ts +6 -17
  160. package/dist/model-select.js +0 -3
  161. package/dist/mods-declaration.d.ts +110 -0
  162. package/dist/mods-declaration.js +109 -0
  163. package/dist/namespaced-rule-name.d.ts +1 -1
  164. package/dist/observability/err-text.d.ts +5 -0
  165. package/dist/observability/err-text.js +9 -0
  166. package/dist/observability/fail-open.d.ts +17 -1
  167. package/dist/observability/fail-open.js +17 -1
  168. package/dist/observability/metrics.js +1 -1
  169. package/dist/observability/run-terminal.js +1 -0
  170. package/dist/observability/secret-env-scrub.d.ts +1 -1
  171. package/dist/observability/secret-env-scrub.js +1 -1
  172. package/dist/operator-ask.d.ts +2 -2
  173. package/dist/org-delivery-gate.js +1 -1
  174. package/dist/org-memory-admission.d.ts +2 -2
  175. package/dist/org-memory-admission.js +39 -2
  176. package/dist/parked-decide.d.ts +15 -2
  177. package/dist/parked-decide.js +17 -10
  178. package/dist/peer-directory.js +2 -0
  179. package/dist/peer-seat.d.ts +150 -0
  180. package/dist/peer-seat.js +239 -0
  181. package/dist/permission-rule-list.d.ts +2 -2
  182. package/dist/permission-rule-vocab.d.ts +7 -7
  183. package/dist/permission-rule-vocab.js +3 -3
  184. package/dist/plain-string-record.d.ts +38 -0
  185. package/dist/plain-string-record.js +38 -0
  186. package/dist/plugins/background-agent-store-sql.js +6 -3
  187. package/dist/plugins/caching-session-store.d.ts +5 -0
  188. package/dist/plugins/caching-session-store.js +6 -0
  189. package/dist/plugins/checkpoint-store-sql.d.ts +34 -29
  190. package/dist/plugins/checkpoint-store-sql.js +14 -14
  191. package/dist/plugins/file-history-store-sql.js +10 -16
  192. package/dist/plugins/file-run-store.js +8 -2
  193. package/dist/plugins/k8s-exec-protocol.d.ts +69 -13
  194. package/dist/plugins/k8s-exec-protocol.js +116 -28
  195. package/dist/plugins/k8s-pod-delete-failure.d.ts +25 -0
  196. package/dist/plugins/k8s-pod-delete-failure.js +17 -0
  197. package/dist/plugins/k8s-pod-reaper.d.ts +106 -0
  198. package/dist/plugins/k8s-pod-reaper.js +122 -0
  199. package/dist/plugins/local-checkpoint-store.d.ts +4 -17
  200. package/dist/plugins/local-checkpoint-store.js +3 -4
  201. package/dist/plugins/local-session-store.d.ts +66 -27
  202. package/dist/plugins/local-session-store.js +60 -28
  203. package/dist/plugins/mailbox-store-sql.d.ts +11 -3
  204. package/dist/plugins/mailbox-store-sql.js +103 -15
  205. package/dist/plugins/memory-run-store.js +2 -0
  206. package/dist/plugins/memory-sync-store-pg.d.ts +16 -5
  207. package/dist/plugins/memory-sync-store-tidb.d.ts +3 -3
  208. package/dist/plugins/one-time-migrations.d.ts +34 -12
  209. package/dist/plugins/one-time-migrations.js +51 -9
  210. package/dist/plugins/permission-rule-store-file.js +2 -2
  211. package/dist/plugins/permission-rule-store-sql.d.ts +17 -17
  212. package/dist/plugins/permission-rule-store-sql.js +37 -30
  213. package/dist/plugins/pg-pool.js +4 -0
  214. package/dist/plugins/pg-session-storage.d.ts +10 -2
  215. package/dist/plugins/pg-session-storage.js +20 -7
  216. package/dist/plugins/remote-env-adb.d.ts +6 -1
  217. package/dist/plugins/remote-env-adb.js +2 -1
  218. package/dist/plugins/remote-env-device.d.ts +6 -1
  219. package/dist/plugins/remote-env-device.js +5 -1
  220. package/dist/plugins/remote-env-e2b.d.ts +5 -0
  221. package/dist/plugins/remote-env-e2b.js +2 -1
  222. package/dist/plugins/remote-env-file-error.d.ts +8 -1
  223. package/dist/plugins/remote-env-file-error.js +7 -1
  224. package/dist/plugins/remote-env-host.d.ts +10 -2
  225. package/dist/plugins/remote-env-host.js +8 -2
  226. package/dist/plugins/remote-env-k8s.d.ts +140 -11
  227. package/dist/plugins/remote-env-k8s.js +277 -15
  228. package/dist/plugins/remote-env-local-docker.d.ts +5 -0
  229. package/dist/plugins/remote-env-local-docker.js +2 -1
  230. package/dist/plugins/remote-env-ssh.d.ts +6 -1
  231. package/dist/plugins/remote-env-ssh.js +2 -1
  232. package/dist/plugins/retention-store-sql.d.ts +14 -2
  233. package/dist/plugins/retention-store-sql.js +6 -0
  234. package/dist/plugins/run-store-sql.js +10 -4
  235. package/dist/plugins/session-fork.d.ts +10 -13
  236. package/dist/plugins/session-fork.js +5 -25
  237. package/dist/plugins/session-ownership.d.ts +24 -3
  238. package/dist/plugins/session-ownership.js +24 -5
  239. package/dist/plugins/session-workspace-cell.d.ts +17 -0
  240. package/dist/plugins/session-workspace-cell.js +38 -0
  241. package/dist/plugins/sql-errors.d.ts +23 -2
  242. package/dist/plugins/sql-errors.js +15 -0
  243. package/dist/plugins/store-backend.js +7 -7
  244. package/dist/plugins/store-contracts.d.ts +10 -1
  245. package/dist/plugins/store-fault.d.ts +2 -2
  246. package/dist/plugins/store-fault.js +4 -2
  247. package/dist/plugins/tidb-pool.js +13 -0
  248. package/dist/plugins/tidb-session-store.d.ts +17 -2
  249. package/dist/plugins/tidb-session-store.js +18 -7
  250. package/dist/plugins/tool-result-store-sql.d.ts +13 -6
  251. package/dist/plugins/tool-result-store-sql.js +8 -7
  252. package/dist/plugins/worktree-isolation.d.ts +3 -2
  253. package/dist/plugins/worktree-isolation.js +1 -7
  254. package/dist/project-identity.d.ts +1 -14
  255. package/dist/project-identity.js +0 -4
  256. package/dist/request-key-closure.js +1 -1
  257. package/dist/request-value-closure.d.ts +31 -2
  258. package/dist/request-value-closure.js +7 -1
  259. package/dist/rule-entry-list.d.ts +3 -2
  260. package/dist/rule-entry-list.js +2 -2
  261. package/dist/rules-consent.js +12 -7
  262. package/dist/run-local.d.ts +2 -2
  263. package/dist/run-local.js +12 -6
  264. package/dist/runs.d.ts +7 -1
  265. package/dist/runs.js +8 -2
  266. package/dist/runtime-governance.d.ts +5 -5
  267. package/dist/sandbox-git-lease.d.ts +49 -0
  268. package/dist/sandbox-git-lease.js +60 -0
  269. package/dist/sandbox-git-plane.d.ts +84 -0
  270. package/dist/sandbox-git-plane.js +105 -0
  271. package/dist/security.d.ts +16 -4
  272. package/dist/security.js +8 -3
  273. package/dist/server-secret-env.d.ts +12 -3
  274. package/dist/server-secret-env.js +18 -2
  275. package/dist/session-error-wire.d.ts +14 -6
  276. package/dist/session-error-wire.js +2 -1
  277. package/dist/session-incarnation.d.ts +4 -5
  278. package/dist/session-incarnation.js +2 -2
  279. package/dist/session-policy-wire.d.ts +1 -1
  280. package/dist/session-policy-wire.js +2 -2
  281. package/dist/session-sync.d.ts +1 -1
  282. package/dist/session-workspace.d.ts +130 -0
  283. package/dist/session-workspace.js +83 -0
  284. package/dist/spec-fields.d.ts +44 -14
  285. package/dist/spec-fields.js +33 -12
  286. package/dist/standing-answer-grant.d.ts +2 -13
  287. package/dist/standing-answer-grant.js +0 -7
  288. package/dist/stored-request-prompt-profile-m30.d.ts +49 -0
  289. package/dist/stored-request-prompt-profile-m30.js +25 -0
  290. package/dist/task-a2a.d.ts +44 -14
  291. package/dist/task-a2a.js +46 -20
  292. package/dist/task-mcp.d.ts +34 -21
  293. package/dist/task-mcp.js +46 -22
  294. package/dist/task-settings.d.ts +2 -2
  295. package/dist/tool-approval.d.ts +43 -9
  296. package/dist/tool-approval.js +57 -15
  297. package/dist/tool-rule-names.d.ts +5 -0
  298. package/dist/trace/core-keyset-guard.d.ts +34 -19
  299. package/dist/trace/engine-notice-wire.d.ts +1 -1
  300. package/dist/trace/engine-notice-wire.js +4 -0
  301. package/dist/trace/exit-seat.d.ts +20 -1
  302. package/dist/trace/exit-seat.js +5 -2
  303. package/dist/trace/extension-call-face.d.ts +33 -0
  304. package/dist/trace/extension-call-face.js +39 -0
  305. package/dist/trace/ledger-sink.d.ts +4 -5
  306. package/dist/trace/ledger-sink.js +3 -7
  307. package/dist/trace/project.d.ts +62 -10
  308. package/dist/trace/project.js +49 -9
  309. package/dist/trace/redact.d.ts +18 -6
  310. package/dist/trace/redact.js +154 -60
  311. package/dist/trace/self-minted-wire.d.ts +500 -7
  312. package/dist/trace/self-minted-wire.js +182 -1
  313. package/dist/trace/wire-projection-faces.d.ts +7 -5
  314. package/dist/trace/wire-projection-faces.js +9 -4
  315. package/dist/user-authored-text.d.ts +2 -2
  316. package/dist/user-authored-text.js +16 -1
  317. package/dist/web-admin-client/apply-effective.js +0 -1
  318. package/dist/web-admin-client/center-request.d.ts +23 -4
  319. package/dist/web-admin-client/center-request.js +42 -8
  320. package/dist/web-admin-client/http-client.js +6 -6
  321. package/dist/web-admin-client/skills-mcp.d.ts +8 -4
  322. package/dist/web-admin-client/skills-mcp.js +31 -18
  323. package/dist/web-admin-client/types.d.ts +10 -5
  324. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +11 -5
  325. package/package.json +3 -3
  326. package/wire-changes/server@7.137.0.json +825 -0
  327. package/wire-changes/server@7.138.0.json +446 -0
package/MIGRATION.md CHANGED
@@ -7,6 +7,368 @@
7
7
  > ⚠️ 完整清单在仓库根 `CHANGELOG.md`——它**不随 npm tarball 出包**(本文件随包)。看完整迁移窗的
8
8
  > 权威姿势是源码 tag diff:`git diff v<旧>..v<新>`(每版都推 `v<版本>` tag);npm 包页也镜像 CHANGELOG。
9
9
 
10
+ ## 7.138.0 —— MCP / A2A 的凭据件改由部署的对端座在发送时作答(行为面;件的形更严;嵌入方 `ServiceCoreDeps.peerDesk` 必填,BREAKING)· 🔴 SQL 后端 `session_meta` 加 `workspace` 列、`mailbox_message` 加 `record_id` 列(升级前先加列)· 请求 `projectId` 与检出记号不等 ⇒ 409 · 记忆同步:升级前写的旧游标 ⇒ 该层停同步直到运维一步(两条出路)· settings hook 子环境维持十二名边界 · 抹除授权集与收执 v2 · 已知缺口:会话级子代在父腿作用域结束后首拨 / 再问被座拒 · 引擎 7.59.0
11
+
12
+ 1. **SQL 后端:`mailbox_message` 表加一列 `decision`(🔴 升级前先加列;持久数据,不能删表重建;引擎 7.57.0 的邮箱留置决定)**:
13
+ 收件人设置把一条消息留置(held)之后,对它的决定(放行 / 拒绝 / 过期 / 已投递……)从本版起是这条记录自己的字段,每个读这只箱的进程读同一个决定;
14
+ 本服务不发 `ALTER`:存量库缺这一列 ⇒ 起服列册对账拒启(`config.schema_mismatch`),拒句带可直接粘贴执行的语句。
15
+ **升级前做**(MySQL 协议):`ALTER TABLE mailbox_message ADD COLUMN decision VARCHAR(16) NULL;`
16
+ (PostgreSQL)`ALTER TABLE mailbox_message ADD COLUMN decision VARCHAR(16) COLLATE "C";`
17
+ 存量行这一列是 NULL = 从未留置,零回填。**顺序**:先升库(加列)、再升副本 —— 加完列之后,仍是 7.137.x 的副本**再启动**会把 `decision` 读成幽灵列而拒启
18
+ (`config.schema_mismatch`,拒句点名 `UNKNOWN column(s) decision`、不给 ALTER;列册对账缺列多列两个方向都拒)—— 只挡重启:已在跑的旧副本写消息时带列名清单、不写这一列。
19
+ 滚动窗里仍在跑的 7.137.x 副本不读这一列,会照旧投递别的副本已留置或已拒绝的记录 —— 不想要这个窗就先停光旧副本再起本版。**回滚**:先停光本版副本,`ALTER TABLE mailbox_message DROP COLUMN decision;`(两方言同一句),再起 7.137.x;丢掉的是留置决定(还在箱里的留置记录回到「从未决定」,下一次读箱重新判)。
20
+ `DB_BACKEND=local` 与内存后端零动作(引擎自带的文件箱)。**嵌入方**经 `RunnerDeps.principalInboxConsumer` 声明 `"terminals"`(这个 scope 的终端会话在自己的箱旁边一起读 principal 收件箱)之前,
21
+ 先把每一个读这只箱的副本 / 终端都升到本版 —— 更早的引擎读不到决定、可能投递已被拒的信。运维旋钮 `PRINCIPAL_INBOX_ASSISTANT` 只声明 `{ assistant }` 一形,不变。
22
+
23
+ 2. **引擎 7.57.0 的部署序:先升读者与续跑者,再升写者与停驻者(两处)**:
24
+ ① **停驻的 shell 审批行多一个成员 `targetReads`**(停驻时 shell 读站判出的读落点;续跑时读落到别处 ⇒ 这次调用被否决 `resume.target_moved`,模型重发会拿到新卡):
25
+ 7.137.x 及更早的副本遇到这种行拒 `version_newer`、行留 pending(不会不绑定地重放)—— 混跑的舰队里 shell 停驻行要等升过的副本来接。SQL 店把 `pendingAction` 整只存成 JSON,零迁移。
26
+ ② **会话规则 / 持久规则桶的文法戳 6**(裸工具名 `Tool` / `Tool()` / `Tool(*)` 成为整工具规则):7.137.x 及更早的引擎读不了戳 6 的桶 / 行 —— 整只拒,那位的规则读成「读不出」、
27
+ 按 fail-closed 多问 / 多拒,不会少问,直到升级。回滚前确认没有写过戳 6 的行,或接受回滚窗内这种 fail-closed。
28
+
29
+ 3. **本机宿主车道(`REMOTE_EXEC=host`)上,选中本服务或其上层进程的模式杀被 Bash 工具拒(行为变更;安全收紧)**:
30
+ `pkill -f <词>`(词出现在本服务或其祖先的命令行里)、`killall <名>`、`kill $(pgrep …)` 这类按模式选进程的命令,本版起在这条车道上照本进程的进程表问一遍,选中本服务自己或其上层进程 ⇒ 不跑、
31
+ 工具结果是带句子的错误(此前在这条车道上不问,会结束发起它的会话)。`pkill -P $$`(只杀本 shell 的子进程)与按字面 pid 杀照常。容器 / k8s / e2b / ssh / 设备 / adb 车道不变(命令跑在别的进程表,不问)。
32
+ ssh 车道的目标恰是本机(或本服务所在容器的宿主)的部署,这一问今天不覆盖 —— 那种车道不要拿 `pkill -f` 清理与本服务同名的进程。
33
+
34
+ 4. **未起名的后台子代停驻的审批可决(行为变更;wire 句子退出)**:Agent 调用省略可选 `name` 的后台子代停驻之后,`POST /v1/approvals/:sessionId/decide` 的 approve 照常复活它、动作执行,
35
+ deny 照常复活它、子代收到拒绝(此前 approve 答 `409 decide.row_unrevivable` 的「parked row carries no agent name …」、deny 作废这张卡)。这句拒退出 wire;
36
+ `409 decide.row_unrevivable` 只剩「行上没有根会话锚」一句(出路照旧:deny 作废)。升级前停驻的无名行同样可决(读作引擎派生名 `agent-<12 位十六进制>`)。
37
+ 名册 `GET /v1/agents/roster` 的行从本版起恒带 `name`(未起名的子代是派生名,此前键缺席),未起名的行另带 `anonymous: true`(`name` 就是引擎派生名时在场,起过名的行缺席这一键;调用方恰好起了与派生名同一个串的,引擎读不出区别,同样在场)—— 据此区分「起的名 / 派生名」,不必自算派生式。
38
+ **滚动窗的反方向 —— 决卡面先升**:本版写下的未起名子代行带着派生名;仍是 7.137.x 的副本决这样一张停驻卡,会把它复活成一只**具名**子代(名字就是那个派生名,
39
+ 以具名子代的身份出现),本版副本决同一张卡,复活的子代仍是匿名的。要避开:先把接 `POST /v1/approvals/:sessionId/decide` 的副本全部升到本版,再让本版副本接会停驻后台子代的任务;
40
+ 或接受滚动窗里少数复活的子代带着派生名。
41
+
42
+ 5. **文件历史导入:来源给出的字节对不上它的地址 ⇒ `adopt_failed`(wire 码变更)**:会话同步重放把店的答原样上 wire;这一臂此前答 `422 unsupported_format`,本版起 `422 adopt_failed`
43
+ (`unsupported_format` 只留给导入门对信封本身的拒)。来源读抛的那一臂多带判得出的 `permanence`。按 `unsupported_format` 判「信封坏、别重试」的调用方零改;按码分支重试的,把这一臂当作来源问题。
44
+
45
+ 6. **无规则文法的工具的审批卡给「这只工具不再问」(行为变更;wire 值加性)**:本服务自带的宿主工具(`Now` / `SendUserFile` / `SelectEnvironment` / `repo_*` 等)与 MCP 工具的问卡,
46
+ `ruleOffers` 多一只整工具候选 `{ kind: "single", rule: "<工具名>", match: "tool", command: "" }`,选中即落一条整工具规则(这只工具的每一次调用)。壳按 `match: "tool"` 渲染「不再询问这只工具」;
47
+ 不认得 `tool` 这个匹配词的壳不渲这一只即可(读者对集外词丢该候选)。卡的编辑面不铸整工具规则。
48
+
49
+ 7. **嵌入方(类型面,BREAKING;引擎 7.57.0)**:手写 `CheckpointStore` 必须实现 `reopen`(缺它的店在店席被拒),删掉 `redecision`;根导出 `checkpointStoreExecutionUndeclared` 改名 `checkpointStoreIncomplete`
50
+ (全齐答 `undefined`);手写 `BackgroundAgentStore` 的记录 / 摘要 `name` 必填(旧行读作 `row.name ?? engineAgentName(row.handle)`);手写 `MailboxStore` 必须实现 `moveDecision`;
51
+ 手写远端执行适配器的 `capabilities` 必须声明 `sharesProcessTable`(命令跑在本进程的进程表上 ⇒ `true`)。只读这些型的代码零动作。
52
+
53
+ 8. **回决门族的 200 体多两个可选键 `decisionCommitted` / `checkpointId`(wire additive;另收紧一处停驻子代的竞态)**:`POST /v1/approvals/:id/decide`(受理 / 终局 / 幂等回放 /
54
+ 停驻子代复活成功 / 复活不了的停驻子代被 deny 作废)、`POST /v1/assistant/tasks/:id/resume`、`POST /v1/assistant/tasks/:id/plan_review` 的 200 体,在「这道门已以
55
+ 这次决定结清过」能被证明时带 `decisionCommitted: true`,并带执行之前选中那一行的门身份 `checkpointId`(与运维队列 / 收件行 / park 账本行同名同值;读不出就缺席)。
56
+ `POST /v1/sessions/:id/wake` 与 `/decide` 交给宿主的回执(workflow 子代的审批)不带。**读法**:「已提交」只读 `decisionCommitted === true`,缺席按「没提交」读;
57
+ 它与 `errorCode:"cancelled"`、`retriable:true` 并存时照样成立,不说明卡的当前状态;`retriable:true` 只说「这一跑已重新停驻,请重读待决列表」。
58
+ 经 `POST /v1/tool-approvals/:id/respond` 迟到兑现的停驻卡:同向重试的回放带两键,反向重试的回放(回放首次那一向)不带。
59
+ **竞态收紧**:决一张后台子代的停驻卡时,若这只子代在你决断的同一刻被别处续过、又在新的卡上停驻,本版答 `409 decide.gate_moved`(此前把决定交给了那张新卡)
60
+ —— 重拉待决列表、对新卡再决。
61
+ **升级前做**:用封闭 schema 校验这些 200 体的调用方(多余键即拒)把两键加进可选键;其余零动作。**升级后看**:选中那一行的门身份读不出时,既有计数
62
+ `server.approvals.durable-row-checkpoint-id-missing` 多一种 detail `face=decision-receipt`(老行 / 坏行在被决断;体照常,只是不带身份)。
63
+
64
+ 9. **令牌声明 `sub_inc`(化身号)在场而畸形 ⇒ 整张中心登录令牌验证不过(行为面;契约包 settings-schema 14.7.0 的令牌判官新读这个声明)**:
65
+ 此前令牌里的 `sub_inc` 被忽略;现在它**在场**时必须是非空字符串 —— 数字(含 0)/ 空串 / `null` / 布尔 / 对象 / 数组 ⇒ 这张令牌按 `malformed` 拒(401 通用体不变;
66
+ 计数 `auth_bridge_verify_total{outcome="malformed"}` 加一、一行 `auth_bridge_rejected{error:"malformed"}`;`malformed` 是这条验证腿既有的通用拒因,不专指 `sub_inc`),与 `sub` / `iat` 畸形同律(声明形是垃圾不降级成「缺席」)。
67
+ 合形的(非空串)随验证出的身份带出 `principalInc` 原样,本版**没有读者**;不带 `sub_inc` 的令牌读数与升级前逐字相同。
68
+ **升级前做**:零动作 —— 已知没有铸畸形 `sub_inc` 的签发方,存量令牌不带该声明。**顺序**:签发方(web-admin)开始铸 `sub_inc` 的时点与本服务升级先后无关:旧版忽略该声明,本版对合形的原样带出、对畸形的拒。
69
+ **升级后看**:上面的 `malformed` 计数与拒行只在签发方铸了畸形 `sub_inc` 时因它增长(其它畸形令牌也走这一因,要确认是不是 `sub_inc`,看签发方铸出的令牌声明);**补偿**:签发方把 `sub_inc` 改成非空串或不铸。**回滚**:回到上一版即回到「忽略该声明」。
70
+
71
+ 10. **`POST /v1/runs/:id/steer` 不带 `Idempotency-Key` 的停放腿:条目的 `inputId` 变成 202 回执上的 `messageId`(wire 值变更;键集 / 状态码 / 回执体逐字不变)**:
72
+ `202 delivery:"queued"`(run 停在检查点上)与 `202 delivery:"parked_for_wake"`(终态 run 铸唤醒卡)两条停放腿,不带 key 时,条目上的 `inputId` 此前是引擎在把条目写进停放队列时自铸的 uuidv7,
73
+ 续跑(或 wake)首轮引擎铸的 `human_input{delivery:"applied"}` 帧带的就是那一个(部署的 `userPromptSubmit` 屏拦下它时,`human_input{delivery:"blocked"}` 帧与 `steering.parked_input_blocked` 通告带的也是它)—— 与回执上的 `messageId` 不是同一个值,按回执找不到那些帧。本版起停放两腿与 live 腿(`200 applied`,早已如此)同形:
74
+ **回执 `messageId` ≡ 引擎收到的 `inputId`**,不带 key 时是本服务对每个请求现铸的 uuidv7,带 key 时是由 key 派生的确定性值(带 key 的形不变)。
75
+ **谁需要**:按回执 `messageId` 去对 `human_input{delivery:"applied"}` 帧(或被拦时的 `blocked` 帧 / `steering.parked_input_blocked` 通告)的消费方(壳 / cli / sdk 的回执账);**谁受伤**:无 —— 每请求现铸的值互不相同,不会撞引擎的 `inputId` 去重,停放队列的容量与顺序不变;**补偿**:不适用。
76
+ **升级前做**:零动作。**升级后看**:升级前已停放、升级后才续跑的条目带的仍是引擎当时自铸的值(不改写),那一批的回执对不上 applied 帧 —— 按「消费与否关账时再定」读。**回滚**:回到上一版即回到引擎自铸值。
77
+
78
+ 11. **部署座可装运维声明的 mod 包:新旋钮 `MODS_ROOT` / `MODS_PACKAGES`(没声明的部署零动作;起服拒句换形)**:部署座(每一只 Runner 共用的那一份扩展注册)在本服务自铸的注册之后,
79
+ 装 `MODS_PACKAGES` 声明的包(JSON 数组,每项 `{ name, dir, tier, options? }`;`dir` 的真实路径须严格在 `MODS_ROOT` 的真实路径之下 —— 根本身不算,`tier` 宿主必填)。包里的文件只有引擎的读包者读;
80
+ 起服整张声明先判完、再逐只装、再整列交引擎准入,任一失败即拒启,拒句一行 `deployment mods refused: <词>(<主语>)[: <细节>]`(词表与读法见契约 §0.9)。
81
+ **不声明的部署**:零动作 —— 部署座与此前同三张,`/health` 与 `/v1/capabilities` 逐字节不变(配置目录多这两根旋钮的两行)。开了 leader 的部署:leader 车道派出的腿(路由 / worker / 修复)
82
+ 此后也挂部署座 —— 拒绝计量计入这些腿上的拒绝(拒绝计数的看板会多出 leader 腿的那一份);`TOOL_TRACE=true` 时它们的工具调用也写追踪行、系统提示多出引擎的钩子段
83
+ (与主车道同配置的腿同读;此前这条车道漏挂)。
84
+ **要装包的部署**:① 把包放进只读物料树(镜像层 / 只读挂载),`MODS_ROOT` 指它;② 包是**受信的部署代码**,在本进程里跑、可触全部租户与进程凭据 —— 多租户部署上声明的包对全体租户生效,
85
+ 准入不是沙箱,只装你审过的包;③ 包按「自包含」构建(执行代码全在 `hooks/register.mjs`,不另 import 包内文件、不读运行时资源),`register` 确定、可重复、不留进程副作用(引擎在每条腿再调它);
86
+ ④ 改声明或换包要重启(配置刷新不重载,也没有自动重启信号);滚动升级期间新旧副本可以并存 —— 声明只在设了它的新副本上生效,停驻的任务在哪只副本续跑就按那只副本当下的部署座再准入。
87
+ **升级后看**:起服日志每包一行 `mods_package_loaded { name, tier, contract, digest }`(`digest` 是引擎读包者读的三件文件的字节摘要,认得出装的是哪几份字节,不是代码完整性凭据);`/health.mods.deploymentPackages` 与能力位 `modsDeploymentPackages`;每条腿 `wiring_manifest.mods[]` 有那只包一行(`seat: "deployment"`、`provenance: "operator"`;本服务自铸的注册那几行带 `provenance: "server"`)。
88
+ **起服拒句换形(运维面,非 wire)**:部署座准入被拒此前是 `deployment extension registration refused: <引擎句>`,现在是 `deployment mods refused: admission_refused[(<引擎码>)]: <引擎句>` ——
89
+ 按旧句匹配起服失败的告警改读新前缀。回滚:删掉两根旋钮(或回到上一版)即回到只有自铸注册的部署座。
90
+
91
+ 12. **`tool_start` / `tool_end` 与审批开卡帧多可选键 `requestedBy` / `answeredBy`(wire additive;零动作)**:扩展经 `$.tool.call` 自己发起的调用,`tool_start` / `tool_end` 与开卡帧
92
+ (旧族 `tool_approval`、呈卡族 `approval_request` 顶层)带 `requestedBy: { kind: "extension", name }`;扩展在 `tool.call` 站上代替工具体作答的调用,`tool_end` 带 `answeredBy: <注册名>`(旁边恒有 `notExecuted: true`)。
93
+ 只在部署座装了能这样做的包时出现;其余帧逐字节不变。按闭集读帧键的消费方:未知键忽略(开集律),要渲染归因的读这两位(契约 §4.0b)。
94
+
95
+ 13. **SQL 后端:三只会话 / 检查点 / 工具结果店的留存声明随扫车道走(扫车道关着的部署不再被引擎拒启;锁着留存策略的那一形拒句换形)**:引擎这一版起,店说自己的行由托管留存按期删(`managed`)而部署不跑执行器 ⇒ 起服拒(锁不锁都拒)。
96
+ 本服务据此把声明改成部署的事实:`RETENTION_SWEEP_INTERVAL_SEC > 0`(扫车道开)⇒ 三只 SQL 店声明 `managed`、执行器交给引擎;关着(缺省)⇒ 声明 `none`、执行器 `null`。
97
+ **扫车道开着的部署**:零动作。**关着、没配留存策略的部署**:零动作(此前也不删;不升级到这一版的同一套店在新引擎上会被拒启,本版正是为此)。
98
+ **关着、配了没锁的策略**:照起;起服 warn `retention_policy_not_executed` 的说明句换成点名扫车道关着。**关着、策略被锁**:照旧拒启,拒句换成引擎的 `config.retention_capability` 句(此前是本服务的「WIRES NO RETENTION EXECUTOR」句)——
99
+ 按旧句匹配告警的改读码;要能起服就开扫车道或解锁 / 删策略。**回滚**:回到上一版即回到旧声明(店恒声明 `managed`)。
100
+
101
+ 14. **wire 加性四处(零动作)**:每条腿 `wiring_manifest.mods[]` 每行多 `provenance`(本服务自铸的注册 `"server"`,每个部署至少拒绝计量那一行;运维声明的包 `"operator"` —— 出处词与同一行上 `seat` 的座词 `deployment` / `task` 不共用词)· `tool_end` 多可选 `rewrite: { by, input }`(门放行时交给工具体的参数被改过才在场;
102
+ `input` 是放行的那份参数、与 `tool_start.args` 同一只脱敏,`by` 每项是 `{ kind: "extension", name }` / `{ kind: "policy" }` / `{ kind: "approver" }`)· 请求面 MCP 条目受理 `sessionMetaKey`(声明了它的服务器在每次 `tools/call` 的 `_meta` 下收这条腿的会话 id;
103
+ 写坏 ⇒ `400 request.field_invalid`)· 名册 `GET /v1/agents/roster` 行的可选键 `anonymous`(`name` 是引擎派生名才在场,恒为 `true`)。按闭集读键的消费方:未知键忽略(开集律)。部署侧在中心 / `config.d` 写的 `sessionMetaKey`,在契约包补这把键之前于读配置那一道被剥(带未知键告警)。
104
+
105
+ 15. **`workspace_changed` 帧的节律随引擎变了(成员不变)**:引擎在每条腿准备好之后、第一次模型 / 工具交互之前先发一帧,其后每变一帧 —— 同一个 `cwd` 可能连着来两帧。本服务只投 `cwd`(与上一版同形)。
106
+ 把每一帧都当作「目录搬了」来渲染的消费方:按帧替换本地副本,只在 `cwd` 与持有值不同时渲染搬迁。
107
+
108
+ 16. **SQL 后端:`session_meta` 表加一列 `workspace`(🔴 升级前先加列;持久数据,不能删表重建;会话的位置与项目)**:
109
+ 这一格存这只会话上一条腿自己的最后一帧 `workspace_changed`(`cwd` / `root` / `entered` / `project` / `remote`),下一条不带 `projectId` 的提交把它的 `project.id` 声明给引擎 —— 只当那是调用方声明过的项目(`project.source` 为 `declared`;见下一条)。
110
+ 持流的腿(同步 / 活流 / 后台 / 续跑)记;只回结果的腿(`verify` / `cascade`)不记(引擎在组合入口里自己排空内层腿的流,宿主看不到这一帧)。
111
+ 本服务不发 `ALTER`:存量库缺这一列 ⇒ 起服列册对账拒启(`config.schema_mismatch`),拒句带可直接粘贴执行的语句。
112
+ **升级前做**(MySQL 协议):`ALTER TABLE session_meta ADD COLUMN workspace JSON NULL;`
113
+ (PostgreSQL)`ALTER TABLE session_meta ADD COLUMN workspace JSONB;`
114
+ 存量行这一列是 NULL = 没有记录,零回填(下一条腿记下)。**顺序**:先升库(加列)、再升副本 —— 加完列之后仍是 7.137.x 的副本**再启动**会把 `workspace` 读成幽灵列而拒启
115
+ (只挡重启:已在跑的旧副本建行时带列名清单、不写这一列)。滚动窗里旧副本上跑的腿不记这一格(下一条提交读到的是更早一条腿的记录,或没有记录)。
116
+ **回滚**:先停光升级后的副本,`ALTER TABLE session_meta DROP COLUMN workspace;`(两方言同一句),再起 7.137.x;丢掉的是各会话记下的位置与项目(没有记号的检出里,会话不再续声明它的项目)。
117
+ `DB_BACKEND=local` 零动作(数据根里多一只 `session-workspaces.json`,随会话删除一起删);内存会话店不记(没有行可读,只交提交带的 `projectId`)。
118
+
119
+ 17. **请求 `projectId` 交给引擎:与检出的 `.sema/project` 记号不等 ⇒ 开跑前拒,同步 409(行为面收窄;BREAKING)**:
120
+ 7.137.x 及更早,提交体的 `projectId` 只挑记忆分区(`proj:<租户>/<projectId>`)与项目登记簿的默认读层,引擎从不知道它。升级后它同时是这条腿交给引擎的项目声明:
121
+ 每条腿声明 = 这次提交带的 `projectId`(续跑重放存下的同一个体)?? 这只会话上一条腿声明过的项目(上一条;引擎从记号判出的项目不续声明);都没有不声明。引擎每条腿判一次 ——
122
+ 检出带记号 ⇒ 声明必须等于记号,否则 `config.project_identity_mismatch`(**409**,零工作、不计费);检出没有记号 ⇒ 声明就是身份;声明了而记号读不出 ⇒ `config.memory_project_marker` /
123
+ `config.memory_project_marker_nested`(**409**)。异步 / 活流腿 HTTP 2xx,同码落在终态 run 行。
124
+ **谁撞上**:① 提交带的 `projectId` 与它跑的检出里的记号不是同一个项目;② 同一只会话在没有记号的检出里声明过项目,之后换到带另一个记号的检出、不带 `projectId` 续跑(声明过的项目被续声明);
125
+ ③ 声明了项目(提交带的或会话声明过的)而检出的记号坏了 / 嵌在仓根之下。不带 `projectId` 的部署零变化(检出带不带记号都一样:记号判出的项目不续声明,记号改写 / 换检出之后续跑照跑)。
126
+ **出路**:声明记号里的那个 id(提交带它就胜过会话声明过的)、改或修记号,或换一只会话(新会话没有记录)。记忆分区、登记簿默认读层与单用户记忆的项目层(按 git 检出)不变。
127
+
128
+ 18. **SQL 后端:`mailbox_message` 表加一列 `record_id`(🔴 升级前先加列;持久数据,不能删表重建;邮箱记录的身份)**:
129
+ 引擎这一版起邮箱记录带生产者铸的身份,店在写锁之内判:同一身份同一条记录 ⇒ 答原来的序号、什么都不写;同一身份不同记录 ⇒ 拒。停驻座写失败时会用同一条记录再问一次,
130
+ 没有这一列的店会把那一问写成第二条记录(同一条消息被读两遍)。本服务不发 `ALTER`:存量库缺这一列 ⇒ 起服列册对账拒启(`config.schema_mismatch`),拒句带可直接粘贴执行的语句。
131
+ **升级前做**(MySQL 协议):`ALTER TABLE mailbox_message ADD COLUMN record_id VARCHAR(1024) NULL;`
132
+ (PostgreSQL)`ALTER TABLE mailbox_message ADD COLUMN record_id VARCHAR(1024) COLLATE "C";`
133
+ 存量行这一列是 NULL = 没说身份(照旧按序号读),零回填。**顺序**:先升库、再升副本(加完列后仍是 7.137.x 的副本再启动会把它读成幽灵列而拒启;已在跑的旧副本不写这一列)。
134
+ **回滚**:先停光升级后的副本,`ALTER TABLE mailbox_message DROP COLUMN record_id;`(两方言同一句),再起旧版。`DB_BACKEND=local` 零动作。
135
+
136
+ 19. **跨升级的在飞件(引擎 7.59.0;行为收窄)**:
137
+ ① **后台子代**:升级前生下的后台子代,行上没有「出生时的限制」(`policyFloor`)⇒ 新引擎跨进程复活它时拒 `revive.policy_floor_unreadable`(SendMessage 回执与 Agent 未起结果的 `details.error`;行不动、不计费)。
138
+ 出路:让它在旧版副本上跑完,或新起一只子代。升级后生下的子代都带这一员(没有任何限制时是空对象)。
139
+ ② **待决的工具审批**:升级前停驻、还没决的工具审批行不带工具声明的摘要 ⇒ 放行它在认领之前被拒(`checkpoint.unsupported_version`,`detail.reason: "tool_identity_missing"`,行仍待决)。
140
+ 三条出路:**拒掉**(模型重发那一次调用,新卡照常问)· 在停驻它的那一版副本上决 · 让它过期。拒不受影响(7.5.x 之前停驻的行连拒也拒,与上一版同)。
141
+ 反方向:旧版副本读到本版写下的审批行 ⇒ 拒 `version_newer`(认领前、可在新副本上重试)—— 滚动升级期间先把会决卡的副本升完。
142
+ ③ **记忆同步游标**:升级前落盘的游标没有本地店绑定(`store`)⇒ 那一层升级后**不同步**(零请求;每轮一条 warn `memory_sync_cursor_predates_store` 点名那只文件与两条出路,该层按失败层报 `memory_sync_layer_failed`,
143
+ 别层照跑),直到运维处置那只文件;本版不以空基线替它跑(空基线会把上一轮之后在一侧删掉的条目从另一侧拉回来,且不报冲突)。文件 = 每层一只 `sync-cursors/<peer>/<scope 摘要>.json`;
144
+ 同步层的新路径上没有文件时,只按 peer 分区的旧文件 `sync-cursor-<peer>.json` 是同步层的基线。**谁受伤**:开着记忆同步的部署(每一层都停到处置为止),上一轮之后有还没同步出去的删除的部署选错出路会丢删除。
145
+ **两条出路**:① 升级前在旧版上跑完一轮同步(删除落到对端),升级后删掉这些文件(可整只删 `sync-cursors/` 目录与旧文件)—— 第一轮两边已一致,没有条目被拉回;
146
+ ② 直接删掉文件 = 接受空基线重收敛:两边都改过的条目按冲突上报,上一轮之后在一侧删掉的条目从另一侧回来。
147
+
148
+ 20. **settings hook 的子进程环境维持十二名边界(零动作为主;授予形更严,随引擎 7.59.0)**:
149
+ command hook 子进程与 http 条目的 `$NAME` 插值只继承一张十二名的名单(`PATH` / `HOME` / `SHELL` / `USER` / `LOGNAME` / `TERM` / `TZ` / `LANG` / `LC_*` / `TMPDIR`)
150
+ 加请求 `settings.env` 与 hook 自己的变量,与上一发布版同;本服务自有凭据任何情况都不交。引擎的 hook 继承词本部署不采:请求的 `inheritEnv` 只给模型的工具 shell,对 hook 不作用。
151
+ 这一版起组合经引擎的宿主子进程环境组合:请求 `settings.env` 里名字带 `=` / NUL、值带 NUL 的项让 hook 起不来(此前子进程会读成另一对名 / 值;http 条目此前剥掉 NUL 照发,现在一个字节都不发)。
152
+ **谁要动**:hook 要用的变量写进请求 `settings.env`,名字不带 `=` / NUL、值不带 NUL。
153
+ 同一版里 hook 不再筛委派子代收到的那段任务文本(子代的开头改到 `SubagentStart` 站):靠 `UserPromptSubmit` 钩子筛子代提示的部署,把规则挪到 `PreToolUse` 且工具是 `Agent` 的那一站。
154
+
155
+ 21. **抹除的授权集与收执 v2(wire;引擎 7.59.0)**:
156
+ `POST /v1/memory/erase` 的请求体可带 `expectedScopes`(授权集,判官是引擎):选择子的 scope 与每个解析出的 id 的绑定 scope 都得在集里,否则 `400 config.memory_erasure_scope`(什么都没删、什么都没记;
157
+ 会话自助面同码同状态)。收执是 v2:`residuals` 换成八类载体表与两计数、`replay`;`erased[].binding` 不带 slug;`erasedPreviously[]` 为 `{ id, ev, at }`。**谁要动**:按 v1 读
158
+ `residuals.quarantineHits` / `binding.slug` 的消费方改读载体表、按自己的 `requestId` 定位被抹条目;读到 `v > 2` 拒读。`memory.erasure_selector_mismatch` 的原句不再带选择子哈希。
159
+
160
+ 22. **几处读法随引擎(零动作为主)**:只含空白的 `ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN` 读作没有凭据(此前算有,与另一把同设会拒启);
161
+ 部署 mod 包的 `hooks.json` 契约号是 `5`(写 `4` 的包起服拒,拒句点名两个号);MCP 要用户授权的那台在清单行、重拨回执与 `//mcp` 面板带 `authorization: { reason }`(加性);
162
+ 写下 `a2a` 锁或合规禁 `a2a_peers` 的部署,能力位 `a2aInjection` 为 false —— 锁了 `a2a` 而请求仍带 `a2aPeers` ⇒ 同步 `400 config.locked_key`(锁先判,与是否多租户 / 合规禁项无关;与 `mcpServers` 的锁同形;续跑重放腿折成 `409 resume_blocked_by_policy`),没锁而合规禁了 `a2a_peers` 时请求自带的 `a2aPeers` 被忽略(留痕);卡编辑落盘不再出 `wildcard` 一词(更早存下的行照读)。
163
+
164
+ 23. **MCP / A2A 的凭据件改由部署的对端座在发送时作答(行为面;件的形比此前严;新提交的 `principalHeader` 撞属主名 ⇒ 400)**:
165
+ **What changed** —— 本服务交给引擎的 MCP / A2A 声明不再带任何件值(http MCP 的凭据头、stdio MCP 子进程的环境变量、A2A 发送的头):件登记在服务进程内存里,声明只带一只不透明引用,
166
+ 引擎在起子进程(stdio)/ 发请求(http · A2A)之前问部署的对端座,座按原字节作答,引擎的读器判件的形。请求面的形不变(仍收 `headers` / `env`,不收引用位)、名册声明的写法不变(`envRefs` / `headerRefs`)。
167
+ **Who is hurt**(对上一发布版;① ② ③ ⑤ ⑧ 是「那一台不再连上、兄弟照挂、提交照收、运行期才见」:连接期 `wiring_manifest.mcp[].errorCode` / 调用期 `tool_end.errorCode` = `credential_unavailable`,A2A 一侧只有文本;因件的形被引擎读器拒的那一台,服务端没有对应的拒行,看这些码 / 文本;`peer_seat_refused` 只在本服务的座自己拒时才有 —— 引用不在表里 / 绑定不符 / 引用种类座不答):
168
+ ① stdio 件值含 CR / LF / NUL(多行 PEM、尾换行的 Secret);② stdio 件名不是标识符形(`ODD.NAME`、`MY-VAR`);③ MCP http 的件头名是传输自己写的头(`content-type` · `accept` · `mcp-session-id` · `mcp-protocol-version` · `last-event-id`);
169
+ ④ MCP 或 A2A 条目的 `principalHeader` 取引擎的断言头名 `connector-assertion`(任何大小写)—— **新提交 `400 request.field_invalid`**(此前受理:上一发布版的引擎只查身份头名与静态头重名);⑤ stdio 的秘密形件(变量名被引擎认作凭据名)的值恰等于一只每个子进程都会继承的变量的值;
170
+ ⑥ 嵌入方(下一条);⑦ MCP 条目的 `principalHeader` 取传输自己写的头名(`mcp-session-id` · `mcp-protocol-version` · `content-type` · `accept` · `last-event-id`,任何大小写)—— **入口 400**,与 ④ 同一道门、同一个码,点名 `mcpServers[i].transport.principalHeader`,拒句不回显写的串
171
+ (A2A 没有传输自有头名表,A2A 只中 ④);⑧ http 件值首尾带 CR / LF(Secret 文件的尾换行;此前由发送时的头规范化吞掉,现在读器拒)。④ ⑦ 的耐久 resume 重放存量体不 4xx:MCP 照挂(引擎拨号时拒那一台),A2A 那一条对端整条不进(warn `a2a_injection_dropped` 点名)。
172
+ 另:⑨ 会话级子代(http / stdio)的已知缺口见第 25 条;⑩ **扣留次序**:引擎把座答里认作凭据的 http 头值与 stdio 秘密形件值记为自己持有的凭据值(服务进程环境里同值的变量不再交给模型可驱动的 host shell 子进程;MCP stdio 子进程只继承 MCP SDK 的少数默认变量〔`HOME` · `LOGNAME` · `PATH` · `SHELL` · `TERM` · `USER`〕与座给的件,拿不到服务进程环境的其余变量),
173
+ 次序是先过读器、放行了才记 —— 被读器拒的形(件值含 CR / LF / NUL、头名不是 HTTP token、两个头名只差大小写、变量名不是标识符形)的值不进扣留表:那一台失败,环境里同值的变量仍交给 host shell 子进程(上一发布版先记后判,同样的形值已在表里);MCP 传输自己写的头名(③)在读器之后的协议层才拒,值此时已在表里。补偿:名册 `headerRefs` 指向的变量值去掉尾换行;件值别与长期留在服务进程环境里的变量同值而又带读器拒的形。
174
+ **How to migrate**(补偿)—— ① 多行值改 base64 或改传文件路径;⑧ 去掉 Secret 文件的尾换行;② 变量名改标识符形;③ 件头名改非协议名;④ ⑦ `principalHeader` 换成非协议、非引擎自有的名(例 `x-agent-principal`);⑤ 换一个与继承变量不同的值;
175
+ ⑥ 见下一条。零数据迁移:名册只存引用名(不存值),停驻任务的续跑上下文形不变(请求体仍只以封签存,每一腿从封签体重铸引用),引用不跨进程、不跨副本 —— 滚动升级期间新旧副本互不依赖。
176
+ **升级后看**:`/metrics` 的 `peer_registry_entries` / `peer_registry_holders`(在飞腿全落定后回名册基线);`wiring_manifest.mcp[]` 里 `credential_unavailable` 的行(点名那一台的 `name`)与座自己拒时的 `peer_seat_refused` 行(`protocol` / `peer` / `reason`,不带件值)。**回滚**:回到上一版即回到件随声明交引擎。
177
+
178
+ 24. **嵌入方(类型面,BREAKING):`ServiceCoreDeps.peerDesk` 必填、`resolveSpec` 的 `opts` 必填且带 `lease`、Runner 要接座**:自建 `createHttpServer` 的嵌入方(不用任何 MCP / A2A 凭据的也一样)用包根导出的 `createPeerDesk()`(零 IO)铸一只 desk:
179
+ `RunnerDeps.peerSeat` 给 `desk.seat.answer`(函数形 `(question) => Promise<PeerAnswer>`,可赋给引擎 7.59.0 的座型 `(question, signal) => Promise<PeerAnswer>`),`ServiceCoreDeps.peerDesk` 给整只 desk;同一只既给 HTTP 服务也给每只 Runner。tsc 红即通知。
180
+ `ServiceDeps.resolveSpec` 的第四参 `opts` 由可选改必填,带 `lease: PeerLease`(这一腿的宿主租约:受理 / 续跑两只漏斗在调用之前开、由漏斗的失败出口或拿到产物的那段作用域放;装配只借用、不放不留;实现方自铸的声明归自己的 desk 时可以不理它),
181
+ 第三参 `auth` 随之写成 `RequestAuth | undefined`(必填 `opts` 不能跟在可选位后);**直调** `resolveSpec` 的代码要递租约。自己手铸 `McpServerSpec` / `A2aServerSpec` 交给 Runner 的嵌入方:引擎不再收带字面 `transport.headers` / `transport.env` / 顶层 `headers` 的声明
182
+ (整任务 prepare 拒 `config.credential_in_declaration`),带引用而 Runner 没有座整任务拒 `config.peer_seat_missing`(一个坏兄弟也拒整单;Runner 之外的面板 / A2A 物化 / 探测则按对端拒、兄弟照挂)—— 把值改走名册引用或请求面条目,经 desk 铸引用。`RunnerDeps.peerSeat` 的型随引擎 7.59.0 是函数形。
183
+
184
+ 25. **已知缺口(行为面,本版披露不修):会话级子代在父腿作用域结束之后首拨 http / stdio、或再发 http 会被对端座拒**:引擎持有引用的计数那一半本版不在,座只认宿主租约。一个会话级(后台)子代继承父的、**请求体自带**的 http / stdio MCP 声明(引用随声明继承),在**父腿作用域结束之后**再问座 ⇒
185
+ 那次发送 / 那一台的挂载 `credential_unavailable`(`delivered:"no"`,一行不带值的 warn `peer_seat_refused`,`reason: handle_not_held`):http 在首次连接与每次发送时问座,stdio 在起子进程时问座 —— 父腿作用域结束之后才首拨的 stdio 子代同样被拒;父腿很快收尾时,子代连自己的挂载都会被座拒(子代的挂载被跳过)。**谁受伤**:请求体带件的 http / stdio MCP + 后台子代的部署(单用户壳的 `.mcp.json` 带头 / 带环境)—— 上一发布版声明里直接带件,子代在父腿之后仍能连;名册(`headerRefs` / `envRefs`)的服务器不受影响:名册件由进程寿命的名册租约持有,父腿结束不动它;
186
+ 同一腿内(含 cascade 各级、同步腿)与父腿作用域之内已起的 stdio 子进程不受影响,A2A 没有这个形(委派子代不继承父的 A2A 对端)。**补偿**:让父腿等子代收尾(父腿作用域内子代的发送照答);或把这类服务器改成名册声明,或让这类子代只用不带件的 MCP;缺口在引擎持有那一半到货后翻绿。
187
+
188
+ 26. **订正 7.133.0 节第 17 条「同步腿的旧游标文件第一轮自动收编(info `memory_sync_cursor_adopted`)」:收编臂已删,这句不再成立(动作见第 19 条 ③)**:
189
+ 同步腿旧游标文件 `sync-cursor-<peer>.json` 不再被收编,日志行 `memory_sync_cursor_adopted` 随之不再存在。升级前落盘的旧文件都没有引擎 7.59.0 起必带的店绑定,收编的形判从不认它,这条臂对任何存量文件都不可达;
190
+ 旧文件不再被当游标、不改名不删:同步层的新路径上没有文件而它是同步层的无绑定基线 ⇒ 同步层不同步、通告点名它,出路与第 19 条 ③ 同。此后每层一只 `sync-cursors/<peer>/<scope 摘要>.json` 的写法不变。
191
+
192
+ 27. **嵌入方直调 local 店的换装三条腿(`importEntries` / `replaceEntries` / 暂存提交)时属主传 `undefined` ⇒ `TypeError`(行为变更;安全收紧;部署与 HTTP 路径零动作)**:
193
+ 经包根导出的 `createStoreBackend(...).session()` 拿到 `DB_BACKEND=local` 的会话店、再直调这三条腿且属主给 `undefined` 的嵌入方(参数的声明型是 `string | null`,JS 或收窄类型才到得了):上一发布版把它宽读成匿名 —— 不存在的 id 建出无主行,既有属主行被静默改写成无主;
194
+ 本版与 `register` 首写同一只判官 ⇒ `TypeError`、一个字节不写。**补偿**:要匿名显式传 `null`,要某位主体传主体名;按整句匹配拒句的调用方改按类 / 开头(`session owner must be a principal name`)匹配 —— 拒句的类与开头同上一发布版,其后不同。
195
+
196
+ 28. **已知缺口(行为面,本版披露不修;引擎侧缺陷已由引擎认领):换了同步目标之后,本机未改的记忆条目会被当成「中心已删」而删除**:同步腿的游标按对端名(`central`,本版恒为缺省)与层各存一只,**不随 `MEMORY_SYNC_URL` / 中心的引擎声明变化**;把 `MEMORY_SYNC_URL` 指向另一台中心(或同地址换了中心的引擎声明 / 店)后,旧游标里的基线对新中心成立「基线有、中心无」,新中心按协议答删除,本机侧照做 —— 本机未改过的条目被删,零冲突上报。
197
+ **升级前做**:零动作(不换中心不触发)。**换中心前做(本版与之前各版同)**:二选一 —— ① 先在旧中心跑完一轮同步使两边收敛,再删该层的游标文件 `sync-cursors/central/<scope 摘要>.json`(同步根下;层目录见第 19 条 ③);② 直接删该游标文件 = 接受以空基线对新中心重收敛(两边都改过的条目按冲突上报)。**升级后看**:换中心后的首轮日志 `memory_sync_round` 里 `localApplied`(本机被应用的变更数,含删除)非零而 `conflicts` 为零、且本机近期没改过记忆 ⇒ 即此症(日志不单列删除数;对账看本机记忆目录条目数)。**回滚**:回到上一版行为相同,不是修复。真修 = 游标绑对端身份、目标不符整轮零请求拒,随引擎的对端身份件在下一版到达。
198
+
199
+ ## 7.137.0 —— 对 web-admin 中心的请求不再跟随重定向(安全收紧;行为面;反代会回 3xx 的部署升级前把两席写成最终地址) · k8s 车道 `K8S_SANDBOX_ENV` 的值改经每只 pod 自己的 Secret(部署面 BREAKING;沙箱 Role 要 secrets 的 `create`,名单非空而 Role 不许 ⇒ 起服拒;共用沙箱命名空间的两套部署升级前各给一个命名空间) · SQL 后端 `task_run` 表加三列 `identity_source` / `identity_scope` / `identity_principal_inc`(🔴 升级前先 `ALTER TABLE` 加列;持久数据,不能删表重建;嵌入方 `RunRecord` 多必填键 `identity`〔BREAKING,类型面〕) · 请求键 `promptProfile` 退役、换成布尔 `promptLean`(BREAKING,wire;零别名;升级前停驻的任务存体起服原地改写〔一次性迁移 M30,窗 30 天〕,没改写到的续跑 409) · 模型目录条目带 `promptGuidance` 的不服务、fable 系模型 id 不再带 fable 提示段(行为变更) · 带图预检的计量 `images_omitted_total` 与日志行 `images_omitted_no_vision_model` 退役(运维面;行为变更;看板 / 告警改读会话流的 `model.capability_downgraded`) · 引擎 7.56.0 的部署序:先升全部读者、回滚前先决完停驻行(三处:停驻审批行 `mount_site`、技能座 `skill_scopes`、会话规则文法 5) · 规则名里的 `*`:限制侧整名 glob、授予侧一条孤 `*` 不再让整张放行表作废(行为变更;升级前先审放行表) · 规则名外缘的空白被拒(行为变更;人敲的规则编辑文本修剪后再提交) · 嵌入方 hook / mod 的 handler 答案按数据收、非普通记录一律拒(行为变更,fail-closed) · 不是名字的主体在鉴权边界被拒:`400 principal_not_a_name`(行为变更;反代把 UTF-8 用户名原样塞进主体头的部署升级前核) · 计划审阅的决断体可带 `checkpointId`:门换了 ⇒ `409 approval_stale`、不落决断(wire additive;决断方先读能力位 `planReviewCheckpointId` 再带键) · `delegation.ask_unresolvable` 通告的 `detail` 多可选键 `remedies`(wire 加性;宿主按 `kind` 渲染出路,闭集外的 `kind` 忽略) · 引擎 7.56.0 的五个新键本版刻意不投(`requestedBy`、`answeredBy`、`hostFloor`;登记披露,无消费方动作) · 本版其余 wire 面变化的消费方动作逐面表态(多数零动作;设备执行器的修订 3、`attachments.mcpUnavailable`、`resultEntryIds` 各有一句真动作) · 7.136.x 停下、技能请求项带 `mods` 的任务续跑失败(行为变更;新提交早已 400) · 订正 7.136.0 节第 4 条:没有返回任务目标全文的读口(`GET /v1/runs/:id` 不带目标)
200
+
201
+ 1. **对 web-admin 中心的请求不再跟随重定向(安全收紧;行为面)**:此前只有令牌续签不跟重定向,其余对中心的请求(拉配置、principal 视图、skill 正文、prompt 产物、配额租约、
202
+ fleet 公告 / 用量 / 注销、服务租约、执行公钥上报)被传输层静默跟随 —— POST 307 / 308 把请求体带去 `Location`,同 origin 的跟随连 `Authorization` 一起带走。本版起每条都不跟:
203
+ 中心回重定向(任何 3xx,304 除外)⇒ 该条请求被拒,拒句 `web-admin center request: endpoint answered with a redirect (HTTP <n>); it was not followed and no credential was sent anywhere else — …`
204
+ 点名这条请求打的那一席。**只伤一类部署**:`SEMA_WEB_ADMIN_URL`(或 `SEMA_WEB_ADMIN_LIVE_URL`)指的不是中心的最终地址,而是会 301 / 302 / 307 / 308 的反代(`http` → `https` 跳转、主机名规范化、尾斜杠重定向)。
205
+ **升级前做**:二选一 —— 让反代直接回答,或把这两席写成最终地址;用文件形用户会话凭证(`SEMA_WEB_ADMIN_TOKEN_FILE` 里的信封)的部署,还要用新地址重新登录一次,使信封里的 `issuer` 也是最终地址
206
+ (续签遇重定向落终态「被拒」:`center_credential_renew_failed`,`reason: "rejected"`,直到凭证文件变化)。**升级后看**:起服那一行 `config_source_unreachable_using_env`(起服拉配置撞上重定向时拒句落在这一行,多数部署第一眼看到的是它)
207
+ 与 `web_admin_refresh_failed` / `fleet_announce_failed` / `fleet_usage_report_failed`、鉴权桥的 `auth_bridge_jwks_fetch_failed` 这几条 warn 的错误字段里是否出现
208
+ `answered with a redirect`;出现 = 还有一席没写成最终地址(JWKS 那一行点名 `AUTH_BRIDGE_JWKS_URL` 或它派生自的签发方地址)。其余部署零动作。
209
+
210
+ 2. **k8s 车道:`K8S_SANDBOX_ENV` 的值改经每只 pod 自己的 Secret ⇒ 沙箱 Role 要 secrets 的 `create`(部署面 BREAKING;名单非空而 Role 不许 ⇒ 起服拒)**:本版起名单点到的值不再写进 pod spec,
211
+ 只进该 pod 的一只 Secret(pod 的容器 env 带 `secretKeyRef`;Secret 属于 pod,随 pod 由集群回收)。**升级前做**:设了 `K8S_SANDBOX_ENV` 的部署,给服务账号在沙箱命名空间的 Role 加一条
212
+ `- apiGroups: [""] resources: [secrets] verbs: [create]`(随包 `deploy/sema-up/chart/templates/sandbox-rbac.yaml` 与 `deploy/sema-up/stack/sema-stack-cluster.yaml` 已带)。
213
+ 动词恰是服务为这只 Secret 真发的调用:`create`(建每只 pod 的 Secret,之后不再碰);**不要**给 `get`(服务从不读回 Secret,给了就让服务账号读得到沙箱命名空间里的每一只 Secret)
214
+ 与 `delete`(Secret 属于它的 pod,由集群的垃圾回收随 pod 删,不经服务账号)。
215
+ 缺了 ⇒ 起服拒,拒句带 `[sandbox-secret-rbac]`、点名缺的动词;起服问不到(API 连不上 / 服务账号建不了 SelfSubjectAccessReview)⇒ 照起,但第一个转发的 run 连接即拒(`auth_failed`)、它的 pod 被删 —— 值不会回落进 pod spec。
216
+ 没设 `K8S_SANDBOX_ENV`(或点到的键在服务进程环境里都没有值)的部署零动作。建议同时给集群开 Secret 静态加密(值现在在 etcd 的 Secret 里)。
217
+ 成员 git 凭据代理的租约 Secret 另要 `patch`(改写租约用 merge-patch;**不需要** `update`)—— 本版该平面恒关、没有代理会被挂上,起服门也不问它,**现在不用给**;
218
+ 平面打开的那一版再加(那时平面判官问的是 `create` / `patch`,不许 ⇒ 平面熄、读数 `secret_seat_denied`)。
219
+ 另一条行为变更不需要动手:服务会删已结束的沙箱 pod(容器全部结束,或它的 run 已终且过了 `max(6 分钟, WORKSPACE_SNAPSHOT_TIMEOUT_MS + 15 秒)`)—— 事后 `kubectl logs` 看不到了,要留现场在 run 结束前取。
220
+ 这里的 `WORKSPACE_SNAPSHOT_TIMEOUT_MS` 是**建这只 pod 的副本**的值:建 pod 时算一次、写进 pod 注解 `sema.io/run-end-hold-ms`,回收器只读这一格、不读自己副本的配置 ——
221
+ 滚动升级或改 `WORKSPACE_SNAPSHOT_TIMEOUT_MS` 时每只 pod 按建它的副本的时限,时限短的副本不会提前删时限长的副本还在存快照的 pod;不带这条注解的 pod(本版之前建的)不按 run 终态删,容器结束后照删。
222
+ 给沙箱命名空间配了限制 pod 注解的准入策略的部署,升级前放行注解键 `sema.io/run-end-hold-ms`(否则建 pod 被拒)。
223
+ **两套部署共用一个沙箱命名空间**(缺省都是 `sandboxes`)时,回收器按身份标签列 pod、标签里没有部署身份 ⇒ 一套部署会删另一套**容器已结束**的 pod:
224
+ 升级前用 `K8S_NAMESPACE` 给每套部署各一个沙箱命名空间(本版没有关掉回收器的旋钮)。
225
+
226
+ 3. **SQL 后端:`task_run` 表加三列 `identity_source` / `identity_scope` / `identity_principal_inc`(🔴 升级前先加列;持久数据,不能删表重建;嵌入方 BREAKING,类型面)**:
227
+ 本服务受理一条 run 时,把这次请求在凭据门上验过的身份来源(`service_token` / `sso` / `direct_door_jwt`)连同登录令牌的 scope 写进 run 行(化身号一列先恒空,
228
+ 契约包给出那一位之后才有值),之后只读 —— 续跑、挂起、终局、重启都不改。本服务不发 `ALTER`:存量库缺这三列 ⇒ 起服列册对账拒启(`config.schema_mismatch`),拒句带可直接粘贴执行的语句。
229
+ **升级前做**(MySQL 协议,三句):
230
+ `ALTER TABLE task_run ADD COLUMN identity_source VARCHAR(32) NULL;`
231
+ `ALTER TABLE task_run ADD COLUMN identity_scope VARCHAR(190) NULL;`
232
+ `ALTER TABLE task_run ADD COLUMN identity_principal_inc VARCHAR(64) NULL;`
233
+ (PostgreSQL,三句)
234
+ `ALTER TABLE task_run ADD COLUMN identity_source VARCHAR(32) COLLATE "C";`
235
+ `ALTER TABLE task_run ADD COLUMN identity_scope VARCHAR(190) COLLATE "C";`
236
+ `ALTER TABLE task_run ADD COLUMN identity_principal_inc VARCHAR(64) COLLATE "C";`
237
+ 存量行三列是 NULL,不回填(没有事实可回填):读法是「这一行没有属主在受理时验过的凭据的记录」,与无鉴权写面(`ALLOW_UNAUTHED_WRITES`)受理的 run、
238
+ 别人替属主按下唤醒 / 决定投递铸的新一跑同读,一律不合格。行上的 `source` 列(系统名,登录令牌直连写 `sso`)只作归因,不被读成认证来源。
239
+ **顺序**:先升库(加列)、再升副本 —— 加完列之后,仍是 7.136.x 的副本**再启动**会把三列看成幽灵列而拒启(只挡重启;已在跑的旧副本建行时带列名清单、不写这三列,
240
+ 它们受理的 run 三列为 NULL,同上读法)。**不要**删表重建 `task_run`:表里是 run 账本(在飞 / 停驻的 run 与提交幂等键)。`DB_BACKEND=local` 与内存后端零动作
241
+ (文件后端的 `run.json` 多三键,升级前写下的文件读成 NULL)。
242
+ **回滚到 7.136.x:只回退二进制不可行**(MySQL 协议与 PG 皆然)—— 加过列的库上,7.136.x 的起服列册对账把多出的三列读成幽灵列、起服拒(拒句点名 `UNKNOWN column(s) identity_source, identity_scope, identity_principal_inc`、不给 ALTER)。
243
+ 回滚 = ① 先停光全部本版副本;② 手工 `ALTER TABLE task_run DROP COLUMN identity_source;`、`ALTER TABLE task_run DROP COLUMN identity_scope;`、`ALTER TABLE task_run DROP COLUMN identity_principal_inc;`(两方言同三句);③ 再起 7.136.x。
244
+ DROP 只丢本版受理的 run 的身份记录:再升回本版、照上面加列之后,这些行读成 NULL(不合格),run 的其余读写不受影响。
245
+ **嵌入方(类型面,BREAKING)**:包根导出的 `RunRecord` 多一个必填键 `identity` —— 三形之一:`{ source: "sso", scope, principalInc }`(`principalInc` 可为 `null`)、
246
+ `{ source: "service_token" 或 "direct_door_jwt", scope: null, principalInc: null }`、`null`。只读它的代码零动作;手写的 `RunRecord` 字面量(测试夹具、自造的 run 读者)tsc 红 —— 补 `identity: null`。
247
+
248
+ 4. **请求键 `promptProfile` 退役,换成布尔 `promptLean`(BREAKING,wire;零别名;引擎 7.56.0)**:新提交三腿(`POST /v1/tasks` · `/v1/tasks/stream` · `/v1/runs`)上带 `promptProfile` ⇒
249
+ `400 request.body_shape`(`unknownKeys` 点名它)。**调用方改法**:`promptProfile: "classic"` ⇒ `promptLean: false`;`promptProfile: "simple"` ⇒ 不带键(或 `promptLean: true`)。
250
+ `promptLean` 不是布尔 ⇒ `400 request.field_invalid`。
251
+ **停驻中的任务**:7.136.x 及以前停驻、请求体里带 `promptProfile` 的任务,本版**起服时**把存下的请求体原地改写(同一张映射:`"classic"` ⇒ `promptLean: false`,长形照旧;
252
+ `"simple"` / 词表外 ⇒ 删键,缺省形;体里已有布尔 `promptLean` ⇒ 它说了算、只删旧键;续跑时钟不动),起服一行运维日志 `checkpoint_ctx_prompt_profile_rewritten`(扫了几行、改了几行,不带值)。
253
+ 这是**一次性迁移,窗 = 本版发布日起 30 天**,窗内每次起服都扫;改写过的任务此后续跑几次、窗关之后再续跑,形都不变 —— 零动作。
254
+ **升级序(与第 7 条同向,且更严)**:**先停光 7.136.x 副本,再起第一个本版副本**(它起服即改写)。改写过的体 7.136.x 读不懂 —— 它只认 `promptProfile`,读到改写后的体回到缺省形
255
+ (`"classic"` 的长形静默丢),所以本版副本起过服之后,不能再有 7.136.x 副本续跑这些任务;反过来,本版起服之后才由 7.136.x 副本停下的任务存体里仍是旧键。
256
+ **升级前先缩光副本,按安装路径分三种**(滚动更新做不到「先停光 7.136.x、再起第一个本版副本」;下面三段各管一种安装路径,照你的那一种做):
257
+ **Helm 形安装**(`kube-up.sh` 的 `--kube=existing` / `--kube=k3s`;`--kube=machines` 下设了 `STACK_ENGINE=helm`):图表只在钥匙卷是 `ReadWriteOnce` 时给 Deployment 写 `Recreate`;缺省的多副本(`server.replicas: 3`、`ReadWriteMany`)不写更新策略,`helm upgrade` 走 Kubernetes 缺省的滚动更新 —— 第一只本版 pod 起服改写存体时 7.136.x 副本还在跑。所以升级前先 `kubectl -n <命名空间> scale deploy/sema-server --replicas=0`(启用 `serverV4pro` 时同样缩 `deploy/sema-server-v4pro`),等旧 pod 退光,再 `helm upgrade`(重跑 `sema-up` / `kube-up.sh` 在这些安装形上走的就是这条),升完核副本数回到 `server.replicas`。
258
+ **`--kube=machines` 缺省形**(不设 `STACK_ENGINE` = `render`;`cluster-up.sh` 渲染清单后 `kubectl apply`,不是 Helm):清单里 `sema-server` 的副本数按机器数取 2(少于 3 台)或 3(3 台及以上),没有 `strategy` 键 = Kubernetes 缺省的滚动更新,也没有 `serverV4pro`。所以升级前先 `kubectl -n sema scale deploy/sema-server --replicas=0`(第一台机器上写 `k3s kubectl`),等旧 pod 退光,再 `kubectl apply`(重跑 `sema-up` 做的就是这一步;清单里的 `replicas` 把副本数写回 2 或 3),升完核副本数。
259
+ **compose 两档**(`--profile=full-single` / `local-plus`):`server` 服务只有一只容器、没有副本数键 —— 没有第二只旧副本在滚动更新里陪跑,零动作。
260
+ **没改写到的**任务(窗内从没起过本版的部署;违反上面的升级序、在本版副本起服之后由 7.136.x 副本停下的任务)续跑答 `409 checkpoint.unsupported_version`(`retriable: true`,卡仍待决;
261
+ 句子点名 `promptProfile`,不回显值),不按旧键读、也不静默丢键:窗内在最后一只 7.136.x 副本停下之后重启一只本版副本,它起服即改写这些任务(重启用的配置里须 `DURABLE_APPROVAL=true` —— 多租户部署缺省关,要显式写,且多租户还需 `OPERATOR_PRINCIPALS` 非空,否则起服拒(拒句点名出路);起服日志里 `checkpoint_ctx_prompt_profile_rewritten`(M30)与 `checkpoint_ctx_credentials_sealed`(M28)两行都出现、且 M30 那一行是 `"window":"open"`,才说明守卫过了、改写跑过 —— M28 的窗先关,窗关后它那一行 `"window":"closed"` 属正常);
262
+ 窗关之后仍带旧键的任务只能取消后作为新任务重提(`promptLean` 代替 `promptProfile`)。跳过本版、直接升到更晚版本的部署,先在本版上起一次服。
263
+ **库形嵌入方**(包根的 `createHttpServer` + 自建 `StoreBackend`,不经 `@sema-agent/server/main` 这个服务进程入口):本条的起服改写(M30;`checkpoint` 存体里请求凭据的封签 M28 同形同处)只在服务进程的起服第 6 段(`src/boot/stage-06-runners.ts`)里跑 ——
264
+ 包根没有导出它,公开的迁移序列(`createStoreBackend()` → `ensureSchema()` → `runOneTimeMigrations()`)也不含它(它要等 checkpoint 店建成之后才能跑)。所以库形嵌入方自己的装配不会改写存体:7.136.x 停驻、体里带 `promptProfile` 的任务续跑一律答 `409 checkpoint.unsupported_version`,
265
+ 上面「窗内重启一只本版副本即改写」的出路对它不成立。窗内的出路:用本包的服务进程入口(`import "@sema-agent/server/main"` 或 `node dist/main.js`,指向同一份库 / 数据根)起一次服 —— 那一次起服即改写,但有两个前提并列,缺哪个都不行:① `DURABLE_APPROVAL=true`(多租户部署缺省关,要显式写,且多租户还需 `OPERATOR_PRINCIPALS` 非空,否则这一次起服拒(拒句点名出路:设 `OPERATOR_PRINCIPALS`,或单租户部署去掉 `REQUIRE_PRINCIPAL`);两只迁移只在 checkpoint 店存在时跑,店只在这个开关为真时建,开关为假 ⇒ 这一次起服静默不跑它们;这道守卫早于本版,本版只补了这句说明);② 只对 M28 的窗内(UTC 日历日,含 2026-11-20 当天)有意义:服务进程入口读到的保管目录里要有嵌入方封签用的那对钥匙 —— 做法是 `SEALED_KEY_DIR` 指向嵌入方自己 `ensureCheckpointCtxSealing(sealedKeyDir)` 用的那个目录(服务进程入口缺省读 `<数据根>/sealed-key`;读到的目录里没有可用的钥匙文件 ⇒ 服务进程新建一对钥匙去封剩余的明文行,嵌入方不持有这对钥匙,这些行的续跑答 `409 conflict.checkpoint_ctx_unsealable` `reason:"key_not_held"`,嵌入方要先持有那对钥匙〔保管目录只在起服时读〕才读得开,否则取消后作为新任务重提)。两只迁移的窗不同:M28(封签剩余明文凭据行)的窗到 2026-11-20,M30(改写 `promptProfile`)的窗到 2026-11-24 —— 2026-11-21 至 2026-11-24 之间的那一次起服只改写 `promptProfile`、不再封签明文凭据行(前提 ② 在那几天不相干;仍是明文的行续跑答 `409 conflict.checkpoint_ctx_unsealable` `reason:"plaintext"`,取消后作为新任务重提),两行日志名都会出现(M28 那一行是 `"window":"closed"`、`rowsScanned` 为 0)。起服后核日志行 `checkpoint_ctx_credentials_sealed`(M28)与 `checkpoint_ctx_prompt_profile_rewritten`(M30)都出现 —— 没出现 = 守卫挡了、迁移没跑;出现了还要看字段,不只看行名:`"window":"open"` 且 `rowsScanned` 是你预期的行数,才说明那一只迁移真扫过(`"window":"closed"` ⇒ 一行没读)。M30 的窗关之后(2026-11-24 之后)与其余部署同,取消后作为新任务重提。
266
+ **回滚到 7.136.x**:被改写过的停驻任务在 7.136.x 上续跑回到缺省形(长形丢,零通告)—— 回滚前先决完或取消停驻的任务(与第 7 条「回滚前先决完停驻行」同一个动作)。
267
+
268
+ 5. **模型目录条目带 `promptGuidance` 的不服务;fable 系模型 id 的 fable 提示段(行为变更;引擎 7.56.0)**:目录条目(中心配置 / `config.d` / 部署 env 条目)写了非空 `promptGuidance` ⇒
269
+ 那一条不服务(与别的坏条目同一个拒因 `config.model_entry_invalid`,`fields: ["promptGuidance"]`,起服 / 刷新时运维日志点名)。**做法**:删掉条目里的 `promptGuidance`;引导句的去处是
270
+ 模型声明的提示特征 `promptTraits` —— 契约包的模型条目还没有这个座,在它到之前本服务不透传。经本服务目录跑 fable 系模型 id 的部署:引擎不再按模型 id 认 fable 系,
271
+ 这些 run 本版起不带 fable 提示段、取模型缺省的短形;要那几段的部署在契约包加座之前留在 7.136.x。
272
+
273
+ 6. **带图预检的计量与日志行退役(运维面;行为变更)**:计量 `images_omitted_total{model}` 与运维日志行 `images_omitted_no_vision_model` 本版起不再出现 —— 带图请求遇不收图的模型,
274
+ 由引擎在真替换图片的那一刻在会话流 / 账本里发 `engine_notice` `model.capability_downgraded`(`detail: { model, capability: "image", status, sessionId, runId }`)。
275
+ **做法**:引用这两者的看板 / 告警改读那条通告(按 `code` 计数);不改的看板会静默少一条线。
276
+
277
+ 7. **引擎 7.56.0 的部署序:先升全部读者,回滚前先决完停驻行(三处)**:
278
+ - **停驻审批行的 `mount_site`**:本版停下的、引擎挂载的工具(每一只内置工具,问答工具在内)的审批行多一个成员与一个要求词;7.136.x 及以前的副本读到它在认领之前拒
279
+ (`checkpoint.unsupported_version`,`version_newer`,行留 pending)。⇒ 多副本滚动升级:先把会续跑的每只副本都升到本版,再放新的停驻;**回滚到 7.136.x 之前**先把本版停下的审批决完或取消。
280
+ - **技能座的 `skill_scopes`**:引擎给「带 hooks 的技能在场时停下的 run」写这个要求词;本服务不编技能 hooks(能力位 `mods.skill_seat` 恒 false、请求面拒 `skills[].mods`),
281
+ 本服务写下的停驻行不会带它 ⇒ 零动作。
282
+ - **会话规则文法 5**:本版的写口给会话规则行盖文法 5 的戳,7.136.x 及以前的副本读不了这种行(那条会话的每一跑开跑即失败,见下面「回滚」);持久规则桶同理(SQL 后端 `permission_rule` 的 `grammar` 列:
283
+ 本版写过的桶旧副本整桶拒)。⇒ 先把读同一只会话规则店 / 规则桶的每只副本都升到本版,再放会话规则与「始终允许」的写;
284
+ **回滚**:本版写下的行旧版读不了,旧版的写口也改不了它(写前读那一行即拒)。实测(同一 local 数据根,本版写过会话规则 —— 连只写一条 `Write` 也盖文法 5 —— 再起 7.136.0):
285
+ 这些会话的**每一跑开跑即 `failed`**、终局码 `corrupt`(一次工具调用都没有),`GET /v1/sessions/:id/policy` 答 `500 corrupt`;没写过会话规则的会话照常。
286
+ 回滚后这些会话的出路只有删会话(或再升回本版)。
287
+ **不要**在库里把戳改小:同一条 `toolDeny` 的 `*` 在文法 4 里什么也不拒(改戳 = 静默放宽)。
288
+
289
+ 8. **规则名里的 `*`:限制侧是整名 glob、授予侧的孤 `*` 不再让整张放行表作废(行为变更;引擎 7.56.0)**:
290
+ - **限制侧**(请求 `settings.permissions.deny` / `ask`、运维 `APPROVAL_REQUIRE` / `APPROVAL_DENY` / `APPROVAL_NEVER_AUTO` 与中心下发的同名表、`excludeTools`、会话规则 `toolDeny`、技能 `disallowedTools` / 子代 `denyTools`):
291
+ 名字里的 `*` 读成整名 glob,孤 `*` = 每一只工具。7.136.x 上这些写法在受理口一律被拒,所以没有存量部署受伤;**变的是调用方的读法**:此前
292
+ `deny:["*"]` ⇒ 422 `invalid.tool_name`、`excludeTools:["*"]` ⇒ 400 `config.tool_face_control`、技能 `disallowedTools:["*"]` ⇒ 400 `request.field_invalid`、子代 `denyTools:["*"]` ⇒ 400 `config.agent.unknown_tool` 这几条拒不再出现 ——
293
+ 它们现在 200 / 受理,而且**真的**全拒 / 全问(`deny:["*"]` 的 run 里每一只工具都被拒)。拿那几条 4xx 当信号的调用方:改按 200 与实际策略读。
294
+ - **授予侧**(请求 `settings.permissions.allow`、技能 `allowedTools`、运维放行席):一条孤 `*` 什么也不授(照旧被通告,`wildcard_all`),但**同表别的条目照常放行** ——
295
+ 此前整张表读空、一条也不放。**升级前做**:靠授予侧一条 `*` 把整张放行表作废的,把表里不该放行的条目删掉(放宽方向,先审已有的表)。
296
+ **回滚到 7.136.x**:限制侧受理过的 `*` 条目(尤其会话规则行,见第 7 条)旧版读不了或读成什么也不拒 —— 回滚前先清掉本版写下的这类条目。
297
+
298
+ 9. **规则名外缘的空白从 7.137.0 起被拒:卡上人敲的规则编辑文本带前导 / 尾随空白或工具名后空格 ⇒ 裁决之前 `400`(行为变更;引擎 7.56.0;消费者动作 = 去掉空白)**:
299
+ `persistRule: { rule, edited: true }` 的文本,**前导空白**(含制表符)、**尾随空白**、**工具名与 `(` 之间的空格**(`" Bash(adb *)"`、`"Bash(adb *) "`、`"Bash (adb *)"`)不再被收下 ——
300
+ 裁决之前 `400 request.body_shape`,体带 `ruleRejectCode: "invalid.grammar"`,`error` 句点名去掉空白后的写法(`Bash(adb *)`);这只 ask 未结算、卡还在、店里零落地。7.136.x 上**前导空白**与**工具名后空格**的文本被收下并落成一行规则(尾随空白那时就已拒,不是本版新拒)。
301
+ **做法**:界面 / 壳把人敲的文本**修剪后再提交**(引擎的解析器不修剪,修剪是编辑器表面的事);文本**内部**的多余空白不在本条之内(`Bash(adb *)` 仍落 `Bash(adb:*)`)。无存量数据要迁移。
302
+
303
+ 10. **嵌入方:hook / mod 的 handler 答案按数据收,非普通记录的答案一律拒(行为变更,fail-closed;引擎 7.56.0「答案是数据」)**:handler(`PreToolUse` 钩子答案、`prompt.compose` 的 overlay 答案等)返回的值只收原始值或普通记录 / 数组(整只拷贝并冻结);
304
+ **类实例、`Map`、函数、symbol、bigint、环、原型上带契约成员的对象、不可枚举成员的载体**是站点违约 —— 该次判决被拒(`PreToolUse` 上读数 `ran=0 denied=1`),此前原型载体与类实例被照常接受。
305
+ 本服务自己铸的 handler 答案逐点核过:答案铸点(带 `action` / `block` / `additionalContext` / `overlays` 键的对象字面量)共 20 处 —— `settings.hooks` 注册 19 处、部署座品牌行 1 处 —— 全是普通对象字面量:`settings.hooks` 的成员只有闭集词串(`action`)、截断后的文本串与钩子 stdout 经 `JSON.parse` 得到的 `updatedInput`;
306
+ 品牌行的成员是引擎交回的上一手答案原样接上本服务的一条 overlay 常量;部署座的拒绝计量与工具追踪两只观察者、`StopFailure` / `PostCompact` 的翻译恒答 `undefined`。
307
+ 服务部署零动作;只有**自己往引擎里挂 handler 的嵌入方**要核:把答案改成普通对象字面量。
308
+
309
+ 11. **不是名字的主体在鉴权边界被拒:`400 principal_not_a_name`(行为变更;引擎 7.56.0 的主体名判官)**:主体头(去掉首尾空白之后)、SSO 令牌的 sub、直连门 JWT 的 sub
310
+ 带控制、行段分隔或不可见格式字符(引擎 `principalNameOf` 的判据),或 sub 只有空白 ⇒ 本版起 400 带码,7.136.x 收下;空的 / 只有空白的主体头照旧读作「没有主体」。
311
+ **最常见的来源**:反代把 UTF-8 用户名原样塞进主体头 —— 本服务按 latin1 一字节一字符读头,UTF-8 字节里的 0x80–0x9F 读成 C1 控制字符、0xAD 读成软连字符(格式字符),
312
+ 于是「张三」(E4 B8 **89**)、`Martín`(C3 **AD**)都被读成「不是名字」的乱码。
313
+ **怎么核**:升级前在反代上看主体头的字节 —— 有 0x80–0x9F 或 0xAD 的字节 ⇒ 本版起被拒,必须改;其余非 ASCII 字节照收(但同一个人在签名令牌的门上解出的是 UTF-8 原文、
314
+ 在主体头上是 latin1 乱码,两个串,建议一并改);或在 7.136.x 的会话列表 / 审批队列里找属主带乱码的行。升级后看 `400 principal_not_a_name` 的计数。
315
+ **怎么改**:反代把主体头编成 ASCII 或其它不含控制字符的规范形(用户 id、百分号编码等)再发 —— 同一个人在每条门上要是同一个串。
316
+ **存量行**:7.136.x 按乱码串记下属主的会话、停驻审批、规则桶,本版上没有主体够得着(那串不再是谁的名字)。本版**没有通用的迁移口**,如实说清能做到哪一步:
317
+ SQL 后端的多租部署,运维可以试收编口 `POST /v1/adoption`(operator 面)把一位用户的行迁到新名字下 —— `fromPrincipal` 写 7.136.x **真存下的**那一串:
318
+ 用户名的 UTF-8 字节按 latin1 逐字节读出、再去掉首尾空白(边界读头时剥过;0xA0 在 latin1 是 NBSP,串尾的会被剥掉),JSON 里用 `\u00XX` 转义写;
319
+ `toPrincipal` 写改编码之后的新串(收编口不判它是不是一位主体的名字,由运维保证;同一个 `fromPrincipal` 只能收编一次)。**限制**:收编口要求旧串编码成记忆作用域段后
320
+ 不超过 64 个字符(非 ASCII 每个字节约占 6 个字符)⇒ 大约三个汉字以内的名字迁得动,更长的会被拒(`400 request.field_invalid`)。迁不动的、以及文件后端
321
+ (`DB_BACKEND=local`,没有收编口)上的旧行,留在旧串名下:只能回滚到 7.136.x 继续用,或删掉。`MEMORY_ORG_DIRECTORY_JSON` 的主体键同判:有这类键 ⇒ 起服拒
322
+ (拒句按键在 JSON 文本里的出现序点名:`principal key #N (in text order)`),改成新串。
323
+ **回滚到 7.136.x**:同一份乱码串照旧被收下,存量行照旧够得着;本版下以新串写下的行归新串。
324
+
325
+ 12. **计划审阅的决断体可带 `checkpointId`(决断方看到的那道门):门换了 ⇒ `409 approval_stale`、不落决断(wire additive;服务部署零动作,消费方动作见下)**:
326
+ `POST /v1/assistant/tasks/:id/plan_review` 认可选键 `checkpointId`;带了而它不是该会话此刻待决的那道 plan 门 ⇒ `409 approval_stale`(与 `/decide` 同码同句),计划未批、卡仍待决,
327
+ 体带当前门 `currentPending: { checkpointId }`(当前门没有可信身份 / 恰被并发消费时缺席);不带键照旧受理。
328
+ 陈旧判过了之后、认领之前门再换(窄窗)⇒ `409 conflict.not_resumable`(认领输家那一码,决断同样不落;直连门上这一份证明的 nonce 已用掉,重签再决)。
329
+ · **决断方(client-core `decidePlanReview` 等)**:透传人看到的那道门的 `checkpointId` —— 取 park 结果的 `terminal.checkpointId`(`GET /v1/runs/:id` 的 `result`、同步提交体、流的 `done.result`),
330
+ 或运维队列 / 收件行上的 `checkpointId`、`GET /v1/runs/:id/events` 的 `needs_review` 账本行 `data.checkpointId`(同一个值)。值形:非空串、≤ 128 字符,否则 `400 request.field_invalid`。
331
+ **先读能力位再带键**:`GET /v1/capabilities` 的 `planReviewCheckpointId === true` 才带(位缺席 = 老 server,带了那一次决断整个失败)—— 别按版本号嗅探。
332
+ · **壳 / cli**:读 `409 approval_stale` 体的 `currentPending.checkpointId`,重取**那道门的计划**给人看,人认可后带新身份再决 —— 别拿它直接重发(那是在批一份没人看过的计划);
333
+ 体里没有 `currentPending` ⇒ 重拉队列或 run 再决。
334
+ · **直连门签名器**:送这个键就要把它签进 HMAC 信封第 6 位的扩展对象(闭集字典序 `answer` / `checkpointId` / `permissionModeAfter`,例:`["s1","nonce-1",null,"approve",null,{"checkpointId":"cp_…"}]`);
335
+ 不送它的签名器零改动(缺席时字节逐字不变);带了不签 ⇒ `401 approval_mac_invalid`。
336
+ · **跨版本**(读上一条的能力位就不会撞上):7.86.0–7.136.x 的 server 收到这个键答 `400 request.body_shape`(`unknownKeys` 含 `checkpointId`)—— 位缺席时不带键(= 回到没有陈旧保护的旧行为);
337
+ 7.86.0 之前的 server 没有键闭集门,键被**静默丢**(200 照收、陈旧保护不在)—— 对那么老的 server 别指望这一位。
338
+ · **重拉还是同一个身份**:体里没有 `currentPending`、重拉 run 结果拿到的身份与你送的一样仍 409(队列 / 收件行上这一道门不带 `checkpointId`)⇒ 这道门的身份没过服务端的信任边界(坏行),带它永远对不上;
339
+ 人看过**当前**计划之后不带这个键再决(这一次没有陈旧保护,告知运维查那一行)。
340
+ · 连带:`/decide` 收到 `checkpointId` 仍是 400,桶由 `unknownKeys` 换成 `unsupportedKeys`(指路计划审阅那道门);按桶分支的客户端核一下。
341
+
342
+ 13. **`delegation.ask_unresolvable` 通告的 `detail` 多可选键 `remedies`(wire 加性;消费方动作 = 读它、按 `kind` 渲染出路;引擎 7.56.0)**:用户读的 `detail.remedy` / `message` 两句自引擎 7.56.0 起不再教 `bypassPermissions`(模式放行那条出路只在运维放开该模式时才可提);这条出路改作数据:`detail.remedies` = 闭集 `approver` / `permission_mode` 上的非空表,恰在 `detail.remedy` 在场时带 —— `{ kind: "approver" }` 与 `{ kind: "permission_mode", value: "bypassPermissions", disclosedOn: "gate.disposition.released" }`(放行披露在那只调用的 `tool_end.gate.disposition.released`)。本服务只透传:不渲染、不改写、不补句。
343
+ **消费方动作**:渲染这条通告的宿主(client-core / cli / web-admin)读 `detail.remedies`、按 `kind` 渲染出路,闭集外的 `kind` 忽略;`remedies` 缺席 = 无出路可渲染。只读 `remedy` 句的消费者看不到 `permission_mode` 那条出路(此前句子里有,现在只在数据里)。服务部署零动作。
344
+
345
+ 14. **引擎 7.56.0 的五个新键本版刻意不投:`tool_start.requestedBy`、`tool_end.requestedBy`、`tool_end.answeredBy`、两个出口的 `hostFloor`(登记披露;无消费方动作)**:无消费方动作。这五位是引擎新增、本服务的帧投影登记簿表态「不投」的键(扩展自己发起调用的归因三位:本部署挂的每张注册都声明 `uses.calls: []`,零到达;主机底线姿态两位:本服务不声明 `RunnerDeps.hostFloor`,恒不会被铸出)。它们在 7.136.0 的 wire 上从未出现过,所以不是面丢失;翻转条件与理由见 CHANGELOG 7.137.0 节同名条。
346
+
347
+ 15. **本版其余 wire 面变化的消费方动作逐面表态(多数零动作;设备执行器的修订 3、`attachments.mcpUnavailable`、`resultEntryIds` 各有一句真动作)**:CHANGELOG 7.137.0 节里下列 wire 面的变化,逐面写消费方要做什么:
348
+ - **会话同步拉取口**(`GET /v1/sessions/:id/sync/manifest` · `…/entries` · `…/history/blobs/:hash`):库断连(含排在最前的会话门那一读)与部署错配(缺表 / 权限拒)由 `500 internal.error` 改答 `503 state.file_history_unreadable`,
349
+ 体带 `permanence`(连接类 `transient` / 部署错配 `terminal`)。**消费方动作**:按 `permanence` 分支 —— `transient` 稍后重发同一请求;`terminal` 不重试、报运维(运维建表 / 授权之后同一请求可再发);
350
+ 别再拿这三口的 `500` 当这两类故障的信号。文件历史店的故障答(`422 adopt_failed` / `restore_failed` 等)对缺表 / 权限拒同样带 `permanence: "terminal"`,同一读法。
351
+ - **`invalid_session`**:已存日志父链断裂的会话,`POST /v1/tasks` 同步腿由 `200` + failed 体改 `500 invalid_session`;`GET /v1/sessions/:id` / `…/memory-status` 的码由 `internal.error` 改 `invalid_session`。
352
+ **消费方动作**:当确定性失败处理(重试改不了判 —— 对 5xx 自动重试的端对这个码别重试),出路是换新会话或从断点之上的条目分叉。
353
+ - **`inheritEnv` 的三只 `400 request.field_invalid`**:拒体多 `field: "inheritEnv"` 与 `reason`(`unknown_word` · `not_a_string` · `lane_not_host` · `no_authorizer_session`)。**无动作**(加性;严格校验拒体键集的客户端放行这两键)。
354
+ - **`409 resume.constraint_rejected` 体的 `acceptableForm`**:**消费方动作**(批准界面):在场就把那一形呈给批准人、照它再批(读法与审批卡上的 `args` 同一种:已脱敏,超帽 ⇒ 缺席);缺席照旧。
355
+ - **`wiring_manifest.skills`**:**无动作**(加性;对 `wiring_manifest` 键集做严格校验的消费方放行它)。名册列的是这条 run **交给**引擎的技能;引擎对单只技能有大小上限,超过的那一只名册里有、引擎不装(CHANGELOG 同条的已知残余)。
356
+ - **`deviceExecutor.relayUrl`**:**消费方动作**(设备拨号方):在场就拨它、不再自己拼引擎地址 + `wsPath`;缺席照旧拼。
357
+ - **`inherit_env.names_withheld`(会话流通告)**:**无动作**(加性;渲染通告的宿主可按 `code` 显示「这些变量没给工具 shell」—— 只有名字没有值,执行环境说不出时 `state: "unknown"`;闭集外的码照旧忽略)。
358
+ - **设备协议修订 3 与结局码 `name_too_long`**(执行器实现者):能力位 `deviceExecutor.protocolVersion` 与 challenge 帧报 `3`。**动作**:要报「路径里有一段超过文件系统名字上限」的执行器,按随包 `docs/DEVICE-EXECUTOR-PROTOCOL.md` §1.2
359
+ 声明修订 3(取 challenge 的与自己实现的较小者)再发 `name_too_long`(只用于文件指令);仍声明 1 / 2 的执行器不受影响,别发这个词。读文件失败码的调用方:`name_too_long` 与 `not_found` 同读(文件不在)。
360
+ - **`attachments.mcpUnavailable`**(请求键,布尔):**消费方动作**:要关掉引擎的「这一回合有 MCP 服务器挂不上」附件帧的调用方发 `attachments.mcpUnavailable: false`(缺省 = 开);非布尔 ⇒ `400 request.field_invalid`。
361
+ 7.136.x 上这个键被静默丢(压回缺省开),所以别按版本号嗅探 —— 对 7.136.x 发它是无害的无效动作。
362
+ - **`result.resultEntryIds`**(引擎的结果键,随整只结果过境):**消费方动作**(可选):要「这段答复对应会话里哪几条消息」的读它(会话条目 id,会话序;空表 = 没读自任何已提交消息,缺席 = 出处不明,两者不同读);不读的忽略未知键即可。
363
+
364
+ 16. **7.136.x 停下、技能请求项带 `mods` 的任务续跑失败(行为变更;新提交早已 400)**:7.136.x 的受理门容技能项的未知键,引擎 7.55.x 忽略 `skills[].mods`,带它的请求照常成功;本版起新提交带它 ⇒ `400 request.field_invalid`。
365
+ 7.136.x 上停下、存下的请求体里技能项带 `mods` 的任务,本版续跑时这一项原样交给引擎 7.56.0,引擎把它当一张技能扩展注册读、形不对即拒 —— 那一次续跑失败(7.136.x 上它被忽略)。
366
+ **怎么核**:只有手写过 `skills[].mods` 的调用方会有这种停驻任务。**做法**:升级前在 7.136.x 上决完或取消它们;升级后撞上的,取消后去掉 `mods` 重提。
367
+
368
+ 17. **订正 7.136.0 节第 4 条:没有返回任务目标全文的读口(`GET /v1/runs/:id` 不带目标)**:7.136.0 节第 4 条让「把 inbox `objective` 当完整目标用的」消费方「改读 run 详情面」—— 这句不真:
369
+ `GET /v1/runs/:id` 不带任务目标(没有 `objective`,也没有 `objectivePreview`)。本服务**没有返回任务目标全文的读口**:inbox 行的 `objective` 与 `GET /v1/assistant/tasks` 的 `objectivePreview`(写入时已脱敏、约 120 字符)是目标唯一的读数。
370
+ **消费方动作**:要全文展示 / 按全文匹配的,在提交时自己留存目标(提交方本来就持有它);会话历史里那一轮的用户消息是引擎处理过的输入(部署的钩子可能在前面加了文字),不保证与提交的目标逐字相同,别把它当目标原文。
371
+
10
372
  ## 7.136.0 —— 中心登录令牌必须带 `scope`,不带的令牌验证不过(安全;行为面收紧,BREAKING;另含嵌入方 `webAdminJwtVerifier` 类型面) · anthropic 车道两把凭据同设起服拒(`ANTHROPIC_API_KEY` 与 `ANTHROPIC_AUTH_TOKEN`;行为收紧) · 一次性迁移 M5 退役(持久数据面;行为变更;嵌入方 `OneTimeMigrationReport` 去两键〔BREAKING,类型面〕;跳过 7.104.0–7.135.x 直升的库补列与铸令牌要自己做) · `GET /v1/assistant/inbox` 行的 `objective` 改成 run 行的目标预览(wire 值变更) · 审批卡信封多一个键 `approvalCard`(整队一次滚完;回滚到 7.135.x 时待决卡按 fail-safe 出口收场) · k8s 工作区快照桶起服时核存在性:没建桶的部署起服拒(行为收紧;升级前确认桶在) · `WORKSPACE_SNAPSHOT_PREFIX` 成为 `/` 分隔的闭集路径:不合形起服拒、未配快照存储也核(行为收紧;同时放宽到多段) · 子进程的命令行停驻时只以封签落盘(安全;零动作,升级序与回滚要留意:先停光 7.135.x 副本再起第一个 7.136.0 副本)
11
373
 
12
374
  1. **中心登录令牌必须带 `scope` —— 不带的令牌自本版起验证不过(安全;行为面收紧,BREAKING;另含嵌入方类型面)**:鉴权桥(`SEMA_WEB_ADMIN_URL` 在位默认开,或 `AUTH_BRIDGE_ISSUER`)
@@ -2447,7 +2809,7 @@
2447
2809
  - **用户可见(引擎 7.40.0,零配置动作)**:`settings.permissions.ask` 里的 `Read(<path>)` 规则现在也管 Grep / Glob 在该路径下的搜索(各出一张 Read 卡;无审批面 ⇒ 拒),`Edit(<path>)` ask 规则也管 Write / NotebookEdit;
2448
2810
  Read 工具结果不再带常驻的内容安全提醒(依赖那句约束弱模型的部署,把同一句放进自己的 `appendSystemPrompt`)。
2449
2811
 
2450
- ## 7.114.0(车UW,S-995;车UY)—— `settings.hooks` 工具事件 matcher:别名写成正则形的同一个错误,提交当场 400(7.112.0 只拒字面形) · `@sema-agent/settings-schema` 7.0.1 + `@sema-agent/core` 7.39.2:车道 / 存储词表改读正本 · 写了 `remote-docker` 的 `config.d/remote-exec.json` 拒启 · local 车道坏会话规则文件改拒 · 被拒的 `resumeAt` 不再挪会话叶
2812
+ ## 7.114.0(车UW;车UY)—— `settings.hooks` 工具事件 matcher:别名写成正则形的同一个错误,提交当场 400(7.112.0 只拒字面形) · `@sema-agent/settings-schema` 7.0.1 + `@sema-agent/core` 7.39.2:车道 / 存储词表改读正本 · 写了 `remote-docker` 的 `config.d/remote-exec.json` 拒启 · local 车道坏会话规则文件改拒 · 被拒的 `resumeAt` 不再挪会话叶
2451
2813
 
2452
2814
  - **🔴 settings 面硬破坏(响亮拒,无迁移代码、无兼容形)**。① *谁受影响*:提交体 `settings.hooks` 里 PreToolUse / PostToolUse / PostToolUseFailure 的 `matcher` **选中引擎工具别名、却选不中它的正名**的 —— 7.112.0 只拒字面的 `ListPeers` / `Read|ListPeers`,
2453
2815
  `^ListPeers$` / `ListPeers.*` / `(ListPeers)` 这类正则写法当时 200、钩子永不命中(core 按 wire 名匹配,别名不是 wire 名)。判据现在是对 core 工具目录、按 hook-runner 运行期**同一只**匹配函数求值(字面 / 名字表读法:`|` 与 `,` 分隔、逐段 trim,与 CC 2.1.280 同形;区分大小写)。
@@ -2534,17 +2896,17 @@
2534
2896
  旧二进制的收敛只扫 `state = 'open'`,不受影响。
2535
2897
  - **嵌入方(类型面)**:包根导出的 `SettleHow` 多一个词 `consumed`(对它穷举的 switch tsc 红即通知);`TaskSpec.outputStyle`(core 7.39.0 新席)本服务不接、请求面不收。
2536
2898
 
2537
- ### 运维日志事件名退役一族(车 UQ S-990 / 车 UR S-1000 / S-569)—— 按事件名配告警 / 数行的运维要改配
2538
- - **退役(不再逐记录发 warn)**:`session_repo_corrupt_read` · `workflow_journal_corrupt_read` · `workflow_run_corrupt_read` · `roster_corrupt_read` · `background_agent_corrupt_read`(该座已删,披露归 backend 的 `file_store_corrupt_read`)· `mailbox_corrupt_read`(S-990 六座);`approval_ask_journal_corrupt_read` · `run_store_corrupt_read` · `resume_anchor_corrupt_read` · `send_file_ledger_corrupt_read` · `approval_ask_audit_corrupt_read` · `workflow_notify_journal_corrupt_read` · `workflow_agent_session_ledger_line_rejected` · `user_input_ledger_corrupt_read`(S-1000 八座)。
2539
- - **替代读法(F 类座纪律,同一只记录器)**:每座一个 tag —— 进程内**一次** `fail_open` warn(首条明细 + 指路)、`fail_open_total{tag}` 计数每命中 +1、`SEMA_FAILOPEN_PROBE=1` 时每命中一行探针(`kind=record path= line= form= reason=`);tag 名见 `docs/FAIL-OPEN-CENSUS.md`(第 110–113 / 115 / 117 行与 S-582 / S-928 / S-967 / S-977 既有行)。
2540
- - **保持逐命中响亮(安全轴混座,不退役)**:`file_store_corrupt_read`;其 session-policy 脸的坏读今天仍 fail-open(core #1299 修后改拒),server 7.113.0 起同时计 `server.session-policy.corrupt-read-fail-open`(P-DEBT)。
2899
+ ### 运维日志事件名退役一族(车 UQ / 车 UR)—— 按事件名配告警 / 数行的运维要改配
2900
+ - **退役(不再逐记录发 warn)**:`session_repo_corrupt_read` · `workflow_journal_corrupt_read` · `workflow_run_corrupt_read` · `roster_corrupt_read` · `background_agent_corrupt_read`(该座已删,披露归 backend 的 `file_store_corrupt_read`)· `mailbox_corrupt_read`(车 UQ 六座);`approval_ask_journal_corrupt_read` · `run_store_corrupt_read` · `resume_anchor_corrupt_read` · `send_file_ledger_corrupt_read` · `approval_ask_audit_corrupt_read` · `workflow_notify_journal_corrupt_read` · `workflow_agent_session_ledger_line_rejected` · `user_input_ledger_corrupt_read`(车 UR 八座)。
2901
+ - **替代读法(F 类座纪律,同一只记录器)**:每座一个 tag —— 进程内**一次** `fail_open` warn(首条明细 + 指路)、`fail_open_total{tag}` 计数每命中 +1、`SEMA_FAILOPEN_PROBE=1` 时每命中一行探针(`kind=record path= line= form= reason=`);tag 名见 `docs/FAIL-OPEN-CENSUS.md`(第 110–113 / 115 / 117 行与其余既有行)。
2902
+ - **保持逐命中响亮(安全轴混座,不退役)**:`file_store_corrupt_read`;其 session-policy 脸的坏读今天仍 fail-open(引擎修后改拒),server 7.113.0 起同时计 `server.session-policy.corrupt-read-fail-open`(P-DEBT)。
2541
2903
  - **run-local 车道**(前台 CLI 进程)的会话 repo 仍走混座逐命中 warn,不降。
2542
2904
 
2543
- ### 会话读三口的非属主 404(车 UQ S-989;**安全修复:存在性探测口闭合**;wire 值变更)
2905
+ ### 会话读三口的非属主 404(车 UQ;**安全修复:存在性探测口闭合**;wire 值变更)
2544
2906
  - **修前(7.112.0 及更早;7.103.x 的 detail 口读码已是此形,head / events 两口与更早版本未逐版核)**:`GET /v1/sessions/:id`(detail / head / events)对**非属主**调用方答 `not_found.run` + run 长文,对**不存在**的会话答 `not_found.session` + `session not found` —— 同一端点两臂的码与句子都不同,多租户部署里任何持有效凭据的调用方可以据此判断「别人的某个会话 id 存不存在」(读不到内容,只能探存在性;7.112.0 发布字节黑盒实测可区分)。**7.113.0 起两臂逐字节相同**(`not_found.session` + `session not found`)。多租户部署(`REQUIRE_PRINCIPAL=true`)建议升到 7.113.0 及以上;单用户部署没有「非属主」这一臂,不受影响。
2545
2907
  - **兼容面**:读 `not_found.run` 判「会话读被拒」的旧端要改读 `not_found.session`;属主 200 不变;run 面(`/v1/runs/:id`)不变。
2546
2908
 
2547
- ## 7.112.0(车UG,S-924)—— `settings.hooks` 里按工具别名写的 matcher 提交当场 400(此前静默不命中)
2909
+ ## 7.112.0(车UG)—— `settings.hooks` 里按工具别名写的 matcher 提交当场 400(此前静默不命中)
2548
2910
 
2549
2911
  - **🔴 settings 面硬破坏(响亮拒,无迁移代码、无兼容形)**。① *谁受影响*:提交体 `settings.hooks` 里 PreToolUse / PostToolUse / PostToolUseFailure 的 `matcher`
2550
2912
  是**引擎工具别名**的(今天只有 `ListPeers` → `ListAgents`;别名表读 core 静态工具目录)—— 它们**早就不命中**(post 两事件自 7.107.0 / core 7.36.0,PreToolUse 一直),只是没人告诉写的人。
@@ -2552,38 +2914,38 @@
2552
2914
  不再是「接受、hook 永不跑」。耐久 resume 重放**不判**(会砖 parked 任务):升级前就 parked 的任务,其存量 body 里的别名 matcher 在续跑腿照旧永不命中、同一份 hooks 里其余钩子照常生效(与 7.111.0 逐字同)。
2553
2915
  嵌入方经 `resolveSpec` 席挂的工具别名在受理面看不见,不在本门射程。
2554
2916
 
2555
- ## 7.111.0(车TA,S-961 / S-972)—— `wiring_manifest` 帧 +`instructions` 段(additive,零动作)
2917
+ ## 7.111.0(车TA)—— `wiring_manifest` 帧 +`instructions` 段(additive,零动作)
2556
2918
 
2557
- - **wire(additive,零动作)**:`wiring_manifest` 帧(四条腿:流式 SSE / 账本行 / 非流式 `wiringManifest` 回执 / 续跑腿)多一段本服务自铸的 `instructions: { selected: string[] }` = 这条腿选中的项目指令文件(相对 cwd 的链成员);`[]` = 没有,缺席 = 无陈述(契约附录 G.21)。按封闭 schema 校验该帧的消费方加这一可选键;不要它的部署 `PROJECT_MEMORY_ENABLED=false`(连同项目记忆注入一起关)。`task.user_steer_undrained{cause:"crashed"}` 的 `message` 改句序(行动句在前、< 400 字符),`detail` 不变 —— 按文本匹配的脚本改读 `detail.cause`(S-972)。
2558
- - **会话删除 / 托管留存级联接上用户输入受理账本(车TC,S-965;零 DDL、零动作)**:`DELETE /v1/sessions/:id` 与 SQL 后端的托管留存清扫自本版起连带删掉该会话的受理行(SQL `user_input_acceptance` 按 `session_id` 删;local `ledger.jsonl` 追加一行会话级墓碑 `{"kind":"erased","sessionId":…,"at":…}`);`DELETE` 回执形不变。**回滚**(local 车道):≤7.110.x 不认 `erased` 行 —— 启动 warn `user_input_ledger_corrupt_read`,被删会话的行在旧进程里复现;要干净回滚,停服后删 `<localDataRoot>/user-input-ledger/ledger.jsonl`(代价 = 丢掉还没告知的崩溃丢失提醒)。SQL 车道回滚无影响。**嵌入方(类型面硬破坏)**:`UserInputLedgerStore`(包根导出型)新增必选 `deleteBySession(sessionId): Promise<number>`;自建 `StoreBackend.userInputLedger()` 的嵌入方 tsc 红即通知。
2559
- - **同步子代的 steer 入用户输入受理账本(车TF,S-966;零 DDL、零动作)**:`POST /v1/runs/:id/subagents/:target/steer` 自本版起与 run 自己的 steer 同一本账(先账后引擎;行记在回执上的那条 run 名下)——进程在子代收场前崩了 ⇒ 同会话下一条 run 首拍的 `task.user_steer_undrained{cause:"crashed"}` 把它并进那条 run 的条数;账本写不进 ⇒ 该路由回 **503 `steering.ledger_unavailable`**(此前 200);200 回执 additive 多一个 `messageId`(按封闭 schema 校验回执的消费方加这一可选键)。workflow agent 的 steer 不变(不入账,崩溃丢失仍零告知,另票)。**回滚**:无数据动作(行形不变;≤7.110.x 读得懂这些行,照常收敛 / 告知)。
2560
- - **用户输入受理账本收敛判词合一 / SQL 坏行逐行跳过(车TD,S-969;零 DDL、零动作)**:local 车道 boot 收敛自本版起读 run 行 —— 前世进程没结清、而承载它的 run 已正常收场 / 已挂起的受理补结清、不再告知(7.110.x 一律按崩溃告知);SQL 表里读不出的行逐行跳过 + 计数 `server.user-input-ledger.corrupt-record-skipped`,其余照常(7.110.x 整页读失败)。**嵌入方(类型面硬破坏)**:`UserInputLedgerStore.listOpen` 返回 `Promise<OpenScanPage>`(`{ open, next? }`,`next` = 这一页原始末行的键、缺席 = 扫到底;包根新导出 `OpenScanPage`)—— 自建店改交页对象、读不出的行自己跳过并照原始行给游标;`WriterGoneEvidence` 改为 `{ kind, runs }`(两臂都带 run 店读口)。tsc 红即通知。**回滚**:回到 7.110.x 无数据动作(账本行形不变)。
2561
- - **`@sema-agent/core` 7.38.0 → 7.38.2(车TG;两只 patch,core 硬破坏 0、wire 键 / 码 / 闭集零变化,零动作)**:① 内建读拒表的家锚定行(`~/.sema/settings.json` 等)另落**账户家**(core 7.38.1 #1244,S-941)—— 引擎进程的 `HOME` 被改指时,账户真实家下的同名文件由「读得到」变为 `read_path_denied`;真要读的部署用 `READ_DENY_BUILTIN_EXCLUDE` 删那一行。S-941 时期按 DEPLOY-PREREQS 加的 `READ_DENY_PATTERNS` 不锚家同名行可撤(不撤无害)。账户查询无答的主机上这些行在任何位置判(项目自己的 `.sema/settings.json` 也拒,一次 `console.warn`,下一条 run 重问)。② local 车道 File 店族的 JSONL 末段整条记录缺换行 ⇒ 认下并在下次打开补换行(core 7.38.2 #1278,S-975);末段非对象 ⇒ 截 + 多一条 `corrupt-record-skipped` 计数。**回滚**到 ≤7.110.x:回退版本的 core 会把「只缺换行」的末行截掉(只在崩溃留下的那一形上;盘上格式不变,零数据动作)。
2919
+ - **wire(additive,零动作)**:`wiring_manifest` 帧(四条腿:流式 SSE / 账本行 / 非流式 `wiringManifest` 回执 / 续跑腿)多一段本服务自铸的 `instructions: { selected: string[] }` = 这条腿选中的项目指令文件(相对 cwd 的链成员);`[]` = 没有,缺席 = 无陈述(契约附录 G.21)。按封闭 schema 校验该帧的消费方加这一可选键;不要它的部署 `PROJECT_MEMORY_ENABLED=false`(连同项目记忆注入一起关)。`task.user_steer_undrained{cause:"crashed"}` 的 `message` 改句序(行动句在前、< 400 字符),`detail` 不变 —— 按文本匹配的脚本改读 `detail.cause`。
2920
+ - **会话删除 / 托管留存级联接上用户输入受理账本(车TC;零 DDL、零动作)**:`DELETE /v1/sessions/:id` 与 SQL 后端的托管留存清扫自本版起连带删掉该会话的受理行(SQL `user_input_acceptance` 按 `session_id` 删;local `ledger.jsonl` 追加一行会话级墓碑 `{"kind":"erased","sessionId":…,"at":…}`);`DELETE` 回执形不变。**回滚**(local 车道):≤7.110.x 不认 `erased` 行 —— 启动 warn `user_input_ledger_corrupt_read`,被删会话的行在旧进程里复现;要干净回滚,停服后删 `<localDataRoot>/user-input-ledger/ledger.jsonl`(代价 = 丢掉还没告知的崩溃丢失提醒)。SQL 车道回滚无影响。**嵌入方(类型面硬破坏)**:`UserInputLedgerStore`(包根导出型)新增必选 `deleteBySession(sessionId): Promise<number>`;自建 `StoreBackend.userInputLedger()` 的嵌入方 tsc 红即通知。
2921
+ - **同步子代的 steer 入用户输入受理账本(车TF;零 DDL、零动作)**:`POST /v1/runs/:id/subagents/:target/steer` 自本版起与 run 自己的 steer 同一本账(先账后引擎;行记在回执上的那条 run 名下)——进程在子代收场前崩了 ⇒ 同会话下一条 run 首拍的 `task.user_steer_undrained{cause:"crashed"}` 把它并进那条 run 的条数;账本写不进 ⇒ 该路由回 **503 `steering.ledger_unavailable`**(此前 200);200 回执 additive 多一个 `messageId`(按封闭 schema 校验回执的消费方加这一可选键)。workflow agent 的 steer 不变(不入账,崩溃丢失仍零告知,另票)。**回滚**:无数据动作(行形不变;≤7.110.x 读得懂这些行,照常收敛 / 告知)。
2922
+ - **用户输入受理账本收敛判词合一 / SQL 坏行逐行跳过(车TD;零 DDL、零动作)**:local 车道 boot 收敛自本版起读 run 行 —— 前世进程没结清、而承载它的 run 已正常收场 / 已挂起的受理补结清、不再告知(7.110.x 一律按崩溃告知);SQL 表里读不出的行逐行跳过 + 计数 `server.user-input-ledger.corrupt-record-skipped`,其余照常(7.110.x 整页读失败)。**嵌入方(类型面硬破坏)**:`UserInputLedgerStore.listOpen` 返回 `Promise<OpenScanPage>`(`{ open, next? }`,`next` = 这一页原始末行的键、缺席 = 扫到底;包根新导出 `OpenScanPage`)—— 自建店改交页对象、读不出的行自己跳过并照原始行给游标;`WriterGoneEvidence` 改为 `{ kind, runs }`(两臂都带 run 店读口)。tsc 红即通知。**回滚**:回到 7.110.x 无数据动作(账本行形不变)。
2923
+ - **`@sema-agent/core` 7.38.0 → 7.38.2(车TG;两只 patch,core 硬破坏 0、wire 键 / 码 / 闭集零变化,零动作)**:① 内建读拒表的家锚定行(`~/.sema/settings.json` 等)另落**账户家**(core 7.38.1)—— 引擎进程的 `HOME` 被改指时,账户真实家下的同名文件由「读得到」变为 `read_path_denied`;真要读的部署用 `READ_DENY_BUILTIN_EXCLUDE` 删那一行。当时按 DEPLOY-PREREQS 加的 `READ_DENY_PATTERNS` 不锚家同名行可撤(不撤无害)。账户查询无答的主机上这些行在任何位置判(项目自己的 `.sema/settings.json` 也拒,一次 `console.warn`,下一条 run 重问)。② local 车道 File 店族的 JSONL 末段整条记录缺换行 ⇒ 认下并在下次打开补换行(core 7.38.2);末段非对象 ⇒ 截 + 多一条 `corrupt-record-skipped` 计数。**回滚**到 ≤7.110.x:回退版本的 core 会把「只缺换行」的末行截掉(只在崩溃留下的那一形上;盘上格式不变,零数据动作)。
2562
2924
 
2563
- ## 7.110.0(车ST,S-955;小车 SV,S-956;车SX,S-958 / S-959;小车 SA,S-962 / S-963;主会话 S-964;车SW,S-928)—— `@sema-agent/core` 7.38.0(minor,core 硬破坏 0):通告码受众 / 铸者改读 core 表 · `terminal.failed.detail` 过境 · hook 载荷 `permission_mode` = 腿实时模式 · 类对判据走 core 屏 · run-local 无 TTY 拒记部署政策名下 · 复合体读不出词的 PreToolUse 结果交引擎屏 · 🔴 `MEMORY_SYNC_SCOPE` 缺省不再从非 v2 `MEMORY_SCOPE` 派生(拒启) · 崩溃丢掉的 200-applied steer 下一条 run 告知(用户输入受理账本)
2925
+ ## 7.110.0(车ST;小车 SV;车SX;小车 SA;主会话;车SW)—— `@sema-agent/core` 7.38.0(minor,core 硬破坏 0):通告码受众 / 铸者改读 core 表 · `terminal.failed.detail` 过境 · hook 载荷 `permission_mode` = 腿实时模式 · 类对判据走 core 屏 · run-local 无 TTY 拒记部署政策名下 · 复合体读不出词的 PreToolUse 结果交引擎屏 · 🔴 `MEMORY_SYNC_SCOPE` 缺省不再从非 v2 `MEMORY_SCOPE` 派生(拒启) · 崩溃丢掉的 200-applied steer 下一条 run 告知(用户输入受理账本)
2564
2926
 
2565
- - **🔴 记忆同步 env(S-964,配置面硬破坏)**:单用户 file 引擎上设了 `MEMORY_SYNC_URL` / `MEMORY_SYNC_TOKEN`、**没设** `MEMORY_SYNC_SCOPE`、且 `MEMORY_SCOPE` 不是 typed 键(`user:` / `org:` / `proj:` / `userproj:`;含缺省 `local`)的部署**升级后拒启**。此前这一形派生同步层 `user:<MEMORY_SCOPE>` —— 一个本部署从不写的层(写家是裸 `MEMORY_SCOPE`,core 同步按同一个名字取条目)⇒ 同步腿自 142-S2.5-W1 起每轮推 0 条。出路二选一(错误句原文点名):`MEMORY_SYNC_SCOPE=<要复制的层>`,或把 `MEMORY_SCOPE` 设成中心期待的 typed 键(如 `user:<tenant>`,缺省同步层随之同名)。显式 `MEMORY_SYNC_SCOPE` 的部署零变化。
2927
+ - **🔴 记忆同步 env(配置面硬破坏)**:单用户 file 引擎上设了 `MEMORY_SYNC_URL` / `MEMORY_SYNC_TOKEN`、**没设** `MEMORY_SYNC_SCOPE`、且 `MEMORY_SCOPE` 不是 typed 键(`user:` / `org:` / `proj:` / `userproj:`;含缺省 `local`)的部署**升级后拒启**。此前这一形派生同步层 `user:<MEMORY_SCOPE>` —— 一个本部署从不写的层(写家是裸 `MEMORY_SCOPE`,core 同步按同一个名字取条目)⇒ 同步腿自 142-S2.5-W1 起每轮推 0 条。出路二选一(错误句原文点名):`MEMORY_SYNC_SCOPE=<要复制的层>`,或把 `MEMORY_SCOPE` 设成中心期待的 typed 键(如 `user:<tenant>`,缺省同步层随之同名)。显式 `MEMORY_SYNC_SCOPE` 的部署零变化。
2566
2928
 
2567
- - **hook 作者(stdin 载荷契约)**:`permission_mode` 的值源从「请求上的模式词」改为**腿的实时模式**(core 回调上下文 `permissionMode`,plan 腿续跑 / 模式释放后的真实值);PreCompact / PostCompact / StopFailure 三事件与上下文缺席时**不带**该键(此前恒带请求词)。按旧值做分支的 hook 改读实时词、对缺席作「无模式语义」处理。**接手屏**(core 7.38.0):PreToolUse hook 结果越界 `action` / 字串布尔 / `null` 成员 / 不可克隆改写 ⇒ 引擎拒(工具不跑、模型读接手句、`permissionDenied` 观察者响);无 `action` 仍是无异议 —— 本服务映射核在约内,部署自写 hook 自查。经本服务 hooks 复合体(部署基线恒挂,挂了 hooks 的 run 都经过它)的结果同判:读不出词的结果(集外 `action`、非对象 —— 含 `0` / `""` / `NaN`;无异议只认 `undefined` / `null` / `false`)原样交引擎屏 ⇒ 引擎拒(S-959;修前复合体把它读作无异议、照跑,带 `additionalContext` 的还被译成 allow)。
2929
+ - **hook 作者(stdin 载荷契约)**:`permission_mode` 的值源从「请求上的模式词」改为**腿的实时模式**(core 回调上下文 `permissionMode`,plan 腿续跑 / 模式释放后的真实值);PreCompact / PostCompact / StopFailure 三事件与上下文缺席时**不带**该键(此前恒带请求词)。按旧值做分支的 hook 改读实时词、对缺席作「无模式语义」处理。**接手屏**(core 7.38.0):PreToolUse hook 结果越界 `action` / 字串布尔 / `null` 成员 / 不可克隆改写 ⇒ 引擎拒(工具不跑、模型读接手句、`permissionDenied` 观察者响);无 `action` 仍是无异议 —— 本服务映射核在约内,部署自写 hook 自查。经本服务 hooks 复合体(部署基线恒挂,挂了 hooks 的 run 都经过它)的结果同判:读不出词的结果(集外 `action`、非对象 —— 含 `0` / `""` / `NaN`;无异议只认 `undefined` / `null` / `false`)原样交引擎屏 ⇒ 引擎拒(修前复合体把它读作无异议、照跑,带 `additionalContext` 的还被译成 allow)。
2568
2930
  - **嵌入方(类型面,不在包导出面)**:`SERVER_NOTICE_AUDIENCE` / `ServerNoticeCode` / `isServerNoticeCode` / `HookRunnerContext.permissionMode` / `ENGINE_ABSENT_PERMISSION_MODE` 仓内硬删 —— 四枚本服务铸码的受众 / 铸者改读 core `NOTICE_AUDIENCE` / `NOTICE_MINTER`;client-core 镜像行可退役(core 包已含四码)。
2569
2931
  - **结果面(additive)**:`terminal.failed.detail? { kind:"provider_rejected", status, code? }` 过境(同步 200 体 / `done.result` / `GET /v1/runs/:id` / `done` 账本行);判「可改重发」看 `status`(401 / 403 / 429 也带)。`engine_notice` D.3 白名单 +`task.tool_turn_incomplete`(user);`memory.layer_locked_legacy` 明拒(operator)。`/metrics` `brain_echo_dropped_total{field}` 可出现 `field="apiErrorCode"`。
2570
2932
  - **审批面(值层,键不变)**:`askClass` / `classes` 读写两面统一走 core `screenAskClassMembers`:投规范序副本;重复员 / 非规范序首员不符形改判(只在 core 自己不写出的形上);`card_json` 存量卡零影响。
2571
- - **🔴 迁移窗口(core #1213)**:本版提货 core 7.38.0 **仍迁移旧模式键检查点行、不拒**;排空窗到提货 core 7.39.0 的 server 版前(7.109.0 段原句)。
2572
- - **run-local(S-956)**:无 TTY 被拒的 run 不再带 `haltedOnUserRejection`。退出码仍为 1;非 `--json` 停因行从 `task stopped (haltedOnUserRejection) …` 改为 `task incomplete (approval unanswered) …`;门记录 `settlement.kind` `human_refused` → `policy_refused`、`who.party` `person` → `none`;模型读 core 策略句 + 拒因。按 7.101.0 迁移建议读 `--json` 的 `haltedOnUserRejection` 判拒的脚本,改看退出码 / stderr 停因行。同一拍的兄弟调用不再被 `gate.batch_halted` 连坐,各自过门。委派子代里无 TTY 的拒也计数 ⇒ CLI 退 1(更严;TTY 下子代人答 N 仍退 0)。
2573
- - **嵌入方(类型面硬破坏,S-928)**:`StoreBackend`(包根导出型)新增**必选** `userInputLedger(): UserInputLedgerStore`;自建 StoreBackend 的嵌入方 tsc 红即通知(7.109.0 `listByCall` 同形);返回型 `UserInputLedgerStore` 及行型 `UserInputAcceptance` / `NewUserInputAcceptance` / `SettleHow` / `OpenScanCursor` / `WriterGoneEvidence` 自本版从包根导出。
2574
- - **用户输入受理账本(S-928;零动作)**:live 腿 steer 在回 200 之前先落一行受理(local:`<数据根>/user-input-ledger/ledger.jsonl`;SQL:新表 `user_input_acceptance`,
2933
+ - **🔴 迁移窗口**:本版提货 core 7.38.0 **仍迁移旧模式键检查点行、不拒**;排空窗到提货 core 7.39.0 的 server 版前(7.109.0 段原句)。
2934
+ - **run-local**:无 TTY 被拒的 run 不再带 `haltedOnUserRejection`。退出码仍为 1;非 `--json` 停因行从 `task stopped (haltedOnUserRejection) …` 改为 `task incomplete (approval unanswered) …`;门记录 `settlement.kind` `human_refused` → `policy_refused`、`who.party` `person` → `none`;模型读 core 策略句 + 拒因。按 7.101.0 迁移建议读 `--json` 的 `haltedOnUserRejection` 判拒的脚本,改看退出码 / stderr 停因行。同一拍的兄弟调用不再被 `gate.batch_halted` 连坐,各自过门。委派子代里无 TTY 的拒也计数 ⇒ CLI 退 1(更严;TTY 下子代人答 N 仍退 0)。
2935
+ - **嵌入方(类型面硬破坏)**:`StoreBackend`(包根导出型)新增**必选** `userInputLedger(): UserInputLedgerStore`;自建 StoreBackend 的嵌入方 tsc 红即通知(7.109.0 `listByCall` 同形);返回型 `UserInputLedgerStore` 及行型 `UserInputAcceptance` / `NewUserInputAcceptance` / `SettleHow` / `OpenScanCursor` / `WriterGoneEvidence` 自本版从包根导出。
2936
+ - **用户输入受理账本(零动作)**:live 腿 steer 在回 200 之前先落一行受理(local:`<数据根>/user-input-ledger/ledger.jsonl`;SQL:新表 `user_input_acceptance`,
2575
2937
  中央 `ensureSchema` 以 `CREATE TABLE IF NOT EXISTS` 自建,两方言 + 两条索引,无 ALTER、无回填)。账本写不进 ⇒ steer 回 **503 `steering.ledger_unavailable`**(此前 200;引擎零字节)——
2576
2938
  local 车道数据根只读 / 盘满、SQL 车道库不可达时出现,其余路由不受影响。进程崩溃时丢掉的受理在该会话下一条 run 首拍告知 `task.user_steer_undrained{cause:"crashed"}`,
2577
2939
  `GET /v1/sessions/:id` 多一个可选键 `userInputUndrained`(缺席 = 零条)。**回滚**:回到 ≤7.109.x 时账本文件 / 表留着无害(旧二进制不读);滚回之后的崩溃丢失恢复修前的静默。
2578
2940
  - **零数据迁移**;DDL 只有上一条的新表(自建)。
2579
2941
 
2580
- ## 7.109.0(车SK,S-934)—— `@sema-agent/core` 7.37.1(7.37.0 的全部变更 + #1224 工具回合律请求修复,运维通告 `context.tool_turn_repaired` 不上会话流):无人值守腿按类作答(`UNATTENDED_PERMISSION_MODE` 退役,设了即拒启)· ask 类对 `askClass` / `classes` 上 wire · 策略决定对象的普通对象律 · 迁移窗口
2942
+ ## 7.109.0(车SK)—— `@sema-agent/core` 7.37.1(7.37.0 的全部变更 + 工具回合律请求修复,运维通告 `context.tool_turn_repaired` 不上会话流):无人值守腿按类作答(`UNATTENDED_PERMISSION_MODE` 退役,设了即拒启)· ask 类对 `askClass` / `classes` 上 wire · 策略决定对象的普通对象律 · 迁移窗口
2581
2943
 
2582
2944
  - **🔴 env:`UNATTENDED_PERMISSION_MODE` 设了即拒启**(任何值,含 7.106.0 的缺省 `bypassPermissions`;拒因带 `config.env_key_retired` 并点名键)。
2583
2945
  **迁移**:从 `.env` / 编排清单里删掉它。leader worker / leader 修复腿 / `sema` 一次性 CLI(run-local)及 leader worker park 的 `/decide` 续跑,
2584
2946
  自本版起恒按 `default` 跑,审批席**按类作答**:机器只答引擎盖了 `ordinary` 类的问(普通写、非只读 shell 的形状层问 —— 照常落地)。
2585
2947
  **写面与 `ordinary` 的边界**:`roots` 只约束 Write / Edit 这类结构化文件工具;shell 的根外写与 Read 工具的根外读属 core `ordinary`,无人值守腿上由机器答(与 ≤7.108.0 的 bypass 放行同一落地结果,记法不同)。
2586
- **审计读者**:机器按类放行在 core 门记录里写成 `settlement.kind:"human_allowed"` / `who.party:"person"`(core 没有「机器放行」归属词,S-953 转 core)—— 无人值守腿上读作机器放行;无席且无 durable 块的 leader 腿被拒的问(run-local 有本地席,不走这一词)结算词 `no_approver` → `approver_unavailable`,按词告警的运维改比码。
2948
+ **审计读者**:机器按类放行在 core 门记录里写成 `settlement.kind:"human_allowed"` / `who.party:"person"`(core 没有「机器放行」归属词,已转 core)—— 无人值守腿上读作机器放行;无席且无 durable 块的 leader 腿被拒的问(run-local 有本地席,不走这一词)结算词 `no_approver` → `approver_unavailable`,按词告警的运维改比码。
2587
2949
  - **🔴 行为面(安全轴收紧)**:这些腿上此前被缺省 `bypassPermissions` 放掉的六类问 —— shell 读会话目录外(`probe`)、MCP / A2A 工具标记、
2588
2950
  transcript 写、规则店读不出(`rule_unreadable`)、共享制品读(`artifact_shared_read`)—— 改为**不答**:run-local 有终端时问你 y/N、无终端当场拒;
2589
2951
  leader 各腿配了 durable 审批块 ⇒ park 到 `/v1/approvals/:id/decide`,没配 ⇒ 当场拒。写保护表目标从「策略层路径拒行拒(人在场也答不了)」改成一问
@@ -2597,8 +2959,8 @@
2597
2959
  `allow` / `deny` / `ask` 之一;契约成员必须是对象**自有可枚举**成员(不放原型上、不靠 getter、不靠 Proxy);改写(`updatedInput` 等)只放可克隆纯数据。
2598
2960
  不合 ⇒ 接手即拒(工具不执行)。本服务自身的策略 / hook 全是字面对象或展开(亲核),部署自写的 `ToolPolicy`(嵌入方)按此自查。
2599
2961
  **委派**:祖先层一次「是」只覆盖它答过的类 —— 子代门查到更严的类(写保护、根外读)会再出一张卡;带出网 / 不可逆标记的工具在委派下首卡即
2600
- `operator_forced`(`bypassPermissions` 不放它)。持久 ask 店车道(流内审批协议上场的部署)上第二张卡同样出卡(S-944,见下一条)。
2601
- - **🔴 安全轴(S-944):持久 ask 店车道上的 askId 身份含这一问的类集**。委派下同一调用的第二张卡(类集不同)自本版是**新问**:新行、出自己的卡、
2962
+ `operator_forced`(`bypassPermissions` 不放它)。持久 ask 店车道(流内审批协议上场的部署)上第二张卡同样出卡(见下一条)。
2963
+ - **🔴 安全轴:持久 ask 店车道上的 askId 身份含这一问的类集**。委派下同一调用的第二张卡(类集不同)自本版是**新问**:新行、出自己的卡、
2602
2964
  等人答这一问 —— 此前它与首卡同 askId,被首卡的「是」回放。同一调用同类集的重试照旧幂等。**行为面(收紧)**:会话授权(`allow_session` /
2603
2965
  耐久 `remember:"session"`)不再代答「这次调用在这条腿上已出过卡」的后续问(同一调用的另一类集问)—— 出卡,人答。**wire 值变更**:不透明 `askId`(呈卡帧、
2604
2966
  `POST /v1/tasks/:taskId/asks/:askId/decision`)对同一调用的取值与 ≤7.108.0 不同(形不变,64 位 hex);持久 `approval_ask.ask_id` 主键的派生同变,
@@ -2608,25 +2970,25 @@
2608
2970
  会话授权(live `allow_session` / 耐久 `remember:"session"`)**不会**替它代答 —— 一揽子放行的复核按**调用**读(这次调用在这条腿上有任何行,
2609
2971
  含旧派生写的人拒 / 挂着的卡 ⇒ 不短路),与 ask 身份无关。**迁移**:自建 `StoreBackend`(不走 `createStoreBackend`)的嵌入方须实现 `ApprovalAskStore.listByCall`(类型面硬破坏,tsc 红即通知);部署零 DDL、零数据迁移。**滚动升级**:混版窗内旧版副本接管本版写过的腿读不到新派生行(反向),
2610
2972
  与 7.107.0 段「持久面反向不兼容边界」同一处置:同一存储上不要让旧版实例接管本版在跑的腿。
2611
- - **leader worker 的增量上传循环随 env 收尾(S-949,P1;嵌入方 / 夹具可见)**:worker `executionEnvFactory` 交出的 env 若**没有 `destroy()`**,工厂当场拒收(与集成沙箱 / grader 同一道闸;生产三车道 e2b / k8s / host 都有);stage 末步起循环、finalize 首步停循环(先于 belt 与真 destroy,等每一代退出 ≤30 s),循环的每次上传带 `curl --max-time 25`;工作区多出 `.leader-upload-loop.sh` / `.gen` / `.seq` / `.pid.<代>`(无凭据)。**迁移**:自建 worker env 的嵌入方补 `destroy()`;依赖「循环与 belt 并跑」时序的无;收尾每 worker 常态多 ≤1–2 s(等循环下一拍退出),上界 = stop 等待 30 s(循环正卡在一次上传上时)。已知边界:S-950(e2b 车道循环是否真活着未核)/ S-951(stop 超界残余窗)。
2612
- - **目录条目 `headers` 两条读腿打通(S-935,settings-schema 6.4.0)**:`config.d/models.json` 与配置中心写的 `models[].headers` 自本版起到达目录(7.108.0 被读腿剥掉)。
2973
+ - **leader worker 的增量上传循环随 env 收尾(P1;嵌入方 / 夹具可见)**:worker `executionEnvFactory` 交出的 env 若**没有 `destroy()`**,工厂当场拒收(与集成沙箱 / grader 同一道闸;生产三车道 e2b / k8s / host 都有);stage 末步起循环、finalize 首步停循环(先于 belt 与真 destroy,等每一代退出 ≤30 s),循环的每次上传带 `curl --max-time 25`;工作区多出 `.leader-upload-loop.sh` / `.gen` / `.seq` / `.pid.<代>`(无凭据)。**迁移**:自建 worker env 的嵌入方补 `destroy()`;依赖「循环与 belt 并跑」时序的无;收尾每 worker 常态多 ≤1–2 s(等循环下一拍退出),上界 = stop 等待 30 s(循环正卡在一次上传上时)。已知边界:e2b 车道循环是否真活着未核 / stop 超界残余窗。
2974
+ - **目录条目 `headers` 两条读腿打通(settings-schema 6.4.0)**:`config.d/models.json` 与配置中心写的 `models[].headers` 自本版起到达目录(7.108.0 被读腿剥掉)。
2613
2975
  **行为面**:秘密形的头值(形似令牌 / 密钥)在 schema 自由形安全闸即让条目不可用(拒因字段整键 `headers`)。**迁移**:零动作。
2614
- - **🔴 迁移窗口(core #1213;core 7.38.0 发车帖把它改期到 **7.39.0**)**:core 7.39.0 删掉旧检查点行的一次性迁移、并**拒续跑**仍带旧模式键(`autoModeRequested` / `approverPosture` /
2976
+ - **🔴 迁移窗口(core 7.38.0 发车帖把它改期到 **7.39.0**)**:core 7.39.0 删掉旧检查点行的一次性迁移、并**拒续跑**仍带旧模式键(`autoModeRequested` / `approverPosture` /
2615
2977
  doctrine `shellGate`)的行。这类行只可能是 **server ≤7.105.0(core ≤7.33.8)时期停放、至今仍 pending** 的行 —— server 7.106.0(core 7.35.2)起写的行
2616
2978
  与在 7.106.0+ 上续跑过一次的行都已是新形。**在升到提货 core 7.39.0 的 server 版本之前**(7.110.0 提货 core 7.38.0 仍迁移、不拒),把这些行答完或放弃:
2617
2979
  列表 = `GET /v1/approvals`(运维队列;`createdAt` 早于本部署升到 server 7.106.0 那一刻的行)与 `GET /v1/assistant/inbox`;
2618
2980
  决定口 = 工具审批 `POST /v1/approvals/:id/decide`(`:id` = sessionId,体 `{ "decision": "approve" | "deny" }`)、计划审阅
2619
2981
  `POST /v1/assistant/tasks/:id/plan_review`、资源停车续跑 `POST /v1/assistant/tasks/:id/resume`。本版(core 7.37.x)上续跑这类行仍会迁移一次再继续。
2620
2982
  本服务不读、也不判这几个旧键(那是 core 的私有迁移面),只按停放时间给出区间。
2621
- ## 7.108.0(车SI,S-919 / S-929 / S-930 / S-920;车SJ,S-931 / S-925 / S-922 / S-921)—— `@sema-agent/core` 7.36.0 不变:按名策略臂读 core 名字全集 · 有序关停 settle 活卡 · 自助抹除口码表补齐 · 目录条目 `headers` · 出站建连失败通告 · side-query `errorMessage` 脱敏
2983
+ ## 7.108.0(车SI;车SJ)—— `@sema-agent/core` 7.36.0 不变:按名策略臂读 core 名字全集 · 有序关停 settle 活卡 · 自助抹除口码表补齐 · 目录条目 `headers` · 出站建连失败通告 · side-query `errorMessage` 脱敏
2622
2984
 
2623
- - **🔴 安全轴(S-919):本仓收紧方向的按名策略臂(`APPROVAL_DENY` / `APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` / commandPolicy ask 表 / 治理 shell 标 / durable 问题门 /
2985
+ - **🔴 安全轴:本仓收紧方向的按名策略臂(`APPROVAL_DENY` / `APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` / commandPolicy ask 表 / 治理 shell 标 / durable 问题门 /
2624
2986
  supervisor 危险门 / workflow 问与 plan 拒)读 core `ruleNamesOf(req)` 全集,任一名命中即算命中。**只影响**经 `resolveSpec` 席挂引擎名别名的嵌入方工具(`MyShell{aliases:["Bash"]}`):
2625
2987
  修前模型按别名调它一个门都不拦,修后照拦照问。**迁移**:要让某只工具不被某条名单够到,别给它挂那条名单里的引擎名作别名;规则归因 `matchedAskRule` 写命中的那个名。
2626
- - **wire 值(S-929):`GET /v1/approvals` 的 `crashConverged[].cause` 从单值 `"crashed_before_park"` 变闭集 `"crashed_before_park" | "shutdown_before_park"`**(有序关停宽限窗满仍未闭的已批腿;
2988
+ - **wire 值:`GET /v1/approvals` 的 `crashConverged[].cause` 从单值 `"crashed_before_park"` 变闭集 `"crashed_before_park" | "shutdown_before_park"`**(有序关停宽限窗满仍未闭的已批腿;
2627
2989
  `orphanState` / `resumeSafe` 判据同形,`shutdown_before_park` 常态 `decided`、`pending` 形只在故障下出现 —— 持久 ask 店 claim 挂住,或 park 路由的停车行到宽限窗满仍未提交)。
2628
2990
  **迁移**:消费方按 `orphanState` / `resumeSafe` 分桶,不按 `cause` 单值判。**消费方版本约束**:client-core ≤0.82.7 的行校验 `cause !== 'crashed_before_park'` 把新词行计进
2629
- `dropped`(cli 渲「could not be read」,fail-safe、不自动续跑);配套 = client-core 认领 CC-218 的那一版(放宽为两值)。审计账本 settle 行 additive `cause:"shutdown_before_park"` + 第六个记录种类 `interrupted_by_shutdown`。
2991
+ `dropped`(cli 渲「could not be read」,fail-safe、不自动续跑);配套 = client-core 认领这一变化的那一版(放宽为两值)。审计账本 settle 行 additive `cause:"shutdown_before_park"` + 第六个记录种类 `interrupted_by_shutdown`。
2630
2992
  **回滚约束**:回滚到 ≤7.107.0 后,本版写下的 `interrupted_by_shutdown` 行在旧二进制上计 `corruptLines`、boot 那一行 `approval_ask_audit_crash_converged` warn 会响
2631
2993
  (无害:旧读者跳过坏行,settle 行多出的 `cause` 键被忽略)。**park 政策下**:有序关停时握着未决卡的 run 落 `done(suspended)`(修前进程退出把它截断在 running,
2632
2994
  由下一次 boot 收成崩溃孤儿)—— 轮询 run 终态的消费方会看到 suspended,可经 `/v1/approvals/:sessionId/decide` 事后决议。
@@ -2635,19 +2997,19 @@
2635
2997
  下一次 boot 照样列成 pending 孤儿(与崩溃同路;子代(未被追踪腿)卡的腿闭证据不由宿主腿提供 —— 重放的腿证据只对 `legTracked` 行作数;`backend.close()` 排在店的在飞 `put` 静默之后)。
2636
2998
  **`UNATTENDED_APPROVAL_POLICY=deny` 的部署**:有序重启时未决卡当场按部署政策拒、腿带着拒绝再跑至多 10s(模型可能把 run 收成 `completed`),该卡不再出现在
2637
2999
  `crashConverged`(修前是 `crashed_before_park` / pending / `resumeSafe:true`)—— 要事后决议就改 `park` 政策,或在排空窗内答完。
2638
- - **wire 值(S-930):`POST /v1/sessions/:id/memory/erase` 的四种 core 失败形从 500 `internal.error` 改为与 operator 面同码同状态**(409 `memory.erasure_selector_mismatch` /
3000
+ - **wire 值:`POST /v1/sessions/:id/memory/erase` 的四种 core 失败形从 500 `internal.error` 改为与 operator 面同码同状态**(409 `memory.erasure_selector_mismatch` /
2639
3001
  `memory.erasure_evidence_unavailable` / `memory.erasure_census_incomplete`;500 `internal.memory_control_plane_corrupt` 固定句)。**迁移**:按「自助抹除失败恒 500」写死的调用方改按 `errorCode` 分支;
2640
3002
  sdk 15.0.0 的 🚧 live 表征钉随 15.0.1 翻 409。
2641
- - **目录条目 +1 键(S-931):`models[].headers`**(闭集白名单,今天只 `anthropic-beta`、只在 `api: "anthropic-messages"` 条目;表外 / 线路不读 / 值不合形 ⇒ 条目不可用
3003
+ - **目录条目 +1 键:`models[].headers`**(闭集白名单,今天只 `anthropic-beta`、只在 `api: "anthropic-messages"` 条目;表外 / 线路不读 / 值不合形 ⇒ 条目不可用
2642
3004
  `[config.model_entry_invalid]` fields `headers.<名>`)。**⚠️ 本版半场**:settings-schema 6.3.0 读腿剥未知键 ⇒ 经生产配置通道写的 `headers` 到不了目录(只有 LKG / 手写 effective 到得了),
2643
- settings-schema 6.4.0 + server 7.109.0 打通(S-935)。**迁移**:零动作;要今天就用,走 effective 直写通道并接受读腿告警。
2644
- - **通告码 +1(S-925):user 受众 `server.model_unreachable`**(`engine_notice` 帧 / 账本行,先于 `done`;`detail = { code, targetHost, proxyInUse?, remedy, sessionId }`;每腿每目标一次;
2645
- 腿里的辅助模型调用同判 —— 帧说的是端点够不着,不是 run 失败)。**迁移**:按 `code` 渲染的消费方零动作;经 client-core 按受众分发的端在 client-core 镜像 +1 行(0.86.x)前看不到它(S-933,core 7.38.0 入册后两边镜像退役)。
3005
+ settings-schema 6.4.0 + server 7.109.0 打通。**迁移**:零动作;要今天就用,走 effective 直写通道并接受读腿告警。
3006
+ - **通告码 +1:user 受众 `server.model_unreachable`**(`engine_notice` 帧 / 账本行,先于 `done`;`detail = { code, targetHost, proxyInUse?, remedy, sessionId }`;每腿每目标一次;
3007
+ 腿里的辅助模型调用同判 —— 帧说的是端点够不着,不是 run 失败)。**迁移**:按 `code` 渲染的消费方零动作;经 client-core 按受众分发的端在 client-core 镜像 +1 行(0.86.x)前看不到它(core 7.38.0 入册后两边镜像退役)。
2646
3008
  运维面另 +1 日志行 `outbound_connect_failed`(代理只报变量名)与 `GET /v1/diagnostics/wiring` 的 `outbound` 段。
2647
- - **wire 值(S-922):`POST /v1/side-query` 200 体 `errorMessage` 过 `redactErrorMessage`**(键不变;服务商错误体里的密钥形换 `«redacted»`)。**迁移**:按原样错误体做字符串匹配的调用方改比错误码。
2648
- - **零动作(S-921 / S-920)**:披露改真与明拒行保鲜钉,无行为变化。
3009
+ - **wire 值:`POST /v1/side-query` 200 体 `errorMessage` 过 `redactErrorMessage`**(键不变;服务商错误体里的密钥形换 `«redacted»`)。**迁移**:按原样错误体做字符串匹配的调用方改比错误码。
3010
+ - **零动作**:披露改真与明拒行保鲜钉,无行为变化。
2649
3011
 
2650
- ## 7.107.0(车SE,S-907 / S-890;车SF)—— `@sema-agent/core` 7.36.0:post 钩子收 wire 名 · 双引擎名声明拒 · 工具调用 id 越界折叠(服务商拿回原串)· 两只恒真能力位删
3012
+ ## 7.107.0(车SE;车SF)—— `@sema-agent/core` 7.36.0:post 钩子收 wire 名 · 双引擎名声明拒 · 工具调用 id 越界折叠(服务商拿回原串)· 两只恒真能力位删
2651
3013
 
2652
3014
  - **🔴 hooks:PostToolUse / PostToolUseFailure 的 matcher 与 payload `tool_name` 改为调用派发到的工具的 wire 名**(此前是模型拼写;PreToolUse 本来就是 wire 名)。
2653
3015
  按工具**别名**写的 post matcher(及条目 `if` 条件的名部)不再命中(只影响执行后面,不放宽任何决定)。**迁移**:matcher 写 wire 名;滚动升级期两名都写(本服务不做双读)。
@@ -2661,16 +3023,16 @@
2661
3023
  **零动作**(join 照旧成立);与服务商日志对账的运维读 `wireId`,或服务端结构化日志 `engine_notice` `route.tool_call_id_folded`(每 run 一行,operator 受众,不上会话流)。
2662
3024
  升级前已 park 的行以原串为键,新版 resume 不再折叠(askId 不变、卡照旧可答)。
2663
3025
  - **耐久停车行 `pendingAction.names` 的序改「拼写先」**(门判定那张脸)。本服务任何 wire 面都不投 `names`;只影响直读店行(SQL `checkpoint` 列 / local 检查点文件)的工具 —— 按 `names[0]` 猜 wire 名的改读 `toolName`。
2664
- - **🔴 wire(能力面,车SF S-899):`GET /v1/capabilities` 的 `modeShellGateTranslation` 与 `permissionModeAuto.intentArming` 删**(两位 7.106.0 起恒 `true`,零信息)。
3026
+ - **🔴 wire(能力面,车SF):`GET /v1/capabilities` 的 `modeShellGateTranslation` 与 `permissionModeAuto.intentArming` 删**(两位 7.106.0 起恒 `true`,零信息)。
2665
3027
  **迁移**:壳不再按 `modeShellGateTranslation` 决定是否注 `MANUAL_MODE_SHELL_GATE`(缺席不是「老 server」;直接不注);`intentArming` 的读者改读 `armed` / `reason`。**真实后果**:已发布 cli ≤1.0.139 的引擎附着门把缺席读成旧引擎 ⇒ 同机多安装下 headless `-p` 拒复用 ≥7.107.0 引擎、交互车道误报一行(fail-closed 有出路:停那台引擎或升级较旧的 cli 安装 ≥1.0.140);sdk 14.0.0 仍把 `intentArming` 写成必填(门 6 红在围栏头校准 7.106.0),随 sdk 14.1.0 删两位 + 抬围栏头。
2666
- - **请求面模式词表(S-902)**:五词受理集不变、`dontAsk` 仍 400 `request.field_invalid`;三处 400 拒句里的词序改随 core `PERMISSION_MODES` 序(文案值变、码不变)—— 按字节比对拒句的测试改比码。
3028
+ - **请求面模式词表**:五词受理集不变、`dontAsk` 仍 400 `request.field_invalid`;三处 400 拒句里的词序改随 core `PERMISSION_MODES` 序(文案值变、码不变)—— 按字节比对拒句的测试改比码。
2667
3029
 
2668
- ### 升级须知补三条(S-923 + 合并复审)
3030
+ ### 升级须知补三条(含合并复审)
2669
3031
  - **工具名帧的拼写**:fresh 腿 `tool_start` / `tool_end.toolName` 是模型拼写(与 7.106.0 同);升级前 park 的行续跑仍给 wire 名(`names` wire 名在先);**只有 7.107.0 起按别名 park 的调用**续跑帧改给拼写。壳按 `toolCallId` join,不按帧的 `toolName` 归一;要 wire 名读 PreToolUse / post 钩子上下文的 `toolName`、`wiring_manifest.tools` 名册或停车行 `pendingAction.toolName`(帧不能反推)。
2670
3032
  - **把引擎手工具名挂成别名的嵌入方**(`aliases:["Read"]` 一类):中断调用按较不安全效应判、效应面按较不安全效应记(只在该名挂载不重登效应时)、结果预算不再豁免、微压缩清理不再达它(上下文可能变大)—— 升级前排空这类声明下的 park,或接受更保守判定;一只名字属于两只引擎工具的声明在 prepare 被拒(`config.tool_face_invalid`),已 park 的调用续跑不动,改声明后重试。
2671
- - **持久面反向不兼容边界(回滚 / 共享存储混版)**:7.107.0(core 7.36.0 #1207)起,服务商给的**越界** tool-call id(字符集外或 >128)在转录 / 检查点里落**折叠形**,原串只在同行 `wireId`;≤7.106.0 的实例(core 7.35.2)不读 `wireId`,续跑这类会话时会把折叠 id 发回网关 ⇒ 要求回传原 id 的网关拒绝后续请求(在形 id 零差异,不受影响;7.35.2 的 pre-CAS 复核按 `names` 先读拼写、取座可能不同)。**约束**:同一存储上不要让 ≤7.106.0 实例接管 7.107.0 已写过折叠 id 的会话;回滚前排空这类会话(会话 `messages[]` 里出现 `wireId` 的行即受影响),或接受重开。
3033
+ - **持久面反向不兼容边界(回滚 / 共享存储混版)**:7.107.0(core 7.36.0)起,服务商给的**越界** tool-call id(字符集外或 >128)在转录 / 检查点里落**折叠形**,原串只在同行 `wireId`;≤7.106.0 的实例(core 7.35.2)不读 `wireId`,续跑这类会话时会把折叠 id 发回网关 ⇒ 要求回传原 id 的网关拒绝后续请求(在形 id 零差异,不受影响;7.35.2 的 pre-CAS 复核按 `names` 先读拼写、取座可能不同)。**约束**:同一存储上不要让 ≤7.106.0 实例接管 7.107.0 已写过折叠 id 的会话;回滚前排空这类会话(会话 `messages[]` 里出现 `wireId` 的行即受影响),或接受重开。
2672
3034
 
2673
- ## 7.106.0(车QY,S-877 / S-881)—— `@sema-agent/core` 7.35.2(7.35.0 的全部变更 + #1206 新会话锁 + 看门狗 30s 等待披露):一只权限模式 · `approverPosture` / `taskApproverPosture` 删 · `MANUAL_MODE_SHELL_GATE=classify` 拒启 · 宿主子进程 env 按 CC 形剥(git 配置族与代理族原样到达)
3035
+ ## 7.106.0(车QY)—— `@sema-agent/core` 7.35.2(7.35.0 的全部变更 + 新会话锁 + 看门狗 30s 等待披露):一只权限模式 · `approverPosture` / `taskApproverPosture` 删 · `MANUAL_MODE_SHELL_GATE=classify` 拒启 · 宿主子进程 env 按 CC 形剥(git 配置族与代理族原样到达)
2674
3036
 
2675
3037
  - **🔴 wire:提交体 `approverPosture` 删,零别名。** 仍带它 ⇒ 400 `request.body_shape`(`unknownKeys:["approverPosture"]`)。**迁移**:删掉这个键;要「宿主自动答卡」的效果用
2676
3038
  `permissionMode`(`acceptEdits` / `bypassPermissions`,后者在托管部署上 422 `request.host_posture_refused`)。能力位 `taskApproverPosture` 同删 —— 读它的探测改读 `taskWriteFaceOpen`
@@ -2685,7 +3047,7 @@
2685
3047
  也被拒(core 路径拒座把 `cp` 的源也按写目标判,与 CC 同形),升级前照跑 —— 补偿 = 旋钮 `acceptEdits|default` + 审批席,或用读工具取内容。
2686
3048
  🔴 **宽于升级前的六类**:根外读探针(`probe`)、MCP / A2A 工具标记、transcript 写、`rule_unreadable`(**规则店读不出时照放** —— 安全轴 fail-open 方向)、
2687
3049
  `artifact_shared_read` —— 升级前这些腿上照问(无人答 ⇒ 拒),缺省旋钮下被释放。**补偿**:`UNATTENDED_PERMISSION_MODE=acceptEdits|default`,或给腿配审批席。
2688
- 想更严设 `acceptEdits` / `default` / `dontAsk`,拼错即拒启。⚰️ **7.109.0 起旋钮退役(设了即拒启),这些腿改按类作答 —— 见 7.109.0 段。** **过渡形**:`UNATTENDED_PERMISSION_MODE` 与写保护派生 deny 行是 7.106.0 过渡形;core 7.37.0 到货后(S-906,`AskRequest.askClass?` / `classes?`)退成 `default` + onAsk 按类作答,并硬删旋钮(拒启点名)—— 已于 7.109.0 兑现。客户端 `bypassPermissions` 不再放掉部署治理层(commandPolicy / 敏感写守卫)的 ask。`config.tool_mount_denied` 的 HTTP 档仍 400。
3050
+ 想更严设 `acceptEdits` / `default` / `dontAsk`,拼错即拒启。⚰️ **7.109.0 起旋钮退役(设了即拒启),这些腿改按类作答 —— 见 7.109.0 段。** **过渡形**:`UNATTENDED_PERMISSION_MODE` 与写保护派生 deny 行是 7.106.0 过渡形;core 7.37.0 到货后(`AskRequest.askClass?` / `classes?`)退成 `default` + onAsk 按类作答,并硬删旋钮(拒启点名)—— 已于 7.109.0 兑现。客户端 `bypassPermissions` 不再放掉部署治理层(commandPolicy / 敏感写守卫)的 ask。`config.tool_mount_denied` 的 HTTP 档仍 400。
2689
3051
  - **会话授权(`remember:"session"` / `allow_session`)对引擎的问也生效**:同会话下一次同工具不再出卡(Write / 非只读 Bash 在 `default` 下同此;
2690
3052
  需要审批席 —— `TOOL_APPROVAL_ENABLED` 开,不要活卡再配 `STREAM_ASK_WINDOW_MS=0`)。`APPROVAL_NEVER_AUTO` / 耐久预算耗尽 / **治理层**
2691
3053
  (`runtime.commandPolicy` 的 ask、`AUTONOMY` 折出的门、敏感写守卫集)的卡改成强制卡(`mandated:true`、`ruleOffersAbsence:"mandated"`,此前 `"shadowed"`),
@@ -2711,67 +3073,67 @@
2711
3073
  引擎按 `default` 跑:这条 worker 每一次写 / 非只读命令再问一次(durable 部署上再 park,fail-closed,无人值守的 worker 卡住等人)。
2712
3074
  没有 leader worker park 的部署零动作;已升级才发现的,逐条答完那些新卡即可(不会放宽)。
2713
3075
 
2714
- ## 7.106.0(车QU,S-795 + S-810)—— 降级壳凭据按 boot 身份取值 · 部分应用的拍也签重启
3076
+ ## 7.106.0(车QU)—— 降级壳凭据按 boot 身份取值 · 部分应用的拍也签重启
2715
3077
 
2716
- - **行为面:反应式降级壳里目标的自有凭据按 boot 那一代的身份取值(S-795)。** 同名 env 变量换值照旧热;降级目标在目录里**换 key 的名字 / 重贴托管密钥**
3078
+ - **行为面:反应式降级壳里目标的自有凭据按 boot 那一代的身份取值。** 同名 env 变量换值照旧热;降级目标在目录里**换 key 的名字 / 重贴托管密钥**
2717
3079
  要重启才进壳 —— `/health.restart.reasons` 会带 `degrade-route` 告诉编排器(托管密钥重贴 7.103.1 起不签,现在签)。候选部分应用(某组被整组拒)的拍现在
2718
- 同样会签(S-810),但审批组 / 模型面组被拒的拍扣下(重启可能起不来),只出 warn `restart_signal_withheld_boot_may_refuse`。**迁移**:无需改配置;按信号
3080
+ 同样会签,但审批组 / 模型面组被拒的拍扣下(重启可能起不来),只出 warn `restart_signal_withheld_boot_may_refuse`。**迁移**:无需改配置;按信号
2719
3081
  重启即可;盯着这条 warn 修被拒的组。
2720
3082
 
2721
- ## 7.106.0(车QR,S-866 云模式波 B)—— 给了 SQL 坐标而没有腿会用它 ⇒ 拒启(点名 `DB_BACKEND` / `SESSION_BACKEND` 出路)· caps 顶层 `sql` 并入 `store.sql` · 目录七行座位与 `center.domainExists` 删除 · 多租租约连接级失败默认 503
3083
+ ## 7.106.0(车QR,云模式波 B)—— 给了 SQL 坐标而没有腿会用它 ⇒ 拒启(点名 `DB_BACKEND` / `SESSION_BACKEND` 出路)· caps 顶层 `sql` 并入 `store.sql` · 目录七行座位与 `center.domainExists` 删除 · 多租租约连接级失败默认 503
2722
3084
 
2723
- - **🔴 行为面:给了 SQL 坐标而没有任何腿会用它 ⇒ 配置期拒启(S-866 ⑤b)。** 命中三形(修前都在**静默跑内存**):只设 `MYSQL_HOST` 而不设
3085
+ - **🔴 行为面:给了 SQL 坐标而没有任何腿会用它 ⇒ 配置期拒启。** 命中三形(修前都在**静默跑内存**):只设 `MYSQL_HOST` 而不设
2724
3086
  `SESSION_BACKEND` / `DB_BACKEND`;只设 `PG_HOST` 而不设 `SESSION_BACKEND` / `DB_BACKEND`;只设 `PG_HOST` + `SESSION_BACKEND=auto`(引擎缺省 mysql,
2725
3087
  PG 坐标没人用)。坐标被用到的形(`SESSION_BACKEND=mysql|auto` + MYSQL 坐标)不受影响。**迁移**:按拒句点名的出路改 —— 要持久 `DB_BACKEND=pg|mysql`;
2726
3088
  要内存 去掉坐标或 `DB_BACKEND=memory`;要尽力而为 `SESSION_BACKEND=auto` 配对的 `DB_BACKEND`。
2727
- - **🔴 wire:`GET /v1/capabilities` 顶层 `sql` 删除,零别名(S-866 ①)。** 对象逐字搬进新键 `store.sql`(`store` = `{declared, backend, durable,
3089
+ - **🔴 wire:`GET /v1/capabilities` 顶层 `sql` 删除,零别名。** 对象逐字搬进新键 `store.sql`(`store` = `{declared, backend, durable,
2728
3090
  degradedReason?, sql?}`,附录 B)。**迁移**:读 `capabilities.sql` 的消费端改读 `capabilities.store?.sql`;`null` 那一义拆成 `store.backend`
2729
3091
  (`memory` / `local` / 降级)与 `store.sql` 缺席。
2730
- - **🔴 wire:`GET /v1/config/catalog` 七行失去中心座位,全部行失去 `center.domainExists`(S-866 ⑤a)。** readFace 四键 / `PERMISSIONS_DISABLE_AUTO_MODE` /
3092
+ - **🔴 wire:`GET /v1/config/catalog` 七行失去中心座位,全部行失去 `center.domainExists`。** readFace 四键 / `PERMISSIONS_DISABLE_AUTO_MODE` /
2731
3093
  `MODEL_DEGRADE_ON` / `MODEL_DEGRADE_REACTIVE` 不再带 `center` / `centerDomain` / `centerPath`,`writeLanes` 恒 `["env"]`;中心在管 models 时
2732
3094
  `summary.centerManaged` −2。**迁移**:删掉读 `center.domainExists` 的分支 —— 有 `center` 块 ⇔ 中心可写。
2733
- - **行为面:多租部署(`REQUIRE_PRINCIPAL=true`)的租约连接级失败默认 503(S-866 ③)。** 新旋钮 `FLEET_LEASE_FAIL_CLOSED` 缺省随姿态派生(多租 true /
3095
+ - **行为面:多租部署(`REQUIRE_PRINCIPAL=true`)的租约连接级失败默认 503。** 新旋钮 `FLEET_LEASE_FAIL_CLOSED` 缺省随姿态派生(多租 true /
2734
3096
  单用户 false):中心拒了本引擎的凭证、凭证文件读不出、中心不可达 / 5xx / 超时 / 坏体(以及中心答 404 / 429 / 3xx 这类 200 / 409 / 4xx 凭证码之外的状态)时,计费入口答 **503 `fleet.lease_unavailable`**(新族
2735
3097
  `fleet.`,`Retry-After` 5,体 `reason`)而不是静默放行。**迁移**:要保留 7.105.0 的放行姿态就显式 `FLEET_LEASE_FAIL_CLOSED=false`;SDK / 壳把
2736
3098
  `fleet.lease_unavailable` 当可重试。
2737
- - **行为面:接了中心而不设 `FLEET_ADVERTISE_ADDRESS` 的引擎开始上报用量(S-866 ④)。** 中心三件齐即每 60s `POST /api/fleet/usage`(不注册、不心跳)。
3099
+ - **行为面:接了中心而不设 `FLEET_ADVERTISE_ADDRESS` 的引擎开始上报用量。** 中心三件齐即每 60s `POST /api/fleet/usage`(不注册、不心跳)。
2738
3100
  不想报就不配中心三件。
2739
3101
 
2740
- ## 7.106.0(车QV,S-891)—— 会话规则 SQL 店:抹除遇计数读不出的行照删,那把键被封、要人恢复
3102
+ ## 7.106.0(车QV)—— 会话规则 SQL 店:抹除遇计数读不出的行照删,那把键被封、要人恢复
2741
3103
 
2742
3104
  - **行为面(只影响库被列外改过的 `DB_BACKEND=mysql|pg` 部署)。** 会话删除 / 2c `overwrite-dst` 抹除到一行计数读不出的 `session_policy`
2743
3105
  行时不再拒 `corrupt`(7.105.0 的半程停),而是照删并**封键**:那把 `(session, principal)` 键之后的读和写都答 500 `corrupt`(与删之前同答;
2744
3106
  这个 principal 在该会话上的新任务拒起,含该会话的 2c 导出),日志一条 `session_policy_erase_sealed_keys` 点名它。**迁移**:按 `USAGE.md` §9.11
2745
3107
  「显式恢复」原地解封那条 `session_policy_rev_mark` 行(`rev` 归 0、`gen` + 1;不要删它);没有坏行的部署零动作。
2746
3108
 
2747
- ## 7.106.0(车RA,S-895 / S-896 / S-897 / S-904 / S-885)—— 模型钥匙缺席不再借网关钥匙 · settings 权限桶超帽 / 坏项响亮拒 · SUP 路由的问带部署出身 · 新请求键 `inheritEnv` · 目录 `retired[]`
3109
+ ## 7.106.0(车RA)—— 模型钥匙缺席不再借网关钥匙 · settings 权限桶超帽 / 坏项响亮拒 · SUP 路由的问带部署出身 · 新请求键 `inheritEnv` · 目录 `retired[]`
2748
3110
 
2749
- - **🔴 行为面:目录条目声明了 `apiKeyEnv` 而进程里没有这个变量 ⇒ 该模型钥匙中毒(S-896)。** 修前静默回落网关钥匙(别家服务的钥匙可能被送到错的端点);修后打这个模型的任务 `failed`、句点名变量名、网关钥匙零字节,`GET /v1/models` 配对标注 `unknown`,起服不受影响。**迁移**:给进程设上那个变量,或从条目删掉 `apiKeyEnv`(走网关钥匙就别声明)。包根类型面 `ModelKeyPoison*` 改名(零别名,tsc 红即通知)。
2750
- - **🔴 行为面:`settings.permissions.allow / deny / ask` 超过 1000 条或含非串 / 空串项 ⇒ 400 `request.field_invalid`(S-904)。** 修前静默截到 1000 条、静默丢坏项(仓库层写上千条规则就能把排在后面的托管 deny 挤出引擎视野);修后 fresh 面 400,体带 `field` / `reason`(`over_cap` | `bad_entry`)/ `count` + `cap` 或 `index`;续跑腿照判 ⇒ 409 `resume_blocked_by_policy` + `blockedBy` + 同组字段。**迁移**:合并规则前按桶去重、控制在 1000 条内;壳按 `errorCode` + `reason` 出句。
2751
- - **行为面:编排路由判到 supervisor 的 shell / 写工具问带 `authoredBy:"deployment"`(S-897;clay 裁定「supervisor 路由的 always 像部署治理钉一样打治理位」)。** 只在 `ROUTER_ENABLED` 开且判到 supervisor 时:这些问变成强制问(卡与 park 行 `mandated:true`),「本会话放行」退不掉、`auto` 下分类器不再替答、`bypassPermissions` 不再放行。**迁移**:无;壳侧 KNOWN-LIMITS 里「SUP 单个强制词被放行」的例外句可删。
2752
- - **additive:请求键 `inheritEnv: "all" | "scrub"`(S-895)** —— host 车道 ∧ 单用户部署(读数 `capabilities.projectContext`)才兑现 `"all"`;托管 × `"all"` ⇒ 422 `request.host_posture_refused`;非 host 车道 × `"all"` / 词表外 ⇒ 400 `request.field_invalid`(`"scrub"` 是缺省,任何车道受理);缺席 = 清洗且清掉该会话上一条声明。7.105.0 及以前发它 ⇒ 400 `request.body_shape`,壳按服务端版本闸发。
2753
- - **additive:`GET /v1/config/catalog` 顶层 `retired[]`(S-885)** —— 恒在场,从 `RETIRED_ENVS` 同一张表派生;包根只读导出 `RETIRED_ENVS`。消费端删手抄退役名单改读它。
3111
+ - **🔴 行为面:目录条目声明了 `apiKeyEnv` 而进程里没有这个变量 ⇒ 该模型钥匙中毒。** 修前静默回落网关钥匙(别家服务的钥匙可能被送到错的端点);修后打这个模型的任务 `failed`、句点名变量名、网关钥匙零字节,`GET /v1/models` 配对标注 `unknown`,起服不受影响。**迁移**:给进程设上那个变量,或从条目删掉 `apiKeyEnv`(走网关钥匙就别声明)。包根类型面 `ModelKeyPoison*` 改名(零别名,tsc 红即通知)。
3112
+ - **🔴 行为面:`settings.permissions.allow / deny / ask` 超过 1000 条或含非串 / 空串项 ⇒ 400 `request.field_invalid`。** 修前静默截到 1000 条、静默丢坏项(仓库层写上千条规则就能把排在后面的托管 deny 挤出引擎视野);修后 fresh 面 400,体带 `field` / `reason`(`over_cap` | `bad_entry`)/ `count` + `cap` 或 `index`;续跑腿照判 ⇒ 409 `resume_blocked_by_policy` + `blockedBy` + 同组字段。**迁移**:合并规则前按桶去重、控制在 1000 条内;壳按 `errorCode` + `reason` 出句。
3113
+ - **行为面:编排路由判到 supervisor 的 shell / 写工具问带 `authoredBy:"deployment"`(clay 裁定「supervisor 路由的 always 像部署治理钉一样打治理位」)。** 只在 `ROUTER_ENABLED` 开且判到 supervisor 时:这些问变成强制问(卡与 park 行 `mandated:true`),「本会话放行」退不掉、`auto` 下分类器不再替答、`bypassPermissions` 不再放行。**迁移**:无;壳侧 KNOWN-LIMITS 里「SUP 单个强制词被放行」的例外句可删。
3114
+ - **additive:请求键 `inheritEnv: "all" | "scrub"`** —— host 车道 ∧ 单用户部署(读数 `capabilities.projectContext`)才兑现 `"all"`;托管 × `"all"` ⇒ 422 `request.host_posture_refused`;非 host 车道 × `"all"` / 词表外 ⇒ 400 `request.field_invalid`(`"scrub"` 是缺省,任何车道受理);缺席 = 清洗且清掉该会话上一条声明。7.105.0 及以前发它 ⇒ 400 `request.body_shape`,壳按服务端版本闸发。
3115
+ - **additive:`GET /v1/config/catalog` 顶层 `retired[]`** —— 恒在场,从 `RETIRED_ENVS` 同一张表派生;包根只读导出 `RETIRED_ENVS`。消费端删手抄退役名单改读它。
2754
3116
 
2755
- ## 7.105.0(车QQ 部分)—— 门前三族只读路要凭据(S-672)· 会话规则写口拒退役 / 无前缀工具名(S-800)· `ServiceDeps.runnerFor` 必填(S-175)
3117
+ ## 7.105.0(车QQ 部分)—— 门前三族只读路要凭据 · 会话规则写口拒退役 / 无前缀工具名 · `ServiceDeps.runnerFor` 必填
2756
3118
 
2757
3119
  ### wire:HTTP / 错误码
2758
3120
 
2759
- - **🔴 行为面:门前三族只读路在配了 service 凭据的部署上要凭据(S-672)。** `GET /v1/tasks`(及 `…/:id/{turns,stream,artifacts,tool-results/:ref}`、
3121
+ - **🔴 行为面:门前三族只读路在配了 service 凭据的部署上要凭据。** `GET /v1/tasks`(及 `…/:id/{turns,stream,artifacts,tool-results/:ref}`、
2760
3122
  `/v1/tasks/source-summary`)、`GET /v1/usage/{summary,series,breakdown}`、`GET /v1/workflows[/:id[/journal|/stream]]`、`GET /v1/fleet/stream`:部署配了
2761
3123
  `SERVICE_AUTH_TOKEN` / `SERVICE_AUTH_TOKENS` 时,请求必须带 service token、只读 `TRACE_TOKEN` 或验过的 principal(registry 登录令牌 / 直连门签名 principal 令牌)
2762
3124
  之一,否则 **401 `auth.unauthorized`**(与全局凭据门同一句)。只带调用方自写的 `x-agent-principal` 头不算。**迁移**:这几条读口带上与提交任务同一把
2763
3125
  service token(或登录令牌);没配 service 凭据的部署不受影响。`/.well-known/agent-card.json` 不变(匿名)。契约 §0.56。
2764
- - **会话规则写口拒「写进去就跑不了」的工具名(S-800)。** `PUT /v1/sessions/:id/policy` 与 `POST /v1/sessions/:id/sync/import` 的 `policy` 面:`toolAllow` /
3126
+ - **会话规则写口拒「写进去就跑不了」的工具名。** `PUT /v1/sessions/:id/policy` 与 `POST /v1/sessions/:id/sync/import` 的 `policy` 面:`toolAllow` /
2765
3127
  `toolDeny` 里有引擎退役名(`Task` / `KillShell` / `MultiEdit` / `bash` / `Recall` …)或含 `__` 却无协议前缀的名字 ⇒ **400 `rules.legacy_tool_name`**
2766
3128
  (新码,体带 `field` / `name`)。7.104.x 及以前照收、之后这个会话每一跑拒启。**迁移**:换成现役名(句子里带指引)/ 给协议工具名加 `mcp__` 等前缀;
2767
3129
  对未知前缀族严格的消费方收下 `rules.` 族(400,改请求再写,原样重试不改判)。部署自己挂了与退役名同名工具的,写口仍拒 —— 走部署级工具策略。
2768
3130
 
2769
3131
  ### 类型面与嵌入方
2770
3132
 
2771
- - **🔴 `ServiceDeps.runnerFor` 必填(S-175)。** 修前可选,缺席时每只任务静默跑在 `deps.runner`(最宽的那只)上;现在缺席 = 编译错,绕过类型的 deps 在
3133
+ - **🔴 `ServiceDeps.runnerFor` 必填。** 修前可选,缺席时每只任务静默跑在 `deps.runner`(最宽的那只)上;现在缺席 = 编译错,绕过类型的 deps 在
2772
3134
  `createHttpServer` 入口抛(报文点名 `runnerFor`)。**迁移**:单 Runner 的嵌入方显式传 `runnerFor: () => runner`(一句表态,不是回落);按场景分有手 / 无手两只 Runner 的嵌入方传自己的选路函数(本仓自己的装配在 `boot/stage-10-http-server.ts`,该工厂不在包根导出面)。
2773
3135
 
2774
- ## 7.105.0(车QP 部分)—— 续读不再答 416 `limit.retention_evicted`(S-211 ①)· `TOOL_RESULT_TTL_SEC ≤ 0` 拒启(S-211 ⑤)· 记号表加索引(S-546 A9)
3136
+ ## 7.105.0(车QP 部分)—— 续读不再答 416 `limit.retention_evicted`· `TOOL_RESULT_TTL_SEC ≤ 0` 拒启· 记号表加索引
2775
3137
 
2776
3138
  - **续读(`Last-Event-ID` / `?from=`)不再答 416 `limit.retention_evicted`**(`GET /v1/runs/:id/events`、`GET /v1/tasks/:id/stream`、
2777
3139
  `GET /v1/images/bakes/:id/events`)。这个码从来判不出一次真淘汰:账本没有局部头部裁剪,唯一的删除是整棵会话树连删 —— run 行
@@ -2790,14 +3152,14 @@
2790
3152
 
2791
3153
  ### wire:HTTP / SSE / 错误码 / 帧
2792
3154
 
2793
- #### 同步提交腿 `POST /v1/tasks` 的拒因分诊(统一规则;S-271 / S-724)
3155
+ #### 同步提交腿 `POST /v1/tasks` 的拒因分诊(统一规则)
2794
3156
 
2795
3157
  - **prepare 期拒只在零工作时答错误体(行为面)**:`corrupt_session`(500)/ `rewind.store_unconfigured`(409)/ `rewind.capture_disabled`(422)/ 名册超界三码(503)与其余 prepare 期拒同一条分诊 —— 零工作(整次提交 turns = 0 ∧ tokens = 0)⇒ 错误体;
2796
3158
  已做过工作的多级 run(`verify` / `cascade`)末级才被拒 ⇒ 200 + failed 体、照常计费与幂等缓存。相对 7.103.2:这几码此前**没有**状态档映射、
2797
3159
  恒 200 + failed 体,所以调用方看到的变化只有「零工作那一形从 200 变成对应 4xx / 5xx」。7.103.2 已有状态档的码在「多级 run 末级才被拒」这一形上的变化
2798
- 见 S-271 一组第二条。
3160
+ 见下面「core 名册超界三码在同步提交腿上改答 503」一节。
2799
3161
 
2800
- #### 会话存档读不出:500 `corrupt_session`;部分记录被跳过:`engine_notice` `session.records_skipped`(S-612)
3162
+ #### 会话存档读不出:500 `corrupt_session`;部分记录被跳过:`engine_notice` `session.records_skipped`
2801
3163
 
2802
3164
  内部构造面一条见「类型面与嵌入方」小节。
2803
3165
 
@@ -2814,9 +3176,9 @@
2814
3176
  - **新 `engine_notice` 码 `session.records_skipped`**(只在文件后端):会话照常唤醒、这一轮照跑,但历史里有 N 条记录读不出被跳过 ⇒ 同一轮里一帧
2815
3177
  `{ dropped, entriesKept, sessionId }`。对未知码严格的消费方要收下这只码(附录 D.3 白名单 26 码);没升级的壳按未知 `engine_notice` 码处置。
2816
3178
  非流式同步口 `POST /v1/tasks` 不收通告帧(所有通告码同一姿态),那一腿上只有运维日志 `session_repo_corrupt_read`。
2817
- - **老壳所见**:没消费 cli L-568 的壳遇到形 A,屏上是 500 的 `error` 原句加错误码。
3179
+ - **老壳所见**:没消费这一形的 cli 壳遇到形 A,屏上是 500 的 `error` 原句加错误码。
2818
3180
 
2819
- #### core 名册超界三码在同步提交腿上改答 503(S-271)
3181
+ #### core 名册超界三码在同步提交腿上改答 503
2820
3182
 
2821
3183
  - **🔴 同步提交腿三码改 503(wire 值形变更)**:`POST /v1/tasks` 上 `config.tool_name_too_long` / `config.tool_contract_too_long` /
2822
3184
  `config.tool_roster_bound`(一只工具的名 / 契约 / `modelGate` 等身份成员超过名册的界,引擎在 prepare 期拒、零计费)由 **200 带 failed 体**
@@ -2831,7 +3193,7 @@
2831
3193
  `rewind.child_scope_unsupported`、`config.memory_capture_unsupported` 等)在这一形上此前答 4xx / 5xx(跳过计费、不进幂等缓存),它们零工作的拒(常态)不变;
2832
3194
  本版新映射的码(`rewind.store_unconfigured` / `rewind.capture_disabled` / 名册超界三码)此前恒 200 + failed 体,见本小节统一规则。**迁移**:多轮提交的客户端对这些码两形都要认(错误体 `errorCode` / 200 体 `terminal.code`)。
2833
3195
 
2834
- #### 请求词 `fileHistory` + `wiring_manifest.fileHistory` + rewind 两码进错误码目录(S-724)
3196
+ #### 请求词 `fileHistory` + `wiring_manifest.fileHistory` + rewind 两码进错误码目录
2835
3197
 
2836
3198
  `FILE_HISTORY_CAPTURE=false` 只关捕获一条见「env 与启动」小节。
2837
3199
 
@@ -2847,7 +3209,7 @@
2847
3209
  operator 同投)多一段 `fileHistory: "on" | "disabled"`(缺席 = 老引擎,不是「在捕获」)。2c sync 面「没有历史店」的 501 句子改为
2848
3210
  `session sync is not available on this deployment: no file-history store is wired, …`(按句子全文匹配的客户端注意)。
2849
3211
 
2850
- #### 同步提交撞 park 的 200 体改为「结果本身 + 回执三键」;park 中的 run 行带 `result`(S-173,additive)
3212
+ #### 同步提交撞 park 的 200 体改为「结果本身 + 回执三键」;park 中的 run 行带 `result`(additive)
2851
3213
 
2852
3214
  持久数据面与混版窗 / 回滚的修复语句见「存储与一次性迁移」小节,内部面见「类型面与嵌入方」小节。
2853
3215
 
@@ -2864,7 +3226,7 @@
2864
3226
  - **同一列的其它读者(行为面,如实)**:会话列表 `lastTaskRunId` 在 park 中在场(此前只在终局在场);`GET /v1/tasks` 列表行的
2865
3227
  `turns` / `tokens` / `costMicroUsd` 在 park 中带停下来那一刻的读数;`/v1/usage/*` 把 park 行按那一刻的读数计入(下界,终局时整块替换)。
2866
3228
 
2867
- #### 删会话后旧的审批卡消失(S-790 / S-506)
3229
+ #### 删会话后旧的审批卡消失
2868
3230
 
2869
3231
  会话化身的新列 + 一次性回填、记忆 opt-out 载体见「存储与一次性迁移」小节,嵌入方读口见「类型面与嵌入方」小节。
2870
3232
 
@@ -2872,26 +3234,26 @@
2872
3234
  消失),本副本上在跑的停掉 —— 做完才删会话记录。**迁移**:依赖「删了会话之后还能对它的旧审批卡做决定」的调用方,那张卡自本版起不在了;
2873
3235
  决定一张 7.104.0 之前删会话留下的旧卡答 `409 decide.not_parked`。有本副本结束不了的子代(在别的副本上:耐久行的写者不是本副本)⇒ 删除开始之前就拒,答 **409
2874
3236
  `conflict.session_children_alive`**(体带 `remaining` = 那些子代的 id 列表,与 `GET /v1/agents/roster` 的 `handle` 同一个串),什么都没动,
2875
- 等它们收尾后重试即可;本副本停得掉却没在时限内停净 ⇒ `500 internal.error`,会话记录保留,重试收敛;有子代的会话删除会慢一些(每轮重新枚举,至多 6 轮)。两处如实登记(修复验证轮 opus 腿,S-886 / S-887):500 之后**立刻**重试,停止仍在落盘的子代会被判成够不着 ⇒ 那一次答 409(句子说「删之前就拒」,但上一次已删了账本;再晚一拍重试即收敛);曾开耐久审批、留下 parked 子代、之后关闭耐久审批(或切到多租户形)的会话,删除会一直 409(本副本没有 checkpoint 店,作废不了那张卡;7.103.2 上这一形答 200)—— 出路候 S-887。
3237
+ 等它们收尾后重试即可;本副本停得掉却没在时限内停净 ⇒ `500 internal.error`,会话记录保留,重试收敛;有子代的会话删除会慢一些(每轮重新枚举,至多 6 轮)。两处如实登记(修复验证轮 opus 腿):500 之后**立刻**重试,停止仍在落盘的子代会被判成够不着 ⇒ 那一次答 409(句子说「删之前就拒」,但上一次已删了账本;再晚一拍重试即收敛);曾开耐久审批、留下 parked 子代、之后关闭耐久审批(或切到多租户形)的会话,删除会一直 409(本副本没有 checkpoint 店,作废不了那张卡;7.103.2 上这一形答 200)—— 出路候后续修复。
2876
3238
  - **parked 决定的复核(行为面)**:决定腿在 claim 之前 / 之后各读一次根会话上是哪一位住客,不在或换了人(包括同一个人删了重建)⇒ 回滚、
2877
3239
  `409 decide.not_parked`;行上没有根会话锚 ⇒ `409 decide.row_unrevivable`。零新码、零新体键。
2878
3240
 
2879
- #### 回决门键闭集的 `unsupported` 桶换成员与文案(S-355)+ 续跑折叠体 `blockedBy` 恒在(S-607)
3241
+ #### 回决门键闭集的 `unsupported` 桶换成员与文案+ 续跑折叠体 `blockedBy` 恒在
2880
3242
 
2881
- - **`/decide` 的 400 `request.body_shape` 换桶(S-355,诊断面)**:`permissionModeAfter`(plan_review 的字段)与 `permissionMode`(提交体的键)由
3243
+ - **`/decide` 的 400 `request.body_shape` 换桶(诊断面)**:`permissionModeAfter`(plan_review 的字段)与 `permissionMode`(提交体的键)由
2882
3244
  `unknownKeys` 移到 `unsupportedKeys`;判决不变(都拒、同码同串)。两道回决门(`/decide`、`plan_review`)的 `unsupported` 文案由一句通用标签改为
2883
3245
  **按去处分句**:`unsupported (a body field of <那条门的路径> — …): k`、`unsupported (a path segment of <带这一段的 URL> — …): k`、
2884
3246
  `unsupported (a submit-body key of POST /v1/tasks — …): k`。键名 `unknownKeys` / `unsupportedKeys`、状态码、`Accepted:` 全表不变。
2885
3247
  **迁移**:按 `unknownKeys` 精确匹配这两个键的调用方 / 测试改读 `unsupportedKeys`;按文案全文匹配的改按两个机读桶判。
2886
3248
  内部面:`decideBodyKeyIssue` / `planReviewBodyKeyIssue` 删,统一为 `decisionBodyKeyIssue(door, body)`(`src/http/routes/approvals-assistant.ts`)。
2887
- - **续跑折叠体 `409 resume_blocked_by_policy` 的 `blockedBy` 恒在(S-607,additive)**:此前只在原拒绝带子码时在场;现在值 = 同一只错误**直接**出去时
3249
+ - **续跑折叠体 `409 resume_blocked_by_policy` 的 `blockedBy` 恒在(additive)**:此前只在原拒绝带子码时在场;现在值 = 同一只错误**直接**出去时
2888
3250
  的 `errorCode`(带码 ⇒ 原码,与此前逐字相同;不带码 ⇒ 按状态的粗码 `request.rejected` / `not_found.resource` / `request.unprocessable` /
2889
3251
  `capability.unavailable` 等)。**迁移**:把「`blockedBy` 缺席」读成「这次拒绝没带子码」的消费方,在本版起的 server 上会读到粗码(判型族按
2890
3252
  `blockedBy ?? errorCode` 取码的,粗码不命中任何专属族,判型不变)。
2891
3253
 
2892
- #### 耐久 ask 回决口收 `settledBy`(S-843)
3254
+ #### 耐久 ask 回决口收 `settledBy`
2893
3255
 
2894
- - **耐久 ask 回决口收 `settledBy`(S-843,additive)**:`POST /v1/tasks/:taskId/asks/:askId/decision` 的体可带 `settledBy`(只配 `decision:"deny"`;
3256
+ - **耐久 ask 回决口收 `settledBy`(additive)**:`POST /v1/tasks/:taskId/asks/:askId/decision` 的体可带 `settledBy`(只配 `decision:"deny"`;
2895
3257
  直连门上 `400 settled_by_not_in_proof`,与 `/decide` 同 —— live `/respond` 口没有这一臂;超过 16 字符 / 空串 ⇒ 400),其余规则与拒句与
2896
3258
  `/decide`、`/respond` 相同。缺席 = 今形。
2897
3259
  `400 request.body_shape` 的拒因句末尾多了 `/ settledBy`(按句子全文匹配的客户端注意)。
@@ -2900,7 +3262,7 @@
2900
3262
  现在裁决之前 400(码 = 这条口体拒的一贯码 `request.body_shape`),卡还在。`/decide` 上此前走到引擎、由引擎按词表拒;现在 400
2901
3263
  `request.field_invalid`。引擎的三个词(`human` / `timeout` / `policy`)都在 16 字符以内,合法请求不受影响。
2902
3264
 
2903
- #### `401 auth.unauthorized` 的 message 换成出路句(S-850)
3265
+ #### `401 auth.unauthorized` 的 message 换成出路句
2904
3266
 
2905
3267
  - **`401 auth.unauthorized` 的 `error` 换句(wire 文案,码不变)**:此前恒为 `unauthorized` 一个词,现在按这道门收什么给三句出路句之一(凭据门 /
2906
3268
  运维口 / 要调用方身份,逐字见 `docs/ASSISTANT-WIRE-CONTRACT.md` 附录 A.1)。按 `error == "unauthorized"` 字面判的调用方改按 `errorCode`
@@ -2919,7 +3281,7 @@
2919
3281
 
2920
3282
  ### env 与启动
2921
3283
 
2922
- #### 多租户姿态 ∧ 不分租户的执行车道拒启 + 执行车道合成步(S-775)
3284
+ #### 多租户姿态 ∧ 不分租户的执行车道拒启 + 执行车道合成步
2923
3285
 
2924
3286
  - **🔴 `REQUIRE_PRINCIPAL=true` ∧ 最终生效的执行车道不分租户 ⇒ 拒启**(新交叉不变量 `multi-tenant-shared-lane`)。**按能力表不按词**:判据读
2925
3287
  执行车道能力表的「分不分租户」一位,**今天覆盖 host / ssh / adb**(worker 宿主 / 一台 SSH 对端 / 一台 ADB 设备,所有任务共享同一个目标);
@@ -2934,17 +3296,17 @@
2934
3296
  `loadConfig()` 拒的形,本版起 `loadConfig()` 照返回 —— 判据在合成步里。包根新导出 `composeExecutionLane(config, ctx)` 与它的同步判据半场
2935
3297
  `assertExecutionLaneInvariants(config)`(同一只,本仓两个入口调的就是它):在 `loadConfig()` 之后调(车QK F4)。
2936
3298
 
2937
- #### `CONFIG_PROVIDER` 闭集拒启(S-841)
3299
+ #### `CONFIG_PROVIDER` 闭集拒启
2938
3300
 
2939
3301
  类型面一条见「类型面与嵌入方」小节。
2940
3302
 
2941
- - **🔴 认不出的 `CONFIG_PROVIDER` ⇒ 拒启(S-841,行为面)**:合法值只有 `local` / `remote` / 不设(空串 = 不设);**逐字比较**,大小写与首尾空白都不宽容。
3303
+ - **🔴 认不出的 `CONFIG_PROVIDER` ⇒ 拒启(行为面)**:合法值只有 `local` / `remote` / 不设(空串 = 不设);**逐字比较**,大小写与首尾空白都不宽容。
2942
3304
  此前认不出的词照起,而且一个进程里三处读法不一:配置源当它是 `local`(配了中心也一样)、隐式 host 执行车道与起服落点披露当它「不是 local」、
2943
3305
  local 配置源的根落回进程 cwd 而车道文件覆写读本地根。拒因句即通知(点名旋钮、列合法词)。**迁移**:改成 `local` / `remote` 之一或删掉。
2944
3306
 
2945
- #### 旧负名与正名同设 ⇒ 拒启(墓碑一张表)(S-588)
3307
+ #### 旧负名与正名同设 ⇒ 拒启(墓碑一张表)
2946
3308
 
2947
- - **🔴 D 族旧负名在场即拒启,不论正名在不在(S-588,行为面)**:下面四个旧名自 server 3.0.0 起就是墓碑,但此前只在**正名没设**时才拒;
3309
+ - **🔴 D 族旧负名在场即拒启,不论正名在不在(行为面)**:下面四个旧名自 server 3.0.0 起就是墓碑,但此前只在**正名没设**时才拒;
2948
3310
  正名设了而旧名还留着,旧名被静默忽略、照常起服。本版起两名同设同样拒启,拒句与其余退役名同一句、同一个码 `[config.env_key_retired]`。
2949
3311
  **迁移**:删掉旧名;若只设了旧名,按下表换成正名(极性相反,别把旧值照抄过去):
2950
3312
 
@@ -2980,9 +3342,9 @@
2980
3342
  `MODEL_CHEAP_*` 给同一只模型造第二种形的部署。**迁移**:在 `config.d/models.json` 写两条不同名的条目(同一个上游 id,各自的形),把 roles
2981
3343
  指过去;不需要第二种形就去掉 `MODEL_CHEAP_ID`。
2982
3344
 
2983
- #### scratchpad 宣告不归 `SANDBOX_ENV_FACTS` 管(S-842)
3345
+ #### scratchpad 宣告不归 `SANDBOX_ENV_FACTS` 管
2984
3346
 
2985
- - **`SANDBOX_ENV_FACTS=false` 不再关会话 scratchpad(S-842,行为面)**:本键此后只管沙箱事实(profile / capabilities / pkgSource / egress / resume)。
3347
+ - **`SANDBOX_ENV_FACTS=false` 不再关会话 scratchpad(行为面)**:本键此后只管沙箱事实(profile / capabilities / pkgSource / egress / resume)。
2986
3348
  会话 scratchpad 的宣告是写面的宣告(core 据它开根围栏的洞,并用同一次裁决决定提示词教不教),与本键无关 ⇒ 这类部署的提示词**开始**出现
2987
3349
  `# Scratchpad Directory` 一节;远程车道(e2b / k8s / local-docker / ssh)的 `/tmp/scratchpad/<sid>` 此后在本键关着时也可 Write(与本键开着同形)。
2988
3350
  缺省部署:提示词重新出现这一节(此前被 core 跳过),每轮那一句 `scratchpad advertised writable directory skipped` 消失。**迁移**:无动作;
@@ -2990,7 +3352,7 @@
2990
3352
  ⚠️ 数据根很深(`<LOCAL_DATA_ROOT>/scratchpad/<段>` 超过 160 字符,根约 107 字符以上)的部署:会话 scratchpad **不再铸出**(不建、不豁免、不宣告),
2991
3353
  每个任务一行 warn `scratchpad_not_minted`。此前它照建、照豁免,提示词里只有一条被截断的假路径。**迁移**:缩短 `LOCAL_DATA_ROOT`。
2992
3354
 
2993
- #### `FILE_HISTORY_CAPTURE=false` 只关捕获(S-724)
3355
+ #### `FILE_HISTORY_CAPTURE=false` 只关捕获
2994
3356
 
2995
3357
  请求词 `fileHistory`、能力词 `fileHistoryCapture`、rewind 两码见「wire」小节。
2996
3358
 
@@ -3004,21 +3366,21 @@
3004
3366
 
3005
3367
  ### 存储与一次性迁移
3006
3368
 
3007
- #### 一次性迁移的窗登记表(S-590)
3369
+ #### 一次性迁移的窗登记表
3008
3370
 
3009
- - **一次性迁移的窗(S-590)**:`src/plugins/one-time-migrations.ts` 的每条迁移在「引入它的版本发布日 + 30 天」之后的第一个 minor 删码,逐条日期只在该文件的
3371
+ - **一次性迁移的窗**:`src/plugins/one-time-migrations.ts` 的每条迁移在「引入它的版本发布日 + 30 天」之后的第一个 minor 删码,逐条日期只在该文件的
3010
3372
  `ONE_TIME_MIGRATIONS` 登记表(随包在 `dist/plugins/one-time-migrations.d.ts`;起动日志行 `one_time_migrations_applied` 新增的 `removableAfter` 读数同源)。
3011
3373
  **跨版跳升**(从 7.73.x 及更早,或从 7.93.4 及更早)要经过一只还带着对应迁移的版本起一次。自建 `StoreBackend` 的嵌入方:`runOneTimeMigrations()`
3012
3374
  在**最后一条**删码时从接口上删(tsc 红即通知)。
3013
3375
 
3014
- #### 会话化身:`session_meta.incarnation` 新列 + 一次性回填(S-790 / S-506)
3376
+ #### 会话化身:`session_meta.incarnation` 新列 + 一次性回填
3015
3377
 
3016
3378
  删会话带走子代、parked 决定的复核见「wire」小节。
3017
3379
 
3018
3380
  - **新列(持久数据面)**:`session_meta.incarnation`(MySQL 协议 `VARCHAR(64) NOT NULL DEFAULT ''`;PG 同名同宽 `COLLATE "C"`)—— 同一个会话 id 上
3019
3381
  **这一位住客**的不透明令牌。新库由中央 DDL 建;存量库由起服的一次性迁移 **M5** 加列并给每一行铸一只互不相同的令牌(窗与删法见
3020
3382
  `src/plugins/one-time-migrations.ts` 的 `ONE_TIME_MIGRATIONS` 登记表;起动日志行 `one_time_migrations_applied` 多两键
3021
- `sessionIncarnationColumn` / `sessionIncarnationsBackfilled`)。**先升库再升副本**这条既有顺序不变:旧副本连上已加列的库会被 S-547 列册探针
3383
+ `sessionIncarnationColumn` / `sessionIncarnationsBackfilled`)。**先升库再升副本**这条既有顺序不变:旧副本连上已加列的库会被列册探针
3022
3384
  判「库比代码新」拒启。回填之后读到空令牌的行 ⇒ 读口响亮拒(`session.incarnation_missing`,parked 决定因此拒、记忆座退回按 id 绑定并 warn),
3023
3385
  **不**当作通配 —— 手工改库的运维给那一行填一只随机令牌即可(`session.incarnation_missing` 是内部错误码,日志可见;wire 上是通用 500,不是新码)。local 文件车道:令牌落在数据根的 `session-incarnations.json`(与
3024
3386
  `session-titles.json` 同一族边档),存量会话第一次被读时补铸并落盘,不在起动期扫。**该文件读不出**(坏 JSON / 形不对 / 权限;缺文件不算,那是「还没有」)⇒ 严格拒:
@@ -3026,7 +3388,7 @@
3026
3388
  拒因不带原文;这一拒记在进程里,修完要重启才重读。**出路** = 修好该文件,或把它移开,然后重启。**移开的代价**:所有旧会话的化身在下一次被读时
3027
3389
  重铸 —— 每只旧会话都成了一位新住客,上一位住客声明的记忆采集 opt-out 从此不再绑它们(按部署缺省采集);要保住 opt-out 就修文件,别移开。
3028
3390
  令牌不上 wire、不进模型上下文,日志只打前 8 位。
3029
- - **滚动升级窗(SQL 两车道)**:第一台 7.104.0 副本起动跑完 M5 之后,**此前已经在跑**的 ≤ 7.103.x 旧副本不会重新对账列集(S-547 探针只在起动期跑),
3391
+ - **滚动升级窗(SQL 两车道)**:第一台 7.104.0 副本起动跑完 M5 之后,**此前已经在跑**的 ≤ 7.103.x 旧副本不会重新对账列集(列册探针只在起动期跑),
3030
3392
  它们新建的会话行落列缺省 `incarnation = ''`。窗内现象:这些会话上的 parked 决定答 `500 internal.error`(读口响亮拒 `session.incarnation_missing`,
3031
3393
  claim 之前就拒,什么都不动);7.104.0 副本对每只这样的会话打一行 `session_incarnation_unavailable reason=session.incarnation_missing`(按会话去重);
3032
3394
  记忆座对它们退回按 id 绑定并 warn `memory_session_incarnation_unknown`。**出路**:全部副本升到 7.104.0(旧副本全部退出)之后,重启其中任意一台 ——
@@ -3034,7 +3396,7 @@
3034
3396
  - **记忆 opt-out 不再跨住客继承(local 文件载体)**:会话声明过记忆采集 opt-out、被删、同一个 id 重建之后,新住客按部署缺省采集。
3035
3397
  ⚠️ SQL 部署的 opt-out 载体(`session_capture_optout`)今天不存令牌 ⇒ 那一形的记录仍按 id 绑(新住客仍被扣 opt-out,保守方向),另车处理。
3036
3398
 
3037
- #### park 中的 run 行带 `result`:持久数据面与混版窗 / 回滚(S-173)
3399
+ #### park 中的 run 行带 `result`:持久数据面与混版窗 / 回滚
3038
3400
 
3039
3401
  wire 面(同步提交撞 park 的 200 体、`GET /v1/runs/:id` 行形、同一列的其它读者)见「wire」小节。
3040
3402
 
@@ -3050,7 +3412,7 @@ wire 面(同步提交撞 park 的 200 体、`GET /v1/runs/:id` 行形、同一
3050
3412
  PostgreSQL:`UPDATE task_run SET result = NULL WHERE status NOT IN ('suspended','needs_review') AND result -> 'terminal' ->> 'kind' = 'paused';`
3051
3413
  回滚到 7.103.x 前若想连 park 行的结果一起撤(旧版读面不会用到它),再加 `UPDATE task_run SET result = NULL WHERE status IN ('suspended','needs_review');`。
3052
3414
 
3053
- #### local 车道 JSONL 店的坏记录:安全轴三店拒用、其余跳过留痕(S-582)
3415
+ #### local 车道 JSONL 店的坏记录:安全轴三店拒用、其余跳过留痕
3054
3416
 
3055
3417
  内部构造面见「类型面与嵌入方」小节。
3056
3418
 
@@ -3070,7 +3432,7 @@ wire 面(同步提交撞 park 的 200 体、`GET /v1/runs/:id` 行形、同一
3070
3432
 
3071
3433
  ### 部署:sema-up
3072
3434
 
3073
- #### sema-up 数据根按项目分、一条根只归一个项目(S-851)
3435
+ #### sema-up 数据根按项目分、一条根只归一个项目
3074
3436
 
3075
3437
  - **sema-up 自动数据根按项目分 + 项目标记(部署面)**:多盘机不给 `--data-root` 时,新装项目的数据根是 `<大盘>/sema-data/<project>`(此前是
3076
3438
  `<大盘>/sema-data`,同机第二个项目会自动落进同一份目录);任何来源的数据根首次使用时落一只 `.sema-up-project` 标记,之后装 / 重跑(含
@@ -3107,28 +3469,28 @@ wire 面(同步提交撞 park 的 200 体、`GET /v1/runs/:id` 行形、同一
3107
3469
  = 本进程阀门的生效判决,只喂配置目录该行的 `effectiveValue`。自建 `ServiceDeps` 的嵌入方填自己进程的真实判决;没有接记忆整理的填
3108
3470
  `{ enabled: false, source: "explicit" }`。(记忆整理阀门;正文见「env 与启动」小节)
3109
3471
  - **类型面(硬 breaking,tsc 红即通知)**:`ServiceConfig.configProvider` `string` → `"local" | "remote"`;`createConfigProvider` 的入参
3110
- `provider` 同收、`localDir` **必填**(不再回落 `process.cwd()` —— 传你的本地配置根;只造中心源的调用方随便传一个,它不被读)。(S-841;正文见「env 与启动」小节)
3472
+ `provider` 同收、`localDir` **必填**(不再回落 `process.cwd()` —— 传你的本地配置根;只造中心源的调用方随便传一个,它不被读)。(正文见「env 与启动」小节)
3111
3473
 
3112
3474
  #### 包导出面:自建会话店 / 自建后端 / 自建 `ServiceDeps`
3113
3475
 
3114
3476
  - **嵌入方**:公共导出的 `OwnerAwareSessionStore` 多一只可选读口 `sessionFaceOf`(属主 + 化身一次读)—— 自建会话店要让 parked 决定可用必须实现它
3115
3477
  (缺席的部署决定整条 500,不静默跳过复核);`StoreBackend.runOneTimeMigrations()` 的报告型多两键(`sessionIncarnationColumn` /
3116
- `sessionIncarnationsBackfilled`,自建后端 tsc 即通知)。其余改名(`ParkedDecideDeps.sessionOwnerOf` → `sessionFaceOf` 等)都在内部装配面,不在包导出面。(S-790 / S-506;正文见「wire」小节与「存储与一次性迁移」小节)
3478
+ `sessionIncarnationsBackfilled`,自建后端 tsc 即通知)。其余改名(`ParkedDecideDeps.sessionOwnerOf` → `sessionFaceOf` 等)都在内部装配面,不在包导出面。(正文见「wire」小节与「存储与一次性迁移」小节)
3117
3479
  - **自建 `ServiceDeps` 的嵌入方**:新增可选位 `sealedKeyPublic`(只含 `latest` 的公钥面);不传 ⇒ 你的 caps 体里没有这一段,其余不变。(`sealedKey`;正文见「wire」小节)
3118
3480
 
3119
3481
  #### 内部构造面(对包消费方零影响)
3120
3482
 
3121
3483
  - 内部面(非公开导出):三家 run 店的 `setSuspended` / `setNeedsReview` 收第二个必填参数 `result`(结果或 `null`),`result` 列经同一只入口
3122
- `sealRunRowResult`(封口 + 脱敏)落列。契约全文见 `docs/ASSISTANT-WIRE-CONTRACT.md` §5.0c。(S-173;正文见「wire」小节与「存储与一次性迁移」小节)
3484
+ `sealRunRowResult`(封口 + 脱敏)落列。契约全文见 `docs/ASSISTANT-WIRE-CONTRACT.md` §5.0c。(正文见「wire」小节与「存储与一次性迁移」小节)
3123
3485
  - **内部构造面(对包消费方零影响)**:`observability/corrupt-read-seat.ts` 的 `createCorruptReadSeat` 多一个可选第 4 位 `leg`;`plugins/session-event-payload.ts`
3124
- 的 `decodeSessionEventPayload` 对坏体抛 `SessionError("corrupt_session")`(此前是 `StoreCorruptError`)。都不在包的导出面上。(S-612;正文见「wire」小节)
3486
+ 的 `decodeSessionEventPayload` 对坏体抛 `SessionError("corrupt_session")`(此前是 `StoreCorruptError`)。都不在包的导出面上。(正文见「wire」小节)
3125
3487
  - **内部构造面(对包消费方零影响)**:`createFilePermissionRuleStores` 的 opts 多一个 `warn`(两份日志的腐读座;`onError` 只接 core 规则文件);
3126
3488
  `FileRuleApprovalRecordStore` / `FileRuleImportTicketStore` 构造参数里原 `onError` 位改为 `warn: Logger["warn"]`;`FileApprovalNonceStore` /
3127
3489
  `FileApprovalExemptionStore` / `FileApprovalAskStore` / `FileResumeAnchorStore` / `FileSendFileLedger` 多一个可选 `{ warn }`、`FileRunStore` 的 opts 多
3128
3490
  `warn`(均可缺席,缺席 ⇒ `console.warn`)。`observability/corrupt-read-seat.ts` 的 `createSkippedRecordSink` 删除(分级收进重放属主)。这些构造器都不在
3129
- 包的导出面上(`package.json` `exports` 只开 `.` / `./main` / `./device-protocol`),`StoreBackend` 交出的实例型不变 —— 列在这里给仓内 fork 与自建装配口。(S-582;正文见「存储与一次性迁移」小节)
3491
+ 包的导出面上(`package.json` `exports` 只开 `.` / `./main` / `./device-protocol`),`StoreBackend` 交出的实例型不变 —— 列在这里给仓内 fork 与自建装配口。(正文见「存储与一次性迁移」小节)
3130
3492
 
3131
- ## 7.103.2 —— core 7.33.8 提货:`GIT_CONFIG_PARAMETERS` 里的嵌套命令凭据助手不论第几条都整只扣;OTLP 头变量一族不进宿主子进程(S-845)
3493
+ ## 7.103.2 —— core 7.33.8 提货:`GIT_CONFIG_PARAMETERS` 里的嵌套命令凭据助手不论第几条都整只扣;OTLP 头变量一族不进宿主子进程
3132
3494
 
3133
3495
  - 宿主子进程(host shell / 三条 git 腿 / 语言服务器 / bake-runner)自本版起:`GIT_CONFIG_PARAMETERS` 里要往里读一层命令的内联凭据助手(`!sh -c '…口令…'`)不论第几条
3134
3496
  ⇒ 整只不交(7.103.1 上第 4 条起放行;鉴权头 / URL userinfo / 口令旗等其它凭据形任何位置早就整只扣),同一只里无害的 `-c` 一起没了。
@@ -3164,7 +3526,7 @@ wire 面(同步提交撞 park 的 200 体、`GET /v1/runs/:id` 行形、同一
3164
3526
  · **不在本条范围**:`local-docker` 与 `e2b` 两条车道不经这一组装,它们的死工作目录报法本节未核。
3165
3527
  · 零 wire 键、零 DDL、零新旋钮。
3166
3528
 
3167
- ## 7.103.0(车OY 部分)—— server 进程出网认 `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY`(S-776)
3529
+ ## 7.103.0(车OY 部分)—— server 进程出网认 `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY`
3168
3530
 
3169
3531
  - **出网跟着代理变量走**:server 进程(HTTP 服务与 `run-local`)的出网 —— 引擎 → 网关、中心拉取 / 公告 / 凭证续签、WebSearch、对象存储、OTLP … ——
3170
3532
  自本版起在 **Node 运行时**按 `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY`(小写同认且优先)走;回环目标恒直连。`NO_PROXY` 不支持 CIDR。**谁受伤**:env 里因别的原因带着 `HTTP(S)_PROXY`、此前
@@ -3177,7 +3539,7 @@ wire 面(同步提交撞 park 的 200 体、`GET /v1/runs/:id` 行形、同一
3177
3539
 
3178
3540
  ## 7.103.0(车OR 部分)—— core 7.33.1 提货:模型调用超时按段重排(`MODEL_CONNECT_TIMEOUT_MS` 退役 / `MODEL_FIRST_BYTE_TIMEOUT_MS` / failover 拓扑首字节 lane / 看门狗 `0` 义 / `wiring_manifest.hands`)
3179
3541
 
3180
- - **`MODEL_CONNECT_TIMEOUT_MS` 删除,设了即拒启**(S-753;任何值,含 `0`;空串 = 未设):拒句带码 `[config.env_key_retired]`,点名替代键。
3542
+ - **`MODEL_CONNECT_TIMEOUT_MS` 删除,设了即拒启**(任何值,含 `0`;空串 = 未设):拒句带码 `[config.env_key_retired]`,点名替代键。
3181
3543
  它名义「建连」、实际计到**响应头**:本仓自带的 30 000 缺省把自托管网关的 prefill(发生在响应头之前)在 30 s 处掐断、同 body 重发、
3182
3544
  报「connection lost」。core 7.33.0 起建连(TCP + TLS)是传输层自己的钟,不再有旋钮。**迁移**:删掉这个键;要给响应头等待设上限,
3183
3545
  改设下一条的新键(值语义变了,别照抄旧值)。
@@ -3186,7 +3548,7 @@ wire 面(同步提交撞 park 的 200 体、`GET /v1/runs/:id` 行形、同一
3186
3548
  `GATEWAY_MAX_RETRIES`),期间流上一帧 `status {phase:"reconnecting", errClass:"stall"}`,终局句点名 `firstByteTimeoutMs`。合法域
3187
3549
  `[0, 2147483647]` 整数,其余拒启。
3188
3550
  - **failover 拓扑(`MODEL_GATEWAY_FALLBACK_URLS`)的首字节 lane = core 缺省**:每条网关路由首窗到点后都有 core 缺省的一次加宽重试,之后才
3189
- 交给 failover。server **不铸** core 7.33.1 #1128 的 `firstByteRetries` 座(任何拓扑;S-753 车PA):它只在构造期,而调用方可按请求写
3551
+ 交给 failover。server **不铸** core 7.33.1 的 `firstByteRetries` 座(任何拓扑;车PA):它只在构造期,而调用方可按请求写
3190
3552
  `resilience.allowFailover: false` 关掉 failover(那一次只用主网关、身后没有备)—— 按拓扑铸 0 会让那一次少一次加宽重试。**谁受伤**:主网关接了
3191
3553
  TCP 却不回响应头时,缺省下要等完 core 的首字节 lane(缺省首窗 + 一次加宽重试;以 core 7.33.x 缺省计约 15 分钟;core 改缺省即变)才切备,
3192
3554
  **时间预算短于那一段的调用切不到备**(code-review council 每个镜头 180 s 与 team discuss 600 s:lane 没走完就被取消,备网关一次都没被尝试 ——
@@ -3198,11 +3560,11 @@ wire 面(同步提交撞 park 的 200 体、`GET /v1/runs/:id` 行形、同一
3198
3560
  failover 拓扑上首字节段设 `0` ⇒ 挂住的主网关**永不**被首字节 lane 切走(只剩 run 级时限收尾)。依赖「设 0 也还有 300 s 兜底」的部署改设
3199
3561
  一个大数。启动日志 `listening` 行 `brain` 段:`connectTimeoutMs` 键删、`firstByteTimeoutMs` 键加(`null` = core 缺省),三只看门狗键设 `0` 时
3200
3562
  显示 `0`(此前显示 `null`)。
3201
- - **`wiring_manifest` 帧多一段 `hands: { mounted, reason? }`**(core 7.33.1 #1039,租户可见,与 `lsp` 同形):`mounted: false` +
3563
+ - **`wiring_manifest` 帧多一段 `hands: { mounted, reason? }`**(core 7.33.1,租户可见,与 `lsp` 同形):`mounted: false` +
3202
3564
  `reason: "no_execution_env"` = **这条腿**没有手(按腿的正面陈述 —— 同一台部署上 scan / council / discuss 这类无手车道也读 false);
3203
3565
  `mounted: true` ≠ shell 可达。operator 面的 `configFingerprint` **一次性变值**
3204
3566
  (同装配各腿仍相等)—— 持久化 / 钉了指纹的读者会见一次跳变。
3205
- - **`GIT_CONFIG_KEY_<i>` 不再被剥**(core 7.33.1 #1129):宿主子进程(host shell / git 腿 / 语言服务器 / bake-runner)里,普通的 git env
3567
+ - **`GIT_CONFIG_KEY_<i>` 不再被剥**(core 7.33.1):宿主子进程(host shell / git 腿 / 语言服务器 / bake-runner)里,普通的 git env
3206
3568
  配置组原样到达;只有某个 KEY 的值带 `<scheme>://<userinfo>@`(令牌 insteadOf)时这一条扣下(7.103.0 是本仓整组扣;7.103.1 起判定全在 core 7.33.6,见本段末条)。🔴 **安全轴披露(core
3207
3569
  KL-1129a)**:`GIT_CONFIG_VALUE_<i>` **不在** core 的凭据形状判据里 —— 组里 KEY 是 `http.extraHeader`、VALUE 是 `Authorization: Bearer …`
3208
3570
  这一形会**原样**进宿主子进程(含模型能驱动的 host shell),并在 `isolateConfig` 的 git 腿上作为命令级配置**生效**(`GIT_CONFIG_GLOBAL /
@@ -3243,23 +3605,23 @@ wire 面(同步提交撞 park 的 200 体、`GET /v1/runs/:id` 行形、同一
3243
3605
  glob `?`;`safe.directory` 写进宿主自有的全局配置文件(`GIT_CONFIG_GLOBAL`;仓库级配置对它无效);`@scope` 包 URL 写进仓库级配置。(把 `@` 写成 `%40`
3244
3606
  同样触发判据 —— 不可用。)**已知边界**(core 7.33.6):① 子进程看得见占位行 `sema.withheld=`(见上);② 运行时才拼出来的口令(`$(…)` / `$VAR` / `read` 取值、
3245
3607
  由展开给出的程序名)core 读不到、照原样交出;③ `http.extraHeader` 下的**非凭据**头(trace / 路由头)照样按键扣,要它到达写进 git 配置文件。
3246
- **带口令的代理(core 7.33.5 #1150 / 7.33.6 #1165)**:`http_proxy` / `https_proxy` / `all_proxy` 与 `npm_config_https_proxy` / `npm_config_proxy` /
3608
+ **带口令的代理(core 7.33.5 / 7.33.6)**:`http_proxy` / `https_proxy` / `all_proxy` 与 `npm_config_https_proxy` / `npm_config_proxy` /
3247
3609
  `ftp_proxy`(大小写两形)值里带 userinfo / `%40` ⇒ 宿主子进程拿不到它(`family-rule`);只有地址的代理与 `NO_PROXY` 照到;写死口令的 `GIT_SSH_COMMAND` /
3248
3610
  `GIT_PROXY_COMMAND`(`sshpass -p <口令>` …)同样不到。出路见 `docs/DEPLOY-PREREQS.md`(服务进程自己的出网不受影响)。
3249
- ⤷ **`GIT_CONFIG_PARAMETERS`(S-783)随 core 7.33.5 #1141 收口**:git 的命令级配置 env(`git -c` 传给子进程的那一份)按 git 自己的引号语法读,
3611
+ ⤷ **`GIT_CONFIG_PARAMETERS`随 core 7.33.5 收口**:git 的命令级配置 env(`git -c` 传给子进程的那一份)按 git 自己的引号语法读,
3250
3612
  任一条带凭据(或 git 会拒的写法)⇒ 整只不到宿主子进程;干净的列表逐字节原样。7.103.0 此处「不在剥密族表里」的披露降级为「core 扣它」。
3251
- ⤷ 7.103.2(core 7.33.8 #1183)起按判、不论第几条(7.103.1 / core 7.33.6 上第 4 条起的嵌套命令凭据助手 `!sh -c '…'` 读不到、整只原样到 —— S-845;其它凭据形任何位置
3613
+ ⤷ 7.103.2(core 7.33.8)起按判、不论第几条(7.103.1 / core 7.33.6 上第 4 条起的嵌套命令凭据助手 `!sh -c '…'` 读不到、整只原样到;其它凭据形任何位置
3252
3614
  都整只扣);任一条带凭据 ⇒ 整只变量不交,同一只里无害的 `-c` 一起没了。凭据别写进它;无害设置按腿分(隔离配置的 project-memory / center-plugins 两腿只能留在 env:
3253
3615
  删掉凭据条目或改用 `GIT_CONFIG_COUNT` 组;其余四腿另可写进宿主 git 配置文件)—— 出路见 `docs/DEPLOY-PREREQS.md` 同段。
3254
3616
 
3255
- ## 7.103.0(车OW 部分)—— `/health.modelRefusals` 是**免鉴权面**上的新键(S-768;7.103.0 验收 G2 格补披露)
3617
+ ## 7.103.0(车OW 部分)—— `/health.modelRefusals` 是**免鉴权面**上的新键(7.103.0 验收 G2 格补披露)
3256
3618
 
3257
3619
  - **披露**:`GET /health` 不鉴权(既有),7.103.0 起它多带 `modelRefusals`(与 fleet 心跳同一对象):条目名与拒因码经 settings-schema 的 `isReportableRefusalName` 出口筛过(7.103.1 换钉 6.3.0 后 = 白名单闭形 ∧ 无密钥形 ∧ 无 URL userinfo),但**合规的条目名本身会出现在免鉴权面上**。不想让匿名读到目录条目名的部署:把 `/health` 放在反代 / 网关的鉴权后面,或按 USAGE「健康面」节改用带鉴权的 `/v1/capabilities` 读同一对象。
3258
3620
  - 无操作项;零 wire 键增删之外的变化。
3259
3621
 
3260
3622
  ## 7.102.0(车OI 部分)—— core 7.32.0 提货带来的四条(后台 shell 退出硬收 / Esc 不收后台 / 读根授权与 artifact store / parked 继承工具新失败形)
3261
3623
 
3262
- - **后台 shell 在进程退出与会话删除时被硬收(core #1107,行为面)**:
3624
+ - **后台 shell 在进程退出与会话删除时被硬收(core 侧变更,行为面)**:
3263
3625
  - **进程退出**:屏蔽 SIGTERM 的后台循环、崩溃出口上宽限跑不完的后台进程,升级后在退出边界被组 SIGKILL 收掉(改前活过引擎,成孤儿)。
3264
3626
  - **`DELETE /v1/sessions/:id`**:7.101.1 只走软梯子(SIGTERM → `HOST_BG_KILL_GRACE_MS` → 组 SIGKILL —— 屏蔽 SIGTERM 的 shell 在宽限后同样死);
3265
3627
  7.102.0 起是「软 → 等一次宽限 → 硬」:SIGTERM 处理器照样有一次宽限跑完,宽限之后再补硬面一枪组 SIGKILL 并出受据。有后台行的会话,
@@ -3269,33 +3631,33 @@ wire 面(同步提交撞 park 的 200 体、`GET /v1/runs/:id` 行形、同一
3269
3631
  - **谁受伤**:① 依赖「引擎挂了后台进程还在跑」而又没有声明保留的部署 —— 迁移:给那条任务写 `retainBackgroundProcesses: true`(或用 env
3270
3632
  级保留),或者干脆把服务交给进程管理器;② **受控退(SIGTERM 排空)时没有开着的连接** —— 退出很快落到退出边界,硬面的组 SIGKILL 紧跟
3271
3633
  早收割的 SIGTERM,后台进程的**优雅退出可能被截断**(7.101.1 在这里只发 SIGTERM,进程作为孤儿把处理器跑完)。这是 core 7.32 契约
3272
- 「每个退出终点软后硬」带来的;缓解(受控退在早收割 + 一次宽限之后再退出)候 S-758,本版不做。要保住优雅退出的长活服务,声明保留。
3273
- - **声明读根落在本地 artifact store 里 ⇒ Artifact 挂载拒(core #1093,部署面 NARROWING,本服务今天零影响)**:core 7.32.0 起
3634
+ 「每个退出终点软后硬」带来的;缓解(受控退在早收割 + 一次宽限之后再退出)候后续,本版不做。要保住优雅退出的长活服务,声明保留。
3635
+ - **声明读根落在本地 artifact store 里 ⇒ Artifact 挂载拒(core 侧变更,部署面 NARROWING,本服务今天零影响)**:core 7.32.0 起
3274
3636
  `additionalReadDirectories` / `additionalDirectories` 里**任何一条**在 artifact store 之内(或就是它、或包含它),挂载期
3275
3637
  `config.artifact_host_invalid`(改前只拒「store 在根内」一个方向)。本服务今天**没有** artifact host,这条到达不了;将来接 host 时,别把
3276
3638
  读根声明到 store 目录里。同批:读根按身份判 —— 声明的根在 run 首次 shell 判定前被换成软链,不再为链的目标作保。
3277
- - **parked 子代停在「继承工具」上的 `/decide` allow ⇒ 422 `parked_resume.startup_failed`(core #1110,新失败形,非回归)**:core 7.32.0 起
3639
+ - **parked 子代停在「继承工具」上的 `/decide` allow ⇒ 422 `parked_resume.startup_failed`(core 侧变更,新失败形,非回归)**:core 7.32.0 起
3278
3640
  子代继承场景层工具,停在这类工具上的审批在赎回交不出继承座时被拒(审批留 pending,`deny` 可结)。本版对一层行交座(不再落这一形;前提是行的根会话现在仍属于这张卡的租户),孙代行 / 根会话已删或易主的行仍落
3279
- (core #1112 候)。7.31.x 的子代根本没有这些工具,所以这不是旧卡的回归。
3641
+ (候 core 侧后续)。7.31.x 的子代根本没有这些工具,所以这不是旧卡的回归。
3280
3642
  - **类型面(本仓内部 API,三句)**:删 `ServiceDeps.parkedReviveTool` / `ParkedDecideDeps.reviveTool`,改 `parkedReviveSurface` /
3281
3643
  `reviveSurface`(按行解析赎回面的工厂,零别名);受害 = 手铸这两个 deps 的嵌入方,tsc 红即通告;补偿 = 固定工具形 `() => ({ reviveTool })`。
3282
3644
 
3283
- ## 7.101.0 —— 十四条(`run-local` 执法三张审批名单 / 人停下的 run 退 1 / 模型目录 fail-closed 三条 + 类型面 `ServiceConfig.modelRefusals` · `ServiceConfig.lspEnvAllow` / 记忆抹除面 409 撤 + 存量只读位一次性 `chmod`(滚动窗内会被旧副本再锁,起服 warn 点名)/ settings 层 `crossSessionInbound: accept` 改答 hold / 子进程剥名收窄 / SQL `session_meta` 新列 / 沙箱名单形错拒启 + 空串值照注入 / `WEB_SEARCH_ENDPOINT` 带 userinfo 拒启 / 配置目录两行 `csv` → `secret` / 被拒名撞档位别名 ⇒ 模型面组拒;S-690 / S-694 / S-699 / S-704 / S-705 / S-712 / S-713 / S-716 / S-723)
3645
+ ## 7.101.0 —— 十四条(`run-local` 执法三张审批名单 / 人停下的 run 退 1 / 模型目录 fail-closed 三条 + 类型面 `ServiceConfig.modelRefusals` · `ServiceConfig.lspEnvAllow` / 记忆抹除面 409 撤 + 存量只读位一次性 `chmod`(滚动窗内会被旧副本再锁,起服 warn 点名)/ settings 层 `crossSessionInbound: accept` 改答 hold / 子进程剥名收窄 / SQL `session_meta` 新列 / 沙箱名单形错拒启 + 空串值照注入 / `WEB_SEARCH_ENDPOINT` 带 userinfo 拒启 / 配置目录两行 `csv` → `secret` / 被拒名撞档位别名 ⇒ 模型面组拒)
3284
3646
 
3285
3647
  - **`run-local` 上 `APPROVAL_REQUIRE` / `APPROVAL_DENY` / `APPROVAL_NEVER_AUTO` 生效**(改前:这条一次性 CLI 腿不读三张名单,名单工具照跑,只有启动日志一条 `tool_policy_only_sensitive_baseline` warn)。改后与 HTTP 腿同一只策略:`APPROVAL_DENY` 命中 ⇒ 当场拒;`APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` 命中 ⇒ stdin 是 TTY 就 `y/N` 问人(问句多一行这次调用的参数),否则当场拒并在 stderr 点名三张名单键(`APPROVAL_NEVER_AUTO` 不吃 `APPROVAL_AUTO_BUDGET` 预算)。**谁受伤**:无 TTY(CI)跑 `run-local`、而 `.env` 与服务共用并带着名单的脚本 —— 名单工具从「照跑」变「当场拒」。**迁移**:给 CLI 环境单独一份 `.env`(不带名单),或设 `APPROVAL_AUTO_BUDGET=<N>` 让 require 名单前 N 次自动批,或在终端里跑(TTY 问人)。`tool_policy_only_sensitive_baseline` 在 `run-local` 上不再出现(名单已执法)。
3286
3648
  - **`run-local`:人拒掉一次工具调用而停下的 run 退 1**(改前退 0)。这类 run 的终局是 completed + `haltedOnUserRejection`(无 TTY 当场拒、TTY 答 N 都是这一形),意思是「停在等人指示」而不是「干完了活」;改后退 1(`--json` 形同样退 1),stdout 仍是模型停下前产出的文字(常为空);非 `--json` 形 stderr 多一行 `task stopped (haltedOnUserRejection): … continue it with --session <id>`。**谁受伤**:靠「`AUTONOMY=ask` / 名单被拒后仍退 0」继续往下跑的脚本。**迁移**:要把「被拒」当成功的脚本改看 stderr 停因行或 `--json` 输出的 `haltedOnUserRejection`。
3287
- - **本部署服务不了的目录条目不可用(S-704 ①,行为面)**:`provider:"anthropic"` 的目录条目在没配 `ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN` 的部署上不进可选目录(`GET /v1/models` 不列、不当缺省),显式选中 ⇒ 400 `request.model_unavailable`(拒因码 `config.model_no_brain`);此前它落网关 brain、带着条目自己的钥匙。不合 settings-schema `ModelEntry` 形的条目同律(`config.model_entry_invalid`;坏 `baseUrl` 此前被退回部署网关)。目录里每条都不可用 ⇒ 那一代模型面整拒(上一代继续服务)。**迁移**:配 anthropic 凭据,或把条目改成 `gateway` / `vllm` 并给它自己的 `baseUrl`;按 `sema_registry_model_no_brain` / `sema_registry_model_entry_invalid` 日志修条目。
3288
- - **一条坏条目只丢它自己(S-704 ②,行为面,所有目录型域)**:schema 逐条丢掉的条目不再让 refresh / 迟到 boot 整拒候选;其余条目照用,坏条目每条一行 `config_entry_dropped`(坐标 + 字段诊断)。**谁受伤**:依赖「一条坏条目冻结整份候选、上一代继续服务」的部署 —— 现在新一代(少那一条)生效。**迁移**:按日志坐标修那一条。
3289
- - **被拒条目的名字撞档位词 / CC 别名 ⇒ 这份候选的模型面整组被拒(S-712,行为面)**:目录里一条不可用(本机无 brain / 形坏被读腿丢掉)的条目恰好叫 `sonnet` / `opus` / `haiku` / `pro` / `flash` / `best` 之类,而档位表会铸出这个词 ⇒ 模型面停在上一代(码 `config.model_refused_name_minted`,warn `sema_registry_model_plane_refused` 点名「被拒名 → 目标条目」);此前(7.101.0 开发期)这个词被静默铸到另一条条目上,显式点它 / 绑它的角色跑在别人的端点与账号上。**迁移**:改名、修好那条条目,或改绑铸出这个词的档位绑定;多台 worker 共用一份中心目录、只有部分 worker 配了 anthropic 凭据(目录里 anthropic 条目叫 `opus` / `sonnet` / `haiku` 且激活了档位组)时,无凭据的 worker 上这一形**每一代**都会出现 —— 在中心按 worker 的 roster(`SEMA_REGISTRY_WORKER`)里把这些条目排出那些 worker,或给它们配凭据,或至少设 `MODEL_ID` 让它们起得来(DEBTS S-749)。没有字符串名的被丢行不触发本条(没有可保留的名字,与停用同处置)。同批:模型面三条不变量(缺省模型 / 路由端点 / 本条)不成立时只拒**模型面这一组**(目录,以及带模型引用、随它同代的 collab 模板 —— boot 按组回落盘上 LKG 时同样整组取 LKG 那一代),同候选的审批名单 / 限额照落(此前整份候选不落,boot 腿日志还写成 `config_source_unreachable_using_env`;拉取成功而应用失败现在是 `config_apply_refused`)。
3290
- - **`MODEL_ID` 不再是 loadConfig 期的硬要求(S-705)**:目录有可用条目即可省;目录应用之后仍没有缺省模型 ⇒ 拒启(`config.default_model_missing`,句首保留 `MODEL_ID is required`)。中心超出 `CONFIG_BOOT_FETCH_BUDGET_MS` 且无 LKG 时 boot 那一刻没有目录:没写 `MODEL_ID` 就拒启 —— 写一个 `MODEL_ID` 兜底或调大预算。
3291
- - **类型面**:`ServiceConfig.modelRefusals`(新必填席;手铸 `ServiceConfig` 的消费方 tsc 即红 —— env 形写 `{}`)与 `ServiceConfig.lspEnvAllow`(S-699 新必填席 `readonly string[]`,同样 tsc 即红 —— 缺省形写 `[]`);`SealedKeyPoisonReason` 删 `unsupported_alg`(形错的 sealed 密文现在让整条不可用,到不了毒丸臂);`FoldedReadWarning` 带 `scope` 判别位、`FetchEffectiveResult` 新键 `droppedEntries`。
3292
- - **记忆抹除面的 409 `memory.layer_unwritable` 撤销(S-697,随 core 7.31.0 #1076 提货;wire 码删除 + 行为面)**:`POST /v1/memory/erase`、`POST /v1/memory/origin/entries/:entryId/clear`、`POST /v1/sessions/:id/memory/erase` 不再在引擎之前做盘上可写预检,这个码不再出现(7.100.0 那条「按 409 体 `chmod u+w <dir>` 后重试」的指路随之撤)—— core 7.31.0 的挂载**一个模式位都不改**(只读层是会话策略:往会话不写的层里写在写点被拒,绕过工具写进去的字节永不被采纳)。7.100.0 上被 409 盖住的三种答复回到 core 自己的读数(非法选择子 400 `config.memory_erasure_request`、清标空理由 422 `memory.origin_clear_invalid`、已提交抹除同 `requestId` 重放的 200 收执),锁住的是别的层时抹除可写层条目照常 200。**升级(一次性)**:存量已锁目录在**最后一个 ≤7.30.x 会话结束后**(= 7.100.0 及更早的 server 副本全部停掉之后)执行 `chmod -R u+w <memoryDir>`(file 记忆引擎的 `<数据根>/memory`)—— 混跑期旧引擎每次只读挂载都会再锁一次,7.31 不替你解。**谁受伤**:没做这一步、又去删一条住在锁住目录里的条目的部署 ⇒ `500`(日志带 core 的同一条 `chmod -R u+w` 补救句),journal 留盘、下次起服失败,照补救句做完即自愈(`docs/DEPLOY-PREREQS.md` 同名段)。**滚动窗内这一形会反复出现**:同一数据根上还有 7.100.0 及更早的副本在跑时,它每次只读挂载一层都会把那一层再锁一次 —— 窗内做过的 `chmod` 会被撤回,7.101.0 副本在那一层上删条目照样 `500` + journal 卡盘。7.101.0 起服时对记忆挂载面探一次:有锁住的层 ⇒ 一条 warn(`engine_notice`,码 `memory.layer_locked_legacy`,`detail.layers` = 层名、`detail.remedy` = 同一句 `chmod -R u+w '<memoryDir>'`),**照常起服**(不拒启:窗内每次 boot 都可能刚被旧副本锁过);看到这一行就先别在那几层上抹除 / 清标,等旧副本全停后执行那一句。按码分支 `memory.layer_unwritable` 的消费方(sdk 错误码目录)删掉那一臂。
3293
- - **settings 层里残留的 `crossSessionInbound: "accept"` ⇒ 跨会话消息 hold(core 7.31.0 #1078,行为面)—— 本服务不受影响(只 env 层接线)**:本服务三层来源里只有 env 管理层 `CROSS_SESSION_INBOUND` 接线(user / repo 两层不读),而 env 写 `accept` 自 7.100.0 起就拒启 ⇒ 下面这一形只波及**自持 settings 层的嵌入方**。7.30.x 把这个退役词读成 `next-turn` 并每腿通告一次(7.100.0 本节那句「由引擎自己读成 `next-turn`」随之过期);7.31.0 起它与任何未知词同路 —— 该层进 `invalidLayers`、fail-closed 落 `hold`(每条跨会话消息以 `invalid-setting` 因由扣住,`peer.inbound_disposition` 披露 `held`)。env `CROSS_SESSION_INBOUND=accept` 自 7.100.0 起就拒启,不受影响;`@sema-agent/settings-schema` 6.0.0 的文件层本就拒这个词,所以只有绕过 schema 写进去的 settings 文件会撞上。**迁移**(仅嵌入方):把每一层的 `accept` 改写成 `next-turn`。
3294
- - **子进程剥名收窄(core 7.31.0 #1081,运行面;7.100.0 本节「子进程按名剥凭据形变量」一条的修正)**:十个预算名(`MAX_NEW_TOKENS` `MAX_COMPLETION_TOKENS` `AIDER_MAP_TOKENS` `AIDER_MAX_CHAT_HISTORY_TOKENS` `MAX_BATCH_PREFILL_TOKENS` `MAX_WAITING_TOKENS` `MAX_TOP_N_TOKENS` `RATE_LIMIT_TOKENS` `PROMPT_TOKENS` `CONTEXT_TOKENS`)与两个开关(`DB_FOREIGN_KEYS` `JSON_SORT_KEYS`)按**精确名**豁免,重新到得了工具子 shell、git 子进程与本地语言服务器;装饰过的变体(`USERS_MAX_NEW_TOKENS`、`MAX_NEW_TOKENS_2`)仍剥。为这五名改过名的部署可以撤回那一手(留着也无害);`inheritEnv:[names]` 是嵌入方构造执行环境时的选项,不是部署级放回旋钮(S-852,7.104.0 起文档写明)。
3295
- - **SQL 后端:`session_meta` 新列 `instruction_source`(S-690,存储面)**:存量 MySQL 协议 / PostgreSQL 库升级后**拒启**(`config.schema_mismatch`,拒因里逐字给出 `ALTER TABLE session_meta ADD COLUMN instruction_source VARCHAR(64) NULL;`,PG 为 `… VARCHAR(64) COLLATE "C";`),照它加列或删库重建;滚动序恒为「**先升库、再升副本**」(加列之后,旧副本重启会把它看成幽灵列而拒启)。`DB_BACKEND=local` 与内存形零动作。见上方「SQL 存储面 BREAKING」表。
3296
- - **沙箱名单形错拒启 + 空串值照注入(S-713,行为面)**:`E2B_SANDBOX_ENV` / `DOCKER_SANDBOX_ENV` 写了空段、尾逗号(`A,`)、带 `-` / `.` 的键名(`MY-TOKEN`)或点名名单型旋钮(自己 / 另一只沙箱名单 / `LSP_ENV_ALLOW`)⇒ **拒启**(拒句点名键与第几段,不回显原值;修前静默吞或照转发)。点到的键值为空串(compose `X=${X:-}` 在宿主没设时的常态)⇒ **照注入空串**(修前不注入):local-docker 上 `-e X=` 盖掉镜像里的同名缺省值,e2b 上盖掉 `SANDBOX_PKG_SOURCE` 推导出的同名包源变量。**迁移**:按拒句修名单;不想盖缺省值就把那个名从名单里删掉。
3297
- - **`WEB_SEARCH_ENDPOINT` 带 userinfo ⇒ 拒启(S-716,行为面)**:`WEB_SEARCH_PROVIDER` 点名了后端、`WEB_SEARCH_ENDPOINT` 形如 `https://user:pw@host/…`(或只带 `user@`)的部署升级后拒启(`config.web_search_invalid`);每请求 `settings.webSearch.endpoint` 带这一形从 202 变 `400 request.field_invalid`(修前这一形本来就用不了:fetch 每次都抛,错误文本还带出口令)。**迁移**:brave / tavily 的凭据走 `WEB_SEARCH_API_KEY`(或 `settings.webSearch.apiKey`);带 basic-auth 的 SearXNG 在前面放一层注入鉴权的反代。
3298
- - **配置目录两行 `csv` → `secret`(S-713,wire 形变)**:`GET /v1/config/catalog` 的 `E2B_SANDBOX_ENV` / `DOCKER_SANDBOX_ENV` 两行 `type` `csv` → `secret`、`valueClass` `plain` → `secret`、`effectiveValue` 从名字数组变 `{ present }`,`summary.secret` 计数 +2。读这两行名单内容的消费方改读起服行 `remote_exec_enabled.sandboxEnvKeys`(只键名);这两只旋钮的原文从此也不进 host shell / git 子进程 / 语言服务器(在这些子进程里读它们的脚本收不到了)。
3649
+ - **本部署服务不了的目录条目不可用(行为面)**:`provider:"anthropic"` 的目录条目在没配 `ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN` 的部署上不进可选目录(`GET /v1/models` 不列、不当缺省),显式选中 ⇒ 400 `request.model_unavailable`(拒因码 `config.model_no_brain`);此前它落网关 brain、带着条目自己的钥匙。不合 settings-schema `ModelEntry` 形的条目同律(`config.model_entry_invalid`;坏 `baseUrl` 此前被退回部署网关)。目录里每条都不可用 ⇒ 那一代模型面整拒(上一代继续服务)。**迁移**:配 anthropic 凭据,或把条目改成 `gateway` / `vllm` 并给它自己的 `baseUrl`;按 `sema_registry_model_no_brain` / `sema_registry_model_entry_invalid` 日志修条目。
3650
+ - **一条坏条目只丢它自己(行为面,所有目录型域)**:schema 逐条丢掉的条目不再让 refresh / 迟到 boot 整拒候选;其余条目照用,坏条目每条一行 `config_entry_dropped`(坐标 + 字段诊断)。**谁受伤**:依赖「一条坏条目冻结整份候选、上一代继续服务」的部署 —— 现在新一代(少那一条)生效。**迁移**:按日志坐标修那一条。
3651
+ - **被拒条目的名字撞档位词 / CC 别名 ⇒ 这份候选的模型面整组被拒(行为面)**:目录里一条不可用(本机无 brain / 形坏被读腿丢掉)的条目恰好叫 `sonnet` / `opus` / `haiku` / `pro` / `flash` / `best` 之类,而档位表会铸出这个词 ⇒ 模型面停在上一代(码 `config.model_refused_name_minted`,warn `sema_registry_model_plane_refused` 点名「被拒名 → 目标条目」);此前(7.101.0 开发期)这个词被静默铸到另一条条目上,显式点它 / 绑它的角色跑在别人的端点与账号上。**迁移**:改名、修好那条条目,或改绑铸出这个词的档位绑定;多台 worker 共用一份中心目录、只有部分 worker 配了 anthropic 凭据(目录里 anthropic 条目叫 `opus` / `sonnet` / `haiku` 且激活了档位组)时,无凭据的 worker 上这一形**每一代**都会出现 —— 在中心按 worker 的 roster(`SEMA_REGISTRY_WORKER`)里把这些条目排出那些 worker,或给它们配凭据,或至少设 `MODEL_ID` 让它们起得来(已记债务)。没有字符串名的被丢行不触发本条(没有可保留的名字,与停用同处置)。同批:模型面三条不变量(缺省模型 / 路由端点 / 本条)不成立时只拒**模型面这一组**(目录,以及带模型引用、随它同代的 collab 模板 —— boot 按组回落盘上 LKG 时同样整组取 LKG 那一代),同候选的审批名单 / 限额照落(此前整份候选不落,boot 腿日志还写成 `config_source_unreachable_using_env`;拉取成功而应用失败现在是 `config_apply_refused`)。
3652
+ - **`MODEL_ID` 不再是 loadConfig 期的硬要求**:目录有可用条目即可省;目录应用之后仍没有缺省模型 ⇒ 拒启(`config.default_model_missing`,句首保留 `MODEL_ID is required`)。中心超出 `CONFIG_BOOT_FETCH_BUDGET_MS` 且无 LKG 时 boot 那一刻没有目录:没写 `MODEL_ID` 就拒启 —— 写一个 `MODEL_ID` 兜底或调大预算。
3653
+ - **类型面**:`ServiceConfig.modelRefusals`(新必填席;手铸 `ServiceConfig` 的消费方 tsc 即红 —— env 形写 `{}`)与 `ServiceConfig.lspEnvAllow`(新必填席 `readonly string[]`,同样 tsc 即红 —— 缺省形写 `[]`);`SealedKeyPoisonReason` 删 `unsupported_alg`(形错的 sealed 密文现在让整条不可用,到不了毒丸臂);`FoldedReadWarning` 带 `scope` 判别位、`FetchEffectiveResult` 新键 `droppedEntries`。
3654
+ - **记忆抹除面的 409 `memory.layer_unwritable` 撤销(随 core 7.31.0 提货;wire 码删除 + 行为面)**:`POST /v1/memory/erase`、`POST /v1/memory/origin/entries/:entryId/clear`、`POST /v1/sessions/:id/memory/erase` 不再在引擎之前做盘上可写预检,这个码不再出现(7.100.0 那条「按 409 体 `chmod u+w <dir>` 后重试」的指路随之撤)—— core 7.31.0 的挂载**一个模式位都不改**(只读层是会话策略:往会话不写的层里写在写点被拒,绕过工具写进去的字节永不被采纳)。7.100.0 上被 409 盖住的三种答复回到 core 自己的读数(非法选择子 400 `config.memory_erasure_request`、清标空理由 422 `memory.origin_clear_invalid`、已提交抹除同 `requestId` 重放的 200 收执),锁住的是别的层时抹除可写层条目照常 200。**升级(一次性)**:存量已锁目录在**最后一个 ≤7.30.x 会话结束后**(= 7.100.0 及更早的 server 副本全部停掉之后)执行 `chmod -R u+w <memoryDir>`(file 记忆引擎的 `<数据根>/memory`)—— 混跑期旧引擎每次只读挂载都会再锁一次,7.31 不替你解。**谁受伤**:没做这一步、又去删一条住在锁住目录里的条目的部署 ⇒ `500`(日志带 core 的同一条 `chmod -R u+w` 补救句),journal 留盘、下次起服失败,照补救句做完即自愈(`docs/DEPLOY-PREREQS.md` 同名段)。**滚动窗内这一形会反复出现**:同一数据根上还有 7.100.0 及更早的副本在跑时,它每次只读挂载一层都会把那一层再锁一次 —— 窗内做过的 `chmod` 会被撤回,7.101.0 副本在那一层上删条目照样 `500` + journal 卡盘。7.101.0 起服时对记忆挂载面探一次:有锁住的层 ⇒ 一条 warn(`engine_notice`,码 `memory.layer_locked_legacy`,`detail.layers` = 层名、`detail.remedy` = 同一句 `chmod -R u+w '<memoryDir>'`),**照常起服**(不拒启:窗内每次 boot 都可能刚被旧副本锁过);看到这一行就先别在那几层上抹除 / 清标,等旧副本全停后执行那一句。按码分支 `memory.layer_unwritable` 的消费方(sdk 错误码目录)删掉那一臂。
3655
+ - **settings 层里残留的 `crossSessionInbound: "accept"` ⇒ 跨会话消息 hold(core 7.31.0,行为面)—— 本服务不受影响(只 env 层接线)**:本服务三层来源里只有 env 管理层 `CROSS_SESSION_INBOUND` 接线(user / repo 两层不读),而 env 写 `accept` 自 7.100.0 起就拒启 ⇒ 下面这一形只波及**自持 settings 层的嵌入方**。7.30.x 把这个退役词读成 `next-turn` 并每腿通告一次(7.100.0 本节那句「由引擎自己读成 `next-turn`」随之过期);7.31.0 起它与任何未知词同路 —— 该层进 `invalidLayers`、fail-closed 落 `hold`(每条跨会话消息以 `invalid-setting` 因由扣住,`peer.inbound_disposition` 披露 `held`)。env `CROSS_SESSION_INBOUND=accept` 自 7.100.0 起就拒启,不受影响;`@sema-agent/settings-schema` 6.0.0 的文件层本就拒这个词,所以只有绕过 schema 写进去的 settings 文件会撞上。**迁移**(仅嵌入方):把每一层的 `accept` 改写成 `next-turn`。
3656
+ - **子进程剥名收窄(core 7.31.0,运行面;7.100.0 本节「子进程按名剥凭据形变量」一条的修正)**:十个预算名(`MAX_NEW_TOKENS` `MAX_COMPLETION_TOKENS` `AIDER_MAP_TOKENS` `AIDER_MAX_CHAT_HISTORY_TOKENS` `MAX_BATCH_PREFILL_TOKENS` `MAX_WAITING_TOKENS` `MAX_TOP_N_TOKENS` `RATE_LIMIT_TOKENS` `PROMPT_TOKENS` `CONTEXT_TOKENS`)与两个开关(`DB_FOREIGN_KEYS` `JSON_SORT_KEYS`)按**精确名**豁免,重新到得了工具子 shell、git 子进程与本地语言服务器;装饰过的变体(`USERS_MAX_NEW_TOKENS`、`MAX_NEW_TOKENS_2`)仍剥。为这五名改过名的部署可以撤回那一手(留着也无害);`inheritEnv:[names]` 是嵌入方构造执行环境时的选项,不是部署级放回旋钮(7.104.0 起文档写明)。
3657
+ - **SQL 后端:`session_meta` 新列 `instruction_source`(存储面)**:存量 MySQL 协议 / PostgreSQL 库升级后**拒启**(`config.schema_mismatch`,拒因里逐字给出 `ALTER TABLE session_meta ADD COLUMN instruction_source VARCHAR(64) NULL;`,PG 为 `… VARCHAR(64) COLLATE "C";`),照它加列或删库重建;滚动序恒为「**先升库、再升副本**」(加列之后,旧副本重启会把它看成幽灵列而拒启)。`DB_BACKEND=local` 与内存形零动作。见上方「SQL 存储面 BREAKING」表。
3658
+ - **沙箱名单形错拒启 + 空串值照注入(行为面)**:`E2B_SANDBOX_ENV` / `DOCKER_SANDBOX_ENV` 写了空段、尾逗号(`A,`)、带 `-` / `.` 的键名(`MY-TOKEN`)或点名名单型旋钮(自己 / 另一只沙箱名单 / `LSP_ENV_ALLOW`)⇒ **拒启**(拒句点名键与第几段,不回显原值;修前静默吞或照转发)。点到的键值为空串(compose `X=${X:-}` 在宿主没设时的常态)⇒ **照注入空串**(修前不注入):local-docker 上 `-e X=` 盖掉镜像里的同名缺省值,e2b 上盖掉 `SANDBOX_PKG_SOURCE` 推导出的同名包源变量。**迁移**:按拒句修名单;不想盖缺省值就把那个名从名单里删掉。
3659
+ - **`WEB_SEARCH_ENDPOINT` 带 userinfo ⇒ 拒启(行为面)**:`WEB_SEARCH_PROVIDER` 点名了后端、`WEB_SEARCH_ENDPOINT` 形如 `https://user:pw@host/…`(或只带 `user@`)的部署升级后拒启(`config.web_search_invalid`);每请求 `settings.webSearch.endpoint` 带这一形从 202 变 `400 request.field_invalid`(修前这一形本来就用不了:fetch 每次都抛,错误文本还带出口令)。**迁移**:brave / tavily 的凭据走 `WEB_SEARCH_API_KEY`(或 `settings.webSearch.apiKey`);带 basic-auth 的 SearXNG 在前面放一层注入鉴权的反代。
3660
+ - **配置目录两行 `csv` → `secret`(wire 形变)**:`GET /v1/config/catalog` 的 `E2B_SANDBOX_ENV` / `DOCKER_SANDBOX_ENV` 两行 `type` `csv` → `secret`、`valueClass` `plain` → `secret`、`effectiveValue` 从名字数组变 `{ present }`,`summary.secret` 计数 +2。读这两行名单内容的消费方改读起服行 `remote_exec_enabled.sandboxEnvKeys`(只键名);这两只旋钮的原文从此也不进 host shell / git 子进程 / 语言服务器(在这些子进程里读它们的脚本收不到了)。
3299
3661
 
3300
3662
  ## 7.100.0 —— 十条 BREAKING(部署面 `CROSS_SESSION_INBOUND=accept` 拒启 / 类型面 `MailboxStore.ack` / WebSearch 配置形错响亮 / 请求面 `settings.webSearch` / WebSearch 报错句换形 / deny 部署的「无人可答」记部署政策 / 记忆抹除面新 409 / 审批名单热应用 / 子进程剥名 / local 车道回滚前收敛 ask 账本)
3301
3663
 
@@ -3304,17 +3666,17 @@ wire 面(同步提交撞 park 的 200 体、`GET /v1/runs/:id` 行形、同一
3304
3666
  - **部署 env:WebSearch 旋钮形错 ⇒ 拒启**。`WEB_SEARCH_PROVIDER` 点名了后端时,`WEB_SEARCH_ENDPOINT`(不是 `scheme://host[:port][/path]` 形的绝对 URL)、`WEB_SEARCH_SEARXNG_PARAMS`(任一段不是 `name=value`、名不是参数名、同名两次、把数组 / 对象的 JSON 文本填进来)、`WEB_SEARCH_MAX_RESULTS` / `WEB_SEARCH_TIMEOUT_MS`(非数或 < 1,含 `30s` 这类带单位的)任一形错,进程起不来,stderr 首屏带键名与机读码 `config.web_search_invalid`。改前这些被静默吸收或落默认。**空串 / 未设不受影响;没配 `WEB_SEARCH_PROVIDER` 的部署不读这四键。** **迁移**:按拒启句把那一键改对或删掉。
3305
3667
  - **每请求 `settings.webSearch` 形错 ⇒ `400 request.field_invalid`**(不分车道,请求面 BREAKING),错误句点名字段。**`provider` 缺席或不在词表里同样 400**(改前:整段丢弃、静默改用部署后端)—— 从 `settings.json` 带着拼错 provider(或只写了 `apiKey` / `endpoint`、没写 provider,或一个空的 `webSearch: {}`)的壳,修后提交即 400。**迁移**:按错误句改请求体(`provider` 写 `brave` / `tavily` / `searxng` 之一,不需要 per-request 搜索就整段删掉);`searxngParams` 用对象 `{ name: value }` 或串 `name=value;name=value`。
3306
3668
  - **brave / tavily 非 2xx 报错句换形**:`<provider> search failed: HTTP <status> — <响应体摘录>`(改前 `<provider> search failed (<status>): …`)。按旧句形匹配的消费方要改。
3307
- - **`UNATTENDED_APPROVAL_POLICY=deny` 下「无人可答」记在部署政策名下(S-689,行为面;点名 cli)**:没人能答的受门调用,`tool_end.gate.settlement` 从 `{kind:"human_refused", who:{party:"person"}}` 变 `{kind:"policy_refused", who:{party:"none"}}`;模型读到引擎的策略句,run **不再**以 `haltedOnUserRejection:true` 收束、接着跑(auto 模式否决限回落那一问被拒时改为 `failed` / `classifier.denial_limit`);持久 ask 行当场落 DECIDED(deny) + `settled_by="policy"`,重入回放同一个政策拒。**谁受伤**:按 `haltedOnUserRejection` 或 `settlement.kind === "human_refused"` 判「用户拒了」的壳。**迁移**:改读 `policy_refused`;模型多跑的拍数由部署的 `maxTurns` / 墙钟兜顶。
3308
- - **记忆抹除面:三个既有端点新答 409 `memory.layer_unwritable`(S-693,行为面)**:`POST /v1/memory/erase`、`POST /v1/memory/origin/entries/:entryId/clear`、`POST /v1/sessions/:id/memory/erase`。锁住且有条目的记忆层在场时(默认路径 core 7.30.1 每次项目会话都会锁 `memory/local`),operator / 属主抹除与清标先答 409 `memory.layer_unwritable`(7.99.0:项目层条目 200、`local` 条目 500 + journal 卡盘、下次起服 fatal);同一门序让这种层在场时的非法选择子(400 `config.memory_erasure_request`)、清标空理由(422 `memory.origin_clear_invalid`)与已提交抹除同 `requestId` 重放的 200 收执也先答 409。挂载面里有指向树外目录的软链 ⇒ 未分类 500(判不了,日志点名软链)。**迁移**:按 409 体点名的目录 `chmod u+w <dir>` 后**用同一个 `requestId`** 重试(得到原答复);软链形把软链移出记忆层。core 7.31.0(#1076)提货版撤销本预检与这个码。
3309
- - **审批名单热应用(S-668 波 2,行为面)**:`governance.approvalRequire` 从「改了要重启」变热,`/health.restart.reasons` 与 `GET /v1/config/catalog` 的 `restartSlices` 不再有 `runtime-gates`(同版波 0:`models-tiers` 出、`memory-consolidation` 进 ⇒ 闭集 7 词)。三处行为变化:① 中心下发的名单形错(非数组 / `null` / 非字符串项)或拼法匹配不到 ⇒ 审批组**整组拒**:活配置零变化、候选不成为 LKG、每拍重判直到修好(改前只 warn、候选照样成为 LKG);没有 checkpoint 店的部署收到非空名单同样整组拒(改前重启后拒启 = 崩溃环);② 中心撤掉这一键 ⇒ 立刻回 env 底 `APPROVAL_REQUIRE`(改前保留到下次重启);③ 开了 leader 端点、有 checkpoint 店、只配 `APPROVAL_DENY` / `APPROVAL_NEVER_AUTO` 而 require 为空的部署,leader worker **开始执行**这两张表(改前一张都不执行;收紧向)。**迁移**:按 `sema_registry_approval_require_invalid` 日志修名单;依赖「leader 不执行 deny / never-auto」的部署核对名单。
3669
+ - **`UNATTENDED_APPROVAL_POLICY=deny` 下「无人可答」记在部署政策名下(行为面;点名 cli)**:没人能答的受门调用,`tool_end.gate.settlement` 从 `{kind:"human_refused", who:{party:"person"}}` 变 `{kind:"policy_refused", who:{party:"none"}}`;模型读到引擎的策略句,run **不再**以 `haltedOnUserRejection:true` 收束、接着跑(auto 模式否决限回落那一问被拒时改为 `failed` / `classifier.denial_limit`);持久 ask 行当场落 DECIDED(deny) + `settled_by="policy"`,重入回放同一个政策拒。**谁受伤**:按 `haltedOnUserRejection` 或 `settlement.kind === "human_refused"` 判「用户拒了」的壳。**迁移**:改读 `policy_refused`;模型多跑的拍数由部署的 `maxTurns` / 墙钟兜顶。
3670
+ - **记忆抹除面:三个既有端点新答 409 `memory.layer_unwritable`(行为面)**:`POST /v1/memory/erase`、`POST /v1/memory/origin/entries/:entryId/clear`、`POST /v1/sessions/:id/memory/erase`。锁住且有条目的记忆层在场时(默认路径 core 7.30.1 每次项目会话都会锁 `memory/local`),operator / 属主抹除与清标先答 409 `memory.layer_unwritable`(7.99.0:项目层条目 200、`local` 条目 500 + journal 卡盘、下次起服 fatal);同一门序让这种层在场时的非法选择子(400 `config.memory_erasure_request`)、清标空理由(422 `memory.origin_clear_invalid`)与已提交抹除同 `requestId` 重放的 200 收执也先答 409。挂载面里有指向树外目录的软链 ⇒ 未分类 500(判不了,日志点名软链)。**迁移**:按 409 体点名的目录 `chmod u+w <dir>` 后**用同一个 `requestId`** 重试(得到原答复);软链形把软链移出记忆层。core 7.31.0提货版撤销本预检与这个码。
3671
+ - **审批名单热应用(行为面)**:`governance.approvalRequire` 从「改了要重启」变热,`/health.restart.reasons` 与 `GET /v1/config/catalog` 的 `restartSlices` 不再有 `runtime-gates`(同版波 0:`models-tiers` 出、`memory-consolidation` 进 ⇒ 闭集 7 词)。三处行为变化:① 中心下发的名单形错(非数组 / `null` / 非字符串项)或拼法匹配不到 ⇒ 审批组**整组拒**:活配置零变化、候选不成为 LKG、每拍重判直到修好(改前只 warn、候选照样成为 LKG);没有 checkpoint 店的部署收到非空名单同样整组拒(改前重启后拒启 = 崩溃环);② 中心撤掉这一键 ⇒ 立刻回 env 底 `APPROVAL_REQUIRE`(改前保留到下次重启);③ 开了 leader 端点、有 checkpoint 店、只配 `APPROVAL_DENY` / `APPROVAL_NEVER_AUTO` 而 require 为空的部署,leader worker **开始执行**这两张表(改前一张都不执行;收紧向)。**迁移**:按 `sema_registry_approval_require_invalid` 日志修名单;依赖「leader 不执行 deny / never-auto」的部署核对名单。
3310
3672
  - **回滚到 7.99.0(local 车道 + `UNATTENDED_APPROVAL_POLICY=deny`)要先收敛 / 压实 ask 账本(NP-9,持久数据面)**:7.100.0 起部署政策拒当场落 ask 行,File 形账本(`<数据根>/approval-asks/asks.jsonl`)把它记成新动词 `claimTerminalRefuse`。账本里只要还留着这种记录,7.99.0 **启动即拒启**并点名(「verb outside this build's closed set (a DOWNGRADE …)」)—— 不会静默把政策拒读成 VOID,但也起不来。**回滚步骤**:①停止接新任务,等所有 run 收敛(`GET /v1/approvals` 的 `pending` / `livePending` 都空,没有停驻或在飞的审批);②再二选一:让 7.100.0 继续跑到账本到阈压实(压实后账本只剩行快照,7.99.0 读得动,政策结算原样保留),或停机把 `asks.jsonl` 移开(已收敛的部署上只丢已决历史 —— 与 `docs/DEPLOY-PREREQS.md`「要清就停机删文件」同一动作);③再启 7.99.0。SQL 车道(`mysql` / `pg`)不受影响:政策结算是行上的列,7.99.0 原样读得动。
3311
- - **子进程按名剥凭据形变量(core 7.30.1 #1072,运行面)**:工具子 shell、git 子进程与本地语言服务器收不到名字以 `KEYS` / `TOKENS` / `PASSWORDS` 结尾的宿主变量;计数豁免只看紧挨结尾词的那一个词 ⇒ `MAX_NEW_TOKENS` / `MAX_COMPLETION_TOKENS` / `MAX_BATCH_PREFILL_TOKENS` / `DB_FOREIGN_KEYS` / `JSON_SORT_KEYS` 这五个 7.30.0 不剥的非密钥名也被剥(core 收紧过头,归 core 修)。**迁移**:给变量改个不以这三形结尾的名字(模型可驱动的 host shell 没有部署级放回旋钮 —— `inheritEnv:[names]` 只是嵌入方构造执行环境时的选项,7.104.0 起文档写明;语言服务器 7.101.0 起有 `LSP_ENV_ALLOW`);规则全文见 `docs/DEPLOY-PREREQS.md`。
3673
+ - **子进程按名剥凭据形变量(core 7.30.1,运行面)**:工具子 shell、git 子进程与本地语言服务器收不到名字以 `KEYS` / `TOKENS` / `PASSWORDS` 结尾的宿主变量;计数豁免只看紧挨结尾词的那一个词 ⇒ `MAX_NEW_TOKENS` / `MAX_COMPLETION_TOKENS` / `MAX_BATCH_PREFILL_TOKENS` / `DB_FOREIGN_KEYS` / `JSON_SORT_KEYS` 这五个 7.30.0 不剥的非密钥名也被剥(core 收紧过头,归 core 修)。**迁移**:给变量改个不以这三形结尾的名字(模型可驱动的 host shell 没有部署级放回旋钮 —— `inheritEnv:[names]` 只是嵌入方构造执行环境时的选项,7.104.0 起文档写明;语言服务器 7.101.0 起有 `LSP_ENV_ALLOW`);规则全文见 `docs/DEPLOY-PREREQS.md`。
3312
3674
 
3313
3675
  ## 7.99.0 —— 三条 BREAKING(行为面 / 类型面 / 运行时下限)
3314
3676
 
3315
- - **显式签发方不再算托管证据(7.99.0,S-671 / B-10;按 clay 裁定「显式签发方不算托管证据」)**:`PRINCIPAL_JWT_*` / `AUTH_BRIDGE_ISSUER` 在场而 `REQUIRE_PRINCIPAL` 未设的部署,7.95–7.98 拒启,7.99.0 起服;托管 ⇔ 运维显式声明 `REQUIRE_PRINCIPAL=true`。**谁受伤**:靠这条推断顶着没设 `REQUIRE_PRINCIPAL` 的多租机器,升级后不再被拦(召回缺口如实登记)。**迁移**:多租机器自己设 `REQUIRE_PRINCIPAL=true`(+ `OPERATOR_PRINCIPALS`),见 `docs/DEPLOY-PREREQS.md` 托管形前置。
3316
- - **`ServiceConfig.configCenter.token` 删除,换成 `credential`(7.99.0,S-651 波 A-1,类型面)**:凭证改为一只每次请求取值的活对象;新旋钮 `SEMA_REGISTRY_TOKEN_FILE`(与 `SEMA_REGISTRY_TOKEN` 二选一,都设 ⇒ 拒启)。手铸 `ServiceConfig` 的消费方 tsc 即红。**盘上数据**:旧 LKG 文件(`config-lkg-<worker>.json`,formatVersion 1)按凭证身份分箱后一次性迁移 —— 此刻凭证是该 worker 的拉取令牌且新箱无文件 ⇒ 迁进新箱、旧文件改名 `.migrated-v1`;其它形响亮拒一行(点名旧路径与出路);迁移代码到期删除(S-683,10-31)。旧 prompt 活动状态目录暂不迁移(S-685)。
3317
- - **Node 运行时下限改成实测值 `^20.19.0 || >=22.12.0`(7.99.0)**:此前 `>=20` 是假话 —— 7.98.0 在 Node 20.0–20.18 与 22.0–22.11 上本就起不来(依赖 e2b 的 CJS 入口撞 chalk@5 纯 ESM,S-682);开了 engine-strict 的安装在范围外会失败。**迁移**:Node 升到 20.19+ 或 22.12+。
3677
+ - **显式签发方不再算托管证据(7.99.0;按 clay 裁定「显式签发方不算托管证据」)**:`PRINCIPAL_JWT_*` / `AUTH_BRIDGE_ISSUER` 在场而 `REQUIRE_PRINCIPAL` 未设的部署,7.95–7.98 拒启,7.99.0 起服;托管 ⇔ 运维显式声明 `REQUIRE_PRINCIPAL=true`。**谁受伤**:靠这条推断顶着没设 `REQUIRE_PRINCIPAL` 的多租机器,升级后不再被拦(召回缺口如实登记)。**迁移**:多租机器自己设 `REQUIRE_PRINCIPAL=true`(+ `OPERATOR_PRINCIPALS`),见 `docs/DEPLOY-PREREQS.md` 托管形前置。
3678
+ - **`ServiceConfig.configCenter.token` 删除,换成 `credential`(7.99.0,类型面)**:凭证改为一只每次请求取值的活对象;新旋钮 `SEMA_REGISTRY_TOKEN_FILE`(与 `SEMA_REGISTRY_TOKEN` 二选一,都设 ⇒ 拒启)。手铸 `ServiceConfig` 的消费方 tsc 即红。**盘上数据**:旧 LKG 文件(`config-lkg-<worker>.json`,formatVersion 1)按凭证身份分箱后一次性迁移 —— 此刻凭证是该 worker 的拉取令牌且新箱无文件 ⇒ 迁进新箱、旧文件改名 `.migrated-v1`;其它形响亮拒一行(点名旧路径与出路);迁移代码到期删除(10-31)。旧 prompt 活动状态目录暂不迁移。
3679
+ - **Node 运行时下限改成实测值 `^20.19.0 || >=22.12.0`(7.99.0)**:此前 `>=20` 是假话 —— 7.98.0 在 Node 20.0–20.18 与 22.0–22.11 上本就起不来(依赖 e2b 的 CJS 入口撞 chalk@5 纯 ESM);开了 engine-strict 的安装在范围外会失败。**迁移**:Node 升到 20.19+ 或 22.12+。
3318
3680
 
3319
3681
  ## SQL 存储面 BREAKING(3.0.0 之后;列增批自 7.101.0 起入表)
3320
3682
 
@@ -3327,7 +3689,7 @@ file/local 存储形(未配 SQL 后端)的部署不受本节任何条目影响
3327
3689
  | **7.6.0**(2026-08-08) | SQL 双端归一化第一刀:隔离键排序规则钉死(MySQL 腿表级 `COLLATE utf8mb4_bin`/PG 腿逐列 `COLLATE "C"`)+索引名 36 条+列名/宽度收窄 | **删库重建**(两方言) |
3328
3690
  | **7.8.0**(2026-08-09) | SQL 命名三轴归一化第二刀:9 张表名单数化、epoch 毫秒列补 `_ms` 后缀 5 列、approval 两表 `version→rev`;wire 面零变化 | **删库重建**(两方言) |
3329
3691
  | **7.14.0**(2026-08-12) | `tool_result` 换代(随 core 5.26.0 的 ref 格式换代):ref 四段单射形、主键 `VARCHAR(190)→518`、新增出处两列 `owner_session_id`/`owner_task_id` | 升级前两方言 **`DROP TABLE tool_result`**(不删=boot 拒启;offload 产物是可恢复窗缓存,转录内联预览不受影响) |
3330
- | **7.101.0** | `session_meta` 新列 `instruction_source VARCHAR(64) NULL`(PG `COLLATE "C"`;S-690 项目指令换源通告的基线) | 两方言按拒启句里给出的 `ALTER TABLE session_meta ADD COLUMN …` 加列,或删库重建;**先升库、再升副本**(加列后旧副本重启见幽灵列拒启) |
3692
+ | **7.101.0** | `session_meta` 新列 `instruction_source VARCHAR(64) NULL`(PG `COLLATE "C"`;项目指令换源通告的基线) | 两方言按拒启句里给出的 `ALTER TABLE session_meta ADD COLUMN …` 加列,或删库重建;**先升库、再升副本**(加列后旧副本重启见幽灵列拒启) |
3331
3693
 
3332
3694
  > 列增批此前只记在 CHANGELOG / `docs/DEPLOY-PREREQS.md`(7.92.0 `session_policy`、7.93.4 `approval_ask.settled_by` 各加过一列),自 7.101.0 起同样入本表。7.101.0 这一列的拒启句自带可粘贴的 `ALTER`,本仓仍不替你执行。
3333
3695
 
@@ -3407,7 +3769,7 @@ file/local 存储形(未配 SQL 后端)的部署不受本节任何条目影响
3407
3769
  - **内网坐标默认值清理(1.180.0,npm 包卫生)**:`MODEL_GATEWAY_BASEURL` 缺省从内部网关 IP 改为
3408
3770
  `http://127.0.0.1:8000/v1` 占位——**依赖旧缺省的部署必须显式配置**;配了 `OA_ISSUE_TOKEN` 的部署
3409
3771
  现在必须同时给 `OA_ISSUE_BASEURL` 或 `GIT_API_BASEURL`(不再有烤死的内网主机兜底,缺失=启动即错)。
3410
- - **模型网关端点去出厂缺省(7.98.0,S-623;上一条那个占位本身也删了)**:`MODEL_GATEWAY_BASEURL` **没有出厂缺省**。配置能派发到的
3772
+ - **模型网关端点去出厂缺省(7.98.0;上一条那个占位本身也删了)**:`MODEL_GATEWAY_BASEURL` **没有出厂缺省**。配置能派发到的
3411
3773
  每一条 openai 兼容路由都必须解析到显式端点(目录条目自己的 `baseUrl`,或本键),否则拒启(码
3412
3774
  `config.model_route_endpoint_missing`,拒因点名模型并给出本机写法 `MODEL_GATEWAY_BASEURL=http://127.0.0.1:8000/v1`);
3413
3775
  只设 `MODEL_GATEWAY_FALLBACK_URLS` 不设本键同拒。**你要做什么**:凡隐式依赖本机 8000 网关的部署,显式写上那一行;