@sema-agent/server 7.149.0 → 7.151.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 +307 -9
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +92 -40
- package/deploy/sema-up/README.md +7 -1
- package/deploy/sema-up/chart/Chart.yaml +1 -1
- package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
- package/deploy/sema-up/chart/templates/server.yaml +5 -3
- package/deploy/sema-up/chart/values-full-single.yaml +3 -1
- package/deploy/sema-up/chart/values.yaml +8 -1
- package/deploy/sema-up/cluster-up.sh +1 -0
- package/deploy/sema-up/kube-up.sh +1 -1
- package/deploy/sema-up/lib/flagshape.sh +1 -1
- package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
- package/deploy/sema-up/lib/helm-values-kube.py +2 -0
- package/dist/adoption/import.js +3 -3
- package/dist/approval-ask-machine.d.ts +1 -1
- package/dist/approval-card.d.ts +3 -3
- package/dist/approval-gate-currency.d.ts +2 -2
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +2 -2
- package/dist/auth-bridge.d.ts +20 -0
- package/dist/auth-bridge.js +9 -0
- package/dist/background-session-reap.d.ts +2 -2
- package/dist/bake-runner/main.d.ts +4 -2
- package/dist/bind-host.d.ts +2 -3
- package/dist/bind-host.js +2 -4
- package/dist/boot/budget-tracing.js +1 -1
- package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
- package/dist/boot/deferred-sandbox-path-env.js +1 -2
- package/dist/boot/engine-lease.d.ts +5 -0
- package/dist/boot/engine-lease.js +1 -0
- package/dist/boot/execution-env.d.ts +8 -14
- package/dist/boot/execution-env.js +54 -17
- package/dist/boot/execution-lane.js +32 -5
- package/dist/boot/late-binds.d.ts +8 -4
- package/dist/boot/late-binds.js +7 -1
- package/dist/boot/memory-consolidation.d.ts +3 -2
- package/dist/boot/memory-consolidation.js +6 -6
- package/dist/boot/parked-revive-gate.d.ts +5 -5
- package/dist/boot/parked-revive-gate.js +2 -3
- package/dist/boot/reapers.d.ts +5 -0
- package/dist/boot/reapers.js +12 -1
- package/dist/boot/resolve-spec.d.ts +7 -8
- package/dist/boot/resolve-spec.js +80 -35
- package/dist/boot/retention-lane.d.ts +1 -1
- package/dist/boot/runner-deps.d.ts +9 -2
- package/dist/boot/runner-deps.js +3 -3
- package/dist/boot/session-age-out.d.ts +36 -0
- package/dist/boot/session-age-out.js +101 -0
- package/dist/boot/session-faces.d.ts +5 -14
- package/dist/boot/session-faces.js +28 -24
- package/dist/boot/stage-01-config.js +2 -0
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-05-execution-env.d.ts +5 -3
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +7 -4
- package/dist/boot/stage-06-runners.js +16 -8
- package/dist/boot/stage-07-capability-layer.d.ts +7 -4
- package/dist/boot/stage-07-capability-layer.js +3 -2
- package/dist/boot/stage-08-reapers.d.ts +7 -4
- package/dist/boot/stage-08-reapers.js +4 -2
- package/dist/boot/stage-09-leader.d.ts +11 -5
- package/dist/boot/stage-09-leader.js +12 -3
- package/dist/boot/stage-10-http-server.d.ts +44 -6
- package/dist/boot/stage-10-http-server.js +12 -10
- package/dist/boot/web-admin.d.ts +1 -1
- package/dist/boot/web-admin.js +3 -1
- package/dist/boot/workflow-orchestration.d.ts +7 -2
- package/dist/boot/workflow-orchestration.js +24 -7
- package/dist/bounded-rotation.d.ts +29 -0
- package/dist/bounded-rotation.js +24 -0
- package/dist/capability-facts.d.ts +84 -66
- package/dist/capability-facts.js +58 -41
- package/dist/center-credential.d.ts +25 -6
- package/dist/center-credential.js +25 -5
- package/dist/config-catalog.d.ts +26 -7
- package/dist/config-catalog.js +15 -12
- package/dist/config-invariants.d.ts +2 -1
- package/dist/config-invariants.js +4 -4
- package/dist/config-types.d.ts +22 -15
- package/dist/config.d.ts +51 -2
- package/dist/config.js +35 -24
- package/dist/deployment-governance.d.ts +7 -28
- package/dist/deployment-governance.js +1 -14
- package/dist/deployment-shape.d.ts +9 -1
- package/dist/deployment-shape.js +2 -1
- package/dist/device-protocol.d.ts +5 -4
- package/dist/device-protocol.js +1 -1
- package/dist/device-ws-hub.d.ts +1 -0
- package/dist/device-ws-hub.js +66 -29
- package/dist/device-ws-protocol.d.ts +79 -12
- package/dist/device-ws-protocol.js +64 -26
- package/dist/engine-identity.d.ts +23 -5
- package/dist/engine-identity.js +13 -0
- package/dist/entry-mode-clamp-notice.d.ts +2 -1
- package/dist/execution-env-refusal.d.ts +23 -0
- package/dist/execution-env-refusal.js +5 -0
- package/dist/execution-lane-caps.d.ts +3 -1
- package/dist/field-conflict.d.ts +3 -3
- package/dist/file-history-capture.d.ts +11 -4
- package/dist/file-history-capture.js +9 -6
- package/dist/file-history-disclosure.d.ts +7 -5
- package/dist/file-history-disclosure.js +7 -5
- package/dist/fleet/drain-entry.d.ts +4 -0
- package/dist/fleet/engine-signal.d.ts +14 -1
- package/dist/fleet/engine-signal.js +5 -1
- package/dist/fleet/fleet-reconciler.d.ts +1 -1
- package/dist/fleet/serving-lease.d.ts +18 -3
- package/dist/fleet/serving-lease.js +81 -35
- package/dist/fleet-client.d.ts +13 -11
- package/dist/fleet-client.js +53 -33
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +1 -3
- package/dist/hitl-delivery.js +1 -1
- package/dist/hooks/hook-runner.js +2 -2
- package/dist/host-lsp-manager.d.ts +2 -2
- package/dist/http/active-run-conflict.d.ts +3 -7
- package/dist/http/active-run-conflict.js +2 -2
- package/dist/http/admission.js +19 -4
- package/dist/http/approval-sweeps.js +7 -6
- package/dist/http/caller-trust.d.ts +2 -2
- package/dist/http/caller-trust.js +3 -3
- package/dist/http/checkpoint-ctx.d.ts +20 -63
- package/dist/http/checkpoint-ctx.js +2 -24
- package/dist/http/claim-heartbeat.d.ts +4 -4
- package/dist/http/claim-heartbeat.js +3 -3
- package/dist/http/dispatch.d.ts +2 -1
- package/dist/http/dispatch.js +36 -29
- package/dist/http/durable-run-leg.js +17 -17
- package/dist/http/health-self-report.d.ts +9 -1
- package/dist/http/health-self-report.js +2 -0
- package/dist/http/owner-access.d.ts +264 -20
- package/dist/http/owner-access.js +215 -5
- package/dist/http/readiness.d.ts +4 -2
- package/dist/http/resume-ctx-read.js +38 -1
- package/dist/http/resume-legs.d.ts +2 -1
- package/dist/http/resume-legs.js +273 -89
- package/dist/http/route-ctx.d.ts +41 -19
- package/dist/http/route-table.d.ts +1 -1
- package/dist/http/routes/a2a-serve.js +15 -14
- package/dist/http/routes/admin-memory-optout.d.ts +1 -1
- package/dist/http/routes/agents-roster.js +2 -3
- package/dist/http/routes/approvals-assistant.d.ts +3 -2
- package/dist/http/routes/approvals-assistant.js +12 -12
- package/dist/http/routes/background.d.ts +3 -3
- package/dist/http/routes/capabilities.js +10 -6
- package/dist/http/routes/config-catalog.d.ts +1 -1
- package/dist/http/routes/fleet.js +10 -8
- package/dist/http/routes/mcp-reconnect.js +2 -2
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/notify-wake.js +2 -3
- package/dist/http/routes/projects.d.ts +4 -2
- package/dist/http/routes/projects.js +7 -6
- package/dist/http/routes/retention-ops.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +1 -1
- package/dist/http/routes/runs.js +125 -66
- package/dist/http/routes/session-memory-sync.js +4 -5
- package/dist/http/routes/session-sync.d.ts +4 -3
- package/dist/http/routes/session-sync.js +174 -83
- package/dist/http/routes/sessions-list.js +13 -7
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +26 -48
- package/dist/http/routes/tasks.js +38 -23
- package/dist/http/routes/trace-usage.js +14 -14
- package/dist/http/routes/workflows.d.ts +1 -0
- package/dist/http/routes/workflows.js +20 -38
- package/dist/http/server.d.ts +28 -30
- package/dist/http/server.js +7 -3
- package/dist/http/stored-body-replay.d.ts +3 -24
- package/dist/http/stored-body-replay.js +2 -12
- package/dist/http/submit-ctx.d.ts +1 -2
- package/dist/http/submit-ctx.js +8 -6
- package/dist/http/submit-replay.d.ts +15 -2
- package/dist/http/submit-replay.js +10 -4
- package/dist/http/wire-types.d.ts +19 -6
- package/dist/identity-source.d.ts +20 -3
- package/dist/identity-source.js +14 -0
- package/dist/index.d.ts +4 -0
- package/dist/lane-home-probe.d.ts +3 -7
- package/dist/lane-home-probe.js +0 -1
- package/dist/leader/endpoint.js +9 -8
- package/dist/leader/leader.d.ts +2 -1
- package/dist/leg-facts.d.ts +19 -5
- package/dist/leg-facts.js +3 -1
- package/dist/mcp-authorization-face.d.ts +18 -14
- package/dist/mcp-authorization-face.js +3 -2
- package/dist/memory-scope.d.ts +5 -4
- package/dist/memory-scope.js +4 -4
- package/dist/memory-store-refusal.d.ts +1 -1
- package/dist/memory-sync-client.d.ts +30 -2
- package/dist/memory-sync-client.js +16 -9
- package/dist/observability/corrupt-read-seat.d.ts +1 -1
- package/dist/observability/err-text.d.ts +7 -0
- package/dist/observability/err-text.js +5 -0
- package/dist/observability/fail-open.d.ts +12 -8
- package/dist/observability/fail-open.js +12 -8
- package/dist/observability/logger.d.ts +7 -0
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -0
- package/dist/observability/run-terminal.d.ts +1 -1
- package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
- package/dist/orchestration/workflow-notify-journal.js +12 -1
- package/dist/orchestration/workflow-park-decision.d.ts +70 -18
- package/dist/orchestration/workflow-park-decision.js +49 -10
- package/dist/orchestration/workflow-park-holder.d.ts +65 -0
- package/dist/orchestration/workflow-park-holder.js +98 -0
- package/dist/orchestration/workflow-record-fence.d.ts +36 -0
- package/dist/orchestration/workflow-record-fence.js +42 -0
- package/dist/owner-faces.d.ts +28 -4
- package/dist/owner-faces.js +2 -0
- package/dist/parked-decide.d.ts +104 -53
- package/dist/parked-decide.js +153 -117
- package/dist/peer-directory.d.ts +2 -2
- package/dist/peer-inbound-face.d.ts +2 -6
- package/dist/peer-inbound-face.js +0 -3
- package/dist/peer-seat.d.ts +1 -1
- package/dist/peer-seat.js +52 -59
- package/dist/permission-mode-admission.d.ts +41 -5
- package/dist/permission-mode-admission.js +29 -3
- package/dist/plugins/adoption-log-sql.d.ts +3 -1
- package/dist/plugins/adoption-log-sql.js +7 -1
- package/dist/plugins/approval-ask-store-file.d.ts +10 -2
- package/dist/plugins/approval-ask-store-file.js +8 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +6 -1
- package/dist/plugins/approval-ask-store-memory.js +28 -9
- package/dist/plugins/approval-ask-store-sql.d.ts +43 -2
- package/dist/plugins/approval-ask-store-sql.js +34 -5
- package/dist/plugins/approval-exemption-store.js +3 -0
- package/dist/plugins/approval-nonce-store.js +2 -0
- package/dist/plugins/breaker-state-sql.js +2 -0
- package/dist/plugins/caching-session-store.d.ts +9 -15
- package/dist/plugins/caching-session-store.js +6 -0
- package/dist/plugins/device-store-sql.js +6 -0
- package/dist/plugins/error-origin.d.ts +18 -0
- package/dist/plugins/error-origin.js +10 -0
- package/dist/plugins/exec-path-law.d.ts +34 -0
- package/dist/plugins/exec-path-law.js +13 -0
- package/dist/plugins/execution-placement-sql.js +6 -6
- package/dist/plugins/file-run-store.js +1 -1
- package/dist/plugins/image-bake-store-sql.js +6 -0
- package/dist/plugins/image-index-sql.js +4 -0
- package/dist/plugins/landed-attendants.d.ts +212 -0
- package/dist/plugins/landed-attendants.js +161 -0
- package/dist/plugins/leader-run-store-sql.js +4 -0
- package/dist/plugins/local-checkpoint-store.d.ts +4 -1
- package/dist/plugins/local-checkpoint-store.js +3 -0
- package/dist/plugins/local-session-live-reference.d.ts +40 -0
- package/dist/plugins/local-session-live-reference.js +39 -0
- package/dist/plugins/local-session-store.d.ts +71 -33
- package/dist/plugins/local-session-store.js +129 -27
- package/dist/plugins/memory-engine-pg.js +4 -0
- package/dist/plugins/memory-engine-sql-apply.js +5 -2
- package/dist/plugins/memory-engine-tidb.js +4 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
- package/dist/plugins/memory-run-store.js +1 -1
- package/dist/plugins/memory-sync-store-pg.js +5 -0
- package/dist/plugins/memory-sync-store-tidb.js +5 -0
- package/dist/plugins/one-time-migrations.d.ts +80 -61
- package/dist/plugins/one-time-migrations.js +241 -104
- package/dist/plugins/org-delivery-quota-store.js +4 -1
- package/dist/plugins/outcome-ledger-sql.js +2 -0
- package/dist/plugins/permission-rule-store-sql.js +11 -4
- package/dist/plugins/pg-cost-quota.js +4 -0
- package/dist/plugins/pg-pool.js +28 -1
- package/dist/plugins/pg-rate-limiter.js +2 -0
- package/dist/plugins/posix-shell-fs.d.ts +6 -1
- package/dist/plugins/posix-shell-fs.js +8 -3
- package/dist/plugins/remote-env-adb.d.ts +19 -15
- package/dist/plugins/remote-env-adb.js +44 -17
- package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
- package/dist/plugins/remote-env-connect-seat.js +72 -0
- package/dist/plugins/remote-env-device.d.ts +22 -5
- package/dist/plugins/remote-env-device.js +114 -14
- package/dist/plugins/remote-env-e2b.d.ts +18 -7
- package/dist/plugins/remote-env-e2b.js +53 -40
- package/dist/plugins/remote-env-file-error.js +6 -2
- package/dist/plugins/remote-env-host.d.ts +18 -1
- package/dist/plugins/remote-env-host.js +48 -47
- package/dist/plugins/remote-env-k8s.d.ts +41 -39
- package/dist/plugins/remote-env-k8s.js +56 -32
- package/dist/plugins/remote-env-local-docker.d.ts +13 -8
- package/dist/plugins/remote-env-local-docker.js +37 -43
- package/dist/plugins/remote-env-ssh.d.ts +18 -12
- package/dist/plugins/remote-env-ssh.js +64 -62
- package/dist/plugins/remote-shell.d.ts +101 -2
- package/dist/plugins/remote-shell.js +221 -3
- package/dist/plugins/replica-registration.d.ts +35 -0
- package/dist/plugins/replica-registration.js +48 -0
- package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
- package/dist/plugins/resume-anchor-store-sql.js +12 -5
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/retention-lane-store-sql.js +4 -0
- package/dist/plugins/retention-sql.d.ts +20 -2
- package/dist/plugins/retention-sql.js +11 -0
- package/dist/plugins/run-store-sql.d.ts +22 -3
- package/dist/plugins/run-store-sql.js +33 -9
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +6 -12
- package/dist/plugins/scenario-prefix-switch-m42.js +7 -5
- package/dist/plugins/schema-consistency.d.ts +9 -5
- package/dist/plugins/schema-consistency.js +48 -18
- package/dist/plugins/schema-drift-sentence.js +1 -1
- package/dist/plugins/send-file-ledger.js +3 -0
- package/dist/plugins/serving-requirement.d.ts +68 -0
- package/dist/plugins/serving-requirement.js +60 -0
- package/dist/plugins/session-birth.d.ts +6 -2
- package/dist/plugins/session-capture-record-store-sql.js +2 -0
- package/dist/plugins/session-ext-table.d.ts +14 -1
- package/dist/plugins/session-ext-table.js +5 -1
- package/dist/plugins/session-row-sql.d.ts +49 -2
- package/dist/plugins/session-row-sql.js +56 -13
- package/dist/plugins/session-store-sql.d.ts +34 -18
- package/dist/plugins/session-store-sql.js +98 -17
- package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
- package/dist/plugins/shared-memory-store-sql.js +6 -2
- package/dist/plugins/sql-driver.d.ts +2 -1
- package/dist/plugins/sql-driver.js +18 -3
- package/dist/plugins/sql-errors.d.ts +11 -6
- package/dist/plugins/sql-errors.js +5 -6
- package/dist/plugins/stop-then-start-sentence.d.ts +48 -3
- package/dist/plugins/stop-then-start-sentence.js +48 -0
- package/dist/plugins/stop-then-start.d.ts +109 -0
- package/dist/plugins/stop-then-start.js +104 -0
- package/dist/plugins/store-backend.d.ts +40 -13
- package/dist/plugins/store-backend.js +169 -27
- package/dist/plugins/store-boundary.d.ts +57 -0
- package/dist/plugins/store-boundary.js +139 -0
- package/dist/plugins/store-contracts.d.ts +29 -2
- package/dist/plugins/store-contracts.js +3 -0
- package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
- package/dist/plugins/store-fault-sentence-m53.js +25 -0
- package/dist/plugins/store-fault.d.ts +26 -7
- package/dist/plugins/store-fault.js +18 -2
- package/dist/plugins/task-attachment-store.js +9 -0
- package/dist/plugins/task-list-store-sql.d.ts +2 -2
- package/dist/plugins/task-list-store-sql.js +10 -8
- package/dist/plugins/tidb-cost-quota.js +4 -0
- package/dist/plugins/tidb-pool.js +6 -1
- package/dist/plugins/tidb-rate-limiter.js +4 -0
- package/dist/plugins/user-input-ledger-sql.js +4 -0
- package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
- package/dist/plugins/workflow-run-store-sql.js +64 -4
- package/dist/plugins/workspace-fill.d.ts +4 -7
- package/dist/plugins/workspace-fill.js +2 -1
- package/dist/plugins/write-behind-counter.js +5 -0
- package/dist/process-instance.d.ts +3 -0
- package/dist/process-instance.js +7 -0
- package/dist/project-context.d.ts +64 -0
- package/dist/project-context.js +66 -0
- package/dist/project-registry.d.ts +46 -0
- package/dist/project-registry.js +44 -0
- package/dist/question.d.ts +9 -21
- package/dist/question.js +28 -19
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +4 -0
- package/dist/request-value-closure.js +10 -0
- package/dist/run-acceptance.d.ts +3 -2
- package/dist/run-acceptance.js +4 -6
- package/dist/run-cancel-card.d.ts +1 -1
- package/dist/run-cancel-card.js +2 -1
- package/dist/run-local.js +1 -0
- package/dist/runs.d.ts +37 -8
- package/dist/runs.js +53 -12
- package/dist/runtime-governance.d.ts +5 -4
- package/dist/security.d.ts +31 -33
- package/dist/security.js +41 -7
- package/dist/server-secret-env.d.ts +12 -10
- package/dist/server-secret-env.js +24 -15
- package/dist/session-agent.d.ts +1 -10
- package/dist/session-agent.js +0 -6
- package/dist/session-bindings.d.ts +82 -0
- package/dist/session-bindings.js +18 -0
- package/dist/session-children-retire.d.ts +2 -2
- package/dist/session-children-retire.js +2 -6
- package/dist/session-deletion.d.ts +16 -1
- package/dist/session-error-wire.d.ts +3 -3
- package/dist/session-error-wire.js +3 -3
- package/dist/session-incarnation.d.ts +28 -4
- package/dist/session-incarnation.js +14 -2
- package/dist/session-kind.d.ts +57 -0
- package/dist/session-kind.js +22 -0
- package/dist/session-notify-door.d.ts +4 -4
- package/dist/session-notify-door.js +5 -6
- package/dist/session-row.d.ts +21 -1
- package/dist/session-row.js +7 -1
- package/dist/session-rules-seat.d.ts +4 -3
- package/dist/session-rules-seat.js +3 -11
- package/dist/session-sync-kernel.d.ts +24 -14
- package/dist/session-sync-kernel.js +3 -6
- package/dist/session-sync.d.ts +4 -98
- package/dist/session-sync.js +4 -74
- package/dist/session-titler.d.ts +10 -3
- package/dist/session-titler.js +19 -6
- package/dist/ssh-host-key.d.ts +5 -0
- package/dist/ssh-host-key.js +3 -0
- package/dist/stores-sql/checkpoint-store-sql.d.ts +21 -2
- package/dist/stores-sql/checkpoint-store-sql.js +106 -18
- package/dist/stores-sql/file-history-store-sql.d.ts +52 -2
- package/dist/stores-sql/file-history-store-sql.js +108 -70
- package/dist/stores-sql/pg-session-storage.d.ts +34 -7
- package/dist/stores-sql/pg-session-storage.js +37 -13
- package/dist/stores-sql/retention-store-sql.d.ts +2 -10
- package/dist/stores-sql/retention-store-sql.js +2 -10
- package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
- package/dist/stores-sql/session-policy-store-sql.js +61 -44
- package/dist/stores-sql/session-write-hooks.d.ts +11 -0
- package/dist/stores-sql/tidb-session-store.d.ts +58 -7
- package/dist/stores-sql/tidb-session-store.js +37 -13
- package/dist/submission-exit.d.ts +3 -2
- package/dist/submission-exit.js +9 -1
- package/dist/task-cwd.d.ts +6 -5
- package/dist/task-settings.d.ts +19 -5
- package/dist/task-settings.js +13 -7
- package/dist/terminal.d.ts +33 -2
- package/dist/terminal.js +139 -9
- package/dist/tool-approval.d.ts +147 -12
- package/dist/tool-approval.js +206 -109
- package/dist/trace/engine-notice-wire.d.ts +14 -0
- package/dist/trace/engine-notice-wire.js +18 -1
- package/dist/trace/project.d.ts +4 -3
- package/dist/trace/project.js +3 -2
- package/dist/trace/projection-table.d.ts +33 -2
- package/dist/trace/self-minted-wire.d.ts +422 -26
- package/dist/trace/self-minted-wire.js +149 -23
- package/dist/trace/tool-card.d.ts +3 -0
- package/dist/trace/tool-card.js +24 -0
- package/dist/trace/tool-output-media.d.ts +2 -1
- package/dist/unattended-permission-mode.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +120 -41
- package/package.json +3 -3
- package/wire-changes/server@7.150.0.json +335 -0
- package/wire-changes/server@7.151.0.json +762 -0
- package/dist/http/session-inherit-env.d.ts +0 -36
- package/dist/http/session-inherit-env.js +0 -6
|
@@ -36,13 +36,13 @@ export const FAIL_OPEN_TAGS = {
|
|
|
36
36
|
cls: "F",
|
|
37
37
|
note: "S-1173(`workflow-notify-journal.ts` 的 `ensurePointersFor`,park 指针的唯一写点):workflow run 记录的 `parks[]` **读不出**(在场却不是列表 / 某条目身份位或持有者两位形坏;读者 = `workflow-agent-session-index.ts` 的 `readRunParks`,整档成败制)⇒ 这一份指针投影派生不出来 ⇒ 写者这次**不写**指针,记录照写(已写过的指针只增不删,原样留着)。修前这一臂静默 `return`。**`parks` 缺席不进这一臂**:那是引擎契约里的合法形(更早引擎写的记录 / 准入没走完的续跑记录),读者答 `[]`(没有条目),没有要写的指针,不计。与指针**写**失败分家:写失败 ⇒ 记录写抛、记录不落(指针先于记录,不 fail-open);本臂没有丢任何一枚已写的指针 —— 读不出的是**记录本身**,引擎对条目形坏的记录整条拒续跑(`park_binding_broken`),读口对已有指针的 run 据记录响亮拒(`unproven/unreadable`),所以要的是查那条记录为什么读不出(投影把它写坏 / 手改)。放行的最坏后果:这条 run 首写就读不出时没有指针 ⇒ 这张卡没有别的指针时 `/decide` 落 legacy 腿、409 响亮拒,方向 fail-closed,不误配、不放行任何东西;例外 —— 同一张卡上另一支的指针在时分叉门判不出、决定投给那一支(引擎从不写坏形,要这一支在首写之前就被写坏);derived cache 没更新、真源读口自带响亮拒 ⇒ F 类。detail = `runId=`;计数非零 = 有记录的 `parks[]` 读不出,按 runId 去查记录。",
|
|
38
38
|
},
|
|
39
|
-
"server.workflow-
|
|
39
|
+
"server.workflow-park-holder.read-failed": {
|
|
40
40
|
cls: "F",
|
|
41
|
-
note: "
|
|
41
|
+
note: "workflow 停驻卡持有进程的拉取腿(`orchestration/workflow-park-holder.ts`,维护拍上读本进程执行中、持有停驻卡的 run 的决定行,把立住的决定在本地交给引擎)这一拍对某条候选读不出:决定行的主键读抛或超过期限(`step=decision`)、卡 / 持有者那一读超过期限(`step=card`),或执行器视图等那条 run 的引擎观察通道收场的那一读拒(`step=channel`,core 的观察队列只关不拒,结构上不可达)。放行的最坏后果:这条决定这一拍不交,行留着、卡仍 pending —— 下一拍再来;`channel` 那一形这条 run 出视图,它的行改由 run 的收场送达交给宿主会话的下一跑(交付晚到 run 收场,不丢、不错交)。不放宽任何判定:交不交、交给谁仍由行 + 卡状态 + 引擎判。detail = `step=<decision|card|channel> runId=<持有者> err=<原句,经记录器脱敏>`;计数持续非零 = 决定店 / 检查点店对这几条读不出,按 runId 查。",
|
|
42
42
|
},
|
|
43
43
|
"server.workflow-park-decision.card-unreadable": {
|
|
44
44
|
cls: "F",
|
|
45
|
-
note: "起跑读者(`parked-decide.ts` 的 `
|
|
45
|
+
note: "交付决定行的三方(起跑读者 `heldWorkflowParkDecisions`,每一只起跑器开跑前一次;workflow 停驻卡持有进程的拉取腿;run 收场送达)共用的逐行判(`parked-decide.ts` 的 `deliverableEntryOf`)读某条已受理的 workflow 子代决定所属的那张卡(`step=card`)或那张卡的当下持有者(`step=holder`:park 索引 / 记录读)时店抛 ⇒ 这一次**不交付**这条决定,行留着(起跑读者:这一跑不带它,下一跑照带;拉取腿:下一拍再来;收场送达:不 ack、`recover` 重投)。放行的最坏后果:这一跑里宿主若续跑那条 workflow run,子代按同一个 token 再停驻一次(卡仍 pending,决定仍在,下一跑照带)—— 方向是少交付一次,不是错交付:这一读失败不代表引擎随后那一读也失败,而引擎对「卡已不 pending、却拿到一条决定」的序数会当确认结算,所以读不出时绝不照供。计数持续非零 = checkpoint 店 / park 索引 / 记录店对这张卡读不出(库故障 / 行坏 / 写者版本更新),按 detail 的 `runId=`(受理那一刻的持有者)去查。detail = `step=<card|holder> runId=<留存锚> err=<原句,经记录器脱敏>`。",
|
|
46
46
|
},
|
|
47
47
|
"server.workflow-park-decision.store-unreadable": {
|
|
48
48
|
cls: "F",
|
|
@@ -178,7 +178,7 @@ export const FAIL_OPEN_TAGS = {
|
|
|
178
178
|
},
|
|
179
179
|
"server.approvals.queue-row-agent-unreadable": {
|
|
180
180
|
cls: "F",
|
|
181
|
-
note: "S-3000(`routes/approvals-assistant.ts` 的 `sessionAgentsOf`):运维待批队列(`GET /v1/approvals` 的 `pending[]` 与 `/v1/approvals/stream` 的 `pending` 帧)每一只停驻行带它那只会话在委派树里的位置 `agent`(会话视图的同名键,唯一读口 `
|
|
181
|
+
note: "S-3000(`routes/approvals-assistant.ts` 的 `sessionAgentsOf`):运维待批队列(`GET /v1/approvals` 的 `pending[]` 与 `/v1/approvals/stream` 的 `pending` 帧)每一只停驻行带它那只会话在委派树里的位置 `agent`(会话视图的同名键,唯一读口 `http/owner-access.ts` 的 `readSessionAgent` = 会话店的 `placementOf` 一读)。某一只会话那一读抛(店瞬断 / 超时 / local 后端的会话存档行头读不出)⇒ **这只会话的行**缺 `agent` 键,列表其余照常。放行的最坏后果 = 这一行这一次没有委派归属线索:壳的归属判官认不到它(行照列、人从队列照样决得了 —— 与本键存在之前同形);`agent` 不是授权事实(队列行本就只列调用方 scope 的卡,决断口另有属主门)。不放行的代价是一只读不出的会话打掉整张待批列表(订阅流上每一拍都是读失败)。故 F 类;必须留痕,否则「这一次没读成」与「这不是一只 placed 委派子代」在 wire 上同形。detail = 会话 id 与经出口座的错误句。计数按次(订阅流每一拍各计一次)。",
|
|
182
182
|
},
|
|
183
183
|
"server.approvals.durable-row-checkpoint-id-missing": {
|
|
184
184
|
cls: "F",
|
|
@@ -332,6 +332,10 @@ export const FAIL_OPEN_TAGS = {
|
|
|
332
332
|
cls: "F",
|
|
333
333
|
note: "#329 / #343(黑板 [5100] Q3):停驻行迟到决议的**受理回执表**(本副本对「200 丢包后重试」的幂等承诺 + 重叠请求的单飞句柄;键 = 行的键 askId,只在一次赎回真开飞时开格;容量帽只数受理之后留下的回执,在飞的单飞句柄永不被逐)**拒留一张回执**。放行的最坏后果 = 这**一次**受理(照旧生效)没有本副本的回执可依:200 丢包后的重试会再进一次赎回腿、拿到那条腿的 409(那张 checkpoint 已被消费)而不是幂等 200 回放(终局恒由赎回腿的 gate CAS 定,不会错兑也不会双兑);迟到受理本身、`GET /v1/approvals` 列表与 `/v1/approvals/:sessionId/decide` 一个字节不动 ⇒ F 类。为什么方向是「拒新」而不是 FIFO 挤最旧:那个形让**甲的用量决定乙的可用性**(已鉴权租户量产受理即可把别家回执挤出,merge-rescan 744 confirmed 的同一病形)。必须留痕:「表被别人打满」与「这一次本来就没有回执」在 wire 上同形。detail 带 owner(判「压力来自谁」的第一手线索)。臂只有一条:全局回执帽满、本 principal 未到子帽、表里没有过期回执可收 ⇒ 拒留(detail 带 owner)。本 principal 到了子帽的常态臂逐自己最旧的一张回执(量产者自伤,设计内有界表纪律),不走本 tag;在飞的单飞句柄不占帽、永不被逐。",
|
|
334
334
|
},
|
|
335
|
+
"server.approval.parked-decision-not-recorded": {
|
|
336
|
+
cls: "F",
|
|
337
|
+
note: "S-1054 α(`tool-approval.ts` 的 `recordParkedOutcome`,停驻赎回那一飞的落行步):停驻门**已经受理**了这次决定(续跑已开始),而把它的记录(决议向 · 署名 · 理由 · 回决幂等键 · 出处)落到仍 `PARKED` 的问行上没成 —— 店错 / 超时 / 行出了门判过的属主域 / 这把键已被同 task 另一只问占着(detail 带 `reason`)。放行的最坏后果 = 这一问在耐久决断口上的**同键回放**读不到这把键:同键重发得到 `409 conflict.ask_decided`(回显门上站着的那次决定,决议向 / 时刻 / 理由取自门,无署名),而不是 200 回放;审计面少一份署名。决定本身零影响(终局恒在停驻门上,门已决);不改判、不重赎、不双兑。计数非零 = 问账店在受理之后写不动了,运维要去看店。",
|
|
338
|
+
},
|
|
335
339
|
"server.approvals.stale-echoed-token-unreadable": {
|
|
336
340
|
cls: "F",
|
|
337
341
|
note: "S-02 codex R1-[medium](验真后修):decide 的 409 `approval_stale` 臂对**调用方回显的旧 token** 做归属判定(`cs.get(binding.checkpointToken)`),那次读**抛了**(store 抖动 / 坏 checkpoint 行 / 行恰被清理)。修前这里是静默 `catch(()=>null)`,「读不出」被折成「确认不在库」——叠上 S-02 的 404 收口后,一次 store 抖动就会把合法旧 token 的 409+terminal 谎报成 404「没有这条审批」。修后:unreadable ⇒ **保持 409**(`terminal` 不披露——证不出归属就不说,与 2026-07-26 纪律同向;404 折叠只在读成功且未命中时走,探测方无法自控 store 故障 ⇒ 谕示封闭不破)。放行的最坏后果 = 该次拒体 `terminal` 诚实缺席(`currentPending` 由它自己的读口与属主复核另判,不受本臂牵连),壳退回重拉列表,judgment 面 fail-safe,故 F 类。留痕理由:这次读是 terminal 披露与 404 折叠两个判定的输入,长期抖动必须在遥测显形。",
|
|
@@ -520,13 +524,13 @@ export const FAIL_OPEN_TAGS = {
|
|
|
520
524
|
cls: "R",
|
|
521
525
|
ruling: "C-R296",
|
|
522
526
|
bound: "FLEET_LEASE_OUTAGE_MAX_MS",
|
|
523
|
-
note: "`fleet/serving-lease.ts`
|
|
527
|
+
note: "`fleet/serving-lease.ts` 的「没确认」一段(两个调用点一只函数、一行 warn `fleet_serving_lease_unconfirmed`、一只连败计数;detail = `worker=<w> generation=<g> why=<…>`):① `renewOnce`(中心宣告了位之后每一次续租;`why=<不可达句 | HTTP <状态> | verdict=unknown>`)—— 中心这一次**没有确认**本实例该不该服务:不可达 / 超时 / 非 2xx / 答复读不成判决,或答 `unknown`(此刻没有本实例的生命周期对象);② `noteHeartbeat` 的沉默臂(fleet 成员还没听到任何声明的推定期,每一拍心跳;`why=heartbeat:<HTTP <状态> | 请求抛出的那句 | reply-unreadable:<因> | not-sent:<那句>>`,不带中心体片段)—— 成员起步即推定在围栏内,心跳没换来中心的声明。按设计**什么都不改**(规则 2 第三臂):到期之前照常 `granted`,过期后 / 推定期 `expired` 照常接单,直到最后一次授予的到期(没有授予 ⇒ 围栏在本进程生效的时刻,推定 = 本进程起点)满 `FLEET_LEASE_OUTAGE_MAX_MS`(`T_max`)才拒新工作(503 `state.lease_expired`,在飞不动、永不自停)。只在围栏生效时计(中心以不带位的声明解除围栏之后,在飞续租迟到的失败不计)。一段的收尾 = 续租判决(`granted` / `denied`)或中心以不带位的声明解除围栏,一行 `fleet_serving_lease_recovered`(`by: verdict | not-enforced`);宣告本身不是确认。归 R:方向与上界由裁定写定 —— 实例只在中心权威终止(`denied`)或运维覆盖时被替换,`T_max` 只是引擎自己「失联后最多再接单多久」的准入上界,不是替换依据;没确认不是被拒。放行的最坏后果 = 一只其实已被取代的实例在中心失联期间多服务至多「租约剩余 + `T_max`」(中心的代际下限持久,恢复后第一次续租即拒);从起步起一直没听到中心的成员**每个不间断进程**至多服务 `T_max`(钟不跨重启:重启即重计)。计数长期保留:持续非零 = 中心长时间没确认本实例,去看 detail 的 why(连不上 / 令牌被拒 / 中心不认识这只实例 / 答复不是声明)。",
|
|
524
528
|
},
|
|
525
529
|
"server.fleet.serving-lease-capability-absent": {
|
|
526
530
|
cls: "R",
|
|
527
531
|
ruling: "C-R296",
|
|
528
532
|
bound: "FLEET_LEASE_OUTAGE_MAX_MS",
|
|
529
|
-
note: "`fleet/serving-lease.ts` 的 `
|
|
533
|
+
note: "`fleet/serving-lease.ts` 的 `noteHeartbeat` 读数臂(fleet 成员每一次中心能力声明;detail = `worker=<w> generation=<g> was=<presumed|on|off>`):中心心跳答复里**显式的** `capabilities` 声明对象在、却**没有宣告** `servingLease`(中心关着围栏开关 / 共享令牌 / 降级中心 / 位撤掉)⇒ 规则 1:租约不生效,`leaseState: none`,零续租、零 503 —— 这只 fleet 成员此刻**不受围栏**。推定期的第一条声明就不带位(`was=presumed`)⇒ 推定作废(`expired → none`),钟不起,之后不限时(直到中心第一次宣告,那一拍起钟)。不是声明的答复不进这一臂(体读不出 / 不是对象 / 没有 `capabilities` 键 / 形坏 —— 那是沉默,推定、位与钟原样,`fleet-client.ts` `capabilityReadingOf`);已被拒的实例不进(拒是黏的,位消失不复活)。归 R:能力门控是契约规则(中心声明不执行 = 中心不执行围栏),裁定写定替换只来自中心权威终止或运维覆盖;位只开关围栏、不碰钟 —— 位缺席期间 `T_max` 的钟照走(最后一次授予的到期 / 围栏在本进程第一次生效的时刻),位一回来即按它判,所以位的抖动绕不过 `FLEET_LEASE_OUTAGE_MAX_MS`。放行的最坏后果 = 中心声明不执行围栏期间,一只被取代的实例照常服务(这一段由中心的选择定界,不由引擎)。计数长期保留:非零 = 这台中心没宣告租约能力。",
|
|
530
534
|
},
|
|
531
535
|
"server.workspace-cache.unavailable": {
|
|
532
536
|
cls: "F",
|
|
@@ -562,11 +566,11 @@ export const FAIL_OPEN_TAGS = {
|
|
|
562
566
|
},
|
|
563
567
|
"server.fleet.announce-reply-unreadable": {
|
|
564
568
|
cls: "P-DEBT",
|
|
565
|
-
note: "7.121.0 修复验证轮(`fleet-client.ts` 的公告环,fleet 成员每一拍心跳 2xx 答复;detail = `why=<body|not-an-object|invalid-capabilities> leaseState=<此刻的租约态>`)
|
|
569
|
+
note: "7.121.0 修复验证轮(`fleet-client.ts` 的公告环,fleet 成员每一拍心跳 2xx 答复;detail = `why=<body|not-an-object|capabilities-absent|invalid-capabilities> leaseState=<此刻的租约态>`):答复不是能力声明(体读不出 / 不是对象 / 没有 `capabilities` 键 / `capabilities` 键在场而形坏 —— settings-schema `readCapabilityReading` 的 `unreadable`〔没有键那一因自 25.0.0 起〕,外加本仓的 `body`)⇒ 这一拍是沉默(交租约客户端 `silent`,`why=reply-unreadable:<因>`),推定、租约的状态与钟原样。**一律**计数(不论租约此刻什么态):推定期(成员还没听到任何声明,`leaseState=expired`)的坏答复同时是一拍「没确认」(另计 `server.fleet.serving-lease-unconfirmed`),推定与钟照走、满 `T_max` 拒新工作;租约已生效时计数说明中心的答复在坏、围栏靠的是上一次声明。归 P 类:围栏轴;归 DEBT:本进程判不出中心为什么答坏体,收口条件 = 中心契约 / 监控(中心侧对心跳答复形的执法)落地。每段连拍另有一行 warn `fleet_announce_reply_unreadable`(带 `why`)。",
|
|
566
570
|
},
|
|
567
571
|
"server.fleet.denied-marker-unpersisted": {
|
|
568
572
|
cls: "P-DEBT",
|
|
569
|
-
note: "7.121.0(`fleet/serving-lease.ts` 的 `enterDenied`,中心以正面证据拒了本实例的服务租约那一拍;detail = `worker=<w> generation=<g>`):拒要落成数据根下一只文件(重启后起步即排空),而这一次**没落下** —— 没有数据根,或写失败(盘满 / 只读挂载 / 目录不在)。本进程照样被拒、照样当拍排空、到期自停;放行的是**重启之后**:同代际重启的实例不记得被拒,在第一次续租得到答复之前会接新工作(中心宣告了能力位时,第一次续租就再被拒一次 ——
|
|
573
|
+
note: "7.121.0(`fleet/serving-lease.ts` 的 `enterDenied`,中心以正面证据拒了本实例的服务租约那一拍;detail = `worker=<w> generation=<g>`):拒要落成数据根下一只文件(重启后起步即排空),而这一次**没落下** —— 没有数据根,或写失败(盘满 / 只读挂载 / 目录不在)。本进程照样被拒、照样当拍排空、到期自停;放行的是**重启之后**:同代际重启的实例不记得被拒,在第一次续租得到答复之前会接新工作(中心宣告了能力位时,第一次续租就再被拒一次 —— 中心的代际下限是持久的;中心那时不可达 / 心跳一直不通则按推定围栏接单到本进程起点满 `FLEET_LEASE_OUTAGE_MAX_MS`,每个进程各一段;重启后第一条声明就不带位 ⇒ 中心的话,不限时)。归 P 类:这是围栏的记忆;归 DEBT:进程内无法把「记不住」变成 fail-closed(「起步首次答复之前零容忍」形已否决:中心宕几秒 + 一次重启就停数据面),收口条件 = 契约给出持久拒位的公告位(心跳 / `/health` 上说「这一次拒只在本进程」,中心据此对该实例下一次续租照拒、并能看见它)。denied 行的 `sticky` 同拍说 `process-only`,不声称跨重启记得。计数非零 = 这台机器的数据根写不进,或部署没有数据根。",
|
|
570
574
|
},
|
|
571
575
|
"server.sql.tidb-row-cap-unread": {
|
|
572
576
|
cls: "F",
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
2
|
+
/**
|
|
3
|
+
* **启动协议行**(闭集):起本进程的那一方(壳 / 嵌入宿主 / 测试夹具)从 stdout 读这几行起步 —— `listening` 带内核分给本进程的口(`port`)与
|
|
4
|
+
* 实绑地址(`boundAddress`),读者拿它们找到并认出自己起的这只引擎。它们是协议,不是诊断:**在不在不随 `LOG_LEVEL`**(档位只滤诊断行;
|
|
5
|
+
* 档位调高而协议行跟着消失 ⇒ 读者要么拒起、要么各自替部署把档位压回 info,同一个事实多出几份读法)。除此之外与任何一行同路:同一只出口座
|
|
6
|
+
* (脱敏)、同一条流(按行上的 `level` 分流)、行上的 `level` 照写 —— 按 `level` 字段筛日志的管道照旧筛得掉它。
|
|
7
|
+
*/
|
|
8
|
+
export declare const STARTUP_PROTOCOL_EVENTS: readonly ["listening"];
|
|
2
9
|
export interface Logger {
|
|
3
10
|
debug(msg: string, fields?: Record<string, unknown>): void;
|
|
4
11
|
info(msg: string, fields?: Record<string, unknown>): void;
|
|
@@ -3,6 +3,8 @@ import { OVERSIZED_REDACTION_PLACEHOLDER, seatText } from "../trace/exit-seat.js
|
|
|
3
3
|
import { errorKindOf } from "./err-text.js";
|
|
4
4
|
import { buildFailOpenAnchor, installFailOpenAnnounceExit } from "./fail-open.js";
|
|
5
5
|
const ORDER = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
6
|
+
export const STARTUP_PROTOCOL_EVENTS = ["listening"];
|
|
7
|
+
const STARTUP_PROTOCOL = new Set(STARTUP_PROTOCOL_EVENTS);
|
|
6
8
|
const LOG_LINE_WITHHELD = "log_line_withheld";
|
|
7
9
|
const SECRET_SCREEN_FAILED = "secret_screen_failed";
|
|
8
10
|
const UNFORMATTABLE = "unformattable";
|
|
@@ -61,7 +63,7 @@ const diagnosticStream = (stream) => (stdoutReservedForAnswer ? "stderr" : strea
|
|
|
61
63
|
export function createLogger(minLevel = "info") {
|
|
62
64
|
swallowStdioErrors();
|
|
63
65
|
const emit = (level, msg, fields) => {
|
|
64
|
-
if (ORDER[level] < ORDER[minLevel])
|
|
66
|
+
if (ORDER[level] < ORDER[minLevel] && !STARTUP_PROTOCOL.has(msg))
|
|
65
67
|
return;
|
|
66
68
|
const ts = new Date().toISOString();
|
|
67
69
|
const line = serializeEntry({ ts, level, msg }, fields);
|
|
@@ -279,6 +279,7 @@ export function createMetrics() {
|
|
|
279
279
|
m.counter("memory_knn_query_failed_total", "Memory KNN searchScored queries that failed at runtime (S22)");
|
|
280
280
|
m.counter("memory_dedup_folded_total", "Memory writes folded into an existing near-duplicate row (LOW)");
|
|
281
281
|
m.counter("memory_dedup_probe_failed_total", "Memory dedup KNN probes that failed and fell through to INSERT (LOW)");
|
|
282
|
+
m.counter("store_boundary_fault_total", "SQL-store failures whose driver error was rewritten at the store boundary (code + fixed sentence leave the store; the driver's own sentence goes to the at=store log line), by site (store.method) and class (store fault judge word)");
|
|
282
283
|
m.counter("redactions_applied_total", "redactSecrets rewrites (S24), by pattern label and `arm` (S-88: full vs prefix-fragment arm — which RULE fired, NOT proof the text was upstream-truncated)");
|
|
283
284
|
m.counter("session_cache_stale_hit_total", "Warm session-cache hits dropped because the store had moved past the cached leaf (written by another replica, or gone); the session was re-woken from the store");
|
|
284
285
|
m.counter("breaker_writethrough_failed_total", "Circuit-breaker cross-replica write-through failures (LOW), by backend");
|
|
@@ -132,7 +132,7 @@ export declare function redactModelText(raw: string, before?: string): string;
|
|
|
132
132
|
* 它进引擎之前已**准入一次**:三只 brain 在建调用的那一行(`brain/tool-call-id.js` 的 `admitToolCallId`)—— 缺席 ⇒ 车道兜底铸;
|
|
133
133
|
* 在形(可见 ASCII 1–128 且不含 `~`)⇒ 原样;越界 ⇒ 单射折叠成引擎 id(`<前 32 码元,越界字符记 `-`>~<sha256 前 32 hex>`),原字节只挂在
|
|
134
134
|
* 转录的 `ToolCall.wireId` 上、只回给 provider。⇒ 一方 brain 在 7.107.0 起新铸的调用,到达本仓任何一张脸的 `toolCallId` 恒在形。
|
|
135
|
-
* 残余两条([ref],如实):① ≤7.106.0 写下的存量行(待批 park 行 `boundCallId` / 检查点 `pendingAction.toolCallId` / 转录)是服务商原串逐字 —— 新版不对存量行二次准入(e2e G4 钉);② 宿主自己的 `Brain`(不经三只一方 adapter)铸的 id 不准入(core
|
|
135
|
+
* 残余两条([ref],如实):① ≤7.106.0 写下的存量行(待批 park 行 `boundCallId` / 检查点 `pendingAction.toolCallId` / 转录)是服务商原串逐字 —— 新版不对存量行二次准入(e2e G4 钉);② 宿主自己的 `Brain`(不经三只一方 adapter)铸的 id 不准入(core [ref];本仓生产装配的 brain 恒是 `createBrain` 的一方 adapter 外套委托装饰,这一形只经嵌入 / 测试注入的 brain 到达)。两条残余里的 id 仍是跨面 join 键、每张脸同值,只是形状不保证(本闸照旧不动它们:动一张脸 = join 断)。
|
|
136
136
|
*
|
|
137
137
|
* 🔴 **本闸只施加在「这个值出现的每一张脸都被覆盖到」的回声上**(codex r1 F1,实测成立的回归后改判):工具调用 id 是
|
|
138
138
|
* **跨面 join 键** —— 同一枚 id 同时逐字出现在 `tool_start` / `tool_end` / 审批卡等逐帧面上。只在结果面动它 ⇒ 结果面与逐帧面
|
|
@@ -278,6 +278,15 @@ export declare class InMemoryWorkflowNotifyJournalStore implements WorkflowNotif
|
|
|
278
278
|
get(runId: string): Promise<WorkflowNotifyJournalEntry | null>;
|
|
279
279
|
get size(): number;
|
|
280
280
|
}
|
|
281
|
+
/** 一笔**落成**的记录写的观察者(执行器视图;型属主在这里,实现 = `workflow-park-holder.ts` 的 `HeldParksHere`)。 */
|
|
282
|
+
export interface LandedRecordObserver {
|
|
283
|
+
noteLanded(runId: string, run: WorkflowRun): void;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* 「本服务的 workflow 记录写者经哪一只记录店写」的唯一读法:交给引擎的那只记录店是 journaling 装饰器 ⇒ 它里面那一只(notify 门的收养翻转也经它写);
|
|
287
|
+
* 否则就是它自己。起服判官(`workflow-park-decision.ts` 的 `parkDecisionStoreRefusal`)拿它与决定店的记录栅栏按身份比。
|
|
288
|
+
*/
|
|
289
|
+
export declare function recordWriterOf(store: object): object;
|
|
281
290
|
/**
|
|
282
291
|
* A {@link WorkflowRunStore} DECORATOR that journals a run the instant core persists it at START. core's
|
|
283
292
|
* `startWorkflow` `put`s the run row (`status: "running"`) synchronously before the body runs, carrying both the
|
|
@@ -304,6 +313,9 @@ export declare class JournalingWorkflowRunStore implements WorkflowRunStore {
|
|
|
304
313
|
* 的派生投影,写点必须与 fleet 行投影/notify journal 同一个(见 index 模块的文件头「单写者」段)。
|
|
305
314
|
* 可选:缺席 ⇒ 一位不维护(与 fleet 半场同姿势,行为逐字不变)。 */
|
|
306
315
|
private readonly agentSessionIndex?;
|
|
316
|
+
/** 本进程执行器视图(`workflow-park-holder.ts` 的 `HeldParksHere`):本装饰器在本进程引擎每一笔**落成**的记录写之后把记录交给它(它读其中本记录持有的停驻 token)。
|
|
317
|
+
* 写抛 / CAS 输 ⇒ 不交(视图保留上一份)。可选:缺席 ⇒ 不维护(没有 workflow 停驻车道的部署)。 */
|
|
318
|
+
private readonly landedRecords?;
|
|
307
319
|
constructor(inner: WorkflowRunStore,
|
|
308
320
|
/** [ref] optional since the fleet decoupling: undefined ⇒ no start-time journal (ephemeral memory
|
|
309
321
|
* backend has nothing to recover), the FLEET half still publishes — the panel is replica-local UI
|
|
@@ -316,7 +328,12 @@ export declare class JournalingWorkflowRunStore implements WorkflowRunStore {
|
|
|
316
328
|
/** [ref] 车CM:workflow 出身 park 的 join 索引。**本装饰器是它全仓唯一的写者** —— 索引是 `WorkflowRun`
|
|
317
329
|
* 的派生投影,写点必须与 fleet 行投影/notify journal 同一个(见 index 模块的文件头「单写者」段)。
|
|
318
330
|
* 可选:缺席 ⇒ 一位不维护(与 fleet 半场同姿势,行为逐字不变)。 */
|
|
319
|
-
agentSessionIndex?: WorkflowAgentSessionIndex | undefined
|
|
331
|
+
agentSessionIndex?: WorkflowAgentSessionIndex | undefined,
|
|
332
|
+
/** 本进程执行器视图(`workflow-park-holder.ts` 的 `HeldParksHere`):本装饰器在本进程引擎每一笔**落成**的记录写之后把记录交给它(它读其中本记录持有的停驻 token)。
|
|
333
|
+
* 写抛 / CAS 输 ⇒ 不交(视图保留上一份)。可选:缺席 ⇒ 不维护(没有 workflow 停驻车道的部署)。 */
|
|
334
|
+
landedRecords?: LandedRecordObserver | undefined);
|
|
335
|
+
/** 本装饰器的每一笔记录写经它落下的那只记录店(起服判官按身份比:决定店的记录栅栏必须就是它 —— {@link recordWriterOf})。 */
|
|
336
|
+
get records(): WorkflowRunStore;
|
|
320
337
|
/** 本进程**亲眼看着落进索引**的指针:run → 它点名过的子会话。只用来跳过重复的 upsert,不是缓存(指针只增不删,记着的必在索引里)。
|
|
321
338
|
*
|
|
322
339
|
* 为什么需要:workflow 的进度写是每只 agent 状态变化一次,而 park 是罕见事件 ⇒ 无条件 upsert 会给每一次写多打几发语句(SQL)
|
|
@@ -270,16 +270,24 @@ export class InMemoryWorkflowNotifyJournalStore {
|
|
|
270
270
|
return this.entries.size;
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
|
+
export function recordWriterOf(store) {
|
|
274
|
+
return store instanceof JournalingWorkflowRunStore ? store.records : store;
|
|
275
|
+
}
|
|
273
276
|
export class JournalingWorkflowRunStore {
|
|
274
277
|
inner;
|
|
275
278
|
gate;
|
|
276
279
|
fleetBus;
|
|
277
280
|
agentSessionIndex;
|
|
278
|
-
|
|
281
|
+
landedRecords;
|
|
282
|
+
constructor(inner, gate, fleetBus, agentSessionIndex, landedRecords) {
|
|
279
283
|
this.inner = inner;
|
|
280
284
|
this.gate = gate;
|
|
281
285
|
this.fleetBus = fleetBus;
|
|
282
286
|
this.agentSessionIndex = agentSessionIndex;
|
|
287
|
+
this.landedRecords = landedRecords;
|
|
288
|
+
}
|
|
289
|
+
get records() {
|
|
290
|
+
return this.inner;
|
|
283
291
|
}
|
|
284
292
|
pointedSessions = new Map();
|
|
285
293
|
async ensurePointersFor(id, run) {
|
|
@@ -338,10 +346,13 @@ export class JournalingWorkflowRunStore {
|
|
|
338
346
|
scope: run.scope,
|
|
339
347
|
});
|
|
340
348
|
await this.writeWithPointers(id, run, () => this.inner.put(id, run), () => true);
|
|
349
|
+
this.landedRecords?.noteLanded(id, run);
|
|
341
350
|
this.publishFleet(id, run);
|
|
342
351
|
}
|
|
343
352
|
async update(id, scope, run, expect) {
|
|
344
353
|
const ok = await this.writeWithPointers(id, run, () => this.inner.update(id, scope, run, expect), (won) => won);
|
|
354
|
+
if (ok)
|
|
355
|
+
this.landedRecords?.noteLanded(id, run);
|
|
345
356
|
if (ok)
|
|
346
357
|
this.publishFleet(id, run);
|
|
347
358
|
return ok;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CheckpointToken, type ResumeOutcome } from "@sema-agent/core";
|
|
1
|
+
import { type CheckpointToken, type ResumeOutcome, type WorkflowRun } from "@sema-agent/core";
|
|
2
2
|
import type { ResumeRestatement } from "../http/resume-restatement.js";
|
|
3
3
|
import { type JsonColumnReader } from "../plugins/sql-json-column.js";
|
|
4
4
|
import { type InProcessClaimFence } from "../plugins/store-contracts.js";
|
|
@@ -15,25 +15,68 @@ export interface WorkflowParkDecision {
|
|
|
15
15
|
/** 带着它的会话 = 受理那一刻那条 run 的发起会话(宿主)。 */
|
|
16
16
|
readonly hostSessionId: string;
|
|
17
17
|
readonly outcome: WorkflowParkOutcome;
|
|
18
|
-
/** {@link parkDecisionFingerprint}:同一决定的判据(
|
|
18
|
+
/** {@link parkDecisionFingerprint}:同一决定的判据(先受理者立 / 回执幂等 / 收场转交的条件)。 */
|
|
19
19
|
readonly fingerprint: string;
|
|
20
|
-
/**
|
|
20
|
+
/** 承运者(回执上的 `taskId`):记录栅栏下 = 持有这张卡的那条 workflow run;认领栅栏下 = 投递那一跑。读者不按它的种类分支(文件头)。 */
|
|
21
21
|
readonly deliveredTaskId: string;
|
|
22
|
-
/** 受理时刻(受理那台副本的墙钟,记录值;不当任何条件
|
|
22
|
+
/** 受理时刻(受理那台副本的墙钟,记录值;不当任何条件)。 */
|
|
23
23
|
readonly acceptedAtMs: number;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* 记录栅栏下一次决断的结局(闭集;`switch` 穷尽):
|
|
27
|
+
* · `not_running` —— 记录已不读作 `running`(或不在)⇒ 承运者换成续跑车道的投递那一跑,零写;
|
|
28
|
+
* · `not_held` —— 仍在跑,本记录的 `parks[]` 已不持有这个 token(或读不出)⇒ 零写;
|
|
29
|
+
* · `restated` —— 仍在跑、仍持有,请求带续跑重述键(`mcpServers` / `a2aPeers`)⇒ 零写(活 run 上的子代带着它停驻时的表继续,重述盖不上);
|
|
30
|
+
* · `other_decision` —— 行上已是**另一个**决定(先受理者立)⇒ 零写;
|
|
31
|
+
* · `stands` —— 本决定落下了,或行上就是同一决定(指纹相等)。
|
|
32
|
+
*/
|
|
33
|
+
export type HolderFenceVerdict = "not_running" | "not_held" | "restated" | "other_decision" | "stands";
|
|
34
|
+
/** 记录栅栏的结局:`running: false` = 记录此刻不读作 `running`(或不在),`fn` 一次都没调。 */
|
|
35
|
+
export type RecordFenced<T> = {
|
|
36
|
+
readonly running: true;
|
|
37
|
+
readonly value: T;
|
|
38
|
+
} | {
|
|
39
|
+
readonly running: false;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* **workflow 记录的「仍在跑」原子段 —— 进程内那一形**(属主 = `workflow-record-fence.ts` 的 `FencedWorkflowRecordStore`:本服务全部记录写者 ——
|
|
43
|
+
* 引擎经 journaling 装饰器、notify 门的收养翻转 —— 都经它写,它按 runId 互斥)。`whileRunning(runId, fn)`:在这条 run 的互斥段里读记录;读作 `running`
|
|
44
|
+
* 才调 `fn`(同步:判与写同一段,型上不许把写挪到段外)、答 `{ running: true, value }`,否则答 `{ running: false }`。
|
|
45
|
+
* SQL 孪生是一个事务(`SqlWorkflowRunStore.whileRunning`:锁住 `workflow_run` 行,`fn` 收那只事务连接),不是本型。
|
|
46
|
+
*/
|
|
47
|
+
export interface InProcessRecordFence {
|
|
48
|
+
whileRunning<T>(runId: string, fn: (run: WorkflowRun) => T): Promise<RecordFenced<T>>;
|
|
49
|
+
}
|
|
50
|
+
/** 记录栅栏的两形(闭集,与认领栅栏 `ClaimFenceStore` 同形):SQL 孪生一只行锁事务 / 进程内按 runId 互斥。决定店的两形各绑各的那一形。 */
|
|
51
|
+
export type WorkflowRecordFenceStore = import("../plugins/workflow-run-store-sql.js").SqlWorkflowRunStore | InProcessRecordFence;
|
|
52
|
+
/**
|
|
53
|
+
* 记录栅栏判的那一半(两形同一只纯函数;写那一半各形自己的原子段):本记录持有这个 token 吗(`heldParksOf`,`parks[]` 读不出 ⇒ 证不出持有),
|
|
54
|
+
* 请求带重述键吗。交回 `land` ⇒ 进「行上没有就落、有就比指纹」那一步。
|
|
55
|
+
*/
|
|
56
|
+
export declare function holderFenceAdmits(run: WorkflowRun, d: Pick<WorkflowParkDecision, "runId" | "token">, restated: boolean): "not_held" | "restated" | "land";
|
|
57
|
+
/**
|
|
58
|
+
* 决定行的店契约(SQL 两方言 / local 文件 / 内存三形同律)。写者两个:`/decide` 与应答口的 workflow 车道(记录栅栏那一笔 / 续跑车道开跑之前那一笔)、
|
|
59
|
+
* run 收场送达的转交(续跑车道那一笔,带条件);读者是起跑读者、持有进程的拉取腿、收场送达与 `/decide` 自己的回执幂等判;删除只有 SQL 收割的级联。
|
|
28
60
|
*/
|
|
29
61
|
export interface WorkflowParkDecisionStore {
|
|
30
|
-
/**
|
|
62
|
+
/** 认领栅栏 = 构造时绑定的那只 run 店。起服判官要它**就是**部署的 run 店({@link parkDecisionStoreRefusal})。 */
|
|
31
63
|
readonly claims: object;
|
|
64
|
+
/** 记录栅栏 = 构造时绑定的那只 workflow 记录店。起服判官要它**就是**本服务记录写者共用的那一只。 */
|
|
65
|
+
readonly records: object;
|
|
66
|
+
/**
|
|
67
|
+
* 认领栅栏的原子段里写(律的第二个取值):投递那一跑此刻持有宿主会话的认领且在跑 ⇒ 写并答 `true`;否则什么都不写、答 `false`。
|
|
68
|
+
* `condition` 缺席 ⇒ 整行写(没有行插入、有行整行取代);在场 ⇒ 行上的指纹仍等于 `expect` 才整行写,否则不写、答 `false`(收场转交:一个更新的决定已在行上)。
|
|
69
|
+
*/
|
|
70
|
+
record(decision: WorkflowParkDecision, condition?: {
|
|
71
|
+
readonly expect: string;
|
|
72
|
+
}): Promise<boolean>;
|
|
32
73
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
74
|
+
* 记录栅栏的原子段里判与写(律的第一个取值;`decision.deliveredTaskId` = `decision.runId` = 持有这张卡的那条 run):结局见 {@link HolderFenceVerdict}。
|
|
75
|
+
* 只有 `stands` 可能写过(行上本来没有时插入),其余零写。
|
|
35
76
|
*/
|
|
36
|
-
|
|
77
|
+
recordForRunningHolder(decision: WorkflowParkDecision, request: {
|
|
78
|
+
readonly restated: boolean;
|
|
79
|
+
}): Promise<HolderFenceVerdict>;
|
|
37
80
|
get(token: CheckpointToken): Promise<WorkflowParkDecision | null>;
|
|
38
81
|
/** 带着这个会话的全部决定行(顺序不承重)。 */
|
|
39
82
|
listByHostSession(hostSessionId: string): Promise<WorkflowParkDecision[]>;
|
|
@@ -41,15 +84,17 @@ export interface WorkflowParkDecisionStore {
|
|
|
41
84
|
/** 起服判官读的那几座(`ServiceDeps` 的子集)。 */
|
|
42
85
|
export interface ParkDecisionLaneSeats {
|
|
43
86
|
readonly runStore?: object | undefined;
|
|
87
|
+
readonly workflowRunStore?: object | undefined;
|
|
44
88
|
readonly workflowAgentSessionIndex?: unknown;
|
|
45
89
|
readonly workflowParkDecisions?: WorkflowParkDecisionStore | undefined;
|
|
46
90
|
}
|
|
47
91
|
/**
|
|
48
|
-
* 🔴
|
|
92
|
+
* 🔴 **「决定店绑对了两只栅栏吗」的唯一判官**(`createHttpServer` 起服时调;拒 ⇒ 拒启)。判的是**递进来的对象**(按身份比),不是配置组合 ——
|
|
49
93
|
* 本服务自己那一形(SQL 后端配 `WORKFLOW_RUN_STORE=file|memory` 且开自编排)由配置不变量 `workflow-park-decision-domain` 在第 1 段、一次性迁移之前拒,走不到这里;
|
|
50
94
|
* 走到这里的不相等只来自嵌入方递错了座。
|
|
51
|
-
* 期望的绑定:workflow 子代停驻车道装了(park 索引在场)且部署有 run 店 ⇒
|
|
52
|
-
*
|
|
95
|
+
* 期望的绑定:workflow 子代停驻车道装了(park 索引在场)且部署有 run 店 ⇒ 决定店在场、`claims` **就是**那只 run 店、`records` **就是**本服务记录写者经它写的那只记录店
|
|
96
|
+
* ({@link recordWriterOf}:journaling 装饰器里面那一只);否则不该有决定店。不相等的四形各一句:
|
|
97
|
+
* ①车道与 run 店都在而决定店缺席;②决定店绑的是别的 run 店;③有决定店,而车道没装或部署没有 run 店;④决定店的记录栅栏不是本服务记录写者经它写的那一只。
|
|
53
98
|
*/
|
|
54
99
|
export declare function parkDecisionStoreRefusal(seats: ParkDecisionLaneSeats): string | undefined;
|
|
55
100
|
/**
|
|
@@ -68,24 +113,31 @@ export declare function parkDecisionFingerprint(outcome: WorkflowParkOutcome, re
|
|
|
68
113
|
*/
|
|
69
114
|
export declare const readWorkflowParkOutcome: JsonColumnReader<WorkflowParkOutcome>;
|
|
70
115
|
/**
|
|
71
|
-
* 单机车道的决定店(`LocalWorkflowAgentSessionIndex` 的同室孪生)
|
|
116
|
+
* 单机车道的决定店(`LocalWorkflowAgentSessionIndex` 的同室孪生),绑在进程内的两只栅栏上:run 店({@link InProcessClaimFence}:Memory / File run 店)与
|
|
117
|
+
* 记录栅栏装饰器({@link InProcessRecordFence})。
|
|
72
118
|
* `root` 在场 ⇒ 追加式 JSONL 账本(0o700 目录 + 0o600 账本,一行 = 一条决定行的整份快照,每一笔写都追加);重放按行序、**末行胜**
|
|
73
|
-
* (
|
|
119
|
+
* (写序就是栅栏的序:每一笔都在栅栏的段里追加);缺席 ⇒ 纯内存(`WORKFLOW_RUN_STORE=memory` 的易失车道)。
|
|
74
120
|
*
|
|
75
121
|
* 🔴 **坏行 fail-closed**(登记座 `workflow-park-decisions`):读不出的一行可能正是**取代**了一条旧决定的那一笔 —— 跳过它重放其余行,
|
|
76
|
-
*
|
|
122
|
+
* 会把被取代的旧决定复活成当下的决定,在下一次交付时交给引擎。闸合上之后四个动词都响亮拒,直到有人处理那只文件;
|
|
77
123
|
* 起跑读者(`parked-decide.ts`)把这一拒读成「本店没有可供的行」(F tag `server.workflow-park-decision.store-unreadable`)—— 起跑不连带拒,写与按 token 读照旧拒。
|
|
78
124
|
* SQL 孪生同律:某一行 `outcome` 坏体 ⇒ 读口拒,起跑读者同一臂。
|
|
79
125
|
*/
|
|
80
126
|
export declare class LocalWorkflowParkDecisionStore implements WorkflowParkDecisionStore {
|
|
81
127
|
readonly claims: InProcessClaimFence;
|
|
128
|
+
readonly records: InProcessRecordFence;
|
|
82
129
|
private readonly fsyncEnabled;
|
|
83
130
|
private readonly ledgerPath;
|
|
84
131
|
private readonly gate;
|
|
85
132
|
private readonly rows;
|
|
86
133
|
private log;
|
|
87
|
-
constructor(claims: InProcessClaimFence, root?: string, fsyncEnabled?: boolean);
|
|
88
|
-
record(decision: WorkflowParkDecision
|
|
134
|
+
constructor(claims: InProcessClaimFence, records: InProcessRecordFence, root?: string, fsyncEnabled?: boolean);
|
|
135
|
+
record(decision: WorkflowParkDecision, condition?: {
|
|
136
|
+
readonly expect: string;
|
|
137
|
+
}): Promise<boolean>;
|
|
138
|
+
recordForRunningHolder(decision: WorkflowParkDecision, request: {
|
|
139
|
+
readonly restated: boolean;
|
|
140
|
+
}): Promise<HolderFenceVerdict>;
|
|
89
141
|
/** 整行写(同步):落盘**先于**内存翻转(调用方观察到的状态背后一定有耐久记录)。交回栅栏的落定记号(同步交回,型上不许让出)。 */
|
|
90
142
|
private landNow;
|
|
91
143
|
get(token: CheckpointToken): Promise<WorkflowParkDecision | null>;
|
|
@@ -5,6 +5,14 @@ import { approvalPayloadFingerprint } from "../plugins/approval-payload-fingerpr
|
|
|
5
5
|
import { createObjectColumnReader, isJsonObject } from "../plugins/sql-json-column.js";
|
|
6
6
|
import { replayJsonlGuarded } from "../observability/corrupt-read-seat.js";
|
|
7
7
|
import { FENCE_LANDED } from "../plugins/store-contracts.js";
|
|
8
|
+
import { heldParksOf, readRunParks } from "./workflow-agent-session-index.js";
|
|
9
|
+
import { recordWriterOf } from "./workflow-notify-journal.js";
|
|
10
|
+
export function holderFenceAdmits(run, d, restated) {
|
|
11
|
+
const parks = readRunParks(run);
|
|
12
|
+
if (parks === undefined || !heldParksOf(d.runId, parks).some((p) => p.token === d.token))
|
|
13
|
+
return "not_held";
|
|
14
|
+
return restated ? "restated" : "land";
|
|
15
|
+
}
|
|
8
16
|
function seatName(v) {
|
|
9
17
|
if (v === undefined)
|
|
10
18
|
return "none";
|
|
@@ -14,7 +22,8 @@ function seatName(v) {
|
|
|
14
22
|
export function parkDecisionStoreRefusal(seats) {
|
|
15
23
|
const wanted = seats.workflowAgentSessionIndex !== undefined ? seats.runStore : undefined;
|
|
16
24
|
const decisions = seats.workflowParkDecisions;
|
|
17
|
-
|
|
25
|
+
const recordWriter = seats.workflowRunStore === undefined ? undefined : recordWriterOf(seats.workflowRunStore);
|
|
26
|
+
if (decisions?.claims === wanted && (decisions === undefined || decisions.records === recordWriter))
|
|
18
27
|
return undefined;
|
|
19
28
|
const pair = `run store: ${seatName(seats.runStore)}; workflow park decision store: ${decisions === undefined ? "none" : `${seatName(decisions)} bound to ${seatName(decisions.claims)}`}`;
|
|
20
29
|
if (decisions === undefined) {
|
|
@@ -27,9 +36,14 @@ export function parkDecisionStoreRefusal(seats) {
|
|
|
27
36
|
"a decision store is only read and written by that lane, which needs both the park index and the run store the decisions are fenced by; " +
|
|
28
37
|
"wire the lane (park index and run store) or drop the decision store; refusing to start rather than keep a store no lane fences");
|
|
29
38
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
if (decisions.claims !== wanted) {
|
|
40
|
+
return (`the workflow park decision store is not bound to this server's run store (${pair}) — ` +
|
|
41
|
+
"its writes are fenced by the run store it was built on, so a different run store means decisions recorded where the session claims are not checked; " +
|
|
42
|
+
"take runStore and workflowParkDecisions from the same store backend (run() and workflowParkDecisions()); refusing to start rather than record decisions the session claim cannot fence");
|
|
43
|
+
}
|
|
44
|
+
return (`the workflow park decision store is not bound to the workflow record store this server writes run records through (workflow record writer: ${seatName(recordWriter)}; decision store's record fence: ${seatName(decisions.records)}) — ` +
|
|
45
|
+
"while the run that holds a card is running, a decision row is written in the same atomic step that checks the run's record still reads running and still holds the card, so the fence must be the store every record write goes through; " +
|
|
46
|
+
"pass the record store the workflow run store wraps to the store backend's workflowParkDecisions(); refusing to start rather than record decisions a run's end cannot be ordered against");
|
|
33
47
|
}
|
|
34
48
|
export function parkDecisionFingerprint(outcome, restatement) {
|
|
35
49
|
const payload = approvalPayloadFingerprint({
|
|
@@ -76,13 +90,15 @@ function readRow(raw) {
|
|
|
76
90
|
const LEDGER_LINE_SHAPE = { what: "a workflow park decision row", read: readRow };
|
|
77
91
|
export class LocalWorkflowParkDecisionStore {
|
|
78
92
|
claims;
|
|
93
|
+
records;
|
|
79
94
|
fsyncEnabled;
|
|
80
95
|
ledgerPath;
|
|
81
96
|
gate;
|
|
82
97
|
rows = new Map();
|
|
83
98
|
log;
|
|
84
|
-
constructor(claims, root, fsyncEnabled = true) {
|
|
99
|
+
constructor(claims, records, root, fsyncEnabled = true) {
|
|
85
100
|
this.claims = claims;
|
|
101
|
+
this.records = records;
|
|
86
102
|
this.fsyncEnabled = fsyncEnabled;
|
|
87
103
|
if (root === undefined) {
|
|
88
104
|
this.ledgerPath = undefined;
|
|
@@ -92,14 +108,37 @@ export class LocalWorkflowParkDecisionStore {
|
|
|
92
108
|
const dir = join(root, "workflow-park-decisions");
|
|
93
109
|
ensureDir(dir);
|
|
94
110
|
this.ledgerPath = join(dir, "decisions.jsonl");
|
|
95
|
-
const
|
|
96
|
-
this.gate = gate;
|
|
97
|
-
for (const d of records)
|
|
111
|
+
const replayed = replayJsonlGuarded(this.ledgerPath, "workflow-park-decisions", LEDGER_LINE_SHAPE);
|
|
112
|
+
this.gate = replayed.gate;
|
|
113
|
+
for (const d of replayed.records)
|
|
98
114
|
this.rows.set(d.token, d);
|
|
99
115
|
}
|
|
100
|
-
async record(decision) {
|
|
116
|
+
async record(decision, condition) {
|
|
117
|
+
this.gate?.assertUsable();
|
|
118
|
+
let superseded = false;
|
|
119
|
+
const held = this.claims.whileHoldingClaim(decision.hostSessionId, decision.deliveredTaskId, () => {
|
|
120
|
+
if (condition !== undefined && this.rows.get(decision.token)?.fingerprint !== condition.expect) {
|
|
121
|
+
superseded = true;
|
|
122
|
+
return FENCE_LANDED;
|
|
123
|
+
}
|
|
124
|
+
return this.landNow(decision);
|
|
125
|
+
});
|
|
126
|
+
return held && !superseded;
|
|
127
|
+
}
|
|
128
|
+
async recordForRunningHolder(decision, request) {
|
|
101
129
|
this.gate?.assertUsable();
|
|
102
|
-
|
|
130
|
+
const fenced = await this.records.whileRunning(decision.runId, (run) => {
|
|
131
|
+
const admits = holderFenceAdmits(run, decision, request.restated);
|
|
132
|
+
if (admits !== "land")
|
|
133
|
+
return admits;
|
|
134
|
+
const existing = this.rows.get(decision.token);
|
|
135
|
+
if (existing === undefined) {
|
|
136
|
+
this.landNow(decision);
|
|
137
|
+
return "stands";
|
|
138
|
+
}
|
|
139
|
+
return existing.fingerprint === decision.fingerprint ? "stands" : "other_decision";
|
|
140
|
+
});
|
|
141
|
+
return fenced.running ? fenced.value : "not_running";
|
|
103
142
|
}
|
|
104
143
|
landNow(decision) {
|
|
105
144
|
if (this.ledgerPath !== undefined) {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **持有进程的拉取腿**:跑着一条持有停驻卡的 workflow run 的进程,在维护拍上读这些卡的决定行,把立住的决定在本地交给引擎(`redeemWorkflowParks`)。
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么需要它
|
|
5
|
+
* 持有卡的 run 仍读作 `running` 时,决断落成一条决定行(记录栅栏,律的属主 = `workflow-park-decision.ts` 文件头)。引擎只收本进程里那条 run 的决定 ——
|
|
6
|
+
* 决断恰落在跑那条 run 的进程上 ⇒ 当场交(`/decide` 的本进程快路);落在别的副本上 ⇒ 行在库里,**没有任何一条本地事件**会把它交给持有进程。
|
|
7
|
+
* ⇒ 持有进程自己回头看行:搭维护拍(`REAP_INTERVAL_SEC`),不新开定时器族、不按副本路由(与审批族悬挂 ask 的跨副本执行通知同一条裁定)。
|
|
8
|
+
*
|
|
9
|
+
* ## 两件
|
|
10
|
+
* · {@link HeldParksHere} —— **本进程执行器视图**:哪几条 run 的执行器在本进程里跑、它们此刻持有哪些 token。journaling 装饰器在本进程引擎每一笔**落成**的记录写上
|
|
11
|
+
* 刷新它(`parks[]` 里 `parkedBy === runId` 的条目);**只在执行器收场时删**(引擎的观察通道走完)。写抛 / CAS 输 / `parks[]` 读不出 ⇒ 不删、保留上一份 token
|
|
12
|
+
* (引擎吞掉记录写失败照跑,「本进程写成功过」不等于执行器的寿命)。视图只选候选,判官是决定行 + 卡状态 + 引擎。
|
|
13
|
+
* · {@link createWorkflowParkHolderPull} —— 拉取腿:每条候选 (run, token) 一次决定行主键读;有行 ⇒ 与起跑读者同一只逐行判(`deliverableEntryOf`:卡仍 pending ∧ 当下持有者
|
|
14
|
+
* 是这条 run)⇒ 在本地交给引擎;答词按 `holderPullDisposition` 处置(交上了 / 下一拍 / 交给收场送达)。每拍有帽、有墙钟预算、整数偏移轮转(与审批族悬挂轮询共用
|
|
15
|
+
* {@link boundedRotation});截断那一拍响亮。每一读带期限,读失败 ⇒ 本拍跳过这条、F 类留痕(`server.workflow-park-holder.read-failed`)、下拍再来。
|
|
16
|
+
* 本进程没有执行中的持有停驻 run ⇒ 一拍零店读。
|
|
17
|
+
*/
|
|
18
|
+
import type { CheckpointToken, WorkflowRun, WorkflowRunStore } from "@sema-agent/core";
|
|
19
|
+
import { type HeldWorkflowParkDecisionSources } from "../parked-decide.js";
|
|
20
|
+
import { type WorkflowAgentSessionIndex } from "./workflow-agent-session-index.js";
|
|
21
|
+
import type { WorkflowParkDecisionStore } from "./workflow-park-decision.js";
|
|
22
|
+
/** 视图里的一条 run:它的 scope 与它此刻持有的 token(上一笔落成的写读出的那一份)。 */
|
|
23
|
+
export interface HeldParkRun {
|
|
24
|
+
readonly runId: string;
|
|
25
|
+
readonly scope: string;
|
|
26
|
+
readonly tokens: readonly CheckpointToken[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 本进程执行器视图(见文件头)。`ended` = 「这条 run 的执行器在本进程里收场了」的读法(缺省 = 引擎观察通道走完;测试换成可控的那一只)。
|
|
30
|
+
* 登记是惰性的:一条 run 第一次有一笔落成的写持有 token 时才登记并挂收场;此前它不在视图里(没有持有停驻就没有可拉的东西)。
|
|
31
|
+
*/
|
|
32
|
+
export declare class HeldParksHere {
|
|
33
|
+
private readonly ended;
|
|
34
|
+
private readonly runs;
|
|
35
|
+
constructor(ended?: (runId: string, scope: string) => Promise<void>);
|
|
36
|
+
/** journaling 装饰器在本进程引擎的一笔**落成**的记录写之后调(put 落成 / update CAS 赢)。`parks[]` 读不出 ⇒ 保留上一份(不删)。 */
|
|
37
|
+
noteLanded(runId: string, run: WorkflowRun): void;
|
|
38
|
+
/** 此刻的候选(快照;顺序 = 登记序)。 */
|
|
39
|
+
candidates(): HeldParkRun[];
|
|
40
|
+
}
|
|
41
|
+
/** 拉取腿每拍的帽与墙钟预算(审批族悬挂轮询同一尺度:常态几条,帽与预算是退化态的护栏)。每读期限与悬挂轮询的点读同值。 */
|
|
42
|
+
export declare const HOLDER_PULL_MAX_PER_TICK = 64;
|
|
43
|
+
export declare const HOLDER_PULL_BUDGET_MS = 5000;
|
|
44
|
+
export declare const HOLDER_PULL_READ_TIMEOUT_MS = 2000;
|
|
45
|
+
export interface WorkflowParkHolderPullDeps {
|
|
46
|
+
readonly held: HeldParksHere;
|
|
47
|
+
readonly decisions: WorkflowParkDecisionStore;
|
|
48
|
+
readonly checkpointStore: NonNullable<HeldWorkflowParkDecisionSources["checkpointStore"]>;
|
|
49
|
+
readonly workflowAgentSessionIndex: WorkflowAgentSessionIndex;
|
|
50
|
+
readonly workflowRunStore: Pick<WorkflowRunStore, "get">;
|
|
51
|
+
readonly warn?: (event: string, fields: Record<string, unknown>) => void;
|
|
52
|
+
readonly now?: () => number;
|
|
53
|
+
}
|
|
54
|
+
/** 一拍的读数:`polled` = 真去读了决定行的候选数;`delivered` / `nextBeat` / `left` = 有可交付行的候选按处置计;`backlog` / `truncated` = 帽与预算截断。 */
|
|
55
|
+
export interface HolderPullTally {
|
|
56
|
+
readonly polled: number;
|
|
57
|
+
readonly delivered: number;
|
|
58
|
+
readonly nextBeat: number;
|
|
59
|
+
readonly left: number;
|
|
60
|
+
readonly backlog: number;
|
|
61
|
+
readonly truncated: boolean;
|
|
62
|
+
}
|
|
63
|
+
/** 拉取腿(维护拍调;调用方守 in-flight,拍间不叠)。 */
|
|
64
|
+
export declare function createWorkflowParkHolderPull(deps: WorkflowParkHolderPullDeps): () => Promise<HolderPullTally>;
|
|
65
|
+
//# sourceMappingURL=workflow-park-holder.d.ts.map
|