@sema-agent/server 7.149.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 +122 -9
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +39 -15
- package/dist/approval-card.d.ts +1 -1
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/audit.d.ts +1 -1
- package/dist/audit.js +2 -2
- 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/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 +61 -25
- package/dist/boot/retention-lane.d.ts +1 -1
- package/dist/boot/session-faces.js +21 -21
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-06-runners.js +1 -2
- package/dist/boot/stage-07-capability-layer.js +1 -1
- package/dist/boot/stage-10-http-server.d.ts +33 -1
- package/dist/boot/stage-10-http-server.js +9 -4
- package/dist/boot/web-admin.d.ts +1 -1
- package/dist/capability-facts.d.ts +65 -56
- package/dist/capability-facts.js +42 -35
- package/dist/config-catalog.js +1 -1
- package/dist/config-types.d.ts +12 -11
- package/dist/deployment-governance.d.ts +7 -28
- package/dist/deployment-governance.js +1 -14
- 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/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/http/active-run-conflict.d.ts +3 -7
- package/dist/http/active-run-conflict.js +2 -2
- package/dist/http/admission.js +2 -2
- package/dist/http/approval-sweeps.js +2 -1
- 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 +4 -4
- package/dist/http/claim-heartbeat.js +3 -3
- package/dist/http/dispatch.js +2 -2
- package/dist/http/durable-run-leg.js +4 -4
- package/dist/http/owner-access.d.ts +243 -19
- package/dist/http/owner-access.js +184 -5
- package/dist/http/readiness.d.ts +4 -2
- package/dist/http/resume-ctx-read.js +16 -1
- package/dist/http/resume-legs.js +18 -14
- package/dist/http/route-ctx.d.ts +23 -11
- package/dist/http/routes/a2a-serve.js +15 -14
- package/dist/http/routes/approvals-assistant.d.ts +3 -2
- package/dist/http/routes/approvals-assistant.js +8 -9
- package/dist/http/routes/capabilities.js +4 -3
- package/dist/http/routes/config-catalog.d.ts +1 -1
- 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 +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 +23 -30
- package/dist/http/routes/session-memory-sync.js +4 -5
- package/dist/http/routes/session-sync.js +3 -7
- package/dist/http/routes/sessions.d.ts +1 -1
- package/dist/http/routes/sessions.js +18 -44
- package/dist/http/routes/tasks.js +9 -8
- 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 +8 -4
- package/dist/http/server.js +5 -1
- 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 +3 -2
- 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/leader/endpoint.js +9 -8
- package/dist/leg-facts.d.ts +8 -2
- package/dist/leg-facts.js +1 -0
- package/dist/mcp-authorization-face.d.ts +18 -14
- package/dist/mcp-authorization-face.js +3 -2
- package/dist/memory-store-refusal.d.ts +1 -1
- package/dist/observability/corrupt-read-seat.d.ts +1 -1
- package/dist/observability/fail-open.d.ts +5 -5
- package/dist/observability/fail-open.js +5 -5
- package/dist/observability/logger.d.ts +7 -0
- package/dist/observability/logger.js +3 -1
- package/dist/observability/run-terminal.d.ts +1 -1
- package/dist/owner-faces.d.ts +27 -3
- package/dist/owner-faces.js +2 -0
- package/dist/peer-seat.d.ts +1 -1
- package/dist/peer-seat.js +52 -59
- 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.js +1 -1
- package/dist/plugins/local-checkpoint-store.d.ts +4 -1
- package/dist/plugins/local-checkpoint-store.js +3 -0
- package/dist/plugins/memory-run-store.js +1 -1
- package/dist/plugins/one-time-migrations.d.ts +74 -49
- package/dist/plugins/one-time-migrations.js +134 -69
- package/dist/plugins/pg-pool.js +4 -0
- package/dist/plugins/posix-shell-fs.js +4 -2
- package/dist/plugins/remote-env-adb.js +3 -2
- package/dist/plugins/remote-env-device.js +8 -6
- package/dist/plugins/remote-env-e2b.d.ts +3 -1
- package/dist/plugins/remote-env-e2b.js +11 -8
- package/dist/plugins/remote-env-host.d.ts +1 -1
- package/dist/plugins/remote-env-host.js +20 -11
- package/dist/plugins/remote-env-k8s.js +3 -2
- package/dist/plugins/remote-env-local-docker.js +3 -2
- 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 +1 -1
- package/dist/plugins/run-store-sql.js +2 -2
- 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 +7 -5
- package/dist/plugins/schema-consistency.js +29 -16
- package/dist/plugins/schema-drift-sentence.js +1 -1
- package/dist/plugins/serving-requirement.d.ts +49 -0
- package/dist/plugins/serving-requirement.js +53 -0
- package/dist/plugins/stop-then-start-sentence.d.ts +42 -3
- package/dist/plugins/stop-then-start-sentence.js +44 -0
- package/dist/plugins/store-backend.d.ts +1 -1
- package/dist/plugins/store-contracts.d.ts +12 -2
- package/dist/plugins/store-contracts.js +3 -0
- package/dist/plugins/tidb-pool.js +4 -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/question.d.ts +9 -21
- package/dist/question.js +28 -19
- package/dist/run-cancel-card.d.ts +1 -1
- package/dist/run-cancel-card.js +2 -1
- package/dist/security.d.ts +1 -1
- package/dist/session-agent.d.ts +1 -10
- package/dist/session-agent.js +0 -6
- 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/stores-sql/checkpoint-store-sql.d.ts +21 -2
- package/dist/stores-sql/checkpoint-store-sql.js +106 -18
- package/dist/stores-sql/retention-store-sql.d.ts +1 -1
- package/dist/task-cwd.d.ts +4 -3
- package/dist/task-settings.d.ts +13 -0
- package/dist/task-settings.js +13 -7
- package/dist/tool-approval.d.ts +7 -6
- package/dist/tool-approval.js +41 -37
- 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 +150 -17
- package/dist/trace/self-minted-wire.js +54 -16
- 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 +57 -29
- package/package.json +2 -2
- package/wire-changes/server@7.150.0.json +335 -0
package/dist/peer-seat.js
CHANGED
|
@@ -151,67 +151,60 @@ export function createPeerDesk(opts = {}) {
|
|
|
151
151
|
return { kind: "carry", env: entry.pieces };
|
|
152
152
|
}
|
|
153
153
|
};
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
case "handle":
|
|
157
|
-
return ref.id;
|
|
158
|
-
case "env":
|
|
159
|
-
case "vault":
|
|
160
|
-
case "assertion":
|
|
161
|
-
return undefined;
|
|
162
|
-
default: {
|
|
163
|
-
const unknownKind = ref;
|
|
164
|
-
void unknownKind;
|
|
165
|
-
return undefined;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
154
|
+
const notMintedHold = () => {
|
|
155
|
+
throw new Error("peer desk: hold of a reference this desk did not mint — not held");
|
|
168
156
|
};
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
157
|
+
const notMintedRelease = () => {
|
|
158
|
+
throw new Error("peer desk: release of a reference this desk did not mint — nothing released");
|
|
159
|
+
};
|
|
160
|
+
const notMinted = (reason) => ({
|
|
161
|
+
answer: (_ref, question) => refuse(question.peer, reason),
|
|
162
|
+
hold: notMintedHold,
|
|
163
|
+
release: notMintedRelease,
|
|
164
|
+
});
|
|
165
|
+
const seatKinds = {
|
|
166
|
+
handle: {
|
|
167
|
+
answer: (ref, question) => {
|
|
168
|
+
const target = question.peer;
|
|
169
|
+
const entry = table.get(ref.id);
|
|
170
|
+
if (entry === undefined)
|
|
171
|
+
return refuse(target, "handle_not_held");
|
|
172
|
+
if (!sameBinding(entry.binding, bindingOf(target)))
|
|
173
|
+
return refuse(target, "binding_mismatch");
|
|
174
|
+
return carry(entry);
|
|
175
|
+
},
|
|
176
|
+
hold: (ref) => {
|
|
177
|
+
const id = ref.id;
|
|
178
|
+
if (id === undefined)
|
|
179
|
+
return notMintedHold();
|
|
180
|
+
const entry = table.get(id);
|
|
181
|
+
if (entry === undefined)
|
|
182
|
+
throw new Error("peer desk: hold of a handle whose entry is gone — not held (a hold never revives an entry)");
|
|
183
|
+
entry.engineHolds += 1;
|
|
184
|
+
},
|
|
185
|
+
release: (ref) => {
|
|
186
|
+
const id = ref.id;
|
|
187
|
+
if (id === undefined)
|
|
188
|
+
return notMintedRelease();
|
|
189
|
+
const entry = table.get(id);
|
|
190
|
+
if (entry === undefined || entry.engineHolds === 0)
|
|
191
|
+
throw new Error("peer desk: release of a handle with no counted engine hold — nothing released");
|
|
192
|
+
entry.engineHolds -= 1;
|
|
193
|
+
dropIfUnheld(id, entry);
|
|
194
|
+
},
|
|
188
195
|
},
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
return carry(entry);
|
|
202
|
-
}
|
|
203
|
-
case "env":
|
|
204
|
-
return refuse(target, "kind_env");
|
|
205
|
-
case "vault":
|
|
206
|
-
return refuse(target, "kind_vault");
|
|
207
|
-
case "assertion":
|
|
208
|
-
return refuse(target, "kind_assertion");
|
|
209
|
-
default: {
|
|
210
|
-
const unknownKind = ref;
|
|
211
|
-
void unknownKind;
|
|
212
|
-
return refuse(target, "kind_unknown");
|
|
213
|
-
}
|
|
214
|
-
}
|
|
196
|
+
env: notMinted("kind_env"),
|
|
197
|
+
vault: notMinted("kind_vault"),
|
|
198
|
+
assertion: notMinted("kind_assertion"),
|
|
199
|
+
};
|
|
200
|
+
const unknownKind = notMinted("kind_unknown");
|
|
201
|
+
const rowOf = (ref) => (Object.hasOwn(seatKinds, ref.kind) ? seatKinds[ref.kind] : unknownKind);
|
|
202
|
+
const seat = Object.freeze({
|
|
203
|
+
hold: (ref) => rowOf(ref).hold(ref),
|
|
204
|
+
release: (ref) => rowOf(ref).release(ref),
|
|
205
|
+
answer: async (question, signal) => {
|
|
206
|
+
const ref = question.peer.credentials;
|
|
207
|
+
return ref === undefined ? { kind: "carry" } : rowOf(ref).answer(ref, question, signal);
|
|
215
208
|
},
|
|
216
209
|
});
|
|
217
210
|
return Object.freeze({
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The execution seam's path law — ONE reading for every execution environment this server mints (the seven lanes: adb / device / e2b /
|
|
3
|
+
* host / k8s / local-docker / ssh) and for the sandbox write gate's stand-in environment (`boot/deferred-sandbox-path-env.ts`).
|
|
4
|
+
*
|
|
5
|
+
* The law (the engine's, `ExecutionEnv` contract; the engine's own `NodeExecutionEnv` reads every path this way): a path a method is
|
|
6
|
+
* handed is ABSOLUTE AS WRITTEN, or relative and ANCHORED at the environment's working directory with exactly one separator. Nothing here
|
|
7
|
+
* folds a `..` or a `.` and nothing resolves a link: the filesystem the path lands on resolves them, components first — so a `..` that
|
|
8
|
+
* follows a symbolic link goes where the link leads (`<base>/bridge/../next` with `bridge -> elsewhere/sub` names `<base>/elsewhere/next`).
|
|
9
|
+
* A lexical fold would name `<base>/next` instead: the write gate (which asks the real filesystem what the spelling names) and the tool
|
|
10
|
+
* (which opened the folded name) would then judge and touch two different files.
|
|
11
|
+
*
|
|
12
|
+
* Three faces, one anchor ({@link anchorUnder}): the path a method reads ({@link anchoredPath}), `joinPath` ({@link joinedPath}) and the
|
|
13
|
+
* paths a listing reports (each entry anchored under the path the listing was handed). The remote lanes' shell scripts (the link-chain walk
|
|
14
|
+
* and the staged write, `remote-shell.ts`) already anchor this way in shell; this module is the same law for the TypeScript faces.
|
|
15
|
+
*
|
|
16
|
+
* Pure leaf: string arithmetic only, no I/O.
|
|
17
|
+
*/
|
|
18
|
+
import type { PlatformPath } from "node:path";
|
|
19
|
+
/**
|
|
20
|
+
* The two facts of a path family the law reads: its separator and its absolute-path judge. The remote lanes read POSIX whatever the
|
|
21
|
+
* worker runs on (`path.posix`; the device lane passes its one absolute-path judge, `isDeviceAbsolutePath`); the host lane reads the
|
|
22
|
+
* worker's own (`path`).
|
|
23
|
+
*/
|
|
24
|
+
export type SeamPathFamily = Pick<PlatformPath, "sep" | "isAbsolute">;
|
|
25
|
+
/** `name` placed under `dir` with exactly one separator — never folded, never re-rooted. */
|
|
26
|
+
export declare function anchorUnder(family: SeamPathFamily, dir: string, name: string): string;
|
|
27
|
+
/** The path a method is handed, as the environment reads it: absolute ⇒ as written; relative ⇒ anchored at `cwd`. */
|
|
28
|
+
export declare function anchoredPath(family: SeamPathFamily, cwd: string, p: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* `joinPath`: the first part as written; every later part is a segment, never a root (its leading separators are dropped); empty parts
|
|
31
|
+
* are dropped; the rest anchored in turn. No parts ⇒ `"."`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function joinedPath(family: SeamPathFamily, parts: readonly string[]): string;
|
|
34
|
+
//# sourceMappingURL=exec-path-law.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function anchorUnder(family, dir, name) {
|
|
2
|
+
const endsInSeparator = dir.endsWith(family.sep) || (family.sep === "\\" && dir.endsWith("/"));
|
|
3
|
+
return endsInSeparator ? `${dir}${name}` : `${dir}${family.sep}${name}`;
|
|
4
|
+
}
|
|
5
|
+
export function anchoredPath(family, cwd, p) {
|
|
6
|
+
return family.isAbsolute(p) ? p : anchorUnder(family, cwd, p);
|
|
7
|
+
}
|
|
8
|
+
export function joinedPath(family, parts) {
|
|
9
|
+
const leading = family.sep === "\\" ? /^[\\/]+/ : /^\/+/;
|
|
10
|
+
const named = parts.map((part, i) => (i === 0 ? part : part.replace(leading, ""))).filter((part) => part !== "");
|
|
11
|
+
return named.length === 0 ? "." : named.reduce((at, part) => anchorUnder(family, at, part));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=exec-path-law.js.map
|
|
@@ -652,7 +652,7 @@ export class FileRunStore {
|
|
|
652
652
|
if (this.active.get(sessionId) !== taskId || r === undefined || r.status !== "running")
|
|
653
653
|
return false;
|
|
654
654
|
this.persist({ ...r, updatedAt: new Date() });
|
|
655
|
-
write({ instanceId: r.instanceId });
|
|
655
|
+
write({ instanceId: r.instanceId, legId: r.legId });
|
|
656
656
|
return true;
|
|
657
657
|
}
|
|
658
658
|
async getRun(taskId) {
|
|
@@ -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";
|
|
@@ -118,6 +118,9 @@ export declare class LocalCheckpointStore {
|
|
|
118
118
|
expire(token: CheckpointToken, scope: string): Promise<boolean>;
|
|
119
119
|
reap(scope: string, cutoff: number): Promise<number>;
|
|
120
120
|
listByScope(scope: string): Promise<CheckpointSummary[]>;
|
|
121
|
+
/** core `CheckpointStore.listBySession`(可选动词,按在不在探):纯委派给内核 —— 读法是 core 的 `selectSessionPage`(SQL 孪生把「这只会话的行」交给同一只);
|
|
122
|
+
* 内核读的是它自己的全部行(任何状态),坏行由内核按行答 `unreadable`、经数据根那只披露座说。包装层不另判、不另列。 */
|
|
123
|
+
listBySession(query: CheckpointSessionQuery): Promise<CheckpointPage<CheckpointRowRead, CheckpointSessionCursor>>;
|
|
121
124
|
close(): void;
|
|
122
125
|
/** C4-B:注册表损坏时从**数据本体**懒重建 scope 集(core 1.424 `listScopes?` = 「有 ≥1 条 pending 的
|
|
123
126
|
* distinct scope 集」,与 listByScope 可见面对齐 —— 恰好是本注册表要的内容)。一次性:重建后回写
|
|
@@ -302,7 +302,7 @@ export class MemoryRunStore {
|
|
|
302
302
|
if (this.active.get(sessionId) !== taskId || r === undefined || r.status !== "running")
|
|
303
303
|
return false;
|
|
304
304
|
r.updatedAt = new Date();
|
|
305
|
-
write({ instanceId: r.instanceId });
|
|
305
|
+
write({ instanceId: r.instanceId, legId: r.legId });
|
|
306
306
|
return true;
|
|
307
307
|
}
|
|
308
308
|
async getRun(taskId) {
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
* **≥** 某条未发布形的 `introducedIn` 而两格仍是 `null` ⇒ 红(发布准备提交就是回填时刻,忘了就当场红;版本更低 = 还在开发,不红)。
|
|
13
13
|
* 最后一条删掉时,整个文件连同 `StoreBackend.runOneTimeMigrations()`(npm 公面上的接口成员)、`NO_SQL_MIGRATIONS`、
|
|
14
14
|
* `logOneTimeMigrations` / `runAndLogOneTimeMigrations`、三只后端与两只测试夹具上的实现、`boot/stores.ts` 的调用点一起删 —— 零例外:本文件里只有带窗的迁移与它们自己的
|
|
15
|
-
* 帮手(两只在场探针、锁腿、方言适配器)
|
|
15
|
+
* 帮手(两只在场探针、锁腿、方言适配器)与迁移段的**段头**两步(副本能力登记、起服准入 —— 常设,码在 `replica-registration.ts` / `serving-requirement.ts`,本文件只在 {@link runSqlOneTimeMigrations}
|
|
16
|
+
* 里排它们的序;最后一条迁移删码时,段头连同锁腿搬进起服序列,不随文件删);没有窗的东西(跳版升级的库的拒启臂)住在起服对账一族(`schema-consistency.ts`、`approval-exemption-skill-cutoff.ts`、local 的
|
|
16
17
|
* `local-data-root-admission.ts`),不在这里 —— 那条迁移还在时臂只判、不拒,读本文件的 {@link migrationCarried}(行随码同删 ⇒ 删码那一版起臂恒判)。
|
|
17
18
|
* 其余文件一律只写「窗口见本文件登记表」,不各写一个日期或版本 —— [ref] 之前本文件头写死了一个删除版本号(7.75.0),
|
|
18
19
|
* 连同 11 个文件里的复述共 23 行;那一版过去了 28 个 minor 也没删,7.93.5 反倒往本文件里又加了一条迁移。
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
* ⇒ 换成本段:**升一次级把存量字节改完,兼容臂当场删干净**。代价是每一条在它的窗内每次启动都要跑一遍(第二次起全是
|
|
26
27
|
* 零命中的空转);收益是窗关之后可以把那一条连同它的 SQL 一起删,而读腿从引入那一版起就只有**一种**读法。
|
|
27
28
|
*
|
|
28
|
-
* ## 已退役的 M1–
|
|
29
|
+
* ## 已退役的 M1–M12 与 M14
|
|
29
30
|
* 退役的整树快照索引表(M1)、退役的单座 steering 列(M2)、被上游改了名的闭集词 `unresolvable` → `ancestor_marked`(M3)三条的改写、计数与读数
|
|
30
31
|
* 窗关后已全部删码,登记行一并删。跳过了它们直接升的库由起服对账一族的拒启臂接住(`schema-consistency.ts` 头注「第二道对账」一节:两件退役 schema
|
|
31
32
|
* 任一在场 ⇒ 拒启、点名出路;先于一切建表)—— 那一道没有窗,所以不在本文件里。本段入口({@link runSqlOneTimeMigrations})不问这一问。
|
|
@@ -64,12 +65,13 @@
|
|
|
64
65
|
* 那一行不参与任何检查,但撤销口删不动它(引擎的写臂对这种 scope 同样拒)。出路 = 运维在库里把那只桶的那一行删掉(整桶 OCC 回写,指纹按 `buildRuleBucketChecksum` 重算)。
|
|
65
66
|
* 起服不再逐桶扫描、也不再有逐行 / 逐桶的删除告警;读腿整桶拒的桶照旧整桶拒(出路是人)。local 车道的持久规则在引擎自己的 File 分区里,这一半对它本来就是空转。
|
|
66
67
|
*
|
|
68
|
+
* M12(停驻行模式词读法记号的拒臂;不写库;7.150.0 删,窗 2026-11-08 关,发版日前已关)同样已删码,登记行一并删:判据、拒臂与答复、两处记号写点与 ctx 上的记号位都没有了,续跑重放不再问「行上有没有记号」。逐条写跳过了它直接升的库由谁接住:
|
|
69
|
+
* ⑦ 停驻行模式词读法记号的拒臂(M12):没有响亮臂 —— 7.121.x 及以前写下、此刻仍停驻的行(把 `APPROVAL_TERMINAL_BACKSTOP_MS` 调长的部署,或跳过了带本条的版本直接升的库)体里是请求原词、没有记号;
|
|
70
|
+
* 在设了 `AUTONOMY=plan` 的部署上不再被拒,续跑按体里的原词重放(运维的 plan 不再被按段重钳;`plan_review` 的驳回仍由引擎留在 plan)。存量行上的那只记号键原样留着、无人读。出路 = 升级前把这些停驻的 run 决掉 / 取消,
|
|
71
|
+
* 或升级窗内设 `AUTONOMY=read-only`(按段的只读围栏)。
|
|
72
|
+
*
|
|
67
73
|
* ## 窗内的迁移(逐条的失败方向刻意不同)
|
|
68
|
-
* · **
|
|
69
|
-
* 一个源(提交入口盖运维 `AUTONOMY=plan` 的地板一次),更早的行体里是请求原词、运维的 plan 由治理层每段重钳。续跑重放之前:本部署此刻有入口地板 ∧
|
|
70
|
-
* ctx 上没有当前记号 `"entry_word"` ∧ 体的生效词被地板钳会变 ⇒ 认领之前 409、行字节不动。规则、拒句与写点在 `http/checkpoint-ctx.ts` 顶注第三问。
|
|
71
|
-
* 没有读数键(它不写库)。
|
|
72
|
-
* · **M13 盘上 LKG 信封 formatVersion 2 → 3**(7.123.0)—— 不在店里(配置候选的盘上缓存,与 M12 同为非店迁移):被丢目录条目收成一份载体
|
|
74
|
+
* · **M13 盘上 LKG 信封 formatVersion 2 → 3**(7.123.0)—— 不在店里(配置候选的盘上缓存):被丢目录条目收成一份载体
|
|
73
75
|
* (`models.droppedCatalogEntries`,每条被丢的目录条目一行),7.122.0 及以前写的 2 只记了有名且启用的行、记在旧键 `droppedIdentities`。
|
|
74
76
|
* `config-lkg.ts` `loadLkg` 读回 2 时在内存里迁一次(旧载体搬成新载体、去掉 etag ⇒ 中心可达后第一拍整拉、重铸完整载体),启动日志
|
|
75
77
|
* `config_lkg_migrated` 一行;写盘一律写 3。规则与判形在 `config-lkg.ts` 顶注与 `migrateV2Lkg`。没有读数键(它不写库)。
|
|
@@ -356,7 +358,7 @@
|
|
|
356
358
|
* `approval_ask.execution_lane` 与会话的 `execution_lane`(`session_meta` 上;M41 搬过之后在 `session_ext` 上 —— 三张表逐张读形,列在哪张改哪张)(本段**第一步**,先于任何写:列不在 ⇒ 那一张零动作 —— 跳版升上来的库由 M32 加列、按声明车道回填,不会再铸旧词);
|
|
357
359
|
* local 的会话元数据边档(`session-incarnations.json` 的 `[会话].execution.lane`,**排在严格边档对账之前** —— `LocalBackend.ensureSchema()` 第一步,否则旧词先撞严格拒)
|
|
358
360
|
* 与问账日志(排在 M32 的 local 问回填之前,一次压实重写整本)。**版本围栏(停-迁-起)**:旧副本不认 `none`、新读者不认旧词,列形不变 ⇒ 混跑没有列检查拦得住。
|
|
359
|
-
* SQL:还有旧词行要改 ∧
|
|
361
|
+
* SQL:还有旧词行要改 ∧ 有停-迁-起证据(`readOlderReplicaEvidence`:`task_run` 的 `running` 行在 `REAP_RUN_STALE_SEC` 之内更新过 —— 收割器判活的同一条谓词 —— 且持有者没有登记为知道 M40)⇒ 拒启
|
|
360
362
|
* (`config.execution_lane_rename_refused`,一行没改;拒句给最新心跳时刻与「全停之后何时再起」);没有旧词行 ⇒ 零动作、可滚动。local:数据根的起服锁(core `FileStorageBackend` 的 `LOCK`)
|
|
361
363
|
* 本来就只许一个进程 ⇒ 不另设守卫。读数 `executionLaneWordsRenamed`(四处合计)。幂等:第二次起服零命中零写。
|
|
362
364
|
* · **M41 会话的部署格搬出引擎座表**(7.147.0)—— 引擎座表 `session_meta` 只带引擎的列;本服务记在会话上的十二格(标题 / 置顶 / 换源通告基线 / 位置与项目 / 执行放置七列 / fork 键)
|
|
@@ -365,7 +367,8 @@
|
|
|
365
367
|
* (`ON DUPLICATE KEY UPDATE` / `ON CONFLICT DO UPDATE`:旁表那一行的这几格 = 根行上的值;中断后重跑同一句同一结果);② 逐行核对(每一列 null 安全相等,旁表行不在 = 缺省)——
|
|
366
368
|
* 有一行不等 ⇒ 拒启 `config.session_ext_move_refused`(`copy_mismatch`,点名那只会话;一列没删,下一次起服重搬);③ **一句** `ALTER TABLE session_meta DROP COLUMN …` 删掉在场的全部部署格列
|
|
367
369
|
* (按后置条件收敛:那几列都不在)。旁表形的库(本版新建、或已搬过)⇒ 零动作。**版本围栏(停-迁-起)**:旧副本对这十二格的每一笔写在删列之后都撞未知列,
|
|
368
|
-
* 搬与删之间落下的写会丢 ⇒ 还有列要搬 ∧
|
|
370
|
+
* 搬与删之间落下的写会丢 ⇒ 还有列要搬 ∧ 有停-迁-起证据(与 M40 同一只读法)⇒ 拒启(`older_replica`,一字节没写;本段第二步,紧随 M40,先于任何别的写)。
|
|
371
|
+
* 如实的边(7.147.0 起已披露,不改):① 搬 → ② 核对 → ③ 删列三步之间一只没被看见的旧副本落下的写会丢 —— 删列让旧写在 ③ 之后响亮失败,却挡不住 ② 与 ③ 之间那一笔。
|
|
369
372
|
* **M32 × M41 的序与读表**:迁移段里 M32 先、M41 后。M32 读两种形 —— 八列在 `session_meta` 上(7.139–7.146 形:M32 全程写根行,随后 M41 连同别的格一起搬进旁表)
|
|
370
373
|
* 或部署格已在旁表(本条之后 / 新库)。旁表形里 M32 的加列 / 回填 / 收尾标记(② ④ ④b ⑥)都不跑(切换早已收尾;回填前提的拒随之不判),剩 ⓪(旧版副本建回的空退役表删掉)、围栏,
|
|
371
374
|
* 与围栏拒句「采旧」造出的中途表 ③ ⑤ —— ③ 写执行格当下的家(旁表:先补行、再覆盖,`migrateDeviceBindingsOntoSideTableStatements`)。删码不改语义:本条删码时 M32 若还在,改成恒旁表形(见登记行)。
|
|
@@ -373,19 +376,19 @@
|
|
|
373
376
|
* · **M42 场景前缀的切换检查**(7.148.0)—— 本版起以 `_scn:` 开头的身份读作「某个人的某个场景」(恢复管线 `owner-brands.ts` 的 `partsOf`);更早的版本不保留这一前缀,
|
|
374
377
|
* 自称 `_scn:<x>:<y>` 的调用方写下的行在本版会被读成另一个人的场景。**持久数据「响亮拒」那一半,不改写**:库里没有本条的标记 ⇒ 只读扫存量身份(本树建表句里名字以
|
|
375
378
|
* owner / scope / principal / subject 结尾、且库里在的每一列;local = run / 会话 / 问 / 附件四处 File 店的属主),一处命中 ⇒ 拒启 `config.scenario_prefix_switch_refused`(点名来源与行数,
|
|
376
|
-
* 一字节没写);零命中 ⇒ 写标记;有标记 ⇒ 不扫(本版自己写下的合法 `_scn:` 行不让第二次起服拒启)。**停-迁-起(SQL)
|
|
377
|
-
*
|
|
379
|
+
* 一字节没写);零命中 ⇒ 写标记;有标记 ⇒ 不扫(本版自己写下的合法 `_scn:` 行不让第二次起服拒启)。**停-迁-起(SQL)**:零命中而有停-迁-起证据(与 M40 / M41 同一只
|
|
380
|
+
* 读法)⇒ 同码拒启(`older_replica`),标记不写 —— 更早版本的副本不保留前缀,扫描之后它还会收下这类身份。标记随库(SQL:本条自己建的标记表一行;local:数据根里一只文件),
|
|
378
381
|
* 不随进程。**第一步**:先于任何写(拒了就是一字节没动)。律、扫描面、拒句的唯一属主 = `scenario-prefix-switch-m42.ts`。读数 `scenarioPrefixSourcesScanned`(0 = 标记在场)。
|
|
379
382
|
* · **M43 撤回出口的启用标记**(7.148.0)—— 不改任何存量行。提交出口撤回一只「受理之前就被拒」的提交铸下的会话之前,读旁表的客户端写计数 `client_writes`
|
|
380
383
|
* (四个客户端写者在锁住根行之后同一事务 +1,`plugins/session-ext-table.ts`);更早版本的副本的写者不计数 ⇒ 混跑窗里它刚给这只会话改了标题,撤回却读到 0,会把人写过的会话删掉。
|
|
381
384
|
* ⇒ 撤回出口只在本库的**标记行**落下之后启用(标记表与 M42 同一张,属主 `one-time-migration-marker.ts`;读者 = 撤回事务里的部署判据 `plugins/session-withdraw-sql.ts`,标记未落 ⇒ 答 `upgrade_pending` = 留,
|
|
382
|
-
* 幽灵会话照旧)。标记由本步落:标记不在 ∧
|
|
385
|
+
* 幽灵会话照旧)。标记由本步落:标记不在 ∧ 没有停-迁-起证据(与 M40 同一只读法;登记为知道 M43 的副本持有的 run 不算)⇒ 落;有 ⇒ 不落、**不拒启**,下一次起服再判(M42 的停-迁-起守卫在同一版里先拒过一次)。
|
|
383
386
|
* 读数 `withdrawMarkWritten`。local 车道:数据根独占、没有混跑窗,版本位在会话元数据格上(`clientWrites`,本版铸的格都带),恒零。
|
|
384
387
|
* · **M51 会话在删态的切换**(7.148.0)—— 不改任何存量行。本版起删会话按会话三态走(活 → 在删 → 没了,律在 `src/session-deletion.ts`):围栏写旁表 `session_ext.deleting_token`,
|
|
385
388
|
* 认领点(规则 L)读它、删除路只在围栏判一次认领。更早版本的副本不读在删态 ⇒ 混跑时它会在一只在删的会话上收下提交、建 run,而本版删除路的账本腿已不再判认领 ——
|
|
386
|
-
* 比修前更坏。⇒ **停-迁-起**,没有运行期开关:标记表(与 M42 同一张)无 `M51` 行 ∧
|
|
387
|
-
* ⇒ 拒启 `config.session_deleting_switch_refused`(`
|
|
388
|
-
* 看不见的边与 M43
|
|
389
|
+
* 比修前更坏。⇒ **停-迁-起**,没有运行期开关:标记表(与 M42 同一张)无 `M51` 行 ∧ 有停-迁-起证据(与 M40 / M41 / M42 同一只读法 {@link readOlderReplicaEvidence})
|
|
390
|
+
* ⇒ 拒启 `config.session_deleting_switch_refused`(`older_replica`,一字节不写,拒句给可再起的时刻);没有 ⇒ 落标记(之后不再判)。
|
|
391
|
+
* 看不见的边与 M43 同:空闲的、早于副本登记的旧副本(零 `running` run)没有证据 —— MIGRATION 写「全部旧副本停下再起」。读数 `sessionDeletingSwitchMarked`(0 或 1)。
|
|
389
392
|
* local 车道:数据根独占、没有混跑窗 ⇒ 恒零。
|
|
390
393
|
* · **M44 run 的 `errorCode` 只读列**(7.148.0)—— 码的唯一读法是 `task_run.error_code` 列;写 `result` 的三个写口同写这一列(停驻两口此前不写)。**改写半场**:
|
|
391
394
|
* 按 `task_id` 键集分批扫 `result IS NOT NULL` 的行,目标 = 「这条行在稳定、非到期时修前 `GET` 会答的码」= 结果投影的码(`persistedPlaneOf`,读盘面认两代形并折码)?? 列原值;
|
|
@@ -446,6 +449,11 @@
|
|
|
446
449
|
* (删 `taskId` 名下的问与批 —— 今天删会话级联的一个子集,语义不丢,`InMemoryApprovalAskStore.deleteByTaskM50`)并算删行记录,构造器末段的起服压实把整本重写成存活行的快照、记录离盘
|
|
447
450
|
* (压实失败 ⇒ 位留着,下一次写或下一次窗内起服再压;重放幂等),恰一行 stderr 点名条数与账本;窗关之后 ⇒ 同一条记录拒启(`StoreBootRefusalError`,拒因点名本条、
|
|
448
451
|
* 窗的最后一天与出路:用早于本条的版本起服一次 —— 它认得这只词,起服即压实删行记录),删码因此是零行为变化。没有起服读数键(它不经迁移段跑,读数是那一行 stderr)。只 local(SQL 两方言从来没有这只词)。
|
|
452
|
+
* · **M52 停-迁-起证据的心跳一半**(7.150.0)—— 不改库。停-迁-起守卫(M40 · M41 · M42 · M51)与 M43 的标记判「库上还有不知道这条迁移的副本在服务吗」只经一只读法
|
|
453
|
+
* `readOlderReplicaEvidence`:判活窗内心跳过的 `running` run,按持有者分组,减去登记为知道这条迁移的持有者(副本能力登记 `replica-registration.ts`,常设;本版起每只进程在
|
|
454
|
+
* 迁移段头登记一行)。早于副本登记的副本不登记,只经它们持有的 run 心跳可见 —— 这一半(与它的判活窗输入 `liveRunWindowMs`)就是本行,窗内才在;
|
|
455
|
+
* 登记一半本版**不判活**,只作归因(点名持有者)。看不见的边如实:空闲的、早于副本登记的副本没有任何证据(终局边界,运维停光旧副本是第一道);
|
|
456
|
+
* 登记行不续期、不观察,**不是围栏**。没有读数键(它不写库)。local 车道:数据根独占 ⇒ 守卫没有判活腿,恒不读。
|
|
449
457
|
*
|
|
450
458
|
* ## 收据账(一次起服一只,每一条迁移同一只)
|
|
451
459
|
* 每一步把它**已提交**的改写 / 删除与点名读数当场记进同一只收据账({@link MigrationReceipts}):计数随每次提交累加、行随每次提交追加、形读数在那一步落定时写。走完 ⇒
|
|
@@ -471,6 +479,8 @@ import type { ExecutionLane } from "../execution-lane-caps.js";
|
|
|
471
479
|
import { type ImportedLayerRootAllowRetired, type ImportedLayerRootBucketSkipped, type ImportedLayerRootRetirementSource } from "./imported-layer-root-retirement.js";
|
|
472
480
|
import { type LocalPlacementBackfillSeat, type UnusableArchiveWord } from "../execution-placement.js";
|
|
473
481
|
import type { PendingShapeChange } from "./schema-consistency.js";
|
|
482
|
+
import { type OlderReplicaEvidence } from "./stop-then-start-sentence.js";
|
|
483
|
+
import { type ReplicaCapability, type ReplicaRegistration } from "./replica-registration.js";
|
|
474
484
|
/** 迁移读数(启动日志一行写全;测试按它断言,不靠日志文本)。 */
|
|
475
485
|
export interface OneTimeMigrationReport {
|
|
476
486
|
/** M17:`session_policy` 装规则的那一列 —— `renamed` = 本次把 `rules` 改名成 `rule_entries`;`current` = 早已是新名(新库 / 第二跑);
|
|
@@ -693,7 +703,7 @@ export declare class OneTimeMigrationInterruptedError extends Error {
|
|
|
693
703
|
* 规则(窗长 30 天、窗关后的第一个 minor 删码、门怎么判)在本文件头注「窗」一节,只写那一次。
|
|
694
704
|
*/
|
|
695
705
|
export interface OneTimeMigrationWindow {
|
|
696
|
-
/** 本文件里的条目名(头注「窗内的迁移」的
|
|
706
|
+
/** 本文件里的条目名(头注「窗内的迁移」的 M13…)。 */
|
|
697
707
|
readonly id: string;
|
|
698
708
|
/** 引入这条迁移的版本 = 第一只含其代码的发布 tag(取证:`git log -S '<该条的常量名>' -- src/plugins/one-time-migrations.ts`
|
|
699
709
|
* 找引入提交 → `git tag --contains <提交> --sort=creatordate` 取最早)。 */
|
|
@@ -719,11 +729,22 @@ export interface OneTimeMigrationWindow {
|
|
|
719
729
|
*/
|
|
720
730
|
readonly shapeChanges?: readonly PendingShapeChange[];
|
|
721
731
|
/**
|
|
722
|
-
*
|
|
723
|
-
*
|
|
732
|
+
* 本条是**停-迁-起**迁移:起服时的守卫在有停-迁-起证据时拒启、一字节不写(动作段的唯一属主 = `stop-then-start-sentence.ts`)。两格见 {@link StopThenStartRow}:
|
|
733
|
+
* 缘由句与「这只库还欠不欠本条」的唯一读法 —— 起服列册对账的升级清单(`schema-consistency.ts` 的 `describeUpgradeChecklist`)只列这只库还欠的行、把缘由句原样列给运维,
|
|
724
734
|
* 于是「本构建有哪几条要先停光旧副本」只有这一处在写、随行删码一起没。读者 = {@link stopThenStartMigrations}。
|
|
725
735
|
*/
|
|
726
|
-
readonly stopThenStart?:
|
|
736
|
+
readonly stopThenStart?: StopThenStartRow;
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* 一条停-迁-起迁移的登记格(一句话 + 一只只读判据的引用;登记表里只写引用,判据的码在本条的迁移步旁边):
|
|
740
|
+
* · `reason` —— 一句英文:更早版本的副本在迁移之后还会写什么、写了会怎样(升级清单原样列给运维);
|
|
741
|
+
* · `owedOn` —— **这只库还欠不欠本条**的唯一读法(只读,一字节不写):本条的守卫先问它(不欠 ⇒ 零动作、不读证据),升级清单第 2 步只列它答「欠」的行 ——
|
|
742
|
+
* 清单不另判(修前清单按登记表全列、不判欠不欠,对走过这几条的库说「不可滚动」,与守卫的放行是一事两说)。读口是列册对账同一只无参读口
|
|
743
|
+
* {@link SchemaProbeRead}:判据的语句只内联本文件的常量(标记键 / 退役词 / 表名列名,与 `tableExists` / `columnExists` 同形),不带参数。
|
|
744
|
+
*/
|
|
745
|
+
export interface StopThenStartRow {
|
|
746
|
+
readonly reason: string;
|
|
747
|
+
readonly owedOn: (read: SchemaProbeRead, dialect: SqlDialect) => Promise<boolean>;
|
|
727
748
|
}
|
|
728
749
|
/**
|
|
729
750
|
* 🔴 [ref] —— 一次性迁移登记表,本文件各条的窗的**唯一属主**。别处(接口 JSDoc、调用点、DDL 注、部署文档)只写「窗口见
|
|
@@ -749,13 +770,12 @@ export declare function migrationWindowEnd(id: string): string;
|
|
|
749
770
|
*/
|
|
750
771
|
export declare function migrationCarried(id: string): boolean;
|
|
751
772
|
/**
|
|
752
|
-
* 本构建带的**停-迁-起**迁移(登记行的 `stopThenStart` 一格;行在 ⇔ 码在 ⇒ 起服会在这一条上判活)
|
|
753
|
-
*
|
|
773
|
+
* 本构建带的**停-迁-起**迁移(登记行的 `stopThenStart` 一格;行在 ⇔ 码在 ⇒ 起服会在这一条上判活),按登记表顺序。读者 = 起服列册对账的升级清单:
|
|
774
|
+
* 逐行问 `owedOn`,只把这只库还欠的列给运维。登记表里再没有这样的行时返回空数组 —— 清单的这一步随之不出。
|
|
754
775
|
*/
|
|
755
|
-
export declare function stopThenStartMigrations(registry?: readonly Pick<OneTimeMigrationWindow, "id" | "stopThenStart">[]): readonly {
|
|
776
|
+
export declare function stopThenStartMigrations(registry?: readonly Pick<OneTimeMigrationWindow, "id" | "stopThenStart">[]): readonly ({
|
|
756
777
|
readonly id: string;
|
|
757
|
-
|
|
758
|
-
}[];
|
|
778
|
+
} & StopThenStartRow)[];
|
|
759
779
|
/** local 车道上 SQL 独有的几条(M17 / M18 / M21 / M23 / M24 / M26 / M27 / M29)的读数(M32 的回填两车道都有、M33 只在 local,local 腿的读数由 `LocalBackend.runOneTimeMigrations` 现算):那几张表 / 列在文件底座上从来不存在 ⇒ 如实答 absent / 0。 */
|
|
760
780
|
export declare const NO_SQL_MIGRATIONS: Omit<OneTimeMigrationReport, "runErrorCodeColumnRewritten" | "runObjectivePreviewRewritten" | "shellSentinelOwnersCleared" | "shellSentinelOwnerRowsRetained" | "checkpointHostSessionsBackfilled" | "legacySkillExemptionsDropped" | "executionPlacementsBackfilled" | "askExecutionLanesBackfilled" | "executionLaneWordsRenamed" | "scenarioPrefixSourcesScanned" | "executionPlacementSessionsUnreadable" | "localArchiveRowFactsBackfilled" | "localArchivesAnonymized" | "localArchivesKeptStamped" | "localArchivesUnreadable" | "localArchiveSnapshotsRecovered" | "localArchiveTokensAdopted" | "localArchiveTokensMinted" | "askJournalRecordsUpgraded" | "importedLayerRootAllowsRetired" | "importedLayerRootBucketsSkipped" | "importedLayerRootBucketsUnnamed">;
|
|
761
781
|
/** 启动期的日志口(logger 的子集)。两级各有其用,见 {@link logOneTimeMigrations}。 */
|
|
@@ -795,7 +815,12 @@ export interface MigrationDb {
|
|
|
795
815
|
* 判官不在两处各写一份。
|
|
796
816
|
*/
|
|
797
817
|
export declare function createSqlImportedLayerRootSource(exec: Parameters<typeof listRuleBucketOwners>[0]): ImportedLayerRootRetirementSource;
|
|
798
|
-
|
|
818
|
+
/**
|
|
819
|
+
* **段头**(常设两步,不带窗;只在这里排序;与迁移步同一条连接):两张表在(不在 ⇒ 拒,点名公开序列)→ 本进程登记(`replica-registration.ts`)→ 起服准入**锁外预读**(`serving-requirement.ts`)
|
|
820
|
+
* → 取迁移锁 → **锁内复核**(同一判据;本进程等锁期间握锁的那一只写下的要求在这里读得到)→ 各迁移步。准入拒 ⇒ 一步迁移都不跑。
|
|
821
|
+
* 登记在任何守卫读证据之前、本进程能持有任何 run 之前落下;跳过 `ensureSchema()` 的嵌入方走同一段。`me` 缺省 = 本进程的登记行;真库钉传别的构建(能力名单不同的起服者)。
|
|
822
|
+
*/
|
|
823
|
+
export declare function runSqlOneTimeMigrations(dialect: SqlDialect, pool: MysqlPool | PgPool, input: SqlOneTimeMigrationInput, me?: ReplicaRegistration): Promise<OneTimeMigrationReport>;
|
|
799
824
|
/** M48 的那一步(见头注 M48 段):输入显式说「没有身份边界」⇒ 改写 —— 改写面里的每张表一句按值的 `UPDATE`(表不在 ⇒ 跳过);写后不再有哨兵值 ⇒ 第二跑零命中。
|
|
800
825
|
* 其余一切(有身份边界,或绕过类型缺这一格 / 不是布尔 ⇒ fail-closed,不静默放宽)零改写,但对同一批表用**同一句 WHERE**({@link shellSentinelOwnerWhereM48})数一遍留着的行,
|
|
801
826
|
* 非零的面记进 `shellSentinelOwnerRowsRetained`(起服日志一行 warn;见头注)。值**逐字节**比的理由在 {@link shellSentinelOwnerWhereM48}。 */
|
|
@@ -815,12 +840,12 @@ export declare function dropLegacySkillExemptionsM46(db: MigrationDb, dialect: S
|
|
|
815
840
|
export declare const SESSION_DELETING_MARK_ID = "M51";
|
|
816
841
|
/** M51 起服拒的机读码(确定的拒启表态:全停之后再起才有另一个答案)。 */
|
|
817
842
|
export declare const SESSION_DELETING_SWITCH_REFUSED_CODE = "config.session_deleting_switch_refused";
|
|
818
|
-
/** M51
|
|
843
|
+
/** M51 起服拒:标记还没落,而有停-迁-起证据(拒因闭集只有 `older_replica`)。 */
|
|
819
844
|
export declare class SessionDeletingSwitchRefusedError extends StoreBootRefusalError {
|
|
820
845
|
readonly code = "config.session_deleting_switch_refused";
|
|
821
|
-
readonly reason: "
|
|
846
|
+
readonly reason: "older_replica";
|
|
822
847
|
/** `tail` = 库此刻还差的列(`describeUpgradeDriftTail`;列齐 ⇒ 空串):一次起服读全,不必补一句再试。 */
|
|
823
|
-
constructor(
|
|
848
|
+
constructor(evidence: OlderReplicaEvidence, tail?: string);
|
|
824
849
|
}
|
|
825
850
|
/**
|
|
826
851
|
* M42 的扫描面:本树建表句(两方言各自的录制,与起服列册对账同一份)里名字合 {@link IDENTITY_COLUMN_NAME}、类型是字符 / 字节串的列,与库里实际在的列取交(条件建的表不在库里 ⇒ 不扫)。
|
|
@@ -832,12 +857,12 @@ export declare function scannedIdentityColumnsM42(db: Pick<MigrationDb, "rows">,
|
|
|
832
857
|
}[]>;
|
|
833
858
|
/**
|
|
834
859
|
* 🔴 M42 的 SQL 腿:标记在场 ⇒ 返回(零扫描);否则逐列只读计数 `LIKE '<前缀>%'`,一处命中 ⇒ {@link ScenarioPrefixSwitchRefusedError}(`stored_prefix`;一字节没写,标记不写);
|
|
835
|
-
*
|
|
860
|
+
* 零命中而有停-迁-起证据({@link readOlderReplicaEvidence})⇒ 同一只拒(`older_replica`;标记不写);否则写标记。
|
|
836
861
|
* 握着迁移段的那一把锁、在那一条连接上:两只副本同时起服时第二只读到第一只写下的标记(写标记用 `INSERT IGNORE` / `ON CONFLICT DO NOTHING`,收敛)。
|
|
837
862
|
*/
|
|
838
863
|
export declare function switchScenarioPrefixM42(db: MigrationDb, dialect: SqlDialect, receipts: {
|
|
839
864
|
scenarioPrefixSourcesScanned: number;
|
|
840
|
-
}, input:
|
|
865
|
+
}, input: LiveRunWindowInput): Promise<void>;
|
|
841
866
|
/** M40 的拒启码(停-迁-起守卫)。 */
|
|
842
867
|
export declare const EXECUTION_LANE_RENAME_REFUSED_CODE = "config.execution_lane_rename_refused";
|
|
843
868
|
/**
|
|
@@ -847,7 +872,7 @@ export declare const EXECUTION_LANE_RENAME_REFUSED_CODE = "config.execution_lane
|
|
|
847
872
|
export declare class ExecutionLaneRenameRefusedError extends StoreBootRefusalError {
|
|
848
873
|
/** 带旧词的行数(两张表合计)。 */
|
|
849
874
|
readonly pendingRows: number;
|
|
850
|
-
/**
|
|
875
|
+
/** 停-迁-起证据里的 `running` run 数(持有者没有登记为知道 M40)。 */
|
|
851
876
|
readonly liveRuns: number;
|
|
852
877
|
/** 全停之后可以再起的最早时刻(ISO;= 最新心跳 + 判活窗 —— 那时收割谓词也判它们为死)。 */
|
|
853
878
|
readonly restartAfter: string;
|
|
@@ -855,7 +880,7 @@ export declare class ExecutionLaneRenameRefusedError extends StoreBootRefusalErr
|
|
|
855
880
|
constructor(
|
|
856
881
|
/** 带旧词的行数(两张表合计)。 */
|
|
857
882
|
pendingRows: number,
|
|
858
|
-
/**
|
|
883
|
+
/** 停-迁-起证据里的 `running` run 数(持有者没有登记为知道 M40)。 */
|
|
859
884
|
liveRuns: number,
|
|
860
885
|
/** 全停之后可以再起的最早时刻(ISO;= 最新心跳 + 判活窗 —— 那时收割谓词也判它们为死)。 */
|
|
861
886
|
restartAfter: string, detail: string);
|
|
@@ -875,8 +900,8 @@ export declare class ExecutionLaneRenameWriteRefusedError extends StoreBootRefus
|
|
|
875
900
|
/** 落不了盘的那只文件(绝对路径)。 */
|
|
876
901
|
file: string, cause: unknown);
|
|
877
902
|
}
|
|
878
|
-
/**
|
|
879
|
-
export interface
|
|
903
|
+
/** 停-迁-起证据读法心跳一半的输入(归 M52 行):判活窗(毫秒)= 本部署的 `REAP_RUN_STALE_SEC` —— 收割器判「这条 run 的持有者还活着」用的同一个窗。 */
|
|
904
|
+
export interface LiveRunWindowInput {
|
|
880
905
|
readonly liveRunWindowMs: number;
|
|
881
906
|
}
|
|
882
907
|
/** M48 的输入:本部署有没有身份边界 = 部署形表 `DEPLOYMENT_SHAPE_PREDICATES.identityBoundary` 那一行的读数(只读配置;调用方读表交来,迁移步不另读配置)。
|
|
@@ -885,27 +910,27 @@ export interface ShellSentinelOwnerInput {
|
|
|
885
910
|
readonly identityBoundary: boolean;
|
|
886
911
|
}
|
|
887
912
|
/** SQL 一次性迁移段的输入(各条目自己的那一半;删码车删掉它那一半)。 */
|
|
888
|
-
export type SqlOneTimeMigrationInput = ExecutionPlacementSwitchInput &
|
|
913
|
+
export type SqlOneTimeMigrationInput = ExecutionPlacementSwitchInput & LiveRunWindowInput & ShellSentinelOwnerInput;
|
|
889
914
|
/**
|
|
890
915
|
* M40 ⓪ —— 带 `execution_lane` 列的表上的旧词改成新名(问行表 + 会话的那一列所在的表:M41 搬之前在 `session_meta`、之后在 `session_ext`;一句 UPDATE 一张表;幂等:第二跑零命中)。列不在的表零动作(跳版升上来的库:M32 稍后加列、按声明车道回填,不会再铸旧词)。
|
|
891
916
|
* 还有旧词行 ⇒ 先过停-迁-起守卫({@link refuseWhileRunsHeartbeat});没有 ⇒ 不读 run 表、零写(没跑过无车道部署的库可滚动升级)。
|
|
892
917
|
*/
|
|
893
918
|
export declare function renameRetiredExecutionLaneWordsM40(db: MigrationDb, dialect: SqlDialect, receipts: {
|
|
894
919
|
executionLaneWordsRenamed: number;
|
|
895
|
-
}, input:
|
|
896
|
-
/**
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
920
|
+
}, input: LiveRunWindowInput): Promise<void>;
|
|
921
|
+
/**
|
|
922
|
+
* **停-迁-起证据的唯一读法**(M40 / M41 / M42 / M43 / M51 同读;拒句与读数的句子属主 = `stop-then-start-sentence.ts`):判活窗内心跳过的 `running` run
|
|
923
|
+
* (收割器 `reapStale` 判活的同一条谓词:`status = 'running'` ∧ `updated_at` 在 `REAP_RUN_STALE_SEC` 窗内),按持有者(`task_run.instance_id`,建行铸、认领接管)分组,
|
|
924
|
+
* **减去登记为知道 `migrationId` 的持有者**(`replica-registration.ts`;`knows` 与起服准入同一只判据)—— 剩下的 run 就是证据:持有者没有登记行(早于副本登记的副本、`NULL` 身份、
|
|
925
|
+
* 自传身份的嵌入方)或登记了而能力名单里没有这条迁移,照算(保守)。登记一半只作归因(点名持有者),**不判活**。
|
|
926
|
+
* 本进程此刻还在迁移段里、一条 run 都没起过 ⇒ 证据里只有别的进程。`task_run` 不在 ⇒ `undefined`。心跳一半随 M52 行删(那一行的 `removal`)。
|
|
927
|
+
* `migrationId` 在型上就要在能力名单里(`ReplicaCapability`):一条迁移读证据 ⇔ 它的名在名单里。
|
|
928
|
+
*/
|
|
929
|
+
export declare function readOlderReplicaEvidence(db: MigrationDb, dialect: SqlDialect, input: LiveRunWindowInput, migrationId: ReplicaCapability): Promise<OlderReplicaEvidence | undefined>;
|
|
905
930
|
/** M41 的拒启码(确定的拒启表态;与 `config.schema_mismatch` 同一族)。 */
|
|
906
931
|
export declare const SESSION_EXT_MOVE_REFUSED_CODE = "config.session_ext_move_refused";
|
|
907
|
-
/** 拒因闭集:`
|
|
908
|
-
export type SessionExtMoveRefusalReason = "
|
|
932
|
+
/** 拒因闭集:`older_replica` = 还有列要搬而有停-迁-起证据;`copy_mismatch` = 搬完核对有一行不等(一列没删)。 */
|
|
933
|
+
export type SessionExtMoveRefusalReason = "older_replica" | "copy_mismatch";
|
|
909
934
|
/** M41 的起服拒。具名类型 + 机读码 + 拒因;继承 {@link StoreBootRefusalError}:SQL 开库的等待窗不重试它。 */
|
|
910
935
|
export declare class SessionExtMoveRefusedError extends StoreBootRefusalError {
|
|
911
936
|
readonly reason: SessionExtMoveRefusalReason;
|
|
@@ -913,10 +938,10 @@ export declare class SessionExtMoveRefusedError extends StoreBootRefusalError {
|
|
|
913
938
|
constructor(reason: SessionExtMoveRefusalReason, detail: string);
|
|
914
939
|
}
|
|
915
940
|
/**
|
|
916
|
-
* M41 ⓪′ —— 停-迁-起守卫(紧随 M40 的守卫,先于任何别的写):还有部署格列要搬 ∧
|
|
941
|
+
* M41 ⓪′ —— 停-迁-起守卫(紧随 M40 的守卫,先于任何别的写):还有部署格列要搬 ∧ 有停-迁-起证据({@link readOlderReplicaEvidence})⇒ 拒 `older_replica`,一字节没写。
|
|
917
942
|
* 旁表形 ⇒ 零动作(不读 run 表)。
|
|
918
943
|
*/
|
|
919
|
-
export declare function refuseSessionExtMoveWhileRunsHeartbeat(db: MigrationDb, dialect: SqlDialect, input:
|
|
944
|
+
export declare function refuseSessionExtMoveWhileRunsHeartbeat(db: MigrationDb, dialect: SqlDialect, input: LiveRunWindowInput): Promise<void>;
|
|
920
945
|
/**
|
|
921
946
|
* M41(规则与理由见头注 M41 段):① 搬(键集分页 upsert)→ ② 逐行核对 → ③ 一句删列。旁表形 ⇒ 零动作。中断 ⇒ 下一次起服从头重跑:① 的 upsert 是「旁表这几格 = 根行上的值」,
|
|
922
947
|
* 重跑同一结果;② 只读;③ 按后置条件收敛(那几列都不在)。排在迁移段最后(M32 之后:M32 读 / 写 `session_meta` 上的八列;M23 改的是引擎列)。导出给真库钉驱动「中断后续跑」。
|