@sema-agent/server 7.141.0 → 7.143.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.
- package/MIGRATION.md +657 -0
- package/USAGE.md +102 -30
- package/dist/adoption/plan.js +22 -0
- package/dist/approval-ask-audit-store.d.ts +61 -43
- package/dist/approval-ask-audit-store.js +69 -44
- package/dist/approval-ask-machine.d.ts +15 -7
- package/dist/approval-ask-machine.js +10 -4
- package/dist/approval-card.d.ts +126 -27
- package/dist/approval-card.js +103 -23
- package/dist/approval-crash-convergence.d.ts +17 -7
- package/dist/approval-crash-convergence.js +94 -22
- package/dist/approval-deny-reasons.d.ts +34 -30
- package/dist/approval-deny-reasons.js +21 -6
- package/dist/approval-policy-settlement.d.ts +1 -1
- package/dist/approval-queue-kind.d.ts +27 -0
- package/dist/approval-queue-kind.js +6 -0
- package/dist/approval-reconciler.d.ts +41 -9
- package/dist/approval-reconciler.js +45 -42
- package/dist/audit.js +4 -2
- package/dist/auth-bridge.d.ts +9 -6
- package/dist/auth-bridge.js +9 -3
- package/dist/boot/adoption.js +2 -1
- package/dist/boot/budget-tracing.d.ts +17 -1
- package/dist/boot/budget-tracing.js +10 -6
- package/dist/boot/device-lane.d.ts +1 -1
- package/dist/boot/execution-env.d.ts +24 -4
- package/dist/boot/execution-env.js +26 -23
- package/dist/boot/execution-lane.js +2 -1
- package/dist/boot/exit-boundary.js +5 -4
- package/dist/boot/governance-seams.d.ts +26 -41
- package/dist/boot/governance-seams.js +61 -28
- package/dist/boot/late-binds.d.ts +7 -4
- package/dist/boot/late-binds.js +3 -1
- package/dist/boot/leader.js +2 -4
- package/dist/boot/memory-consolidation.d.ts +0 -8
- package/dist/boot/memory-consolidation.js +5 -4
- package/dist/boot/parked-revive-gate.js +2 -1
- package/dist/boot/permission-rules-audit.d.ts +0 -28
- package/dist/boot/permission-rules-audit.js +2 -1
- package/dist/boot/read-deny-anchor-audit.js +2 -1
- package/dist/boot/reapers.js +9 -7
- package/dist/boot/resolve-spec.d.ts +1 -1
- package/dist/boot/resolve-spec.js +19 -10
- package/dist/boot/retention-lane.js +5 -3
- package/dist/boot/runner-deps.d.ts +10 -7
- package/dist/boot/runner-deps.js +20 -29
- package/dist/boot/runtime-caps.js +3 -2
- package/dist/boot/session-faces.js +4 -3
- package/dist/boot/shutdown.d.ts +9 -0
- package/dist/boot/shutdown.js +19 -4
- package/dist/boot/stage-02-web-admin-pull.js +3 -0
- package/dist/boot/stage-03-store-backend.d.ts +4 -1
- package/dist/boot/stage-03-store-backend.js +1 -2
- package/dist/boot/stage-04-stores.d.ts +5 -2
- package/dist/boot/stage-04-stores.js +6 -7
- package/dist/boot/stage-05-execution-env.d.ts +6 -3
- package/dist/boot/stage-05-execution-env.js +8 -6
- package/dist/boot/stage-06-runners.d.ts +6 -3
- package/dist/boot/stage-06-runners.js +3 -4
- package/dist/boot/stage-07-capability-layer.d.ts +6 -3
- package/dist/boot/stage-07-capability-layer.js +7 -2
- package/dist/boot/stage-08-reapers.d.ts +6 -3
- package/dist/boot/stage-08-reapers.js +3 -2
- package/dist/boot/stage-09-leader.d.ts +6 -3
- package/dist/boot/stage-10-http-server.d.ts +6 -3
- package/dist/boot/stage-10-http-server.js +14 -5
- package/dist/boot/stores.d.ts +5 -2
- package/dist/boot/stores.js +10 -9
- package/dist/boot/web-admin.d.ts +5 -1
- package/dist/boot/web-admin.js +48 -36
- package/dist/boot/webfetch-summarize-lane.js +2 -1
- package/dist/boot/workflow-orchestration.js +3 -2
- package/dist/capabilities/builtin-tools.d.ts +2 -1
- package/dist/capabilities/builtin-tools.js +2 -4
- package/dist/capabilities/composite-members.d.ts +2 -1
- package/dist/capabilities/composite-members.js +2 -1
- package/dist/capabilities/hands-lane.d.ts +9 -39
- package/dist/capabilities/hands-lane.js +8 -13
- package/dist/capabilities/mcp-probe.d.ts +3 -2
- package/dist/capabilities/scenarios.d.ts +11 -1
- package/dist/capabilities/scenarios.js +1 -0
- package/dist/capabilities/skills.d.ts +1 -17
- package/dist/capabilities/skills.js +0 -8
- package/dist/capability-facts.d.ts +31 -7
- package/dist/capability-facts.js +27 -4
- package/dist/card-void.d.ts +6 -9
- package/dist/config-catalog.js +2 -1
- package/dist/config-dir-trust.js +58 -29
- package/dist/config-invariants.d.ts +7 -1
- package/dist/config-invariants.js +7 -0
- package/dist/config-provider.d.ts +10 -0
- package/dist/config-provider.js +15 -4
- package/dist/config-root-migration.d.ts +13 -0
- package/dist/config-root-migration.js +99 -0
- package/dist/config-types.d.ts +19 -8
- package/dist/config.d.ts +10 -3
- package/dist/config.js +18 -4
- package/dist/delegated-session-owner.d.ts +5 -3
- package/dist/delegated-session-owner.js +1 -1
- package/dist/device-ws-protocol.d.ts +1 -0
- package/dist/device-ws-protocol.js +2 -1
- package/dist/env-model-table-gate.d.ts +53 -0
- package/dist/env-model-table-gate.js +53 -0
- package/dist/execution-lane-caps.d.ts +2 -1
- package/dist/fleet/fleet-bus.d.ts +34 -55
- package/dist/fleet/fleet-bus.js +35 -100
- package/dist/fleet/fleet-reconciler.d.ts +4 -4
- package/dist/fleet/fleet-reconciler.js +1 -1
- package/dist/fleet/subagent-tail-bus.d.ts +14 -11
- package/dist/fleet/subagent-tail-bus.js +15 -28
- package/dist/hooks/hook-runner.d.ts +6 -0
- package/dist/hooks/hook-runner.js +58 -8
- package/dist/host-decision.d.ts +54 -20
- package/dist/host-decision.js +42 -14
- package/dist/http/admission.d.ts +1 -1
- package/dist/http/admission.js +7 -3
- package/dist/http/approval-sweeps.js +11 -8
- package/dist/http/caller-trust.d.ts +1 -1
- package/dist/http/dispatch.js +4 -2
- package/dist/http/durable-run-leg.js +2 -2
- package/dist/http/engine-refusal.d.ts +16 -0
- package/dist/http/engine-refusal.js +17 -0
- package/dist/http/execution-context.d.ts +2 -2
- package/dist/http/idempotency.d.ts +1 -1
- package/dist/http/memory-compliance-failure-reply.d.ts +1 -3
- package/dist/http/memory-compliance-failure-reply.js +4 -6
- package/dist/http/owner-access.d.ts +11 -0
- package/dist/http/owner-access.js +13 -0
- package/dist/http/principal-gate.d.ts +3 -1
- package/dist/http/principal-gate.js +17 -8
- package/dist/http/resume-legs.d.ts +21 -7
- package/dist/http/resume-legs.js +76 -58
- package/dist/http/resume-restatement.d.ts +39 -0
- package/dist/http/resume-restatement.js +25 -0
- package/dist/http/route-ctx.d.ts +35 -10
- package/dist/http/route-ctx.js +1 -1
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/approvals-assistant.d.ts +9 -1
- package/dist/http/routes/approvals-assistant.js +142 -31
- package/dist/http/routes/attachments.js +18 -0
- package/dist/http/routes/capabilities.js +16 -4
- package/dist/http/routes/memory-policy.d.ts +2 -2
- package/dist/http/routes/memory-policy.js +27 -7
- package/dist/http/routes/notify-wake.js +23 -25
- package/dist/http/routes/rules.js +48 -13
- package/dist/http/routes/runs.js +12 -11
- package/dist/http/routes/session-memory-sync.d.ts +91 -0
- package/dist/http/routes/session-memory-sync.js +174 -0
- package/dist/http/routes/session-sync.js +13 -20
- package/dist/http/routes/sessions-list.d.ts +2 -1
- package/dist/http/routes/sessions.d.ts +2 -2
- package/dist/http/routes/sessions.js +22 -23
- package/dist/http/routes/tasks.js +34 -54
- package/dist/http/run-read-face.d.ts +7 -0
- package/dist/http/run-read-face.js +9 -3
- package/dist/http/send.d.ts +5 -0
- package/dist/http/send.js +9 -2
- package/dist/http/server.d.ts +27 -15
- package/dist/http/server.js +4 -6
- package/dist/http/stored-body-replay.js +15 -4
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +2 -2
- package/dist/http/sync-submit-body.d.ts +21 -4
- package/dist/http/sync-submit-body.js +13 -0
- package/dist/http/wire-types.d.ts +17 -7
- package/dist/identity-source.d.ts +21 -2
- package/dist/identity-source.js +6 -0
- package/dist/leader/leader.js +5 -2
- package/dist/leader/wire.d.ts +7 -1
- package/dist/leader/wire.js +6 -5
- package/dist/leg-facts.d.ts +37 -0
- package/dist/leg-facts.js +15 -0
- package/dist/memory-bundle-engine.d.ts +1 -4
- package/dist/memory-bundle-engine.js +2 -2
- package/dist/memory-incident-sink.d.ts +19 -6
- package/dist/memory-incident-sink.js +8 -4
- package/dist/memory-operator-faces.d.ts +30 -66
- package/dist/memory-operator-faces.js +17 -88
- package/dist/memory-scope-stores.d.ts +38 -40
- package/dist/memory-scope-stores.js +51 -36
- package/dist/memory-scope.d.ts +0 -9
- package/dist/memory-scope.js +0 -9
- package/dist/memory-sync-client.d.ts +21 -21
- package/dist/memory-sync-client.js +62 -43
- package/dist/memory-sync-identity.d.ts +24 -0
- package/dist/memory-sync-identity.js +57 -0
- package/dist/memory-sync.d.ts +27 -5
- package/dist/memory-sync.js +29 -7
- package/dist/model-plane-face.d.ts +13 -7
- package/dist/model-plane-face.js +2 -1
- package/dist/observability/fail-open.d.ts +47 -14
- package/dist/observability/fail-open.js +37 -11
- package/dist/observability/run-terminal.d.ts +92 -34
- package/dist/observability/run-terminal.js +171 -162
- package/dist/orchestration/workflow-completion-inbox.d.ts +5 -19
- package/dist/orchestration/workflow-completion-inbox.js +0 -12
- package/dist/orchestration/workflow-notify-journal.d.ts +3 -2
- package/dist/orchestration/workflow-park-decision.d.ts +8 -3
- package/dist/orchestration/workflow-park-decision.js +5 -3
- package/dist/org-delivery-gate.d.ts +11 -0
- package/dist/org-delivery-gate.js +19 -1
- package/dist/parked-decide.d.ts +13 -9
- package/dist/parked-decide.js +7 -7
- package/dist/parked-revive-surface.js +1 -1
- package/dist/peer-inbound-face.d.ts +127 -0
- package/dist/peer-inbound-face.js +158 -0
- package/dist/permission-rule-list.d.ts +13 -9
- package/dist/permission-rule-list.js +7 -3
- package/dist/plugins/approval-ask-store-file.d.ts +14 -4
- package/dist/plugins/approval-ask-store-file.js +64 -11
- package/dist/plugins/approval-ask-store-memory.d.ts +2 -1
- package/dist/plugins/approval-ask-store-memory.js +17 -14
- package/dist/plugins/approval-ask-store-sql.d.ts +70 -23
- package/dist/plugins/approval-ask-store-sql.js +79 -30
- package/dist/plugins/checkpoint-store-sql.d.ts +4 -4
- package/dist/plugins/checkpoint-store-sql.js +9 -7
- package/dist/plugins/file-history-store-sql.d.ts +24 -18
- package/dist/plugins/file-history-store-sql.js +24 -19
- package/dist/plugins/file-run-store.d.ts +35 -1
- package/dist/plugins/file-run-store.js +108 -9
- package/dist/plugins/imported-layer-root-retirement.d.ts +82 -0
- package/dist/plugins/imported-layer-root-retirement.js +96 -0
- package/dist/plugins/local-checkpoint-store.d.ts +1 -1
- package/dist/plugins/local-checkpoint-store.js +2 -2
- package/dist/plugins/local-session-store.d.ts +42 -9
- package/dist/plugins/local-session-store.js +83 -33
- package/dist/plugins/local-task-attachment-store.d.ts +12 -2
- package/dist/plugins/local-task-attachment-store.js +67 -43
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +9 -31
- package/dist/plugins/mailbox-recipient-lifecycle.js +4 -0
- package/dist/plugins/mailbox-store-sql.d.ts +12 -8
- package/dist/plugins/mailbox-store-sql.js +76 -7
- package/dist/plugins/memory-key-guards.d.ts +3 -3
- package/dist/plugins/memory-run-store.d.ts +6 -1
- package/dist/plugins/memory-run-store.js +11 -1
- package/dist/plugins/memory-sync-store-pg.d.ts +15 -0
- package/dist/plugins/memory-sync-store-pg.js +21 -0
- package/dist/plugins/memory-sync-store-tidb.d.ts +2 -0
- package/dist/plugins/memory-sync-store-tidb.js +13 -1
- package/dist/plugins/one-time-migrations.d.ts +58 -2
- package/dist/plugins/one-time-migrations.js +161 -4
- package/dist/plugins/org-delivery-quota-store.d.ts +1 -1
- package/dist/plugins/org-delivery-quota-store.js +2 -12
- package/dist/plugins/park-commit-watch.d.ts +1 -1
- package/dist/plugins/permission-rule-store-file.d.ts +10 -1
- package/dist/plugins/permission-rule-store-file.js +15 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +31 -1
- package/dist/plugins/permission-rule-store-sql.js +35 -2
- package/dist/plugins/remote-env-device.d.ts +8 -11
- package/dist/plugins/remote-env-device.js +6 -3
- package/dist/plugins/remote-env-e2b.d.ts +23 -4
- package/dist/plugins/remote-env-e2b.js +111 -28
- package/dist/plugins/remote-env-k8s.d.ts +61 -22
- package/dist/plugins/remote-env-k8s.js +133 -33
- package/dist/plugins/remote-env-local-docker.d.ts +15 -3
- package/dist/plugins/remote-env-local-docker.js +40 -12
- package/dist/plugins/retention-store-sql.d.ts +2 -2
- package/dist/plugins/run-store-sql.d.ts +9 -1
- package/dist/plugins/run-store-sql.js +9 -1
- package/dist/plugins/sandbox-read-floor.d.ts +5 -7
- package/dist/plugins/sandbox-read-floor.js +2 -7
- package/dist/plugins/sql-errors.d.ts +10 -1
- package/dist/plugins/sql-errors.js +13 -0
- package/dist/plugins/store-backend.d.ts +33 -35
- package/dist/plugins/store-backend.js +10 -1
- package/dist/plugins/store-contracts.d.ts +50 -1
- package/dist/plugins/store-contracts.js +6 -0
- package/dist/plugins/task-attachment-store.d.ts +112 -14
- package/dist/plugins/task-attachment-store.js +207 -29
- package/dist/plugins/tool-result-store-sql.d.ts +9 -8
- package/dist/plugins/tool-result-store-sql.js +23 -2
- package/dist/plugins/wiring-section-codec.d.ts +32 -0
- package/dist/plugins/wiring-section-codec.js +55 -0
- package/dist/plugins/workspace-fill.d.ts +60 -0
- package/dist/plugins/workspace-fill.js +106 -0
- package/dist/project-bundle.d.ts +38 -0
- package/dist/project-bundle.js +609 -0
- package/dist/rule-entry-list.d.ts +3 -2
- package/dist/rule-entry-list.js +5 -1
- package/dist/rules-consent.d.ts +28 -5
- package/dist/rules-consent.js +40 -28
- package/dist/run-local.js +11 -13
- package/dist/runs.d.ts +12 -8
- package/dist/runs.js +6 -8
- package/dist/runtime-governance.d.ts +1 -1
- package/dist/sandbox-egress-policy.d.ts +4 -1
- package/dist/sandbox-egress-policy.js +3 -1
- package/dist/sandbox-git-plane.d.ts +31 -12
- package/dist/sandbox-git-plane.js +24 -4
- package/dist/security.d.ts +9 -0
- package/dist/security.js +8 -0
- package/dist/server-secret-env.d.ts +4 -0
- package/dist/session-error-wire.d.ts +36 -0
- package/dist/session-error-wire.js +13 -0
- package/dist/session-incarnation.d.ts +1 -1
- package/dist/session-notify-door.d.ts +106 -0
- package/dist/session-notify-door.js +93 -0
- package/dist/session-sync.d.ts +9 -14
- package/dist/session-sync.js +5 -5
- package/dist/session-workspace.d.ts +3 -13
- package/dist/session-workspace.js +0 -9
- package/dist/standing-answer-grant.d.ts +5 -0
- package/dist/standing-answer-grant.js +10 -0
- package/dist/stores-sql/session-policy-store-sql.d.ts +4 -2
- package/dist/stores-sql/session-policy-store-sql.js +3 -13
- package/dist/task-mcp.d.ts +1 -1
- package/dist/task-settings.d.ts +21 -10
- package/dist/task-settings.js +46 -13
- package/dist/terminal.d.ts +39 -19
- package/dist/terminal.js +65 -22
- package/dist/tool-approval.d.ts +56 -37
- package/dist/tool-approval.js +78 -71
- package/dist/trace/core-keyset-guard.d.ts +134 -14
- package/dist/trace/engine-notice-wire.d.ts +9 -3
- package/dist/trace/engine-notice-wire.js +7 -3
- package/dist/trace/exit-seat.d.ts +9 -2
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/ledger-sink.d.ts +10 -6
- package/dist/trace/ledger-sink.js +2 -2
- package/dist/trace/model-segment.d.ts +55 -25
- package/dist/trace/model-segment.js +101 -33
- package/dist/trace/project.d.ts +25 -5
- package/dist/trace/project.js +22 -0
- package/dist/trace/redact.d.ts +61 -9
- package/dist/trace/redact.js +1490 -468
- package/dist/trace/self-minted-wire.d.ts +745 -24
- package/dist/trace/self-minted-wire.js +239 -9
- package/dist/trace/wire-projection-faces.d.ts +2 -2
- package/dist/trace/wire-projection-faces.js +2 -2
- package/dist/verifier-pause-card.d.ts +33 -5
- package/dist/verifier-pause-card.js +15 -10
- package/dist/web-admin-client/apply-effective.d.ts +12 -16
- package/dist/web-admin-client/apply-effective.js +109 -9
- package/dist/web-admin-client/effective-keys.js +2 -0
- package/dist/web-admin-client/types.d.ts +4 -0
- package/dist/workspace-space.d.ts +19 -3
- package/dist/workspace-space.js +8 -4
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -1
- package/package.json +3 -2
- package/wire-changes/server@7.142.0.json +639 -0
- package/wire-changes/server@7.143.0.json +1167 -0
package/MIGRATION.md
CHANGED
|
@@ -7,6 +7,663 @@
|
|
|
7
7
|
> ⚠️ 完整清单在仓库根 `CHANGELOG.md`——它**不随 npm tarball 出包**(本文件随包)。看完整迁移窗的
|
|
8
8
|
> 权威姿势是源码 tag diff:`git diff v<旧>..v<新>`(每版都推 `v<版本>` tag);npm 包页也镜像 CHANGELOG。
|
|
9
9
|
|
|
10
|
+
## 7.143.0 —— `wiring_manifest` 帧的容器段在 run 店 File 孪生按会话块账本去重(持久面;体量;回滚地板 = 本版) · env 两槽 × 目录:本地根首份管模型面目录的首次写入决定文档(K0)、`planeRefusalCode` 只答最新候选、leader 路由模型经服务表解、env cheap 槽悬空一次性 warn(配置面;行为收紧) · 🔴 部署治理的装配相容性门改在部署 MCP 服务器 / A2A 对端物化之后判:`mcp` / `a2a` 锁、合规否决 `mcp_servers` / `a2a_peers` 撞上部署自带的服务器 / 对端 ⇒ 起服拒(行为收紧,fail-closed;部署面) · 运维审批队列行带族名 `kind`、被扣的跨会话来信作 `peer_inbound` 行进审批席(wire 加性;🔴 消费方先按 `kind` 分支) · k8s 车道:停驻时沙箱从未起过的停驻,续跑改作一次新连接(空间开 ⇒ 恢复 `latest`);打包过的停驻快照对象不在 ⇒ 一行 `workspace_latest_dangling`(`lane: "park"`)+ 空目录;更正 7.142.0 节第 9 条尾的已知限制(行为修复;运维面日志加性) · 订正 7.141.0 节第 1 条的「谁受伤」:结构化 warn 只覆盖本服务写的那一行,网关密钥被拒收时引擎另说一行裸 `console.warn`(引擎已知限制),logger 接上后的那一行受 `LOG_LEVEL` 约束(文字订正;零行为变更) · 🔴 SQL 后端 `task_attachment` 加一列生成列 `seed_session_id` + 唯一索引 `uq_att_seed`:一只会话一只种子改由唯一键判,已有种子会话上的并发提交恒答 409(行为修复;DDL 升级前先加列;wire 零变化) · 续跑请求可重述对端表:四道续跑门收提交体同键的 `mcpServers` / `a2aPeers`,缺席 = 冻结读法(wire 加性;行为面;壳宜每次续跑送当前表) · 🔴 活流模型文本过同一只脱敏器:`text_delta` / `reasoning_delta` 逐块帧只放已判定的字节,拼接 = 段末帧正文 = `done.result`,段末余下的字节一帧补齐(wire 值语义;安全) · 会话读面(视图 · 记忆状态 · 记忆抹除 · 头探针 · 事件流 · 执行放置)对「文件后端上行事实没有落下、存档又读不出」的会话,从 500 `corrupt_session` 改答 404 `not_found.session`(与对非属主、对不存在的会话同一只;原故障进运维日志 `session_owner_unreadable`;行为面;应答格状态变化) · 中心 MCP 声明撞同一工具命名空间前缀:同步提交腿从 `200` + `failed` 体改 `409 config.mcp_server_name_collision`,`GET /v1/capabilities/mcp` 从无码 `500` 改同码同状态同句(wire 码与状态变;按 HTTP 状态分支的提交方看一眼) · 🔴 持久 ask 店车道上 askId 的身份含这一问展示给人的动作(工具名 + 入参摘要):同一 run 同一腿里复用调用 id、换了入参或换了工具的那一问出自己的卡(安全轴;行为收紧;不透明 `askId` 值变;零 DDL) · 🔴 `POST /v1/approvals/:sessionId/decide` 的 `boundCallId` 与 `boundInputHash` 两位必带,缺哪位 400 `decide_requires_binding` 点名哪位;不再拿当前停驻行补;`remember_requires_binding` 退役(BREAKING 行为面;安全轴;决断方回显队列行上的那一对) · 订正 7.142.0 节第 18 / 19 条的两处读数说法:坏块 / 撤块时能力位读 `no_caller_credential`(`no_origins` 是平面的第九条前提);强锚名紧贴前一枚凭据尾巴那一形在 7.142.0 上于 `GET /v1/runs/:id/events` 回放的 `tool_end` 行与活流逐块帧明文(文字订正;零行为变更;这一形本版起已修,见第 41 条) · 会话记忆同步触发口的 409 `conflict.session_memory_unobserved` 体恒带 `reason`:最近一条已结 run 的记录里没有记忆观测 ⇒ 点名它的记录里有什么、句子给出路;🔴 它配了记忆而没挂上(`memoryless`)⇒ 由 200 空报告改 409 `memory_not_mounted`;读集仍只读最近一条已结 run(wire 加性;行为面;三句拒句换形 / 新句;零 DDL;部署零动作) · 🔴 引擎 7.61.0:升级前结清在途审批、排空旧 worker,mod 包按契约 7 重建(部署面;BREAKING) · 🔴 审批卡的委派子代出处键 `sourceTaskId` 改名 `sourceSessionId`(wire BREAKING;零别名) · 通告码 `context.image_removed` 改名 `context.media_removed`、TaskOutput 退役(wire 码改名;策略名单) · 设备车道放置围栏 + 协议修订 4 `symlink_loop`(行为面;wire 加性) · SQL 后端新表 `mailbox_consumed`(起服自建) · `DB_BACKEND=local` 工具结果按 TTL 回收(行为变化) · blob 上传哈希不符一律 400、嵌入方两只店换新组形(wire 值变化;类型面 BREAKING) · 记忆同步:别的 scheme 里的 URL userinfo 也判凭据(行为收紧) · 设置导入:用户层 `/` 形路径规则留在文件里(行为收窄)、导入预览的用户层不收 `root`(wire BREAKING) · 🔴 SQL 后端 `approval_ask` 加一列 `decided_via`、决定体加性键 `decidedVia`、能力位 `approvalDecidedVia`(wire 加性;DDL 升级前先加列) · `verify:true` 任务的上限封住实现腿与各轮修复的合计,花光 ⇒ 不再修复(行为收窄;wire 加性) · 订正 7.139.0 节第 24 条 ③:没配包装的 worktree 子代仍由本服务拒(文字订正;零行为变更) · 嵌入方包 `resolveSpec` 的包装须返回同一只对象(嵌入方行为面 BREAKING) · 验证器自己停驻的那张卡改由引擎的作废动词结算、会话钉随之放掉,编排(leader)路径同样作废(行为面;修复;部署零动作;订正 7.141.0 节第 31 条的两条已知限制) · `settings.permissions.allow` 的条目也可带出处层,user 层的 `/` 形 allow 读在执行环境的配置根(wire 条目型放宽 + 能力位;端见位才发;收掉 7.141.0 节第 15 条「已知限制」的 allow 那一半) · 后台子代一个 id:面板 / 完成通知 / 孙代嵌套 / 审批归属都读注册表行 id;升级与回滚前各让停驻的后台子代结清(行为面;部署面) · Runner 之外复活的后台子代(停驻赎回 / 操作员续跑)的完成走委派树根会话的会话通知门(行为修复;wire 零新键) · 🔴 记忆同步:中心每个层分区一只化身、同步口改到 `/v2/memory/sync/:scope`、本机游标原样携带化身(引擎三处硬破坏;中心库新表起服自建;部署:两端同版 + 停驻层删游标) · 🔴 抹除与会话记忆状态答整个部署(`409 memory.erasure_store_unjudged` 与会话自助抹除体的 `scope` 退役;嵌入方类型面 BREAKING) · 🔴 规则店:引擎 7.61.0 之前从用户层设置导入的、从 `/` 写起的全局放行起服即退役(按 add;deny / ask 不动;一次性迁移 M36,每次起服幂等;持久数据面;行为收紧;部署零动作) · 本地导入载体的 deny / ask 在 prepare 当场落店、预览成员带 `outcome`,放行仍在 redeem 落;收紧写不进 ⇒ 整批 503、放行扣下(行为面;wire 加性) · 自由文本脱敏的取证读法按出处读:一枚凭据不拿自己上一轮的读数当证据、私钥收尾栅栏落在不完整读数里两读取并、SSH2 块之后紧跟的孤立收尾之前读作无头体、取证级数界 32 到顶整段遮(行为面;安全;脱敏产物可能变;运维面多一个 fail-open 标签) · 🔴 审批卡的断连重放帧与活铸帧同事实:问行卡信封加一座 `liveFacts`,断连重放的 `approval_request` 带活铸帧顶层的同一组卡外事实;本版之前铸的行重放帧带 `liveFactsUnknown: true`(安全轴;wire 加性;存形加性,零 DDL;🔴 多副本先停光旧副本再让本版接流量) · 🔴 自由文本脱敏的名字面:复合凭据名(`api_key=` 一族)在自由文本的声明形里是名字锚、名字的左界止于前一枚已认出凭据的终点(紧贴形首遍即遮、各出口同读)、不带引号的值里面的赋值照问(行为面;安全;脱敏产物变;带这些赋值的命令不再给常驻放行;部署零动作) · 运行时依赖 `@modelcontextprotocol/server` 2.4.0(npm 安装多一只包;部署零动作)
|
|
11
|
+
|
|
12
|
+
1. **`DB_BACKEND=local`:run 账本里每条 run 的装配清单(`wiring_manifest` 行)按会话去重存 —— 容器段存进每会话一只块账本 `<数据根>/run-blobs/<会话>.jsonl`,行里只留引用(持久数据面:存形加性,存量不迁移;wire 与读面零变化;回滚地板 = 本版;部署零动作)**:
|
|
13
|
+
旧形:`runs/<taskId>/events.jsonl` 里每条 run 的 `wiring_manifest` 行带一整份清单(名册、MCP、技能……;实测每行约 37–44 KB,同会话每条 run 一份,占 run 账本约八成)。
|
|
14
|
+
新形:这一行里值为对象 / 数组的段换成 `{ "$blob": "sha256:<64 hex>" }`,段体按会话在 `run-blobs/<会话>.jsonl`(一行一只 `{ digest, body }`;文件名 = 会话 id 的可读前缀 + `-` + 会话 id 的 sha256)里只存一份 —— 没变的段跨 run 共用一块,变了的段多一块;
|
|
15
|
+
标量段与 `eventId` 照旧在行里。`GET /v1/runs/:id/events`、run 事件流、会话 MCP 面板与其余经 run 店的读口读到的仍是整帧,逐字段与以前相等(同一段的嵌套键序取首次存下的那一份)。
|
|
16
|
+
升级前写下的整帧行不改写、照常读;从本版起新写的行是引用形 —— 账本只向前缩,旧会话随删会话回收。删会话先删这只块账本、再删各 run 目录;
|
|
17
|
+
块账本删不掉(权限 / 挂载)⇒ 这次删会话整次答错误、一样都不删,修好之后重试即可。
|
|
18
|
+
块账本缺行 / 坏行(断电丢尾、手工改动)⇒ 引用它的那一帧读不出:读口不交出这一帧(其余帧照交;不交出缺段的清单),计数 `fail_open_total{tag="server.run-store.corrupt-record-skipped"}` 每帧每进程一次;
|
|
19
|
+
块账本整份读不出(权限 / 挂载)与 `events.jsonl` 读不出同一条路:`RUN_STORE_STRICT_HYDRATE=on` 拒启并点名路径,否则起服原样抛。
|
|
20
|
+
直读 `events.jsonl` 的离线工具(取证脚本、按行统计)从本版起读到引用形:要整帧就经 `GET /v1/runs/:id/events` 读,或按 `run-blobs/<会话>.jsonl` 的 `{ digest, body }` 自行换回。
|
|
21
|
+
**谁需要**:长会话的 local 车道(run 账本的盘面、起服堆与读盘随 run 数线性长,其中约八成是重复的清单)。**谁受伤**:直读 `events.jsonl` 的离线工具(见上);回滚到上一版(见下)。
|
|
22
|
+
**补偿**:直读账本的离线工具改经 `GET /v1/runs/:id/events` 读整帧,或按 `run-blobs/<会话>.jsonl` 的 `{ digest, body }` 自行换回;回滚只伤回放面,再升回本版即复原。**升级前做**:无。**回滚地板 = 本版**:本版写过的数据根回到上一版,旧二进制读得出账本但不认引用 —— 回放面(`GET /v1/runs/:id/events`、事件流重连)上本版写下的 run 的清单段显示成 `{ "$blob": … }`,
|
|
23
|
+
会话 MCP 面板对这些 run 读成缺席;活 run 不受影响(旧二进制整帧写)。再升回本版即复原(块账本还在)。旧二进制删会话不删 `run-blobs/` 里的块账本 —— 留下的只占空间。
|
|
24
|
+
|
|
25
|
+
2. **🔴 本地配置源:一份管模型面的 `config.d/models.json`,在设了 `MODEL_ID` 时只有配置根的 `config.env-models.json` 读作 `replaced` 才顶替 env 模型表;升级的本地根由起服时的一次性迁移铸这份确认(行为收紧;升级之后才写下目录的根要写一份确认;中心配置源零变化)**:
|
|
26
|
+
— **谁受影响**:`CONFIG_PROVIDER=local`(含 `run-local` / `sema` CLI)、设了 `MODEL_ID`(env 模型表已声明;严格名册布防 `CONFIG_REQUIRE_ROSTER=true` 时 env 表是占位,不算)、`config.d/models.json` 有启用条目的配置根。中心配置源不守卫:中心发布的目录照旧整表顶替 env 表。
|
|
27
|
+
— **配置根**就是放 `config.d/` 的那个目录(`CONFIG_LOCAL_DIR` → `AGENT_DATA_DIR` → `~/.ai-agent`)。决定文件 `<配置根>/config.env-models.json`,两种写法 `{"envModels":"replaced"}`(目录顶替 env 表)/ `{"envModels":"kept"}`(env 表保留);
|
|
28
|
+
缺席读作 `kept`;读不懂(坏 JSON / 坏形 / 读不出)从不读成确认(每份内容每进程一行 warn `config_env_models_unreadable`)。
|
|
29
|
+
— **升级时自动做的**:本版第一次起服(读本地配置之前、目录信任判官之后)在每个本地配置根上跑一次契约包的迁移:独占创建运行记录 `<配置根>/config.migration.SS-M11.json`;决定缺席且 `config.d/models.json` 此刻管模型面 ⇒
|
|
30
|
+
铸 `{"envModels":"replaced"}` —— 升级前「目录顶替 env 表」的读法原样保住:info `config_dir_migrated` 记一条收据,env 模型已声明时再一行 warn `config_env_models_replaced_by_migration` 点名从此被顶替的 env 模型。
|
|
31
|
+
根不在 ⇒ 以 `0700` 建出(只放运行记录,不建 `config.d`)。运行记录在场之后迁移不再跑,决定缺席就是 `kept`。
|
|
32
|
+
— **升级后要动手的几形**:① 升级时还没有管模型面的目录、之后才写下第一份的根(含新装):这份目录的模型面被拒 ——
|
|
33
|
+
`/health.modelRefusals.plane` = `config.catalog_replaces_env_models`,`GET /v1/models.modelPlane` = `{ "servedTable": "env", "catalog": "refused", "planeRefusalCode": "config.catalog_replaces_env_models" }`,warn `web_admin_model_plane_refused` 点名路径与出路;
|
|
34
|
+
env 模型继续服务,同一份目录的其余配置照落。要让目录顶替 env 表:写 `config.env-models.json` = `{"envModels":"replaced"}`(下一个刷新拍或 `POST /v1/admin/config/refresh` 生效,不用重启),或撤掉 `MODEL_ID` / `MODEL_CHEAP_ID`。
|
|
35
|
+
② 升级时 `models.json` 读不出(权限 / I/O)或确认写不成:warn `config_env_models_mint_failed` 带手工恢复句,之后同 ① 处置。③ 只读配置根:运行记录建不成 ⇒ 不铸,每次起服重跑、每进程一行 warn `config_dir_migration_failed`;手写的决定照常生效。
|
|
36
|
+
④ 运行记录读不懂 ⇒ warn `config_env_models_marker_unreadable`,按已跑处置。
|
|
37
|
+
— **撤销**:要回到 env 模型,删掉决定文件或写 `{"envModels":"kept"}`,再**重启**:运行中的进程在下一个刷新拍对目录判组拒(`planeRefusalCode` 在场),但组拒不降档 —— 在服的那一代目录照旧服务,env 模型在下一次起服才回来。删掉运行记录再起服 ⇒ 迁移重跑,决定缺席即重铸。
|
|
38
|
+
— **目录信任**:根上这两份文档与 `config.d` 下的文档同一套判据(属主只能是本服务的用户 / root / `CONFIG_LOCAL_OWNER_UID`,不得组 / 他人可写,常规文件,≤ 16 MiB),不过 ⇒ 拒启 `[config.dir_untrusted]`;`config.d` 缺席时也判到根。手写决定文件后核一下模式位(`chmod go-w`)。
|
|
39
|
+
— **跳版**:迁移随契约包下一个大版本删除;在那之后才第一次升到本系列的根没有迁移替它铸确认,管模型面的目录被拒,按 ① 处置。
|
|
40
|
+
— **回滚**:回到上一版 ⇒ 决定文件与运行记录不被读(目录照旧整表顶替 env 表);两份文件留在盘上,再升回本版照读。
|
|
41
|
+
**谁需要**:同一个本地配置根上既声明 env 模型、又放目录的部署(目录顶不顶替 env 模型由盘上一份文件说)。**谁受伤**:如上 ① – ③。**出路**:如上。
|
|
42
|
+
|
|
43
|
+
3. **`GET /v1/models.modelPlane` 加性键 `planeRefusalCode`;`catalog: "refused"` 的模型面那一半改读最新到达的候选(wire 加性;wire 值语义收窄;部署零动作)**:
|
|
44
|
+
`planeRefusalCode` 在场 ⇔ 最新到达的目录候选被模型面组拒,值 = 那一拒的码(契约包 `MODEL_PLANE_REFUSAL_CODES` 之一);`catalog: "refused"` 而本键缺席 ⇔ 最新到达的候选被候选判官整拒(看同一应答的 `candidateRejected`)。
|
|
45
|
+
此前 `catalog` 的模型面那一半读 `/health.modelRefusals.plane`:更新的候选到了而没走到模型面那一判(被候选判官整拒,或过了判官、却在换装时被拒)时,旧候选的组拒仍让 `catalog` 答 `refused`;
|
|
46
|
+
本版起这一形改按在服的表答(`adopted` / `absent`),那一份换装失败只在 `/health` 的世代账(target ≠ applied)里看得见(与「装配期被引擎整份拒收」同一形,本版仍没有座)。`/health.modelRefusals.plane` 的读法不变(最近一份被判过的模型面的组拒判决,不随更新的到达撤)。
|
|
47
|
+
同一只路由判官的码可能同时出现在 `planeRefusalCode` 与 `refusalCode`:前者指最新到达的候选目录,后者指此刻在服的那张表。
|
|
48
|
+
**谁需要**:读 `modelPlane` 判「刚写 / 刚发布的目录为什么没落」的壳与控制台。**谁受伤**:把 `catalog: "refused"` 读成「上一份被拒的目录还挂着」的消费方。
|
|
49
|
+
**出路**:用 `planeRefusalCode` 与 `candidateRejected` 分两种拒;要问「最新候选落没落」读世代账。**升级前做**:无;**回滚**:键消失,`catalog` 回到旧读法。
|
|
50
|
+
|
|
51
|
+
4. **leader 路由腿:没有 `MODEL_ROUTER_ID` 时在服务表里解 `classifier` 角色(classifier → summarize → default),不再钉 `MODEL_CHEAP_ID` 的名;目录采纳后悬空的 env 角色绑定每名一行 warn(行为面;运维面日志加性;部署零动作或目录里一行绑定)**:
|
|
52
|
+
纯 env 部署:路由腿仍跑在 `MODEL_CHEAP_ID` 的模型上(env cheap 槽绑 `summarize`),没有 cheap 槽仍跑主模型 —— 零变化。采纳了目录的 leader 部署:路由腿跑目录自己的 `classifier` 绑定,没有就 `summarize`,都没有就目录缺省(此前钉的 env cheap 名不在目录表里)。
|
|
53
|
+
要路由跑便宜模型:在目录 `roles` 里把 `classifier`(或 `summarize`)绑到一条便宜条目、激活 `flash` 档,或设 `MODEL_ROUTER_ID=<目录条目名>`(按名在服务表里解,与此前同)。
|
|
54
|
+
leader 的每一只 Runner(修复 / 路由 / worker 腿)从本版起带档位表,角色在档位展开的视图里解,与主 runner 同答:激活了档位的部署上,worker 腿里按档位缺省解的角色(委派子代 / 压缩)从此解到档位绑定的条目(此前落到缺省模型)。
|
|
55
|
+
同版:目录的模型面落地时,env 角色底里目录没覆写的角色(`MODEL_CHEAP_ID` 绑的 `subagent` / `summarize`)绑的名不在这份目录(档位展开后)里 ⇒ 每个名每进程一行 warn `config_env_role_binding_dangling { model, env, roles, engineNotice: "model.role_defaulted" }`;
|
|
56
|
+
选模不变(引擎读作未设、沿角色链回落,每个任务一条 `model.role_defaulted`)。出路同上:在目录里绑这些角色,或让目录里有一条叫这个名的条目。**回滚**:路由腿回到 `MODEL_ROUTER_ID || MODEL_CHEAP_ID`,warn 行消失。
|
|
57
|
+
**谁需要**:采纳了目录的 leader 部署 —— 路由腿跑在这份目录里真有的条目上(此前钉的 env cheap 名不在目录表里);运维在目录落地那一刻读到哪一条 env 角色绑定悬空,而不是只在每个任务的 `model.role_defaulted` 里零散读到。
|
|
58
|
+
**谁受伤**:采纳了目录、目录里既没绑 `classifier` 也没绑 `summarize`、又没激活 `flash` 档、却指望路由腿跑 `MODEL_CHEAP_ID` 那只便宜模型的 leader 部署 —— 路由腿改跑目录缺省模型;激活了档位的 leader 部署 —— worker 腿里按档位缺省解的角色改解到档位绑定的条目。
|
|
59
|
+
**补偿**:在目录 `roles` 里绑 `classifier`(或 `summarize`),或设 `MODEL_ROUTER_ID=<目录条目名>`;warn 行点名悬空的名与它绑的角色。
|
|
60
|
+
|
|
61
|
+
5. **🔴 部署治理的装配相容性门改在部署 MCP 服务器 / A2A 对端物化之后判:`LOCKED_CONFIG_KEYS` 的 `mcp` / `a2a` 锁、合规否决 `mcp_servers` / `a2a_peers`,撞上部署自带的服务器 / 对端(`config.d/mcp.json` 或中心下发)⇒ 起服拒(行为收紧,fail-closed;部署面;落在这四形里的部署要动手)**:
|
|
62
|
+
— **此前**:USAGE「部署治理三声明」写明的两形启动期拒 —— `LOCKED_CONFIG_KEYS=mcp` + 部署自己配了 MCP 服务器、合规档位禁 `mcp_servers` + 部署自己配了 MCP 服务器 —— 在 HTTP 服务上从未发生:
|
|
63
|
+
判据在部署 MCP 基线读进来之前就跑完了,于是这两形照常起服,而每条任务在引擎门口被拒 —— 锁形答 `400 config.locked_key`(不带 `mcpServers` 的任务也一样),否决形落 `200` 失败体(`config.compliance_denied`),部署自带的服务器零拨号。
|
|
64
|
+
同族的 `LOCKED_CONFIG_KEYS=a2a` / 否决 `a2a_peers` + 中心下发的 A2A 对端同样只在任务腿上撞拒(判据此前不看这两项)。`run-local` / `sema` 的 MCP 两形早已在启动时拒(零变化)。
|
|
65
|
+
— **本版**:四形都在起服时拒(进程退出码 1;句子点名那把锁 / 那条否决与两条出路),与 `toolPolicy` 锁、单用户形禁 `web_fetch` 同一只判据、同一个出口。判据的时点挪到部署基线物化之后:`toolPolicy` 锁与单用户禁 `web_fetch` 两形照旧拒启,
|
|
66
|
+
只是拒的那一刻在起服序列里稍晚(仍早于场景装配、reaper 与 HTTP 监听)。`enabled: false` 的条目、引用的 env 名在本服务上缺席而被跳过的条目不算「配了」。
|
|
67
|
+
— **升级前做**:落在四形里的部署二选一 —— 去掉锁 / 否决(`LOCKED_CONFIG_KEYS` 里删 `mcp` / `a2a`,`COMPLIANCE_ADDITIONAL_DENIES` 里删 `mcp_servers` / `a2a_peers`),或去掉部署自带的服务器 / 对端(`config.d/mcp.json` 的条目、中心 `mcp` / `a2a` 域的条目)。
|
|
68
|
+
中心侧之后再加服务器 / 对端仍是 restart-to-apply:落进这四形的那一次变更让滚动重启的新副本起服拒(旧副本照跑),出路同上。
|
|
69
|
+
**谁需要**:配了锁或合规档位的部署 —— 配错的组合在起服时点名,而不是起得来、任务全失败。**谁受伤**:落在四形里、服务器 / 对端只挂在某几个场景上、其余场景的任务今天照常服务的部署 —— 升级后整台起不来。
|
|
70
|
+
**出路**:同「升级前做」;要锁住请求自带的 MCP / A2A 而保留部署自带的,本服务没有这一形(引擎的锁守的是同一个字段)。**回滚**:HTTP 服务回到上一版 ⇒ 四形照旧起服、任务腿照旧撞拒(`run-local` / `sema` 上 MCP 两形在上一版就拒启,回滚不改)。
|
|
71
|
+
|
|
72
|
+
6. **🔴 运维审批队列的行带族名 `kind`(闭集 `checkpoint` | `peer_inbound`);被扣下、等收信方审的跨会话来信作 `peer_inbound` 行进 `GET /v1/approvals` 的 `pending[]` 与 `/v1/approvals/stream`,经同一决断口 `POST /v1/approvals/:id/decide` 批 / 拒(wire 加性;🔴 按「每一行都是停驻门」写死的消费方要先按 `kind` 分支;部署零动作)**:
|
|
73
|
+
`pending[]` 的每一行与流上的 `pending` / `resolved` 帧从本版起带 `kind`:停驻门的行 `kind: "checkpoint"`,其余键与上一版逐字同;新族 `peer_inbound` = 收信会话的权限档对等判扣下的跨会话来信
|
|
74
|
+
(发信方的权限档与收信方对不上,成因 `mode-mismatch` / `no-mode-asserted` / `invalid-mode-attestation`),行键 `id` / `recipientSessionId` / `lane` / `cause` / `content` / `sentAt` / `heldAt` / `fromSession?` / `fromName?` / `fromScope?`,**没有** `sessionId` / `toolCallId` / `riskDescriptor` / `deadline`。
|
|
75
|
+
决断口 `:id` = 行的 `id`(`peer_inbound:` 前缀,不透明),体只收 `{ decision: "approve" | "deny" }`(其余键 400 点名拒),答 `200 { kind, id, outcome }` / `404 not_found.approval` / `503 state.peer_decision_unrecorded`(新码,可重试)。
|
|
76
|
+
`resolved` 帧按族:`checkpoint` 族带 `sessionId` + `toolCallId`(同上一版,另加 `kind`),`peer_inbound` 族带 `id`。`synced.count` 数 `pending` 车道全部行(两族同计)。
|
|
77
|
+
部署策略扣下的信(`CROSS_SESSION_INBOUND=hold`)**不进**审批席(组织策略不由收信方逐封越过);只有收信方本人列得出、决得了(operator 不多看)。行是**本副本**进程内投影(跨副本看不到,同 `livePending`);有序关停把仍被扣的信以 `expired` 结清并回执发信方。
|
|
78
|
+
**谁需要**:用跨会话通信、收发两方权限档会不一致的部署 —— 此前被扣的信只能等到期,收信方没有任何面能放行或拒绝。
|
|
79
|
+
**谁受伤**:按 `pending[]` 每一行都是停驻门写死的消费方(读 `row.sessionId` 去 `/decide`、读 `riskDescriptor`、按 `(sessionId, toolCallId)` 消 `resolved`)—— 一行 `peer_inbound` 到来时读到缺席。
|
|
80
|
+
**出路**:先按 `kind` 分支;不认识的 `kind` 跳过该行、不要拿它去 `/decide`(契约 §0.11)。**升级前做**:无;**回滚**:`kind` 键与 `peer_inbound` 行消失,被扣的信回到只能等到期。
|
|
81
|
+
|
|
82
|
+
7. **k8s 车道:停驻时沙箱从未起过(什么都没打包)的停驻,续跑改作一次新连接 —— 空间开着就等上一条提交、按 `latest` 恢复;打包过的停驻快照对象不在 ⇒ 一行 `workspace_latest_dangling`(`lane: "park"`)+ 空目录;更正 7.142.0 节第 9 条尾的「已知限制」(行为修复;运维面日志加性;部署零动作)**:
|
|
83
|
+
此前:run 在首次碰到沙箱之前就停驻(pod 还没起)⇒ 停驻快照 id 下没有对象;续跑走停驻车道、取包得 404,读作「空快照」⇒ 新 pod 上的空目录,不读空间的 `latest`。
|
|
84
|
+
空间开着(`WORKSPACE_PERSIST=space`,缺省)时这条腿的 run 末提交随后覆写 `latest` ⇒ 此前各条 run 的改动从下一条 run 起不在了,且不报警。
|
|
85
|
+
同一个 404 也是「打包过的停驻快照被桶的生命周期规则 / 手工删掉」的读数 —— 两件事一样静默。
|
|
86
|
+
现在:停驻快照 id 自己说清打包没打包 —— `kata-<记号>-…` = 打包过(此前铸下的 id 都是这一族);`nopack-<记号>-…` = 停驻时没有 pod、什么都没打包,桶里从不放对象。
|
|
87
|
+
— `nopack-…` 的续跑 = 一次新连接(与 run 首次碰沙箱同一条走法),这种 id 下不发任何取包请求:空间开 ⇒ 等上一条提交落定、读 `latest`,在 ⇒ 恢复(不播种),不在 ⇒ 空目录(播种);
|
|
88
|
+
空间关 ⇒ 空目录(播种,同此前);没有这只会话 ⇒ 空目录 + 一行 `workspace_space_unavailable`(此前续跑不出这行);读住客 / 提交围栏 / `latest` 失败 ⇒ 续跑 `connect_failed`(与连接同句,引擎按续跑重试)。
|
|
89
|
+
— `kata-…` 的续跑照旧取包;对象不在 ⇒ 一行 `workspace_latest_dangling`(`lane: "park"` / `key` / `sessionId` / `effect`),与空间 `latest` 悬空同一行名、同一条规则(响亮、可继续),这条腿从空目录开始(播种);
|
|
90
|
+
空间开着时它的 run 末提交成为新的 `latest`。空间那一臂的同一行多一个字段 `lane: "space"`(其余字段不变)。
|
|
91
|
+
**升级窗**:升级之前铸下的停驻 id 都是 `kata-…` 形(那时还不区分):升级时仍停驻着、而停驻前 pod 还没起的 run,续跑读到的是「打包过、对象不在」⇒ 一行 `workspace_latest_dangling`(`lane: "park"`)+ 空目录 ——
|
|
92
|
+
工作区与此前同,多一行;空间开着时它的 run 末提交仍覆写 `latest`(只这一窗;升级之后的停驻不再如此)。
|
|
93
|
+
**谁需要**:k8s 车道上空间开着、用耐久审批(停驻 → 续跑)的会话 —— 在首次碰沙箱之前就停驻的 run(首个工具就要审批、计划审阅)续跑后看得到此前各条 run 的文件,run 末提交不再把它们冲掉;想看见停驻快照被清走的运维。
|
|
94
|
+
**谁受伤**:按 `workspace_latest_dangling` 告警的运维:停驻快照的悬空也报这一行;升级窗里停驻着的那几条 run 续跑时各报一行(见上)。
|
|
95
|
+
**出路**:告警按 `lane` 分两类;升级窗那几行按 `key` 里的会话 id 对账即可。**回滚**:回到上一版 ⇒ `nopack-…` 的停驻在旧二进制上续跑取包得 404 ⇒ 旧形(空目录、不报警);`kata-…` 不受影响。
|
|
96
|
+
**更正(7.142.0 节第 9 条尾,文书)**:那一条的「已知限制」—— 空间开着时停驻在先、续跑不恢复 `latest`、run 末提交覆写此前改动且不报警 —— 自本版起不再成立(本条即其修法);7.142.0 节原文不改(已发节字节不动)。
|
|
97
|
+
|
|
98
|
+
8. **更正(7.141.0 节第 1 条「谁受伤」,文书;零行为变化)**:该条说起服自有凭据值被引擎拒收「此前是一行裸 stderr 文本,现在是日志器的一行 `warn` `own_credential_value_not_withheld { name, reason }`」—— 说的是**本服务自己**写的那一行,这一半不改。没写全的是另两件事(亲读:真主进程起服,7.141.0 标签与本版读数同形):
|
|
99
|
+
① **网关密钥**(`MODEL_API_KEY` / `ANTHROPIC_API_KEY`,起服交给模型适配器的那一个)被引擎判「不是凭据值」(占位词 / 不足 8 字符 / 一个字符重复)时,进程输出里除这一行结构化 `warn`,**还有一行引擎写的裸文本**:
|
|
100
|
+
`a credential the engine was handed is … — it is used as given, but a variable holding the same string is not withheld from a spawned child (said once per value; the value is not repeated)`。
|
|
101
|
+
引擎在适配器构造口收下网关密钥的那一刻对同一个值「每进程每值说一次」,而这个收值口没有通告席(适配器的配置没有通告位),引擎落它自己的 `console.warn` —— 引擎文档把这一形列为已知限制(无席的收值口共四个:适配器构造 / 请求路由读 / 对端拨号 / 直建蒸馏座)。
|
|
102
|
+
本服务不是这一行的写者、也无席可接,不在引擎外面吞 `console`;引擎不收的自有凭据变量(例如 `SERVICE_AUTH_TOKEN`,本版真主进程读数)被拒时只有结构化那一行。两行说的是同一个值同一件事,都不带值;本服务这一行点名变量,引擎那一行只说哪一类。
|
|
103
|
+
② 结构化行走日志器:起服第一步(日志器未建)的那一行当拍写 stderr,不受 `LOG_LEVEL` 约束;日志器接上之后(模型目录换代并进的条目的值被拒)受 `LOG_LEVEL` 约束 —— `error` 级读不到,而此前的裸 `console.warn` 无条件出。
|
|
104
|
+
**谁需要**:读这件事告警的运维。**谁受伤**:① 以为 7.141.0 之后这件事在 stderr 里只剩 JSON 行的日志管线 / 告警规则(把「不是 JSON 的行」当异常、或按行解析 stderr 的)—— 网关密钥是占位词时仍会读到引擎那一行(7.141.0 与本版同形,不是新回归);② `LOG_LEVEL=error` 的部署:换代并进条目的值被拒那一行读不到。
|
|
105
|
+
**补偿**:给网关密钥一个真值(至少 8 字符、不是占位词)—— 引擎与本服务的两行一起消失;按事件名 `own_credential_value_not_withheld` 与字段 `name` 筛本服务的行;机读事实读 `GET /v1/capabilities` 的 `inherit_env.own_credential_values_withheld`(一个值没按值扣 ⇒ false,不随日志级走);`LOG_LEVEL` 至少 `warn`。
|
|
106
|
+
引擎一侧那一行等引擎给收值口一席、或让声明口拒收的值记作已说,本服务再接;在此之前它是引擎的,本版不改。7.141.0 节原文不改(已发节字节不动)。
|
|
107
|
+
|
|
108
|
+
9. **🔴 SQL 后端:`task_attachment` 加一列生成列 `seed_session_id` 与唯一索引 `uq_att_seed` ——「一只会话一只种子」改由表上的唯一键判;已有种子的会话上的并发提交恒答 `409 attachment.bundle_seed_fixed`,不再撞死锁 / 锁等待成店错(行为修复;DDL:升级前先加列,先升库再升副本;wire 零变化;订正 7.142.0 节第 10 条的「已知限制」)**:
|
|
109
|
+
— **此前**:SQL 两方言判「这只会话有没有种子」用的是一只事务里的锚读:按 id 序加锁读全部未绑的项目包与本会话的项目包,再加锁读这只包自己的行。两只并发事务的取锁序可以反向,引擎挑一只输家回滚,
|
|
110
|
+
店最多重来 4 次,被反复挑中的那只把店错抛给调用方(PG `40P01`);任何一只未绑的项目包(不论哪个会话、哪个属主)被别的事务长时间锁住时,项目包绑定在锁等待上限处答店错(MySQL 协议 `1205`、PG `55P03`)。
|
|
111
|
+
— **本版**:每一行的绑定都是同一条带谓词的 `UPDATE`;「一只会话一只种子」是表上的唯一键 —— 生成列 `seed_session_id` = 项目包行的 `session_id`(其余行 NULL;库从 `mime` 与 `session_id` 推导,本服务不写它),
|
|
112
|
+
唯一索引 `uq_att_seed` 在它上面,第二只项目包的绑定被库以唯一键冲突拒,答 `409 attachment.bundle_seed_fixed`。一次绑定只碰要绑的行与这只会话在唯一键上的那一个值:已有种子的会话上的提交不等别的会话 / 别的属主的行即答 409(只在这只会话自己的种子行正被别的事务写着时排在那只写者之后);
|
|
113
|
+
无种子会话的两次并发首绑恰一只绑上(与 7.142.0 的契约同)。local 后端零变化。
|
|
114
|
+
— **升级前做(`DB_BACKEND=mysql|pg`)**:先在库上加列 —— 没加就起服 ⇒ 列册对账拒启 `config.schema_mismatch`,拒句逐字打印同一句:
|
|
115
|
+
MySQL 协议(TiDB / MySQL)`ALTER TABLE task_attachment ADD COLUMN seed_session_id VARCHAR(190) GENERATED ALWAYS AS (CASE WHEN mime = 'application/vnd.sema.project-bundle' THEN session_id END) VIRTUAL;`;PostgreSQL `ALTER TABLE task_attachment ADD COLUMN seed_session_id VARCHAR(190) COLLATE "C" GENERATED ALWAYS AS (CASE WHEN mime = 'application/vnd.sema.project-bundle' THEN session_id END) STORED;`
|
|
116
|
+
唯一索引 `uq_att_seed` 由本版起服时自己补建(MySQL 协议在线 `ADD UNIQUE INDEX`;PG `CREATE UNIQUE INDEX CONCURRENTLY`)。存量行不迁移:列由库从已有两列算出;7.142.0 的店已保证一只会话至多一只项目包,存量行不撞这只唯一键。
|
|
117
|
+
先升库、再升副本:加了列的库上,重启的旧副本被列册对账判成「库比代码新」而拒启;还在跑的旧副本照常服务(它的写同样受唯一键约束 —— 与新副本并发绑第二只项目包的那一窄形,旧副本答店错而不是 409)。
|
|
118
|
+
**谁需要**:SQL 后端上用项目包的会话 —— 并发提交(壳重试、多端同时续)不再偶发店错。**谁受伤**:SQL 后端的部署者:升级前多一句 DDL(PG 的 `STORED` 生成列加列时重写整表;MySQL 协议的 `VIRTUAL` 不重写)。
|
|
119
|
+
**出路**:同「升级前做」。**回滚**:先停光本版的全部副本(唯一键是本版判「一只会话一只种子」的唯一判官:删索引时还在服务的本版副本会让同一会话并发绑上两只项目包),再删索引、删列(否则旧版起服拒启:库比代码新),再起 7.142.x —— MySQL 协议 `ALTER TABLE task_attachment DROP INDEX uq_att_seed;` 再 `ALTER TABLE task_attachment DROP COLUMN seed_session_id;`;
|
|
120
|
+
PG `DROP INDEX IF EXISTS uq_att_seed;` 再 `ALTER TABLE task_attachment DROP COLUMN seed_session_id;`。删列不动任何一行的绑定。
|
|
121
|
+
|
|
122
|
+
10. **续跑请求可重述对端表:`/decide` · `plan_review` · `/resume` · `/wake` 的请求体收提交体同键的 `mcpServers` / `a2aPeers`(wire 加性;行为面;部署零动作)**:
|
|
123
|
+
— **本版**:键在场(不是 `null`)⇒ 这张表取代停驻任务存下的提交体里的同名表(本次续跑读它,续跑受理后随续跑输入写回,之后不送的续跑重放的也是它);值形与 `POST /v1/tasks` 同一只判官(坏形同码同句 400)。
|
|
124
|
+
键缺席或 `null` ⇒ 冻结读法:重放提交时存下的表(与上一版逐字同)。两键各自独立;空数组是一张空表,不是缺席。
|
|
125
|
+
— **任务停在一只 MCP 调用上、目标台不在送去的表里**:由引擎判,本服务不判 —— 引擎 7.61.0 起三码各答各形,以 core 为准:那只工具不在了 ⇒ `resume.tool_unavailable`(引擎重开检查点:卡仍 pending、可再决);同名而已不是批准时那一只 ⇒ `resume.tool_contract_mismatch`(同样重开);还是那一只而它的面或声明变了 ⇒ `resume.target_moved`(这次调用不执行、批准用掉,须重新发起),本服务逐字过境。出路:把那一台加回表再决,或取消这条 run。
|
|
126
|
+
— **`/resume` 现在读体**:无体照旧;体不是 JSON ⇒ `400 request.invalid_json`(上一版不读体)。**直连门部署**:`/decide` / `plan_review` 送这两键 ⇒ `400 restatement_not_in_proof`(不论值),不送即可。
|
|
127
|
+
— **不读重述的路**:SLA 到期拒扫、live 卡答复口的停驻赎回(没有调用方送来的表)。`/decide` 命中停驻后台子代的卡 ⇒ `400 decide.parked_restatement_unsupported`
|
|
128
|
+
(子代复活的是它停驻时的那一份,表无处可盖;卡仍 pending)—— 去掉这两键再决。workflow 出身的卡:投递那一跑还活着时同一决定换一张表重投 ⇒ `409 conflict.session_active_run`(不再答首投回执)。
|
|
129
|
+
**谁需要**:任务停着期间移除过自己 MCP 服务器 / A2A 对端的用户(例如 `sema mcp remove` 之后续跑,不让它被重连)和替他们续跑的壳。
|
|
130
|
+
**谁受伤**:不送当前表的壳 —— 续跑仍按提交时的表重连(含已删的台),本服务不替它判、不预拒(本条如实披露);每次都送表的壳在停驻后台子代的卡上得 400,要去掉两键再决(见上)。
|
|
131
|
+
**补偿**:壳在**每次**续跑送它此刻的整张表(MCP 与 A2A 各一张);写回失败时(运维面 warn + `resume_ctx_not_persisted_total`)这一跑照用送来的表,之后一次不送的续跑回到上一张 —— 每次都送就没有这一形。
|
|
132
|
+
**升级前做**:无。**回滚**:回到上一版 ⇒ `/decide` / `plan_review` 送这两键得 `400`,`/resume` / `/wake` 忽略它们;已经写回的表留在续跑输入里,照常重放。
|
|
133
|
+
|
|
134
|
+
11. **🔴 活流模型文本过同一只脱敏器:`text_delta` / `reasoning_delta` 逐块帧只放脱敏器已判定的字节,一段的拼接 = 段末帧正文;段末余下的字节在段末帧之前一帧补齐(wire 值语义;安全;部署零动作)**:
|
|
135
|
+
— **本版**:`POST /v1/tasks/stream`(顶层与转发子代腿)与 `GET /v1/runs/:id/subagents/:handle/stream` 上,模型文本的逐块帧经与 `done` / 账本 / `text_end` / `reasoning_end` **同一只**自由文本脱敏器放行:
|
|
136
|
+
服务端按流身份把每段喂进脱敏器的流式口,只放它已判定的字节 —— 末尾那一截(脱敏器的未决尾:本版至多 202 个读法单元,外加一个重扫步长)等更多字节到了再判。含凭据形的段,活流拼接出来的字节与该段的 `text_end.content` / `reasoning_end.content` 相同(凭据是记号,不再是明文);
|
|
137
|
+
文字段的单位是引擎的文字块(与 `text_end` 同),账本 `text` 行按 turn 拼接后再判 —— 一条凭据的锚与值分落在同一 turn 的两个文字块里时,账本行遮、`text_end` 与活流不遮(此前 `text_end` 上就是这样);
|
|
138
|
+
不含凭据形的段逐字节不变,只是分帧变了。
|
|
139
|
+
— **帧怎么变**:core 的每一块仍恰出一帧、同一枚 `eventId`、原序,但 `delta` 可以是 `""`(这一块的字节还在窗里);段末还有没放出的字节 ⇒ 紧贴段末帧之前多一帧 `text_delta` / `reasoning_delta`,
|
|
140
|
+
**不带 `eventId`**(因而不发 `id:` 行),身份三键(`parentToolCallId` / `sourceTaskId` / `bgAgentId`)随行。转发子代腿与 tail 面的逐块帧此后也带上 core 给的 `sourceTaskId` / `bgAgentId`(加性)。
|
|
141
|
+
— **延迟**:一个字节在它之后又到了未决尾上界(本版 202 个读法单元,由脱敏器的臂表读出:各臂判定距离的最大值)之后的下一次重扫时出门(重扫步长 = max(64, 段长 / 32) 个码元);
|
|
142
|
+
落在还没判定完的凭据形(PEM 栅栏、没收尾的 JSON 串值 / URL userinfo、带引号的值)里的那一截等判定或段末。不到上界的短段在段末一次出。
|
|
143
|
+
— **tail 面半路订阅**:订阅者在一段中途开始听,从此刻起收逐块帧,判定仍按整段上下文;它收到的 `reasoning_end` 是整段(此前只覆盖它开始听之后的那一截)。
|
|
144
|
+
**谁需要**:读活流的 API 消费方与渲染端 —— 此前一条凭据在 `done` 上是记号、在活流上是明文。
|
|
145
|
+
**谁受伤**:① 拿活流逐块原文做 diff / 校验和、或拿它当「模型原文」存档的消费方(含凭据形的段字节变了);② 假设每个 `text_delta` 都带 `eventId`、或每帧 `delta` 非空的消费方;③ 对首字延迟敏感的渲染端。
|
|
146
|
+
**补偿**:① 要的是一段的定稿 ⇒ 读 `text_end` / `reasoning_end` / `done`(与活流拼接同一份字节),或经 `GET /v1/runs/:id/events` 回放;② 空 `delta` 照常拼接,余下那一帧按身份三键归并,续流游标沿用上一枚 `id:`;
|
|
147
|
+
③ 延迟上界是脱敏器的未决尾上界(本版 202 单元)加段长的 1/32,散文在头 202 单元之后按步长连续流出。
|
|
148
|
+
**升级前做**:无。**回滚**:回到上一版 ⇒ `text_delta` 逐块原样、`reasoning_delta` 逐块各自脱敏(跨块的凭据形在活流上露出);落盘数据不受影响。
|
|
149
|
+
|
|
150
|
+
12. **会话读面对「属主读不出」的会话答 404,不再是 500 `corrupt_session`(行为面:一个应答格的状态变了;运维面日志加性;零新码;部署零动作)**:
|
|
151
|
+
— **哪一形**:文件后端(`DB_BACKEND=local`)上,会话的行事实(属主 / 化身)只住在会话元数据边档的那一格;7.104.0 之前写下、此后从没被读过的会话没有这一格,要从存档补铸它,存档又读不出(会话头坏 / 截在会话头里 / 日志结构走不通)
|
|
152
|
+
⇒ 这只会话没有可读的属主。SQL 后端的会话行就是 `session_meta` 那一行,没有这一形。
|
|
153
|
+
— **本版**:`GET /v1/sessions/:id` · `GET …/memory-status` · `POST …/memory/erase` · `GET …/head` · `GET …/events` · `GET …/execution-placement` 对这一形答 404 `not_found.session`,体与「没有这只会话」逐字同,带着身份的谁来读都一样(此前 500 + 原故障的码 `corrupt_session` / `invalid_session`,
|
|
154
|
+
读者拿得到「这个 id 在盘上、且坏了」)。原故障(码与句)进运维日志一行 warn `session_owner_unreadable`,字段 `{ face, sessionId, errorCode, err }`(`errorCode` = 此前这一读答的码)。
|
|
155
|
+
— **没动**:边档有格而存档读不出的会话(属主可判)—— 非属主 404、属主照旧 500(原故障的码;执行放置口读的是行格、不读存档内容,属主 200);I/O 级读故障(说不出在不在)与别的读故障照旧 500;改名 · 分叉 · 删除 · 规则 · 后台任务 · 通知 · MCP 重连 ·
|
|
156
|
+
会话同步各口 · 提交三口对这一形仍答原故障的 500;没有身份边界的部署上同一形同样 404。
|
|
157
|
+
**谁需要**:带身份边界的文件后端部署的 API 消费方与运维 —— 读面对别人的会话、对属主读不出的会话、对不存在的会话是同一句话。
|
|
158
|
+
**谁受伤**:① 把读面的 500 当「服务错」告警、或拿读面的 `corrupt_session` 判「这只会话存档坏了」的运维 / 监控 / 壳(这一形现在与「没有这只会话」不可区分);② 本来就依赖「读面 500 ⇒ 去查盘」的手工流程。
|
|
159
|
+
**补偿**:按运维日志行 `session_owner_unreadable` 告警与定位(它带会话 id 与原码);这一形本来就不在会话列表里;要修就把它的存档文件(数据根 `sessions/` 目录下)从留存副本恢复 —— 恢复后第一次读会补铸行事实,读面随之恢复。
|
|
160
|
+
**升级前做**:无。**回滚**:回到上一版 ⇒ 读面对这一形重新答 500 + 原故障的码(`corrupt_session` / `invalid_session`);落盘数据不受影响。
|
|
161
|
+
|
|
162
|
+
13. **中心 MCP 声明撞同一工具命名空间前缀:同步提交腿从 `200` + `failed` 体改 `409 config.mcp_server_name_collision`;`GET /v1/capabilities/mcp` 从无码 `500 internal.error` 改同码、同状态、同句(wire 码与状态变;部署零动作)**:
|
|
163
|
+
— **本版**:部署声明的 MCP 服务器里,两台的名字归一后(引擎铸工具名只留 `[a-zA-Z0-9_-]`,其余换成 `_`)同挂一个工具命名空间前缀 —— `my.srv` / `my_srv` 同挂 `mcp__my_srv__` —— 引擎在任何传输被触碰之前把整份声明集拒掉(码 `config.mcp_server_name_collision`,句子点名两个原拼写、指路改名)。
|
|
164
|
+
同一份声明集上,两个面现在读**同一张**「引擎拒码 → 状态」表:`POST /v1/tasks`(同步腿)答 `409`,体 `{ error, errorCode }`;`GET /v1/capabilities/mcp` 答 `409`,同体、同码、同句(句子里若有凭据形的拼写,两面都盖住、不外露,只是记号写法不同)。
|
|
165
|
+
此前:同步腿 `200` + `terminal.failed`(码与整句在终局体里);读面 `500 internal.error` 无码。
|
|
166
|
+
— **不变**:异步 `POST /v1/runs` 与流式腿 HTTP 2xx,同码落终态 run 行;`POST /v1/capabilities/mcp/probe` 自带申报那一口,同一份坏申报仍是 `400 request.field_invalid`(因由不回显);逐字同名的中心声明被配置包的 `mcp` 域在候选判官那一拍整份拒(`config_candidate_rejected`;整份候选不采纳,读面继续答在服的那一份中心声明,没有更早的在服配置就是 `servers: []`),不经引擎。
|
|
167
|
+
**谁需要**:中心(或 `config.d/mcp.json`)里配了 MCP 声明、其中有归一后同前缀的部署:运维与壳的 `mcp list` 在读面上读到原因,而不是无码 `500`;按 HTTP 状态分支的提交方不再把挂不起来的声明集读成一次成功的 `200`。声明集的另一个来源 —— 单用户部署上请求自带的 `mcpServers` —— 里归一后同前缀的两条,同步腿同样答这个码这个状态(一个码一个状态,不分来源)。
|
|
168
|
+
**谁受伤**:① 在这类部署上(或自带了撞前缀的 `mcpServers`)调同步 `POST /v1/tasks`、按 `200` 走成功路径再读 `terminal` 的调用方:现在拿到 `409` 与 `{ error, errorCode }`,没有 `terminal`(该部署每一次提交本来就失败,只是状态换了);② 把读面 `500` 当「服务坏了」做重试或告警的探活:现在 `409`,重试不改判。
|
|
169
|
+
**补偿**:一律按 `errorCode` 分支(两个面同码);出路在运维手里 —— 改中心声明里的名字,让归一后各不相同(拒句点名两个原拼写)。配置坏的部署读面另落一条 warn `mcp_status_face_declaration_refused { code, error }`。
|
|
170
|
+
**升级前做**:无(声明集里没有归一后同前缀的两台的部署零变化)。**回滚**:回到上一版 ⇒ 同步腿 `200` + `failed` 体、读面无码 `500`;落盘数据不受影响。
|
|
171
|
+
|
|
172
|
+
14. **🔴 持久 ask 店车道:askId 的身份含这一问展示给人的动作(工具名 + 入参摘要)—— 同一 run 同一腿里,模型在后一次回复中复用了前一次的调用 id、换了入参或换了工具,那一问是新问、出自己的卡(安全轴;行为收紧;不透明 `askId` 值变;零 DDL;部署零动作)**:
|
|
173
|
+
— **本版**:流内审批协议上场的部署(持久 ask 店在场)上,ask 身份 = (会话, run, 调用 id, 腿, 委派父调用 id, 类集, **工具名, 入参摘要**);入参摘要是引擎在派发这一问时铸的、与停驻卡上 `boundInputHash` 同一只值。
|
|
174
|
+
引擎的入参摘要只覆盖入参、不覆盖工具名,所以工具名单独进身份。
|
|
175
|
+
此前身份不含这两样:引擎只在一次回复之内拒重复的调用 id,跨回复复用同一 id、换了入参(或换了工具、入参逐字同)的第二问与第一问同身份 ⇒ 幂等命中第一问已决的行,
|
|
176
|
+
第一问的「是」被回放给第二问 —— 那次调用不出卡、不经人就执行。同一调用同工具同入参的重试照旧幂等(同一身份、回各自的答)。
|
|
177
|
+
— **wire 值变更**:不透明 `askId`(`approval_request` 呈卡帧、`POST /v1/tasks/:taskId/asks/:askId/decision` 的路径段)的**每一只值**都与上一版不同 ——
|
|
178
|
+
身份元组多了两元,没有入参摘要的问那一元是空串,同样改值(形不变:64 位十六进制串)。消费方只把它当不透明 id 用 ⇒ 零动作。
|
|
179
|
+
— **升级窗**:升级前写下的问行按上一版的派生存着,本服务不重算、不迁移。升级时还挂着的一张卡照旧按它行上的 `askId` 可答;同一调用在升级之后再被问一次时得一只新 id、出一张新卡(人多答一次)。
|
|
180
|
+
没有入参摘要的问(绕过引擎派发点的嵌入方自铸的问)只按工具名分问,不按入参分;对账器的 `unmatchableNoHash` 计数照旧报这类行。
|
|
181
|
+
**谁需要**:流内审批协议上场的部署 —— 一次批准只放行人看到的那一个动作(那一个工具、那一份入参)。
|
|
182
|
+
**谁受伤**:无(收紧:换了入参或换了工具的那一问回到人面前)。升级窗里同一调用再问一次的那张卡多出一次。
|
|
183
|
+
**补偿**:n/a(答那张卡)。**升级前做**:无。**回滚**:回到上一版 ⇒ 身份回到不含动作的形,本版写下的问行按它们存下的 `askId` 照旧可答。
|
|
184
|
+
|
|
185
|
+
15. **🔴 `POST /v1/approvals/:sessionId/decide`:`boundCallId` 与 `boundInputHash` 两位必带(决断方回显它在 `GET /v1/approvals` 那一行上看到的那一对),缺哪位 ⇒ `400 decide_requires_binding`,体带 `missingKeys` 点名缺的那几位;本服务不再拿当前停驻行补;`remember_requires_binding` 退役(BREAKING 行为面;安全轴;wire:错误码集少一码、拒体加性键 `missingKeys`)**:
|
|
186
|
+
— **本版**:决定落在决断方点名的那一个动作上。两位都是非空串才受理;缺席或空串 ⇒ 400(`null` 等非字符串值照旧先在值形门答 `400 request.field_invalid`)。判在门型守卫之后
|
|
187
|
+
(错门型照旧先拿 `409 gate_not_tool_approval` + 指路),续跑一步都不驱动、卡仍 pending。同一判对这道门的每一个决定者成立:本口、活卡回决停驻成的那张卡(停驻时绑定的那一对)、SLA 到期拒扫(它读下的那张卡的那一对)。
|
|
188
|
+
— **此前**:只要求 `checkpointToken` 或 `boundCallId` 之一,缺的 `boundInputHash` 由**此刻**停在门上的那一行补。同一调用 id、换了入参的新停驻顶替了决断方看到的那一张时,对旧动作的批准落在新动作上 ——
|
|
189
|
+
只回显 `boundCallId` 的合规形正中这一形。
|
|
190
|
+
— **跟着收的三处**:① `remember: "session"` 不再另有一道门:不带那一对 ⇒ 与一切决定同答 `400 decide_requires_binding`(此前 `400 remember_requires_binding`,本码退役);
|
|
191
|
+
② 幂等回放(首决已结清后同一份体重发)要求 `boundInputHash` 与行逐字相等 —— 不带 hash 的重发不回放、答 404(此前跳过这一判、回放成功);一份按本版首决成功过的体必然带着它;
|
|
192
|
+
③ 体形拒句把那一对写成必带键。
|
|
193
|
+
— **决不了的卡**:队列行上没有 `boundInputHash` 的工具审批卡 —— 只有引擎铸入参摘要之前停驻的老行(绑定纪元之前的行)—— 本口决不了,SLA 拒扫也决不了;
|
|
194
|
+
用 `POST /v1/runs/:id/cancel` 收场,或候它的终局时刻收割。
|
|
195
|
+
**谁需要**:每一个决断方 —— 一次批准只落在人看到的那一个动作上。
|
|
196
|
+
**谁受伤**:只回显 `boundCallId`(或只回显 `checkpointToken`)的决断方 —— 升级后决定得 400;拿 `remember_requires_binding` 分支的消费方(码不再出现)。
|
|
197
|
+
**补偿**:从队列行原样回显那一对:`GET /v1/approvals` 的 `pending[]` 行与 `/v1/approvals/stream` 的 `pending` 帧都带 `boundCallId` / `boundInputHash`;按 `missingKeys` 补齐再决。
|
|
198
|
+
**升级前做**:决断方(SDK / 壳 / BFF)先升到回显两位的版本,再升本服务。**回滚**:回到上一版 ⇒ 缺 `boundInputHash` 的决定重新被当前停驻行补(本条修的那一形回来);带全那一对的决定两版同答。
|
|
199
|
+
|
|
200
|
+
16. **更正(7.142.0 节第 18 条与第 19 条的两处读数说法,文书;零行为变化)**:
|
|
201
|
+
① **第 18 条**「谁受伤」写「坏块的部署(平面读 `no_origins`)」,回滚句写「平面读 `no_origins` 那一侧不变」;7.142.0 节 CHANGELOG 同说,`web_admin_sandbox_git_refused` 行的 `effect` 句也说「the sandbox git plane reads no_origins」。这些说的是平面的**第九条前提**(`sandboxGit.origins` 非空)不成立。
|
|
202
|
+
`GET /v1/capabilities` 的 `credentialPlane.sandboxGit.reason` 取判序里**第一个**不成立的前提(九词闭集与判序见契约附录 B):第三条前提(取值口的 worker 凭据)恒不成立,所以坏块、撤块、没有块的部署线上读到的都是 `no_caller_credential`(或更前的词),`no_origins` 要前八条都成立才会成为读数。第 18 条 ② 那一句(读数停在 `no_caller_credential`)本来就这样写,以它为准。
|
|
203
|
+
② **第 19 条**对第二形(强锚名紧贴在前一枚凭据的尾巴上)写「run 行与账本回放上被遮(读面多过一遍脱敏)」。在 7.142.0 上该形首遍不遮、第二遍才遮,读数看这个出口过几遍:`GET /v1/runs/:id` 的 run 行(写口一遍、读口一遍;经同步 / 流式提交落库的结果写前还多过出口那一遍)与 `GET /v1/runs/:id/events` 回放里的 `text` / `reasoning` / `done` 行(账本汇点写口一遍、回放读面一遍,至少两遍)被遮;
|
|
204
|
+
**回放里的 `tool_end` 行**(工具自己的输出,例如 Bash 回显)只过工具输出投影那一遍、回放读面不再过 —— 这一形在那里**明文**。流式 `done` 帧、同步体、运维日志行不变(一遍,明文);活流逐块帧 `text_delta` / `reasoning_delta` 与 `text_end` / `reasoning_end`(7.143.0 起与 `done` 同一只脱敏器、同一遍)同样明文。
|
|
205
|
+
第一形(复合凭据名)在每个出口都是明文,第 19 条原句不变。**本版起两形都遮**(第 41 条):复合凭据名在自由文本的声明形里是名字锚;名字的左界止于前一枚已认出的凭据的终点,第二形首遍即遮、各出口同读,上面这段出口遍数读数只是 7.142.0 的读数。
|
|
206
|
+
**谁需要**:按「凭据不会以明文出现在日志 / 转录里」配告警、做审计的部署,以及把 `GET /v1/runs/:id/events` 当作已脱敏副本交给下游的消费方;读 `credentialPlane.sandboxGit.reason` 并按 `no_origins` 分支的运维 / 嵌入方。
|
|
207
|
+
**谁受伤**:无新增(零行为变更);照第 19 条原句认定「账本回放不带这一形」的部署 —— 7.142.0 写下的回放里的 `tool_end` 行会带。
|
|
208
|
+
**补偿**:升级前已落库的 `tool_end` 行回放读面不再过脱敏(第 41 条「存量行」)⇒ 已有的回放可按这两形自查;`reason` 按判序第一个不成立的前提读。7.142.0 节原文不改(已发节字节不动)。**升级前做**:无。**回滚**:无关。
|
|
209
|
+
|
|
210
|
+
17. **🔴 引擎 7.61.0:升级前结清在途审批、排空旧 worker;部署的 mod 包按契约 7 重建(部署面;BREAKING)**:
|
|
211
|
+
— **此前**:引擎 7.60.0 的检查点把发起会话记在 `sourceTaskId` 下;mod 内核契约号是 6。
|
|
212
|
+
— **本版**:引擎只认新键 `sourceSessionId`(零别名)—— 升级前停驻、升级后才决断的卡,读回答 `requirements_damaged`,不能再决断;SQL 检查点店读到旧键的行同样判不可读,不静默读成空。
|
|
213
|
+
引擎只加载声明 `"contract": 7` 的 mod 包:按契约 6 写的包在起服被拒 `config.mods_invalid`,拒句点名两个契约号。
|
|
214
|
+
**谁需要**:所有升级到本版的部署。**谁受伤**:升级时还停着审批卡的部署(那几张卡作废,要重新提交任务);同一只库上混跑旧 worker 的滚动窗;装了 mod 包的部署。
|
|
215
|
+
**补偿**:升级前在旧版上把在途审批批完 / 拒完(`GET /v1/approvals` 为空),排空并停光旧 worker 再起本版;mod 包把 `hooks.json` 的 `"contract"` 改成 7 并按新契约重建(新站点与 `$` 调用见引擎文档)。回滚到 7.142.x:同样先结清本版的在途审批再起旧版。
|
|
216
|
+
|
|
217
|
+
18. **🔴 审批卡的委派子代出处键 `sourceTaskId` 改名 `sourceSessionId`(wire BREAKING;零别名;值不变)**:
|
|
218
|
+
— **此前**:活的 `tool_approval` / `approval_request` 帧、`GET /v1/approvals` 的 `livePending` 与停驻行、卡片 JSON 上,委派子代的卡带 `sourceTaskId`(值是子代的会话 id)。
|
|
219
|
+
— **本版**:同一格叫 `sourceSessionId`,同值;`sourceTaskId` 不再出现。唤醒腿写进检查点的这一格改填会话 id(此前误填了 run 的 task id)。
|
|
220
|
+
本版之前铸的卡信封(SQL `approval_ask.card_json` / local 问账里同一份信封)上那一格还叫 `sourceTaskId`:读口改名读回(一次性迁移 M37,只有读侧,窗口见登记表;
|
|
221
|
+
每改一次计一次 fail-open `server.approval-card.retired-card-key-read`)—— 断连重放、回决口、幂等重入照读,wire 上只出 `sourceSessionId`(不是别名)。
|
|
222
|
+
**谁需要**:引擎同一个会话身份只有一个名字。**谁受伤**:按 `sourceTaskId` 在场判「这是委派子代的卡」、或拿它关联子代行的壳 / SDK / 控制台。**补偿**:改读 `sourceSessionId`;`fromSubagent` 判别位与 `originTaskId` 不变。
|
|
223
|
+
|
|
224
|
+
19. **通告码 `context.image_removed` 改名 `context.media_removed`;TaskOutput 工具退役(wire 码改名;任务柄读腿文字;策略名单)**:
|
|
225
|
+
— **本版**:媒体离开模型请求的通告只铸 `context.media_removed`(`detail.reason` 说原因、`documents` 计文档),旧码不再出现;模型名册里没有 `TaskOutput`(后台命令的输出读输出文件,后台 agent / 工作流的结果在完成通告里);
|
|
226
|
+
HTTP 任务柄读腿的正文围栏标签由 `TaskOutput <id>` 改为 `task <id>`;策略的 deny / ask 名单点名 `TaskOutput`(或 `TeamCreate` / `TeamDelete`)⇒ 跑前拒 `config.legacy_tool_name`,allow 名单只得一行提示。
|
|
227
|
+
**谁需要**:读媒体移出通告的消费方 —— 图片与文档离开模型请求是同一只码(`detail.reason` 说原因、`documents` 计文档);在 deny / ask 名单里写了已退役工具名的部署 —— 跑前被点名,而不是一条名册里已经没有的工具名在名单里匹配不到任何调用。
|
|
228
|
+
**谁受伤**:按旧通告码写分支的消费方;按旧围栏标签匹配任务柄正文的 UI;策略名单里写了 `TaskOutput` 的部署。**补偿**:改读新码;按新标签匹配;从 deny / ask 名单里删掉这三个名字。
|
|
229
|
+
|
|
230
|
+
20. **设备车道:放置围栏 + 设备执行器协议修订 4(行为面;wire 加性;部署零动作)**:
|
|
231
|
+
— **本版**:被放在某台设备上的续跑 / 委派 / 唤醒腿,根会话此刻绑的不是那台设备(中途换绑过)⇒ `device.identity_mismatch`,在连接之前拒,不改道到新设备;引擎对报告与围栏不符的新腿答 `config.placement_not_honored`。
|
|
232
|
+
协议修订号 3 → 4:文件操作的结局码闭集加 `symlink_loop`,执行器声明修订 4 才发;`deviceExecutor.protocolVersion` 报 4。
|
|
233
|
+
**谁需要**:用设备车道、任务停着期间可能给根会话换绑设备的部署 —— 续跑 / 委派 / 唤醒腿在连接之前被拒,不跑到一台没有那份工作区的设备上;执行器在文件操作上撞到符号链接环时有一个专门的结局码可报。
|
|
234
|
+
**谁受伤**:在任务停着时给根会话换绑设备、又想在新设备上续跑的用户(新设备上没有那份工作区)。**补偿**:结束或取消在途任务,在新设备上重新开始;执行器升到修订 4 再发新词。
|
|
235
|
+
|
|
236
|
+
21. **SQL 后端:新表 `mailbox_consumed`(信箱已收窗;本服务起服自建;部署零动作)**:
|
|
237
|
+
— **本版**:`ack` 删掉的带身份记录各留一行(每盒留最新的引擎窗那么多行,同段修剪),追加时与持有行一起交引擎判重 —— 已收过的记录重投答它原来的 `seq`,不再当新信。表由起服的建表语句自建(`CREATE TABLE IF NOT EXISTS`),存量信箱行不迁移。
|
|
238
|
+
**谁需要**:SQL 后端上会重投带身份记录的发信方(重试、断线重连)—— 已收过的那一条答它原来的 `seq`,收信方不把它当一封新信再收一次。
|
|
239
|
+
**谁受伤**:SQL 部署多一张表(每盒的行数以引擎窗为界、同段修剪);回滚到 7.142.x 的那段时间里,重投已收过的记录照旧当新信收(旧版不读这张表)。
|
|
240
|
+
**补偿**:部署零动作(表起服自建);升级之前已被 `ack` 删掉的记录没有窗行(存量不迁移),升级后重投它们仍当新信 —— 窗从升级那一刻起积累。
|
|
241
|
+
**回滚**到 7.142.x:旧版不读这张表,表留着即可(再升回本版时接着用)。
|
|
242
|
+
|
|
243
|
+
22. **`DB_BACKEND=local`:落盘的工具结果按 `TOOL_RESULT_TTL_SEC` 老化回收(行为变化;运维面日志 tag 改名)**:
|
|
244
|
+
— **此前**:本机后端的工具结果目录没有任何清理路径,只增不减;SQL 后端按 TTL 回收。
|
|
245
|
+
— **本版**:本机与 SQL 同一只回收腿,按 `TOOL_RESULT_TTL_SEC`(缺省 86400 秒)收走更老的工具结果;回收失败的节流日志 tag 由 `tool_result_reap_older_than` 改为 `tool_result_reap`。
|
|
246
|
+
**谁需要**:长期运行的本机部署 —— 工具结果目录此前只增不减,盘面无界。
|
|
247
|
+
**谁受伤**:本机部署里依赖比 TTL 更老的工具结果引用的会话(引用读不回)。**补偿**:把 `TOOL_RESULT_TTL_SEC` 调大;告警规则按新 tag 匹配。
|
|
248
|
+
|
|
249
|
+
23. **会话同步 blob 上传:内容与哈希不符一律 400;嵌入方的文件历史店 / 工具结果店换新组形(wire 值变化;嵌入方类型面 BREAKING)**:
|
|
250
|
+
— **本版**:`PUT /v1/sessions/:id/sync/blobs/:hash` 内容地址对不上 ⇒ 400 `request.hash_mismatch`(此前一形答 502 `unsupported_format`)。
|
|
251
|
+
嵌入方自建的文件历史店:`syncBlobFaces` / `putBlob` / `getBlob` / `hasBlobs` 退役,改交引擎的 `blobExchange` 组(`put` / `get` / `has`,整组或没有;内容地址在 `put` 判);自建工具结果店:`reapOlderThan` 退役,改 `reap(now, { maxAgeMs })`。
|
|
252
|
+
**谁需要**:会话同步客户端 —— 内容与哈希不符读到一个确定的 400(同一份字节重传不会好),而不是一个看似可重试的 502;嵌入方 —— 两只店的 blob 面收成引擎的一组,内容地址只在 `put` 一处判。
|
|
253
|
+
**谁受伤**:把 502 当可重试的同步客户端;自建这两只店的嵌入方(编译即红)。**补偿**:哈希不符按 400 处理(重传正确内容);按新组形实现。
|
|
254
|
+
|
|
255
|
+
24. **记忆同步:套在别的 scheme 下的 URL userinfo 也判作凭据(行为收紧;部署面)**:
|
|
256
|
+
— **本版**:`MEMORY_SYNC_URL` / `MEMORY_SYNC_SERVE_IDENTITY` / 同步层名里出现 `proj:https://user@host/…` 这一形 ⇒ 起服拒;同步口请求的 `peer` / `target` 带这一形 ⇒ 400(不回显值)。
|
|
257
|
+
**谁需要**:不让凭据落进会被日志记下、存进本机游标、经能力位 `memorySyncServe.identity` 逐字公开的那些值的部署 —— 此前 `proj:https://user@host/…` 这种外面再套一层 scheme 的写法漏判。
|
|
258
|
+
**谁受伤**:把凭据写进这些值的部署(此前放行)。**补偿**:凭据从这些值里拿掉,走凭据配置。
|
|
259
|
+
|
|
260
|
+
25. **设置导入:用户层里以 `/` 起的路径规则留在设置文件里(行为收窄);🔴 导入预览请求体的 `userSettings` 层不再收 `root`(wire BREAKING;零别名)**:
|
|
261
|
+
— **本版**:导入预览把这类规则列进 `preview.skipped`(原因前缀 `unsupported.layer_root:`),不再存成每个项目根都读的全局规则;先前准备好的导入记录在兑现时拒这类候选。
|
|
262
|
+
`POST /v1/rules/cc-import/prepare` 的每一层按 `layer` 分形:`{ layer: "userSettings", path, content }`(**没有** `root`)| `{ layer: "projectSettings" | "localSettings", path, root, content }`。
|
|
263
|
+
用户层带 `root` ⇒ 400 `request.body_shape`,拒句 `body must be {layers:[{layer:"userSettings",path,content} | {layer:"projectSettings"|"localSettings",path,root,content}]}`(此前每一层都必带 `root`,用户层那一格从不被读)。
|
|
264
|
+
**谁需要**:从 CC 导入用户层设置的用户 —— 用户层的 `/x` 规则此前存成每个项目根都读的全局规则(第 37 条起服退役的就是这批存量);导入客户端 —— 用户层不再要一个从不被读的 `root`。
|
|
265
|
+
**谁受伤**:靠导入把用户层 `/x` 规则带进来的用户;在用户层上照旧带 `root` 的导入客户端 —— 每次带用户层的预览都 400,不只是带 `/x` 规则的那几次。
|
|
266
|
+
**补偿**:在项目层写同一条规则(项目层的 `/` 形读在那个项目的根);导入客户端在 `userSettings` 层上去掉 `root`(项目层 / 本地层照旧带)。
|
|
267
|
+
|
|
268
|
+
26. **🔴 SQL 后端:`approval_ask` 加一列 `decided_via`;决定体加性键 `decidedVia`;能力位 `approvalDecidedVia`(wire 加性;DDL:升级前先加列,先升库再升副本;零一次性迁移)**:
|
|
269
|
+
— **本版**:四条决定口(`POST /v1/tool-approvals/:id/respond`、`POST /v1/tasks/:taskId/asks/:askId/decision`、`POST /v1/approvals/:sessionId/decide`、`plan_review`)受理 `decidedVia`(取引擎的座位闭集,只许在 `decidedBy: "policy"` 旁),
|
|
270
|
+
`hostDecision.decidedVia` 原样交引擎;问账行与决定同一条 UPDATE 落列 `decided_via`。行上 NULL(含加列前的旧行)读作缺席 = 部署自己的策略;请求体上的 `decidedVia: null` 不是缺席,答 400。
|
|
271
|
+
— **DDL**(升级前先在库上执行;没加就起服 ⇒ 拒启 `config.schema_mismatch`,拒句逐字打印同一句):
|
|
272
|
+
MySQL 协议 `ALTER TABLE approval_ask ADD COLUMN decided_via VARCHAR(32) NULL;`;PostgreSQL `ALTER TABLE approval_ask ADD COLUMN decided_via VARCHAR(32) COLLATE "C";`
|
|
273
|
+
存量行不改写(加列即 NULL)。加了列的库上,重启的 7.142.x 副本拒启(库比代码新)。
|
|
274
|
+
**谁需要**:按 PermissionRequest 钩子代答卡片的壳与宿主(模型读到「一只 PermissionRequest 钩子拒了这次调用」,不是部署策略句)。**谁受伤**:已有问账表的 SQL 部署(`DB_BACKEND=mysql|pg`):升级前多一句 DDL。
|
|
275
|
+
**补偿**:能力位 `approvalDecidedVia`(恒 `true`)见位才发;**回滚**到 7.142.x:先停光本版全部副本,再 `ALTER TABLE approval_ask DROP COLUMN decided_via;`,再起旧版。
|
|
276
|
+
|
|
277
|
+
27. **`verify:true` 任务的上限封住整个任务的实现侧:每轮修复只拿余额,一条轴花光 ⇒ 不再修复(行为收窄;wire 加性 `verification.allowanceExhausted`;部署零动作)**:
|
|
278
|
+
— **本版**:任务的 `limits`(请求的 `maxCostUsd` / `maxTokens` / `limits.maxTurns`,或 `MAX_TASK_COST_USD` / `MAX_TASK_TOKENS` 落成的值;开着 `RESOURCE_SUSPEND` 时是跨片总额 `RESOURCE_SUSPEND_TOTAL_TOKENS` / `_TOTAL_BUDGET_USD`,每一片仍按 `limits` 的窗走)
|
|
279
|
+
管实现腿与各轮修复的合计:每轮修复拿的是上限减去前面各腿自报的花费。修复腿越过余额 ⇒ 照常 `limits.max_cost_exceeded` / `max_tokens_exceeded` / `max_turns_exceeded`;某条轴已花光 ⇒ 不派修复,判词停在那次 FAIL,
|
|
280
|
+
结果带 `verification.allowanceExhausted: { axis: "cost" | "tokens" | "turns", remaining?: 0 }`。前面有一腿没报价(模型无价目,结果里没有 `costMicroUsd`)而任务带美元上限 ⇒ 美元轴余额算不出,读作没有余额(`axis: "cost"`,不带 `remaining`)。
|
|
281
|
+
此前每轮修复是新开的一次运行、整份重拿上限,跨片总额也逐腿重给 —— 本文件 7.140.0 节第 10 条「补偿」里「verify 任务没有跨腿的总额」一句自本版起不再成立(已发节字节不动)。
|
|
282
|
+
**谁需要**:给 verify 任务设了花费上限、要它真封住整个任务的部署。**谁受伤**:按「每轮修复各有一份上限」配额的调用方(修复轮数可能变少,结果多一键);配了 `MAX_TASK_COST_USD` 却跑无价目模型的部署 —— verify 任务第一次 FAIL 之后不再修复(起服那行 `cost_ceiling_without_pricing` 说的就是这台)。
|
|
283
|
+
**补偿**:按整个任务配上限(各轮可能花的加起来);给模型配价目(`MODEL_COST_*` / 名册行的 `cost`);轮数仍由 `verifyRounds` 管。**回滚**:回到 7.142.x 即回到逐腿整份(无数据面)。
|
|
284
|
+
|
|
285
|
+
28. **更正(7.139.0 节第 24 条 ③,文书;零行为变化)**:本机宿主车道上没配 worktree 包装、要 `isolation: "worktree"` 的 workflow 子代,拒它的仍是本服务的 host 工厂(码 `isolation.unavailable`,句子点名 `WORKTREE_ISOLATION_ENABLED` / `WORKTREE_REPO_ROOT`),
|
|
286
|
+
不随引擎 7.61.0 改由引擎拒:worktree 的核验在引擎契约里是执行环境工厂一方的义务(必须铸 worktree 或抛),引擎没有回执可核。部署零动作;7.139.0 节原文不改(已发节字节不动)。
|
|
287
|
+
|
|
288
|
+
29. **嵌入方:包一层 `ServiceDeps.resolveSpec` 的包装必须返回装配器交回的同一只对象(嵌入方行为面 BREAKING;部署零动作)**:
|
|
289
|
+
— **此前**:本服务的部署事实(执行车道、run 技能名册、受理见证)以 symbol 键挂在装配器交回的 spec 上,`{ ...spec, model }` 这类拷贝把它们一起带过去。
|
|
290
|
+
— **本版**:事实登记在以装配器交回的那一只对象为键的载体里,不在 spec 上;拷贝读不到 ⇒ 选路答 500(`HandsLaneUnstampedError`,日志留原句),技能名册与会话工作区见证缺席。
|
|
291
|
+
**谁需要**:每一条 run 与续跑 —— 引擎的 `TaskSpec` 一读门按 `Reflect.ownKeys` 判自有成员,不是它声明的键(含 symbol 键)一律拒(新 run `config.spec_unknown_key`、续跑 `checkpoint.config_refused`),挂在 spec 上的部署事实会让任务跑不起来。
|
|
292
|
+
**谁受伤**:在 `createResolveSpec` 外面再包一层、返回拷贝的嵌入方。**补偿**:在交回的对象上改并返回它(`return Object.assign(spec, { model: … })`);只用本服务装配器的部署零动作。
|
|
293
|
+
|
|
294
|
+
30. **验证器自己停驻的那张卡改由引擎的作废动词结算,会话钉随之放掉;编排(leader)路径同样作废(行为面;修复;部署零动作;订正 7.141.0 节第 31 条的两条已知限制)**:
|
|
295
|
+
7.141.0 第 31 条写的两条已知限制 ——「作废只结清卡,引擎为它钉住的验证器会话不在这里释放,留在副本内存里直到进程重启」「编排(leader)路径上的验证器卡本版不作废」—— 本版两条都收:
|
|
296
|
+
后台 run、同步提交、续跑 verify 臂与 leader 的 worker 结算一律交跑过那次验证门的 Runner 的作废动词(引擎读卡上记的组合腿,只收验证器腿铸的卡;卡 `expired`、验证器会话放钉),本服务不再读卡、比会话、店级作废。
|
|
297
|
+
**谁需要**:长寿副本、看待决面的人与壳。**谁受伤**:按 `server.verifier-pause.card-void-failed` 探针行的旧原因词(`reason=store_error|card_mismatch|no_checkpoint_store`)筛的告警 —— 探针行改带引擎的码(`code=<码 | thrown>`)。
|
|
298
|
+
**补偿**:告警改按 `code=` 筛(`thrown` = checkpoint 店在出错;`checkpoint.void_unpin_failed` = 卡已作废、会话钉没放掉)。7.141.0 节原文不改(已发节字节不动)。
|
|
299
|
+
|
|
300
|
+
31. **`settings.permissions.allow` 的条目也可带出处层 `{ rule, layer }`;user 层的 `/` 形 allow 读在执行环境的配置根(wire 条目型放宽 + 能力位 `settings.permissions.layeredAllow`;端见位才发;部署零动作,沙箱车道配置根读不出的部署见补偿)**:
|
|
301
|
+
7.141.0 节第 15 条为 deny / ask 立的读法 —— 一条路径规则的 `/` 读在它那一层的根上 —— 本版扩到 allow 桶(收掉那一条「已知限制」里 allow 桶只收纯串的那一半):`userSettings` 里要根的 allow 规则免问的是配置根下的路径、不再是任务根下的;
|
|
302
|
+
别的层与纯串照旧读在任务根。条目一条一员按位置交给引擎(命中报的位置 = settings 表的下标)。
|
|
303
|
+
**谁需要**:user 层写了 `/` 形 allow 的端用户。**谁受伤**:① 依赖「user 层 `/x` 放每个项目的 `x`」的人 —— 端升级发带层条目后任务根下 `x` 的写照问;② 沙箱车道配置根读不出的部署(home 未声明且没转 `SEMA_CONFIG_DIR`):这样的 allow 422 `home_unresolvable`;
|
|
304
|
+
③ 回滚 / 滚动发布中的旧副本读到带层 allow 的体 ⇒ 新提交 400、续跑 409。
|
|
305
|
+
**补偿**:① 规则挪进项目层,或写相对形 `x/**` / `//` 绝对形;② 沙箱 env 名单加 `SEMA_CONFIG_DIR`,或声明 `REMOTE_EXEC_HOME_DIR`;转进去的值写绝对路径(相对值由引擎在开跑时拒这条 run);③ 端读能力位 `settings.permissions.layeredAllow`、见位才发。7.141.0 节原文不改(已发节字节不动)。
|
|
306
|
+
|
|
307
|
+
32. **后台子代一个 id(引擎换代):面板、完成通知、孙代嵌套、审批归属都读注册表行 id `a…`;升级前停驻的后台子代先结清,回滚前同样(行为面;部署面:升级 / 回滚前各一步;wire 键零变化)**:
|
|
308
|
+
引擎这一版起后台子代的 tick、结果、完成通知、孙代的父链接与问上的 `agentId` 都是它的注册表行 id;本服务按这一个 id 读,不把它的会话 id 当别名读(升级前的 id 不被读成新 id 的别名)。
|
|
309
|
+
**谁需要**:看面板的端(一只后台子代一行)。**谁受伤**:① 升级时还停驻着的后台子代 —— 它升级前登记的那些行(它自己的后台任务、它派出的子代,属主是它当时的会话 id)在它以行 id 复活之后够不着;
|
|
310
|
+
② 回滚:本版停驻的后台子代的卡记着行 id(要求词 `row_task_id`),上一版读不懂这个词,续跑拒 `version_newer`。
|
|
311
|
+
**补偿**:升级前与回滚前各让停驻的后台子代结清(答掉它的审批、或停掉它);没结清的卡升回本版即可续跑。**升级前做**:让停驻的后台子代结清(答掉它的审批、或停掉它)。**回滚前做**:同样让本版停驻的后台子代结清;没结清的卡在回滚后的副本上续跑不了,升回本版即可续跑。
|
|
312
|
+
运维日志 `task_notification_observed` 删 `hadFleetRow` 键(后台子代的行不经那条腿)。
|
|
313
|
+
|
|
314
|
+
33. **Runner 之外复活的后台子代,完成通告走委派树根会话的会话通知门(行为修复;wire 零新键;部署零动作)**:
|
|
315
|
+
— **此前**:引擎 7.61.0 下,停驻的后台子代经 `POST /v1/approvals/:sessionId/decide` 批准恒答 409 `decide.revive_rejected`(引擎 `revive.no_background`:Runner 之外的续跑解不出完成 sink 就不起),子代永不再跑;
|
|
316
|
+
7.61.0 之前续跑起得来、完成谁都收不到。操作员续跑(`POST /v1/runs/:id/subagents/:target/resume`)起的续跑同样起得来、完成不交给任何人。
|
|
317
|
+
— **本版**:这两种续跑跑完,完成交给委派树根会话的会话通知门(与 `POST /v1/sessions/:id/notify` 同一只门):根会话在本副本有活流 ⇒ 注入那条 run(`<task-notification type="external">`,最早边界);
|
|
318
|
+
空闲 ⇒ 进它的收件箱,下次开流排空成一帧 `task_notification`。帧 = notify 门的 external 形:`task_type: "external"`、`task_id` = 子代句柄、`status`、`summary`、`result?`、`seq`(停驻周期号),不带 `completionId`。
|
|
319
|
+
投递那一刻根会话不在、或住客已换(删了、同 id 被重新登记、属主变了)⇒ 不交,一行 warn `background_completion_undelivered`。更深的行(孙代)报给委派树的根。
|
|
320
|
+
门在投递动作之前紧邻地复核住客(属主与化身两样),`POST /v1/sessions/:id/notify` 同此:属主门读过之后、投递之前这只会话被删、同 id 换了住客或换了属主 ⇒ 答 404 `not_found.session`(此前照投给下一位住客);
|
|
321
|
+
收件箱条目的属主照旧取属主门那一读(无主会话盖请求主体)。会话店不铸住客令牌(嵌入方自建的店;头读没有 `incarnation`)⇒ 复核只比属主:属主没变 ⇒ 照投(与此前同形),变了 ⇒ 404;
|
|
322
|
+
本服务自带的店每次建行都铸令牌。
|
|
323
|
+
**谁需要**:停驻后台子代、再由人决断的部署;用操作员续跑动词的壳。**谁受伤**:把复活的完成帧当噪声的消费方(根会话多一帧 `task_notification`);按 `task_type: "background_agent"` 或 `completionId` 关联子代完成的消费方
|
|
324
|
+
(这一形上两键都不在);根会话空闲时排空的是展示帧,下一次 run 的模型上下文里没有它。**补偿**:帧形是 notify 门既有的 external 形,按 `task_id`(子代句柄)关联;同一子代两次复活的完成 `seq` 不同。
|
|
325
|
+
|
|
326
|
+
34. **会话记忆同步触发口 `POST /v1/sessions/:id/memory/sync`:409 `conflict.session_memory_unobserved` 体恒带 `reason`(闭集五词),句子由 `reason` 定;最近一条已结 run 的记录里没有记忆观测的那一形有了自己的一句出路;🔴 它配了记忆而没挂上(`memoryless`)的那一形由 200 空报告改 409(wire 加性;行为面;三句拒句换形 / 新句;零 DDL;部署零动作)**:
|
|
327
|
+
— **本版**:读集照旧只读会话**最近一条已结 run** 的记忆观测,不往更早的 run 找。读集取不到时 409 体多一个键 `reason`,判序 = 读的先后:
|
|
328
|
+
`no_settled_run`(会话还没有已结 run)· `run_result_missing`(最近一条已结 run 的记录里没有结果:实例丢了被收割、停驻过期被收割 —— 收割写空结果,停驻时那份观测随之不在 —— 、在引擎答出之前抛)·
|
|
329
|
+
`run_result_unobserved`(记录里有结果、结果里没有记忆观测:引擎在准备阶段拒了 / 失败了它,引擎答出之前被取消,或更早版本的引擎写下的结果)·
|
|
330
|
+
`memory_not_mounted`(观测在,说那一条配了记忆而没挂上:引擎 `memoryless`,`mount-failed` / `no-backend`)· `no_leaf`(观测在、说得出读集,会话还没有叶子)。
|
|
331
|
+
停因本身读那条 run 的终局(`GET /v1/runs/:id` 的 `status` / `errorCode`;没挂上的因由读它的 `result.effectiveMemoryScopes.reason`)。有在飞 run 时照旧另带 `activeTaskId`。
|
|
332
|
+
— **行为变化(🔴)**:最近一条已结 run 的观测是 `memoryless` 时,上一版把读集读作 `[]`、答 200 空报告(`scopes: []`、`layers: []`);本版答 409 `memory_not_mounted` —— 挂载失败时那一腿本该读哪几层不可知,`[]` 只留给本会话没配记忆(`none`)。
|
|
333
|
+
— **句子**:`no_settled_run` 不变;两只空观测因由同一句(「the latest settled run in this session has no memory observation on record, and an earlier run is never read in its place — run another task in this session (if that run was refused, fix what refused it first), then sync」);
|
|
334
|
+
`memory_not_mounted` 一句(「memory was configured for the latest settled run in this session but did not mount, so which memory this session reads is unknown, and an earlier run is never read in its place — run another task in this session (if its memory fails to mount again, fix that first), then sync」,新臂);
|
|
335
|
+
`no_leaf` 一句(「this session has no transcript yet, so there is no revision to sync from — run a task in it (or let the run in flight finish), then sync」)。此前三臂同一句「this session has no settled run with a memory observation yet …」。
|
|
336
|
+
— **不变**:码、状态 409、门序、零请求零写;观测是 `mounted` / `none` 的 run 读集与 200 报告逐字同上一版;持久数据零变化(空观测由读口从行上已有事实算出,不落盘)。
|
|
337
|
+
**谁需要**:壳与控制台 —— 按 `reason` 告诉用户同步为什么不可用、怎么解开(会话里早先成功过的 run 不再让人以为同步坏了;记忆没挂上的会话不再被当成「同步完了」推上云)。
|
|
338
|
+
**谁受伤**:按 409 体逐字节比对、或按句子匹配这一码的消费方:体多一个键,空观测两臂与 `no_leaf` 臂换了句子;最近一条 run 记忆没挂上的会话 —— 上一版 200 空报告、本版 409,同步按钮灰到再跑一条挂上记忆的任务为止。
|
|
339
|
+
**补偿**:按 `errorCode` + `reason` 分支,不比句子;`reason` 是闭集,读不懂的词按「读集取不到」处置(在会话里跑一条任务、等在飞的 run 结束,再触发);`memory_not_mounted` 反复出现 ⇒ 读那条 run 的 `result.effectiveMemoryScopes.reason`,查记忆引擎的挂载故障。
|
|
340
|
+
**升级前做**:无。**回滚**:回到上一版 ⇒ 409 体不再带 `reason`,三臂回到同一句,`memoryless` 回到 200 空报告;落盘数据不受影响。
|
|
341
|
+
|
|
342
|
+
35. **🔴 记忆同步:中心每个层分区一只化身,写之前判请求的主张;同步口改到 `POST /v2/memory/sync/:scope`(`/v1/…` 答 404);本机游标原样携带化身(引擎 7.61.0 三处硬破坏;持久数据面:中心库新表 `agent_memory_engine_sync_partition`,起服自建、零 ALTER;部署:两端同版 + 停驻层删游标)**:
|
|
343
|
+
此前:游标只绑层、对端地址与本机店。中心库被清空重建或从更早的备份恢复,同一地址读作同一个对端 —— 下一轮按旧基线对账,中心没有的基线条目答成「中心已删」、旧副本答成「中心改过」,本机照落,这一轮还报 `ok`。
|
|
344
|
+
现在:① 中心每个层分区一只化身(分区第一次被同步读到时出生、存在中心库),结果体 `cursor.incarnation` 恒在场;请求的 `peerIncarnation` 在任何读写之前比 —— 不是本分区的、或带非空基线却没有主张 ⇒ 200 `{ refused: "baseline_incarnation", incarnation }`,零读零写;
|
|
345
|
+
一轮写完之后化身已变 ⇒ 500(不答算在旧状态上的结果)。② 同步口路径 `/v2/memory/sync/:scope`;`/v1/memory/sync/…` 无人认领 ⇒ 404。③ 本机执行器把落盘游标的 `peerIncarnation` 原样交引擎;中心在化身轴上的拒 = 停驻(同另三轴,一条出路:删游标;运维行 `axis: "incarnation"`)。
|
|
346
|
+
**谁需要**:DB 记忆平面的中心与连它的本机同步腿 —— 中心库重建之后设备上的条目不再被一轮「成功」的同步删掉或回滚。
|
|
347
|
+
**谁受伤**:① 升级期:新旧两端互答 404(新客户端只打 `/v2`、旧中心只认 `/v1`;新中心对旧客户端同样 404),两侧都什么都没写,**同步暂停,两端同版后恢复**;
|
|
348
|
+
② 两端同版后的第一轮:每一层带基线的游标(升级前写下的,没有化身)被中心拒 `absent`,本机那一层停驻(`GET /v1/sessions/:id/memory-status` 的 `memorySync.parked[]`、运维行 `memory_sync_layer_parked { axis: "incarnation", found: "absent" }`),停驻层每一轮仍发一次请求、被中心在写之前拒掉;
|
|
349
|
+
③ 中心从备份恢复:恢复回来的化身就是备份时那一只,读作同一份状态 —— 备份之后设备上的新条目照旧会被删掉或回滚(引擎的已知限制)。
|
|
350
|
+
**补偿**:① 两端都升到本版,先后不限(升级期只是不同步,不丢数据);② 删掉停驻层的游标文件(运维行 `cursorPath` 逐字;`<记忆引擎根>/sync-cursors/<scope 的 sha256 前 32 位>.json`),下一轮从空基线重收敛:
|
|
351
|
+
两边都改过的条目按冲突报,上一轮之后一侧删掉的条目会从另一侧回来;③ 中心从备份恢复之后、起服之前删掉 `agent_memory_engine_sync_partition` 的全部行(轮换化身):每个客户端下一轮被拒 `other`、按 ② 处置(DEPLOY-PREREQS)。
|
|
352
|
+
**升级前做**:无(新表起服时 `CREATE TABLE IF NOT EXISTS` 自建;库账号已有建表权限)。**回滚**:旧中心不认 `/v2` ⇒ 同步再停;本版写下的游标带 `peerIncarnation`,旧二进制按名挑员时丢掉它 —— 回到旧版即回到旧语义;新表留着无读者。
|
|
353
|
+
**嵌入方**(自建 `ServiceDeps`):`memorySync` 的答型改为 `MemorySyncAnswer`(结果或拒答);自建 `MemorySyncStore` 多一口 `partitionIncarnation(scope)`(TypeScript 编译红即通知)。
|
|
354
|
+
|
|
355
|
+
36. **🔴 抹除与会话记忆状态答整个部署:两只抹除口走引擎的一只部署对象,会话记忆状态不带层座 ⇒ 引擎在每只店上折成的那一份,本部署有哪些店读盘上的(行为面;409 `memory.erasure_store_unjudged` 退役、会话自助抹除体的 `scope` 退役;嵌入方类型面 BREAKING;部署零动作)**:
|
|
356
|
+
此前(7.140.0 起):目录钉住的 file 部署上,落到个人挂载那只店的抹除一律 `409 memory.erasure_store_unjudged`、什么都没擦;会话记忆状态由本服务折;本部署的店集由配置点名的层推。
|
|
357
|
+
现在:① 抹除(`POST /v1/memory/erase` 与 `POST /v1/sessions/:id/memory/erase`)交引擎的部署对象 —— 一个 `requestId` 在整个部署里只名一次请求:执行之前读遍每只店的锚,同一个 id 头一回换了选择子或执行在另一只店 ⇒ `409 memory.erasure_selector_mismatch`,
|
|
358
|
+
换了授权集 ⇒ `400 config.memory_erasure_scope`,什么都没删;个人层的抹除照常执行;`select.ids` / `select.sessionId` 不带 `expectedScopes` ⇒ 每只店各擦各的那一份、收执合成一份;授权集的层分住两只店 ⇒ `400 config.memory_erasure_scope`。
|
|
359
|
+
② 会话记忆状态不带层座 ⇒ 引擎的部署对象折好的一份;带层座 ⇒ 那只店上的引擎答案。③ 本部署的店集 = 盘上的(个人挂载上有店就算,配置不再点名个人层也算)。
|
|
360
|
+
**谁需要**:目录钉住的 file 部署上要擦个人层记忆的 operator 与会话所有者(擦得掉、重放收敛);换过 `MEMORY_SCOPE` 的部署(个人挂载上留下的那一份照样被状态数到、被按会话抹除擦掉)。
|
|
361
|
+
**谁受伤**:① 按 `409 memory.erasure_store_unjudged` 分支的客户端 —— 码退役,这些请求现在照常执行;② 会话自助抹除体带 `scope` ⇒ `400 request.body_shape`(7.140.0 起的层座,本版退役:抹除交整个部署,没有「落哪只店」可点);
|
|
362
|
+
③ 个人挂载上有店的部署,不带层座的出处 / 清标 / 清标账请求 ⇒ `400 request.memory_layer`(此前配置不点名个人层时答在部署的店上);④ 抹除那一条只走 incident 座的码(`memory.erasure_index_residue`)的运维行名由 `memory_compliance_incident` 变为 `memory_engine_incident`;
|
|
363
|
+
⑤ 嵌入方(自建 `ServiceDeps` / 直调记忆作用域店):`SessionMemoryStatusFace` 改为 `readingAt(at?) → { key, status(sessionId) }`、`MemoryComplianceFaces.erase(input)` 去掉层座参、`createMemoryScopeStores` 去掉 `namedLayers`(多一个可选 `captureRecords`)、
|
|
364
|
+
`foldPlaneStatuses` / `memoryStoresOfDeployment` / `memoryLayersNamedBy` / `MemoryErasureStoreUnjudged` 删除、`backendOwnsControlPlane` 改从 `memory-scope-stores.ts` 导入(TypeScript 编译红即通知;零别名)。
|
|
365
|
+
**补偿**:① ② 去掉对退役码 / 键的分支;③ 在请求里点名层(GET 口 `?scope=<层键>`,POST 口体 `"scope"`);④ 告警按码匹配(两种行名都带 `code`);⑤ 照新形改。记忆引擎根下多一个目录 `.memory-erasure-judge`(抹除判官锁;根本就要可写)。
|
|
366
|
+
**升级前做**:无。**回滚**:回到上一版即回到上一版的答法(本版个人店上执行过的抹除,其锚留在那只店里:上一版对那只店的抹除照答 409,不会重复执行)。
|
|
367
|
+
|
|
368
|
+
37. **🔴 规则店:引擎 7.61.0 之前从用户层设置导入、从 `/` 写起的全局放行,起服即退役(一次性迁移 M36;持久数据面;行为收紧;部署零动作)**:
|
|
369
|
+
旧形:引擎 7.61.0 之前的设置导入(`/v1/rules/cc-import/*`、`/v1/rules/local-import/*`)把用户层(用户配置目录下那份 settings)里 `Edit(/notes/**)` 这样从 `/` 写起的路径规则存成**全局**行。
|
|
370
|
+
全局行在每个任务的**项目根**读 `/x`,用户层却在它自己的配置目录读 —— 一条本意是「配置目录下的 notes」的放行,在每个项目里放行 `notes/` 的编辑、不问。
|
|
371
|
+
引擎 7.61.0 起导入不再这样存(本版第 25 条);已存的行引擎不迁、也不在读侧丢,判据交给店的属主跑。
|
|
372
|
+
新形:每次起服的一次性迁移读规则桶(SQL:规则表里的每一只;local:导入记录点名过的属主的那几只),按引擎那一句判据退役:态是 `allow` ∧ add 的出处是设置导入(`imported-cc`)∧ 行的 scope 是全局 ∧ 规则在项目根读 `/x`。
|
|
373
|
+
**按 add 退役、不按行**:同一条规则另有人亲手同意过的那一份(`user` 出处),规则照旧生效,只少了导入那一份;deny / ask 不动(它们在项目根只收紧);`//abs`、`~/`、相对路径、非路径规则与项目 scope 的行不动。
|
|
374
|
+
第二次起服零写。SQL 两库与 local(File)同一只函数、同一处写法:墓碑经这只桶自己的写面落(与撤销口同一形),删除点由本副本铸。
|
|
375
|
+
读数:起服报告两键 `importedLayerRootAllowsRetired`(逐行:桶键 / 工具名 / 退役的 add 数 / 规则是否还生效;不带规则正文)与 `importedLayerRootBucketsSkipped`(闭集四词 `bucket_unreadable` / `vanished` / `not_writable` / `contended`;`vanished` = 写它的那一步里这只桶被另一副本删掉了,无可退役、不拒启);
|
|
376
|
+
warn `imported_layer_root_allow_retired` / `imported_layer_root_bucket_skipped`,一行一桶 / 一行一规则。
|
|
377
|
+
**谁需要**:用过设置导入的部署 —— 那几条放行从此不在每个项目里替人答应。
|
|
378
|
+
**谁受伤**:① 依赖那条错位放行的人:升级后在项目里编辑 / 读那几个目录会被问(本意本来就不是它);② 回滚到引擎 7.61.0 之前的版本后再导入:旧导入门会把同形的行再铸出来;
|
|
379
|
+
③ local 车道审批记录日志损坏、或某只规则桶文件 / 规则目录的收编标记读不出(含一次 I/O 失败)的数据根:迁移读不全 ⇒ 起服拒(此前起服照常、只在规则面上拒)—— 不跳过(跳过就是让那几行照旧放行而不说);
|
|
380
|
+
④ SQL 后端:窗内每次起服读一遍规则表里的每一只桶,桶多的库起服变慢;起服那一刻库读失败 ⇒ 起服拒(SQL 店的判官判为损坏的桶不在此列 —— 指纹 / 文法戳 / 行形不合,或某只 JSON 列的体读不出:点名跳过 `bucket_unreadable`、一个字节不动、接着读下一只桶,它本来就什么都不放行;一只与导入无关的坏桶不挡起服);
|
|
381
|
+
⑤ local 车道:引擎的本地数据根收编把一只桶改名到没有任何导入记录点名的身份之后,这只桶迁移叫不出、不退役(已知缺口)。
|
|
382
|
+
**补偿**:① 真要在每个项目里放行的,以项目 scope 或 `//abs` 绝对路径重新同意一次;本意是用户配置目录的,写 `~/…`;② 再升回本版,起服把再铸的那几只 add 再退役一次(每次起服都跑);③ 按拒句点名的文件与行修好再起;④ 读失败照常重启(迁移幂等);⑤ 那只桶里导入的全局 `/x` 放行经撤销面撤掉(`DELETE /v1/rules`)。
|
|
383
|
+
**回滚**:墓碑是上一版撤销口写的同一形,上一版照常读;回滚不动库,被退役的那几条不回来(要回来就重新同意)。迁移码在不再支持回滚到引擎 7.61.0 之前的版本时删(窗口见登记表)。
|
|
384
|
+
|
|
385
|
+
38. **本地导入载体(`POST /v1/rules/local-import/{prepare,redeem}`)的 deny / ask 在 prepare 当场落店 —— 收紧不等同意(行为面;wire 加性;部署零动作)**:
|
|
386
|
+
旧形:三态都合成进导入层、经导入记录与票在 redeem 落;引擎 7.61.0 起导入门把用户层里从 `/` 写起的路径规则留在设置文件里,全局 `/x` 的 deny / ask 因此成员级 `not_importable`(云端不拒)。
|
|
387
|
+
新形:收下的 deny / ask 按提交序经直写接缝当场落(与 `POST /v1/rules` 同一只;出处 `user`),预览成员 `{key, admitted:true, outcome:"persisted"|"no-op"}`;allow 照旧经记录与票在 redeem 落,
|
|
388
|
+
本版铸的票的回执只有 allow;只有 deny / ask 的一批没有票。整工具的 deny / ask 同样当场落。一条 deny / ask 写不进店 ⇒ `503 state.rule_write_failed`(带 `committed`),这一批的 allow 全部扣下、没有票;同一批重发幂等。
|
|
389
|
+
**谁需要**:用载体迁移本机规则的人 —— 本机生效的收紧在云端同样生效。**谁受伤**:按回执数收紧的客户端;把 prepare 当无副作用预览的客户端;按出处 `imported-cc` 筛收紧的治理面。
|
|
390
|
+
**补偿**:收紧的结局读预览成员的 `outcome`;撤销走 `DELETE /v1/rules`;出处词与直写口同义(放行仍是 `imported-cc`)。滚动窗里旧版本铸的票照旧在 redeem 落它记录里的 deny / ask。
|
|
391
|
+
|
|
392
|
+
39. **自由文本脱敏的取证读法按出处读(行为面;安全;脱敏产物可能变;运维面多一个 fail-open 标签 `server.redact.forensic-level-cap`;部署零动作)**:
|
|
393
|
+
— **本版**:一枚凭据不再拿自己上一轮的读数当证据,嵌套或相邻的另一枚凭据照算;一段由字符类自然停下的值盖住私钥栅栏或 URL 的 `@` 时两种读法都算、取覆盖多的那一份;
|
|
394
|
+
SSH2 私钥块收好之后的孤立收尾栅栏之前读作丢了起头的体(体从体长上界内最早的那一枚已收口块的终点起,体与孤立收尾那一行照遮;此前一枚记号盖到孤立收尾之后,现在各块与体各一枚);
|
|
395
|
+
私钥收尾本身落在一段值里的块只在一读里收好 ⇒ 不藏、也不越过它体里的起始栅栏(那一枚照读截断律,收尾之后的体形串遮掉);证据链深过 32 环的输入从那一处遮到末尾,并记一次 `server.redact.forensic-level-cap`。
|
|
396
|
+
**谁需要**:日志 / 转录 / 结果里出现「赋值形凭据紧贴私钥栅栏或 URL」、URL 密码里带 `@`、或嵌套 / 相邻私钥块的部署 —— 此前这些形下私钥体或 URL 凭据的一段原样出门。
|
|
397
|
+
**谁受伤**:按字节比对脱敏产物的消费方(这些形遮得更多;两枚起始栅栏共用一枚收尾、其后不远另有收尾时,遮到后一枚收尾;私钥收尾被一段值盖住、其后只剩别的块自己的收尾时,遮到最后一枚;
|
|
398
|
+
只看窗内的读法里私钥块的收尾只有两读的(例如落在没写完的 JSON 秘密字段里)⇒ 遮到窗尾;SSH2 块与其后的孤立收尾之间从一枚记号变成几枚,覆盖不变;
|
|
399
|
+
SSH2 / PEM 起始栅栏成千上万枚、共用其后同一枚收尾的输入整段遮,级数随枚数涨、32 级封顶,耗时为上一版的数倍到百倍)。
|
|
400
|
+
**补偿**:无开关(凭据轴只收紧);done 帧与事件回放同一份产物可作比对基准;到顶的输入看 `server.redact.forensic-level-cap` 计数(每次脱敏至多一次)。
|
|
401
|
+
**升级前做**:无。**回滚**:回到上一版 ⇒ 读法回到旧形,上述形下的那一段重新原样出门;无持久数据。
|
|
402
|
+
|
|
403
|
+
40. **🔴 审批卡的断连重放帧与活铸帧同事实:问行卡信封(SQL `approval_ask.card_json` / File 问账的同一份信封)加一座 `liveFacts`,断连重放的 `approval_request` 帧带活铸帧顶层的同一组卡外事实;本版之前铸的行重放帧带 `liveFactsUnknown: true`(安全轴;wire 加性;持久数据面:存形加性,零 DDL;🔴 多副本先停光旧副本再让本版接流量)**:
|
|
404
|
+
— **本版**:铸卡时活铸帧顶层的十一位卡外事实(`mandated` / `mandate` / `origin` / `boundGrantDigest` / `boundGrants` / `classifierNoRuling` / `boundGrantAbsence` / `approvalCard` / `readRootCandidate` / `probeReason` / `requestedBy`)
|
|
405
|
+
与卡同一条写落进卡信封的 `liveFacts` 座(在场才拷;一位都不在场时是空座;这组事实里有 NUL / 孤代理 ⇒ 不落座,行读作「不知道」—— PostgreSQL 问店存不下逐字的那一份)。
|
|
406
|
+
断流续读、开流 preamble、起服接管行与按问读口内嵌的帧只读这一座 ⇒ 行上记着的每一位与活铸帧逐字同值;起服接管行顶层的 `mandated` / `mandate` / `origin` 读内嵌帧,
|
|
407
|
+
行上没有座 ⇒ 行顶层同带 `liveFactsUnknown: true`。同一只问被另一腿再问(重启续跑、另一只副本)时,重入那一腿的活铸帧与列表行采信行上这一座;
|
|
408
|
+
「本会话放行」的判据只收窄(强制位取两边之并、授予绑定两边一致才认)(行上没有座 ⇒ 这一腿的读数照旧)。
|
|
409
|
+
行上没有这一座(本版之前铸的行)或它读不出 ⇒ 重放帧带 `liveFactsUnknown: true`、十一位一位不带;这时的缺席不是断言,按强制 / 未知渲。活铸帧恒不带它。
|
|
410
|
+
— **不回填**:存量行不改写、不迁移;待决的问被答掉或到期即离开重放集,存量随 ask 期限收敛。零 DDL(卡信封是不透明列)。
|
|
411
|
+
— **滚动升级窗**:上一版的卡信封读者是 `.strict()` 的,读不动带这一座的行。上一版副本碰到本版写下的行:断连重放跳过那只卡(一次 warn)、幂等重入走 park、回决口按「要人」读(拒策略放行)、
|
|
412
|
+
持久规则兑付答素材缺席(规则不落)。都是收紧方向,不会错放;本版副本读上一版写下的行 ⇒ 存量行形(`liveFactsUnknown`)。
|
|
413
|
+
**谁需要**:断线重连的壳与控制台 —— 重连之后的卡与断开前同一张;只经 preamble 到达的后台子代的问第一次带全开卡事实。
|
|
414
|
+
**谁受伤**:滚动升级窗里由上一版副本服务的问(上一句的四形);把重放帧上的缺席读成「不是 X」的消费方,在存量行上读到 `liveFactsUnknown`。
|
|
415
|
+
**补偿**:读 `liveFactsUnknown` 分支(在场 ⇒ 按强制 / 未知渲);上一版 server 既不带事实也不带标记,按服务版本分支。
|
|
416
|
+
**升级前做**:先停光上一版副本再让本版接流量(k8s 多副本用 `Recreate`,或先把旧副本摘出负载均衡)。只排空待决的问不够 —— 本版副本新写的问,还在服务的旧副本照样读不动。
|
|
417
|
+
不这样做也可以:窗里旧副本上的四形都是收紧方向、不会错放,代价是那些卡在旧副本上重连看不到、走 park。
|
|
418
|
+
**回滚**:回到上一版 ⇒ 本版写下的、仍待决的问在旧副本上落滚动升级窗那四形(走 park / 人答);local 车道起服收敛读不出这些行的卡信封,成因词落 `crashed_before_park`(一次兜底计数);
|
|
419
|
+
旧副本新铸的行回到无座形,再升回本版即读作存量行。
|
|
420
|
+
|
|
421
|
+
41. **🔴 自由文本脱敏的名字面:复合凭据名在自由文本的声明形里是名字锚;名字的左界止于前一枚已认出的凭据的终点;不带引号的值里面的赋值照问(行为面;安全;脱敏产物变;带这些赋值的命令不再给常驻放行;部署零动作)**:
|
|
422
|
+
— **本版**:① `api_key` / `apikey` / `api-key` / `access_token` / `refresh_token` / `id_token` / `private_key` / `x-amz-signature` / `x-amz-security-token` / `x-amz-credential` 与 `password` / `secret` / `client_secret` 同档:
|
|
423
|
+
在自由文本 `名=值` / `名: 值` 的声明形(名字带引号、值带引号,或赋值符两侧零空白)上,值是以字母数字起头的字面量时遮(`$VAR` / `%s` / `<占位>` / 表达式 / `None` 不算值)。
|
|
424
|
+
② 名字的左界止于前一枚已认出的凭据(或可读的结构块)的终点:强锚名紧贴在前一枚凭据的尾巴上(`-----END PRIVATE KEY-----password=…`;PGP 收尾栅栏、PuTTY 的 `Private-MAC:` 行、AWS 键 id 同形,中间无分隔)时首遍即遮、再过一遍读数不变 ⇒
|
|
425
|
+
流式 `done` 帧、同步体、运维日志行、活流逐块帧、`GET /v1/runs/:id` 的 run 行与 `GET /v1/runs/:id/events` 回放里的 `text` / `reasoning` / `done` / `tool_end` 行同读(此前单遍口明文、多遍口被遮,见第 16 条)。
|
|
426
|
+
③ 每个赋值符恰问一次,值怎么读不取决于它在不在另一只值里:不带引号的值里面的赋值照问 —— `api_key=abc,password="my secret value"` 里两个值都遮,强锚的不带引号值里夹着的 `…?Sig=password="n "<尾段>` 尾段也遮(此前外层不带引号的值把里面的赋值藏住,里面那一只不认)。
|
|
427
|
+
常驻放行的命令素材闸读同一只脱敏器:命令里带 ① 这类赋值(`curl … -d api_key=<字面量>`)⇒ 判为带凭据,不给常驻放行。
|
|
428
|
+
— **不变**:JSON 字段与 URL 参数位的读法(表里每个名字照旧都是锚);`token` / `key` / `auth` / `sig` / `signature` / `sas` 在自由文本里仍只是常用词(只在结构位置上是锚);
|
|
429
|
+
赋值符两侧带空白的不带引号形(`api_key = abc`)不是声明形;名字按整名认(`DB_PASSWORD` / `foo-api_key` 是另一个名字)。
|
|
430
|
+
— **存量行**:回放读面对 run 行与 `text` / `reasoning` / `done` 行再过一遍脱敏 ⇒ 升级前落下的这些行按本版读法遮;`tool_end` 行回放读面不再过(只剥媒体字节)⇒ 升级前写下的这几形照旧明文,升级后新写的行照遮。
|
|
431
|
+
— **仍不遮**:名字整个落在前一枚已认出凭据的值里(以字母数字收尾的令牌后面紧贴强锚名,`ghp_…password=<值>`)时令牌照遮、`<值>` 明文,各出口同读;中间有分隔照遮。
|
|
432
|
+
**谁需要**:prompt / 工具输出 / 日志 / 结果里出现这些赋值形的部署 —— 此前 `api_key=<字面量>` 一族在自由文本里原样出门,紧贴形在单遍口上原样出门。
|
|
433
|
+
**谁受伤**:① 关键字参数透传(`f(api_key=api_key)`)的变量名换成记号;② 带这些赋值的命令不再给常驻放行(每次问人);③ 脱敏计数上升;④ 不带引号的值里面的赋值现在也遮(上一版跳过),外层值与里面那一只相交时两枚记号相邻、里面那一只的名字随外层记号盖住;⑤ 源码与配置片段里的对象字面量(`apiKey: "…"` / `access_token: "…"`;名字大小写不敏感,值带引号即声明形)的值换成记号,测试夹具与示例代码里的假值同样;⑥ 赋值符密集的长输入脱敏变慢,仍与长度同阶(每几个字符一个赋值符的 40 万字符输入约为上一版的 2–8 倍,约 0.1 s;散文与长值不变);⑦ 这些名字后面、本来由值自身形状认出的值(`api_key=ghp_…` / `access_token=AKIA…` / `API_KEY=sk-…`)记号从 `«redacted:<种类>»` 变成强锚值的 `«redacted»`(与 `password=` 同读),`redactions_applied_total` 的 `pattern` 随之由种类名移到 `redacted`;
|
|
434
|
+
按字节比对脱敏产物的消费方在这几形上读到差。
|
|
435
|
+
**补偿**:赋值符两侧带空白(`api_key = x`)不是声明形、不作锚(既有判据);新遮的值记在 `redactions_applied_total{pattern="redacted",arm="full"}`(与 `password=` 一族同一格),按 `arm` 维与弱证据臂分开读;
|
|
436
|
+
无开关(凭据轴只收紧);done 帧与事件回放同一份产物可作比对基准。
|
|
437
|
+
**升级前做**:无。**回滚**:回到上一版 ⇒ 上述几形回到上一版读法(复合凭据名在自由文本里只靠值自身形状、紧贴形在单遍口上明文、不带引号的值里面的赋值不问);无持久数据。
|
|
438
|
+
|
|
439
|
+
42. **运行时依赖 `@modelcontextprotocol/server` 2.4.0(npm 消费方安装时一并装上;部署零动作;镜像里的回声 MCP 可作探针)**:
|
|
440
|
+
— **此前**:镜像里的回声 MCP 脚本(`/app/scripts/mcp-echo.mjs`)借引擎带进安装树的 MCP SDK v1 跑;本包 `dependencies` 里没有 MCP 服务端包。
|
|
441
|
+
— **本版**:引擎 7.61.0 不再把 SDK v1 带进安装树,回声脚本改依赖本包自己声明的 `@modelcontextprotocol/server` 2.4.0(`package.json` 的 `dependencies`);
|
|
442
|
+
镜像照旧把脚本拷到 `/app/scripts/mcp-echo.mjs`。`npm install @sema-agent/server` 一并装上这只包;服务进程本身不加载它(只有回声类脚本用:镜像回声 + `scripts/drill/mcp-principal-echo.mjs`)。
|
|
443
|
+
**谁需要**:用镜像里的回声 MCP(stdio,`bun /app/scripts/mcp-echo.mjs`;工具 `echo` / `env_check`)探 MCP 接线与 `envRefs` 注入的部署。
|
|
444
|
+
**谁受伤**:只装 npm 包的消费方多装一只依赖 —— 这只包 7 023 377 字节、117 个文件(其中源图 4 305 531 字节);它的两只依赖 `@modelcontextprotocol/core` 2.4.0 与 `zod`(^4.2.0)
|
|
445
|
+
已随引擎 / 契约包在安装树里(去重),净增只有这一只包。npm 包不带回声脚本(`files` 不含 `scripts/mcp-echo.mjs`),这只依赖在 npm 安装里没有读者。
|
|
446
|
+
**补偿**:无(本版不拆成可选依赖)。**升级前做**:无。**回滚**:回到上一版 ⇒ 依赖表回到上一版(上一版的回声脚本读引擎带进来的 SDK v1);无持久数据。
|
|
447
|
+
|
|
448
|
+
43. **更正(7.141.0 节「谁受伤 ①」,文书;零行为变化)**:`DB_BACKEND=local` 上,回滚到上一版后上一版读本版写过的 `session-incarnations.json` 不是「严格拒启」—— 严格读在第一次用到那只边档时才拒(`ensureLoaded`),
|
|
449
|
+
所以读不出的那一形(≤ 7.140.0 的副本附着 ≥ 7.141.0 写下的数据根 —— 7.141.0 起每格多 `createdAt` / `forkedFrom` 两键;本版边档形零改,7.141.0 / 7.142.0 读得了本版写的根)用户面是每个碰到它的请求答 500 `internal.error`(引擎日志:边档 malformed),服务进程本身起得来。规则不变:**不许降级附着;回滚 = 恢复升级前的数据根备份**。
|
|
450
|
+
「数据根比代码新 ⇒ 起服拒 + 机器码」(与 SQL 后端 `config.schema_mismatch` 同一条律)另票、不在本版。无三问(更正条)。
|
|
451
|
+
|
|
452
|
+
## 7.142.0 —— `onError` 汇点的日志行一律带引擎错自带的机器码 `code`(码须合码形,否则省略;记忆事故行与起服面三只引擎座的无码占位改为键缺席;`mcp_server_unavailable` / `a2a_peer_unavailable` / `task_degraded` / `prompt_composition_warning` / `prompt_cache_break` / `runner_error` 多结构化字段;运维面;日志形加性) · 一次性兜底 warn 由 stderr 裸文本行改为一行 JSON 日志(`msg` 逐字 `[sema] fail-open: <tag>`,字段 `{ tag, count }`;运维面;日志形变更) · 订正 7.139.0 节第 16 条:停驻赎回在认领之前判卡的主体的车道裁定,不被许可本部署车道的主体对停驻卡的 approve / deny 答 409 `resume_blocked_by_policy`(文字订正;零行为变更) · 折码的运维线索:读面上的再读改走 fail-open 的计数与一次 warn、长得像码的秘密报 `<not-a-code>`(订正 7.141.0 节第 30 条读面那一半;运维面;日志形变更;安全) · 起服面运维行里的异常句改经出口座:凭据形遮掉、控制字符剥掉、界 200 码元(运维面;日志形变更;安全) · 会话列表不再漏掉存档读不出的会话:行带加性键 `unreadable: { errorCode }`(行为面;wire 加性) · 🔴 记忆同步中心必须声明同步身份 `MEMORY_SYNC_SERVE_IDENTITY`(没声明 ⇒ 同步口 501);中心侧同步口拒不是同步身份的 `peer`(400)与不是本中心的 `peer`(409)(BREAKING 部署面;升级序先客户端后中心;wire 加性) · 会话记忆同步触发口 `POST /v1/sessions/:id/memory/sync`(wire 加性);同步一轮从不整轮失败、客户端侧轮级日志行 `memory_sync_failed` 退役(运维面;中心同步口答 500 的那一臂照旧发同名行);同步层名带凭据形拒启(行为收紧);`ServiceDeps.memorySyncLeg` 多要两成员(嵌入方类型面 BREAKING) · 隔离车道的附件改由恢复点放进工作区(行为修复) · 项目包:`application/vnd.sema.project-bundle` 上传、绑进隔离车道的会话作为工作区的种子(wire 加性:一个受理的 mime 值 + 四个新拒码;嵌入方 `ServiceDeps.taskAttachmentStore` 类型面 BREAKING) · 附件一经绑定不再改绑(行为收窄;`409 attachment.bound_elsewhere`) · local 车道有序关停截断的审批卡:`crashConverged[].cause` 与决断口同一个词,前世 `PARKING` 孤儿起服即 `VOID`(行为面;wire 值变化;零新键、零新词;审计收敛行写不进起服拒,行为收紧) · 嵌入方(自建 `StoreBackend`):`StoreBackend.checkpointReadView()` 多交一口 `findCheckpointCandidatesForAsk()`(BREAKING,类型面;零别名) · 结果上组合腿的自由文本过脱敏(`verification.findings[]` / `evidence`、`attempts[].diagnostics` / `gateError`;completed 因由的 `finishReasonUnknown` 过回声形状闸;行为面;安全;wire 值可能变) · `GET /v1/runs/:id/events` 的停驻尾帧一律是状态帧:挂起前的 `model_usage` 行写在 `suspended` / `needs_review` 之前,`verify:true` 的停驻与不带 `verify` 的停驻同序(行为面;wire 事件序;订正 7.141.0 节第 32 条 ①) · 同键重放的同步体改成首答的信封 + `replay: true`(BREAKING 对按重放形解析的消费方;wire 形;订正 7.141.0 节第 32 条 ②) · http hook 名单在拨出点执行:`settings.allowedHttpHookUrls` 不放行 ⇒ http hook 不发出、`settings.httpHookAllowedEnvVars` 与条目 `allowedEnvVars` 取交(安全;行为面;wire 加性) · 🔴 问账行成因拆成两列:SQL 后端 `approval_ask.denied_reason` 改名 `ending_cause`、加列 `park_trigger`,local 问账日志整本重写一次(本服务起服时自己改;升级前备份、先停光旧副本;回滚 = 恢复备份或手工三句;嵌入方类型面 BREAKING;wire 零变化) · 沙箱 git 平面接上有效配置块 `sandboxGit`(中心投影、热生效;坏块读作没有 origin + 一行 warn `web_admin_sandbox_git_refused`;本版平面读数不变;运维面) · run 行记下令牌化身号(零 DDL;部署零动作) · `ServiceDeps.sandboxGitPlane` 由值改为读函数(嵌入方类型面 BREAKING) · 自由文本脱敏的两处已知漏形写明:复合凭据名(`api_key=` 一族)的值、紧贴前一枚凭据尾巴的强锚值(安全披露;零行为变更) · 用户面通告多一键 `eventId`、live 帧带 `id:` 行;有账本口的腿断流后通告与文件卡的死直写不再记丢帧,文件卡账本孪生写失败改记计数(wire 加性;运维面计数口径变化)
|
|
453
|
+
|
|
454
|
+
1. **`onError` 汇点的日志行一律带引擎错自带的机器码 `code`(运维面;日志形加性,记忆事故行与起服面三只引擎座的无码占位除外;部署零动作)**:
|
|
455
|
+
引擎把「运维该按码告警」的事交给本服务时,码挂在错对象上(`err.code`),句子里不一定有那串码 —— 例:MCP 服务器没申报 `tools` 能力而部署声明的 `allowTools` 非空,引擎铸 `mcp.tools_capability_absent`,句子只说 `declared no "tools" capability`。
|
|
456
|
+
此前只有 `runner_config_advisory` 一条行把码写成结构化字段;`mcp_server_unavailable` / `a2a_peer_unavailable` / `task_degraded` / `prompt_composition_warning` / `prompt_cache_break` / 兜底 `runner_error` 把码折进 `info` / `err` 散文里。
|
|
457
|
+
现在这七条行同一条律:错带非空串 `code`、且它**是码**(不超过 64 字符的短 token:字母、数字与 `_ . : -`,并且秘密脱敏器原样放过它 —— `sk-…` / `AKIA…` / `ghp_…` 这类长得像码的凭据不是码)⇒ 行里多结构化字段 `code`(逐字);读不出(没有 / 不是串 / 空串 / 读取时抛)或不是码 ⇒ 该键缺席,不补占位。
|
|
458
|
+
「是不是码」只问一只判官(`codeFieldOf` 里的读口 + 判官;折码运维线索与执行车道占位读的故障词读的是同一只):`code` 是别人写的串,一句话或一把凭据都能挂在上面;wire 上同一个值在 message 尾注里被脱敏器遮掉,日志行与指标标签若照印就是日志露、wire 遮。`rewind_snapshot_failed` 早已带码,形不动。记忆引擎事故行(`memory_engine_incident` 与计数 `memory_engine_incident_total`)读同一只判官:此前它自写一份读口(码是什么都照写,无码写 `code:null` / 标签 `code="none"`),现在是码才带,无码或不是码 ⇒ `code` 键与 `code` 标签缺席,不再写 `null` / `none`。起服面三只 operator 面引擎座(`memory_compliance_incident` / `memory_origin_incident` / `memory_consolidation_incident`)同判官:此前各写一份 `code: err.code ?? null`,现在三座共用一只落点工厂、`code` 位读同一只判官,无码或不是码 ⇒ 键缺席;事件名与 `detail` 句不变。子代额外工具故障行 `subagent_extra_tools_error` 的 `code`(引擎的 `config.extra_tool_names`,或部署工厂自己抛的错)同判官:此前是串就原样进行,现在不是码 ⇒ 键缺席。`info` / `err` 句的级别与计数器一字未动;句文本已按本节第 5 条改走运维文本座(凭据形遮掉、控制字符剥掉、界 200 码元),不再是抛出物原文。
|
|
459
|
+
读面收紧(`runner_config_advisory` 行与它的指标标签 `code`):码是空串、不是码(超长 / 含空白 / 凭据形)、或抛出物不是 `Error` 实例时,此前写成 `code:""` / 原样的串 / 读抛出物上的串码,现在键缺席(与其余六条同一读口、同一判官)。已读到的引擎告警码(`config.*` / `mcp.*`)都是 `Error` 实例上的短 token 非空串,不受影响。
|
|
460
|
+
**谁需要**:按码(而不是按句子)路由引擎运维告警的日志管道。**谁受伤**:无(加性字段);只有按 `code:""`、按「非 `Error` 抛出物上的 `code`」、按「不是码的串」(超长 / 含空白 / 凭据形),按记忆事故行的 `code:null` / 计数标签 `code="none"`,按起服面三只引擎座的 `code:null`,或按 `subagent_extra_tools_error` 里不是码的 `code` 串匹配的规则会失配。**出路**:告警规则改按 `code` 字段匹配;无需动作(要找「没有码的记忆事故」或「没有码的起服面引擎座事件」就按 `code` 键 / 标签缺席匹配)。**回滚**:回到上一版即回到旧行形。
|
|
461
|
+
|
|
462
|
+
2. **一次性兜底 warn(每进程每 tag 一次)由 stderr 裸文本行改为一行 JSON 日志(运维面;日志形变更;部署零动作)**:
|
|
463
|
+
此前 `[sema] fail-open: <tag>` 作为**裸文本**直写 stderr,而日志器写 stderr 的日志都是 JSON 行 —— 把 stderr 当 JSON 行流收的日志管道,在每个 tag 第一次走兜底时撞上一行解析不了的文本。
|
|
464
|
+
现在同一句话(逐字)做一行 JSON 日志的 `msg`:`{"ts":…,"level":"warn","msg":"[sema] fail-open: <tag>","tag":"<tag>","count":<n>}`,字段闭集 `{ tag, count }`(`count` = 此刻为止该 tag 的累计命中数)。这一行不随 `LOG_LEVEL`(级别钉在 warn)、
|
|
465
|
+
不依赖日志器装配(boot 之前的兜底同样出),仍是每进程每 tag 一次;这一行不再是裸文本(stderr 上别处的非 JSON 文本,如引擎的 `process.emitWarning`,不在本条范围)。结构化 `fail_open` 日志行、`fail_open_total{tag,cls}` 指标、`SEMA_FAILOPEN_PROBE` 探针文件三件一字未动。
|
|
466
|
+
**谁需要**:把 stderr 当 JSON 行流收的日志管道;按文字子串找这一行的黑盒断言(文字没变,照读)。**谁受伤**:锚住整行 / 行首的匹配(`^\[sema\] fail-open:`)会失配。**出路**:改按子串 `[sema] fail-open: <tag>` 或 JSON 的 `msg` 字段匹配;要计数读 `fail_open_total{tag}`。**回滚**:回到上一版即回到裸文本行。
|
|
467
|
+
|
|
468
|
+
3. **停驻赎回在认领之前判卡的主体的车道裁定:不被许可本部署车道的主体,对停驻卡的 approve / deny 答 `409 resume_blocked_by_policy`(7.139.0 起的行为,当时未披露;本条是文字订正,零行为变更)**:
|
|
469
|
+
`POST /v1/approvals/:sessionId/decide` 复活停驻的后台子代之前,走与续跑家族同一只执行上下文解析器:根会话行那一格 → 车道 → **卡的主体**(停驻那一刻 checkpoint 上的主体,不是发决定的人)的车道裁定。
|
|
470
|
+
中心对这位主体的裁定 `required: true` 而 `allowedLanes` 不含本部署的车道 ⇒ `409 resume_blocked_by_policy`,体 `blockedBy: "execution_lane_not_allowed"` · `allowedLanes` · `lane` · `retriable: true`;
|
|
471
|
+
能复活的停驻行上 approve 与 deny 同答(deny 也要复活子代、让它在这条车道上读到拒绝再往下跑);停驻行不被认领、卡仍待决、被门的工具零执行。7.138.x 及以前这一形照常复活。
|
|
472
|
+
复活不了的停驻行(行上没有根会话锚)在这一判之前分流、不判车道:approve 照旧 `409 decide.row_unrevivable`,deny 照旧作废这张卡(200)。
|
|
473
|
+
续跑家族的任务级入口(`/answer` · `/plan_review` · `/wake` · 任务级 `/decide`)早已同判同折,码与体不变(7.139.0 节第 16 条的「这些拒」包括这一只)。
|
|
474
|
+
**谁受伤**:中心在任务停驻之后收窄了某位主体车道的部署 —— 那位主体停驻的卡决不动;SLA 拒扫不替停驻卡代决;拒句尾点名的 `POST /v1/runs/:id/cancel` 只结算 run 行,停驻的后台子代没有 run 行。
|
|
475
|
+
**出路**:在中心把本部署的车道放回这位主体的 `allowedLanes` 再决(卡一直待决,放回之后照常决);不打算放回 ⇒ 会话属主或 operator 发 `POST /v1/sessions/:id/children/retire`,
|
|
476
|
+
结清以该会话为根的全部后台子代(停驻的作废卡、在跑的停掉;是整棵树,不是单张卡)。
|
|
477
|
+
**升级前做**:无。**回滚**:无需(只改文字)。
|
|
478
|
+
|
|
479
|
+
4. **折码的运维线索(订正 7.141.0 节第 30 条读面那一半):读面上的再读不再出 `[terminal] outward_failure_code_folded` 行,改计数 + 每进程一次 warn;长得像码的秘密报 `<not-a-code>`(运维面;日志形变更;安全;部署零动作)**:
|
|
480
|
+
7.141.0 节第 30 条说,读面上的再读(`at=run.result` / `at=ev.done.result`)同一读面同一原码每进程只一行(表有界,1024 条)。本版起这两种行不再出现 ——
|
|
481
|
+
读面上的再读按**被折的码座**计数:`fail_open_total{tag="server.terminal.stored-result-code-folded",cls="F"}` 每折一座加一(一次读里,因由码 `terminal.code` 一座、cascade 每一级的 `attempts[].errorCode` 各一座 —— 折了三座就加三,不是加一);每进程一次结构化 warn `fail_open`(`tag` 同上,`detail` = 第一次被折的那一座的字段句
|
|
482
|
+
`original=<码 | <not-a-code>> outward=internal.store_error messageBytes=<n> at=<run.result | ev.done.result>`)与一次性兜底 warn 那一行(`msg` = `[sema] fail-open: server.terminal.stored-result-code-folded`,行形见第 2 条);
|
|
483
|
+
配了 `SEMA_FAILOPEN_PROBE` 的部署,探针文件每折一座一行。`at=exit` 那一行(结果第一次离开引擎,每折一座一行)不变。
|
|
484
|
+
另:码形之内、却被秘密脱敏器认作凭据形的码(`sk-…` / `AKIA…` 之类)在 `original=` 处报 `<not-a-code>`,不再报原值(写口那一行与读面的 `detail` 同判)。
|
|
485
|
+
**谁受伤**:按 `[terminal] outward_failure_code_folded` 且 `at=run.result` / `at=ev.done.result` 写的告警 / 看板(那两种行不再出现);按 `original=` 原值聚合、而那个值本就是秘密的规则(改报 `<not-a-code>`)。
|
|
486
|
+
**出路**:读面上的再读改看计数器 `fail_open_total{tag="server.terminal.stored-result-code-folded"}`(或 warn `fail_open` 的 `tag`);要逐座明细就开探针文件。**回滚**:回到 7.141.0 即回到那两种行(仍不带失败句原文)。
|
|
487
|
+
|
|
488
|
+
5. **起服面运维行里抛出物的句子经出口座:凭据形遮掉、控制字符剥掉、界 200 码元(运维面;日志形变更;安全;部署零动作)**:
|
|
489
|
+
起服面(装配、起服自检、关停收割、配置拉取与应用、保留期清扫、交给各店 / 车道的失败回调)运维日志里装异常句的字段(`err` / `error` / `detail` / `info` / `lastError` / `why`,事件名不变),
|
|
490
|
+
旧形是抛出物原文(`String(e)` 或 `e.message`,多行照原样);新形与 `tool_trace` / hook 失败句同一行规则:认出的凭据形换成 `«redacted…»` 记号,控制与双向字符剥掉(多行折成一行),
|
|
491
|
+
超过 200 码元截断并以 `…` 收尾(记号计入界)。k8s 车道起服自检三行在内:`sandbox_secret_seat_unverified.detail`、`sandbox_egress_policy_check_crashed.error`、读不到时的 `sandbox_egress_policy_gap.detail`;
|
|
492
|
+
异常句先转一手再进行的同改:`counter_flush_degraded.error`、`memory_consolidation_default_off_no_cheap_model.detail` 里嵌的引擎拒句那一段、`config_loaded_lkg.why`(起服拉配置失败回落 LKG;
|
|
493
|
+
旧形只剥控制字符、截 120 码元,不认凭据形)。致命退出那一行不变(整句多行、只过凭据形脱敏)。
|
|
494
|
+
**谁受伤**:按异常原文全文排障的人(长句被截、多行的折成一行);按某个字段整句精确匹配的告警(凭据形处换成记号)。**出路**:原因句的前 200 码元照旧在(错误类与首句,凭据形之外逐字);
|
|
495
|
+
规则改按事件名与字段前缀匹配。**回滚**:回到上一版即回到原文。
|
|
496
|
+
|
|
497
|
+
6. **会话列表不再漏掉存档读不出的会话:行带加性键 `unreadable: { errorCode }`(行为面:列表不再静默漏行;wire 加性;部署零动作)**:
|
|
498
|
+
文件后端(`DB_BACKEND=local`)上,会话头坏了、整份截在会话头半截、或存档读不出来(权限不对、I/O 故障)的会话,此前从 `GET /v1/sessions` 里消失(引擎的会话仓列表跳过它),
|
|
499
|
+
而同一只会话的 `GET /v1/sessions/:id` 与 `…/head` 答 500。本版起它照样是列表里的一行:行上的格出自会话行(`owner` / `title` / `pinned` / `lastActivityAt` / `firstActivityAt` / `rowTag` /
|
|
500
|
+
run 四位 / `tempo`,与好行同读),`objectivePreview: null`,另带 `unreadable: { errorCode }` —— present-iff 这只会话的头的叶子读不出,键闭集只有 `errorCode`,值 = 读口打开这只会话时答的码
|
|
501
|
+
(`corrupt_session`:会话头坏 / 截在头里;`internal.error`:I/O 级读不出)。同一张码表也是全局兜底答码的那一张,两处不会分叉;各读口的答复逐字不变。
|
|
502
|
+
边档里没有格、存档头又读不出的会话(7.104.0 之前写下、此后从没被读过)没有可读的属主,仍不列(运维面照旧点名它)。SQL 后端的行从不带这只键(叶子是会话行上一列,一行坏事件照旧在列表里)。
|
|
503
|
+
订正契约 §17.2 的旧句「整份读不出的会话不出现在列表里」—— 那是本版之前文件后端的行为。
|
|
504
|
+
**谁受伤**:把列表每一行都当「点开就能读」的端(这些行点开得 500,就是读口一向答的码);不认识新键的端会把它画成一行没有预览的普通会话;按列表行数计数的面多出这些行;
|
|
505
|
+
跨会话对端目录在文件后端上多出这些会话(与 SQL 后端坏事件行今天的读法相同);`?q=` 搜索不命中它们(没有预览)。
|
|
506
|
+
**出路**:按 `unreadable` 在场分支(灰显 / 提示读不出 / 只给删除);`DELETE /v1/sessions/:id` 对属主照常删掉它;要修就把它的存档文件(数据根 `sessions/` 目录下)从留存副本恢复、或修好文件权限 / 磁盘,行上的标记随之消失。**回滚**:回到上一版,这些会话重新从列表里消失(数据不动)。
|
|
507
|
+
7. **🔴 记忆同步中心必须声明自己的同步身份 `MEMORY_SYNC_SERVE_IDENTITY`;中心侧同步口只服务点名这一身份的轮(BREAKING 部署面:中心升级要加一行 env;行为收紧;wire 加性)**:
|
|
508
|
+
**同步身份** = 客户端到达中心同步口用的基址的规范形:小写协议与主机、无缺省端口、路径去尾斜杠,不带 userinfo / 查询串 / 片段 / 凭据形的段,≤ 190 字符。客户端腿发的 `peer` 自 7.139.0 起就是它自己 `MEMORY_SYNC_URL` 的规范形(本版不变)。
|
|
509
|
+
① DB 记忆平面的中心(`MEMORY_ENGINE_BACKEND=pg|mysql`)用新旋钮 `MEMORY_SYNC_SERVE_IDENTITY` 声明它;没声明 ⇒ `POST /v1/memory/sync/:scope` 答 501 `feature.memory_sync_serve_disabled`(鉴权之后),每个客户端的每一轮都失败(客户端那一层出 `memory_sync_layer_failed`,下一轮重试)。
|
|
510
|
+
声明不是规范形(大写主机、`:443`、尾斜杠……)/ 带凭据 / 查询 / 片段 / 非 http(s) / 超宽 ⇒ **拒启**,拒句给出规范形(不静默规范化);引擎关着也读、也拒。
|
|
511
|
+
② 入站 `peer` 不是同步身份的规范形 ⇒ 400 `request.field_invalid`(`field: "peer"`,`reason` ∈ `not-http-url` / `userinfo` / `query` / `fragment` / `credential` / `too-long` / `not-canonical`;不回显值)。7.139.0 之前的客户端发的标签 `"central"` 落这一格(`not-http-url`)。
|
|
512
|
+
③ `peer` 是规范形但 ≠ 声明 ⇒ 409 `config.memory_sync_target_mismatch`,整轮零读零写(此前按 `(scope, peer)` 新开一只游标 —— 别名客户端在中心上是第二条同步线;那些已经写下的旧游标行本版不动、不读)。拒句只点名本中心声明的身份。
|
|
513
|
+
④ 同步口与 `GET /v1/memory/export` 的 501 `capability.memory_store_required` 改读能力事实(执行位 / 导出读面在不在),不再读 `MEMORY_ENGINE_BACKEND` 的词;能力面加位 `memorySyncServe`(`false` | `{ identity }`)与 `memoryExport`(boolean)。
|
|
514
|
+
**谁需要**:多台客户端经不同地址连同一台中心的部署(别名不再悄悄分叉);要读中心身份的会话记忆同步触发口(本节第 8 条)。**谁受伤**:没声明身份就升级的中心(同步全停,直到声明);7.139.0 之前的客户端(400);经别名到达的客户端(409);
|
|
515
|
+
嵌入方装了同步执行位、后端名写 `file` 的部署(两口从 501 变成受理)。**出路**:**升级序 = 先客户端、后中心** —— 先把所有客户端升到 ≥ 7.139.0,再升中心并在同一次发布里加 `MEMORY_SYNC_SERVE_IDENTITY=<客户端 MEMORY_SYNC_URL 的规范形>`(写错了拒启句会给出规范形);
|
|
516
|
+
别名客户端把 `MEMORY_SYNC_URL` 改成声明的那一个(409 的拒句点名它)—— 改了地址的客户端在它那一侧游标照旧绑旧身份,会停驻在对端轴上,按 7.141.0 的处置删游标。**回滚**:回到上一版即回到旧收法(声明被忽略)。
|
|
517
|
+
|
|
518
|
+
8. **会话记忆同步触发口 `POST /v1/sessions/:id/memory/sync`;同步一轮从不整轮失败(wire 加性;运维面日志形变更;嵌入方类型面 BREAKING;部署零动作)**:
|
|
519
|
+
① 新口:本机形(file 记忆引擎 + `MEMORY_SYNC_URL` + 持久 run 账面)上壳在 fork 之前调它,体恰好 `{ "target": <会话要去的那台引擎 GET /v1/capabilities 上的 memorySyncServe.identity,逐字> }`;答 200 + 引擎的同步报告(`layers` 逐层结局,或整轮 `refused`:
|
|
520
|
+
`config.memory_sync_target_mismatch` = 目标不是本机同步腿到达的那台 / `session_active` = 会话有在飞 run,或读完它的记忆观测之后又受理了 run / 会话记录前进了)。读集 = 会话最近一条已结 run 的记忆观测;取不到 ⇒ 409 `conflict.session_memory_unobserved`。读集里被同步腿覆盖的项目层经 `syncOnce(…, { reading })` **永久**加入本进程的后台同步集(此后每一轮后台同步都带上它、直到进程退出:多一份游标、每轮多几次往返)。能力位 `sessionMemorySync`;位为假时 501(`feature.memory_sync_disabled` /
|
|
521
|
+
`capability.run_store_required` / `capability.session_ownership_required`)。
|
|
522
|
+
② 同步一轮里一层失败只结束那一层,别的层照跑、轮照样落定(此前在轮末汇总抛错,同一轮成功层的结果随之丢掉);客户端侧后台轮的轮级日志行 `memory_sync_failed` **退役**(中心侧同步口答 500 `internal.error` 的那一臂照旧发同名 warn 行 `memory_sync_failed`,不在本条),逐层失败各一行 `memory_sync_layer_failed` / `memory_sync_layer_parked`(键不变);这两行与 `memory_sync_cursor_write_failed` 的 `err` 值改由不抛的读口出 —— 错误的消息原文,不再带 `Error: ` 前缀,打印不出的抛出物记 `<unprintable>`(此前 `String(err)`:那种抛出物会让轮在失败行里再抛)。
|
|
523
|
+
③ 同步层名(`MEMORY_SYNC_SCOPE`,缺省 `MEMORY_SCOPE`)带凭据形的段 ⇒ **起服拒**(这个名字随每一份报告逐字上 wire);`MEMORY_SYNC_URL` 的起服拒句改由同步身份的同一只铸点出(判据不变,句子变)。
|
|
524
|
+
④ 嵌入方类型面:自建 `ServiceDeps` 带 `memorySyncLeg` 的,它多要 `peer` 与 `syncOnce`(tsc 红即通告);`MemorySyncRunner.syncOnce` 的兑现值由 `{ layers }` 改为 `{ calls }`(每层每次调用如它落定的那样),不再 reject。
|
|
525
|
+
**谁需要**:把本机会话推上云的壳;运维(部分层失败不再抹掉成功层)。**谁受伤**:按 `memory_sync_failed` 告警的规则;按旧拒句子串匹配 `MEMORY_SYNC_URL` 起服失败的规则;同步层名带令牌形的本机部署(起不来);上面 ④ 的嵌入方。
|
|
526
|
+
**出路**:客户端侧告警改认 `memory_sync_layer_failed` / `memory_sync_layer_parked`(中心侧 500 那一臂照旧认 `memory_sync_failed`);起服失败按 env 键名匹配;同步层改名;嵌入方按 `createMemorySyncRunner` 装配即可。**回滚**:回到上一版(新口随之消失,能力位缺席)。
|
|
527
|
+
|
|
528
|
+
9. **隔离车道(e2b / k8s / local-docker)的附件改由恢复点放进工作区(行为修复;部署零动作)**:
|
|
529
|
+
此前附件物化在引擎恢复相之前碰执行环境:e2b 上会话带附件的续跑腿跑在一只为写附件新建的沙箱上(停驻的那只没被恢复,停驻前的工作区不在,不报错);
|
|
530
|
+
无附件的 e2b / local-docker 续跑腿在引擎读收据句柄那一步抛 `connect_failed`;k8s 续跑腿多起一只 pod(先前那只靠 pod 收割兜),续跑前新绑的附件不在恢复出来的 pod 里。
|
|
531
|
+
现在隔离车道的附件只在恢复点放(沙箱铸出或恢复之后、交给任务之前);其余车道照旧在执行环境建立时放。k8s 续跑腿若在恢复之前已有一只 pod,先删掉它并写一行运维 warn `sandbox_pod_released_before_restore`。
|
|
532
|
+
**谁受伤**:无;e2b 的附件写失败从「执行环境建立失败」变成「这一次连接失败」(同码 `connect_failed`、同样带写失败句)。**出路**:无需动作。**回滚**:回到上一版即回到旧形(上面三种病随之回来)。
|
|
533
|
+
**已知限制(7.141.0 既有;本版不改)**:空间开的隔离车道会话里,若 run 在首次触到执行环境之前就停驻(pod 还没起、没有快照对象),续跑走停驻车道、不恢复 `latest`,run 结束提交的快照会覆盖此前 run 的改动,且不报警。修法候选:没有对象的停驻快照,续跑改作一次新连接、走 establish。
|
|
534
|
+
|
|
535
|
+
10. **项目包:没有 git 的项目以 `application/vnd.sema.project-bundle` 上传、绑进隔离车道的会话作为工作区的种子(wire 加性);附件一经绑定不再改绑(行为收窄);嵌入方附件店类型面 BREAKING**:
|
|
536
|
+
① **行为面(收窄)**:提交体 `attachmentIds` 里的附件已绑在别的会话上 ⇒ 新提交 `409 attachment.bound_elsewhere`(体 `id`),此前同属主下后绑会把它从前一个会话移过来。
|
|
537
|
+
同会话重绑(首交重试、续跑腿重放)照旧受理、不改绑定时刻;续跑腿重放存量体时这只拒不 4xx,写一行运维 warn `attachment_refused_on_resume`、该 id 跳过。
|
|
538
|
+
**谁受伤**:把同一只已上传的附件交给多个会话的调用方。**出路**:每个会话各上传一次(SQL 后端按 sha256 去重,不多占对象存储;local 后端多一份字节)。
|
|
539
|
+
② **wire 面(加性)**:`POST /v1/attachments` 新受理 mime 值 `application/vnd.sema.project-bundle`(gzip 的 POSIX tar,顶层即工作根);体读不出项目包 ⇒ `400 attachment.bundle_invalid`,体 `reason`(七词闭集,见契约附录 A.1)与 `path`(读得出、且不是放不下的超长路径才在)。
|
|
540
|
+
提交体带项目包而这条腿的车道不隔离 ⇒ `409 attachment.bundle_lane_not_isolated`(体 `id` · `lane`);会话已有种子或同一提交体带第二只 ⇒ `409 attachment.bundle_seed_fixed`(体 `id`);
|
|
541
|
+
「会话已有种子」由附件店在绑定那一步原子地判(两次并发的提交各带一只新项目包到同一会话 ⇒ 恰一只受理);店拒了提交体那只新项目包时,体里其余附件一只都不绑(提交体上读得到的拒 —— 已绑别的会话、车道不隔离、第二只新项目包 —— 同样在任何绑定之前到)。读与绑之间才被别的会话抢走的普通附件不在此列:请求答 409,同一次提交里已先绑上的种子与同组未被抢走的附件不回滚。
|
|
542
|
+
嵌入方类型面(自建 `ServiceDeps.taskAttachmentStore`):`bind` 的兑现值由「此刻绑在本会话上的 id 数组」改为 `{ bound, refused }`,两条绑定律(不改绑 · 一只会话一只种子)由店判(BREAKING;tsc 红即通告)。PG 店 `PgTaskAttachmentStore` 不从包根导出(包的 `exports` 表也不放深路径);它的构造参数由查询函数改为池,只对直接 import 本仓源码路径的嵌入方可见。
|
|
543
|
+
种子只在隔离车道的恢复点铸出新工作区时解到工作根本身(恢复出来的工作区从不播种、fork 不搬、不进目标里的附件告知);运维 info 行 `workspace_seeded{sessionId, bundleId, entries}`。
|
|
544
|
+
③ **部署面**:配了 `ATTACHMENT_MIME_ALLOWLIST` 的部署,要用项目包就把 `application/vnd.sema.project-bundle` 加进白名单(否则上传 415 `attachment.mime_not_allowed`);
|
|
545
|
+
隔离车道的沙箱镜像要带支持 gzip 的 `tar`(k8s 工作区快照早已靠它;e2b 自定义模板与 local-docker 镜像自查),缺 ⇒ 带种子的会话在执行环境建立时被拒、句子点名 `tar`;
|
|
546
|
+
镜像若在工作目录预置了内容,与项目顶层同名 ⇒ 被拒、句子点名路径(不覆写、不合并)。
|
|
547
|
+
**谁需要**:用壳把没有 git 的本机项目交到云端隔离车道继续的用户。**谁受伤**:见 ①;顶层恰有 `attachments` 目录的项目(包被拒,改名);
|
|
548
|
+
e2b / local-docker / `WORKSPACE_PERSIST=off` 的 k8s 上,每个新回合都从上传态开始(车道本就不留工作区;壳读能力位 `workspaceSync.persist === "space"` 判跨回合持久)。
|
|
549
|
+
**升级前做**:配了 mime 白名单的部署按需加一项;无 DDL、无数据迁移。**回滚**:回到上一版 ⇒ 项目包 mime 的附件当普通附件放进 `attachments/`(不解包),改绑回到「移过去」。
|
|
550
|
+
**已知限制(SQL 两方言;本版不改)**:同一会话已有种子时并发提交,若撞锁序死锁、重试(4 次)耗尽 ⇒ 店错(不是 `409 attachment.bundle_seed_fixed`);TiDB 另有:另一笔未绑的项目包被长锁占住、超过锁等待上限时答 1205(同样是店错,不是 409)。
|
|
551
|
+
11. **local 车道有序关停截断的审批卡:`crashConverged[].cause` 与决断口同一个词;前世审计判孤儿的 `PARKING` 问起服即 `VOID`(行为面;wire 值变化;零新键、零新词;部署零动作)**:
|
|
552
|
+
此前有序关停(SIGTERM / SIGINT / SIGHUP)截断、停车行在关停宽限窗内没提交的**后台 / 委派子代**卡,重启后三个读面三个词:问账行记 `shutdown_before_park`(关停那一拍),`GET /v1/approvals` 的
|
|
553
|
+
`crashConverged[].cause` 却是 `crashed_before_park`(审计账的关停记号按腿落,子代卡的腿不在协调器追踪视野里),决断口先答 `425`,对账器走到它再收成 `DENIED` / `routing_failure_fail_closed`。
|
|
554
|
+
现在只有一个词:有序关停是进程的事实 —— 审计账每一世在审批收尾等待结束那一拍落一行 `interrupted_by_shutdown`,这一世此刻没结清的卡一律 `shutdown_before_park`;起服收敛把审计判为孤儿的前世
|
|
555
|
+
`PARKING` 行与 `STREAM_PENDING` 同一拍处置(停车行其实已提交 ⇒ `PARKED`,运维日志一行 `approval_crash_convergence_park_committed`,同批仍在停驻途中的兄弟随之 `VOID` / `batch_bound_elsewhere`;
|
|
556
|
+
否则 `VOID`,成因与 `crashConverged` 同词)。「停车行提交了没有」读后端的只读口,与这一世开没开 `DURABLE_APPROVAL` 无关(前世已提交的停驻不因这一世关着 durable 被收掉)。
|
|
557
|
+
**wire 值的变化(local 车道;键与闭集不变)**:① `crashConverged[].cause`:有序关停截断、收尾结束时仍未结清的后台 / 委派子代卡 `crashed_before_park` → `shutdown_before_park`(`orphanState` / `resumeSafe` 不变);
|
|
558
|
+
② 前世 `PARKING` 孤儿的决断口 `POST /v1/tasks/:taskId/asks/:askId/decision`:`425` →(对账后)`410 gone.ask {state:"DENIED", cause:"routing_failure_fail_closed"}` 改为起服即 `410 gone.ask {state:"VOID", cause:<crashConverged 同词>}`;
|
|
559
|
+
晚答 `404 tool_approval.not_pending` 体的 `cause` 与按问读口 `GET /v1/tool-approvals/:approvalId`(`parked` → `void` + `cause`)同步变化。SQL 车道(`DB_BACKEND=mysql|pg`)零变化。
|
|
560
|
+
**审计账本形**(`<数据根>/approval-ask-audit/ledger.jsonl`,留盘给取证):关停记录 `{kind:"interrupted_by_shutdown", atMs}` 不再带 `taskId`;上一版写的带 `taskId` 的旧行照读(零迁移)。
|
|
561
|
+
**升级后的历史读数**:上一版已收敛过的组照新规则重投影 —— 那一世走完了有序收尾、而旧规则因腿证据缺席判成 `crashed_before_park` 的组,升级后 `crashConverged[].cause` 读 `shutdown_before_park`;
|
|
562
|
+
它们的问账行早已是终态(`VOID` / `DENIED`),终态行不改写,所以这一批历史问上两处的词可能不同,随审批账本留存窗整问删除而消失。
|
|
563
|
+
**起服拒(行为收紧)**:起服收敛写不进审计收敛行(盘满 / 只读;那一行是这一组的幂等锚与成因上界)⇒ 拒启,问账一字不动;此前写丢被吞、照常起服。出路:修好数据根再起,照收、同一个词。
|
|
564
|
+
**谁需要**:有序重启后读 `crashConverged`、或对旧卡作答的壳(子代卡此前被说成「崩了」,作答先撞 425 再拿到「路由失败」)。**谁受伤**:按 `cause === "crashed_before_park"` 判「崩溃」的消费方少数到这类卡(两词处置相同);
|
|
565
|
+
依赖「起服后 `PARKING` 孤儿先 425、之后 `DENIED`」时序的断言;审计账本盘坏了的 local 部署(由照常起改为拒启)。**出路**:按闭集两词读;作答见 410 即消卡;按拒启句修盘。**回滚**:回到上一版时新形关停记录(缺 `taskId`)被计坏行、经 F 类座披露(`server.approval-ask-audit.corrupt-record-skipped`),那几组回到上一版的答法;已收成 `VOID` / `PARKED` 的问账行保持终态。
|
|
566
|
+
|
|
567
|
+
12. **嵌入方(自建 `StoreBackend`、不走 `createStoreBackend` 的进程):`StoreBackend.checkpointReadView()` 的返回型多一口 `findCheckpointCandidatesForAsk()`(BREAKING,类型面;零别名)**:
|
|
568
|
+
这只只读口原先只交 `listPendingSessionIds()`(审批账本留存读它);local 车道的起服收敛现在也经它跑对账器判据 ① 的候选读口(第 6 条:前世已提交的停驻不因这一世关着 `DURABLE_APPROVAL` 被收掉),
|
|
569
|
+
返回型按 `ReturnType<StoreBackend["checkpointReadView"]>` 读(两口:`listPendingSessionIds()` 与 `findCheckpointCandidatesForAsk(scope, sessionId, toolCallId, sinceMs)`)。本服务自带的三个后端零动作(SQL 孪生与 local 交的本就是整只 checkpoint 店)。
|
|
570
|
+
**谁受伤**:自建后端的嵌入方(tsc 红即通知)。**出路**:有 checkpoint 店就交它本身;没有就交恒空读口 `{ listPendingSessionIds: async () => [], findCheckpointCandidatesForAsk: async () => [] }`(没有店 ⇒ 没有停驻)。
|
|
571
|
+
**回滚**:回到上一版,多出的成员无人读。
|
|
572
|
+
13. **结果上组合腿的自由文本过脱敏:`verification.findings[]` / `verification.evidence` / `attempts[].diagnostics` / `attempts[].gateError`(行为面;安全;wire 值可能变;部署零动作)**:
|
|
573
|
+
`verify:true` 任务结果的 `verification.findings[]` / `verification.evidence`、`cascade:true` 任务结果的 `attempts[].diagnostics` 与 `attempts[].gateError` 此前原样落 run 行 / 账本 `done` 行、
|
|
574
|
+
原样上同步 200 体 / `GET /v1/runs/:id` / `GET /v1/runs/:id/events`。本版起它们经本服务的结果脱敏器(前三片与 `result` 同一只,`gateError` 与 `terminal.message` 同一只):
|
|
575
|
+
认出的凭据片段换成 `«redacted…»` 记号,键集、数组条数与顺序不变;判词 / 轮数 / 验证器花费、每级的序号 / 模型 / 状态 / 是否通过逐字;升级前落盘的存量行在读面上同样脱。
|
|
576
|
+
每级的失败码 `attempts[].errorCode` 与 `terminal.code` 同一只出口封口折:出了本服务码形的(驱动原生码、长得像凭据的串)读作 `internal.store_error`,原码只进运维线索 —— 写口(结果第一次离开引擎)每折一座一行 `outward_failure_code_folded`,读面上的再读改记 fail-open 计数(按被折的码座计)与每进程一次 warn(第 4 条)(此前级码原样)。
|
|
577
|
+
completed 因由的 `terminal.detail.finishReasonUnknown` 过服务商回声的形状闸(可见 ASCII、1–128 字符):越界 ⇒ 该键缺席;completed 臂上不认识的成员按自由文本脱。
|
|
578
|
+
**谁受伤**:按判词 / 门异常原文逐字比对或存档的消费方;把 `finishReasonUnknown` 当任意串读的端;按 `attempts[].errorCode` 读驱动原生码的端(此后与 `terminal.code` 同读 `internal.store_error`)。**出路**:按条数与判词分支照旧;比对改按记号之外的文本;
|
|
579
|
+
`finishReasonUnknown` 缺席读作「服务商的词不在回声形内」。**回滚**:回到上一版即回到原文(本版落库时已脱的字节不会复原)。
|
|
580
|
+
|
|
581
|
+
14. **`GET /v1/runs/:id/events` 的停驻尾帧一律是状态帧:挂起前尚未落账的 `model_usage` 行写在 `suspended` / `needs_review` 之前,`verify:true` 的停驻与不带 `verify` 的停驻同序(行为面;wire 事件序;订正 7.141.0 节第 32 条 ①;部署零动作)**:
|
|
582
|
+
7.141.0 节第 32 条 ① 写的是「`verify:true` 任务停驻期间回放的最后一帧是一帧 `model_usage`,排在状态帧之后;不带 `verify` 的停驻以状态帧收尾;两形同序的修正不在本版」。本版起两形同序:停驻帧是这一腿主线写下的最后一帧(晚到的子代转发帧、完成后追加的 `suggestions` 是旁路写,本来就可能排在状态帧之后,不在此列)。
|
|
583
|
+
成因与改法:停驻行此前先写、挂起前的用量行紧随其后;不带 `verify` 的停驻在最后一个 `turn_end` 就把用量结清了,所以尾帧恰好是 `suspended`;`verify:true` 的任务是只回结果的组合腿、没有 `turn_end`,挂起前的用量只有停驻这一拍才落账。
|
|
584
|
+
(不带 `verify` 的形上,最后一个 `turn_end` 之后、停驻之前还有未结清的用量时,同样的尾巴也在。)现在停驻行只经一只写口:先把这一片未落账的用量结清(`model_usage`;没有用量就不写),再写 `suspended` / `needs_review`。
|
|
585
|
+
后台腿、同步 detach 腿、续跑腿的再停与重开臂、续跑 verify 臂同序。用量行落不下 ⇒ 停驻帧照落、随后把失败抛给调用方 —— 失败语义与此前逐字同(后台腿按「停驻没落定」收场:行 `failed`、手里那张卡作废;detach 腿的兜底停驻与续跑腿的重开臂照旧吞掉它)。
|
|
586
|
+
终局帧的序不变(用量行本来就在 `done` 之前);`model_usage` 行的内容、逐行求和与 `stats.modelUsage` 回声不变,变的只是用量行在流里的位置。
|
|
587
|
+
**谁需要**:按「主线最后一帧 = 当前状态」读事件流的客户端(此前 verify 停驻上要改读最后一只状态帧)。**谁受伤**:按「`model_usage` 紧跟在 `suspended` / `needs_review` 之后」配对计费行的解析器 —— 用量行现在在停驻帧之前,按位置配对的会错位。
|
|
588
|
+
**出路**:按 `model_usage` 行逐条求和(与位置无关),或读 `GET /v1/runs/:id` 的 `stats.modelUsage`;读「当前状态」可以读事件流的最后一帧,也可以读 `GET /v1/runs/:id` 的 `status`。**升级前做**:无。**回滚**:回到 7.141.0 即回到停驻帧在前的序。
|
|
589
|
+
|
|
590
|
+
15. **同键重放的同步体改成首答的信封 + `replay: true`,不再是 run 行读面(wire 形;BREAKING 对按重放形解析的消费方;订正 7.141.0 节第 32 条 ②)**:
|
|
591
|
+
同一把 `Idempotency-Key` 再投 `POST /v1/tasks` / `POST /v1/tasks/stream`,命中既有行(另一个进程 / 副本 / 重启之后)时,此前的体是 `GET /v1/runs/:id` 的读面加 `replay: true`(`result` 是对象,外加 `status` / `errorCode` / `error` / `heldBy` / `cancelRequested` 等读面键),
|
|
592
|
+
与首答(引擎结果,`result` 是串)的信封对不上 —— 7.141.0 节第 32 条 ② 写的「外层形不同;重放回首答同一形的修正不在本版」。本版起重放与首答同一个信封,同一个铸点(`buildSyncSubmitBody`):
|
|
593
|
+
— 命中的行**已终局** ⇒ 体 = 引擎结果本身(`terminal` / `stats` / `taskId` / `sessionId` / `result`(串)……在顶层,终局体不带 `status`),加 `replay: true`;
|
|
594
|
+
— 命中的行**停在门上**(`suspended` / `needs_review`)⇒ 体 = 引擎结果 + 回执三键 `{ taskId, sessionId, status }`(与同步停驻的首答同形),加 `replay: true`;
|
|
595
|
+
— 命中的行**还在跑**(首投在别的进程上没落定),或行上没有结果可交 ⇒ 首答在这一刻不存在:体只有回执三键 `{ taskId, sessionId, status }` 加 `replay: true`(`status` 是那一行此刻的词:在跑 ⇒ `running`;结果已被清空的终局行 ⇒ 它的终局词;失联的行与读面同判折成 `failed`),去 `GET /v1/runs/:taskId` 轮询 / 读行。
|
|
596
|
+
流式腿:`done.result` 是同一份体,帧上的 `replay: true` 照旧(已知差:停驻体上的回执三键,同步腿的首答带、流式腿的首答 `done.result` 不带,流式重放照同步腿带)。`POST /v1/runs` 与 A2A 的重放回执(202 `{ taskId, sessionId, status }`)不变。体上没有 `wiringManifest`、`notice`、`warnings`(照旧:它们说的是首帧的活捕获 / 本次请求)。
|
|
597
|
+
**键差**(重放体与上一版相比):没有了 `status`(终局)/ `errorCode` / `error` / `supervisorCost` / `suggestions` / `jobId` / `source` / `heldBy` / `cancelRequested` / `msSinceLastActivity` / `crossSliceUsage`;`result` 由对象变成串;引擎结果的其余顶层键(`terminal` / `stats` 等)现在在顶层。
|
|
598
|
+
**谁需要**:按首答形解析同步体的调用方(SDK / CLI / client-core 的同步路径)—— 重放体不用另写一支解析。**谁受伤**:按 `replay === true` 分流、再读 `body.result`(对象)/ `body.status` / `body.errorCode` 的重放分支。
|
|
599
|
+
**出路**:读顶层的引擎结果(判终局 / 停驻读 `terminal.kind`,与首答同);要读面键就读 `GET /v1/runs/:taskId`(`taskId` 在体里)。**升级前做**:无(部署零动作);**回滚**:回到 7.141.0 即回到读面形。
|
|
600
|
+
|
|
601
|
+
16. **http hook 名单在拨出点执行:请求 `settings.allowedHttpHookUrls` 在场而不放行 ⇒ 这条 http hook 一个字节都不发;`settings.httpHookAllowedEnvVars` 与条目 `allowedEnvVars` 取交(安全;行为面:名单在场时 http hook 可能被拒;wire 加性;部署零动作)**:
|
|
602
|
+
① **wire 面(加性)**:`settings` 受理键多两只 `allowedHttpHookUrls` / `httpHookAllowedEnvVars`(上一版新提交答 `400 request.body_shape`);能力位 `taskSettings.httpHookAllowlists`(与 `taskSettings.hooks` 同谓词,单用户车道 true)—— 端见位才发;
|
|
603
|
+
`hook_notice` 两族的 `reason` 各多一词 `url_not_allowed`(`hook_non_blocking_failure` / `hook_managed_unrun`;按开集读未知词的消费端零动作)。
|
|
604
|
+
② **行为面**:两张名单是请求 `settings` 这一层的(设置源 `flagSettings`),读法与判决只在契约包;http 条目**拨出之前**问判官 —— URL 名单在场而这条的 `url` 不命中、名单是空的 `[]`、或名单不是串数组 ⇒ 不发出(零字节),
|
|
605
|
+
非托管组是非阻断故障(故障帧 + 运维 warn `hook_http_withheld`),托管组失效关闭(`PreToolUse` 在没有否决时折 `ask`);帧的句子点名 `settings.hooks.<event>`、规则词(`url` / `empty` / `malformed`)与出路。
|
|
606
|
+
变量名单在场 ⇒ header 只插值条目 `allowedEnvVars` 与它的交集,名单外的名字置空(既有置空行,只点名不带值)。两键都缺席 ⇒ 与上一版逐字同。提交面不判名单的值(坏形照收,在拨出点由判官拦)。
|
|
607
|
+
**谁需要**:单用户部署上带着组织或用户 http hook 名单的端(hook 在本服务上执行,名单只有在拨出处才执行得了)。**谁受伤**:带了名单而 hook 地址不在名单里的请求(那条 hook 不再发出;托管组上 `PreToolUse` 改问人);
|
|
608
|
+
上一版两键新提交即 400,停驻任务的存量体里不会有它们 ⇒ 已在跑的任务零变化。**出路**:把 hook 地址的模式加进 `settings.allowedHttpHookUrls`(模式文法见契约包;例 `https://hooks.example.com/*`),变量名加进 `settings.httpHookAllowedEnvVars`;
|
|
609
|
+
或不发这两张名单(不限)。**回滚**:回到上一版 ⇒ 两键新提交重新 400,不带名单的请求行为不变。
|
|
610
|
+
17. **🔴 问账行的成因拆成两列:SQL 后端 `approval_ask.denied_reason` 改名 `ending_cause`、加一列 `park_trigger`;local 后端问账日志整本重写一次(本服务起服时自己改;升级前备份、先停光旧副本再起本版;回滚 = 恢复备份,或下面三句手工改回;嵌入方类型面 BREAKING;wire 零变化)**:
|
|
611
|
+
旧形:一列 `denied_reason VARCHAR(64)`,`PARKING` / `PARKED` 行上是转 park 的触发成因,`VOID` / `DENIED` 行上是终态成因;对账器收 `PARKING` 行时终态成因覆盖触发成因。
|
|
612
|
+
新形:`ending_cause VARCHAR(64)`(终态成因;到 `VOID` / `DENIED` 的转移带着它写)+ `park_trigger VARCHAR(64)`(触发成因;只由转 park 的那一次写,此后不变)。新建的库直接建成新形。
|
|
613
|
+
本条**不用手跑 `ALTER`**:起服时在一次性迁移锁内依次 —— ① `denied_reason` 在 ⇒ 改名 `ending_cause`(MySQL 协议 `CHANGE COLUMN`、PostgreSQL `RENAME COLUMN`);② `park_trigger` 不在 ⇒ 加列;
|
|
614
|
+
③ `PARKING` / `PARKED` 行上那一格搬进 `park_trigger`,再把这两态上的 `ending_cause` 置空。中途被打断,下次起服从断点续;第二次起服零命中。库账号要有 DDL 权限(起服建表本就要求)。
|
|
615
|
+
终态行上早已被覆盖掉的触发词没有出处可补 —— 如实缺席(决断口 `410` / 晚答 `404` / 按问读口读的终态成因逐字不变)。
|
|
616
|
+
`DB_BACKEND=local`:问账日志 `approval-asks/asks.jsonl` 的记录信封号 1 → 2;窗内信封 1 的记录按旧律译读(行快照按行的状态、转移补丁按目标态),起服一次压实把整本重写成信封 2。
|
|
617
|
+
起服行 `one_time_migrations_applied` 的三个读数键:`askCauseColumnsChanged`(表形改动 0–2 处;SQL)· `askParkTriggersMoved`(搬了几行触发词;SQL)· `askJournalRecordsUpgraded`(重写前读到的信封 1 记录数;local)。
|
|
618
|
+
**升级步**:① 备份整个库 / 整个数据根(回滚的前提)。② 推荐先停光全部旧副本再起本版:改名之后仍在跑的旧副本对 `approval_ask` 的每一条读写都响亮失败(不会写错列),重叠期间它们上的审批卡读写报错。
|
|
619
|
+
③ 窗口:本条迁移自引入它的版本发布日起 30 天内每次起服都跑,窗关之后的第一个小版本删码 —— **跳版升级要在窗内先起一次带本条的版本**:删码之后,SQL 库上仍带 `denied_reason` ⇒ 起服拒
|
|
620
|
+
(退役 schema 探针,拒句点名出路);local 数据根里仍有信封 1 的记录 ⇒ 问账店拒启(`unknown envelope version`)。
|
|
621
|
+
**回滚**:旧版对改名后的表读写失败、对信封 2 的日志拒启。支持形 = 恢复升级前的备份;SQL 也可手工改回(终态行上本版记下的触发成因随之丢):
|
|
622
|
+
MySQL 协议 `UPDATE approval_ask SET ending_cause = park_trigger WHERE state IN ('PARKING', 'PARKED') AND park_trigger IS NOT NULL; ALTER TABLE approval_ask DROP COLUMN park_trigger; ALTER TABLE approval_ask CHANGE COLUMN ending_cause denied_reason VARCHAR(64) NULL;`;
|
|
623
|
+
PostgreSQL 前两句同,第三句 `ALTER TABLE approval_ask RENAME COLUMN ending_cause TO denied_reason;`。local:恢复数据根备份(或移开 `approval-asks/asks.jsonl` —— 其上的每张审批卡作废)。
|
|
624
|
+
**嵌入方类型面(BREAKING,零别名)**:`StoreBackend.approvalAsk()` 的行型 `AskRow.deniedReason` → `endingCause` + `parkTrigger`;转移补丁 `AskTransitionPatch.deniedReason` → `endingCause`(值域 = 结局成因闭集;补丁没有触发成因那一键);
|
|
625
|
+
终局 claim 的败方读数 `current.cause`(`{ kind, cause }`)→ `current.endingCause` / `current.parkTrigger`(各是词本身,读不出即缺席);按状态分派的读口 `causeOfAskRow` 与型 `AskRowCause` 删除,换 `askRowEndingCause` / `askRowParkTrigger`;
|
|
626
|
+
`StoreBackend.runOneTimeMigrations()` 的报告多三键(上列)。自建问店的嵌入方:到 `VOID` / `DENIED` 的转移写终态成因格,赢下 `STREAM_PENDING → PARKING` 的 `claimTerminal(expire, { cause })` 写触发成因格,其后不再写它。
|
|
627
|
+
— **谁需要**:排查「这张卡为什么进了投递面、后来又为什么被收掉」的运维与取证。— **谁受伤**:滚动升级重叠期的旧副本(审批读写报错)、回滚(只剩恢复备份或手工三句)、自建问店 / 读行型的嵌入方(tsc 红)。
|
|
628
|
+
— **出路**:如上升级步;嵌入方按上列改名。
|
|
629
|
+
18. **沙箱 git 平面接上有效配置块 `sandboxGit`:中心投影的块热生效,坏块读作没有任何 origin 并一行 warn `web_admin_sandbox_git_refused`;本版平面读数不变;嵌入方 `ServiceDeps.sandboxGitPlane` 由值改为读函数(部署面零动作;运维面多两行日志;嵌入方类型面 BREAKING)**:
|
|
630
|
+
① **部署面**:块的唯一来源是中心有效配置 —— 控制台按部署登记册投影,只在本 worker 自己的拉取上(配了 `SEMA_WEB_ADMIN_WORKER`)出现;没有 env 旋钮,本地配置源(`CONFIG_PROVIDER=local`)没有这一块。
|
|
631
|
+
块随有效配置的每次提交热换代(刷新拍 / 迟到起服 / LKG 起服都一样),不签重启;中心凭证换人降档时随整份中心配置撤下。块判不过契约(重复 origin / 超过 16 项 / 非规范 origin / `connectUrl` 不是 https / 不是对象)⇒
|
|
632
|
+
当作没有任何 origin,一行 warn `web_admin_sandbox_git_refused`(`version` / `issues` 逐条坐标 + 契约拒句 / `effect`,不回显值),同一份候选的其余配置照常落地;块换代一行 info `web_admin_sandbox_git { version, origins }`。
|
|
633
|
+
已经建起的沙箱 pod 的路由表在建 pod 时定下:删 / 加 origin 对新 pod 生效。
|
|
634
|
+
② **本版平面读数不变**:取值口的 worker 凭据仍没接线,`GET /v1/capabilities` 的 `credentialPlane.sandboxGit` 停在 `no_caller_credential`(或更前的词),没有 pod 挂代理。
|
|
635
|
+
这个值现在每次读时求值(起服读数 + 当前生效配置的块),不再是起服时算一次的读数。
|
|
636
|
+
③ **嵌入方类型面**:自建 `ServiceDeps` 带 `sandboxGitPlane` 的,它由读数(`SandboxGitPlane`)改为读函数(`() => SandboxGitPlane`;能力位每次请求调它)—— tsc 红即通知;组合根交的是平面座的 `now`。
|
|
637
|
+
④ **同版(部署零动作)**:run 行记下登录令牌的化身号(`sub_inc` ⇒ `task_run.identity_principal_inc`,零 DDL);超过 64 字符的声明不记、一行 warn `run_identity_claim_unrecorded { claim, chars, max }`(scope 超过 190 字符铸不出元组的旧行为同一行告警)。
|
|
638
|
+
嵌入方自建的鉴权桥验证器交出在场而不是非空串的 `principalInc` ⇒ 身份不装(计数 `auth_bridge_verify_total{outcome="malformed"}`),声明缺席时不铸这一键即可。
|
|
639
|
+
**谁需要**:多租户 k8s 部署里要让成员用自己的 Gitea 凭据 clone / push 的团队、在控制台增删 origin 要不重启就生效的运维。**谁受伤**:坏块的部署(平面读 `no_origins`);按 `sandboxGitPlane` 读数装配的嵌入方。
|
|
640
|
+
**出路**:按 warn 行点名的坐标修控制台上的块;嵌入方交读函数。**升级前做**:无。**回滚**:回到上一版 ⇒ 块被忽略(平面读 `no_origins` 那一侧不变),run 行化身号一格回到恒空。
|
|
641
|
+
19. **自由文本脱敏的两处已知漏形(安全披露;零行为变更;部署零动作)**:
|
|
642
|
+
这两形在本版与此前各版都**不遮**,不是本版引入;写在这里,是让按「凭据不会以明文出现在日志 / 转录里」配告警、做审计的部署知道它们在射程外:
|
|
643
|
+
— **复合凭据名在自由文本里的 `名=值`**:`api_key` / `apikey` / `api-key` / `access_token` / `refresh_token` / `id_token` / `private_key` / `x-amz-signature` / `x-amz-security-token` / `x-amz-credential` 在自由文本里没有名字锚:后面的值只有自身形状被别的臂认出(`ghp_…` / `sk-…` / `AKIA…` 这类)时才遮,否则在结果、账本回放、流式与同步体、运维日志行上都原样 ——
|
|
644
|
+
与旁边有没有私钥栅栏无关(私钥块本身照遮)。同一批名字在 JSON 字段(`{"api_key": "…"}`)与 URL 参数(`?api_key=…`)位上照遮;`password` / `passwd` / `pwd` / `secret` / `client_secret` 在赋值符两侧零空白的 `名=值` 形上、值是以字母数字起头的字面量时照遮(`$VAR` / `%s` / `<占位>` / 表达式 / `None` 一类不算值)。
|
|
645
|
+
— **强锚名紧贴在前一枚凭据的尾巴上**(`-----END PRIVATE KEY-----password=…`;PGP 收尾栅栏、PuTTY 的 `Private-MAC:` 行、AWS 键 id 同形;中间没有空白、换行、`?` / `&` 或引号):
|
|
646
|
+
流式 done 帧、同步体、运维日志行上原样;run 行与账本回放上被遮(读面多过一遍脱敏)。
|
|
647
|
+
**谁受伤**:无(零行为变更)。**读法 / 出路**:要靠脱敏挡住的凭据,别以这两种形写进 prompt、工具输出或错误句;放进 JSON 字段 / URL 参数 / `Authorization` 头这类结构化位置照遮;
|
|
648
|
+
已有的日志与转录可按这两种形自查。修好的那一版,这些值改成 `«redacted»`(那一版的本文件另写一条)。**升级前做**:无;**回滚**:无关。
|
|
649
|
+
20. **用户面通告多一键 `eventId`(每次投递的身份),live 帧自此带 `id:` 行;有账本口的腿上,断流后通告与文件卡的死直写不再记「丢帧」,文件卡账本孪生的写失败改记计数(wire 加性;运维面计数口径变化;部署零动作)**:
|
|
650
|
+
`engine_notice` 帧的载荷由五键(`code` · `message` · `detail` · `sessionId` · `ts`)变六键:多 `eventId`(非空串,uuidv7 形)。server 在分流器扇出时给每一条通告铸一枚,同腿的 live 帧与 durable 账本行是同一只行,所以同值;
|
|
651
|
+
live 帧因此发 `id:` 行(值逐字 = 载荷 `eventId`;此前通告帧没有 `id:` 行,契约 §0.6「无锚不发行」名单里不再有它);`GET /v1/runs/:id/events` 的 `id:` 仍是行 `seq`(两个 id 域不可互推)。
|
|
652
|
+
同一内容的两次投递是两枚。本版之前写下的账本行没有这一键,重放不补。读者从 live 换到 events 车道只能从 0 重放,重放里会再看到 live 上已见过的通告 —— 按载荷 `eventId` 认同一件事(契约附录 D.1「投递律」)。
|
|
653
|
+
无新帧、无新端点、无新能力位、无新拒码;账本行 `data` 是 JSON,多一键不动 SQL。
|
|
654
|
+
遥测(运维面):`frame=engine_notice` 与 `frame=file_link` 的 `server.stream.frame-dropped-stream-closed`(断流丢帧)自此**只在本腿没有账本口的部署上记**(无 run 店 ⇒ 无 durable run 行);有账本口的腿上,客户端已断时这一帧在账本里,账本孪生即送达,不再另记 ——
|
|
655
|
+
丢没丢只由账本那一笔判:通告写失败记 `server.engine-notice.durable-append-failed`(旧有),文件卡账本孪生写失败改记 `server.ledger.forward-append-failed`(`type=file_link`;修前静默吞,工具面仍不 fault;流已断时账本那一笔失败 = 这张文件卡整张没送达)。
|
|
656
|
+
所以有 run 店的部署上这个丢帧计数会掉:不是壳修好了,是有账本口的那部分不再被当成丢。live 可以多于账本:账本那一笔写失败时,用户在线上看见了这一条、重放里没有。
|
|
657
|
+
本版保证到哪:在该腿把终局帧入链之前发出的通告,账本里先于终局帧(按停的中断说明即是);终局帧之后才发出的通告(引擎收尾阶段的通告、非 detach 断连之后引擎中止尾巴上的通告、无在册腿时发出的通告)不在保证内(契约附录 D.1)。
|
|
658
|
+
**谁需要**:从 live 换到 events 车道的客户端(无报告 id 的通告码,如中断说明,此前跨车道会渲两次);读遥测查「通告丢没丢」的运维(此前计数把没丢的也算成丢)。
|
|
659
|
+
**谁受伤**:① 严格按「五键」校验通告载荷的消费端(多一键);② 把 live 流最后一枚 `id:` 当续流游标的消费端:游标现在可能落在通告帧上(值仍是 uuidv7,与其它 live 帧同域);
|
|
660
|
+
③ 按 `frame-dropped-stream-closed` 做看板 / 告警的运维:有 run 店的部署上计数会掉;④ 本版之前写下的账本行没有 `eventId`,对它们跨车道仍去不了重。
|
|
661
|
+
**出路**:消费端接受第六键、按 `eventId` 去重(键缺席回到流内序);看板改按 `server.engine-notice.durable-append-failed` 与 `server.ledger.forward-append-failed` 读「没落账」,按 `frame-dropped-stream-closed` 读「无账本腿上真丢」。
|
|
662
|
+
**回滚**:回到上一版,通告帧回到五键、无 `id:` 行,计数口径回到旧样;已写下的账本行多着一键,旧版读口逐字透传,不受影响。
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
21. **更正(7.138.0 节第 19 条 ②,文书;零行为变化)**:待决工具审批行被拒的拒体是**顶层** `reason: "tool_identity_missing"`(`src/http/refusal-body.ts:37`,与 `blockedBy` / `field` 同一层),不是 `detail.reason` —— 本仓拒体没有 `detail` 对象。读那一条的消费方按顶层 `reason` 读;7.138.0 节原文不改(已发节字节不动)。
|
|
666
|
+
|
|
10
667
|
## 7.141.0 —— 起服自有凭据值被引擎拒收改发结构化 warn `own_credential_value_not_withheld`(运维面;日志形变更) · 两条用户面文案订正(起服行 `tool_policy_single_user_default` 的 `posture`、`SENSITIVE_WRITE_PATTERNS` 说明;文字,零行为变更) · `/decide` 续跑腿批准后被取消:终局文案改「已取消、不可再续」(行为面;文字;码不变) · 会话同步导入的 `anchors[]` 必须指向这次导入声明的条目(新提交 400;出口过滤存量悬空锚) · 流式口每帧带 `event:` 行(BREAKING)· 回退锚写入腿内落定(有界) · device 车道 `DEVICE_RELAY_URL` 必声明(URL 或 `none`;缺席拒起) · 显式 `DB_BACKEND=mysql|pg` 而该引擎的坐标缺席 ⇒ 起服拒,与 `SESSION_BACKEND` 怎么写无关(行为收紧,fail-closed;运维面) · 起服多一次只读普查:存量停驻行里带「无 `kind` 的 batch 成员」的行数(运维面;零动作;不改任何一行) · 🔴 local 后端数据根一次性迁移:会话的建档时刻与 fork 谱系搬进会话元数据边档、带属主戳的会话存档改写成匿名(本服务起服时自己改;升级前备份数据根、先停光旧进程;回滚只有恢复备份)· 仍带戳的存档 fork / 改日志推送答 409 `conflict`(行为收紧)· 先清后导之后建档时刻不变(行为修复) · 本机形(`DB_BACKEND=local`)后台子代的转录活过重启、随记录同亡;接线清单 `fleet.subagentTranscripts` 在 local 上改答 `full`、`rows` 档不再由本服务产出(行为变更;wire 值变化) · 记忆同步停驻:游标用不了的层只点名删游标一条出路,`GET /v1/sessions/:id/memory-status` 加性键 `memorySync`、停驻层的运维行改名 `memory_sync_layer_parked`(wire 加性;运维面日志形变更;订正 7.139.0 / 7.140.0 两节的处置句) · 在飞 run 的权限模式切档口 `POST /v1/runs/:id/permission-mode`(wire 加性;能力位 `permissionModeWrite` 按部署翻真) · `settings.permissions.deny` / `ask` 的条目可带出处层 `{ rule, layer }`:user 层的 `/` 形路径规则读在执行环境的配置根(wire 条目型放宽 + 能力位 `settings.permissions.layers`;端见位才发) · `GET /v1/runs/:id` 的 `heldBy` 终态行恒 `null`(一个条件:`null` = claim 已释放;wire 值域变化) · 运维队列行 / `/stream` `pending` 帧恰带授予绑定一臂,升级前停驻的卡投 `boundGrantAbsence: "unreadable"`(wire 值域变化) · 沙箱三车道读拒表字节地板的接线与新旋钮 `SANDBOX_READ_FLOOR`(keep | off,缺省 keep;本版地板模块不服务任何车道 ⇒ 三车道照旧不守,零行为变化;起服行多一个字段) · `REMOTE_EXEC` 是有序车道表,表里不止一条 ⇒ 起服拒(部署 env 形变 BREAKING;单词零变化) · `MEMORY_ENGINE_BACKEND=tidb` 改名 `mysql`(旧词拒启;`memoryEngine.backend` 值变化,BREAKING) · `config.d/remote-exec.json` 非空串字段只含空白 ⇒ 起服拒(行为收紧) · 契约包 settings-schema 16.0.0 的其余读点(设备入口拒句取契约 · 本地配置一次读、过深文档成被拒文档 `too_deep`) · SQL 后端(`DB_BACKEND=mysql|pg`)的主 runner 接线清单 `session.store` 由 `process_local` 改答 `declared_durable`(会话店补上顶层耐久声明;wire 值变化;只改读数) · `workflow_complete` 补投帧多可选键 `diagnostics`(引擎的诊断教学文本;过脱敏、有界;wire 加性;零 DDL;崩溃恢复补投不带) · `GET /v1/capabilities` 加能力位 `mcpTransportKinds`(请求面读器与引擎今天能拨的 MCP 传输种类;wire 加性;提交面不放宽)· `GET /health` 加性键 `engineLease: { lingerMs, tickMs }`(引擎附着租约窗上 wire;运维面)· 名单型 env 旋钮点到自有凭据名的起服拒句一句只用一套序号(文字;运维面)· 订正 7.139.0 节第 23 条 ⑤:服务进程被 `SIGKILL` 时暂存目录留在目标旁(文字订正) · 折码的运维 warn 行 `outward_failure_code_folded` 不再带失败句原文、读面同一原码只一行(运维面;日志形变更;安全) · 验证器自己停驻:恢复凭据不再外出、那张卡结算时作废、读面上不合本服务码形的存量失败码读作 `internal.store_error`(行为面;安全 / 修复) · 订正 7.140.0 节第 7 / 10 / 12 / 13 条的四处说法、第 8 条补一句(文字订正) · 契约包 settings-schema 16.0.0 · 引擎 7.60.0
|
|
11
668
|
|
|
12
669
|
1. **起服自有凭据值被引擎拒收改发结构化 warn(运维面;日志形变更;部署零动作)**:本进程自有凭据变量(配置目录 secret 名与模型条目 `apiKeyEnv`)的值被引擎判「不是凭据值」(空白 / 占位词 / 一个字符重复 / 不足 8 字符)时,
|