@sema-agent/server 7.147.0 → 7.149.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 +1468 -24
- package/README.md +35 -7
- package/README.zh-CN.md +18 -8
- package/USAGE.md +444 -193
- package/deploy/sema-up/README.md +16 -5
- package/deploy/sema-up/chart/templates/NOTES.txt +1 -1
- package/deploy/sema-up/chart/templates/_helpers.tpl +20 -4
- package/deploy/sema-up/chart/values.yaml +3 -2
- package/deploy/sema-up/cluster-up.sh +74 -176
- package/deploy/sema-up/kube-up.sh +29 -49
- package/deploy/sema-up/lib/chart-run.sh +23 -0
- package/deploy/sema-up/lib/dataroot.sh +3 -3
- package/deploy/sema-up/lib/health.sh +62 -13
- package/deploy/sema-up/lib/helm-values-cluster.py +18 -0
- package/deploy/sema-up/lib/helm-values-kube.py +35 -0
- package/deploy/sema-up/lib/regcred.py +8 -0
- package/deploy/sema-up/lib/remote/helm-install.sh +3 -0
- package/deploy/sema-up/lib/remote/image-import.sh +6 -0
- package/deploy/sema-up/lib/remote/machine-precheck.sh +11 -0
- package/deploy/sema-up/lib/remote/region-probe.sh +3 -0
- package/deploy/sema-up/lib/remote/stack-ready.sh +26 -0
- package/deploy/sema-up/lib/remote/vxlan-guard.sh +8 -0
- package/deploy/sema-up/lib/render-stack.py +17 -0
- package/deploy/sema-up/lib/shell-text.sh +87 -0
- package/deploy/sema-up/lib/usage-flags.txt +10 -0
- package/deploy/sema-up/lib/usage-head.txt +1 -0
- package/deploy/sema-up/lib/usage-tail.txt +13 -0
- package/deploy/sema-up/preflight.sh +10 -8
- package/deploy/sema-up/sema-up.sh +14 -39
- package/deploy/sema-up/smoke.sh +7 -6
- package/deploy/sema-up/stack/compose.dataroot.yaml +3 -0
- package/deploy/sema-up/stack/compose.yaml +13 -1
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +21 -0
- package/dist/adoption/plan.d.ts +24 -0
- package/dist/adoption/plan.js +53 -1
- package/dist/adoption/runner.d.ts +10 -1
- package/dist/adoption/runner.js +36 -16
- package/dist/approval-card.d.ts +36 -38
- package/dist/approval-gate-currency.js +3 -2
- package/dist/approval-leg-origin.d.ts +33 -0
- package/dist/approval-leg-origin.js +4 -0
- package/dist/approval-reconciler.d.ts +4 -13
- package/dist/approval-reconciler.js +2 -2
- package/dist/approval.d.ts +13 -11
- package/dist/approval.js +3 -3
- package/dist/audit.d.ts +10 -3
- package/dist/audit.js +15 -7
- package/dist/auth-bridge.d.ts +9 -15
- package/dist/auth-bridge.js +4 -11
- package/dist/auth-keys.d.ts +10 -1
- package/dist/auth-keys.js +8 -0
- package/dist/auto-mode-face.d.ts +10 -7
- package/dist/auto-mode-face.js +7 -4
- package/dist/background-agent-name.d.ts +19 -1
- package/dist/background-agent-name.js +12 -2
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/bake-runner/main.js +9 -6
- package/dist/bench/s1/arms.js +6 -5
- package/dist/bench/s1/live-deps.js +5 -2
- package/dist/bench/s1/run-firm.js +6 -5
- package/dist/bind-host.d.ts +25 -0
- package/dist/bind-host.js +25 -0
- package/dist/boot/adoption.d.ts +3 -0
- package/dist/boot/adoption.js +1 -0
- package/dist/boot/deployment-mods.d.ts +1 -1
- package/dist/boot/execution-env.d.ts +17 -7
- package/dist/boot/execution-env.js +47 -42
- package/dist/boot/execution-lane.d.ts +6 -4
- package/dist/boot/execution-lane.js +3 -1
- package/dist/boot/exit-boundary.d.ts +2 -2
- package/dist/boot/exit-boundary.js +6 -5
- package/dist/boot/fatal-exit.d.ts +3 -5
- package/dist/boot/fatal-exit.js +2 -2
- package/dist/boot/leader.d.ts +15 -0
- package/dist/boot/leader.js +17 -15
- package/dist/boot/memory-consolidation.d.ts +37 -29
- package/dist/boot/memory-consolidation.js +11 -5
- package/dist/boot/org-delivery.d.ts +3 -2
- package/dist/boot/org-memory.js +1 -1
- package/dist/boot/parked-revive-gate.js +2 -2
- package/dist/boot/reapers.d.ts +4 -3
- package/dist/boot/reapers.js +19 -16
- package/dist/boot/resolve-spec.d.ts +5 -3
- package/dist/boot/resolve-spec.js +60 -70
- package/dist/boot/retention-lane.d.ts +4 -4
- package/dist/boot/retention-lane.js +2 -2
- package/dist/boot/runner-deps.d.ts +28 -7
- package/dist/boot/runner-deps.js +14 -5
- package/dist/boot/runtime-caps.d.ts +2 -2
- package/dist/boot/runtime-caps.js +16 -2
- package/dist/boot/session-faces.d.ts +16 -7
- package/dist/boot/session-faces.js +114 -94
- package/dist/boot/shutdown.d.ts +5 -4
- package/dist/boot/shutdown.js +6 -4
- package/dist/boot/stage-01-config.d.ts +1 -0
- package/dist/boot/stage-01-config.js +13 -4
- package/dist/boot/stage-02-web-admin-pull.d.ts +2 -0
- package/dist/boot/stage-02-web-admin-pull.js +16 -3
- package/dist/boot/stage-03-store-backend.d.ts +4 -0
- package/dist/boot/stage-03-store-backend.js +4 -3
- package/dist/boot/stage-04-stores.d.ts +3 -0
- package/dist/boot/stage-04-stores.js +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +8 -3
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +12 -13
- package/dist/boot/stage-06-runners.js +23 -15
- package/dist/boot/stage-07-capability-layer.d.ts +13 -9
- package/dist/boot/stage-07-capability-layer.js +5 -3
- package/dist/boot/stage-08-reapers.d.ts +13 -9
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +14 -16
- package/dist/boot/stage-09-leader.js +12 -4
- package/dist/boot/stage-10-http-server.d.ts +14 -16
- package/dist/boot/stage-10-http-server.js +7 -4
- package/dist/boot/store-evidence.d.ts +20 -0
- package/dist/boot/store-evidence.js +13 -0
- package/dist/boot/stores.d.ts +6 -0
- package/dist/boot/stores.js +41 -27
- package/dist/boot/task-list-lane.d.ts +4 -4
- package/dist/boot/web-admin.d.ts +4 -2
- package/dist/boot/web-admin.js +55 -35
- package/dist/boot/webfetch-summarize-lane.d.ts +1 -1
- package/dist/boot-reclaim.d.ts +3 -1
- package/dist/boot-reclaim.js +1 -1
- package/dist/brain.d.ts +7 -18
- package/dist/brain.js +5 -17
- package/dist/budget.js +6 -6
- package/dist/capabilities/center-plugins.d.ts +7 -1
- package/dist/capabilities/center-plugins.js +32 -10
- package/dist/capabilities/center-wiring.js +1 -1
- package/dist/capabilities/composite-members.d.ts +2 -2
- package/dist/capabilities/composite-members.js +2 -2
- package/dist/capabilities/repo-tools.d.ts +2 -0
- package/dist/capabilities/repo-tools.js +14 -12
- package/dist/capabilities/scenarios.d.ts +6 -15
- package/dist/capabilities/scenarios.js +11 -16
- package/dist/capabilities/skills.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/capability-facts.d.ts +39 -11
- package/dist/capability-facts.js +35 -7
- 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 +8 -13
- package/dist/card-void.js +2 -7
- package/dist/center-credential-renewer.d.ts +6 -2
- package/dist/center-credential-renewer.js +7 -3
- package/dist/config-catalog.d.ts +28 -1
- package/dist/config-catalog.js +95 -85
- package/dist/config-dir-trust.d.ts +37 -4
- package/dist/config-dir-trust.js +88 -44
- package/dist/config-invariants.d.ts +43 -3
- package/dist/config-invariants.js +69 -5
- package/dist/config-lkg.d.ts +23 -1
- package/dist/config-lkg.js +17 -3
- package/dist/config-provider.d.ts +9 -9
- package/dist/config-provider.js +25 -110
- package/dist/config-pull-failure.d.ts +50 -0
- package/dist/config-pull-failure.js +48 -0
- package/dist/config-types.d.ts +62 -21
- package/dist/config.d.ts +14 -21
- package/dist/config.js +141 -64
- package/dist/context-window-notice.d.ts +31 -0
- package/dist/context-window-notice.js +28 -0
- package/dist/delegated-session-owner.d.ts +1 -1
- package/dist/deleted-session-ids.d.ts +3 -2
- package/dist/deployment-governance.d.ts +3 -3
- package/dist/deployment-shape.d.ts +46 -11
- package/dist/deployment-shape.js +8 -0
- package/dist/egress-redirect.d.ts +25 -7
- package/dist/egress-redirect.js +20 -2
- package/dist/elicitation.d.ts +6 -5
- package/dist/elicitation.js +23 -22
- package/dist/engine-identity.d.ts +28 -0
- package/dist/engine-identity.js +10 -0
- package/dist/entry-problems.d.ts +5 -7
- package/dist/entry-problems.js +1 -1
- package/dist/env-facts.js +2 -1
- package/dist/env-name-allowlist-knobs.d.ts +6 -5
- package/dist/env-name-allowlist-knobs.js +5 -0
- package/dist/env-witness.d.ts +7 -0
- package/dist/env-witness.js +16 -0
- package/dist/execution-lane-caps.d.ts +25 -23
- package/dist/execution-lane-caps.js +18 -26
- package/dist/execution-placement.d.ts +58 -18
- package/dist/execution-placement.js +41 -2
- package/dist/field-conflict.d.ts +7 -11
- package/dist/field-conflict.js +3 -3
- package/dist/file-history-capture.d.ts +3 -3
- package/dist/file-history-disclosure.js +1 -0
- package/dist/fleet/fleet-bus.d.ts +21 -3
- package/dist/fleet/fleet-bus.js +35 -25
- package/dist/fleet/fleet-reconciler.js +2 -2
- package/dist/fleet/serving-lease.js +3 -3
- package/dist/fleet-client.js +3 -3
- package/dist/fleet-lease.d.ts +0 -1
- package/dist/fleet-lease.js +4 -5
- package/dist/history-anchor.d.ts +23 -3
- package/dist/history-anchor.js +24 -4
- package/dist/hitl-delivery.d.ts +90 -0
- package/dist/hitl-delivery.js +98 -0
- package/dist/hooks/classic-stations.d.ts +8 -11
- package/dist/hooks/classic-stations.js +0 -7
- package/dist/hooks/command-spawn.d.ts +7 -2
- package/dist/hooks/command-spawn.js +13 -6
- package/dist/hooks/hook-llm.d.ts +5 -1
- package/dist/hooks/hook-llm.js +24 -15
- package/dist/hooks/hook-runner.d.ts +72 -57
- package/dist/hooks/hook-runner.js +271 -193
- package/dist/host-lsp-manager.d.ts +22 -8
- package/dist/host-lsp-manager.js +4 -1
- package/dist/http/active-run-conflict.d.ts +2 -43
- package/dist/http/active-run-conflict.js +3 -7
- package/dist/http/admission.d.ts +4 -18
- package/dist/http/admission.js +76 -79
- package/dist/http/approval-sweeps.d.ts +3 -3
- package/dist/http/approval-sweeps.js +56 -31
- package/dist/http/caller-trust.d.ts +8 -10
- package/dist/http/caller-trust.js +1 -2
- package/dist/http/claim-heartbeat.d.ts +49 -0
- package/dist/http/claim-heartbeat.js +46 -0
- package/dist/http/claimed-run.d.ts +16 -8
- package/dist/http/claimed-run.js +8 -0
- package/dist/http/dispatch.d.ts +8 -1
- package/dist/http/dispatch.js +78 -30
- package/dist/http/durable-run-leg.d.ts +11 -4
- package/dist/http/durable-run-leg.js +45 -21
- package/dist/http/execution-context.d.ts +122 -47
- package/dist/http/execution-context.js +135 -43
- package/dist/http/health-reader.d.ts +36 -0
- package/dist/http/health-reader.js +21 -0
- package/dist/http/health-self-report.d.ts +9 -9
- package/dist/http/health-self-report.js +4 -4
- package/dist/http/idempotency.d.ts +9 -5
- package/dist/http/idempotency.js +4 -4
- package/dist/http/memory-compliance-failure-reply.d.ts +15 -16
- package/dist/http/memory-compliance-failure-reply.js +4 -2
- package/dist/http/memory-face-fault-reply.d.ts +67 -0
- package/dist/http/memory-face-fault-reply.js +71 -0
- package/dist/http/memory-store-refusal-reply.d.ts +1 -1
- package/dist/http/memory-store-refusal-reply.js +3 -0
- package/dist/http/owner-access.d.ts +392 -67
- package/dist/http/owner-access.js +370 -35
- package/dist/http/principal-gate.d.ts +39 -89
- package/dist/http/principal-gate.js +26 -68
- package/dist/http/refusal-body.d.ts +35 -2
- package/dist/http/refusal-body.js +34 -0
- package/dist/http/request-guards.d.ts +9 -13
- package/dist/http/request-guards.js +34 -68
- package/dist/http/resume-composition.d.ts +37 -0
- package/dist/http/resume-composition.js +18 -0
- package/dist/http/resume-ctx-read.d.ts +46 -12
- package/dist/http/resume-ctx-read.js +31 -6
- package/dist/http/resume-legs.d.ts +54 -19
- package/dist/http/resume-legs.js +408 -196
- package/dist/http/retired-skill-manifest.d.ts +1 -1
- package/dist/http/route-ctx.d.ts +31 -32
- package/dist/http/routes/a2a-serve.d.ts +43 -5
- package/dist/http/routes/a2a-serve.js +60 -37
- package/dist/http/routes/admin-config-refresh.js +2 -2
- package/dist/http/routes/admin-drain.js +2 -2
- package/dist/http/routes/admin-memory-optout.js +4 -3
- package/dist/http/routes/adoption.d.ts +3 -0
- package/dist/http/routes/adoption.js +17 -10
- package/dist/http/routes/agents-roster.js +13 -7
- package/dist/http/routes/approvals-assistant.js +73 -67
- package/dist/http/routes/attachments.js +2 -2
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/background.js +9 -17
- package/dist/http/routes/capabilities.js +16 -19
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.d.ts +3 -3
- package/dist/http/routes/devices.js +4 -4
- package/dist/http/routes/diagnostics.d.ts +29 -3
- package/dist/http/routes/diagnostics.js +49 -18
- package/dist/http/routes/engine.js +2 -2
- package/dist/http/routes/fleet.js +5 -3
- package/dist/http/routes/images.js +10 -6
- package/dist/http/routes/leader.d.ts +7 -2
- package/dist/http/routes/leader.js +12 -3
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +7 -15
- package/dist/http/routes/memory-bundle.js +4 -7
- package/dist/http/routes/memory-compliance.js +4 -4
- package/dist/http/routes/memory-consolidation.js +6 -9
- package/dist/http/routes/memory-origin.d.ts +2 -0
- package/dist/http/routes/memory-origin.js +7 -8
- package/dist/http/routes/memory-policy.js +17 -12
- package/dist/http/routes/notify-wake.js +10 -19
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/principal-inbox.d.ts +4 -2
- package/dist/http/routes/principal-inbox.js +5 -4
- package/dist/http/routes/projects.d.ts +1 -1
- package/dist/http/routes/projects.js +3 -2
- package/dist/http/routes/retention-ops.js +6 -9
- package/dist/http/routes/rules.js +20 -5
- package/dist/http/routes/run-memory-capture.d.ts +2 -2
- package/dist/http/routes/run-memory-capture.js +6 -12
- package/dist/http/routes/run-permission-mode.d.ts +2 -2
- package/dist/http/routes/run-permission-mode.js +10 -17
- package/dist/http/routes/runs.js +155 -237
- package/dist/http/routes/session-memory-sync.d.ts +2 -2
- package/dist/http/routes/session-memory-sync.js +7 -13
- package/dist/http/routes/session-sync.d.ts +28 -7
- package/dist/http/routes/session-sync.js +63 -50
- package/dist/http/routes/sessions-list.d.ts +3 -3
- package/dist/http/routes/sessions-list.js +9 -9
- package/dist/http/routes/sessions.js +87 -124
- package/dist/http/routes/shared-memory.js +6 -6
- package/dist/http/routes/side-query.js +2 -2
- package/dist/http/routes/tasks.js +237 -187
- package/dist/http/routes/trace-usage.d.ts +0 -12
- package/dist/http/routes/trace-usage.js +40 -46
- package/dist/http/routes/workflows.d.ts +39 -4
- package/dist/http/routes/workflows.js +42 -14
- package/dist/http/run-concurrency-cap.d.ts +20 -12
- package/dist/http/run-concurrency-cap.js +39 -26
- package/dist/http/run-read-face.d.ts +3 -5
- package/dist/http/run-read-face.js +8 -13
- package/dist/http/send.d.ts +12 -3
- package/dist/http/send.js +42 -6
- package/dist/http/server.d.ts +43 -45
- package/dist/http/server.js +61 -11
- package/dist/http/sse-log.d.ts +17 -10
- package/dist/http/sse-log.js +7 -7
- package/dist/http/stored-body-replay.d.ts +12 -0
- package/dist/http/stored-body-replay.js +2 -2
- package/dist/http/submit-ctx.d.ts +17 -8
- package/dist/http/submit-ctx.js +8 -5
- package/dist/http/submit-replay.d.ts +19 -6
- package/dist/http/submit-replay.js +18 -6
- package/dist/http/sync-submit-body.d.ts +3 -4
- package/dist/http/sync-submit-body.js +4 -5
- package/dist/http/wire-types.d.ts +4 -3
- package/dist/identity-source.d.ts +36 -5
- package/dist/identity-source.js +27 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2 -0
- package/dist/key-resolver.d.ts +32 -0
- package/dist/key-resolver.js +23 -9
- package/dist/leader/diffup.js +2 -1
- package/dist/leader/endpoint.d.ts +26 -5
- package/dist/leader/endpoint.js +154 -14
- package/dist/leader/fanout.d.ts +3 -0
- package/dist/leader/fanout.js +78 -63
- package/dist/leader/leader.d.ts +16 -0
- package/dist/leader/leader.js +43 -3
- package/dist/leader/merge.d.ts +9 -1
- package/dist/leader/merge.js +16 -1
- package/dist/leader/repair-wire.js +1 -1
- package/dist/leader/wire.d.ts +36 -3
- package/dist/leader/wire.js +59 -18
- package/dist/leg-facts.d.ts +7 -2
- package/dist/leg-facts.js +1 -0
- package/dist/local-store-declaration.d.ts +54 -0
- package/dist/local-store-declaration.js +59 -0
- package/dist/lsp-evict.d.ts +6 -4
- package/dist/lsp-evict.js +2 -3
- package/dist/mcp-assertion-header.d.ts +1 -1
- package/dist/mcp-assertion-header.js +1 -1
- package/dist/memory-operator-faces.d.ts +5 -4
- package/dist/memory-operator-faces.js +1 -1
- package/dist/memory-project-layer.js +1 -1
- package/dist/memory-scope.d.ts +33 -6
- package/dist/memory-scope.js +68 -19
- package/dist/memory-store-refusal.d.ts +5 -2
- package/dist/memory-sync-client.d.ts +3 -2
- package/dist/memory-sync-client.js +8 -5
- package/dist/model-compat.d.ts +17 -8
- package/dist/model-compat.js +6 -2
- package/dist/model-context-window.d.ts +57 -0
- package/dist/model-context-window.js +21 -0
- package/dist/model-entry-headers.d.ts +46 -4
- package/dist/model-entry-headers.js +2 -2
- package/dist/model-entry-refusal.d.ts +40 -20
- package/dist/model-entry-refusal.js +57 -30
- package/dist/model-plane-face.d.ts +19 -11
- package/dist/model-plane-face.js +9 -1
- package/dist/model-plane-probe.d.ts +2 -0
- package/dist/model-plane-probe.js +17 -0
- package/dist/model-provider.d.ts +3 -3
- package/dist/model-reach-scope.d.ts +2 -1
- package/dist/model-route-endpoint.d.ts +9 -5
- package/dist/model-route-endpoint.js +29 -7
- package/dist/model-select.d.ts +16 -0
- package/dist/model-select.js +4 -0
- package/dist/mountinfo.d.ts +37 -0
- package/dist/mountinfo.js +47 -0
- package/dist/namespaced-rule-name.d.ts +23 -14
- package/dist/namespaced-rule-name.js +8 -11
- package/dist/net-address.d.ts +1 -1
- package/dist/observability/corrupt-read-seat.d.ts +4 -4
- package/dist/observability/corrupt-read-seat.js +5 -3
- package/dist/observability/fail-open.d.ts +72 -40
- package/dist/observability/fail-open.js +74 -40
- package/dist/observability/logger.d.ts +22 -1
- package/dist/observability/logger.js +89 -12
- package/dist/observability/metrics.js +4 -5
- package/dist/observability/otel-exporter.js +2 -1
- package/dist/observability/principal-context.d.ts +14 -7
- package/dist/observability/principal-context.js +8 -3
- package/dist/observability/run-terminal.d.ts +7 -1
- package/dist/observability/run-terminal.js +6 -2
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/orchestration/hardened-vm-runner.d.ts +1 -0
- package/dist/orchestration/hardened-vm-runner.js +11 -5
- package/dist/orchestration/hardened-vm-worker-runner.d.ts +0 -14
- package/dist/orchestration/hardened-vm-worker-runner.js +5 -0
- package/dist/orchestration/hardened-vm-worker.js +2 -1
- package/dist/orchestration/workflow-completion-inbox.d.ts +3 -3
- package/dist/orchestration/workflow-completion-inbox.js +3 -2
- package/dist/org-delivery-gate.d.ts +36 -10
- package/dist/org-delivery-gate.js +12 -8
- package/dist/outbound-dispatcher.d.ts +1 -1
- package/dist/outbound-dispatcher.js +6 -12
- package/dist/owner-brands.d.ts +81 -0
- package/dist/owner-brands.js +42 -0
- package/dist/owner-faces.d.ts +532 -0
- package/dist/owner-faces.js +126 -0
- package/dist/park-row-commit.d.ts +67 -0
- package/dist/park-row-commit.js +76 -0
- package/dist/parked-decide.d.ts +76 -12
- package/dist/parked-decide.js +152 -11
- package/dist/parked-revive-surface.d.ts +14 -4
- package/dist/parked-revive-surface.js +5 -4
- package/dist/peer-directory.d.ts +7 -9
- package/dist/peer-directory.js +3 -2
- package/dist/permission-rule-vocab.d.ts +53 -8
- package/dist/permission-rule-vocab.js +30 -2
- package/dist/plugins/adoption-log-sql.d.ts +3 -25
- package/dist/plugins/adoption-log-sql.js +23 -21
- package/dist/plugins/approval-ask-retired-delete-by-task-m50.d.ts +7 -0
- package/dist/plugins/approval-ask-retired-delete-by-task-m50.js +17 -0
- package/dist/plugins/approval-ask-store-file.d.ts +18 -7
- package/dist/plugins/approval-ask-store-file.js +37 -14
- package/dist/plugins/approval-ask-store-memory.d.ts +12 -4
- package/dist/plugins/approval-ask-store-memory.js +24 -10
- package/dist/plugins/approval-ask-store-sql.d.ts +40 -21
- package/dist/plugins/approval-ask-store-sql.js +44 -15
- 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 +14 -0
- package/dist/plugins/approval-exemption-skill-m46.js +21 -0
- package/dist/plugins/approval-exemption-store.d.ts +32 -2
- package/dist/plugins/approval-exemption-store.js +42 -19
- package/dist/plugins/approval-nonce-store.d.ts +39 -12
- package/dist/plugins/approval-nonce-store.js +72 -23
- package/dist/plugins/blob-backend.d.ts +2 -0
- package/dist/plugins/blob-backend.js +9 -6
- package/dist/plugins/caching-session-store.d.ts +13 -1
- package/dist/plugins/caching-session-store.js +43 -4
- package/dist/plugins/checkpoint-index-columns.d.ts +32 -5
- package/dist/plugins/checkpoint-index-columns.js +36 -1
- package/dist/plugins/checkpoint-store-face.d.ts +83 -10
- package/dist/plugins/checkpoint-store-face.js +18 -1
- package/dist/plugins/device-store-sql.js +1 -0
- package/dist/plugins/ensure-index.d.ts +13 -1
- package/dist/plugins/ensure-index.js +154 -21
- package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -18
- package/dist/plugins/ensure-schema-lock-policy.js +76 -9
- package/dist/plugins/file-run-store.d.ts +85 -32
- package/dist/plugins/file-run-store.js +177 -94
- package/dist/plugins/host-platform.d.ts +24 -3
- package/dist/plugins/host-platform.js +15 -1
- package/dist/plugins/image-bake-store-sql.js +2 -0
- package/dist/plugins/imported-layer-root-retirement.d.ts +2 -2
- package/dist/plugins/k8s-pod-reaper.d.ts +1 -3
- package/dist/plugins/k8s-pod-reaper.js +0 -1
- package/dist/plugins/leader-run-store-sql.d.ts +22 -0
- package/dist/plugins/leader-run-store-sql.js +34 -4
- package/dist/plugins/local-checkpoint-store.d.ts +62 -23
- package/dist/plugins/local-checkpoint-store.js +197 -77
- package/dist/plugins/local-data-dir-modes-m39.js +2 -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-docker-capacity.d.ts +93 -0
- package/dist/plugins/local-docker-capacity.js +194 -0
- package/dist/plugins/local-docker-reaper.d.ts +92 -0
- package/dist/plugins/local-docker-reaper.js +102 -0
- package/dist/plugins/local-engine-high-water.d.ts +29 -6
- package/dist/plugins/local-engine-high-water.js +27 -19
- package/dist/plugins/local-session-store.d.ts +458 -140
- package/dist/plugins/local-session-store.js +906 -292
- package/dist/plugins/local-session-window.d.ts +3 -2
- package/dist/plugins/local-session-window.js +3 -2
- package/dist/plugins/local-sidecar-quarantine.js +3 -2
- package/dist/plugins/local-task-attachment-store.d.ts +18 -1
- package/dist/plugins/local-task-attachment-store.js +22 -1
- package/dist/plugins/memory-embedder.js +9 -7
- package/dist/plugins/memory-engine-pg.d.ts +3 -2
- package/dist/plugins/memory-engine-pg.js +14 -5
- package/dist/plugins/memory-engine-sql-apply.d.ts +8 -4
- package/dist/plugins/memory-engine-sql-apply.js +6 -8
- package/dist/plugins/memory-engine-tidb.d.ts +4 -2
- package/dist/plugins/memory-engine-tidb.js +11 -2
- package/dist/plugins/memory-optout-grant-store-sql.d.ts +1 -1
- package/dist/plugins/memory-optout-grant-store-sql.js +3 -3
- package/dist/plugins/memory-run-store.d.ts +53 -36
- package/dist/plugins/memory-run-store.js +116 -88
- package/dist/plugins/one-time-migration-marker.d.ts +26 -0
- package/dist/plugins/one-time-migration-marker.js +13 -0
- package/dist/plugins/one-time-migrations.d.ts +214 -47
- package/dist/plugins/one-time-migrations.js +481 -135
- package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
- package/dist/plugins/org-delivery-quota-store.js +31 -15
- package/dist/plugins/permission-rule-store-file.d.ts +3 -3
- package/dist/plugins/permission-rule-store-sql.d.ts +5 -64
- package/dist/plugins/permission-rule-store-sql.js +11 -95
- package/dist/plugins/pg-pool.d.ts +2 -32
- package/dist/plugins/pg-pool.js +24 -17
- package/dist/plugins/remote-env-device.d.ts +3 -2
- package/dist/plugins/remote-env-e2b.d.ts +8 -32
- package/dist/plugins/remote-env-e2b.js +44 -32
- package/dist/plugins/remote-env-host.d.ts +51 -17
- package/dist/plugins/remote-env-host.js +111 -42
- package/dist/plugins/remote-env-k8s.d.ts +40 -45
- package/dist/plugins/remote-env-k8s.js +111 -60
- package/dist/plugins/remote-env-local-docker.d.ts +152 -15
- package/dist/plugins/remote-env-local-docker.js +352 -72
- package/dist/plugins/remote-scratchpad.js +4 -0
- package/dist/plugins/retention-deployment.d.ts +49 -17
- package/dist/plugins/retention-deployment.js +39 -8
- package/dist/plugins/run-preview-m45.d.ts +11 -0
- package/dist/plugins/run-preview-m45.js +19 -0
- package/dist/plugins/run-store-sql.d.ts +82 -75
- package/dist/plugins/run-store-sql.js +164 -125
- package/dist/plugins/s3-answer.d.ts +2 -1
- package/dist/plugins/sandbox-reaper.d.ts +26 -0
- package/dist/plugins/sandbox-reaper.js +2 -0
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +56 -0
- package/dist/plugins/scenario-prefix-switch-m42.js +56 -0
- package/dist/plugins/scheduler-support.d.ts +16 -1
- package/dist/plugins/scheduler-support.js +22 -2
- package/dist/plugins/schema-consistency.d.ts +131 -14
- package/dist/plugins/schema-consistency.js +388 -18
- package/dist/plugins/schema-drift-sentence.d.ts +10 -6
- package/dist/plugins/schema-drift-sentence.js +15 -7
- package/dist/plugins/schema-ensure-legs.d.ts +9 -0
- package/dist/plugins/schema-ensure-legs.js +1 -1
- package/dist/plugins/schema-indexes.js +3 -0
- package/dist/plugins/schema-live-columns.d.ts +14 -5
- package/dist/plugins/schema-live-columns.js +10 -10
- package/dist/plugins/send-user-file.js +2 -1
- package/dist/plugins/session-birth.d.ts +37 -0
- package/dist/plugins/session-birth.js +38 -0
- package/dist/plugins/session-epoch-anchor.d.ts +40 -12
- package/dist/plugins/session-epoch-anchor.js +33 -11
- package/dist/plugins/session-ext-table.d.ts +27 -3
- package/dist/plugins/session-ext-table.js +19 -6
- package/dist/plugins/session-fork.d.ts +15 -1
- package/dist/plugins/session-fork.js +3 -0
- package/dist/plugins/session-ownership.d.ts +1 -1
- package/dist/plugins/session-placement.d.ts +27 -20
- package/dist/plugins/session-placement.js +15 -12
- package/dist/plugins/session-row-sql.d.ts +12 -0
- package/dist/plugins/session-row-sql.js +3 -3
- package/dist/plugins/session-run-rollup.d.ts +29 -0
- package/dist/plugins/session-run-rollup.js +40 -0
- package/dist/plugins/session-store-sql.d.ts +38 -12
- package/dist/plugins/session-store-sql.js +130 -30
- package/dist/plugins/session-withdraw-sql.d.ts +36 -0
- package/dist/plugins/session-withdraw-sql.js +42 -0
- package/dist/plugins/shared-memory-store-sql.d.ts +0 -69
- package/dist/plugins/shared-memory-store-sql.js +2 -1
- package/dist/plugins/shell-sentinel-owner-m48.d.ts +42 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +9 -0
- package/dist/plugins/snapshot-bucket-presence.d.ts +2 -1
- package/dist/plugins/sql-driver.d.ts +1 -1
- package/dist/plugins/sql-driver.js +2 -1
- package/dist/plugins/sql-errors.d.ts +32 -5
- package/dist/plugins/sql-errors.js +55 -7
- package/dist/plugins/sql-json-column.d.ts +8 -7
- package/dist/plugins/sql-json-column.js +10 -6
- package/dist/plugins/stop-then-start-sentence.d.ts +16 -0
- package/dist/plugins/stop-then-start-sentence.js +7 -0
- package/dist/plugins/store-backend.d.ts +99 -16
- package/dist/plugins/store-backend.js +230 -65
- package/dist/plugins/store-contracts.d.ts +123 -33
- package/dist/plugins/store-contracts.js +38 -1
- package/dist/plugins/store-fault.d.ts +28 -2
- package/dist/plugins/store-fault.js +20 -2
- package/dist/plugins/task-attachment-store.d.ts +15 -3
- package/dist/plugins/task-attachment-store.js +22 -9
- package/dist/plugins/tidb-pool.d.ts +11 -6
- package/dist/plugins/tidb-pool.js +39 -18
- package/dist/plugins/web-search.js +5 -3
- package/dist/plugins/workflow-run-store-sql.d.ts +6 -1
- package/dist/plugins/workflow-run-store-sql.js +11 -5
- package/dist/plugins/workspace-custody.d.ts +44 -0
- package/dist/plugins/workspace-custody.js +47 -0
- package/dist/principal-jwt.d.ts +4 -4
- package/dist/principal-jwt.js +20 -5
- package/dist/principal-shape.d.ts +41 -0
- package/dist/principal-shape.js +19 -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 +13 -23
- package/dist/question.js +21 -39
- 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/request-declaration-refusal.d.ts +35 -12
- package/dist/request-declaration-refusal.js +21 -9
- package/dist/request-form.d.ts +58 -0
- package/dist/request-form.js +72 -0
- package/dist/request-image-urls.d.ts +8 -2
- package/dist/request-image-urls.js +2 -1
- package/dist/request-images.d.ts +20 -0
- package/dist/request-images.js +59 -0
- package/dist/request-key-closure.d.ts +6 -7
- package/dist/request-key-closure.js +15 -2
- package/dist/resource-suspend.d.ts +7 -16
- package/dist/resource-suspend.js +1 -1
- package/dist/retired-name-host-notice.d.ts +21 -0
- package/dist/retired-name-host-notice.js +12 -0
- package/dist/rule-entry-list.d.ts +2 -2
- package/dist/rule-entry-list.js +3 -4
- package/dist/rule-issue-reading.d.ts +58 -0
- package/dist/rule-issue-reading.js +14 -0
- package/dist/rules-consent.d.ts +5 -3
- package/dist/rules-consent.js +1 -0
- package/dist/run-acceptance.d.ts +3 -1
- package/dist/run-acceptance.js +3 -0
- package/dist/run-cancel-card.d.ts +28 -0
- package/dist/run-cancel-card.js +19 -0
- package/dist/run-cancel-context.d.ts +10 -0
- package/dist/run-cancel-context.js +1 -0
- package/dist/run-local.d.ts +14 -6
- package/dist/run-local.js +117 -90
- package/dist/run-stale-default.d.ts +7 -0
- package/dist/run-stale-default.js +2 -0
- package/dist/runs.d.ts +56 -21
- package/dist/runs.js +73 -43
- package/dist/runtime-caps-resolver.d.ts +21 -6
- package/dist/runtime-caps-resolver.js +17 -4
- package/dist/runtime-governance.d.ts +2 -2
- package/dist/runtime-governance.js +5 -3
- package/dist/sealed-key-layout.d.ts +12 -5
- package/dist/sealed-key-layout.js +5 -0
- package/dist/sealed-key.d.ts +12 -2
- package/dist/sealed-key.js +115 -27
- package/dist/security.d.ts +128 -158
- package/dist/security.js +163 -59
- package/dist/sema-config-dir.d.ts +20 -0
- package/dist/sema-config-dir.js +25 -0
- package/dist/server-secret-env.d.ts +55 -25
- package/dist/server-secret-env.js +75 -22
- package/dist/session-agent.d.ts +3 -2
- package/dist/session-children-retire.d.ts +13 -8
- package/dist/session-children-retire.js +9 -7
- package/dist/session-deletion.d.ts +88 -0
- package/dist/session-deletion.js +8 -0
- package/dist/session-erase.d.ts +145 -0
- package/dist/session-erase.js +115 -0
- package/dist/session-error-wire.d.ts +5 -5
- package/dist/session-error-wire.js +1 -1
- package/dist/session-incarnation.d.ts +52 -5
- package/dist/session-incarnation.js +19 -2
- package/dist/session-policy-wire.d.ts +6 -3
- package/dist/session-policy-wire.js +11 -1
- package/dist/session-resident-background.d.ts +0 -71
- package/dist/session-resident-background.js +4 -3
- package/dist/session-row.d.ts +2 -1
- package/dist/session-rules-seat.d.ts +12 -0
- package/dist/session-rules-seat.js +19 -0
- package/dist/session-titler.d.ts +7 -15
- package/dist/session-titler.js +1 -1
- package/dist/session-workspace.d.ts +3 -3
- package/dist/spec-fields.d.ts +57 -3
- package/dist/spec-fields.js +72 -51
- package/dist/store-admission.d.ts +33 -0
- package/dist/store-admission.js +49 -0
- package/dist/store-posture.d.ts +141 -20
- package/dist/store-posture.js +205 -3
- package/dist/stored-request-hooks-m20.js +2 -2
- package/dist/stores-sql/background-agent-store-sql.d.ts +11 -2
- package/dist/stores-sql/background-agent-store-sql.js +73 -20
- package/dist/stores-sql/checkpoint-store-sql.d.ts +34 -29
- package/dist/stores-sql/checkpoint-store-sql.js +78 -49
- 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/mailbox-store-sql.d.ts +7 -4
- package/dist/stores-sql/mailbox-store-sql.js +31 -32
- package/dist/stores-sql/pg-session-storage.d.ts +7 -5
- package/dist/stores-sql/pg-session-storage.js +54 -46
- package/dist/stores-sql/retention-store-sql.d.ts +87 -19
- package/dist/stores-sql/retention-store-sql.js +92 -27
- package/dist/stores-sql/session-policy-store-sql.d.ts +32 -10
- package/dist/stores-sql/session-policy-store-sql.js +44 -36
- package/dist/stores-sql/session-write-hooks.d.ts +12 -6
- package/dist/stores-sql/tidb-session-storage.d.ts +4 -4
- package/dist/stores-sql/tidb-session-storage.js +13 -8
- package/dist/stores-sql/tidb-session-store.d.ts +36 -17
- package/dist/stores-sql/tidb-session-store.js +69 -39
- 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/stores-sql/windowed-session-storage.d.ts +5 -0
- package/dist/stores-sql/windowed-session-storage.js +9 -0
- package/dist/submission-exit.d.ts +50 -0
- package/dist/submission-exit.js +108 -0
- package/dist/task-a2a.d.ts +3 -8
- package/dist/task-a2a.js +28 -30
- package/dist/task-cwd.d.ts +43 -7
- package/dist/task-cwd.js +11 -0
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +4 -4
- package/dist/task-settings.d.ts +14 -10
- package/dist/task-settings.js +19 -7
- package/dist/terminal.d.ts +27 -43
- package/dist/terminal.js +49 -14
- package/dist/tool-approval.d.ts +173 -163
- package/dist/tool-approval.js +247 -232
- package/dist/trace/core-keyset-guard.d.ts +13 -6
- package/dist/trace/core-vocab-wire.d.ts +95 -0
- package/dist/trace/core-vocab-wire.js +15 -0
- package/dist/trace/engine-notice-wire.d.ts +24 -21
- package/dist/trace/engine-notice-wire.js +7 -3
- package/dist/trace/exit-seat.d.ts +30 -4
- package/dist/trace/exit-seat.js +40 -36
- package/dist/trace/extension-call-face.d.ts +3 -2
- package/dist/trace/extension-call-face.js +3 -1
- package/dist/trace/ledger-events.d.ts +4 -7
- package/dist/trace/ledger-sink.d.ts +4 -31
- package/dist/trace/ledger-sink.js +0 -11
- package/dist/trace/model-segment.d.ts +5 -5
- package/dist/trace/model-segment.js +5 -5
- package/dist/trace/project.d.ts +59 -44
- package/dist/trace/project.js +60 -26
- package/dist/trace/redact.d.ts +135 -27
- package/dist/trace/redact.js +884 -260
- package/dist/trace/self-minted-wire.d.ts +567 -20
- package/dist/trace/self-minted-wire.js +205 -24
- package/dist/trace/wire-projection-faces.d.ts +5 -6
- package/dist/trace/wire-projection-faces.js +2 -2
- package/dist/upstream-body.d.ts +23 -0
- package/dist/upstream-body.js +16 -0
- package/dist/url-refusal.d.ts +3 -3
- package/dist/url-refusal.js +11 -4
- package/dist/user-authored-text.d.ts +1 -1
- package/dist/user-input-ledger.d.ts +7 -8
- package/dist/user-input-ledger.js +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +6 -3
- package/dist/web-admin-client/apply-effective.js +33 -23
- package/dist/web-admin-client/apply-ledger.d.ts +16 -7
- package/dist/web-admin-client/apply-ledger.js +5 -2
- package/dist/web-admin-client/center-request.d.ts +2 -2
- package/dist/web-admin-client/center-request.js +15 -15
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.js +1 -1
- package/dist/web-admin-client/entry-metadata.d.ts +8 -0
- package/dist/web-admin-client/entry-metadata.js +13 -0
- package/dist/web-admin-client/http-client.d.ts +1 -1
- package/dist/web-admin-client/http-client.js +23 -4
- package/dist/web-admin-client/mcp-revocation.d.ts +1 -1
- package/dist/web-admin-client/mcp-revocation.js +2 -1
- package/dist/web-admin-client/read-warnings.d.ts +1 -0
- package/dist/web-admin-client/read-warnings.js +1 -0
- package/dist/web-admin-client/restart-signal.js +8 -4
- package/dist/web-admin-client/skills-mcp.d.ts +2 -2
- package/dist/web-admin-client/types.d.ts +1 -2
- package/dist/workspace-space.d.ts +3 -2
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +4 -4
- package/docs/error-text-lexicon.json +317 -0
- package/package.json +8 -3
- package/scripts/drain-check-local.mjs +118 -147
- package/scripts/drain-check.mysql.sql +22 -2
- package/scripts/drain-check.pg.sql +22 -2
- package/scripts/embed-minimal.mjs +183 -0
- package/wire-changes/server@7.148.0.json +1517 -0
- package/wire-changes/server@7.149.0.json +372 -0
- package/dist/http/memory-control-plane-corrupt-reply.d.ts +0 -25
- package/dist/http/memory-control-plane-corrupt-reply.js +0 -19
- package/dist/http/memory-layer-reply.d.ts +0 -30
- package/dist/http/memory-layer-reply.js +0 -24
- package/dist/lsp/e2b-bridge.d.ts +0 -57
- package/dist/lsp/e2b-bridge.js +0 -139
- package/dist/lsp/e2b-manager.d.ts +0 -93
- package/dist/lsp/e2b-manager.js +0 -178
- package/dist/lsp/lsp-frames.d.ts +0 -14
- package/dist/lsp/lsp-frames.js +0 -25
- package/dist/lsp/manager.d.ts +0 -129
- package/dist/lsp/manager.js +0 -127
- package/dist/lsp/types.d.ts +0 -12
- package/dist/lsp/types.js +0 -2
- package/dist/lsp/ws-transport.d.ts +0 -40
- package/dist/lsp/ws-transport.js +0 -210
- package/dist/plain-string-record.js +0 -70
package/dist/http/resume-legs.js
CHANGED
|
@@ -1,41 +1,50 @@
|
|
|
1
1
|
import { redactErrorMessage, redactHead } from "../observability/run-terminal.js";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
|
-
import { uuidv7, resumeWithVerification, CheckpointError, judgeCheckpointRow, defaultTaskRegistry, taskNotificationDedupKey, validatePendingSteer, GLOBAL_USAGE_KEY } from "@sema-agent/core";
|
|
4
|
-
import { decideParkedAgent, denyWorkflowParkForked, denyWorkflowParksUnreadable, findParkOrigin, heldWorkflowParkDecisions, planWorkflowParkedDecide } from "../parked-decide.js";
|
|
3
|
+
import { uuidv7, resumeWithVerification, resumeCascade, CheckpointError, judgeCheckpointRow, defaultTaskRegistry, taskNotificationDedupKey, validatePendingSteer, GLOBAL_USAGE_KEY } from "@sema-agent/core";
|
|
4
|
+
import { decideParkedAgent, deliverToHoldingRun, denyWorkflowParkForked, denyWorkflowParksUnreadable, findParkOrigin, heldWorkflowParkDecisions, planWorkflowParkedDecide } from "../parked-decide.js";
|
|
5
5
|
import { parkDecisionFingerprint } from "../orchestration/workflow-park-decision.js";
|
|
6
6
|
import { headReadOf } from "../session-incarnation.js";
|
|
7
7
|
import { createSessionWorkspaceRecorder, sessionWorkspaceStoreOf } from "../session-workspace.js";
|
|
8
8
|
const DELIVERY_NOT_RECORDED = "workflow park decide: this delivery no longer holds the host session (its claim was released) — the decision was not recorded and this delivery was not started";
|
|
9
|
-
import { HttpError, decodeCheckpointScope, CHECKPOINT_PUBLIC_SCOPE } from "../security.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { HttpError, checkpointPartsOf, decodeCheckpointScope, scopeCellOf, CHECKPOINT_PUBLIC_SCOPE } from "../security.js";
|
|
10
|
+
import { keyAdmits } from "../owner-faces.js";
|
|
11
|
+
import { personOf } from "../owner-brands.js";
|
|
12
|
+
import { recoveredSubject } from "../owner-faces.js";
|
|
13
|
+
import { beatRunHeartbeat, graftParkToolCallId, heldParkOf, parkToolCallId, TurnAnchorCapture, HEARTBEAT_MS, markChildrenStoppedByUserOnAbort, voidHeldParkCard } from "../runs.js";
|
|
14
|
+
import { commitParkRow } from "../park-row-commit.js";
|
|
15
|
+
import { atHostBoundary, failureCodeOf, nestedPauseOf, sealResultForExit, outwardPlane, outwardThrownMessage } from "../terminal.js";
|
|
12
16
|
import { voidVerifierPauseCard } from "../verifier-pause-card.js";
|
|
13
|
-
import { buildCancelledLedgerRow, CARD_SETTLED_BY_CANCEL_MESSAGE, createRunAbort, mintCancelledResult, withCardSettledByCancelMessage } from "../run-cancel-context.js";
|
|
14
|
-
import { isTerminalRunStatus } from "../plugins/store-contracts.js";
|
|
17
|
+
import { buildCancelledLedgerRow, CANCELLED_CODE, CARD_SETTLED_BY_CANCEL_MESSAGE, createRunAbort, mintCancelledResult, withCardSettledByCancelMessage } from "../run-cancel-context.js";
|
|
18
|
+
import { isTerminalRunStatus, runProvenElsewhere } from "../plugins/store-contracts.js";
|
|
15
19
|
import { readTurnActivityMs, recordTurnActivity } from "../turn-activity.js";
|
|
16
20
|
import { recordResumeResourceWindow } from "../resource-window.js";
|
|
17
21
|
import { emitPendingWorkflowCompletions, taskNotificationInboxEntry, taskNotificationStreamKeyOf, NotifiedKeys } from "../orchestration/workflow-completion-inbox.js";
|
|
18
22
|
import { fleetRunPublisher, fleetRunLabels, fleetRunResiduals } from "../fleet/fleet-bus.js";
|
|
19
23
|
import { defaultSubagentTailBus } from "../fleet/subagent-tail-bus.js";
|
|
20
24
|
import { currentApprovalGateToken, currentGateFacesOf, sightsCurrentGate } from "../approval-gate-currency.js";
|
|
21
|
-
import { approverFacingArgs,
|
|
25
|
+
import { approverFacingArgs, declaredApprovalFrameFamilies, parkRowStandingAnswerFacts, resolveApprovalLeg, resolveStreamApprovalGate, standingAnswerDurablyRecordable } from "../tool-approval.js";
|
|
26
|
+
import { createHitlTransport } from "../hitl-delivery.js";
|
|
22
27
|
import { buildCheckpointAnchorHash } from "../approval-ask-audit-store.js";
|
|
23
28
|
import { APPROVAL_ENDING_CAUSES } from "../approval-deny-reasons.js";
|
|
24
29
|
import { serviceVersion } from "../service-version.js";
|
|
25
30
|
import { TERMINAL_PARK_GATE_KINDS, UnreadableCheckpointRowError } from "../plugins/checkpoint-store-face.js";
|
|
26
|
-
import {
|
|
31
|
+
import { cancelSettlesCard } from "../run-cancel-card.js";
|
|
32
|
+
import { CARD_EXPIRE_OUTCOME, expireCardUnderStoredScope } from "../card-settle-stored-scope.js";
|
|
33
|
+
import { withSubject } from "../observability/principal-context.js";
|
|
27
34
|
import { withModelReachScope } from "../model-reach-scope.js";
|
|
35
|
+
import { approvalLegOriginOf } from "../approval-leg-origin.js";
|
|
28
36
|
import { legFactsOf } from "../leg-facts.js";
|
|
37
|
+
import { compositionLegRoot } from "../task-cwd.js";
|
|
29
38
|
import { createInstructionSelectionLeg } from "../instruction-selection.js";
|
|
30
39
|
import { modelTextEventData, appendParkRow, turnEndEventData, contextUsageEventData, toolStartEventData, toolEndEventData, taskProgressEventData, taskStartedEventData, taskNotificationEventData, compactedEventData, diagnosticsEventData, brainStatusEventData, steeringInjectedEventData, compactionOutcomeEventData, compactionStartedEventData, workspaceChangedEventData, wiringManifestEventData, toolRosterDeltaEventData, toolDisclosureEventData, humanInputEventData, appendModelUsageDelta, attachModelUsage, createPromptManifestSeat } from "../trace/project.js";
|
|
31
40
|
import { redactSecrets } from "../trace/redact.js";
|
|
32
41
|
import { buildRunObjectivePreview } from "../user-authored-text.js";
|
|
33
42
|
import { createForwardAppendFailedNote, createLedgerSink, createSerialLedgerAppend } from "../trace/ledger-sink.js";
|
|
34
|
-
import { registerEngineNoticeLeg } from "../trace/engine-notice-wire.js";
|
|
43
|
+
import { defaultEngineNoticeRouter, registerEngineNoticeLeg } from "../trace/engine-notice-wire.js";
|
|
35
44
|
import { blockText, reasoningDeltaBytes, reasoningSegmentEventId } from "../trace/model-segment.js";
|
|
36
45
|
import { errorText } from "../observability/err-text.js";
|
|
37
46
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
38
|
-
import {
|
|
47
|
+
import { resumeCompositionOf } from "./resume-composition.js";
|
|
39
48
|
import { planReviewDecisionExitsPlan, storedBodyPermissionMode } from "../task-settings.js";
|
|
40
49
|
import { acceptedResumingReceipt, acceptedTaskIdOf } from "./route-ctx.js";
|
|
41
50
|
import { heldFor } from "../peer-seat.js";
|
|
@@ -46,15 +55,16 @@ import { createSessionsLocal } from "./routes/sessions.js";
|
|
|
46
55
|
import { createSessionSyncLocal } from "./routes/session-sync.js";
|
|
47
56
|
import { createImagesLocal } from "./routes/images.js";
|
|
48
57
|
import { createCapabilitiesLocal } from "./routes/capabilities.js";
|
|
49
|
-
import {
|
|
58
|
+
import { gatedSubject, explicitOperatorOk, runIdentityOf } from "./principal-gate.js";
|
|
50
59
|
import { buildActiveRunConflict, resumeEntryForGate } from "./active-run-conflict.js";
|
|
51
|
-
import {
|
|
60
|
+
import { refusalAfterLostClaim } from "./claim-heartbeat.js";
|
|
61
|
+
import { CONTINUATION_CLAIM_FACE, ClaimFaultAnswer, commitExecutionContext, faultedAnswerOf, isRootSessionGoneError, resolveBeforeClaim, rootSessionAbsentAnswer, stampSpecRoot, withdrawClaim } from "./execution-context.js";
|
|
52
62
|
import { timeClaim } from "./claim-latency.js";
|
|
53
63
|
import { commitSessionInheritEnv } from "./session-inherit-env.js";
|
|
54
64
|
import { ASK_USER_QUESTION_TOOL_NAME, isApprovalGateKind, isEngineQuestionRow } from "../approval-content-kind.js";
|
|
55
65
|
import { deploymentListAsks } from "../approval.js";
|
|
56
66
|
import { isParkLedgerEventType } from "../trace/ledger-events.js";
|
|
57
|
-
import { readResumeCtx, resumeCtxCorruptAnswer, resumeCtxUnsealableAnswer } from "./resume-ctx-read.js";
|
|
67
|
+
import { readResumeCtx, resumeCtxCorruptAnswer, resumeCtxUnreadableAnswer, resumeCtxUnsealableAnswer, resumeStoreFailureOf } from "./resume-ctx-read.js";
|
|
58
68
|
import { objectiveWithheldIn } from "./submit-ctx.js";
|
|
59
69
|
import { buildCheckpointVersionKeys, resumeAssemblyRefusalAnswer, resumeRefusalWithCard, sealCheckpointCtx, storedBodyReplayAnswer, storedBodyReplayLogFields, withPermissionModeRewritten } from "./checkpoint-ctx.js";
|
|
60
70
|
import { refusalBody, resumeRefusalFacts } from "./refusal-body.js";
|
|
@@ -62,8 +72,12 @@ import { storedBodyReplayRefusal } from "./stored-body-replay.js";
|
|
|
62
72
|
import { restateResumeCtx } from "./resume-restatement.js";
|
|
63
73
|
import { httpErrorRefusal } from "./send.js";
|
|
64
74
|
import { createRunAcceptance } from "../run-acceptance.js";
|
|
75
|
+
import { createSubmissionSeat } from "../submission-exit.js";
|
|
65
76
|
import { fieldConflictFacts } from "../field-conflict.js";
|
|
66
77
|
import { createSessionNotifyDoor } from "../session-notify-door.js";
|
|
78
|
+
function compositionUnlinkedAnswer() {
|
|
79
|
+
return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context does not match this card — the run is a cascade but the card records no ladder rung, so the ladder cannot be continued" }) };
|
|
80
|
+
}
|
|
67
81
|
function legMayHaveReopenedCheckpoint(r) {
|
|
68
82
|
return r.terminal.kind === "failed" && nestedPauseOf(r.terminal) === undefined;
|
|
69
83
|
}
|
|
@@ -196,6 +210,9 @@ function decisionRefusalCauseOf(e, gate) {
|
|
|
196
210
|
function notResumableAnswer() {
|
|
197
211
|
return { status: 409, body: refusalBody({ errorCode: "conflict.not_resumable", message: "run is not in a resumable (suspended) state (already resumed, decided, or expired)" }) };
|
|
198
212
|
}
|
|
213
|
+
function resumeClaimFaultAnswerOf(e) {
|
|
214
|
+
return faultedAnswerOf(e, CONTINUATION_CLAIM_FACE.faulted);
|
|
215
|
+
}
|
|
199
216
|
function approvalStaleAnswer(facts) {
|
|
200
217
|
return {
|
|
201
218
|
status: 409,
|
|
@@ -209,9 +226,42 @@ function approvalStaleAnswer(facts) {
|
|
|
209
226
|
}),
|
|
210
227
|
};
|
|
211
228
|
}
|
|
212
|
-
function rowRefusalAnswer(verdict, diagnostic, ctx) {
|
|
229
|
+
function rowRefusalAnswer(verdict, diagnostic, ctx, wayOut) {
|
|
213
230
|
const refusal = new CheckpointError(verdict.code, diagnostic === undefined ? verdict.sentence : `${verdict.sentence} Diagnostic: ${diagnostic}`, verdict.reason === undefined ? undefined : { reason: verdict.reason });
|
|
214
|
-
return checkpointRefusalAnswer(refusal, { gate: "policy_ask", retriable: resumeRefusalDisposition(refusal) === "retriable", versionKeys: refusalVersionKeys(refusal, ctx) });
|
|
231
|
+
return checkpointRefusalAnswer(refusal, { gate: "policy_ask", retriable: resumeRefusalDisposition(refusal) === "retriable", versionKeys: refusalVersionKeys(refusal, ctx), ...(wayOut !== undefined ? { wayOut } : {}) });
|
|
232
|
+
}
|
|
233
|
+
export async function rowWayOutOf(seat, kind) {
|
|
234
|
+
switch (kind) {
|
|
235
|
+
case "lacking":
|
|
236
|
+
return "newer_worker";
|
|
237
|
+
case "damaged":
|
|
238
|
+
try {
|
|
239
|
+
return (await cancelSettlesCard(seat.cs, seat.runs, seat.token)) ? "cancel_run" : undefined;
|
|
240
|
+
}
|
|
241
|
+
catch (e) {
|
|
242
|
+
seat.logger?.warn?.("row_way_out_probe_failed", { note: "the store could not answer whether cancel would settle this card — no wayOut offered", err: errorText(e) });
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
default: {
|
|
246
|
+
const unhandled = kind;
|
|
247
|
+
throw new Error(`row verdict ${String(unhandled)} has no way out`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
async function loadedRowWayOut(cp, seat) {
|
|
252
|
+
const verdict = judgeCheckpointRow(cp);
|
|
253
|
+
return verdict.kind === "ok" ? undefined : rowWayOutOf(seat, verdict.kind);
|
|
254
|
+
}
|
|
255
|
+
async function loadedRowRefusal(cp, seat, writer) {
|
|
256
|
+
const verdict = judgeCheckpointRow(cp);
|
|
257
|
+
if (verdict.kind === "ok")
|
|
258
|
+
return undefined;
|
|
259
|
+
return rowRefusalAnswer(verdict, undefined, verdict.code === "checkpoint.unsupported_version" ? await writer() : {}, await rowWayOutOf(seat, verdict.kind));
|
|
260
|
+
}
|
|
261
|
+
export async function rowReadRefusalAnswer(e, seat) {
|
|
262
|
+
if (e instanceof UnreadableCheckpointRowError && e.rowVerdict.kind !== "ok")
|
|
263
|
+
return rowRefusalAnswer(e.rowVerdict, errorText(e), {}, seat === undefined ? undefined : await rowWayOutOf(seat, e.rowVerdict.kind));
|
|
264
|
+
return { status: 409, body: refusalBody({ errorCode: "conflict.checkpoint_unreadable", message: errorText(e) }) };
|
|
215
265
|
}
|
|
216
266
|
function refusalVersionKeys(e, ctx) {
|
|
217
267
|
return e.code === "checkpoint.unsupported_version" ? buildCheckpointVersionKeys(ctx.writerVersion, serviceVersion()) : {};
|
|
@@ -239,6 +289,7 @@ export function checkpointRefusalAnswer(e, at) {
|
|
|
239
289
|
: {}),
|
|
240
290
|
...at.versionKeys,
|
|
241
291
|
...(e.code === "resume.constraint_rejected" ? acceptableFormFacts(detail) : {}),
|
|
292
|
+
...(at.wayOut !== undefined ? { wayOut: at.wayOut } : {}),
|
|
242
293
|
},
|
|
243
294
|
}),
|
|
244
295
|
}, at.retriable);
|
|
@@ -249,9 +300,9 @@ export function decidedActionOf(binding) {
|
|
|
249
300
|
return missingKeys.length === 0 ? { action: { boundCallId: boundCallId, boundInputHash: boundInputHash } } : { missingKeys };
|
|
250
301
|
}
|
|
251
302
|
export function createResumeLegs(ctx) {
|
|
252
|
-
const { deps, runnerFor, idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters, readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, admitRun, safeDecode,
|
|
303
|
+
const { deps, runnerFor, idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters, readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, admitRun, safeDecode, prepareSpec, finalizeTaskResult, ownerCostQuotaDenied, ownerFleetLeaseDenied, usageWindowDenialFor } = ctx;
|
|
253
304
|
const ctxOpening = (sessionId) => ({ sessionId, opener: deps.checkpointCtxSealing });
|
|
254
|
-
const resumeFleetScope = (req, auth) => req ? (
|
|
305
|
+
const resumeFleetScope = (req, auth) => req ? (gatedSubject(req, deps.config) ?? "default") : (auth.subject ?? "default");
|
|
255
306
|
function createRememberIntent(sessionId, remember) {
|
|
256
307
|
let pending;
|
|
257
308
|
return {
|
|
@@ -302,8 +353,7 @@ export function createResumeLegs(ctx) {
|
|
|
302
353
|
return null;
|
|
303
354
|
});
|
|
304
355
|
const curPa = cur?.pendingAction;
|
|
305
|
-
const
|
|
306
|
-
const scopeOk = cur !== null && (decider.explicitOperator || curOwner === undefined || curOwner === decider.principal);
|
|
356
|
+
const scopeOk = cur != null && (await decisionRowAdmits(cs, token, decider, cur.scope));
|
|
307
357
|
if (cur && cur.sessionId === sessionId && !scopeOk) {
|
|
308
358
|
deps.logger?.info?.("approval_decide_no_pending", { sessionId, staleTokenEchoed: true, foreignCurrentSuppressed: true });
|
|
309
359
|
return { status: 404, body: refusalBody({ errorCode: "not_found.approval", message: "approval not found" }) };
|
|
@@ -323,10 +373,23 @@ export function createResumeLegs(ctx) {
|
|
|
323
373
|
return { status: 404, body: refusalBody({ errorCode: "not_found.approval", message: "approval not found" }) };
|
|
324
374
|
}
|
|
325
375
|
const cpPromise = cs.get(token);
|
|
326
|
-
const
|
|
376
|
+
const runSessionPromise = cs.hostSessionOfCard(token).then((id) => (typeof id === "string" ? { kind: "owned", id } : { kind: "unowned" }), (e) => ({ kind: "failed", failure: resumeStoreFailureOf(e) }));
|
|
377
|
+
const runCtxOf = async () => {
|
|
378
|
+
const owner = await runSessionPromise;
|
|
379
|
+
if (owner.kind === "unowned")
|
|
380
|
+
return undefined;
|
|
381
|
+
const read = owner.kind === "failed" ? owner.failure : await readResumeCtx(cs.getCtx(owner.id), ctxOpening(owner.id));
|
|
382
|
+
if (read.kind === "corrupt")
|
|
383
|
+
return { refusal: resumeCtxCorruptAnswer(read.where) };
|
|
384
|
+
if (read.kind === "unsealable")
|
|
385
|
+
return { refusal: resumeCtxUnsealableAnswer(read) };
|
|
386
|
+
if (read.kind === "unreadable")
|
|
387
|
+
return { refusal: resumeCtxUnreadableAnswer() };
|
|
388
|
+
return owner.kind === "owned" ? { runSessionId: owner.id, ctx: read.kind === "ok" ? read.ctx : null } : undefined;
|
|
389
|
+
};
|
|
390
|
+
const ctxPromise = runCtxOf();
|
|
327
391
|
void ctxPromise.catch(() => { });
|
|
328
392
|
const noApproval = { status: 404, body: refusalBody({ errorCode: "not_found.approval", message: "approval not found" }) };
|
|
329
|
-
const rowOwnRefusal = async (verdict, diagnostic) => rowRefusalAnswer(verdict, diagnostic, verdict.code === "checkpoint.unsupported_version" ? ((await ctxPromise.catch(() => null)) ?? {}) : {});
|
|
330
393
|
let cp;
|
|
331
394
|
try {
|
|
332
395
|
cp = await cpPromise;
|
|
@@ -337,31 +400,28 @@ export function createResumeLegs(ctx) {
|
|
|
337
400
|
deps.logger?.warn?.("approval_decide_unreadable_row_withheld", { sessionId, note: "row unreadable and the caller's ownership of THAT token is unproven — folded into the uniform 404" });
|
|
338
401
|
return noApproval;
|
|
339
402
|
}
|
|
340
|
-
|
|
341
|
-
return rowOwnRefusal(e.rowVerdict, errorText(e));
|
|
342
|
-
return { status: 409, body: refusalBody({ errorCode: "conflict.checkpoint_unreadable", message: errorText(e) }) };
|
|
403
|
+
return rowReadRefusalAnswer(e, { cs, runs: deps.runStore, token, logger: deps.logger });
|
|
343
404
|
}
|
|
344
405
|
if (!cp) {
|
|
345
406
|
if (!(await mayDiscloseRowError(cs, token, decider)))
|
|
346
407
|
return noApproval;
|
|
347
408
|
return { status: 404, body: refusalBody({ errorCode: "not_found.checkpoint", message: "checkpoint not found" }) };
|
|
348
409
|
}
|
|
349
|
-
if (
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
deps.logger?.warn?.("approval_decide_row_scope_mismatch", { sessionId, note: "loaded pending row is foreign to the verified caller — TOCTOU fold" });
|
|
353
|
-
return { status: 404, body: refusalBody({ errorCode: "not_found.approval", message: "approval not found" }) };
|
|
354
|
-
}
|
|
410
|
+
if (!(await decisionRowAdmits(cs, token, decider, cp.scope))) {
|
|
411
|
+
deps.logger?.warn?.("approval_decide_row_scope_mismatch", { sessionId, note: "loaded pending row is foreign to the verified caller — TOCTOU fold" });
|
|
412
|
+
return { status: 404, body: refusalBody({ errorCode: "not_found.approval", message: "approval not found" }) };
|
|
355
413
|
}
|
|
414
|
+
const rowOwn = await loadedRowRefusal(cp, { cs, runs: deps.runStore, token, logger: deps.logger }, () => ctxPromise.then((r) => (r !== undefined && "ctx" in r ? (r.ctx ?? {}) : {}), () => ({})));
|
|
415
|
+
if (rowOwn !== undefined)
|
|
416
|
+
return rowOwn;
|
|
356
417
|
const decideGateKind = cp.gate?.kind;
|
|
357
418
|
if (!isApprovalGateKind(decideGateKind)) {
|
|
358
|
-
const verdict = judgeCheckpointRow(cp);
|
|
359
|
-
if (verdict.kind !== "ok")
|
|
360
|
-
return rowOwnRefusal(verdict);
|
|
361
419
|
if (typeof decideGateKind !== "string" || decideGateKind === "") {
|
|
362
420
|
return { status: 409, body: refusalBody({ errorCode: "gate_not_tool_approval", message: "task is suspended on a gate whose kind this engine cannot read, so it cannot say which endpoint resolves it" }) };
|
|
363
421
|
}
|
|
364
|
-
const
|
|
422
|
+
const ownerForPath = await runSessionPromise;
|
|
423
|
+
const runSessionForPath = ownerForPath.kind === "owned" ? ownerForPath.id : undefined;
|
|
424
|
+
const activeForPath = typeof runSessionForPath === "string" ? await deps.runStore?.getActiveTaskId(runSessionForPath).catch(() => undefined) : undefined;
|
|
365
425
|
const gnPath = activeForPath ? resumeEntryForGate(decideGateKind, { sessionId, taskId: activeForPath }) : null;
|
|
366
426
|
return {
|
|
367
427
|
status: 409,
|
|
@@ -432,10 +492,10 @@ export function createResumeLegs(ctx) {
|
|
|
432
492
|
noteLateSettleIfAccepted(committed);
|
|
433
493
|
return intent === undefined ? out : { ...out, rememberApplied: await intent.settle(committed) };
|
|
434
494
|
};
|
|
435
|
-
const parkedForkQuotaDenial = req !== undefined ? ownerCostQuotaDenied(
|
|
495
|
+
const parkedForkQuotaDenial = req !== undefined ? ownerCostQuotaDenied(checkpointPartsOf(cp.scope)?.person) : undefined;
|
|
436
496
|
if (parkedForkQuotaDenial)
|
|
437
497
|
return parkedForkQuotaDenial;
|
|
438
|
-
const parkedForkLeaseDenial = req !== undefined ? await ownerFleetLeaseDenied(
|
|
498
|
+
const parkedForkLeaseDenial = req !== undefined ? await ownerFleetLeaseDenied(checkpointPartsOf(cp.scope)?.person) : undefined;
|
|
439
499
|
if (parkedForkLeaseDenial)
|
|
440
500
|
return parkedForkLeaseDenial;
|
|
441
501
|
const ownerLeaseAdmittedHere = req !== undefined;
|
|
@@ -460,21 +520,22 @@ export function createResumeLegs(ctx) {
|
|
|
460
520
|
...(boundGrant && intent ? { remember: { anchor: (rootSessionId) => boundGrant(rootSessionId), laneCannotRecord: intent.laneCannotRecord } } : {}),
|
|
461
521
|
};
|
|
462
522
|
if (origin?.kind === "background" && parkedAgentStore !== undefined && parkedSurface !== undefined) {
|
|
463
|
-
const parked = await
|
|
523
|
+
const parked = await withSubject(checkpointPartsOf(cp.scope)?.subject, () => decideParkedAgent({
|
|
464
524
|
agentStore: parkedAgentStore,
|
|
465
525
|
checkpointStore: cs,
|
|
466
526
|
registry: defaultTaskRegistry,
|
|
467
527
|
reviveSurface: parkedSurface,
|
|
468
|
-
...(deps.parkedKnownAgentTypes ? { knownAgentTypes: deps.parkedKnownAgentTypes } : {}),
|
|
469
528
|
...(deps.parkedReviveInheritedGate ? { rebuildInheritedGate: deps.parkedReviveInheritedGate } : {}),
|
|
470
529
|
...(deps.toolApproval ? { approverSeatFor: windowZeroSeatOf(deps.toolApproval) } : {}),
|
|
471
530
|
execution: {
|
|
472
|
-
resolve: async (root) => {
|
|
531
|
+
resolve: async (root, face) => {
|
|
473
532
|
let ctx;
|
|
474
533
|
try {
|
|
475
|
-
ctx = await
|
|
534
|
+
ctx = await resolveBeforeClaim(deps, { kind: "continuation", root, principal: checkpointPartsOf(cp.scope)?.person }, face);
|
|
476
535
|
}
|
|
477
536
|
catch (e) {
|
|
537
|
+
if (e instanceof ClaimFaultAnswer)
|
|
538
|
+
return { ok: false, gone: false, answer: e.answer };
|
|
478
539
|
if (isRootSessionGoneError(e))
|
|
479
540
|
return { ok: false, gone: true };
|
|
480
541
|
if (e instanceof HttpError)
|
|
@@ -507,12 +568,15 @@ export function createResumeLegs(ctx) {
|
|
|
507
568
|
const plan = planWorkflowParkedDecide(origin, parkedReq);
|
|
508
569
|
if (!plan.ok)
|
|
509
570
|
return plan.deny;
|
|
571
|
+
const fingerprint = parkDecisionFingerprint(plan.outcome, restatement);
|
|
572
|
+
const live = await deliverToHoldingRun(origin, { token, outcome: plan.outcome, decision: parkedReq.decision, fingerprint, restated: restatement !== undefined });
|
|
573
|
+
if (live.kind === "answered")
|
|
574
|
+
return live.answer;
|
|
510
575
|
const decisions = deps.workflowParkDecisions;
|
|
511
576
|
const runStore = deps.runStore;
|
|
512
577
|
if (decisions === undefined || runStore === undefined) {
|
|
513
578
|
return { status: 501, body: refusalBody({ errorCode: "capability.run_store_required", message: "delivering this decision requires a durable run store (DB_BACKEND=mysql|pg|local)" }) };
|
|
514
579
|
}
|
|
515
|
-
const fingerprint = parkDecisionFingerprint(plan.outcome, restatement);
|
|
516
580
|
const liveReceiptOf = async (held) => {
|
|
517
581
|
if (held === null || held.fingerprint !== fingerprint)
|
|
518
582
|
return undefined;
|
|
@@ -523,44 +587,65 @@ export function createResumeLegs(ctx) {
|
|
|
523
587
|
if (replay !== undefined)
|
|
524
588
|
return replay;
|
|
525
589
|
let recordFailure;
|
|
590
|
+
const answerOfRecordFailure = async (failed) => {
|
|
591
|
+
if (failed.kind === "faulted")
|
|
592
|
+
return faultedAnswerOf(failed.err, CONTINUATION_CLAIM_FACE.faulted);
|
|
593
|
+
try {
|
|
594
|
+
return await refusalAfterLostClaim(deps, runStore, plan.hostSessionId, failed.deliveredTaskId);
|
|
595
|
+
}
|
|
596
|
+
catch (e) {
|
|
597
|
+
return faultedAnswerOf(e, CONTINUATION_CLAIM_FACE.faulted);
|
|
598
|
+
}
|
|
599
|
+
};
|
|
526
600
|
const delivery = {
|
|
527
601
|
carried: [{ runId: plan.runId, token, outcome: plan.outcome }],
|
|
528
602
|
commitBeforeLaunch: async (deliveredTaskId) => {
|
|
603
|
+
let recorded;
|
|
529
604
|
try {
|
|
530
|
-
|
|
531
|
-
if (!recorded)
|
|
532
|
-
throw new Error(DELIVERY_NOT_RECORDED);
|
|
605
|
+
recorded = await decisions.record({ token, runId: plan.runId, hostSessionId: plan.hostSessionId, outcome: plan.outcome, fingerprint, deliveredTaskId, acceptedAtMs: Date.now() });
|
|
533
606
|
}
|
|
534
607
|
catch (err) {
|
|
535
|
-
recordFailure = { err };
|
|
608
|
+
recordFailure = { kind: "faulted", err };
|
|
536
609
|
throw err;
|
|
537
610
|
}
|
|
611
|
+
if (!recorded) {
|
|
612
|
+
recordFailure = { kind: "not_recorded", deliveredTaskId };
|
|
613
|
+
throw new Error(DELIVERY_NOT_RECORDED);
|
|
614
|
+
}
|
|
538
615
|
},
|
|
539
616
|
};
|
|
540
617
|
const hostToken = await cs
|
|
541
618
|
.findPendingTokenBySession(plan.hostSessionId, undefined, { gateKinds: TERMINAL_PARK_GATE_KINDS, pick: "oldest" })
|
|
542
619
|
.catch(() => undefined);
|
|
543
620
|
const admittedPayer = decodeCheckpointScope(cp.scope);
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
621
|
+
let out;
|
|
622
|
+
try {
|
|
623
|
+
out = hostToken
|
|
624
|
+
? await resumeWake(plan.hostSessionId, plan.message, decider?.subject, req, acceptEarly, delivery, admittedPayer, restatement)
|
|
625
|
+
: await startFreshHostTurn(plan.hostSessionId, plan.message.text, admittedPayer, req, delivery, plan.runId, restatement);
|
|
626
|
+
}
|
|
627
|
+
catch (err) {
|
|
628
|
+
const failed = recordFailure;
|
|
629
|
+
if (failed === undefined)
|
|
630
|
+
throw err;
|
|
631
|
+
return await answerOfRecordFailure(failed);
|
|
632
|
+
}
|
|
633
|
+
const failed = recordFailure;
|
|
634
|
+
if (failed !== undefined)
|
|
635
|
+
return await answerOfRecordFailure(failed);
|
|
549
636
|
if (acceptedTaskIdOf(out) === undefined)
|
|
550
637
|
return (await liveReceiptOf(await decisions.get(token))) ?? out;
|
|
551
638
|
return out;
|
|
552
639
|
}
|
|
553
640
|
}
|
|
554
|
-
const
|
|
555
|
-
if (
|
|
556
|
-
return
|
|
557
|
-
if (
|
|
558
|
-
return resumeCtxUnsealableAnswer(ctxRead0);
|
|
559
|
-
const storedCtx = ctxRead0.kind === "ok" ? ctxRead0.ctx : null;
|
|
560
|
-
if (!storedCtx)
|
|
641
|
+
const runCtx = await ctxPromise;
|
|
642
|
+
if (runCtx !== undefined && "refusal" in runCtx)
|
|
643
|
+
return runCtx.refusal;
|
|
644
|
+
if (runCtx === undefined || runCtx.ctx === null)
|
|
561
645
|
return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
|
|
646
|
+
const { runSessionId, ctx: storedCtx } = runCtx;
|
|
562
647
|
const ctx = restateResumeCtx(storedCtx, restatement);
|
|
563
|
-
const auth = { sessionId:
|
|
648
|
+
const auth = { sessionId: runSessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
|
|
564
649
|
const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
|
|
565
650
|
if (!resolved.ok)
|
|
566
651
|
return resolved.answer;
|
|
@@ -586,8 +671,10 @@ export function createResumeLegs(ctx) {
|
|
|
586
671
|
...(answer !== undefined ? { answer } : {}),
|
|
587
672
|
hostDecision,
|
|
588
673
|
};
|
|
589
|
-
const
|
|
590
|
-
|
|
674
|
+
const composition = resumeCompositionOf(ctx.body, cp, deps.config.cascadeLadder);
|
|
675
|
+
if (composition?.entry === "cascade_unlinked")
|
|
676
|
+
return compositionUnlinkedAnswer();
|
|
677
|
+
const driven = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: resolved.runner, legFacts: resolved.legFacts, token, sessionId: runSessionId, subject: auth.subject, fleetScope: resumeFleetScope(req, auth), taskConfig, resumeObjective, outcome, commitment: { kind: "gate_resolved", ...captureSelectedGate() }, composition, resumeCtx: { sessionId: runSessionId, ctx }, ...(engineNotices.length > 0 ? { engineNotices } : {}), ...(boundGrant ? { onResumeCommitted: boundGrant } : {}), ...(acceptEarly === true ? { acceptEarly: true } : {}), ...(req !== undefined ? { callerInitiated: true } : {}), ...(ownerLeaseAdmittedHere ? { ownerLeaseAdmitted: true } : {}) });
|
|
591
678
|
return await landAfterCommit(driven);
|
|
592
679
|
}
|
|
593
680
|
finally {
|
|
@@ -598,7 +685,7 @@ export function createResumeLegs(ctx) {
|
|
|
598
685
|
const ONE_SHOT_SUBMIT_STRIP = Object.fromEntries(ONE_SHOT_SUBMIT_KEYS.map((k) => [k, undefined]));
|
|
599
686
|
const resolveResumeSpec = async (ctx, req, auth, lease) => {
|
|
600
687
|
const engineNotices = [];
|
|
601
|
-
const execution = await
|
|
688
|
+
const execution = await resolveBeforeClaim(deps, { kind: "continuation", root: auth.sessionId, principal: auth.subject === undefined ? undefined : personOf(recoveredSubject(auth.subject)) }, CONTINUATION_CLAIM_FACE);
|
|
602
689
|
const resolved = await deps.resolveSpec({ ...ctx.body, ...ONE_SHOT_SUBMIT_STRIP }, req, auth, {
|
|
603
690
|
leg: "resume",
|
|
604
691
|
onNotice: (n) => engineNotices.push(n),
|
|
@@ -608,7 +695,7 @@ export function createResumeLegs(ctx) {
|
|
|
608
695
|
});
|
|
609
696
|
const legFacts = legFactsOf(resolved);
|
|
610
697
|
const runner = runnerFor(resolved);
|
|
611
|
-
const spec = stampSpecRoot(resolved, execution);
|
|
698
|
+
const spec = stampSpecRoot(resolved, execution, { use: "session", requireExistingSession: ctx.body.requireExistingSession });
|
|
612
699
|
return { spec, runner, legFacts, engineNotices, execution };
|
|
613
700
|
};
|
|
614
701
|
const refuseStoredBodyReplay = (sessionId, refusal) => {
|
|
@@ -626,6 +713,8 @@ export function createResumeLegs(ctx) {
|
|
|
626
713
|
}
|
|
627
714
|
catch (e) {
|
|
628
715
|
lease.release();
|
|
716
|
+
if (e instanceof ClaimFaultAnswer)
|
|
717
|
+
return { ok: false, answer: e.answer };
|
|
629
718
|
if (e instanceof HttpError) {
|
|
630
719
|
return { ok: false, answer: resumeRefusalWithCard(resumeAssemblyRefusalAnswer(e.status, httpErrorRefusal(e)), true) };
|
|
631
720
|
}
|
|
@@ -654,13 +743,30 @@ export function createResumeLegs(ctx) {
|
|
|
654
743
|
}
|
|
655
744
|
async function driveResumeLeg(args, onAccepted) {
|
|
656
745
|
const resumeLegStartedAt = Date.now();
|
|
657
|
-
const { runner: legRunner, token, sessionId,
|
|
746
|
+
const { runner: legRunner, token, sessionId, subject, fleetScope, taskConfig, resumeObjective, outcome, composition, resumeCtx, execution } = args;
|
|
747
|
+
const legSubject = recoveredSubject(subject);
|
|
748
|
+
const payer = legSubject === undefined ? undefined : personOf(legSubject);
|
|
658
749
|
const heldObjective = objectiveWithheldIn(resumeCtx.ctx) ? undefined : resumeObjective;
|
|
659
750
|
const reparkStatus = outcome.gate === "plan_review" ? "needs_review" : "suspended";
|
|
660
|
-
const
|
|
751
|
+
const commitResumePark = (runStore, runId, word, parkResult, cardToken) => {
|
|
752
|
+
if (heldLeg === undefined)
|
|
753
|
+
throw new Error(`resume leg: run ${runId} parked without the holding leg its claim handed back — the park cannot be committed`);
|
|
754
|
+
return commitParkRow({
|
|
755
|
+
runStore, taskId: runId, word, result: parkResult, card: { token: cardToken, sessionId }, cards: deps.checkpointStore, leg: "resume",
|
|
756
|
+
legId: heldLeg, staleWindowMs: deps.config?.runStaleSec === undefined ? undefined : deps.config.runStaleSec * 1000,
|
|
757
|
+
});
|
|
758
|
+
};
|
|
759
|
+
const resumeCtxNotPersisted = (why) => {
|
|
661
760
|
deps.metrics?.inc("resume_ctx_not_persisted_total");
|
|
662
|
-
deps.logger?.warn?.("resume_ctx_not_persisted", { sessionId: resumeCtx.sessionId, gate: outcome.gate, error:
|
|
663
|
-
}
|
|
761
|
+
deps.logger?.warn?.("resume_ctx_not_persisted", { sessionId: resumeCtx.sessionId, gate: outcome.gate, error: why, note: "this continuation runs with the body it was given; the durable rebuild input still holds the PREVIOUS body, so the NEXT continuation of this session rebuilds from that one — its permission mode is never wider than this leg's, but if this leg restated its MCP / A2A peer tables (mcpServers / a2aPeers on the resume request), a later continuation that does not restate them runs with the previous tables again" });
|
|
762
|
+
};
|
|
763
|
+
const commitResumeCtx = () => Promise.resolve().then(async () => {
|
|
764
|
+
const sealed = sealCheckpointCtx({ ...resumeCtx.ctx, writerVersion: serviceVersion() }, deps.checkpointCtxSealing, resumeCtx.sessionId);
|
|
765
|
+
const claim = claimedRow && taskId !== undefined && deps.runStore !== undefined ? { fence: deps.runStore, taskId, legHolds: (run) => !runProvenElsewhere(run, deps.instanceId) } : undefined;
|
|
766
|
+
const landed = await deps.checkpointStore.putCtx(resumeCtx.sessionId, sealed, claim);
|
|
767
|
+
if (landed === "claim_released")
|
|
768
|
+
resumeCtxNotPersisted("claim_released: this run no longer holds the session claim (settled or reaped before the write-back landed) — nothing written");
|
|
769
|
+
}).catch((e) => resumeCtxNotPersisted(errorText(e)));
|
|
664
770
|
const legKey = createHash("sha256").update(String(token)).digest("hex");
|
|
665
771
|
const streamApprovalOn = resolveStreamApprovalGate({
|
|
666
772
|
toolApprovalEnabled: Boolean(deps.toolApproval),
|
|
@@ -677,38 +783,58 @@ export function createResumeLegs(ctx) {
|
|
|
677
783
|
declaredFamilies: declaredApprovalFrameFamilies(resumeCtx.ctx.body.settings),
|
|
678
784
|
});
|
|
679
785
|
const legDeadlineMonotonic = approvalLeg.legDeadlineMonotonic;
|
|
680
|
-
const ownerQuotaDenial = args.callerInitiated === true ? ownerCostQuotaDenied(
|
|
786
|
+
const ownerQuotaDenial = args.callerInitiated === true ? ownerCostQuotaDenied(payer) : undefined;
|
|
681
787
|
if (ownerQuotaDenial)
|
|
682
788
|
return ownerQuotaDenial;
|
|
683
|
-
const ownerLeaseDenial = args.callerInitiated === true && args.ownerLeaseAdmitted !== true ? await ownerFleetLeaseDenied(
|
|
789
|
+
const ownerLeaseDenial = args.callerInitiated === true && args.ownerLeaseAdmitted !== true ? await ownerFleetLeaseDenied(payer) : undefined;
|
|
684
790
|
if (ownerLeaseDenial)
|
|
685
791
|
return ownerLeaseDenial;
|
|
686
792
|
const heldDecisions = await heldWorkflowParkDecisions(deps, sessionId, args.workflowDecision?.carried);
|
|
687
793
|
let taskId = await deps.runStore?.getActiveTaskId(sessionId);
|
|
688
794
|
let freshRunClaimed = false;
|
|
795
|
+
let heldLeg;
|
|
796
|
+
let legClaim;
|
|
797
|
+
let engineHandedOff = false;
|
|
798
|
+
let restored;
|
|
799
|
+
const cancelledInClaimWindow = () => restored?.kind === "ended" && restored.row?.errorCode === CANCELLED_CODE;
|
|
689
800
|
if (args.mintFreshRun && taskId && deps.runStore) {
|
|
690
|
-
return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config,
|
|
801
|
+
return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, sessionId, taskId) };
|
|
691
802
|
}
|
|
692
803
|
if (!taskId && args.mintFreshRun && deps.runStore) {
|
|
693
804
|
const freshId = uuidv7();
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
805
|
+
let created;
|
|
806
|
+
try {
|
|
807
|
+
created = await timeClaim(deps.metrics, "run_claim", deps.runStore.createRun(freshId, sessionId, subject ?? null, deps.instanceId ?? "default", {
|
|
808
|
+
source: args.mintFreshRun.source,
|
|
809
|
+
identity: args.mintFreshRun.identity,
|
|
810
|
+
objectivePreview: heldObjective === undefined ? null : buildRunObjectivePreview(heldObjective),
|
|
811
|
+
}));
|
|
812
|
+
}
|
|
813
|
+
catch (e) {
|
|
814
|
+
return resumeClaimFaultAnswerOf(e);
|
|
815
|
+
}
|
|
699
816
|
if (created.existing) {
|
|
700
817
|
throw new Error(`wake fresh run: createRun observed an existing row for the freshly minted taskId ${freshId} (no idempotency key was sent) — refusing to treat it as a busy session`);
|
|
701
818
|
}
|
|
702
819
|
if (created.sessionAbsent)
|
|
703
820
|
return rootSessionAbsentAnswer();
|
|
704
821
|
if (!created.ok) {
|
|
705
|
-
return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config,
|
|
822
|
+
return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, turnActivity: readTurnActivityMs }, sessionId, created.activeTaskId) };
|
|
823
|
+
}
|
|
824
|
+
legClaim = { kind: "run", runStore: deps.runStore, taskId: freshId, legId: created.legId };
|
|
825
|
+
let placementReject;
|
|
826
|
+
try {
|
|
827
|
+
const refusal = await commitExecutionContext(deps, legClaim, execution);
|
|
828
|
+
placementReject = refusal === null ? null : CONTINUATION_CLAIM_FACE.refused(refusal);
|
|
829
|
+
}
|
|
830
|
+
catch (e) {
|
|
831
|
+
placementReject = resumeClaimFaultAnswerOf(e);
|
|
706
832
|
}
|
|
707
|
-
const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: freshId }, execution);
|
|
708
833
|
if (placementReject)
|
|
709
834
|
return placementReject;
|
|
710
835
|
taskId = freshId;
|
|
711
836
|
freshRunClaimed = true;
|
|
837
|
+
heldLeg = created.legId;
|
|
712
838
|
}
|
|
713
839
|
const fleetPub = taskId && deps.fleetBus
|
|
714
840
|
? fleetRunPublisher(deps.fleetBus, { runId: taskId, scope: fleetScope, rootTaskId: taskId, sessionId, ...fleetRunLabels(heldObjective) })
|
|
@@ -717,12 +843,12 @@ export function createResumeLegs(ctx) {
|
|
|
717
843
|
if (deps.toolApproval && taskId) {
|
|
718
844
|
const toolApproval = deps.toolApproval;
|
|
719
845
|
resumeTaskConfig.onAsk = approvalLeg.unattended
|
|
720
|
-
? toolApproval.boundUnattendedAsk({ owner:
|
|
846
|
+
? toolApproval.boundUnattendedAsk({ owner: subject ?? null, taskId, sessionId, ...approvalLegOriginOf(execution) }, approvalLeg.unattended)
|
|
721
847
|
: toolApproval.boundAsk({
|
|
722
|
-
owner:
|
|
848
|
+
owner: subject ?? null,
|
|
723
849
|
taskId,
|
|
724
850
|
sessionId,
|
|
725
|
-
|
|
851
|
+
...approvalLegOriginOf(execution),
|
|
726
852
|
...(approvalLeg.active ? { legKey, ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}) } : {}),
|
|
727
853
|
});
|
|
728
854
|
}
|
|
@@ -751,16 +877,15 @@ export function createResumeLegs(ctx) {
|
|
|
751
877
|
}
|
|
752
878
|
};
|
|
753
879
|
const settleCardForCancel = async () => {
|
|
880
|
+
if (freshRunClaimed)
|
|
881
|
+
return false;
|
|
754
882
|
const cs2 = deps.checkpointStore;
|
|
755
883
|
if (!cs2)
|
|
756
884
|
return false;
|
|
757
885
|
try {
|
|
758
|
-
|
|
759
|
-
if (live?.status !== "pending")
|
|
760
|
-
return false;
|
|
761
|
-
if (await cs2.expire(token, live.scope))
|
|
886
|
+
if ((await expireCardUnderStoredScope(cs2, token)) === CARD_EXPIRE_OUTCOME.expired)
|
|
762
887
|
return true;
|
|
763
|
-
deps.logger?.
|
|
888
|
+
deps.logger?.info?.("resume_cancel_checkpoint_not_settled", { taskId, sessionId });
|
|
764
889
|
return false;
|
|
765
890
|
}
|
|
766
891
|
catch (cancelSettleErr) {
|
|
@@ -786,26 +911,52 @@ export function createResumeLegs(ctx) {
|
|
|
786
911
|
let resumeLegLive = false;
|
|
787
912
|
const subagentHandleEvictions = [];
|
|
788
913
|
let claimedRow = false;
|
|
789
|
-
const cancelCtrl = createRunAbort(
|
|
914
|
+
const cancelCtrl = createRunAbort(subject ?? null);
|
|
790
915
|
let cancelLedgerAppend;
|
|
791
916
|
const preemptCtrl = new AbortController();
|
|
792
917
|
if (taskId && deps.runStore) {
|
|
793
|
-
|
|
918
|
+
if (freshRunClaimed)
|
|
919
|
+
claimedRow = true;
|
|
920
|
+
else {
|
|
921
|
+
try {
|
|
922
|
+
heldLeg = await deps.runStore.markResuming(taskId, deps.instanceId ?? "default");
|
|
923
|
+
}
|
|
924
|
+
catch (e) {
|
|
925
|
+
return resumeClaimFaultAnswerOf(e);
|
|
926
|
+
}
|
|
927
|
+
claimedRow = heldLeg !== undefined;
|
|
928
|
+
}
|
|
794
929
|
if (!claimedRow)
|
|
795
930
|
return notResumableAnswer();
|
|
931
|
+
inflightRuns.set(taskId, cancelCtrl);
|
|
796
932
|
if (!freshRunClaimed) {
|
|
797
|
-
const
|
|
798
|
-
|
|
799
|
-
|
|
933
|
+
const rs0 = deps.runStore;
|
|
934
|
+
const claimedTask = taskId;
|
|
935
|
+
const restoreClaim = async () => {
|
|
936
|
+
restored = await commitResumePark(rs0, claimedTask, reparkStatus, null, token);
|
|
937
|
+
};
|
|
938
|
+
legClaim = { kind: "resumed", runStore: rs0, taskId: claimedTask, restore: restoreClaim };
|
|
939
|
+
let placementReject;
|
|
940
|
+
try {
|
|
941
|
+
const refusal = await commitExecutionContext(deps, legClaim, execution);
|
|
942
|
+
placementReject = refusal === null ? null : CONTINUATION_CLAIM_FACE.refused(refusal);
|
|
943
|
+
}
|
|
944
|
+
catch (e) {
|
|
945
|
+
placementReject = resumeClaimFaultAnswerOf(e);
|
|
946
|
+
}
|
|
947
|
+
if (placementReject) {
|
|
948
|
+
if (inflightRuns.get(claimedTask) === cancelCtrl)
|
|
949
|
+
inflightRuns.delete(claimedTask);
|
|
950
|
+
return cancelledInClaimWindow() ? { status: 200, body: { taskId: claimedTask, sessionId, status: "failed", errorCode: "cancelled" } } : placementReject;
|
|
951
|
+
}
|
|
800
952
|
}
|
|
801
|
-
markChildrenStoppedByUserOnAbort(cancelCtrl.signal, taskId,
|
|
953
|
+
markChildrenStoppedByUserOnAbort(cancelCtrl.signal, taskId, subject);
|
|
802
954
|
fleetPub?.onStart();
|
|
803
955
|
const rs = deps.runStore;
|
|
804
|
-
const owner =
|
|
805
|
-
inflightRuns.set(taskId, cancelCtrl);
|
|
956
|
+
const owner = subject ?? null;
|
|
806
957
|
preemptableRuns.set(taskId, preemptCtrl);
|
|
807
958
|
resumeHeartbeat = setInterval(() => {
|
|
808
|
-
|
|
959
|
+
beatRunHeartbeat(rs, taskId, owner, () => cancelCtrl.abort("stall_verdict"), () => undefined);
|
|
809
960
|
if (!cancelCtrl.signal.aborted) {
|
|
810
961
|
void rs.isCancelRequested(taskId, owner).then((c) => { if (c)
|
|
811
962
|
cancelCtrl.abort("cancel_verb"); }).catch(() => undefined);
|
|
@@ -831,15 +982,19 @@ export function createResumeLegs(ctx) {
|
|
|
831
982
|
if (args.onResumeCommitted)
|
|
832
983
|
await args.onResumeCommitted();
|
|
833
984
|
let unregisterEngineNotice;
|
|
985
|
+
const handToEngine = (start) => {
|
|
986
|
+
engineHandedOff = true;
|
|
987
|
+
return start();
|
|
988
|
+
};
|
|
834
989
|
try {
|
|
835
990
|
const instructionLeg = createInstructionSelectionLeg();
|
|
836
991
|
const legWiringSections = () => ({ instructions: instructionLeg.segment(), skills: args.legFacts?.skills });
|
|
837
|
-
result = await instructionLeg.run(sessionId, () => withModelReachScope({ sessionId, taskId }, () =>
|
|
992
|
+
result = await instructionLeg.run(sessionId, () => withModelReachScope({ sessionId, taskId }, () => withSubject(legSubject, async () => {
|
|
838
993
|
const resumeNotifiedKeys = new NotifiedKeys();
|
|
839
994
|
if (deps.runStore && taskId) {
|
|
840
995
|
const rs0 = deps.runStore;
|
|
841
996
|
let drainSeq = (await rs0.maxSeq(taskId)) + 1;
|
|
842
|
-
await emitPendingWorkflowCompletions(deps.workflowCompletionInbox, sessionId,
|
|
997
|
+
await emitPendingWorkflowCompletions(deps.workflowCompletionInbox, sessionId, subject ?? null, (frame) => {
|
|
843
998
|
const { type, ...rest } = frame;
|
|
844
999
|
const f = frame;
|
|
845
1000
|
const write = rs0.appendEvent(taskId, drainSeq++, type, rest);
|
|
@@ -849,7 +1004,22 @@ export function createResumeLegs(ctx) {
|
|
|
849
1004
|
return write;
|
|
850
1005
|
}, { route: "resume-open", connection: "durable-append", log: (m, x) => deps.logger?.info?.(m, x) });
|
|
851
1006
|
}
|
|
852
|
-
|
|
1007
|
+
const openEngineNoticePort = async (append) => {
|
|
1008
|
+
unregisterEngineNotice = registerEngineNoticeLeg({
|
|
1009
|
+
sessionId,
|
|
1010
|
+
...(taskId !== undefined ? { taskId } : {}),
|
|
1011
|
+
durable: (row) => append("engine_notice", row).then(() => true, (err) => {
|
|
1012
|
+
recordFailOpen("server.engine-notice.durable-append-failed", `leg=resume code=${row.code} task=${taskId ?? ""}`);
|
|
1013
|
+
deps.logger?.warn?.("engine_notice_append_failed", { taskId, noticeCode: row.code, sessionId: row.sessionId, err: err instanceof Error ? err.message : String(err) });
|
|
1014
|
+
return false;
|
|
1015
|
+
}),
|
|
1016
|
+
});
|
|
1017
|
+
for (const notice of args.engineNotices ?? [])
|
|
1018
|
+
await defaultEngineNoticeRouter.routeConfirmed(notice);
|
|
1019
|
+
if (deps.userInputLedger && taskId)
|
|
1020
|
+
await deps.userInputLedger.announceUndrained({ sessionId, taskId });
|
|
1021
|
+
};
|
|
1022
|
+
if (composition !== undefined) {
|
|
853
1023
|
const rsV = deps.runStore;
|
|
854
1024
|
const vSeqBase = rsV && taskId ? await rsV.maxSeq(taskId) : 0;
|
|
855
1025
|
const verifySink = createLedgerSink({
|
|
@@ -861,9 +1031,11 @@ export function createResumeLegs(ctx) {
|
|
|
861
1031
|
});
|
|
862
1032
|
const vAppend = (type, data) => verifySink.append(type, data);
|
|
863
1033
|
cancelLedgerAppend = vAppend;
|
|
1034
|
+
await openEngineNoticePort(vAppend);
|
|
864
1035
|
const verifyTailContentMode = resumeTaskConfig.forwardSubagentEvents === true ? "on" : "progress_only";
|
|
865
1036
|
const verifyInternals = {
|
|
866
1037
|
...launchInternals,
|
|
1038
|
+
...compositionLegRoot(args.legFacts?.registeredCwd),
|
|
867
1039
|
...(taskId ? { onActivity: () => recordTurnActivity(taskId) } : {}),
|
|
868
1040
|
onForwardEvent: (e) => {
|
|
869
1041
|
fleetPub?.onForwardEvent(e);
|
|
@@ -891,7 +1063,7 @@ export function createResumeLegs(ctx) {
|
|
|
891
1063
|
const parked = !resumeLegLive && Boolean(deps.workflowCompletionInbox && sessionId);
|
|
892
1064
|
deps.logger?.info?.("task_notification_observed", { route: "resume-verify", taskId: n.task_id, taskType: n.task_type, status: n.status, legLive: resumeLegLive, parkedDurable: parked });
|
|
893
1065
|
if (parked) {
|
|
894
|
-
void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(sessionId,
|
|
1066
|
+
void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(sessionId, subject ?? null, n, Date.now(), taskId, opts?.priority)).catch((err) => deps.logger?.warn?.("park_enqueue_failed", { route: "resume-verify", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
|
|
895
1067
|
}
|
|
896
1068
|
else if (resumeLegLive) {
|
|
897
1069
|
const key = taskNotificationDedupKey(n);
|
|
@@ -909,10 +1081,23 @@ export function createResumeLegs(ctx) {
|
|
|
909
1081
|
: {}),
|
|
910
1082
|
};
|
|
911
1083
|
resumeLegLive = true;
|
|
912
|
-
const
|
|
1084
|
+
const legSpec = { ...resumeTaskConfig, signal: cancelCtrl.signal, preemptSignal: preemptCtrl.signal };
|
|
1085
|
+
let vrEngine;
|
|
1086
|
+
switch (composition.entry) {
|
|
1087
|
+
case "verify":
|
|
1088
|
+
vrEngine = await handToEngine(() => resumeWithVerification(legRunner, token, outcome, legSpec, resumeObjective, composition.rounds, verifyInternals));
|
|
1089
|
+
break;
|
|
1090
|
+
case "cascade":
|
|
1091
|
+
vrEngine = await handToEngine(() => resumeCascade(legRunner, token, outcome, stampSpecRoot({ ...legSpec, ...composition.objectiveInputs, objective: resumeObjective }, execution, { use: "ladder_host" }), composition.config, composition.parkedLeg, verifyInternals));
|
|
1092
|
+
break;
|
|
1093
|
+
default: {
|
|
1094
|
+
const unhandled = composition;
|
|
1095
|
+
throw new Error(`unhandled resume composition: ${JSON.stringify(unhandled)}`);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
913
1098
|
const vrCause = cancelCtrl.cause();
|
|
914
1099
|
await voidVerifierPauseCard(vrEngine, legRunner);
|
|
915
|
-
const vrJudged = atHostBoundary(vrEngine
|
|
1100
|
+
const vrJudged = atHostBoundary(vrEngine);
|
|
916
1101
|
if (vrJudged.terminal.kind === "paused")
|
|
917
1102
|
heldPark = vrJudged;
|
|
918
1103
|
const vrMinted = vrCause !== undefined && taskId !== undefined ? mintCancelledResult({ taskId, sessionId, startedAtMs: resumeLegStartedAt, message: "cancelled by user", engineResult: vrJudged, cause: vrCause }) : vrJudged;
|
|
@@ -940,8 +1125,9 @@ export function createResumeLegs(ctx) {
|
|
|
940
1125
|
}
|
|
941
1126
|
}
|
|
942
1127
|
catch (e) {
|
|
943
|
-
if (!vrReopened)
|
|
1128
|
+
if (!reSuspended && !vrReopened)
|
|
944
1129
|
throw e;
|
|
1130
|
+
recordFailOpen("server.runs.terminal-ledger-write-failed", `arm=resume-park-projection ${errorText(e)}`);
|
|
945
1131
|
}
|
|
946
1132
|
}
|
|
947
1133
|
if (reSuspended)
|
|
@@ -960,18 +1146,8 @@ export function createResumeLegs(ctx) {
|
|
|
960
1146
|
const serialAppend = createSerialLedgerAppend((s, type, data) => rs.appendEvent(taskId, s, type, data), startSeq);
|
|
961
1147
|
const append = (type, data) => (rs && taskId ? serialAppend(type, data) : Promise.resolve());
|
|
962
1148
|
cancelLedgerAppend = append;
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
...(args.engineNotices !== undefined && args.engineNotices.length > 0 ? { pending: [...args.engineNotices] } : {}),
|
|
966
|
-
durable: (row) => append("engine_notice", row).then(() => true, (err) => {
|
|
967
|
-
recordFailOpen("server.engine-notice.durable-append-failed", `leg=resume code=${row.code} task=${taskId ?? ""}`);
|
|
968
|
-
deps.logger?.warn?.("engine_notice_append_failed", { taskId, noticeCode: row.code, sessionId: row.sessionId, err: err instanceof Error ? err.message : String(err) });
|
|
969
|
-
return false;
|
|
970
|
-
}),
|
|
971
|
-
});
|
|
972
|
-
if (deps.userInputLedger && taskId)
|
|
973
|
-
await deps.userInputLedger.announceUndrained({ sessionId, taskId });
|
|
974
|
-
const anchorOwner = principal ?? null;
|
|
1149
|
+
await openEngineNoticePort(append);
|
|
1150
|
+
const anchorOwner = subject ?? null;
|
|
975
1151
|
const headOf = headReadOf(deps.sessionStorage);
|
|
976
1152
|
const captureTurnAnchor = deps.resumeAnchorStore && headOf
|
|
977
1153
|
? async (eventId) => { const leaf = (await headOf(sessionId))?.leafId; if (leaf)
|
|
@@ -998,7 +1174,7 @@ export function createResumeLegs(ctx) {
|
|
|
998
1174
|
resumeLegLive = true;
|
|
999
1175
|
const tailContentMode = resumeTaskConfig.forwardSubagentEvents === true ? "on" : "progress_only";
|
|
1000
1176
|
const resumeWorkspace = createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), args.legFacts?.sessionWitness);
|
|
1001
|
-
const stream = await legRunner.resumeStream(token, outcome, { ...resumeTaskConfig, signal: cancelCtrl.signal, preemptSignal: preemptCtrl.signal }, {
|
|
1177
|
+
const stream = await handToEngine(() => legRunner.resumeStream(token, outcome, { ...resumeTaskConfig, signal: cancelCtrl.signal, preemptSignal: preemptCtrl.signal }, {
|
|
1002
1178
|
...launchInternals,
|
|
1003
1179
|
onForwardEvent: (e) => {
|
|
1004
1180
|
fleetPub?.onForwardEvent(e);
|
|
@@ -1037,7 +1213,7 @@ export function createResumeLegs(ctx) {
|
|
|
1037
1213
|
const parked = !resumeLegLive && Boolean(deps.workflowCompletionInbox && sessionId);
|
|
1038
1214
|
deps.logger?.info?.("task_notification_observed", { route: "resume", taskId: n.task_id, taskType: n.task_type, status: n.status, legLive: resumeLegLive, parkedDurable: parked });
|
|
1039
1215
|
if (parked) {
|
|
1040
|
-
void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(sessionId,
|
|
1216
|
+
void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(sessionId, subject ?? null, n, Date.now(), taskId, opts?.priority)).catch((err) => deps.logger?.warn?.("park_enqueue_failed", { route: "resume", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
|
|
1041
1217
|
}
|
|
1042
1218
|
else if (resumeLegLive) {
|
|
1043
1219
|
const key = taskNotificationDedupKey(n);
|
|
@@ -1053,7 +1229,7 @@ export function createResumeLegs(ctx) {
|
|
|
1053
1229
|
},
|
|
1054
1230
|
}
|
|
1055
1231
|
: {}),
|
|
1056
|
-
});
|
|
1232
|
+
}));
|
|
1057
1233
|
await commitResumeCtx();
|
|
1058
1234
|
resumeStreamRef = stream;
|
|
1059
1235
|
if (taskId)
|
|
@@ -1211,11 +1387,7 @@ export function createResumeLegs(ctx) {
|
|
|
1211
1387
|
const settledLeg = await reopenedAfterLeg(r, causeAtDone !== undefined);
|
|
1212
1388
|
if (settledLeg.reopened) {
|
|
1213
1389
|
reopenConfirmedPark = true;
|
|
1214
|
-
|
|
1215
|
-
await appendParkRow(append, { modelUsage: deps.modelUsage, taskId }, reparkStatus, r, failureCodeOf(r.terminal) ?? null);
|
|
1216
|
-
}
|
|
1217
|
-
catch {
|
|
1218
|
-
}
|
|
1390
|
+
await appendParkRow(append, { modelUsage: deps.modelUsage, taskId }, reparkStatus, r, failureCodeOf(r.terminal) ?? null);
|
|
1219
1391
|
return r;
|
|
1220
1392
|
}
|
|
1221
1393
|
const safe = await attachModelUsage(sealResultForExit(settledLeg.leg), { append, getEvents: (id, a) => rs.getEvents(id, a), modelUsage: deps.modelUsage, taskId });
|
|
@@ -1227,25 +1399,22 @@ export function createResumeLegs(ctx) {
|
|
|
1227
1399
|
}
|
|
1228
1400
|
return safe;
|
|
1229
1401
|
};
|
|
1230
|
-
const
|
|
1231
|
-
const { type, ...rest } = frame;
|
|
1232
|
-
return append(type, rest);
|
|
1233
|
-
};
|
|
1402
|
+
const hitlTransport = createHitlTransport({ ledger: append });
|
|
1234
1403
|
const withApproval = () => deps.toolApproval && taskId && approvalLeg.active && approvalLeg.unattended === undefined
|
|
1235
1404
|
? deps.toolApproval.runWithContext({
|
|
1236
1405
|
taskId,
|
|
1237
|
-
owner:
|
|
1406
|
+
owner: subject ?? null,
|
|
1238
1407
|
abortSignal: cancelCtrl.signal,
|
|
1239
1408
|
sessionId,
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1409
|
+
...approvalLegOriginOf(execution),
|
|
1410
|
+
family: "approval_request",
|
|
1411
|
+
transport: hitlTransport,
|
|
1243
1412
|
legKey,
|
|
1244
1413
|
...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}),
|
|
1245
1414
|
}, driveResume)
|
|
1246
1415
|
: driveResume();
|
|
1247
1416
|
const withElicitation = () => deps.elicitation && taskId
|
|
1248
|
-
? deps.elicitation.runWithContext({ taskId, owner:
|
|
1417
|
+
? deps.elicitation.runWithContext({ taskId, owner: subject ?? null, transport: hitlTransport, abortSignal: cancelCtrl.signal }, withApproval)
|
|
1249
1418
|
: withApproval();
|
|
1250
1419
|
return await (deps.sendUserFile && taskId
|
|
1251
1420
|
? deps.sendUserFile.runWithContext({ taskId, emit: async (frame) => { const { type, ...rest } = frame; await append(type, rest); } }, withElicitation)
|
|
@@ -1269,6 +1438,7 @@ export function createResumeLegs(ctx) {
|
|
|
1269
1438
|
return { status: 200, body: { taskId, sessionId, status: "failed", errorCode: "cancelled" } };
|
|
1270
1439
|
}
|
|
1271
1440
|
const retriable = disposition === "retriable";
|
|
1441
|
+
let reparkEnded = false;
|
|
1272
1442
|
if (claimedRow && taskId && deps.runStore) {
|
|
1273
1443
|
if (retriable && freshRunClaimed) {
|
|
1274
1444
|
const c = { taskId, sessionId, terminal: { kind: "failed", code: e.code, message: e.message }, stats: { turns: 0, tokens: 0, usageMissing: true } };
|
|
@@ -1278,15 +1448,17 @@ export function createResumeLegs(ctx) {
|
|
|
1278
1448
|
settleFleet("failed");
|
|
1279
1449
|
}
|
|
1280
1450
|
else if (retriable) {
|
|
1281
|
-
|
|
1282
|
-
|
|
1451
|
+
const parked = await commitResumePark(deps.runStore, taskId, reparkStatus, null, token);
|
|
1452
|
+
reparkEnded = parked.kind === "ended";
|
|
1453
|
+
settleFleet(reparkEnded ? "failed" : reparkStatus);
|
|
1283
1454
|
}
|
|
1284
1455
|
else {
|
|
1285
1456
|
await deps.runStore.setTerminal(taskId, "failed", null, e.message).catch(() => undefined);
|
|
1286
1457
|
settleFleet("failed");
|
|
1287
1458
|
}
|
|
1288
1459
|
}
|
|
1289
|
-
|
|
1460
|
+
const answerRetriable = retriable && !reparkEnded;
|
|
1461
|
+
return checkpointRefusalAnswer(e, { gate: outcome.gate, retriable: answerRetriable, ...(taskId !== undefined ? { taskId } : {}), versionKeys: refusalVersionKeys(e, resumeCtx.ctx), ...(answerRetriable && args.rowWayOut !== undefined ? { wayOut: args.rowWayOut } : {}) });
|
|
1290
1462
|
}
|
|
1291
1463
|
const thrownCause = cancelCtrl.cause();
|
|
1292
1464
|
if (thrownCause !== undefined) {
|
|
@@ -1299,12 +1471,28 @@ export function createResumeLegs(ctx) {
|
|
|
1299
1471
|
settleFleet("failed");
|
|
1300
1472
|
return { status: 200, body: { taskId, sessionId, status: "failed", errorCode: "cancelled" } };
|
|
1301
1473
|
}
|
|
1302
|
-
if (
|
|
1303
|
-
|
|
1304
|
-
await deps
|
|
1474
|
+
if (!engineHandedOff && legClaim !== undefined) {
|
|
1475
|
+
const claim = legClaim;
|
|
1476
|
+
await withdrawClaim(deps, claim, `the resume could not be handed to the engine: ${outwardThrownMessage(e, errorText(e))}`, "faulted");
|
|
1477
|
+
const parkedAgain = claim.kind === "resumed" && restored?.kind !== "ended";
|
|
1478
|
+
settleFleet(parkedAgain ? reparkStatus : "failed");
|
|
1479
|
+
if (cancelledInClaimWindow())
|
|
1480
|
+
return { status: 200, body: { taskId, sessionId, status: "failed", errorCode: "cancelled" } };
|
|
1481
|
+
return resumeClaimFaultAnswerOf(e);
|
|
1305
1482
|
}
|
|
1306
|
-
|
|
1307
|
-
|
|
1483
|
+
const heldParkWord = heldPark === undefined ? undefined : heldParkOf(heldPark);
|
|
1484
|
+
if (!(claimedRow && taskId && deps.runStore && heldPark !== undefined && heldParkWord !== undefined)) {
|
|
1485
|
+
if (claimedRow && taskId && deps.runStore) {
|
|
1486
|
+
await voidHeldParkCard(heldPark, sessionId, deps.checkpointStore, "resume");
|
|
1487
|
+
await deps.runStore.setTerminal(taskId, "failed", null, outwardThrownMessage(e, errorText(e))).catch(() => undefined);
|
|
1488
|
+
}
|
|
1489
|
+
settleFleet("failed");
|
|
1490
|
+
throw e;
|
|
1491
|
+
}
|
|
1492
|
+
recordFailOpen("server.runs.terminal-ledger-write-failed", `arm=resume-park-held ${errorText(e)}`);
|
|
1493
|
+
if (cancelLedgerAppend !== undefined)
|
|
1494
|
+
await appendParkRow(cancelLedgerAppend, { modelUsage: deps.modelUsage, taskId }, heldParkWord.word, await graftParkToolCallId(heldPark, deps.checkpointStore));
|
|
1495
|
+
result = heldPark;
|
|
1308
1496
|
}
|
|
1309
1497
|
finally {
|
|
1310
1498
|
unregisterEngineNotice?.();
|
|
@@ -1329,31 +1517,38 @@ export function createResumeLegs(ctx) {
|
|
|
1329
1517
|
const checkpointReopened = reopenConfirmedPark;
|
|
1330
1518
|
const sealed = sealResultForExit(result);
|
|
1331
1519
|
const resumePlane = outwardPlane(sealed.terminal);
|
|
1520
|
+
let parkEnded;
|
|
1332
1521
|
if (taskId && deps.runStore) {
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
await deps.runStore
|
|
1522
|
+
const park = checkpointReopened && reparkStatus === "needs_review" ? { word: "needs_review", result: null }
|
|
1523
|
+
: resumePlane.status === "suspended" || checkpointReopened ? { word: "suspended", result: sealed.terminal.kind === "paused" ? sealed : null }
|
|
1524
|
+
: resumePlane.status === "needs_review" ? { word: "needs_review", result: sealed }
|
|
1525
|
+
: undefined;
|
|
1526
|
+
if (park !== undefined) {
|
|
1527
|
+
const parked = await commitResumePark(deps.runStore, taskId, park.word, park.result, heldPark?.terminal.kind === "paused" ? heldPark.terminal.token : token);
|
|
1528
|
+
if (parked.kind === "ended")
|
|
1529
|
+
parkEnded = { row: parked.row };
|
|
1530
|
+
}
|
|
1339
1531
|
else
|
|
1340
1532
|
await deps.runStore.setTerminal(taskId, resumePlane.status, sealed, resumePlane.errorMessage ?? null);
|
|
1341
1533
|
}
|
|
1342
|
-
settleFleet(checkpointReopened ? reparkStatus : resumePlane.status, fleetRunResiduals(sealed));
|
|
1534
|
+
settleFleet(parkEnded !== undefined ? "failed" : checkpointReopened ? reparkStatus : resumePlane.status, fleetRunResiduals(sealed, sealed ? failureCodeOf(sealed.terminal) : undefined));
|
|
1535
|
+
const answered = parkEnded !== undefined
|
|
1536
|
+
? { status: parkEnded.row?.status ?? "failed", errorCode: parkEnded.row?.errorCode ?? undefined, errorMessage: parkEnded.row?.error ?? undefined }
|
|
1537
|
+
: { status: resumePlane.status, errorCode: resumePlane.errorCode, errorMessage: resumePlane.errorMessage };
|
|
1343
1538
|
return {
|
|
1344
1539
|
status: 200,
|
|
1345
1540
|
body: {
|
|
1346
|
-
taskId, sessionId, status:
|
|
1541
|
+
taskId, sessionId, status: answered.status,
|
|
1347
1542
|
bindingEnforced: true,
|
|
1348
|
-
...(
|
|
1349
|
-
...(
|
|
1350
|
-
...(checkpointReopened ? { retriable: true } : {}),
|
|
1543
|
+
...(answered.errorCode ? { errorCode: answered.errorCode } : {}),
|
|
1544
|
+
...(answered.errorMessage ? { errorMessage: redactErrorMessage(answered.errorMessage) ?? "" } : {}),
|
|
1545
|
+
...(checkpointReopened && parkEnded === undefined ? { retriable: true } : {}),
|
|
1351
1546
|
...buildSettlementEvidence({ at: "engine_terminal", commitment: args.commitment }),
|
|
1352
1547
|
},
|
|
1353
1548
|
};
|
|
1354
1549
|
}
|
|
1355
1550
|
async function mayDiscloseRowError(cs, token, decider) {
|
|
1356
|
-
if (decider === undefined || decider.
|
|
1551
|
+
if (decider === undefined || decider.operator)
|
|
1357
1552
|
return true;
|
|
1358
1553
|
let scope;
|
|
1359
1554
|
try {
|
|
@@ -1365,24 +1560,28 @@ export function createResumeLegs(ctx) {
|
|
|
1365
1560
|
}
|
|
1366
1561
|
if (scope === undefined)
|
|
1367
1562
|
return false;
|
|
1368
|
-
|
|
1369
|
-
|
|
1563
|
+
return keyAdmits("scope.decide", decider, scopeCellOf(scope ?? CHECKPOINT_PUBLIC_SCOPE));
|
|
1564
|
+
}
|
|
1565
|
+
async function decisionRowAdmits(cs, token, who, bodyScope) {
|
|
1566
|
+
if (who === undefined)
|
|
1567
|
+
return true;
|
|
1568
|
+
const cell = bodyScope === undefined ? undefined : scopeCellOf(bodyScope);
|
|
1569
|
+
return cell !== undefined ? keyAdmits("scope.decide", who, cell) : mayDiscloseRowError(cs, token, who);
|
|
1370
1570
|
}
|
|
1371
1571
|
async function resumePreempted(sessionId, req, acceptEarly, decider, restatement) {
|
|
1372
1572
|
const cs = deps.checkpointStore;
|
|
1373
1573
|
const RESUMABLE_GATE_KIND = "resource_limit";
|
|
1374
|
-
const preemptBinding = { gateKinds: [RESUMABLE_GATE_KIND] };
|
|
1375
|
-
const token = (await cs.findPendingTokenBySession(sessionId, undefined, preemptBinding)) ?? (await cs.findPendingTokenBySession(sessionId));
|
|
1574
|
+
const preemptBinding = { gateKinds: [RESUMABLE_GATE_KIND], axis: "run" };
|
|
1575
|
+
const token = (await cs.findPendingTokenBySession(sessionId, undefined, preemptBinding)) ?? (await cs.findPendingTokenBySession(sessionId, undefined, { axis: "run" }));
|
|
1376
1576
|
const noSuspension = { status: 404, body: refusalBody({ errorCode: "not_found.suspension", message: "no resumable suspension for this task (already running, resumed, or expired)" }) };
|
|
1377
1577
|
if (!token)
|
|
1378
1578
|
return noSuspension;
|
|
1379
|
-
if (decider !== undefined && !decider.
|
|
1579
|
+
if (decider !== undefined && !decider.operator) {
|
|
1380
1580
|
const peeked = await cs
|
|
1381
1581
|
.peekPendingScope(sessionId, preemptBinding)
|
|
1382
|
-
.then((sc) => (sc === undefined ? cs.peekPendingScope(sessionId) : sc))
|
|
1582
|
+
.then((sc) => (sc === undefined ? cs.peekPendingScope(sessionId, { axis: "run" }) : sc))
|
|
1383
1583
|
.catch(() => undefined);
|
|
1384
|
-
|
|
1385
|
-
if (peekedOwner !== undefined && peekedOwner !== decider.principal) {
|
|
1584
|
+
if (!keyAdmits("scope.decide", decider, scopeCellOf(peeked ?? CHECKPOINT_PUBLIC_SCOPE))) {
|
|
1386
1585
|
deps.logger?.warn?.("assistant_resume_row_scope_mismatch", { sessionId, note: "pending row is foreign to the verified caller — owner gate ahead of the row load" });
|
|
1387
1586
|
return noSuspension;
|
|
1388
1587
|
}
|
|
@@ -1396,14 +1595,14 @@ export function createResumeLegs(ctx) {
|
|
|
1396
1595
|
deps.logger?.warn?.("assistant_resume_unreadable_row_withheld", { sessionId, note: "row unreadable and the caller's ownership of THAT token is unproven — folded into the uniform 404" });
|
|
1397
1596
|
return noSuspension;
|
|
1398
1597
|
}
|
|
1399
|
-
return {
|
|
1598
|
+
return rowReadRefusalAnswer(e, { cs, runs: deps.runStore, token, logger: deps.logger });
|
|
1400
1599
|
}
|
|
1401
1600
|
if (!cp) {
|
|
1402
1601
|
if (!(await mayDiscloseRowError(cs, token, decider)))
|
|
1403
1602
|
return noSuspension;
|
|
1404
1603
|
return { status: 404, body: refusalBody({ errorCode: "not_found.checkpoint", message: "checkpoint not found" }) };
|
|
1405
1604
|
}
|
|
1406
|
-
if (decider !== undefined && !
|
|
1605
|
+
if (decider !== undefined && !keyAdmits("scope.decide", decider, scopeCellOf(cp.scope))) {
|
|
1407
1606
|
deps.logger?.warn?.("assistant_resume_row_scope_mismatch", { sessionId, note: "loaded pending row is foreign to the verified caller — TOCTOU fold" });
|
|
1408
1607
|
return noSuspension;
|
|
1409
1608
|
}
|
|
@@ -1416,25 +1615,30 @@ export function createResumeLegs(ctx) {
|
|
|
1416
1615
|
return resumeCtxCorruptAnswer(ctxRead.where);
|
|
1417
1616
|
if (ctxRead.kind === "unsealable")
|
|
1418
1617
|
return resumeCtxUnsealableAnswer(ctxRead);
|
|
1618
|
+
if (ctxRead.kind === "unreadable")
|
|
1619
|
+
return resumeCtxUnreadableAnswer();
|
|
1419
1620
|
if (ctxRead.kind === "absent")
|
|
1420
1621
|
return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
|
|
1421
1622
|
const ctx = restateResumeCtx(ctxRead.ctx, restatement);
|
|
1422
|
-
const auth = { sessionId
|
|
1623
|
+
const auth = { sessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
|
|
1423
1624
|
const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
|
|
1424
1625
|
if (!resolved.ok)
|
|
1425
1626
|
return resolved.answer;
|
|
1426
1627
|
try {
|
|
1427
1628
|
const { spec, engineNotices } = resolved;
|
|
1428
1629
|
const { objective: resumeObjective, sessionId: _sessionId, ...taskConfig } = spec;
|
|
1429
|
-
const
|
|
1630
|
+
const composition = resumeCompositionOf(ctx.body, cp, deps.config.cascadeLadder);
|
|
1631
|
+
if (composition?.entry === "cascade_unlinked")
|
|
1632
|
+
return compositionUnlinkedAnswer();
|
|
1430
1633
|
const selectedGate = durableRowIdentity("decision-receipt", cp.checkpointId, token);
|
|
1431
|
-
|
|
1634
|
+
const rowWayOut = await loadedRowWayOut(cp, { cs, runs: deps.runStore, token, logger: deps.logger });
|
|
1635
|
+
return await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: resolved.runner, legFacts: resolved.legFacts, token, sessionId, subject: auth.subject, fleetScope: resumeFleetScope(req, auth), taskConfig, resumeObjective, outcome: { gate: "resource_limit", decision: "continue" }, commitment: { kind: "gate_resolved", ...selectedGate }, composition, resumeCtx: { sessionId, ctx }, ...(rowWayOut !== undefined ? { rowWayOut } : {}), ...(engineNotices.length > 0 ? { engineNotices } : {}), ...(acceptEarly === true ? { acceptEarly: true } : {}), ...(req !== undefined ? { callerInitiated: true } : {}) });
|
|
1432
1636
|
}
|
|
1433
1637
|
finally {
|
|
1434
1638
|
resolved.peerLease.release();
|
|
1435
1639
|
}
|
|
1436
1640
|
}
|
|
1437
|
-
async function startFreshHostTurn(sessionId, objective,
|
|
1641
|
+
async function startFreshHostTurn(sessionId, objective, subject, req, workflowDecision, runId, restatement) {
|
|
1438
1642
|
const cs = deps.checkpointStore;
|
|
1439
1643
|
if (!deps.runStore) {
|
|
1440
1644
|
return { status: 501, body: refusalBody({ errorCode: "capability.run_store_required", message: "delivering this decision requires a durable run store (DB_BACKEND=mysql|pg|local)" }) };
|
|
@@ -1444,6 +1648,8 @@ export function createResumeLegs(ctx) {
|
|
|
1444
1648
|
return resumeCtxCorruptAnswer(ctxRead.where);
|
|
1445
1649
|
if (ctxRead.kind === "unsealable")
|
|
1446
1650
|
return resumeCtxUnsealableAnswer(ctxRead);
|
|
1651
|
+
if (ctxRead.kind === "unreadable")
|
|
1652
|
+
return resumeCtxUnreadableAnswer();
|
|
1447
1653
|
const storedCtx = ctxRead.kind === "ok" ? ctxRead.ctx : null;
|
|
1448
1654
|
if (!storedCtx) {
|
|
1449
1655
|
return {
|
|
@@ -1459,10 +1665,10 @@ export function createResumeLegs(ctx) {
|
|
|
1459
1665
|
};
|
|
1460
1666
|
}
|
|
1461
1667
|
const ctx = restateResumeCtx(storedCtx, restatement);
|
|
1462
|
-
const windowDenial = await usageWindowDenialFor(
|
|
1668
|
+
const windowDenial = await usageWindowDenialFor(subject === undefined ? undefined : personOf(recoveredSubject(subject)));
|
|
1463
1669
|
if (windowDenial)
|
|
1464
1670
|
return { status: windowDenial.status, body: windowDenial.body };
|
|
1465
|
-
const auth = { sessionId,
|
|
1671
|
+
const auth = { sessionId, subject, memoryScope: ctx.memoryScope };
|
|
1466
1672
|
const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
|
|
1467
1673
|
if (!resolved.ok)
|
|
1468
1674
|
return resolved.answer;
|
|
@@ -1470,12 +1676,13 @@ export function createResumeLegs(ctx) {
|
|
|
1470
1676
|
const { spec, engineNotices } = resolved;
|
|
1471
1677
|
const hostSpec = { ...spec, objective };
|
|
1472
1678
|
const out = await mintAndDriveDurableRun(routeCtxBase, deps.runStore, {
|
|
1473
|
-
prepared: { spec: hostSpec, runner: resolved.runner, legFacts: resolved.legFacts, auth, body: ctx.body, ...(objectiveWithheldIn(ctx) ? { bodyFromScreenedCtx: true } : {}), acceptance: createRunAcceptance({}, { objective, screened: false }), peerLease: resolved.peerLease, execution: resolved.execution, ...(engineNotices.length > 0 ? { engineNotices } : {}) },
|
|
1679
|
+
prepared: { spec: hostSpec, runner: resolved.runner, legFacts: resolved.legFacts, auth, body: ctx.body, ...(objectiveWithheldIn(ctx) ? { bodyFromScreenedCtx: true } : {}), seat: createSubmissionSeat({ deployment: deps.config }), acceptance: createRunAcceptance({}, { objective, screened: false }), peerLease: resolved.peerLease, execution: resolved.execution, ...(engineNotices.length > 0 ? { engineNotices } : {}) },
|
|
1474
1680
|
fleetScope: resumeFleetScope(req, auth),
|
|
1475
|
-
elicitOwner:
|
|
1681
|
+
elicitOwner: subject ?? null,
|
|
1476
1682
|
source: "workflow_parked_decide",
|
|
1477
|
-
identity: runIdentityOf(req, deps.config,
|
|
1683
|
+
identity: runIdentityOf(req, deps.config, subject ?? null),
|
|
1478
1684
|
workflowDecision,
|
|
1685
|
+
face: CONTINUATION_CLAIM_FACE,
|
|
1479
1686
|
});
|
|
1480
1687
|
if (out.existing) {
|
|
1481
1688
|
throw new Error(`decide host turn: createRun observed an existing row ${out.existing.taskId} for a freshly minted taskId (no idempotency key was sent)`);
|
|
@@ -1495,11 +1702,10 @@ export function createResumeLegs(ctx) {
|
|
|
1495
1702
|
const token = (await cs.findPendingTokenBySession(sessionId, undefined, wakeBinding)) ?? (await cs.findPendingTokenBySession(sessionId));
|
|
1496
1703
|
if (!token)
|
|
1497
1704
|
return { status: 404, body: refusalBody({ errorCode: "not_found.parked_checkpoint", message: "no parked checkpoint for this session (nothing to wake)" }) };
|
|
1498
|
-
const
|
|
1499
|
-
if (!operator) {
|
|
1705
|
+
const who = { subject: caller, operator: explicitOperatorOk(caller === undefined ? undefined : personOf(caller), deps.config) };
|
|
1706
|
+
if (!who.operator) {
|
|
1500
1707
|
const scope = await cs.peekPendingScope(sessionId, wakeBinding).then((s) => (s === undefined ? cs.peekPendingScope(sessionId) : s)).catch(() => undefined);
|
|
1501
|
-
|
|
1502
|
-
if (decodedScope !== undefined && decodedScope !== caller) {
|
|
1708
|
+
if (!keyAdmits("scope.decide", who, scopeCellOf(scope ?? CHECKPOINT_PUBLIC_SCOPE))) {
|
|
1503
1709
|
return { status: 404, body: refusalBody({ errorCode: "not_found.parked_checkpoint", message: "no parked checkpoint for this session (nothing to wake)" }) };
|
|
1504
1710
|
}
|
|
1505
1711
|
}
|
|
@@ -1508,19 +1714,19 @@ export function createResumeLegs(ctx) {
|
|
|
1508
1714
|
cp = await cs.get(token);
|
|
1509
1715
|
}
|
|
1510
1716
|
catch (e) {
|
|
1511
|
-
if (!(await mayDiscloseRowError(cs, token,
|
|
1717
|
+
if (!(await mayDiscloseRowError(cs, token, who))) {
|
|
1512
1718
|
deps.logger?.warn?.("wake_unreadable_row_withheld", { sessionId, note: "row unreadable and the caller's ownership of THAT token is unproven — folded into the uniform 404" });
|
|
1513
1719
|
return { status: 404, body: refusalBody({ errorCode: "not_found.parked_checkpoint", message: "no parked checkpoint for this session (nothing to wake)" }) };
|
|
1514
1720
|
}
|
|
1515
|
-
return
|
|
1721
|
+
return rowReadRefusalAnswer(e, undefined);
|
|
1516
1722
|
}
|
|
1517
1723
|
if (!cp) {
|
|
1518
|
-
if (!(await mayDiscloseRowError(cs, token,
|
|
1724
|
+
if (!(await mayDiscloseRowError(cs, token, who))) {
|
|
1519
1725
|
return { status: 404, body: refusalBody({ errorCode: "not_found.parked_checkpoint", message: "no parked checkpoint for this session (nothing to wake)" }) };
|
|
1520
1726
|
}
|
|
1521
1727
|
return { status: 404, body: refusalBody({ errorCode: "not_found.checkpoint", message: "checkpoint not found" }) };
|
|
1522
1728
|
}
|
|
1523
|
-
if (!
|
|
1729
|
+
if (!keyAdmits("scope.decide", who, scopeCellOf(cp.scope))) {
|
|
1524
1730
|
return { status: 404, body: refusalBody({ errorCode: "not_found.parked_checkpoint", message: "no parked checkpoint for this session (nothing to wake)" }) };
|
|
1525
1731
|
}
|
|
1526
1732
|
const gateKind = cp.gate?.kind;
|
|
@@ -1543,10 +1749,12 @@ export function createResumeLegs(ctx) {
|
|
|
1543
1749
|
return resumeCtxCorruptAnswer(ctxRead.where);
|
|
1544
1750
|
if (ctxRead.kind === "unsealable")
|
|
1545
1751
|
return resumeCtxUnsealableAnswer(ctxRead);
|
|
1752
|
+
if (ctxRead.kind === "unreadable")
|
|
1753
|
+
return resumeCtxUnreadableAnswer();
|
|
1546
1754
|
if (ctxRead.kind === "absent")
|
|
1547
1755
|
return { status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) };
|
|
1548
1756
|
const ctx = restateResumeCtx(ctxRead.ctx, restatement);
|
|
1549
|
-
const auth = { sessionId: cp.sessionId,
|
|
1757
|
+
const auth = { sessionId: cp.sessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
|
|
1550
1758
|
const resolved = await resolveResumeSpecOrBlocked(ctx, req, auth);
|
|
1551
1759
|
if (!resolved.ok)
|
|
1552
1760
|
return resolved.answer;
|
|
@@ -1560,20 +1768,20 @@ export function createResumeLegs(ctx) {
|
|
|
1560
1768
|
legFacts: resolved.legFacts,
|
|
1561
1769
|
token,
|
|
1562
1770
|
sessionId: cp.sessionId,
|
|
1563
|
-
|
|
1771
|
+
subject: auth.subject,
|
|
1564
1772
|
fleetScope: resumeFleetScope(req, auth),
|
|
1565
1773
|
taskConfig,
|
|
1566
1774
|
resumeObjective,
|
|
1567
1775
|
outcome: { gate: "wake", ...(message !== undefined ? { message } : {}) },
|
|
1568
1776
|
commitment: { kind: "delivered" },
|
|
1569
|
-
|
|
1777
|
+
composition: undefined,
|
|
1570
1778
|
resumeCtx: { sessionId, ctx },
|
|
1571
|
-
mintFreshRun: { source: "wake", identity: runIdentityOf(req, deps.config, auth.
|
|
1779
|
+
mintFreshRun: { source: "wake", identity: runIdentityOf(req, deps.config, auth.subject ?? null) },
|
|
1572
1780
|
...(workflowDecision !== undefined ? { workflowDecision } : {}),
|
|
1573
1781
|
...(engineNotices.length > 0 ? { engineNotices } : {}),
|
|
1574
1782
|
...(acceptEarly === true ? { acceptEarly: true } : {}),
|
|
1575
1783
|
...(req !== undefined ? { callerInitiated: true } : {}),
|
|
1576
|
-
...(ownerLeaseAdmittedFor !== undefined && auth.
|
|
1784
|
+
...(ownerLeaseAdmittedFor !== undefined && auth.subject === ownerLeaseAdmittedFor ? { ownerLeaseAdmitted: true } : {}),
|
|
1577
1785
|
});
|
|
1578
1786
|
}
|
|
1579
1787
|
finally {
|
|
@@ -1589,20 +1797,19 @@ export function createResumeLegs(ctx) {
|
|
|
1589
1797
|
...(log?.principalPresent !== undefined ? { principalPresent: log.principalPresent } : {}),
|
|
1590
1798
|
});
|
|
1591
1799
|
const PLAN_REVIEW_GATE_KIND = "plan_review";
|
|
1592
|
-
const planReviewBinding = { gateKinds: [PLAN_REVIEW_GATE_KIND] };
|
|
1593
|
-
const token = (await cs.findPendingTokenBySession(sessionId, undefined, planReviewBinding)) ?? (await cs.findPendingTokenBySession(sessionId));
|
|
1800
|
+
const planReviewBinding = { gateKinds: [PLAN_REVIEW_GATE_KIND], axis: "run" };
|
|
1801
|
+
const token = (await cs.findPendingTokenBySession(sessionId, undefined, planReviewBinding)) ?? (await cs.findPendingTokenBySession(sessionId, undefined, { axis: "run" }));
|
|
1594
1802
|
const noPending = { status: 404, body: refusalBody({ errorCode: "not_found.plan_review", message: "no pending plan_review for this session (already decided or expired)" }) };
|
|
1595
1803
|
if (!token) {
|
|
1596
1804
|
log404("no-pending-checkpoint");
|
|
1597
1805
|
return refuse(noPending);
|
|
1598
1806
|
}
|
|
1599
|
-
if (decider !== undefined && !decider.
|
|
1807
|
+
if (decider !== undefined && !decider.operator) {
|
|
1600
1808
|
const peeked = await cs
|
|
1601
1809
|
.peekPendingScope(sessionId, planReviewBinding)
|
|
1602
|
-
.then((sc) => (sc === undefined ? cs.peekPendingScope(sessionId) : sc))
|
|
1810
|
+
.then((sc) => (sc === undefined ? cs.peekPendingScope(sessionId, { axis: "run" }) : sc))
|
|
1603
1811
|
.catch(() => undefined);
|
|
1604
|
-
|
|
1605
|
-
if (peekedOwner !== undefined && peekedOwner !== decider.principal) {
|
|
1812
|
+
if (!keyAdmits("scope.decide", decider, scopeCellOf(peeked ?? CHECKPOINT_PUBLIC_SCOPE))) {
|
|
1606
1813
|
deps.logger?.warn?.("plan_review_row_scope_mismatch", { sessionId, note: "pending row is foreign to the verified caller — owner gate ahead of the row load" });
|
|
1607
1814
|
return refuse(noPending);
|
|
1608
1815
|
}
|
|
@@ -1616,7 +1823,7 @@ export function createResumeLegs(ctx) {
|
|
|
1616
1823
|
deps.logger?.warn?.("plan_review_unreadable_row_withheld", { sessionId, note: "row unreadable and the caller's ownership of THAT token is unproven — folded into the uniform 404" });
|
|
1617
1824
|
return refuse(noPending);
|
|
1618
1825
|
}
|
|
1619
|
-
return refuse(
|
|
1826
|
+
return refuse(await rowReadRefusalAnswer(e, { cs, runs: deps.runStore, token, logger: deps.logger }));
|
|
1620
1827
|
}
|
|
1621
1828
|
if (!cp) {
|
|
1622
1829
|
log404("checkpoint-missing");
|
|
@@ -1624,7 +1831,7 @@ export function createResumeLegs(ctx) {
|
|
|
1624
1831
|
return refuse(noPending);
|
|
1625
1832
|
return refuse({ status: 404, body: refusalBody({ errorCode: "not_found.checkpoint", message: "checkpoint not found" }) });
|
|
1626
1833
|
}
|
|
1627
|
-
if (decider !== undefined && !
|
|
1834
|
+
if (decider !== undefined && !keyAdmits("scope.decide", decider, scopeCellOf(cp.scope))) {
|
|
1628
1835
|
deps.logger?.warn?.("plan_review_row_scope_mismatch", { sessionId, note: "loaded pending row is foreign to the verified caller — TOCTOU fold" });
|
|
1629
1836
|
return refuse(noPending);
|
|
1630
1837
|
}
|
|
@@ -1650,6 +1857,8 @@ export function createResumeLegs(ctx) {
|
|
|
1650
1857
|
return refuse(resumeCtxCorruptAnswer(ctxRead.where));
|
|
1651
1858
|
if (ctxRead.kind === "unsealable")
|
|
1652
1859
|
return refuse(resumeCtxUnsealableAnswer(ctxRead));
|
|
1860
|
+
if (ctxRead.kind === "unreadable")
|
|
1861
|
+
return refuse(resumeCtxUnreadableAnswer());
|
|
1653
1862
|
if (ctxRead.kind === "absent")
|
|
1654
1863
|
return refuse({ status: 409, body: refusalBody({ errorCode: "conflict.resume_context_unavailable", message: "resume context missing — cannot rebuild task config" }) });
|
|
1655
1864
|
const ctx = restateResumeCtx(ctxRead.ctx, restatement);
|
|
@@ -1660,9 +1869,9 @@ export function createResumeLegs(ctx) {
|
|
|
1660
1869
|
}
|
|
1661
1870
|
async function drivePlanReview(prepared, decision, editedPlan, reason, hostDecision, req, acceptEarly, permissionModeAfter) {
|
|
1662
1871
|
const { sessionId, token, cp, ctx } = prepared;
|
|
1663
|
-
if ((await deps.checkpointStore.findPendingTokenBySession(sessionId, undefined, { gateKinds: ["plan_review"] })) !== token)
|
|
1872
|
+
if ((await deps.checkpointStore.findPendingTokenBySession(sessionId, undefined, { gateKinds: ["plan_review"], axis: "run" })) !== token)
|
|
1664
1873
|
return notResumableAnswer();
|
|
1665
|
-
const auth = { sessionId
|
|
1874
|
+
const auth = { sessionId, subject: checkpointPartsOf(cp.scope)?.subject, memoryScope: ctx.memoryScope };
|
|
1666
1875
|
const effMode = storedBodyPermissionMode(ctx.body);
|
|
1667
1876
|
if (permissionModeAfter !== undefined && effMode !== "plan") {
|
|
1668
1877
|
throw new Error("drivePlanReview: permissionModeAfter was passed for a task whose stored permission mode is not \"plan\" — the caller must refuse this before any state changes (see the plan_review route's pre-nonce gate)");
|
|
@@ -1675,7 +1884,9 @@ export function createResumeLegs(ctx) {
|
|
|
1675
1884
|
try {
|
|
1676
1885
|
const { spec, engineNotices } = resolved;
|
|
1677
1886
|
const { objective: resumeObjective, sessionId: _sessionId, ...taskConfig } = spec;
|
|
1678
|
-
const
|
|
1887
|
+
const composition = resumeCompositionOf(ctx.body, cp, deps.config.cascadeLadder);
|
|
1888
|
+
if (composition?.entry === "cascade_unlinked")
|
|
1889
|
+
return compositionUnlinkedAnswer();
|
|
1679
1890
|
const outcome = {
|
|
1680
1891
|
gate: "plan_review",
|
|
1681
1892
|
decision,
|
|
@@ -1684,7 +1895,8 @@ export function createResumeLegs(ctx) {
|
|
|
1684
1895
|
hostDecision,
|
|
1685
1896
|
};
|
|
1686
1897
|
const selectedGate = durableRowIdentity("decision-receipt", cp.checkpointId, token);
|
|
1687
|
-
const
|
|
1898
|
+
const rowWayOut = await loadedRowWayOut(cp, { cs: deps.checkpointStore, runs: deps.runStore, token, logger: deps.logger });
|
|
1899
|
+
const out = await driveResumeIntoRunLog({ peerLease: resolved.peerLease, execution: resolved.execution, runner: resolved.runner, legFacts: resolved.legFacts, token, sessionId, subject: auth.subject, fleetScope: resumeFleetScope(req, auth), taskConfig, resumeObjective, outcome, commitment: { kind: "gate_resolved", ...selectedGate }, composition, resumeCtx: { sessionId, ctx: rebuildCtx }, ...(rowWayOut !== undefined ? { rowWayOut } : {}), ...(engineNotices.length > 0 ? { engineNotices } : {}), ...(acceptEarly === true ? { acceptEarly: true } : {}), ...(req !== undefined ? { callerInitiated: true } : {}) });
|
|
1688
1900
|
return out;
|
|
1689
1901
|
}
|
|
1690
1902
|
finally {
|
|
@@ -1700,10 +1912,10 @@ export function createResumeLegs(ctx) {
|
|
|
1700
1912
|
const routeCtxBase = {
|
|
1701
1913
|
deps,
|
|
1702
1914
|
registry: { idemCache, inflightRuns, preemptableRuns, steerableRuns, wakeParkMints, counters },
|
|
1703
|
-
helpers: { readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, admitRun, safeDecode
|
|
1915
|
+
helpers: { readJson, readRawBody, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, usageWindowDenied, admitRun, safeDecode },
|
|
1704
1916
|
local: { images: createImagesLocal(deps), sessions: createSessionsLocal(), sessionSync: createSessionSyncLocal(), capabilities: createCapabilitiesLocal() },
|
|
1705
1917
|
legs: { prepareSpec, finalizeTaskResult, resumeCheckpoint, driveResumeIntoRunLog, resumePreempted, resumeWake, preparePlanReview, drivePlanReview, sessionNotify: sessionNotifyDoor },
|
|
1706
1918
|
};
|
|
1707
|
-
return { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg,
|
|
1919
|
+
return { routeCtxBase, resumeCheckpoint, driveResumeIntoRunLog, driveResumeLeg, decisionRowAdmits, resumePreempted, startFreshHostTurn, resumeWake, preparePlanReview, drivePlanReview, sessionNotifyDoor };
|
|
1708
1920
|
}
|
|
1709
1921
|
//# sourceMappingURL=resume-legs.js.map
|