@sema-agent/server 7.148.0 → 7.150.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 +551 -9
- package/README.md +17 -2
- package/README.zh-CN.md +5 -1
- package/USAGE.md +126 -68
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +33 -33
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/approval-leg-origin.d.ts +33 -0
- package/dist/approval-leg-origin.js +4 -0
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +2 -2
- package/dist/auth-bridge.d.ts +9 -1
- package/dist/auth-bridge.js +4 -4
- package/dist/auth-keys.d.ts +10 -1
- package/dist/auth-keys.js +8 -0
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
- package/dist/boot/deferred-sandbox-path-env.js +1 -2
- package/dist/boot/execution-env.js +10 -11
- package/dist/boot/execution-lane.d.ts +6 -4
- package/dist/boot/execution-lane.js +3 -1
- package/dist/boot/org-delivery.d.ts +3 -2
- package/dist/boot/parked-revive-gate.d.ts +5 -5
- package/dist/boot/parked-revive-gate.js +2 -3
- package/dist/boot/resolve-spec.d.ts +4 -5
- package/dist/boot/resolve-spec.js +66 -28
- package/dist/boot/retention-lane.d.ts +1 -1
- package/dist/boot/runner-deps.js +3 -1
- package/dist/boot/session-faces.js +21 -21
- package/dist/boot/stage-01-config.d.ts +1 -0
- package/dist/boot/stage-01-config.js +4 -3
- package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
- package/dist/boot/stage-02-web-admin-pull.js +10 -2
- package/dist/boot/stage-03-store-backend.d.ts +1 -0
- package/dist/boot/stage-03-store-backend.js +4 -4
- package/dist/boot/stage-04-stores.d.ts +1 -0
- package/dist/boot/stage-05-execution-env.d.ts +1 -0
- package/dist/boot/stage-06-runners.d.ts +2 -1
- package/dist/boot/stage-06-runners.js +1 -2
- package/dist/boot/stage-07-capability-layer.d.ts +2 -1
- package/dist/boot/stage-07-capability-layer.js +1 -1
- package/dist/boot/stage-08-reapers.d.ts +2 -1
- package/dist/boot/stage-09-leader.d.ts +2 -1
- package/dist/boot/stage-10-http-server.d.ts +35 -2
- package/dist/boot/stage-10-http-server.js +9 -4
- package/dist/boot/stores.d.ts +3 -0
- package/dist/boot/stores.js +22 -19
- package/dist/boot/web-admin.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/capability-facts.d.ts +70 -60
- package/dist/capability-facts.js +45 -49
- package/dist/card-settle-stored-scope.d.ts +56 -0
- package/dist/card-settle-stored-scope.js +27 -0
- package/dist/card-void.d.ts +7 -12
- package/dist/card-void.js +2 -7
- package/dist/config-catalog.d.ts +12 -0
- package/dist/config-catalog.js +37 -33
- package/dist/config-invariants.d.ts +5 -4
- package/dist/config-invariants.js +4 -4
- package/dist/config-types.d.ts +49 -16
- package/dist/config.d.ts +6 -5
- package/dist/config.js +35 -24
- package/dist/context-window-notice.d.ts +31 -0
- package/dist/context-window-notice.js +28 -0
- package/dist/deployment-governance.d.ts +7 -28
- package/dist/deployment-governance.js +1 -14
- package/dist/deployment-shape.d.ts +20 -11
- package/dist/deployment-shape.js +1 -0
- package/dist/device-ws-hub.d.ts +1 -0
- package/dist/device-ws-hub.js +64 -28
- package/dist/device-ws-protocol.d.ts +20 -6
- package/dist/device-ws-protocol.js +9 -2
- package/dist/engine-identity.d.ts +7 -1
- package/dist/engine-identity.js +5 -0
- package/dist/env-name-allowlist-knobs.d.ts +6 -5
- package/dist/env-name-allowlist-knobs.js +5 -0
- package/dist/execution-lane-caps.d.ts +20 -5
- package/dist/execution-lane-caps.js +18 -4
- package/dist/field-conflict.d.ts +2 -2
- package/dist/fleet/engine-signal.d.ts +14 -1
- package/dist/fleet/engine-signal.js +5 -1
- package/dist/fleet/fleet-reconciler.d.ts +1 -1
- package/dist/fleet/serving-lease.d.ts +18 -3
- package/dist/fleet/serving-lease.js +81 -35
- package/dist/fleet-client.d.ts +13 -11
- package/dist/fleet-client.js +53 -33
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +1 -3
- package/dist/hitl-delivery.js +1 -1
- package/dist/hooks/command-spawn.d.ts +7 -2
- package/dist/hooks/command-spawn.js +13 -6
- package/dist/hooks/hook-runner.d.ts +5 -0
- package/dist/hooks/hook-runner.js +11 -7
- package/dist/http/active-run-conflict.d.ts +3 -7
- package/dist/http/active-run-conflict.js +2 -2
- package/dist/http/admission.js +5 -5
- package/dist/http/approval-sweeps.js +5 -3
- package/dist/http/caller-trust.d.ts +2 -2
- package/dist/http/caller-trust.js +3 -3
- package/dist/http/checkpoint-ctx.d.ts +18 -63
- package/dist/http/checkpoint-ctx.js +1 -24
- package/dist/http/claim-heartbeat.d.ts +6 -6
- package/dist/http/claim-heartbeat.js +6 -6
- package/dist/http/claimed-run.d.ts +16 -9
- package/dist/http/claimed-run.js +8 -0
- package/dist/http/dispatch.js +7 -5
- package/dist/http/durable-run-leg.d.ts +8 -1
- package/dist/http/durable-run-leg.js +34 -15
- package/dist/http/execution-context.d.ts +115 -14
- package/dist/http/execution-context.js +130 -40
- package/dist/http/owner-access.d.ts +246 -21
- package/dist/http/owner-access.js +186 -8
- package/dist/http/principal-gate.d.ts +18 -11
- package/dist/http/principal-gate.js +3 -1
- package/dist/http/readiness.d.ts +4 -2
- package/dist/http/resume-ctx-read.d.ts +14 -3
- package/dist/http/resume-ctx-read.js +24 -3
- package/dist/http/resume-legs.d.ts +35 -3
- package/dist/http/resume-legs.js +262 -106
- package/dist/http/route-ctx.d.ts +29 -11
- package/dist/http/routes/a2a-serve.js +17 -14
- package/dist/http/routes/approvals-assistant.d.ts +3 -2
- package/dist/http/routes/approvals-assistant.js +11 -11
- package/dist/http/routes/capabilities.js +5 -4
- package/dist/http/routes/config-catalog.d.ts +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -1
- package/dist/http/routes/diagnostics.js +30 -5
- package/dist/http/routes/mcp-reconnect.js +2 -2
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/notify-wake.js +2 -3
- package/dist/http/routes/principal-inbox.d.ts +3 -1
- package/dist/http/routes/principal-inbox.js +3 -2
- package/dist/http/routes/projects.d.ts +1 -0
- package/dist/http/routes/projects.js +5 -3
- package/dist/http/routes/retention-ops.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +1 -1
- package/dist/http/routes/runs.js +33 -37
- package/dist/http/routes/session-memory-sync.js +4 -5
- package/dist/http/routes/session-sync.d.ts +24 -5
- package/dist/http/routes/session-sync.js +45 -37
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +18 -44
- package/dist/http/routes/tasks.js +136 -101
- package/dist/http/routes/trace-usage.js +14 -14
- package/dist/http/routes/workflows.d.ts +1 -0
- package/dist/http/routes/workflows.js +20 -38
- package/dist/http/server.d.ts +12 -9
- package/dist/http/server.js +35 -6
- package/dist/http/stored-body-replay.d.ts +3 -24
- package/dist/http/stored-body-replay.js +2 -12
- package/dist/http/submit-ctx.d.ts +2 -2
- package/dist/http/submit-ctx.js +5 -5
- package/dist/http/submit-replay.d.ts +15 -2
- package/dist/http/submit-replay.js +10 -4
- package/dist/http/wire-types.d.ts +6 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/leader/endpoint.js +9 -8
- package/dist/leg-facts.d.ts +13 -2
- package/dist/leg-facts.js +2 -0
- package/dist/local-store-declaration.d.ts +54 -0
- package/dist/local-store-declaration.js +59 -0
- package/dist/mcp-assertion-header.d.ts +1 -1
- package/dist/mcp-assertion-header.js +1 -1
- package/dist/mcp-authorization-face.d.ts +18 -14
- package/dist/mcp-authorization-face.js +3 -2
- package/dist/memory-project-layer.js +1 -1
- package/dist/memory-scope.d.ts +4 -4
- package/dist/memory-scope.js +4 -4
- package/dist/memory-store-refusal.d.ts +1 -1
- package/dist/memory-sync-client.js +2 -2
- package/dist/model-context-window.d.ts +50 -11
- package/dist/model-context-window.js +20 -1
- package/dist/model-entry-refusal.d.ts +5 -4
- package/dist/model-entry-refusal.js +17 -3
- package/dist/model-reach-scope.d.ts +2 -1
- package/dist/observability/corrupt-read-seat.d.ts +1 -1
- package/dist/observability/fail-open.d.ts +19 -7
- package/dist/observability/fail-open.js +19 -7
- package/dist/observability/logger.d.ts +7 -0
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -1
- package/dist/observability/run-terminal.d.ts +1 -1
- package/dist/observability/run-terminal.js +1 -0
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/org-delivery-gate.d.ts +31 -6
- package/dist/org-delivery-gate.js +7 -4
- package/dist/owner-faces.d.ts +30 -5
- package/dist/owner-faces.js +2 -0
- package/dist/park-row-commit.d.ts +67 -0
- package/dist/park-row-commit.js +76 -0
- package/dist/parked-decide.d.ts +9 -7
- package/dist/parked-decide.js +25 -6
- package/dist/peer-directory.d.ts +1 -1
- package/dist/peer-seat.d.ts +1 -1
- package/dist/peer-seat.js +52 -59
- package/dist/plugins/adoption-log-sql.d.ts +3 -3
- package/dist/plugins/adoption-log-sql.js +19 -19
- package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
- package/dist/plugins/approval-ask-store-sql.js +3 -5
- package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
- package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
- package/dist/plugins/approval-exemption-skill-m46.d.ts +0 -6
- package/dist/plugins/approval-exemption-skill-m46.js +6 -10
- package/dist/plugins/approval-exemption-store.d.ts +26 -1
- package/dist/plugins/approval-exemption-store.js +28 -19
- package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -3
- package/dist/plugins/ensure-schema-lock-policy.js +75 -9
- package/dist/plugins/exec-path-law.d.ts +34 -0
- package/dist/plugins/exec-path-law.js +13 -0
- package/dist/plugins/file-run-store.d.ts +22 -9
- package/dist/plugins/file-run-store.js +51 -23
- package/dist/plugins/local-checkpoint-store.d.ts +8 -1
- package/dist/plugins/local-checkpoint-store.js +5 -1
- package/dist/plugins/local-data-root-admission.d.ts +52 -0
- package/dist/plugins/local-data-root-admission.js +100 -0
- package/dist/plugins/local-engine-high-water.d.ts +28 -7
- package/dist/plugins/local-engine-high-water.js +27 -22
- package/dist/plugins/local-session-store.d.ts +134 -49
- package/dist/plugins/local-session-store.js +149 -108
- package/dist/plugins/memory-run-store.d.ts +14 -9
- package/dist/plugins/memory-run-store.js +48 -22
- package/dist/plugins/one-time-migration-marker.d.ts +19 -3
- package/dist/plugins/one-time-migration-marker.js +7 -1
- package/dist/plugins/one-time-migrations.d.ts +110 -59
- package/dist/plugins/one-time-migrations.js +224 -136
- package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
- package/dist/plugins/org-delivery-quota-store.js +29 -14
- package/dist/plugins/permission-rule-store-sql.d.ts +1 -1
- package/dist/plugins/permission-rule-store-sql.js +5 -9
- package/dist/plugins/pg-pool.d.ts +1 -1
- package/dist/plugins/pg-pool.js +14 -12
- package/dist/plugins/posix-shell-fs.js +4 -2
- package/dist/plugins/remote-env-adb.js +3 -2
- package/dist/plugins/remote-env-device.d.ts +3 -2
- package/dist/plugins/remote-env-device.js +8 -6
- package/dist/plugins/remote-env-e2b.d.ts +4 -8
- package/dist/plugins/remote-env-e2b.js +21 -15
- package/dist/plugins/remote-env-host.d.ts +51 -10
- package/dist/plugins/remote-env-host.js +97 -31
- package/dist/plugins/remote-env-k8s.js +7 -4
- package/dist/plugins/remote-env-local-docker.d.ts +6 -3
- package/dist/plugins/remote-env-local-docker.js +11 -25
- package/dist/plugins/remote-env-ssh.js +4 -3
- package/dist/plugins/remote-shell.d.ts +3 -1
- package/dist/plugins/remote-shell.js +3 -3
- package/dist/plugins/replica-registration.d.ts +35 -0
- package/dist/plugins/replica-registration.js +48 -0
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/run-store-sql.d.ts +27 -8
- package/dist/plugins/run-store-sql.js +46 -18
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +8 -12
- package/dist/plugins/scenario-prefix-switch-m42.js +9 -6
- package/dist/plugins/schema-consistency.d.ts +91 -5
- package/dist/plugins/schema-consistency.js +189 -7
- package/dist/plugins/schema-drift-sentence.d.ts +6 -5
- package/dist/plugins/schema-drift-sentence.js +13 -5
- package/dist/plugins/serving-requirement.d.ts +49 -0
- package/dist/plugins/serving-requirement.js +53 -0
- package/dist/plugins/session-placement.d.ts +5 -4
- package/dist/plugins/shell-sentinel-owner-m48.d.ts +22 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +6 -0
- package/dist/plugins/stop-then-start-sentence.d.ts +55 -0
- package/dist/plugins/stop-then-start-sentence.js +51 -0
- package/dist/plugins/store-backend.d.ts +23 -9
- package/dist/plugins/store-backend.js +58 -24
- package/dist/plugins/store-contracts.d.ts +45 -5
- package/dist/plugins/store-contracts.js +19 -0
- package/dist/plugins/tidb-pool.d.ts +11 -6
- package/dist/plugins/tidb-pool.js +22 -12
- package/dist/plugins/workspace-custody.d.ts +44 -0
- package/dist/plugins/workspace-custody.js +47 -0
- package/dist/process-instance.d.ts +3 -0
- package/dist/process-instance.js +7 -0
- package/dist/project-context.d.ts +66 -0
- package/dist/project-context.js +70 -0
- package/dist/project-identity.d.ts +8 -7
- package/dist/project-identity.js +40 -17
- package/dist/project-layer-key.d.ts +13 -2
- package/dist/project-layer-key.js +9 -1
- package/dist/question.d.ts +9 -21
- package/dist/question.js +28 -19
- package/dist/read-deny-floor-notice.d.ts +36 -0
- package/dist/read-deny-floor-notice.js +40 -0
- package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
- package/dist/request-declaration-disposition.js +39 -0
- package/dist/run-cancel-card.d.ts +28 -0
- package/dist/run-cancel-card.js +20 -0
- package/dist/run-cancel-context.d.ts +10 -0
- package/dist/run-cancel-context.js +1 -0
- package/dist/run-local.js +28 -13
- package/dist/runs.d.ts +31 -7
- package/dist/runs.js +34 -16
- package/dist/security.d.ts +3 -3
- package/dist/server-secret-env.d.ts +34 -20
- package/dist/server-secret-env.js +61 -18
- package/dist/session-agent.d.ts +4 -12
- package/dist/session-agent.js +0 -6
- package/dist/session-children-retire.d.ts +6 -3
- package/dist/session-children-retire.js +2 -5
- package/dist/session-incarnation.d.ts +18 -4
- package/dist/session-incarnation.js +4 -1
- package/dist/session-notify-door.d.ts +4 -4
- package/dist/session-notify-door.js +5 -6
- package/dist/session-rules-seat.d.ts +4 -3
- package/dist/session-rules-seat.js +3 -11
- package/dist/session-sync.js +3 -3
- package/dist/session-workspace.d.ts +3 -3
- package/dist/store-admission.d.ts +33 -0
- package/dist/store-admission.js +49 -0
- package/dist/store-posture.d.ts +5 -0
- package/dist/store-posture.js +18 -1
- package/dist/stores-sql/checkpoint-store-sql.d.ts +22 -3
- package/dist/stores-sql/checkpoint-store-sql.js +109 -23
- package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
- package/dist/stores-sql/file-history-store-sql.js +3 -5
- package/dist/stores-sql/retention-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +4 -6
- package/dist/task-a2a.d.ts +3 -8
- package/dist/task-a2a.js +25 -27
- package/dist/task-cwd.d.ts +27 -10
- package/dist/task-cwd.js +3 -0
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +1 -1
- package/dist/task-settings.d.ts +13 -0
- package/dist/task-settings.js +14 -7
- package/dist/terminal.d.ts +2 -0
- package/dist/terminal.js +21 -6
- package/dist/tool-approval.d.ts +50 -41
- package/dist/tool-approval.js +96 -73
- package/dist/trace/engine-notice-wire.d.ts +38 -21
- package/dist/trace/engine-notice-wire.js +25 -4
- package/dist/trace/ledger-sink.d.ts +3 -1
- package/dist/trace/project.d.ts +8 -5
- package/dist/trace/project.js +11 -9
- package/dist/trace/projection-table.d.ts +33 -2
- package/dist/trace/redact.d.ts +12 -0
- package/dist/trace/redact.js +5 -1
- package/dist/trace/self-minted-wire.d.ts +268 -56
- package/dist/trace/self-minted-wire.js +110 -40
- package/dist/trace/tool-card.d.ts +3 -0
- package/dist/trace/tool-card.js +24 -0
- package/dist/trace/tool-output-media.d.ts +2 -1
- package/dist/unattended-permission-mode.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.js +22 -9
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -29
- package/docs/error-text-lexicon.json +317 -0
- package/package.json +4 -2
- package/scripts/embed-minimal.mjs +183 -0
- package/wire-changes/server@7.149.0.json +372 -0
- package/wire-changes/server@7.150.0.json +335 -0
- package/dist/plain-string-record.js +0 -70
package/dist/http/route-ctx.d.ts
CHANGED
|
@@ -36,8 +36,10 @@ import type { RootedTaskSpec } from "./execution-context.js";
|
|
|
36
36
|
import type { GateCommitment, GateSettlementEvidence } from "../gate-settlement.js";
|
|
37
37
|
import type { ResumeRestatement } from "./resume-restatement.js";
|
|
38
38
|
import type { RememberLaneCannotRecord } from "../parked-decide.js";
|
|
39
|
+
import type { RowWayOut } from "./resume-legs.js";
|
|
39
40
|
import type { KeyCaller } from "../owner-faces.js";
|
|
40
41
|
import type { Subject } from "../owner-brands.js";
|
|
42
|
+
import type { RouteBackend, RouteRunStore, RouteSessionStore } from "./owner-access.js";
|
|
41
43
|
/** 跨域可变状态 = lens1 §C2 实测的那 8 条「运行期登记簿」,一个对象。
|
|
42
44
|
* [ref]:`cancelledViaVerb`(按 taskId 键控的「这次是取消动词」旁表)删除 —— 中止成因改挂在每条腿自己的
|
|
43
45
|
* {@link RunAbort} 句柄上(`inflightRuns` 的值),同寿同删,不再有一张与腿不同寿的旁表。 */
|
|
@@ -198,14 +200,6 @@ export interface CheckpointCtx {
|
|
|
198
200
|
* 传原 ctx / 其展开 ⇒ 标随行。缺席 = 不是无人值守腿(HTTP 提交腿;7.106.0 前落盘的行 —— 那时这些腿不铸模式,checkpoint 里也没有)。
|
|
199
201
|
*/
|
|
200
202
|
unattendedLeg?: true;
|
|
201
|
-
/**
|
|
202
|
-
* 体里**模式词的读法记号**(闭集只有当前一词 `"entry_word"`):在场 = 这一行体的顶层 `permissionMode` 是这条 run 模式词唯一的源(提交入口盖过运维
|
|
203
|
-
* `AUTONOMY=plan` 的地板;`plan_review` 写回改它),续跑照它读。**服务端写、不来自请求体**。缺席(7.121.x 及以前写下的行 —— 那时运维的 plan 由治理层每段重钳)
|
|
204
|
-
* 而本部署此刻有入口地板、体的词被地板钳会变 ⇒ 续跑腿响亮拒、行字节不动(规则与删除条件的属主 = `http/checkpoint-ctx.ts` 顶注「模式词问」)。
|
|
205
|
-
* 写点两个(写模式词的人盖记号,同模块):`buildCheckpointCtx`(每一次新的持久化写都写)与 `withPermissionModeRewritten`(`plan_review` 改词的写回);
|
|
206
|
-
* 不改词的续跑腿写回传原 ctx ⇒ 记号随行。
|
|
207
|
-
*/
|
|
208
|
-
permissionModeReading?: import("./checkpoint-ctx.js").PermissionModeReading;
|
|
209
203
|
/**
|
|
210
204
|
* 🔴 [ref] —— **写这份上下文的服务版本**(`package.json` 的 `version`),**服务端写、不来自请求体**(与 {@link unattendedLeg} 同为 `body` 的兄弟键)。
|
|
211
205
|
* 写点两个:`buildCheckpointCtx`(每一次新的持久化写)与续跑腿的写回({@link DriveResumeArgs.resumeCtx} 的唯一写点,CAS 赢点盖本进程的版本 —— 接下来写下一张停车行的就是它)。
|
|
@@ -225,6 +219,14 @@ export interface CheckpointCtx {
|
|
|
225
219
|
* 缺席 = 体里的目标就是交付的那一份(腿上没有屏)。
|
|
226
220
|
*/
|
|
227
221
|
promptScreened?: true;
|
|
222
|
+
/**
|
|
223
|
+
* 这条 run 继承到的**项目上下文**(`project-context.ts` 的 {@link import("../project-context.js").ProjectContext}:项目 id · 继承的 `cwd` · 项目简报)——
|
|
224
|
+
* 新提交腿在装配器头部判一次,**服务端写、不来自请求体**(与 {@link memoryScope} 同为 `body` 的兄弟键,先例同形:提交腿推导、落盘,续跑原样读回)。
|
|
225
|
+
* 写点:`buildCheckpointCtx`(提交腿那一笔,经 `persistSubmissionCtx` 读这条腿的部署事实);leader worker 的写者不带(它的 spec 不经新提交腿的判)。续跑腿的写回传原 ctx / 其展开 ⇒ 随行。
|
|
226
|
+
* 读者只有一只:`resume-legs.ts` `resolveResumeSpec` 把它原样递给装配器(`opts.projectContext`)—— 续跑腿不再读登记簿、不再推观者(停驻期间登记被改 / 被删 / 看不见了,续跑照旧用这一份)。
|
|
227
|
+
* 缺席 = 没继承(含 7.150.0 之前写下的行:不回填,续跑不继承 = 那时的行为)。
|
|
228
|
+
*/
|
|
229
|
+
projectContext?: import("../project-context.js").ProjectContext;
|
|
228
230
|
}
|
|
229
231
|
/**
|
|
230
232
|
* `/decide` 第三条车道交给宿主投递腿(wake:`DriveResumeArgs` / fresh:`DurableRunLegArgs`)的**一件**:这一跑在内存里带着的决定,
|
|
@@ -291,6 +293,11 @@ export interface DriveResumeArgs {
|
|
|
291
293
|
sessionId: string;
|
|
292
294
|
ctx: CheckpointCtx;
|
|
293
295
|
};
|
|
296
|
+
/**
|
|
297
|
+
* 判官判本引擎续不了这条腿要续的那张卡时,这张卡的出路(`resume-legs.ts` 的 `rowWayOutOf`;判 `ok` / 说不出 ⇒ 缺席)。`/plan_review` 与 `/resume` 在驱动前对载入行求它;
|
|
298
|
+
* catch 臂在引擎的拒留卡 pending(处置 `retriable`)时把它作 `wayOut` 加进拒体 —— 引擎的拒原样不改(码、`field`、`blockedBy`、`thrownName`、诊断都在)。
|
|
299
|
+
*/
|
|
300
|
+
rowWayOut?: RowWayOut;
|
|
294
301
|
/**
|
|
295
302
|
* 这条续跑的**宿主租约**(续跑漏斗 `resolveResumeSpecOrBlocked` 开、装配在它之下登记对端声明;调用方作用域的 `finally` 放)。
|
|
296
303
|
* 驱动腿经 `heldFor(args.peerLease, () => driveResumeLeg(…))` 自持一只:受理早回的那一形里,腿活过调用方作用域,自己落定才放。
|
|
@@ -436,13 +443,13 @@ export interface RouteLegs {
|
|
|
436
443
|
/** POST /v1/tasks · /v1/tasks/stream · /v1/runs 的共同前段:读体 → 校验 → resolveSpec。null = 已应答(400/…)。
|
|
437
444
|
*
|
|
438
445
|
* `body` = **已解析好的**请求体,给那些体不是「这条 HTTP 请求的 JSON 正文」的调用方
|
|
439
|
-
* (
|
|
446
|
+
* ([ref] 车2:A2A JSON-RPC 腿已经把正文读成了一条 `message/send` 请求,再 `readJson(req)`
|
|
440
447
|
* 一次只会读到空流)。缺席 ⇒ 照旧自己读体,既有三个调用方一字不改。
|
|
441
448
|
* ⚠️ 这是**入口形**的分歧,不是校验面的分歧:传进来的体与自己读的体走**同一段**校验/授权/
|
|
442
449
|
* resolveSpec —— 分叉出第二条校验路径正是本参数存在的理由的反面。
|
|
443
450
|
*
|
|
444
451
|
* `onTypedFailure` = 「typed 拒绝**别写响应**,交回给我」。默认(缺席)行为不变:`HttpError` 走
|
|
445
|
-
* `sendError` 连 `extra` 一起回显。
|
|
452
|
+
* `sendError` 连 `extra` 一起回显。[ref] 车2 的 A2A 腿必须传它 —— 那些 `extra`(尤其
|
|
446
453
|
* `scenario_unknown` 的**全部场景名**)对壳是指路材料,对一个外部 peer 是内部词表外泄。 */
|
|
447
454
|
prepareSpec(req: IncomingMessage, res: ServerResponse, body?: TaskRequestBody, onTypedFailure?: (err: import("../security.js").HttpError) => void,
|
|
448
455
|
/** [ref] 件C:**腿身份**(不是能力表态)。`liveStream: true` 只由 `POST /v1/tasks/stream` 的装配点按
|
|
@@ -594,8 +601,19 @@ export declare function sendResumeOutcome(res: ServerResponse, out: {
|
|
|
594
601
|
}, logger: {
|
|
595
602
|
info?: (msg: string, fields?: Record<string, unknown>) => void;
|
|
596
603
|
} | undefined, extraBody?: Record<string, unknown>): void;
|
|
604
|
+
/**
|
|
605
|
+
* 🔴 **路由层的服务 deps(类型墙,[ref] 第二阶段)**:run 店 / 会话店上带属主的读口(按 id / 按键 / 按会话 / 列表 —— `owner-access.ts` 的 {@link RouteRunStore} /
|
|
606
|
+
* {@link RouteSessionStore})、会话视图读 `sessionAudit` 与后端铸这两只店的工厂(`backend.run()` / `backend.session()`,{@link RouteBackend})在型上调不了:路由在不在照判(能力事实只问方法在不在,见证随视图封着),带属主的行只经属主存取器读。
|
|
607
|
+
* 值上就是服务的那一只 deps,只在 `owner-access.ts` 的 `sealRouteDeps` 铸一次;视图是完整 deps 的子型(交给持认领腿的写口照常)。
|
|
608
|
+
*/
|
|
609
|
+
export type RouteDeps = Omit<FlatServiceDeps, "runStore" | "sessionStorage" | "sessionAudit" | "backend"> & {
|
|
610
|
+
runStore?: RouteRunStore;
|
|
611
|
+
sessionStorage?: RouteSessionStore;
|
|
612
|
+
sessionAudit?: never;
|
|
613
|
+
backend?: RouteBackend;
|
|
614
|
+
};
|
|
597
615
|
export interface RouteCtxBase {
|
|
598
|
-
deps:
|
|
616
|
+
deps: RouteDeps;
|
|
599
617
|
registry: RunRegistry;
|
|
600
618
|
helpers: RouteHelpers;
|
|
601
619
|
local: RouteLocals;
|
|
@@ -4,12 +4,13 @@ import { memoRedactedRead, redactErrorMessage } from "../../observability/run-te
|
|
|
4
4
|
import { isParkedRunStatus, isTerminalRunStatus } from "../../plugins/store-contracts.js";
|
|
5
5
|
import { HttpError } from "../../security.js";
|
|
6
6
|
import { idemCallerOf, idemIdentityOf, idemKeyOf, inflightKeyOf } from "../idempotency.js";
|
|
7
|
-
import {
|
|
7
|
+
import { answerReplay, isRunExistsConflictBody } from "../submit-replay.js";
|
|
8
8
|
import { isActiveRunConflictBody } from "../active-run-conflict.js";
|
|
9
9
|
import { sendJson, sendError, sendHttpError } from "../send.js";
|
|
10
10
|
import { admissionRefusalOf, readinessOf, sendBillableRefusal } from "../readiness.js";
|
|
11
|
+
import { memberLeaseOf } from "../../fleet/engine-signal.js";
|
|
11
12
|
import { gatedPerson, gatedSubject, sendPrincipalRefusal, verifiedIdentitySource } from "../principal-gate.js";
|
|
12
|
-
import { callerOf, protocolEntry, readVisibleRun, runRowAt } from "../owner-access.js";
|
|
13
|
+
import { callerOf, protocolEntry, readReplayHit, readVisibleRun, runRowAt } from "../owner-access.js";
|
|
13
14
|
import { assertNever } from "../route-ctx.js";
|
|
14
15
|
import * as facts from "../../capability-facts.js";
|
|
15
16
|
import { createDurableRun } from "./runs.js";
|
|
@@ -181,7 +182,7 @@ function rpcErrorFromTypedFailure(err) {
|
|
|
181
182
|
}
|
|
182
183
|
function submitUnavailable(res, ctx) {
|
|
183
184
|
const { deps } = ctx;
|
|
184
|
-
const refusal = admissionRefusalOf(readinessOf(deps), deps
|
|
185
|
+
const refusal = admissionRefusalOf(readinessOf(deps), memberLeaseOf(deps), "submit");
|
|
185
186
|
if (refusal === undefined)
|
|
186
187
|
return false;
|
|
187
188
|
sendBillableRefusal(res, refusal);
|
|
@@ -197,15 +198,14 @@ function readBlocking(params) {
|
|
|
197
198
|
throw new RpcError(JSONRPC_INVALID_PARAMS, "params.configuration.blocking must be a boolean");
|
|
198
199
|
return c.blocking;
|
|
199
200
|
}
|
|
200
|
-
async function waitForRun(ctx, store, res, taskId, budgetMs) {
|
|
201
|
+
async function waitForRun(ctx, entry, store, res, taskId, budgetMs) {
|
|
201
202
|
const { deps } = ctx;
|
|
202
203
|
const deadline = Date.now() + budgetMs;
|
|
203
204
|
let last = null;
|
|
204
205
|
for (;;) {
|
|
205
206
|
let run;
|
|
206
207
|
try {
|
|
207
|
-
|
|
208
|
-
run = raw ? await runRowAt("run.a2a", store, raw) : null;
|
|
208
|
+
run = (await readVisibleRun(entry, store, taskId))?.row ?? null;
|
|
209
209
|
}
|
|
210
210
|
catch (e) {
|
|
211
211
|
deps.logger?.warn?.("a2a_serve_wait_read_failed", { error: e?.message });
|
|
@@ -254,10 +254,11 @@ async function handleMessageSend({ req, res, ctx, params, serve, runStore }) {
|
|
|
254
254
|
...(contextId !== undefined ? { sessionId: contextId } : {}),
|
|
255
255
|
...(scenario !== undefined ? { scenario } : {}),
|
|
256
256
|
};
|
|
257
|
-
const keyed = (await
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
257
|
+
const keyed = (await readReplayHit(submitter, deps.config, runStore, { idemKey: idem.key }, body.taskId).catch(() => undefined)) ??
|
|
258
|
+
(await readReplayHit(submitter, deps.config, runStore, { taskId: body.taskId }, body.taskId).catch(() => undefined));
|
|
259
|
+
const replay = keyed ? await answerReplay(keyed, { subject: submitter, clientTaskId: body.taskId, idem }, "durable", runStore) : undefined;
|
|
260
|
+
if (keyed?.kind === "visible" && replay?.status === 202) {
|
|
261
|
+
return taskFromRun(await runRowAt("run.a2a", runStore, keyed.row));
|
|
261
262
|
}
|
|
262
263
|
const inflight = replay === undefined ? ctx.registry.idemCache.peek(inflightKeyOf(idem, "durable", body.taskId)) : undefined;
|
|
263
264
|
let receipt;
|
|
@@ -298,7 +299,7 @@ async function handleMessageSend({ req, res, ctx, params, serve, runStore }) {
|
|
|
298
299
|
}
|
|
299
300
|
const taskId = receiptBody.taskId;
|
|
300
301
|
const sessionId = receiptBody.sessionId;
|
|
301
|
-
const run = await waitForRun(ctx, runStore, res, taskId, blocking ? serve.blockingWaitMs : 0);
|
|
302
|
+
const run = await waitForRun(ctx, protocolEntry(req, deps, "run.a2a", callerOf(req, deps)), runStore, res, taskId, blocking ? serve.blockingWaitMs : 0);
|
|
302
303
|
if (run)
|
|
303
304
|
return taskFromRun(run);
|
|
304
305
|
return {
|
|
@@ -311,6 +312,8 @@ async function handleMessageSend({ req, res, ctx, params, serve, runStore }) {
|
|
|
311
312
|
function rpcErrorFromRefusedReceipt(receipt) {
|
|
312
313
|
const code = receipt.body?.errorCode;
|
|
313
314
|
const head = `the serving deployment did not accept this submission (it answered ${receipt.status}${typeof code === "string" ? ` ${code}` : ""})`;
|
|
315
|
+
if (receipt.status >= 500)
|
|
316
|
+
return new RpcError(JSONRPC_INTERNAL_ERROR, `${head}; the failure is on the serving side and nothing was started, so the same message can be sent again later`);
|
|
314
317
|
if (isActiveRunConflictBody(receipt.body))
|
|
315
318
|
return new RpcError(JSONRPC_INVALID_PARAMS, `${head}; a session already running a turn must finish or be cancelled before the next message on the same contextId`);
|
|
316
319
|
if (isRunExistsConflictBody(receipt.body))
|
|
@@ -328,10 +331,10 @@ function durableIdempotencyTaskId(scope, messageId) {
|
|
|
328
331
|
async function handleTasksGet({ req, ctx, params, runStore }) {
|
|
329
332
|
const { deps } = ctx;
|
|
330
333
|
const id = asNonEmptyString(params.id, "params.id", MAX_TASK_ID_CHARS);
|
|
331
|
-
const
|
|
332
|
-
if (!
|
|
334
|
+
const admitted = await readVisibleRun(protocolEntry(req, deps, "run.a2a", callerOf(req, deps)), runStore, id);
|
|
335
|
+
if (!admitted)
|
|
333
336
|
throw new RpcError(A2A_TASK_NOT_FOUND, A2A_TASK_NOT_FOUND_MESSAGE);
|
|
334
|
-
return taskFromRun(
|
|
337
|
+
return taskFromRun(admitted.row);
|
|
335
338
|
}
|
|
336
339
|
async function handleExtendedCard({ req, ctx, serve }) {
|
|
337
340
|
return buildAgentCard(serve, cardReaderOf(req, ctx.deps.config), A2A_METHODS);
|
|
@@ -2,12 +2,13 @@ import type { IncomingMessage, ServerResponse } from "node:http";
|
|
|
2
2
|
import type { QuestionAnswer } from "@sema-agent/core";
|
|
3
3
|
import type { CheckpointStoreFull } from "../../plugins/store-backend.js";
|
|
4
4
|
import { type ToolApprovalCoordinator } from "../../tool-approval.js";
|
|
5
|
+
import { type RouteSessionStore } from "../owner-access.js";
|
|
5
6
|
import { type GovernancePosture } from "../../runtime-governance.js";
|
|
6
7
|
import { type GateIntentView } from "../../approval.js";
|
|
7
8
|
import { type RouteCtx, type RouteDecl, type RouteMatch, type RouteIdsOf } from "../route-ctx.js";
|
|
8
9
|
import { type KeyClosureIssue } from "../../request-key-closure.js";
|
|
9
10
|
import { type PeerInboundPendingRow } from "../../peer-inbound-face.js";
|
|
10
|
-
import
|
|
11
|
+
import type { SessionAgent } from "../../session-agent.js";
|
|
11
12
|
/** 族的成员 = 路由表行 id(改名 / 删行 ⇒ 下表的键当场编译红)。 */
|
|
12
13
|
export type DecisionDoorId = Extract<ApprovalsAssistantRouteId, "approval-decide" | "assistant-task-plan-review">;
|
|
13
14
|
/** 一道门的静态描述 —— 只写**这道门自己**的东西;路径、路径段、别门的键一概不在这里写(从来源读)。 */
|
|
@@ -164,7 +165,7 @@ peerInbound: (() => readonly PeerInboundPendingRow[]) | undefined,
|
|
|
164
165
|
* 🔴 [ref]:停驻行 `agent` 的会话店面 —— 与 `GET /v1/approvals` 同一只(`deps.sessionStorage`),经同一只整批投影 {@link projectDurableQueue}。
|
|
165
166
|
* `undefined` / 店不交 `placementOf` = 这台部署不存委派元组 ⇒ 没有一帧带 `agent`(帧字节与 [ref] 之前逐字相同)。位置在 `scope` 之前、与 `live` 并列:每个生产调用点都必须表态。
|
|
166
167
|
*/
|
|
167
|
-
sessions:
|
|
168
|
+
sessions: Pick<RouteSessionStore, "placementOf"> | undefined, scope: string | undefined,
|
|
168
169
|
/** [ref]②:出身归因的部署侧一半 + 三张审批名单(问的属主)。缺席 ⇒ 归不出治理出身(键缺席,与 best-effort 同方向)、没有一行读作
|
|
169
170
|
* 部署名单的问(记不住,方向是多问)。**位置在 `pollMs` 之前**是刻意的:`pollMs` 只有测试传,而本参数是每个生产调用点都必须给的那一个。 */
|
|
170
171
|
governance?: PendingProjectionDeployment, pollMs?: number): Promise<void>;
|
|
@@ -8,7 +8,7 @@ import { approvalPayloadFingerprint } from "../../plugins/approval-payload-finge
|
|
|
8
8
|
import { carriesDeploymentListQuestion, standingAnswerDurablyRecordable } from "../../tool-approval.js";
|
|
9
9
|
import { APPROVAL_GATE_KINDS } from "../../approval-content-kind.js";
|
|
10
10
|
import { isParkedRunStatus } from "../../plugins/store-contracts.js";
|
|
11
|
-
import { principalFrom,
|
|
11
|
+
import { principalFrom, scopeCellOf, CHECKPOINT_PUBLIC_SCOPE, PRINCIPAL_TOKEN_HEADER, APPROVAL_MAC_HEADER, APPROVAL_MAC_KID_HEADER } from "../../security.js";
|
|
12
12
|
import { keyAdmits } from "../../owner-faces.js";
|
|
13
13
|
import { personOf } from "../../owner-brands.js";
|
|
14
14
|
import { editedPlanBinding, verifyDirectDoorProof } from "../../principal-jwt.js";
|
|
@@ -23,7 +23,7 @@ import { sleep } from "../sse-log.js";
|
|
|
23
23
|
import { bindSseLifecycle } from "../sse-lifecycle.js";
|
|
24
24
|
import { sendJson, sendError, sseHeaders, logRequestError, SSE_MAX_STREAM_MS, SSE_HEARTBEAT_IDLE_MS } from "../send.js";
|
|
25
25
|
import { gatedSubject, explicitOperatorOk, sendPrincipalRefusal } from "../principal-gate.js";
|
|
26
|
-
import { admitRunById, admitSessionById, callerEntry, callerOf, callerOfDecision, deciderSubjectOf, enter,
|
|
26
|
+
import { admitRunById, admitSessionById, callerEntry, callerOf, callerOfDecision, deciderSubjectOf, enter, latestRunIdOf, listRunsOfScope, protocolEntry, readSessionAgent, readVisibleRun, refuse, runFactsOf, withCaller } from "../owner-access.js";
|
|
27
27
|
import { governanceOriginOf } from "../../runtime-governance.js";
|
|
28
28
|
import { deploymentListAsks } from "../../approval.js";
|
|
29
29
|
import { grantBindingOf } from "../../standing-answer-grant.js";
|
|
@@ -40,7 +40,6 @@ import { seatText } from "../../trace/exit-seat.js";
|
|
|
40
40
|
import { approvalQueueKindOfDoorId } from "../../approval-queue-kind.js";
|
|
41
41
|
import { defaultPeerInboundFace, parsePeerInboundId, peerBoxScope } from "../../peer-inbound-face.js";
|
|
42
42
|
import { RESUME_RESTATABLE_KEYS, readResumeRestatement } from "../resume-restatement.js";
|
|
43
|
-
import { readSessionAgent } from "../../session-agent.js";
|
|
44
43
|
const DECIDE_BODY_DECLARED_KEYS = [
|
|
45
44
|
"answer", "boundCallId", "boundInputHash", "checkpointToken", "decidedBy", "decidedVia", "decision", "feedback", "reason", "remember", "updatedInput",
|
|
46
45
|
...RESUME_RESTATABLE_KEYS,
|
|
@@ -280,8 +279,8 @@ async function decideIdempotentReplay(cs, args) {
|
|
|
280
279
|
};
|
|
281
280
|
}
|
|
282
281
|
async function gateObjectivePreview(reader, runStore, agentStore, gate, runSessionId) {
|
|
283
|
-
const previewOf = (taskId) => readVisibleRun(reader, runStore, taskId);
|
|
284
|
-
const own = typeof runSessionId === "string" ? ((await runStore.getActiveTaskId(runSessionId)) ?? (await runStore
|
|
282
|
+
const previewOf = async (taskId) => (await readVisibleRun(reader, runStore, taskId))?.row;
|
|
283
|
+
const own = typeof runSessionId === "string" ? ((await runStore.getActiveTaskId(runSessionId)) ?? (await latestRunIdOf(runStore, runSessionId))) : undefined;
|
|
285
284
|
if (own !== undefined)
|
|
286
285
|
return (await previewOf(own))?.objectivePreview ?? null;
|
|
287
286
|
if (agentStore === undefined)
|
|
@@ -334,10 +333,11 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
334
333
|
return;
|
|
335
334
|
}
|
|
336
335
|
const pending = [...(await projectDurableQueue(durableRows, deps.config, deps.sessionStorage)), ...peerInboundRowsFor(defaultPeerInboundFace, principal, ownerParam)()];
|
|
336
|
+
const livePending = deps.toolApproval ? await deps.toolApproval.listLivePending(scope) : undefined;
|
|
337
337
|
sendJson(res, 200, {
|
|
338
338
|
pending,
|
|
339
339
|
serverNowMs: Date.now(),
|
|
340
|
-
...(
|
|
340
|
+
...(livePending !== undefined ? { livePending } : {}),
|
|
341
341
|
...(deps.approvalAskAudit ? { crashConverged: deps.approvalAskAudit.listCrashConverged(scope) } : {}),
|
|
342
342
|
});
|
|
343
343
|
return;
|
|
@@ -461,7 +461,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
461
461
|
if (typeof host === "string")
|
|
462
462
|
byGate.set(host, s);
|
|
463
463
|
});
|
|
464
|
-
const runs = await runStore
|
|
464
|
+
const runs = await listRunsOfScope(runStore, scope, 100);
|
|
465
465
|
const tasks = runs
|
|
466
466
|
.filter((r) => r.status === "running" || isParkedRunStatus(r.status))
|
|
467
467
|
.map((r) => {
|
|
@@ -510,7 +510,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
510
510
|
let flagged = await runStore.requestPreempt(taskId, run.owner);
|
|
511
511
|
const PREEMPT_RECLASSIFY_ATTEMPTS = 3;
|
|
512
512
|
for (let attempt = 0; !flagged; attempt++) {
|
|
513
|
-
const now = await runStore
|
|
513
|
+
const now = (await readVisibleRun(preemptEntry, runStore, taskId))?.row;
|
|
514
514
|
if (now !== undefined && isParkedRunStatus(now.status)) {
|
|
515
515
|
sendError(res, 409, "conflict.already_suspended", "task is already suspended", { taskId, status: now.status });
|
|
516
516
|
return;
|
|
@@ -660,7 +660,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
660
660
|
}
|
|
661
661
|
const sighting = typeof body.checkpointId === "string" ? { face: "checkpointId", value: body.checkpointId } : undefined;
|
|
662
662
|
const decisionEntry = callerEntry(req, deps, match.decl.id);
|
|
663
|
-
const run = await runStore
|
|
663
|
+
const run = await runFactsOf(runStore, taskId);
|
|
664
664
|
if (!run) {
|
|
665
665
|
if (!deps.config.directDoorActive)
|
|
666
666
|
deps.logger?.info?.("decide_404", { reason: "no-row", taskId, principalPresent: principal !== undefined });
|
|
@@ -693,7 +693,7 @@ export async function handleApprovalsAssistant(req, res, match, ctx) {
|
|
|
693
693
|
singleUse = proof.singleUse === undefined ? undefined : { proof: proof.singleUse, store };
|
|
694
694
|
}
|
|
695
695
|
const deciderEntry = withCaller(decisionEntry, callerOfDecision(decisionEntry.caller, deciderPrincipal, deps.config));
|
|
696
|
-
const decisionAdmitted =
|
|
696
|
+
const decisionAdmitted = await readVisibleRun(deciderEntry, runStore, taskId);
|
|
697
697
|
if (decisionAdmitted === undefined) {
|
|
698
698
|
deps.logger?.info?.("decide_404", { reason: "owner-mismatch", taskId, principalPresent: principal !== undefined });
|
|
699
699
|
refuse(deciderEntry, res, "not_visible");
|
|
@@ -1122,7 +1122,7 @@ export async function streamApprovals(req, res, cs, live, peerInbound, sessions,
|
|
|
1122
1122
|
let snapshot;
|
|
1123
1123
|
try {
|
|
1124
1124
|
const pending = [...(await projectDurableQueue(await cs.listPending(scope), governance, sessions)), ...(peerInbound?.() ?? [])];
|
|
1125
|
-
snapshot = { pending, livePending: live ? live.listLivePending(scope) : [] };
|
|
1125
|
+
snapshot = { pending, livePending: live ? await live.listLivePending(scope) : [] };
|
|
1126
1126
|
}
|
|
1127
1127
|
catch (err) {
|
|
1128
1128
|
const failure = approvalsReadFailureOf(err);
|
|
@@ -37,7 +37,7 @@ import { judgeAutoModeArming } from "../../auto-mode-face.js";
|
|
|
37
37
|
import { coercePermissionModeStrict, PERMISSION_MODE_WORDS, taskHooksHonored } from "../../task-settings.js";
|
|
38
38
|
import { gatedPerson, sendPrincipalRefusal } from "../principal-gate.js";
|
|
39
39
|
import { readAdoptionImportCapability } from "../../adoption/import.js";
|
|
40
|
-
import {
|
|
40
|
+
import { headReadPresent } from "../../session-incarnation.js";
|
|
41
41
|
import { callerTrust } from "../caller-trust.js";
|
|
42
42
|
import { sessionRulesNamespaceFormsHonored } from "../../session-policy-wire.js";
|
|
43
43
|
function routePairingOf(deps, name, m) {
|
|
@@ -207,6 +207,7 @@ export async function handleCapabilities(req, res, match, ctx) {
|
|
|
207
207
|
sideQuery: true,
|
|
208
208
|
agentRoster: facts.agentRoster(deps).available,
|
|
209
209
|
projects: facts.projectRegistry(deps).available,
|
|
210
|
+
projectInheritance: facts.projectRegistry(deps).available,
|
|
210
211
|
retention: retentionAdvertisement(deps.config),
|
|
211
212
|
peerLane: Boolean(deps.peerDirectory),
|
|
212
213
|
scenarioSubject: true,
|
|
@@ -214,12 +215,12 @@ export async function handleCapabilities(req, res, match, ctx) {
|
|
|
214
215
|
sessionSearch: facts.sessionList(deps).available,
|
|
215
216
|
sessionFork: facts.sessionFork(deps).available,
|
|
216
217
|
sessionDelete: facts.sessionDelete(deps).available,
|
|
217
|
-
resumeAt: Boolean(deps.resumeAnchorStore &&
|
|
218
|
+
resumeAt: Boolean(deps.resumeAnchorStore && headReadPresent(deps.sessionStorage)),
|
|
218
219
|
promptSuggestions: true,
|
|
219
220
|
sessionPolicy: facts.sessionPolicy(deps).available,
|
|
220
221
|
sessionRulesNamespaceForms: sessionRulesNamespaceFormsHonored(),
|
|
221
222
|
restoreFiles: Boolean(deps.fileHistoryStore),
|
|
222
|
-
rewindFilesTo: Boolean(deps.fileHistoryStore && deps.resumeAnchorStore &&
|
|
223
|
+
rewindFilesTo: Boolean(deps.fileHistoryStore && deps.resumeAnchorStore && headReadPresent(deps.sessionStorage)),
|
|
223
224
|
sessionRewindFiles: facts.sessionRewindFiles(deps).available,
|
|
224
225
|
sessionRewindFilesPreview: facts.sessionRewindFilesPreview(deps).available,
|
|
225
226
|
fileHistoryCapture: fileHistoryCaptureOf(deps.fileHistoryStore, deps.config.fileHistoryCapture),
|
|
@@ -299,7 +300,7 @@ export async function handleCapabilities(req, res, match, ctx) {
|
|
|
299
300
|
...(modelReasoningDecl(m) !== undefined ? { reasoning: modelReasoningDecl(m) } : {}),
|
|
300
301
|
...(modelImageInput(m) !== "undeclared" ? { vision: modelImageInput(m) === "yes" } : {}),
|
|
301
302
|
supportsThinkingOff: thinkingOffSpelled(m),
|
|
302
|
-
...(m.contextWindow ? { contextWindow: m.contextWindow } : {}),
|
|
303
|
+
...(m.contextWindow ? { contextWindow: m.contextWindow, ...(Object.hasOwn(deps.config.contextWindowSources, name) ? { contextWindowSource: deps.config.contextWindowSources[name] } : {}) } : {}),
|
|
303
304
|
...(m.maxTokens ? { maxOutputTokens: m.maxTokens } : {}),
|
|
304
305
|
...((levels) => (levels !== undefined ? { supportedEffortLevels: [...levels] } : {}))(reasoningEffortLevelsOf(m)),
|
|
305
306
|
...(m.compat !== undefined ? { compat: m.compat } : {}),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* [ref] §5 S2([ref])—— `GET /v1/config/catalog`:配置目录自描述端点(operator lane)。
|
|
3
3
|
*
|
|
4
4
|
* TOB 运维在 web 上要一个**不撒谎**的配置目录:哪个键、什么腿(env/center)、改了何时生效
|
|
5
5
|
* (hot/restart-片名/deploy/inert)、本机实际值 —— 今天这些事实散在 config.ts 数千行与三份文档里,
|
|
@@ -86,7 +86,9 @@ export interface StaticWiringFacts {
|
|
|
86
86
|
* 白白关掉一个可用的协议。`capable` 真而 `effective` 不真同样致命:能力在、这条部署形上却不会真的
|
|
87
87
|
* park,窗到期依旧无降级目的地。
|
|
88
88
|
* ② 会话店持久性:manifest 声明 `declared_durable`,而会话店的介质(店持久性判定里的**数据根**那一行:SQL 两方言 = 委托给库、local = 数据根所在挂载、
|
|
89
|
-
* 没有后端 = 内存)判为 `ephemeral` ⇒ 「替换后还在」的声明没有介质兑现 ⇒ 拒启 `config.store_not_durable`(拒句逐根列三根判定 +
|
|
89
|
+
* 没有后端 = 内存)判为 `ephemeral` ⇒ 「替换后还在」的声明没有介质兑现 ⇒ 拒启 `config.store_not_durable`(拒句逐根列三根判定 + 三条出路)。
|
|
90
|
+
* local 店的声明不是常量:它由 `local-store-declaration.ts` 的唯一读者定(运维声明 `LOCAL_STORE_DURABILITY=ephemeral`,或店落在调用方自己那块易失盘上 ⇒
|
|
91
|
+
* 会话店与检查点店两半一起声明 `process-local`)—— 那时清单读 `process_local`,本条恒过,改出 warn 一行(带依据与挂卷出路;同一件事 park 那条不再另说)。
|
|
90
92
|
* 介质判不出(`unknown`:非 Linux / 挂载表读不到 / 介质形不在规则表里)⇒ 只 warn —— 判不了的部署不能因自报位停机;
|
|
91
93
|
* 数据根持久而另两根(封签钥匙目录 / file 记忆根)易失或判不出 ⇒ 也只 warn:会话店的声明兑现了,掉的是停驻行的封签钥匙 / 记忆,不是会话(能力位如实报最弱)。
|
|
92
94
|
* 声明不是 `declared_durable` ⇒ 恒过。这条与 memory+durable 两条既有拒启同族(声明与介质必须对得上)。
|
|
@@ -8,6 +8,7 @@ import { gatedPerson, explicitOperatorOk, isLoopbackAddress, sendOperatorPrincip
|
|
|
8
8
|
import * as facts from "../../capability-facts.js";
|
|
9
9
|
import { assertNever } from "../route-ctx.js";
|
|
10
10
|
import { STORE_NOT_DURABLE_CODE, StoreNotDurableError, describeStoreRoot, projectStoreDurabilityWiring, unwiredStorePosture } from "../../store-posture.js";
|
|
11
|
+
import { describeLocalStoreDeclaration } from "../../local-store-declaration.js";
|
|
11
12
|
export function buildServerWiringGates(input) {
|
|
12
13
|
const gate = resolveStreamApprovalGate({
|
|
13
14
|
toolApprovalEnabled: input.toolApprovalEnabled,
|
|
@@ -44,6 +45,21 @@ export function buildServerWiringGates(input) {
|
|
|
44
45
|
approvalGrant: [...input.approvalGrant],
|
|
45
46
|
};
|
|
46
47
|
}
|
|
48
|
+
function processLocalMediumSentence(dataRoot, aggregate, listed) {
|
|
49
|
+
const readFaces = `Store durability by root: ${listed}; GET /v1/capabilities store.durability and /health.store.durability say "${aggregate}" (the weakest root).`;
|
|
50
|
+
switch (dataRoot) {
|
|
51
|
+
case "ephemeral":
|
|
52
|
+
return `The data root's medium does not survive a replacement either — sessions and parked approvals on it go with the next replacement. ${readFaces}`;
|
|
53
|
+
case "durable":
|
|
54
|
+
return `The data root's medium measures durable today — the declaration is what this deployment promises, not what the disk does today. ${readFaces}`;
|
|
55
|
+
case "unknown":
|
|
56
|
+
return `This server could not prove whether the data root survives a replacement. ${readFaces}`;
|
|
57
|
+
default: {
|
|
58
|
+
const unhandled = dataRoot;
|
|
59
|
+
throw new Error(`unhandled store durability ${JSON.stringify(unhandled)}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
47
63
|
export function buildStaticWiringAudit(facts) {
|
|
48
64
|
const refusals = [];
|
|
49
65
|
const warnings = [];
|
|
@@ -58,15 +74,16 @@ export function buildStaticWiringAudit(facts) {
|
|
|
58
74
|
`A window expiry would then have no degradation target and adjudicate as a fail-closed deny — refusing to start.`);
|
|
59
75
|
}
|
|
60
76
|
let refusalCode;
|
|
77
|
+
const roots = facts.store.roots;
|
|
78
|
+
const listed = roots.map((r) => `${describeStoreRoot(r)}`).join("; ");
|
|
79
|
+
const processLocalDeclaration = facts.store.localDeclaration?.durability === "process-local" ? facts.store.localDeclaration : undefined;
|
|
61
80
|
if (facts.manifest.session.store === "declared_durable") {
|
|
62
|
-
const roots = facts.store.roots;
|
|
63
81
|
const session = roots.find((r) => r.root === "data");
|
|
64
|
-
const listed = roots.map((r) => `${describeStoreRoot(r)}`).join("; ");
|
|
65
82
|
if (session === undefined || session.verdict === "ephemeral") {
|
|
66
83
|
refusalCode = STORE_NOT_DURABLE_CODE;
|
|
67
84
|
const wayOut = session?.rule === "backend_memory" || session === undefined
|
|
68
85
|
? `No store backend was assembled (env-only worker or a degraded boot) — wire DB_BACKEND=mysql|pg|local, or fix the session store's durability declaration.`
|
|
69
|
-
: `
|
|
86
|
+
: `Three ways out: mount a persistent volume at ${session.path ?? "the data root"} (or point LOCAL_DATA_ROOT at one); or declare the local store ephemeral (LOCAL_STORE_DURABILITY=ephemeral — sessions, parked approvals and memory then do not survive a container / Pod replacement); or keep nothing on disk (DB_BACKEND=memory).`;
|
|
70
87
|
refusals.push(`${STORE_NOT_DURABLE_CODE}: the engine's static wiring reports session.store="declared_durable" while the session store's medium does not survive a container / Pod replacement (store durability by root: ${listed}). ` +
|
|
71
88
|
`A durable declaration on an ephemeral medium is a claim nothing can honor — sessions, parked approvals and memory would vanish with the next replacement while every read face said "durable". Refusing to start. ${wayOut}`);
|
|
72
89
|
}
|
|
@@ -74,11 +91,19 @@ export function buildStaticWiringAudit(facts) {
|
|
|
74
91
|
warnings.push(`store durability is "${facts.store.durability}" (by root: ${listed}). ` +
|
|
75
92
|
(facts.store.durability === "unknown"
|
|
76
93
|
? `This server could not prove that every root survives a container / Pod replacement (no mount evidence for it — not Linux, an unreadable mount table, or a mount shape outside the rule table); GET /v1/capabilities store.durability and /health.store.durability say "unknown". `
|
|
77
|
-
: `The session store's medium holds, but a root marked ephemeral does not survive a container / Pod replacement — mount a persistent volume there (SEALED_KEY_DIR / MEMORY_ENGINE_DIR name those directories). `
|
|
94
|
+
: `The session store's medium holds, but a root marked ephemeral does not survive a container / Pod replacement — mount a persistent volume there (SEALED_KEY_DIR / MEMORY_ENGINE_DIR name those directories). ` +
|
|
95
|
+
`A sealing-key directory declared with SEALED_KEY_DIR on such a medium is refused at boot while parked approvals are durable (the parked rows would outlive the key their credentials are sealed to); ` +
|
|
96
|
+
`the default <data root>/sealed-key and the file memory root are reported here, not refused. `) +
|
|
78
97
|
`Per-root detail: GET /v1/diagnostics/wiring storeDurability.roots.`);
|
|
79
98
|
}
|
|
80
99
|
}
|
|
81
|
-
if (
|
|
100
|
+
else if (processLocalDeclaration !== undefined) {
|
|
101
|
+
const declaration = processLocalDeclaration;
|
|
102
|
+
warnings.push(`the local store declares itself process-local (${describeLocalStoreDeclaration(declaration)}): its session store and checkpoint store promise their rows survive a process restart, not a container / Pod replacement. ` +
|
|
103
|
+
`${processLocalMediumSentence(roots.find((r) => r.root === "data")?.verdict ?? "unknown", facts.store.durability, listed)} ` +
|
|
104
|
+
`To keep them across replacements, mount a persistent volume at each root above that does not read durable (LOCAL_DATA_ROOT / SEALED_KEY_DIR / MEMORY_ENGINE_DIR point the three roots at one)${declaration.rule === "declared_ephemeral" ? " and unset LOCAL_STORE_DURABILITY" : ""}.`);
|
|
105
|
+
}
|
|
106
|
+
if (facts.parkFacility && facts.manifest.parkLane.checkpointDurability !== "declared_durable" && processLocalDeclaration === undefined) {
|
|
82
107
|
warnings.push(`park facility is enabled but the checkpoint store does not declare durable storage ` +
|
|
83
108
|
`(parkLane.checkpointDurability=${JSON.stringify(facts.manifest.parkLane.checkpointDurability ?? null)}). ` +
|
|
84
109
|
`A parked approval survives a restart only on a durable store, and this reading folds "declared process-local" together with "declared nothing" — every in-tree adapter declares "durable", so a non-durable reading here means a store this build does not own. ` +
|
|
@@ -2,7 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { isParkedRunStatus, isTerminalRunStatus, runProvenElsewhere } from "../../plugins/store-contracts.js";
|
|
3
3
|
import { DeadlineExceeded, MCP_DIAL_DEADLINE_MS, raceDeadline } from "../mcp-dial-deadline.js";
|
|
4
4
|
import { sendJson, sendError } from "../send.js";
|
|
5
|
-
import { admitSessionById, enter } from "../owner-access.js";
|
|
5
|
+
import { admitSessionById, enter, runFactsOf } from "../owner-access.js";
|
|
6
6
|
import { assertNever } from "../route-ctx.js";
|
|
7
7
|
import * as facts from "../../capability-facts.js";
|
|
8
8
|
import { seatText } from "../../trace/exit-seat.js";
|
|
@@ -118,7 +118,7 @@ export async function handleMcpReconnect(req, res, match, ctx) {
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
|
-
const run = activeTaskId === undefined ? undefined : await runStore
|
|
121
|
+
const run = activeTaskId === undefined ? undefined : await runFactsOf(runStore, activeTaskId);
|
|
122
122
|
if (run && isParkedRunStatus(run.status)) {
|
|
123
123
|
sendError(res, 409, "steering.not_running", "run is waiting on a pending decision — the MCP re-dial verb needs a live turn; a resumed continuation dials every declared server afresh (the re-dial applies to the current turn only and is not persisted), so resume this run first — a re-dial cannot be queued behind the decision");
|
|
124
124
|
return;
|
|
@@ -116,7 +116,7 @@ export declare function buildClearanceRowWire(r: OriginClearanceRow): {
|
|
|
116
116
|
baseRev: string;
|
|
117
117
|
origin: {
|
|
118
118
|
at: number;
|
|
119
|
-
cause?: "static" | "
|
|
119
|
+
cause?: "static" | "observed" | "derived" | "unattributed" | undefined;
|
|
120
120
|
taint: "external";
|
|
121
121
|
};
|
|
122
122
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { sendJson, sendError } from "../send.js";
|
|
2
2
|
import { gatedSubject, sendPrincipalRefusal } from "../principal-gate.js";
|
|
3
|
-
import {
|
|
3
|
+
import { admitSessionById, enter, refuse } from "../owner-access.js";
|
|
4
4
|
import { sendResumeOutcome } from "../route-ctx.js";
|
|
5
5
|
import { assertNever } from "../route-ctx.js";
|
|
6
6
|
import * as facts from "../../capability-facts.js";
|
|
@@ -54,8 +54,7 @@ export async function handleNotifyWake(req, res, match, ctx) {
|
|
|
54
54
|
sendError(res, 501, "capability.session_ownership_required", "external notify requires the session-ownership face (sessionStorage.headOf)");
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
|
-
const
|
|
58
|
-
const notifyAdmitted = await admitSessionRow(notifyEntry, res, owned.sessionStorage, notifySession, notifyHead);
|
|
57
|
+
const notifyAdmitted = await admitSessionById(notifyEntry, res, owned.sessionStorage, notifySession);
|
|
59
58
|
if (notifyAdmitted === undefined)
|
|
60
59
|
return;
|
|
61
60
|
const payload = {
|
|
@@ -15,10 +15,12 @@
|
|
|
15
15
|
*
|
|
16
16
|
* 拒绝词 → HTTP 状态(穷举 `switch`,core 加词 ⇒ 编译红):
|
|
17
17
|
* · `not_member` → 404:「不同 org」「查无此人」「目录答不上来」同一份字节(门保证),404 与本仓反枚举的既有形一致;
|
|
18
|
-
* · `rate_limited` → 429
|
|
18
|
+
* · `rate_limited` → 429,体带 `retryAfterSec`、头带同值 `Retry-After`(门答案里的那一个数 —— 配额店按店钟算的到当前窗结束的整秒数;本口不再算一遍,
|
|
19
|
+
* 一个数两个投影,先例 `run-concurrency-cap.ts`);三界(尝试 / 对偶 / 聚合)同一句同一个数,另三只词没有这两样;
|
|
19
20
|
* · `inbox_full` → 409(收件人那一侧的状态,不是发件人的速率;与 `steering.queue_full` 同档);
|
|
20
21
|
* · `recipient_tombstoned` → 410(收件人正在被删除,这条路关了)。
|
|
21
22
|
* 门缺席(本部署没声明收件箱消费方)⇒ 501 `capability.unavailable`,能力位 `principalInboxDelivery` 读同一只事实。
|
|
23
|
+
* 配额店读不出自己的状态 ⇒ 门抛 `OrgDeliveryQuotaUnreadableError`,由 HTTP 兜底(`http/server.ts`)答带因的 500(fail-closed,一封都没投)。
|
|
22
24
|
*/
|
|
23
25
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
24
26
|
import type { RouteCtx, RouteMatch, RouteIdsOf } from "../route-ctx.js";
|
|
@@ -10,7 +10,8 @@ function sendRefusal(res, outcome) {
|
|
|
10
10
|
sendError(res, 404, "org_delivery.not_member", outcome.message);
|
|
11
11
|
return;
|
|
12
12
|
case "org_delivery.rate_limited":
|
|
13
|
-
|
|
13
|
+
res.setHeader("retry-after", String(outcome.retryAfterSec));
|
|
14
|
+
sendError(res, 429, "org_delivery.rate_limited", outcome.message, { retryAfterSec: outcome.retryAfterSec });
|
|
14
15
|
return;
|
|
15
16
|
case "org_delivery.inbox_full":
|
|
16
17
|
sendError(res, 409, "org_delivery.inbox_full", outcome.message);
|
|
@@ -19,7 +20,7 @@ function sendRefusal(res, outcome) {
|
|
|
19
20
|
sendError(res, 410, "org_delivery.recipient_tombstoned", outcome.message);
|
|
20
21
|
return;
|
|
21
22
|
default:
|
|
22
|
-
return assertNever(outcome
|
|
23
|
+
return assertNever(outcome);
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
export async function handlePrincipalInbox(req, res, match, ctx) {
|
|
@@ -48,6 +48,7 @@ export declare const PROJECT_ROW_DISPOSITIONS: {
|
|
|
48
48
|
readonly registeredBy: "forward";
|
|
49
49
|
readonly registeredAt: "forward";
|
|
50
50
|
readonly archivedAt: "forward";
|
|
51
|
+
readonly contentAttestedAt: "forward";
|
|
51
52
|
};
|
|
52
53
|
/** 项目行的键全集(处置表的键 = wire 上可能出现的每一个键;自铸登记表 `trace/self-minted-wire.ts` 的 `projectRowKey` 按它 `satisfies`)。 */
|
|
53
54
|
export type ProjectRowKey = keyof typeof PROJECT_ROW_DISPOSITIONS;
|
|
@@ -4,6 +4,7 @@ import { sendUnauthorized } from "../principal-gate.js";
|
|
|
4
4
|
import { routeListFilter } from "../owner-access.js";
|
|
5
5
|
import { assertNever } from "../route-ctx.js";
|
|
6
6
|
import * as facts from "../../capability-facts.js";
|
|
7
|
+
import { projectVisible } from "../../project-context.js";
|
|
7
8
|
import { projectByTable } from "../../trace/projection-table.js";
|
|
8
9
|
export const PROJECT_NOT_FOUND_MESSAGE = "no such project";
|
|
9
10
|
export const PROJECT_ROW_DISPOSITIONS = {
|
|
@@ -19,6 +20,7 @@ export const PROJECT_ROW_DISPOSITIONS = {
|
|
|
19
20
|
registeredBy: "forward",
|
|
20
21
|
registeredAt: "forward",
|
|
21
22
|
archivedAt: "forward",
|
|
23
|
+
contentAttestedAt: "forward",
|
|
22
24
|
};
|
|
23
25
|
export function projectRowOf(id, registration) {
|
|
24
26
|
return projectByTable("project", PROJECT_ROW_DISPOSITIONS, registration, { id });
|
|
@@ -37,8 +39,8 @@ function readArchivedQuery(raw) {
|
|
|
37
39
|
export async function handleProjects(req, res, match, ctx) {
|
|
38
40
|
const { deps } = ctx;
|
|
39
41
|
const { safeDecode } = ctx.helpers;
|
|
40
|
-
const
|
|
41
|
-
if (!fleetWide && gateOwner === null) {
|
|
42
|
+
const viewer = routeListFilter(req, deps, match.decl.id);
|
|
43
|
+
if (!viewer.fleetWide && viewer.gateOwner === null) {
|
|
42
44
|
sendUnauthorized(res, "identity");
|
|
43
45
|
return;
|
|
44
46
|
}
|
|
@@ -47,7 +49,7 @@ export async function handleProjects(req, res, match, ctx) {
|
|
|
47
49
|
sendError(res, 501, "capability.unavailable", "the project registry is not available on this deployment: projects are published only by the configuration center, and no center configuration is applied here");
|
|
48
50
|
return;
|
|
49
51
|
}
|
|
50
|
-
const visible = (registration) =>
|
|
52
|
+
const visible = (registration) => projectVisible(registration, viewer);
|
|
51
53
|
switch (match.decl.id) {
|
|
52
54
|
case "projects-list": {
|
|
53
55
|
const archived = readArchivedQuery(new URLSearchParams(match.search).get("archived"));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* [ref] 车2 —— **托管留存的 operator 治理面**(设计稿 `docs/
|
|
2
|
+
* [ref] 车2 —— **托管留存的 operator 治理面**(设计稿 `docs/[ref]-retention-lane.md` §5/§6)。
|
|
3
3
|
*
|
|
4
4
|
* · `PUT /v1/ops/retention/holds/:domain` —— 放置 legal hold;
|
|
5
5
|
* · `DELETE /v1/ops/retention/holds/:domain` —— 解除;
|
|
@@ -43,7 +43,7 @@ export type PermissionModePersistMiss = (typeof PERMISSION_MODE_PERSIST_MISSES)[
|
|
|
43
43
|
* · run 行仍在本副本(`runProvenElsewhere` 的反面 —— 别的副本续跑了它,续跑的 CAS 赢点把行上的副本改成它自己);
|
|
44
44
|
* · 本副本这条 run 此刻登记的活流仍是接下切档的那一只(本副本上续跑的新腿登记的是另一只流对象;腿收场时按对象身份摘掉自己的)。
|
|
45
45
|
*/
|
|
46
|
-
export declare function switchLegHolds<S extends object>(fenced: FencedRun, thisInstanceId: string | undefined, liveNow: S | undefined, switched: S): boolean;
|
|
46
|
+
export declare function switchLegHolds<S extends object>(fenced: Pick<FencedRun, "instanceId">, thisInstanceId: string | undefined, liveNow: S | undefined, switched: S): boolean;
|
|
47
47
|
/** 本判官改了词时回执旁的那一格(`admission`)。 */
|
|
48
48
|
interface PermissionModeAdmissionNote {
|
|
49
49
|
readonly requested: PermissionMode;
|
|
@@ -7,7 +7,7 @@ import * as facts from "../../capability-facts.js";
|
|
|
7
7
|
import { PERMISSION_MODE_WORDS, coercePermissionModeStrict, parseTaskSettings } from "../../task-settings.js";
|
|
8
8
|
import { admitPermissionModeWord } from "../../permission-mode-admission.js";
|
|
9
9
|
import { readResumeCtx, resumeCtxCorruptAnswer, resumeCtxUnreadableAnswer, resumeCtxUnsealableAnswer } from "../resume-ctx-read.js";
|
|
10
|
-
import { sealCheckpointCtx
|
|
10
|
+
import { sealCheckpointCtx } from "../checkpoint-ctx.js";
|
|
11
11
|
import { serviceVersion } from "../../service-version.js";
|
|
12
12
|
import { recordFailOpen } from "../../observability/fail-open.js";
|
|
13
13
|
export const PERMISSION_MODE_PERSIST_MISSES = ["claim_released", "context_absent", "store_failed"];
|
|
@@ -114,7 +114,7 @@ export async function handlePermissionMode(req, res, match, ctx) {
|
|
|
114
114
|
}
|
|
115
115
|
let persistMiss;
|
|
116
116
|
try {
|
|
117
|
-
const next = sealCheckpointCtx({ ...
|
|
117
|
+
const next = sealCheckpointCtx({ ...stored, body: { ...stored.body, permissionMode: admitted }, writerVersion: serviceVersion() }, deps.checkpointCtxSealing, sessionId);
|
|
118
118
|
const rewrite = await checkpointStore.rewriteCtxWhileClaimed(sessionId, next, { fence: runStore, taskId, legHolds: (fenced) => switchLegHolds(fenced, deps.instanceId, ctx.registry.steerableRuns.get(taskId), live) });
|
|
119
119
|
persistMiss = rewrite === "written" ? undefined : rewrite;
|
|
120
120
|
}
|