@sema-agent/server 7.148.0 → 7.150.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +551 -9
- package/README.md +17 -2
- package/README.zh-CN.md +5 -1
- package/USAGE.md +126 -68
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +33 -33
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/approval-leg-origin.d.ts +33 -0
- package/dist/approval-leg-origin.js +4 -0
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +2 -2
- package/dist/auth-bridge.d.ts +9 -1
- package/dist/auth-bridge.js +4 -4
- package/dist/auth-keys.d.ts +10 -1
- package/dist/auth-keys.js +8 -0
- package/dist/background-session-reap.d.ts +1 -1
- package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
- package/dist/boot/deferred-sandbox-path-env.js +1 -2
- package/dist/boot/execution-env.js +10 -11
- package/dist/boot/execution-lane.d.ts +6 -4
- package/dist/boot/execution-lane.js +3 -1
- package/dist/boot/org-delivery.d.ts +3 -2
- package/dist/boot/parked-revive-gate.d.ts +5 -5
- package/dist/boot/parked-revive-gate.js +2 -3
- package/dist/boot/resolve-spec.d.ts +4 -5
- package/dist/boot/resolve-spec.js +66 -28
- package/dist/boot/retention-lane.d.ts +1 -1
- package/dist/boot/runner-deps.js +3 -1
- package/dist/boot/session-faces.js +21 -21
- package/dist/boot/stage-01-config.d.ts +1 -0
- package/dist/boot/stage-01-config.js +4 -3
- package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
- package/dist/boot/stage-02-web-admin-pull.js +10 -2
- package/dist/boot/stage-03-store-backend.d.ts +1 -0
- package/dist/boot/stage-03-store-backend.js +4 -4
- package/dist/boot/stage-04-stores.d.ts +1 -0
- package/dist/boot/stage-05-execution-env.d.ts +1 -0
- package/dist/boot/stage-06-runners.d.ts +2 -1
- package/dist/boot/stage-06-runners.js +1 -2
- package/dist/boot/stage-07-capability-layer.d.ts +2 -1
- package/dist/boot/stage-07-capability-layer.js +1 -1
- package/dist/boot/stage-08-reapers.d.ts +2 -1
- package/dist/boot/stage-09-leader.d.ts +2 -1
- package/dist/boot/stage-10-http-server.d.ts +35 -2
- package/dist/boot/stage-10-http-server.js +9 -4
- package/dist/boot/stores.d.ts +3 -0
- package/dist/boot/stores.js +22 -19
- package/dist/boot/web-admin.d.ts +1 -1
- package/dist/capabilities/tool-defer.d.ts +1 -1
- package/dist/capability-facts.d.ts +70 -60
- package/dist/capability-facts.js +45 -49
- package/dist/card-settle-stored-scope.d.ts +56 -0
- package/dist/card-settle-stored-scope.js +27 -0
- package/dist/card-void.d.ts +7 -12
- package/dist/card-void.js +2 -7
- package/dist/config-catalog.d.ts +12 -0
- package/dist/config-catalog.js +37 -33
- package/dist/config-invariants.d.ts +5 -4
- package/dist/config-invariants.js +4 -4
- package/dist/config-types.d.ts +49 -16
- package/dist/config.d.ts +6 -5
- package/dist/config.js +35 -24
- package/dist/context-window-notice.d.ts +31 -0
- package/dist/context-window-notice.js +28 -0
- package/dist/deployment-governance.d.ts +7 -28
- package/dist/deployment-governance.js +1 -14
- package/dist/deployment-shape.d.ts +20 -11
- package/dist/deployment-shape.js +1 -0
- package/dist/device-ws-hub.d.ts +1 -0
- package/dist/device-ws-hub.js +64 -28
- package/dist/device-ws-protocol.d.ts +20 -6
- package/dist/device-ws-protocol.js +9 -2
- package/dist/engine-identity.d.ts +7 -1
- package/dist/engine-identity.js +5 -0
- package/dist/env-name-allowlist-knobs.d.ts +6 -5
- package/dist/env-name-allowlist-knobs.js +5 -0
- package/dist/execution-lane-caps.d.ts +20 -5
- package/dist/execution-lane-caps.js +18 -4
- package/dist/field-conflict.d.ts +2 -2
- package/dist/fleet/engine-signal.d.ts +14 -1
- package/dist/fleet/engine-signal.js +5 -1
- package/dist/fleet/fleet-reconciler.d.ts +1 -1
- package/dist/fleet/serving-lease.d.ts +18 -3
- package/dist/fleet/serving-lease.js +81 -35
- package/dist/fleet-client.d.ts +13 -11
- package/dist/fleet-client.js +53 -33
- package/dist/history-anchor.js +1 -1
- package/dist/hitl-delivery.d.ts +1 -3
- package/dist/hitl-delivery.js +1 -1
- package/dist/hooks/command-spawn.d.ts +7 -2
- package/dist/hooks/command-spawn.js +13 -6
- package/dist/hooks/hook-runner.d.ts +5 -0
- package/dist/hooks/hook-runner.js +11 -7
- package/dist/http/active-run-conflict.d.ts +3 -7
- package/dist/http/active-run-conflict.js +2 -2
- package/dist/http/admission.js +5 -5
- package/dist/http/approval-sweeps.js +5 -3
- package/dist/http/caller-trust.d.ts +2 -2
- package/dist/http/caller-trust.js +3 -3
- package/dist/http/checkpoint-ctx.d.ts +18 -63
- package/dist/http/checkpoint-ctx.js +1 -24
- package/dist/http/claim-heartbeat.d.ts +6 -6
- package/dist/http/claim-heartbeat.js +6 -6
- package/dist/http/claimed-run.d.ts +16 -9
- package/dist/http/claimed-run.js +8 -0
- package/dist/http/dispatch.js +7 -5
- package/dist/http/durable-run-leg.d.ts +8 -1
- package/dist/http/durable-run-leg.js +34 -15
- package/dist/http/execution-context.d.ts +115 -14
- package/dist/http/execution-context.js +130 -40
- package/dist/http/owner-access.d.ts +246 -21
- package/dist/http/owner-access.js +186 -8
- package/dist/http/principal-gate.d.ts +18 -11
- package/dist/http/principal-gate.js +3 -1
- package/dist/http/readiness.d.ts +4 -2
- package/dist/http/resume-ctx-read.d.ts +14 -3
- package/dist/http/resume-ctx-read.js +24 -3
- package/dist/http/resume-legs.d.ts +35 -3
- package/dist/http/resume-legs.js +262 -106
- package/dist/http/route-ctx.d.ts +29 -11
- package/dist/http/routes/a2a-serve.js +17 -14
- package/dist/http/routes/approvals-assistant.d.ts +3 -2
- package/dist/http/routes/approvals-assistant.js +11 -11
- package/dist/http/routes/capabilities.js +5 -4
- package/dist/http/routes/config-catalog.d.ts +1 -1
- package/dist/http/routes/diagnostics.d.ts +3 -1
- package/dist/http/routes/diagnostics.js +30 -5
- package/dist/http/routes/mcp-reconnect.js +2 -2
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/notify-wake.js +2 -3
- package/dist/http/routes/principal-inbox.d.ts +3 -1
- package/dist/http/routes/principal-inbox.js +3 -2
- package/dist/http/routes/projects.d.ts +1 -0
- package/dist/http/routes/projects.js +5 -3
- package/dist/http/routes/retention-ops.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.d.ts +1 -1
- package/dist/http/routes/run-permission-mode.js +2 -2
- package/dist/http/routes/runs.d.ts +1 -1
- package/dist/http/routes/runs.js +33 -37
- package/dist/http/routes/session-memory-sync.js +4 -5
- package/dist/http/routes/session-sync.d.ts +24 -5
- package/dist/http/routes/session-sync.js +45 -37
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +18 -44
- package/dist/http/routes/tasks.js +136 -101
- package/dist/http/routes/trace-usage.js +14 -14
- package/dist/http/routes/workflows.d.ts +1 -0
- package/dist/http/routes/workflows.js +20 -38
- package/dist/http/server.d.ts +12 -9
- package/dist/http/server.js +35 -6
- package/dist/http/stored-body-replay.d.ts +3 -24
- package/dist/http/stored-body-replay.js +2 -12
- package/dist/http/submit-ctx.d.ts +2 -2
- package/dist/http/submit-ctx.js +5 -5
- package/dist/http/submit-replay.d.ts +15 -2
- package/dist/http/submit-replay.js +10 -4
- package/dist/http/wire-types.d.ts +6 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/leader/endpoint.js +9 -8
- package/dist/leg-facts.d.ts +13 -2
- package/dist/leg-facts.js +2 -0
- package/dist/local-store-declaration.d.ts +54 -0
- package/dist/local-store-declaration.js +59 -0
- package/dist/mcp-assertion-header.d.ts +1 -1
- package/dist/mcp-assertion-header.js +1 -1
- package/dist/mcp-authorization-face.d.ts +18 -14
- package/dist/mcp-authorization-face.js +3 -2
- package/dist/memory-project-layer.js +1 -1
- package/dist/memory-scope.d.ts +4 -4
- package/dist/memory-scope.js +4 -4
- package/dist/memory-store-refusal.d.ts +1 -1
- package/dist/memory-sync-client.js +2 -2
- package/dist/model-context-window.d.ts +50 -11
- package/dist/model-context-window.js +20 -1
- package/dist/model-entry-refusal.d.ts +5 -4
- package/dist/model-entry-refusal.js +17 -3
- package/dist/model-reach-scope.d.ts +2 -1
- package/dist/observability/corrupt-read-seat.d.ts +1 -1
- package/dist/observability/fail-open.d.ts +19 -7
- package/dist/observability/fail-open.js +19 -7
- package/dist/observability/logger.d.ts +7 -0
- package/dist/observability/logger.js +3 -1
- package/dist/observability/metrics.js +1 -1
- package/dist/observability/run-terminal.d.ts +1 -1
- package/dist/observability/run-terminal.js +1 -0
- package/dist/observability/secret-env-scrub.d.ts +1 -1
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/org-delivery-gate.d.ts +31 -6
- package/dist/org-delivery-gate.js +7 -4
- package/dist/owner-faces.d.ts +30 -5
- package/dist/owner-faces.js +2 -0
- package/dist/park-row-commit.d.ts +67 -0
- package/dist/park-row-commit.js +76 -0
- package/dist/parked-decide.d.ts +9 -7
- package/dist/parked-decide.js +25 -6
- package/dist/peer-directory.d.ts +1 -1
- package/dist/peer-seat.d.ts +1 -1
- package/dist/peer-seat.js +52 -59
- package/dist/plugins/adoption-log-sql.d.ts +3 -3
- package/dist/plugins/adoption-log-sql.js +19 -19
- package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
- package/dist/plugins/approval-ask-store-sql.js +3 -5
- package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
- package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
- package/dist/plugins/approval-exemption-skill-m46.d.ts +0 -6
- package/dist/plugins/approval-exemption-skill-m46.js +6 -10
- package/dist/plugins/approval-exemption-store.d.ts +26 -1
- package/dist/plugins/approval-exemption-store.js +28 -19
- package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -3
- package/dist/plugins/ensure-schema-lock-policy.js +75 -9
- package/dist/plugins/exec-path-law.d.ts +34 -0
- package/dist/plugins/exec-path-law.js +13 -0
- package/dist/plugins/file-run-store.d.ts +22 -9
- package/dist/plugins/file-run-store.js +51 -23
- package/dist/plugins/local-checkpoint-store.d.ts +8 -1
- package/dist/plugins/local-checkpoint-store.js +5 -1
- package/dist/plugins/local-data-root-admission.d.ts +52 -0
- package/dist/plugins/local-data-root-admission.js +100 -0
- package/dist/plugins/local-engine-high-water.d.ts +28 -7
- package/dist/plugins/local-engine-high-water.js +27 -22
- package/dist/plugins/local-session-store.d.ts +134 -49
- package/dist/plugins/local-session-store.js +149 -108
- package/dist/plugins/memory-run-store.d.ts +14 -9
- package/dist/plugins/memory-run-store.js +48 -22
- package/dist/plugins/one-time-migration-marker.d.ts +19 -3
- package/dist/plugins/one-time-migration-marker.js +7 -1
- package/dist/plugins/one-time-migrations.d.ts +110 -59
- package/dist/plugins/one-time-migrations.js +224 -136
- package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
- package/dist/plugins/org-delivery-quota-store.js +29 -14
- package/dist/plugins/permission-rule-store-sql.d.ts +1 -1
- package/dist/plugins/permission-rule-store-sql.js +5 -9
- package/dist/plugins/pg-pool.d.ts +1 -1
- package/dist/plugins/pg-pool.js +14 -12
- package/dist/plugins/posix-shell-fs.js +4 -2
- package/dist/plugins/remote-env-adb.js +3 -2
- package/dist/plugins/remote-env-device.d.ts +3 -2
- package/dist/plugins/remote-env-device.js +8 -6
- package/dist/plugins/remote-env-e2b.d.ts +4 -8
- package/dist/plugins/remote-env-e2b.js +21 -15
- package/dist/plugins/remote-env-host.d.ts +51 -10
- package/dist/plugins/remote-env-host.js +97 -31
- package/dist/plugins/remote-env-k8s.js +7 -4
- package/dist/plugins/remote-env-local-docker.d.ts +6 -3
- package/dist/plugins/remote-env-local-docker.js +11 -25
- package/dist/plugins/remote-env-ssh.js +4 -3
- package/dist/plugins/remote-shell.d.ts +3 -1
- package/dist/plugins/remote-shell.js +3 -3
- package/dist/plugins/replica-registration.d.ts +35 -0
- package/dist/plugins/replica-registration.js +48 -0
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/run-store-sql.d.ts +27 -8
- package/dist/plugins/run-store-sql.js +46 -18
- package/dist/plugins/scenario-prefix-switch-m42.d.ts +8 -12
- package/dist/plugins/scenario-prefix-switch-m42.js +9 -6
- package/dist/plugins/schema-consistency.d.ts +91 -5
- package/dist/plugins/schema-consistency.js +189 -7
- package/dist/plugins/schema-drift-sentence.d.ts +6 -5
- package/dist/plugins/schema-drift-sentence.js +13 -5
- package/dist/plugins/serving-requirement.d.ts +49 -0
- package/dist/plugins/serving-requirement.js +53 -0
- package/dist/plugins/session-placement.d.ts +5 -4
- package/dist/plugins/shell-sentinel-owner-m48.d.ts +22 -0
- package/dist/plugins/shell-sentinel-owner-m48.js +6 -0
- package/dist/plugins/stop-then-start-sentence.d.ts +55 -0
- package/dist/plugins/stop-then-start-sentence.js +51 -0
- package/dist/plugins/store-backend.d.ts +23 -9
- package/dist/plugins/store-backend.js +58 -24
- package/dist/plugins/store-contracts.d.ts +45 -5
- package/dist/plugins/store-contracts.js +19 -0
- package/dist/plugins/tidb-pool.d.ts +11 -6
- package/dist/plugins/tidb-pool.js +22 -12
- package/dist/plugins/workspace-custody.d.ts +44 -0
- package/dist/plugins/workspace-custody.js +47 -0
- package/dist/process-instance.d.ts +3 -0
- package/dist/process-instance.js +7 -0
- package/dist/project-context.d.ts +66 -0
- package/dist/project-context.js +70 -0
- package/dist/project-identity.d.ts +8 -7
- package/dist/project-identity.js +40 -17
- package/dist/project-layer-key.d.ts +13 -2
- package/dist/project-layer-key.js +9 -1
- package/dist/question.d.ts +9 -21
- package/dist/question.js +28 -19
- package/dist/read-deny-floor-notice.d.ts +36 -0
- package/dist/read-deny-floor-notice.js +40 -0
- package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
- package/dist/request-declaration-disposition.js +39 -0
- package/dist/run-cancel-card.d.ts +28 -0
- package/dist/run-cancel-card.js +20 -0
- package/dist/run-cancel-context.d.ts +10 -0
- package/dist/run-cancel-context.js +1 -0
- package/dist/run-local.js +28 -13
- package/dist/runs.d.ts +31 -7
- package/dist/runs.js +34 -16
- package/dist/security.d.ts +3 -3
- package/dist/server-secret-env.d.ts +34 -20
- package/dist/server-secret-env.js +61 -18
- package/dist/session-agent.d.ts +4 -12
- package/dist/session-agent.js +0 -6
- package/dist/session-children-retire.d.ts +6 -3
- package/dist/session-children-retire.js +2 -5
- package/dist/session-incarnation.d.ts +18 -4
- package/dist/session-incarnation.js +4 -1
- package/dist/session-notify-door.d.ts +4 -4
- package/dist/session-notify-door.js +5 -6
- package/dist/session-rules-seat.d.ts +4 -3
- package/dist/session-rules-seat.js +3 -11
- package/dist/session-sync.js +3 -3
- package/dist/session-workspace.d.ts +3 -3
- package/dist/store-admission.d.ts +33 -0
- package/dist/store-admission.js +49 -0
- package/dist/store-posture.d.ts +5 -0
- package/dist/store-posture.js +18 -1
- package/dist/stores-sql/checkpoint-store-sql.d.ts +22 -3
- package/dist/stores-sql/checkpoint-store-sql.js +109 -23
- package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
- package/dist/stores-sql/file-history-store-sql.js +3 -5
- package/dist/stores-sql/retention-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
- package/dist/stores-sql/tool-result-store-sql.js +4 -6
- package/dist/task-a2a.d.ts +3 -8
- package/dist/task-a2a.js +25 -27
- package/dist/task-cwd.d.ts +27 -10
- package/dist/task-cwd.js +3 -0
- package/dist/task-mcp.d.ts +3 -3
- package/dist/task-mcp.js +1 -1
- package/dist/task-settings.d.ts +13 -0
- package/dist/task-settings.js +14 -7
- package/dist/terminal.d.ts +2 -0
- package/dist/terminal.js +21 -6
- package/dist/tool-approval.d.ts +50 -41
- package/dist/tool-approval.js +96 -73
- package/dist/trace/engine-notice-wire.d.ts +38 -21
- package/dist/trace/engine-notice-wire.js +25 -4
- package/dist/trace/ledger-sink.d.ts +3 -1
- package/dist/trace/project.d.ts +8 -5
- package/dist/trace/project.js +11 -9
- package/dist/trace/projection-table.d.ts +33 -2
- package/dist/trace/redact.d.ts +12 -0
- package/dist/trace/redact.js +5 -1
- package/dist/trace/self-minted-wire.d.ts +268 -56
- package/dist/trace/self-minted-wire.js +110 -40
- package/dist/trace/tool-card.d.ts +3 -0
- package/dist/trace/tool-card.js +24 -0
- package/dist/trace/tool-output-media.d.ts +2 -1
- package/dist/unattended-permission-mode.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.js +22 -9
- package/dist/web-admin-client/effective-keys.d.ts +1 -1
- package/dist/web-admin-client/skills-mcp.d.ts +1 -1
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -29
- package/docs/error-text-lexicon.json +317 -0
- package/package.json +4 -2
- package/scripts/embed-minimal.mjs +183 -0
- package/wire-changes/server@7.149.0.json +372 -0
- package/wire-changes/server@7.150.0.json +335 -0
- package/dist/plain-string-record.js +0 -70
|
@@ -10,10 +10,10 @@ import { AppendLog, atomicWriteFile, ensureDir, isProcessLive, processFingerprin
|
|
|
10
10
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
11
11
|
import { replayJsonlSkipping } from "../observability/corrupt-read-seat.js";
|
|
12
12
|
import { joinFromStore, splitForStore } from "./wiring-section-codec.js";
|
|
13
|
-
import { RUN_HOLDER_DEATH_CODES, RUN_ORPHANED_ERROR, RUN_STALLED_ERROR, RUN_STALL_DEFAULT_WIRING, RUN_STALL_VERDICT_UNLANDED_TAG, StoreBootRefusalError, runLivenessOf, buildRunOrphanedError, isTerminalRunStatus, settledLegObservationOf } from "./store-contracts.js";
|
|
13
|
+
import { RUN_HOLDER_DEATH_CODES, RUN_ORPHANED_ERROR, RUN_STALLED_ERROR, RUN_STALL_DEFAULT_WIRING, RUN_STALL_VERDICT_UNLANDED_TAG, StoreBootRefusalError, mintRunLegId, runLivenessOf, buildRunOrphanedError, isTerminalRunStatus, settledLegObservationOf } from "./store-contracts.js";
|
|
14
14
|
import { buildSessionRunRollups } from "./session-run-rollup.js";
|
|
15
15
|
import { normalizedRunPreviewM45 } from "./run-preview-m45.js";
|
|
16
|
-
import {
|
|
16
|
+
import { isShellSentinelOwnerM48 } from "./shell-sentinel-owner-m48.js";
|
|
17
17
|
import { notifyRunTerminal } from "../observability/run-terminal.js";
|
|
18
18
|
import { readRunIdentityCells, runIdentityCells } from "../identity-source.js";
|
|
19
19
|
import { createInProcessSpaceCommitTable, fenceSpaceCommitAtTerminal, SPACE_COMMIT_RECORD_SCHEMA } from "../workspace-space-commit.js";
|
|
@@ -174,6 +174,7 @@ export class FileRunStore {
|
|
|
174
174
|
return {
|
|
175
175
|
...rest,
|
|
176
176
|
result: d.result ?? null,
|
|
177
|
+
legId: typeof d.legId === "string" ? d.legId : null,
|
|
177
178
|
idemKey: typeof d.idemKey === "string" ? d.idemKey : null,
|
|
178
179
|
idemBodyFingerprint: typeof d.idemBodyFingerprint === "string" ? d.idemBodyFingerprint : null,
|
|
179
180
|
identity: readRunIdentityCells(identitySource, identityScope, identityPrincipalInc),
|
|
@@ -198,6 +199,7 @@ export class FileRunStore {
|
|
|
198
199
|
source: r.source,
|
|
199
200
|
identity: r.identity,
|
|
200
201
|
instanceId: r.instanceId,
|
|
202
|
+
legId: r.legId,
|
|
201
203
|
cancelRequested: r.cancelRequested,
|
|
202
204
|
objectivePreview: r.objectivePreview,
|
|
203
205
|
createdAt: r.createdAt.toISOString(),
|
|
@@ -421,6 +423,7 @@ export class FileRunStore {
|
|
|
421
423
|
}
|
|
422
424
|
this.active.set(sessionId, taskId);
|
|
423
425
|
const now = new Date();
|
|
426
|
+
const legId = mintRunLegId();
|
|
424
427
|
try {
|
|
425
428
|
this.persist({
|
|
426
429
|
taskId,
|
|
@@ -433,6 +436,7 @@ export class FileRunStore {
|
|
|
433
436
|
jobId: meta.jobId ?? null,
|
|
434
437
|
source: meta.source ?? null,
|
|
435
438
|
instanceId,
|
|
439
|
+
legId,
|
|
436
440
|
objectivePreview: meta.objectivePreview ?? null,
|
|
437
441
|
idemKey,
|
|
438
442
|
idemBodyFingerprint: meta.idem?.bodyFingerprint ?? null,
|
|
@@ -449,7 +453,7 @@ export class FileRunStore {
|
|
|
449
453
|
}
|
|
450
454
|
if (idemKey !== null)
|
|
451
455
|
this.byIdem.set(idemKey, taskId);
|
|
452
|
-
return { ok: true };
|
|
456
|
+
return { ok: true, legId };
|
|
453
457
|
}
|
|
454
458
|
async fillObjectivePreview(taskId, preview) {
|
|
455
459
|
const r = this.runs.get(taskId);
|
|
@@ -606,35 +610,39 @@ export class FileRunStore {
|
|
|
606
610
|
notifyRunTerminal(pending);
|
|
607
611
|
return fenced;
|
|
608
612
|
}
|
|
609
|
-
async setSuspended(taskId, result) {
|
|
613
|
+
async setSuspended(taskId, result, legId) {
|
|
610
614
|
const sealed = sealRunRowResult(result);
|
|
611
615
|
const r = this.runs.get(taskId);
|
|
612
|
-
if (r
|
|
613
|
-
|
|
614
|
-
}
|
|
616
|
+
if (!r || r.legId !== legId || (r.status !== "running" && r.status !== "suspended") || r.cancelRequested)
|
|
617
|
+
return false;
|
|
618
|
+
this.persist({ ...r, status: "suspended", result: sealed, errorCode: runRowErrorCodeOf(sealed), updatedAt: new Date() });
|
|
619
|
+
return true;
|
|
615
620
|
}
|
|
616
|
-
async setNeedsReview(taskId, result) {
|
|
621
|
+
async setNeedsReview(taskId, result, legId) {
|
|
617
622
|
const sealed = sealRunRowResult(result);
|
|
618
623
|
const r = this.runs.get(taskId);
|
|
619
|
-
if (r
|
|
620
|
-
|
|
621
|
-
}
|
|
624
|
+
if (!r || r.legId !== legId || (r.status !== "running" && r.status !== "needs_review") || r.cancelRequested)
|
|
625
|
+
return false;
|
|
626
|
+
this.persist({ ...r, status: "needs_review", result: sealed, errorCode: runRowErrorCodeOf(sealed), updatedAt: new Date() });
|
|
627
|
+
return true;
|
|
622
628
|
}
|
|
623
629
|
async markResuming(taskId, instanceId) {
|
|
624
630
|
const r = this.runs.get(taskId);
|
|
625
631
|
if (!r || (r.status !== "suspended" && r.status !== "needs_review"))
|
|
626
|
-
return
|
|
632
|
+
return undefined;
|
|
633
|
+
const legId = mintRunLegId();
|
|
627
634
|
this.persist({
|
|
628
635
|
...r,
|
|
629
636
|
status: "running",
|
|
630
637
|
result: null,
|
|
631
638
|
errorCode: null,
|
|
632
639
|
instanceId,
|
|
640
|
+
legId,
|
|
633
641
|
cancelRequested: false,
|
|
634
642
|
preemptRequested: false,
|
|
635
643
|
updatedAt: new Date(),
|
|
636
644
|
});
|
|
637
|
-
return
|
|
645
|
+
return legId;
|
|
638
646
|
}
|
|
639
647
|
async getActiveTaskId(sessionId) {
|
|
640
648
|
return this.active.get(sessionId);
|
|
@@ -644,7 +652,7 @@ export class FileRunStore {
|
|
|
644
652
|
if (this.active.get(sessionId) !== taskId || r === undefined || r.status !== "running")
|
|
645
653
|
return false;
|
|
646
654
|
this.persist({ ...r, updatedAt: new Date() });
|
|
647
|
-
write({ instanceId: r.instanceId });
|
|
655
|
+
write({ instanceId: r.instanceId, legId: r.legId });
|
|
648
656
|
return true;
|
|
649
657
|
}
|
|
650
658
|
async getRun(taskId) {
|
|
@@ -653,13 +661,31 @@ export class FileRunStore {
|
|
|
653
661
|
}
|
|
654
662
|
async releaseIdemKey(taskId) {
|
|
655
663
|
const r = this.runs.get(taskId);
|
|
656
|
-
if (
|
|
664
|
+
if (r)
|
|
665
|
+
this.dropIdemBinding(r);
|
|
666
|
+
}
|
|
667
|
+
dropIdemBinding(r) {
|
|
668
|
+
if (r.idemKey === null && r.idemBodyFingerprint === null)
|
|
657
669
|
return;
|
|
658
670
|
const key = r.idemKey;
|
|
659
671
|
this.persist({ ...r, idemKey: null, idemBodyFingerprint: null });
|
|
660
|
-
if (key !== null && this.byIdem.get(key) === taskId)
|
|
672
|
+
if (key !== null && this.byIdem.get(key) === r.taskId)
|
|
661
673
|
this.byIdem.delete(key);
|
|
662
674
|
}
|
|
675
|
+
async withdrawMintedRun(taskId, legId) {
|
|
676
|
+
const r = this.runs.get(taskId);
|
|
677
|
+
if (r === undefined || r.legId !== legId)
|
|
678
|
+
return false;
|
|
679
|
+
if (r.status !== "running") {
|
|
680
|
+
if (isTerminalRunStatus(r.status))
|
|
681
|
+
this.dropIdemBinding(r);
|
|
682
|
+
return false;
|
|
683
|
+
}
|
|
684
|
+
this.dropRun(taskId);
|
|
685
|
+
if (this.active.get(r.sessionId) === taskId)
|
|
686
|
+
this.releaseClaim(r.sessionId);
|
|
687
|
+
return true;
|
|
688
|
+
}
|
|
663
689
|
async bindIdemBodyFingerprint(taskId, idem) {
|
|
664
690
|
const r = this.runs.get(taskId);
|
|
665
691
|
if (!r || r.idemKey !== idem.key)
|
|
@@ -1146,14 +1172,16 @@ export class FileRunStore {
|
|
|
1146
1172
|
return migrated;
|
|
1147
1173
|
}
|
|
1148
1174
|
clearShellSentinelOwnersM48() {
|
|
1149
|
-
|
|
1150
|
-
for (const r of
|
|
1151
|
-
if (r.owner !== SHELL_SENTINEL_OWNER_M48)
|
|
1152
|
-
continue;
|
|
1175
|
+
const hits = this.shellSentinelRunsM48();
|
|
1176
|
+
for (const r of hits)
|
|
1153
1177
|
this.persist({ ...r, owner: null });
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1178
|
+
return hits.length;
|
|
1179
|
+
}
|
|
1180
|
+
countShellSentinelOwnersM48() {
|
|
1181
|
+
return this.shellSentinelRunsM48().length;
|
|
1182
|
+
}
|
|
1183
|
+
shellSentinelRunsM48() {
|
|
1184
|
+
return [...this.runs.values()].filter((r) => isShellSentinelOwnerM48(r.owner));
|
|
1157
1185
|
}
|
|
1158
1186
|
sessionIdsWithRuns() {
|
|
1159
1187
|
return new Set([...this.runs.values()].map((r) => r.sessionId));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Checkpoint, type CheckpointSummary, type CheckpointToken, type PendingSteerInput, type ReopenReason, type ResolveExpectation, type ExecutionOutcomeRecordWord, type GateOutcome, type ResumeOutcome, type StoreDurability, type StoreFidelity } from "@sema-agent/core";
|
|
1
|
+
import { type Checkpoint, type CheckpointPage, type CheckpointRowRead, type CheckpointSessionCursor, type CheckpointSessionQuery, type CheckpointSummary, type CheckpointToken, type PendingSteerInput, type ReopenReason, type ResolveExpectation, type ExecutionOutcomeRecordWord, type GateOutcome, type ResumeOutcome, type StoreDurability, type StoreFidelity } from "@sema-agent/core";
|
|
2
2
|
import { type CheckpointAskCandidate, type CtxClaimPut, type CtxClaimRewrite, type CtxRowRewrite, type CtxRowsRewrite, type DecidedApprovalRecord, type ExpiredApprovalGate, type ExpiredGatePosition, type PendingCheckpoint, type PendingRowBinding } from "./checkpoint-store-face.js";
|
|
3
3
|
import { type CtxWriteClaim } from "./store-contracts.js";
|
|
4
4
|
import type { SealedCheckpointCtx } from "../http/checkpoint-ctx.js";
|
|
@@ -9,6 +9,8 @@ import type { SealedCheckpointCtx } from "../http/checkpoint-ctx.js";
|
|
|
9
9
|
*/
|
|
10
10
|
export declare function dropLocalCheckpointCtxStrict(root: string, sessionId: string): void;
|
|
11
11
|
export interface LocalCheckpointStoreOptions {
|
|
12
|
+
/** 本店对引擎的耐久声明(装配方给 —— local 后端递 `localStoreDeclarationOf` 那一份,与会话店同读:两半一起)。缺席 ⇒ 内核的读数 `"durable"`(见字段注)。 */
|
|
13
|
+
durability?: StoreDurability;
|
|
12
14
|
/** 会话认领联结(the local FileRunStore's `getActiveTaskId`)—— 停驻行 `taskId` 的第二格读数([ref],写者 `parkedLegTaskId`)。Absent ⇒ 只剩行上的记录。 */
|
|
13
15
|
getActiveTaskId?: (sessionId: string) => Promise<string | undefined>;
|
|
14
16
|
/** E21 owner guard (the LocalSessionStore's owner read, `headOf(id)?.owner`: `undefined` = no session row). Absent ⇒ owner guard degrades
|
|
@@ -31,6 +33,8 @@ export declare class LocalCheckpointStore {
|
|
|
31
33
|
*
|
|
32
34
|
* 它与「session store 的 local 形声明 durable 就拒启」不矛盾:那条判据管的是**声明 vs 介质**,而这里
|
|
33
35
|
* 的介质就是盘。真正的 process-local 形(`InMemoryCheckpointStore`)由 core 自己声明 `"process-local"`。
|
|
36
|
+
* 装配方给了声明就用它(local 后端递 `localStoreDeclarationOf` 那一份 —— 运维声明易失 / 调用方自己那块易失盘 ⇒ 与会话店一起降为 `"process-local"`:
|
|
37
|
+
* 进程重启照旧活过,容器替换不保留;只降一半会让引擎的 durable-park 自检读出缺口)。
|
|
34
38
|
*/
|
|
35
39
|
readonly durability: StoreDurability;
|
|
36
40
|
/**
|
|
@@ -114,6 +118,9 @@ export declare class LocalCheckpointStore {
|
|
|
114
118
|
expire(token: CheckpointToken, scope: string): Promise<boolean>;
|
|
115
119
|
reap(scope: string, cutoff: number): Promise<number>;
|
|
116
120
|
listByScope(scope: string): Promise<CheckpointSummary[]>;
|
|
121
|
+
/** core `CheckpointStore.listBySession`(可选动词,按在不在探):纯委派给内核 —— 读法是 core 的 `selectSessionPage`(SQL 孪生把「这只会话的行」交给同一只);
|
|
122
|
+
* 内核读的是它自己的全部行(任何状态),坏行由内核按行答 `unreadable`、经数据根那只披露座说。包装层不另判、不另列。 */
|
|
123
|
+
listBySession(query: CheckpointSessionQuery): Promise<CheckpointPage<CheckpointRowRead, CheckpointSessionCursor>>;
|
|
117
124
|
close(): void;
|
|
118
125
|
/** C4-B:注册表损坏时从**数据本体**懒重建 scope 集(core 1.424 `listScopes?` = 「有 ≥1 条 pending 的
|
|
119
126
|
* distinct scope 集」,与 listByScope 可见面对齐 —— 恰好是本注册表要的内容)。一次性:重建后回写
|
|
@@ -94,7 +94,7 @@ export function localCheckpointStoreDirsFor(root) {
|
|
|
94
94
|
}
|
|
95
95
|
export class LocalCheckpointStore {
|
|
96
96
|
retention = UNMANAGED_RETENTION;
|
|
97
|
-
durability
|
|
97
|
+
durability;
|
|
98
98
|
fidelity = "json";
|
|
99
99
|
execution = { outcome: true };
|
|
100
100
|
inner;
|
|
@@ -110,6 +110,7 @@ export class LocalCheckpointStore {
|
|
|
110
110
|
opts;
|
|
111
111
|
constructor(root, opts = {}) {
|
|
112
112
|
this.inner = new FileCheckpointStore(root);
|
|
113
|
+
this.durability = opts.durability ?? this.inner.durability;
|
|
113
114
|
this.opts = opts;
|
|
114
115
|
this.scopesPath = join(root, "checkpoint-scopes.json");
|
|
115
116
|
this.sessionTokensPath = join(root, "checkpoint-session-tokens.json");
|
|
@@ -226,6 +227,9 @@ export class LocalCheckpointStore {
|
|
|
226
227
|
listByScope(scope) {
|
|
227
228
|
return this.inner.listByScope(scope);
|
|
228
229
|
}
|
|
230
|
+
listBySession(query) {
|
|
231
|
+
return this.inner.listBySession(query);
|
|
232
|
+
}
|
|
229
233
|
close() {
|
|
230
234
|
this.inner.close();
|
|
231
235
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type EngineHighWaterReading } from "./local-engine-high-water.js";
|
|
2
|
+
import { type ArchiveTokenAdoptionDutyAction, type DataRootFileText } from "./local-session-store.js";
|
|
3
|
+
import { type SkillExemptionCutoffAction } from "./approval-exemption-skill-cutoff.js";
|
|
4
|
+
import { type ReleaseTriple } from "./release-version.js";
|
|
5
|
+
/** 准入的一次观察(纯数据;判的全部输入)—— 锁内逐项比的那一份。读不出的输入在判里已拒,所以存下来的观察里只有「缺席 / 字节」两态。 */
|
|
6
|
+
export interface LocalDataRootObservation {
|
|
7
|
+
readonly marker: DataRootFileText;
|
|
8
|
+
/** 严格边档清册的字节(按清册次序)。 */
|
|
9
|
+
readonly strictSidecars: readonly DataRootFileText[];
|
|
10
|
+
/** 存档目录里的会话 id(目录不在 ⇒ 空)。 */
|
|
11
|
+
readonly archiveIds: readonly string[];
|
|
12
|
+
/** 收令牌欠账标记在不在。 */
|
|
13
|
+
readonly adoptionPending: boolean;
|
|
14
|
+
/** `Skill` 豁免截点文件的字节。 */
|
|
15
|
+
readonly skillCutoff: DataRootFileText;
|
|
16
|
+
/** 会话豁免日志目录的指纹(`exemptionLogFingerprints`);`null` = 没读:本构建还带 M46,截点之前的行归它删,判不读日志。 */
|
|
17
|
+
readonly exemptionLogs: readonly string[] | null;
|
|
18
|
+
}
|
|
19
|
+
/** 准入的读数(纯数据;唯一铸点 {@link admitLocalDataRoot},唯一消费者 {@link holdLocalDataRootAdmission})。 */
|
|
20
|
+
export interface LocalDataRootAdmission {
|
|
21
|
+
/** 判的是哪只根:物理路径(core 打开它的同一读法);`undefined` = 准入时数据根上什么都没有(还不存在 / 不是目录 / 空目录)。 */
|
|
22
|
+
readonly root: string | undefined;
|
|
23
|
+
/** 判的输入(锁内逐项比)。 */
|
|
24
|
+
readonly observed: LocalDataRootObservation;
|
|
25
|
+
/** 引擎高水位的读数(抬的依据)。 */
|
|
26
|
+
readonly highWater: EngineHighWaterReading;
|
|
27
|
+
/** 跳版臂要在锁内、抬之前做的动作。 */
|
|
28
|
+
readonly archiveDuty: ArchiveTokenAdoptionDutyAction;
|
|
29
|
+
/** `Skill` 豁免截点要在锁内、抬之前做的动作(缺席 ⇒ 落)。 */
|
|
30
|
+
readonly skillCutoff: SkillExemptionCutoffAction;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* **准入**(只读;拒 = 抛 —— 拒句是 `LocalDataRootSchemaMismatchError` 的 `boot` 形,或本构建版本读不出的那一只 `StoreBootRefusalError`;
|
|
34
|
+
* 判不了的 I/O 故障如存档目录读不了原样抛 = 不放行)。`engine` 缺席 = 本构建(`serviceVersion()`)。
|
|
35
|
+
* 数据根上什么都没有(不存在 / 不是目录 / 空目录 —— {@link localDataRootHoldsData},与起服降级臂同一读法)⇒ 没有可判的,按缺席放行(首启;只判本构建发布线);
|
|
36
|
+
* 建不建得出根是打开那一步的事(显式 local 拒句点名「打不开数据根」,缺省推导的 local 走降级臂)—— 准入不把「根还不存在」读成「marker 读不出」。
|
|
37
|
+
*/
|
|
38
|
+
export declare function admitLocalDataRoot(root: string, engine?: string): LocalDataRootAdmission;
|
|
39
|
+
/**
|
|
40
|
+
* **判 `Skill` 豁免截点**(律见 `approval-exemption-skill-cutoff.ts`;唯一调用点 = {@link admitLocalDataRoot},判的是准入那一次观察里的截点文件字节):
|
|
41
|
+
* · 截点文件读不出(I/O / 正文不是时刻)⇒ 拒(读不出的那一形)—— 带不带 M46 都判(fail-closed 律:读不出的截点不猜);
|
|
42
|
+
* · `carried`(本构建还带 M46)⇒ 不读日志、不因行拒:截点缺席 ⇒ `lay`(锁内先落,M46 读它删截点之前的行),否则 `none`;
|
|
43
|
+
* · 不带 ⇒ 首次放行早于截点(截点缺席 ⇒ 任一)的 `Skill` 行所在的会话 > 0 ⇒ 拒(`skipped-required-migration`,
|
|
44
|
+
* 出路版本不低于 {@link SKILL_EXEMPTION_CUTOFF_SINCE} 与已记高水位);都没有 ⇒ 截点缺席则 `lay`。拒在准入里 ⇒ 数据根零写、高水位不抬 ⇒ 拒句点名的那一版仍开得了这只根。
|
|
45
|
+
*/
|
|
46
|
+
export declare function judgeLocalSkillExemptionCutoff(root: string, raw: DataRootFileText, priorHighWater: ReleaseTriple | undefined, carried: boolean): SkillExemptionCutoffAction;
|
|
47
|
+
/**
|
|
48
|
+
* **锁内一步**(唯一调用点 = `openLocalBackend`:数据根锁在手之后、本仓任何一只店建起之前):核数据根没动(物理路径是准入那一只、再观察一次与准入那一次逐项相同)
|
|
49
|
+
* → 做跳版臂的动作 → 落 `Skill` 豁免截点(缺席才落)→ 抬。任一步抛 ⇒ 不抬、不建店(调用方交回拒后端,只放锁)。
|
|
50
|
+
*/
|
|
51
|
+
export declare function holdLocalDataRootAdmission(physicalRoot: string, admission: LocalDataRootAdmission): void;
|
|
52
|
+
//# sourceMappingURL=local-data-root-admission.d.ts.map
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { physicalPathOf } from "@sema-agent/core";
|
|
3
|
+
import { serviceVersion } from "../service-version.js";
|
|
4
|
+
import { localDataRootHoldsData } from "../store-posture.js";
|
|
5
|
+
import { StoreBootRefusalError } from "./store-contracts.js";
|
|
6
|
+
import { engineHighWaterPath, judgeEngineHighWater, ownReleaseLine, raiseEngineHighWater } from "./local-engine-high-water.js";
|
|
7
|
+
import { archiveIdsInSync, archiveTokenAdoptionPendingPresent, judgeArchiveTokenAdoptionDuty, judgeStrictSidecars, readDataRootFileTextSync, readStrictSidecarTextsSync, settleArchiveTokenAdoptionDuty, dataRootMismatchOf, LocalDataRootSchemaMismatchError, } from "./local-session-store.js";
|
|
8
|
+
import { LOCAL_SKILL_EXEMPTION_CUTOFF_FILE, SKILL_EXEMPTION_CUTOFF_SINCE, exemptionLogFingerprints, localSkillExemptionSessionsBefore, settleLocalSkillExemptionCutoff, skillExemptionCutoffOfText, } from "./approval-exemption-skill-cutoff.js";
|
|
9
|
+
import { APPROVAL_EXEMPTION_DIR } from "./approval-exemption-store.js";
|
|
10
|
+
import { SKILL_EXEMPTION_CUTOFF_ID } from "./one-time-migration-marker.js";
|
|
11
|
+
import { migrationCarried } from "./one-time-migrations.js";
|
|
12
|
+
import { releaseText } from "./release-version.js";
|
|
13
|
+
const ABSENT = { state: "absent" };
|
|
14
|
+
const EMPTY_OBSERVATION = Object.freeze({ marker: ABSENT, strictSidecars: [], archiveIds: [], adoptionPending: false, skillCutoff: ABSENT, exemptionLogs: [] });
|
|
15
|
+
function observeLocalDataRoot(root, exemptionLogs) {
|
|
16
|
+
return {
|
|
17
|
+
marker: readDataRootFileTextSync(engineHighWaterPath(root)),
|
|
18
|
+
strictSidecars: readStrictSidecarTextsSync(root),
|
|
19
|
+
archiveIds: archiveIdsInSync(root),
|
|
20
|
+
adoptionPending: archiveTokenAdoptionPendingPresent(root),
|
|
21
|
+
skillCutoff: readDataRootFileTextSync(join(root, LOCAL_SKILL_EXEMPTION_CUTOFF_FILE)),
|
|
22
|
+
exemptionLogs: exemptionLogs ? exemptionLogFingerprints(root) : null,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const textOf = (r) => (r.state === "text" ? r.text : r.state === "absent" ? undefined : null);
|
|
26
|
+
function movedInput(admitted, now) {
|
|
27
|
+
if (textOf(admitted.marker) !== textOf(now.marker))
|
|
28
|
+
return "the engine high-water marker";
|
|
29
|
+
const sidecars = Math.max(admitted.strictSidecars.length, now.strictSidecars.length);
|
|
30
|
+
for (let i = 0; i < sidecars; i++) {
|
|
31
|
+
if (textOf(admitted.strictSidecars[i] ?? ABSENT) !== textOf(now.strictSidecars[i] ?? ABSENT))
|
|
32
|
+
return "a strict sidecar (session-meta)";
|
|
33
|
+
}
|
|
34
|
+
if (admitted.archiveIds.join("\n") !== now.archiveIds.join("\n"))
|
|
35
|
+
return "the session archive directory";
|
|
36
|
+
if (admitted.adoptionPending !== now.adoptionPending)
|
|
37
|
+
return "the archive-token adoption record";
|
|
38
|
+
if (textOf(admitted.skillCutoff) !== textOf(now.skillCutoff))
|
|
39
|
+
return "the Skill exemption cutoff";
|
|
40
|
+
if ((admitted.exemptionLogs ?? []).join("\n") !== (now.exemptionLogs ?? []).join("\n"))
|
|
41
|
+
return "the session approval exemption logs";
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
export function admitLocalDataRoot(root, engine = serviceVersion()) {
|
|
45
|
+
const given = root.normalize("NFC");
|
|
46
|
+
if (!localDataRootHoldsData(given)) {
|
|
47
|
+
return Object.freeze({ root: undefined, observed: EMPTY_OBSERVATION, highWater: { own: ownReleaseLine(given, engine), prior: undefined }, archiveDuty: "none", skillCutoff: "lay" });
|
|
48
|
+
}
|
|
49
|
+
const carried = migrationCarried(SKILL_EXEMPTION_CUTOFF_ID);
|
|
50
|
+
const physical = physicalPathOf(given);
|
|
51
|
+
const observed = observeLocalDataRoot(physical, !carried);
|
|
52
|
+
const highWater = judgeEngineHighWater(physical, observed.marker, engine);
|
|
53
|
+
const cells = judgeStrictSidecars(physical, observed.strictSidecars);
|
|
54
|
+
const archiveDuty = judgeArchiveTokenAdoptionDuty(physical, highWater.prior, migrationCarried("M47"), { cells, archiveIds: observed.archiveIds, adoptionPending: observed.adoptionPending });
|
|
55
|
+
const skillCutoff = judgeLocalSkillExemptionCutoff(physical, observed.skillCutoff, highWater.prior, carried);
|
|
56
|
+
return Object.freeze({ root: physical, observed, highWater, archiveDuty, skillCutoff });
|
|
57
|
+
}
|
|
58
|
+
export function judgeLocalSkillExemptionCutoff(root, raw, priorHighWater, carried) {
|
|
59
|
+
const path = join(root, LOCAL_SKILL_EXEMPTION_CUTOFF_FILE);
|
|
60
|
+
const label = `${LOCAL_SKILL_EXEMPTION_CUTOFF_FILE} (the local Skill exemption cutoff)`;
|
|
61
|
+
if (raw.state === "unreadable")
|
|
62
|
+
throw new LocalDataRootSchemaMismatchError([dataRootMismatchOf(path, label, raw.fault)], "boot");
|
|
63
|
+
const cutoffMs = raw.state === "text" ? skillExemptionCutoffOfText(raw.text) : undefined;
|
|
64
|
+
if (raw.state === "text" && cutoffMs === undefined)
|
|
65
|
+
throw new LocalDataRootSchemaMismatchError([{ path, label, problem: "malformed", unknownFields: [] }], "boot");
|
|
66
|
+
if (carried)
|
|
67
|
+
return cutoffMs === undefined ? "lay" : "none";
|
|
68
|
+
const sessions = localSkillExemptionSessionsBefore(root, cutoffMs);
|
|
69
|
+
if (sessions > 0) {
|
|
70
|
+
throw new LocalDataRootSchemaMismatchError([
|
|
71
|
+
{
|
|
72
|
+
path: join(root, APPROVAL_EXEMPTION_DIR),
|
|
73
|
+
label: `${APPROVAL_EXEMPTION_DIR} (the local session approval exemptions)`,
|
|
74
|
+
problem: "skipped-required-migration",
|
|
75
|
+
unknownFields: [],
|
|
76
|
+
skippedMigration: {
|
|
77
|
+
residue: "pre-cutoff-skill-exemptions",
|
|
78
|
+
highWater: priorHighWater === undefined ? null : releaseText(priorHighWater),
|
|
79
|
+
requiredSince: SKILL_EXEMPTION_CUTOFF_SINCE,
|
|
80
|
+
sessions,
|
|
81
|
+
cutoff: cutoffMs === undefined ? null : new Date(cutoffMs).toISOString(),
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
], "boot");
|
|
85
|
+
}
|
|
86
|
+
return cutoffMs === undefined ? "lay" : "none";
|
|
87
|
+
}
|
|
88
|
+
export function holdLocalDataRootAdmission(physicalRoot, admission) {
|
|
89
|
+
const moved = admission.root !== undefined && admission.root !== physicalRoot
|
|
90
|
+
? "the data root's physical path"
|
|
91
|
+
: movedInput(admission.observed, observeLocalDataRoot(physicalRoot, admission.observed.exemptionLogs !== null));
|
|
92
|
+
if (moved !== undefined) {
|
|
93
|
+
throw new StoreBootRefusalError(`DB_BACKEND=local: ${moved} under ${physicalRoot} changed between this start's data-root admission and taking the data-root lock — another engine opened this data root meanwhile; ` +
|
|
94
|
+
"refusing to open it on a stale reading. Restart: the next start judges the data root as it is then.");
|
|
95
|
+
}
|
|
96
|
+
settleArchiveTokenAdoptionDuty(physicalRoot, admission.highWater.prior, admission.archiveDuty);
|
|
97
|
+
settleLocalSkillExemptionCutoff(physicalRoot, admission.skillCutoff);
|
|
98
|
+
raiseEngineHighWater(physicalRoot, admission.highWater);
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=local-data-root-admission.js.map
|
|
@@ -1,13 +1,34 @@
|
|
|
1
|
+
import { type DataRootFileText } from "./local-session-store.js";
|
|
1
2
|
import { type ReleaseTriple } from "./release-version.js";
|
|
2
3
|
/** marker 的文件名(数据根顶层;公开契约)。 */
|
|
3
4
|
export declare const ENGINE_HIGH_WATER_FILE = "engine-high-water.json";
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* ② 读 `<root>/engine-high-water.json`:读不出 / 高水位高于本构建 ⇒ 抛 {@link LocalDataRootSchemaMismatchError}(`boot` 形;文件原地不动,不抬);
|
|
8
|
-
* ③ 判前钩 `judgePrior`(在场时)以打开之前的高水位(缺席 ⇒ `undefined`)调一次(它可以在判过之后写调用方自己的事实 —— 先于抬);它抛 ⇒ 原样上抛、不抬;
|
|
9
|
-
* ④ 缺席或低于本构建 ⇒ 原子写 `{"highWater": <本构建的纯三段>}`(`required`);相等 ⇒ 不写,只过持久化屏障(读到的可能是上一次没证完的那份)。写不进 / 证不了 ⇒ 抛(点名路径与原因)。
|
|
10
|
-
* 同步:它在后端打开的同步段里跑(建店之前),拒在这里就不会有一只店被建起。
|
|
6
|
+
* 准入判出的高水位(**读数**,不是活物):{@link raiseEngineHighWater} 按它抬。唯一的铸点 = {@link judgeEngineHighWater} / 空根那一格的 {@link ownReleaseLine}
|
|
7
|
+
* (都在数据根准入 `local-data-root-admission.ts` 的 `admitLocalDataRoot` 里)。
|
|
11
8
|
*/
|
|
12
|
-
export
|
|
9
|
+
export interface EngineHighWaterReading {
|
|
10
|
+
/** 本构建的发布线(纯三段;判与抬都按它)。 */
|
|
11
|
+
readonly own: ReleaseTriple;
|
|
12
|
+
/** marker 记的高水位(缺席 = `undefined`);跳版拒启臂读它。 */
|
|
13
|
+
readonly prior: ReleaseTriple | undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 本构建的发布线(判与抬都按它):`engine` 按发布线读不出({@link buildReleaseTriple})⇒ 抛 {@link StoreBootRefusalError} —— 判不了「不比打开过这只根的引擎旧」,
|
|
17
|
+
* 也写不出自己的水位(坏包,不服务这只根;数据根上有没有东西都一样拒)。
|
|
18
|
+
*/
|
|
19
|
+
export declare function ownReleaseLine(root: string, engine: string): ReleaseTriple;
|
|
20
|
+
/** marker 在一只(物理)数据根下的路径。 */
|
|
21
|
+
export declare function engineHighWaterPath(root: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* **判**(纯;唯一调用点 = 数据根准入:判的是准入那一次观察里 marker 的字节 `raw`,不自己读盘):
|
|
24
|
+
* ① 本构建版本按发布线读不出 ⇒ 抛({@link ownReleaseLine});
|
|
25
|
+
* ② marker 读不出 / 高水位高于本构建 ⇒ 抛 {@link LocalDataRootSchemaMismatchError}(`boot` 形);
|
|
26
|
+
* ③ 否则交回读数(缺席 / 低于 / 等于)。
|
|
27
|
+
*/
|
|
28
|
+
export declare function judgeEngineHighWater(root: string, raw: DataRootFileText, engine: string): EngineHighWaterReading;
|
|
29
|
+
/**
|
|
30
|
+
* **抬**(锁内;紧随准入的「数据根没动」核对与跳版臂的记账之后、本仓任何一只店建起之前):缺席或低于本构建 ⇒ 原子写 `{"highWater": <本构建的纯三段>}`(`required`);
|
|
31
|
+
* 相等 ⇒ 不写,只过持久化屏障(读到的可能是上一次没证完的那份)。写不进 / 证不了 ⇒ 抛(点名路径与原因)。
|
|
32
|
+
*/
|
|
33
|
+
export declare function raiseEngineHighWater(physicalRoot: string, admitted: EngineHighWaterReading): void;
|
|
13
34
|
//# sourceMappingURL=local-engine-high-water.d.ts.map
|
|
@@ -2,7 +2,7 @@ import { join, resolve } from "node:path";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { atomicWriteFileSync, proveDurableSync } from "./owner-only-file-mode.js";
|
|
4
4
|
import { createZodColumnReader, decodeJsonColumn } from "./sql-json-column.js";
|
|
5
|
-
import { LocalDataRootSchemaMismatchError, dataRootMismatchOf
|
|
5
|
+
import { LocalDataRootSchemaMismatchError, dataRootMismatchOf } from "./local-session-store.js";
|
|
6
6
|
import { buildReleaseTriple, compareReleaseTriples, releaseText, releaseTriple } from "./release-version.js";
|
|
7
7
|
import { StoreBootRefusalError } from "./store-contracts.js";
|
|
8
8
|
export const ENGINE_HIGH_WATER_FILE = "engine-high-water.json";
|
|
@@ -19,40 +19,45 @@ const ENGINE_HIGH_WATER_SHAPE = z
|
|
|
19
19
|
return { highWater: v.highWater, triple };
|
|
20
20
|
});
|
|
21
21
|
const readEngineHighWater = createZodColumnReader(ENGINE_HIGH_WATER_SHAPE);
|
|
22
|
-
export function
|
|
22
|
+
export function ownReleaseLine(root, engine) {
|
|
23
23
|
const own = buildReleaseTriple(engine);
|
|
24
24
|
if (own === undefined) {
|
|
25
25
|
throw new StoreBootRefusalError(`DB_BACKEND=local: this build's own version (package.json "version": ${JSON.stringify(engine.slice(0, 64))}) is not a release version (x.y.z, optionally with a prerelease or build suffix) — refusing to open the data root ${root}: ` +
|
|
26
26
|
"the engine high-water fence needs this build's release line to show it is not older than the engines that opened this data root, and to record its own. " +
|
|
27
27
|
"Run a build whose package.json carries a release version.");
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
return own;
|
|
30
|
+
}
|
|
31
|
+
export function engineHighWaterPath(root) {
|
|
32
|
+
return resolve(join(root, ENGINE_HIGH_WATER_FILE));
|
|
33
|
+
}
|
|
34
|
+
export function judgeEngineHighWater(root, raw, engine) {
|
|
35
|
+
const own = ownReleaseLine(root, engine);
|
|
36
|
+
const path = engineHighWaterPath(root);
|
|
33
37
|
if (raw.state === "unreadable")
|
|
34
38
|
throw new LocalDataRootSchemaMismatchError([dataRootMismatchOf(path, ENGINE_HIGH_WATER_LABEL, raw.fault)], "boot");
|
|
35
|
-
if (raw.state === "
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
catch (e) {
|
|
41
|
-
throw new LocalDataRootSchemaMismatchError([dataRootMismatchOf(path, ENGINE_HIGH_WATER_LABEL, e)], "boot");
|
|
42
|
-
}
|
|
43
|
-
const order = compareReleaseTriples(marker.triple, own);
|
|
44
|
-
if (order > 0) {
|
|
45
|
-
throw new LocalDataRootSchemaMismatchError([{ path, label: ENGINE_HIGH_WATER_LABEL, problem: "newer-engine", unknownFields: [], engineHighWater: { highWater: marker.highWater, engine } }], "boot");
|
|
46
|
-
}
|
|
47
|
-
equal = order === 0;
|
|
48
|
-
prior = marker.triple;
|
|
39
|
+
if (raw.state === "absent")
|
|
40
|
+
return { own, prior: undefined };
|
|
41
|
+
let marker;
|
|
42
|
+
try {
|
|
43
|
+
marker = decodeJsonColumn(raw.text, readEngineHighWater, ENGINE_HIGH_WATER_LABEL);
|
|
49
44
|
}
|
|
50
|
-
|
|
45
|
+
catch (e) {
|
|
46
|
+
throw new LocalDataRootSchemaMismatchError([dataRootMismatchOf(path, ENGINE_HIGH_WATER_LABEL, e)], "boot");
|
|
47
|
+
}
|
|
48
|
+
if (compareReleaseTriples(marker.triple, own) > 0) {
|
|
49
|
+
throw new LocalDataRootSchemaMismatchError([{ path, label: ENGINE_HIGH_WATER_LABEL, problem: "newer-engine", unknownFields: [], engineHighWater: { highWater: marker.highWater, engine } }], "boot");
|
|
50
|
+
}
|
|
51
|
+
return { own, prior: marker.triple };
|
|
52
|
+
}
|
|
53
|
+
export function raiseEngineHighWater(physicalRoot, admitted) {
|
|
54
|
+
const path = engineHighWaterPath(physicalRoot);
|
|
55
|
+
const equal = admitted.prior !== undefined && compareReleaseTriples(admitted.prior, admitted.own) === 0;
|
|
51
56
|
try {
|
|
52
57
|
if (equal)
|
|
53
58
|
proveDurableSync(path);
|
|
54
59
|
else
|
|
55
|
-
atomicWriteFileSync(path, `${JSON.stringify({ highWater: releaseText(own) })}\n`, { durability: "required" });
|
|
60
|
+
atomicWriteFileSync(path, `${JSON.stringify({ highWater: releaseText(admitted.own) })}\n`, { durability: "required" });
|
|
56
61
|
}
|
|
57
62
|
catch (e) {
|
|
58
63
|
throw new Error(`DB_BACKEND=local cannot record the engine high-water ${path} durably: ${e instanceof Error ? e.message : String(e)} — refusing to open the data root: ` +
|