@sema-agent/server 7.133.0 → 7.135.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 (526) hide show
  1. package/MIGRATION.md +221 -0
  2. package/README.md +2 -2
  3. package/README.zh-CN.md +2 -2
  4. package/USAGE.md +222 -36
  5. package/deploy/sema-up/README.md +16 -0
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +15 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +129 -0
  9. package/deploy/sema-up/chart/templates/sealed-key.yaml +24 -0
  10. package/deploy/sema-up/chart/templates/server-v4pro.yaml +14 -0
  11. package/deploy/sema-up/chart/templates/server.yaml +14 -0
  12. package/deploy/sema-up/chart/values-full-single.yaml +5 -1
  13. package/deploy/sema-up/chart/values.yaml +34 -0
  14. package/dist/adoption/plan.d.ts +1 -1
  15. package/dist/approval-ask-audit-store.d.ts +25 -25
  16. package/dist/approval-ask-machine.d.ts +2 -2
  17. package/dist/approval-card.d.ts +66 -154
  18. package/dist/approval-card.js +33 -52
  19. package/dist/approval-content-kind.d.ts +26 -6
  20. package/dist/approval-content-kind.js +23 -3
  21. package/dist/approval-deny-reasons.d.ts +1 -1
  22. package/dist/approval-gate-currency.d.ts +91 -0
  23. package/dist/approval-gate-currency.js +120 -0
  24. package/dist/approval-hmac.d.ts +7 -7
  25. package/dist/approval-policy-settlement.d.ts +2 -2
  26. package/dist/approval-reconciler.d.ts +3 -3
  27. package/dist/approval.d.ts +14 -8
  28. package/dist/approval.js +35 -16
  29. package/dist/auth-bridge.d.ts +1 -1
  30. package/dist/auto-mode-face.d.ts +4 -4
  31. package/dist/background-session-reap.d.ts +2 -2
  32. package/dist/bake-runner/main.d.ts +2 -2
  33. package/dist/bake-runner/runner.d.ts +4 -4
  34. package/dist/bench/s1/live-deps.d.ts +1 -1
  35. package/dist/bench/s1/run-firm.d.ts +1 -1
  36. package/dist/boot/coordinators.d.ts +7 -2
  37. package/dist/boot/coordinators.js +8 -5
  38. package/dist/boot/deferred-sandbox-path-env.d.ts +0 -6
  39. package/dist/boot/deferred-sandbox-path-env.js +0 -5
  40. package/dist/boot/engine-lease.d.ts +5 -5
  41. package/dist/boot/execution-env.d.ts +16 -15
  42. package/dist/boot/execution-env.js +19 -21
  43. package/dist/boot/fatal-exit.d.ts +2 -2
  44. package/dist/boot/late-binds.d.ts +1 -1
  45. package/dist/boot/leader.d.ts +2 -0
  46. package/dist/boot/leader.js +2 -1
  47. package/dist/boot/memory-boundary.d.ts +2 -2
  48. package/dist/boot/memory-consolidation.d.ts +15 -15
  49. package/dist/boot/parked-revive-gate.d.ts +3 -3
  50. package/dist/boot/parked-revive-gate.js +3 -2
  51. package/dist/boot/read-deny-anchor-audit.js +2 -2
  52. package/dist/boot/reapers.d.ts +4 -4
  53. package/dist/boot/resolve-spec.d.ts +1 -1
  54. package/dist/boot/resolve-spec.js +28 -24
  55. package/dist/boot/runner-deps.d.ts +29 -16
  56. package/dist/boot/runner-deps.js +12 -2
  57. package/dist/boot/session-faces.d.ts +3 -3
  58. package/dist/boot/session-faces.js +11 -30
  59. package/dist/boot/shutdown.d.ts +5 -5
  60. package/dist/boot/side-query-lane.d.ts +2 -2
  61. package/dist/boot/stage-05-execution-env.js +4 -4
  62. package/dist/boot/stage-06-runners.d.ts +4 -3
  63. package/dist/boot/stage-06-runners.js +15 -4
  64. package/dist/boot/stage-07-capability-layer.d.ts +2 -1
  65. package/dist/boot/stage-08-reapers.d.ts +2 -1
  66. package/dist/boot/stage-09-leader.d.ts +2 -1
  67. package/dist/boot/stage-09-leader.js +2 -2
  68. package/dist/boot/stage-10-http-server.d.ts +2 -1
  69. package/dist/boot/stage-10-http-server.js +2 -1
  70. package/dist/boot/stores.d.ts +8 -0
  71. package/dist/boot/stores.js +10 -13
  72. package/dist/boot/web-admin.d.ts +21 -15
  73. package/dist/boot/web-admin.js +16 -12
  74. package/dist/boot/workflow-orchestration.js +2 -9
  75. package/dist/brain.d.ts +11 -11
  76. package/dist/budget.d.ts +4 -4
  77. package/dist/budget.js +5 -1
  78. package/dist/caller-text-echo.d.ts +2 -0
  79. package/dist/caller-text-echo.js +2 -1
  80. package/dist/canonical-json.d.ts +2 -41
  81. package/dist/canonical-json.js +2 -13
  82. package/dist/capabilities/approvals-push.d.ts +4 -4
  83. package/dist/capabilities/builtin-tools.d.ts +5 -5
  84. package/dist/capabilities/center-plugins.d.ts +5 -5
  85. package/dist/capabilities/center-plugins.js +1 -1
  86. package/dist/capabilities/center-prompts.d.ts +1 -1
  87. package/dist/capabilities/center-wiring.d.ts +1 -1
  88. package/dist/capabilities/composite-members.d.ts +2 -2
  89. package/dist/capabilities/composite-members.js +1 -1
  90. package/dist/capabilities/execution-lane.d.ts +5 -5
  91. package/dist/capabilities/execution-lane.js +2 -2
  92. package/dist/capabilities/hands-lane.d.ts +5 -5
  93. package/dist/capabilities/mcp-probe.d.ts +10 -7
  94. package/dist/capabilities/mcp-probe.js +2 -2
  95. package/dist/capabilities/sandbox-file-send.d.ts +1 -18
  96. package/dist/capabilities/sandbox-file-send.js +0 -7
  97. package/dist/capabilities/scenarios.d.ts +28 -10
  98. package/dist/capabilities/scenarios.js +15 -5
  99. package/dist/capabilities/send-user-file-tool.d.ts +1 -1
  100. package/dist/capabilities/skills.d.ts +31 -12
  101. package/dist/capabilities/skills.js +23 -17
  102. package/dist/capabilities/tool-defer.d.ts +1 -1
  103. package/dist/capability-facts.d.ts +27 -24
  104. package/dist/capability-facts.js +18 -20
  105. package/dist/center-config-tier.d.ts +1 -1
  106. package/dist/center-credential.d.ts +4 -4
  107. package/dist/checkpoint-ctx-seal-m28.d.ts +42 -0
  108. package/dist/checkpoint-ctx-seal-m28.js +19 -0
  109. package/dist/checkpoint-identity.d.ts +5 -0
  110. package/dist/checkpoint-identity.js +14 -0
  111. package/dist/config-catalog.d.ts +12 -12
  112. package/dist/config-invariants.d.ts +4 -4
  113. package/dist/config-invariants.js +3 -2
  114. package/dist/config-lkg.d.ts +1 -1
  115. package/dist/config-provider.d.ts +13 -13
  116. package/dist/config-provider.js +2 -1
  117. package/dist/config-types.d.ts +83 -83
  118. package/dist/config.d.ts +26 -24
  119. package/dist/config.js +12 -10
  120. package/dist/cross-session-settings.d.ts +1 -1
  121. package/dist/delegated-session-owner.d.ts +16 -13
  122. package/dist/delegated-session-owner.js +9 -10
  123. package/dist/deployment-governance.d.ts +16 -16
  124. package/dist/deployment-shape.d.ts +127 -0
  125. package/dist/deployment-shape.js +72 -0
  126. package/dist/device-store.d.ts +1 -1
  127. package/dist/device-ws-hub.d.ts +1 -1
  128. package/dist/egress-redirect.d.ts +1 -1
  129. package/dist/entry-mode-clamp-notice.d.ts +2 -2
  130. package/dist/env-facts.d.ts +10 -9
  131. package/dist/env-facts.js +1 -1
  132. package/dist/env-name-allowlist-knobs.d.ts +5 -5
  133. package/dist/exec-bounds.d.ts +2 -2
  134. package/dist/execution-lane-caps.d.ts +31 -43
  135. package/dist/execution-lane-caps.js +0 -13
  136. package/dist/field-conflict.d.ts +2 -1
  137. package/dist/field-conflict.js +1 -0
  138. package/dist/file-history-capture.d.ts +9 -9
  139. package/dist/file-history-disclosure.d.ts +50 -9
  140. package/dist/file-history-disclosure.js +8 -13
  141. package/dist/fleet/drain-entry.d.ts +2 -2
  142. package/dist/fleet/fleet-bus.d.ts +26 -14
  143. package/dist/fleet/fleet-bus.js +6 -5
  144. package/dist/fleet/fleet-reconciler.d.ts +9 -9
  145. package/dist/fleet/subagent-tail-bus.d.ts +4 -4
  146. package/dist/fleet-client.d.ts +13 -13
  147. package/dist/fleet-lease.d.ts +16 -16
  148. package/dist/governance-http-status.d.ts +2 -2
  149. package/dist/hooks/hook-llm.d.ts +7 -7
  150. package/dist/hooks/hook-runner.d.ts +57 -30
  151. package/dist/hooks/hook-runner.js +38 -20
  152. package/dist/host-decision.d.ts +5 -5
  153. package/dist/host-lsp-manager.d.ts +5 -5
  154. package/dist/hosted-posture.d.ts +23 -13
  155. package/dist/hosted-posture.js +4 -9
  156. package/dist/http/admission.d.ts +2 -2
  157. package/dist/http/admission.js +28 -5
  158. package/dist/http/approval-sweeps.d.ts +1 -1
  159. package/dist/http/approval-sweeps.js +5 -2
  160. package/dist/http/checkpoint-ctx.d.ts +183 -2
  161. package/dist/http/checkpoint-ctx.js +197 -2
  162. package/dist/http/dispatch.d.ts +3 -3
  163. package/dist/http/dispatch.js +3 -3
  164. package/dist/http/durable-run-leg.js +7 -5
  165. package/dist/http/idempotency.d.ts +4 -4
  166. package/dist/http/idempotency.js +2 -2
  167. package/dist/http/mcp-dial-deadline.d.ts +7 -5
  168. package/dist/http/memory-compliance-failure-reply.d.ts +4 -4
  169. package/dist/http/owner-access.d.ts +4 -6
  170. package/dist/http/owner-access.js +1 -1
  171. package/dist/http/principal-gate.d.ts +39 -13
  172. package/dist/http/principal-gate.js +30 -6
  173. package/dist/http/readiness.d.ts +1 -1
  174. package/dist/http/refusal-body.d.ts +12 -0
  175. package/dist/http/refusal-body.js +11 -0
  176. package/dist/http/request-guards.d.ts +4 -13
  177. package/dist/http/request-guards.js +4 -17
  178. package/dist/http/resume-ctx-read.d.ts +53 -6
  179. package/dist/http/resume-ctx-read.js +26 -3
  180. package/dist/http/resume-legs.d.ts +5 -4
  181. package/dist/http/resume-legs.js +47 -29
  182. package/dist/http/route-ctx.d.ts +29 -38
  183. package/dist/http/route-table.d.ts +9 -9
  184. package/dist/http/routes/agents-roster.d.ts +1 -1
  185. package/dist/http/routes/agents-roster.js +2 -3
  186. package/dist/http/routes/approvals-assistant.d.ts +5 -5
  187. package/dist/http/routes/approvals-assistant.js +91 -17
  188. package/dist/http/routes/background.d.ts +3 -3
  189. package/dist/http/routes/background.js +2 -2
  190. package/dist/http/routes/capabilities.d.ts +1 -1
  191. package/dist/http/routes/capabilities.js +16 -8
  192. package/dist/http/routes/config-catalog.d.ts +1 -1
  193. package/dist/http/routes/devices.d.ts +1 -1
  194. package/dist/http/routes/diagnostics.d.ts +6 -6
  195. package/dist/http/routes/diagnostics.js +1 -1
  196. package/dist/http/routes/fleet.d.ts +1 -1
  197. package/dist/http/routes/fleet.js +5 -4
  198. package/dist/http/routes/mcp-reconnect.d.ts +4 -4
  199. package/dist/http/routes/mcp-reconnect.js +3 -3
  200. package/dist/http/routes/memory-consolidation.d.ts +1 -1
  201. package/dist/http/routes/memory-origin.d.ts +1 -1
  202. package/dist/http/routes/notify-wake.d.ts +1 -1
  203. package/dist/http/routes/notify-wake.js +2 -2
  204. package/dist/http/routes/rules.d.ts +1 -1
  205. package/dist/http/routes/rules.js +4 -4
  206. package/dist/http/routes/runs.js +44 -11
  207. package/dist/http/routes/session-sync.d.ts +3 -2
  208. package/dist/http/routes/session-sync.js +109 -62
  209. package/dist/http/routes/sessions-list.d.ts +1 -1
  210. package/dist/http/routes/sessions-list.js +4 -5
  211. package/dist/http/routes/sessions.js +34 -48
  212. package/dist/http/routes/tasks.d.ts +1 -1
  213. package/dist/http/routes/tasks.js +21 -16
  214. package/dist/http/routes/trace-usage.d.ts +1 -1
  215. package/dist/http/routes/trace-usage.js +7 -9
  216. package/dist/http/routes/workflows.d.ts +3 -0
  217. package/dist/http/routes/workflows.js +31 -28
  218. package/dist/http/send.d.ts +5 -5
  219. package/dist/http/server.d.ts +39 -33
  220. package/dist/http/server.js +5 -2
  221. package/dist/http/session-inherit-env.d.ts +3 -3
  222. package/dist/http/sse-lifecycle.d.ts +1 -1
  223. package/dist/http/sse-log.d.ts +2 -2
  224. package/dist/http/submit-ctx.d.ts +4 -3
  225. package/dist/http/submit-ctx.js +19 -3
  226. package/dist/http/sync-submit-body.d.ts +1 -1
  227. package/dist/http/verify-rounds.d.ts +1 -1
  228. package/dist/http/wire-types.d.ts +35 -24
  229. package/dist/index.d.ts +2 -0
  230. package/dist/index.js +1 -0
  231. package/dist/instruction-source-notice.d.ts +2 -2
  232. package/dist/key-resolver.d.ts +3 -3
  233. package/dist/lane-home-probe.d.ts +1 -1
  234. package/dist/leader/diffout.d.ts +1 -1
  235. package/dist/leader/diffup.d.ts +2 -2
  236. package/dist/leader/endpoint.d.ts +1 -1
  237. package/dist/leader/fanout.d.ts +1 -1
  238. package/dist/leader/leader.d.ts +4 -4
  239. package/dist/leader/merge.d.ts +3 -3
  240. package/dist/leader/repair-wire.d.ts +1 -1
  241. package/dist/leader/wire.d.ts +9 -5
  242. package/dist/leader/wire.js +8 -7
  243. package/dist/list-entry-display.d.ts +1 -1
  244. package/dist/lsp-evict.d.ts +1 -1
  245. package/dist/main.js +1 -1
  246. package/dist/mcp-assertion-header.d.ts +1 -1
  247. package/dist/memory-layer-legacy-lock.d.ts +1 -1
  248. package/dist/memory-operator-faces.d.ts +1 -1
  249. package/dist/memory-origin-fence.js +2 -2
  250. package/dist/memory-posture.js +4 -2
  251. package/dist/memory-project-layer.d.ts +1 -1
  252. package/dist/memory-scope.d.ts +19 -19
  253. package/dist/memory-store-refusal.d.ts +4 -4
  254. package/dist/model-compat.d.ts +1 -1
  255. package/dist/model-entry-headers.d.ts +2 -2
  256. package/dist/model-entry-refusal.d.ts +17 -17
  257. package/dist/model-provider.d.ts +10 -10
  258. package/dist/model-reach-scope.d.ts +1 -1
  259. package/dist/model-route-endpoint.d.ts +6 -6
  260. package/dist/model-route-url.d.ts +5 -5
  261. package/dist/model-select.d.ts +15 -6
  262. package/dist/model-select.js +5 -0
  263. package/dist/model-unreachable-notice.d.ts +3 -3
  264. package/dist/namespaced-rule-name.d.ts +15 -5
  265. package/dist/namespaced-rule-name.js +3 -2
  266. package/dist/observability/corrupt-read-seat.d.ts +9 -9
  267. package/dist/observability/cost-taxonomy.d.ts +1 -1
  268. package/dist/observability/err-text.d.ts +1 -1
  269. package/dist/observability/fail-open.d.ts +12 -8
  270. package/dist/observability/fail-open.js +12 -8
  271. package/dist/observability/metrics.d.ts +3 -3
  272. package/dist/observability/prompt-manifest.d.ts +19 -8
  273. package/dist/observability/prompt-manifest.js +9 -8
  274. package/dist/observability/run-terminal.d.ts +36 -36
  275. package/dist/observability/secret-env-scrub.d.ts +3 -3
  276. package/dist/observability/tool-trace.d.ts +1 -1
  277. package/dist/observability/tool-trace.js +8 -9
  278. package/dist/operator-ask.d.ts +4 -4
  279. package/dist/orchestration/workflow-agent-session-index.d.ts +3 -3
  280. package/dist/orchestration/workflow-completion-inbox.d.ts +20 -5
  281. package/dist/orchestration/workflow-completion-inbox.js +29 -7
  282. package/dist/orchestration/workflow-notify-journal.d.ts +43 -19
  283. package/dist/orchestration/workflow-notify-journal.js +17 -0
  284. package/dist/orchestration/workflow-park-decision.d.ts +1 -1
  285. package/dist/orchestration/workflow-park-decision.js +1 -0
  286. package/dist/outbound-dispatcher.d.ts +4 -4
  287. package/dist/parent-watch.d.ts +4 -4
  288. package/dist/parked-decide.d.ts +20 -20
  289. package/dist/parked-decide.js +8 -5
  290. package/dist/parked-revive-surface.d.ts +7 -7
  291. package/dist/parked-revive-surface.js +2 -3
  292. package/dist/peer-directory.d.ts +3 -3
  293. package/dist/peer-directory.js +1 -1
  294. package/dist/permission-rule-list.d.ts +10 -1
  295. package/dist/permission-rule-list.js +7 -5
  296. package/dist/permission-rule-vocab.d.ts +3 -25
  297. package/dist/permission-rule-vocab.js +0 -13
  298. package/dist/plugins/adoption-log-sql.d.ts +1 -1
  299. package/dist/plugins/approval-ask-store-file.d.ts +8 -1
  300. package/dist/plugins/approval-ask-store-file.js +6 -3
  301. package/dist/plugins/approval-ask-store-memory.d.ts +11 -7
  302. package/dist/plugins/approval-ask-store-memory.js +11 -7
  303. package/dist/plugins/approval-ask-store-sql.d.ts +34 -15
  304. package/dist/plugins/approval-ask-store-sql.js +18 -5
  305. package/dist/plugins/approval-exemption-store.d.ts +3 -3
  306. package/dist/plugins/approval-nonce-store.d.ts +3 -3
  307. package/dist/plugins/approval-payload-fingerprint.d.ts +14 -6
  308. package/dist/plugins/approval-payload-fingerprint.js +1 -1
  309. package/dist/plugins/background-agent-store-sql.d.ts +1 -1
  310. package/dist/plugins/background-shell-support.d.ts +2 -2
  311. package/dist/plugins/blob-backend.d.ts +1 -1
  312. package/dist/plugins/caching-session-store.d.ts +24 -33
  313. package/dist/plugins/caching-session-store.js +8 -19
  314. package/dist/plugins/checkpoint-index-columns.d.ts +81 -0
  315. package/dist/plugins/checkpoint-index-columns.js +62 -0
  316. package/dist/plugins/checkpoint-store-sql.d.ts +66 -67
  317. package/dist/plugins/checkpoint-store-sql.js +100 -103
  318. package/dist/plugins/device-store-sql.d.ts +7 -6
  319. package/dist/plugins/e2b-orphan-reclaim.d.ts +1 -1
  320. package/dist/plugins/ensure-schema-lock-policy.d.ts +1 -1
  321. package/dist/plugins/file-history-store-sql.d.ts +9 -7
  322. package/dist/plugins/file-history-store-sql.js +27 -15
  323. package/dist/plugins/file-run-store.d.ts +8 -8
  324. package/dist/plugins/fork-routing-session-store.d.ts +2 -2
  325. package/dist/plugins/fork-routing-session-store.js +1 -1
  326. package/dist/plugins/host-platform.d.ts +10 -10
  327. package/dist/plugins/image-bake-store-sql.d.ts +1 -1
  328. package/dist/plugins/image-index-sql.d.ts +1 -1
  329. package/dist/plugins/leader-run-store-sql.d.ts +1 -1
  330. package/dist/plugins/local-checkpoint-store.d.ts +23 -12
  331. package/dist/plugins/local-checkpoint-store.js +29 -4
  332. package/dist/plugins/local-session-store.d.ts +44 -45
  333. package/dist/plugins/local-session-store.js +42 -52
  334. package/dist/plugins/local-session-window.d.ts +12 -6
  335. package/dist/plugins/local-session-window.js +1 -17
  336. package/dist/plugins/mailbox-store-sql.d.ts +2 -2
  337. package/dist/plugins/memory-engine-pg.d.ts +1 -1
  338. package/dist/plugins/memory-run-store.d.ts +4 -4
  339. package/dist/plugins/memory-sync-store-pg.d.ts +3 -3
  340. package/dist/plugins/one-time-migrations.d.ts +76 -39
  341. package/dist/plugins/one-time-migrations.js +127 -34
  342. package/dist/plugins/outcome-ledger-sql.d.ts +1 -1
  343. package/dist/plugins/park-commit-watch.d.ts +3 -3
  344. package/dist/plugins/permission-rule-store-file.d.ts +5 -5
  345. package/dist/plugins/permission-rule-store-file.js +16 -19
  346. package/dist/plugins/permission-rule-store-sql.d.ts +38 -4
  347. package/dist/plugins/permission-rule-store-sql.js +74 -31
  348. package/dist/plugins/pg-cost-quota.d.ts +1 -1
  349. package/dist/plugins/pg-pool.d.ts +2 -2
  350. package/dist/plugins/pg-pool.js +5 -2
  351. package/dist/plugins/pg-rate-limiter.d.ts +1 -1
  352. package/dist/plugins/pg-session-storage.d.ts +9 -21
  353. package/dist/plugins/pg-session-storage.js +51 -42
  354. package/dist/plugins/remote-env-adb.d.ts +10 -10
  355. package/dist/plugins/remote-env-device.d.ts +22 -14
  356. package/dist/plugins/remote-env-device.js +28 -16
  357. package/dist/plugins/remote-env-e2b.d.ts +3 -3
  358. package/dist/plugins/remote-env-host.d.ts +16 -16
  359. package/dist/plugins/remote-env-k8s.d.ts +8 -8
  360. package/dist/plugins/remote-env-local-docker.d.ts +2 -2
  361. package/dist/plugins/remote-env-ssh.d.ts +4 -4
  362. package/dist/plugins/remote-scratchpad.d.ts +2 -3
  363. package/dist/plugins/remote-scratchpad.js +0 -4
  364. package/dist/plugins/remote-shell.d.ts +6 -6
  365. package/dist/plugins/retention-lane-store-sql.d.ts +4 -4
  366. package/dist/plugins/retention-store-sql.d.ts +4 -4
  367. package/dist/plugins/roster-store-sql.d.ts +1 -1
  368. package/dist/plugins/run-store-sql.d.ts +8 -8
  369. package/dist/plugins/schema-consistency.d.ts +2 -2
  370. package/dist/plugins/schema-ensure-legs.d.ts +3 -3
  371. package/dist/plugins/schema-indexes.d.ts +1 -1
  372. package/dist/plugins/schema-live-columns.d.ts +1 -1
  373. package/dist/plugins/session-event-payload.d.ts +4 -4
  374. package/dist/plugins/session-fork.d.ts +34 -0
  375. package/dist/plugins/session-fork.js +29 -0
  376. package/dist/plugins/session-ownership.d.ts +11 -0
  377. package/dist/plugins/session-ownership.js +11 -0
  378. package/dist/plugins/session-placement.d.ts +12 -14
  379. package/dist/plugins/session-placement.js +2 -15
  380. package/dist/plugins/session-policy-store-sql.d.ts +12 -12
  381. package/dist/plugins/session-store.d.ts +2 -2
  382. package/dist/plugins/session-store.js +2 -2
  383. package/dist/plugins/shared-memory-store-sql.d.ts +2 -2
  384. package/dist/plugins/sql-driver.d.ts +8 -8
  385. package/dist/plugins/sql-errors.d.ts +1 -1
  386. package/dist/plugins/sql-json-column.d.ts +21 -21
  387. package/dist/plugins/sql-row-helpers.d.ts +2 -2
  388. package/dist/plugins/store-backend.d.ts +17 -16
  389. package/dist/plugins/store-backend.js +3 -3
  390. package/dist/plugins/store-contracts.d.ts +21 -21
  391. package/dist/plugins/task-attachment-store.d.ts +2 -2
  392. package/dist/plugins/task-list-store-sql.d.ts +1 -1
  393. package/dist/plugins/tidb-pool.d.ts +2 -2
  394. package/dist/plugins/tidb-pool.js +9 -2
  395. package/dist/plugins/tidb-session-store.d.ts +17 -27
  396. package/dist/plugins/tidb-session-store.js +52 -42
  397. package/dist/plugins/tool-result-store-sql.d.ts +1 -1
  398. package/dist/plugins/usage-window-store-sql.d.ts +3 -3
  399. package/dist/plugins/user-input-ledger-file.d.ts +1 -1
  400. package/dist/plugins/user-input-ledger-sql.d.ts +3 -3
  401. package/dist/plugins/web-search.d.ts +19 -5
  402. package/dist/plugins/web-search.js +19 -4
  403. package/dist/{orchestration/workflow-journal-entry.d.ts → plugins/workflow-journal-payload.d.ts} +23 -32
  404. package/dist/plugins/workflow-journal-payload.js +32 -0
  405. package/dist/plugins/workflow-journal-store-sql.d.ts +28 -14
  406. package/dist/plugins/workflow-journal-store-sql.js +34 -15
  407. package/dist/plugins/workflow-run-store-sql.d.ts +4 -4
  408. package/dist/posture-source.d.ts +11 -11
  409. package/dist/principal-jwt.d.ts +6 -6
  410. package/dist/project-identity.d.ts +3 -3
  411. package/dist/project-memory.d.ts +4 -4
  412. package/dist/read-face-posture.d.ts +7 -7
  413. package/dist/request-key-closure.d.ts +1 -1
  414. package/dist/request-key-closure.js +1 -1
  415. package/dist/request-tool-axes.d.ts +12 -0
  416. package/dist/request-tool-axes.js +20 -0
  417. package/dist/request-value-closure.d.ts +15 -8
  418. package/dist/request-value-closure.js +2 -0
  419. package/dist/router/route-orchestration.d.ts +11 -16
  420. package/dist/router/route-orchestration.js +2 -12
  421. package/dist/rule-entry-list.d.ts +8 -7
  422. package/dist/rule-entry-list.js +2 -9
  423. package/dist/rules-consent.d.ts +6 -6
  424. package/dist/rules-consent.js +2 -0
  425. package/dist/run-cancel-context.d.ts +5 -5
  426. package/dist/run-local.d.ts +10 -10
  427. package/dist/run-local.js +1 -0
  428. package/dist/runs.d.ts +15 -12
  429. package/dist/runs.js +19 -4
  430. package/dist/runtime-caps-resolver.d.ts +6 -6
  431. package/dist/runtime-governance.d.ts +9 -9
  432. package/dist/sandbox-pkg-source.d.ts +9 -31
  433. package/dist/sandbox-pkg-source.js +14 -8
  434. package/dist/sealed-key.d.ts +34 -2
  435. package/dist/sealed-key.js +55 -1
  436. package/dist/security.d.ts +31 -32
  437. package/dist/security.js +12 -9
  438. package/dist/server-secret-env.d.ts +10 -10
  439. package/dist/session-children-retire.d.ts +1 -1
  440. package/dist/session-error-wire.d.ts +19 -12
  441. package/dist/session-error-wire.js +4 -1
  442. package/dist/session-incarnation.d.ts +52 -35
  443. package/dist/session-incarnation.js +23 -8
  444. package/dist/session-policy-wire.d.ts +27 -5
  445. package/dist/session-policy-wire.js +15 -1
  446. package/dist/session-records-skipped-notice.d.ts +1 -1
  447. package/dist/session-sync-kernel.d.ts +38 -11
  448. package/dist/session-sync-kernel.js +10 -0
  449. package/dist/session-sync.d.ts +49 -6
  450. package/dist/session-sync.js +52 -10
  451. package/dist/session-titler.d.ts +7 -6
  452. package/dist/session-titler.js +8 -13
  453. package/dist/session-watch.d.ts +3 -3
  454. package/dist/session-watch.js +4 -4
  455. package/dist/sighup-idle.d.ts +2 -2
  456. package/dist/spec-fields.d.ts +4 -4
  457. package/dist/sql-engine-posture.d.ts +3 -3
  458. package/dist/store-posture.d.ts +2 -2
  459. package/dist/stored-request-tool-axes-m19.d.ts +1 -1
  460. package/dist/task-a2a.d.ts +3 -1
  461. package/dist/task-a2a.js +38 -5
  462. package/dist/task-cwd.d.ts +7 -88
  463. package/dist/task-cwd.js +2 -15
  464. package/dist/task-mcp.d.ts +14 -10
  465. package/dist/task-mcp.js +39 -12
  466. package/dist/task-settings.d.ts +34 -18
  467. package/dist/task-settings.js +34 -4
  468. package/dist/task-workflow.d.ts +0 -24
  469. package/dist/task-workflow.js +2 -1
  470. package/dist/terminal.d.ts +5 -5
  471. package/dist/tighten-only-seats.d.ts +7 -6
  472. package/dist/tighten-only-seats.js +1 -1
  473. package/dist/tool-approval.d.ts +273 -228
  474. package/dist/tool-approval.js +125 -47
  475. package/dist/tool-rule-names.d.ts +7 -1
  476. package/dist/trace/core-keyset-guard.d.ts +15 -9
  477. package/dist/trace/engine-notice-wire.d.ts +5 -5
  478. package/dist/trace/engine-notice-wire.js +1 -0
  479. package/dist/trace/exit-seat.d.ts +40 -1
  480. package/dist/trace/exit-seat.js +46 -14
  481. package/dist/trace/ledger-events.d.ts +6 -4
  482. package/dist/trace/ledger-sink.d.ts +1 -1
  483. package/dist/trace/model-segment.d.ts +3 -3
  484. package/dist/trace/project.d.ts +65 -46
  485. package/dist/trace/project.js +49 -5
  486. package/dist/trace/redact.d.ts +44 -27
  487. package/dist/trace/redact.js +343 -73
  488. package/dist/trace/self-minted-wire.d.ts +39 -14
  489. package/dist/trace/self-minted-wire.js +9 -0
  490. package/dist/trace/sema-provenance.d.ts +1 -1
  491. package/dist/trace/task-notification-facets.d.ts +4 -4
  492. package/dist/trace/wire-projection-faces.d.ts +9 -3
  493. package/dist/trace/wire-projection-faces.js +7 -1
  494. package/dist/unattended-permission-mode.d.ts +5 -5
  495. package/dist/url-credential.d.ts +52 -0
  496. package/dist/url-credential.js +49 -0
  497. package/dist/url-refusal.d.ts +6 -2
  498. package/dist/url-refusal.js +8 -1
  499. package/dist/usage-analytics.d.ts +2 -2
  500. package/dist/user-input-ledger.d.ts +23 -23
  501. package/dist/web-admin-client/apply-effective.d.ts +5 -5
  502. package/dist/web-admin-client/apply-effective.js +2 -1
  503. package/dist/web-admin-client/apply-ledger.d.ts +2 -2
  504. package/dist/web-admin-client/center-request.d.ts +2 -2
  505. package/dist/web-admin-client/facade.d.ts +5 -5
  506. package/dist/web-admin-client/facade.js +1 -1
  507. package/dist/web-admin-client/hot-keys-registry.d.ts +2 -2
  508. package/dist/web-admin-client/http-client.d.ts +4 -4
  509. package/dist/web-admin-client/mcp-revocation.d.ts +1 -1
  510. package/dist/web-admin-client/pull-state.d.ts +1 -1
  511. package/dist/web-admin-client/read-face.d.ts +2 -2
  512. package/dist/web-admin-client/read-warnings.d.ts +5 -5
  513. package/dist/web-admin-client/restart-signal.d.ts +6 -6
  514. package/dist/web-admin-client/skills-mcp.d.ts +29 -4
  515. package/dist/web-admin-client/skills-mcp.js +31 -4
  516. package/dist/web-admin-client/types.d.ts +17 -10
  517. package/dist/workspace-space.d.ts +5 -3
  518. package/dist/write-protection.d.ts +2 -2
  519. package/package.json +4 -3
  520. package/scripts/drain-check-local.mjs +35 -2
  521. package/scripts/drain-check.mysql.sql +22 -2
  522. package/scripts/drain-check.pg.sql +22 -2
  523. package/skills/loop.md +1 -1
  524. package/dist/mcp-tool-faces.d.ts +0 -69
  525. package/dist/mcp-tool-faces.js +0 -104
  526. package/dist/orchestration/workflow-journal-entry.js +0 -27
package/USAGE.md CHANGED
@@ -11,7 +11,8 @@
11
11
 
12
12
  > 部署 = 把本仓跑在一台**能连到模型网关 + TiDB** 的机器上;那台机器的 `IP:8090` 就是你的 `<host>:8090`。
13
13
  > 该机器需要 **Node 22 / Bun**(路线 A,无 docker)**或** **Docker**(路线 B)——二选一。
14
- > 容器镜像自 7.128.0 起暂停发布,npm 包是唯一发布件;恢复另行通告(路线 B 用 `docker compose up --build` 就地构建,不受影响;已发布的旧镜像仍可拉,`:latest` 停在 7.128.0 之前的版本)。
14
+ > 容器镜像自 7.128.0 起不再发布,npm 包是唯一发布件;自建镜像步骤见 USAGE 9.13(路线 B 用 `docker compose up --build` 就地构建,不受影响;已发布的旧镜像仍可拉,`:latest` 停在 7.128.0 之前的版本)。
15
+ > 要自己构建引擎镜像(推私有 registry / 导入 k3s 节点 / 升到 ≥ 7.128.0):两条路径 —— 有源码仓访问权就在源码 tag 上用仓根 `Dockerfile` 构建,只有 npm 访问权就从 npm 包构建 —— 步骤见 §9.13。
15
16
 
16
17
  **路线 A — 不用 docker(单实例,最简单)**
17
18
  ```bash
@@ -407,7 +408,7 @@ MODEL_ID=<your-model-name> MODEL_CHEAP_ID=<your-cheap-model-name>
407
408
  存量中心配置里的 `roles.team` / `roles.synthesize` 由 settings-schema 的一次性迁移搬走,side query 带 `modelRole` 表外词(含 `advisor`)⇒ **400**
408
409
  `request.field_invalid`(不再回落主模型;带了 `model` 也一样拒)。要给委派子代配模型就绑 `subagent`,主任务绑 `default`。
409
410
  - 调用方可在 `objective` 里 `@<模型名>` 选模型,**只认已配置的名单**(`MODEL_ID` / `MODEL_CHEAP_ID`,或目录条目)——注入不了 `baseUrl`/`apiKey`;无 `@` → 默认模型;`@` 点中一条已发布但本部署不可用的目录条目 ⇒ 400 `request.model_unavailable`。
410
- - **`GET /v1/models`**(带 Bearer)→ `{models:[{name,id,provider,reasoning,vision,…}],default,defaultModel,droppedEntries}`,只含名字/能力、**不含密钥** —— 消费方(如 OA)拿它做 `@` 自动补全下拉的数据源;`reasoning` / `vision` 两列是**三态**:声明了给布尔,**未声明 = 键缺席**(7.131.0 起;env 部署不设 `MODEL_REASONING` / `MODEL_VISION` 就是未声明,没有 `true` 缺省 —— 需要思考的模型显式写 `MODEL_REASONING=true`,纯文本模型写 `MODEL_VISION=false`;缺席时引擎对图收、对思考档不发),契约 §A.1d;`droppedEntries`(7.123.0 起恒在场,零条 = `[]`)是本代目录里被读腿逐条丢掉的条目(下标 + 闭集原因词 + 可披露身份),契约 §A.1d。 7.126.0 起另有**可选**顶层键 `candidateRejected: { domains, at, source }`:最近一次配置候选被候选判官整拒时在场(`domains` = 判形失败的配置域名,`source` = `local` 本机 `config.d` / `remote` 中心,`at` = 判下它的时刻)—— 在场就说明这份目录是回落的那一份(整份候选没收,候选里的模型一个都不在),真因域在 `domains` 里;后来的候选被判 clean 即缺席;dry-run 姿势(web-admin 腿 compare-only)恒缺席(拒判只走日志)。**缺席不等于配置一定干净**(也可能是更早的 server)。只含域名 / 时刻 / 源形态,拒因句与文件路径只在引擎日志 `config_candidate_rejected` 里,契约 §A.1d。 7.133.0 起另有**恒在场**的顶层键 `modelPlane: { servedTable, catalog, refusalCode?, gap? }` —— 壳问 server,不猜:`servedTable`(`"env"` | `"catalog"`)= 此刻服务哪张模型表;`catalog`(`"absent"` | `"adopted"` | `"refused"`)= 最近一份目录候选在两道判官手里的结局(`refused` = 候选判官整拒,或模型面组拒;`adopted` 说的是「没有被判官整拒」,不是「最新候选已落地」,后者问 `/health` 的世代账;没有 LKG 时服务的是 env 表,有 LKG 时目录表仍在服,谁在服归 `servedTable`;逐条被拒的条目不算整拒);`refusalCode` / `gap` 是起服路由判官(`judgeServedModelRoute`)对当前 config 的判决,通过 ⇒ 两键缺席(进程起来了,正常缺席;自建装配 / 不拒启的入口可能在场),不带拒因句。只在起服后可答,没有起服前的预判口;新键追加在应答最末。契约 §A.1d。
411
+ - **`GET /v1/models`**(带 Bearer)→ `{models:[{name,id,provider,reasoning,vision,…}],default,defaultModel,droppedEntries}`,只含名字/能力、**不含密钥** —— 消费方(如 OA)拿它做 `@` 自动补全下拉的数据源;`reasoning` / `vision` 两列是**三态**:声明了给布尔,**未声明 = 键缺席**(7.131.0 起;env 部署不设 `MODEL_REASONING` / `MODEL_VISION` 就是未声明,没有 `true` 缺省 —— 需要思考的模型显式写 `MODEL_REASONING=true`,纯文本模型写 `MODEL_VISION=false`;缺席时引擎对图收、对思考档不发),契约 §A.1d;`droppedEntries`(7.123.0 起恒在场,零条 = `[]`)是本代目录里被读腿逐条丢掉的条目(下标 + 闭集原因词 + 可披露身份),契约 §A.1d。 7.126.0 起另有**可选**顶层键 `candidateRejected: { domains, at, source }`:最近一次配置候选被候选判官整拒时在场(`domains` = 判形失败的配置域名,`source` = `local` 本机 `config.d` / `remote` 中心,`at` = 判下它的时刻)—— 在场就说明这份目录是回落的那一份(整份候选没收,候选里的模型一个都不在),真因域在 `domains` 里;后来的候选被判 clean 即缺席;dry-run 姿势(web-admin 腿 compare-only)恒缺席(拒判只走日志)。**缺席不等于配置一定干净**(也可能是更早的 server)。只含域名 / 时刻 / 源形态,拒因句与文件路径只在引擎日志 `config_candidate_rejected` 里,契约 §A.1d。 7.133.0 起另有**恒在场**的顶层键 `modelPlane: { servedTable, catalog, refusalCode?, gap? }` —— 壳问 server,不猜:`servedTable`(`"env"` | `"catalog"`)= 此刻服务哪张模型表;`catalog`(`"absent"` | `"adopted"` | `"refused"`)= 最近一份目录候选在两道判官手里的结局(`refused` = 候选判官整拒,或模型面组拒;`adopted` 说的是「没有被判官整拒」,不是「最新候选已落地」,后者问 `/health` 的世代账;没有 LKG 时服务的是 env 表,有 LKG 时目录表仍在服,谁在服归 `servedTable`;逐条被拒的条目不算整拒);`refusalCode` / `gap` 是起服路由判官(`judgeServedModelRoute`)对当前 config 的判决,通过 ⇒ 两键缺席(进程起来了,正常缺席;自建装配 / 不拒启的入口可能在场),不带拒因句。只在起服后可答,没有起服前的预判口;新键追加在应答最末。契约 §A.1d。 7.135.0 起另有**恒在场**的顶层键 `aliases: [{ name, atMentionable? }]` —— `model` 被认、却不是 `models` 行名的每一个词:`default` 别名(服务表有缺省模型才在)、按部署档位绑定铸出的档位词 / CC 别名 / `best`、以及被认的上游 id 写法;成员资格由受理口的判官逐词定(服务端不写词表)。判受理一条:`model` 的值是某一行或某一别名的 `name`(大小写敏感),且那一项的 `atMentionable` 不是 `false` ⇒ 过模型门;其余 ⇒ 400(不要再拿行的 `id` 推)。`atMentionable` 与行同一只判定、同一条在场律(`atMention` 不是 `all` 才出键)。零条 = `[]`,缺席 = 更早的 server(档位词 / `default` 判「说不清」)。契约 §A.1d。
411
412
  - 不设 `MODEL_CHEAP_ID` → 所有角色 = 主模型(行为不变)。
412
413
  - `MODEL_CHEAP_ID` 写成与 `MODEL_ID` **同一个 id**(7.104.0 起)→ 那就是主模型本身:不铸 cheap 槽,所有角色 = 主模型,起服一行
413
414
  `config_env_entry_cheap_same_as_main`(同时设的其余 `MODEL_CHEAP_*` 键一并不生效)。要给同一只上游 id 第二种形(另一个价 / 思考 /
@@ -878,6 +879,13 @@ QUESTION_TTL_MS=300000
878
879
  > `streamApproval` 为真)只发 `approval_request` / `approval_complete` / `approval_revoke`,旧族 `tool_approval` / `tool_approval_complete`
879
880
  > 不再发;协议不上场的 worker 只发旧族。帧格式、消费端契约、五合取全表在
880
881
  > [`docs/ASSISTANT-WIRE-CONTRACT.md` §4a-quint](docs/ASSISTANT-WIRE-CONTRACT.md)(错误码 `feature.approval_ask_disabled` 在附录 A)。
882
+ > 🔴 **7.134.0 起卡只发给声明认得这一族的客户端**:提交体 `settings.approvalFrameFamilies: ("tool_approval" | "approval_request")[]` 声明这条 run 的客户端
883
+ > 渲染得了哪些族;一条 run 只在声明含 `GET /v1/capabilities` 顶层 `approvalFrameFamilies` 那个词时收到活卡。缺席 / 不含 ⇒ 这条 run 不呈卡(不换族、不双发)、
884
+ > 开流不重放挂着的卡,每只审批问(会话里已记住的放行照旧先兑现)当场收场,结局看这台 worker 有没有耐久店(`DURABLE_APPROVAL` 开着):在场 ⇒ 交 `UNATTENDED_APPROVAL_POLICY`:`park`(缺省)⇒ 任务停驻、`/v1/approvals/:sessionId/decide` 作答;`deny` ⇒ 当场拒,拒因句点名缺的族与出路;
885
+ > 不在场(`DURABLE_APPROVAL=false`,含 helm 图表关持久的形)⇒ 受门工具当场拒(缺省 `park` 政策下是引擎按 `approver_unavailable` 拒,结算当事方是「无人」,不是 `deny` 政策的结算,拒因句不点名缺的族与声明键;`deny` 政策下是部署政策拒)、run 跑完、无卡无 `/decide`(对 7.133.x 是有意的行为收窄:那类 worker 原本出活的 `tool_approval` 卡);两形都不出任何一个族的卡。
886
+ > 运维日志 `approver_unavailable` 的 `arm` 是 `frame_family_undeclared`。对两个族同一条(`STREAM_APPROVAL_ENABLED=false` 的 worker 呈 `tool_approval`,同样要声明)。
887
+ > 续跑读持久化的提交体(声明随体重放);耐久事件流 `GET /v1/runs/:id/events` 的开流重放只列这条 run 名下的卡,声明由卡作证(没有通道的腿一张卡都不落;7.135.0 起不读落盘的声明,run 跑完之后名下仍在窗内的卡照样重放);与同步流开流共读同一只判据函数,入参不全对称:关窗臂里「贴 deadline ⇒ `window_zero`」由 sync 腿判,事件流只按窗判。坏形(非数组 / 词表外 / 重复)⇒ `400 request.field_invalid`(`field` / `reason: "bad_entry"` / `index`)。
888
+ > 受理位 `taskSettings.approvalFrameFamilies`(恒真;老 server 对这个键 `400 request.body_shape` —— 见位才发)。读法全文在契约 §0.58。
881
889
 
882
890
  ```bash
883
891
  # 协议总开关。默认 true;显式 =false 是**本协议面**的干净还原键(不发 approval_request / approval_complete、改发旧族帧、不落 ask 行、
@@ -1210,7 +1218,7 @@ READ_DENY_PATTERNS='[{"pattern":"**/secrets/**"},{"pattern":".ssh","caseSensitiv
1210
1218
  名字文法与永不匹配的名字(退役名、无前缀短名……)的判决与 env 腿同一只判官:有这类名字 ⇒ 整请求 422。审批卡的问句是 `human approval required to run "<工具名>"`;出处串(`settings.permissions.neverAuto(<命中的工具名>)`)只在引擎闸内部消费、不上卡(部署的 `APPROVAL_NEVER_AUTO` 同样)。
1211
1219
  - **合规禁项是「拒而不是收窄」**:请求禁了某能力而任务自己带着它 ⇒ 整个任务以 `config.compliance_denied` 失败(`workflows` + `selfOrchestration`;`mcp_servers` + 任务带 MCP 服务器;`web_fetch` + 花名册挂着 `WebFetch`)。
1212
1220
  ⚠️ 单用户部署的默认工具面恒挂 `WebFetch`,请求的 `excludeTools` 补偿不了(引擎先查花名册、后卸载),所以 `web_fetch` 这个词今天只在多租户部署的请求座上可用。不需要部署配 `COMPLIANCE_PROFILE`(env 腿需要)。
1213
- - **`readDenyPatterns` 的请求侧成本界**:引擎按路径段回溯匹配,把每一颗 `*` 编成一个回溯点,每次判路径对每条模式、每个路径段各跑一遍,所以请求里**一段最多 2 颗 `*`**(每一颗都算,相邻的也逐颗算;`**` 整段、`a**b`、`id_rsa*`、`*.pem`、`*secret*` 都在内)、**整张列表合计最多 16 颗**、**最多 32 条**;超了 ⇒ 400,句子点名坐标与上限。进任务的就是写下的那一份(不改写模式)。需要更复杂或更多的行,合并成更宽的模式、改用不带星的字面形,或让运维写进 `READ_DENY_PATTERNS`(部署表不受此界)。
1221
+ - **`readDenyPatterns` 的请求侧界**:请求里**一段最多 2 颗 `*`**(每一颗都算,相邻的也逐颗算;`**` 整段、`a**b`、`id_rsa*`、`*.pem`、`*secret*` 都在内)、**整张列表合计最多 16 颗**、**最多 32 条**;超了 ⇒ 400,句子点名坐标与上限。这是请求面的受理口径(请求是不可信的写者);引擎 7.55.0 起路径段按 `*` glob 匹配,星的个数不再影响匹配代价。进任务的就是写下的那一份(不改写模式)。需要更复杂或更多的行,合并成更宽的模式、改用不带星的字面形,或让运维写进 `READ_DENY_PATTERNS`(部署表不受此界)。
1214
1222
  - **坏值不静默丢**:不是数组 / 超帽(读拒模式 32 条,其余三座 1000 条)/ 坏条目 ⇒ 400 `request.field_invalid` + `{ field, reason: "bad_entry" | "over_cap", index | count + cap }`;续跑重放存体时同判(409 `resume_blocked_by_policy`)。
1215
1223
  **能力位** `GET /v1/capabilities` → `taskSettings.tightenOnlySeats`(恒真;老 server 对这四个键 400 `request.body_shape`,见位才发)。顶层请求体的 `readDenyPatterns` 仍不受理,拒句指路 `settings.readDenyPatterns`。
1216
1224
  不设信任地板:只收紧的座位任何过了凭据门的调用方都能用(多租部署上登录令牌 scope 角色低的也一样);放宽成员(`allow`)的信任档准入照旧。
@@ -1293,14 +1301,22 @@ TASK_WRITE_FACE_ESCALATION=allow # 词表 allow|refuse;坏词启动期响亮
1293
1301
  或 `<名>/SKILL.md`(同目录的其余文件作附件)是一条。**设了 `SKILLS_DIR` 就整个替换包内出厂技能,不叠加** —— 想在出厂集上加几条,把包内 `skills/` 拷过去再加;
1294
1302
  目录不存在 = 零出厂技能(不报错)。**frontmatter 读不了的技能不装**:文件第一行是围栏 `---`(行尾只许空白 / 制表)而块没有收尾 ⇒ 这一条被拒载(一行 warn `skill_refused`,点名技能与文件,`reason: frontmatter_unclosed`),
1295
1303
  不会降成每个场景都有的全局技能;第一行不是围栏的文件没有 frontmatter,仍是全局技能。兄弟技能照装。
1296
- 2. **配置源的技能**:配了中心 = web-admin 的 skills 域;`CONFIG_PROVIDER=local` = `config.d/skills.json`(`{ "skills": [{ "name", "description", "content", "scenarios"?, "enabled"? }] }`,
1297
- 正文写在 `content` 里)。**按名盖在出厂技能上**(同名 ⇒ 配置源这条赢),`enabled: false` 的不装;两种配置源同一条路径(7.128.0 起;此前本地形整域不生效)。
1304
+ 2. **配置源的技能**:配了中心 = web-admin 的 skills 域;`CONFIG_PROVIDER=local` = `config.d/skills.json`(`{ "skills": [{ "name", "description", "content", "scenarios"?, "enabled"?, "allowedTools"?, "disallowedTools"? }] }`,
1305
+ 正文写在 `content` 里;两只工具名单 = 字符串数组,缺席 = 没有,在场 = 整只原样交给引擎:`allowedTools` 是该技能被激活的那一 run 的免问规则来源,`disallowedTools` 是拒规则来源,
1306
+ 拒侧引擎读成空的条目 ⇒ 那次激活不发生(`userInvokedSkills` 按名点用的终局 `failed`、码 `config.skill_deny_unreadable`;模型自己调 `Skill` 工具的,那一次调用被拒);中心的技能域同形)。**按名盖在出厂技能上**(同名 ⇒ 配置源这条赢),`enabled: false` 的不装;两种配置源同一条路径(7.128.0 起;此前本地形整域不生效)。
1298
1307
  起服每装上一条一行 `web_admin_skill`(`overrodeBuiltin` 说盖没盖出厂的);拿不到正文的一条一行 `web_admin_skill_failed`(`reason`:`body_absent` / `read_failed`;**正文为空串视同缺席**:`content` 缺省或写成 `""` 的条目,本地与中心同判 `body_absent`),
1299
1308
  这一条不装、同名出厂技能保留、起服照常。重启生效(与 MCP 同:改了之后 `/health` 的 `restart.reasons` 含 `skills`)。
1300
1309
  3. **插件带的技能**(plugins 域):只补**没被占的名字**,撞名让位(起服行 `center_plugins_applied` 的 `letGo`)。
1301
1310
  4. **请求体自带的技能**(`skills[]`):只补这一 run **没被占的名字** —— 与部署的技能同名的那条被丢(一行 `user_skills_dropped`),不覆盖;
1302
1311
  `disableSkills: true` ⇒ 这一 run 一只技能都不装(部署的、请求的都不装)。
1303
1312
 
1313
+ **看一个场景装着哪些技能(7.135.0 起)**:`GET /v1/capabilities/scenarios/<name>` 的 `skills` = 上面 1–3 叠出来、按这个场景过滤后的那一组(第 4 条请求自带的不在内 —— 那是调用方自己的),
1314
+ 每条 `{ name, description, source }`:`source` 是 `"factory"`(第 1 条,本部署的技能目录)或 `"center"`(第 2、3 条,配置源交来的;盖掉出厂同名的也是 `"center"`),不带正文。
1315
+ 与这个场景的 run 交给引擎的是**同一只过滤**:卡上列的就是本服务交给这一 run 的部署技能,点名(提交体 `userInvokedSkills`)用它的 `name`;没有技能 ⇒ `skills: []`。
1316
+ 两种情形卡上有、run 里没有:带 `disableSkills: true` 的那一发(一只都不装);正文超过引擎的加载上限(1 048 576 字符)的技能 —— 引擎不装它、每一 run 报一条配置错,点它的名字答 `400 config.user_invoked_skill_unknown`(缩正文或把材料挪进附件)。
1317
+ 内建 `code` 与 `default` 共用一只工厂,技能按 `default` 过滤 —— 只写了 `scenarios: code` 的技能不进内建 `code` 的 run,卡上也不列(要进,标 `default` 或不标);配置中心声明了同名场景 `code` 盖掉内建时,按它自己的名字 `code` 过滤。
1318
+ 能力位 `scenarioSkills`(恒 `true`)缺席 = 老 server,卡上没有这一键;别从 `400 config.user_invoked_skill_unknown` 的拒句里刮名字(那是引擎的散文,会变)。
1319
+
1304
1320
  **MCP 条目的工具风险轴(`toolAxes`,7.128.0 起)**
1305
1321
 
1306
1322
  `config.d/mcp.json` 的 `servers[]`(或配置中心下发的同形条目)可带 `toolAxes`,为这台 server 的**每只工具**声明风险轴;声明逐字上引擎的 `McpServerSpec.toolAxes`,喂审批门与计划模式围栏:
@@ -1640,13 +1656,13 @@ bake-runner 要用 ⇒ `LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW` 点名放回。
1640
1656
  `config_env_forwarded_multi_tenant`(`env` = 旋钮名、`entries` = 名单段数、`note` = 姿态句:这张 worker 级名单进每个租户的沙箱),
1641
1657
  不回显名单原文;单用户部署不出这一行。
1642
1658
 
1643
- **区域包源 `SANDBOX_PKG_SOURCE=custom` 的六只显式地址不得带 userinfo(7.133.0 起)**:`custom` 把 `SEMA_APT_MIRROR` / `SEMA_PIP_INDEX` / `SEMA_UV_INDEX` / `SEMA_UV_PY_MIRROR` /
1659
+ **区域包源 `SANDBOX_PKG_SOURCE=custom` 的六只显式地址不得带凭据(userinfo 7.133.0 起;凭据名参数 7.135.0 起)**:`custom` 把 `SEMA_APT_MIRROR` / `SEMA_PIP_INDEX` / `SEMA_UV_INDEX` / `SEMA_UV_PY_MIRROR` /
1644
1660
  `SEMA_NPM_REGISTRY` / `SEMA_NODE_MIRROR` **原样**写进每个 e2b VM / k8s pod 的环境(并映射到 `PIP_INDEX_URL` / `UV_*` / `NPM_CONFIG_REGISTRY` / `COREPACK_NPM_REGISTRY` /
1645
- `NVM_NODEJS_ORG_MIRROR` / `NODE_MIRROR`),沙箱里模型驱动的命令 `env` 读得到,所以**凡注入模型可见环境的 URL 不得带 userinfo**:地址带 `user:pass@`(或是判官判不了无凭据的形 ——
1661
+ `NVM_NODEJS_ORG_MIRROR` / `NODE_MIRROR`),沙箱里模型驱动的命令 `env` 读得到,所以**凡注入模型可见环境的 URL 不得带凭据**:地址带 `user:pass@`、带名字在凭据名表里的 query / fragment 参数(`?token=` · `?api_key=` · `?key=` …;7.135.0 起;表与读法见契约附录 A `request.field_invalid` 行,与请求面 MCP `transport.url` 同一只判官)(或是判官判不了无凭据的形 ——
1646
1662
  无 scheme 的 `令牌:口令@host:端口`、`file://`、无 scheme 的 `host:port`、值里带反斜杠(URL 标准把 `\` 读成 `/`,所以 `https://用户\:口令@host/…` 在判官眼里没有 userinfo,pip 一类却读得出;读法不唯一的值不收);
1647
1663
  这个座位只收层级式 http(s) 地址)⇒ **起服拒启**,拒句点名 env 名、只回显 `scheme://host[:port]`(**不回显用户名与口令**),
1648
1664
  并给两条出路:① 地址改成不带凭据的形,凭据走包管理器自己的通道 —— 上面三只沙箱名单旋钮点名一个令牌变量(点名即承担:沙箱里所有进程含模型都读得到;pod 容器 env 里它与派生值
1649
- 同名时名单赢),或把按主机记凭据的文件烤进镜像(npm 的 `.npmrc` 里 `//主机/:_authToken=…`、pip / uv / curl 的 `.netrc`;**别**写进 `pip.conf` 的 `index-url`,注入的 `PIP_INDEX_URL` 比配置文件优先);② 源不需要认证就去掉 userinfo。不剥、不改写、不静默继续。**只在 `custom` 时判**(`global` / `cn` / `none` 不注入这六只);读与判都在起服那一次,
1665
+ 同名时名单赢),或把按主机记凭据的文件烤进镜像(npm 的 `.npmrc` 里 `//主机/:_authToken=…`、pip / uv / curl 的 `.netrc`;**别**写进 `pip.conf` 的 `index-url`,注入的 `PIP_INDEX_URL` 比配置文件优先);② 源不需要认证就去掉 userinfo / 那个参数。不剥、不改写、不静默继续。**只在 `custom` 时判**(`global` / `cn` / `none` 不注入这六只);读与判都在起服那一次,
1650
1666
  车道的 env 合成处只读起服读到的配置位。请求面没有任何包源地址键(只有部署面);名单点名放行的值不受这条律管(照旧原样交出)—— 但名单点名的恰是这六只 `SEMA_*` 之一、profile 为 `custom` 时,读口照判环境里的值。
1651
1667
 
1652
1668
  **`CONFIG_REQUIRE_ROSTER=true`(3.1.0,可选,缺省关)**:远程 registry 非 dryRun 车道的 fleet worker
@@ -1663,7 +1679,7 @@ bake-runner 要用 ⇒ `LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW` 点名放回。
1663
1679
  | 头 | 什么时候必须 | 含义 |
1664
1680
  |---|---|---|
1665
1681
  | `Authorization: Bearer <SERVICE_AUTH_TOKEN>` | 设了 `SERVICE_AUTH_TOKEN` 时,除 `/health` / `/readyz` 外的所有请求 | **谁有权调本服务**(OA 后端持有,服务到服务) |
1666
- | `x-agent-principal: user:42` | 设了 `REQUIRE_PRINCIPAL=true` 时 | **代表哪个终端用户**(决定 session 归属 + 记忆隔离;**绝不从 body 取**) |
1682
+ | `x-agent-principal: user:42` | 设了 `REQUIRE_PRINCIPAL=true` 时 | **代表哪个终端用户**(决定 session 归属 + 记忆隔离;**绝不从 body 取**)。7.134.0 起也决定 fleet 面看得见什么:带了它的 service 凭据请求只看得到、动得到这位用户的(舰队流 / 列表 / 名册 / trace / 用量 / 删除 / fork / 同步);全舰队视图不带它(直连门部署上身份是签名的 principal 令牌,不是这个头) |
1667
1683
 
1668
1684
  > **dev-open 部署的主体头是过滤 / 展示用,不是隔离。** 没接任何身份来源(没配 `SERVICE_AUTH_TOKEN(S)`、没装中心鉴权桥、没开直连门 —— 即 `/health.auth.kinds` 为空)、
1669
1685
  > 也没配 `TRACE_TOKEN`、没开 `REQUIRE_PRINCIPAL` 的部署上,`x-agent-principal` 谁都能自报:
@@ -1682,7 +1698,7 @@ bake-runner 要用 ⇒ `LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW` 点名放回。
1682
1698
  > **`401 auth.unauthorized` 的 `error` 是一句出路(7.104.0 起;此前只有一个词 `unauthorized`)**,按这道门收什么分三句,码都是 `auth.unauthorized`、都**不含任何值**,
1683
1699
  > 同一道门上「没带」与「带错」逐字同一句(区分就是探测面):① 全局凭据门 —— 说「带这台部署的 service token 作 Bearer」,并指 sema-up 部署的
1684
1700
  > 令牌在 `~/.sema-up/<project>/.env` 的 `SERVICE_AUTH_TOKEN`;② 运维口(`/metrics*`、`GET /v1/tasks/source-summary`)—— 说要运维凭据
1685
- > (service token;指标口另认只读的 `METRICS_TOKEN`);③ 过了凭据门、但这一口要调用方身份(属主寻址读写、规则、记忆)—— 说要一个验过的
1701
+ > (不带主体头的 service token —— 带主体头的 service token 请求代那位主体、不是运维凭据,7.134.0 起;指标口另认只读的 `METRICS_TOKEN`,`source-summary` 另认只读的 `TRACE_TOKEN`);③ 过了凭据门、但这一口要调用方身份(属主寻址读写、规则、记忆)—— 说要一个验过的
1686
1702
  > 调用方身份,**不**叫你再去带 service token。逐字句子见 `docs/ASSISTANT-WIRE-CONTRACT.md` 附录 A.1 码表。壳(sema CLI)接 sema-up 引擎的
1687
1703
  > 令牌交法见 `deploy/sema-up/README.md`「壳接入」。
1688
1704
 
@@ -1712,6 +1728,7 @@ PostgreSQL 硬上限 ⇒ 只有缩小),运维日志一行 `submit_ctx_row_too_la
1712
1728
  | `scenario` | — | 省略时取本部署的 `DEFAULT_SCENARIO`(工厂缺省场景名 = **`code`**——CC 编码 persona 蒸馏版,default 全量工具面,终验旋钮独立;`default` 场景**已非出厂缺省**,要用它须显式传 `scenario:"default"`,或部署方显式设 `DEFAULT_SCENARIO=default`)。可选内建名:`default`(通用/助理场景,域中性 persona,CC agent loop 全量工具面)/ **`cowork`**(办公向场景,**7.133.0+**:`default` 的工具面去掉编码类工具 —— 不带 `Bash` / `Edit` / `Write` / `NotebookEdit` / `RepoMap` / `LSP` / `EnterWorktree` / `ExitWorktree` / `Monitor`,留 `Read` / `Glob` / `Grep` 文件读、浏览(WebFetch / WebSearch)与连接器挂载;role 层是 core 的 Cowork 角色基底,调用方的 `systemPrompt` 照样整替它;仍挂手,所以附件 `path` 在有执行环境的部署上照常受理;你自己请求体里的 `excludeTools` 与它取并,只会多卸)/ `code-review`(见 §5)/ `scan`(同 §5 的 repo 只读工具但**中性无框架提示词**——objective+中心下发 skill 全权主导输出,OA 扫描类用;与 `code-review` 同属 clone-free 无执行环境场景,见 §5 末)/ **配置控制面可声明任意新场景**(`{name, toolset: none\|repo-readonly, prompt?}`,组合即配置、能力写死在部署;restart-to-apply;center 可覆盖内建名,boot 日志 `config_center_scenarios.shadowsBuiltin` 可审计)。**缺省与指派都必须是本部署在册的场景名,悬空不回落 `default`**:`DEFAULT_SCENARIO` 不在册 ⇒ **起服拒**(拒句点名那个名字与在册词表);中心按主体指派的场景名本部署没有 ⇒ 该主体的 run 答 **503 `state.scenario_assignment_unknown`**(体 `detail: { scenario, source: "ruling" }`,不带 `Retry-After`;修法 = 中心改指派,或把那个场景加回本部署,然后原样重试);请求体显式给的未知名仍是 400 `scenario_unknown` |
1713
1729
  | `repo` | — | `code-review`/`scan` 必填,见 §5(7.126.0 起 `council` / `debate` / `lenses` / `rounds` / `team` / `businessContext` 是未知键 ⇒ 400:它们喂的评审团腿与 `discuss` 场景随引擎 7.49.0 删掉团队运行时一并删除) |
1714
1730
  | `systemPrompt` / `appendSystemPrompt` | — | 调用方自带的系统提示 / 追加段(各 ≤16384 字符,超限 400 `request.field_invalid`;`appendSystemPrompt` 必须非空串)—— 任务自带时优先于角色 / 全局缺省(见 §模型角色)。`systemPrompt` 是**角色层**:它整替所选角色的基底(`code-review` 场景把自己的评审员文本放在它前面),宪法、行为段、记忆段由引擎组在它之后;追加段恒排在宪法之后。逐字含引擎提示段的提示(一份已组装的提示)⇒ 400 `prompt.assembled_role_refused`(7.132.0 起) |
1731
+ | `projectMemory` | — | 7.135.0+(能力位 `projectMemory`):`"disabled"` = 这一条 run 不读部署的项目上下文 —— 引擎不调部署的项目上下文座,项目指令文件(`CLAUDE.md` / `AGENTS.md` 链)与项目层都不进上下文,这条腿的 `wiring_manifest` 答 `projectMemory: "disabled"`、本服务的 `instructions` 段缺席;引擎自己的 git 状态、记忆、技能 / hooks / MCP 不受影响,委派与后台子代随父继承。唯一的词是 `"disabled"`(缺席 = 照常读);别的值 `400 request.field_invalid`(与 `fileHistory` 同一道拼写门)。没接项目上下文座的部署照样受理(清单答 `"absent"`) |
1715
1732
  | `outputStyle` / `settings.outputStyle` | — | 输出风格**两个座位、两件事**:风格的**正文**(指南全文)走 `settings.outputStyle`(折进系统提示的追加段);**每轮一句**走顶层 `outputStyle: { name, turnReminder? }`(7.121.0+,能力位 `outputStyle`)—— 原样交引擎,引擎每个回合用自己的标记帧说「`<name> output style is active. <turnReminder>`」(`turnReminder` 缺席用引擎缺省句),流上回声 `steering_injected` `source:"output_style"`。只在非缺省风格时声明顶层键;它的值形由引擎判(`name` 非空、≤256 字;`turnReminder` 在场即非空串;不许别的键),坏值这一轮终态 `failed`、码 `config.output_style_invalid` |
1716
1733
  | `model` | — | 本次用哪个模型:只能点服务端**已配置目录**里的名字 / 档位词 / 模型 id(目录见 `GET /v1/models`;请求体带不进新模型)。未知 ⇒ 400 `request.unknown_reference`(带 `available` 列表);目录里有、但本部署服务不了 ⇒ 400 `request.model_unavailable`;空串 / 非字符串 ⇒ 400 `request.field_invalid` |
1717
1734
  | ~~tools~~ | 🚫 | **不是受理键**(传了 ⇒ 400 `request.body_shape`,`unknownKeys` 点名)——工具面走场景装配;按请求只能**减**:`allowTools`(7.126.0 起;引擎的可用性选择器,只留列出的,原样透传)/ `excludeTools` / `settings.permissions` 的 deny · ask(`allow` 7.115.0 起是 allow 规则:给出「有人表态」,回答没人表态的服务器工具 / A2A 调用;不加工具、不放掉任何一层自己的问) |
@@ -1850,12 +1867,13 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
1850
1867
  ## 7. 其它接口(按需)
1851
1868
  | 端点 | 用途 |
1852
1869
  |---|---|
1853
- | `GET /v1/sessions/<id>` | 审计回溯:当前上下文 + 摘要(owner 校验);消息里模型 / 工具产出的文本与 live 帧、账本帧同一只脱敏(密钥形换占位,其余字节不变);Read 图像 / PDF 的媒体卡(工具结果消息的 `details`)的 `file.base64` 是字节编码,逐字。**委派子代的转录**也走这一口:`<id>` = 子代帧 / fleet 子代行上的 `transcriptId`(未压缩过的子代首条用户消息是委派 prompt;子代跑过的工具是 assistant 消息里的 `toolCall` 段 + 同 `toolCallId` 的 `toolResult` 行;整段逐字条目走 `…/sync/entries`)。体顶层加性键 `agent: { id?, parentSessionId?, rootSessionId? }`(**7.133.0+**)说这是哪只子代:只投影会话行上存下来的委派元组,`id` 与 fleet 行的 `id`、`GET /v1/agents/roster` 的 `handle` 同一个串;键缺席 = 普通会话 / 老 server / 会话店不存元组(local 后端),读作「没存」、回落 fleet 行 / 名册上的 id。子代会话的属主是铸行那一刻它所在委派树的根会话的属主(**7.133.0+**,写下那一行时按当时读到的写入;此前 SQL 后端上子代会话无主、谁都读得到)⇒ 用发起子代的那位主体读;别的主体与不存在的 id 同一个 `404 not_found.session`。属主为空的委派子代行(根会话本就无主,或升级前写下、还没回填)只有 fleet 调用方读得到(出示 service 凭据、不带主体头;dev-open 部署不钉人),任何具名主体、没有 service 凭据的无身份调用方同样 404(fork / 删除对 `default` 主的存量无主会话互认、审批豁免、notify 对这些行同样不放行;fork / 删除 / `/sync/*` 把带 service 凭据的调用方读成 fleet-wide、不看主体头,这一点不变);SQL 后端每次起服回填这些行(起服读数行 `placedSessionOwnersRemaining` 非零 = 还有没定下的,再起直到为 0,或等它们下一次停驻)。推不出属主的子代写成属主 `_orphan:<id>`,只有 fleet-wide / operator 读得到:SQL 后端的子代行根会话已删时按它记录的父会话,父也删了才是 `_orphan:`;停驻时拷进宿主店的那一份(local 后端)只按根判,根会话已删 ⇒ `_orphan:`;子代被派出 / 批准之后、再次停驻读根之前根会话被删并由别人以同一 id 重新登记 ⇒ 其下的子代再次停驻被否决(读过根之后才换的,写进去的仍是读根那一刻的属主) |
1854
- | `GET /v1/approvals?owner=user:42` | 高危写审批(durable,需 `DURABLE_APPROVAL=true`):**operator** 看待办队列(可按 owner 过滤);非 operator 只看自己的 |
1870
+ | `GET /v1/sessions/<id>` | 审计回溯:当前上下文 + 摘要(owner 校验);消息里模型 / 工具产出的文本与 live 帧、账本帧同一只脱敏(密钥形换占位,其余字节不变);Read 图像 / PDF 的媒体卡(工具结果消息的 `details`)的 `file.base64` 是字节编码,逐字。**委派子代的转录**也走这一口:`<id>` = 子代帧 / fleet 子代行上的 `transcriptId`(未压缩过的子代首条用户消息是委派 prompt;子代跑过的工具是 assistant 消息里的 `toolCall` 段 + 同 `toolCallId` 的 `toolResult` 行;整段逐字条目走 `…/sync/entries`)。体顶层加性键 `agent: { id?, parentSessionId?, rootSessionId? }`(**7.133.0+**)说这是哪只子代:只投影会话行上存下来的委派元组,`id` 与 fleet 行的 `id`、`GET /v1/agents/roster` 的 `handle` 同一个串;键缺席 = 普通会话 / 老 server / 会话店不存元组(local 后端),读作「没存」、回落 fleet 行 / 名册上的 id。子代会话的属主是铸行那一刻它所在委派树的根会话的属主(**7.133.0+**,写下那一行时按当时读到的写入;此前 SQL 后端上子代会话无主、谁都读得到)⇒ 用发起子代的那位主体读;别的主体与不存在的 id 同一个 `404 not_found.session`。属主为空的委派子代行(根会话本就无主,或升级前写下、还没回填)只有 fleet 调用方读得到(出示 service 凭据、不带主体头;dev-open 部署不钉人),任何具名主体、没有 service 凭据的无身份调用方同样 404(存量无主会话互认臂 —— 单用户形下 `default` 主对无主的普通会话放行,fork / 删除 / `/sync/*`(同步族自 7.134.0 起)同走这一只 —— 对这些 placed 行同样不放行,审批豁免、notify 同样不放行;fork / 删除 / `/sync/*` 的 fleet 调用方与此处同一个判据:出示 service 凭据、不带主体头,带主体头的 service 凭据请求是那位主体,7.134.0 起);SQL 后端每次起服回填这些行(起服读数行 `placedSessionOwnersRemaining` 非零 = 还有没定下的,再起直到为 0,或等它们下一次停驻)。推不出属主的子代写成属主 `_orphan:<id>`,只有 fleet-wide / operator 读得到:SQL 后端的子代行根会话已删时按它记录的父会话,父也删了才是 `_orphan:`;停驻时拷进宿主店的那一份(local 后端)只按根判,根会话已删 ⇒ `_orphan:`;子代被派出 / 批准之后、再次停驻读根之前根会话被删并由别人以同一 id 重新登记 ⇒ 其下的子代再次停驻被否决(读过根之后才换的,写进去的仍是读根那一刻的属主) |
1871
+ | `GET /v1/approvals?owner=user:42` | 高危写审批(durable,需 `DURABLE_APPROVAL=true`):**operator** 看待办队列(可按 owner 过滤);非 operator 只看自己的。队列里某一行的存储体读不出来、重试不会好时,答 `500` + `errorCode:"approvals.read_corrupt"`(**7.134.0+**;与订阅流同码、同一只判官;运维处置那一行后再读,别原样重试);此刻读不出队列(连接 / 超时 / 店抖动)⇒ `503` + `errorCode:"approvals.read_unavailable"`(**7.135.0+**,此前 500 `internal.error`;稍后重发,这一答不表示队列为空)。`GET /v1/assistant/inbox` / `GET /v1/assistant/tasks` 读同一个队列,两种读失败同码同状态(**7.135.0+**) |
1855
1872
  | `GET /v1/approvals/stream` | 同一队列的 SSE 推送(范围同上):首拍快照 → `pending` / `resolved` 增量(开了工具审批时另有 `live_pending` / `live_resolved`),空闲时心跳,15 分钟上限(`STREAM_MAX_DURATION` 帧后重连)。**心跳只表示流活着,不表示这一拍读过队列**:队列读不出时每次读失败发一帧 `error`(`approvals.read_unavailable`,流留着、下一拍再读,恢复后同一条流继续);某一行的存储体读不出来、重试不会好时发 `approvals.read_corrupt` 并收流(运维处置那一行后再重连)。15 分钟上限对读失败的拍同样算数 |
1856
1873
  | `POST /v1/approvals/<sessionId>/decide` `{"decision":"approve"|"deny","reason":"…"}` | 批/否并恢复挂起任务(CAS,重复决议 409);**仅 operator**(非 operator → 403)。5.0.0 起旧轮询腿 `POST /v1/approvals/<id>` 已退役 |
1857
- | `GET /v1/agents/roster` | 后台 agent **名册**(7.29 起,需 durable background-agent store,否则 501 `capability.background_agent_store_required`):调用方自己 scope 的 `a…` 行,新→旧。行只带 `handle`/`name`/`agentType`/`status`/`spawnedAt`/`updatedAt`/`settledAt`(content-free;子代产物正文走 `GET /v1/runs/<id>/subagents/<handle>/output`)。查询:`?limit=`(1..100,默认 20)、`?before=`(上一页的 `nextBefore` 游标)、`?status=`(running\|parked\|completed\|failed\|killed)、`?session=`(按会话树窄化)、`?scope=`(**仅** service-token/单用户形;带 principal 的调用方锁定自己)。回体 `{agents,total,nextBefore?,truncated?}`;`truncated:true` = 租户行数超过名册窗(500),`total` 此时是窗内数。非属主的行**不出现也不计数**(无存在性 oracle) |
1858
- | `GET /v1/capabilities/scenarios/<name>` | 单个场景的只读详情:工具面、提示词概览、**本部署现在跑不跑得动**(见下) |
1874
+ | `GET /v1/tool-approvals/<approvalId>` | 按问读口(**7.133.0+**;与 `POST …/respond` 同门同身份,不是你的 ask 与查无同形 404):一只审批问此刻在哪一态,`state` ∈ `pending` / `decided` / `parked` / `void`(闭集)。停驻卡被答过 ⇒ `decided`、停驻 run 被取消 ⇒ `void`(**7.134.0+**;7.133.x 恒答 `parked`);停驻行的门已结算却读不出可用的决议(含坏行:状态词 / 种类 / 当事方不在闭集、结算记录过不了引擎的不变量筛、缺必填成员、时刻 / 方向读不出)⇒ 404 `tool_approval.not_pending`,运维日志一行 error(`defect` 首条缺陷句 · `defectCount`)。停驻行的 `decided` 可回到 `parked`:续跑腿在被批准的动作开跑前失败时,引擎重开同一张门 —— 读口答 `parked` + `decidePath` 并另带 `reopened`(**7.135.0+**):`reason` 是引擎的重开因由词(`env_failed` 按原决议经 `decidePath` 再交一次 —— 本副本还留着首次受理回执时(缺省 1 小时内)`…/respond` 回放那张回执、不驱续跑;`tool_unavailable` / `constraint_rejected` 重新决;`config_refused` 改好配置再交或重新决),`decision` / `decidedAtMs` / `decisionNote?` 是重开之前的那次决议(读不出 ⇒ 只带 `reason`);再决之后回到 `decided`。续跑被取消 ⇒ 重开的门被收掉,读作 `void`。全文见契约 §4a-bis-read |
1875
+ | `GET /v1/agents/roster` | 后台 agent **名册**(7.29 起,需 durable background-agent store,否则 501 `capability.background_agent_store_required`):调用方自己 scope 的 `a…` 行,新→旧。行只带 `handle`/`name`/`agentType`/`status`/`spawnedAt`/`updatedAt`/`settledAt`(content-free;子代产物正文走 `GET /v1/runs/<id>/subagents/<handle>/output`)。查询:`?limit=`(1..100,默认 20)、`?before=`(上一页的 `nextBefore` 游标)、`?status=`(running\|parked\|completed\|failed\|killed)、`?session=`(按会话树窄化)、`?scope=`(**仅** fleet 调用方:不带主体头的 service 凭据 / 只读 `TRACE_TOKEN`(只在没配 service 凭据的部署上够得着这一口)/ dev-open;带主体头的调用方 —— 含带 service 凭据的 —— 锁定自己)。回体 `{agents,total,nextBefore?,truncated?}`;`truncated:true` = 租户行数超过名册窗(500),`total` 此时是窗内数。非属主的行**不出现也不计数**(无存在性 oracle) |
1876
+ | `GET /v1/capabilities/scenarios/<name>` | 单个场景的只读详情:工具面、提示词概览、**本部署现在跑不跑得动**、附件供给、**技能清单**(见下) |
1859
1877
  | `GET /v1/capabilities/mcp[?scenario=<场景名>]` | **无需先跑 run 的逐台 MCP 状态**(现连、列工具、关掉;按调用方限速 + 30 秒复用)。答的是**某个场景**会挂哪些中心声明的 MCP 服务器:不带参数 = 这位主体 run 时的场景(**7.131.0+**:中心按主体指派的场景胜出,否则部署缺省场景;此前恒读部署缺省场景;指派悬空 ⇒ `503 state.scenario_assignment_unknown`,与提交任务时同一句;`GET /v1/sessions/:id/mcp` 与 `…/a2a` 两张会话面板同读这位主体 run 时的场景:a2a 面板悬空时同样整面 503,而 mcp 面板另有「这个会话上一次真挂上了什么」那一半(`lastLegMcp`),悬空时答 `200`、`lastLegMcp` 照答、`servers` 缺席、拒因在 `scenarioRefusal: { errorCode, error, detail }`(与状态面整面 503 的体是同一份成员,`detail` 是门拒的机读事实 `{ scenario, source }`;`servers` 缺席 = 场景这一半没答,`servers: []` = 该场景没配 MCP));`?scenario=<名>`(**7.130.0+**)= 点名场景,可见集与同场景任务 run 时是同一只解析、过同一只场景门 —— 不在册 `400 scenario_unknown`(附在册词表;空串 `?scenario=` 同此,与提交 `scenario: ""` 同答)、这位 principal 的场景白名单集外 `400 scenario_not_allowed`(附 allowlist),两者的体与提交任务时的拒逐字同形;重复给出参数 `400 request.field_invalid`(提交腿没有这一形)。场景门接缝 `scenarioGate` 是 `createHttpServer` 的必填件:自建 `ServiceDeps` 的嵌入方用包根导出的 `createScenarioGate` 铸它(`"peek"` 腿给读面),没递就是 tsc 红。老 server 忽略这个参数、回缺省场景那一份,按 `GET /v1/capabilities` 的 `version` 判。`REQUIRE_PRINCIPAL` 下无身份 `401`(先于场景门)。每一行(两条口同形)在 §G.7 的行形之外多两个可选键(**7.133.0+**):`toolNames`(这台会挂上的工具名,引擎命名空间形 `mcp__<server>__<tool>`,读数序)+ `toolNamesTruncated: true`(名单超过 200 只时只截表,`toolCount` 仍是真数;读数用 `toolCount`,别用 `toolNames.length`);该台读数里没有名单 ⇒ 两键缺席(不编 `[]`),没连上的台是在场的 `[]`;老 server 没有这两键,按缺席读。自带 `.mcp.json` 的探测口是 `POST /v1/capabilities/mcp/probe` |
1860
1878
  | `POST /v1/admin/drain` `{"actionId":"…","worker":"…","deadlineAt":…}` | **排空口**(7.121.0 起体 = settings-schema `DrainRequest`;operator-only —— principal 须在 `OPERATOR_PRINCIPALS` 内,或单用户部署声明了 `OPERATOR_SINGLE_USER=true`;两条出路都没有〔名单为空且没声明〕⇒ 501)。体 `{ actionId, worker, deadlineAt, scope?, expectedGeneration?, instanceId?, term? }`:`actionId` 幂等键(人手形自取,如 `manual:<uuid>`)、`worker` 本引擎的 worker 名(`SEMA_WEB_ADMIN_WORKER`)、`deadlineAt` 到期自停的 epoch ms、`scope` 本引擎的租户 scope(`FLEET_SCOPE`;不带 = 缺省 scope `global`,与没设 `FLEET_SCOPE` 的引擎相符 —— 多租引擎要带它自己的)、`expectedGeneration` fleet 成员的代际(`FLEET_GENERATION`;非成员不带)、`instanceId` 本进程身份(`GET /health` 读;不带则不比)。身份逐字段比(`worker` / `expectedGeneration` 缺席对缺席),不符 ⇒ `409 conflict.fleet_identity`(什么都不变);首次 ⇒ `200 {actionId, since, deadlineAt, state:"draining"}` 并**进入排空**(拒新提交、本副本可抢占的在飞腿当拍让出、活的审批卡改路耐久停驻、在飞归零或到期限即停);再来 ⇒ `200 … state:"already_draining"` 回显第一次的 `since` / `deadlineAt`,不重置。体坏 ⇒ `400 request.field_invalid`;`deadlineAt` 离本引擎此刻超过 `FLEET_LEASE_OUTAGE_MAX_MS`(缺省 24 h,一台实例活着而不服务的最长时长;7.122.0 起)⇒ 同码 400(什么都不变;拒句点名字段与上界的值;只在这一发会进入排空时判 —— 已在排空或硬停已在进行时任何重发都回 `already_draining`),已过的期限照收(进入即到期);嵌入宿主(无收尾链)⇒ `501 capability.drain_state_required`。没有 worker 身份的引擎(没配 `SEMA_WEB_ADMIN_WORKER`)恒 409 —— 用 SIGTERM。经本口进的排空之后,平台随后发的第一发 SIGTERM 被吸收、不缩短期限(第二发判据见「排空期的第二发信号」)。7.120.x 的 `{"reason":"…"}` 声明形与 `/health.drainReason` 已退役。 |
1861
1879
  | `GET /v1/config/catalog` | **配置目录自描述**(operator-only —— `explicitOperatorOk`:没有运维名册〔`OPERATOR_PRINCIPALS` 为空且没有单用户声明 `OPERATOR_SINGLE_USER=true`〕⇒ 501 `capability.operator_principals_required`,有名册而调用方不是运维 ⇒ 403)。逐 env 键一行:`{name, domain, type, semantics, writeLanes, effectiveLane, envHeld, envTiming, staticDefault?/derivedDefaultNote?, effectiveValue, valueClass, danger, center?{domain,path,precedence,timing,restartSlice?,managedNow,effectiveNow}}`(🔴 7.106.0 起 `center.domainExists` 删除:座位在加载期对契约 `DOMAIN_SCHEMAS` 核过域 + 路径,核不过即拒启 ⇒ 有 `center` 块 ⇔ 中心可写;readFace 四键 / `PERMISSIONS_DISABLE_AUTO_MODE` / `MODEL_DEGRADE_ON` / `_REACTIVE` 七行的座位随之删除);顶层带 `restartSlices`(重启片闭集)与 `centerDomains`(settings-schema 现行域表)。**两轴不混**:`writeLanes`=谁能写,`effectiveLane`=现在谁在生效(env-wins 族 env 占位 ⇒ center 腿 `effectiveNow:false`)。secret 类值**永不回传**(只回在场位;opaque 回在场位+长度;URL 剥 userinfo)。完备性由仓内 AST 双向对账门执法(分母=全 `src/` 生产 env 读取点)。旋钮 `CONFIG_CATALOG_ENABLED=false`(合规部署)⇒ 501 `feature.config_catalog_disabled`(路径恒挂载)+ 能力位 `configCatalog:false`。响应 `Cache-Control: no-store`。**7.57.0 起**:`enum` 行的 `effectiveValue` **恒落在该行自己的 `enumValues` 闭集内**(仓内机器门执法)——此前 `SESSION_BACKEND` 回的是**内部标签** `tidb`(自 5.0.0 起是**退役公名**,写回去 boot 拒),现归一成公名 `mysql`;`MODEL_DEFAULT_THINKING` 补上一直被解析器接受、却漏在目录闭集外的 `xhigh`,并改为回**实算值**(`off`/未设 ⇒ `null`)而不是 env 原文。 |
@@ -1876,6 +1894,10 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
1876
1894
  > **场景的附件供给(7.133.0 起)**:场景详情另带 `attachmentSupplies`(`"path"` / `"content_text"` / `"content_image"` 的数组,顶层能力位 `userAttachments.supplies` 的子集、保持席位序、键恒在场)= 这个场景在**本部署**上受理的
1877
1895
  > 请求层附件供给。`path` 读的是这一 run 的工作区,只有「场景挂手 ∧ 部署的执行车道有手」的 run 才有:`scan` / `code-review`、center 声明的场景(它们的工具集不挂手)与 `provider: "in-process"` 的部署整台,
1878
1896
  > 详情里没有 `path`,这些 run 上的 `path` 条目由引擎整条拒 `400 config.user_attachment_invalid`;`content_text` / `content_image` 与工作区无关,恒在。判据只有一只(详情与引擎的拒读同一个「这一 run 有没有工作区」)。
1897
+ >
1898
+ > **场景的技能清单(7.135.0 起)**:场景详情另带 `skills`(`{ name, description, source }` 的数组,键恒在场,没有技能是 `[]`)= 这个场景的 run 装着的部署技能 ——
1899
+ > `source: "factory"` 来自本部署的技能目录(`SKILLS_DIR`),`"center"` 来自配置源(中心 / `config.d` / 配置声明的插件)。与交给引擎的那一份同一只过滤、同序,
1900
+ > 卡上列的是本服务交给这个场景的 run 的部署技能,点名(`userInvokedSkills`)用它;`disableSkills: true` 的那一发一只都不装,正文超过引擎的加载上限的技能引擎不装(点名答 400)。请求体自带的 `skills` 不在卡上。能力位 `scenarioSkills`;来源与覆盖序见 §「技能从哪来」。
1879
1901
 
1880
1902
  > **operator 鉴权(审批队列与全部运维面,一条读法)**:`OPERATOR_PRINCIPALS=ops:alice,ops:bob`(CSV)= 谁能当 operator —— 列任意 owner 待办 + 决议(批/否)。非名单 principal 列待办只看自己的、且**不能决议**(防「请求方批自己的高危操作」跳过 F4 闸);
1881
1903
  > **名单为空 = 没有人是 operator**(每个调用方只看自己的待批 —— 不带主体的调用方看到的是匿名卡〔不带主体提交的任务停下的那几张,即决断口对它开放的那几张〕,`?owner=` 不生效;7.133.0 之前审批四个读面在名单为空时把每个调用方当 operator,那条读法已删)。
@@ -1883,6 +1905,12 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
1883
1905
  > 没配服务凭据的部署上能连上端口的都是 operator;不带主体的 operator 没有身份可记,记「谁改的」的写面(`PUT /v1/admin/memory-optout[/:principal]`)要带主体(否则 401)。
1884
1906
  > 单用户 + 名单空 + 没声明 + 有审批底座 ⇒ 起服 warn `operator_undeclared_single_user`(不拒启)。
1885
1907
  > ⚠️ **多租户形拒启**:`DURABLE_APPROVAL=true` + `REQUIRE_PRINCIPAL=true` 而 `OPERATOR_PRINCIPALS` 空 ⇒ 进程启动失败并点名修法(空名单下没人能当这台多租 worker 审批队列的 operator)。设名单,或确属单租户则不设 `REQUIRE_PRINCIPAL`。
1908
+ > 🔒 **停驻任务续跑上下文里的凭据是密封的(7.134.0 起)**:任务停驻时存下的提交体里,请求自带的凭据(`mcpServers[].transport.headers` / `.env` 的值、`a2aPeers[].headers` 的值、`settings.env` 的值、
1909
+ > `settings.webSearch.apiKey`、http hook 条目的静态头 `settings.hooks.<事件>[].hooks[].headers` 的值、command hook 条目的插件选项 `settings.hooks.<事件>[].hooks[].plugin.options` 的值〔7.135.0 起〕)只以封签落盘(对着这一域自己的保管钥匙 `<数据根>/sealed-key/checkpoint-ctx-keys/` 最新那把公钥封、
1910
+ > 绑着这一行的会话;与 sealed 模型钥匙那对钥匙不共用),续跑时开封;开不开 ⇒ `409 conflict.checkpoint_ctx_unsealable`(`field` + `reason`)。
1911
+ > URL 一类自由文本不入封签位:体里「值是 URL」的四个座位(MCP `transport.url` · A2A 对端 `url` / `cardUrl` · http 钩子 `url` · 搜索后端 `endpoint`)改由受理口拒绝带凭据的 URL(7.135.0 起,见 9.5g)。
1912
+ > 因此耐久审批在场的部署(`DURABLE_APPROVAL`;单用户 + 有耐久店时缺省开)要能建保管目录(建不了 ⇒ 起服拒;不要停驻就显式 `DURABLE_APPROVAL=false`),`<数据根>/sealed-key/` 要跨重启持久
1913
+ > (SQL 后端也一样:钥匙不进库;不持久 ⇒ 每次重启换钥匙,重启前停驻的任务续跑答 `reason:"key_not_held"`),多副本要让每个副本的 `<数据根>/sealed-key/` 是同一份(§9.10 ⑦)。升级与回滚序见 §9.10 ⑦ 与 MIGRATION 7.134.0 第 1 条。
1886
1914
  >
1887
1915
  > **部署治理三声明(7.21.0 起)**——三根都是**配置期**旋钮,「谁能改它们」≡「谁能改
1888
1916
  > 部署配置」,不引入新鉴权面;三根**都不设 = 现行为逐字不变**,坏值一律**拒启**(安全轴上的旋钮不静默失效)。
@@ -2198,7 +2226,7 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
2198
2226
  ## 8. 三类调用方怎么接
2199
2227
 
2200
2228
  **A. OA 系统(服务到服务后端)**
2201
- - OA 后端持有 `SERVICE_AUTH_TOKEN`,每个请求按当前终端用户设 `x-agent-principal: user:<id>`。
2229
+ - OA 后端持有 `SERVICE_AUTH_TOKEN`,每个请求按当前终端用户设 `x-agent-principal: user:<id>`。带了主体头的请求只看得到、动得到那位用户的(7.134.0 起 fleet 面同读);后台自己的全舰队运维视图**不带主体头**(或用只读 `TRACE_TOKEN`)。
2202
2230
  - 短问答 → `/v1/tasks`(同步);长任务/要进度条 → `/v1/runs` + `/events`(异步)。
2203
2231
  - 续聊:把上次 `sessionId` 存在 OA 会话里,下次带回。
2204
2232
 
@@ -2237,13 +2265,13 @@ curl -N http://<host>:8090/v1/tasks/stream -H 'content-type: application/json' \
2237
2265
  | HTTP `400` + `errorCode:"prompt.assembled_role_refused"`(7.132.0 起;流式 / 后台腿是 `failed` 终局带同码) | 请求的 `systemPrompt` / `appendSystemPrompt`(含 `settings.outputStyle`)逐字含引擎提示里的一段锁定文本(宪法、安全段、`# Harness` 这样的标题行)—— 一份已组装的提示。开跑前拒、零调用,句子点名字段与命中段 | 只写角色层:删掉抄进来的引擎段(引擎自己组宪法与行为段;追加段恒排在宪法之后) |
2238
2266
  | HTTP `400`(`request.field_invalid` · `config.agent.unknown_tool` · `config.tool_face_control`)· HTTP `422`(设置规则桶)· HTTP `409` `resume_blocked_by_policy` 的拒体另带 `field` + `detail`(7.133.0 起;additive,句子与码不变) | 工具名清单与设置规则里**读成空**的条目被拒时,句子仍只点名先撞上的那一张清单(前 5 条 + `; and K more`);机读位把这一遍判下来的**全部**问题一次列全:`detail.problems` 每条 `{ code, field, entry, reason }`(`code` = 这一条所在清单被拒时的码,`field` = 清单的体内坐标,`entry` = 条目的脱敏原值,`reason` = 原因词),`detail.total` = 问题总数(`problems` 至多 1000 条),顶层 `field` = 第一条问题的坐标(句子点名的那张清单),体的 `errorCode` = 第一条问题的 `code`;只有一条问题就是长度 1 的列表,不是另一种形。超帽的清单整只拒、不逐条读,不在列表里(第一处命中就是它时体只带撞帽的 `field` / `reason` / `count` / `cap`)。同步提交腿上引擎开跑前拒这两张工具名清单(`config.agent.unknown_tool` / `config.tool_face_control`:有后继的退役名、文法读不出的放行条目)的 400 体同形:句子是引擎的,只点名它先撞上的一条,`detail.problems` 是受理口对放行侧选择器清单的读数(只列与体的码同码的那一族清单,所以第一条问题的 `code` 恒等于 `errorCode`) | 按 `detail.problems` 逐条提示 / 改;不要解析句子;`total` 大于 `problems` 的条数 ⇒ 列表被截 |
2239
2267
  | HTTP `200` / `202` 应答里的 `warnings`(7.133.0 起;同步腿 200 体 · 流式腿 `meta` 帧 · 异步腿 202 回执;**有话说才在场**) | 请求的放行侧选择器清单(根 `allowTools`、子代定义的 `allowTools`)里有什么也不放的条目,而受理口没拒(放行侧只拒近似名,其余交引擎):`reason` 是引擎条目读法的原因词(`tool_name` · `grammar` · …)或 `not_in_roster`(读得出、却不在名册 —— 引擎目录 ∪ 本服务自铸工具 ∪ 本请求挂的调用方工具(主名 · 别名 · 子代工具池);协议命名空间名 `mcp__*` / `a2a__*` 懒挂载、`*` 是「不设名单」,都不判)。每条 `{ code, field, entry, reason }`,形同上一行。这不是拒:请求照常受理、照跑,引擎对这些条目的既有处置不变 | 把 `warnings` 当提示给用户看(「这几条什么也没放」);同一 `Idempotency-Key` 的重放从 run 记录答,不重判、不带;在飞合流回放的是首发那一腿铸的应答 |
2240
- | HTTP `422`(`request settings cannot be applied as written: …`)/ HTTP `400` + `errorCode:"request.field_invalid"`(7.131.0 起的读成空) | 请求体 `settings.permissions.deny` / `ask` 里的孪生与退役名 ⇒ 422、句子点名带内容的现名(`BASH(*)` ⇒ 写 `Bash(*)`);`settings.permissions.allow` 与技能 `allowedTools` 里的**近似名**(`BASH`)⇒ 400(退役名 · 内容形 · 文法读不出(带空白 / 括号不配 / 规则内容文法不成立,如 `Bash(echo $HOME)`)· 对端段通配照 7.130.0 受理,引擎通告)—— 全部读**同一张名册**(引擎目录 ∪ 本服务自铸的工具名)。运维 `APPROVAL_REQUIRE` / `APPROVAL_DENY` / `APPROVAL_NEVER_AUTO` / `APPROVAL_GRANT` 里的孪生 **拒启**,中心下发的 `governance.approvalRequire` 里的孪生整组被拒、保前值。续跑:停驻在升级前的任务,超 1000 条的清单(任一方向)与限制方向的存量孪生 `409 resume_blocked_by_policy`,放行方向的存量近似名照旧续跑 + 一行 warn `stored_allow_list_inert_resumed` | 改成句子里 `write` 后的现名(或删掉条目);超帽的合并成更宽的条目 |
2268
+ | HTTP `422`(`request settings cannot be applied as written: …`)/ HTTP `400` + `errorCode:"request.field_invalid"`(7.131.0 起的读成空) | 请求体 `settings.permissions.deny` / `ask` 里的孪生与退役名 ⇒ 422、句子点名带内容的现名(`BASH(*)` ⇒ 写 `Bash(*)`);同两桶里参数不属于该工具的规则(`WebFetch(foo:…)`、`WebSearch(domain:…)`)⇒ 422 `unsupported.param_unknown`,句子列出该工具能写的参数(7.135.0 起;此前受理、永不命中);`settings.permissions.allow` 与技能 `allowedTools` 里的**近似名**(`BASH`)⇒ 400(退役名 · 内容形 · 文法读不出(带空白 / 括号不配 / 规则内容文法不成立,如 `Bash(echo $HOME)`)· 对端段通配照 7.130.0 受理,引擎通告)—— 全部读**同一张名册**(引擎目录 ∪ 本服务自铸的工具名)。运维 `APPROVAL_REQUIRE` / `APPROVAL_DENY` / `APPROVAL_NEVER_AUTO` / `APPROVAL_GRANT` 里的孪生 **拒启**,中心下发的 `governance.approvalRequire` 里的孪生整组被拒、保前值。续跑:停驻在升级前的任务,超 1000 条的清单(任一方向)与限制方向的存量孪生 `409 resume_blocked_by_policy`,放行方向的存量近似名照旧续跑 + 一行 warn `stored_allow_list_inert_resumed` | 改成句子里 `write` 后的现名(或删掉条目);超帽的合并成更宽的条目 |
2241
2269
  | HTTP `400` + `errorCode:"request.field_invalid"` + `detail.problems[].reason:"below_trust_floor"`(7.133.0 起) | 多租部署(`REQUIRE_PRINCIPAL=true`)上调用方的信任档低于 `settings.permissions.allow`(或 `userInvokedSkills` 点用的自带技能的 `allowedTools`,`field: skills[i].allowedTools`)要的 `global`:档只由这次请求验过的凭据推 —— 部署的 service 凭据、或中心登录令牌在活动 scope 里的角色 ≥ `editor`(settings-schema 的治理写角色)⇒ `global`;角色更低 / 令牌不带角色 / 直连门 principal 令牌 / 没有验过的凭据 ⇒ `project`(`detail.callerTrust`)。`deny` / `ask` 与空 `allow` 照收;单用户部署任何调用方都是 `global` | 去掉 `allow`、开跑时答卡;请运维把规则放进 `APPROVAL_GRANT`;或请 scope 管理员把成员角色抬到 `editor` 及以上。提交前可读 `GET /v1/capabilities` 的 `settings.permissions.callerTrust` |
2242
2270
  | HTTP `429` + `errorCode:"usage.window_exhausted"` | 部署级治理窗耗尽(`USAGE_WINDOWS`,token 或 $ 天花板先满者) | 看响应体 `retryAfterSec` 退避;窗滑动/桶到期后放行 |
2243
2271
  | `terminal:{kind:"failed", code:"usage.window_exhausted"}` | 已受理的 run 在 **turn 边界**撞上治理窗且无法 durable 挂起 | 同上退避后重投;配好 checkpoint 基建则改为 `suspended` 等窗自动续跑 |
2244
2272
  | HTTP `501`(`/v1/runs`) | 内存模式不支持异步 | 配持久存储(`DB_BACKEND=mysql` / `pg` + 坐标;7.106.0 起给了坐标必须点名 `DB_BACKEND`) |
2245
- | HTTP `500` + `errorCode:"corrupt_session"`(7.104.0 起;流式口在应答头之后则是 `done` 帧的 `result.terminal.code`,后台 run 是 run 行的 `errorCode`) | 这只会话的**存档读不出**、唤不醒(文件后端:会话日志没有会话头;SQL 后端:一行事件读不出)。这一轮没跑,一个 token 没烧。直接读这只会话的口(头探针 / 会话视图 / 导出 / 分叉 / 2c 同步)同答(契约 §17) | **别重试**(确定性失败)。运维看日志 `session_repo_corrupt_read`(带文件路径与跳过行号)修或移开那份存档;要继续工作就换一个新会话 |
2246
- | 流里一帧 `engine_notice` `code:"session.records_skipped"`,`detail:{ dropped, entriesKept, sessionId }`(7.104.0 起,只在文件后端) | 这只会话的存档打开时有 `dropped` 条记录读不出、被跳过了;这一轮**照跑**,但模型读到的历史只剩 `entriesKept` 条。存档没修好之前,每次真正打开这只会话都会再说一次(会话缓存命中的轮次不打开、不说;`SESSION_CACHE_TTL_SEC=0` 时每一轮都说) | 告诉用户「这段对话的一部分历史丢了」;运维按日志 `session_repo_corrupt_read` 查那份文件。非流式 `POST /v1/tasks` 收不到通告帧(只有日志) |
2273
+ | HTTP `500` + `errorCode:"corrupt_session"`(7.104.0 起;流式口在应答头之后则是 `done` 帧的 `result.terminal.code`,后台 run 是 run 行的 `errorCode`) | 这只会话的**存档读不出**、唤不醒(文件后端:会话日志没有会话头;SQL 后端:一行事件读不出)。这一轮没跑,一个 token 没烧。直接读这只会话的口(头探针 / 会话视图 / 导出 / 分叉 / 2c 同步)同答(契约 §17) | **别重试**(确定性失败)。**文件后端**:运维看 `fail_open_total{tag="server.session-repo.corrupt-record-skipped"}` 的计数、stderr 契约行 `[sema] fail-open: server.session-repo.corrupt-record-skipped` 与随带的一条 `fail_open` warn(后两者每进程每 tag 只一次,warn 带首条明细);逐条明细(文件路径、会话 id、行号、成因)每命中一行进探针文件 —— 起服前设 `SEMA_FAILOPEN_PROBE=<文件路径>`(会话头那一行本身读不出时,它就是其中一条);修或移开那份存档。**SQL 后端**不经这只座:坏的那一行由错误句子点名(`session_event.payload` + 会话 id + 序号 `seq`)。要继续工作就换一个新会话 |
2274
+ | 流里一帧 `engine_notice` `code:"session.records_skipped"`,`detail:{ dropped, entriesKept, sessionId }`(7.104.0 起,只在文件后端) | 这只会话的存档打开时有 `dropped` 条记录读不出、被跳过了;这一轮**照跑**,但模型读到的历史只剩 `entriesKept` 条。存档没修好之前,每次真正打开这只会话都会再说一次(会话缓存命中的轮次不打开、不说;`SESSION_CACHE_TTL_SEC=0` 时每一轮都说) | 告诉用户「这段对话的一部分历史丢了」;运维按 `fail_open_total{tag="server.session-repo.corrupt-record-skipped"}` 的计数与探针文件(`SEMA_FAILOPEN_PROBE=<文件路径>`,每命中一行)里的逐条明细(文件路径、会话 id、行号、成因)查那份文件。非流式 `POST /v1/tasks` 收不到通告帧(只有运维面的计数与探针) |
2247
2275
  | 流里一帧 `engine_notice` `code:"route.finish_reason_unknown"`,`detail:{ finishReason, sessionId, runId }`(7.126.0 起) | 提供方用一个引擎读不懂的结束原因结束了这一轮:回答按模型留下的样子保留,但可能被提供方截短了 | 告诉用户「这一段回答可能不完整」;同一个词同一 run 只说一次。运维按 `finishReason` 查是哪家网关 / 模型发的 |
2248
2276
  | 流里一帧 `engine_notice` `code:"route.stream_end_ignored"`,`detail:{ statement, word, frames, sessionId, runId }`(7.126.0 起) | 提供方已经结束了这一轮,它的流却又发来了东西(又一个结束 / 一个错误 / 内容);第一个结束算数,之后的没进这一轮 | 一般无需处置;频繁出现 ⇒ 运维查那条网关的流式实现(`statement` / `word` 说的是迟到的第一帧) |
2249
2277
 
@@ -2653,7 +2681,7 @@ TOC 本地形)时被**采纳**;`REQUIRE_PRINCIPAL=true`(多租户)上一段**形
2653
2681
  |---|---|---|---|---|
2654
2682
  | `provider` | `"brave"|"tavily"|"searxng"` | **是** | 无 | 缺席、不是字符串、或不是三词之一(大小写 / 首尾空白照旧归一)——一段 `settings.webSearch` 就是在点名目的地,认不出就 400 点名 `settings.webSearch.provider`(括号里只说哪一形:`it is missing` / `it is not a string` / `it is not one of them`,**不回显**收到的串 —— 7.101.0 起),**不**静默换成部署 env 的 backend(改前:整段丢弃、回落 env backend、不报错)。词表守卫与 env 腿**同一只** `isWebSearchProvider`;env 腿词表外是「不装配」(部署自己的缺席) |
2655
2683
  | `apiKey` | string(明文) | brave/tavily 建议带(缺了首次调用才报错,见下表);searxng 不读 | 无(不继承 env 的 `WEB_SEARCH_API_KEY`);空串同缺席 | 不是字符串,或不能当 HTTP 请求头值(含换行 / NUL / 其它控制字符 / U+007F / U+00FF 以上字符等;判据 = 运行时构造并发出请求头的那条流水线,与 env `WEB_SEARCH_API_KEY` 同一只;7.118.0 起,句 `settings.webSearch.apiKey must be usable as an HTTP header value (it contains a character an HTTP header cannot carry, such as a line break)`,**不回显值**;改前采纳、首次搜索时运行时抛的错误句带着整串明文)。首尾空白(含换行)运行时会剥掉 ⇒ 照收 |
2656
- | `endpoint` | string | searxng 必需(缺了首次调用才报错);brave/tavily 可选覆盖 | 无(不继承 env 的 `WEB_SEARCH_ENDPOINT`);空串同缺席 | 不是字符串,或不是 `scheme://host[:port][/path]` 形的绝对 URL(`localhost:8888` 这类少了 `scheme://` 的也算),或带 userinfo(`user:pw@` / 只带 `user@`;7.101.0 起,句 `settings.webSearch.endpoint must not carry userinfo (user or user:password before the host)`,不回显值) |
2684
+ | `endpoint` | string | searxng 必需(缺了首次调用才报错);brave/tavily 可选覆盖 | 无(不继承 env 的 `WEB_SEARCH_ENDPOINT`);空串同缺席 | 不是字符串,或不是 `scheme://host[:port][/path]` 形的绝对 URL(`localhost:8888` 这类少了 `scheme://` 的也算),或带 userinfo(`user:pw@` / 只带 `user@`;7.101.0 起,句 `settings.webSearch.endpoint must not carry userinfo (user or user:password before the host)`,不回显值),或带凭据名表里的 query / fragment 参数(7.135.0 起,体带 `field` / `reason`;凭据走 `apiKey`,见 9.5g;部署 env 的 `WEB_SEARCH_ENDPOINT` 不判) |
2657
2685
  | `searxngParams` | `Record<string,string>`(对象)或 `"name=value;name=value"`(字符串) | 否 | 无;空串 / 空对象同缺席 | 与 env `WEB_SEARCH_SEARXNG_PARAMS` 同一套文法:数组、数字、一段不是 `name=value`、名不是参数名(字母 / 数字 / `_` / `-` / `.`)、值为空或不是字符串、同名两次(句里只报第几项 `entry #N`,不回显名或值 —— 7.101.0 起)。⚠️ **未列入已发布的 `@sema-agent/sdk` 8.8.0 `SettingsWebSearch` 类型**(该接口只有 `provider`/`apiKey`/`endpoint`/`maxResults` 四键、无开放下标)——server 侧代码认这个键,但当前发布的 TS 类型接不到它;手写 JSON 请求体仍可以发,server 会照常解析(源码头注自述:字段和消费点先落地,配置录入面尚未跟上,是一笔尚未还清的既有债务) |
2658
2686
  | `maxResults` | number | 否 | 10(与 env 同一 clamp,`[1,20]`,小数向下取整;999 夹到 20 不是形错) | 不是数,或 < 1(`"10"` 这种字符串也算) |
2659
2687
  | *(无)* `timeoutMs` | — | — | — | **per-request 车道没有这个字段**——即便部署用 `WEB_SEARCH_TIMEOUT_MS` 配了非默认超时,per-request 生效那次调用永远退回 backend 自己的默认(10000ms,下限 1000ms),因为"整段整取"意味着 env 的 `timeoutMs` 根本不在 `reqWebSearch` 那个新对象里 |
@@ -2738,6 +2766,7 @@ WebSearch 工具的 `tool_result` 错误文本,回到模型的对话里,**不是
2738
2766
  - 每个 header 值剥 CR / LF / NUL;header 名不展开。
2739
2767
  - 置空(名单外 / 凭据名)时日志一行 `hook_http_header_env_blanked`(名字与原因,不带值)。
2740
2768
  例:`"headers": { "Authorization": "Bearer ${HOOK_TOKEN}" }`、`"allowedEnvVars": ["HOOK_TOKEN"]`,并在请求 `settings.env` 里给 `HOOK_TOKEN`。7.125.x 及更早的读法不同(升级见 MIGRATION)。
2769
+ **`url` 不得带凭据(7.135.0 起)**:`http` 条目的 `url` 带 userinfo 或凭据名表里的 query / fragment 参数 ⇒ 新提交 `400 request.field_invalid`,体带 `field: "settings.hooks.<事件>[g].hooks[h].url"` 与 `reason`;凭据走同一条目的 `headers`(上面的 `$NAME` + `allowedEnvVars`)。整条规则与出路见 9.5g。
2741
2770
 
2742
2771
  ### 9.5c-bis `settings.hooks` 的执行模型与时限(7.132.0 起)
2743
2772
 
@@ -2755,6 +2784,15 @@ WebSearch 工具的 `tool_result` 错误文本,回到模型的对话里,**不是
2755
2784
  `hook_command_killed`(`event` / `type` / `killed: true` / `signal`:`SIGTERM` = 组长在宽限内就退了,`SIGKILL` = 宽限到点组长还在、升级过)。钩子确实要跑得更久:调大 `HOOKS_TIMEOUT_MS`
2756
2785
  (与条目自己的 `timeout`);要在被叫停时收尾,在命令里 `trap … TERM` 快速落盘(宽限 1 秒,不可配)。
2757
2786
 
2787
+ ### 9.5c-ter `settings.hooks` 的键:写了就要被读,否则整份新提交 400(7.135.0 起)
2788
+
2789
+ - 一只匹配组 / 一个条目上出现 hooks 读者不读的键 ⇒ 新提交(`POST /v1/tasks` · `/v1/tasks/stream` · `/v1/runs`)`400 request.body_shape`,体里 `unknownKeys` 逐个点名全坐标
2790
+ (如 `settings.hooks.PreToolUse.0.hooks.0.onFailure`),与 `settings` 子树、请求体顶层的未知键同一种拒法。读不读以读者为准:组上是 `matcher` / `hooks` / `source`,
2791
+ command 条目上是契约字段加 `plugin` / `args`,其余条目类型上是各自的契约字段(`plugin` / `args` 写在 http / prompt / agent 条目上同样被拒)。
2792
+ - 常见撞上的形:参照实现 2.1.296 新增的 `onFailure`(本服务不执行这个键 —— 7.134.x 及更早它被悄悄剥掉,写了 `"block"` 的守卫起不来时照放行)、拼错的 `timout` / `matchr`。
2793
+ 出路:删掉那个键,或改成读者读的拼法;拒体里的坐标就是要动的那一处。
2794
+ - 停驻任务续跑时不判这一条(存量请求里的这些键照旧被剥掉、其余钩子照采纳)。
2795
+
2758
2796
  ### 9.5d MCP 服务器 http 传输的身份头:`principalHeader` 与 `assertionHeader` 二选一(请求体与部署声明同一种读法)
2759
2797
 
2760
2798
  `mcpServers[].transport`(`kind:"http"`)上有两个「用哪个头送身份」的可选键,**只能设一个**:`principalHeader`(runner 把该任务已认证的终端用户 principal 注入这个头)与 `assertionHeader`(托管连接器断言所用的头**名**)。
@@ -2763,12 +2801,19 @@ WebSearch 工具的 `tool_result` 错误文本,回到模型的对话里,**不是
2763
2801
  - 本版只承载、不发送断言:声明了 `assertionHeader` 的 server 照常挂载,但不带断言头;每台这样的 server 一行 info `mcp_assertion_header_not_sent`(`server` / `note`)。探测口 `POST /v1/capabilities/mcp/probe` 对声明了该键的条目整条拒 `400 request.field_invalid`(探测不拨一份少了断言头的配置)。
2764
2802
  **发不发有一位可读**:`GET /v1/capabilities` 的 `mcpAssertionHeaderSent`(布尔,今天恒 `false`)—— 它与剥键、那行 info、探测口的那一拒读同一只开关,**互斥**:位 `false` ⇒ 三者都在(别指望断言头会发出去);位 `true` ⇒ 三者都不再出现、声明的头名随规格交给引擎。按位分支,不要匹配 info 文字;键缺席 = 老 server,按「不发送」读。
2765
2803
 
2766
- ### 9.5e 请求体 `mcpServers` 的列表与条目键:写坏,整份新提交 400(7.131.0 起;列表级与词表外的键 7.132.0 起;`startupTimeoutMs` 的值形由引擎在拨号时判,见本节首段)
2767
-
2768
- 条目的受理键 = `name` · `transport` · `allowTools` · `toolAxes` · `toolFaces` · `contentOrigin` · `elicitation` · `source` · `startupTimeoutMs`(7.132.0 起)(`transport` 的子键:`kind` · `command` · `args` · `env`(stdio),`kind` · `url` · `headers` · `principalHeader` · `assertionHeader`(http))。**新提交上每个键只有一只判官;除 `startupTimeoutMs` 外,判官在受理口,写坏的答案只有一种**(下面第一条:400)。`startupTimeoutMs`(这一只 server 自己的启动界,毫秒整数)的判官只在引擎里(引擎包根没给读口),受理口不判它的值形、原样交给引擎:数字串 / 小数 / 越界 ⇒ 请求照常 **200**,引擎拨号时**只拒这一只 server**(`config.mcp_startup_timeout_invalid`,兄弟照挂)。下面各条说的「写坏 ⇒ 400」是对其余受理键:
2769
- - **新提交**(`POST /v1/tasks` · `/v1/tasks/stream` · `/v1/runs`):键在场却判不出形 ⇒ `400 request.field_invalid`,拒句形如 `mcpServers[2].allowTools (server "crm") is not a usable declaration — must be an array of strings (omit the key to leave the server's tools unrestricted) — got a string of 4 characters. …`:点名 `mcpServers[i].<键路径>`、server 名与该键判官的原因句,**整份请求不收** —— 不挂一半、不丢声明、不默认。原因句不回显声明的值,有几处例外,回显只有一只口径(剥控制与双向字符、截到 64 字、超出加 `…`):server 名(含写坏的 `name` 值,另报送来的原长度)、`contentOrigin` 词表外的值、`toolFaces` 点名的工具名;`toolAxes` 点名的工具名在引擎写的原因句里,由引擎截长(80 字);`transport.url` 的值从不回显:它常带凭据。可选键**缺席**永远合法(真「没声明」),必填的 `name` / `transport` 缺席同样 400;在场的 `null` 不是缺席。与单用户 / 多租户无关。列表本身同一条律(7.132.0 起,先于条目判):`mcpServers` 在场却不是数组、超过 32 条(整份拒,不挂前 32 条)、某一条不是对象 ⇒ `400 request.field_invalid`,拒句点名 `mcpServers` 或 `mcpServers[i]` 与形的种类;条目层或 `transport` 层出现词表外的键 ⇒ `400 request.body_shape`,拒体带 `unknownKeys`(全路径、至多 20 条)。`mcpServers` 缺席或为 `null` = 没声明,照常受理。
2770
- - **耐久 resume 重放存量请求**:不拒(拒会把升级前 park 的任务永久卡死)。写坏的 `name` · `transport` 的 `kind`/`command`/`url` · `allowTools` · `toolAxes` · `toolFaces` ⇒ 这一条 server 整条不进,运维 warn `mcp_injection_dropped`(`reason: malformed_entry`,`field` 点名)并投用户面通告 `mcp.injection_dropped`(其中 `toolAxes` 在一次性迁移 M19 的窗开着时先按升级前读法重读一次,过了就挂,见上文 `toolAxes` 一节);写坏的 `contentOrigin` · `elicitation` · `source` · `transport` 的 `args`/`principalHeader` 与词表外的键 ⇒ 丢掉那一个键、server 照挂;`transport` 的 `env`/`headers`(名 → 串记录)对 JSON 存体按 7.131.x 的读法交:有值不是串的成员 ⇒ 整键不交,只有 `__proto__` 名的成员坏 ⇒ 剔掉它、其余照交;server 照挂,一行运维 warn `mcp_transport_members_dropped` 点名(见 9.5c-bis 同段);条目不是对象 ⇒ 这一条不进(`malformed_entry`);超过 32 条 ⇒ 第 33 条起只记 `over_cap`;整只不是数组 ⇒ 整只忽略 + 运维 warn `mcp_injection_ignored`。
2771
- - `POST /v1/capabilities/mcp/probe` 问的是新提交那**同一只判官**:上面每一形同码同句(含 `unknownKeys`),拒之前零拨号;判官受理的申报,探测口拨的就是一条任务提交会交给引擎的那一份(判官的合法归一照收)。它多出的两形:本口的体就是这份列表,`mcpServers` 缺席或为 `null` ⇒ `400 request.body_shape`(缺必需字段);声明了 `transport.assertionHeader` 的条目 ⇒ `400 request.field_invalid`(见 9.5d:本版承载、不发送,新提交照挂,探测不拨一份少了断言头的配置 —— 同一只谓词,后果按门分)。7.131.x 上本口另有一只判法(申报原文与读器产物逐字比),列表不是数组 / 条目不是对象答 `request.body_shape`。
2804
+ ### 9.5e 请求体 `mcpServers` 的列表与条目键:写坏,整份新提交 400(7.131.0 起;列表级与词表外的键 7.132.0 起;`startupTimeoutMs` 与 `toolFaces` 的引擎判官 7.134.0 起;`transport.url` 带凭据 7.135.0 起)
2805
+
2806
+ 条目的受理键 = `name` · `transport` · `allowTools` · `toolAxes` · `toolFaces` · `contentOrigin` · `elicitation` · `source` · `startupTimeoutMs`(7.132.0 起)(`transport` 的子键:`kind` · `command` · `args` · `env`(stdio),`kind` · `url` · `headers` · `principalHeader` · `assertionHeader`(http))。**新提交上每个键只有一只判官,判官在受理口,写坏的答案只有一种**(下面第一条:400)。`startupTimeoutMs`(这一只 server 自己的启动界,毫秒整数,范围与引擎 env 旋钮 `MCP_TIMEOUT` 同一段)7.134.0 起同样在受理口判 —— 判官是引擎包根导出的 `mcpStartupTimeoutMs`(启动界的唯一读者):数字串 / 小数 / 越界 / `null` ⇒ `400 request.field_invalid`,原因句是引擎的那一句(7.132.0–7.133.x:受理口不判、请求照常 200,引擎拨号时只拒这一只 server);耐久 resume 重放存量请求不判(原样交引擎,坏值在拨号时只拒这一只 server —— `config.mcp_startup_timeout_invalid`,兄弟照挂)。
2807
+ - **新提交**(`POST /v1/tasks` · `/v1/tasks/stream` · `/v1/runs`):键在场却判不出形 ⇒ `400 request.field_invalid`,拒句形如 `mcpServers[2].allowTools (server "crm") is not a usable declaration — must be an array of strings (omit the key to leave the server's tools unrestricted) — got a string of 4 characters. …`:点名 `mcpServers[i].<键路径>`、server 名与该键判官的原因句,**整份请求不收** —— 不挂一半、不丢声明、不默认。原因句不回显声明的值,有几处例外,回显只有一只口径(剥控制与双向字符、截到 64 字、超出加 `…`):server 名(含写坏的 `name` 值,另报送来的原长度)、`contentOrigin` 词表外的值;`toolAxes` / `toolFaces` 的原因句是引擎写的(7.134.0 起 `toolFaces` 的判官也是引擎包根导出的 `readToolFaces`):点名工具名(引擎截 80 字)与成员,`toolFaces` 还会点名闭词表拒的那个词,整句详情由引擎截到 240 字、本服务再剥控制与双向字符 —— 不回显显示文本、不回显合规的列表;`transport.url` 的值从不回显(带凭据的 url 被拒时,原因句只点名命中的那一段与凭据名表里的那个词)。可选键**缺席**永远合法(真「没声明」),必填的 `name` / `transport` 缺席同样 400;在场的 `null` 不是缺席。与单用户 / 多租户无关。列表本身同一条律(7.132.0 起,先于条目判):`mcpServers` 在场却不是数组、超过 32 条(整份拒,不挂前 32 条)、某一条不是对象 ⇒ `400 request.field_invalid`,拒句点名 `mcpServers` 或 `mcpServers[i]` 与形的种类;条目层或 `transport` 层出现词表外的键 ⇒ `400 request.body_shape`,拒体带 `unknownKeys`(全路径、至多 20 条)。`mcpServers` 缺席或为 `null` = 没声明,照常受理。
2808
+ - **`transport.url` 不得带凭据(7.135.0 起)**:http 传输的 `url` 带 userinfo(`https://user:pass@host/mcp`,只有用户名也算),或带名字在凭据名表里的 query / fragment 参数(`?api_key=` · `?key=` · `?token=` · `#access_token=` …;表 = 本服务日志脱敏器认作凭据名的那一张,全表见契约附录 A `request.field_invalid` 行;名字大小写不敏感,按解一次百分号编码读)⇒ 新提交 `400 request.field_invalid`,体另带 `field: "mcpServers[i].transport.url"` 与 `reason`(`url_userinfo` | `url_credential_param`),原因句点名出路:**凭据改写进 `transport.headers`**(如 `"Authorization": "Bearer …"`)。为什么:任务停驻时提交体整份进续跑上下文,`transport.headers` 的值在那里只以封签存在,`url` 照原样存(日志与读面同理)。值从不回显;解析不了的 url 不在这一问里判(拨号时失败)。7.134.x 及以前照收、原样落停驻上下文;带 userinfo 的 url 本就连不上(fetch 对带凭据的 URL 构造即抛),带名表参数的升级后要改。同一条规则在 A2A 对端 / http 钩子 / 搜索后端上的三座见 9.5g。
2809
+ - **耐久 resume 重放存量请求**:不拒(拒会把升级前 park 的任务永久卡死;`transport.url` 带凭据的存量条目照挂、url 逐字交引擎)。写坏的 `name` · `transport` 的 `kind`/`command`/`url` · `allowTools` · `toolAxes` · `toolFaces` ⇒ 这一条 server 整条不进,运维 warn `mcp_injection_dropped`(`reason: malformed_entry`,`field` 点名)并投用户面通告 `mcp.injection_dropped`(其中 `toolAxes` 在一次性迁移 M19 的窗开着时先按升级前读法重读一次,过了就挂,见上文 `toolAxes` 一节);写坏的 `contentOrigin` · `elicitation` · `source` · `transport` 的 `args`/`principalHeader` 与词表外的键 ⇒ 丢掉那一个键、server 照挂;`transport` 的 `env`/`headers`(名 → 串记录)对 JSON 存体按 7.131.x 的读法交:有值不是串的成员 ⇒ 整键不交,只有 `__proto__` 名的成员坏 ⇒ 剔掉它、其余照交;server 照挂,一行运维 warn `mcp_transport_members_dropped` 点名(见 9.5c-bis 同段);条目不是对象 ⇒ 这一条不进(`malformed_entry`);超过 32 条 ⇒ 第 33 条起只记 `over_cap`;整只不是数组 ⇒ 整只忽略 + 运维 warn `mcp_injection_ignored`。
2810
+ - `POST /v1/capabilities/mcp/probe` 问的是新提交那**同一只判官**:上面每一形同码同句(含 `unknownKeys`,与 url 带凭据那一形的 `field` / `reason`),拒之前零拨号;判官受理的申报,探测口拨的就是一条任务提交会交给引擎的那一份(判官的合法归一照收)。它多出的两形:本口的体就是这份列表,`mcpServers` 缺席或为 `null` ⇒ `400 request.body_shape`(缺必需字段);声明了 `transport.assertionHeader` 的条目 ⇒ `400 request.field_invalid`(见 9.5d:本版承载、不发送,新提交照挂,探测不拨一份少了断言头的配置 —— 同一只谓词,后果按门分)。7.131.x 上本口另有一只判法(申报原文与读器产物逐字比),列表不是数组 / 条目不是对象答 `request.body_shape`。
2811
+ - **`toolFaces` 的判官是引擎的 `readToolFaces`(7.134.0 起;此前本服务自带一只只判 JSON 形的读器)**:它在门口就判声明本身能说的一切 —— 成员与类型、五张闭词表、上界、跨成员律 ——
2812
+ 所以下面几形 7.133.x 受理、7.134.0 起 400(重放腿整条 server 不进、中心 / `config.d` 腿跳过该 server 并点名 warn):空工具名;保留审批卡(`renderHints.approvalCard: "question"` / `"plan"`);
2813
+ 🔴 **`pathTarget.access` 是闭集 `read` / `create` / `edit`** —— 写成 `"write"`(或任何别的词)整条拒;**`pathTarget.base: "root"` 要求 `access: "read"`**(写面落根基底整条拒);
2814
+ `patternParam` 只在 `absent: "base"` 旁有意义,单独写是一份读不到的声明(inert)、同样整条拒;未知成员(笔误)、安全轴写成面成员(`effect` 属于 `toolAxes`)、非布尔旗、错型成员。
2815
+ 部署腿(中心 / `config.d`)的坏声明若绕过本服务直接到引擎,引擎在准备门**整任务**拒(`config.tool_face_invalid`)—— 一处笔误整任务起不来,写之前对一下这三条。
2816
+ 要看物化 schema 才判得了的那一半(`param` 是不是工具的顶层参数、审批卡要的键在不在)与 `resultCards` 落在别的命名空间,仍由引擎在列举处**按工具**判(那一只工具不挂,通告 `config.tool_face_invalid`,兄弟照挂)。
2772
2817
  - 7.130.x 及更早:`allowTools` / `toolFaces` / `name` / `transport` 写坏 ⇒ 200 + 这条 server 不挂;`elicitation` / `source` / `transport` 的可选子键写坏 ⇒ 200 + 悄悄丢键。7.131.x 及更早:列表整只不是数组 ⇒ 200、整只忽略;条目不是对象 ⇒ 200 + 点名丢弃;超过 32 条 ⇒ 200、挂前 32 条;词表外的键 ⇒ 悄悄不读。升级后这些请求变 400:改对那个键(或删掉它)、把列表改成数组、删掉第 33 条起的条目。
2773
2818
 
2774
2819
  ### 9.5f 中心提示层:一种 wire 形、按场景挂段、品牌行与「无持久记忆」披露(7.132.0 起)
@@ -2789,6 +2834,24 @@ WebSearch 工具的 `tool_result` 错误文本,回到模型的对话里,**不是
2789
2834
  - **「本会话没有持久记忆」**:引擎判、引擎渲染(记忆面没挂 ∧ 名册不能持久 ∧ 不是委派子代)。本部署有引擎推断看不见的持久通道(MCP 记忆服务器、自定义写工具)⇒ `MEMORY_PERSISTENCE_CAPABLE=true`
2790
2835
  撤回这段披露;host 车道自动声明。
2791
2836
 
2837
+ ### 9.5g 请求体里的 URL 不得带凭据:MCP 传输 · A2A 对端 · http 钩子 · 搜索后端(7.135.0 起,新提交 400)
2838
+
2839
+ 任务停驻时提交体整份进续跑上下文,请求自带的凭据位(`mcpServers[i].transport.headers` · `a2aPeers[i].headers` · `settings.hooks.<事件>[g].hooks[h].headers` · `settings.webSearch.apiKey`)在那里只以封签存在;
2840
+ 而「值是 URL」的字段不在封签位里 —— URL 里的凭据会原样落库 / 落盘(日志与读面同理)。所以同一条规则落在四个座位上,**一只判官、一个拒形**:
2841
+
2842
+ | 座位(体内坐标) | 凭据该写在哪(已封签的位) |
2843
+ |---|---|
2844
+ | `mcpServers[i].transport.url`(http 传输) | 同条目的 `transport.headers` |
2845
+ | `a2aPeers[i].url` · `a2aPeers[i].cardUrl` | 同对端的 `headers` |
2846
+ | `settings.hooks.<事件>[g].hooks[h].url`(`type:"http"` 条目) | 同条目的 `headers`(`$NAME` + `allowedEnvVars`,配置本身不带密钥值,见 9.5c) |
2847
+ | `settings.webSearch.endpoint` | 同段的 `apiKey`(brave / tavily 发成请求头;searxng 腿不发鉴权头,要凭据的实例在部署面声明 `WEB_SEARCH_ENDPOINT`) |
2848
+
2849
+ - **判据**:URL 带 userinfo(`https://user:pass@host/…`,只有用户名也算),或带名字在凭据名表里的 query / fragment 参数(`?api_key=` · `?key=` · `?token=` · `#access_token=` …;表 = 本服务日志脱敏器认作凭据名的那一张,全表见契约附录 A `request.field_invalid` 行;名字大小写不敏感,解一次百分号编码读,整名相等)。
2850
+ - **答案**:新提交(`POST /v1/tasks` · `/v1/tasks/stream` · `/v1/runs`)`400 request.field_invalid`,体另带 `field`(上表的体内全坐标)与 `reason`(`url_userinfo` | `url_credential_param`);句子点名坐标、命中的那一段与表里的词,**不回显 URL 的值**,并指出路。MCP 座另有探测口(`POST /v1/capabilities/mcp/probe`,同码同句同机读位)。
2851
+ - **A2A 座**逐条扫整只数组(含读器会丢弃的条目 —— 字节一样落盘);`a2aPeers` 超过 32 条(读器的挂载上限)整份 `400 request.field_invalid`(`field:"a2aPeers"` · `reason:"over_cap"` · `count` · `cap`):界外的尾项读器本就不挂,但提交体整份落盘 —— 判官要么看过每一条对端的 `url` / `cardUrl`,要么这份体不收。判的范围是条目上**串值**的 `url` / `cardUrl`:非串值的键、条目上多余的键、`a2aPeers` 不是数组仍是读器既有的读法(这条对端丢弃 / 整只忽略 + 运维 warn),它们的字节照落盘 —— A2A 请求面还没有 MCP 那样的条目判官表。7.134.x 及以前超过 32 条是 200、第 33 条起丢弃(运维 warn 点名条数)。**搜索后端座**:userinfo 形此前已是 400(句子逐字不变,本版起体另带 `field` / `reason`),凭据名参数是本版新拒的。
2852
+ - **不判**:续跑重放存量请求(拒会把升级前停驻的任务永久卡死;已落盘的字节不因拒而消失 —— 介意的部署把这些任务结掉后轮换那几枚凭据);解析不了的 url(拨号期失败);部署面(中心 / `config.d` / 部署 env)声明的地址 —— 那是运维的配置,不进任何请求的停驻上下文。
2853
+ - 7.134.x 及以前照收、原样落停驻上下文。升级后用凭据名参数鉴权的对端 / 托管 MCP / 搜索后端要改:凭据挪进上表的位;只认 query 鉴权、不收请求头的服务端,改在部署面声明。
2854
+
2792
2855
  ### 9.6 trace 脱敏的射程:与出站请求体无关
2793
2856
 
2794
2857
  🔴 **脱敏 ≠ 出站控制**:trace 脱敏(账本 / SSE / turns / 审批预览里的 `«redacted»` 标记)只作用于
@@ -2953,8 +3016,9 @@ web-admin 拉取 / fleet 公告 / 凭证续签、WebSearch、对象存储、OTLP
2953
3016
  停链,不给没测过的提交打 tag)。GitHub Actions 不再发 npmjs 包(`ci.yml` 的 `npmjs-publish` job 已删;
2954
3017
  镜像 job 与 GH Packages 镜像位照旧随 tag 跑)。脚本的步骤,每步一行 `PUBLISH-STEP v=… step=…` 进链日志 `scratchpad/release-gates-<v>.log`:
2955
3018
  `tag`(本地 tag 在、tag 树的版本对)→ `precheck`(registry 上本版在不在;读不出 ⇒ 红,不盲发)→ `token` → `clone`(干净 tag 树 =
2956
- `git clone --depth 1 --branch v<v> file://<仓>`)→ `npm-ci` → `prepublish`(`npm run prepublishOnly`)→ `pack` → `publish`(**在 tag 树目录里**
2957
- `npm publish --ignore-scripts`)→ `readback-wait`(轮询 registry 至多 20 min)→ `readback-shasum`(dist.shasum = 本地 tarball 的 sha1)→
3019
+ `git clone --depth 1 --branch v<v> file://<仓>`)→ `npm-ci`(**k3s8**:tag 树上船、容器里 `npm ci`)→ `prepublish`(**k3s8**:`npm run prepublishOnly`)→
3020
+ `pack`(**k3s8** 上 `npm pack --ignore-scripts`,远端打 sha1 → 取回、sha1 核同 → 解进本机 tag 树 → 本机 `npm pack --ignore-scripts` 复包 → 两只解压后的
3021
+ tar 流逐字节同才往下走;读数 `remote-shasum=… tar=identical`)→ `publish`(**在 tag 树目录里** `npm publish --ignore-scripts`)→ `readback-wait`(轮询 registry 至多 20 min)→ `readback-shasum`(dist.shasum = 本地 tarball 的 sha1)→
2958
3022
  `readback-bytes`(curl 回读 tarball,与本地 `cmp` 逐字节同;**传输失败**在 `readback-wait` 用的同一只窗里重试、窗满才红,**字节差**不重试、立即红,两种红句分开说)→ `githead`(registry 的 gitHead = tag commit)。脚本钉 `umask 022`(文件权限进 tar 头,
2959
3023
  换 umask 重跑会 pack 出另一份字节);每次 registry 请求有硬上限(60 s),回读等待另有 20 min 墙钟截止,registry 挂住不会挂死链。成功尾行
2960
3024
  `PUBLISH v=<v> shasum=<sha1> gitHead=<sha> bytes=<n> readback=identical`(发车帖 / CHANGELOG 回填 shasum 与 gitHead 从这里取);任一步红 ⇒
@@ -2965,9 +3029,19 @@ web-admin 拉取 / fleet 公告 / 凭证续签、WebSearch、对象存储、OTLP
2965
3029
  (别的机器上新 clone 的树 / `npm ci` 半途断掉的树先 `npm ci --no-audit --no-fund`;缺了它封口红,红句带这条出路)。
2966
3030
  - **为什么是 clone 而不是 git worktree**:npm 从目录发布时读 `<git 根>/.git/HEAD` 填 gitHead;worktree 的 `.git` 是文件 ⇒ gitHead 为空
2967
3031
  (与 7.103.1 从 tarball 文件发布同一个结果)。
3032
+ - **重活只在 k3s8**(7.135.0 起):`npm ci` / `prepublishOnly` / `pack` 三步经 `scripts/remote-gate.sh` 在集群主机的容器里跑(车道目录
3033
+ `/root/ci/publish-<包名>-<版本>-<随机后缀>`,每次调用一条、私有,调用结束即删 —— 链里那次与手跑重跑 / dry-run 从不共用远端树),**需要环境变量 `GATE_HOST`**(同门 2;`release.sh` 起链即查,
3034
+ 启动器缺省给集群主机)。`GATE_HOST` 缺席 / 集群主机不可达 ⇒ 红在 `npm-ci` 这一步,**不回落本机跑**。发车机这一侧只 clone、取回、复包、发:
3035
+ 不装依赖、不跑任何生命周期脚本。不直接发取回的 tarball 文件:npm 从 tarball 文件发布不填 gitHead,还会把那只文件在发车机上的绝对路径
3036
+ (`_resolved` / `_from`)写进公开元数据;所以在 tag 树目录里复包、从目录发。核的是**解压后的 tar 流**而不是 gzip 字节:同一份内容在集群
3037
+ 主机与发车机上 gzip 出来的字节不同(两边 zlib 不同),内容一样。`remote-gate.sh` 为此多了两个口:`fetch <车道目录内的相对路径> <本机文件>`
3038
+ (路径闭集、断了不留半截)与 `clean`(按车道标签强停这条车道的全部容器、再删目录,有硬时限);它的 ssh 带 keepalive,半开连接约一分钟内报错退出,不再永挂。
3039
+ - **dry-run**:`bash scripts/publish-local.sh <v> --dry-run` 跑到 `pack` 止(集群主机构建 + 取回 + 两道核同),不查令牌、不发、不回读;
3040
+ 链日志尾行 `PUBLISH-DRYRUN v=<v> stop=pack`(不写 `PUBLISH v=…`)。
2968
3041
  - **凭据**:**需要环境变量 `NPM_TOKEN`**(只在要发的时候查;发车机 `~/.npmrc` 那一行本身就是 `//registry.npmjs.org/:_authToken=${NPM_TOKEN}`
2969
- 引用)。脚本不读 `~/.npmrc`:每条 npm 调用带临时 `--userconfig`,临时 npmrc 只写 `${NPM_TOKEN}` 引用、不写值;开头封口,`npm ci` 的安装脚本 /
2970
- 构建 / pack-hygiene 测试拿不到任何凭据,只有 `npm publish` 那一个进程拿到 `NPM_TOKEN`(且带 `--ignore-scripts`)。令牌从不打印。
3042
+ 引用)。脚本不读 `~/.npmrc`:每条 npm 调用带临时 `--userconfig`,临时 npmrc 只写 `${NPM_TOKEN}` 引用、不写值;开头封口,`remote-gate.sh`
3043
+ 与它起的 ssh / 容器(`npm ci` 的安装脚本 / 构建 / pack-hygiene 测试)、本机复包拿不到任何凭据,只有发车机上 `npm publish` 那一个进程拿到
3044
+ `NPM_TOKEN`(且带 `--ignore-scripts`)—— 令牌不出发车机。令牌从不打印。
2971
3045
  - **门 4 不再等 CI**(同一裁定):`scripts/post-publish-gates.sh` 的门 4 = 一个 45 min 的 npm 窗(公开 packument 上 `versions[<v>]` 在且
2972
3046
  `dist-tags.latest` 追平)。判决行 `GATES456 v=… rc4=… rc5=… rc6=… shasum=… elapsed=… ciTag=… ciMain=… tagRun=… mainRun=… why4=… chain=…`:既有十一键形状不变,末尾追加第十二键 `chain=<本轮标识>`(见下一条起链启动器);
2973
3047
  CI 两腿(`ciTag` / `ciMain` / `tagRun` / `mainRun`)是**信息格**,不进 rc4、不进 why4;`why4` 只剩 `propagation_timeout`(rc4 非零)与 `-`(绿)。
@@ -2981,8 +3055,8 @@ web-admin 拉取 / fleet 公告 / 凭证续签、WebSearch、对象存储、OTLP
2981
3055
  `<态> <versions> <latest> <shasum> <tarball> <gitHead>`,态 ∈ `present` / `absent` / `unreadable:<因>` —— 读不出与「不在」永远是两个词,
2982
3056
  由各门自己判(门 1.5 读不出就说跳过;门 2.5 / 3.5 读不出即红)。此前门 1.5 / 2.5 / 4 的 curl 不限时(registry 挂住就挂死同步链),门 2.5 还手抄包名。
2983
3057
  起链的 `npm whoami` 错误体两种流都认(npm 11 写 stdout、npm 8 写 stderr —— 只读 stdout 会把 npm 8 的 E401 误判成「网络不可达」)。
2984
- - **门 2.9 = build + pack-hygiene**(7.105.0 起):门 2 的 tsc 之后、全量之前跑 `npm run prepublishOnly`(与门 3.5 在 tag 树里
2985
- 跑的是同一只脚本;远端臂在 k3s8 的容器里 build)。此前 pack-hygiene 的 dist 字节段在远端臂恒 skip,第一次真执行是门 3.5 —— tag 已推;
3058
+ - **门 2.9 = build + pack-hygiene**(7.105.0 起):门 2 的 tsc 之后、全量之前跑 `npm run prepublishOnly`(与门 3.5 在 tag 树上
3059
+ 跑的是同一只脚本;门 3.5 恒在 k3s8 的容器里 build,门 2.9 的远端臂也在那里)。此前 pack-hygiene 的 dist 字节段在远端臂恒 skip,第一次真执行是门 3.5 —— tag 已推;
2986
3060
  本机臂又读盘上上一次留下的旧 dist,合并批改了 fail-open 词表注文就误红。
2987
3061
  - **门 3 推 main 前核 main = 起链提交**(7.105.0 起):发车树 detached 在起链提交上、本地 `main` 被别处挪走 ⇒ 停链点名两只 sha
2988
3062
  (此前只核 HEAD,推出去的 main 是门 1–2 没测过的提交)。
@@ -3150,7 +3224,9 @@ const ciphertext = Buffer.from(sodium.crypto_box_seal(sodium.from_string(apiKey)
3150
3224
 
3151
3225
  **⑥ 保管目录与轮换。** 保管目录 = `<数据根>/sealed-key/`(数据根 = `LOCAL_DATA_ROOT` → `CONFIG_LOCAL_DIR` → `AGENT_DATA_DIR` → `~/.ai-agent`),
3152
3226
  每把钥匙一个文件 `<publicKeyId>.json`(文件 `0600`,目录 `0700`)。**私钥只在这里**:丢了,对着它封的密文全部变成 `stale_ciphertext`,
3153
- 只能重封 —— 备份时按私钥对待。
3227
+ 只能重封 —— 备份时按私钥对待。7.134.0 起它下面还有一个子目录 `checkpoint-ctx-keys/`:停驻任务续跑上下文里请求凭据的封签钥匙(一个域一对钥匙,与模型钥匙不共用;
3228
+ 同样的文件形、同样的「空目录生成一把」;不向中心登记、不出现在 caps 上)。它丢了,封在停驻行里的凭据就开不开(续跑答 `409 conflict.checkpoint_ctx_unsealable` `reason:"key_not_held"`)——
3229
+ 所以整个 `sealed-key/` 目录要**跨重启持久**(SQL 后端也一样:钥匙不进库)。下面的轮换步骤对这个子目录同样适用:旧私钥文件留到用它封的停驻行都已结束为止。
3154
3230
 
3155
3231
  - 起服时读目录里的全部钥匙文件;一个可用的都没有 ⇒ 生成一把新的。读不了的文件(坏 JSON / 不认识的格式)跳过、**不删**,warn
3156
3232
  `sealed_key_file_unreadable`。文件只在起服时读:运行中放进来的钥匙文件要重启才认。
@@ -3166,9 +3242,17 @@ const ciphertext = Buffer.from(sodium.crypto_box_seal(sodium.from_string(apiKey)
3166
3242
  或放好钥匙文件)再起其余副本 —— 空目录上并发首启会各自生成一把,各副本只持有自己那一把,直到下次重启。目录要对每个副本**可写**(每次起服
3167
3243
  会把它设成 `0700`;只读挂载 ⇒ 建店失败 ⇒ `no_key_store`)。⚠️ 只共享 `sealed-key/` 这一个子目录:`DB_BACKEND=local` 的整个数据根禁止跨容器 /
3168
3244
  跨主机共享(`docs/DEPLOY-PREREQS.md`)。
3245
+ 照随包 `deploy/sema-up` 图表部署时这一步图表替你做了:`sealedKey.persistence` 块(缺省开)把整个 `sealed-key/` 目录挂成一只 PVC,访问模式缺省单副本 `ReadWriteOnce`、多副本 `ReadWriteMany`
3246
+ (要存储类支持 RWX;空卷首装后 `rollout restart` 一次,让并发首启各生成的钥匙互相都持有);显式关掉它(`sealedKey.persistence.enabled: false`)图表会同时给 worker 设 `DURABLE_APPROVAL=false`,并拒绝再配 `server.durableApproval: true`。
3169
3247
  - **走中心形**:接 web-admin,执行侧公钥登记在中心(起服时带管理令牌自动上报,否则把公钥打印出来供手工登记),web 面对着登记的公钥封、中心存密文。
3170
3248
  调用方不必逐台去问 caps;但同一个 worker 的多个副本各有各的保管店这件事中心形不改变 —— 要它们都开得了同一份密文,仍要共享保管目录。
3171
3249
 
3250
+ **停驻任务的凭据封签(7.134.0 起)同一个目录**:共享的是整个 `<数据根>/sealed-key/`(含子目录 `checkpoint-ctx-keys/` —— 停驻行封签那一域自己的钥匙)。不共享 ⇒ A 副本停驻、带请求凭据的任务
3251
+ 在 B 副本上续跑答 `409 conflict.checkpoint_ctx_unsealable` `reason:"key_not_held"`;单副本也要让这个目录跨重启持久。**7.133.x 与 7.134.0 不能混跑**:先停掉全部 7.133.x 副本,再起第一个 7.134.0 副本
3252
+ (一次性迁移 M28 在它起服时把升级前停驻行里的明文封好);混跑时 7.133.x 副本续跑一条已封签的行会把凭据位当空值、任务无凭据照跑、不报错。降级到 7.133.x 之前先把带凭据的停驻行结掉(决定或取消)。
3253
+ 多副本升级时先起一个 7.134.0 副本、等它起好再起其余副本(耐久审批开着时它起好即打出 `checkpoint_ctx_credentials_sealed` 一行):停驻封签的钥匙在新子目录 `checkpoint-ctx-keys/` 里,
3254
+ 升级后第一个起服的副本生成它(`sealed-key/` 早已共享好也一样);同时起多个副本会各建一把、互相答 `key_not_held`,直到各自重启一次(钥匙只在起服时读目录里的全部文件)。
3255
+
3172
3256
  ### 9.11 会话规则店:抹除封键与显式恢复(7.106.0 起)
3173
3257
 
3174
3258
  适用于 `DB_BACKEND=mysql|pg`(SQL 会话规则店;`DB_BACKEND=local` 用的是引擎自带的文件店,不在本节)。
@@ -3207,23 +3291,37 @@ UPDATE session_policy_rev_mark SET rev = 0, gen = gen + 1 WHERE policy_key = '<w
3207
3291
 
3208
3292
  - `toolDeny` / `toolAllow`:**规则条目**的列表 —— 工具名(`Read`)、协议工具的命名空间(`mcp__<server>`)或工具自己文法的规则(`Bash(git push:*)`、`Edit(src/**)`、
3209
3293
  `WebFetch(domain:<host>)`)。`toolDeny: ["Bash(rm:*)"]` 按命令名拒 `rm`(连接链里任何一段跑到它都算;写成路径的 `/bin/rm` 不是这个名字 —— 要整只拒 shell 写 `Bash`)。
3294
+ `toolDeny: ["WebFetch(domain:evil.com)"]` 按调用实际到达的主机拒(大小写、尾点不算另一个主机;`WebFetch(domain:*.evil.com)` 拒子域、不含 `evil.com` 本身;URL 读不出主机的取数也拒)——
3295
+ 7.135.0 起;7.134.0 及以前这一形写进 `toolDeny` 答 `400 rules.inert_entry`(`content_unsupported`)。主机文法只有 `WebFetch` 有:`WebSearch(domain:…)` 照旧 `400 rules.inert_entry`。
3296
+ 同一形在请求的 `settings.permissions.deny` / `.ask`、技能 `disallowedTools`、`POST /v1/rules` 的 deny / ask 里同一读法(7.134.0 及以前:请求两桶里受理却从没生效,其余三处 400)。
3210
3297
  `toolAllow` 是收窄名单:没有一条条目放行的调用被拒。
3211
3298
  - `allowDirs`:写工具只许落在这些目录里(不能按路径收住的写类工具,例如 shell,在它生效时整只被拒)。
3212
3299
  - 7.128.x 及以前的 `commandAllow` / `commandDeny` 已退役:`commandDeny: ["rm"]` 的新写法是 `toolDeny: ["Bash(rm:*)"]`,但旧桶还拒写成路径的 `/bin/rm …` 和读不成一条命令名的
3213
3300
  命令行(管道、`&&`),新写法不拒这两类;`commandAllow` 没有「只收窄 shell」的写法,要收窄就在 `toolAllow` 里列出允许的工具(shell 写成 `Bash(<命令>:*)` 条目)。
3214
3301
 
3302
+ **协议命名空间的覆盖形(7.135.0 起有能力位)。** 条目写协议命名空间 —— 整对端 `mcp__srv` / `a2a__peer`、工具段通配 `mcp__srv__*`、工具段 glob `mcp__srv__get_*` —— 写口收(`200`),引擎把它们读成**一组工具**:
3303
+ `toolDeny` 里拒这一组,`toolAllow` 里只放这一组。要不要放开对这几形的扣下,读 `GET /v1/capabilities` 的顶层布尔 `sessionRulesNamespaceForms`(不按版本号猜):`true` = 引擎协议表上每个命名空间的这三形写口真收、
3304
+ 引擎真认成一组;键缺席(≤7.134.x)或 `false` ⇒ 当不放宽。它与 `sessionPolicy`(这台有没有会话规则写面)正交 —— 没有会话规则店的部署上它也是 `true`,所以条件是两位同真。位只说命名空间覆盖形:
3305
+ `*`、对端段的部分通配(`mcp__git*`)、尾分隔(`mcp__srv__`)照旧 `400 rules.inert_entry`(下),`mcp__*` 只在 `toolDeny` 收。
3306
+
3215
3307
  **两只拒码**(判官是引擎的那一只,两条写口与店里的拒同码、同一份拒体;同步导入的写口在句首加记录坐标 `policy: [i].rules: `;店里一个字节都不落):
3216
3308
 
3217
3309
  - `400 rules.invalid_shape` —— 规则体形不对:`rules` 缺席或不是对象、有一个不是桶的键(含退役的命令桶,**不会被静默忽略**)、一只桶不是一列字符串、`allowDirs` 里有空目录。
3218
3310
  体顶层 `field`(哪个键;整体不是对象时是空串)与 `got`(那个值的类型,不回显值),`error` 是引擎的句子。
3219
- - `400 rules.inert_entry` —— 一条条目读成「什么都不是」,写进去什么都不拒 / 不许:退役的工具名、带 `__` 却没有协议前缀的名、协议名里铸不出的段、`*`、`mcp__*`、工具没有的规则形
3311
+ - `400 rules.inert_entry` —— 一条条目读成「什么都不是」,写进去什么都不拒 / 不许:退役的工具名、带 `__` 却没有协议前缀的名、协议名里铸不出的段(含对端段里的部分通配 `mcp__git*`)、`*`、
3312
+ `toolAllow` 里的整协议名 `mcp__*`(7.135.0 起 `toolDeny` 里的 `mcp__*` / `mcp__*__*` 是一条规则:拒每一台 MCP 服务器的每一只工具)、工具没有的规则形
3220
3313
  (`Monitor(touch:*)`)、文法不成的写法(空串、`Bash(`)。体顶层 `field` / `entry` / `reason`,外加 `verdict` / `currentName` / `guidance`(有就带)。按 `reason` 改写那一条再写。
3221
3314
 
3222
3315
  一条什么都不拒的 deny 已经在库里时,会话属主自己删得掉(删它不算放宽)。
3223
3316
 
3224
- **行自带文法戳。** 7.129.0 起每一行会话规则自带规则文法戳 `grammar`(写口判官盖引擎当前的文法:7.129.0–7.131.x 写下的行是 `1`,7.132.0 起写下的行是 `2`;
3225
- 早先写下的行保留自己的戳、引擎按它的戳读;店整只存、读回原样交出)—— `GET` / `PUT` 回包的 `rules` 与同步导出的
3226
- 记录里多这一个键。客户端改规则时只写三只桶,不要把读回的 `rev` / `gen` / `grammar` 一起回传:带着 `rev` 却没有 `grammar` 的值引擎按存量行的文法(0)读,括号形 allow 条目答
3317
+ **谁收得回什么(7.135.0 起,引擎 7.55.0)。** 一行会话规则记下自己的 **operator 部分**(回包与同步导出的记录里的 `operatorRules`:最近一次 operator 写下的那一部分;
3318
+ **缺席 = 整行都是 operator 的**,包括升级前存下的每一行)。会话属主(非 operator 的写)收得回非 operator 写加上去的条目 —— `PUT` 一份不带那一条的值(`expectedRev` = 读到的那一行),
3319
+ 下一次工具调用起生效;收不回 operator 写下的那一部分(两边都写过的条目也算):`403 loosen_forbidden`,句子 `a non-operator session-rule write may not loosen what an operator wrote; …`
3320
+ (7.134.x 及以前的句子是 `… may only tighten …`,按句子匹配的脚本改读码)。operator 写一次就把整行变成 operator 的。`operatorRules` 由引擎铸,客户端改规则时**不要**回传它。
3321
+
3322
+ **行自带文法戳。** 7.129.0 起每一行会话规则自带规则文法戳 `grammar`(写口判官盖引擎当前的文法:7.129.0–7.131.x 写下的行是 `1`,7.132.0–7.134.x 写下的行是 `2`,7.135.0 起写下的行是 `4`;
3323
+ 早先写下的行保留自己的戳、引擎按它的戳读;店整只存、读回原样交出;7.134.x 及更早的引擎读不了戳 3 / 4 的行 —— 整行拒、那条会话每一次调用都拒,升级序见 MIGRATION 7.135.0)—— `GET` / `PUT` 回包的 `rules` 与同步导出的
3324
+ 记录里多这一个键。客户端改规则时只写三只桶,不要把读回的 `rev` / `gen` / `grammar` / `operatorRules` 一起回传:带着 `rev` 却没有 `grammar` 的值引擎按存量行的文法(0)读,括号形 allow 条目答
3227
3325
  `400 rules.inert_entry`(`reason: "earlier_grammar"`;出路在句子里);`grammar` 坏或比引擎新 ⇒ `400 rules.invalid_shape`(`field: "grammar"`)。
3228
3326
 
3229
3327
  **存量行(`DB_BACKEND=mysql|pg`)。** 7.129.0 第一次起服时一次性迁移把装规则的列 `session_policy.rules` 改名为 `rule_entries`。带 `commandAllow` / `commandDeny` 的行:退役桶
@@ -3245,3 +3343,91 @@ UPDATE session_policy_rev_mark SET rev = 0, gen = gen + 1 WHERE policy_key = '<w
3245
3343
  而且本版写下的规则条目在旧版上不生效(见 `MIGRATION.md` 7.129.0 节)。`DB_BACKEND=local` 的规则在引擎自带的文件店里,不改列名:带命令桶的规则文件读回 `corrupt`,出路在引擎的拒句里。
3246
3344
  文件店也没有上面那一步判读,也不需要:引擎按行自带的文法读,7.128.x 写下的无戳文件里 `toolAllow` 的 `Bash(rm:*)` 这类条目照旧什么都不放行(不放宽),升级后按引擎通告重写。停驻的 run 里引擎写下的
3247
3345
  祖先规则快照同理(本服务不改写),升级前决掉或取消待决的停驻 run。
3346
+
3347
+ ### 9.13 自建引擎镜像:两条路径(源码 tag 或 npm 包)
3348
+
3349
+ 自 7.128.0 起没有新的容器镜像发布(§0 开头的说明):要把引擎升到 ≥ 7.128.0,只能自己构建镜像。两条路径产出同一个 HTTP 服务 —— 入口都是 `main`(路径 1 跑源码 `src/main.ts`,
3350
+ 路径 2 跑包里编译好的 `dist/main.js`,装配次序同一张表)—— 按手里有什么访问权选:
3351
+
3352
+ - **路径 1 · 源码 tag**(有源码仓访问权):在 tag `v<版本>` 的检出上用仓根 `Dockerfile` 构建。基镜像 `oven/bun:1-slim`,Bun 直跑 TypeScript,没有构建步骤;入口 `bun run src/main.ts`(工作目录 `/app`)。
3353
+ - **路径 2 · npm 包**(只有 npm 访问权;包是公开的,匿名可装):`npm install @sema-agent/server@<版本>`。基镜像 `node:24-slim`(包的 `engines` 是 `^20.19.0 || >=22.12.0`);
3354
+ 入口 `node node_modules/@sema-agent/server/dist/main.js`。包的 `bin` 里没有 HTTP 服务(`run-local` 是单机一次性 runner、`sema-up` 是部署引导脚本),要起服务必须直接跑这个 `dist/main.js`。
3355
+
3356
+ **构建(二选一)**
3357
+
3358
+ 路径 1:
3359
+
3360
+ ```bash
3361
+ # 1. 取 tag 的检出
3362
+ git clone --depth 1 --branch v<版本> <你有权访问的源码仓地址> sema-server && cd sema-server
3363
+ # 2. 构建 —— 到不了 Docker Hub / npmjs 时用两只 build-arg 换源(下面是国内写法)
3364
+ docker build \
3365
+ --build-arg BUN_IMAGE=docker.m.daocloud.io/oven/bun:1-slim \
3366
+ --build-arg NPM_DEFAULT_REGISTRY=https://registry.npmmirror.com \
3367
+ -t sema-server:<版本> .
3368
+ ```
3369
+
3370
+ 两只 build-arg 的缺省:`BUN_IMAGE=oven/bun:1-slim`、`NPM_DEFAULT_REGISTRY=https://registry.npmmirror.com`;海外构建把后者换成 `https://registry.npmjs.org`。
3371
+ 还有第三只 `PKG_SOURCE`:缺省 `cn` 把最终阶段的 apt 源改写到 aliyun 来装 `git`(leader 把合并结果推回远端要用),官方源直连传 `--build-arg PKG_SOURCE=global`。
3372
+
3373
+ 路径 2:先写 `Dockerfile`(构建上下文里不需要别的文件)——
3374
+
3375
+ ```dockerfile
3376
+ ARG NODE_IMAGE=node:24-slim
3377
+ FROM ${NODE_IMAGE}
3378
+ ARG SEMA_SERVER_VERSION
3379
+ ARG NPM_DEFAULT_REGISTRY=https://registry.npmmirror.com
3380
+ WORKDIR /app
3381
+ # leader 把合并结果推回远端要用 git;slim 基镜像不带。不用 leader 车道可删这一行。
3382
+ RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates && rm -rf /var/lib/apt/lists/*
3383
+ RUN test -n "$SEMA_SERVER_VERSION" \
3384
+ && printf '{"name":"sema-engine-image","private":true}\n' > package.json \
3385
+ && npm install --omit=dev --save-exact --no-audit --no-fund --registry "$NPM_DEFAULT_REGISTRY" "@sema-agent/server@${SEMA_SERVER_VERSION}"
3386
+ EXPOSE 8090
3387
+ HEALTHCHECK --interval=30s --timeout=3s CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||8090)+'/readyz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
3388
+ CMD ["node", "node_modules/@sema-agent/server/dist/main.js"]
3389
+ ```
3390
+
3391
+ ```bash
3392
+ # 1–2. 构建 —— 换源同路径 1:`--build-arg NODE_IMAGE=docker.m.daocloud.io/library/node:24-slim`;海外或镜像源没有该版本时 `--build-arg NPM_DEFAULT_REGISTRY=https://registry.npmjs.org`
3393
+ docker build --build-arg SEMA_SERVER_VERSION=<版本> -t sema-server:<版本> .
3394
+ ```
3395
+
3396
+ `HEALTHCHECK` 指 `/readyz`:它的 unhealthy 只表示「别往我这儿路由」,不是「重启我」(§0 探针一段)。
3397
+ 包本身不带 lockfile,传递依赖按构建那天的 semver 解析;要同一版本两次构建得到同一棵依赖树:在本机用同样的 `npm install` 命令生成 `package.json` 与 `package-lock.json` 一并提交,
3398
+ `Dockerfile` 里改 `COPY package.json package-lock.json ./` 再 `RUN npm ci --omit=dev`。
3399
+
3400
+ **之后(两条路径相同)**
3401
+
3402
+ ```bash
3403
+ # 3. 让节点拿到镜像 —— 单机 docker 不用这一步。k3s:在节点上导入(每个会调度它的节点各导一次)
3404
+ docker save sema-server:<版本> | k3s ctr -n k8s.io images import -
3405
+ # 或推到你自己的 registry:docker tag sema-server:<版本> <你的 registry>/sema-server:<版本> && docker push <你的 registry>/sema-server:<版本>
3406
+ # 4. 起服 —— 数据根挂持久卷(AGENT_DATA_DIR 指到卷上)。下面是不带模型目录的最小形:缺 MODEL_ID 或 MODEL_GATEWAY_BASEURL 起服即拒,拒句点名缺的键
3407
+ docker run -d --name sema-server -p 8090:8090 \
3408
+ -e DB_BACKEND=local -e AGENT_DATA_DIR=/data -v sema-data:/data \
3409
+ -e MODEL_GATEWAY_BASEURL=https://<your-gateway>/v1 -e MODEL_ID=<your-model-name> -e MODEL_API_KEY=… \
3410
+ -e SERVICE_AUTH_TOKEN=<随机长串> \
3411
+ sema-server:<版本>
3412
+ # SERVICE_AUTH_TOKEN 不是起服必需,但没有它(且没开 ALLOW_UNAUTHED_WRITES)提交任务一律 503 auth.service_token_required —— 第 5 步只验就绪,交任务前先配它。另一形是显式 ALLOW_UNAUTHED_WRITES=1:那时没有 service 令牌的 worker 只绑 127.0.0.1(自收窄),容器里还要 BIND_HOST=0.0.0.0 才能经 -p 访问,并把第 4 步的映射改成 `-p 127.0.0.1:8090:8090`(否则无鉴权的提交口暴露给整个局域网)—— 两形的取舍见 §0「监听绑址」段。
3413
+ # 5. 验收 —— 就绪 + 版本
3414
+ curl -fsS http://127.0.0.1:8090/readyz # {"ready":true}
3415
+ curl -s http://127.0.0.1:8090/health # "version" 应等于你构建的 <版本>
3416
+ ```
3417
+
3418
+ - **随包 `deploy/sema-up`**:图表 `server.image` 必填,填你自建的引用;节点本地导入的(第 3 步 k3s)`--set server.image=sema-server:<版本> --set server.pullPolicy=Never`,推了 registry 的填完整引用并保持缺省 `IfNotPresent`。图表不覆写镜像的启动命令,两条路径的镜像都按它自己的 `CMD` 起。`sema-up` 脚本自己的入口:`full-cluster --kube=machines`(`-f machines.yaml`,≥ 3 台)在环境里设 `SEMA_SERVER_IMAGE_TAR=<docker save 出的 tar 或 .tar.gz>`,脚本逐台灌入并 `k3s ctr images import`,部署的镜像名是固定的 `docker.io/library/sema-server:local`、拉取策略 `Never` —— **所以 tar 里的镜像必须带 `sema-server:local` 这个标签**:`docker tag sema-server:<版本> sema-server:local && docker save sema-server:local -o sema-server.tar`(只存 `sema-server:<版本>` 的 tar 导入成功,但部署找不到 `:local`);或设 `server_image:` / `SEMA_SERVER_IMAGE=<你的 registry 引用>`,二选一;含 server 的 compose 档(`full-single` / `local-plus`)与 `full-cluster --kube=existing|k3s` 要的是 `SEMA_SERVER_IMAGE`。⚠️ 缺镜像时 `sema-up` 打印的提示与 `machines.example.yaml` 的注释仍写着 ghcr 引用 —— 那是曾发布的镜像,7.128.0 之后没有新版;照本节自建,把你的引用填进去。
3419
+ - **数据根**:第 4 步 `DB_BACKEND=local` 是单容器形(数据目录禁跨容器共享)。生产用 `DB_BACKEND=mysql|pg` 与 §0「生产」那组坐标替换它 —— **数据根卷仍要挂**:`<数据根>/sealed-key/` 在 SQL 后端下也不进库,跨重启要持久。不设 `AGENT_DATA_DIR` 时数据根落在容器用户家目录下的 `.ai-agent`,容器一删就没。
3420
+ - **升级 = 换一只更高版本的镜像**:升级序、先升库再升副本、排空与回滚前置,按你跨过的每一版读 `MIGRATION.md` 与源码仓文档 DEPLOY-PREREQS 的同版节(不随包);一次性迁移与新表在起服时自跑,不用手跑。
3421
+
3422
+ **与曾发布镜像的差异**
3423
+
3424
+ - **标签 / 引用**:曾发布的镜像是 `ghcr.io/sema-agent/sema-server:v<版本>`(另有 `:<提交>` 与 `:latest`),停在 7.128.0 之前;自建的引用你自己定,编排里写旧引用的地方(compose、图表 `server.image`、部署清单)要同步换成你的。
3425
+ - **入口**:路径 1 与曾发布镜像同(同一份 `Dockerfile`:`bun run src/main.ts`、端口 8090、`/readyz` 的 `HEALTHCHECK`);路径 2 跑 Node,入口与文件布局不同,编排里若覆写了启动命令成 `bun run src/main.ts`,要改成 node 入口。
3426
+ - **用户**:两条路径的 `Dockerfile` 都没有 `USER` 行,两只基镜像(`oven/bun:1-slim`、`node:24-slim`)的镜像配置里也没设 `User`,容器内以 root 运行(与曾发布镜像相同)。要降权:自己加 `USER`,并让数据根卷对那个 uid 可写。
3427
+
3428
+ **arm64 与可选原生件**
3429
+
3430
+ - 两只基镜像的清单都含 linux/amd64 与 linux/arm64(`oven/bun:1-slim`、`node:24-slim`);构建机是 arm64 就得 arm64 镜像,跨架构构建用 `docker buildx build --platform`。
3431
+ - `sharp`(图片降采样)是可选依赖,按平台装预编译平台包:linux/arm64 glibc 上是 `@img/sharp-linux-arm64`(两条路径的依赖解析在 arm64 目标上都解出了它);Alpine 一类 musl 基镜像要的是 `linuxmusl` 平台包,本节的 Debian 系 `slim` 不涉及。
3432
+ 它不是起服条件:引擎用到图片降采样时才动态加载它,装不上就没有降采样。
3433
+ - `slim` 基镜像没有编译器:`ssh2` / `cpu-features` 的可选原生件编译失败不让安装失败,起服也不依赖它们(没有这两件原生件的依赖树能起服到 `/readyz` 200)。