@sema-agent/server 7.146.0 → 7.148.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 +1423 -24
- package/README.md +21 -8
- package/README.zh-CN.md +15 -9
- package/USAGE.md +537 -216
- package/deploy/facts/lanes.json +7 -0
- package/deploy/sema-up/README.md +18 -7
- package/deploy/sema-up/chart/templates/NOTES.txt +1 -1
- package/deploy/sema-up/chart/templates/_helpers.tpl +42 -4
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -4
- package/deploy/sema-up/chart/templates/server.yaml +5 -4
- package/deploy/sema-up/chart/values.yaml +4 -3
- package/deploy/sema-up/cluster-up.sh +75 -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/flagshape.sh +4 -0
- 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/lanes.json +2 -5
- 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 +26 -48
- 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 +18 -5
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +25 -3
- 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/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +32 -34
- package/dist/approval-gate-currency.js +3 -2
- package/dist/approval-reconciler.d.ts +4 -13
- package/dist/approval-reconciler.js +2 -2
- package/dist/approval.d.ts +16 -14
- package/dist/approval.js +3 -3
- package/dist/audit.d.ts +10 -3
- package/dist/audit.js +17 -9
- package/dist/auth-bridge.d.ts +0 -14
- package/dist/auth-bridge.js +0 -7
- 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 +8 -3
- 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/crash-last.js +2 -1
- package/dist/boot/deployment-mods.d.ts +1 -1
- package/dist/boot/device-lane.js +5 -5
- package/dist/boot/engine-lease.d.ts +12 -11
- package/dist/boot/execution-env.d.ts +19 -8
- package/dist/boot/execution-env.js +80 -62
- package/dist/boot/execution-lane.d.ts +37 -9
- package/dist/boot/execution-lane.js +74 -20
- package/dist/boot/exit-boundary.d.ts +3 -3
- package/dist/boot/exit-boundary.js +6 -5
- package/dist/boot/exit-last.js +2 -1
- package/dist/boot/fatal-exit.d.ts +3 -5
- package/dist/boot/fatal-exit.js +2 -2
- package/dist/boot/governance-seams.d.ts +2 -2
- package/dist/boot/leader.d.ts +15 -0
- package/dist/boot/leader.js +18 -16
- package/dist/boot/memory-boundary.d.ts +11 -11
- package/dist/boot/memory-boundary.js +3 -3
- package/dist/boot/memory-consolidation.d.ts +50 -53
- package/dist/boot/memory-consolidation.js +11 -18
- package/dist/boot/org-memory.js +4 -3
- package/dist/boot/parked-revive-gate.d.ts +1 -1
- package/dist/boot/parked-revive-gate.js +3 -3
- package/dist/boot/reapers.d.ts +4 -3
- package/dist/boot/reapers.js +20 -17
- package/dist/boot/resolve-spec.d.ts +5 -3
- package/dist/boot/resolve-spec.js +133 -165
- package/dist/boot/retention-lane.d.ts +7 -45
- package/dist/boot/retention-lane.js +2 -2
- package/dist/boot/runner-deps.d.ts +28 -7
- package/dist/boot/runner-deps.js +11 -4
- package/dist/boot/runtime-caps.d.ts +2 -2
- package/dist/boot/runtime-caps.js +16 -2
- package/dist/boot/session-faces.d.ts +17 -7
- package/dist/boot/session-faces.js +122 -96
- package/dist/boot/shutdown.d.ts +5 -4
- package/dist/boot/shutdown.js +6 -4
- package/dist/boot/stage-01-config.d.ts +1 -1
- package/dist/boot/stage-01-config.js +14 -2
- package/dist/boot/stage-02-web-admin-pull.d.ts +2 -1
- package/dist/boot/stage-02-web-admin-pull.js +15 -8
- package/dist/boot/stage-03-store-backend.d.ts +4 -1
- package/dist/boot/stage-03-store-backend.js +4 -3
- package/dist/boot/stage-04-stores.d.ts +3 -1
- package/dist/boot/stage-04-stores.js +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +9 -5
- package/dist/boot/stage-05-execution-env.js +5 -5
- package/dist/boot/stage-06-runners.d.ts +13 -15
- package/dist/boot/stage-06-runners.js +24 -18
- package/dist/boot/stage-07-capability-layer.d.ts +14 -11
- package/dist/boot/stage-07-capability-layer.js +9 -12
- package/dist/boot/stage-08-reapers.d.ts +14 -11
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +16 -18
- package/dist/boot/stage-09-leader.js +12 -4
- package/dist/boot/stage-10-http-server.d.ts +16 -18
- package/dist/boot/stage-10-http-server.js +9 -5
- package/dist/boot/store-evidence.d.ts +20 -0
- package/dist/boot/store-evidence.js +13 -0
- package/dist/boot/stores.d.ts +12 -0
- package/dist/boot/stores.js +39 -17
- 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 +58 -38
- 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 +9 -1
- package/dist/capabilities/center-plugins.js +37 -11
- package/dist/capabilities/center-wiring.js +1 -1
- package/dist/capabilities/composite-members.d.ts +3 -2
- package/dist/capabilities/composite-members.js +3 -2
- package/dist/capabilities/execution-lane.d.ts +7 -7
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +1 -1
- package/dist/capabilities/repo-tools.d.ts +2 -0
- package/dist/capabilities/repo-tools.js +14 -12
- package/dist/capabilities/scenarios.d.ts +38 -33
- package/dist/capabilities/scenarios.js +24 -25
- package/dist/capabilities/settings-contract.d.ts +29 -0
- package/dist/capabilities/settings-contract.js +14 -0
- package/dist/capabilities/skills.d.ts +6 -6
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/capability-facts.d.ts +69 -4
- package/dist/capability-facts.js +77 -5
- package/dist/card-void.d.ts +4 -4
- package/dist/card-void.js +1 -1
- package/dist/center-credential-renewer.d.ts +6 -2
- package/dist/center-credential-renewer.js +10 -5
- package/dist/config-catalog.d.ts +16 -1
- package/dist/config-catalog.js +68 -61
- package/dist/config-dir-trust.d.ts +37 -4
- package/dist/config-dir-trust.js +88 -44
- package/dist/config-invariants.d.ts +58 -4
- package/dist/config-invariants.js +104 -23
- package/dist/config-lkg.d.ts +24 -2
- package/dist/config-lkg.js +22 -9
- package/dist/config-provider.d.ts +9 -9
- package/dist/config-provider.js +25 -108
- package/dist/config-pull-failure.d.ts +50 -0
- package/dist/config-pull-failure.js +48 -0
- package/dist/config-types.d.ts +215 -202
- package/dist/config.d.ts +69 -14
- package/dist/config.js +188 -96
- package/dist/degenerate-instrument.js +1 -1
- package/dist/delegated-session-owner.d.ts +1 -1
- package/dist/deleted-session-ids.d.ts +3 -2
- package/dist/deploy-facts.js +3 -2
- package/dist/deployment-governance.d.ts +3 -3
- package/dist/deployment-shape.d.ts +51 -16
- package/dist/deployment-shape.js +31 -6
- 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.d.ts +7 -5
- package/dist/env-facts.js +12 -7
- package/dist/env-witness.d.ts +7 -0
- package/dist/env-witness.js +16 -0
- package/dist/execution-config-root.d.ts +5 -5
- package/dist/execution-config-root.js +5 -5
- package/dist/execution-env-purpose.d.ts +14 -0
- package/dist/execution-env-purpose.js +29 -0
- package/dist/execution-lane-caps.d.ts +53 -103
- package/dist/execution-lane-caps.js +51 -83
- package/dist/execution-placement.d.ts +65 -9
- package/dist/execution-placement.js +58 -0
- 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.d.ts +2 -2
- package/dist/file-history-disclosure.js +1 -0
- package/dist/fleet/drain-entry.d.ts +17 -10
- package/dist/fleet/drain-entry.js +1 -1
- 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 +6 -7
- 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 +42 -0
- package/dist/history-anchor.js +34 -0
- 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 +1 -4
- package/dist/hooks/command-spawn.js +0 -11
- package/dist/hooks/hook-llm.d.ts +5 -1
- package/dist/hooks/hook-llm.js +24 -15
- package/dist/hooks/hook-runner.d.ts +119 -65
- package/dist/hooks/hook-runner.js +415 -217
- 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 +75 -78
- package/dist/http/approval-sweeps.d.ts +5 -8
- package/dist/http/approval-sweeps.js +55 -30
- package/dist/http/caller-trust.d.ts +8 -10
- package/dist/http/caller-trust.js +1 -2
- package/dist/http/checkpoint-ctx.d.ts +17 -0
- package/dist/http/checkpoint-ctx.js +6 -0
- package/dist/http/claim-heartbeat.d.ts +49 -0
- package/dist/http/claim-heartbeat.js +46 -0
- package/dist/http/claim-latency.d.ts +10 -0
- package/dist/http/claim-latency.js +12 -0
- package/dist/http/claimed-run.d.ts +4 -3
- package/dist/http/dispatch.d.ts +8 -1
- package/dist/http/dispatch.js +77 -31
- package/dist/http/durable-run-leg.d.ts +3 -3
- package/dist/http/durable-run-leg.js +18 -12
- package/dist/http/execution-context.d.ts +18 -42
- package/dist/http/execution-context.js +11 -5
- 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 +7 -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 +3 -3
- package/dist/http/memory-store-refusal-reply.js +6 -0
- package/dist/http/owner-access.d.ts +391 -56
- package/dist/http/owner-access.js +372 -33
- package/dist/http/principal-gate.d.ts +26 -94
- package/dist/http/principal-gate.js +24 -81
- package/dist/http/refusal-body.d.ts +35 -2
- package/dist/http/refusal-body.js +34 -0
- package/dist/http/request-guards.d.ts +10 -14
- 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 +35 -12
- package/dist/http/resume-ctx-read.js +25 -6
- package/dist/http/resume-legs.d.ts +24 -24
- package/dist/http/resume-legs.js +260 -171
- package/dist/http/retired-skill-manifest.d.ts +1 -1
- package/dist/http/rewind-files-reply.d.ts +34 -0
- package/dist/http/rewind-files-reply.js +36 -0
- package/dist/http/route-ctx.d.ts +56 -47
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/a2a-serve.d.ts +43 -5
- package/dist/http/routes/a2a-serve.js +58 -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 -88
- 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 +23 -20
- package/dist/http/routes/config-catalog.js +2 -2
- package/dist/http/routes/devices.d.ts +3 -3
- package/dist/http/routes/devices.js +5 -5
- package/dist/http/routes/diagnostics.d.ts +27 -3
- package/dist/http/routes/diagnostics.js +27 -21
- 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 +3 -1
- 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 +12 -20
- package/dist/http/routes/observability.js +3 -3
- package/dist/http/routes/principal-inbox.d.ts +1 -1
- package/dist/http/routes/principal-inbox.js +2 -2
- package/dist/http/routes/projects.d.ts +70 -0
- package/dist/http/routes/projects.js +87 -0
- package/dist/http/routes/retention-ops.js +6 -9
- package/dist/http/routes/rules.js +50 -7
- 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 +148 -233
- 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 +4 -2
- package/dist/http/routes/session-sync.js +48 -30
- package/dist/http/routes/sessions-list.d.ts +3 -3
- package/dist/http/routes/sessions-list.js +9 -9
- package/dist/http/routes/sessions.d.ts +7 -1
- package/dist/http/routes/sessions.js +177 -112
- package/dist/http/routes/shared-memory.js +6 -6
- package/dist/http/routes/side-query.js +2 -2
- package/dist/http/routes/tasks.js +144 -122
- 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 +63 -50
- package/dist/http/server.js +52 -16
- 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 +17 -3
- package/dist/http/stored-body-replay.js +11 -2
- package/dist/http/submit-ctx.d.ts +16 -8
- package/dist/http/submit-ctx.js +6 -2
- 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 +23 -13
- package/dist/identity-source.d.ts +36 -5
- package/dist/identity-source.js +27 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/instruction-source-notice.d.ts +1 -1
- 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/lsp-evict.d.ts +6 -4
- package/dist/lsp-evict.js +2 -3
- package/dist/memory-embedder-reembed.d.ts +38 -0
- package/dist/memory-embedder-reembed.js +20 -0
- package/dist/memory-incident-sink.d.ts +0 -28
- package/dist/memory-incident-sink.js +5 -0
- package/dist/memory-operator-faces.d.ts +5 -4
- package/dist/memory-operator-faces.js +1 -1
- package/dist/memory-scope.d.ts +31 -4
- package/dist/memory-scope.js +65 -16
- package/dist/memory-store-refusal.d.ts +20 -4
- package/dist/memory-store-refusal.js +1 -1
- package/dist/memory-sync-client.d.ts +5 -2
- package/dist/memory-sync-client.js +19 -14
- package/dist/memory-sync.js +1 -1
- package/dist/model-compat.d.ts +51 -28
- package/dist/model-compat.js +55 -23
- package/dist/model-context-window.d.ts +18 -0
- package/dist/model-context-window.js +2 -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 +46 -17
- package/dist/model-entry-refusal.js +47 -27
- 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-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 +28 -2
- package/dist/namespaced-rule-name.js +10 -1
- 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 +75 -47
- package/dist/observability/fail-open.js +77 -47
- package/dist/observability/logger.d.ts +22 -1
- package/dist/observability/logger.js +89 -12
- package/dist/observability/metrics.d.ts +2 -0
- package/dist/observability/metrics.js +5 -4
- 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 +5 -2
- package/dist/observability/secret-env-scrub.d.ts +30 -4
- package/dist/observability/secret-env-scrub.js +15 -3
- 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-agent-session-index.d.ts +7 -12
- package/dist/orchestration/workflow-agent-session-index.js +1 -6
- package/dist/orchestration/workflow-completion-inbox.d.ts +29 -9
- package/dist/orchestration/workflow-completion-inbox.js +65 -46
- package/dist/org-delivery-gate.d.ts +5 -4
- package/dist/org-delivery-gate.js +7 -6
- package/dist/org-memory-admission.d.ts +5 -2
- package/dist/org-memory-admission.js +25 -10
- 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 +531 -0
- package/dist/owner-faces.js +126 -0
- package/dist/parked-decide.d.ts +100 -31
- package/dist/parked-decide.js +162 -48
- package/dist/parked-revive-surface.d.ts +14 -4
- package/dist/parked-revive-surface.js +5 -4
- package/dist/peer-directory.d.ts +6 -8
- 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 +0 -22
- package/dist/plugins/adoption-log-sql.js +5 -3
- 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 +28 -9
- package/dist/plugins/approval-ask-store-file.js +74 -18
- package/dist/plugins/approval-ask-store-memory.d.ts +17 -7
- package/dist/plugins/approval-ask-store-memory.js +35 -12
- package/dist/plugins/approval-ask-store-sql.d.ts +42 -20
- package/dist/plugins/approval-ask-store-sql.js +44 -11
- package/dist/plugins/approval-exemption-skill-m46.d.ts +20 -0
- package/dist/plugins/approval-exemption-skill-m46.js +25 -0
- package/dist/plugins/approval-exemption-store.d.ts +6 -1
- package/dist/plugins/approval-exemption-store.js +14 -0
- 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 +40 -195
- package/dist/plugins/blob-backend.js +41 -234
- package/dist/plugins/caching-session-store.d.ts +22 -5
- package/dist/plugins/caching-session-store.js +43 -4
- package/dist/plugins/checkpoint-index-columns.d.ts +33 -6
- package/dist/plugins/checkpoint-index-columns.js +39 -3
- package/dist/plugins/checkpoint-store-face.d.ts +84 -11
- package/dist/plugins/checkpoint-store-face.js +18 -1
- package/dist/plugins/device-store-sql.d.ts +2 -2
- package/dist/plugins/device-store-sql.js +6 -10
- 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 +0 -15
- package/dist/plugins/ensure-schema-lock-policy.js +3 -2
- package/dist/plugins/execution-lane-rename-m40.d.ts +20 -0
- package/dist/plugins/execution-lane-rename-m40.js +10 -0
- package/dist/plugins/execution-placement-sql.d.ts +63 -88
- package/dist/plugins/execution-placement-sql.js +94 -54
- package/dist/plugins/file-run-store.d.ts +89 -35
- package/dist/plugins/file-run-store.js +197 -142
- 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 +19 -10
- package/dist/plugins/imported-layer-root-retirement.js +4 -8
- package/dist/plugins/inbox-payload-column.d.ts +14 -0
- package/dist/plugins/inbox-payload-column.js +13 -0
- 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 +63 -23
- package/dist/plugins/local-checkpoint-store.js +204 -81
- package/dist/plugins/local-data-dir-modes-m39.d.ts +48 -0
- package/dist/plugins/local-data-dir-modes-m39.js +183 -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 +13 -0
- package/dist/plugins/local-engine-high-water.js +62 -0
- package/dist/plugins/local-session-store.d.ts +442 -143
- package/dist/plugins/local-session-store.js +941 -289
- 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 +20 -1
- package/dist/plugins/local-task-attachment-store.js +32 -12
- package/dist/plugins/memory-embedder-fingerprint.d.ts +33 -10
- package/dist/plugins/memory-embedder-fingerprint.js +52 -12
- package/dist/plugins/memory-embedder.d.ts +1 -1
- package/dist/plugins/memory-embedder.js +11 -9
- package/dist/plugins/memory-engine-pg.d.ts +7 -5
- package/dist/plugins/memory-engine-pg.js +18 -9
- package/dist/plugins/memory-engine-sql-apply.d.ts +21 -8
- package/dist/plugins/memory-engine-sql-apply.js +7 -9
- package/dist/plugins/memory-engine-tidb.d.ts +12 -7
- package/dist/plugins/memory-engine-tidb.js +18 -10
- 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 +39 -27
- package/dist/plugins/memory-run-store.js +72 -70
- package/dist/plugins/one-time-migration-marker.d.ts +10 -0
- package/dist/plugins/one-time-migration-marker.js +7 -0
- package/dist/plugins/one-time-migrations.d.ts +325 -74
- package/dist/plugins/one-time-migrations.js +705 -230
- package/dist/plugins/org-delivery-quota-store.js +2 -1
- package/dist/plugins/owner-only-file-mode.d.ts +29 -0
- package/dist/plugins/owner-only-file-mode.js +141 -0
- package/dist/plugins/permission-rule-store-file.d.ts +11 -11
- package/dist/plugins/permission-rule-store-file.js +14 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +4 -63
- package/dist/plugins/permission-rule-store-sql.js +6 -86
- package/dist/plugins/pg-pool.d.ts +3 -32
- package/dist/plugins/pg-pool.js +27 -11
- package/dist/plugins/release-version.d.ts +20 -0
- package/dist/plugins/release-version.js +28 -0
- package/dist/plugins/remote-env-adb.d.ts +20 -4
- package/dist/plugins/remote-env-adb.js +39 -11
- package/dist/plugins/remote-env-e2b.d.ts +19 -28
- package/dist/plugins/remote-env-e2b.js +40 -29
- package/dist/plugins/remote-env-host.d.ts +11 -10
- package/dist/plugins/remote-env-host.js +40 -27
- package/dist/plugins/remote-env-k8s.d.ts +45 -47
- package/dist/plugins/remote-env-k8s.js +122 -62
- package/dist/plugins/remote-env-local-docker.d.ts +152 -15
- package/dist/plugins/remote-env-local-docker.js +370 -75
- package/dist/plugins/remote-env-ssh.d.ts +8 -2
- package/dist/plugins/remote-env-ssh.js +26 -24
- package/dist/plugins/remote-scratchpad.js +4 -0
- package/dist/plugins/remote-shell.d.ts +59 -30
- package/dist/plugins/remote-shell.js +175 -62
- package/dist/plugins/retention-declaration.d.ts +37 -0
- package/dist/plugins/retention-declaration.js +9 -0
- package/dist/plugins/retention-deployment.d.ts +158 -0
- package/dist/plugins/retention-deployment.js +119 -0
- package/dist/plugins/retention-lane-store-sql.d.ts +74 -4
- package/dist/plugins/retention-lane-store-sql.js +103 -1
- package/dist/plugins/retention-sql.d.ts +29 -0
- package/dist/plugins/retention-sql.js +8 -0
- 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 +56 -68
- package/dist/plugins/run-store-sql.js +127 -116
- 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 +54 -0
- package/dist/plugins/scenario-prefix-switch-m42.js +55 -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 +42 -15
- package/dist/plugins/schema-consistency.js +213 -13
- package/dist/plugins/schema-drift-sentence.d.ts +4 -1
- package/dist/plugins/schema-drift-sentence.js +4 -4
- package/dist/plugins/schema-ensure-legs.d.ts +10 -1
- package/dist/plugins/schema-ensure-legs.js +12 -2
- 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 +98 -0
- package/dist/plugins/session-ext-table.js +134 -0
- package/dist/plugins/session-fork.d.ts +16 -2
- package/dist/plugins/session-fork.js +3 -0
- package/dist/plugins/session-ownership.d.ts +1 -1
- package/dist/plugins/session-placement.d.ts +22 -16
- package/dist/plugins/session-placement.js +15 -12
- package/dist/plugins/session-row-sql.d.ts +20 -7
- package/dist/plugins/session-row-sql.js +16 -8
- 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 +157 -0
- package/dist/plugins/session-store-sql.js +398 -0
- package/dist/plugins/session-withdraw-sql.d.ts +36 -0
- package/dist/plugins/session-withdraw-sql.js +42 -0
- package/dist/plugins/session-workspace-cell.d.ts +2 -2
- package/dist/plugins/session-workspace-cell.js +2 -2
- package/dist/plugins/shared-memory-store-sql.d.ts +10 -69
- package/dist/plugins/shared-memory-store-sql.js +15 -14
- package/dist/plugins/shell-sentinel-owner-m48.d.ts +20 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +3 -0
- package/dist/plugins/snapshot-bucket-presence.d.ts +2 -1
- package/dist/plugins/snapshot-bucket-presence.js +1 -1
- package/dist/plugins/sql-driver.d.ts +24 -8
- package/dist/plugins/sql-driver.js +43 -9
- package/dist/plugins/sql-errors.d.ts +35 -5
- package/dist/plugins/sql-errors.js +55 -3
- package/dist/plugins/sql-json-column.d.ts +8 -7
- package/dist/plugins/sql-json-column.js +10 -6
- package/dist/plugins/store-backend.d.ts +114 -18
- package/dist/plugins/store-backend.js +340 -87
- package/dist/plugins/store-contracts.d.ts +97 -30
- package/dist/plugins/store-contracts.js +23 -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 +21 -11
- package/dist/plugins/task-attachment-store.js +37 -19
- package/dist/plugins/task-list-store-sql.d.ts +1 -1
- package/dist/plugins/text-column-capacity.d.ts +21 -0
- package/dist/plugins/text-column-capacity.js +5 -0
- package/dist/plugins/tidb-pool.d.ts +3 -2
- package/dist/plugins/tidb-pool.js +42 -39
- package/dist/plugins/user-input-ledger-sql.d.ts +1 -1
- 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/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/question.d.ts +13 -23
- package/dist/question.js +21 -39
- package/dist/read-face-posture.d.ts +6 -6
- package/dist/read-face-posture.js +2 -2
- 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/request-value-closure.d.ts +5 -5
- package/dist/request-value-closure.js +1 -1
- 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 +46 -16
- package/dist/rules-consent.js +102 -53
- package/dist/run-acceptance.d.ts +3 -1
- package/dist/run-acceptance.js +3 -0
- package/dist/run-local.d.ts +14 -6
- package/dist/run-local.js +109 -93
- package/dist/run-stale-default.d.ts +7 -0
- package/dist/run-stale-default.js +2 -0
- package/dist/runs.d.ts +73 -44
- package/dist/runs.js +65 -43
- package/dist/runtime-caps-resolver.d.ts +36 -14
- package/dist/runtime-caps-resolver.js +31 -14
- package/dist/runtime-governance.d.ts +2 -2
- package/dist/runtime-governance.js +5 -3
- package/dist/sealed-key-layout.d.ts +12 -6
- package/dist/sealed-key-layout.js +5 -1
- package/dist/sealed-key.d.ts +12 -2
- package/dist/sealed-key.js +116 -26
- package/dist/security.d.ts +133 -161
- package/dist/security.js +163 -59
- package/dist/sema-config-dir.d.ts +20 -0
- package/dist/sema-config-dir.js +27 -2
- package/dist/server-secret-env.d.ts +23 -5
- package/dist/server-secret-env.js +14 -4
- package/dist/service-version.d.ts +2 -1
- package/dist/service-version.js +2 -2
- package/dist/session-children-retire.d.ts +7 -5
- package/dist/session-children-retire.js +7 -2
- 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 +6 -6
- package/dist/session-error-wire.js +1 -1
- package/dist/session-incarnation.d.ts +60 -10
- 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 +29 -47
- package/dist/session-resident-background.js +77 -8
- package/dist/session-row.d.ts +3 -2
- package/dist/session-rules-seat.d.ts +12 -0
- package/dist/session-rules-seat.js +19 -0
- package/dist/session-sync-kernel.d.ts +1 -1
- package/dist/session-titler.d.ts +7 -15
- package/dist/session-titler.js +1 -1
- package/dist/session-workspace.d.ts +11 -2
- package/dist/session-workspace.js +5 -0
- package/dist/sighup-idle.d.ts +1 -1
- package/dist/spec-fields.d.ts +57 -3
- package/dist/spec-fields.js +72 -51
- package/dist/store-posture.d.ts +138 -21
- package/dist/store-posture.js +188 -3
- package/dist/stored-request-hooks-m20.d.ts +3 -2
- package/dist/stored-request-hooks-m20.js +21 -16
- 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/blob-index-sql.d.ts +148 -0
- package/dist/stores-sql/blob-index-sql.js +154 -0
- package/dist/stores-sql/checkpoint-store-sql.d.ts +34 -29
- package/dist/stores-sql/checkpoint-store-sql.js +86 -71
- package/dist/{plugins → stores-sql}/file-history-store-sql.d.ts +23 -11
- package/dist/{plugins → stores-sql}/file-history-store-sql.js +23 -18
- package/dist/stores-sql/mailbox-store-sql.d.ts +7 -4
- package/dist/stores-sql/mailbox-store-sql.js +31 -32
- package/dist/{plugins → stores-sql}/pg-session-storage.d.ts +30 -81
- package/dist/{plugins → stores-sql}/pg-session-storage.js +123 -244
- package/dist/{plugins → stores-sql}/retention-store-sql.d.ts +197 -223
- package/dist/{plugins → stores-sql}/retention-store-sql.js +148 -207
- package/dist/{plugins → stores-sql}/session-event-payload.d.ts +1 -1
- package/dist/{plugins → stores-sql}/session-event-payload.js +1 -1
- package/dist/stores-sql/session-policy-store-sql.d.ts +33 -11
- package/dist/stores-sql/session-policy-store-sql.js +44 -36
- package/dist/stores-sql/session-write-hooks.d.ts +65 -0
- package/dist/stores-sql/session-write-hooks.js +2 -0
- package/dist/{plugins → stores-sql}/tidb-session-storage.d.ts +14 -15
- package/dist/{plugins → stores-sql}/tidb-session-storage.js +22 -28
- package/dist/{plugins → stores-sql}/tidb-session-store.d.ts +67 -138
- package/dist/{plugins → stores-sql}/tidb-session-store.js +130 -200
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +1 -1
- package/dist/stores-sql/windowed-session-storage.d.ts +61 -0
- package/dist/stores-sql/windowed-session-storage.js +70 -0
- package/dist/submission-exit.d.ts +50 -0
- package/dist/submission-exit.js +108 -0
- package/dist/task-a2a.d.ts +7 -1
- package/dist/task-a2a.js +18 -17
- package/dist/task-cwd.d.ts +31 -3
- package/dist/task-cwd.js +25 -1
- package/dist/task-mcp.d.ts +11 -3
- package/dist/task-mcp.js +16 -19
- package/dist/task-settings.d.ts +23 -14
- package/dist/task-settings.js +35 -13
- package/dist/terminal.d.ts +25 -43
- package/dist/terminal.js +31 -11
- package/dist/tool-approval.d.ts +152 -137
- package/dist/tool-approval.js +199 -199
- package/dist/trace/core-keyset-guard.d.ts +22 -9
- 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 +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.d.ts +52 -4
- package/dist/trace/exit-seat.js +43 -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 +1 -30
- 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 +88 -58
- package/dist/trace/project.js +64 -28
- package/dist/trace/redact.d.ts +124 -28
- package/dist/trace/redact.js +936 -328
- package/dist/trace/self-minted-wire.d.ts +750 -29
- package/dist/trace/self-minted-wire.js +262 -25
- package/dist/trace/sema-provenance.d.ts +45 -41
- package/dist/trace/sema-provenance.js +81 -10
- package/dist/trace/task-notification-facets.d.ts +70 -2
- package/dist/trace/task-notification-facets.js +71 -1
- package/dist/trace/wire-projection-faces.d.ts +43 -8
- package/dist/trace/wire-projection-faces.js +28 -3
- package/dist/unread-request-members.d.ts +66 -0
- package/dist/unread-request-members.js +41 -0
- 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 -40
- 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/candidate-gate.d.ts +35 -3
- package/dist/web-admin-client/candidate-gate.js +53 -5
- package/dist/web-admin-client/center-request.d.ts +6 -3
- package/dist/web-admin-client/center-request.js +17 -16
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.js +1 -2
- 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/facade.d.ts +1 -1
- package/dist/web-admin-client/http-client.d.ts +2 -1
- package/dist/web-admin-client/http-client.js +40 -13
- 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 +13 -6
- package/dist/web-admin-client/skills-mcp.d.ts +22 -8
- package/dist/web-admin-client/skills-mcp.js +26 -21
- package/dist/web-admin-client/types.d.ts +35 -51
- package/dist/workspace-space.d.ts +3 -2
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +4 -4
- package/package.json +16 -12
- package/scripts/drain-check-local.mjs +118 -173
- package/scripts/drain-check.mysql.sql +20 -16
- package/scripts/drain-check.pg.sql +20 -16
- package/wire-changes/server@7.147.0.json +813 -0
- package/wire-changes/server@7.148.0.json +1517 -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
|
@@ -4,29 +4,34 @@ import { judgeCheckpointIndexCells } from "./checkpoint-index-columns.js";
|
|
|
4
4
|
import { dialectProtocolJsonEncoder } from "./sql-driver.js";
|
|
5
5
|
import { SCHEMA_STATEMENTS, acquireEnsureSchemaLock, releaseEnsureSchemaLock } from "./tidb-pool.js";
|
|
6
6
|
import { PG_SCHEMA_STATEMENTS, acquirePgEnsureSchemaLock, releasePgEnsureSchemaLock } from "./pg-pool.js";
|
|
7
|
-
import { CENTRAL_SCHEMA_INDEXES } from "./schema-indexes.js";
|
|
8
|
-
import { ensureIndexes } from "./ensure-index.js";
|
|
9
7
|
import { createObjectColumnReader, decodeJsonColumn, decodeNullableJsonColumn, isJsonColumnBodyProblem, jsonColumnText, jsonColumnTextExpr, readOpaqueJsonValueColumn, } from "./sql-json-column.js";
|
|
10
8
|
import { incarnationFromCell, sessionFaceFromRow } from "../session-incarnation.js";
|
|
11
9
|
import { StoreBootRefusalError } from "./store-contracts.js";
|
|
12
|
-
import {
|
|
10
|
+
import { decodeRunResultCellM44 } from "./run-store-sql.js";
|
|
11
|
+
import { persistedPlaneOf } from "../terminal.js";
|
|
12
|
+
import { RUN_PREVIEW_COARSE_PREFIXES_M45, normalizedRunPreviewM45 } from "./run-preview-m45.js";
|
|
13
|
+
import { SHELL_SENTINEL_OWNER_M48, SHELL_SENTINEL_OWNER_TABLES_M48 } from "./shell-sentinel-owner-m48.js";
|
|
14
|
+
import { LEGACY_SKILL_EXEMPTION_MARKER_ID, LEGACY_SKILL_EXEMPTION_PAGE, LEGACY_SKILL_EXEMPTION_TOOL_NAME } from "./approval-exemption-skill-m46.js";
|
|
15
|
+
import { PERMISSION_RULE_TABLE, SqlDurableRulePartitionProvider, isSqlBucketRefusal, isSqlBucketVanished, listRuleBucketOwners } from "./permission-rule-store-sql.js";
|
|
13
16
|
import { SESSION_RULES_COLUMN } from "./session-rules-column.js";
|
|
14
17
|
import { readJsonObjectColumn } from "./sql-json-column.js";
|
|
15
18
|
import { retireStoredCardWords } from "../retired-card-words.js";
|
|
16
19
|
import { redactSecrets } from "../trace/redact.js";
|
|
17
20
|
import { CLAIM_OWNERLESS_PLACED_SQL, claimOwnerlessParams, isOrphanSessionOwner, judgeDelegatedOwner } from "../delegated-session-owner.js";
|
|
18
21
|
import { MAILBOX_KEYED_TABLES, mailboxKeyDeleteSql, storedMailboxKeyless } from "../stores-sql/mailbox-store-sql.js";
|
|
19
|
-
import {
|
|
22
|
+
import { backfillWriterStatement, countOrphanBindingsStatement, migrateDeviceBindingsOntoSideTableStatements, migrateDeviceBindingsStatement } from "./execution-placement-sql.js";
|
|
23
|
+
import { WITHDRAW_MARK_ID } from "./session-withdraw-sql.js";
|
|
24
|
+
import { EXECUTION_PLACEMENT_COLUMNS, SESSION_EXT_MOVED_COLUMNS, SESSION_EXT_TABLE } from "./session-ext-table.js";
|
|
20
25
|
import { APPROVAL_ASK_ENDING_CAUSE_COLUMN, APPROVAL_ASK_EXECUTION_LANE_COLUMN, APPROVAL_ASK_PARK_TRIGGER_COLUMN, APPROVAL_ASK_TABLE } from "./approval-ask-store-sql.js";
|
|
26
|
+
import { RENAMED_EXECUTION_LANE_M40, RETIRED_EXECUTION_LANE_WORD_M40, retiredExecutionLaneHintM40 } from "./execution-lane-rename-m40.js";
|
|
21
27
|
import { retireImportedLayerRootAllows } from "./imported-layer-root-retirement.js";
|
|
22
28
|
import { isUnusableArchive } from "../execution-placement.js";
|
|
29
|
+
import { IDENTITY_COLUMN_NAME, SCENARIO_PREFIX_LIKE, SCENARIO_PREFIX_MARKER_ID, ScenarioPrefixSwitchRefusedError } from "./scenario-prefix-switch-m42.js";
|
|
30
|
+
import { MIGRATION_MARKER_TABLE, migrationMarkerDdl } from "./one-time-migration-marker.js";
|
|
31
|
+
import { expectedTableShapes } from "./schema-consistency.js";
|
|
23
32
|
const RETIRED_SESSION_RULE_BUCKETS = ["commandAllow", "commandDeny"];
|
|
24
33
|
export function buildMigrationReceipts() {
|
|
25
34
|
return {
|
|
26
|
-
workflowParkIndexRowsCarried: 0,
|
|
27
|
-
undurableScopeRuleRows: [],
|
|
28
|
-
undurableScopeRuleBucketsDeferred: 0,
|
|
29
|
-
undurableScopeRuleBucketsUnreadable: [],
|
|
30
35
|
sessionRuleRowsWithRetiredBuckets: [],
|
|
31
36
|
sessionRuleRowsWithOldGrammarEntries: [],
|
|
32
37
|
sessionRuleRowsWithUnreadableDeny: [],
|
|
@@ -52,33 +57,42 @@ export function buildMigrationReceipts() {
|
|
|
52
57
|
deviceBindingTablesDropped: 0,
|
|
53
58
|
executionPlacementsBackfilled: 0,
|
|
54
59
|
askExecutionLanesBackfilled: 0,
|
|
60
|
+
executionLaneWordsRenamed: 0,
|
|
61
|
+
sessionExtRowsMoved: 0,
|
|
62
|
+
sessionMetaColumnsDropped: 0,
|
|
63
|
+
scenarioPrefixSourcesScanned: 0,
|
|
64
|
+
withdrawMarkWritten: 0,
|
|
65
|
+
sessionDeletingSwitchMarked: 0,
|
|
66
|
+
runErrorCodeColumnRewritten: 0,
|
|
67
|
+
runObjectivePreviewRewritten: 0,
|
|
68
|
+
shellSentinelOwnersCleared: 0,
|
|
69
|
+
checkpointHostSessionsBackfilled: 0,
|
|
70
|
+
legacySkillExemptionsDropped: 0,
|
|
55
71
|
executionPlacementSessionsUnreadable: [],
|
|
56
72
|
localArchiveRowFactsBackfilled: 0,
|
|
57
73
|
localArchivesAnonymized: 0,
|
|
58
74
|
localArchivesKeptStamped: [],
|
|
59
75
|
localArchivesUnreadable: [],
|
|
60
76
|
localArchiveSnapshotsRecovered: 0,
|
|
77
|
+
localArchiveTokensAdopted: 0,
|
|
78
|
+
localArchiveTokensMinted: 0,
|
|
61
79
|
askCauseColumnsChanged: 0,
|
|
62
80
|
askParkTriggersMoved: 0,
|
|
63
81
|
askJournalRecordsUpgraded: 0,
|
|
64
82
|
importedLayerRootAllowsRetired: [],
|
|
65
83
|
importedLayerRootBucketsSkipped: [],
|
|
84
|
+
importedLayerRootBucketsUnnamed: 0,
|
|
66
85
|
};
|
|
67
86
|
}
|
|
68
87
|
function completedReport(r) {
|
|
69
|
-
const {
|
|
70
|
-
if (
|
|
71
|
-
throw new Error(`one-time migrations finished without settling a shape reading (
|
|
88
|
+
const { sessionRuleColumn, workflowJournalScopeColumn } = r;
|
|
89
|
+
if (sessionRuleColumn === undefined || workflowJournalScopeColumn === undefined) {
|
|
90
|
+
throw new Error(`one-time migrations finished without settling a shape reading (M17 ${String(sessionRuleColumn)} / M24 ${String(workflowJournalScopeColumn)}) — a step did not record it`);
|
|
72
91
|
}
|
|
73
|
-
return { ...r,
|
|
92
|
+
return { ...r, sessionRuleColumn, workflowJournalScopeColumn };
|
|
74
93
|
}
|
|
75
94
|
function changedAnything(r) {
|
|
76
|
-
return (r.
|
|
77
|
-
r.workflowParkIndexRowsCarried > 0 ||
|
|
78
|
-
r.undurableScopeRuleRows.length > 0 ||
|
|
79
|
-
r.undurableScopeRuleBucketsDeferred > 0 ||
|
|
80
|
-
r.undurableScopeRuleBucketsUnreadable.length > 0 ||
|
|
81
|
-
r.sessionRuleColumn === "renamed" ||
|
|
95
|
+
return (r.sessionRuleColumn === "renamed" ||
|
|
82
96
|
r.sessionRuleRowsWithRetiredBuckets.length > 0 ||
|
|
83
97
|
r.sessionRuleRowsWithOldGrammarEntries.length > 0 ||
|
|
84
98
|
r.sessionRuleRowsWithUnreadableDeny.length > 0 ||
|
|
@@ -105,23 +119,34 @@ function changedAnything(r) {
|
|
|
105
119
|
r.deviceBindingTablesDropped > 0 ||
|
|
106
120
|
r.executionPlacementsBackfilled > 0 ||
|
|
107
121
|
r.askExecutionLanesBackfilled > 0 ||
|
|
122
|
+
r.executionLaneWordsRenamed > 0 ||
|
|
123
|
+
r.sessionExtRowsMoved > 0 ||
|
|
124
|
+
r.sessionMetaColumnsDropped > 0 ||
|
|
125
|
+
r.withdrawMarkWritten > 0 ||
|
|
126
|
+
r.sessionDeletingSwitchMarked > 0 ||
|
|
127
|
+
r.runErrorCodeColumnRewritten > 0 ||
|
|
128
|
+
r.runObjectivePreviewRewritten > 0 ||
|
|
129
|
+
r.shellSentinelOwnersCleared > 0 ||
|
|
130
|
+
r.checkpointHostSessionsBackfilled > 0 ||
|
|
131
|
+
r.legacySkillExemptionsDropped > 0 ||
|
|
108
132
|
r.executionPlacementSessionsUnreadable.length > 0 ||
|
|
109
133
|
r.localArchiveRowFactsBackfilled > 0 ||
|
|
110
134
|
r.localArchivesAnonymized > 0 ||
|
|
111
135
|
r.localArchivesKeptStamped.length > 0 ||
|
|
112
136
|
r.localArchivesUnreadable.length > 0 ||
|
|
113
137
|
r.localArchiveSnapshotsRecovered > 0 ||
|
|
138
|
+
r.localArchiveTokensAdopted > 0 ||
|
|
139
|
+
r.localArchiveTokensMinted > 0 ||
|
|
114
140
|
r.askCauseColumnsChanged > 0 ||
|
|
115
141
|
r.askParkTriggersMoved > 0 ||
|
|
116
142
|
r.askJournalRecordsUpgraded > 0 ||
|
|
117
143
|
r.importedLayerRootAllowsRetired.length > 0 ||
|
|
118
|
-
r.importedLayerRootBucketsSkipped.length > 0
|
|
144
|
+
r.importedLayerRootBucketsSkipped.length > 0 ||
|
|
145
|
+
r.importedLayerRootBucketsUnnamed > 0);
|
|
119
146
|
}
|
|
120
147
|
function readingsSnapshot(r) {
|
|
121
148
|
return {
|
|
122
149
|
...r,
|
|
123
|
-
undurableScopeRuleRows: [...r.undurableScopeRuleRows],
|
|
124
|
-
undurableScopeRuleBucketsUnreadable: [...r.undurableScopeRuleBucketsUnreadable],
|
|
125
150
|
sessionRuleRowsWithRetiredBuckets: [...r.sessionRuleRowsWithRetiredBuckets],
|
|
126
151
|
sessionRuleRowsWithOldGrammarEntries: [...r.sessionRuleRowsWithOldGrammarEntries],
|
|
127
152
|
sessionRuleRowsWithUnreadableDeny: [...r.sessionRuleRowsWithUnreadableDeny],
|
|
@@ -139,7 +164,6 @@ function receiptSentence(r) {
|
|
|
139
164
|
.filter(([, v]) => (typeof v === "number" ? v > 0 : v !== undefined))
|
|
140
165
|
.map(([k, v]) => `${k}=${String(v)}`);
|
|
141
166
|
const rows = [
|
|
142
|
-
...r.undurableScopeRuleRows.map((x) => `removed ${x.kind} in permission-rule bucket ${x.ownerKey} (${x.behavior} ${x.tool}, scope root ${JSON.stringify(x.scopeRoot)})`),
|
|
143
167
|
...r.sessionRuleRowsWithOldGrammarEntries.map((x) => `${x.policyKey} (session ${x.sessionId}): toolAllowDropped=${JSON.stringify(x.toolAllowDropped)}`),
|
|
144
168
|
...r.sessionRuleRowsWithUnreadableDeny.map((x) => `${x.policyKey} (session ${x.sessionId}): left as stored, toolDenyUnreadable=${JSON.stringify(x.toolDenyUnreadable)}${x.retiredBuckets !== undefined ? `, retiredBuckets=${JSON.stringify(x.retiredBuckets)}` : ""}`),
|
|
145
169
|
...r.importedLayerRootAllowsRetired.map((x) => `retired ${x.addsRetired} imported add(s) of an allow ${x.tool} rule in permission-rule bucket ${x.ownerKey} (${x.stillLive ? "the rule stays in effect through another approval" : "the rule no longer takes effect"})`),
|
|
@@ -157,53 +181,6 @@ export class OneTimeMigrationInterruptedError extends Error {
|
|
|
157
181
|
}
|
|
158
182
|
}
|
|
159
183
|
export const ONE_TIME_MIGRATIONS = [
|
|
160
|
-
{
|
|
161
|
-
id: "M9",
|
|
162
|
-
introducedIn: "7.118.0",
|
|
163
|
-
releasedOn: "2026-10-07",
|
|
164
|
-
removableAfter: "2026-11-06",
|
|
165
|
-
removal: "删 migrateOn 的 M9 步(`reshapeWorkflowParkIndex` / `execAtomically` / `finishParkIndexShape`:收尾段、主键宽度探针、暂存表复制、换名、删旧表、索引补建、主键约束名)与 " +
|
|
166
|
-
"`primaryKeyWidth` / `WORKFLOW_PARK_INDEX_TABLE` / `WORKFLOW_PARK_INDEX_STAGING` / `WORKFLOW_PARK_INDEX_RETIRED`;报告、日志行与 `NO_SQL_MIGRATIONS` 的 " +
|
|
167
|
-
"`workflowParkIndexKey` / `workflowParkIndexRowsCarried`;**连同读侧半场一起删**(都是「引擎 7.43 及以前写下的 workflow 子代停驻记录」这同一件事,同窗同删,不另起登记行):" +
|
|
168
|
-
"`orchestration/workflow-agent-session-index.ts` 的 `older_engine` 读臂(`routeWorkflowPark` 规则 ③、`WorkflowParkRoute` 与 `parked-decide.ts` `ParkOrigin` 上 `cause` 里的这一词," +
|
|
169
|
-
"`denyWorkflowParksUnreadable` 的对应分支;`unreadable` 成为唯一成因)与随包排空判据 `workflow-park-holder`(`scripts/drain-check.mysql.sql` / `scripts/drain-check.pg.sql` 的那一段" +
|
|
170
|
-
"与文件头判据清单里的那一行、`scripts/drain-check-local.mjs` 的 `DRAIN_CRITERIA` 那一条与 `readParkIndex`,以及 `MIGRATION.md` / `docs/DEPLOY-PREREQS.md` 里点名它的说明)",
|
|
171
|
-
afterRemoval: "没有响亮臂:删码之后仍是旧主键(只有 `session_id`)的库(跳过了带本条的版本直接升)上,同一个子会话只能有一枚指针 —— 续跑链 / 分叉里" +
|
|
172
|
-
"后写的那条记录覆盖先写的,判决只看得到一条记录:分叉判不出、链尾可能被更早的记录盖掉(决定投给那一条)。运维手工照中央 DDL 重建这张表即可" +
|
|
173
|
-
"(它是派生投影,丢了只丢升级那一刻还停驻着的旧卡的指针 —— 那些卡改答诚实 miss)。读侧半场删后:升级那一刻还停驻着、点名它的条目没有持有者位的存量卡" +
|
|
174
|
-
"(跳过了带本条的版本直接升的库)路由判 `none` ⇒ 落 legacy 腿,答 `409 conflict.resume_context_unavailable`(响亮,但成因是子会话没有续跑上下文,不再是 " +
|
|
175
|
-
"`decide.workflow_parks_unreadable`);出路不变(续跑发起它的那条 workflow run);随包排空判据没了,换钉前没有机器读数可数这些卡",
|
|
176
|
-
reportKeys: ["workflowParkIndexKey", "workflowParkIndexRowsCarried"],
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
id: "M10",
|
|
180
|
-
introducedIn: "7.119.0",
|
|
181
|
-
releasedOn: "2026-10-08",
|
|
182
|
-
removableAfter: "2026-11-07",
|
|
183
|
-
removal: "删 local 车道的认领臂:`LocalSessionStore.register` 里「属主从没被记下的存量会话 ⇒ 带 principal 的登记认领它」那一支、认领日志行 `session_owner_claimed`" +
|
|
184
|
-
"(连同店构造参数里只为它存在的 `log` 位)与读本表 M10 行的 `ownerClaimWindowOpen`;`security.ts` `createAuthorizer` 里对无主会话的那次认领 `register` 调用;" +
|
|
185
|
-
"`http/routes/sessions.ts` 409 `conflict.session_ownerless` 句里「Ways out: on the local backend, during the upgrade window …」那半句(连同冻结表 " +
|
|
186
|
-
"`test/api-error-text-freeze.test.ts` 那一行、契约码目录 `docs/ASSISTANT-WIRE-CONTRACT.md` 那一行);本文件的 `migrationWindowOpen`(若再无别的读者)",
|
|
187
|
-
afterRemoval: "没有响亮臂(删码本身零行为变化:窗关那一刻起认领臂已经不生效):属主从没被记下的存量会话(边档那一格只有化身 —— 跳过了带本条的版本直接升," +
|
|
188
|
-
"或窗内从没被带 principal 提交过)照旧答无主(`headOf(id)?.owner` = null):它的会话规则这条路由读不了也改不了(409 `conflict.session_ownerless`)," +
|
|
189
|
-
"已存的规则对写下它们的 principal 的 run 照旧生效;出路 = 删会话(`DELETE /v1/sessions/:id`,规则随之删)",
|
|
190
|
-
reportKeys: [],
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
id: "M11",
|
|
194
|
-
introducedIn: "7.120.0",
|
|
195
|
-
releasedOn: "2026-10-08",
|
|
196
|
-
removableAfter: "2026-11-07",
|
|
197
|
-
removal: "删 migrateOn 的 M11 步(`permission_rule` 在场探针 + `purgeUndurableScopeRows` 调用)与 `permission-rule-store-sql.ts` 的 `purgeUndurableScopeRows` / " +
|
|
198
|
-
"`purgeOneBucket` / `contentFreeRefusal` / `UndurableScopeRuleRow` / `UnreadableRuleBucket` / `UndurableScopePurgeReadings` / " +
|
|
199
|
-
"`UndurableScopePurgeDb` / `UNDURABLE_PURGE_PAGE` / `UNDURABLE_PURGE_OCC_ATTEMPTS`、本文件的 `removedRuleRowNote`,以及 `BucketRefusedError` 的 `verdict` 位(若届时再无别的读者;" +
|
|
200
|
-
"判官 `decodeBucketRow` 与写法 `writeBucket` 是读腿 / 写臂本身,留);报告、日志行(含逐行的 `permission_rule_row_removed` 与逐桶的 " +
|
|
201
|
-
"`permission_rule_bucket_unreadable`)与 `NO_SQL_MIGRATIONS` 的 `undurableScopeRuleRows` / `undurableScopeRuleBucketsDeferred` / `undurableScopeRuleBucketsUnreadable`",
|
|
202
|
-
afterRemoval: "引擎读侧的既有响亮臂:scope root 不是完整绝对路径的存量行(跳过了带本条的版本直接升的库,或窗关之后别的写者写进来的)在有效视图里被丢、" +
|
|
203
|
-
"每次 run 一条 `permission.rule_row_dropped`(点名规则与 root)—— 那一行不参与任何检查,但撤销口删不动它(引擎的写臂对这种 scope 同样拒);" +
|
|
204
|
-
"出路 = 运维在库里把那只桶的那一行删掉(整桶 OCC 回写,指纹按 `buildRuleBucketChecksum` 重算)",
|
|
205
|
-
reportKeys: ["undurableScopeRuleRows", "undurableScopeRuleBucketsDeferred", "undurableScopeRuleBucketsUnreadable"],
|
|
206
|
-
},
|
|
207
184
|
{
|
|
208
185
|
id: "M12",
|
|
209
186
|
introducedIn: "7.122.0",
|
|
@@ -307,6 +284,9 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
307
284
|
"`test/task-a2a.test.ts` 里的克隆钉(标题去掉开头的 `🔴 ` 后以 `克隆钉:` 开头的各格,整格删;按这个精确前缀删,不按标题里的「M19 重读」之类泛词删 —— 那会误删同文件里的通用不变式钉),以及三格不带前缀、删码后要改写的钉:`需要「读」的两个键…` 那格的 `readRequestToolAxes` 调用方名单(`normalizeA2aPeer` 只在 M19 重读臂里调它,删后名单只剩 `mintPeerSnapshot`,标题里「与读器里 M19 重读产物的那一次」半句同删)、`读器与门的差别只有三格…` 改成两格(删 ③ 的注释行与标题里的 ③)、`请求入口快照的形…` 里 `snapshotRequestA2a(…, { reread: false })` 的第二实参(删 `reread` 形参后改成单参);" +
|
|
308
285
|
"`test/one-time-migration-window-gate.test.ts` 里 M19 一节中与克隆有关的三格(声明抽取器正负控 · 删法条与克隆名字两向对账 · 克隆钉标题前缀对账)与它们共用的帮手 `declaredNames`;" +
|
|
309
286
|
"`test/mcp-tool-axes-m19.test.ts`(窗关那一格 —— 存量坏形整条不进、warn 与通告点名 `field: toolAxes` —— 改钉到 `test/task-mcp.test.ts`);" +
|
|
287
|
+
"「请求成员读不出」一问上的重读座走线:`http/stored-body-replay.ts` 里递给 `unreadRequestMembers` 的 `storedToolAxes: storedToolAxesRereadM19(today)` 与它的 import," +
|
|
288
|
+
"`unread-request-members.ts` 的 `StoredToolAxesRereadM19` 型 import、`UnreadMembersLeg` 续跑臂的 `storedToolAxes` 字段与 `unreadRequestMembers` 里取它、递给两只谓词的那几处," +
|
|
289
|
+
"`task-mcp.ts` 的 `requestMcpTransportUnread` 与 `task-a2a.ts` 的 `requestA2aHeadersUnread` 的 `storedToolAxes` 形参(连同它们递给 `normalizeServer` / `normalizeA2aPeer` 的那一实参);" +
|
|
310
290
|
"本文件的 `migrationWindowOpen`(若再无别的读者)",
|
|
311
291
|
afterRemoval: "没有新的臂,接住它的是今天的读法(删码零行为变化:窗关那一刻起重读臂已经不生效):升级前存下的请求体里引擎判官判不过的 `toolAxes`,续跑重放时这一条 server 整条不进," +
|
|
312
292
|
"运维 warn `mcp_injection_dropped`(`reason: malformed_entry`、`field: toolAxes`)+ 用户面通告 `mcp.injection_dropped`,兄弟照挂;停驻在这台 server 工具审批上的任务" +
|
|
@@ -320,14 +300,16 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
320
300
|
introducedIn: "7.131.0",
|
|
321
301
|
releasedOn: "2026-10-16",
|
|
322
302
|
removableAfter: "2026-11-15",
|
|
323
|
-
removal: "删 `src/stored-request-hooks-m20.ts` 整只文件(`storedHooksRereadM20` / `rereadStoredHooksM20` / `StoredHooksRereadM20` / `
|
|
303
|
+
removal: "删 `src/stored-request-hooks-m20.ts` 整只文件(`storedHooksRereadM20` / `rereadStoredHooksM20` / `StoredHooksRereadM20` / `MATCHER_FIELD_NAMES` / `nodeAt` / `cloneDoc` / `removeKeyAt`);" +
|
|
324
304
|
"`boot/resolve-spec.ts` 里递给 `parseTaskSettings` 的重读座实参(`opts?.leg === \"fresh\" || !taskHooksHonored(config) ? {} : { storedHooksReread: storedHooksRereadM20(…) }`)与它的 import、" +
|
|
325
305
|
"`hooks_read_as_before_upgrade` 那一段 warn;`task-settings.ts` 的 `ParseTaskSettingsSeats` / `ParseTaskSettingsResult.hooksReread` / `parseTaskSettings` 第二形参与 hooks 臂里的重读那一支;" +
|
|
326
|
-
"`hooks/hook-runner.ts` 的 `ParseHooksConfigResult.pieces` / `HooksRefusalPiece`(若再无别的读者)
|
|
327
|
-
"
|
|
328
|
-
|
|
329
|
-
"
|
|
330
|
-
|
|
306
|
+
"`hooks/hook-runner.ts` 的 `ParseHooksConfigResult.pieces` / `HooksRefusalPiece`(若再无别的读者);" +
|
|
307
|
+
"「请求成员读不出」一问上的重读座走线:`unread-request-members.ts` 的 `storedHooksRereadM20` import 与 `unreadRequestMembers` 里 `hooksReread` 那一行(递给 `parseTaskSettings` 的 `storedHooksReread` 座)、" +
|
|
308
|
+
"`UnreadMembersLeg` 续跑臂的 `today` 字段(只为 M20 的窗问它)与 `http/stored-body-replay.ts`、`boot/resolve-spec.ts` 递 `today` 的那两处(`stored-body-replay.ts` 的 `today` 局部若 M19 已删再无读者一并删);" +
|
|
309
|
+
"`test/hooks-stored-reread-m20.test.ts`(窗关那一格 —— 续跑拒 409 `resume_blocked_by_policy` —— 改钉到 `test/hooks-entry-admission.test.ts` 的续跑腿组)",
|
|
310
|
+
afterRemoval: "没有新的臂,接住它的是今天的读法(删码零行为变化:窗关那一刻起重读臂已经不生效):升级前存下的请求体里带这两形的 `settings.hooks`,在会采纳 hooks 的车道上续跑被拒 —— " +
|
|
311
|
+
"「请求成员读不出」判据(`src/unread-request-members.ts`)答 409 `resume_blocked_by_policy`(`blockedBy: request.field_invalid`,`field: settings.hooks`),卡仍待决、行不动(7.147.0 起;此前是整份不采纳照跑)—— " +
|
|
312
|
+
"出路是取消这类停驻任务、删掉那个未知字段 / `__proto__` 键后重新提交。会撞上它的是活过窗的升级前停驻行:发布后才升级的部署、调长了 `APPROVAL_TERMINAL_BACKSTOP_MS` 的部署、滚动升级里旧副本在窗内新写的行(头注 M20 段)",
|
|
331
313
|
reportKeys: [],
|
|
332
314
|
},
|
|
333
315
|
{
|
|
@@ -505,10 +487,11 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
505
487
|
"`RETIRED_DEVICE_BINDING_TABLE` / `PARKED_DEVICE_BINDING_TABLE` / `FENCE_ROOTS_SHOWN`、`ExecutionPlacementSwitchRefusedError` / `EXECUTION_PLACEMENT_SWITCH_REFUSED_CODE` / `ExecutionPlacementSwitchRefusalReason`)" +
|
|
506
488
|
"与 DDL 前探针(`assertExecutionPlacementSwitchAdmissible` / `assertExecutionPlacementSwitchAdmissibleOnPool`,`store-backend.ts` 的 `withRetiredSchemaProbe` 里调它的那一行);" +
|
|
507
489
|
"`runSqlOneTimeMigrations` 的第三参 `ExecutionPlacementSwitchInput`(若再无别的条目用它)与它在两只 SQL 后端 / 测试夹具上的实参;local 腿(`LocalBackend.runOneTimeMigrations` 里的 `backfillLocalExecutionPlacements` 与 `FileRunStore.sessionIdsWithRuns`);" +
|
|
508
|
-
"`execution-placement-sql.ts` 的 `backfillWriterStatement` / `migrateDeviceBindingsStatement` / `countOrphanBindingsStatement`;报告、日志行与 `NO_SQL_MIGRATIONS` 的 `executionPlacementColumnsAdded` / `deviceBindingsMoved` / " +
|
|
490
|
+
"`execution-placement-sql.ts` 的 `backfillWriterStatement` / `migrateDeviceBindingsStatement` / `migrateDeviceBindingsOntoSideTableStatements` / `countOrphanBindingsStatement`;报告、日志行与 `NO_SQL_MIGRATIONS` 的 `executionPlacementColumnsAdded` / `deviceBindingsMoved` / " +
|
|
509
491
|
"`deviceBindingsOrphaned` / `deviceBindingTablesDropped` / `executionPlacementsBackfilled` / `executionPlacementSessionsUnreadable` 与 `device_bindings_orphaned` / `execution_placement_session_unreadable` 两行 warn;`test/execution-placement-switch-db-integration.test.ts` 整份与 `test/one-time-migrations.test.ts` 的 M32 组。" +
|
|
510
|
-
"**local 腿的回填席与它的点名词一并删**:`LocalSessionStore` 的 `executionPlacementBackfill`(属性与构造里的那一臂)
|
|
511
|
-
"`
|
|
492
|
+
"**local 腿的回填席与它的点名词一并删**:`LocalSessionStore` 的 `executionPlacementBackfill`(属性与构造里的那一臂)与它唯一的成员 `backfillPlacement`、`unusableArchiveOfFault`、" +
|
|
493
|
+
"`execution-placement.ts` 的 `LocalPlacementBackfillSeat` / `LocalPlacementBackfillOutcome` / `UnusableArchive` / `UnusableArchiveWord`(含它的 `storage` 词 —— 读存档文件时抛了别的故障、`errno` 随带,该词只有回填点名用)/ `isUnusableArchive`、" +
|
|
494
|
+
"`ExecutionPlacementSessionUnreadable`(会话店的观察与存档探针不随删:它们不带这几只型,说不出在不在就原样抛);" +
|
|
512
495
|
"`test/execution-placement-switch-local.test.ts` 与 `test/execution-placement-local-boot-unreadable-e2e.test.ts` 整份。" +
|
|
513
496
|
"**不随本条删**:执行放置八列、会话店的执行席、设备店的首绑 / 换绑两只写(常设的数据形)",
|
|
514
497
|
afterRemoval: "起服对账一族的跳版库拒启臂接住:删码同版把 `device_session` / `device_session_retired` 两张表加进退役 schema 判据(`schema-consistency.ts` 的跳版库探针,先于建表)⇒ " +
|
|
@@ -521,13 +504,14 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
521
504
|
releasedOn: "2026-10-30",
|
|
522
505
|
removableAfter: "2026-11-29",
|
|
523
506
|
removal: "删 `LocalSessionStore.migrateLocalArchives` 与它的私有助手 `anonymizeArchiveHeld` / `fillRowFacts`、`settleArchiveSnapshots` 里除最后一句常设臂 `assertNoArchiveSnapshots(dir)` 以外的一切(逐份消化的循环与 `settleArchiveSnapshot`)、" +
|
|
524
|
-
"`archiveSnapshotsSettled` 字段、`
|
|
507
|
+
"`archiveSnapshotsSettled` 字段、`rowFactsFilled` / `ARCHIVE_SNAPSHOT_RECORD` / `ArchiveSnapshotRecord` / `readArchiveSnapshotRecord` / `sameLog` / " +
|
|
508
|
+
"`ArchivedRowFacts` / `archivedRowFactsOf`(M47 仍在树时留着,随 M47 删)/ " +
|
|
525
509
|
"`ArchiveRewriteStep` / `LocalArchiveMigrationReading` / `errnoOf`、" +
|
|
526
|
-
"`archiveRewriteReadScope` / `noteReplayInArchiveRewriteRead` 与 `createLocalSessionRepo` 座里调它的那一腿、`SidecarMap.syncToDisk`(若再无别的调用方)
|
|
510
|
+
"`archiveRewriteReadScope` / `noteReplayInArchiveRewriteRead` 与 `createLocalSessionRepo` 座里调它的那一腿、`SidecarMap.syncToDisk`(若再无别的调用方);" +
|
|
527
511
|
"`store-backend.ts` 的 `LocalBackend.runOneTimeMigrations` 里对 `migrateLocalArchives` 的调用与报告五键的那五行;本文件的 `LocalArchiveKeptReason` / `LocalArchiveKeptStamped` / `LocalArchiveUnreadable`、" +
|
|
528
512
|
"报告 / 收据 / `changedAnything` / `readingsSnapshot` / `readingFields` 里的 `localArchiveRowFactsBackfilled` / `localArchivesAnonymized` / `localArchivesKeptStamped` / `localArchivesUnreadable` / `localArchiveSnapshotsRecovered`、" +
|
|
529
513
|
"`local_archive_kept_stamped` / `local_archive_unreadable` 两行 warn、读数行 note 里的 M33 句与头注 M33 段;`test/local-archive-owner.test.ts` 里标题含 `P3` / `P4` / `P5` / `P6` / `F1` / `F2` / `F3` 的格与 `legacyRoot` / `writeArchive` / `boot` / `M33_ZERO` / `m33Of` 助手。" +
|
|
530
|
-
"**不随本条删**:行格的 `createdAt` / `forkedFrom` 两键(常设的数据形)、`LocalArchiveSnapshotsPresentError` / `assertNoArchiveSnapshots` / `LOCAL_ARCHIVE_SNAPSHOT_DIR` 与 `LocalBackend.ensureSchema` 里调它的那一句、" +
|
|
514
|
+
"**不随本条删**:行格的 `createdAt` / `forkedFrom` 两键(常设的数据形)、存档目录屏障 `syncArchiveDirectory` 与 `fsyncPaths`(会话删序的常设一步)、`LocalArchiveSnapshotsPresentError` / `assertNoArchiveSnapshots` / `LOCAL_ARCHIVE_SNAPSHOT_DIR` 与 `LocalBackend.ensureSchema` 里调它的那一句、" +
|
|
531
515
|
"`session-error-wire.ts` 的 `StampedSessionArchiveError` / `STAMPED_SESSION_ARCHIVE_SENTENCE` / `sessionErrorWireOf` 与本店带戳判的唯一读口 `assertArchiveAnonymous`(fork 的源、改日志推送的落点、会话同步导入第一阶段的早拒三处问它)、行上缺建档时刻的 F 类读法(`server.local-session-row.created-at-absent`)",
|
|
532
516
|
afterRemoval: "三只常设臂接住:① 数据根下的快照目录非空 ⇒ 拒启(`config.local_archive_snapshot_present`,点名文件与两条出路);② 跳过了带本条的版本直接升的数据根(或本条留着的存档),带属主戳的存档被 fork、改日志的推送与会话同步导入第一阶段对 fork / stale 的早拒同一只具名拒(409 `conflict.session_archive_stamped` + 固定句,零写 / 行格净零写)," +
|
|
533
517
|
"读 / 续跑 / 拉取照常 —— 出路 = 删掉会话后重推,或升级时先过一次带本条的版本并在窗内起服;③ 行上没有建档时刻的格(同一类数据根)⇒ 列表 / 会话视图 / 交出的元数据读纪元(F 类 tag 计数)",
|
|
@@ -570,13 +554,13 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
570
554
|
"删什么:`src/plugins/imported-layer-root-retirement.ts` 整个文件;migrateStepsOn 的 M36 步(规则表与 `grammar` 列的在场探针 + 对 `retireImportedLayerRootAllows` 的调用)与握锁连接上的 `query` 口" +
|
|
571
555
|
"(`LockedMigrationDb` 与 `mysqlDb` / `pgDb` 里的那一员,若届时再无别的步骤用它);`permission-rule-store-sql.ts` 的 `listRuleBucketOwners` / `isSqlBucketRefusal` / `isSqlBucketVanished` / `RuleBucketVanishedError`(取点那一句的具名类,届时若再无别的读者按类判它,收回成裸错)/ `IMPORT_RECORD_KIND`;" +
|
|
572
556
|
"`permission-rule-store-file.ts` 的 `FileRuleApprovalRecordStore.importRecordOwners` / `fileRuleBucketOwners` / `isFileBucketDamaged`;`store-backend.ts` 的 `LocalBackend.runOneTimeMigrations` 里 M36 那一腿(规则目录在场判与那一处调用)与报告两键的那两行;" +
|
|
573
|
-
"本文件的 `createSqlImportedLayerRootSource` 与 `importedLayerRootAllowsRetired` / `importedLayerRootBucketsSkipped`(报告 / 收据 / `changedAnything` / `readingsSnapshot` / `readingFields` / `receiptSentence` / `NO_SQL_MIGRATIONS` 的排除表)、" +
|
|
574
|
-
"`imported_layer_root_allow_retired` / `imported_layer_root_bucket_skipped`
|
|
557
|
+
"本文件的 `createSqlImportedLayerRootSource` 与 `importedLayerRootAllowsRetired` / `importedLayerRootBucketsSkipped` / `importedLayerRootBucketsUnnamed`(报告 / 收据 / `changedAnything` / `readingsSnapshot` / `readingFields` / `receiptSentence` / `NO_SQL_MIGRATIONS` 的排除表)、" +
|
|
558
|
+
"`imported_layer_root_allow_retired` / `imported_layer_root_bucket_skipped` / `imported_layer_root_buckets_unnamed` 三行 warn 与 `importedLayerRootSkipNote`、读数行 note 里的 M36 句与头注 M36 段;" +
|
|
575
559
|
"`test/imported-layer-root-retirement.test.ts`、`test/imported-layer-root-retirement-db-integration.test.ts`(连同 `scripts/db-integration-files.json` 里它那一行)与 `test/helpers/imported-layer-root-fixture.ts` 整文件。" +
|
|
576
560
|
"**不随本条删**:`SqlDurableRulePartitionProvider` 收「方言 + 执行口」的那一形(`BucketSql`;常设,池照旧满足它)",
|
|
577
561
|
afterRemoval: "没有响亮臂(如实):删码之后,跳过了带本条的版本直接升的库(或回滚到引擎 7.61.0 之前、在其上又导入过的库),存量的这种全局 `/x` allow 照旧在每个项目根放行,本服务不再点名 —— " +
|
|
578
562
|
"出路 = 升级时先过一次带本条的版本并起服;或运维列出桶里出处为导入(`adds[].origin` = `imported-cc`)、scope 为全局、从 `/` 写起的 allow(`GET /v1/rules`)并撤掉(`DELETE /v1/rules`,撤的是这条规则的全部批准)",
|
|
579
|
-
reportKeys: ["importedLayerRootAllowsRetired", "importedLayerRootBucketsSkipped"],
|
|
563
|
+
reportKeys: ["importedLayerRootAllowsRetired", "importedLayerRootBucketsSkipped", "importedLayerRootBucketsUnnamed"],
|
|
580
564
|
},
|
|
581
565
|
{
|
|
582
566
|
id: "M37",
|
|
@@ -604,6 +588,174 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
604
588
|
"出路是取消那条 run,把凭据挪进引擎进程环境后重新提交。会撞上它的是活过窗的升级前停驻行:发布后才升级的部署、调长了 `APPROVAL_TERMINAL_BACKSTOP_MS` 的部署、滚动升级里旧副本在窗内新写的行、窗内续跑过又停驻到窗外的任务(头注 M38 段)",
|
|
605
589
|
reportKeys: [],
|
|
606
590
|
},
|
|
591
|
+
{
|
|
592
|
+
id: "M39",
|
|
593
|
+
introducedIn: "7.147.0",
|
|
594
|
+
releasedOn: "2026-11-07",
|
|
595
|
+
removableAfter: "2026-12-07",
|
|
596
|
+
removal: "删 `src/plugins/local-data-dir-modes-m39.ts` 整只文件;`store-backend.ts` 里 `LocalBackend.runOneTimeMigrations` 开头调它的那一段(两只日志座的接线)、`dataDirLayout` 字段与它的赋值、顶部的 import(含 `memoryEngineRootFor`),以及 `runOneTimeMigrations` 与 `discloseWarn` 注释里点名 M39 的那两句;" +
|
|
597
|
+
"各店为名册导出的目录路径函数(`fileRunStoreDirsFor` / `localCheckpointStoreDirsFor` / `attachmentStoreDirFor` / `scratchpadRootFor` / `memorySyncCursorDirFor`)只剩本店自己读的去掉 `export` 与注释里的 M39 一句(`pluginCacheRootFor` 组合根仍读,留);" +
|
|
598
|
+
"`test/data-dir-modes-upgrade-m39.test.ts` 整只文件;`test/data-dir-law-census.test.ts` 例外名册里 `plugins/local-data-dir-modes-m39.ts` 那一行、模式值例外名册里它那一行、「M39 名册零字面路径」一格与「字面量 = ensureDir 铸出的模式」一格里的迁移半场;本文件头注 M39 段;重生成 `docs/core-consumption/READ-TABLE.json`(迁移读 core 的 `physicalPathOf` 那一行随之去掉)。" +
|
|
599
|
+
"**不随本条删**:数据根建目录只经 `ensureDir` 这条律本身(常设)、`plugins/owner-only-file-mode.ts`(本服务文件的 `0600` 唯一值与原子写的两个出口:异步出口常设,同步出口按它自己的退役条件 —— core 的原子写改成独占新建 tmp —— 走,不随本条)及它们的钉 —— `test/data-dir-law-census.test.ts`(`src/**` 零裸 mkdir、零手写 0o700、文件模式只认一个名字、tmp 只在一只写口里铸)与 `test/data-dir-modes.test.ts`(每只 local 店首建目录 0700、旧 tmp 不被复用)",
|
|
600
|
+
afterRemoval: "没有响亮臂(如实,也无需):删码之后,跳过了带本条的版本直接升的数据根,升级前铸成的 0755 目录原样留着(新建的目录一律 0700,不受影响;里面的文件多半仍是 0600),本服务不再点名 —— " +
|
|
601
|
+
"出路 = 运维一次 `chmod 700` 数据根下 `runs`(及其子目录)· `space-commits` · `checkpoint-ctx` · `.tmp` · `attachments` · `scratchpad`(及其子目录)· `plugin-cache`(及其子目录)· `<记忆引擎根>/sync-cursors`,或升级时先过一次带本条的版本并起服",
|
|
602
|
+
reportKeys: [],
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
id: "M40",
|
|
606
|
+
introducedIn: "7.147.0",
|
|
607
|
+
releasedOn: "2026-11-07",
|
|
608
|
+
removableAfter: "2026-12-07",
|
|
609
|
+
removal: "删 `src/plugins/execution-lane-rename-m40.ts` 整只文件;本文件的 M40 步(`renameRetiredExecutionLaneWordsM40` / `refuseWhileRunsHeartbeat`〔它读的 `readLiveRunHeartbeat` / `LiveRunHeartbeat` 由 M41 / M42 共读,两条也已删码时随之删〕/ `ExecutionLaneRenameRefusedError` / " +
|
|
610
|
+
"`EXECUTION_LANE_RENAME_REFUSED_CODE` / `ExecutionLaneRenameInput`,`migrateStepsOn` 第一步那一行与 `SqlOneTimeMigrationInput` 里的那一半)、报告 / 收据 / 日志 / `NO_SQL_MIGRATIONS` 的 `executionLaneWordsRenamed`、头注 M40 段;" +
|
|
611
|
+
"`store-backend.ts` 的 `LocalBackend.ensureSchema` 第一步与 `executionLaneWordsRenamed` 字段、两只 SQL 后端递 `liveRunWindowMs` 的那一半;" +
|
|
612
|
+
"`LocalSessionStore.renameRetiredExecutionLaneWordM40`、`FileApprovalAskStore.renameRetiredExecutionLaneWordM40` 与内核的 `renameExecutionLaneWord`;" +
|
|
613
|
+
"`approval-ask-store-sql.ts` / `execution-placement-sql.ts` 拒句里的 `retiredExecutionLaneHintM40(…)` 补句;`test/execution-lane-rename-m40.test.ts` 整只文件与 `test/execution-placement-switch-db-integration.test.ts` 的 M40 组",
|
|
614
|
+
afterRemoval: "既有读口的拒臂接住(响亮,不再改名):仍带旧词的行 —— 跳过了带本条的版本直接升的库、窗关之后还在写的更早版本副本 —— SQL 问行读口拒、会话执行格读口拒(`ExecutionPlacementRowError`)," +
|
|
615
|
+
"local 会话元数据边档整只严格拒启(`config.schema_mismatch`),local 问账日志由 M32 回填的词表外拒臂拒启(M32 删码之后:那只问行原样装回)。出路 = 升级时先过一次带本条的版本并起服",
|
|
616
|
+
reportKeys: ["executionLaneWordsRenamed"],
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
id: "M41",
|
|
620
|
+
introducedIn: "7.147.0",
|
|
621
|
+
releasedOn: "2026-11-07",
|
|
622
|
+
removableAfter: "2026-12-07",
|
|
623
|
+
removal: "删本文件的 M41 步(`moveSessionCellsToSideTable` / `refuseSessionExtMoveWhileRunsHeartbeat` / `deploymentColumnsOnMeta` / `SessionExtMoveRefusedError` / `SESSION_EXT_MOVE_REFUSED_CODE` / " +
|
|
624
|
+
"`SessionExtMoveRefusalReason` / `sameCell` / `SESSION_EXT_MOVE_PAGE`,`migrateStepsOn` 里那两行)、报告 / 收据 / 日志 / `NO_SQL_MIGRATIONS` 的 `sessionExtRowsMoved` / `sessionMetaColumnsDropped`、头注 M41 段;" +
|
|
625
|
+
"M32 读形里的 `cellsOnSideTable` 判(它读本条的 `deploymentColumnsOnMeta`):M32 还在时改成恒旁表形 —— 删 M32 写 `session_meta` 八列的那些臂(② ④ ④b ⑥ 与 ③ 的 `migrateDeviceBindingsStatement` 臂)," +
|
|
626
|
+
"留 ③ 的旁表臂(`migrateDeviceBindingsOntoSideTableStatements`:围栏拒句的「采旧」在任何库上仍要能落到执行格);M32 先于本条删码时这些随 M32 一并删;`readLiveRunHeartbeat` 在 M40 与 M42 也已删码时随之删;`test/session-ext-move-db-integration.test.ts` 整只文件",
|
|
627
|
+
afterRemoval: "跳过了带本条的版本直接升上来的库:`session_meta` 上仍带部署格列 ⇒ 起服列册对账拒启(`config.schema_mismatch`,那几列是本树之外的多余列,拒句不给 ALTER —— 出路是带本条的版本);" +
|
|
628
|
+
"部署格从旁表读,旧列上的值不被任何读者读。出路 = 升级时先过一次带本条的版本并起服",
|
|
629
|
+
reportKeys: ["sessionExtRowsMoved", "sessionMetaColumnsDropped"],
|
|
630
|
+
dropsColumns: { session_meta: SESSION_EXT_MOVED_COLUMNS.map((c) => c.name) },
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
id: "M42",
|
|
634
|
+
introducedIn: "7.148.0",
|
|
635
|
+
releasedOn: "2026-11-08",
|
|
636
|
+
removableAfter: "2026-12-08",
|
|
637
|
+
removal: "删 `src/plugins/scenario-prefix-switch-m42.ts` 整只文件;本文件的 M42 步(`switchScenarioPrefixM42` / `scannedIdentityColumnsM42`,`migrateStepsOn` 第一步那一行)、报告 / 收据 / 日志的 `scenarioPrefixSourcesScanned`、头注 M42 段;" +
|
|
638
|
+
"`readLiveRunHeartbeat` / `LiveRunHeartbeat` 在 M40 与 M41 也已删码时随之删;`store-backend.ts` 的 `LocalBackend.runOneTimeMigrations` 里 M42 那一腿(`switchLocalScenarioPrefixM42`)与四只 File 店的 `scenarioPrefixOwnerRowsM42`(run / 会话 / 问 / 附件);`test/scenario-prefix-switch-m42.test.ts` 与 `test/scenario-prefix-switch-db-integration.test.ts` 两只文件。" +
|
|
639
|
+
"标记表的属主 `one-time-migration-marker.ts` 在 M43 也已删码时随之删;库里留下的标记表 / 数据根里的标记文件无人再读,不删(起服列册对账只核本树声明的表)",
|
|
640
|
+
afterRemoval: "没有响亮臂(如实):跳过了带本条的版本直接升的库,存量里以 `_scn:` 开头的身份被恢复管线读作某个人的场景(拆不出合文法的场景与人的 ⇒ `owner.malformed_subject` 响亮)。" +
|
|
641
|
+
"出路 = 升级时先过一次带本条的版本并起服(它扫一次、命中即拒启点名)",
|
|
642
|
+
reportKeys: ["scenarioPrefixSourcesScanned"],
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
id: "M43",
|
|
646
|
+
introducedIn: "7.148.0",
|
|
647
|
+
releasedOn: "2026-11-08",
|
|
648
|
+
removableAfter: "2026-12-08",
|
|
649
|
+
removal: "删本文件的 M43 步(`markWithdrawEnabledM43`,`migrateStepsOn` 里那一行)、报告 / 收据 / 日志 / `NO_SQL_MIGRATIONS` 的 `withdrawMarkWritten`、头注 M43 段;" +
|
|
650
|
+
"`plugins/session-withdraw-sql.ts` 的 `WITHDRAW_MARK_ID` 与部署判据里读标记的那一句(撤回出口无条件启用);标记表 `one-time-migration-marker.ts` 在 M42 也已删码时随之删、`plugins/session-birth.ts` 的 `upgrade_pending` 词与出口计数里的同名词;" +
|
|
651
|
+
"local 会话元数据格「没有 `clientWrites` 位 ⇒ upgrade_pending」那一臂;库里留下的标记行无人再读,不删(与 M42 同一张标记表)",
|
|
652
|
+
afterRemoval: "窗 30 天之后更早版本的副本早已不在;标记行不再被任何读者读(留着无害)。跳过了带本条的版本直接升上来的库:撤回出口从第一次起服就启用 —— " +
|
|
653
|
+
"跨两版以上的混跑本就不被支持(7.147.0 起的停-迁-起)。出路 = 升级时先过一次带本条的版本并起服",
|
|
654
|
+
reportKeys: ["withdrawMarkWritten"],
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
id: "M44",
|
|
658
|
+
introducedIn: "7.148.0",
|
|
659
|
+
releasedOn: "2026-11-08",
|
|
660
|
+
removableAfter: "2026-12-08",
|
|
661
|
+
removal: "删本文件的 M44 步(`rewriteRunErrorCodeColumnM44`,`migrateStepsOn` 里那一行)、报告 / 收据 / 日志 / `NO_SQL_MIGRATIONS` 的 `runErrorCodeColumnRewritten`、头注 M44 段;" +
|
|
662
|
+
"`run-store-sql.ts` 的读侧半场 `m44ErrorCodeReadSide`(行映射的码改成只读列;窗内停驻行列空时读结果体的码)与 `decodeRunResultCellM44`;" +
|
|
663
|
+
"local 腿 `FileRunStore.migrateRunErrorCodeColumnM44` 与 `LocalBackend.runOneTimeMigrations` 里那一格;`test/run-error-code-column.test.ts` 的 M44 组与双库集成文件的 M44 组",
|
|
664
|
+
afterRemoval: "没有响亮臂(如实):跳过了带本条的版本直接升上来的库,旧行按列答 —— 停驻两口在列建立之前写下的 `needs_review` 行 `errorCode` 缺席(`review.pending` 仍在 `result` 里)、" +
|
|
665
|
+
"列里是没折过的原码的旧行答原码;`result.terminal.code` 仍在 `result` 里。调长了停驻终局兜底(`APPROVAL_TERMINAL_BACKSTOP_MS` > 30 天)的部署,窗关时还可能有更早版本写下的停驻没结清,读法同上。" +
|
|
666
|
+
"出路 = 升级时先过一次带本条的版本并起服",
|
|
667
|
+
reportKeys: ["runErrorCodeColumnRewritten"],
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
id: "M45",
|
|
671
|
+
introducedIn: "7.148.0",
|
|
672
|
+
releasedOn: "2026-11-08",
|
|
673
|
+
removableAfter: "2026-12-08",
|
|
674
|
+
removal: "删 `src/plugins/run-preview-m45.ts` 整个文件;本文件的 M45 步(`rewriteRunObjectivePreviewM45`,`migrateStepsOn` 里那一行)、报告 / 收据 / 日志 / `NO_SQL_MIGRATIONS` 的 `runObjectivePreviewRewritten`、头注 M45 段;" +
|
|
675
|
+
"local 腿 `FileRunStore.migrateRunObjectivePreviewM45` 与 `LocalBackend.runOneTimeMigrations` 里那一格;" +
|
|
676
|
+
"`test/run-preview-m45.test.ts` 与 `test/helpers/run-preview-m45-rows.ts` 整个文件、`test/session-preview-single-source-db-integration.test.ts` 的 M45 组",
|
|
677
|
+
afterRemoval: "没有响亮臂(如实):跳过了带本条的版本直接升上来的库,7.124.0 之前写下的、以注入块起头的预览照旧按列答 —— 会话列表 / `GET /v1/tasks` / 助手任务行名 / 收件箱上显示那段块文本。" +
|
|
678
|
+
"出路 = 升级时先过一次带本条的版本并起服",
|
|
679
|
+
reportKeys: ["runObjectivePreviewRewritten"],
|
|
680
|
+
},
|
|
681
|
+
{
|
|
682
|
+
id: "M46",
|
|
683
|
+
introducedIn: "7.148.0",
|
|
684
|
+
releasedOn: "2026-11-08",
|
|
685
|
+
removableAfter: "2026-12-08",
|
|
686
|
+
removal: "删 `src/plugins/approval-exemption-skill-m46.ts` 整个文件;本文件的 M46 步(`dropLegacySkillExemptionsM46`,`migrateStepsOn` 里那一行)、报告 / 收据 / 日志 / `NO_SQL_MIGRATIONS` 的 `legacySkillExemptionsDropped`、头注 M46 段、`logReceiptRows` 里的 `legacy_skill_exemptions_dropped` 一行;" +
|
|
687
|
+
"`approval-exemption-store.ts` 的 `FileApprovalExemptionStore.dropToolRowsCreatedBeforeM46` 与 `LocalBackend.runOneTimeMigrations` 里那一格;" +
|
|
688
|
+
"`test/approval-exemption-skill-m46.test.ts` 整个文件、`test/one-time-migrations-db-integration.test.ts` 的 M46 组;标记表 `one-time-migration-marker.ts` 在 M42 / M43 也已删码时随之删(库里留下的 `M46` 标记行与数据根里的标记文件无人再读,不删)",
|
|
689
|
+
afterRemoval: "没有响亮臂(如实):跳过了带本条的版本直接升上来的库,7.116.0 之前写下的 `(会话, \"Skill\")` 豁免行照旧代答「不绑授予」的同名调用 —— 部署自挂一只叫 `Skill` 的工具、没有技能时," +
|
|
690
|
+
"那个人当年批的是「激活某技能」,代答的却是这只工具的调用。出路 = 升级时先过一次带本条的版本并起服(或运维手工删那些行:`DELETE FROM approval_exemption WHERE tool_name = 'Skill'` / 删会话)",
|
|
691
|
+
reportKeys: ["legacySkillExemptionsDropped"],
|
|
692
|
+
},
|
|
693
|
+
{
|
|
694
|
+
id: "M47",
|
|
695
|
+
introducedIn: "7.148.0",
|
|
696
|
+
releasedOn: "2026-11-08",
|
|
697
|
+
removableAfter: "2026-12-08",
|
|
698
|
+
removal: "删 `LocalSessionStore.adoptArchiveTokensM47`(含欠账起服的 `required` 分档、证明 `assertArchiveTokensAdoptedM47` / `adoptionScopeOf` / `skippedFromAdoption` 与它那一处销账)与 `LocalArchiveTokenAdoption`、`archiveTokenAdoptionCarried`;" +
|
|
699
|
+
"收令牌欠账的记账(`recordArchiveTokenAdoptionPending`);窗内长第一格的规则 `firstCellIncarnationOf` / `LocalSessionStore.firstCellIncarnationHeld`(调用点 —— 补铸、登记、执行位回填、M33 的行回填与快照恢复 —— 回到新铸);" +
|
|
700
|
+
"`holdArchiveTokenAdoptionDuty` 的 `adoptionCarried` 参数与记账那一支、`store-backend.ts` 判前钩里传它的那一处(臂恒判);" +
|
|
701
|
+
"`LocalBackend.ensureSchema` 里对 `adoptArchiveTokensM47` 的调用与两只读数字段、`runOneTimeMigrations` 里报告两键那几行;报告 / 收据 / `changedAnything` / `readingFields` / `NO_SQL_MIGRATIONS` 的 `localArchiveTokensAdopted` / `localArchiveTokensMinted`、头注 M47 段;" +
|
|
702
|
+
"M33 也已删码时连同 `archivedRowFactsOf` / `ArchivedRowFacts`;`test/local-root-one-row-store.test.ts` 里标题含 `P3` / `P4` 的格。" +
|
|
703
|
+
"**不随本条删**:跳版拒启臂 `holdArchiveTokenAdoptionDuty`(不带本条那一支:标记在而无格存档为零 ⇒ 销账放行)/ `archiveIdsWithoutCellSync` / `archiveTokenAdoptionPendingPresent` / `dischargeArchiveTokenAdoptionPending` / `ARCHIVE_TOKEN_ADOPTION_SINCE`、读数种别 `skipped-required-migration` 与它按高水位分支的拒句(常设)",
|
|
704
|
+
afterRemoval: "跳版拒启臂接住(常设,起服对账一族、数据根打开那一刻、引擎高水位抬之前):(打开之前的引擎高水位早于 7.148.0 或缺席 ∨ 数据根里的收令牌欠账标记还在 —— 带本条的版本打开过、没收完)" +
|
|
705
|
+
"∧ 根里有存档在而会话元数据格缺的会话 ⇒ 拒启 `config.schema_mismatch`(读数种别 `skipped-required-migration`,点名会话数与版本),零写、不抬高水位 —— " +
|
|
706
|
+
"出路 = 先用一个仍带本条、不低于 7.148.0 且不低于已记高水位的版本(服务或 run-local)完整起一次,再升",
|
|
707
|
+
reportKeys: ["localArchiveTokensAdopted", "localArchiveTokensMinted"],
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
id: "M48",
|
|
711
|
+
introducedIn: "7.148.0",
|
|
712
|
+
releasedOn: "2026-11-08",
|
|
713
|
+
removableAfter: "2026-12-08",
|
|
714
|
+
removal: "删 `src/plugins/shell-sentinel-owner-m48.ts` 整个文件;本文件的 M48 步(`clearShellSentinelOwnersM48`,`migrateStepsOn` 里那一行)、报告 / 收据 / 日志的 `shellSentinelOwnersCleared`、头注 M48 段;" +
|
|
715
|
+
"`SqlOneTimeMigrationInput` 里 M48 那一半(`ShellSentinelOwnerInput`)与它在两只 SQL 后端 / 测试夹具上的实参(`identityBoundary`);" +
|
|
716
|
+
"local 腿 `LocalSessionStore.clearShellSentinelOwnersM48` / `FileRunStore.clearShellSentinelOwnersM48` 与 `LocalBackend.runOneTimeMigrations` 里那一格(连同后端的 `identityBoundary` 字段);部署形表行 `identityBoundary` 不随删(dev-open 判据读它);" +
|
|
717
|
+
"`test/shell-sentinel-owner-m48.test.ts` 整个文件、`test/one-time-migrations-db-integration.test.ts` 的 M48 组",
|
|
718
|
+
afterRemoval: "没有响亮臂(如实):没有身份边界的部署跳过了带本条的版本直接升上来,哨兵属主的存量行仍记着那个字面量,属主面表已不认它 —— 不带主体的本地单用户读不到、续不上那些会话与 run(404)," +
|
|
719
|
+
"带同一个头的请求仍读得到(属主相同)。出路 = 升级时先过一次带本条的版本并起服(或运维手工 `UPDATE <表> SET owner = NULL WHERE owner = 'anon:shell-live'`,三张表见删法)。" +
|
|
720
|
+
"有身份边界的部署本条本来就零改写,删码前后同答(哨兵是一位普通的具名属主)",
|
|
721
|
+
reportKeys: ["shellSentinelOwnersCleared"],
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
id: "M49",
|
|
725
|
+
introducedIn: "7.148.0",
|
|
726
|
+
releasedOn: "2026-11-08",
|
|
727
|
+
removableAfter: "2026-12-08",
|
|
728
|
+
removal: "删本文件的 M49 步(`backfillCheckpointHostSessionsM49`,`migrateStepsOn` 里那一行)与 `HOST_SESSION_BACKFILL_PAGE`、报告 / 收据 / 日志的 `checkpointHostSessionsBackfilled`、头注 M49 段;" +
|
|
729
|
+
"local 腿 `LocalCheckpointStore.backfillHostSessionsM49` 与 `LocalBackend.runOneTimeMigrations` 里那一格;`test/checkpoint-host-session.test.ts` 的 M49 组、" +
|
|
730
|
+
"`test/one-time-migrations-db-integration.test.ts` 的 M49 组。**不随本条删**:`host_session_id` 列、写口的 `hostSessionOf`、按 run 找卡的读口(常设)",
|
|
731
|
+
afterRemoval: "没有响亮臂(如实):跳过了带本条的版本直接升上来的库,升级前停下、升级后仍挂着的卡归属为空 —— 按 run 找卡的读口找不到它:取消那条 run 不作废它、" +
|
|
732
|
+
"两条停驻收割把那条 run 当成「卡已不在」收掉(`approval.expired`)、决断答 409 `conflict.resume_context_unavailable`,卡由终局兜底收割收走。出路 = 升级前答完 / 拒掉停驻的卡," +
|
|
733
|
+
"或升级时先过一次带本条的版本并起服(或运维手工 `UPDATE checkpoint SET host_session_id = session_id WHERE host_session_id IS NULL`)",
|
|
734
|
+
reportKeys: ["checkpointHostSessionsBackfilled"],
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
id: "M50",
|
|
738
|
+
introducedIn: "7.148.0",
|
|
739
|
+
releasedOn: "2026-11-08",
|
|
740
|
+
removableAfter: "2026-12-08",
|
|
741
|
+
removal: "删 `src/plugins/approval-ask-retired-delete-by-task-m50.ts` 整只文件(`RETIRED_DELETE_BY_TASK_OP_M50` / `retiredDeleteByTaskReplayOpenM50` / `retiredDeleteByTaskClosedWhyM50`);" +
|
|
742
|
+
"`approval-ask-store-file.ts` 重放里认它的那一段(`replayRecord` 里 `probe.op === RETIRED_DELETE_BY_TASK_OP_M50` 一段)、`retiredDeleteByTaskRecordsM50` 计数与构造器末段那一行 stderr、那一行 import、顶注里随 M50 的那半句;" +
|
|
743
|
+
"`approval-ask-store-memory.ts` 的 `deleteByTaskM50`;`test/approval-ask-session-cascade.test.ts` 的 M50 组(窗内 / 窗关当天 / 窗关次日 / 坏记录四格与 `withM50Window` 助手);本文件头注 M50 段",
|
|
744
|
+
afterRemoval: "既有的词表外动词拒启(`approval-ask-store-file.ts` 重放的动词闭集判,拒句点名账本路径,出路 = 用写下它的那一版起服一次或把文件挪开)—— 与窗关之后本条自己的拒启同一个结局,删码零行为变化。" +
|
|
745
|
+
"会撞上它的是窗内一次都没在带本条的版本上起过服的 local 数据根(跳过本版直接升的),账本里又恰好留着一条嵌入方写下的这只词",
|
|
746
|
+
reportKeys: [],
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
id: "M51",
|
|
750
|
+
introducedIn: "7.148.0",
|
|
751
|
+
releasedOn: "2026-11-08",
|
|
752
|
+
removableAfter: "2026-12-08",
|
|
753
|
+
removal: "删本文件的 M51 步(`switchSessionDeletingM51` / `SessionDeletingSwitchRefusedError` / `SESSION_DELETING_SWITCH_REFUSED_CODE` / `SESSION_DELETING_MARK_ID`,`migrateStepsOn` 里那一行)、" +
|
|
754
|
+
"报告 / 收据 / `changedAnything` / `readingFields` / `NO_SQL_MIGRATIONS` 的 `sessionDeletingSwitchMarked`、头注 M51 段;`test/session-deleting-state-db-integration.test.ts` 的 M51 组;" +
|
|
755
|
+
"标记表 `one-time-migration-marker.ts` 在 M42 / M43 / M46 也已删码时随之删(库里留下的 `M51` 标记行无人再读,不删)。**不随本条删**:在删态本身(列、围栏、规则 L 的在删半、终刀判令牌 —— 常设)",
|
|
756
|
+
afterRemoval: "没有响亮臂(也无需):窗 30 天之后更早版本的副本早已不在;跳过了带本条的版本直接升上来的库 —— 跨两版以上的混跑本就不被支持(7.147.0 起的停-迁-起)。出路 = 升级时先过一次带本条的版本并起服",
|
|
757
|
+
reportKeys: ["sessionDeletingSwitchMarked"],
|
|
758
|
+
},
|
|
607
759
|
];
|
|
608
760
|
export function migrationWindowOpen(window, today) {
|
|
609
761
|
return window.removableAfter === null || today <= window.removableAfter;
|
|
@@ -616,12 +768,23 @@ export function migrationWindowEnd(id) {
|
|
|
616
768
|
throw new Error(`one-time-migrations: ${id} is in the unreleased form (removableAfter: null) — there is no window end to quote yet`);
|
|
617
769
|
return row.removableAfter;
|
|
618
770
|
}
|
|
771
|
+
export function columnsRemovedByPendingMigrations(registry = ONE_TIME_MIGRATIONS) {
|
|
772
|
+
const removals = new Map();
|
|
773
|
+
for (const row of registry) {
|
|
774
|
+
for (const [table, columns] of Object.entries(row.dropsColumns ?? {})) {
|
|
775
|
+
const owners = removals.get(table) ?? new Map();
|
|
776
|
+
for (const column of columns) {
|
|
777
|
+
const owner = owners.get(column);
|
|
778
|
+
if (owner !== undefined)
|
|
779
|
+
throw new Error(`one-time-migrations: ${table}.${column} is claimed as dropped by both ${owner} and ${row.id} — one column has one dropping migration`);
|
|
780
|
+
owners.set(column, row.id);
|
|
781
|
+
}
|
|
782
|
+
removals.set(table, owners);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
return removals;
|
|
786
|
+
}
|
|
619
787
|
export const NO_SQL_MIGRATIONS = {
|
|
620
|
-
workflowParkIndexKey: "file-ledger",
|
|
621
|
-
workflowParkIndexRowsCarried: 0,
|
|
622
|
-
undurableScopeRuleRows: [],
|
|
623
|
-
undurableScopeRuleBucketsDeferred: 0,
|
|
624
|
-
undurableScopeRuleBucketsUnreadable: [],
|
|
625
788
|
sessionRuleColumn: "file-store",
|
|
626
789
|
sessionRuleRowsWithRetiredBuckets: [],
|
|
627
790
|
sessionRuleRowsWithOldGrammarEntries: [],
|
|
@@ -647,6 +810,10 @@ export const NO_SQL_MIGRATIONS = {
|
|
|
647
810
|
deviceBindingsMoved: 0,
|
|
648
811
|
deviceBindingsOrphaned: 0,
|
|
649
812
|
deviceBindingTablesDropped: 0,
|
|
813
|
+
sessionExtRowsMoved: 0,
|
|
814
|
+
sessionMetaColumnsDropped: 0,
|
|
815
|
+
withdrawMarkWritten: 0,
|
|
816
|
+
sessionDeletingSwitchMarked: 0,
|
|
650
817
|
askCauseColumnsChanged: 0,
|
|
651
818
|
askParkTriggersMoved: 0,
|
|
652
819
|
};
|
|
@@ -703,7 +870,7 @@ async function columnExists(db, dialect, table, column) {
|
|
|
703
870
|
return (await db.rows(sql)).length > 0;
|
|
704
871
|
}
|
|
705
872
|
export function createSqlImportedLayerRootSource(exec) {
|
|
706
|
-
return { candidateOwners: () => listRuleBucketOwners(exec), durable: new SqlDurableRulePartitionProvider(exec), isWholeBucketRefusal: isSqlBucketRefusal, isVanishedBucket: isSqlBucketVanished };
|
|
873
|
+
return { candidateOwners: async () => ({ owners: await listRuleBucketOwners(exec), unnamedBuckets: 0 }), durable: new SqlDurableRulePartitionProvider(exec), isWholeBucketRefusal: isSqlBucketRefusal, isVanishedBucket: isSqlBucketVanished };
|
|
707
874
|
}
|
|
708
875
|
export async function runSqlOneTimeMigrations(dialect, pool, input) {
|
|
709
876
|
return dialect === "mysql" ? withMysqlLock(pool, (db) => migrateOn(db, "mysql", input)) : withPgLock(pool, (db) => migrateOn(db, "pg", input));
|
|
@@ -747,16 +914,21 @@ async function migrateOn(db, dialect, input) {
|
|
|
747
914
|
return completedReport(receipts);
|
|
748
915
|
}
|
|
749
916
|
async function migrateStepsOn(db, dialect, receipts, input) {
|
|
917
|
+
await switchScenarioPrefixM42(db, dialect, receipts, input);
|
|
918
|
+
await renameRetiredExecutionLaneWordsM40(db, dialect, receipts, input);
|
|
919
|
+
await refuseSessionExtMoveWhileRunsHeartbeat(db, dialect, input);
|
|
920
|
+
await switchSessionDeletingM51(db, dialect, receipts, input);
|
|
921
|
+
await rewriteRunErrorCodeColumnM44(db, dialect, receipts);
|
|
922
|
+
await rewriteRunObjectivePreviewM45(db, dialect, receipts);
|
|
923
|
+
await clearShellSentinelOwnersM48(db, dialect, receipts, input);
|
|
924
|
+
await backfillCheckpointHostSessionsM49(db, dialect, receipts);
|
|
750
925
|
await migrateRetiredCardWords(db, dialect, receipts);
|
|
751
926
|
await splitApprovalAskCauseColumns(db, dialect, receipts);
|
|
752
|
-
await reshapeWorkflowParkIndex(db, dialect, receipts);
|
|
753
927
|
await migrateSessionRuleGrammar(db, dialect, receipts);
|
|
754
928
|
await repairParkedRows(db, dialect, receipts);
|
|
755
929
|
await backfillParkedApprovalCards(db, dialect, receipts);
|
|
756
930
|
if (await tableExists(db, dialect, "session_meta"))
|
|
757
931
|
await inheritPlacedSessionOwners(db, dialect, receipts);
|
|
758
|
-
if ((await tableExists(db, dialect, PERMISSION_RULE_TABLE)) && (await columnExists(db, dialect, PERMISSION_RULE_TABLE, "grammar")))
|
|
759
|
-
await purgeUndurableScopeRows(db, dialect, receipts);
|
|
760
932
|
if ((await tableExists(db, dialect, PERMISSION_RULE_TABLE)) && (await columnExists(db, dialect, PERMISSION_RULE_TABLE, "grammar"))) {
|
|
761
933
|
await retireImportedLayerRootAllows(createSqlImportedLayerRootSource({ dialect, query: (sql, params) => db.query(sql, params) }), receipts);
|
|
762
934
|
}
|
|
@@ -765,6 +937,351 @@ async function migrateStepsOn(db, dialect, receipts, input) {
|
|
|
765
937
|
await dropRetiredBreakerTable(db, dialect, receipts);
|
|
766
938
|
await dropRejectedMailboxKeys(db, dialect, receipts);
|
|
767
939
|
await switchExecutionPlacement(db, dialect, receipts, input);
|
|
940
|
+
await moveSessionCellsToSideTable(db, dialect, receipts);
|
|
941
|
+
await markWithdrawEnabledM43(db, dialect, receipts, input);
|
|
942
|
+
await dropLegacySkillExemptionsM46(db, dialect, receipts);
|
|
943
|
+
}
|
|
944
|
+
const M44_PAGE = 500;
|
|
945
|
+
async function rewriteRunErrorCodeColumnM44(db, dialect, receipts) {
|
|
946
|
+
if (!(await tableExists(db, dialect, "task_run")))
|
|
947
|
+
return;
|
|
948
|
+
receipts.runErrorCodeColumnRewritten += await db.exec("UPDATE task_run SET error_code = NULL WHERE status = 'running' AND error_code IS NOT NULL");
|
|
949
|
+
let after = "";
|
|
950
|
+
for (;;) {
|
|
951
|
+
const page = await db.rows(dialect === "mysql"
|
|
952
|
+
? `SELECT task_id, status, updated_at, error_code, ${jsonColumnText(dialect, "result")} FROM task_run WHERE task_id > ? AND result IS NOT NULL AND status <> 'running' ORDER BY task_id LIMIT ${M44_PAGE}`
|
|
953
|
+
: `SELECT task_id, status, updated_at, error_code, ${jsonColumnText(dialect, "result")} FROM task_run WHERE task_id > $1 AND result IS NOT NULL AND status <> 'running' ORDER BY task_id LIMIT ${M44_PAGE}`, [after]);
|
|
954
|
+
for (const row of page) {
|
|
955
|
+
const taskId = String(row["task_id"]);
|
|
956
|
+
const first = await rewriteOneRunErrorCodeM44(db, dialect, row);
|
|
957
|
+
if (first !== 0) {
|
|
958
|
+
if (first > 0)
|
|
959
|
+
receipts.runErrorCodeColumnRewritten += 1;
|
|
960
|
+
continue;
|
|
961
|
+
}
|
|
962
|
+
const [now] = await db.rows(dialect === "mysql"
|
|
963
|
+
? `SELECT task_id, status, updated_at, error_code, ${jsonColumnText(dialect, "result")} FROM task_run WHERE task_id = ? AND result IS NOT NULL AND status <> 'running'`
|
|
964
|
+
: `SELECT task_id, status, updated_at, error_code, ${jsonColumnText(dialect, "result")} FROM task_run WHERE task_id = $1 AND result IS NOT NULL AND status <> 'running'`, [taskId]);
|
|
965
|
+
if (now !== undefined && (await rewriteOneRunErrorCodeM44(db, dialect, now)) > 0)
|
|
966
|
+
receipts.runErrorCodeColumnRewritten += 1;
|
|
967
|
+
}
|
|
968
|
+
if (page.length < M44_PAGE)
|
|
969
|
+
return;
|
|
970
|
+
after = String(page[page.length - 1]["task_id"]);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
async function rewriteOneRunErrorCodeM44(db, dialect, row) {
|
|
974
|
+
const taskId = String(row["task_id"]);
|
|
975
|
+
const storedCode = row["error_code"] ?? null;
|
|
976
|
+
const result = decodeRunResultCellM44(row["result"], taskId);
|
|
977
|
+
if (result === "unreadable" || result === null)
|
|
978
|
+
return -1;
|
|
979
|
+
const target = persistedPlaneOf(result).errorCode ?? storedCode;
|
|
980
|
+
if (target === storedCode)
|
|
981
|
+
return -1;
|
|
982
|
+
return db.exec(dialect === "mysql"
|
|
983
|
+
? "UPDATE task_run SET error_code = ? WHERE task_id = ? AND status = ? AND updated_at = ? AND error_code <=> ?"
|
|
984
|
+
: "UPDATE task_run SET error_code = $1 WHERE task_id = $2 AND status = $3 AND updated_at = $4 AND error_code IS NOT DISTINCT FROM $5", [target, taskId, String(row["status"]), row["updated_at"], storedCode]);
|
|
985
|
+
}
|
|
986
|
+
const M45_PAGE = 500;
|
|
987
|
+
async function rewriteRunObjectivePreviewM45(db, dialect, receipts) {
|
|
988
|
+
if (!(await tableExists(db, dialect, "task_run")))
|
|
989
|
+
return;
|
|
990
|
+
const ph = (i) => (dialect === "mysql" ? "?" : `$${i}`);
|
|
991
|
+
const coarse = RUN_PREVIEW_COARSE_PREFIXES_M45.map((_, i) => `objective_preview LIKE ${ph(i + 2)}`).join(" OR ");
|
|
992
|
+
let after = "";
|
|
993
|
+
for (;;) {
|
|
994
|
+
const page = await db.rows(`SELECT task_id, objective_preview FROM task_run WHERE task_id > ${ph(1)} AND (${coarse}) ORDER BY task_id LIMIT ${M45_PAGE}`, [after, ...RUN_PREVIEW_COARSE_PREFIXES_M45]);
|
|
995
|
+
for (const row of page) {
|
|
996
|
+
const current = row["objective_preview"];
|
|
997
|
+
if (typeof current !== "string")
|
|
998
|
+
continue;
|
|
999
|
+
const target = normalizedRunPreviewM45(current);
|
|
1000
|
+
if (target === undefined || target === current)
|
|
1001
|
+
continue;
|
|
1002
|
+
receipts.runObjectivePreviewRewritten += await db.exec(dialect === "mysql" ? "UPDATE task_run SET objective_preview = ? WHERE task_id = ? AND objective_preview = ?" : "UPDATE task_run SET objective_preview = $1 WHERE task_id = $2 AND objective_preview = $3", [target, String(row["task_id"]), current]);
|
|
1003
|
+
}
|
|
1004
|
+
if (page.length < M45_PAGE)
|
|
1005
|
+
return;
|
|
1006
|
+
after = String(page[page.length - 1]["task_id"]);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
export async function clearShellSentinelOwnersM48(db, dialect, receipts, input) {
|
|
1010
|
+
if (input.identityBoundary !== false)
|
|
1011
|
+
return;
|
|
1012
|
+
const sentinelOwner = dialect === "mysql" ? "CAST(owner AS BINARY) = CAST(? AS BINARY)" : "owner = $1";
|
|
1013
|
+
for (const table of SHELL_SENTINEL_OWNER_TABLES_M48) {
|
|
1014
|
+
if (!(await tableExists(db, dialect, table)))
|
|
1015
|
+
continue;
|
|
1016
|
+
receipts.shellSentinelOwnersCleared += await db.exec(`UPDATE ${table} SET owner = NULL WHERE ${sentinelOwner}`, [SHELL_SENTINEL_OWNER_M48]);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
const HOST_SESSION_BACKFILL_PAGE = 500;
|
|
1020
|
+
async function backfillCheckpointHostSessionsM49(db, dialect, receipts) {
|
|
1021
|
+
if (!(await tableExists(db, dialect, "checkpoint")) || !(await columnExists(db, dialect, "checkpoint", "host_session_id")))
|
|
1022
|
+
return;
|
|
1023
|
+
const ph = (i) => (dialect === "mysql" ? "?" : `$${i}`);
|
|
1024
|
+
let after = "";
|
|
1025
|
+
for (;;) {
|
|
1026
|
+
const page = (await db.rows(`SELECT token FROM checkpoint WHERE host_session_id IS NULL AND token > ${ph(1)} ORDER BY token ASC LIMIT ${HOST_SESSION_BACKFILL_PAGE}`, [after])).map((r) => String(r.token));
|
|
1027
|
+
if (page.length === 0)
|
|
1028
|
+
return;
|
|
1029
|
+
receipts.checkpointHostSessionsBackfilled += await db.exec(`UPDATE checkpoint SET host_session_id = session_id WHERE host_session_id IS NULL AND token IN (${page.map((_, i) => ph(i + 1)).join(", ")})`, page);
|
|
1030
|
+
after = page[page.length - 1];
|
|
1031
|
+
if (page.length < HOST_SESSION_BACKFILL_PAGE)
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
export async function dropLegacySkillExemptionsM46(db, dialect, receipts) {
|
|
1036
|
+
if (!(await tableExists(db, dialect, "approval_exemption")))
|
|
1037
|
+
return;
|
|
1038
|
+
if (!(await tableExists(db, dialect, MIGRATION_MARKER_TABLE)))
|
|
1039
|
+
await execUntil(db, migrationMarkerDdl(dialect), () => tableExists(db, dialect, MIGRATION_MARKER_TABLE));
|
|
1040
|
+
const ph = (i) => (dialect === "mysql" ? "?" : `$${i}`);
|
|
1041
|
+
const readMark = async () => {
|
|
1042
|
+
const [row] = await db.rows(`SELECT marked_at_ms FROM ${MIGRATION_MARKER_TABLE} WHERE migration_id = ${ph(1)}`, [LEGACY_SKILL_EXEMPTION_MARKER_ID]);
|
|
1043
|
+
return row === undefined ? undefined : Number(row["marked_at_ms"]);
|
|
1044
|
+
};
|
|
1045
|
+
let markedAtMs = await readMark();
|
|
1046
|
+
if (markedAtMs === undefined) {
|
|
1047
|
+
await db.exec(dialect === "mysql"
|
|
1048
|
+
? `INSERT INTO ${MIGRATION_MARKER_TABLE} (migration_id, marked_at_ms) VALUES (?, ?) ON DUPLICATE KEY UPDATE migration_id = migration_id`
|
|
1049
|
+
: `INSERT INTO ${MIGRATION_MARKER_TABLE} (migration_id, marked_at_ms) VALUES ($1, $2) ON CONFLICT (migration_id) DO NOTHING`, [LEGACY_SKILL_EXEMPTION_MARKER_ID, Date.now()]);
|
|
1050
|
+
markedAtMs = await readMark();
|
|
1051
|
+
}
|
|
1052
|
+
if (markedAtMs === undefined || !Number.isFinite(markedAtMs))
|
|
1053
|
+
throw new Error("one-time migration M46: the marker row is missing or unreadable right after it was written — refusing to delete rows without a recorded cutoff");
|
|
1054
|
+
const cutoff = new Date(markedAtMs);
|
|
1055
|
+
let after = "";
|
|
1056
|
+
for (;;) {
|
|
1057
|
+
const page = await db.rows(`SELECT session_id FROM approval_exemption WHERE tool_name = ${ph(1)} AND created_at < ${ph(2)} AND session_id > ${ph(3)} ORDER BY session_id LIMIT ${LEGACY_SKILL_EXEMPTION_PAGE}`, [LEGACY_SKILL_EXEMPTION_TOOL_NAME, cutoff, after]);
|
|
1058
|
+
if (page.length === 0)
|
|
1059
|
+
return;
|
|
1060
|
+
const sessionIds = page.map((r) => String(r["session_id"]));
|
|
1061
|
+
receipts.legacySkillExemptionsDropped += await db.exec(`DELETE FROM approval_exemption WHERE tool_name = ${ph(1)} AND created_at < ${ph(2)} AND session_id IN (${sessionIds.map((_, i) => ph(i + 3)).join(", ")})`, [LEGACY_SKILL_EXEMPTION_TOOL_NAME, cutoff, ...sessionIds]);
|
|
1062
|
+
if (page.length < LEGACY_SKILL_EXEMPTION_PAGE)
|
|
1063
|
+
return;
|
|
1064
|
+
after = sessionIds[sessionIds.length - 1];
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
async function markWithdrawEnabledM43(db, dialect, receipts, input) {
|
|
1068
|
+
if (!(await tableExists(db, dialect, MIGRATION_MARKER_TABLE)))
|
|
1069
|
+
await execUntil(db, migrationMarkerDdl(dialect), () => tableExists(db, dialect, MIGRATION_MARKER_TABLE));
|
|
1070
|
+
const marked = await db.rows(dialect === "mysql" ? `SELECT 1 AS present FROM ${MIGRATION_MARKER_TABLE} WHERE migration_id = ?` : `SELECT 1 AS present FROM ${MIGRATION_MARKER_TABLE} WHERE migration_id = $1`, [WITHDRAW_MARK_ID]);
|
|
1071
|
+
if (marked.length > 0)
|
|
1072
|
+
return;
|
|
1073
|
+
if ((await readLiveRunHeartbeat(db, dialect, input)) !== undefined)
|
|
1074
|
+
return;
|
|
1075
|
+
receipts.withdrawMarkWritten += await db.exec(dialect === "mysql"
|
|
1076
|
+
? `INSERT INTO ${MIGRATION_MARKER_TABLE} (migration_id, marked_at_ms) VALUES (?, ?) ON DUPLICATE KEY UPDATE migration_id = migration_id`
|
|
1077
|
+
: `INSERT INTO ${MIGRATION_MARKER_TABLE} (migration_id, marked_at_ms) VALUES ($1, $2) ON CONFLICT (migration_id) DO NOTHING`, [WITHDRAW_MARK_ID, Date.now()]);
|
|
1078
|
+
}
|
|
1079
|
+
export const SESSION_DELETING_MARK_ID = "M51";
|
|
1080
|
+
export const SESSION_DELETING_SWITCH_REFUSED_CODE = "config.session_deleting_switch_refused";
|
|
1081
|
+
export class SessionDeletingSwitchRefusedError extends StoreBootRefusalError {
|
|
1082
|
+
code = SESSION_DELETING_SWITCH_REFUSED_CODE;
|
|
1083
|
+
reason = "live_runs";
|
|
1084
|
+
constructor(live) {
|
|
1085
|
+
super(`${SESSION_DELETING_SWITCH_REFUSED_CODE} (reason: live_runs): this version deletes a session through a deleting state that every replica must read ` +
|
|
1086
|
+
`(a submission on a session being deleted is refused), but ${live.liveRuns} running run(s) heartbeated on this database within the last ${live.windowSec}s (REAP_RUN_STALE_SEC) — ` +
|
|
1087
|
+
"a replica of an earlier version may still be serving; it does not read that state and would accept a submission on a session this version is deleting. Nothing was changed and no marker was written. " +
|
|
1088
|
+
"Stop every replica of the earlier version, then start this version (stop, migrate, start — this release cannot be rolled across replicas of both versions). " +
|
|
1089
|
+
`If every replica is already stopped, those are the runs they left behind: start this version again after ${live.after}`);
|
|
1090
|
+
this.name = "SessionDeletingSwitchRefusedError";
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
async function switchSessionDeletingM51(db, dialect, receipts, input) {
|
|
1094
|
+
if (!(await tableExists(db, dialect, MIGRATION_MARKER_TABLE)))
|
|
1095
|
+
await execUntil(db, migrationMarkerDdl(dialect), () => tableExists(db, dialect, MIGRATION_MARKER_TABLE));
|
|
1096
|
+
const marked = await db.rows(dialect === "mysql" ? `SELECT 1 AS present FROM ${MIGRATION_MARKER_TABLE} WHERE migration_id = ?` : `SELECT 1 AS present FROM ${MIGRATION_MARKER_TABLE} WHERE migration_id = $1`, [SESSION_DELETING_MARK_ID]);
|
|
1097
|
+
if (marked.length > 0)
|
|
1098
|
+
return;
|
|
1099
|
+
const heartbeat = await readLiveRunHeartbeat(db, dialect, input);
|
|
1100
|
+
if (heartbeat !== undefined)
|
|
1101
|
+
throw new SessionDeletingSwitchRefusedError(heartbeat);
|
|
1102
|
+
receipts.sessionDeletingSwitchMarked += await db.exec(dialect === "mysql"
|
|
1103
|
+
? `INSERT INTO ${MIGRATION_MARKER_TABLE} (migration_id, marked_at_ms) VALUES (?, ?) ON DUPLICATE KEY UPDATE migration_id = migration_id`
|
|
1104
|
+
: `INSERT INTO ${MIGRATION_MARKER_TABLE} (migration_id, marked_at_ms) VALUES ($1, $2) ON CONFLICT (migration_id) DO NOTHING`, [SESSION_DELETING_MARK_ID, Date.now()]);
|
|
1105
|
+
}
|
|
1106
|
+
export async function scannedIdentityColumnsM42(db, dialect) {
|
|
1107
|
+
const scope = dialect === "mysql" ? "DATABASE()" : "current_schema()";
|
|
1108
|
+
const live = new Set((await db.rows(`SELECT table_name AS t, column_name AS c FROM information_schema.columns WHERE table_schema = ${scope}`)).map((r) => `${String(r["t"] ?? r["T"])}.${String(r["c"] ?? r["C"])}`));
|
|
1109
|
+
const out = [];
|
|
1110
|
+
for (const [table, shape] of await expectedTableShapes(dialect)) {
|
|
1111
|
+
for (const c of shape.columns) {
|
|
1112
|
+
if (!IDENTITY_COLUMN_NAME.test(c.name) || !/^\S+\s+(VAR)?(CHAR|BINARY)\(|^\S+\s+TEXT\b/i.test(c.ddl))
|
|
1113
|
+
continue;
|
|
1114
|
+
if (live.has(`${table}.${c.name}`))
|
|
1115
|
+
out.push({ table, column: c.name });
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
return out.sort((a, b) => `${a.table}.${a.column}`.localeCompare(`${b.table}.${b.column}`));
|
|
1119
|
+
}
|
|
1120
|
+
export async function switchScenarioPrefixM42(db, dialect, receipts, input) {
|
|
1121
|
+
if (!(await tableExists(db, dialect, MIGRATION_MARKER_TABLE)))
|
|
1122
|
+
await execUntil(db, migrationMarkerDdl(dialect), () => tableExists(db, dialect, MIGRATION_MARKER_TABLE));
|
|
1123
|
+
const marked = await db.rows(dialect === "mysql" ? `SELECT 1 AS present FROM ${MIGRATION_MARKER_TABLE} WHERE migration_id = ?` : `SELECT 1 AS present FROM ${MIGRATION_MARKER_TABLE} WHERE migration_id = $1`, [SCENARIO_PREFIX_MARKER_ID]);
|
|
1124
|
+
if (marked.length > 0)
|
|
1125
|
+
return;
|
|
1126
|
+
const columns = await scannedIdentityColumnsM42(db, dialect);
|
|
1127
|
+
const hits = [];
|
|
1128
|
+
for (const { table, column } of columns) {
|
|
1129
|
+
const sql = dialect === "mysql" ? `SELECT COUNT(*) AS n FROM ${table} WHERE ${column} LIKE ? ESCAPE '!'` : `SELECT COUNT(*) AS n FROM ${table} WHERE ${column} LIKE $1 ESCAPE '!'`;
|
|
1130
|
+
const n = Number((await db.rows(sql, [SCENARIO_PREFIX_LIKE]))[0]?.["n"] ?? 0);
|
|
1131
|
+
if (n > 0)
|
|
1132
|
+
hits.push({ source: `${table}.${column}`, rows: n });
|
|
1133
|
+
}
|
|
1134
|
+
receipts.scenarioPrefixSourcesScanned += columns.length;
|
|
1135
|
+
if (hits.length > 0)
|
|
1136
|
+
throw new ScenarioPrefixSwitchRefusedError("stored_prefix", hits);
|
|
1137
|
+
const live = await readLiveRunHeartbeat(db, dialect, input);
|
|
1138
|
+
if (live !== undefined)
|
|
1139
|
+
throw new ScenarioPrefixSwitchRefusedError("live_runs", [], live);
|
|
1140
|
+
await db.exec(dialect === "mysql"
|
|
1141
|
+
? `INSERT INTO ${MIGRATION_MARKER_TABLE} (migration_id, marked_at_ms) VALUES (?, ?) ON DUPLICATE KEY UPDATE migration_id = migration_id`
|
|
1142
|
+
: `INSERT INTO ${MIGRATION_MARKER_TABLE} (migration_id, marked_at_ms) VALUES ($1, $2) ON CONFLICT (migration_id) DO NOTHING`, [SCENARIO_PREFIX_MARKER_ID, Date.now()]);
|
|
1143
|
+
}
|
|
1144
|
+
export const EXECUTION_LANE_RENAME_REFUSED_CODE = "config.execution_lane_rename_refused";
|
|
1145
|
+
export class ExecutionLaneRenameRefusedError extends StoreBootRefusalError {
|
|
1146
|
+
pendingRows;
|
|
1147
|
+
liveRuns;
|
|
1148
|
+
restartAfter;
|
|
1149
|
+
code = EXECUTION_LANE_RENAME_REFUSED_CODE;
|
|
1150
|
+
constructor(pendingRows, liveRuns, restartAfter, detail) {
|
|
1151
|
+
super(`${EXECUTION_LANE_RENAME_REFUSED_CODE}: ${detail}`);
|
|
1152
|
+
this.pendingRows = pendingRows;
|
|
1153
|
+
this.liveRuns = liveRuns;
|
|
1154
|
+
this.restartAfter = restartAfter;
|
|
1155
|
+
this.name = "ExecutionLaneRenameRefusedError";
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
export class ExecutionLaneRenameWriteRefusedError extends StoreBootRefusalError {
|
|
1159
|
+
file;
|
|
1160
|
+
code = EXECUTION_LANE_RENAME_REFUSED_CODE;
|
|
1161
|
+
errno;
|
|
1162
|
+
constructor(file, cause) {
|
|
1163
|
+
const errno = typeof cause?.code === "string" ? cause.code : undefined;
|
|
1164
|
+
const fault = errno ?? (cause instanceof Error ? cause.message : String(cause));
|
|
1165
|
+
super(`${EXECUTION_LANE_RENAME_REFUSED_CODE}: one-time migration M40 could not rewrite ${file} (${fault}) — it still records the retired execution-lane word ` +
|
|
1166
|
+
`"${RETIRED_EXECUTION_LANE_WORD_M40}" (now "${RENAMED_EXECUTION_LANE_M40}"), which this build refuses to read, so it refuses to start rather than run without that data. ` +
|
|
1167
|
+
`The file is unchanged. Restore write access to the file and its directory (clear an immutable flag, remount read-write, free disk space), then restart: the rename runs again on the next start.`, { cause });
|
|
1168
|
+
this.file = file;
|
|
1169
|
+
this.name = "ExecutionLaneRenameWriteRefusedError";
|
|
1170
|
+
this.errno = errno;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
const EXECUTION_LANE_TABLES = [APPROVAL_ASK_TABLE, "session_meta", SESSION_EXT_TABLE];
|
|
1174
|
+
export async function renameRetiredExecutionLaneWordsM40(db, dialect, receipts, input) {
|
|
1175
|
+
const tables = [];
|
|
1176
|
+
for (const table of EXECUTION_LANE_TABLES)
|
|
1177
|
+
if (await columnExists(db, dialect, table, "execution_lane"))
|
|
1178
|
+
tables.push(table);
|
|
1179
|
+
let pendingRows = 0;
|
|
1180
|
+
for (const table of tables) {
|
|
1181
|
+
const [row] = await db.rows(`SELECT COUNT(*) AS n FROM ${table} WHERE execution_lane = ${dialect === "mysql" ? "?" : "$1"}`, [RETIRED_EXECUTION_LANE_WORD_M40]);
|
|
1182
|
+
pendingRows += Number(row?.["n"] ?? 0);
|
|
1183
|
+
}
|
|
1184
|
+
if (pendingRows === 0)
|
|
1185
|
+
return;
|
|
1186
|
+
await refuseWhileRunsHeartbeat(db, dialect, pendingRows, input);
|
|
1187
|
+
for (const table of tables) {
|
|
1188
|
+
receipts.executionLaneWordsRenamed += await db.exec(dialect === "mysql" ? `UPDATE ${table} SET execution_lane = ? WHERE execution_lane = ?` : `UPDATE ${table} SET execution_lane = $1 WHERE execution_lane = $2`, [RENAMED_EXECUTION_LANE_M40, RETIRED_EXECUTION_LANE_WORD_M40]);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
async function readLiveRunHeartbeat(db, dialect, input) {
|
|
1192
|
+
if (!(await tableExists(db, dialect, "task_run")))
|
|
1193
|
+
return undefined;
|
|
1194
|
+
const since = new Date(Date.now() - input.liveRunWindowMs);
|
|
1195
|
+
const [row] = await db.rows(`SELECT COUNT(*) AS n, MAX(updated_at) AS newest FROM task_run WHERE status = 'running' AND updated_at >= ${dialect === "mysql" ? "?" : "$1"}`, [since]);
|
|
1196
|
+
const liveRuns = Number(row?.["n"] ?? 0);
|
|
1197
|
+
if (liveRuns === 0)
|
|
1198
|
+
return undefined;
|
|
1199
|
+
const newestCell = row?.["newest"];
|
|
1200
|
+
const newest = newestCell instanceof Date ? newestCell : new Date(String(newestCell));
|
|
1201
|
+
const now = Date.now();
|
|
1202
|
+
const restartAtMs = (Number.isNaN(newest.getTime()) ? now : newest.getTime()) + input.liveRunWindowMs;
|
|
1203
|
+
return {
|
|
1204
|
+
liveRuns,
|
|
1205
|
+
windowSec: Math.round(input.liveRunWindowMs / 1000),
|
|
1206
|
+
restartAfter: new Date(restartAtMs).toISOString(),
|
|
1207
|
+
after: `${new Date(restartAtMs).toISOString()} (${Math.max(0, Math.ceil((restartAtMs - now) / 1000))}s from now)`,
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
1210
|
+
async function refuseWhileRunsHeartbeat(db, dialect, pendingRows, input) {
|
|
1211
|
+
const heartbeat = await readLiveRunHeartbeat(db, dialect, input);
|
|
1212
|
+
if (heartbeat === undefined)
|
|
1213
|
+
return;
|
|
1214
|
+
const { liveRuns, windowSec, restartAfter, after } = heartbeat;
|
|
1215
|
+
throw new ExecutionLaneRenameRefusedError(pendingRows, liveRuns, restartAfter, `${pendingRows} stored rows (approval asks / sessions) carry the execution lane word "${RETIRED_EXECUTION_LANE_WORD_M40}", the name an earlier version gave the lane with no execution environment, ` +
|
|
1216
|
+
`which this version calls "${RENAMED_EXECUTION_LANE_M40}" and does not read; this boot renames them (one-time migration M40), but ${liveRuns} running runs on this database heartbeat within the last ${windowSec}s ` +
|
|
1217
|
+
`(REAP_RUN_STALE_SEC) — a replica of an earlier version is still serving, and it would keep writing the old word after the rename. No stored row was changed. ` +
|
|
1218
|
+
"Stop every replica of the earlier version, then start this version (stop, migrate, start — this release cannot be rolled across replicas of both versions). " +
|
|
1219
|
+
`If every replica is already stopped, those are the runs they left behind: start this version again after ${after}`);
|
|
1220
|
+
}
|
|
1221
|
+
export const SESSION_EXT_MOVE_REFUSED_CODE = "config.session_ext_move_refused";
|
|
1222
|
+
export class SessionExtMoveRefusedError extends StoreBootRefusalError {
|
|
1223
|
+
reason;
|
|
1224
|
+
code = SESSION_EXT_MOVE_REFUSED_CODE;
|
|
1225
|
+
constructor(reason, detail) {
|
|
1226
|
+
super(`${SESSION_EXT_MOVE_REFUSED_CODE} (reason: ${reason}): ${detail}`);
|
|
1227
|
+
this.reason = reason;
|
|
1228
|
+
this.name = "SessionExtMoveRefusedError";
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
async function deploymentColumnsOnMeta(db, dialect) {
|
|
1232
|
+
if (!(await tableExists(db, dialect, "session_meta")))
|
|
1233
|
+
return [];
|
|
1234
|
+
const present = [];
|
|
1235
|
+
for (const column of SESSION_EXT_MOVED_COLUMNS)
|
|
1236
|
+
if (await columnExists(db, dialect, "session_meta", column.name))
|
|
1237
|
+
present.push(column);
|
|
1238
|
+
return present;
|
|
1239
|
+
}
|
|
1240
|
+
const sameCell = (dialect, column) => {
|
|
1241
|
+
const side = column.name === "pinned" ? "COALESCE(se.pinned, FALSE)" : `se.${column.name}`;
|
|
1242
|
+
return dialect === "mysql" ? `sm.${column.name} <=> ${side}` : `sm.${column.name} IS NOT DISTINCT FROM ${side}`;
|
|
1243
|
+
};
|
|
1244
|
+
const SESSION_EXT_MOVE_PAGE = 500;
|
|
1245
|
+
export async function refuseSessionExtMoveWhileRunsHeartbeat(db, dialect, input) {
|
|
1246
|
+
const columns = await deploymentColumnsOnMeta(db, dialect);
|
|
1247
|
+
if (columns.length === 0)
|
|
1248
|
+
return;
|
|
1249
|
+
const heartbeat = await readLiveRunHeartbeat(db, dialect, input);
|
|
1250
|
+
if (heartbeat === undefined)
|
|
1251
|
+
return;
|
|
1252
|
+
throw new SessionExtMoveRefusedError("live_runs", `${columns.length} session cells (${columns.map((c) => c.name).join(", ")}) still live on session_meta; this version keeps them on the side table ${SESSION_EXT_TABLE} and moves them on this boot ` +
|
|
1253
|
+
`(one-time migration M41: copy, verify, then drop the columns), but ${heartbeat.liveRuns} running runs on this database heartbeat within the last ${heartbeat.windowSec}s (REAP_RUN_STALE_SEC) — ` +
|
|
1254
|
+
"a replica of an earlier version is still serving; a cell it writes between the copy and the drop would be lost, and every cell write it makes after the drop fails. Nothing was changed. " +
|
|
1255
|
+
"Stop every replica of the earlier version, then start this version (stop, migrate, start — this release cannot be rolled across replicas of both versions). " +
|
|
1256
|
+
`If every replica is already stopped, those are the runs they left behind: start this version again after ${heartbeat.after}`);
|
|
1257
|
+
}
|
|
1258
|
+
export async function moveSessionCellsToSideTable(db, dialect, receipts) {
|
|
1259
|
+
const columns = await deploymentColumnsOnMeta(db, dialect);
|
|
1260
|
+
if (columns.length === 0)
|
|
1261
|
+
return;
|
|
1262
|
+
const names = columns.map((c) => c.name);
|
|
1263
|
+
const p = dialect === "mysql" ? () => "?" : (n) => `$${n}`;
|
|
1264
|
+
const upsert = `INSERT INTO ${SESSION_EXT_TABLE} (session_id, ${names.join(", ")}) SELECT session_id, ${names.join(", ")} FROM session_meta ` +
|
|
1265
|
+
`WHERE session_id > ${p(1)} AND session_id <= ${p(2)} ` +
|
|
1266
|
+
(dialect === "mysql" ? `ON DUPLICATE KEY UPDATE ${names.map((n) => `${SESSION_EXT_TABLE}.${n} = VALUES(${n})`).join(", ")}` : `ON CONFLICT (session_id) DO UPDATE SET ${names.map((n) => `${n} = EXCLUDED.${n}`).join(", ")}`);
|
|
1267
|
+
let after = "";
|
|
1268
|
+
for (;;) {
|
|
1269
|
+
const page = await db.rows(`SELECT session_id FROM session_meta WHERE session_id > ${p(1)} ORDER BY session_id LIMIT ${SESSION_EXT_MOVE_PAGE}`, [after]);
|
|
1270
|
+
if (page.length === 0)
|
|
1271
|
+
break;
|
|
1272
|
+
const last = String(page[page.length - 1]["session_id"]);
|
|
1273
|
+
await db.exec(upsert, [after, last]);
|
|
1274
|
+
receipts.sessionExtRowsMoved += page.length;
|
|
1275
|
+
after = last;
|
|
1276
|
+
}
|
|
1277
|
+
const [mismatch] = await db.rows(`SELECT sm.session_id FROM session_meta sm LEFT JOIN ${SESSION_EXT_TABLE} se ON se.session_id = sm.session_id WHERE NOT (${columns.map((c) => sameCell(dialect, c)).join(" AND ")}) LIMIT 1`);
|
|
1278
|
+
if (mismatch !== undefined) {
|
|
1279
|
+
throw new SessionExtMoveRefusedError("copy_mismatch", `after copying the session cells (${names.join(", ")}) from session_meta to ${SESSION_EXT_TABLE}, session ${String(mismatch["session_id"])} does not hold the same values on both tables — ` +
|
|
1280
|
+
"a writer changed it while this boot copied (an earlier-version replica still serving), or the copy did not land. No column was dropped. " +
|
|
1281
|
+
"Stop every replica of the earlier version and start this version again: the copy runs again from the start");
|
|
1282
|
+
}
|
|
1283
|
+
await execUntil(db, `ALTER TABLE session_meta ${names.map((n) => `DROP COLUMN ${n}`).join(", ")}`, async () => (await deploymentColumnsOnMeta(db, dialect)).length === 0);
|
|
1284
|
+
receipts.sessionMetaColumnsDropped += columns.length;
|
|
768
1285
|
}
|
|
769
1286
|
const RETIRED_ASK_CAUSE_COLUMN = "denied_reason";
|
|
770
1287
|
function renameAskCauseColumnSql(dialect) {
|
|
@@ -806,12 +1323,13 @@ async function readSwitchShape(db, dialect) {
|
|
|
806
1323
|
const sessionMeta = await tableExists(db, dialect, "session_meta");
|
|
807
1324
|
const placementColumns = new Set();
|
|
808
1325
|
if (sessionMeta)
|
|
809
|
-
for (const c of
|
|
1326
|
+
for (const c of EXECUTION_PLACEMENT_COLUMNS)
|
|
810
1327
|
if (await columnExists(db, dialect, "session_meta", c.name))
|
|
811
1328
|
placementColumns.add(c.name);
|
|
812
1329
|
return {
|
|
813
1330
|
sessionMeta,
|
|
814
1331
|
placementColumns,
|
|
1332
|
+
cellsOnSideTable: sessionMeta && (await deploymentColumnsOnMeta(db, dialect)).length === 0,
|
|
815
1333
|
bindingTable: await tableExists(db, dialect, RETIRED_DEVICE_BINDING_TABLE),
|
|
816
1334
|
parkedTable: await tableExists(db, dialect, PARKED_DEVICE_BINDING_TABLE),
|
|
817
1335
|
taskRun: sessionMeta && (await tableExists(db, dialect, "task_run")),
|
|
@@ -823,11 +1341,11 @@ async function askTableShape(db, dialect) {
|
|
|
823
1341
|
return { askTable, askLaneColumn: askTable && (await columnExists(db, dialect, APPROVAL_ASK_TABLE, "execution_lane")) };
|
|
824
1342
|
}
|
|
825
1343
|
function switchStarted(s) {
|
|
826
|
-
return s.placementColumns.has("execution_role") || s.parkedTable;
|
|
1344
|
+
return s.placementColumns.has("execution_role") || s.parkedTable || s.cellsOnSideTable;
|
|
827
1345
|
}
|
|
828
1346
|
const SWITCH_COMPLETION_COLUMN = "fork_key";
|
|
829
1347
|
function switchComplete(s) {
|
|
830
|
-
return s.placementColumns.size ===
|
|
1348
|
+
return (s.placementColumns.size === EXECUTION_PLACEMENT_COLUMNS.length || s.cellsOnSideTable) && (!s.askTable || s.askLaneColumn) && !s.bindingTable && !s.parkedTable;
|
|
831
1349
|
}
|
|
832
1350
|
function askLaneBackfillSql(dialect) {
|
|
833
1351
|
return dialect === "mysql"
|
|
@@ -878,7 +1396,7 @@ const EXECUTION_PLACEMENT_BACKFILL_NEEDS = [
|
|
|
878
1396
|
{ what: "approval ask rows that do not record the execution lane they were raised on (they would record their root session's lane, or the only declared lane)", holds: askRowsAwaitingLane },
|
|
879
1397
|
];
|
|
880
1398
|
async function refuseOnAmbiguousBackfill(read, dialect, shape, lanes) {
|
|
881
|
-
if (!shape.sessionMeta || switchComplete(shape) || lanes.length === 1)
|
|
1399
|
+
if (!shape.sessionMeta || shape.cellsOnSideTable || switchComplete(shape) || lanes.length === 1)
|
|
882
1400
|
return;
|
|
883
1401
|
const pending = [];
|
|
884
1402
|
for (const need of EXECUTION_PLACEMENT_BACKFILL_NEEDS)
|
|
@@ -931,7 +1449,7 @@ const EXECUTION_PLACEMENT_SWITCH_STEPS = [
|
|
|
931
1449
|
id: "① park the retired binding table",
|
|
932
1450
|
run: async ({ db, dialect, shape }) => {
|
|
933
1451
|
const s = await shape();
|
|
934
|
-
if (!s.bindingTable || s.placementColumns.has("execution_role"))
|
|
1452
|
+
if (!s.bindingTable || s.placementColumns.has("execution_role") || s.cellsOnSideTable)
|
|
935
1453
|
return;
|
|
936
1454
|
const sql = dialect === "mysql" ? `RENAME TABLE ${RETIRED_DEVICE_BINDING_TABLE} TO ${PARKED_DEVICE_BINDING_TABLE}` : `ALTER TABLE ${RETIRED_DEVICE_BINDING_TABLE} RENAME TO ${PARKED_DEVICE_BINDING_TABLE}`;
|
|
937
1455
|
await execUntil(db, sql, async () => {
|
|
@@ -955,7 +1473,9 @@ const EXECUTION_PLACEMENT_SWITCH_STEPS = [
|
|
|
955
1473
|
{
|
|
956
1474
|
id: "② add the execution placement columns",
|
|
957
1475
|
run: async ({ db, dialect, receipts, shape }) => {
|
|
958
|
-
|
|
1476
|
+
if ((await shape()).cellsOnSideTable)
|
|
1477
|
+
return;
|
|
1478
|
+
for (const column of EXECUTION_PLACEMENT_COLUMNS) {
|
|
959
1479
|
if (column.name === SWITCH_COMPLETION_COLUMN)
|
|
960
1480
|
continue;
|
|
961
1481
|
if ((await shape()).placementColumns.has(column.name))
|
|
@@ -973,10 +1493,17 @@ const EXECUTION_PLACEMENT_SWITCH_STEPS = [
|
|
|
973
1493
|
{
|
|
974
1494
|
id: "③ move the bindings onto the root session rows",
|
|
975
1495
|
run: async ({ db, dialect, receipts, shape }) => {
|
|
976
|
-
|
|
1496
|
+
const s = await shape();
|
|
1497
|
+
if (!s.parkedTable)
|
|
977
1498
|
return;
|
|
978
1499
|
const orphans = countOrphanBindingsStatement(dialect, PARKED_DEVICE_BINDING_TABLE);
|
|
979
1500
|
receipts.deviceBindingsOrphaned += Number((await db.rows(orphans.text, orphans.values))[0]?.["orphans"] ?? 0);
|
|
1501
|
+
if (s.cellsOnSideTable) {
|
|
1502
|
+
const [ensure, move] = migrateDeviceBindingsOntoSideTableStatements(dialect, PARKED_DEVICE_BINDING_TABLE);
|
|
1503
|
+
await db.exec(ensure.text, ensure.values);
|
|
1504
|
+
receipts.deviceBindingsMoved += await db.exec(move.text, move.values);
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
980
1507
|
const move = migrateDeviceBindingsStatement(dialect, PARKED_DEVICE_BINDING_TABLE);
|
|
981
1508
|
receipts.deviceBindingsMoved += await db.exec(move.text, move.values);
|
|
982
1509
|
},
|
|
@@ -985,6 +1512,8 @@ const EXECUTION_PLACEMENT_SWITCH_STEPS = [
|
|
|
985
1512
|
id: "④ backfill placements of sessions with runs",
|
|
986
1513
|
run: async ({ db, dialect, input, receipts, shape }) => {
|
|
987
1514
|
const s = await shape();
|
|
1515
|
+
if (s.cellsOnSideTable)
|
|
1516
|
+
return;
|
|
988
1517
|
if (input.lanes.length !== 1) {
|
|
989
1518
|
await refuseOnAmbiguousBackfill((sql) => db.rows(sql), dialect, s, input.lanes);
|
|
990
1519
|
return;
|
|
@@ -998,7 +1527,7 @@ const EXECUTION_PLACEMENT_SWITCH_STEPS = [
|
|
|
998
1527
|
id: "④b backfill the execution lane of approval ask rows",
|
|
999
1528
|
run: async ({ db, dialect, input, receipts, shape }) => {
|
|
1000
1529
|
const s = await shape();
|
|
1001
|
-
if (!s.askTable || !s.askLaneColumn)
|
|
1530
|
+
if (!s.askTable || !s.askLaneColumn || s.cellsOnSideTable)
|
|
1002
1531
|
return;
|
|
1003
1532
|
if (input.lanes.length !== 1) {
|
|
1004
1533
|
await refuseOnAmbiguousBackfill((sql) => db.rows(sql), dialect, s, input.lanes);
|
|
@@ -1019,9 +1548,10 @@ const EXECUTION_PLACEMENT_SWITCH_STEPS = [
|
|
|
1019
1548
|
{
|
|
1020
1549
|
id: "⑥ add the completion marker column",
|
|
1021
1550
|
run: async ({ db, dialect, receipts, shape }) => {
|
|
1022
|
-
|
|
1551
|
+
const s = await shape();
|
|
1552
|
+
if (s.placementColumns.has(SWITCH_COMPLETION_COLUMN) || s.cellsOnSideTable)
|
|
1023
1553
|
return;
|
|
1024
|
-
const marker =
|
|
1554
|
+
const marker = EXECUTION_PLACEMENT_COLUMNS.find((c) => c.name === SWITCH_COMPLETION_COLUMN);
|
|
1025
1555
|
await execUntil(db, `ALTER TABLE session_meta ADD COLUMN ${marker[dialect]}`, async () => (await shape()).placementColumns.has(SWITCH_COMPLETION_COLUMN));
|
|
1026
1556
|
receipts.executionPlacementColumnsAdded += 1;
|
|
1027
1557
|
},
|
|
@@ -1037,35 +1567,48 @@ export async function switchExecutionPlacement(db, dialect, receipts, input) {
|
|
|
1037
1567
|
await step.run({ db, dialect, input, receipts, shape });
|
|
1038
1568
|
}
|
|
1039
1569
|
export async function backfillLocalExecutionPlacements(sessionIds, seat, input) {
|
|
1040
|
-
|
|
1570
|
+
let backfilled = 0;
|
|
1571
|
+
let ambiguous = 0;
|
|
1041
1572
|
const unreadable = [];
|
|
1042
1573
|
for (const root of sessionIds) {
|
|
1043
|
-
const
|
|
1044
|
-
if (
|
|
1574
|
+
const out = await seat.backfill(root, input.lanes);
|
|
1575
|
+
if (isUnusableArchive(out)) {
|
|
1576
|
+
unreadable.push({ sessionId: root, fault: out.word, ...(out.errno !== undefined ? { errno: out.errno } : {}) });
|
|
1045
1577
|
continue;
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1578
|
+
}
|
|
1579
|
+
switch (out.outcome) {
|
|
1580
|
+
case "placed":
|
|
1581
|
+
backfilled += 1;
|
|
1582
|
+
break;
|
|
1583
|
+
case "ambiguous":
|
|
1584
|
+
ambiguous += 1;
|
|
1585
|
+
break;
|
|
1586
|
+
case "skipped":
|
|
1587
|
+
break;
|
|
1588
|
+
default: {
|
|
1589
|
+
const unknownOutcome = out;
|
|
1590
|
+
throw new Error(`backfillLocalExecutionPlacements: no outcome ${JSON.stringify(unknownOutcome)}`);
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
if (ambiguous > 0) {
|
|
1595
|
+
throw new ExecutionPlacementSwitchRefusedError("backfill_ambiguous", `the local data root holds sessions that have runs but no execution placement (${ambiguous}), and the deployment declares ${input.lanes.length === 0 ? "no lane" : `${input.lanes.length} lanes (${input.lanes.join(", ")})`} — ` +
|
|
1055
1596
|
"with more than one lane there is no single right answer, and this server will not guess one. Nothing was changed. " +
|
|
1056
1597
|
"Start this version once with a single declared lane (REMOTE_EXEC set to one lane), then declare the additional lanes");
|
|
1057
1598
|
}
|
|
1058
|
-
|
|
1059
|
-
let placed = 0;
|
|
1060
|
-
for (const { root, occupant } of absent) {
|
|
1061
|
-
if ((await seat.place(root, occupant, { role: "writer", lane })).outcome === "placed")
|
|
1062
|
-
placed += 1;
|
|
1063
|
-
}
|
|
1064
|
-
return { backfilled: placed, unreadable };
|
|
1599
|
+
return { backfilled, unreadable };
|
|
1065
1600
|
}
|
|
1601
|
+
const UNKNOWN_LANE_ASKS_SHOWN = 5;
|
|
1066
1602
|
export function backfillLocalAskExecutionLanes(store, input) {
|
|
1067
|
-
return store.backfillExecutionLanes(input.lanes, (
|
|
1068
|
-
|
|
1603
|
+
return store.backfillExecutionLanes(input.lanes, (refusal) => {
|
|
1604
|
+
if (refusal.kind === "unknown_lane") {
|
|
1605
|
+
const shown = refusal.asks.slice(0, UNKNOWN_LANE_ASKS_SHOWN).map((a) => `${a.askId} = ${JSON.stringify(a.word)}${retiredExecutionLaneHintM40(a.word) === "" ? "" : " (the retired name of none)"}`);
|
|
1606
|
+
const more = refusal.asks.length > shown.length ? ` and ${refusal.asks.length - shown.length} more` : "";
|
|
1607
|
+
throw new ExecutionPlacementSwitchRefusedError("unknown_lane", `the local approval ask journal holds ${refusal.asks.length} asks whose recorded execution lane is not a lane this version knows (${shown.join(", ")}${more}) — ` +
|
|
1608
|
+
"recording the deployment's lane over it would rewrite the lane the ask was raised on, and this server will not guess one. Nothing was changed. " +
|
|
1609
|
+
"The journal was written by a newer version or altered by hand: start the version that wrote it, or restore the journal from a copy");
|
|
1610
|
+
}
|
|
1611
|
+
throw new ExecutionPlacementSwitchRefusedError("backfill_ambiguous", `the local approval ask journal holds asks that do not record the execution lane they were raised on (${refusal.pending}), and the deployment declares ${input.lanes.length === 0 ? "no lane" : `${input.lanes.length} lanes (${input.lanes.join(", ")})`} — ` +
|
|
1069
1612
|
"with more than one lane there is no single right answer, and this server will not guess one. Nothing was changed. " +
|
|
1070
1613
|
"Start this version once with a single declared lane (REMOTE_EXEC set to one lane), then declare the additional lanes");
|
|
1071
1614
|
});
|
|
@@ -1294,55 +1837,6 @@ function renameSessionRulesColumnSql(dialect, from, to) {
|
|
|
1294
1837
|
const definition = SESSION_RULES_COLUMN.mysql.slice(SESSION_RULES_COLUMN.name.length);
|
|
1295
1838
|
return dialect === "mysql" ? `ALTER TABLE ${SESSION_POLICY_TABLE} CHANGE COLUMN ${from} ${to}${definition}` : `ALTER TABLE ${SESSION_POLICY_TABLE} RENAME COLUMN ${from} TO ${to}`;
|
|
1296
1839
|
}
|
|
1297
|
-
const WORKFLOW_PARK_INDEX_TABLE = "workflow_agent_session";
|
|
1298
|
-
async function primaryKeyWidth(db, dialect, table) {
|
|
1299
|
-
const sql = dialect === "mysql"
|
|
1300
|
-
? `SELECT COUNT(*) AS n FROM information_schema.key_column_usage WHERE table_schema = DATABASE() AND table_name = '${table}' AND constraint_name = 'PRIMARY'`
|
|
1301
|
-
: `SELECT COUNT(*) AS n FROM information_schema.table_constraints tc JOIN information_schema.key_column_usage kcu ` +
|
|
1302
|
-
`ON kcu.constraint_name = tc.constraint_name AND kcu.table_schema = tc.table_schema AND kcu.table_name = tc.table_name ` +
|
|
1303
|
-
`WHERE tc.table_schema = current_schema() AND tc.table_name = '${table}' AND tc.constraint_type = 'PRIMARY KEY'`;
|
|
1304
|
-
return Number((await db.rows(sql))[0]?.n ?? 0);
|
|
1305
|
-
}
|
|
1306
|
-
const WORKFLOW_PARK_INDEX_STAGING = `${WORKFLOW_PARK_INDEX_TABLE}_m9`;
|
|
1307
|
-
const WORKFLOW_PARK_INDEX_RETIRED = `${WORKFLOW_PARK_INDEX_TABLE}_m9_old`;
|
|
1308
|
-
async function reshapeWorkflowParkIndex(db, dialect, receipts) {
|
|
1309
|
-
const T = WORKFLOW_PARK_INDEX_TABLE;
|
|
1310
|
-
const S = WORKFLOW_PARK_INDEX_STAGING;
|
|
1311
|
-
const O = WORKFLOW_PARK_INDEX_RETIRED;
|
|
1312
|
-
const exists = (t) => tableExists(db, dialect, t);
|
|
1313
|
-
const ddl = (dialect === "mysql" ? SCHEMA_STATEMENTS : PG_SCHEMA_STATEMENTS).find((stmt) => stmt.includes(`CREATE TABLE IF NOT EXISTS ${T} (`));
|
|
1314
|
-
if (ddl === undefined)
|
|
1315
|
-
throw new Error(`one-time migration M9: the central schema carries no definition of ${T} — refusing to reshape a table it cannot rebuild`);
|
|
1316
|
-
const copyPointers = (to, from) => db.exec(dialect === "mysql"
|
|
1317
|
-
? `INSERT IGNORE INTO ${to} (session_id, run_id, agent_key, scope) SELECT session_id, run_id, agent_key, scope FROM ${from}`
|
|
1318
|
-
: `INSERT INTO ${to} (session_id, run_id, agent_key, scope) SELECT session_id, run_id, agent_key, scope FROM ${from} ON CONFLICT DO NOTHING`);
|
|
1319
|
-
const resumed = await exists(S);
|
|
1320
|
-
if (resumed) {
|
|
1321
|
-
await db.exec(ddl);
|
|
1322
|
-
receipts.workflowParkIndexRowsCarried += await copyPointers(T, S);
|
|
1323
|
-
await execUntil(db, `DROP TABLE ${S}`, async () => !(await exists(S)));
|
|
1324
|
-
}
|
|
1325
|
-
if (await exists(O))
|
|
1326
|
-
await execUntil(db, `DROP TABLE ${O}`, async () => !(await exists(O)));
|
|
1327
|
-
if ((await primaryKeyWidth(db, dialect, T)) !== 1) {
|
|
1328
|
-
if (await exists(T))
|
|
1329
|
-
await finishParkIndexShape(db, dialect);
|
|
1330
|
-
receipts.workflowParkIndexKey = resumed ? "reshaped" : "current";
|
|
1331
|
-
return;
|
|
1332
|
-
}
|
|
1333
|
-
await db.exec(ddl.replace(`CREATE TABLE IF NOT EXISTS ${T} (`, `CREATE TABLE IF NOT EXISTS ${S} (`));
|
|
1334
|
-
receipts.workflowParkIndexRowsCarried += await copyPointers(S, T);
|
|
1335
|
-
const swapped = async () => !(await exists(S)) && (await exists(T)) && (await primaryKeyWidth(db, dialect, T)) !== 1;
|
|
1336
|
-
if (dialect === "mysql") {
|
|
1337
|
-
await execUntil(db, `RENAME TABLE ${T} TO ${O}, ${S} TO ${T}`, swapped);
|
|
1338
|
-
await execUntil(db, `DROP TABLE IF EXISTS ${O}`, async () => !(await exists(O)));
|
|
1339
|
-
}
|
|
1340
|
-
else {
|
|
1341
|
-
await execAtomically(db, [`ALTER TABLE ${T} RENAME TO ${O}`, `ALTER TABLE ${S} RENAME TO ${T}`, `DROP TABLE ${O}`], async () => (await swapped()) && !(await exists(O)));
|
|
1342
|
-
}
|
|
1343
|
-
await finishParkIndexShape(db, dialect);
|
|
1344
|
-
receipts.workflowParkIndexKey = "reshaped";
|
|
1345
|
-
}
|
|
1346
1840
|
async function execAtomically(db, statements, postcondition) {
|
|
1347
1841
|
try {
|
|
1348
1842
|
await db.exec("BEGIN");
|
|
@@ -1362,16 +1856,6 @@ async function execAtomically(db, statements, postcondition) {
|
|
|
1362
1856
|
throw e;
|
|
1363
1857
|
}
|
|
1364
1858
|
}
|
|
1365
|
-
async function finishParkIndexShape(db, dialect) {
|
|
1366
|
-
await ensureIndexes(async (sql, params) => (dialect === "mysql" ? [await db.rows(sql, params)] : { rows: await db.rows(sql, params) }), dialect, CENTRAL_SCHEMA_INDEXES.filter((spec) => spec.table === WORKFLOW_PARK_INDEX_TABLE));
|
|
1367
|
-
if (dialect !== "pg")
|
|
1368
|
-
return;
|
|
1369
|
-
const conventional = `${WORKFLOW_PARK_INDEX_TABLE}_pkey`;
|
|
1370
|
-
const pk = await db.rows(`SELECT constraint_name FROM information_schema.table_constraints WHERE table_schema = current_schema() AND table_name = '${WORKFLOW_PARK_INDEX_TABLE}' AND constraint_type = 'PRIMARY KEY'`);
|
|
1371
|
-
const name = pk[0]?.constraint_name;
|
|
1372
|
-
if (typeof name === "string" && name !== conventional)
|
|
1373
|
-
await db.exec(`ALTER TABLE ${WORKFLOW_PARK_INDEX_TABLE} RENAME CONSTRAINT ${name} TO ${conventional}`);
|
|
1374
|
-
}
|
|
1375
1859
|
const RETIRED_CARD_WORD_PATTERNS = ['%"shadowed"%', '%"governance_unavailable"%'];
|
|
1376
1860
|
const RETIRED_CARD_WORD_BATCH = 500;
|
|
1377
1861
|
function decodeForM18(text, where) {
|
|
@@ -1421,8 +1905,8 @@ async function migrateRetiredCardWords(db, dialect, receipts) {
|
|
|
1421
1905
|
return;
|
|
1422
1906
|
}
|
|
1423
1907
|
}
|
|
1424
|
-
const M21_GATE = {
|
|
1425
|
-
const M21_PENDING_ACTION = {
|
|
1908
|
+
const M21_GATE = { path: ["gate"], as: "m21_gate" };
|
|
1909
|
+
const M21_PENDING_ACTION = { path: ["pendingAction"], as: "m21_pending_action" };
|
|
1426
1910
|
const PARKED_ROW_REPAIR_PAGE = 200;
|
|
1427
1911
|
const QUESTION_CARD = "question";
|
|
1428
1912
|
const readM21Subtree = createObjectColumnReader();
|
|
@@ -1621,11 +2105,6 @@ export async function inheritPlacedSessionOwners(db, dialect, receipts) {
|
|
|
1621
2105
|
}
|
|
1622
2106
|
function readingFields(r) {
|
|
1623
2107
|
return {
|
|
1624
|
-
...(r.workflowParkIndexKey !== undefined ? { workflowParkIndexKey: r.workflowParkIndexKey } : {}),
|
|
1625
|
-
workflowParkIndexRowsCarried: r.workflowParkIndexRowsCarried,
|
|
1626
|
-
undurableScopeRuleRowsRemoved: r.undurableScopeRuleRows.length,
|
|
1627
|
-
undurableScopeRuleBucketsDeferred: r.undurableScopeRuleBucketsDeferred,
|
|
1628
|
-
undurableScopeRuleBucketsUnreadable: r.undurableScopeRuleBucketsUnreadable.length,
|
|
1629
2108
|
...(r.sessionRuleColumn !== undefined ? { sessionRuleColumn: r.sessionRuleColumn } : {}),
|
|
1630
2109
|
sessionRuleRowsWithRetiredBuckets: r.sessionRuleRowsWithRetiredBuckets.length,
|
|
1631
2110
|
sessionRuleRowsWithOldGrammarEntries: r.sessionRuleRowsWithOldGrammarEntries.length,
|
|
@@ -1653,17 +2132,31 @@ function readingFields(r) {
|
|
|
1653
2132
|
deviceBindingTablesDropped: r.deviceBindingTablesDropped,
|
|
1654
2133
|
executionPlacementsBackfilled: r.executionPlacementsBackfilled,
|
|
1655
2134
|
askExecutionLanesBackfilled: r.askExecutionLanesBackfilled,
|
|
2135
|
+
executionLaneWordsRenamed: r.executionLaneWordsRenamed,
|
|
2136
|
+
sessionExtRowsMoved: r.sessionExtRowsMoved,
|
|
2137
|
+
sessionMetaColumnsDropped: r.sessionMetaColumnsDropped,
|
|
2138
|
+
scenarioPrefixSourcesScanned: r.scenarioPrefixSourcesScanned,
|
|
2139
|
+
withdrawMarkWritten: r.withdrawMarkWritten,
|
|
2140
|
+
sessionDeletingSwitchMarked: r.sessionDeletingSwitchMarked,
|
|
2141
|
+
runErrorCodeColumnRewritten: r.runErrorCodeColumnRewritten,
|
|
2142
|
+
runObjectivePreviewRewritten: r.runObjectivePreviewRewritten,
|
|
2143
|
+
shellSentinelOwnersCleared: r.shellSentinelOwnersCleared,
|
|
2144
|
+
checkpointHostSessionsBackfilled: r.checkpointHostSessionsBackfilled,
|
|
2145
|
+
legacySkillExemptionsDropped: r.legacySkillExemptionsDropped,
|
|
1656
2146
|
executionPlacementSessionsUnreadable: r.executionPlacementSessionsUnreadable.length,
|
|
1657
2147
|
localArchiveRowFactsBackfilled: r.localArchiveRowFactsBackfilled,
|
|
1658
2148
|
localArchivesAnonymized: r.localArchivesAnonymized,
|
|
1659
2149
|
localArchivesKeptStamped: r.localArchivesKeptStamped.length,
|
|
1660
2150
|
localArchivesUnreadable: r.localArchivesUnreadable.length,
|
|
1661
2151
|
localArchiveSnapshotsRecovered: r.localArchiveSnapshotsRecovered,
|
|
2152
|
+
localArchiveTokensAdopted: r.localArchiveTokensAdopted,
|
|
2153
|
+
localArchiveTokensMinted: r.localArchiveTokensMinted,
|
|
1662
2154
|
askCauseColumnsChanged: r.askCauseColumnsChanged,
|
|
1663
2155
|
askParkTriggersMoved: r.askParkTriggersMoved,
|
|
1664
2156
|
askJournalRecordsUpgraded: r.askJournalRecordsUpgraded,
|
|
1665
2157
|
importedLayerRootAllowsRetired: r.importedLayerRootAllowsRetired.length,
|
|
1666
2158
|
importedLayerRootBucketsSkipped: r.importedLayerRootBucketsSkipped.length,
|
|
2159
|
+
importedLayerRootBucketsUnnamed: r.importedLayerRootBucketsUnnamed,
|
|
1667
2160
|
};
|
|
1668
2161
|
}
|
|
1669
2162
|
export function logOneTimeMigrations(log, backend, report) {
|
|
@@ -1671,12 +2164,7 @@ export function logOneTimeMigrations(log, backend, report) {
|
|
|
1671
2164
|
backend,
|
|
1672
2165
|
...readingFields(report),
|
|
1673
2166
|
removableAfter: Object.fromEntries(ONE_TIME_MIGRATIONS.map((w) => [w.id, w.removableAfter])),
|
|
1674
|
-
note: "one-time persisted-data migrations (
|
|
1675
|
-
"its rows carried over; M10 writes nothing at boot — on the local backend, while its window is open, the first task submitted with a principal " +
|
|
1676
|
-
"on a session written by an earlier version (which recorded no owner) claims that session for the principal, one session_owner_claimed line per claim; " +
|
|
1677
|
-
"M11: persisted permission rules whose project scope root is not a complete absolute path — accepted by earlier versions, dropped on every read " +
|
|
1678
|
-
"by the current engine and not removable through DELETE /v1/rules — removed, one permission_rule_row_removed line per row; a bucket the read path " +
|
|
1679
|
-
"refuses in whole is left untouched, one permission_rule_bucket_unreadable line per bucket; M17: the session-rules column renamed from `rules` to " +
|
|
2167
|
+
note: "one-time persisted-data migrations (M17: the session-rules column renamed from `rules` to " +
|
|
1680
2168
|
"`rule_entries`, so a build that reads rules under the earlier name-only grammar finds no column to misread; at that rename every row's rule entries " +
|
|
1681
2169
|
"are read by the engine in the grammar the row carries (none = the grammar before the stamp) and rewritten as the same statement in the current grammar " +
|
|
1682
2170
|
"(the column carries the in-progress name rule_entries_old_grammar until every row is rewritten, so an interrupted boot resumes there) — toolAllow entries " +
|
|
@@ -1721,7 +2209,10 @@ export function logOneTimeMigrations(log, backend, report) {
|
|
|
1721
2209
|
"M36: allow approvals that an import before engine 7.61.0 stored as global rules from a settings file's user-layer path written from `/` — which the user layer reads at its " +
|
|
1722
2210
|
"configuration directory and a global rule reads at every task's project root — retired by tombstones naming exactly those approvals (a rule that also holds an approval a person " +
|
|
1723
2211
|
"gave directly stays in effect; deny and ask rules are never retired), one imported_layer_root_allow_retired line per rule; a bucket that could not be read or written, or that another replica deleted while it was being written, is named by an " +
|
|
1724
|
-
"imported_layer_root_bucket_skipped line on every boot
|
|
2212
|
+
"imported_layer_root_bucket_skipped line on every boot; " +
|
|
2213
|
+
"M40: the stored execution lane word in-process — the name earlier versions gave the lane with no execution environment, which this version calls none and does not read — " +
|
|
2214
|
+
"rewritten as none on approval ask rows and session rows (on the local backend: in the session metadata file and the approval ask journal); a boot that finds such rows while " +
|
|
2215
|
+
"runs on the same database still heartbeat refuses with nothing changed, because a replica of an earlier version is still serving and would keep writing the old word). Each step " +
|
|
1725
2216
|
"runs on every boot until its window closes (the release that introduced it + 30 days; the per-step date is in " +
|
|
1726
2217
|
"removableAfter, null while that release is not published yet) and is deleted in the first minor after that — start a " +
|
|
1727
2218
|
"version that still carries a step at least once before upgrading past its deletion.",
|
|
@@ -1751,6 +2242,15 @@ function logReceiptRows(log, backend, r) {
|
|
|
1751
2242
|
"(the next boot then migrates it) or the session is deleted. Named on every boot until then",
|
|
1752
2243
|
});
|
|
1753
2244
|
}
|
|
2245
|
+
if (r.legacySkillExemptionsDropped > 0) {
|
|
2246
|
+
log.warn("legacy_skill_exemptions_dropped", {
|
|
2247
|
+
backend,
|
|
2248
|
+
count: r.legacySkillExemptionsDropped,
|
|
2249
|
+
note: "session approval-exemption rows for the engine's Skill tool that were written before this boot's first run of this step (by 7.116.0 or earlier for an activation card or a deployment-list question that named Skill, " +
|
|
2250
|
+
"or by a later version for a call that granted nothing) were deleted: a stored row for a tool by that name would answer a call by that name — and when no skill is loaded a call by that name is another tool, not the activation the person approved. " +
|
|
2251
|
+
"The people in those sessions are asked once more on their next Skill call. Rows written after this step first ran are never touched",
|
|
2252
|
+
});
|
|
2253
|
+
}
|
|
1754
2254
|
if (r.deviceBindingsOrphaned > 0) {
|
|
1755
2255
|
log.warn("device_bindings_orphaned", {
|
|
1756
2256
|
backend,
|
|
@@ -1813,17 +2313,6 @@ function logReceiptRows(log, backend, r) {
|
|
|
1813
2313
|
"in the session store by hand if someone should read one, or leave them to the transcript retention",
|
|
1814
2314
|
});
|
|
1815
2315
|
}
|
|
1816
|
-
for (const row of r.undurableScopeRuleRows) {
|
|
1817
|
-
log.warn("permission_rule_row_removed", {
|
|
1818
|
-
backend,
|
|
1819
|
-
ownerKey: row.ownerKey,
|
|
1820
|
-
kind: row.kind,
|
|
1821
|
-
behavior: row.behavior,
|
|
1822
|
-
tool: row.tool,
|
|
1823
|
-
scopeRoot: row.scopeRoot,
|
|
1824
|
-
note: removedRuleRowNote(row.kind),
|
|
1825
|
-
});
|
|
1826
|
-
}
|
|
1827
2316
|
for (const row of r.importedLayerRootAllowsRetired) {
|
|
1828
2317
|
log.warn("imported_layer_root_allow_retired", {
|
|
1829
2318
|
backend,
|
|
@@ -1841,14 +2330,14 @@ function logReceiptRows(log, backend, r) {
|
|
|
1841
2330
|
for (const bucket of r.importedLayerRootBucketsSkipped) {
|
|
1842
2331
|
log.warn("imported_layer_root_bucket_skipped", { backend, ownerKey: bucket.ownerKey, reason: bucket.reason, why: bucket.why, note: importedLayerRootSkipNote(bucket.reason) });
|
|
1843
2332
|
}
|
|
1844
|
-
|
|
1845
|
-
log.warn("
|
|
2333
|
+
if (r.importedLayerRootBucketsUnnamed > 0) {
|
|
2334
|
+
log.warn("imported_layer_root_buckets_unnamed", {
|
|
1846
2335
|
backend,
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
"
|
|
1851
|
-
"
|
|
2336
|
+
count: r.importedLayerRootBucketsUnnamed,
|
|
2337
|
+
note: "this many permission-rule bucket files are present in the rules directory but neither the directory (the local owner's bucket, the identities its adoption marker names) " +
|
|
2338
|
+
"nor this store's import records name their owner (a bucket file is named by a one-way digest of its owner), so the one-time retirement of imported allow rules written from `/` " +
|
|
2339
|
+
"did not read them: any such rule in them stays in effect. This is a gap in the census, not a statement that they are empty. Each boot reports it again; " +
|
|
2340
|
+
"list the rules of every owner you know (`GET /v1/rules`) and remove what should not stand",
|
|
1852
2341
|
});
|
|
1853
2342
|
}
|
|
1854
2343
|
for (const row of r.sessionRuleRowsWithOldGrammarEntries) {
|
|
@@ -1901,7 +2390,7 @@ function logOneTimeMigrationsInterrupted(log, backend, error) {
|
|
|
1901
2390
|
...readingFields(error.receipts),
|
|
1902
2391
|
note: "the one-time migrations failed after committing changes: the readings on this line and the lines that follow are what this boot already committed — a retried " +
|
|
1903
2392
|
"boot finds that work done and does not report it again, so these lines are the only record of them, written once by this boot — save them. The failure itself follows " +
|
|
1904
|
-
"as this boot's refusal. A shape reading absent from this line (
|
|
2393
|
+
"as this boot's refusal. A shape reading absent from this line (sessionRuleColumn / workflowJournalScopeColumn) belongs to a step that did not " +
|
|
1905
2394
|
"finish; sessionRuleColumn absent after session_rule_row_old_grammar_entries lines means the column still carries its in-progress name — the next boot rewrites the " +
|
|
1906
2395
|
"remaining rows (rows already rewritten are left alone) and publishes the final name",
|
|
1907
2396
|
});
|
|
@@ -1936,18 +2425,4 @@ function importedLayerRootSkipNote(reason) {
|
|
|
1936
2425
|
}
|
|
1937
2426
|
}
|
|
1938
2427
|
}
|
|
1939
|
-
function removedRuleRowNote(kind) {
|
|
1940
|
-
switch (kind) {
|
|
1941
|
-
case "rule":
|
|
1942
|
-
return "a persisted permission rule whose project scope root is not a complete absolute path was removed by a one-time migration: the current engine drops such a row on every read (it protected nothing) and refuses any write naming that scope, so it could not be revoked through DELETE /v1/rules; re-add it with the project's full path if it is still wanted";
|
|
1943
|
-
case "revoked-rule":
|
|
1944
|
-
return "a persisted permission rule row whose project scope root is not a complete absolute path, and which had no live approval left (every approval behind it was already removed, or it never had one), was removed by a one-time migration: the row took effect nowhere before and takes effect nowhere now — no action needed";
|
|
1945
|
-
case "tombstone":
|
|
1946
|
-
return "a revocation record (tombstone) whose project scope root is not a complete absolute path was removed by a one-time migration: it can only cover rules with that same scope, which were removed with it or were never there, so nothing it revoked comes back — no action needed";
|
|
1947
|
-
default: {
|
|
1948
|
-
const unknown = kind;
|
|
1949
|
-
throw new Error(`M11: no log sentence for removed-row kind ${JSON.stringify(unknown)}`);
|
|
1950
|
-
}
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
2428
|
//# sourceMappingURL=one-time-migrations.js.map
|