@sema-agent/server 7.142.0 → 7.144.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 +608 -0
- package/USAGE.md +63 -36
- package/dist/adoption/plan.js +22 -0
- package/dist/approval-ask-audit-store.d.ts +7 -5
- package/dist/approval-ask-audit-store.js +12 -6
- package/dist/approval-ask-machine.d.ts +15 -7
- package/dist/approval-ask-machine.js +10 -4
- package/dist/approval-card.d.ts +155 -39
- package/dist/approval-card.js +111 -31
- package/dist/approval-queue-kind.d.ts +27 -0
- package/dist/approval-queue-kind.js +6 -0
- package/dist/approval-reconciler.d.ts +8 -8
- package/dist/approval-reconciler.js +3 -3
- package/dist/audit.js +4 -2
- package/dist/boot/budget-tracing.d.ts +1 -1
- package/dist/boot/execution-env.js +1 -1
- 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 +3 -3
- package/dist/boot/reapers.js +5 -4
- package/dist/boot/resolve-spec.d.ts +1 -1
- package/dist/boot/resolve-spec.js +8 -8
- package/dist/boot/runner-deps.d.ts +14 -6
- package/dist/boot/runner-deps.js +6 -17
- package/dist/boot/shutdown.d.ts +9 -0
- package/dist/boot/shutdown.js +18 -2
- package/dist/boot/stage-01-config.js +2 -0
- 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 +3 -5
- package/dist/boot/stage-05-execution-env.d.ts +5 -2
- package/dist/boot/stage-06-runners.d.ts +5 -2
- package/dist/boot/stage-06-runners.js +1 -3
- package/dist/boot/stage-07-capability-layer.d.ts +5 -2
- package/dist/boot/stage-07-capability-layer.js +6 -2
- package/dist/boot/stage-08-reapers.d.ts +5 -2
- package/dist/boot/stage-09-leader.d.ts +5 -2
- package/dist/boot/stage-10-http-server.d.ts +5 -2
- package/dist/boot/stage-10-http-server.js +4 -1
- package/dist/boot/stores.d.ts +5 -2
- package/dist/boot/stores.js +7 -7
- package/dist/boot/web-admin.d.ts +5 -1
- package/dist/boot/web-admin.js +31 -19
- 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 +23 -17
- package/dist/capabilities/scenarios.js +2 -2
- package/dist/capabilities/skills.d.ts +1 -17
- package/dist/capabilities/skills.js +0 -8
- package/dist/capability-facts.d.ts +8 -8
- package/dist/capability-facts.js +4 -4
- package/dist/card-void.d.ts +6 -9
- package/dist/config-catalog.js +1 -1
- package/dist/config-d-migration.d.ts +2 -0
- 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 +5 -5
- package/dist/config.d.ts +4 -3
- package/dist/config.js +1 -1
- package/dist/delegated-session-owner.d.ts +35 -151
- package/dist/delegated-session-owner.js +1 -83
- package/dist/device-ws-protocol.d.ts +1 -0
- package/dist/device-ws-protocol.js +2 -1
- package/dist/entry-mode-clamp-notice.d.ts +1 -1
- package/dist/env-model-table-gate.d.ts +53 -0
- package/dist/env-model-table-gate.js +53 -0
- package/dist/execution-placement.d.ts +7 -4
- package/dist/fleet/fleet-bus.d.ts +28 -52
- 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/classic-stations.d.ts +3 -1
- package/dist/hooks/classic-stations.js +2 -0
- package/dist/hooks/hook-runner.js +28 -7
- 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/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/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 +1 -1
- package/dist/http/refusal-body.d.ts +7 -3
- package/dist/http/refusal-body.js +1 -0
- package/dist/http/resume-legs.d.ts +21 -7
- package/dist/http/resume-legs.js +82 -53
- 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/routes/approvals-assistant.d.ts +9 -1
- package/dist/http/routes/approvals-assistant.js +143 -31
- package/dist/http/routes/capabilities.js +11 -2
- package/dist/http/routes/memory-policy.d.ts +2 -2
- package/dist/http/routes/memory-policy.js +1 -1
- package/dist/http/routes/notify-wake.js +23 -25
- package/dist/http/routes/rules.js +48 -13
- package/dist/http/routes/runs.js +9 -8
- package/dist/http/routes/session-memory-sync.d.ts +34 -6
- package/dist/http/routes/session-memory-sync.js +27 -10
- package/dist/http/routes/session-sync.js +13 -20
- package/dist/http/routes/sessions.d.ts +2 -2
- package/dist/http/routes/sessions.js +22 -23
- package/dist/http/routes/tasks.js +27 -49
- package/dist/http/server.d.ts +13 -7
- package/dist/http/server.js +2 -2
- package/dist/http/stored-body-replay.js +15 -4
- package/dist/http/wire-types.d.ts +17 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lane-home-probe.d.ts +15 -0
- package/dist/lane-home-probe.js +4 -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-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.js +14 -3
- package/dist/memory-sync.d.ts +20 -4
- package/dist/memory-sync.js +23 -4
- package/dist/model-plane-face.d.ts +13 -7
- package/dist/model-plane-face.js +2 -1
- package/dist/observability/corrupt-read-seat.d.ts +5 -9
- package/dist/observability/corrupt-read-seat.js +1 -2
- package/dist/observability/fail-open.d.ts +30 -10
- package/dist/observability/fail-open.js +27 -10
- package/dist/observability/run-terminal.d.ts +1 -1
- package/dist/observability/run-terminal.js +6 -2
- 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.d.ts +6 -7
- package/dist/parked-revive-surface.js +1 -1
- package/dist/peer-inbound-face.d.ts +122 -0
- package/dist/peer-inbound-face.js +123 -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.js +18 -6
- package/dist/plugins/approval-ask-store-memory.js +8 -6
- package/dist/plugins/approval-ask-store-sql.d.ts +28 -13
- package/dist/plugins/approval-ask-store-sql.js +30 -11
- package/dist/plugins/caching-session-store.d.ts +0 -3
- package/dist/plugins/caching-session-store.js +0 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +45 -38
- package/dist/plugins/checkpoint-store-sql.js +108 -45
- 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 +29 -0
- package/dist/plugins/file-run-store.js +97 -8
- package/dist/plugins/fork-routing-session-store.d.ts +8 -1
- package/dist/plugins/fork-routing-session-store.js +6 -0
- 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 +6 -8
- package/dist/plugins/local-checkpoint-store.js +5 -4
- package/dist/plugins/local-session-store.d.ts +69 -30
- package/dist/plugins/local-session-store.js +133 -57
- package/dist/plugins/local-session-window.d.ts +4 -2
- 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-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 +44 -14
- package/dist/plugins/one-time-migrations.js +118 -15
- 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/pg-session-storage.d.ts +1 -9
- package/dist/plugins/pg-session-storage.js +2 -19
- package/dist/plugins/remote-env-device.d.ts +8 -11
- package/dist/plugins/remote-env-device.js +6 -3
- package/dist/plugins/remote-env-host.d.ts +8 -4
- package/dist/plugins/remote-env-host.js +7 -9
- package/dist/plugins/remote-env-k8s.d.ts +37 -24
- package/dist/plugins/remote-env-k8s.js +50 -17
- package/dist/plugins/remote-shell.js +12 -2
- package/dist/plugins/retention-store-sql.d.ts +2 -2
- package/dist/plugins/sandbox-read-floor.d.ts +5 -7
- package/dist/plugins/sandbox-read-floor.js +2 -7
- package/dist/plugins/schema-consistency.d.ts +5 -1
- package/dist/plugins/session-fork.d.ts +1 -1
- package/dist/plugins/session-ownership.d.ts +9 -0
- package/dist/plugins/session-ownership.js +6 -0
- package/dist/plugins/session-store.d.ts +13 -16
- package/dist/plugins/session-store.js +9 -10
- package/dist/plugins/sql-errors.d.ts +10 -1
- package/dist/plugins/sql-errors.js +13 -0
- package/dist/plugins/sql-json-column.d.ts +24 -2
- package/dist/plugins/sql-json-column.js +38 -3
- package/dist/plugins/store-backend.d.ts +23 -28
- package/dist/plugins/store-backend.js +12 -3
- package/dist/plugins/store-contracts.d.ts +29 -5
- package/dist/plugins/store-contracts.js +4 -1
- package/dist/plugins/task-attachment-store.d.ts +2 -2
- package/dist/plugins/task-attachment-store.js +37 -52
- package/dist/plugins/tidb-session-store.d.ts +2 -14
- package/dist/plugins/tidb-session-store.js +2 -20
- 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 +1 -1
- 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 -6
- package/dist/runs.d.ts +12 -8
- package/dist/runs.js +10 -7
- package/dist/runtime-governance.d.ts +1 -1
- package/dist/security.d.ts +0 -4
- package/dist/server-secret-env.d.ts +4 -0
- package/dist/session-error-wire.d.ts +34 -23
- package/dist/session-error-wire.js +8 -3
- package/dist/session-incarnation.d.ts +3 -3
- package/dist/session-notify-door.d.ts +106 -0
- package/dist/session-notify-door.js +97 -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 +11 -8
- package/dist/task-settings.js +31 -11
- package/dist/tool-approval.d.ts +55 -35
- package/dist/tool-approval.js +112 -74
- package/dist/trace/core-keyset-guard.d.ts +12 -9
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +4 -2
- package/dist/trace/exit-seat.d.ts +7 -1
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/ledger-sink.d.ts +2 -2
- package/dist/trace/ledger-sink.js +12 -4
- package/dist/trace/model-segment.d.ts +74 -25
- package/dist/trace/model-segment.js +141 -32
- package/dist/trace/project.d.ts +15 -6
- package/dist/trace/project.js +12 -4
- package/dist/trace/redact.d.ts +72 -9
- package/dist/trace/redact.js +1509 -471
- package/dist/trace/self-minted-wire.d.ts +598 -47
- package/dist/trace/self-minted-wire.js +190 -20
- package/dist/trace/wire-projection-faces.d.ts +1 -1
- package/dist/trace/wire-projection-faces.js +1 -1
- 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 +90 -10
- 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.143.0.json +1167 -0
- package/wire-changes/server@7.144.0.json +291 -0
- package/dist/session-records-skipped-notice.d.ts +0 -21
- package/dist/session-records-skipped-notice.js +0 -27
|
@@ -183,12 +183,20 @@ export const FAIL_OPEN_TAGS = {
|
|
|
183
183
|
},
|
|
184
184
|
"server.approvals.park-row-blob-unreadable": {
|
|
185
185
|
cls: "F",
|
|
186
|
-
note: "S-700(`plugins/checkpoint-store-sql.ts` 的 `readParkRowActionCell`):运维待批队列(`GET /v1/approvals` / `/stream`)的某一行,`checkpoint` 列里寄存行的 **`pendingAction` 子树**(NP-3 / 7.100.0 起引擎内只取这一棵、整只快照不出库;只为 park 行事实 `requiresRealApproval` / `ruleOffersAbsence` / `mandated`(S-663 二段,core #1079)/ `mandate`(S-721)/ `origin`(S-755)而读 —— 事实位的真源是 `approval-card.ts` 的 `ParkRowFacts`)**在场却不是一只对象**(JSON `null` 字面 / 串 / 数 —— 手改 / 迁移脚本改过)。子树**缺席**(SQL NULL:成员不在,或整只文档不是对象 —— 后者 `get()` 照旧拒;MariaDB 文本承载上的非 JSON 字节同样答 SQL NULL)⇒ 事实缺席、不计数。放行的最坏后果 = **这一行**的 park 行事实(`ParkRowFacts` 各位)缺席(展示/分诊材料;core 定性 display metadata,resume 的带子读 gate 自己的位),队列其余部分照常 —— 而这一行本来就 resume 不了(`get()` 对同一格拒)。不放行的代价是整只 `rows.map` 抛出 ⇒ 一行坏 blob 打掉整个租户的队列(列表 500、SSE 心跳照常而队列永远空),与同一 `rows.map` 里 `rule_suggestions` / `risk_descriptor` 两格同族同判。故 F 类;tag 与那两格**分开计**(哪一格在坏要读得出来)。计数非零 = 这一行的 decide 同样读不动(`get()` 对同一格拒),去按 session 查那一行。 (`member=gate` 那第二座随 core 7.55.0 #1468 P1 阶段二退役:队列行的卡与到期分法改读 `approval_card` / `gate_kind` 两列 —— 写口与 M29 回填同一只派生落下的格 —— 本读面不再读 blob 的 `gate` 子树。)S-2076
|
|
186
|
+
note: "S-700(`plugins/checkpoint-store-sql.ts` 的 `readParkRowActionCell`):运维待批队列(`GET /v1/approvals` / `/stream`)的某一行,`checkpoint` 列里寄存行的 **`pendingAction` 子树**(NP-3 / 7.100.0 起引擎内只取这一棵、整只快照不出库;只为 park 行事实 `requiresRealApproval` / `ruleOffersAbsence` / `mandated`(S-663 二段,core #1079)/ `mandate`(S-721)/ `origin`(S-755)而读 —— 事实位的真源是 `approval-card.ts` 的 `ParkRowFacts`)**在场却不是一只对象**(JSON `null` 字面 / 串 / 数 —— 手改 / 迁移脚本改过)。子树**缺席**(SQL NULL:成员不在,或整只文档不是对象 —— 后者 `get()` 照旧拒;MariaDB 文本承载上的非 JSON 字节同样答 SQL NULL)⇒ 事实缺席、不计数。放行的最坏后果 = **这一行**的 park 行事实(`ParkRowFacts` 各位)缺席(展示/分诊材料;core 定性 display metadata,resume 的带子读 gate 自己的位),队列其余部分照常 —— 而这一行本来就 resume 不了(`get()` 对同一格拒)。不放行的代价是整只 `rows.map` 抛出 ⇒ 一行坏 blob 打掉整个租户的队列(列表 500、SSE 心跳照常而队列永远空),与同一 `rows.map` 里 `rule_suggestions` / `risk_descriptor` 两格同族同判。故 F 类;tag 与那两格**分开计**(哪一格在坏要读得出来)。计数非零 = 这一行的 decide 同样读不动(`get()` 对同一格拒),去按 session 查那一行。 7.144.0 起同 tag 另有一座:判官判决 `rowVerdict` 与技能卡两位共用的那一次**整行读**(`projectStoredRow`;按快照摘要记忆,未命中才读)—— 整行解不出 ⇒ 这一行不带判决与两位;体是对象但 core 摘要读不动 ⇒ 判决照给、只丢两位;两形逐次计、不进记忆,一行坏体在子树与整行两读上各计一次。 (`member=gate` 那第二座随 core 7.55.0 #1468 P1 阶段二退役:队列行的卡与到期分法改读 `approval_card` / `gate_kind` 两列 —— 写口与 M29 回填同一只派生落下的格 —— 本读面不再读 blob 的 `gate` 子树。)(S-2076 的 `readParkedSkillCardFacts` 两座已由上面那次 `projectStoredRow` 整行读取代,树上零命中。)",
|
|
187
187
|
},
|
|
188
188
|
"server.approvals.durable-row-checkpoint-id-missing": {
|
|
189
189
|
cls: "F",
|
|
190
190
|
note: "7.133.0(`checkpoint-identity.ts` 的 `durableRowIdentity`;两只店的 `listPending` + `/v1/assistant/inbox` handler):三处 durable 读面(运维队列行 `GET /v1/approvals` 与 `/v1/approvals/stream` 的 `pending` 帧;停驻收件 `GET /v1/assistant/inbox` 的行)读到一行停驻门**没有可用的 `checkpointId`** ⇒ 这一行**照列、`checkpointId` 键缺席**(消费方按「这一行没有可 join 的身份」处理)。detail = `face=<approvals-queue|assistant-inbox> why=<absent|untrusted>`:`absent` = 行上没有这一格(core 5.42.0 之前停驻的老行 —— core 明写不回填);`untrusted` = 在场却没过信任边界(非串 / 空串 / 超长 / 含 resume token —— 数据污染;没过边界的值不上 wire)。放行(列、键缺席)的最坏后果 = 消费方对这一行做不了跨面 join(三面对账少一行)—— 行本身、决断口(`/v1/approvals/:sessionId/decide`,按会话)、到期收割都照常。不放行有两种形:整只拒的代价是一行老 / 坏行打掉整个租户的队列(列表 500、SSE 心跳照常而队列永远停在旧帧);把这一行藏起来的代价更糟 —— 人看不到要批的东西(审批面上的 fail-open,方向反了)。故 F 类;必须留痕(两种成因从此可分)。计数非零 = 有老 / 坏行在飞(列着、没身份);`/stream` 每 3s 一拍重读,同一行每拍计一次(量值 = 行 × 拍数,在场才是信号)。 7.137.0 起第四面:park 账本行(`GET /v1/runs/:id/events` 的 `suspended` / `needs_review`;唯一构造器 `trace/project.ts` 的 `parkEventData`,写时判一次,detail `face=run-events-park`)—— 暂停因由上的门身份没过信任边界 ⇒ 行照写、`checkpointId` 键缺席(决断方回显不了这道门,退回不带键的决断或从 run 结果取原值;行本身、门、待批调用身份照常)。 第五面:回决门族的 200 体(`/decide` / `/resume` / `/plan_review` 执行之前从选中的那一行捕获一次,`http/resume-legs.ts` 三处;detail `face=decision-receipt`)—— 选中那一行的门身份没过信任边界 ⇒ 结清证据照铸、体上 `checkpointId` 键缺席(决断方只是对不上身份;位、决定、续跑都照常)。每次走到捕获点的决断计一次(计的是选中那一行的事实,与这次决断随后走哪条车道无关)。",
|
|
191
191
|
},
|
|
192
|
+
"server.peer-inbound.queue-box-unknown": {
|
|
193
|
+
cls: "F",
|
|
194
|
+
note: "S-1370(`peer-inbound-face.ts` 的 `list`;core 7.62.0 起读 core 的队列枚举 `listPeerHeldQueues`):一只有可审卡的 held 队列,它的箱(`PeerHeldQueueSnapshot.box`)既不是打开它的那只会话自己的箱、也不是 principal 收件箱 ⇒ 拼不出决断口 id 的车道段,那只队列的卡**不列**。按构造不可达:core 的快照注逐字只有这两种箱。放行(不列、队列其余照常)的最坏后果 = 那张被扣的信不出现在 `GET /v1/approvals` 的 `pending[]` 上 —— 它仍在 core 的队列里,按 `dialogExpiry` 带 `expired` 回执结清(core 的安全默认),有序关停照样结清它(关停不按车道筛)。不放行(抛)= 一只读不懂的队列打掉调用方整张审批列表(列表 500、`/stream` 每拍重读每拍抛)。故 F 类;detail `cards=<那只队列的卡数>`;`/stream` 每 3 s 一拍重读,同一只队列每拍计一次(在场才是信号);计数非零 = core 加了第三种箱,对 core 的 d.ts 重核车道读法(`org-delivery-gate.ts` 的 `laneOfBox`)。",
|
|
195
|
+
},
|
|
196
|
+
"server.session-notify.active-run-read-failed": {
|
|
197
|
+
cls: "F",
|
|
198
|
+
note: "`session-notify-door.ts` 的 `deliver`(会话通知门的判活读;两只调用方 `POST /v1/sessions/:id/notify` 与后台子代完成 relay 同经):判活读 —— run 店的单活认领读 `getActiveTaskId` —— 抛(店瞬断 / 超时 / 连接被回收)⇒ 门当这只会话**没有在飞的 run**,落空闲臂:入收件箱,下次开流排空成 `task_notification` 帧,不把读失败抛给调用方。放行的最坏后果 = 这一条通知晚到 —— 本该在活流的下一个边界投递(`priority: next`),改成下一次开流才排空(至少一次,晚一次开流),不丢、不错投;两臂的投递动作之前紧邻的住客复核照做,所以这不是门、不是权限、不是凭证。不放行(抛)= 一次 run 店瞬断把通知路由答成 500(经全局兜底)、把后台子代的完成通知记成 `relay_failed` 交不出去,比晚一次开流更糟。读失败与「会话真的空闲」在外部同形,所以必须留痕:计数 + 探针(detail 带会话 id 与错句,经记录器统一脱敏)+ 每进程一次 warn。",
|
|
199
|
+
},
|
|
192
200
|
"server.approvals.queue-row-gate-kind-missing": {
|
|
193
201
|
cls: "F",
|
|
194
202
|
note: "S-1681(`plugins/checkpoint-store-sql.ts` 的 `queueRowGateKind`,7.132.0;SQL 与 local 两只孪生的 `listPending` 同调这一只判官):运维待批队列(`GET /v1/approvals` / `/stream`)读到一行 pending 的门型(SQL 孪生:`checkpoint.gate_kind` 列;local 孪生:快照上的门)是 NULL 或不是 core 登记的门型 ⇒ 这一行**不列**。按构造不可达:每次停驻都把门型反范式进这一列,一次性迁移 M21 把没有它的存量行从门子树补齐(读不出登记门型的置 expired)。放行(不列、队列其余照常)的最坏后果 = 一行谁也决不了的行不出现在队列上 —— 它本来就不可决:每一条决断口按门型绑定取行(`gate_kind IN (…)`),证不出门型就不当它是这道门;不放行(整只拒)的代价是一行坏行打掉整个租户的队列(列表 500、SSE 心跳照常而队列永远停在旧帧)。也不按缺键投出去:消费方按 `gateKind` 路由、缺键即 fail-closed,队列行的契约是 `gateKind` 恒在场。故 F 类;计数非零 = 写腿或手改出了错,`SELECT session_id FROM checkpoint WHERE status = 'pending' AND gate_kind IS NULL` 查那一行(置 expired 或删会话)。",
|
|
@@ -303,7 +311,7 @@ export const FAIL_OPEN_TAGS = {
|
|
|
303
311
|
},
|
|
304
312
|
"server.park.toolcallid-read-failed": {
|
|
305
313
|
cls: "F",
|
|
306
|
-
note: "[4913]:durable park 投影腿在 strip 之前拿结果里的 checkpointToken 换 `pendingAction.toolCallId`(cs.get 一次读),那次读**抛了**(store 抖动 /
|
|
314
|
+
note: "[4913]:durable park 投影腿在 strip 之前拿结果里的 checkpointToken 换 `pendingAction.toolCallId`(cs.get 一次读),那次读**抛了**(store 抖动 / 坏 checkpoint 行 / 行已被并发消费)⇒ 本次 park 的 wire 投影**缺 `toolCallId` 键**,其余键(gate/checkpointId)照旧。放行的最坏后果 = 消费方(cli 判别子 v3 写者②)退回该键到货前的行为——同族多兄弟 durable park 分不出主角、诚实全不标(cli 侧 S3 局限,成文的旧现状),纯展示/关联面,不参与任何门/CAS/resume 判定,故 F 类。绝不挡终局路径是承重的:park 投影点全在 done/suspended 事件写链上,让它抛会把一次 store 抖动升级成整条 run 终局写失败。必须留痕:键缺席与「tool-less park 本就无键」([1995]② OMITTED 契约)在 wire 上同形,不计数则「投影为什么总缺」在遥测里永不显形。",
|
|
307
315
|
},
|
|
308
316
|
"server.exec-lane.ssh-host-key-unverified": {
|
|
309
317
|
cls: "P-DEBT",
|
|
@@ -315,7 +323,7 @@ export const FAIL_OPEN_TAGS = {
|
|
|
315
323
|
},
|
|
316
324
|
"server.approvals.stale-echoed-token-unreadable": {
|
|
317
325
|
cls: "F",
|
|
318
|
-
note: "S-02 codex R1-[medium](验真后修):decide 的 409 `approval_stale` 臂对**调用方回显的旧 token** 做归属判定(`cs.get(binding.checkpointToken)`),那次读**抛了**(store 抖动 /
|
|
326
|
+
note: "S-02 codex R1-[medium](验真后修):decide 的 409 `approval_stale` 臂对**调用方回显的旧 token** 做归属判定(`cs.get(binding.checkpointToken)`),那次读**抛了**(store 抖动 / 坏 checkpoint 行 / 行恰被清理)。修前这里是静默 `catch(()=>null)`,「读不出」被折成「确认不在库」——叠上 S-02 的 404 收口后,一次 store 抖动就会把合法旧 token 的 409+terminal 谎报成 404「没有这条审批」。修后:unreadable ⇒ **保持 409**(`terminal` 不披露——证不出归属就不说,与 2026-07-26 纪律同向;404 折叠只在读成功且未命中时走,探测方无法自控 store 故障 ⇒ 谕示封闭不破)。放行的最坏后果 = 该次拒体 `terminal` 诚实缺席(`currentPending` 由它自己的读口与属主复核另判,不受本臂牵连),壳退回重拉列表,judgment 面 fail-safe,故 F 类。留痕理由:这次读是 terminal 披露与 404 折叠两个判定的输入,长期抖动必须在遥测显形。",
|
|
319
327
|
},
|
|
320
328
|
"server.resume.reopen-confirm-unreadable": {
|
|
321
329
|
cls: "F",
|
|
@@ -323,7 +331,7 @@ export const FAIL_OPEN_TAGS = {
|
|
|
323
331
|
},
|
|
324
332
|
"server.approvals.stale-current-pending-unreadable": {
|
|
325
333
|
cls: "F",
|
|
326
|
-
note: "S-02 件2([5522]④→[5525]):409 `approval_stale` 拒体铸 additive 指路键 `currentPending`(本会话当前 pending 的 D-1 坐标,壳一跳重定位)时,当前 pending 行的 `cs.get(token)` 读**抛了**(store 抖动 /
|
|
334
|
+
note: "S-02 件2([5522]④→[5525]):409 `approval_stale` 拒体铸 additive 指路键 `currentPending`(本会话当前 pending 的 D-1 坐标,壳一跳重定位)时,当前 pending 行的 `cs.get(token)` 读**抛了**(store 抖动 / 坏 checkpoint 行 / 行恰被并发消费)⇒ 本次拒体**缺 `currentPending` 键**,409 本体与 `terminal` 判定照旧。放行的最坏后果 = 壳退回该键到货前的行为(重拉 GET /v1/approvals 自行重定位),纯指路/便利面,不参与任何门/CAS/resume 判定,故 F 类(同族先例:`server.park.toolcallid-read-failed`,同为 cs.get 投影读失败臂)。必须留痕:键缺席与「此刻确实没有 pending」在 wire 上同形,不计数则「指路为什么总缺」在遥测里永不显形。",
|
|
327
335
|
},
|
|
328
336
|
"server.file-history.retention-trim-failed": {
|
|
329
337
|
cls: "F",
|
|
@@ -347,7 +355,7 @@ export const FAIL_OPEN_TAGS = {
|
|
|
347
355
|
},
|
|
348
356
|
"server.run-terminal.redact-threw": {
|
|
349
357
|
cls: "F",
|
|
350
|
-
note: "三个发射座(errorMessage 终态文案 / 诊断文本 diag / 工件 artifact,probe 前缀判别;普查 56 行;补丁头 patch-head 那座随 7.83.0 / S-113 的 redactPatchHead 一并退役)+ 出口座(S-485 / RH-1:`trace/exit-seat.ts` 的 `seatText`,probe 前缀 `seat=<座表行>`;trace 帧自由文本位上抛 ⇒ 这一位换同一枚占位、投影不抛):S-105 最终轮 [medium]:终态 errorMessage/blockedReason/remoteEnvFailures[].message 脱敏抛出(RangeError:关键字/前缀臂那一形由 S-219 的 atLeast 铸点闭掉;JSON 秘密字段臂的转义对循环与 PEM 栅栏臂的标签交替循环由 S-265 换成手写线性扫描器闭掉 —— 已知形全部闭掉,本臂留作结构性兜底,计数恒零是证据、不归零即新形)⇒ 落固定占位 «redacted:oversized»——绝不落原文(安全轴 fail-closed),也绝不阻断终态翻转与 claim 释放(可用性)。方向刻意:一条超大错误体不得把 run 卡在 running。",
|
|
358
|
+
note: "三个发射座(errorMessage 终态文案 / 诊断文本 diag / 工件 artifact,probe 前缀判别;普查 56 行;补丁头 patch-head 那座随 7.83.0 / S-113 的 redactPatchHead 一并退役)+ 出口座(S-485 / RH-1:`trace/exit-seat.ts` 的 `seatText`,probe 前缀 `seat=<座表行>`;trace 帧自由文本位上抛 ⇒ 这一位换同一枚占位、投影不抛)+ 活面放行窗(`trace/model-segment.ts` 的 `createLiveModelText`,probe 前缀 `live-hold`:逐块放行口抛 ⇒ 这一拍不放、字节留在窗里;段末整段读法抛 ⇒ 余下的字节整段换同一枚占位):S-105 最终轮 [medium]:终态 errorMessage/blockedReason/remoteEnvFailures[].message 脱敏抛出(RangeError:关键字/前缀臂那一形由 S-219 的 atLeast 铸点闭掉;JSON 秘密字段臂的转义对循环与 PEM 栅栏臂的标签交替循环由 S-265 换成手写线性扫描器闭掉 —— 已知形全部闭掉,本臂留作结构性兜底,计数恒零是证据、不归零即新形)⇒ 落固定占位 «redacted:oversized»——绝不落原文(安全轴 fail-closed),也绝不阻断终态翻转与 claim 释放(可用性)。方向刻意:一条超大错误体不得把 run 卡在 running。",
|
|
351
359
|
},
|
|
352
360
|
"server.run-terminal.provider-echo-shaped": {
|
|
353
361
|
cls: "F",
|
|
@@ -359,11 +367,20 @@ export const FAIL_OPEN_TAGS = {
|
|
|
359
367
|
"server.run-terminal.output-truncated": { cls: "F", note: "S-107:持久 error 脱后 UTF-8 字节 > 65,000(TiDB TEXT 65,535 字节)⇒ 脱后切并带标记(切在占位里不是泄漏);计数=多少条终态文案被字节封顶截断" },
|
|
360
368
|
"server.runs.abort-cause-missing": { cls: "F", note: "S-947 候裁 ⑤(主会话裁:默认值保留,miss 臂必须响):续跑腿 `http/resume-legs.ts` 的 `checkpoint.resume_aborted` 臂 —— core 只在本腿递进去的信号**已中止**时铸该码,而那只信号唯一的写者是取消动词(快路 / 耐久旗轮询,句柄登记 `cancel_verb`),所以**只有 core 契约外的形**(桩 / 非 core Runner 直接抛该码,本腿句柄从未中止)才到得了「句柄上读不到成因」这一臂。取消终局照铸,成因取本腿唯一的中止词 `cancel_verb`(取消终局恒带成因由铸点签名保证,不让它缺);detail `task=<taskId>`;计数 = 多少次取消成因是默认值而不是句柄登记的。生产上恒零是证据,不归零 = 有一条不走 core 契约的 Runner 在跑续跑腿。" },
|
|
361
369
|
"server.runs.terminal-ledger-write-failed": { cls: "F", note: "S-107(全量门 silent-degradation 棘轮抓出的五处静默 `catch {}`):run 终局链里**账本腿**(flush 缓冲 text/reasoning、append `failed` 行)与终态翻转(setTerminal)已不共命运——账本 INSERT 抛不再让 run 卡 running 到 reaper;但那条抛掉的账本行之前是**静默**吞的。detail `arm=` 四臂(flush-clean-cancel / append-clean-cancel / flush-catch / append-thrown-cancel / append-failed);S-947 起续跑腿(`http/resume-legs.ts`)两座同 tag:resume-append-resume-aborted / resume-append-thrown-cancel(取消抛出两臂的 `failed` 行,修前那两臂根本不落账本终局行):缺的是 run_events 尾巴(缓冲文本或 failed 事件),run 行本身仍是 durable truth,读面/reaper 容忍缺失,故 F 类;计数=多少次终局账本写失败。" },
|
|
370
|
+
"server.live-text.hold-diverged": {
|
|
371
|
+
cls: "P-DEBT",
|
|
372
|
+
note: "live 面模型文本的流式口(`trace/model-segment.ts` 的 `createLiveModelText`,三条 live 腿共用;流式口 = `trace/redact.ts` 的 `createRedactionStream`:喂入 / 取已判定前缀 / 收尾冲刷):一段冲刷时,已取出去的逐块字节与整段读法在那一截上的渲染对不上,或有一条整段读法的跨度横跨放行位 —— 流式口的律被打破(某条臂的判定在脱敏器读出的未决尾上界 `PENDING_TAIL_UNITS` 之外落定,而它没有把那一支标成未决尾)。处置:余下的字节照整段读法出(横跨放行位的跨度整枚换记号,不再出它的原文字节),段末帧照发整段脱敏的正文、消费端按它整段替换;但**已经出门**的那几块收不回 —— 其中可能有整段读法会遮的字节(这就是 P 族的理由)。债:未决尾上界是候选池成员判定距离的最大值,正则臂从正则源读出,手写扫描器的那一项是成员处的陈述(它起头要读全的字面锚),不是从扫描器的代码机械读出;已知一形是多遮方向(方案词锚的头值在文本末尾被读成「收在行尾」,其后隔着长过上界的行内空白又跟了词 ⇒ 整段读法不遮、活流已出记号)。钉 = 基线语料逐条按块流过流式口拼接 = 整段脱敏 + 判定距离最远的几形逐码元。detail `family=<text|reasoning> len=<段长>`;计数 = 多少段的律被打破(期望恒 0)。",
|
|
373
|
+
},
|
|
362
374
|
"server.redact.ppk-eat-to-end": { cls: "F", note: "S-107 第三十二轮重扫:PuTTY .ppk 容器扫描器(redact.ts redactPpkContainers)在「无合格终止 / 收口后同容器范围再见私钥字段 / 收口后到下一版本头之间夹非空白」三形下从头**吃到输入末尾**(fail-closed 取证丢弃)——终态 errorMessage 座上=整条错误文案变成 «redacted:private-key»,与 redactions_applied_total{private-key} 的诚实替换同形不可分,故要有自己的计数/探针;影子扫不计;出口座有界行的 head 读法(只扫一段头)上「窗内无合格终止」是终止可能在窗外的未决 —— 照样遮到窗尾,但不是兜底,不计;计数=多少次整段吃尾。" },
|
|
375
|
+
"server.redact.forensic-level-cap": { cls: "F", note: "脱敏器取证相(redact.ts armPool 第二相)跑满级数界 FORENSIC_LEVEL_MAX 仍没收敛(证据链里层被认出、外层才认得出,刻意交替嵌套的私钥块 / URL 每层多一级,深过 31 层才够得着;现役语料最深 3 级)⇒ 下一级本会重跑的取证臂各自从它读证据的起点遮到窗尾(fail-closed:多遮可见、不少遮),不再升级;每次调用至多一条;影子扫不计;detail from=/len= 是视图坐标。" },
|
|
363
376
|
"server.approval-card.closed-word-out-of-set": {
|
|
364
377
|
cls: "F",
|
|
365
378
|
note: "S-249(`approval-card.ts` 的边界窄读族;今天四个成员:`readRuleOffersAbsence`、S-934 ② 起的 `readAskClassPair`(core 7.37.0 #1214 的类对 `askClass` / `classes`,活卡帧 / 呈卡帧的卡 / 运维队列行同一只,判法 = core 屏 `screenAskClassMembers`(S-955 ⑥ / core 7.38.0 #1249,本仓零自写对判),两键同在同缺,半对 / 集外 / 首员不符 / 重复员 = 屏拒 = 读不出;detail 前缀 `askClass=` / `classes=`),与 S-721 起的 `readClosedWordSeat` —— 一座一只 core 成员筛,座是参数:`mandate`(core 7.32.0 #1092,活卡帧 / 活挂起行 / 运维队列行同一只,闭集筛 = core `isPersistedRuleMandate`)与 S-755 起的 `origin`(运维队列行读 park 行孪生座,闭集筛 = core `isAskOrigin`,与 inbox 行 core 投影处同一只筛)、S-1170 起的 `classifierNoRuling`(core 7.43.0 #1353 的成因词,活卡帧读 `AskRequest.classifierNoRuling`,闭集筛 = core `isAutoModeFallbackCause`)与 `differs`(core 7.44.0 #1374,载体是 `runs.ts` 的 409 `steering.duplicate_input_id` 体读的引擎拒错 `detail.differs`,闭集筛 = core `STEER_REPLAY_FACETS` 的非空子集;集外成员 / 空 / 非数组 ⇒ 不铸 `detail`,码仍是契约);detail 前缀 `ruleOffersAbsence=` / `mandate=` / `origin=` / `classifierNoRuling=` / `differs=` 判别是哪一座;第四个成员是 `approval-content-kind.ts` 的 `readApprovalCard` —— 卡词 `approvalCard` 自己的闭集窄读,活 ask / LOCAL 店停驻门 / SQL 店读出的门子树三个载体共用一只,闭集 = core `TOOL_APPROVAL_CARDS`,detail 前缀 `approvalCard=`):活卡帧 / `card_json` / (S-700 起)运维队列行(`parkRowFacts` 读寄存行上的 park 孪生座;队列是热读面 ⇒ 同一行每读一次计一次)的一个**闭集词**座上,键在场而词不在本仓认得的那张表里(世代差,或第三方 producer)⇒ 该座**按缺席**处置。放行的最坏后果=卡上少一行「为什么这次没有规则候选」的解释(壳退回不显示该行),它**不改变任何裁决**——门在引擎里早已判完,本座是展示/观测面;反方向(把一个消费端词表外的值原样上卡)更坏:下游按闭集写的分支会落进 default 臂或渲染出生词。本臂存在的全部理由是**判别**:修前「上游发了个生词」与「上游根本没发这个键」在遥测上同形,而前者意味着本仓的词表该跟着 core 加词了(型面另有两向编译围栏,但那只在**重新编译**时说话,跑在线上的那一版不会自己红)。detail 带座名与那个词(经 redactSecrets 截 40);数 / 布尔等原始值原样,对象 / 数组 / 函数 / null 只报形名(`<object>` / `<array>` / `<function>` / `<null>`,S-700 codex r1:格式化从不调用值自己的转换方法 —— 持久层里一格 `{\"toString\":null}` 曾让诊断本身抛出、打掉整只队列)。",
|
|
366
379
|
},
|
|
380
|
+
"server.approval-card.retired-card-key-read": {
|
|
381
|
+
cls: "F",
|
|
382
|
+
note: "一次性迁移 M37 的读侧(`approval-card.ts` 的 `renameRetiredSourceKey`,存卡的唯一读者入口 `readStoredCardEnvelope` 先调它;窗与删法见 `plugins/one-time-migrations.ts` 登记表 M37 —— 窗关随 M37 删本 tag):存下的审批卡信封(`approval_ask.card_json` / local 问账的同一份信封)上,委派出处键还是引擎 7.61.0 之前的旧名 `card.sourceTaskId` ⇒ 读时改名 `sourceSessionId`(值不变),整卡照读。这不是放行:改名前后是同一个值、同一个事实,只是不改名 `.strict()` 的卡 schema 就整卡读不出(断连重放跳过、回决口按要人、幂等重入走 park)。计数非零 = 有本版之前铸的存卡还在被读(滚动升级窗里旧副本新写的、升级前已结仍被幂等重入 / 兑付读的);窗关前应归零。",
|
|
383
|
+
},
|
|
367
384
|
"server.approval-card.retired-card-word-read": {
|
|
368
385
|
cls: "F",
|
|
369
386
|
note: "S-1562(core 7.51.0 #1515 / #1702;一次性迁移 M18 的**读侧半场**,`approval-card.ts` 的 `readStoredCardEnvelope` / `currentParkArm`,窗与删法见 `plugins/one-time-migrations.ts` 登记表 M18 —— 窗关随 M18 删本 tag):存下的审批卡(`approval_ask.card_json`)或停驻行(`pendingAction` 的 `tool_approval` 臂)上带着引擎 7.51.0 退役的词 —— `ruleOffersAbsence: \"shadowed\"` 或类对里的 `governance_unavailable` —— 读时按 M18 那一只改写读(前者删键 = 合法缺席,后者换成 `rule_unreadable`、类集去重按引擎序)。每改写一次记一次;detail = 载体(`card_json` / `parked row`)与座名,不带值。放行的最坏后果 = 无:这一读与存卡的起服改写对同一份字节给同一个答案(一只函数);它不是兜底,它登记在这里是为了**响亮** —— 载体 `card_json` 计数非零 = 有起服改写够不着的卡(滚动升级窗里 7.128.x 副本新写的卡、local 文件 ask 账);载体 `parked row` 计数非零 = 读到了带旧词的停驻行(引擎写的文档,本服务从不改写它 —— 行摘要覆盖类对 `askClass` / `classes`,改写 = 续跑判 `damaged`;所以这一格在窗内随每次读到那样的行而涨,直到那些行被决掉 / 收割),运维据它判断旧副本是否都已换下、窗关删码前是否还有这种行在飞。反方向(不改写)= 修前:整张存卡读不出(断连重放跳过、幂等重入走 park、回决口按要人)、停驻行的 `shadowed` 读成「读不出 ⇒ 按强制」(拿不到「本会话放行」)。",
|
|
@@ -382,7 +399,7 @@ export const FAIL_OPEN_TAGS = {
|
|
|
382
399
|
},
|
|
383
400
|
"server.run-store.corrupt-record-skipped": {
|
|
384
401
|
cls: "F",
|
|
385
|
-
note: "S-582(`plugins/file-run-store.ts`,local 车道的 File 形 run
|
|
402
|
+
note: "S-582(`plugins/file-run-store.ts`,local 车道的 File 形 run 店;四个盘面同一只座):盘上一条记录读不出形 —— 一行 `42` / 缺本店必填键的对象 / 中间的半截 JSON(撕尾不走本 tag,那是崩溃的正常落盘形)⇒ 跳过它继续。前三个盘面各自的最坏后果:`run.json` 坏 ⇒ 那条 run 读成**缺席**(`GET /v1/runs/:id` 404,listRuns 少一行;它若占着 claim,EEXIST 路按「行不在」判残骸接管);`events.jsonl` 一行坏 ⇒ 回放少一个事件(其余照读、按 seq 去重不变);claim 记录坏 ⇒ 走既有的撕裂 claim 路(有非终局行就收编,否则隔离出 activeDir)。第四个盘面 `run-blobs/<会话>.jsonl`(`wiring_manifest` 行容器段的块账本,`plugins/wiring-section-codec.ts`)同一只座、两个检测点:① 重放时一条块记录形不合(`digest` 不是串 / `body` 不是容器)⇒ 跳过;② 读口(`getEvents`)装回时清单行引用的块不在本会话账本里(块缺:账本行被删 / 被跳过、断电丢尾、删会话时 run 目录删不掉留下的僵尸 run)⇒ 那一帧这一次不交出(永不交出缺段的清单),每个 `(taskId, seq)` 每进程计一次,`maxSeq` / `retainedFrom` 照旧按存位;明细 `kind=section-ref taskId= seq= sections=<段:摘要,…>`。块账本整份读不出(权限 / 挂载)不走本 tag,与 `events.jsonl` 读不出同一条路(strict 拒启,否则原样抛)。都是**可用性**损失,不开任何门 ⇒ F。修前三面全零披露(店自己的 `typeof … continue` 与 core 的静默跳过);计数让「这台机器的 run 账在腐」在遥测里显形。⚠️ `RUN_STORE_STRICT_HYDRATE=on` 的射程是「文件读不出」,不含「文件里有坏行」—— strict 档下坏行照走本 tag(未改 strict 语义,见普查表第 96 行)。",
|
|
386
403
|
},
|
|
387
404
|
"server.resume-anchor.corrupt-record-skipped": {
|
|
388
405
|
cls: "F",
|
|
@@ -426,7 +443,7 @@ export const FAIL_OPEN_TAGS = {
|
|
|
426
443
|
},
|
|
427
444
|
"server.session-repo.corrupt-record-skipped": {
|
|
428
445
|
cls: "F",
|
|
429
|
-
note: "S-990(`plugins/local-session-store.ts` `createLocalSessionRepo` 的 `FileSessionRepo` 座,local 车道的会话存档;`LocalSessionStore` 与会话视图口 `audit.ts` 共用,S-879):一份会话存档里有记录读不出(整行毁 / 半截 JSON / 形不对,core 记成 `kind:\"record\"` 逐条披露)或存档文件 / 目录整体读不出(`kind:\"file\"`)⇒ core 的成文处置是跳过 + 披露,会话照常打开、列表少一行。最坏后果 = 模型读到的历史少了一截 / 列表静默少一份会话 —— 都是**可用性**损失,不开任何门;发起这一轮的人另有 wire 面披露(
|
|
446
|
+
note: "S-990(`plugins/local-session-store.ts` `createLocalSessionRepo` 的 `FileSessionRepo` 座,local 车道的会话存档;`LocalSessionStore` 与会话视图口 `audit.ts` 共用,S-879):一份会话存档里有记录读不出(整行毁 / 半截 JSON / 形不对,core 记成 `kind:\"record\"` 逐条披露)或存档文件 / 目录整体读不出(`kind:\"file\"`)⇒ core 的成文处置是跳过 + 披露,会话照常打开、列表少一行。最坏后果 = 模型读到的历史少了一截 / 列表静默少一份会话 —— 都是**可用性**损失,不开任何门;发起这一轮的人另有 wire 面披露(core 7.62.0 起引擎在 run 里说 `engine_notice` 码 `session.lineage_rerooted`,丢失账读自 core 交出的存储 `getReplayLoss`,与本 tag 无关;7.104.0–7.143.0 是本仓自铸的 `session.records_skipped`)⇒ F。**计数单位 = 一条被跳过的记录 = 一次命中**(`replay` 级是同一批记录的汇总,不计,S-616 同教训);**每命中一行探针**(`SEMA_FAILOPEN_PROBE`)带 `path` / `sessionId` / `line` / `form` / `reason` 逐条明细 —— 运维要看「哪份存档的哪一行坏了」读探针,不读本条 warn:本条是每进程每 tag 一次的告警(`detail` 是首条明细,不是全部)。修前:每命中一行 warn,一份 113 行坏记录的存档做一次列表 + 一次查看打出 342 行,存档没修好每读再发。",
|
|
430
447
|
},
|
|
431
448
|
"server.workflow-run.corrupt-record-skipped": {
|
|
432
449
|
cls: "F",
|
|
@@ -540,15 +557,15 @@ export const FAIL_OPEN_TAGS = {
|
|
|
540
557
|
},
|
|
541
558
|
"server.remote-write.stage-seal-fallback": {
|
|
542
559
|
cls: "F",
|
|
543
|
-
note: "远端五条车道的写(`plugins/remote-shell.ts` 的暂存编排):准备脚本把刚建的私有暂存目录收成 0700 并读回核实(`chmod 700` 退出 0 ∧ `stat` 读回的模式低三位恰是 700 ∧ 属主 = 本身份),任一步不成 —— `chmod` 被文件系统 / 内核拒;退出 0 却没生效(不认权限位的文件系统);父目录带缺省 ACL
|
|
560
|
+
note: "远端五条车道的写(`plugins/remote-shell.ts` 的暂存编排):准备脚本把刚建的私有暂存目录收成 0700 并读回核实(`chmod 700` 退出 0 ∧ `stat` 读回的模式低三位恰是 700 ∧ 属主 = 本身份),任一步不成 —— `chmod` 被文件系统 / 内核拒;退出 0 却没生效(不认权限位的文件系统);父目录带缺省 ACL 而掩码收不下来;目录上有继承来的 ACL 条目(macOS 原生 ACL / FreeBSD · illumos ZFS 的 NFSv4 ACL)去不掉或读不出,或目标机平台不在读 ACL 的适配器闭集里(`uname -s` 不是 Linux / Darwin / FreeBSD / SunOS);目标机上没有 `stat` —— 准备退出 4、这次写**不暂存**,两只文件面、五条腿一律改为直接写目标(与「目标目录不收新名字」同一条回落;能追加写的腿直接追加,e2b / adb 的追加 = 读旧 + 拼 + 整份写目标 —— adb 的这一形就是 7.138.x 的追加,push 没有追加写)。修前这一步是 `chmod 700 … || :`:加固失败照样放行上传,字节落在一只别的身份可能读得到的目录里(P 轴 fail-open),那一臂已删,字节从不进一只没核成私有的目录。放行的最坏后果 = 这一次写失去「整旧或整新」(非原子:中途断 / 取消 ⇒ 目标可能只写了一半,整份写目标的 e2b / adb 上可能没了或只剩半份;写目标那一步因取消中断答 `unknown`,那一步开始之前取消答 `aborted`、目标未碰,那一步不收取消(ssh 的 sftp)照样写完);ssh / local-docker / k8s 写进原 inode、权限位不变,e2b 的 `files.write` 与 adb 的 push 整份写目标、inode / 权限位由对端定(adbd 不保,与 7.138.x 同形);不是门、不是凭据。Android 共享存储(`/sdcard` 一类:权限位由挂载派生、不认 chmod)上 adb 的写按 sdcardfs / MediaProvider FUSE 的权限语义**推断**每一次都走这里(未上真机,真机读数候 test;结构性,运维修不掉;工作区放在 `/data/local/tmp` 一类认权限位的目录就不走)。计数非零 = 这台目标机的这个目录上私有目录收不成私有(文件系统不认权限位 / 缺省 ACL 掩码收不下来 / 继承来的 ACL 条目去不掉 / 平台不可知 / 缺 `stat`),写在走非原子的退路,去看那个目录。detail = `<目标路径>: <准备脚本写的原因句>`。",
|
|
544
561
|
},
|
|
545
562
|
"server.park.held-card-void-failed": {
|
|
546
563
|
cls: "F",
|
|
547
|
-
note: "停驻没落定就以失败收场的腿(`runs.ts` 的 `voidHeldParkCard`;两处:后台腿 catch 的失败臂 `leg=bg`、续跑腿 catch 放认领的取消 / 普通异常两臂 `leg=resume`):手里的结果是宿主层停驻(引擎交回之前已把卡落进 checkpoint 店,卡在本 run 的会话上),而停驻行 / 用量行 / 结果到手之后的账本写抛 ⇒ 腿以 `failed` 收场、放认领;放认领之前先按卡自己的 scope 店级 `expire` 作废那张卡(动词 = `card-void.ts`
|
|
564
|
+
note: "停驻没落定就以失败收场的腿(`runs.ts` 的 `voidHeldParkCard`;两处:后台腿 catch 的失败臂 `leg=bg`、续跑腿 catch 放认领的取消 / 普通异常两臂 `leg=resume`):手里的结果是宿主层停驻(引擎交回之前已把卡落进 checkpoint 店,卡在本 run 的会话上),而停驻行 / 用量行 / 结果到手之后的账本写抛 ⇒ 腿以 `failed` 收场、放认领;放认领之前先按卡自己的 scope 店级 `expire` 作废那张卡(动词 = `card-void.ts` 的结算作废)。作废没做成 —— 店读 / 作废抛错(`store_error`)、卡的会话与本 run 的会话对不上(`card_mismatch`,只作废那一张,对不上就不动)、本部署没接 checkpoint 店(`no_checkpoint_store`)—— 照样以 `failed` 收场、放认领,每次记一次。放行的最坏后果 = 那张卡回到修前的形:留在待决面上,兑现它的 run 已经 `failed`、认领已放,决定口照样受理、续跑在没有认领的会话上驱动(`resume-legs.ts` 认领缺席成因 ②),由审批兜底收割收走;前提是停驻簿记写失败,并且这张卡没作废成(三个 reason 任一:checkpoint 店这一笔也失败 / 卡与本 run 的会话对不上 / 没接店 —— 后两者不需要第二次写失败)。不是门、不是凭据、不改 run 的判词。计数非零 = 有一次停驻没落定的失败收场留下了一张卡:按 reason 看 —— `store_error` = checkpoint 店在同一拍也出错,`card_mismatch` = 结果里的卡与本 run 的会话对不上,`no_checkpoint_store` = 这台部署没接 checkpoint 店;去看那只会话。detail = `reason=<词> leg=<bg|resume> [err=<原句>]`(不含凭据)。",
|
|
548
565
|
},
|
|
549
566
|
"server.verifier-pause.card-void-failed": {
|
|
550
567
|
cls: "F",
|
|
551
|
-
note: "验证门结算(`verifier-pause-card.ts` 的 `voidVerifierPauseCard
|
|
568
|
+
note: "验证门结算(`verifier-pause-card.ts` 的 `voidVerifierPauseCard`;四处结算点:bg 组合腿、同步提交腿、续跑 verify 臂、leader 的 worker 结算):验证器自己的停驻卡(结果上 `verification.verifierPause`)是本服务兑现不了的卡(它在验证器现铸的会话上,`/decide` 读不到续跑输入),结算时交跑过这次验证门的那只 Runner 的动词 `voidVerifierPause` 当场作废(引擎读卡上的组合腿,只收组合腿 `verify` 的卡;卡 `expired` + 停驻环境销毁 + 验证器会话放钉)。动词答 `false`(别的结算者先到)不计;动词抛 ⇒ 结算照常往下走,每次记一次:卡上记的不是验证器的腿(`resume.composition_mismatch`)、卡不在 / 没接店(`checkpoint.not_found`)、作废了但会话钉没放掉(`checkpoint.void_unpin_failed`,引擎同时报 `onError`)、店读 / 作废抛错(引擎原样抛,码读不出记 `thrown`)。放行的最坏后果 = 那张卡回到修前的形:留在待决面上点不动(`/decide` 答 409),由审批兜底收割收走;`void_unpin_failed` 时卡已作废、只是验证器会话留在副本内存里直到进程重启;不是门、不是凭据(凭据由出口封口摘,与本臂无关)、不改 run 的判词。计数非零 = 按码看:`thrown` = checkpoint 店在出错;`composition_mismatch` = 结果上的验证器停驻指向一张不是验证器腿铸的卡(去看那只会话);`void_unpin_failed` = 会话店放钉出错。detail = `code=<码 | thrown> err=<原句>`(不含凭据)。",
|
|
552
569
|
},
|
|
553
570
|
"server.run-permission-mode.write-back-unpersisted": {
|
|
554
571
|
cls: "F",
|
|
@@ -122,7 +122,7 @@ export declare function redactErrorMessage(raw: string | undefined): string | un
|
|
|
122
122
|
* `plugins/pg-pool.ts` 的 DDL),数 MB 终稿是正常形 —— {@link redactErrorMessage} 的两道上限是为
|
|
123
123
|
* `task_run.error` 那一列 `TEXT(65 535 字节)` 定的,套到这里等于用静默的数据损坏换一次脱敏。
|
|
124
124
|
*/
|
|
125
|
-
export declare function redactModelText(raw: string): string;
|
|
125
|
+
export declare function redactModelText(raw: string, before?: string): string;
|
|
126
126
|
/**
|
|
127
127
|
* 🔴 **provider 回声字段的形状闸 —— 唯一铸点**([ref],7.105.0;test [ref] 附带;动作经 [ref] 与 core 源头闸归一)。
|
|
128
128
|
*
|
|
@@ -85,9 +85,9 @@ export function redactErrorMessage(raw) {
|
|
|
85
85
|
return OVERSIZED_REDACTION_PLACEHOLDER;
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
export function redactModelText(raw) {
|
|
88
|
+
export function redactModelText(raw, before = "") {
|
|
89
89
|
try {
|
|
90
|
-
return redactSecrets(raw);
|
|
90
|
+
return redactSecrets(raw, before === "" ? undefined : { before });
|
|
91
91
|
}
|
|
92
92
|
catch (err) {
|
|
93
93
|
recordFailOpen("server.run-terminal.redact-threw", `model-text len=${raw.length} err=${errorText(err)}`);
|
|
@@ -133,6 +133,7 @@ export const RESULT_TEXT_LEAVES = {
|
|
|
133
133
|
taskId: "verbatim",
|
|
134
134
|
runId: "verbatim",
|
|
135
135
|
sessionId: "verbatim",
|
|
136
|
+
placementRoot: "verbatim",
|
|
136
137
|
model: "verbatim",
|
|
137
138
|
"terminal.code": "outward-code",
|
|
138
139
|
"terminal.message": "error-text",
|
|
@@ -166,6 +167,7 @@ export const RESULT_TEXT_LEAVES = {
|
|
|
166
167
|
"verification.findings.[]": "model-text",
|
|
167
168
|
"verification.evidence": "model-text",
|
|
168
169
|
"verification.verifierPause.sessionId": "verbatim",
|
|
170
|
+
"verification.verifierPause.checkpointId": "verbatim",
|
|
169
171
|
"attempts.[].model": "verbatim",
|
|
170
172
|
"attempts.[].errorCode": "outward-code",
|
|
171
173
|
"attempts.[].gateError": "error-text",
|
|
@@ -277,6 +279,8 @@ const TERMINAL_FAILURE_DETAIL_TREATMENT = {
|
|
|
277
279
|
providerConditionSource: "verbatim",
|
|
278
280
|
providerResetAtMs: "verbatim",
|
|
279
281
|
route: "verbatim",
|
|
282
|
+
errorKind: "verbatim",
|
|
283
|
+
tool: "verbatim",
|
|
280
284
|
},
|
|
281
285
|
coded: { kind: "verbatim", detail: "free-text-tree" },
|
|
282
286
|
model_output_invalid: { kind: "verbatim", cause: "verbatim", outputLimit: "verbatim" },
|
|
@@ -46,10 +46,9 @@ export interface WorkflowCompletionInbox {
|
|
|
46
46
|
* the ownerless fence silently starved the new claimant's push). Omitted `purgedOwner` = conservative
|
|
47
47
|
* fence-all (an ownerless caller can't distinguish). */
|
|
48
48
|
purge(sessionId: string, purgedOwner?: string | null): Promise<void>;
|
|
49
|
-
/** The originating session OBSERVED this run's terminal state
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* it already summarized). Drops the pending entry (a deliberate ack) AND arms a {@link SERVED_FENCE_MS}
|
|
49
|
+
/** The originating session already OBSERVED this run's terminal state on another delivery (the fleet bus's
|
|
50
|
+
* task-notification fold acks the family it delivered), so the push would be a pure duplicate (double
|
|
51
|
+
* delivery: the model burns turns dismissing a completion it already summarized). Drops the pending entry (a deliberate ack) AND arms a {@link SERVED_FENCE_MS}
|
|
53
52
|
* enqueue fence for this (session, runId) so a LATE-arriving notify (the notifier races the poll) is
|
|
54
53
|
* dropped too. Fence is in-memory only — a crash between poll and notify re-delivers (at-least-once; the
|
|
55
54
|
* shell's own runId dedup + the model tolerate it), mirroring the purge fence's restart posture. */
|
|
@@ -147,7 +146,7 @@ export declare class InMemoryWorkflowCompletionInbox implements WorkflowCompleti
|
|
|
147
146
|
* refused. Swept on BOTH enqueue and purge (a purge-heavy, enqueue-quiet process must not accumulate
|
|
148
147
|
* stamps unboundedly — review). */
|
|
149
148
|
private readonly purgedAt;
|
|
150
|
-
/** servedKey(sessionId, runId) → stamp:
|
|
149
|
+
/** servedKey(sessionId, runId) → stamp: served fences; an enqueue for the pair within
|
|
151
150
|
* {@link SERVED_FENCE_MS} is refused (the poll already told the model). Swept alongside the purge fence. */
|
|
152
151
|
private readonly servedAt;
|
|
153
152
|
constructor(onWarn?: ((msg: string, meta: Record<string, unknown>) => void) | undefined);
|
|
@@ -323,7 +322,7 @@ export declare function externalNotificationInboxEntry(sessionId: string, owner:
|
|
|
323
322
|
* UNTRUSTED free text). `status` collapses onto the inbox's completed|failed column; the ORIGINAL status rides
|
|
324
323
|
* the payload extras and overrides on drain (killed/cancelled reach the shell verbatim). Workflow-type
|
|
325
324
|
* notifications are the CALLER's job to filter (they have their own durable chain — double-enqueueing here would
|
|
326
|
-
*
|
|
325
|
+
* deliver the same completion twice). External notifications enter through {@link externalNotificationInboxEntry}.
|
|
327
326
|
*/
|
|
328
327
|
export declare function taskNotificationInboxEntry(sessionId: string, owner: string | null, n: EngineNotificationParkInput, enqueuedAt: number,
|
|
329
328
|
/** lead-b (dual-ID audit): the PARENT run's durable taskId (the uuid the shell's footer rows
|
|
@@ -372,18 +371,5 @@ export declare function resolveCompletionRoute(p: {
|
|
|
372
371
|
sessionId: string;
|
|
373
372
|
owner: string | null;
|
|
374
373
|
} | undefined>;
|
|
375
|
-
/**
|
|
376
|
-
* core 1.232 — resolve WHICH session's inbox entry a poll-served ack targets: the payload's
|
|
377
|
-
* `originatingSessionId` directly (core threads it on `ackServed`), else the originating run row via
|
|
378
|
-
* `sourceTaskId` (mirrors {@link resolveCompletionRoute}'s session half — same fallback, same reason:
|
|
379
|
-
* older runs may predate the lookup-free field). Returns undefined when there is no attribution — the
|
|
380
|
-
* entry stays pending (at-least-once; the shell's own dedup covers a rare duplicate).
|
|
381
|
-
*/
|
|
382
|
-
export declare function resolveServedSession(p: {
|
|
383
|
-
originatingSessionId?: string;
|
|
384
|
-
sourceTaskId?: string;
|
|
385
|
-
}, getRun?: (taskId: string) => Promise<{
|
|
386
|
-
sessionId?: string | null;
|
|
387
|
-
} | undefined | null>): Promise<string | undefined>;
|
|
388
374
|
export {};
|
|
389
375
|
//# sourceMappingURL=workflow-completion-inbox.d.ts.map
|
|
@@ -429,16 +429,4 @@ export async function resolveCompletionRoute(p, getRun, requirePrincipal) {
|
|
|
429
429
|
}
|
|
430
430
|
return { sessionId, owner };
|
|
431
431
|
}
|
|
432
|
-
export async function resolveServedSession(p, getRun) {
|
|
433
|
-
if (p.originatingSessionId)
|
|
434
|
-
return p.originatingSessionId;
|
|
435
|
-
if (p.sourceTaskId && getRun) {
|
|
436
|
-
try {
|
|
437
|
-
return (await getRun(p.sourceTaskId))?.sessionId ?? undefined;
|
|
438
|
-
}
|
|
439
|
-
catch {
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
return undefined;
|
|
443
|
-
}
|
|
444
432
|
//# sourceMappingURL=workflow-completion-inbox.js.map
|
|
@@ -8,8 +8,9 @@ import { type WorkflowAgentSessionIndex } from "./workflow-agent-session-index.j
|
|
|
8
8
|
* `completionId` = 引擎的一次完成的相关 id(fill-once,终态转换上铸):逐字、不脱敏、本服务零自铸。
|
|
9
9
|
* `diagnostics` = 引擎在完成通知上铸的诊断教学文本(未完成 agent 的摘要行、完整记录的读取手柄、journal 坐标、续跑句):补投路径是它在原腿已不在(断线重连 / 重启)时唯一的去处,
|
|
10
10
|
* 所以搬运;它是自由文本,出门前在入箱处过出口座(见 `buildWorkflowCompleteInboxEntry`),载荷上仍是引擎值。**崩溃恢复臂不带**:`WorkflowRun` 行上没有这一位,本服务不编。
|
|
11
|
-
* · `drop`:这条持久链只搬运一句受限摘要 + 诊断文本 + 路由键 —— `task_id` / `task_type` / `toolUseId` 是 live `task_notification` 帧的键(那条路径自带),`result` / `usage` 是完整结果 /
|
|
12
|
-
*
|
|
11
|
+
* · `drop`:这条持久链只搬运一句受限摘要 + 诊断文本 + 路由键 —— `task_id` / `task_type` / `toolUseId` 是 live `task_notification` 帧的键(那条路径自带),`result` / `usage` 是完整结果 / 计量,
|
|
12
|
+
* 不进补投帧:完整结果在引擎存下的运行记录里,上面搬运的 `diagnostics` 点名它的读取手柄(`ReadToolResult`;引擎没存下时那句如实说)—— 自 core 7.61.0 起
|
|
13
|
+
* 这是模型读到它的唯一一条路(轮询工具已删),所以 `diagnostics` 必须 `carry`。
|
|
13
14
|
* 键名直呼 core 的入参型(型文本里就有 core 名)⇒ 读表的 literals 段收得到这些键。
|
|
14
15
|
*/
|
|
15
16
|
export declare const WORKFLOW_NOTIFY_KEY_DISPOSITION: {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type CheckpointToken, type ResumeOutcome } from "@sema-agent/core";
|
|
2
|
+
import type { ResumeRestatement } from "../http/resume-restatement.js";
|
|
2
3
|
import { type JsonColumnReader } from "../plugins/sql-json-column.js";
|
|
3
4
|
import { type InProcessClaimFence } from "../plugins/store-contracts.js";
|
|
4
5
|
/** 一条人对审批卡的决定(引擎 `ResumeOutcome` 的 `policy_ask` 臂 —— 子代停驻只会是这一门)。 */
|
|
@@ -52,11 +53,15 @@ export interface ParkDecisionLaneSeats {
|
|
|
52
53
|
*/
|
|
53
54
|
export declare function parkDecisionStoreRefusal(seats: ParkDecisionLaneSeats): string | undefined;
|
|
54
55
|
/**
|
|
55
|
-
* 决定的同一性判据:判词 + 绑定两位 +
|
|
56
|
-
*
|
|
56
|
+
* 决定的同一性判据:判词 + 绑定两位 + 出处(`decidedBy`,带了机器座位 `decidedVia` 时是 `[decidedBy, decidedVia]` 一对)+ 载荷指纹
|
|
57
|
+
* (`updatedInput` / `answer` / `reason` / `feedback`,与 live 腿幂等回放的门⑦同一只 {@link approvalPayloadFingerprint})。通道自报的 `approver` 不进 ——
|
|
58
|
+
* 它是归属标签,不改引擎铸的结算词;`decidedVia` 进 —— 它定模型读到的那一句(部署策略拒 / PermissionRequest 钩子拒),换了座位是另一个决定。
|
|
59
|
+
* 出处位按在场取形(与下面的重述同一条成员律):不带座位 ⇒ 那一位仍是裸 `decidedBy`,字节不变;带了 ⇒ 一对(数组与串不可能相等,不与任何不带座位的决定撞)。
|
|
57
60
|
* 载荷序列化不了 ⇒ 抛(两侧都源自 JSON,走到这里是结构异常;那只函数自己已经响亮 warn)。
|
|
61
|
+
* 决定体带的续跑请求重述键(`mcpServers` / `a2aPeers`)也是这次决定的一部分:同一决定带另一张表是另一个决定(投递跑还活着时不答首投回执,
|
|
62
|
+
* 走既有的会话占用拒),同一张表(键序无关,引擎的规范串)才是重投。按在场追加 —— 不带的决定指纹字节不变,落了库的存量指纹不换字节。
|
|
58
63
|
*/
|
|
59
|
-
export declare function parkDecisionFingerprint(outcome: WorkflowParkOutcome): string;
|
|
64
|
+
export declare function parkDecisionFingerprint(outcome: WorkflowParkOutcome, restatement?: ResumeRestatement): string;
|
|
60
65
|
/**
|
|
61
66
|
* 存下的决定体 → 内域形的**唯一读者**(SQL 列与 local 账本行共用)。判到本仓自己读的那几格为止(门、判词、绑定两位、出处对象);
|
|
62
67
|
* 其余键的属主是引擎,它在续跑入口 pre-CAS 再判一遍(与 checkpoint 店读 `outcome` 列同一条分工,见 `checkpoint-store-sql.ts` 的形读者注)。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { AppendLog, ensureDir } from "@sema-agent/core";
|
|
3
|
+
import { AppendLog, canonicalJsonStringify, ensureDir } from "@sema-agent/core";
|
|
4
4
|
import { approvalPayloadFingerprint } from "../plugins/approval-payload-fingerprint.js";
|
|
5
5
|
import { createObjectColumnReader, isJsonObject } from "../plugins/sql-json-column.js";
|
|
6
6
|
import { replayJsonlGuarded } from "../observability/corrupt-read-seat.js";
|
|
@@ -31,7 +31,7 @@ export function parkDecisionStoreRefusal(seats) {
|
|
|
31
31
|
"its writes are fenced by the run store it was built on, so a different run store means decisions recorded where the session claims are not checked; " +
|
|
32
32
|
"take runStore and workflowParkDecisions from the same store backend (run() and workflowParkDecisions()); refusing to start rather than record decisions the session claim cannot fence");
|
|
33
33
|
}
|
|
34
|
-
export function parkDecisionFingerprint(outcome) {
|
|
34
|
+
export function parkDecisionFingerprint(outcome, restatement) {
|
|
35
35
|
const payload = approvalPayloadFingerprint({
|
|
36
36
|
...(outcome.updatedInput !== undefined ? { updatedInput: outcome.updatedInput } : {}),
|
|
37
37
|
...(outcome.answer !== undefined ? { answer: outcome.answer } : {}),
|
|
@@ -40,7 +40,9 @@ export function parkDecisionFingerprint(outcome) {
|
|
|
40
40
|
});
|
|
41
41
|
if (payload === null)
|
|
42
42
|
throw new Error("workflow park decision: the decision payload cannot be serialized — refusing to record a decision whose identity cannot be stated");
|
|
43
|
-
const
|
|
43
|
+
const { decidedBy, decidedVia } = outcome.hostDecision;
|
|
44
|
+
const provenance = decidedVia !== undefined ? [decidedBy, decidedVia] : decidedBy;
|
|
45
|
+
const identity = JSON.stringify([outcome.decision, outcome.boundCallId, outcome.boundInputHash, provenance, payload, ...(restatement !== undefined ? [canonicalJsonStringify(restatement)] : [])]);
|
|
44
46
|
return createHash("sha256").update(identity).digest("hex");
|
|
45
47
|
}
|
|
46
48
|
const readOutcomeObject = createObjectColumnReader();
|
|
@@ -78,4 +78,15 @@ export interface OrgDeliveryGateDeps {
|
|
|
78
78
|
* 活对象(闭包持有目录 / 两只店 / 消费方)⇒ `create*`(CLAUDE.md 工厂命名律)。
|
|
79
79
|
*/
|
|
80
80
|
export declare function createOrgDeliveryGate(deps: OrgDeliveryGateDeps): OrgDeliveryGate;
|
|
81
|
+
/**
|
|
82
|
+
* 箱址的读侧映射也归门(单一属主:箱址常量只在本文件出现,`test/org-delivery-gate-single-path.test.ts` ①):
|
|
83
|
+
* 被扣的跨会话信在收信会话的哪条车道上 ⇄ core 队列键的 `box`。消费方 = `src/peer-inbound-face.ts`。
|
|
84
|
+
*/
|
|
85
|
+
/** 一封被扣的信在收信会话的哪条车道上:会话自己的箱,或它代为排空的本 principal 收件箱(core 的 `PRINCIPAL_INBOX_HANDLE`)。闭集。 */
|
|
86
|
+
export declare const PEER_INBOUND_LANES: readonly ["session", "principal_inbox"];
|
|
87
|
+
export type PeerInboundLane = (typeof PEER_INBOUND_LANES)[number];
|
|
88
|
+
/** 车道 → core 队列键的第三位(`peerHeldQueueIfAny` 的 `box`;会话自己的箱 = 缺席)。 */
|
|
89
|
+
export declare function boxOfLane(lane: PeerInboundLane): string | undefined;
|
|
90
|
+
/** 通告里的箱句柄 → 车道(会话箱按 core 的句柄函数比对,不手拼前缀);两者都不是 ⇒ `undefined`。 */
|
|
91
|
+
export declare function laneOfBox(box: string, sessionId: string): PeerInboundLane | undefined;
|
|
81
92
|
//# sourceMappingURL=org-delivery-gate.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CrossSessionCodecError, MAILBOX_TOMBSTONED_RECIPIENT_CODE, PRINCIPAL_INBOX_HANDLE, mintCrossPrincipalRecord, uuidv7, } from "@sema-agent/core";
|
|
1
|
+
import { CrossSessionCodecError, MAILBOX_TOMBSTONED_RECIPIENT_CODE, PRINCIPAL_INBOX_HANDLE, peerSessionBoxHandle, mintCrossPrincipalRecord, uuidv7, } from "@sema-agent/core";
|
|
2
2
|
import { principalShapeProblem } from "./security.js";
|
|
3
3
|
import { mailboxKeyProblem } from "./plugins/mailbox-store-sql.js";
|
|
4
4
|
export const ORG_DELIVERY_QUOTA = Object.freeze({ windowMs: 3_600_000, attemptsPerSender: 60, perPair: 10, perRecipient: 30 });
|
|
@@ -56,4 +56,22 @@ export function createOrgDeliveryGate(deps) {
|
|
|
56
56
|
},
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
|
+
export const PEER_INBOUND_LANES = ["session", "principal_inbox"];
|
|
60
|
+
export function boxOfLane(lane) {
|
|
61
|
+
switch (lane) {
|
|
62
|
+
case "session":
|
|
63
|
+
return undefined;
|
|
64
|
+
case "principal_inbox":
|
|
65
|
+
return PRINCIPAL_INBOX_HANDLE;
|
|
66
|
+
default: {
|
|
67
|
+
const unreachable = lane;
|
|
68
|
+
throw new Error(`peer inbound lane outside its closed set: ${String(unreachable)}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export function laneOfBox(box, sessionId) {
|
|
73
|
+
if (box === PRINCIPAL_INBOX_HANDLE)
|
|
74
|
+
return "principal_inbox";
|
|
75
|
+
return box === peerSessionBoxHandle(sessionId) ? "session" : undefined;
|
|
76
|
+
}
|
|
59
77
|
//# sourceMappingURL=org-delivery-gate.js.map
|
package/dist/parked-decide.d.ts
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* 行永 parked、生命周期分叉)。
|
|
10
10
|
*/
|
|
11
11
|
import type { HostDecision } from "./host-decision.js";
|
|
12
|
-
import type { DecideBinding } from "./http/wire-types.js";
|
|
12
|
+
import type { DecideBinding, DecidedAction } from "./http/wire-types.js";
|
|
13
|
+
import type { ResumeRestatement } from "./http/resume-restatement.js";
|
|
13
14
|
import type { BackgroundAgentRecord, BackgroundAgentStore, CheckpointStore, CheckpointToken, QuestionAnswer, RunInternals, TaskRegistry, ToolExecuteContext, WorkflowRun, WorkflowRunStore } from "@sema-agent/core";
|
|
14
15
|
import type { ParkedReviveSurfaceFactory } from "./parked-revive-surface.js";
|
|
15
16
|
import type { RebuiltInheritedGate } from "./boot/parked-revive-gate.js";
|
|
@@ -133,7 +134,7 @@ export declare function heldWorkflowParkDecisions(sources: HeldWorkflowParkDecis
|
|
|
133
134
|
/**
|
|
134
135
|
* pending checkpoint → parked bg 行匹配。
|
|
135
136
|
*
|
|
136
|
-
* 键链(core 1.390 事实):park 时 cp 落 `
|
|
137
|
+
* 键链(core 1.390 事实):park 时 cp 落 `sourceSessionId: sessionId`(子会话 id,**不是** bg handle),
|
|
137
138
|
* 而 bg 行同样存该子会话 id(`row.sessionId`)与绑定 token(`row.parkedCheckpointToken`)。
|
|
138
139
|
* `listByScope` 只回 summary(含 handle/sessionId、不含 token),故两步:summary.sessionId 初筛 →
|
|
139
140
|
* `get(handle, scope)` 全行复核 token。
|
|
@@ -219,7 +220,7 @@ export interface ParkedDecideRequest {
|
|
|
219
220
|
token: string;
|
|
220
221
|
scope: string;
|
|
221
222
|
sessionId: string;
|
|
222
|
-
/** cp.pendingAction 原样(
|
|
223
|
+
/** cp.pendingAction 原样(只读两件行事实:引擎自己的问题工具之判 `isEngineQuestionRow`、AskUserQuestion 预检的工具名;从不作绑定的回落源)。 */
|
|
223
224
|
pendingAction: unknown;
|
|
224
225
|
decision: "approve" | "deny";
|
|
225
226
|
/** [ref] 件6③ / [ref](core 7.6.0 S6-A):**这次结算的事实**,由调用方陈述(必填,理由与 legacy 腿
|
|
@@ -231,12 +232,12 @@ export interface ParkedDecideRequest {
|
|
|
231
232
|
* deny-sweep 恰是 req 缺席的那条腿,它对 parked 行另有静默跳过臂)⇒ 恒 `decidedBy:"person"`。 */
|
|
232
233
|
hostDecision: HostDecision;
|
|
233
234
|
reason?: string;
|
|
234
|
-
/** D-1
|
|
235
|
-
*
|
|
236
|
-
binding
|
|
235
|
+
/** D-1 决断绑定:决断方点名它看到的那一对(必在 —— 续跑腿的判官 `decidedActionOf` 判过才交下来)与决定体的其余两位;
|
|
236
|
+
* server 绝不重算、绝不从停驻行补,core resume 侧做 fail-closed 等值校验 —— 与 legacy 腿同姿势。 */
|
|
237
|
+
binding: Omit<DecideBinding, "checkpointToken" | "boundCallId" | "boundInputHash"> & DecidedAction;
|
|
237
238
|
/** body 带了 `remember:"session"` 时路由传入的 grant 执行器([ref] 候裁② 的 server 侧修,经两轮
|
|
238
239
|
* 行为探针实证):豁免必须锚在**行的 root/host 会话 id**——部署侧三个豁免探针(policy 层/fs-write
|
|
239
|
-
* 门/workflow 门)的闭包统一捕获 host 会话键且签名不携身份(1.393 seam 亲读:`
|
|
240
|
+
* 门/workflow 门)的闭包统一捕获 host 会话键且签名不携身份(1.393 seam 亲读:`sourceSessionId` 只在
|
|
240
241
|
* onAsk 层的 AskRequest,durable 车道无 onAsk),grant 落子代会话则键永不相交(G-F4 原案);落
|
|
241
242
|
* root 会话则宿主键闭包立即命中,复活子代的后续同工具 ask 被短路(探针 v2 实证),语义与同步车道/
|
|
242
243
|
* 宿主任务的「本会话不再询问」一致(= host 会话树全域)。行无 root 锚(病态形)⇒ claim 前诚实 400。 */
|
|
@@ -246,6 +247,9 @@ export interface ParkedDecideRequest {
|
|
|
246
247
|
* server 不预判)。core 拒绝形:同步腿 409 invalid_outcome field:"answer",parked 腿经 drive 失败
|
|
247
248
|
* 面 422 parked_resume.startup_failed。 */
|
|
248
249
|
answer?: QuestionAnswer;
|
|
250
|
+
/** 决定体带的续跑请求重述键(`mcpServers` / `a2aPeers`;路由已过提交腿同一只判官)。两条车道各自决定拿它怎么办:workflow 车道盖在宿主会话的续跑输入上、
|
|
251
|
+
* 并进决定的同一性({@link parkDecisionFingerprint});bg 赎回腿不从存量提交体重建任务规格,盖不上 ⇒ claim 前诚实 400(`decide.parked_restatement_unsupported`)。 */
|
|
252
|
+
restatement?: ResumeRestatement;
|
|
249
253
|
/** claim CAS 赢了(≈ legacy 腿的 markResuming 赢)之后、execute 之前触发——remember 豁免 grant
|
|
250
254
|
* 的挂点(调用方自吞错,绝不抛落赎回)。claim 败/判别 miss 恒不触发。 */
|
|
251
255
|
onDecideCommitted?: () => Promise<void>;
|
|
@@ -272,8 +276,8 @@ export interface ParkedDecideResult {
|
|
|
272
276
|
* 判据一字未改,只是从 bg 腿里提出来:两条腿结算的是**同一种门**(core gateMatch 的 `policy_ask`),
|
|
273
277
|
* 各铸一份必然漂移,而漂的是「人到底批了什么」这条审计事实。
|
|
274
278
|
*
|
|
275
|
-
* · D-1
|
|
276
|
-
*
|
|
279
|
+
* · D-1 绑定:决断方在 GET 看到的 `boundCallId`/`boundInputHash` 原样透传,server **绝不重算、绝不从行上补**
|
|
280
|
+
* (那一对必在,续跑腿的判官判过;core resume 侧做 fail-closed 等值校验)。
|
|
277
281
|
* · `reason` 走**存在性**判定(`!== undefined`),不是真值判定 —— 本铸点不折叠,原样上送。
|
|
278
282
|
* 🔴 但**别把这条读成「空串与缺席在结算上是两件事」**(7.19.0 / [ref] 之前那句话是真的,之后不是):
|
|
279
283
|
* 上送域的属主是引擎的单铸点,它把空文本折成缺席 ⇒ 到了消费端,`reason:""`、不传 `reason`、
|
package/dist/parked-decide.js
CHANGED
|
@@ -120,17 +120,14 @@ function mintReviveArgs(row, knownAgentTypes) {
|
|
|
120
120
|
};
|
|
121
121
|
}
|
|
122
122
|
export function buildParkedResumeOutcome(req) {
|
|
123
|
-
const pa = req.pendingAction;
|
|
124
|
-
const persistedCallId = pa?.kind === "tool_approval" ? (pa.toolCallId ?? "") : "";
|
|
125
|
-
const persistedHash = pa?.kind === "tool_approval" ? (pa.boundInputHash ?? "") : "";
|
|
126
123
|
const engineQuestion = isEngineQuestionRow(req.pendingAction);
|
|
127
124
|
return {
|
|
128
125
|
gate: "policy_ask",
|
|
129
|
-
boundCallId: req.binding
|
|
130
|
-
boundInputHash: req.binding
|
|
126
|
+
boundCallId: req.binding.boundCallId,
|
|
127
|
+
boundInputHash: req.binding.boundInputHash,
|
|
131
128
|
decision: req.decision === "approve" ? "allow" : "deny",
|
|
132
|
-
...(req.decision === "approve" && !engineQuestion && req.binding
|
|
133
|
-
...(req.binding
|
|
129
|
+
...(req.decision === "approve" && !engineQuestion && req.binding.updatedInput !== undefined ? { updatedInput: req.binding.updatedInput } : {}),
|
|
130
|
+
...(req.binding.feedback !== undefined ? { feedback: req.binding.feedback } : {}),
|
|
134
131
|
...(req.answer !== undefined ? { answer: req.answer } : {}),
|
|
135
132
|
...(req.reason !== undefined ? { reason: req.reason } : {}),
|
|
136
133
|
hostDecision: req.hostDecision,
|
|
@@ -263,6 +260,9 @@ export async function decideParkedAgent(deps, req, match) {
|
|
|
263
260
|
if (req.grantRemember !== undefined && rememberRoot === undefined) {
|
|
264
261
|
return { status: 400, body: refusalBody({ errorCode: "decide.parked_remember_unsupported", message: "remember cannot be applied: this parked agent row carries no root/parent session anchor for the exemption", facts: { taskId: match.handle } }) };
|
|
265
262
|
}
|
|
263
|
+
if (req.restatement !== undefined) {
|
|
264
|
+
return { status: 400, body: refusalBody({ errorCode: "decide.parked_restatement_unsupported", message: "mcpServers / a2aPeers cannot be applied: this approval belongs to a background agent that stopped to wait for it, and that agent resumes with the MCP / A2A tables it had when it stopped — re-issue the decide without them to resume it that way", facts: { taskId: match.handle } }) };
|
|
265
|
+
}
|
|
266
266
|
const pendingTool = req.pendingAction?.toolName;
|
|
267
267
|
if (pendingTool === ASK_USER_QUESTION_TOOL_NAME && req.decision === "approve" && req.answer === undefined) {
|
|
268
268
|
return { status: 400, body: refusalBody({ errorCode: "decide.parked_answer_required", message: "pending action is AskUserQuestion — approve requires body.answer (the operator's answers[]); deny needs none", facts: { taskId: match.handle } }) };
|
|
@@ -24,17 +24,16 @@
|
|
|
24
24
|
* 近似如实记:重解的列表是**部署缺省**那一份,读不回那一 run 的逐请求差异(`settings.webSearch` 后端、center overlay 场景)——
|
|
25
25
|
* 座只判 bundle 实例的成员性,继承面是 `[...web, ...scaffolds]`,那两项差异不改变谁在面内。
|
|
26
26
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* `{
|
|
31
|
-
*
|
|
32
|
-
* (批准之后删了、同 id 被重新登记)⇒ 停驻否决 —— 两件都在挂点那一侧判,与这里无关。
|
|
27
|
+
* **委派树根见证([ref])与交座是两个独立判据**:Runner 之外复活的后台子代的完成 relay(会话通知门,`session-notify-door.ts`)要**委派树根的见证**:
|
|
28
|
+
* 根 id(行上本来就带 `rootSessionId`)+ 判断那一刻的根行住客 = 写口放行的那一位(赎回腿解析器那一读;不是那一位时写口整条拒,走不到这里)—— 见证恒带住客。
|
|
29
|
+
* 所以**每一行**都交出它({@link ScenarioContext} 的 `delegationRoot`):交座的一层行以 `{ sessionId: root, delegationRoot }` 重解,不交座的行(更深的行、根属主不是卡的租户的
|
|
30
|
+
* 一层行)以 `{ delegationRoot }` 重解 —— 只喂 relay,不挂任何会话级设施、不带 principal,交座判据(上面三条)一个字不动。行上没有根 ⇒ boot 期那只裸 Agent(没有根可交 ⇒ 不接 relay)。
|
|
31
|
+
* 复活的子代再要审批时的停驻挂点(`plugins/session-store.ts`)不读见证:引擎交它那一行自己的属主,挂点只比对(core 7.62.0 [ref];根见证在挂点的读法随 [ref] P-5 退役)。
|
|
33
32
|
*/
|
|
34
33
|
import { type BackgroundAgentRecord, type ToolSpec } from "@sema-agent/core";
|
|
35
34
|
import type { Scenario } from "./capabilities/scenarios.js";
|
|
36
35
|
import type { SessionFace } from "./session-incarnation.js";
|
|
37
|
-
/** 一次赎回用的面:驱动的 Agent 工具(
|
|
36
|
+
/** 一次赎回用的面:驱动的 Agent 工具(它的完成 relay 绑着行上的根)+ (交座时)与它同出一张列表的继承座。 */
|
|
38
37
|
export interface ParkedReviveSurface {
|
|
39
38
|
readonly reviveTool: ToolSpec;
|
|
40
39
|
/** 缺席 = 不交座(core fail-closed:复活的子代不继承任何场景层工具)。 */
|
|
@@ -9,7 +9,7 @@ export function createParkedReviveSurface(defaultScenario) {
|
|
|
9
9
|
if (root === undefined)
|
|
10
10
|
return { reviveTool: bootTool };
|
|
11
11
|
const seated = holdsSeat(row.parentSessionId === root, identity);
|
|
12
|
-
const delegationRoot = { sessionId: root, incarnation: identity.rootOccupant.incarnation };
|
|
12
|
+
const delegationRoot = { sessionId: root, owner: identity.rootOccupant.owner, incarnation: identity.rootOccupant.incarnation };
|
|
13
13
|
const tools = (seated ? defaultScenario({}, identity.principal, { sessionId: root, delegationRoot }) : defaultScenario({}, undefined, { delegationRoot })).tools;
|
|
14
14
|
const reviveTool = agentOf(tools);
|
|
15
15
|
if (reviveTool === undefined)
|