@sema-agent/server 7.143.0 → 7.145.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 (139) hide show
  1. package/MIGRATION.md +295 -0
  2. package/README.md +3 -0
  3. package/README.zh-CN.md +1 -0
  4. package/USAGE.md +34 -16
  5. package/dist/approval-card.d.ts +31 -14
  6. package/dist/approval-card.js +8 -8
  7. package/dist/audit.d.ts +2 -21
  8. package/dist/audit.js +0 -9
  9. package/dist/boot/execution-env.js +1 -1
  10. package/dist/boot/runner-deps.d.ts +10 -5
  11. package/dist/boot/runner-deps.js +5 -4
  12. package/dist/boot/session-faces.d.ts +1 -1
  13. package/dist/boot/session-faces.js +3 -3
  14. package/dist/boot/shutdown.d.ts +1 -1
  15. package/dist/boot/shutdown.js +4 -2
  16. package/dist/boot/stage-01-config.js +2 -0
  17. package/dist/boot/stage-07-capability-layer.js +1 -1
  18. package/dist/boot/stage-09-leader.d.ts +1 -1
  19. package/dist/boot/stage-10-http-server.d.ts +1 -1
  20. package/dist/boot/stage-10-http-server.js +4 -9
  21. package/dist/capabilities/scenarios.d.ts +14 -18
  22. package/dist/capabilities/scenarios.js +1 -2
  23. package/dist/config-d-migration.d.ts +3 -0
  24. package/dist/delegated-session-owner.d.ts +33 -151
  25. package/dist/delegated-session-owner.js +1 -83
  26. package/dist/entry-mode-clamp-notice.d.ts +1 -1
  27. package/dist/execution-placement.d.ts +7 -4
  28. package/dist/fleet/fleet-bus.d.ts +13 -3
  29. package/dist/fleet/fleet-bus.js +17 -3
  30. package/dist/hooks/classic-stations.d.ts +3 -1
  31. package/dist/hooks/classic-stations.js +2 -0
  32. package/dist/http/admission.js +2 -1
  33. package/dist/http/checkpoint-ctx.d.ts +1 -0
  34. package/dist/http/checkpoint-ctx.js +1 -0
  35. package/dist/http/durable-run-leg.js +7 -6
  36. package/dist/http/principal-gate.d.ts +1 -1
  37. package/dist/http/refusal-body.d.ts +7 -3
  38. package/dist/http/refusal-body.js +1 -0
  39. package/dist/http/resume-legs.js +16 -7
  40. package/dist/http/route-ctx.d.ts +15 -0
  41. package/dist/http/routes/approvals-assistant.d.ts +20 -1
  42. package/dist/http/routes/approvals-assistant.js +28 -6
  43. package/dist/http/routes/rules.d.ts +1 -1
  44. package/dist/http/routes/rules.js +5 -2
  45. package/dist/http/routes/session-sync.js +12 -0
  46. package/dist/http/routes/tasks.js +12 -9
  47. package/dist/http/run-meta.d.ts +14 -7
  48. package/dist/http/run-meta.js +5 -2
  49. package/dist/http/server.d.ts +13 -5
  50. package/dist/http/server.js +3 -0
  51. package/dist/http/submit-ctx.d.ts +12 -0
  52. package/dist/http/submit-ctx.js +23 -0
  53. package/dist/index.d.ts +1 -0
  54. package/dist/index.js +1 -0
  55. package/dist/lane-home-probe.d.ts +15 -0
  56. package/dist/lane-home-probe.js +4 -0
  57. package/dist/observability/corrupt-read-seat.d.ts +5 -9
  58. package/dist/observability/corrupt-read-seat.js +1 -2
  59. package/dist/observability/fail-open.d.ts +26 -10
  60. package/dist/observability/fail-open.js +26 -10
  61. package/dist/observability/run-terminal.d.ts +1 -1
  62. package/dist/observability/run-terminal.js +2 -2
  63. package/dist/parked-revive-surface.d.ts +6 -7
  64. package/dist/peer-inbound-face.d.ts +29 -34
  65. package/dist/peer-inbound-face.js +28 -63
  66. package/dist/plugins/approval-ask-store-file.d.ts +16 -2
  67. package/dist/plugins/approval-ask-store-file.js +21 -1
  68. package/dist/plugins/approval-ask-store-memory.d.ts +8 -2
  69. package/dist/plugins/approval-ask-store-memory.js +11 -8
  70. package/dist/plugins/caching-session-store.d.ts +3 -3
  71. package/dist/plugins/caching-session-store.js +3 -3
  72. package/dist/plugins/checkpoint-store-sql.d.ts +62 -37
  73. package/dist/plugins/checkpoint-store-sql.js +123 -40
  74. package/dist/plugins/file-run-store.d.ts +13 -1
  75. package/dist/plugins/file-run-store.js +11 -1
  76. package/dist/plugins/fork-routing-session-store.d.ts +8 -1
  77. package/dist/plugins/fork-routing-session-store.js +6 -0
  78. package/dist/plugins/local-checkpoint-store.d.ts +17 -8
  79. package/dist/plugins/local-checkpoint-store.js +26 -7
  80. package/dist/plugins/local-session-store.d.ts +105 -34
  81. package/dist/plugins/local-session-store.js +168 -65
  82. package/dist/plugins/local-session-window.d.ts +4 -2
  83. package/dist/plugins/memory-run-store.d.ts +2 -0
  84. package/dist/plugins/memory-run-store.js +6 -0
  85. package/dist/plugins/one-time-migrations.d.ts +12 -12
  86. package/dist/plugins/one-time-migrations.js +13 -13
  87. package/dist/plugins/pg-session-storage.d.ts +1 -9
  88. package/dist/plugins/pg-session-storage.js +2 -19
  89. package/dist/plugins/remote-env-host.d.ts +8 -4
  90. package/dist/plugins/remote-env-host.js +7 -9
  91. package/dist/plugins/remote-shell.js +12 -2
  92. package/dist/plugins/run-store-sql.d.ts +4 -0
  93. package/dist/plugins/run-store-sql.js +3 -0
  94. package/dist/plugins/schema-consistency.d.ts +5 -1
  95. package/dist/plugins/session-fork.d.ts +1 -1
  96. package/dist/plugins/session-ownership.d.ts +9 -0
  97. package/dist/plugins/session-ownership.js +6 -0
  98. package/dist/plugins/session-store.d.ts +13 -16
  99. package/dist/plugins/session-store.js +9 -10
  100. package/dist/plugins/sql-json-column.d.ts +24 -2
  101. package/dist/plugins/sql-json-column.js +38 -3
  102. package/dist/plugins/store-backend.js +3 -2
  103. package/dist/plugins/tidb-session-store.d.ts +2 -14
  104. package/dist/plugins/tidb-session-store.js +2 -20
  105. package/dist/prompt-screen.d.ts +21 -0
  106. package/dist/prompt-screen.js +8 -0
  107. package/dist/rules-consent.d.ts +63 -51
  108. package/dist/rules-consent.js +6 -10
  109. package/dist/run-acceptance.d.ts +40 -10
  110. package/dist/run-acceptance.js +38 -5
  111. package/dist/run-local.js +2 -1
  112. package/dist/runs.js +5 -1
  113. package/dist/security.d.ts +10 -7
  114. package/dist/session-agent.d.ts +39 -0
  115. package/dist/session-agent.js +16 -0
  116. package/dist/session-error-wire.d.ts +25 -26
  117. package/dist/session-error-wire.js +4 -5
  118. package/dist/session-incarnation.d.ts +2 -2
  119. package/dist/session-notify-door.d.ts +2 -2
  120. package/dist/session-notify-door.js +5 -1
  121. package/dist/tool-approval.d.ts +3 -1
  122. package/dist/tool-approval.js +47 -18
  123. package/dist/trace/core-keyset-guard.d.ts +1 -1
  124. package/dist/trace/engine-notice-wire.d.ts +1 -1
  125. package/dist/trace/engine-notice-wire.js +1 -1
  126. package/dist/trace/ledger-sink.js +12 -4
  127. package/dist/trace/model-segment.d.ts +26 -6
  128. package/dist/trace/model-segment.js +58 -9
  129. package/dist/trace/project.d.ts +8 -2
  130. package/dist/trace/project.js +6 -4
  131. package/dist/trace/redact.d.ts +77 -2
  132. package/dist/trace/redact.js +234 -99
  133. package/dist/trace/self-minted-wire.d.ts +160 -9
  134. package/dist/trace/self-minted-wire.js +52 -3
  135. package/package.json +3 -3
  136. package/wire-changes/server@7.144.0.json +291 -0
  137. package/wire-changes/server@7.145.0.json +146 -0
  138. package/dist/session-records-skipped-notice.d.ts +0 -21
  139. package/dist/session-records-skipped-notice.js +0 -27
package/MIGRATION.md CHANGED
@@ -7,6 +7,301 @@
7
7
  > ⚠️ 完整清单在仓库根 `CHANGELOG.md`——它**不随 npm tarball 出包**(本文件随包)。看完整迁移窗的
8
8
  > 权威姿势是源码 tag diff:`git diff v<旧>..v<新>`(每版都推 `v<版本>` tag);npm 包页也镜像 CHANGELOG。
9
9
 
10
+ ## 7.145.0 —— ① 🔴 `DB_BACKEND=local`:带戳存档上会话同步导入的第一阶段也答 `conflict.session_archive_stamped`(wire 加性:多一口答该码;行为修复;部署零动作) ② 运维审批队列的停驻行带它那只会话的 `agent`(委派子代在委派树里的位置;与会话视图同一只读口):后台委派子代停驻的那一行能连回发起委派的会话(wire 加性;行为修复;部署零动作) ③ 订正 7.144.0 节第 12 条「远端五车道不变」一句:k8s / local-docker / ssh / adb / e2b 上家目录主张证不了时,第一句拒是哪一形按命令形、执行面与会话分(文字订正;零行为变更) ④ 🔴 `DB_BACKEND=local`:委派子代转录的建行先记属主、再建存档,进程崩在两笔之间不再留下无主的子代转录(行为修复;持久面;部署零动作) ⑤ 🔴 规则导入:cc-import 兑付时成员表里有引擎拒的成员 ⇒ 落定 200 + 回执逐成员交出,不再 503 `state.rule_import_retry` 到票过期;cc-import 口的 200 体换成与 local-import 口同一张回执 `{ members, rev }`(wire BREAKING;行为修复;部署零动作) ⑥ 🔴 `CONFIG_PROVIDER=local`:配置根里的悬空符号链接(链接在、目标不在)不再读成「缺席」—— `config.d/remote-exec.json` 或 `config.d` 目录链接悬空 ⇒ 起服拒(此前无声落宿主车道),`config.d/<域>.json` 悬空 ⇒ 整份本地候选被判官拒、回落 env(此前读成域缺省);提货 settings-schema 17.0.0;更正 7.144.0 及更早(行为收紧,fail-closed;升级前先查链接) ⑦ 🔴 装着 prompt 屏(`prompt.submit` / `classic.UserPromptSubmit`)的腿:run 行预览、会话自动标题、fleet 行名只取引擎原样交付的目标,屏判完之前不落盘,续跑输入不存目标;屏改写 / 丢弃 / 抛错 ⇒ 这些面缺席(行为修复;机密;wire 值变化:预览可缺席;嵌入方类型面 BREAKING:`ServiceDeps.deploymentMods` 必填) ⑧ 停驻行一行坏字节只坏它自己那一行:SQL 后端的收件箱照列它、带 `rowVerdict`,收件箱与任务视图不再整张 500 / 503;`DB_BACKEND=local` 上别的卡的决断不再被一张坏卡拖成 500,local 的列表面候引擎(行为修复;wire 加性;部署零动作;更正 7.144.0 节第 5 条两句) ⑨ `DB_BACKEND=local`:审批账本里任何真删了行的调用(留存清扫的两只动词与 `deleteByTask`)的那一拍,问账日志 `approval-asks/asks.jsonl` 同拍整本重写成存活行的快照 —— 被删的问的字节(含工具实参字面)当拍离开活文件;订正 7.133.0 节第 14 条 local 一句(行为修复;持久面;部署零动作)
11
+
12
+ 1. **🔴 `DB_BACKEND=local`:仍带属主戳的存档上,会话同步导入的第一阶段(`POST /v1/sessions/:id/sync/import`)按 id 分类出 fork / stale 且没带同意时,直接答 409 `conflict.session_archive_stamped` + 带出路句,不再先答通用的 `conflict`(wire 加性:这一口多答一个已在册的码;行为修复;部署零动作)**:
13
+ 旧形(7.144.0 节第 10 条「范围」一句):带戳存档上,第一阶段按 id 分类出 fork / stale 且没带同意(`resolution: "overwrite-dst"`)时,仍先答通用的 `409 conflict`(`sync conflict` + `relation`)——
14
+ 那一口只按 id 分类、不经提交里的带戳判,所以这两形的推送要到带同意的第二轮才读到出路句,而它指的出路(带同意重来)在带戳存档上是死路。
15
+ 新形:第一阶段对这两形先问带戳判的唯一读口(店里「这份存档带不带戳」只有这一只读口,fork 的源与提交里的带戳判问的是同一只),带戳 ⇒ 直接答 `409` + `errorCode:"conflict.session_archive_stamped"` + 同一句固定句
16
+ (体只有 `error` / `errorCode` 两键,不带 `relation`),不开暂存、不拿租约、不写存档(存档原样带戳),重发同答;请求前的门读口照旧可能为从没被读过的旧会话补铸一格只有化身的行格(既有的读时补铸)。
17
+ 其余各形不变:`fast_forward`(干净追加 / 载荷分叉)与带同意的 fork / stale,第一阶段照旧受理 200,带戳判仍在提交里、答同一码同一句;匿名存档和 SQL 后端上第一阶段的应答不变(它们没有带戳存档这一形)。
18
+ **谁需要**:壳 / SDK 等对迁移留着的带戳存档(起服 warn `local_archive_kept_stamped` 点名)推送的客户端 —— fork / stale 形的推送在第一阶段就读到「删掉会话后重推」,不再先去试带同意重来。
19
+ **谁受伤**:在第一阶段按 `errorCode == "conflict"` 或体里 `relation` 键判「要解决冲突、带同意重来」的客户端 —— local 部署的带戳存档上,fork / stale 无同意这两形它们不再读到(这两形在带戳存档上本来就解决不了)。
20
+ **补偿**:改读新码 `conflict.session_archive_stamped`(读体的 `error` 即出路:删掉会话 `DELETE /v1/sessions/:id` 后重推);按状态 `409` 分支的不受影响。**升级前做**:无。**回滚**:回到上一版即恢复旧形(本版不写任何新形,落盘数据不受影响)。
21
+
22
+ 2. **运维审批队列的停驻行带它那只会话的 `agent`:`{ id?, parentSessionId?, rootSessionId? }`,与 `GET /v1/sessions/:id` 体顶层的同名键同一只读口、逐值同答(wire 加性;行为修复;部署零动作)**:
23
+ 旧形:后台委派子代撞审批门停驻后,它那一行在 `GET /v1/approvals` 的 `pending[]` 与 `/v1/approvals/stream` 的 `pending` 帧上 `taskId` 空、`sessionId` = 子代自己的会话,行上没有一位能连回发起委派的那只会话 ——
24
+ 只认「本端提交的 run」或「行的会话 = 当前会话」的归属判官认不领这一行,非交互(`-p`)的壳上这张卡没有入口。
25
+ 新形:停驻行(`kind: "checkpoint"`)带 `agent` = 行的 `sessionId` 那只会话在会话视图上的 `agent`(`id` = 耐久 agent 行的 `a…` 键;`parentSessionId` = 派它的会话;`rootSessionId` = 委派树的根会话;
26
+ 会话行上存的委派元组缺哪一格缺哪一格)。`/stream` 的 `pending` 帧同键同值(新订阅首拍补给的帧与之后推出的帧都带);`resolved` 帧不带。不回填:读的是会话行,升级前停驻的行升级后即带。
27
+ 缺席 = 这台 server 没有说,不是「不是子代」:宿主会话自己的停驻行、同步委派的子代、`subagent_type: "fork"` 的后台子代(它的会话是父会话的一只普通分叉,没有委派元组 —— 这一形的停驻行本版仍连不回发起会话)、
28
+ 不存元组的店(`DB_BACKEND=memory`)、`DB_BACKEND=local` 在 7.140.x 及以前拷进宿主店的子代转录、那一读没读成(只这一行缺键,列表照出,计 `fail_open_total{tag="server.approvals.queue-row-agent-unreadable"}`)。
29
+ **谁需要**:非交互(`-p`)与交互车道的壳、按「行上的父 / 根会话 = 本会话」认领停驻行的归属判官(一只判官,不另铸)。**谁受伤**:无(加性键)。
30
+ **补偿**:老 server 不带这个键 ⇒ 按原读法(本端提交的 run / 行的会话 = 当前会话)。**升级前做**:无。**回滚**:回到上一版即不带这个键;落盘数据不受影响(本版不写任何新形)。
31
+
32
+ 3. **订正 7.144.0 节第 12 条「远端五车道不变」一句:k8s / local-docker / ssh / adb / e2b 上家目录主张证不了时,第一句拒是哪一形按命令形、执行面与会话分(文字订正;零行为变更)**:
33
+ 7.144.0 节第 12 条(与契约附录 A 的 `env.home_unconfirmed` 行、USAGE §9 的同一行、DEPLOY-PREREQS 的 `REMOTE_EXEC_HOME_DIR` 节)写这些车道「照旧在开环境那一拍拒、拒句落在工具结果里;递归读形与 adb 上连带路径的普通读先被读边界拦下」。
34
+ 7.144.0 发出后的复跑(真引擎 Runner,五条车道的供方换成假的;每格另跑一遍主张 = 实测的负控,只记两遍不同的形)读到的形比这句多,读法以本条为准(已发节原文不改):
35
+ ① **环境在开跑前就被打开**:新提交腿上,引擎拿到执行环境后的第一件事是把任务根读成规范路径,这一读就让车道建连、问 `$HOME`、判出拒;引擎把这次失败读作「任务根读不成规范形」,照样开跑(模型照常被调),拒句要等模型的第一条工具调用才再被答出来。模型要跑的命令一条都没进环境(车道自己建根、探 shell、问 `$HOME` 的命令照跑)。
36
+ ② **全 shell 面**:不带路径的命令(`echo hi`、`ls`)⇒ 工具结果 `shell_unavailable` + 判官的拒句(点名声明值、实测值与改法)。带路径的命令(路径不在读拒表上 —— 读拒表命中的路径照旧先答读拒表的拒)先撞引擎的读边界(要人批,句子「could not establish what is read」,不点名家目录)的范围:
37
+ `~/` 下的递归读(`grep -r … ~/…`)五条车道都是(ssh 上这一形家目录对得上也先要人批);`~/` 下的普通读(`cat ~/x`)在 ssh、adb 上是(k8s / local-docker / e2b 答判官的拒句);工作区内相对路径的普通读(`cat x`)只在 adb 上是。
38
+ ③ **只读面**(`AUTONOMY=read-only`):不带路径的命令同 ②;adb 上工作区内相对路径的读先被读边界拒(句子不点名家目录;家目录对得上时照读)。只读面的读边界不展开 `~`,`~/` 下路径的读在那里不论家目录对不对都被拒 —— 不是这一因。
39
+ ④ **ssh / adb 上会话绑了附件**:附件在建执行环境时写进工作目录,写入撞拒 ⇒ run 在开跑前 `failed`、模型零调用,终局**不带码**,句子以 `attachment materialization failed (createDir attachments/): ` 起头、后接判官的拒句;同步提交腿答 200 + `failed` 体(不落零工作拒档)。
40
+ ⑤ **从快照恢复的续跑腿**(e2b;配了快照存储的 k8s):恢复出来的沙箱 / pod 对不上 ⇒ 准备期 `resume.env_failed`,句子里带判官的拒句。e2b 会尝试把沙箱重新挂起 —— 挂起成功快照留着,挂起失败只记一行 warn `remote_env_home_refused_repause_failed`、沙箱按自己的寿命到期。
41
+ 不从快照恢复的续跑腿(local-docker / ssh / adb,没配快照存储的 k8s:只停驻、不打包)不经恢复,形同 ①–④。
42
+ 本版这些车道的行为不变,改法也不变:把 `REMOTE_EXEC_HOME_DIR` 设成环境里 `echo $HOME` 的结果,或让环境的 `HOME` 读声明那个值;删掉声明只在没有出厂答案的车道(k8s / local-docker / ssh / adb)上是一条路 —— e2b 删掉后主张回落 `/home/user`,仍要与 `$HOME` 一致。
43
+ 读边界拦下的那几形(② 后半、③)句子里没有家目录,④ 的终局不带码 —— 远端车道上看到这几形时先核一次声明与环境的 `$HOME`。
44
+ **谁需要**:远端车道上排查「为什么这条 run 一读 `~/` 就要人批」「为什么带附件的会话开跑就失败」的运维。**谁受伤**:无(行为不变)。**补偿**:不需要(改法照旧:把 `REMOTE_EXEC_HOME_DIR` 设成环境里 `echo $HOME` 的结果,或让环境的 `HOME` 读声明那个值)。**升级前做**:无。**回滚**:不适用(文字订正,零行为变更)。
45
+
46
+ 4. **🔴 `DB_BACKEND=local`:委派子代转录的建行改为先记属主、再建存档 —— 进程崩在两笔之间不再留下属主从没被记下的子代转录(行为修复;持久面;部署零动作)**:
47
+ 旧形:local 后端建一只后台子代的转录先建存档(行头带委派元组)、再写会话元数据那一格(属主);进程崩在两笔之间 ⇒ 存档在而属主格缺,重启后这只转录读作无主,
48
+ 具名委派树的停驻每次被否决、不自愈。另外存档行头的委派元组里多带了一份属主(引擎不声明这一成员,无人读)。
49
+ 新形:先写属主格、再建存档(与登记 / fork / 导入同一写序);崩在两笔之间留下的是一只没有转录的属主格 —— 不是子代转录(不进会话列表、不进委派分区枚举),复活那只子代读到「转录不在」、
50
+ 同 id 再建子代转录被拒。建存档失败 ⇒ 盘上不是本次的子代转录(别的写者抢先建了同 id 的存档 / 根本没建成)就撤回刚写的格;引擎写完行头之后才报错 ⇒ 格留着(它就是那只转录的属主);撤不回 ⇒ 响亮报两只故障。新写的元组不再带属主(存档匿名,属主只在会话元数据那一格)。
51
+ **存量**:升级前(7.144.x 及更早)崩在两笔之间留下的无主子代转录不迁移、不回填 —— 照旧读作无主,具名树停驻被否决(响亮)。出路:取消 / 删掉那只后台子代(联合收割随后删它的转录)。
52
+ 7.144.x 写下的元组里那一份属主留在盘上、不被读。
53
+ **谁需要**:local 上带身份(具名委派树)的部署。**谁受伤**:崩溃之后同一 id 再建子代转录被拒(引擎新起的子代每次用新 id,复活不重建同 id);残留的属主格不被收割(惰性,不上列表)。
54
+ **补偿**:存量行按上面的出路处置。**升级前做**:无。**回滚**:回到上一版即恢复旧写序;本版写下的子代转录(元组不带属主、属主在格里)上一版照常读。
55
+
56
+ 5. **🔴 规则导入:`POST /v1/rules/cc-import/redeem` 兑付时成员表里有引擎拒的成员 ⇒ 这次兑付落定,`200` + 回执逐成员交出,不再 503 `state.rule_import_retry` 到票过期;cc-import 口的 200 体换成与 `POST /v1/rules/local-import/redeem` 同一张回执 `{ members, rev }`(wire BREAKING;行为修复;部署零动作)**:
57
+ 旧形:cc-import 口拿到引擎的完整成员表后,只要其中一行被拒,整次兑付就放回认领、答 `503 state.rule_import_retry`(「票还能用,重试」)。引擎的成员拒只带自由文本,永久的裁定也在里面 ——
58
+ 引擎对旧导入记录里从 `/` 写起的全局规则(7.142.0 及更早在用户层收下的,如 `Edit(/notes/**)`)兑付期答 `unsupported.layer_root:`。这样一条成员让同票重试一直 503 到票过期(10 分钟),临期答 `404 not_found.rule_ticket`;
59
+ 同一记录里已落的成员不撤、被拒的那条永不落。200 体是 `{ result: { members: [{ candidateIndex, behavior, rule, scope: {kind, root?}, status: "persisted" | "deduped", alreadyRedeemed, dot }], rev } }`。
60
+ 新形:两只 redeem 口一条规则 —— 兑付走完、拿到完整成员表 ⇒ 落定:`200 { members, rev }`(两键),每个成员一行 `{ key: { behavior, rule, scope }, outcome, reason?, detail? }`,`scope` 是与 `GET /v1/rules` 列举行同形的判别式串(`global` / `project:<root>`),行序是引擎的走序;
61
+ `outcome` = `persisted`(这次写了)/ `no-op`(等价规则已在店)/ `indeterminate`(引擎在这一条上答了拒,带 `reason: "store_refused"` 与 `detail` = 引擎原话;拒因只有自由文本,本服务不猜它是裁定还是瞬时,所以不说落了、也不担保没落)。
62
+ 票不放回:cc-import 的票照旧一次性(同票再兑 `404`);local-import 照旧先把回执落进票行(SETTLED)再答 200、同票重放逐字回放,落定这一跳答不成(落定写抛 / 认领被租约接管而新持有者还没落定)时照旧答 `409 conflict.rule_import_in_flight`、同票再来读权威的那份回执。同一个引擎成员拒,两口回执逐字节相同。
63
+ `503 state.rule_import_retry` 只剩**没有完整成员表**的兑付:引擎在走之前整批拒、成员循环走到一半抛、confirm 输给并发写者、店在走之前抛 —— 认领已放回,同一张票重来就是重走一遍;中途抛时此前的成员可能已落,重走交出完整表、那几条读 `no-op`。
64
+ local-import 回执 `reason` 的词表收成一词 `store_refused`(契约此前还列着 `walk_failed`,它从未被铸过:没走完的兑付不落定,没有那一行)。
65
+ **谁需要**:兑付旧导入记录的部署(7.142.0 及更早铸、10 分钟票寿内在本版兑付的导入 —— 滚动升级窗)、任何成员表里含永久被拒成员的 cc 导入。
66
+ **谁受伤**:① 收到 `503 state.rule_import_retry` 就原样重发同一张票的客户端 —— 瞬时的成员拒(店写抖动)不再按票重试,那一行在回执里是 `indeterminate`,票已用掉;
67
+ ② 读 cc-import 200 体 `result.members[].status`(或 `candidateIndex` / `alreadyRedeemed` / `dot`)的客户端 —— 那一形退出 wire,体里不再有 `result` 键,只读那一形的计数读口会读出「看不懂的结局形」。
68
+ **补偿**:按回执的成员行读结局 —— `persisted` / `no-op` 是落了;`indeterminate` 读 `detail`(引擎的话即出路,`unsupported.layer_root:` 那句自己写着「重新 prepare,这一条会披露在 skipped」),
69
+ 对账读 `GET /v1/rules`(按 `key` 的三格比),要补就重新走一次导入(幂等,已落的读 `no-op`);cc-import 与 local-import 同一只读口。`503 state.rule_import_retry` 的读法不变(拿同一张票重试)。滚动升级窗里 7.144.x 与本版的副本并存时,同一个客户端可能先后读到两种 200 形(`{ result: { members, rev } }` / `{ members, rev }`):读口两形都认,旧形那一支在客户端自己的下个版本里删。
70
+ **升级前做**:无。**回滚**:回到上一版即恢复旧形(成员拒 503 到票过期、cc-import 体 `{ result: … }`);local-import 票行里写下的回执形不变,上一版读得回。
71
+
72
+ 6. **🔴 `CONFIG_PROVIDER=local`:配置根里的悬空符号链接(链接在、目标不在)不再读成「缺席」—— `config.d/remote-exec.json` 或 `config.d` 目录链接悬空 ⇒ 起服拒(`run-local` 退 2);`config.d/<域>.json` 悬空 ⇒ 整份本地候选被判官拒、回落 env,`config_candidate_rejected` 与 `GET /v1/models` 的 `candidateRejected` 点名(行为收紧,fail-closed;提货 `@sema-agent/settings-schema` 17.0.0;更正 7.144.0 及更早;升级前先查链接)**:
73
+ 旧形(7.144.0 及更早,发车时作为已知限制披露过的那一形):悬空链接上读文件得 `ENOENT`,本服务读 `config.d` 的契约读者把它读成「文档缺席」。`config.d/remote-exec.json` 悬空 ⇒ 执行车道合成步当文件缺席,引擎落缺省车道
74
+ (`CONFIG_PROVIDER=local` ⇒ host),文件里写的是 `local-docker` 也一样 —— 链接一断(卷没挂上 / NFS 掉了 / 目标被删),隔离车道无声降成宿主车道;`config.d/<域>.json` 悬空 ⇒ 域缺省(`governance.json` 里的护栏不生效);
75
+ `config.d` 目录链接悬空 ⇒ 整个 `config.d` 读成不存在。起服日志上唯一的信号是一次性迁移那一行 `config_dir_migration_failed`,而且只对文档链接出(目录链接悬空连它都没有)。
76
+ 新形:契约 17.0.0 起「缺席 = 路径上没有任何条目」,悬空链接是「在场却读不出」,读它拒,句子点名链接、目标与出路:`<链接> is a dangling symbolic link (it points at <目标>, which does not exist) — nothing is read or written through it; repair or remove the link`
77
+ (与一次性迁移的读口同一句)。三处读点各走既有的拒路,本服务零改码:
78
+ ① `config.d/remote-exec.json` 悬空、或 `config.d` 目录链接悬空 ⇒ 起服拒:一行 `remote_exec_file_invalid`,fatal 句 `config.d/remote-exec.json under <配置根> is invalid: <悬空句>`,进程非零退出,不进入服务、不落宿主车道(`run-local` 同一读点:退出码 2、同一句);
79
+ ② `config.d/<域>.json` 悬空 ⇒ 本地读腿交出的拒单里多一条 `{ document, reason: "io", error: <悬空句> }`,候选判官整拒这份本地候选(`config.d` 里别的域也一个不应用,起服回落 env —— 与同一份文档写坏 JSON 同形):
80
+ 一行 `config_candidate_rejected`(`domains` 点名这份文档、`errors[].reason` = `io`、悬空句),`GET /v1/models` 顶层 `candidateRejected`(域名 + 源 `local`)在场;刷新拍保持当前已应用的配置并原样重判,修好链接即落地。回落 env 之后起服的缺省模型检查照常:有 `MODEL_ID` ⇒ 照常起服、服务 env 表;没设 `MODEL_ID`、模型只配在 `config.d/models.json` ⇒ 起服拒 `config.default_model_missing`(拒句不点名链接 —— 先出的 `config_candidate_rejected` 行点名);
81
+ ③ 一次性迁移对悬空的 `config.d` 目录链接仍答「没有 `config.d`」、不出声(迁移的读口先 `stat`)—— 读者的拒(①)是目录链接悬空这件事唯一的信号,也是够用的信号;对悬空的文档链接,迁移那一行 `config_dir_migration_failed` 照出,读者的拒是它之外的第二行(同一句)。
82
+ 不在本条范围:配置根自己(或更上层)是悬空链接 —— 读法不变(读成缺席);`<配置根>/.env`:本服务不读(契约的 `loadEnvFile` / `loadLocalConfig` 本仓零调用),悬空的 `.env` 对本服务无影响。
83
+ **谁需要**:`CONFIG_PROVIDER=local` 且把 `config.d`、其下的文档(尤其 `remote-exec.json`)链到卷 / NFS / 部署工具链管理路径的部署 —— 要的是「链接断了 ⇒ 起服响亮」,断链不许悄悄把隔离车道变成宿主车道。
84
+ **谁受伤**:今天带着悬空链接静默跑缺省的部署(升级前它们没有任何一行错误):`remote-exec.json` / `config.d` 目录链接悬空的升级后起不来;域文档悬空的整份本地候选被拒(`config.d` 里别的设置也不生效,直到修好):有 `MODEL_ID` 兜底的照常起服、服务 env 表;**没有 `MODEL_ID`、模型只配在 `config.d/models.json` 的部署也起不来**(缺省模型检查拒启,见 ②)。
85
+ **补偿**:拒句自带出路 —— 修好链接(挂上卷 / 恢复目标)或删掉它(删掉 = 回到缺席时的缺省:`remote-exec.json` 缺席 ⇒ 缺省车道)。**升级前做**:在每个本地配置根(`CONFIG_LOCAL_DIR` → `AGENT_DATA_DIR` → `~/.ai-agent`)上跑
86
+ `find -L <配置根> -maxdepth 2 -type l`(`-L` 之下只有悬空的链接还显示为链接;空输出且退出码 0、stderr 无报错 = 无事可做,权限不够时 `find` 会漏列);命中 `config.d` 目录链接本身、或 `config.d/` 下的 `*.json`(本服务读的就是这一集:便携域文档、退役域的墓碑文件、`remote-exec.json`)的先修好或删掉;配置根上的根级文档 `config.env-models.json` 悬空的读法本版不变(契约的根级文档读者一直把它读成读不出、不读成缺席);其余命中与本服务无关。**回滚**:回到上一版即恢复旧形(读成缺席);本条不改任何落盘数据。
87
+
88
+ 7. **🔴 装着 prompt 屏的腿:本服务存 / 转目标的面只取引擎原样交付的那一份,屏判完之前不落盘;屏改写 / 丢弃 / 抛错 ⇒ 这些面缺席(行为修复;机密;wire 值变化;嵌入方类型面 BREAKING)**:
89
+ 旧形:一次提交的目标有三处早于部署的 prompt 屏(扩展站 `prompt.submit` 的改写 / 丢弃 / 抛错,`classic.UserPromptSubmit` 的拦截)落盘或外送:建 run 行时写预览列(`GET /v1/tasks` 行的 `objectivePreview`、`GET /v1/assistant/tasks` 的行名、助手收件箱行的 `objective`、会话列表的回退与 fleet 行的 `name` 同读这一列);
90
+ 续跑输入(checkpoint ctx)存整份请求体;屏改写过的目标仍拿请求原文去起会话标题(原文进标题模型的请求)。模型与会话转录只见屏后文本,屏前文本却留在这几处。
91
+ 新形:一条律 —— 本服务的目标副本 = 引擎交付的那一份,屏判完之前一个字节都不存。这条腿的部署座(交给 Runner 的 `mods`)或任务座(`settings.hooks` 的 `UserPromptSubmit` 那一张)声明了这两站之一(含 `prompt.*` / `classic.*` 通配)⇒
92
+ 提交时预览列 NULL、fleet 行不带名、续跑输入里的目标留空串;目标的受理帧(`human_input{ carrier: "objective", delivery: "applied" }`)不带 `rewrittenBy`(原样送达)⇒ 这一拍补上预览、给 fleet 行补名、起标题;
93
+ 受理帧带 `rewrittenBy`,或没有受理帧(丢弃 / 抛错 / 受理前取消或失败)⇒ 这些面一直缺席、标题器不起。引擎今天不把屏后文本交给宿主,所以改写过的那一臂是缺席,不显示屏后文本(引擎交出之后改读它,律不变)。
94
+ 只回结果的腿(`verify` / `cascade` 形)看不到受理帧 ⇒ 有屏时预览、标题、fleet 行名缺席。**例外(已知债)**:`verify` 形提交的续跑输入照旧存请求原文(停驻后的续跑把它交给验证器当任务陈述),每次计 `fail_open_total{tag="server.objective-delivery.verify-replay-copy"}`。
95
+ **不在本条覆盖**:leader 车道 durable worker 的子目标续跑输入(`src/leader/wire.ts` 每只 worker 铸续跑上下文的写序)不经受理座、不打标记,屏前原文照旧落盘 —— 另票。
96
+ 续跑输入里的目标在有屏的腿上一直留空(交付之后也不补:续跑期间还有别的写者改写这一行 —— 权限模式切档口的回写 —— 交付时的补写会与它抢写);读它的只有两处展示:wake 腿新建的 run 行预览与续跑腿的 fleet 行名,
97
+ 这类腿写下的续跑输入一律缺席(`verify` 形那份照存的原文也不进这两处 —— 它只给验证器)。目标里的内联 `@名`(用户点模型)随目标一起留空 ⇒ 请求没带 `model` 时,续跑输入的 `model` 记下这次选中的那只模型,续跑腿照旧跑它。没有声明这两站的腿逐字不变(提交时照写)。补写失败(店抖动)⇒ 那张面保持空、run 照跑,计 `fail_open_total{tag="server.objective-delivery.face-fill-failed"}`。
98
+ 嵌入方:`createHttpServer` 的 `ServiceDeps` 多一只必填件 `deploymentMods`(交给 Runner 当 `mods` 的同一只数组;没有 mod 传 `[]`)—— 省掉是编译错;绕过类型省掉 ⇒ 构造期拒启,句子以 `createHttpServer: the deploymentMods seat is required` 起头。
99
+ **谁需要**:装 prompt 屏做内容过滤 / 改写的部署 —— 屏拦下或改写的原文不再留在 run 行、续跑输入里,也不再送进标题模型的请求。
100
+ **谁受伤**:① 这类部署上,被屏改写 / 拦下的 run 在任务列表、收件箱、fleet 面板上不显示「这是什么任务」(预览缺席,客户端渲占位),也不自动起会话标题;有屏的 `cascade` 提交同样缺席;订 `prompt.*` / `classic.*` 通配的只观察型运维 mod 也被算成屏(判据读声明,与引擎的通配语义一致):这类部署上只回结果的腿(`verify` / `cascade`)的预览 / 标题 / fleet 行名同样缺席,wake 新建的 run 行与续跑腿的 fleet 行名同样缺席,其余腿按 ② 在受理那一拍补上;
101
+ ② 原样交下的 run,预览在受理那一拍才出现(建行到受理之间读列表读不到预览);有屏的腿上 wake 新建的 run 行没有预览、续跑腿的 fleet 行不带名(原样交下也一样);③ 嵌入方 tsc 红 / 起服拒;④ 升级前写下的续跑输入与 run 行不改写 —— 那些行里的屏前文本留到它们被收割或会话被删。
102
+ **补偿**:① 预览缺席时行上其余键照旧,会话标题可手工设;要预览的部署可让屏原样交下(只加上下文、不改写);② 无;③ 把交给 Runner 的同一只 `mods` 数组传进 `deploymentMods`(没有 mod 传 `[]`);④ 要清旧行的部署按既有留存窗收割或删会话。
103
+ **升级前做**:嵌入方补 `deploymentMods`;其余零动作(零 DDL)。**回滚**:回到上一版即恢复旧形;本版留空的续跑输入在上一版上续跑时目标是空串(只影响 wake 腿新行的预览与 fleet 行名的显示);本版有屏的 `verify` 形续跑输入在上一版上续跑时,那份原文会进 wake 新行的预览与 fleet 行名(上一版不读这类行上的标记)。
104
+
105
+ 8. **停驻行一行坏字节只坏它自己那一行:SQL 后端的助手收件箱照列它、带引擎判官的 `rowVerdict`,收件箱与任务视图不再整张 500 / 503;`DB_BACKEND=local` 上别的卡的决断不再被一张坏卡拖成 500;local 的列表面候引擎;更正 7.144.0 节第 5 条两句(行为修复;wire 加性:坏行在场、`rowVerdict` 在场面放宽;部署零动作)**:
106
+ 旧形:同库一张停驻行的存储体被手改坏(`{}`;整段缺 `state` / `pendingAction` / `gate`;非 JSON / JSON 字面 `null` / 标量 / 数组)。
107
+ SQL 后端:助手收件箱 `GET /v1/assistant/inbox` 与任务视图 `GET /v1/assistant/tasks` 整张拒 —— `{}` / 缺 `state` 落 `503 approvals.read_unavailable`(「稍后重试」,而坏行不修同一请求恒失败)、
108
+ 存储体非 JSON / 字面 `null` 落 `500 approvals.read_corrupt`;同一张卡在运维队列 `GET /v1/approvals` 上照列(同一张坏行两个读者两个方向),队列上存储体读不成检查点的那一行不带 `rowVerdict`。
109
+ `DB_BACKEND=local`:一张缺 `state` 的卡让运维队列与收件箱对所有调用 `503 approvals.read_unavailable`,另一张好卡的决断 `500 internal.error`,坏卡自己的决断同样 500。
110
+ 新形:店的每一个停驻行读者一种失败方向 —— 逐行隔离,同一只判官(引擎的 `judgeCheckpointRow`)判坏行。
111
+ ① SQL 后端的收件箱照列那一行:`rowVerdict` = 判官对这份字节的判决(上面这些形今天答 `damaged` · `checkpoint.invalid_outcome` · `requirements_damaged`;例外:只缺 `pendingAction` 的行判官答 `ok` —— 引擎判官的已知缺口,这张卡的决断会失败),其余只带列事实
112
+ (`sessionId` / `scope` / `createdAt` / `gateKind` / `deadline` / `checkpointId`),摘要派生的键缺席、`input` 为 `null`;门型列读不出的行照旧不列。任务视图不再整张拒:那条 run 照列,`gate` 的 `severity` / `spentMicroUsd` 为 `null`(任务视图的行不带 `rowVerdict`,7.144.0 起就如此 —— 判决读收件箱或运维队列)。
113
+ ② 运维队列行上存储体读不成检查点的那一行也带 `rowVerdict`(判官对原样字节作答,恒 `damaged`)。两种读者同计 `fail_open_total{tag="server.approvals.park-row-blob-unreadable"}`(每次列表各计一次)。
114
+ ③ 决断只读自己那一行:local 后端按会话的三个读口(决断选行 / 属主门的 scope 预读 / 会话删除)改经引擎店的按会话读,一行读不出只坏它自己 —— 别的卡的决断照常 200;
115
+ 坏卡自己的决断答 409 带码拒、卡仍待决、字节不动(续跑第一级判官的拒:今天落 `approval_binding_mismatch` + 体顶层 `reason: "requirements_damaged"`、`retriable: true`)。
116
+ SQL 后端的决断本来就按会话选行(别的卡不受影响);它上面坏卡自己的决断:缺 `state` 这类同上,存储体 `{}` 落 `gate_not_tool_approval`(决断口的门型守卫读存储体的门)。坏卡的决断码与行上 `rowVerdict.code` 尚未收成同一个码。
117
+ **local 列表面本版未收**:local 后端的列举经引擎店的按 scope 列举,一行摘要读不动整只抛 ⇒ 运维队列 / 订阅流 / 收件箱 / 任务视图照旧整张 `503 approvals.read_unavailable`,候引擎对这种行答一行(带判决);
118
+ local 上存储体 `{}` 的行在引擎店重放时即被丢弃并披露,读作「这一行不在」(列表只列别的行、它的决断 404)。
119
+ **更正 7.144.0 节第 5 条(文书)**:那一条的「缺席(存储体解不出 / …)不是 `ok`」与「存储体解不出的行照列、不带 `rowVerdict`」两句,自本版起 SQL 后端上存储体解不出的行带 `rowVerdict`;缺席只剩「两次读之间行离开待决或字节变了」。7.144.0 节原文不改(已发节字节不动)。
120
+ **谁需要**:运维与助手壳 —— 一张手改坏 / 迁移残留的停驻行不再让整张收件箱、任务视图打不开,local 上也不再让别人的卡决不掉;坏行本身在列表上看得见(人要知道它停在哪)。
121
+ **谁受伤**:① 把收件箱 / 任务视图的 503 读作「店在抖、稍后重试」的监控:坏行这一形不再出 503;② 假设收件箱行恒有 `severity` 等摘要键、`input` 恒有内容的客户端:坏行上它们缺席(`input` 为 `null`)—— 契约本来就把它们标为可缺席;
122
+ ③ 把运维队列行 `rowVerdict` 缺席读作「存储体坏」的看板:那一形改为在场的 `damaged`。
123
+ **补偿**:按 `rowVerdict.kind !== "ok"` 把行呈成不可批的卡、把 `sentence` 原句给人;找坏行看计数 `server.approvals.park-row-blob-unreadable`,按会话查那一行修或删。**升级前做**:无。**回滚**:回到上一版即恢复整张拒形;落盘数据不受影响(本版不写任何新形)。
124
+
125
+ 9. **`DB_BACKEND=local`:审批账本里任何真删了行的调用(留存清扫的两只动词与 `deleteByTask`)的那一拍,问账日志 `approval-asks/asks.jsonl` 同拍整本重写成存活行的快照 —— 被删的问的字节(含工具实参字面)当拍离开活文件;订正 7.133.0 节第 14 条 local 一句(行为修复;持久面;部署零动作)**:
126
+ 旧形:7.133.0 起的留存清扫(和删一个 run 名下全部问行与批行的 `deleteByTask`)在 local 上把每次真删当一条写调用追加进 `asks.jsonl`,被删的问行 —— 连同卡上的工具实参(`Write` / `Edit` 的内容字面)—— 的字节仍留在文件里,
127
+ 直到记录数过阈(≥ 2000 条且 ≥ 存活行数的两倍)才整本重写;写得少的部署上,「整问删掉」之后的字节可以在盘上留很久(要等记录数过阈)。
128
+ 而 7.133.0 节第 14 条与 USAGE「审批账本保留多久」一段对运维写的是「它在三本账里的全部记录由维护 tick 整问删掉」,没有 local 的限定:SQL 两方言的 `DELETE` 当即成真,审计账的轮转本来就整文件原子重写,只有 local 问账日志不是。
129
+ 新形:任何删行的调用(留存清扫的问行 / 批行两只动词与 `deleteByTask`)真删了 ≥ 1 行 ⇒ 同一拍把整本账原子重写成存活行的快照(既有的压实动作;没有新阈值、没有新旋钮),活文件里只剩存活行;没删东西的调用不落记录、不重写(`deleteByTask` 零删原先会落一条无用的记录,现在同样不落);普通写的压实阈值(≥ 2000 条且 ≥ 存活行数的两倍)不变。
130
+ 压实失败(盘满 / 只读挂载 / 压实落点不可写)不影响删行的调用:行照删,计 `fail_open_total{tag="server.approval-ask-journal.compaction-failed"}`,账本里留着那条删行记录,下一次写(任何写)或下一次起服再压实 —— 到那时字节才离盘。
131
+ 升级前删过行的账本:起服重放到账本里的删行记录(升级前的清扫或 `deleteByTask`,或上面失败的那一次)⇒ 起服压实一次(信封 1 的老账本同一次压实顺带写成信封 2,迁移的 local 腿读数照报、不再重写第二次),此后活文件里没有被删的问的字节;账本里没有删行记录的部署,起服不因删行而重写(撕尾 / 坏行收拢、信封升级、车道回填各自的重写照旧)。
132
+ **边界(如实)**:① 留存清扫的问行、批行动词各按批删(每批至多 500 行),每个真删了行的调用重写一次整本 —— 一次清扫的重写次数 = ⌈删掉的问数 / 500⌉ + ⌈删掉的批数 / 500⌉(删掉的问与批各不到 500 只的清扫至多两次;积压的头几次清扫更多);写的是存活行的快照,同步跑在事件循环上,
133
+ 量级(本机单次读数,合成账本):1 万行 × 2 KB 的存活账本约 0.15 s,3 万行 × 5 KB(约 160 MB)约 1 s;② 压实是原子换文件,不是文件系统层的安全擦除(空闲块、备份、快照不在本服务手里);
134
+ ③ 起服时因撕尾 / 坏行隔离出去的原件 `asks.jsonl.corrupt-<ts>` 没有清扫腿,里面仍有当时的字节 —— 取证材料,要清由人来(正常部署恒零)。
135
+ **订正 7.133.0 节第 14 条(文书)**:那一条「从三本账里整问删掉」在 `DB_BACKEND=local` 的问账日志上,7.144.0 及更早是「读不到了」—— 字节要等记录数过阈的压实才离盘;自本版起与 SQL 同拍。7.133.0 节原文不改(已发节字节不动)。
136
+ **谁需要**:把审批账本的留存窗当机密 / 取证边界的 local 部署(过窗的问里有 `Write` / `Edit` 实参这类内容,按窗期待它离盘)。**谁受伤**:无 —— 每次真删了行的调用多一次整本重写(留存清扫每小时至多一次、通常问行与批行各一次;`deleteByTask` 本服务自己的路径不调用它;体量随窗内存活的问走),读数 / 日志形不变。
137
+ **补偿**:不需要。**升级前做**:无。**回滚**:回到上一版(7.144.0)⇒ 账本照读(存活行快照是既有的压实形,上一版认这三只删行动词);删行回到「追加记录、过阈才重写」。
138
+
139
+ ## 7.144.0 —— 🔴 会话日志回放丢了记录:用户面通告只剩引擎的 `session.lineage_rerooted`(`session.records_skipped` 退役)、丢了分支上祖先的会话从断点续上、走不成一棵树的已存日志答 `corrupt_session`(打开面 `invalid_session` 退役)(wire BREAKING:一个通告码与一个错误码退出;行为修复;部署零动作) · 跨会话来信有序关停:info 行字段改为 `{ queues, cards }`、回执没落进发信方的箱每条一行 warn(运维面;日志形变更) · 引擎在没有自己席的地方说的话落结构化 `engine_notice` 日志行,不再是裸 `console.warn` 句(运维面;日志形变更) · 🔴 `DB_BACKEND=local`:数据根里的会话元数据边档本构建读不出(更新的引擎写下 / 损坏 / 读不了)⇒ `ensureSchema()` 拒启 `config.schema_mismatch`,开始服务之前判(行为修复;fail-closed;持久面;零 DDL) · SQL 后端:更新引擎停驻的行续跑 / 决断答 409 `checkpoint.unsupported_version`(不再答 `conflict.checkpoint_unreadable`)、运维队列行与助手收件箱行带 `rowVerdict`(wire 拒码改答 + 加性;部署零动作) · 持久问店车道上同一只审批问被另一腿再问时,「这一问要人」取行上那张卡与这一腿请求的并集(安全;行为收紧;wire 零形变;部署零动作) · 🔴 引擎 7.62.0:部署的 mod 包按内核契约 8 重建(部署面;BREAKING) · 远端五车道的私有暂存目录多一道 ACL 核:继承来的 ACL 条目去不掉 / 读不出 / 目标机系统不在闭集里 ⇒ 不暂存,退回就地写目标(行为收紧,fail-closed;安全;部署零动作) · 🔴 活流文字段的脱敏单位收成段(与账本 `text` 行同一个):引擎的 `text_end` 是文字块的交付点、不收段,锚与值分在同一段两块时 `text_delta` / `text_end` 照样遮;更正 7.143.0 节第 11 条「文字段的单位是引擎的文字块」一句(wire 值语义;安全;部署零动作) · 🔴 `DB_BACKEND=local`:仍带属主戳的存档的拒有了自己的码 `conflict.session_archive_stamped`,fork 与改日志的各形推送(含载荷分叉的 fast_forward)同码同句(wire BREAKING:这两扇写口上带戳存档的拒由 `conflict` 改新码;行为修复;部署零动作) · 更正 7.143.0 节五处说法:退役工具名写进 deny / ask 规则时按名单的来源各答各码(请求体 422 `request.unprocessable` · 部署名单拒启 · `config.legacy_tool_name` 只来自存量会话规则)、`decidedVia` 在直连门部署上哪几口不收、续跑门 `/resume` 的真路由、user 层要根的 allow 免不了配置根下写保护表上的写、被拒的个人层抹除与点名个人层的只读也会在盘上留下一只从没写过的个人店(文书;零行为变化) · host 车道:执行环境的家目录主张证不了 ⇒ 环境在开跑前就不铸,run 失败终局码 `env.home_unconfirmed`(同步提交腿 409),命令带不带路径同一首拒;worktree 的 git 基环境不再带家目录主张;更正 7.140.0 节第 12 条 ③(wire 新码;行为修复;部署零动作)
140
+
141
+ 1. **🔴 `DB_BACKEND=local`:会话日志回放丢了读不出的记录 —— 用户面只剩一只帧 `session.lineage_rerooted`(引擎铸),本服务自铸的 `session.records_skipped` 退役;丢了分支上祖先的会话从断点续上;走不成一棵树的已存日志答 `corrupt_session`,打开面不再出现 `invalid_session`(wire BREAKING;行为修复;部署零动作)**:
142
+ 旧形(7.143.0,core 7.61.0):打开一只回放跳过了记录的会话时,只有本服务自铸的一帧 `session.records_skipped`(`{ dropped, entriesKept, sessionId }`,每次打开一帧、会话缓存命中的轮次不说);引擎不发 `session.lineage_rerooted`(那一帧从 core 7.62.0 才有)。
143
+ 被跳过的记录若是分支上的祖先,这一轮失败(`invalid_session`:同步口 500、流式终帧 failed、后台 run 行 failed),会话再也跑不动;读口与提交口对走不成一棵树的已存日志答 500 `invalid_session`。
144
+ 新形:只剩 `session.lineage_rerooted`(`detail: { break, recordsDropped, recordsTotal, leaf, entriesOnPath, sessionId, runId }`,`break: true` 另带 `{ missingParentId, rootedAt, entriesCut }`),每条腿一帧(会话缓存命中的轮次照样说)。
145
+ 丢了祖先的会话从断点续上(`break: true`),这一轮跑完(同步口 200)。回放没丢记录的断开(悬空父 / 自指 / 成环 / 叶子缺席)答 `corrupt_session`(与存档读不出同码、同一个客户端动作);
146
+ `invalid_session` 只剩会话同步导入面(答 `422 invalid_entries`,不变)。
147
+ 已知差异:进程已持有这只会话的活存储时盘上才坏的行,这一轮读的是内存里那份完整历史 ⇒ 不发帧(此前每次打开一帧),下一次起服后的第一轮才发;
148
+ 丢了祖先的会话 run 续上了,而会话视图(`GET /v1/sessions/:id` / `…/memory-status`)对同一只断开照答 500 `corrupt_session`。
149
+ 运维面不变:回放跳过的每条记录照样计 `fail_open_total{tag="server.session-repo.corrupt-record-skipped"}`、逐条进探针文件(`SEMA_FAILOPEN_PROBE`)。执行放置回填(一次性迁移)点名读不出存档的 `fault` 闭集收成 `corrupt_session` / `storage`。
150
+ **谁需要**:文件后端上存档坏了的会话的用户(会话还能跑;一件事一只帧)。**谁受伤**:按 `session.records_skipped` 渲染、或按打开面 `invalid_session` 分支的消费方。
151
+ **补偿**:同一事实改读 `session.lineage_rerooted`(`recordsDropped` = 旧 `dropped`;`entriesOnPath` 是 run 上下文里保留的条目数,不等于旧 `entriesKept` 的全部幸存条目);结构坏改读 `corrupt_session`
152
+ (别重试;换一个新会话、从断点之上的条目分叉,或请运维修好 / 移走那份日志)。
153
+ **升级前做**:无。**回滚**:回到上一版 ⇒ 回到只有 `session.records_skipped` 那一帧(上一版的引擎不发 `session.lineage_rerooted`)、丢了祖先的会话重新失败(`invalid_session`);落盘数据不受影响(本版不写任何新形)。
154
+
155
+ 2. **跨会话来信的有序关停改为结清进程里的每只 held 队列,并等结清回执落进发信方的箱(运维面;日志形变更;部署零动作)**:
156
+ 旧形:info `peer_inbound_settled_at_shutdown` 的字段是 `{ queues, scopeUnresolved }`(`queues` = 结清了的、scope 求得出的队列数;`queues > 0` 或 `scopeUnresolved > 0` 才发);关停按会话行的属主求每只队列的 scope,求不出的计进 `scopeUnresolved`、那只队列不结清;结清回执投出即返。
157
+ 新形:字段改为 `{ queues, cards }`(`queues` = 注册表里的每只队列、含空的;`cards` = 关停那一刻快照里的卡数;只在 `cards > 0` 时发;`scopeUnresolved` 退役:关停读引擎的队列枚举,不再求 scope);回执没落进发信方的箱 ⇒ 每只有回执没落箱的队列一行 warn `peer_inbound_shutdown_receipt_unlanded`(带引擎那句话,点名该队列所有没落箱的 seq,同一只队列两条都没落是一行里列两个 seq;卡照样已结清)。
158
+ 兜底计数 `server.peer-inbound.notice-coordinates-unreadable` 退役,新计数 `server.peer-inbound.queue-box-unknown`(按构造不可达的一形:队列的箱既不是会话自己的箱、也不是收件箱)。
159
+ **谁需要**:滚动发布与重启时关停的运维 —— 关停真的等结清回执落进发信方的箱,落不进的按队列一行 warn 点名 seq。
160
+ **谁受伤**:按 `scopeUnresolved` 或旧计数告警的运维。**补偿**:回执没落箱改读 `peer_inbound_shutdown_receipt_unlanded`。**升级前做**:无。**回滚**:回到上一版即恢复旧字段。
161
+
162
+ 3. **引擎在没有自己通告席的地方说的话(品牌模型构造 / 一次请求的路由读 / 对端拨号 / 直建蒸馏座)改落结构化 `engine_notice` 日志行,不再是裸 `console.warn` 句(运维面;日志形变更;部署零动作)**:
163
+ 典型一形:`MODEL_API_KEY` 不足 8 字符时,起服日志里只剩本服务那一行结构化 `own_credential_value_not_withheld`,引擎那一行裸句消失。HTTP 服务与本机单次运行两个入口在日志接上之后装这只进程缺省席;装席之前的几步(读配置)引擎若说话仍是裸句。
164
+ **谁需要**:把 stderr 当 JSON 行流收的日志管道(引擎裸句不再混进来)。
165
+ **谁受伤**:按引擎裸句子串告警的运维。**补偿**:同一事实改读 `engine_notice` 行的 `code`。**升级前做**:无。**回滚**:回到上一版即恢复裸句。
166
+
167
+ 4. **🔴 `DB_BACKEND=local`:数据根里的严格边档(今天一只:`session-incarnations.json`)本构建读不出 ⇒ 起服拒 `config.schema_mismatch`,在 `ensureSchema()` 里、开始服务之前判(行为修复;fail-closed;零 DDL;部署零动作)**:
168
+ — **此前**:没有这只码。严格读在第一次用到那只边档时抛一句无码的拒因(`… is unreadable (malformed) — refusing to read or write session owners and incarnations …`),落点随路径漂:
169
+ 起服一次性迁移读到这只边档的(7.141.0 起迁移窗内每次起服都读;7.139.0 / 7.140.0 在数据根里有 run 的会话时读)以它拒启;起服路径没读到它的(例:只调 `ensureSchema()` 的嵌入方)起得来,每个碰到会话元数据的请求答 500 `internal.error`。
170
+ 起服之后另一只写者写进来的、本构建读不出的字节,会被本进程下一次写静默盖掉。
171
+ — **本版**:`ensureSchema()`(先于 M33 快照消化与任何请求)把这只边档从盘上读一遍(同一进程里先前已载入的也重读),读不出 ⇒ 拒启,码与 SQL 后端列册对账同一个 `config.schema_mismatch`,拒句同形:
172
+ 点名文件、种别与不认得的键名,方向句「the data root is NEWER than this build」,出路三条 —— 部署写下它的那一版;回滚 = 恢复升级前的数据根备份(字节损坏同此出路);读不出字节(例:`EACCES`)⇒ 修好读权限 / 盘 / 挂载再起,文件不用动。
173
+ 检查只读,文件原地不动。没设 `DB_BACKEND`(缺省推导的 local)同样拒启,不退回内存。
174
+ 起服之后这只边档第一次被碰时才读不出(嵌入方跳过了 `ensureSchema()`;或起服后另一只写者把它写成本构建读不出的形 —— 每次写之前先读盘上现有字节)⇒ 同一只拒(同码);
175
+ 读不出的是形 ⇒ 这只边档在本进程里此后每一读每一写都拒(重启才重判),碰它的请求失败(经全局兜底的路由答 500 `internal.error`、运维日志一行 error 级 `request_error` 带本码);盘上字节一个不盖。
176
+ 读不出字节(I/O)只让那一次读写失败,不粘。
177
+ 嵌入方:包根多导出一只类 `LocalDataRootSchemaMismatchError`(`code` = `config.schema_mismatch`;`findings` 逐文件 `{ path, label, problem, unknownFields }`)与它的类型 `LocalSidecarMismatch`,与 SQL 后端的 `RetiredSchemaPresentError` 同码。
178
+ **谁需要**:`DB_BACKEND=local` 的部署与壳起的本机引擎 —— 降级附着(新引擎写过的根交给旧一些的引擎)拒在开始服务之前、带机读码,拒句即出路。
179
+ **谁受伤**:只调 `ensureSchema()` 的嵌入方遇到读不出的会话元数据边档,此前起得来(只有碰它的请求失败),现在拒启;按旧拒因句子写的告警失配。
180
+ **补偿**:拒句点名文件、种别与出路;判只读,文件原地不动;告警改按码 `config.schema_mismatch`。≤ 7.143.0 的引擎附着更新引擎写过的根时照旧按各自的旧路径失败(已发版本改不了),规则不变:**不许降级附着;回滚 = 恢复升级前的数据根备份**。
181
+ 订正 7.143.0 节第 43 条:「服务进程本身起得来」只对起服时不读这只边档的引擎与路径成立(7.141.0 起起服一次性迁移在窗内每次起服都读它;7.139.0 / 7.140.0 在数据根里有 run 的会话时起服回填读它;读不出即以无码的拒因拒启);规则与出路不变。
182
+ **升级前做**:无。**回滚**:回到上一版即回到上一版的落点;本条不改任何持久数据。
183
+
184
+ 5. **`DB_BACKEND=mysql|pg`:更新引擎停驻的审批行,续跑 / 决断答 409 `checkpoint.unsupported_version`,不再答 409 `conflict.checkpoint_unreadable`;运维队列行带 `rowVerdict`(wire:一处拒码改答 + 加性键;行为修复;部署零动作)**:
185
+ 旧形:滚动升级 / 回滚中,一行由更新的引擎停驻(格式版本超出本副本的上限),本副本 SQL 店的 `get()` 在解码之前按格式版本列先行拒:续跑 / 决断答 409 `conflict.checkpoint_unreadable`,体里 `error` 是店内句子
186
+ 「checkpoint format version N is newer than this build supports (max M) — upgrade the service to resume it」;运维队列(`GET /v1/approvals` / `/stream`)上这张卡与可批的卡同形。
187
+ 新形:行照常读出,续跑第一级由引擎的判官拒 —— 409 `checkpoint.unsupported_version`、体顶层 `reason: "version_newer"`(引擎 `detail.reason` 原值过境;行留 pending、字节不动;`retriable` 与两版本键照该码的既有读法,与 LOCAL 后端同一答)。
188
+ 运维队列行带 `rowVerdict`(引擎判官对这一行的判决;`{ "kind": "lacking", "code": "checkpoint.unsupported_version", "reason": "version_newer", "sentence": … }` 这一形就是上面那一行),与助手收件箱行同名位同一答(收件箱行本版起也带这一位,两只后端同读);
189
+ 缺席(存储体解不出 / 两次读之间行离开待决或字节变了)不是 `ok`。`conflict.checkpoint_unreadable` 不再由格式版本产生,剩下的是读这一行时抛出的故障(存储体解不出、库读故障等)。流内审批找停驻门时,判官答 `lacking` 的行本副本不绑(留给能续它的副本)。
190
+ 运维面:SQL 后端起服后第一次列出审批队列时把待决行的存储体各读一次(之后按存储体摘要记忆,字节不变不再读);存储体解不出的行照列、不带 `rowVerdict`,计 `fail_open_total{tag="server.approvals.park-row-blob-unreadable"}`。
191
+ **谁需要**:运维(队列上看得出哪张卡本引擎续不了);混版车队(那张卡留给能续它的副本)。**谁受伤**:SQL 后端上按 `conflict.checkpoint_unreadable` 的句子判「版本太新」的消费方。
192
+ **补偿**:改读 `checkpoint.unsupported_version` 体顶层的 `reason`,或在列表上先读 `rowVerdict`。**升级前做**:无。**回滚**:回到上一版即恢复旧拒形;落盘数据不受影响(本版不写任何新形)。
193
+
194
+ 6. **持久问店车道:同一只审批问被另一腿再问(换副本重入 / 混版窗)时,「这一问要人」取行上那张卡与这一腿请求的并集(安全;行为收紧;wire 零形变;部署零动作)**:
195
+ 旧形:重入腿的呈卡帧采信行上那张卡,判据只读这一腿的请求 —— 行上要人而这一腿请求没带时,`allow_session` 记下会话放行、`decidedBy:"policy"` 的放行被收下、旧族 `tool_approval` 帧与
196
+ `livePending[]` 行不带 `requiresRealApproval` / `rememberRefused`;行上不要人而这一腿请求带时,呈卡帧的 `card.risk.requiresRealApproval` 说 `false`。
197
+ 新形:两者任一说要人即按要人 —— `allow_session` 只放行这一次(`rememberApplied:false`)、策略的放行答 400(卡还在)、两族帧与列表行同说要人、提示位亮;
198
+ 同一副本上同一只问的重复登记同值(应答口按最早那条答);行不回写(重放帧与耐久问回决口照读行)。
199
+ **谁需要**:多副本 / 滚动升级部署上答审批卡的人与按卡作答的策略客户端。**谁受伤**:依赖重入腿上要人卡被「本会话放行」记住的调用方。**补偿**:不需要(人照常逐次放行这一次)。
200
+ **升级前做**:无。**回滚**:回到上一版即恢复旧读法(本版不写任何新形,落盘数据不受影响)。
201
+
202
+ 7. **🔴 引擎 7.62.0:部署的 mod 包按内核契约 8 重建(部署面;BREAKING)**:
203
+ — **此前**:mod 内核契约号是 7。
204
+ — **本版**:引擎只加载声明 `"contract": 8` 的 mod 包(读包者按相等判):按契约 7 写的包在起服被拒 `config.mods_invalid`(`MODS_PACKAGES` 的那一席,拒句点名两个契约号)。
205
+ 8 = 扩展内核闭集收成参照实现的 145 名:`session.start` / `turn.start` / `session.measure` / `prompt.submit` 等事件开站(`session.start` / `session.end` 的底升 `classic.SessionStart` / `classic.SessionEnd`)、
206
+ `$.session.turns` / `usage` / `version` 有底、`session.messages` 收 `{ agentId }`。扩展在 `prompt.submit` 上改写过的输入,模型看到改写后的文本,它的 `human_input` 帧带 `rewrittenBy`(改写它的扩展注册名,按改写序;缺席 = 原样送达)。
207
+ 请求 `settings.hooks` 里的 `SessionStart` / `SessionEnd` 照收、不在服务端挂(壳属主事件,与 `PermissionDenied` / `SubagentStart` / `SubagentStop` 同一读法)。
208
+ **谁需要**:写扩展改写 / 审阅输入、观察腿生命周期的部署。**谁受伤**:装了按契约 7 写的 mod 包的部署(起服拒);没声明 `MODS_PACKAGES` 的部署零动作。
209
+ **补偿**:mod 包把 `hooks.json` 的 `"contract"` 改成 8 并按新契约重建(新站点与 `$` 方法见引擎文档)。**升级前做**:装了 mod 包的部署先备好契约 8 的包。**回滚**:回到上一版须同时换回契约 7 的包。
210
+
211
+ 8. **远端五车道的私有暂存目录多一道 ACL 核:读到继承来的 ACL 条目就去掉,去不掉 / 读不出 / 目标机系统不在闭集里 ⇒ 不暂存,退回就地写目标(行为收紧,fail-closed;安全;部署零动作)**:
212
+ 旧形:私有暂存目录收紧后只读回模式位与属主。目标机是 macOS、且工作区目录带可继承的原生 ACL 允许条目(`directory_inherit`)时,新目录一建出来就带着条目,读回 `700` 也挡不住 ——
213
+ 暂存件(替换 0600 的目标时,新内容)对条目所点的身份可见;FreeBSD / illumos ZFS 的 NFSv4 ACL(`aclmode=passthrough`)同类。7.139.0 节第 23 条 ⑧ 末尾把它写成已知缺口,就私有目录自身而言自本版起不再成立(已发节原文不改)。
214
+ 新形:读回模式与属主之后,再在**目标机**上按 `uname -s` 读目录的 ACL 条目,闭集四臂 —— Linux(POSIX ACL 由模式位读回的掩码覆盖,不另读)· Darwin(`ls -led` 读、`chmod -N` 去)· FreeBSD(`ls -ld` 的 `+` 读、`setfacl -b` 去)·
215
+ SunOS / illumos(同读、`chmod A-` 去)。读到条目就去、去完再读,读不到才算私有;读不出、去不掉、去完仍读到、`uname` 读不出或名字在闭集之外 ⇒ 这一次写不暂存,退回就地写目标
216
+ (与第 23 条 ⑧ 同一条退路:非原子;ssh / local-docker / k8s 写进原 inode、权限位不变,e2b 的 `files.write` 与 adb 的 `adb push` 整份写目标、inode / 权限位由对端定),遥测计 `server.remote-write.stage-seal-fallback`。
217
+ 整文件替换提交时跟一跳符号链接到别的目录重新暂存的那只私有目录走同一只判。wire 零变化。
218
+ 覆盖面:只管五条远端车道的私有暂存目录;host 车道的暂存是引擎的、device 车道的是设备侧执行器的,本版不动;Linux 上经 NFS 挂载、由服务端自己执行的 NFSv4 ACL 在客户端读不出条目,Linux 臂按掩码读法算过;
219
+ FreeBSD / illumos 两臂按系统文档写、未上真机,工具输出与预期不符(退出状态不成、往 stderr 报了一句、头一行不是权限串、多出一行)时同样退回就地写;读 ACL 的工具若自己静默吞掉读取错误(macOS 的 `ls -le` 没有第二条读路),读到的是「没有条目」,本版看不出;
220
+ 替换之后目标不带原件自己的 ACL 条目(整文件替换换 inode)本版不改。
221
+ **谁需要**:ssh 车道上目标机是 macOS / FreeBSD / illumos、且工作区目录带可继承 ACL 条目的部署(其余四条车道的目标是 Linux 容器或 Android 设备,走 Linux 臂)。
222
+ **谁受伤**:ssh 目标机系统不在 Linux / macOS / FreeBSD / illumos 之内的部署(OpenBSD / NetBSD / AIX / Cygwin 一类):这类目标上每一次写都改走就地写(与 7.138.x 同形,非原子),`stage-seal-fallback` 计数非零。
223
+ **补偿**:就地写与 7.138.x 逐字同形、写照常成功;计数点名目录;要原子替换就把工作区放到被支持的系统上。macOS / FreeBSD / illumos 目标上继承来的条目去得掉的照常暂存,无需动作。
224
+ **升级前做**:无。**回滚**:回到上一版即恢复旧形(私有目录上继承来的条目不再被去);暂存名是瞬时的,零数据面动作。
225
+
226
+ 9. **🔴 活流文字段的脱敏单位收成段(与账本 `text` 行同一个):引擎的 `text_end` 是文字块的交付点、不收段 —— 锚与值分在同一段的两个文字块里时,`text_delta` 与 `text_end` 照样遮(wire 值语义;安全;帧数 / 帧序 / 身份零变化;部署零动作)**:
227
+ 旧形(7.143.0):`POST /v1/tasks/stream`(顶层与转发子代腿)与子代 tail 面上,文字段的流式口在引擎每个 `text_end` 上收掉重开,`text_end.content` 是引擎那一块孤立地过脱敏器;
228
+ 账本 `text` 行(`GET /v1/runs/:id/events` / turns)按段把同一段的几块拼起来判 —— 锚在块 1(`password=`)、值在块 2 时,活流与 `text_end` 带值明文、账本遮;
229
+ 账本行只拼逐块帧字节,只有 `text_end`(没有逐块帧字节)的块不在行里。
230
+ 7.143.0 节第 11 条「文字段的单位是引擎的文字块 … 此前 `text_end` 上就是这样」一句自本版起不再成立(已发节原文不改)。
231
+ 新形:文字段与推理段同一条状态边界 —— 段(段界谓词 + 腿终局 / 子代终态),= 账本 `text` 行的单位。引擎的 `text_end` 是这一块的交付点:块里还在窗里的字节按整段读法、文本到此为止交出
232
+ (紧贴 `text_end` 之前那一帧不带 `eventId` 的 `text_delta`),`text_end.content` = 引擎这一块的正文接在本段前文之后判、只交这一块那一截。一块的原文 = 它的逐块帧字节,
233
+ 只有 `text_end`(没有逐块帧字节)的块 = 它的正文;段文本 = 各块原文依次拼接,活流的段与账本 `text` 行同读(只有 `text_end` 的块活流上由它的 `text_end` 交付、不另出逐块帧,账本行里照样有它)。
234
+ 有逐块帧的块:逐块帧拼接 = 该块 `text_end.content`(只有 `text_end` 的块没有逐块帧,它的正文只在自己的 `text_end.content` 里;引擎修剪过退化循环尾的块照旧以修剪后的为准);各块依次拼接 = 账本 `text` 行(下面两个方向除外)。交付时按到此为止的判定与整段判定不同的两个方向一个处置:凭据形恰横跨块界(读得出的半形出 `«redacted…»` 记号;读不出的半截 —— 如 `sk-ant-api0` 这样的短前缀 —— 原样出门,
235
+ 至多是块界之前的字节;后一块上横跨的那一条整枚换记号),或交付时认作凭据、后文让它不再是(如 `password=config.` | `password2;`:活流那一截是记号、账本原样)——
236
+ 活流按到此为止,账本整段判,该段收段时计一次 `server.live-text.hold-diverged`。帧数、帧序、`eventId`、`text_end` 在场性与 7.143.0 相同。
237
+ **谁需要**:读活流的 API 消费方与壳(多文字块的段:引用切块、穿插思考的回答 —— 活流与 `GET /v1/runs/:id/events` 对同一段文字同一个答案)。
238
+ **谁受伤**:按 `text_end` / `text_delta` 字节做逐字 diff 的消费方 —— 锚值分块的那一形从明文变记号;凭据形恰横跨块界时,后一块的 `text_end` 与逐块帧以一枚整的记号起头(前一块已带一枚);块界上认作凭据、后文让它不再是的那一截活流是记号、账本原样;按账本 `text` 行逐字 diff 的消费方 —— 只有 `text_end` 的块的正文从本版起在行里;
239
+ 多文字块长段的 CPU:每个 `text_end` 整段扫两次(交付余下字节一次、`text_end.content` 接本段前文判一次),上界 O(块数 × 段长)(7.143.0 每块只扫这一块)。
240
+ **补偿**:按段读的同一份文本在 `GET /v1/runs/:id/events` 的 `text` 行;按块整段替换的读法照旧幂等(有逐块帧的块:逐块帧拼接 = 该块 `text_end.content`)。
241
+ **升级前做**:无。**回滚**:回到上一版即恢复旧形(文字段按块判、账本行只拼逐块帧字节);本版写下的行原样留着;零数据面动作。
242
+
243
+ 10. **🔴 `DB_BACKEND=local`:仍带属主戳的存档的拒有了自己的码 `conflict.session_archive_stamped`,fork 与改日志的各形推送同码同句;载荷分叉的 `fast_forward` 与提交时才翻成 fork / stale 的无同意推送也答它(wire BREAKING:这两扇写口上带戳存档的拒由 `conflict` 改新码,按 `errorCode == "conflict"` 分支的消费方先改读;行为修复;部署零动作)**:
244
+ 旧形(7.141.0 节第 10 条):仍带戳的存档(一次性迁移留着的,或跳过带迁移的版本升上来的数据根)上,`POST /v1/sessions/:id/fork` 与改日志的推送(会话同步导入的提交)答 `409 conflict` + 带出路句的固定句
245
+ (「… delete the session and push it again」)。两处不齐:
246
+ ① **码**:`conflict` 同时是暂存提交时属主格已变那一拒的码(固定句「… start the sync again」,出路相反:从第一阶段重来)—— 同状态、同码、两条相反的出路,按码分支的机读方分不开,只能读句子;
247
+ ② **句**:改日志的推送在提交时先过「谁赢」的判,带戳判排在它们后面 ⇒ 三形被截住,答通用的 `409 conflict`、句子 `sync conflict`、体带 `relation`:`fast_forward` 而共享条目的载荷与目的端的不同
248
+ (目的端把某条补写过、id 不变,推送拿着旧版本再追加);第一阶段到提交之间分类翻成 fork、翻成 stale,又没带同意(`resolution: "overwrite-dst"`)。这三形的通用句指的出路是「带同意重来」,而带同意重来在带戳存档上照样被拒 —— 死路;
249
+ 干净追加的 `fast_forward`、同 id 异载荷、带同意的 fork 答的是带出路句的那一条,这三形不带。
250
+ 新形:① 带戳存档的拒有自己的 wire 码 `conflict.session_archive_stamped`(状态 409,固定句的字节不变,附录 A.1 新行);fork 路由与会话同步导入的提交两扇写口读同一张映射,同码同句;
251
+ 属主变更那一拒仍是 `conflict`。② 带戳判是提交里第一道存档判 —— 只要这一提交要换日志(「id 与内容都相同」那一支之外的一切),先问这份存档的日志换不换得了;
252
+ 带戳存档上各形(干净追加 / 载荷分叉的 `fast_forward` / 同 id 异载荷 / fork / stale,带同意与否)一律答同一码同一句,体只有 `error` / `errorCode` 两键(不带 `relation`),什么都没写(行不动、存档原样带戳)。
253
+ 「id 与内容都相同」的重推照旧不碰存档、照常落定;匿名存档上的应答不变(提交现在先读一次存档头:头读不出的存储故障先于同步冲突上抛,不再答 409)。
254
+ 提交里的次序也随之定下:带戳判排在本处写者拒(`conflict.session_writer`)与引擎的日志校验之前 —— 前者在 HTTP 上只有第一阶段之后别处认领了本处写者的竞态窗里才到得了(第一阶段已拒写者),
255
+ 后者流式上传时已判过(只有直接调店方法的嵌入方碰得到);带戳存档与这两样同时成立时,先读到新码。
256
+ 范围(如实):第一阶段(`POST /v1/sessions/:id/sync/import`)按 id 分类出 fork / stale 且没带同意时,仍先答通用的 `409 conflict`(`sync conflict` + `relation`)—— 那一口只按 id 分类、不经提交里的带戳判,答的是同步协议的冲突答复;
257
+ 带同意重来之后,第二阶段答新码。所以带戳存档上 fork / stale 形的推送,要到带同意的第二轮才读到出路句。
258
+ **谁需要**:壳 / SDK 等按机读码分支的消费方(带戳存档:删掉会话再推;属主变更:从第一阶段重来)—— 两件事现在是两个码;local 部署上对迁移留着的带戳存档(起服 warn `local_archive_kept_stamped` 点名)推送的客户端,载荷分叉的推送一次就读到「删掉会话后重推」,不会先去试带同意重来。
259
+ **谁受伤**:① 按 `errorCode == "conflict"` 处置带戳存档的 fork / 改日志推送拒的消费方(7.141.0–7.143.0 的读法)—— 这两扇写口上它们不再读到 `conflict`,按状态 `409` 或按 `conflict.session_archive_stamped` 分支;
260
+ ② 按 `sync conflict` 句子或体里 `relation` 键判「要解决冲突」的客户端:载荷分叉的 `fast_forward` 与无同意的 fork / stale 在带戳存档上不再读到它们(这三形在带戳存档上本来就解决不了)。
261
+ **补偿**:改读新码 `conflict.session_archive_stamped`(读体的 `error` 即出路:删掉会话 `DELETE /v1/sessions/:id` 后重推);按状态 `409` 分支的不受影响。**升级前做**:无。**回滚**:回到上一版即恢复旧码与旧判序(本版不写任何新形,落盘数据不受影响)。
262
+
263
+ 11. **更正(7.143.0 节第 19 条、第 26 条、第 10 条、第 31 条与第 36 条五处说法,文书;零行为变化)**:
264
+ ① **第 19 条**写「策略的 deny / ask 名单点名 `TaskOutput`(或 `TeamCreate` / `TeamDelete`)⇒ 跑前拒 `config.legacy_tool_name`」,这只对一种来源成立。退役工具名写进 deny / ask 规则时,在哪里拒、答什么,按名单的来源分:
265
+ — 请求体 `settings.permissions.deny` / `ask`:三条提交口(`POST /v1/tasks` · `/v1/tasks/stream` · `/v1/runs`)受理时拒,零模型调用;`422`、码 `request.unprocessable`、句首 `request settings cannot be applied as written:`,体带 `field`(`settings.permissions.deny` / `settings.permissions.ask`)与 `detail.problems[]`,退役名那一条 `reason: "retired"`。
266
+ — 部署名单 `APPROVAL_REQUIRE` / `APPROVAL_DENY` / `APPROVAL_NEVER_AUTO` / `APPROVAL_GRANT`:起服拒启,拒句点名条目(没有 wire 码);中心下发的 `governance.approvalRequire` 整组被拒、保前值。
267
+ — `config.legacy_tool_name`(同步腿 `400`;异步与流式腿落在终态 run 行的码上)只来自存量:升级前的写口收下、盘上留着的会话规则 `toolDeny`(例:7.142.x 上经 `PUT /v1/sessions/:id/policy` 写进去的 `TaskOutput`),升级后在那只会话上提交即得这一码,拒句是引擎的;出路 = operator 用 `PUT /v1/sessions/:id/policy` 改写那条会话的规则。
268
+ 请求体 `settings.permissions.allow` 点名这三个名字照旧只得一行提示。
269
+ ② **第 26 条**没有标门。**直连门部署**(`DIRECT_APPROVAL_DOOR` 连同它要求的 HMAC 钥与签名身份锚都在)上,`POST /v1/approvals/:sessionId/decide`、`POST /v1/assistant/tasks/:id/plan_review` 与 `POST /v1/tasks/:taskId/asks/:askId/decision` 三口不收 `decidedBy`(在场即 `400 decided_by_not_in_proof`,不论值),
270
+ 所以 `decidedBy: "policy"` + `decidedVia` 在这三口上是 400;只带 `decidedVia`(旁边是缺席的人)在任何部署的任何一口上都是 400(live `/respond` 码 `request.body_shape`,其余三口 `request.field_invalid`)。
271
+ live `POST /v1/tool-approvals/:id/respond` 不带决策证明,直连门部署上照样按第 26 条受理。不是直连门的部署,四口按第 26 条原句受理。
272
+ ③ **第 10 条**的 `/resume` 是 `POST /v1/assistant/tasks/:id/resume`(没有 `POST /v1/runs/:id/resume` 这条路由)。四道续跑门各续各的门:`POST /v1/approvals/:sessionId/decide` 续工具审批卡;`POST /v1/assistant/tasks/:id/plan_review` 续 `plan_review` 门;
273
+ `/resume` 续资源限停驻(门 `resource_limit`:调度抢占,或预算 / 轮数 / 墙钟分片),停在审批卡上的任务打它得 `409 gate_not_resumable`;`POST /v1/sessions/:id/wake` 续 `task_done` 停驻,有未决门时得 `409 wake.gate_pending`。
274
+ ④ **第 31 条**写「`userSettings` 里要根的 allow 规则免问的是配置根下的路径」(CHANGELOG 同节「现在」句:「它免问配置根下 `secret` 的写」),对配置根下的**写**不成立:
275
+ — 写:目标在引擎缺省写保护表上的写(配置根就在表的 `.sema` 行上,见下)照问,任何 allow 规则 —— 带层条目、纯串、`//` 绝对形 —— 都清不掉;卡上 `mandate: "write_protection"`,问句说它由确认这一次清掉、不由常驻 allow 规则。
276
+ 规则答不了这一类问;模式级放行与 auto 模式分类器对它照引擎自己的读法,不在本条。
277
+ — 配置根在每条车道上都在 `.sema` 行上:声明了 `SEMA_CONFIG_DIR` 时它就是交给引擎的配置目录,`.sema` 行在它及其以下全命中;缺省 `~/.sema` 与路径里带 `.sema` 段的任何目录(含沙箱车道缺省的 `<home>/.sema`)在任何车道上都命中;
278
+ 转进沙箱的 `SEMA_CONFIG_DIR` 是本服务同名 env 的原值(名单只收名),与交给引擎的配置目录是同一只。
279
+ — 两处不归这一行:引擎数据根(记忆引擎的根;壳布局 `~/.sema/engine-data`)坐在配置根下时,根里的写按根内的相对路径判、豁免于 `.sema` 行(表上别的行照判);
280
+ 部署整表替换写保护表(`WRITE_PROTECTED_TABLE_REPLACE`)去掉 `.sema` 行时,这一行随之不在。
281
+ — 读不在写保护表上(这张表只管写),第 31 条对读的说法不受本条影响。
282
+ 构造:本机车道,请求体 `settings.permissions.allow` 带 `{ "rule": "Edit(/secret/**)", "layer": "userSettings" }`,写配置根下 `secret/n.txt` ⇒ 停在一张审批卡上(`mandate: "write_protection"`),不是免问落盘。
283
+ ⑤ **第 36 条 ③**写「本部署的店集 = 盘上的(个人挂载上有店就算)」,少说了「盘上的店」是怎么来的:记忆引擎的 file 店**一打开就建目录、写根锚**,部署对象又把「目录在 / 本对象开过」算进店集 —— 所以一次**被拒**的个人层抹除(`400 config.memory_erasure_scope`,什么都没擦)、或任何一次点名个人层的只读(`GET …/memory-status?scope=user:<x>`、出处 / 清标账带层座)都会留下一只从没写过的个人店,
284
+ 此后不点名层的出处 / 清标账 / 清标请求永久答 `400 request.memory_layer`(重启照旧);7.142.0 同序列不翻(那时店集由配置点名的层推出,不读盘)。这是缺陷(被拒请求不该改变部署之后的应答),根在引擎的店集读法,本服务只能消症状、不修根,本版**不改**:
285
+ **补偿**:在请求里点名层(GET 口 `?scope=<层键>`、POST 口体 `"scope"`)照常可用;要退回「不点名层」的读法时,确认个人店目录 `<记忆根>/personal/.engine` 下**只有** `root-anchor.json` 一个文件(= 从没写过)再删掉整只 `personal/` 目录 —— 有别的文件就不是空店,别删。构造与现状读数见本版发车帖。
286
+ 7.143.0 节原文不改(已发节字节不动)。无三问(更正条)。
287
+
288
+ 12. **host 车道:执行环境的家目录主张证不了 ⇒ 环境在开跑前就不铸,run `failed` 终局带码 `env.home_unconfirmed`(同步提交腿 409),命令带不带路径都是同一首拒;worktree 的 git 基环境不再带家目录主张;更正 7.140.0 节第 12 条 ③(wire 新码;行为修复;部署零动作)**:
289
+ 旧形(7.140.0–7.143.0):host 车道(含 `run-local`)上家目录主张(`REMOTE_EXEC_HOME_DIR`,缺席时服务进程的家目录)与子进程拿到的 `HOME`(继承面 + 会话 `settings.env`)对不上 / 读不出 / 不是绝对路径时,环境照铸、门不开:
290
+ run 照常开跑、模型照常被调;模型发出的命令不带路径(`echo hi` / `ls`)⇒ 工具结果是环境的拒句(`shell_unavailable`,点名声明值与量到的 `HOME`);带路径(`cat notes.txt` / `cat ~/notes.txt`)⇒ 先撞引擎的读边界
291
+ (`read_unestablished`,「could not establish what is read」),句子不点名家目录 —— 同一根因两种首拒,后一种把人引去读边界。run 多以 `completed` 收场(模型读到拒句后自己作答)。
292
+ 新形:host 环境在构造时就判(读数是本服务组合给子进程的那份 env,铸环境时就到手),证不了 ⇒ 环境不铸 —— 工厂抛带码的拒,引擎在准备期原样承运:run `failed`,
293
+ `terminal.code` = `env.home_unconfirmed`,`terminal.message` = 判官的拒句(点名主张、量到的 `HOME` 与改法;与旧形无路径命令那一句同文)。一条命令没跑、模型一次没调、一个 token 没烧,命令带不带路径无从分别。
294
+ 同步提交腿 `POST /v1/tasks` 按零工作拒答 **409** `errorCode: "env.home_unconfirmed"`(不计费、不占提交幂等键);流式腿终帧 `done.result.terminal`、后台 run 行同码。码是本服务自铸的执行环境拒码(`env.*` 族)今天唯一的一员,契约附录 A 有行。
295
+ worktree 隔离的子代:引擎先铸树,子环境构造即拒,树随即被引擎收掉,子代以同码失败。worktree 的 git 基环境(起服铸、只跑 `git worktree add/remove/prune`、从不交给引擎)不再带家目录主张:不对证、不拒,孤儿 worktree 清扫照跑。
296
+ 远端五车道(k8s / local-docker / ssh / adb / e2b)不变:家目录读数要环境开起来才有,照旧在开环境那一拍拒、拒句落在工具结果里;引擎的读边界要先读环境才判得了的命令(递归读形 `grep -r … ~/…` 一类;adb 上连带路径的普通读)在那里先被读边界拦下(要人批 / 只读面拒),句子不点名家目录 —— 这些车道上同一根因两种首拒仍在。
297
+ **订正 7.140.0 节第 12 条 ③**(已发节原文不改):「那只环境拒起(命令面 `shell_unavailable`、文件面 `target_unavailable`、连接 `connect_failed`)」本版起读作「环境不铸,run 失败终局 `env.home_unconfirmed`(同步腿 409)」;
298
+ 「起服时铸的 worktree 基环境同样被证,对不上时孤儿 worktree 清扫不跑」本版起不成立(基环境不带主张,清扫照跑)。三条出路不变:删掉声明(或设成 `HOME` 的值),或去掉会话里的 `HOME`。
299
+ 7.141.0 节第 32 条 ③ 所述的两种首拒(`shell_unavailable` / `read_unestablished`),在 host 车道上本版起收成上面那一只;那一条说到的 adb 与其余远端车道仍是那一形(上段)。
300
+ **谁需要**:host 车道的部署与 `run-local` 用户 —— 家目录配错时第一句就点名根因(声明值 vs 量到的 `HOME`),不再被带路径命令的读边界拒引去别处;零 token 早失败。
301
+ **谁受伤**:按 run `completed` + 工具结果里的拒句(或 `shell_unavailable` 字样)认这一形的脚本与告警;同步腿上按 HTTP 200 读这一形的调用方(现为 409)。
302
+ **补偿**:按码 `env.home_unconfirmed` 分支(同步腿 `errorCode` / 终局 `terminal.code`);句子与旧形无路径命令那一句同文。
303
+ **升级前做**:无(主张与 `HOME` 一致的部署零差别)。**回滚**:回到上一版即恢复旧形;本条不写任何持久数据。
304
+
10
305
  ## 7.143.0 —— `wiring_manifest` 帧的容器段在 run 店 File 孪生按会话块账本去重(持久面;体量;回滚地板 = 本版) · env 两槽 × 目录:本地根首份管模型面目录的首次写入决定文档(K0)、`planeRefusalCode` 只答最新候选、leader 路由模型经服务表解、env cheap 槽悬空一次性 warn(配置面;行为收紧) · 🔴 部署治理的装配相容性门改在部署 MCP 服务器 / A2A 对端物化之后判:`mcp` / `a2a` 锁、合规否决 `mcp_servers` / `a2a_peers` 撞上部署自带的服务器 / 对端 ⇒ 起服拒(行为收紧,fail-closed;部署面) · 运维审批队列行带族名 `kind`、被扣的跨会话来信作 `peer_inbound` 行进审批席(wire 加性;🔴 消费方先按 `kind` 分支) · k8s 车道:停驻时沙箱从未起过的停驻,续跑改作一次新连接(空间开 ⇒ 恢复 `latest`);打包过的停驻快照对象不在 ⇒ 一行 `workspace_latest_dangling`(`lane: "park"`)+ 空目录;更正 7.142.0 节第 9 条尾的已知限制(行为修复;运维面日志加性) · 订正 7.141.0 节第 1 条的「谁受伤」:结构化 warn 只覆盖本服务写的那一行,网关密钥被拒收时引擎另说一行裸 `console.warn`(引擎已知限制),logger 接上后的那一行受 `LOG_LEVEL` 约束(文字订正;零行为变更) · 🔴 SQL 后端 `task_attachment` 加一列生成列 `seed_session_id` + 唯一索引 `uq_att_seed`:一只会话一只种子改由唯一键判,已有种子会话上的并发提交恒答 409(行为修复;DDL 升级前先加列;wire 零变化) · 续跑请求可重述对端表:四道续跑门收提交体同键的 `mcpServers` / `a2aPeers`,缺席 = 冻结读法(wire 加性;行为面;壳宜每次续跑送当前表) · 🔴 活流模型文本过同一只脱敏器:`text_delta` / `reasoning_delta` 逐块帧只放已判定的字节,拼接 = 段末帧正文 = `done.result`,段末余下的字节一帧补齐(wire 值语义;安全) · 会话读面(视图 · 记忆状态 · 记忆抹除 · 头探针 · 事件流 · 执行放置)对「文件后端上行事实没有落下、存档又读不出」的会话,从 500 `corrupt_session` 改答 404 `not_found.session`(与对非属主、对不存在的会话同一只;原故障进运维日志 `session_owner_unreadable`;行为面;应答格状态变化) · 中心 MCP 声明撞同一工具命名空间前缀:同步提交腿从 `200` + `failed` 体改 `409 config.mcp_server_name_collision`,`GET /v1/capabilities/mcp` 从无码 `500` 改同码同状态同句(wire 码与状态变;按 HTTP 状态分支的提交方看一眼) · 🔴 持久 ask 店车道上 askId 的身份含这一问展示给人的动作(工具名 + 入参摘要):同一 run 同一腿里复用调用 id、换了入参或换了工具的那一问出自己的卡(安全轴;行为收紧;不透明 `askId` 值变;零 DDL) · 🔴 `POST /v1/approvals/:sessionId/decide` 的 `boundCallId` 与 `boundInputHash` 两位必带,缺哪位 400 `decide_requires_binding` 点名哪位;不再拿当前停驻行补;`remember_requires_binding` 退役(BREAKING 行为面;安全轴;决断方回显队列行上的那一对) · 订正 7.142.0 节第 18 / 19 条的两处读数说法:坏块 / 撤块时能力位读 `no_caller_credential`(`no_origins` 是平面的第九条前提);强锚名紧贴前一枚凭据尾巴那一形在 7.142.0 上于 `GET /v1/runs/:id/events` 回放的 `tool_end` 行与活流逐块帧明文(文字订正;零行为变更;这一形本版起已修,见第 41 条) · 会话记忆同步触发口的 409 `conflict.session_memory_unobserved` 体恒带 `reason`:最近一条已结 run 的记录里没有记忆观测 ⇒ 点名它的记录里有什么、句子给出路;🔴 它配了记忆而没挂上(`memoryless`)⇒ 由 200 空报告改 409 `memory_not_mounted`;读集仍只读最近一条已结 run(wire 加性;行为面;三句拒句换形 / 新句;零 DDL;部署零动作) · 🔴 引擎 7.61.0:升级前结清在途审批、排空旧 worker,mod 包按契约 7 重建(部署面;BREAKING) · 🔴 审批卡的委派子代出处键 `sourceTaskId` 改名 `sourceSessionId`(wire BREAKING;零别名) · 通告码 `context.image_removed` 改名 `context.media_removed`、TaskOutput 退役(wire 码改名;策略名单) · 设备车道放置围栏 + 协议修订 4 `symlink_loop`(行为面;wire 加性) · SQL 后端新表 `mailbox_consumed`(起服自建) · `DB_BACKEND=local` 工具结果按 TTL 回收(行为变化) · blob 上传哈希不符一律 400、嵌入方两只店换新组形(wire 值变化;类型面 BREAKING) · 记忆同步:别的 scheme 里的 URL userinfo 也判凭据(行为收紧) · 设置导入:用户层 `/` 形路径规则留在文件里(行为收窄)、导入预览的用户层不收 `root`(wire BREAKING) · 🔴 SQL 后端 `approval_ask` 加一列 `decided_via`、决定体加性键 `decidedVia`、能力位 `approvalDecidedVia`(wire 加性;DDL 升级前先加列) · `verify:true` 任务的上限封住实现腿与各轮修复的合计,花光 ⇒ 不再修复(行为收窄;wire 加性) · 订正 7.139.0 节第 24 条 ③:没配包装的 worktree 子代仍由本服务拒(文字订正;零行为变更) · 嵌入方包 `resolveSpec` 的包装须返回同一只对象(嵌入方行为面 BREAKING) · 验证器自己停驻的那张卡改由引擎的作废动词结算、会话钉随之放掉,编排(leader)路径同样作废(行为面;修复;部署零动作;订正 7.141.0 节第 31 条的两条已知限制) · `settings.permissions.allow` 的条目也可带出处层,user 层的 `/` 形 allow 读在执行环境的配置根(wire 条目型放宽 + 能力位;端见位才发;收掉 7.141.0 节第 15 条「已知限制」的 allow 那一半) · 后台子代一个 id:面板 / 完成通知 / 孙代嵌套 / 审批归属都读注册表行 id;升级与回滚前各让停驻的后台子代结清(行为面;部署面) · Runner 之外复活的后台子代(停驻赎回 / 操作员续跑)的完成走委派树根会话的会话通知门(行为修复;wire 零新键) · 🔴 记忆同步:中心每个层分区一只化身、同步口改到 `/v2/memory/sync/:scope`、本机游标原样携带化身(引擎三处硬破坏;中心库新表起服自建;部署:两端同版 + 停驻层删游标) · 🔴 抹除与会话记忆状态答整个部署(`409 memory.erasure_store_unjudged` 与会话自助抹除体的 `scope` 退役;嵌入方类型面 BREAKING) · 🔴 规则店:引擎 7.61.0 之前从用户层设置导入的、从 `/` 写起的全局放行起服即退役(按 add;deny / ask 不动;一次性迁移 M36,每次起服幂等;持久数据面;行为收紧;部署零动作) · 本地导入载体的 deny / ask 在 prepare 当场落店、预览成员带 `outcome`,放行仍在 redeem 落;收紧写不进 ⇒ 整批 503、放行扣下(行为面;wire 加性) · 自由文本脱敏的取证读法按出处读:一枚凭据不拿自己上一轮的读数当证据、私钥收尾栅栏落在不完整读数里两读取并、SSH2 块之后紧跟的孤立收尾之前读作无头体、取证级数界 32 到顶整段遮(行为面;安全;脱敏产物可能变;运维面多一个 fail-open 标签) · 🔴 审批卡的断连重放帧与活铸帧同事实:问行卡信封加一座 `liveFacts`,断连重放的 `approval_request` 带活铸帧顶层的同一组卡外事实;本版之前铸的行重放帧带 `liveFactsUnknown: true`(安全轴;wire 加性;存形加性,零 DDL;🔴 多副本先停光旧副本再让本版接流量) · 🔴 自由文本脱敏的名字面:复合凭据名(`api_key=` 一族)在自由文本的声明形里是名字锚、名字的左界止于前一枚已认出凭据的终点(紧贴形首遍即遮、各出口同读)、不带引号的值里面的赋值照问(行为面;安全;脱敏产物变;带这些赋值的命令不再给常驻放行;部署零动作) · 运行时依赖 `@modelcontextprotocol/server` 2.4.0(npm 安装多一只包;部署零动作)
11
306
 
12
307
  1. **`DB_BACKEND=local`:run 账本里每条 run 的装配清单(`wiring_manifest` 行)按会话去重存 —— 容器段存进每会话一只块账本 `<数据根>/run-blobs/<会话>.jsonl`,行里只留引用(持久数据面:存形加性,存量不迁移;wire 与读面零变化;回滚地板 = 本版;部署零动作)**:
package/README.md CHANGED
@@ -136,6 +136,9 @@ curl -s localhost:8090/v1/tasks -H "Authorization: Bearer <SERVICE_AUTH_TOKEN>"
136
136
  `createHttpServer` requires the `authorize` seat — the only resolver of a submission's root session (the server stamps
137
137
  that root onto every spec it runs; `resolveSpec` returns no `sessionId` and reads `opts.execution.root` when it needs it).
138
138
  A single-user embedding passes `createAuthorizer(config, runner.sessions)` (package root); omitting the seat refuses at construction.
139
+ Since 7.145.0 it also requires `deploymentMods` — the very array the Runners carry as `mods` (`[]` for an embedding without mods): the server reads it to
140
+ learn whether a prompt screen runs on a leg, and on such a leg stores objective text only once the engine delivered it unchanged (two paths sit outside that: a `verify`
141
+ submission's resume input keeps the request text for its verifier, and that copy is never shown; and the leader lane's durable-worker sub-goal resume inputs, which do not go through that seat and are still stored as submitted — tracked separately); omitting it refuses at construction.
139
142
  Build-time tools (e.g. a catalog editor) read two allowlists from the package root instead of hand-copying them: `RETIRED_ENVS` (the retired-env
140
143
  tombstones) and, since 7.110.0, `CATALOG_ENTRY_HEADER_LANES` / `CATALOG_ENTRY_HEADER_NAMES` (+ type `CatalogEntryHeaderName`) — the closed allowlist of
141
144
  model-catalog entry `headers` and the API line that reads each name. Both are frozen, the very objects the server judges with.
package/README.zh-CN.md CHANGED
@@ -117,6 +117,7 @@ curl -s localhost:8090/v1/tasks -H "Authorization: Bearer <SERVICE_AUTH_TOKEN>"
117
117
  `assertExecutionLaneInvariants(config)` 是同一份判据,不做 `config.d/remote-exec.json` 覆写。
118
118
  `createHttpServer` 的 `authorize` 席是必填:它是一次提交的根会话唯一的来源(server 把这只根盖进它执行的每一只 spec;`resolveSpec`
119
119
  不返回 `sessionId`,要用根时读 `opts.execution.root`)。单用户嵌入传 `createAuthorizer(config, runner.sessions)`(包根导出);省掉即构造期拒。
120
+ 7.145.0 起它还要 `deploymentMods`:交给 Runner 当 `mods` 的同一只数组(没有 mod 传 `[]`)—— server 从它读这条腿上有没有 prompt 屏,有屏的腿只在引擎原样交付之后才存目标文本(有两处在此之外:`verify` 形提交的续跑输入为验证器留着请求原文,那一份从不展示;leader 车道 durable worker 的子目标续跑输入不经这一座,屏前原文照旧落盘 —— 另票);省掉即构造期拒。
120
121
  构建期工具(如目录编辑页)从包根取两张表、不手抄:`RETIRED_ENVS`(退役 env 墓碑)与 7.110.0 起的 `CATALOG_ENTRY_HEADER_LANES` /
121
122
  `CATALOG_ENTRY_HEADER_NAMES`(+ 型 `CatalogEntryHeaderName`)—— 模型目录条目 `headers` 的闭集白名单及读每个名字的线路。两者都冻结,就是服务端自己判据用的那一只。
122
123
  壳要知道一台在跑的引擎服务的是哪张模型表、目录采纳了没有、起服路由判官怎么说,读 `GET /v1/models` 的 `modelPlane`