@sema-agent/server 7.132.0 → 7.134.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 +353 -0
- package/README.md +8 -9
- package/README.zh-CN.md +7 -6
- package/USAGE.md +301 -64
- package/deploy/sema-up/README.md +35 -1
- package/deploy/sema-up/chart/Chart.yaml +1 -1
- package/deploy/sema-up/chart/templates/NOTES.txt +15 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +129 -0
- package/deploy/sema-up/chart/templates/sealed-key.yaml +24 -0
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +19 -2
- package/deploy/sema-up/chart/templates/server.yaml +19 -2
- package/deploy/sema-up/chart/values-full-single.yaml +5 -1
- package/deploy/sema-up/chart/values.yaml +34 -0
- package/deploy/sema-up/stack/compose.yaml +3 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
- package/dist/adoption/plan.d.ts +3 -2
- package/dist/adoption/plan.js +7 -5
- package/dist/adoption/runner.js +3 -10
- package/dist/adoption/sql.d.ts +3 -2
- package/dist/adoption/sql.js +3 -5
- package/dist/adoption/wire.d.ts +4 -1
- package/dist/adoption/wire.js +1 -0
- package/dist/approval-ask-audit-store.d.ts +32 -14
- package/dist/approval-ask-audit-store.js +272 -74
- package/dist/approval-ask-machine.d.ts +15 -0
- package/dist/approval-ask-machine.js +6 -0
- package/dist/approval-ask-retention.d.ts +136 -0
- package/dist/approval-ask-retention.js +102 -0
- package/dist/approval-card.d.ts +83 -23
- package/dist/approval-card.js +45 -15
- package/dist/approval-content-kind.d.ts +5 -2
- package/dist/approval-content-kind.js +16 -3
- package/dist/approval-deny-reasons.d.ts +1 -1
- package/dist/approval-gate-currency.d.ts +72 -0
- package/dist/approval-gate-currency.js +94 -0
- package/dist/approval.d.ts +15 -0
- package/dist/approval.js +55 -17
- package/dist/audit.d.ts +27 -10
- package/dist/audit.js +12 -16
- package/dist/bake-runner/main.js +3 -2
- package/dist/boot/coordinators.d.ts +6 -1
- package/dist/boot/coordinators.js +6 -3
- package/dist/boot/deferred-sandbox-path-env.js +1 -1
- package/dist/boot/execution-env.js +9 -7
- package/dist/boot/execution-lane.js +11 -0
- package/dist/boot/leader.d.ts +2 -0
- package/dist/boot/leader.js +4 -1
- package/dist/boot/memory-boundary.js +2 -2
- package/dist/boot/memory-consolidation.d.ts +5 -4
- package/dist/boot/memory-consolidation.js +7 -6
- package/dist/boot/org-delivery.d.ts +28 -0
- package/dist/boot/org-delivery.js +20 -0
- package/dist/boot/read-deny-anchor-audit.js +2 -2
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +21 -1
- package/dist/boot/resolve-spec.d.ts +3 -0
- package/dist/boot/resolve-spec.js +60 -81
- package/dist/boot/runner-deps.d.ts +18 -5
- package/dist/boot/runner-deps.js +10 -0
- package/dist/boot/session-faces.d.ts +1 -0
- package/dist/boot/session-faces.js +4 -2
- package/dist/boot/stage-02-web-admin-pull.js +4 -1
- package/dist/boot/stage-06-runners.d.ts +6 -3
- package/dist/boot/stage-06-runners.js +20 -4
- package/dist/boot/stage-07-capability-layer.d.ts +4 -1
- package/dist/boot/stage-07-capability-layer.js +24 -3
- package/dist/boot/stage-08-reapers.d.ts +4 -1
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +5 -1
- package/dist/boot/stage-09-leader.js +2 -2
- package/dist/boot/stage-10-http-server.d.ts +5 -1
- package/dist/boot/stage-10-http-server.js +6 -6
- package/dist/boot/stores.d.ts +8 -0
- package/dist/boot/stores.js +10 -14
- package/dist/boot/web-admin.d.ts +10 -0
- package/dist/boot/web-admin.js +162 -65
- package/dist/boot/workflow-orchestration.d.ts +2 -0
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/brain.js +8 -3
- package/dist/breaker-key.d.ts +6 -0
- package/dist/breaker-key.js +29 -0
- package/dist/budget.js +5 -1
- package/dist/caller-text-echo.d.ts +11 -6
- package/dist/caller-text-echo.js +10 -12
- package/dist/canonical-json.d.ts +2 -41
- package/dist/canonical-json.js +2 -13
- package/dist/capabilities/center-plugins.d.ts +7 -0
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/execution-lane.js +2 -2
- package/dist/capabilities/hands-lane.d.ts +21 -0
- package/dist/capabilities/hands-lane.js +10 -0
- package/dist/capabilities/mcp-probe.d.ts +36 -4
- package/dist/capabilities/mcp-probe.js +29 -6
- package/dist/capabilities/scenarios.d.ts +63 -7
- package/dist/capabilities/scenarios.js +39 -7
- package/dist/capability-facts.d.ts +36 -4
- package/dist/capability-facts.js +30 -4
- package/dist/center-config-tier.d.ts +69 -0
- package/dist/center-config-tier.js +42 -0
- package/dist/checkpoint-ctx-seal-m28.d.ts +42 -0
- package/dist/checkpoint-ctx-seal-m28.js +19 -0
- package/dist/checkpoint-identity.d.ts +16 -0
- package/dist/checkpoint-identity.js +19 -0
- package/dist/config-catalog.d.ts +17 -10
- package/dist/config-catalog.js +43 -28
- package/dist/config-d-migration.d.ts +3 -1
- package/dist/config-d-migration.js +2 -2
- package/dist/config-dir-trust.d.ts +114 -0
- package/dist/config-dir-trust.js +388 -0
- package/dist/config-invariants.d.ts +18 -5
- package/dist/config-invariants.js +35 -3
- package/dist/config-provider.d.ts +6 -1
- package/dist/config-provider.js +6 -2
- package/dist/config-types.d.ts +71 -14
- package/dist/config-types.js +8 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +121 -59
- package/dist/delegated-session-owner.d.ts +185 -0
- package/dist/delegated-session-owner.js +119 -0
- package/dist/device-protocol.d.ts +5 -3
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.js +21 -2
- package/dist/device-ws-protocol.d.ts +70 -6
- package/dist/device-ws-protocol.js +50 -23
- package/dist/elicitation.js +3 -2
- package/dist/entry-problems.d.ts +34 -0
- package/dist/entry-problems.js +14 -0
- package/dist/execution-lane-caps.d.ts +49 -10
- package/dist/execution-lane-caps.js +43 -4
- package/dist/field-conflict.d.ts +44 -0
- package/dist/field-conflict.js +21 -0
- package/dist/file-history-disclosure.d.ts +34 -5
- package/dist/file-history-disclosure.js +2 -2
- package/dist/fleet/fleet-bus.d.ts +84 -6
- package/dist/fleet/fleet-bus.js +42 -9
- package/dist/hooks/classic-stations.d.ts +10 -5
- package/dist/hooks/classic-stations.js +4 -4
- package/dist/hooks/command-spawn.d.ts +57 -0
- package/dist/hooks/command-spawn.js +139 -0
- package/dist/hooks/hook-llm.js +2 -2
- package/dist/hooks/hook-runner.d.ts +127 -25
- package/dist/hooks/hook-runner.js +668 -287
- package/dist/hooks/hook-source.d.ts +44 -0
- package/dist/hooks/hook-source.js +40 -0
- package/dist/http/active-run-conflict.d.ts +5 -13
- package/dist/http/active-run-conflict.js +17 -27
- package/dist/http/admission.js +111 -60
- package/dist/http/approval-sweeps.js +58 -19
- package/dist/http/caller-trust.d.ts +77 -0
- package/dist/http/caller-trust.js +143 -0
- package/dist/http/checkpoint-ctx.d.ts +173 -18
- package/dist/http/checkpoint-ctx.js +171 -12
- package/dist/http/claimed-run.d.ts +4 -3
- package/dist/http/device-placement.d.ts +2 -4
- package/dist/http/device-placement.js +2 -1
- package/dist/http/dispatch.js +13 -7
- package/dist/http/durable-run-leg.d.ts +4 -32
- package/dist/http/durable-run-leg.js +37 -12
- package/dist/http/idempotency.d.ts +2 -2
- package/dist/http/idempotency.js +2 -2
- package/dist/http/owner-access.d.ts +56 -0
- package/dist/http/owner-access.js +42 -0
- package/dist/http/principal-gate.d.ts +78 -27
- package/dist/http/principal-gate.js +64 -14
- package/dist/http/readiness.d.ts +11 -5
- package/dist/http/readiness.js +10 -3
- package/dist/http/refusal-body.d.ts +12 -0
- package/dist/http/refusal-body.js +11 -0
- package/dist/http/request-guards.d.ts +16 -32
- package/dist/http/request-guards.js +31 -30
- package/dist/http/resume-ctx-read.d.ts +50 -6
- package/dist/http/resume-ctx-read.js +33 -7
- package/dist/http/resume-legs.d.ts +5 -5
- package/dist/http/resume-legs.js +163 -91
- package/dist/http/retired-service-deps.d.ts +43 -0
- package/dist/http/retired-service-deps.js +18 -0
- package/dist/http/route-ctx.d.ts +44 -37
- package/dist/http/route-ctx.js +4 -0
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/a2a-serve.js +3 -4
- package/dist/http/routes/admin-config-refresh.js +1 -1
- package/dist/http/routes/admin-drain.js +1 -1
- package/dist/http/routes/admin-memory-optout.js +5 -1
- package/dist/http/routes/adoption.js +2 -9
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.js +91 -56
- package/dist/http/routes/background.js +3 -2
- package/dist/http/routes/capabilities.js +20 -4
- package/dist/http/routes/config-catalog.d.ts +3 -3
- package/dist/http/routes/config-catalog.js +1 -1
- package/dist/http/routes/devices.js +3 -17
- package/dist/http/routes/diagnostics.d.ts +3 -3
- package/dist/http/routes/diagnostics.js +6 -2
- package/dist/http/routes/fleet.js +4 -4
- package/dist/http/routes/images.js +6 -7
- package/dist/http/routes/leader.js +1 -8
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +3 -2
- package/dist/http/routes/memory-bundle.js +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-consolidation.js +1 -1
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/memory-origin.js +1 -1
- package/dist/http/routes/memory-policy.d.ts +1 -1
- package/dist/http/routes/memory-policy.js +3 -2
- package/dist/http/routes/notify-wake.js +8 -21
- package/dist/http/routes/observability.js +2 -2
- package/dist/http/routes/principal-inbox.d.ts +39 -0
- package/dist/http/routes/principal-inbox.js +76 -0
- package/dist/http/routes/retention-ops.js +2 -9
- package/dist/http/routes/rules.js +9 -22
- package/dist/http/routes/runs.d.ts +5 -0
- package/dist/http/routes/runs.js +63 -115
- package/dist/http/routes/session-sync.d.ts +3 -2
- package/dist/http/routes/session-sync.js +53 -48
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions-list.js +3 -4
- package/dist/http/routes/sessions.js +33 -43
- package/dist/http/routes/side-query.js +6 -4
- package/dist/http/routes/tasks.js +71 -30
- package/dist/http/routes/trace-usage.js +7 -9
- package/dist/http/routes/workflows.d.ts +351 -0
- package/dist/http/routes/workflows.js +153 -119
- package/dist/http/run-declared-families.d.ts +16 -0
- package/dist/http/run-declared-families.js +12 -0
- package/dist/http/send.d.ts +24 -3
- package/dist/http/send.js +14 -2
- package/dist/http/server.d.ts +23 -18
- package/dist/http/server.js +20 -15
- package/dist/http/stored-body-replay.js +17 -4
- package/dist/http/submit-ctx.d.ts +4 -3
- package/dist/http/submit-ctx.js +23 -6
- package/dist/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +5 -4
- package/dist/http/wire-types.d.ts +17 -10
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -1
- package/dist/lane-home-probe.d.ts +78 -9
- package/dist/lane-home-probe.js +78 -12
- package/dist/leader/endpoint.d.ts +4 -1
- package/dist/leader/endpoint.js +11 -10
- package/dist/leader/wire.d.ts +4 -0
- package/dist/leader/wire.js +8 -7
- package/dist/limit-refusal.d.ts +17 -5
- package/dist/limit-refusal.js +4 -1
- package/dist/main.js +1 -1
- package/dist/mcp-assertion-header.d.ts +31 -10
- package/dist/mcp-assertion-header.js +10 -3
- package/dist/memory-origin-fence.js +2 -2
- package/dist/memory-project-layer.d.ts +37 -0
- package/dist/memory-project-layer.js +46 -0
- package/dist/memory-scope.d.ts +23 -16
- package/dist/memory-scope.js +24 -8
- package/dist/memory-sync-client.d.ts +27 -13
- package/dist/memory-sync-client.js +107 -18
- package/dist/model-compat.d.ts +1 -1
- package/dist/model-entry-refusal.d.ts +9 -1
- package/dist/model-entry-refusal.js +6 -1
- package/dist/model-plane-face.d.ts +51 -0
- package/dist/model-plane-face.js +24 -0
- package/dist/model-provider.d.ts +5 -0
- package/dist/model-provider.js +4 -2
- package/dist/model-route-endpoint.d.ts +8 -11
- package/dist/model-route-endpoint.js +4 -7
- package/dist/model-route-env.d.ts +22 -0
- package/dist/model-route-env.js +2 -0
- package/dist/model-route-gap.d.ts +60 -30
- package/dist/model-route-gap.js +21 -15
- package/dist/observability/corrupt-read-seat.d.ts +7 -0
- package/dist/observability/corrupt-read-seat.js +9 -0
- package/dist/observability/err-text.d.ts +6 -0
- package/dist/observability/err-text.js +18 -4
- package/dist/observability/fail-open.d.ts +35 -9
- package/dist/observability/fail-open.js +35 -9
- package/dist/observability/metrics.js +1 -0
- package/dist/observability/prompt-manifest.d.ts +22 -25
- package/dist/observability/prompt-manifest.js +54 -50
- package/dist/observability/tool-trace.js +9 -10
- package/dist/operator-ask.d.ts +10 -0
- package/dist/operator-ask.js +3 -0
- package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
- package/dist/orchestration/workflow-agent-session-index.js +9 -13
- package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
- package/dist/orchestration/workflow-completion-inbox.js +13 -0
- package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
- package/dist/orchestration/workflow-notify-journal.js +27 -34
- package/dist/orchestration/workflow-park-decision.d.ts +89 -0
- package/dist/orchestration/workflow-park-decision.js +119 -0
- package/dist/org-delivery-gate.d.ts +81 -0
- package/dist/org-delivery-gate.js +59 -0
- package/dist/panel-tool-names.d.ts +23 -0
- package/dist/panel-tool-names.js +8 -0
- package/dist/parked-decide.d.ts +43 -11
- package/dist/parked-decide.js +100 -51
- package/dist/parked-revive-surface.d.ts +9 -2
- package/dist/parked-revive-surface.js +11 -8
- package/dist/permission-rule-list.d.ts +1 -1
- package/dist/permission-rule-list.js +2 -2
- package/dist/permission-rule-vocab.d.ts +1 -23
- package/dist/permission-rule-vocab.js +0 -13
- package/dist/plugins/approval-ask-store-file.d.ts +16 -1
- package/dist/plugins/approval-ask-store-file.js +21 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
- package/dist/plugins/approval-ask-store-memory.js +34 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
- package/dist/plugins/approval-ask-store-sql.js +37 -1
- package/dist/plugins/approval-payload-fingerprint.d.ts +14 -6
- package/dist/plugins/approval-payload-fingerprint.js +1 -1
- package/dist/plugins/blob-backend.d.ts +38 -25
- package/dist/plugins/blob-backend.js +29 -19
- package/dist/plugins/breaker-state-sql.d.ts +2 -2
- package/dist/plugins/breaker-state-sql.js +4 -4
- package/dist/plugins/caching-session-store.d.ts +4 -1
- package/dist/plugins/caching-session-store.js +7 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +36 -1
- package/dist/plugins/checkpoint-store-sql.js +65 -3
- package/dist/plugins/file-history-store-sql.d.ts +5 -2
- package/dist/plugins/file-history-store-sql.js +3 -1
- package/dist/plugins/file-run-store.d.ts +5 -13
- package/dist/plugins/file-run-store.js +9 -0
- package/dist/plugins/fork-routing-session-store.d.ts +9 -1
- package/dist/plugins/fork-routing-session-store.js +12 -1
- package/dist/plugins/host-platform.d.ts +2 -0
- package/dist/plugins/host-platform.js +2 -1
- package/dist/plugins/local-checkpoint-store.d.ts +15 -2
- package/dist/plugins/local-checkpoint-store.js +32 -1
- package/dist/plugins/local-session-store.d.ts +13 -10
- package/dist/plugins/local-session-store.js +23 -14
- package/dist/plugins/local-session-window.d.ts +45 -0
- package/dist/plugins/local-session-window.js +38 -0
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
- package/dist/plugins/mailbox-store-sql.d.ts +30 -48
- package/dist/plugins/mailbox-store-sql.js +77 -52
- package/dist/plugins/memory-embedder-fingerprint.js +2 -1
- package/dist/plugins/memory-run-store.d.ts +5 -13
- package/dist/plugins/memory-run-store.js +8 -0
- package/dist/plugins/one-time-migrations.d.ts +121 -5
- package/dist/plugins/one-time-migrations.js +332 -8
- package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
- package/dist/plugins/org-delivery-quota-store.js +228 -0
- package/dist/plugins/permission-rule-store-file.js +10 -6
- package/dist/plugins/permission-rule-store-sql.js +8 -8
- package/dist/plugins/pg-pool.js +39 -7
- package/dist/plugins/pg-session-storage.d.ts +18 -5
- package/dist/plugins/pg-session-storage.js +68 -23
- package/dist/plugins/remote-env-adb.d.ts +6 -12
- package/dist/plugins/remote-env-adb.js +12 -2
- package/dist/plugins/remote-env-device.d.ts +14 -7
- package/dist/plugins/remote-env-device.js +23 -15
- package/dist/plugins/remote-env-k8s.d.ts +8 -12
- package/dist/plugins/remote-env-k8s.js +23 -5
- package/dist/plugins/remote-env-local-docker.d.ts +10 -15
- package/dist/plugins/remote-env-local-docker.js +12 -9
- package/dist/plugins/remote-env-ssh.d.ts +10 -16
- package/dist/plugins/remote-env-ssh.js +17 -11
- package/dist/plugins/run-store-sql.d.ts +16 -14
- package/dist/plugins/run-store-sql.js +22 -2
- package/dist/plugins/schema-indexes.js +2 -0
- package/dist/plugins/send-user-file.js +2 -2
- package/dist/plugins/session-epoch-anchor.d.ts +32 -6
- package/dist/plugins/session-epoch-anchor.js +2 -3
- package/dist/plugins/session-ownership.d.ts +11 -0
- package/dist/plugins/session-ownership.js +11 -0
- package/dist/plugins/session-placement.d.ts +12 -14
- package/dist/plugins/session-placement.js +2 -15
- package/dist/plugins/session-store.d.ts +18 -8
- package/dist/plugins/session-store.js +15 -4
- package/dist/plugins/sql-driver.d.ts +74 -11
- package/dist/plugins/sql-driver.js +210 -12
- package/dist/plugins/sql-errors.d.ts +23 -0
- package/dist/plugins/sql-errors.js +21 -0
- package/dist/plugins/store-backend.d.ts +36 -1
- package/dist/plugins/store-backend.js +40 -14
- package/dist/plugins/store-contracts.d.ts +42 -0
- package/dist/plugins/store-contracts.js +1 -0
- package/dist/plugins/tidb-pool.d.ts +6 -1
- package/dist/plugins/tidb-pool.js +44 -10
- package/dist/plugins/tidb-session-storage.d.ts +3 -2
- package/dist/plugins/tidb-session-storage.js +2 -2
- package/dist/plugins/tidb-session-store.d.ts +25 -5
- package/dist/plugins/tidb-session-store.js +67 -21
- package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
- package/dist/plugins/workflow-journal-store-sql.js +19 -6
- package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
- package/dist/plugins/workflow-run-store-sql.js +50 -9
- package/dist/posture-source.d.ts +18 -10
- package/dist/posture-source.js +4 -1
- package/dist/project-identity.d.ts +45 -6
- package/dist/project-identity.js +162 -8
- package/dist/project-layer-key.d.ts +28 -0
- package/dist/project-layer-key.js +29 -0
- package/dist/question.js +3 -2
- package/dist/read-deny-entry.d.ts +25 -0
- package/dist/read-deny-entry.js +12 -0
- package/dist/read-face-posture.d.ts +37 -11
- package/dist/read-face-posture.js +32 -3
- package/dist/request-key-closure.d.ts +7 -0
- package/dist/request-key-closure.js +9 -1
- package/dist/request-tool-axes.d.ts +12 -0
- package/dist/request-tool-axes.js +20 -0
- package/dist/request-value-closure.d.ts +5 -0
- package/dist/request-value-closure.js +11 -3
- package/dist/rule-entry-list.d.ts +26 -2
- package/dist/rule-entry-list.js +72 -12
- package/dist/rules-consent.js +3 -4
- package/dist/run-acceptance.d.ts +19 -3
- package/dist/run-acceptance.js +13 -1
- package/dist/run-local.js +37 -6
- package/dist/runs.d.ts +12 -10
- package/dist/runs.js +25 -6
- package/dist/runtime-caps-resolver.d.ts +16 -6
- package/dist/runtime-caps-resolver.js +18 -5
- package/dist/sandbox-pkg-source.d.ts +19 -1
- package/dist/sandbox-pkg-source.js +29 -7
- package/dist/sealed-key.d.ts +32 -0
- package/dist/sealed-key.js +55 -1
- package/dist/security.d.ts +95 -15
- package/dist/security.js +52 -9
- package/dist/session-error-wire.d.ts +31 -7
- package/dist/session-error-wire.js +9 -2
- package/dist/session-sync-kernel.d.ts +37 -10
- package/dist/session-sync-kernel.js +10 -0
- package/dist/session-titled-frame.d.ts +33 -0
- package/dist/session-titled-frame.js +4 -0
- package/dist/session-titler.d.ts +9 -1
- package/dist/session-titler.js +15 -4
- package/dist/spec-fields.js +21 -2
- package/dist/sql-engine-posture.d.ts +3 -1
- package/dist/task-a2a.js +4 -3
- package/dist/task-cwd.d.ts +1 -1
- package/dist/task-mcp.d.ts +5 -5
- package/dist/task-mcp.js +27 -74
- package/dist/task-settings.d.ts +93 -88
- package/dist/task-settings.js +71 -63
- package/dist/text-bidi.d.ts +0 -4
- package/dist/text-bidi.js +1 -3
- package/dist/tighten-only-seats.d.ts +150 -0
- package/dist/tighten-only-seats.js +196 -0
- package/dist/tool-approval.d.ts +451 -136
- package/dist/tool-approval.js +733 -256
- package/dist/tool-rule-names.d.ts +6 -0
- package/dist/trace/core-keyset-guard.d.ts +108 -25
- package/dist/trace/exit-seat.d.ts +40 -0
- package/dist/trace/exit-seat.js +130 -0
- package/dist/trace/ledger-events.d.ts +6 -3
- package/dist/trace/project.d.ts +98 -13
- package/dist/trace/project.js +57 -32
- package/dist/trace/projection-table.d.ts +100 -0
- package/dist/trace/projection-table.js +130 -0
- package/dist/trace/redact.d.ts +57 -0
- package/dist/trace/redact.js +962 -168
- package/dist/trace/self-minted-wire.d.ts +349 -1
- package/dist/trace/self-minted-wire.js +118 -1
- package/dist/trace/wire-projection-faces.d.ts +304 -2
- package/dist/trace/wire-projection-faces.js +160 -13
- package/dist/url-refusal.js +2 -0
- package/dist/web-admin-client/apply-effective.d.ts +12 -0
- package/dist/web-admin-client/apply-effective.js +56 -5
- package/dist/web-admin-client/facade.d.ts +1 -1
- package/dist/web-admin-client/facade.js +1 -1
- package/dist/web-admin-client/read-face.js +5 -9
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.js +6 -8
- package/dist/web-admin-client/types.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
- package/package.json +8 -4
- package/scripts/drain-check-local.mjs +34 -2
- package/scripts/drain-check.mysql.sql +20 -2
- package/scripts/drain-check.pg.sql +20 -2
- package/dist/mcp-tool-faces.d.ts +0 -69
- package/dist/mcp-tool-faces.js +0 -106
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* - **不翻 `streamApproval` 能力位**([ref] 当时的裁 (c);⚠️ **这一位已由 S-384 翻真,不是被本店翻的**):
|
|
24
24
|
* 当年不翻的理由是「该位在 SQL 车道隐含 durable park 兜底,local 给不了」+「local 的 ask 账是进程内
|
|
25
25
|
* 易失形」。后半条已由 `FileApprovalAskStore` 消掉(持久账落地);前半条的答案一直在谓词里 ——
|
|
26
|
-
* `resolveStreamApprovalGate` 的 `
|
|
26
|
+
* `resolveStreamApprovalGate` 的 park 设施(`checkpointStore`)合取项要求 `backend.checkpoint` 在场 ∧ `DURABLE_APPROVAL`,
|
|
27
27
|
* 所以位报 true 的 local 部署**必然**配齐了 File 形 checkpoint 店(`durable-approval-local-e2e` 第一格
|
|
28
28
|
* 实证:park 行跨双 kill 存活、重启后 decide 驱动 resume 真跑完)。本店与那一位自此无关:它治的是
|
|
29
29
|
* **活卡窗内崩溃**(park 还没落盘)那一格的零痕迹病,而那一格无论位真位假都不复活 run。
|
|
@@ -166,11 +166,16 @@
|
|
|
166
166
|
* 同源(`store-backend.ts:780` 的 `config.localDataRoot`),数据落 `<root>/approval-ask-audit/`。
|
|
167
167
|
*
|
|
168
168
|
* ## 体量与保留
|
|
169
|
-
* 只在真出卡时写(人批一次 = 3 行),量级 =
|
|
170
|
-
*
|
|
169
|
+
* 只在真出卡时写(人批一次 = 3 行),量级 = 人的手速。保留 = 审批账本的留存律(律一处成文在 `approval-ask-retention.ts`;维护 tick 按
|
|
170
|
+
* `APPROVAL_ASK_RETENTION_MS` 调 {@link FileApprovalAskAuditStore.rotateOlderThan}):**整问**删 —— 一问不再欠下一次起服收敛一个答案
|
|
171
|
+
* (下面的收敛判官此刻不会把它收成孤儿)且它所有记录里最晚的时刻早于 cutoff,它的全部行(铸造 / 决议 / 收敛 / 迟到结算)一起离开文件;
|
|
172
|
+
* 腿记录(按 taskId)只在没有任何留下的问还认它、且它自己也过窗时才删,于是留下的问的收敛投影(成因 / `resumeSafe`)一字不变;
|
|
173
|
+
* 认不出的行证不出到期,原样留;发起它的 run 还能动(跑着 / 停驻)的问也留。**只删不改**:留下的行逐字节写回(原子换文件,0o600),删了多少进读数行。
|
|
174
|
+
* 读面列表按收敛时刻新前旧后、上限 {@link CRASH_CONVERGED_LIST_MAX}(有界 wire)。
|
|
171
175
|
*/
|
|
172
176
|
import type { HostDecision } from "./host-decision.js";
|
|
173
177
|
import { AppendLog } from "@sema-agent/core";
|
|
178
|
+
import type { AuditRotationReading } from "./approval-ask-retention.js";
|
|
174
179
|
import { SETTLE_OUTCOME, type HolderGoneCause, type SettleCause } from "./approval-deny-reasons.js";
|
|
175
180
|
/** 数据子目录名(挂在 local 数据根下,与 `workflow-notify/` 同层同形)。 */
|
|
176
181
|
export declare const APPROVAL_ASK_AUDIT_DIR = "approval-ask-audit";
|
|
@@ -328,6 +333,8 @@ export declare class FileApprovalAskAuditStore implements ApprovalAskAuditSink,
|
|
|
328
333
|
private log;
|
|
329
334
|
/** 追加口的铸造座(测试注入席:单条写失败 / 半写的确定性构造;生产恒缺省 = `new AppendLog(path)`)。 */
|
|
330
335
|
private readonly openLog;
|
|
336
|
+
/** 轮转换文件之后的目录 fsync(测试注入席:失败的确定性构造;生产恒缺省 = {@link fsyncDirectory})。 */
|
|
337
|
+
private readonly fsyncDir;
|
|
331
338
|
/** boot 重放快照(冻结于构造时刻 = 前世账本;本进程新写的行不进它 —— 收敛只对前世行)。 */
|
|
332
339
|
private readonly replayed;
|
|
333
340
|
/** 前世账本里的腿闭事件(taskId + 行序;decided 臂按「决议行之后」判)。 */
|
|
@@ -369,12 +376,12 @@ export declare class FileApprovalAskAuditStore implements ApprovalAskAuditSink,
|
|
|
369
376
|
*/
|
|
370
377
|
constructor(root: string, internals?: {
|
|
371
378
|
appendLog?: (path: string) => AuditAppendPort;
|
|
379
|
+
fsyncDir?: (dir: string) => void;
|
|
372
380
|
});
|
|
373
381
|
/** 重放的坏值计数(`convergeCrashedAsks().corruptLines`):重放属主跳过的坏行(撕尾不计)+ 成因词表外的行(行在、结清照认,坏值照样计数)。 */
|
|
374
382
|
private corruptLines;
|
|
375
383
|
/** 重放前世账本(共用口 `replayJsonlSkipping`):撕尾 = 未落完的写,静默跳过;坏行跳过 + 逐条计数 / 探针;坏行数另暴露给收敛日志。 */
|
|
376
384
|
private replay;
|
|
377
|
-
private group;
|
|
378
385
|
/** append + fsync(逐行落盘:进程猝死不丢已记的行 —— 本店的全部价值就在崩溃时刻;写口 = 共用的 `AppendLog`:单次 `writeSync` 一行、末段在打开与每次追加前修(撕尾截、完整末行补换行)、失败的写截回开写处)。
|
|
379
386
|
* 运行期失败**响亮不阻断**:审批可用性不押在审计盘上(盘满/只读时人还得能批),但丢行必须在遥测
|
|
380
387
|
* 显形([ref] 三件套,census 登记行同批)。
|
|
@@ -445,18 +452,29 @@ export declare class FileApprovalAskAuditStore implements ApprovalAskAuditSink,
|
|
|
445
452
|
/** S-929 收敛行的成因注(判据见头注「收敛行的 `cause`」):组的最后一个事件行之后、收敛行(若已收敛)之前,有本 taskId 的
|
|
446
453
|
* 有序关停记号 ⇒ `shutdown_before_park`;否则 `crashed_before_park`。 */
|
|
447
454
|
private causeOf;
|
|
448
|
-
/**
|
|
449
|
-
* 🔴 **S-945([ref])—— 腿证据只对被追踪的 ask 行作数**:一处成文,三处读(pending 臂的腿闭反证门 / decided 臂 / 收敛行成因注)。
|
|
450
|
-
* 腿闭行与有序关停记号都只按 `taskId` 落;委派 / 后台子代 ask 行的 `taskId` 是**宿主** run(出处),承载它的不是宿主腿(铸造时
|
|
451
|
-
* `legTracked:false`)⇒ 宿主腿的这两类记录对它什么都不证明(修前反证门不看 `legTracked`:宿主腿闭把子代未结清卡判成 inconsistent、不列孤儿)。
|
|
452
|
-
* 返回 `undefined` = 这一行没有可作证的腿;否则 = 本 taskId 在 `(afterLine, beforeLine)` 之间有没有该类记录。
|
|
453
|
-
*/
|
|
454
|
-
private legEvidence;
|
|
455
455
|
private projectRow;
|
|
456
|
-
/** scope 门与 `listLivePending`
|
|
457
|
-
* `owner === scope` 的行(null-owner
|
|
458
|
-
* 未鉴权哨兵自然恒空)。 */
|
|
456
|
+
/** scope 门与 `listLivePending` 逐字同律(同一只 checkpoint scope 解码):`undefined` = operator 全量(含 owner null 行);
|
|
457
|
+
* `_` = 匿名那一组 = owner null 的行;其余串 = 只见 `owner === scope` 的行(null-owner 行对具名主体不列,宁少列不超范围)。 */
|
|
459
458
|
listCrashConverged(scope: string | undefined): CrashConvergedRow[];
|
|
459
|
+
/**
|
|
460
|
+
* **留存轮转**(审批账本留存律的审计账半场;律一处成文在 `approval-ask-retention.ts`,判据见头注「体量与保留」)。维护 tick 是唯一调用方。
|
|
461
|
+
*
|
|
462
|
+
* 读的是**文件**(前世 + 本进程两段账,行序即语义序),不是构造时冻结的前世快照:本进程铸的问要按它此刻在盘上的样子判「结了没有」。
|
|
463
|
+
* 判「结了」= 它挂靠的格(铸造行的 `taskId` / `sessionId` / `sourceTaskId`)都不在 `keepAnchors`(还能动的东西的挂靠集,由清扫从 run 账与
|
|
464
|
+
* 后台子代账列出)∧ {@link judgeOrphan} 此刻不欠它答案 —— 停驻 run / 能动子代的问(窗到期转 durable、迟到结算还要这组前置事实)、活卡
|
|
465
|
+
* (铸了没决)与批了腿没闭的问多老都留。删的单位是**整问**:
|
|
466
|
+
* · 一问的最后动静 = 它所有记录(铸造 / 决议 / 收敛 / 迟到结算)里最晚的时刻;早于 cutoff ∧ 不欠答案 ⇒ 这一问的全部行删;
|
|
467
|
+
* · 腿记录(按 taskId)只在它自己也早于 cutoff ∧ 没有任何留下的问是这个 taskId ∧ 这个 taskId 不在挂靠集时才删 —— 留下的问的收敛投影(成因 / `resumeSafe`)读得到的腿证据一条不少;
|
|
468
|
+
* · 身份说不清的迟到结算(`approvalId:null`)按它自己的时刻;认不出的行(腐行 / 词表外)证不出到期 ⇒ 原样留;
|
|
469
|
+
* 末尾没换行的那一段原样留在末尾(不补换行),由追加口下次打开时按 core 的同一只判词修(解析成对象补换行、撕尾截断)。
|
|
470
|
+
* 只删不改:留下的每一行按**原字节**写回(按换行字节切段,不经解码 —— 非 UTF-8 的字节一个不变),原子换文件({@link replaceFileBytes}:
|
|
471
|
+
* 0o600;换上之前失败 ⇒ 原文件原样,错误抛给维护 tick 的节流 catch;换上之后只剩目录 fsync,失败走 F 类 tag、读数照交);
|
|
472
|
+
* 追加口先收,下一次 append 在新文件上惰性重开。没有可删的行 ⇒ 文件一字不动、不重写。
|
|
473
|
+
*
|
|
474
|
+
* 内存同步剪:被删的问离开迟到结算的反查索引(之后对它的迟到决议证不出「窗到期已转 durable」⇒ 一行不写 —— 盘上查无前置事实的行不许写)、
|
|
475
|
+
* 离开 `crashConverged` 读面与前世快照。前世快照里留下的组与腿记录的行序不动(它们只在起服收敛那一拍被读,彼此仍自洽)。
|
|
476
|
+
*/
|
|
477
|
+
rotateOlderThan(cutoffMs: number, keepAnchors: ReadonlySet<string>): AuditRotationReading;
|
|
460
478
|
/** 收追加口(优雅关闭腿;SIGKILL 下不跑也不丢 —— 每行已 fsync)。core `AppendLog.close()` 自己吞 `closeSync` 的错、不抛(全函数),本店不再包 catch。 */
|
|
461
479
|
close(): void;
|
|
462
480
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
|
+
import { closeSync, existsSync, fsyncSync, openSync, readFileSync, renameSync, unlinkSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { AppendLog, ensureDir, isHostDecider, writeThenLink } from "@sema-agent/core";
|
|
4
5
|
import { recordFailOpen } from "./observability/fail-open.js";
|
|
6
|
+
import { ownerOfCheckpointScope } from "./security.js";
|
|
5
7
|
import { replayJsonlSkipping } from "./observability/corrupt-read-seat.js";
|
|
6
8
|
import { isSettleCause, SETTLE_OUTCOME } from "./approval-deny-reasons.js";
|
|
7
9
|
export const APPROVAL_ASK_AUDIT_DIR = "approval-ask-audit";
|
|
@@ -168,10 +170,157 @@ const LEDGER_SHAPE = {
|
|
|
168
170
|
return rec === undefined ? undefined : { rec, outOfSetCause };
|
|
169
171
|
},
|
|
170
172
|
};
|
|
173
|
+
function foldLedger(records) {
|
|
174
|
+
const groups = new Map();
|
|
175
|
+
const legClosed = [];
|
|
176
|
+
const shutdownMarks = [];
|
|
177
|
+
const group = (approvalId, line) => {
|
|
178
|
+
let g = groups.get(approvalId);
|
|
179
|
+
if (!g) {
|
|
180
|
+
g = { firstLine: line };
|
|
181
|
+
groups.set(approvalId, g);
|
|
182
|
+
}
|
|
183
|
+
return g;
|
|
184
|
+
};
|
|
185
|
+
for (const { rec, line } of records) {
|
|
186
|
+
switch (rec.kind) {
|
|
187
|
+
case "ask": {
|
|
188
|
+
const g = group(rec.approvalId, line);
|
|
189
|
+
if (g.ask === undefined) {
|
|
190
|
+
g.ask = rec;
|
|
191
|
+
g.askLine = line;
|
|
192
|
+
}
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
case "settle": {
|
|
196
|
+
const g = group(rec.approvalId, line);
|
|
197
|
+
if (g.settle === undefined) {
|
|
198
|
+
g.settle = rec;
|
|
199
|
+
g.settleLine = line;
|
|
200
|
+
}
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
case "late_settle":
|
|
204
|
+
break;
|
|
205
|
+
case "leg_closed":
|
|
206
|
+
legClosed.push({ taskId: rec.taskId, line });
|
|
207
|
+
break;
|
|
208
|
+
case "interrupted_by_shutdown":
|
|
209
|
+
shutdownMarks.push({ taskId: rec.taskId, line });
|
|
210
|
+
break;
|
|
211
|
+
case "crash_converged": {
|
|
212
|
+
const g = group(rec.approvalId, line);
|
|
213
|
+
g.converged = rec;
|
|
214
|
+
g.convergedLine = line;
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
default: {
|
|
218
|
+
const unreachable = rec;
|
|
219
|
+
throw new Error(`approval-ask-audit fold: unreachable record ${String(unreachable)}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return { groups, legClosed, shutdownMarks };
|
|
224
|
+
}
|
|
225
|
+
function legEvidenceOf(g, records, afterLine, beforeLine = Number.POSITIVE_INFINITY) {
|
|
226
|
+
const ask = g.ask;
|
|
227
|
+
if (!ask.legTracked)
|
|
228
|
+
return undefined;
|
|
229
|
+
return records.some((r) => r.taskId === ask.taskId && r.line > afterLine && r.line < beforeLine);
|
|
230
|
+
}
|
|
231
|
+
function judgeOrphan(g, legClosed) {
|
|
232
|
+
if (g.ask === undefined || g.converged !== undefined)
|
|
233
|
+
return undefined;
|
|
234
|
+
if (g.settle === undefined) {
|
|
235
|
+
return legEvidenceOf(g, legClosed, g.askLine ?? 0) === true ? "inconsistent" : "pending";
|
|
236
|
+
}
|
|
237
|
+
if (g.settle.outcome === "allowed" && legEvidenceOf(g, legClosed, g.settleLine ?? 0) === false)
|
|
238
|
+
return "decided";
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
function readLedgerLine(raw) {
|
|
242
|
+
let parsed;
|
|
243
|
+
try {
|
|
244
|
+
parsed = JSON.parse(raw.toString("utf8"));
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
return { unparsable: err };
|
|
248
|
+
}
|
|
249
|
+
return { rec: readLedgerRecord(parsed, () => { }) };
|
|
250
|
+
}
|
|
251
|
+
function recordOfLine(raw) {
|
|
252
|
+
const read = readLedgerLine(raw);
|
|
253
|
+
return "rec" in read ? read.rec : undefined;
|
|
254
|
+
}
|
|
255
|
+
function replaceFileBytes(target, bytes) {
|
|
256
|
+
const staging = join(dirname(target), ".tmp", `${APPROVAL_ASK_AUDIT_LEDGER}.${process.pid}.${randomBytes(6).toString("hex")}.rotate`);
|
|
257
|
+
try {
|
|
258
|
+
writeThenLink(staging, bytes);
|
|
259
|
+
renameSync(staging, target);
|
|
260
|
+
}
|
|
261
|
+
finally {
|
|
262
|
+
if (existsSync(staging))
|
|
263
|
+
unlinkSync(staging);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
function fsyncDirectory(dir) {
|
|
267
|
+
const fd = openSync(dir, "r");
|
|
268
|
+
try {
|
|
269
|
+
fsyncSync(fd);
|
|
270
|
+
}
|
|
271
|
+
finally {
|
|
272
|
+
closeSync(fd);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function splitLedgerBytes(bytes) {
|
|
276
|
+
const lines = [];
|
|
277
|
+
let start = 0;
|
|
278
|
+
for (let i = bytes.indexOf(0x0a, start); i !== -1; i = bytes.indexOf(0x0a, start)) {
|
|
279
|
+
lines.push(bytes.subarray(start, i));
|
|
280
|
+
start = i + 1;
|
|
281
|
+
}
|
|
282
|
+
return { lines, tail: bytes.subarray(start) };
|
|
283
|
+
}
|
|
284
|
+
function approvalIdOf(rec) {
|
|
285
|
+
switch (rec.kind) {
|
|
286
|
+
case "ask":
|
|
287
|
+
case "settle":
|
|
288
|
+
case "crash_converged":
|
|
289
|
+
case "late_settle":
|
|
290
|
+
return rec.approvalId;
|
|
291
|
+
case "leg_closed":
|
|
292
|
+
case "interrupted_by_shutdown":
|
|
293
|
+
return undefined;
|
|
294
|
+
default: {
|
|
295
|
+
const unreachable = rec;
|
|
296
|
+
throw new Error(`approval-ask-audit: unreachable record ${String(unreachable)}`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function atMsOf(rec) {
|
|
301
|
+
switch (rec.kind) {
|
|
302
|
+
case "ask":
|
|
303
|
+
return rec.mintedAtMs;
|
|
304
|
+
case "settle":
|
|
305
|
+
case "late_settle":
|
|
306
|
+
return rec.settledAtMs;
|
|
307
|
+
case "crash_converged":
|
|
308
|
+
return rec.convergedAtMs;
|
|
309
|
+
case "leg_closed":
|
|
310
|
+
return rec.closedAtMs;
|
|
311
|
+
case "interrupted_by_shutdown":
|
|
312
|
+
return rec.atMs;
|
|
313
|
+
default: {
|
|
314
|
+
const unreachable = rec;
|
|
315
|
+
throw new Error(`approval-ask-audit: unreachable record ${String(unreachable)}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
171
319
|
export class FileApprovalAskAuditStore {
|
|
172
320
|
ledgerPath;
|
|
173
321
|
log;
|
|
174
322
|
openLog;
|
|
323
|
+
fsyncDir;
|
|
175
324
|
replayed = new Map();
|
|
176
325
|
replayedLegClosed = [];
|
|
177
326
|
replayedShutdownMarks = [];
|
|
@@ -185,6 +334,7 @@ export class FileApprovalAskAuditStore {
|
|
|
185
334
|
askTaskId = new Map();
|
|
186
335
|
constructor(root, internals) {
|
|
187
336
|
this.openLog = internals?.appendLog ?? ((p) => new AppendLog(p));
|
|
337
|
+
this.fsyncDir = internals?.fsyncDir ?? fsyncDirectory;
|
|
188
338
|
const dir = join(root, APPROVAL_ASK_AUDIT_DIR);
|
|
189
339
|
ensureDir(dir);
|
|
190
340
|
this.ledgerPath = join(dir, APPROVAL_ASK_AUDIT_LEDGER);
|
|
@@ -193,59 +343,20 @@ export class FileApprovalAskAuditStore {
|
|
|
193
343
|
corruptLines = 0;
|
|
194
344
|
replay() {
|
|
195
345
|
const { records, skipped } = replayJsonlSkipping(this.ledgerPath, "approval-ask-audit", LEDGER_SHAPE);
|
|
196
|
-
this.corruptLines = skipped;
|
|
197
|
-
|
|
198
|
-
for (const
|
|
199
|
-
line += 1;
|
|
200
|
-
if (outOfSetCause)
|
|
201
|
-
this.corruptLines += 1;
|
|
202
|
-
switch (rec.kind) {
|
|
203
|
-
case "ask": {
|
|
204
|
-
const g = this.group(rec.approvalId, line);
|
|
205
|
-
if (g.ask === undefined) {
|
|
206
|
-
g.ask = rec;
|
|
207
|
-
g.askLine = line;
|
|
208
|
-
}
|
|
209
|
-
this.indexAsk(rec);
|
|
210
|
-
break;
|
|
211
|
-
}
|
|
212
|
-
case "settle": {
|
|
213
|
-
const g = this.group(rec.approvalId, line);
|
|
214
|
-
if (g.settle === undefined) {
|
|
215
|
-
g.settle = rec;
|
|
216
|
-
g.settleLine = line;
|
|
217
|
-
}
|
|
218
|
-
this.indexSettle(rec);
|
|
219
|
-
break;
|
|
220
|
-
}
|
|
221
|
-
case "late_settle":
|
|
222
|
-
break;
|
|
223
|
-
case "leg_closed":
|
|
224
|
-
this.replayedLegClosed.push({ taskId: rec.taskId, line });
|
|
225
|
-
break;
|
|
226
|
-
case "interrupted_by_shutdown":
|
|
227
|
-
this.replayedShutdownMarks.push({ taskId: rec.taskId, line });
|
|
228
|
-
break;
|
|
229
|
-
case "crash_converged": {
|
|
230
|
-
const g = this.group(rec.approvalId, line);
|
|
231
|
-
g.converged = rec;
|
|
232
|
-
g.convergedLine = line;
|
|
233
|
-
break;
|
|
234
|
-
}
|
|
235
|
-
default: {
|
|
236
|
-
const unreachable = rec;
|
|
237
|
-
throw new Error(`approval-ask-audit replay: unreachable record ${String(unreachable)}`);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
group(approvalId, line) {
|
|
243
|
-
let g = this.replayed.get(approvalId);
|
|
244
|
-
if (!g) {
|
|
245
|
-
g = { firstLine: line };
|
|
346
|
+
this.corruptLines = skipped + records.filter((r) => r.outOfSetCause).length;
|
|
347
|
+
const fold = foldLedger(records.map(({ rec }, i) => ({ rec, line: i + 1 })));
|
|
348
|
+
for (const [approvalId, g] of fold.groups)
|
|
246
349
|
this.replayed.set(approvalId, g);
|
|
350
|
+
for (const r of fold.legClosed)
|
|
351
|
+
this.replayedLegClosed.push(r);
|
|
352
|
+
for (const r of fold.shutdownMarks)
|
|
353
|
+
this.replayedShutdownMarks.push(r);
|
|
354
|
+
for (const { rec } of records) {
|
|
355
|
+
if (rec.kind === "ask")
|
|
356
|
+
this.indexAsk(rec);
|
|
357
|
+
else if (rec.kind === "settle")
|
|
358
|
+
this.indexSettle(rec);
|
|
247
359
|
}
|
|
248
|
-
return g;
|
|
249
360
|
}
|
|
250
361
|
append(rec) {
|
|
251
362
|
try {
|
|
@@ -346,18 +457,12 @@ export class FileApprovalAskAuditStore {
|
|
|
346
457
|
this.convergedRows.push({ row: this.projectRow(g, g.converged.orphanState, g.converged.convergedAtMs, this.causeOf(g)), owner: g.ask.owner });
|
|
347
458
|
continue;
|
|
348
459
|
}
|
|
349
|
-
|
|
350
|
-
if (
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
continue;
|
|
354
|
-
}
|
|
355
|
-
orphanState = "pending";
|
|
356
|
-
}
|
|
357
|
-
else if (g.settle.outcome === "allowed" &&
|
|
358
|
-
this.legEvidence(g, this.replayedLegClosed, g.settleLine ?? 0) === false) {
|
|
359
|
-
orphanState = "decided";
|
|
460
|
+
const verdict = judgeOrphan(g, this.replayedLegClosed);
|
|
461
|
+
if (verdict === "inconsistent") {
|
|
462
|
+
inconsistent += 1;
|
|
463
|
+
continue;
|
|
360
464
|
}
|
|
465
|
+
const orphanState = verdict;
|
|
361
466
|
if (orphanState === undefined)
|
|
362
467
|
continue;
|
|
363
468
|
const convergedAtMs = Date.now();
|
|
@@ -379,13 +484,7 @@ export class FileApprovalAskAuditStore {
|
|
|
379
484
|
causeOf(g) {
|
|
380
485
|
const after = g.settleLine ?? g.askLine ?? 0;
|
|
381
486
|
const before = g.convergedLine ?? Number.POSITIVE_INFINITY;
|
|
382
|
-
return
|
|
383
|
-
}
|
|
384
|
-
legEvidence(g, records, afterLine, beforeLine = Number.POSITIVE_INFINITY) {
|
|
385
|
-
const ask = g.ask;
|
|
386
|
-
if (!ask.legTracked)
|
|
387
|
-
return undefined;
|
|
388
|
-
return records.some((r) => r.taskId === ask.taskId && r.line > afterLine && r.line < beforeLine);
|
|
487
|
+
return legEvidenceOf(g, this.replayedShutdownMarks, after, before) === true ? "shutdown_before_park" : "crashed_before_park";
|
|
389
488
|
}
|
|
390
489
|
projectRow(g, orphanState, convergedAtMs, cause) {
|
|
391
490
|
const ask = g.ask;
|
|
@@ -401,18 +500,117 @@ export class FileApprovalAskAuditStore {
|
|
|
401
500
|
orphanState,
|
|
402
501
|
...(orphanState === "decided" ? { originalDecision: "approve", ...(g.settle !== undefined ? { decidedAtMs: g.settle.settledAtMs } : {}) } : {}),
|
|
403
502
|
convergedAtMs,
|
|
404
|
-
resumeSafe: orphanState === "pending" &&
|
|
503
|
+
resumeSafe: orphanState === "pending" && legEvidenceOf(g, this.replayedLegClosed, g.askLine ?? 0) === false,
|
|
405
504
|
};
|
|
406
505
|
}
|
|
407
506
|
listCrashConverged(scope) {
|
|
408
507
|
const rows = [];
|
|
508
|
+
const owner = scope === undefined ? undefined : ownerOfCheckpointScope(scope);
|
|
409
509
|
for (const e of this.convergedRows) {
|
|
410
|
-
if (
|
|
510
|
+
if (owner !== undefined && e.owner !== owner)
|
|
411
511
|
continue;
|
|
412
512
|
rows.push(e.row);
|
|
413
513
|
}
|
|
414
514
|
return rows;
|
|
415
515
|
}
|
|
516
|
+
rotateOlderThan(cutoffMs, keepAnchors) {
|
|
517
|
+
let bytes;
|
|
518
|
+
try {
|
|
519
|
+
bytes = readFileSync(this.ledgerPath);
|
|
520
|
+
}
|
|
521
|
+
catch (err) {
|
|
522
|
+
if (err.code === "ENOENT")
|
|
523
|
+
return { droppedAsks: 0, droppedRecords: 0, keptRecords: 0 };
|
|
524
|
+
throw err;
|
|
525
|
+
}
|
|
526
|
+
const { lines, tail } = splitLedgerBytes(bytes);
|
|
527
|
+
const entries = lines.map((raw) => ({ raw, terminated: true, rec: recordOfLine(raw) }));
|
|
528
|
+
if (tail.length > 0)
|
|
529
|
+
entries.push({ raw: tail, terminated: false, rec: recordOfLine(tail) });
|
|
530
|
+
const numbered = entries.flatMap((e, i) => (e.rec !== undefined ? [{ rec: e.rec, line: i + 1 }] : []));
|
|
531
|
+
const fold = foldLedger(numbered);
|
|
532
|
+
const lastAt = new Map();
|
|
533
|
+
const anchorsOf = new Map();
|
|
534
|
+
for (const { rec } of numbered) {
|
|
535
|
+
const id = approvalIdOf(rec);
|
|
536
|
+
if (typeof id !== "string")
|
|
537
|
+
continue;
|
|
538
|
+
lastAt.set(id, Math.max(lastAt.get(id) ?? Number.NEGATIVE_INFINITY, atMsOf(rec)));
|
|
539
|
+
const cells = rec.kind === "ask" ? [rec.taskId, rec.sessionId, rec.sourceTaskId] : rec.kind === "late_settle" ? [rec.taskId, rec.sessionId] : [];
|
|
540
|
+
const list = anchorsOf.get(id) ?? [];
|
|
541
|
+
for (const c of cells)
|
|
542
|
+
if (c !== undefined)
|
|
543
|
+
list.push(c);
|
|
544
|
+
anchorsOf.set(id, list);
|
|
545
|
+
}
|
|
546
|
+
const dropped = new Set();
|
|
547
|
+
for (const [id, at] of lastAt) {
|
|
548
|
+
if (at >= cutoffMs)
|
|
549
|
+
continue;
|
|
550
|
+
if ((anchorsOf.get(id) ?? []).some((a) => keepAnchors.has(a)))
|
|
551
|
+
continue;
|
|
552
|
+
const g = fold.groups.get(id);
|
|
553
|
+
const verdict = g === undefined ? undefined : judgeOrphan(g, fold.legClosed);
|
|
554
|
+
if (verdict === "pending" || verdict === "decided")
|
|
555
|
+
continue;
|
|
556
|
+
dropped.add(id);
|
|
557
|
+
}
|
|
558
|
+
const claimedTasks = new Set();
|
|
559
|
+
for (const [id, g] of fold.groups)
|
|
560
|
+
if (!dropped.has(id) && g.ask !== undefined)
|
|
561
|
+
claimedTasks.add(g.ask.taskId);
|
|
562
|
+
const keep = (rec) => {
|
|
563
|
+
if (rec === undefined)
|
|
564
|
+
return true;
|
|
565
|
+
switch (rec.kind) {
|
|
566
|
+
case "ask":
|
|
567
|
+
case "settle":
|
|
568
|
+
case "crash_converged":
|
|
569
|
+
return !dropped.has(rec.approvalId);
|
|
570
|
+
case "late_settle":
|
|
571
|
+
return rec.approvalId !== null ? !dropped.has(rec.approvalId) : rec.settledAtMs >= cutoffMs;
|
|
572
|
+
case "leg_closed":
|
|
573
|
+
case "interrupted_by_shutdown":
|
|
574
|
+
return atMsOf(rec) >= cutoffMs || claimedTasks.has(rec.taskId) || keepAnchors.has(rec.taskId);
|
|
575
|
+
default: {
|
|
576
|
+
const unreachable = rec;
|
|
577
|
+
throw new Error(`approval-ask-audit rotate: unreachable record ${String(unreachable)}`);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
const kept = entries.filter((e) => keep(e.rec));
|
|
582
|
+
const droppedRecords = entries.length - kept.length;
|
|
583
|
+
if (droppedRecords === 0)
|
|
584
|
+
return { droppedAsks: 0, droppedRecords: 0, keptRecords: entries.length };
|
|
585
|
+
this.log?.close();
|
|
586
|
+
this.log = undefined;
|
|
587
|
+
const NEWLINE = Buffer.from([0x0a]);
|
|
588
|
+
replaceFileBytes(this.ledgerPath, Buffer.concat(kept.flatMap((e) => (e.terminated ? [e.raw, NEWLINE] : [e.raw]))));
|
|
589
|
+
for (const id of dropped) {
|
|
590
|
+
this.replayed.delete(id);
|
|
591
|
+
this.askTaskId.delete(id);
|
|
592
|
+
this.parkExpired.delete(id);
|
|
593
|
+
}
|
|
594
|
+
for (const bucket of [this.askByCallAnchor, this.askBySessionOnly]) {
|
|
595
|
+
for (const [key, ids] of bucket) {
|
|
596
|
+
for (const id of dropped)
|
|
597
|
+
ids.delete(id);
|
|
598
|
+
if (ids.size === 0)
|
|
599
|
+
bucket.delete(key);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
const survivors = this.convergedRows.filter((e) => !dropped.has(e.row.approvalId));
|
|
603
|
+
this.convergedRows.length = 0;
|
|
604
|
+
for (const e of survivors)
|
|
605
|
+
this.convergedRows.push(e);
|
|
606
|
+
try {
|
|
607
|
+
this.fsyncDir(dirname(this.ledgerPath));
|
|
608
|
+
}
|
|
609
|
+
catch (err) {
|
|
610
|
+
recordFailOpen("server.approval-ask-audit.rotate-dir-fsync-failed", `path=${this.ledgerPath} err=${err instanceof Error ? err.message : String(err)}`);
|
|
611
|
+
}
|
|
612
|
+
return { droppedAsks: dropped.size, droppedRecords, keptRecords: kept.length };
|
|
613
|
+
}
|
|
416
614
|
close() {
|
|
417
615
|
this.log?.close();
|
|
418
616
|
this.log = undefined;
|
|
@@ -15,6 +15,21 @@ export declare const BATCH_TERMINAL: ReadonlySet<BatchState>;
|
|
|
15
15
|
* 都在这里),放这里不引新依赖边。
|
|
16
16
|
*/
|
|
17
17
|
export declare const MAX_DECISION_NOTE_CHARS = 2048;
|
|
18
|
+
/**
|
|
19
|
+
* 回决回执上「理由记上了吗」(`noteRecorded`)一格的**唯一判官与唯一组句器** —— 两口回决(live
|
|
20
|
+
* `POST /v1/tool-approvals/:id/respond` 与耐久 `POST /v1/tasks/:taskId/asks/:askId/decision`)的每一个 200
|
|
21
|
+
* 回体(PARKED 行经赎回腿受理的那一腿除外:它的理由走检查点回决链、不写 ask 行,尚无「记在哪张行」的定义,契约里点名为未覆盖)都经这两只函数说这件事,
|
|
22
|
+
* 不在各自的回体字面量里手写第二份。
|
|
23
|
+
*
|
|
24
|
+
* 三态同一份契约:请求**没带** `note` ⇒ 键缺席(不是 `false`);带了 ⇒ `true | false`:`true` = **已确认**持久行上那段文本就是这次提交的
|
|
25
|
+
* (逐字相等才算 —— 文本真的相同就不是谎,哪怕是别人写的);`false` = **没确认**(行上是别人的理由 / 这台没有店 / 店抖动而确认读也读不到 ——
|
|
26
|
+
* 不知道不许说成成功),不是「这台部署有没有店」。耐久回决口手里恒有那一行,它的 `false` 就是「行上不是这次那段」。
|
|
27
|
+
*/
|
|
28
|
+
export declare function noteLandedOnRow(requestNote: string | undefined, rowNote: string | null): boolean;
|
|
29
|
+
/** {@link noteLandedOnRow} 的组句器:只在请求带了 `note` 时铸 `noteRecorded`(`landed` 由调用方按各自能证明的事实给)。 */
|
|
30
|
+
export declare function noteRecordedReceipt(requestNote: string | undefined, landed: boolean): {
|
|
31
|
+
noteRecorded?: boolean;
|
|
32
|
+
};
|
|
18
33
|
/** ask 转移合法性(表驱动,含拒绝同值自环——STREAM_PENDING→STREAM_PENDING 不在表里,故 false)。 */
|
|
19
34
|
export declare function canAskTransition(from: AskState, to: AskState): boolean;
|
|
20
35
|
/** 批转移合法性,同形。 */
|
|
@@ -2,6 +2,12 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
export const ASK_TERMINAL = new Set(["DECIDED", "PARKED", "DENIED", "VOID"]);
|
|
3
3
|
export const BATCH_TERMINAL = new Set(["ROUTING_BOUND", "ABORTED"]);
|
|
4
4
|
export const MAX_DECISION_NOTE_CHARS = 2048;
|
|
5
|
+
export function noteLandedOnRow(requestNote, rowNote) {
|
|
6
|
+
return requestNote !== undefined && rowNote === requestNote;
|
|
7
|
+
}
|
|
8
|
+
export function noteRecordedReceipt(requestNote, landed) {
|
|
9
|
+
return requestNote === undefined ? {} : { noteRecorded: landed };
|
|
10
|
+
}
|
|
5
11
|
const ASK_TRANSITIONS = {
|
|
6
12
|
STREAM_PENDING: ["DECIDED", "PARKING", "VOID"],
|
|
7
13
|
PARKING: ["PARKED", "DENIED", "VOID"],
|