@sema-agent/server 7.145.0 → 7.146.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 +492 -0
- package/USAGE.md +218 -47
- package/deploy/facts/CHANGES.json +25 -0
- package/deploy/facts/README.md +57 -0
- package/deploy/facts/lanes.json +54 -0
- package/deploy/facts/lanes.schema.json +57 -0
- package/deploy/facts/sandbox-rbac.json +113 -0
- package/deploy/facts/sandbox-rbac.schema.json +74 -0
- package/deploy/facts/sealed-key.json +9 -0
- package/deploy/facts/sealed-key.schema.json +52 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +19 -0
- package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +47 -7
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +4 -0
- package/deploy/sema-up/chart/templates/server.yaml +4 -0
- package/deploy/sema-up/chart/values.yaml +7 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +30 -14
- package/dist/adoption/import-limits.d.ts +6 -0
- package/dist/adoption/import-limits.js +7 -0
- package/dist/adoption/import.d.ts +62 -0
- package/dist/adoption/import.js +107 -0
- package/dist/adoption/wire.d.ts +52 -0
- package/dist/adoption/wire.js +9 -0
- package/dist/approval-ask-machine.d.ts +2 -2
- package/dist/approval-card.d.ts +3 -12
- package/dist/approval-card.js +0 -4
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/approval-gate-currency.js +1 -1
- package/dist/approval-reconciler.d.ts +1 -1
- package/dist/boot/deployment-mods.d.ts +11 -1
- package/dist/boot/deployment-mods.js +15 -2
- package/dist/boot/device-lane.js +2 -0
- package/dist/boot/engine-lease.d.ts +193 -21
- package/dist/boot/engine-lease.js +146 -20
- package/dist/boot/execution-env.d.ts +4 -0
- package/dist/boot/execution-env.js +12 -0
- package/dist/boot/exit-boundary.d.ts +50 -0
- package/dist/boot/exit-boundary.js +32 -0
- package/dist/boot/exit-last.d.ts +20 -4
- package/dist/boot/exit-last.js +21 -4
- package/dist/boot/governance-seams.js +1 -0
- package/dist/boot/memory-consolidation.d.ts +29 -17
- package/dist/boot/memory-consolidation.js +26 -15
- package/dist/boot/reapers.d.ts +12 -4
- package/dist/boot/reapers.js +39 -15
- package/dist/boot/resolve-spec.d.ts +2 -0
- package/dist/boot/resolve-spec.js +38 -15
- package/dist/boot/runner-deps.js +1 -1
- package/dist/boot/session-faces.js +3 -1
- package/dist/boot/shutdown.js +27 -9
- package/dist/boot/stage-01-config.js +1 -1
- package/dist/boot/stage-03-store-backend.d.ts +1 -0
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -0
- package/dist/boot/stage-05-execution-env.d.ts +3 -0
- package/dist/boot/stage-05-execution-env.js +3 -3
- package/dist/boot/stage-06-runners.d.ts +3 -0
- package/dist/boot/stage-06-runners.js +11 -10
- package/dist/boot/stage-07-capability-layer.d.ts +3 -0
- package/dist/boot/stage-07-capability-layer.js +7 -2
- package/dist/boot/stage-08-reapers.d.ts +3 -0
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +3 -0
- package/dist/boot/stage-10-http-server.d.ts +3 -0
- package/dist/boot/stage-10-http-server.js +3 -2
- package/dist/boot/stores.d.ts +1 -0
- package/dist/boot/stores.js +35 -19
- package/dist/boot/workflow-orchestration.d.ts +1 -1
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/capabilities/composite-members.d.ts +3 -1
- package/dist/capabilities/composite-members.js +3 -1
- package/dist/capabilities/scenarios.d.ts +2 -2
- package/dist/capability-facts.d.ts +18 -1
- package/dist/capability-facts.js +25 -7
- package/dist/checkpoint-ctx-seal-m28.d.ts +1 -1
- package/dist/config-catalog.js +13 -4
- package/dist/config-provider.d.ts +2 -2
- package/dist/config-types.d.ts +43 -4
- package/dist/config.d.ts +6 -1
- package/dist/config.js +67 -11
- package/dist/deleted-session-ids.d.ts +19 -0
- package/dist/deleted-session-ids.js +26 -0
- package/dist/deploy-facts.d.ts +155 -0
- package/dist/deploy-facts.js +94 -0
- package/dist/device-ws-hub.d.ts +48 -3
- package/dist/device-ws-hub.js +48 -2
- package/dist/error-code-family.d.ts +35 -0
- package/dist/error-code-family.js +26 -0
- package/dist/fleet/drain-entry.d.ts +39 -3
- package/dist/fleet/drain-entry.js +6 -0
- package/dist/fleet/fleet-bus.d.ts +2 -1
- package/dist/hooks/branch-transcript.d.ts +1 -1
- package/dist/hooks/branch-transcript.js +1 -0
- package/dist/hooks/classic-stations.d.ts +25 -8
- package/dist/hooks/classic-stations.js +29 -3
- package/dist/hooks/hook-runner.d.ts +33 -16
- package/dist/hooks/hook-runner.js +166 -73
- package/dist/hooks/hook-source.d.ts +14 -2
- package/dist/hooks/hook-source.js +8 -0
- package/dist/http/active-run-conflict.d.ts +1 -1
- package/dist/http/active-run-conflict.js +1 -1
- package/dist/http/admission.js +11 -1
- package/dist/http/checkpoint-ctx.d.ts +59 -71
- package/dist/http/checkpoint-ctx.js +34 -40
- package/dist/http/dispatch.js +18 -2
- package/dist/http/durable-run-leg.d.ts +5 -0
- package/dist/http/durable-run-leg.js +1 -0
- package/dist/http/execution-context.d.ts +4 -0
- package/dist/http/execution-context.js +9 -0
- package/dist/http/health-self-report.d.ts +6 -2
- package/dist/http/health-self-report.js +3 -2
- package/dist/http/memory-compliance-failure-reply.d.ts +1 -1
- package/dist/http/memory-compliance-failure-reply.js +2 -15
- package/dist/http/memory-control-plane-corrupt-reply.d.ts +25 -0
- package/dist/http/memory-control-plane-corrupt-reply.js +19 -0
- package/dist/http/principal-gate.d.ts +35 -12
- package/dist/http/principal-gate.js +16 -12
- package/dist/http/request-guards.d.ts +1 -1
- package/dist/http/request-guards.js +5 -5
- package/dist/http/resume-legs.d.ts +22 -0
- package/dist/http/resume-legs.js +26 -17
- package/dist/http/route-ctx.d.ts +11 -10
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/adoption.d.ts +11 -0
- package/dist/http/routes/adoption.js +80 -6
- package/dist/http/routes/agents-roster.js +1 -0
- package/dist/http/routes/approvals-assistant.js +2 -1
- package/dist/http/routes/background.js +1 -0
- package/dist/http/routes/capabilities.js +4 -1
- package/dist/http/routes/diagnostics.d.ts +9 -14
- package/dist/http/routes/diagnostics.js +10 -20
- package/dist/http/routes/engine.d.ts +31 -0
- package/dist/http/routes/engine.js +81 -0
- package/dist/http/routes/memory-bundle.js +3 -0
- package/dist/http/routes/memory-consolidation.js +3 -5
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/memory-origin.js +2 -4
- package/dist/http/routes/memory-policy.js +5 -1
- package/dist/http/routes/observability.js +3 -6
- package/dist/http/routes/runs.js +7 -3
- package/dist/http/routes/session-sync.js +12 -25
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions.js +4 -0
- package/dist/http/routes/tasks.js +23 -5
- package/dist/http/routes/trace-usage.js +1 -1
- package/dist/http/run-concurrency-cap.d.ts +86 -0
- package/dist/http/run-concurrency-cap.js +54 -0
- package/dist/http/server.d.ts +15 -12
- package/dist/http/server.js +18 -3
- package/dist/http/stored-body-replay.d.ts +9 -6
- package/dist/http/stored-body-replay.js +19 -5
- package/dist/http/wire-types.d.ts +8 -3
- package/dist/json-body-limit.d.ts +8 -0
- package/dist/json-body-limit.js +2 -0
- package/dist/leader/diffout.d.ts +1 -1
- package/dist/local-data-root.d.ts +2 -2
- package/dist/memory-operator-faces.d.ts +9 -4
- package/dist/memory-scope-stores.d.ts +9 -7
- package/dist/memory-scope-stores.js +3 -14
- package/dist/memory-scope.d.ts +36 -0
- package/dist/memory-scope.js +32 -1
- package/dist/net-address.d.ts +53 -0
- package/dist/net-address.js +111 -0
- package/dist/observability/fail-open.d.ts +14 -10
- package/dist/observability/fail-open.js +14 -10
- package/dist/orchestration/workflow-notify-journal.js +2 -3
- package/dist/org-delivery-gate.js +1 -1
- package/dist/peer-directory.d.ts +6 -12
- package/dist/peer-directory.js +5 -1
- package/dist/plugins/caching-session-store.d.ts +3 -1
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-store-face.d.ts +426 -0
- package/dist/plugins/checkpoint-store-face.js +152 -0
- package/dist/plugins/file-run-store.d.ts +0 -6
- package/dist/plugins/file-run-store.js +1 -12
- package/dist/plugins/fork-routing-session-store.d.ts +6 -2
- package/dist/plugins/fork-routing-session-store.js +2 -2
- package/dist/plugins/imported-layer-root-retirement.d.ts +10 -8
- package/dist/plugins/local-checkpoint-store.d.ts +2 -2
- package/dist/plugins/local-checkpoint-store.js +2 -1
- package/dist/plugins/local-session-store.d.ts +28 -5
- package/dist/plugins/local-session-store.js +32 -8
- package/dist/plugins/memory-engine-pg.d.ts +29 -6
- package/dist/plugins/memory-engine-pg.js +96 -214
- package/dist/plugins/memory-engine-sql-apply.d.ts +121 -0
- package/dist/plugins/memory-engine-sql-apply.js +358 -0
- package/dist/plugins/memory-engine-tidb.d.ts +35 -9
- package/dist/plugins/memory-engine-tidb.js +97 -227
- package/dist/plugins/memory-key-guards.d.ts +1 -1
- package/dist/plugins/memory-origin-law.d.ts +3 -3
- package/dist/plugins/one-time-migrations.d.ts +32 -56
- package/dist/plugins/one-time-migrations.js +25 -117
- package/dist/plugins/permission-rule-store-file.d.ts +17 -3
- package/dist/plugins/permission-rule-store-file.js +8 -1
- package/dist/plugins/pg-pool.js +1 -1
- package/dist/plugins/pg-session-storage.d.ts +17 -4
- package/dist/plugins/pg-session-storage.js +8 -4
- package/dist/plugins/run-store-sql.js +2 -2
- package/dist/plugins/schema-ensure-legs.js +2 -2
- package/dist/plugins/session-fork.d.ts +31 -9
- package/dist/plugins/session-fork.js +3 -2
- package/dist/plugins/session-placement.d.ts +4 -2
- package/dist/plugins/sql-json-column.d.ts +5 -1
- package/dist/plugins/store-backend.d.ts +11 -8
- package/dist/plugins/store-backend.js +8 -7
- package/dist/plugins/store-contracts.d.ts +1 -11
- package/dist/plugins/store-contracts.js +0 -9
- package/dist/plugins/store-sweep.d.ts +63 -0
- package/dist/plugins/store-sweep.js +48 -0
- package/dist/plugins/tidb-pool.js +1 -1
- package/dist/plugins/tidb-session-store.d.ts +16 -3
- package/dist/plugins/tidb-session-store.js +8 -4
- package/dist/prompt-screen.d.ts +6 -9
- package/dist/prompt-screen.js +2 -5
- package/dist/rules-consent.d.ts +20 -27
- package/dist/rules-consent.js +82 -6
- package/dist/run-cancel-context.d.ts +4 -1
- package/dist/run-cancel-context.js +2 -1
- package/dist/runs.js +1 -1
- package/dist/sandbox-egress-policy.js +6 -11
- package/dist/sandbox-rbac-rules.d.ts +88 -0
- package/dist/sandbox-rbac-rules.js +80 -0
- package/dist/sealed-key-layout.d.ts +17 -0
- package/dist/sealed-key-layout.js +4 -0
- package/dist/sealed-key.js +5 -5
- package/dist/security.d.ts +38 -6
- package/dist/security.js +9 -2
- package/dist/session-notify-door.d.ts +5 -3
- package/dist/session-resident-background.d.ts +57 -0
- package/dist/session-resident-background.js +20 -0
- package/dist/session-sync-kernel.d.ts +53 -14
- package/dist/session-sync-kernel.js +70 -1
- package/dist/session-sync.d.ts +5 -3
- package/dist/session-workspace.d.ts +1 -0
- package/dist/session-workspace.js +1 -0
- package/dist/sighup-idle.d.ts +9 -7
- package/dist/sighup-idle.js +4 -5
- package/dist/spec-fields.d.ts +16 -0
- package/dist/spec-fields.js +7 -0
- package/dist/stored-request-env-credentials-m38.d.ts +3 -0
- package/dist/stored-request-env-credentials-m38.js +8 -0
- package/dist/stored-request-prompt-profile-m30.d.ts +1 -1
- package/dist/{plugins → stores-sql}/checkpoint-store-sql.d.ts +13 -427
- package/dist/{plugins → stores-sql}/checkpoint-store-sql.js +33 -194
- package/dist/{plugins → stores-sql}/mailbox-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/mailbox-store-sql.js +4 -4
- package/dist/{plugins → stores-sql}/roster-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/roster-store-sql.js +1 -1
- package/dist/{plugins → stores-sql}/tool-result-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/tool-result-store-sql.js +6 -6
- package/dist/{plugins → stores-sql}/workflow-journal-store-sql.d.ts +7 -12
- package/dist/{plugins → stores-sql}/workflow-journal-store-sql.js +3 -8
- package/dist/task-settings.d.ts +59 -4
- package/dist/task-settings.js +50 -4
- package/dist/tool-approval.d.ts +2 -2
- package/dist/trace/core-keyset-guard.d.ts +8 -7
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.d.ts +6 -0
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/project.js +9 -0
- package/dist/trace/redact.d.ts +13 -2
- package/dist/trace/redact.js +305 -24
- package/dist/trace/self-minted-wire.d.ts +326 -8
- package/dist/trace/self-minted-wire.js +125 -7
- package/dist/trace/wire-projection-faces.d.ts +1 -1
- package/dist/trace/wire-projection-faces.js +1 -1
- package/dist/usage-analytics.d.ts +4 -0
- package/package.json +12 -4
- package/scripts/drain-check-local.mjs +8 -29
- package/scripts/drain-check.mysql.sql +3 -24
- package/scripts/drain-check.pg.sql +3 -24
- package/skills/update-config.md +1 -1
- package/wire-changes/server@7.146.0.json +3221 -0
- package/dist/approval-batch-census.d.ts +0 -27
- package/dist/approval-batch-census.js +0 -27
|
@@ -6,16 +6,16 @@ import { SCHEMA_STATEMENTS, acquireEnsureSchemaLock, releaseEnsureSchemaLock } f
|
|
|
6
6
|
import { PG_SCHEMA_STATEMENTS, acquirePgEnsureSchemaLock, releasePgEnsureSchemaLock } from "./pg-pool.js";
|
|
7
7
|
import { CENTRAL_SCHEMA_INDEXES } from "./schema-indexes.js";
|
|
8
8
|
import { ensureIndexes } from "./ensure-index.js";
|
|
9
|
-
import { createObjectColumnReader, decodeJsonColumn, decodeNullableJsonColumn, isJsonColumnBodyProblem, jsonColumnText, jsonColumnTextExpr,
|
|
9
|
+
import { createObjectColumnReader, decodeJsonColumn, decodeNullableJsonColumn, isJsonColumnBodyProblem, jsonColumnText, jsonColumnTextExpr, readOpaqueJsonValueColumn, } from "./sql-json-column.js";
|
|
10
10
|
import { incarnationFromCell, sessionFaceFromRow } from "../session-incarnation.js";
|
|
11
|
-
import {
|
|
11
|
+
import { StoreBootRefusalError } from "./store-contracts.js";
|
|
12
12
|
import { PERMISSION_RULE_TABLE, SqlDurableRulePartitionProvider, isSqlBucketRefusal, isSqlBucketVanished, listRuleBucketOwners, purgeUndurableScopeRows } from "./permission-rule-store-sql.js";
|
|
13
13
|
import { SESSION_RULES_COLUMN } from "./session-rules-column.js";
|
|
14
14
|
import { readJsonObjectColumn } from "./sql-json-column.js";
|
|
15
15
|
import { retireStoredCardWords } from "../retired-card-words.js";
|
|
16
16
|
import { redactSecrets } from "../trace/redact.js";
|
|
17
17
|
import { CLAIM_OWNERLESS_PLACED_SQL, claimOwnerlessParams, isOrphanSessionOwner, judgeDelegatedOwner } from "../delegated-session-owner.js";
|
|
18
|
-
import { MAILBOX_KEYED_TABLES, mailboxKeyDeleteSql, storedMailboxKeyless } from "
|
|
18
|
+
import { MAILBOX_KEYED_TABLES, mailboxKeyDeleteSql, storedMailboxKeyless } from "../stores-sql/mailbox-store-sql.js";
|
|
19
19
|
import { SESSION_META_PLACEMENT_COLUMNS, backfillWriterStatement, countOrphanBindingsStatement, migrateDeviceBindingsStatement } from "./execution-placement-sql.js";
|
|
20
20
|
import { APPROVAL_ASK_ENDING_CAUSE_COLUMN, APPROVAL_ASK_EXECUTION_LANE_COLUMN, APPROVAL_ASK_PARK_TRIGGER_COLUMN, APPROVAL_ASK_TABLE } from "./approval-ask-store-sql.js";
|
|
21
21
|
import { retireImportedLayerRootAllows } from "./imported-layer-root-retirement.js";
|
|
@@ -23,9 +23,6 @@ import { isUnusableArchive } from "../execution-placement.js";
|
|
|
23
23
|
const RETIRED_SESSION_RULE_BUCKETS = ["commandAllow", "commandDeny"];
|
|
24
24
|
export function buildMigrationReceipts() {
|
|
25
25
|
return {
|
|
26
|
-
holderDeathCodeRowsBackfilled: 0,
|
|
27
|
-
allowRuleShadowRowsMigrated: 0,
|
|
28
|
-
allowRuleShadowRowsUnreadable: 0,
|
|
29
26
|
workflowParkIndexRowsCarried: 0,
|
|
30
27
|
undurableScopeRuleRows: [],
|
|
31
28
|
undurableScopeRuleBucketsDeferred: 0,
|
|
@@ -76,10 +73,7 @@ function completedReport(r) {
|
|
|
76
73
|
return { ...r, workflowParkIndexKey, sessionRuleColumn, workflowJournalScopeColumn };
|
|
77
74
|
}
|
|
78
75
|
function changedAnything(r) {
|
|
79
|
-
return (r.
|
|
80
|
-
r.allowRuleShadowRowsMigrated > 0 ||
|
|
81
|
-
r.allowRuleShadowRowsUnreadable > 0 ||
|
|
82
|
-
r.workflowParkIndexKey === "reshaped" ||
|
|
76
|
+
return (r.workflowParkIndexKey === "reshaped" ||
|
|
83
77
|
r.workflowParkIndexRowsCarried > 0 ||
|
|
84
78
|
r.undurableScopeRuleRows.length > 0 ||
|
|
85
79
|
r.undurableScopeRuleBucketsDeferred > 0 ||
|
|
@@ -163,42 +157,6 @@ export class OneTimeMigrationInterruptedError extends Error {
|
|
|
163
157
|
}
|
|
164
158
|
}
|
|
165
159
|
export const ONE_TIME_MIGRATIONS = [
|
|
166
|
-
{
|
|
167
|
-
id: "M6",
|
|
168
|
-
introducedIn: "7.116.0",
|
|
169
|
-
releasedOn: "2026-10-05",
|
|
170
|
-
removableAfter: "2026-11-04",
|
|
171
|
-
removal: "删 migrateOn 的 M6 步(`task_run` 两条 `UPDATE … SET error_code`)与 local 腿 `FileRunStore.migrateLegacyHolderDeathCodes`(及 " +
|
|
172
|
-
"`LocalBackend.runOneTimeMigrations` 里那一格);报告与日志行的 `holderDeathCodeRowsBackfilled`;**连同读侧半场一起删**:" +
|
|
173
|
-
"`store-contracts.ts` 的 `readLegacyHolderDeathCode` 与 SQL 行映射 `run-store-sql.ts#rowToRun` 里对它的调用(码列改回原样读)",
|
|
174
|
-
afterRemoval: "没有响亮臂:窗关删码之后仍只有句子、码列为空的行(跳过了所有带 M6 的版本直接升的库,或窗关之后还在写的 ≤7.115.x 副本)不再被判成持有者死亡 —— " +
|
|
175
|
-
"用户输入受理账本的收敛判词(`user-input-ledger.ts` `judgeOpen`)对这种行落到「其余」臂 `leg_over`:补落 `settled{leg_end}`、不告知,那条 run 上" +
|
|
176
|
-
"丢掉的 steer 不再告诉用户;`GET /v1/runs/:id` 上 `errorCode` 缺席、只剩 `error` 句子",
|
|
177
|
-
reportKeys: ["holderDeathCodeRowsBackfilled"],
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
id: "M7",
|
|
181
|
-
introducedIn: "7.117.0",
|
|
182
|
-
releasedOn: "2026-10-06",
|
|
183
|
-
removableAfter: "2026-11-05",
|
|
184
|
-
removal: "删 `http/checkpoint-ctx.ts` 的读法记号判据与拒臂(`allowListReadingUnstated` / `allowListReadingEraOf` / `allowListReadingRefusal` / " +
|
|
185
|
-
"`PERMISSIONS_ALLOW_READINGS` / `ALLOW_LIST_READING_ERAS`、`buildCheckpointCtx` 里的记号写点)、`CheckpointCtx.permissionsAllowReading`、" +
|
|
186
|
-
"`resume-legs.ts` 两个判点与 `approval-sweeps.ts` 的跳过臂、随包排空判据 `permissions-allow-list`(两份 SQL + 本地脚本那一条)",
|
|
187
|
-
afterRemoval: "没有响亮臂:删码之后仍停驻、体里带非空 allow 的旧读法行(把 `APPROVAL_TERMINAL_BACKSTOP_MS` 调长的部署,或跳过了带本条的版本直接升的库)会被按" +
|
|
188
|
-
"当前读法静默重放(名单时代的行:名单外的工具放开;表态时代的行:普通问不再问)—— 升级前按 MIGRATION 7.117.0 节跑排空判据清零",
|
|
189
|
-
reportKeys: [],
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
id: "M8",
|
|
193
|
-
introducedIn: "7.117.0",
|
|
194
|
-
releasedOn: "2026-10-06",
|
|
195
|
-
removableAfter: "2026-11-05",
|
|
196
|
-
removal: "删 migrateOn 的 M8 步(`checkpoint.risk_descriptor` 的旧键扫描 + CAS 回写)与 `migrateShadowedRuleKey` / `migrateShadowedRuleDescriptor`;" +
|
|
197
|
-
"报告、日志行与 `NO_SQL_MIGRATIONS` 的 `allowRuleShadowRowsMigrated` / `allowRuleShadowRowsUnreadable`",
|
|
198
|
-
afterRemoval: "没有响亮臂:删码之后仍带旧键的停驻行(跳过了带本条的版本直接升的库)在运维待批队列上只缺结构化披露 `allowRuleShadowed`;旧键的文本仍经脱敏叶表" +
|
|
199
|
-
"「认不得的键按内容脱敏」一条脱敏后原样显示,卡上 `message` 里引擎写好的那句话不受影响",
|
|
200
|
-
reportKeys: ["allowRuleShadowRowsMigrated", "allowRuleShadowRowsUnreadable"],
|
|
201
|
-
},
|
|
202
160
|
{
|
|
203
161
|
id: "M9",
|
|
204
162
|
introducedIn: "7.118.0",
|
|
@@ -411,7 +369,7 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
411
369
|
"`test/one-time-migrations.test.ts` 的 M23 组与 `test/one-time-migrations-db-integration.test.ts` 的 M23 格。" +
|
|
412
370
|
"**不随本条删**:`ORPHAN_SESSION_OWNER_PREFIX` 与它在 `security.ts` 保留主体前缀里的登记(已落库的行可能带哨兵,永久保留);" +
|
|
413
371
|
"属主为 NULL 的 placed 行只对 fleet 调用方放行(`security.ts` 的 `ownerlessRowOpen` / `sessionOwnerCellOf` 与各门读 `placementOf` 的那一次)—— 那是常设的读面律",
|
|
414
|
-
afterRemoval: "会话面的读面律(常设,不随本条删)接住:跳过了带本条的版本直接升的库里,属主为 NULL 的存量 placed 子代行只对 fleet 调用方放行(出示 service
|
|
372
|
+
afterRemoval: "会话面的读面律(常设,不随本条删)接住:跳过了带本条的版本直接升的库里,属主为 NULL 的存量 placed 子代行只对 fleet 调用方放行(出示 service 凭据、不报主体 —— 除非部署声明 `SERVICE_TOKEN_ACTS_FOR_DEPLOYMENT=false`,那时这一形是无身份调用方、不在其内;或 dev-open 部署上的任何调用方)," +
|
|
415
373
|
"其余调用方答 404(与别人的行同体)—— 出路是升级时先过一次带本条的版本,或运维按 `placement_root_session_id`(缺则 `placement_parent_session_id`)那一行的属主手工回填、" +
|
|
416
374
|
"推不出的写一个任何主体都不匹配的值;停驻挂点只比对宿主行属主与引擎交来的属主(复活腿交那一行自己的属主),不写无主行;" +
|
|
417
375
|
"建行那一笔记 `placement.owner` 不随本条删(那是常设的写法 —— core 盒义务 7,不是迁移)",
|
|
@@ -472,13 +430,13 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
472
430
|
introducedIn: "7.134.0",
|
|
473
431
|
releasedOn: "2026-10-21",
|
|
474
432
|
removableAfter: "2026-11-20",
|
|
475
|
-
removal: "删 `src/checkpoint-ctx-seal-m28.ts` 整个文件(`sealCheckpointCtxCredentialsM28`)与起服第 6 段(`src/boot/stage-06-runners.ts`)顶部对 `sealCheckpointCtxCredentialsM28` 的 import 行与对它的那一处调用(连同起服 info 行 `checkpoint_ctx_credentials_sealed`);两孪生共有的 ctx 行改写店腿(`src/
|
|
433
|
+
removal: "删 `src/checkpoint-ctx-seal-m28.ts` 整个文件(`sealCheckpointCtxCredentialsM28`)与起服第 6 段(`src/boot/stage-06-runners.ts`)顶部对 `sealCheckpointCtxCredentialsM28` 的 import 行与对它的那一处调用(连同起服 info 行 `checkpoint_ctx_credentials_sealed`);两孪生共有的 ctx 行改写店腿(`src/stores-sql/checkpoint-store-sql.ts`、`src/plugins/checkpoint-store-face.ts` 与 `src/plugins/local-checkpoint-store.ts` 里的 `rewriteCtxRows` / `CtxRowsRewrite` / `CtxRowRewrite` / `CheckpointCtxRowsRewriter` / 扫描页 `CTX_REWRITE_PAGE`)只在本表再无别的条目用它时(今天 M30 也用)一起删;店腿删时 `test/checkpoint-ctx-sealed-brand.test.ts` 里 `rewriteCtxRows` 的断言(`@ts-expect-error` 与 `void local.rewriteCtxRows(` 两行)一起删 —— 店腿不在后那一行的 tsc 错变成「属性不存在」,`@ts-expect-error` 照样满足,断言静默变空 —— 同文件 `putCtx` 的常设断言保留;**店腿格不随本条删**:`test/checkpoint-ctx-rows-rewrite-db-integration.test.ts`(店腿自己的 CAS / 分页 / 一行装不下三格)与 `test/checkpoint-ctx-rows-rewrite-local.test.ts`(读不出的档 / 信封 updatedAt 不动两格)用中性的行改写、不借任何一条迁移的函数,店腿还有用户时它们要活着;店腿删时两个文件整文件随店腿删,`scripts/db-integration-files.json` 里 db 那个文件的行同删;店腿删时的同族注释(店腿是两条迁移共用的,谁后删谁做;两条 removal 都点名,逐条同字面):`src/http/checkpoint-ctx.ts`:「与一次性迁移的 ctx 行改写店腿(`rewriteCtxRows`)」删;`test/checkpoint-ctx-sealed-brand.test.ts`:「与 ctx 行改写回调(M28 / M30 共用)」删、「,M28 行改写回调交回裸对象 —— 三处都是 tsc 错」改成「 —— 两处都是 tsc 错」;`test/checkpoint-ctx-credential-seal-db-integration.test.ts`:「另有各随一条一次性迁移的格」起到「别的文件的行一个都不碰);」止整段删;" +
|
|
476
434
|
"`http/checkpoint-ctx.ts` 的 `sealStoredCheckpointCtxM28`;`test/checkpoint-ctx-seal-m28.test.ts` 整个文件与 `test/checkpoint-ctx-credential-seal-db-integration.test.ts` 里的「[M28] 明文旧行」那一格(它调 `sealStoredCheckpointCtxM28`);" +
|
|
477
435
|
"`test/doc-claims-upgrade-notes.test.ts` ㊵ 组里读这处调用与日志行的三行断言随删(两格本身与其余断言留着;不删就是删码后这两格红):「锚(嵌入方段的每件事实读实现)」格的 `callSites(\"sealCheckpointCtxCredentialsM28\")` 一行;" +
|
|
478
436
|
"「锚(恢复句的每件事实读实现)」格里 guarded 上对 `sealCheckpointCtxCredentialsM28` 调用的断言与对 `logger.info(\"checkpoint_ctx_credentials_sealed\"` 日志行的断言两行;" +
|
|
479
437
|
"`test/stored-request-prompt-profile-m30.test.ts` 里钉起服第 6 段调用次序的那一格(`describe` 名含「起服接线」;M30 删码时才删它,M28 的窗先关,先删 M28 时它要活着)里读 M28 调用位置的 `const m28` 那一行(它用 indexOf 找 `sealCheckpointCtxCredentialsM28` 的调用)与「M28 在那一臂里」「M30 在那一臂里、M28 之后」两条断言,改成只相对 `guard` 比较 M30 的位置;" +
|
|
480
438
|
"依赖本行的格(行一删就红):doc-claims ㊵ 的「嵌入方一段分清两只迁移的窗」格(读 M28 / M30 两行的窗末日;哪一行先删就先删这一格,MIGRATION 7.137.0 节的文字是已发布的历史、留着不动),`test/stored-request-prompt-profile-m30.test.ts` 里「M28 登记行」组整组随删(组内三格都读 M28 行的 `removal`:「M28 的 removal 同样点名」「M28 删法条补四类漏项」「同一注释半句只归一条 removal」)、同文件 SHARED 表里 rows 含 M28 的五行改成只剩 M30 并入 SITES(M30 的登记行组已先删时该表已不在,这一句无事可做);" +
|
|
481
|
-
"同族注释(每个半句只归本条或 M30 条之一,不重复改;标〔另一条的〕的几处住在另一条迁移的文件 / 头注段里,那条已先删则宿主已不在,跳过):`src/http/checkpoint-ctx.ts`:「一次性迁移 M28 对存量行用同一只走法」删、「({@link sealStoredCheckpointCtxM28})」删、「、{@link sealStoredCheckpointCtxM28}」删、「(开口与 M28 同一只)」删、「(更早版本写下、M28 还没扫到)」改成「(更早版本写下)」、「读写两侧与一次性迁移 M28 共用」改成「读写两侧共用」、「已落盘的行由 M28 补封」改成「已落盘的行不补封(要补封须另起迁移)」、「M28 封的是」起到「窗外加位要另起迁移)。」止整段删、「(读写两侧与 M28 共用这一只)」改成「(读写两侧共用这一只)」、「(开口与 M28 共用这一只判词,闭集三词)」改成「(开口用这一只判词,闭集三词)」、「开口去开它;M28 不动它;」改成「开口去开它;」、「M28 把它封好;」删、「M28 不动它(留给读口响亮拒)」改成「(留给读口响亮拒)」、「封口 / 开口 / M28 共用的那一只」改成「封口 / 开口共用的那一只」;`src/sealed-key.ts`:「起服的一次性迁移 M28 会用它把还读得懂的明文行换成谁都开不开的密文」改成「新写的停驻行会被封成谁都开不开的密文」;`src/boot/web-admin.ts`:「与一次性迁移 M28(stage-06)」删、「M28 会拿它毁掉还读得懂的行」改成「新写的停驻行会被封成谁都开不开的密文」;`src/boot/stage-06-runners.ts`:「也是一次性迁移 M28 要它的地方。M28 在任何路由装配之前跑(窗外不扫;读数一行 info)。」删、「排在 M28 之后」删;`src/plugins/checkpoint-store-
|
|
439
|
+
"同族注释(每个半句只归本条或 M30 条之一,不重复改;标〔另一条的〕的几处住在另一条迁移的文件 / 头注段里,那条已先删则宿主已不在,跳过):`src/http/checkpoint-ctx.ts`:「一次性迁移 M28 对存量行用同一只走法」删、「({@link sealStoredCheckpointCtxM28})」删、「、{@link sealStoredCheckpointCtxM28}」删、「(开口与 M28 同一只)」删、「(更早版本写下、M28 还没扫到)」改成「(更早版本写下)」、「读写两侧与一次性迁移 M28 共用」改成「读写两侧共用」、「已落盘的行由 M28 补封」改成「已落盘的行不补封(要补封须另起迁移)」、「M28 封的是」起到「窗外加位要另起迁移)。」止整段删、「(读写两侧与 M28 共用这一只)」改成「(读写两侧共用这一只)」、「(开口与 M28 共用这一只判词,闭集三词)」改成「(开口用这一只判词,闭集三词)」、「开口去开它;M28 不动它;」改成「开口去开它;」、「M28 把它封好;」删、「M28 不动它(留给读口响亮拒)」改成「(留给读口响亮拒)」、「封口 / 开口 / M28 共用的那一只」改成「封口 / 开口共用的那一只」;`src/sealed-key.ts`:「起服的一次性迁移 M28 会用它把还读得懂的明文行换成谁都开不开的密文」改成「新写的停驻行会被封成谁都开不开的密文」;`src/boot/web-admin.ts`:「与一次性迁移 M28(stage-06)」删、「M28 会拿它毁掉还读得懂的行」改成「新写的停驻行会被封成谁都开不开的密文」;`src/boot/stage-06-runners.ts`:「也是一次性迁移 M28 要它的地方。M28 在任何路由装配之前跑(窗外不扫;读数一行 info)。」删、「排在 M28 之后」删;`src/plugins/checkpoint-store-face.ts`:「M28(凭据位明文封好)」删;`src/stored-request-prompt-profile-m30.ts`:〔另一条的〕「,与 M28 同一只」删、〔另一条的〕「本条与 M28 同在起服第 6 段」改成「本条在起服第 6 段」、〔另一条的〕「(M28 用同一只)」删;`src/plugins/one-time-migrations.ts`:〔另一条的〕「起服第 6 段 M28 之后调一次」改成「起服第 6 段调一次」、〔另一条的〕「店腿是两孪生共有的 `rewriteCtxRows`,与 M28 同一只」改成「店腿是两孪生共有的 `rewriteCtxRows`」;`test/owner-gate-single-owner.test.ts`:「两只封口 `sealCheckpointCtx` / `sealStoredCheckpointCtxM28` 经它」改成「封口 `sealCheckpointCtx` 经它」;`test/drain-check-local.test.ts`:「封口 / 开口 / M28 共用的凭据位遍历器」改成「封口 / 开口共用的凭据位遍历器」;`test/checkpoint-ctx-credential-seal.test.ts`:「(否则 M28 会把可用的明文行换成谁都开不开的密文)」改成「(否则新写的停驻行会被封成谁都开不开的密文)」;`test/helpers/ctx-sealing.ts`:「 / M28 的行改写」删;`test/checkpoint-ctx-credential-seal-db-integration.test.ts`:「/ `checkpoint-ctx-seal-m28.test.ts`」删、「窗与读数那一层在 local 半场(`checkpoint-ctx-seal-m28.test.ts`)钉」起到「两半场共用同一只行改写 `sealStoredCheckpointCtxM28`。」止整段删;`test/checkpoint-ctx-sealed-brand.test.ts`:「与 M28 的行改写(`sealStoredCheckpointCtxM28`)」删;" +
|
|
482
440
|
"**不随本条删**:凭据位密封的常设规则(封口 / 开口 / 闭集 / 读口第四态 / 409 码 / 装配期拒启)",
|
|
483
441
|
afterRemoval: "读口对凭据位上明文的常设拒臂接住:跳过了带本条的版本直接升的库,带明文凭据的停驻行续跑答 409 `conflict.checkpoint_ctx_unsealable`(`reason:\"plaintext\"`)," +
|
|
484
442
|
"行字节不动 —— 出路 = 作为新任务重提(仍停驻的先取消),或升级时先过一次带本条的版本",
|
|
@@ -502,13 +460,13 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
502
460
|
releasedOn: "2026-10-25",
|
|
503
461
|
removableAfter: "2026-11-24",
|
|
504
462
|
removal: "删 `src/stored-request-prompt-profile-m30.ts` 整个文件(`retirePromptProfileM30` / `retirePromptProfileRowM30` / `PromptProfileRetireM30Report`)与起服第 6 段(`src/boot/stage-06-runners.ts`)顶部对 `retirePromptProfileM30` 的 import 行与对它的那一处调用(连同起服 info 行 `checkpoint_ctx_prompt_profile_rewritten`);" +
|
|
505
|
-
"`http/checkpoint-ctx.ts` 的 `rewriteStoredBodyKeys` 与 `CREDENTIAL_SLOT_ROOTS`(若再无别的调用方);两孪生共有的 ctx 行改写店腿(`src/
|
|
463
|
+
"`http/checkpoint-ctx.ts` 的 `rewriteStoredBodyKeys` 与 `CREDENTIAL_SLOT_ROOTS`(若再无别的调用方);两孪生共有的 ctx 行改写店腿(`src/stores-sql/checkpoint-store-sql.ts`、`src/plugins/checkpoint-store-face.ts` 与 `src/plugins/local-checkpoint-store.ts` 里的 `rewriteCtxRows` / `CtxRowsRewrite` / `CtxRowRewrite` / `CheckpointCtxRowsRewriter` / `CTX_REWRITE_PAGE`)只在本表再无别的条目用它时一起删(今天 M28 也用);店腿删时 `test/checkpoint-ctx-sealed-brand.test.ts` 里 `rewriteCtxRows` 的断言(`@ts-expect-error` 与 `void local.rewriteCtxRows(` 两行)一起删 —— 店腿不在后那一行的 tsc 错变成「属性不存在」,`@ts-expect-error` 照样满足,断言静默变空 —— 同文件 `putCtx` 的常设断言保留;**店腿格不随本条删**:`test/checkpoint-ctx-rows-rewrite-db-integration.test.ts`(店腿自己的 CAS / 分页 / 一行装不下三格)与 `test/checkpoint-ctx-rows-rewrite-local.test.ts`(读不出的档 / 信封 updatedAt 不动两格)用中性的行改写、不借任何一条迁移的函数,店腿还有用户时它们要活着;店腿删时两个文件整文件随店腿删,`scripts/db-integration-files.json` 里 db 那个文件的行同删;店腿删时的同族注释(店腿是两条迁移共用的,谁后删谁做;两条 removal 都点名,逐条同字面):`src/http/checkpoint-ctx.ts`:「与一次性迁移的 ctx 行改写店腿(`rewriteCtxRows`)」删;`test/checkpoint-ctx-sealed-brand.test.ts`:「与 ctx 行改写回调(M28 / M30 共用)」删、「,M28 行改写回调交回裸对象 —— 三处都是 tsc 错」改成「 —— 两处都是 tsc 错」;`test/checkpoint-ctx-credential-seal-db-integration.test.ts`:「另有各随一条一次性迁移的格」起到「别的文件的行一个都不碰);」止整段删;" +
|
|
506
464
|
"`http/checkpoint-ctx.ts` 的拒句铸点 `retiredRequestKeyRefusal`:模板串里从「If whoever operates this deployment restarts this server on or before 〈窗末日〉 (UTC), the stored request is rewritten in place and the same request can be sent again; otherwise submit」起的整段换成大写开头的「Submit」(窗关后重启不再改写;只删半句会留下句首小写、悬空的 otherwise),模板串变回整句双引号字面 —— 删后整句(逐字;冻结表那一行搬回字面表时也是这一句):「this task was suspended by an earlier server version and its stored request still carries promptProfile, a request key this version no longer reads (it was replaced by the boolean promptLean: classic is promptLean: false, simple is leaving promptLean out), so continuing would run the task with a prompt form it was not submitted with. Nothing was decided and nothing was resumed. Submit the work again as a new task with promptLean in place of promptProfile, and if this task is still suspended cancel it first (POST /v1/runs/:id/cancel).」," +
|
|
507
465
|
"它的第二参数 `rewriteWindowEnd` 同删(定义处与私有的 `storedBodyReplayArmAnswer` 里 `retired_request_key` 臂上的那一处调用),`StoredBodyReplayRefusal` 的 `retired_request_key` 臂上的必填字段 `rewriteWindowEnd` 同删;" +
|
|
508
466
|
"`src/trace/self-minted-wire.ts` 的 `refusalSentenceForm` 里「409 checkpoint.unsupported_version#retired_request_key」那一行(自铸句型登记):骨架 attr 尾上的「submit the work again」改成「Submit the work again」(删后整句的形),since 改写成删码所在的版本(该表的律:改 attr 的同时改 since);" +
|
|
509
467
|
"`http/checkpoint-ctx.ts` 的日志字段铸点 `storedBodyReplayLogFields` 里 `retired_request_key` 臂的 `note` 句改成常设拒臂的句子(原句里「the one-time rewrite at startup did not reach it」与「or a restart of this version inside the window rewrites the row」两半删码后成假话,与本行 afterRemoval 的「出路 = 重提」矛盾;" +
|
|
510
468
|
"改后句:「this session's stored request still carries a request key this version retired and nothing rewrites it any more; it is not replayed — the task stays suspended until someone cancels it and resubmits it as a new task (promptLean in place of promptProfile)」);" +
|
|
511
|
-
"同族注释(每个半句只归本条或 M28 条之一,不重复改;标〔另一条的〕的几处住在另一条迁移的文件 / 头注段里,那条已先删则宿主已不在,跳过):`src/http/checkpoint-ctx.ts`:「两条出路(运维在一次性迁移的窗内重启本服务 ⇒ 起服改写存体、同一请求可再发;否则作为新任务重提,仍停驻的先取消)」改成「出路(作为新任务重提,仍停驻的先取消)」、「**窗的日期不手写**」起到「删法见登记表 M30 的」止整段删、「存体里的旧键由一次性迁移在起服时原地改写」改成「存体里的旧键没有迁移改写」、「(M30,`stored-request-prompt-profile-m30.ts`,行改写经本模块的 {@link rewriteStoredBodyKeys})。改写不到的残留行」改成「仍带旧键的残留行」、「;存体由 M30 起服改写」删、「与 {@link rewriteStoredBodyKeys}」删、「(存量行非凭据顶层体键的改写,凭据位与读法记号原样随行)」删;`src/http/wire-types.ts`:「由一次性迁移 M30 在起服时按同一张映射原地改写」改成「没有迁移改写」、「(`stored-request-prompt-profile-m30.ts`;M30 · 窗口见 `plugins/one-time-migrations.ts` 登记表)」删;`src/spec-fields.ts`:「由一次性迁移 M30 在起服时改写成 `promptLean`(`stored-request-prompt-profile-m30.ts`),」改成「不改写,」;`src/boot/stage-06-runners.ts`:「M30(存体里的退役请求键 `promptProfile` 原地改写)同在这里、」删、「(同一只 ctx 行改写店腿;不要封签器),同样早于任何续跑入口。」删;`src/plugins/checkpoint-store-
|
|
469
|
+
"同族注释(每个半句只归本条或 M28 条之一,不重复改;标〔另一条的〕的几处住在另一条迁移的文件 / 头注段里,那条已先删则宿主已不在,跳过):`src/http/checkpoint-ctx.ts`:「两条出路(运维在一次性迁移的窗内重启本服务 ⇒ 起服改写存体、同一请求可再发;否则作为新任务重提,仍停驻的先取消)」改成「出路(作为新任务重提,仍停驻的先取消)」、「**窗的日期不手写**」起到「删法见登记表 M30 的」止整段删、「存体里的旧键由一次性迁移在起服时原地改写」改成「存体里的旧键没有迁移改写」、「(M30,`stored-request-prompt-profile-m30.ts`,行改写经本模块的 {@link rewriteStoredBodyKeys})。改写不到的残留行」改成「仍带旧键的残留行」、「;存体由 M30 起服改写」删、「与 {@link rewriteStoredBodyKeys}」删、「(存量行非凭据顶层体键的改写,凭据位与读法记号原样随行)」删;`src/http/wire-types.ts`:「由一次性迁移 M30 在起服时按同一张映射原地改写」改成「没有迁移改写」、「(`stored-request-prompt-profile-m30.ts`;M30 · 窗口见 `plugins/one-time-migrations.ts` 登记表)」删;`src/spec-fields.ts`:「由一次性迁移 M30 在起服时改写成 `promptLean`(`stored-request-prompt-profile-m30.ts`),」改成「不改写,」;`src/boot/stage-06-runners.ts`:「M30(存体里的退役请求键 `promptProfile` 原地改写)同在这里、」删、「(同一只 ctx 行改写店腿;不要封签器),同样早于任何续跑入口。」删;`src/plugins/checkpoint-store-face.ts`:「、M30(退役请求键改写)」删;`src/plugins/one-time-migrations.ts`:〔另一条的〕「M30 用同一只;」删;`src/checkpoint-ctx-seal-m28.ts`:〔另一条的〕「(M30 用同一只)」删;`test/task-agents-876.test.ts`:「体由一次性迁移 M30 在起服时原地改写」改成「体没有迁移改写」;`test/allow-list-reading-park-refusal.test.ts`:「一次性迁移 M30 没改写到的残留」改成「没有迁移改写的残留」;`test/api-error-text-freeze.test.ts`:「一次性迁移 M30 没改写到的残留」改成「没有迁移改写的残留」、「洞 = 窗的最后一天(绝对日期)」起到「不手写。」止整段删;" +
|
|
512
470
|
"`http/stored-body-replay.ts` 里 `RETIRED_KEY_REWRITE_MIGRATION` 的 JSDoc 随表删;" +
|
|
513
471
|
"`http/stored-body-replay.ts` 的 `RETIRED_KEY_REWRITE_MIGRATION`(`satisfies Record<ReplayRefusedRetiredKey, string>`:M30 删后 `promptProfile` 仍是退役键,这张表只能整张删)、" +
|
|
514
472
|
"判据里 `rewriteWindowEnd: migrationWindowEnd(…)` 那一项与 `migrationWindowEnd` 的引入行;`plugins/one-time-migrations.ts` 导出的 `migrationWindowEnd` 在无别的读者时一起删;" +
|
|
@@ -611,7 +569,7 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
611
569
|
removal: "**删码前提**:本服务已不支持回滚到引擎 7.61.0 之前的版本(更早的引擎的导入门会重新铸出这种 add,本条要在每次起服把它们收掉)—— 窗关时仍支持这种回滚 ⇒ 本行两格顺延(改日期,并在本注里写明为什么),不删。" +
|
|
612
570
|
"删什么:`src/plugins/imported-layer-root-retirement.ts` 整个文件;migrateStepsOn 的 M36 步(规则表与 `grammar` 列的在场探针 + 对 `retireImportedLayerRootAllows` 的调用)与握锁连接上的 `query` 口" +
|
|
613
571
|
"(`LockedMigrationDb` 与 `mysqlDb` / `pgDb` 里的那一员,若届时再无别的步骤用它);`permission-rule-store-sql.ts` 的 `listRuleBucketOwners` / `isSqlBucketRefusal` / `isSqlBucketVanished` / `RuleBucketVanishedError`(取点那一句的具名类,届时若再无别的读者按类判它,收回成裸错)/ `IMPORT_RECORD_KIND`;" +
|
|
614
|
-
"`permission-rule-store-file.ts` 的 `FileRuleApprovalRecordStore.importRecordOwners`;`store-backend.ts` 的 `LocalBackend.runOneTimeMigrations` 里 M36 那一腿(规则目录在场判与那一处调用)与报告两键的那两行;" +
|
|
572
|
+
"`permission-rule-store-file.ts` 的 `FileRuleApprovalRecordStore.importRecordOwners` / `fileRuleBucketOwners` / `isFileBucketDamaged`;`store-backend.ts` 的 `LocalBackend.runOneTimeMigrations` 里 M36 那一腿(规则目录在场判与那一处调用)与报告两键的那两行;" +
|
|
615
573
|
"本文件的 `createSqlImportedLayerRootSource` 与 `importedLayerRootAllowsRetired` / `importedLayerRootBucketsSkipped`(报告 / 收据 / `changedAnything` / `readingsSnapshot` / `readingFields` / `receiptSentence` / `NO_SQL_MIGRATIONS` 的排除表)、" +
|
|
616
574
|
"`imported_layer_root_allow_retired` / `imported_layer_root_bucket_skipped` 两行 warn 与 `importedLayerRootSkipNote`、读数行 note 里的 M36 句与头注 M36 段;" +
|
|
617
575
|
"`test/imported-layer-root-retirement.test.ts`、`test/imported-layer-root-retirement-db-integration.test.ts`(连同 `scripts/db-integration-files.json` 里它那一行)与 `test/helpers/imported-layer-root-fixture.ts` 整文件。" +
|
|
@@ -632,6 +590,20 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
632
590
|
"幂等重入走 park、回决口按要人",
|
|
633
591
|
reportKeys: [],
|
|
634
592
|
},
|
|
593
|
+
{
|
|
594
|
+
id: "M38",
|
|
595
|
+
introducedIn: "7.146.0",
|
|
596
|
+
releasedOn: "2026-11-06",
|
|
597
|
+
removableAfter: "2026-12-06",
|
|
598
|
+
removal: "删 `src/stored-request-env-credentials-m38.ts` 整只文件(`storedEnvCredentialsDropM38`);" +
|
|
599
|
+
"`boot/resolve-spec.ts` 里凭据判据那一段的重放腿分支(`opts?.leg !== \"fresh\" && storedEnvCredentialsDropM38(…)` 那一臂、`withoutKeys` 那一行、`settings_env_credentials_dropped` 那一行 warn)与 `storedEnvCredentialsDropM38` / `withoutKeys` 的 import —— 判据命中改为两腿一律抛,`settingsEnv` 改回 `const`;" +
|
|
600
|
+
"`task-settings.ts` 的 `withoutKeys`(`readSettingsEnv` 一只读法、`ParseTaskSettingsSeats.settingsEnv` 座与 `resolveSpec` 两腿递它**不删**:判据与装配读同一份是常设的,不随窗走;删后 `reaching` 不再出现 `{}`,`SettingsEnvLayer` 文档里那半句一起删);" +
|
|
601
|
+
"`http/stored-body-replay.ts` 预判那一臂里的窗问(`storedEnvCredentialsDropM38(…)`,删后命中即拒)与它的 import;" +
|
|
602
|
+
"`test/settings-env-credential.test.ts` 里窗开的三格(剥键照续 / 剥空登记空表 / 预判窗开不拦)与「窗关当天仍开」那格、`withM38Window` 助手(窗关的几格改成不注入窗直接断言拒)、M38 登记行那一格;本文件头注 M38 段",
|
|
603
|
+
afterRemoval: "没有新的臂,接住它的是窗关之后的读法(删码零行为变化:窗关那一刻起剥键臂已经不生效):存体 `settings.env` 里仍带凭据条目的停驻行,续跑前的预判拒(409 `resume_blocked_by_policy`,`blockedBy: request.env_credential_refused`,机读位点名键与命中类),卡仍 pending —— " +
|
|
604
|
+
"出路是取消那条 run,把凭据挪进引擎进程环境后重新提交。会撞上它的是活过窗的升级前停驻行:发布后才升级的部署、调长了 `APPROVAL_TERMINAL_BACKSTOP_MS` 的部署、滚动升级里旧副本在窗内新写的行、窗内续跑过又停驻到窗外的任务(头注 M38 段)",
|
|
605
|
+
reportKeys: [],
|
|
606
|
+
},
|
|
635
607
|
];
|
|
636
608
|
export function migrationWindowOpen(window, today) {
|
|
637
609
|
return window.removableAfter === null || today <= window.removableAfter;
|
|
@@ -645,8 +617,6 @@ export function migrationWindowEnd(id) {
|
|
|
645
617
|
return row.removableAfter;
|
|
646
618
|
}
|
|
647
619
|
export const NO_SQL_MIGRATIONS = {
|
|
648
|
-
allowRuleShadowRowsMigrated: 0,
|
|
649
|
-
allowRuleShadowRowsUnreadable: 0,
|
|
650
620
|
workflowParkIndexKey: "file-ledger",
|
|
651
621
|
workflowParkIndexRowsCarried: 0,
|
|
652
622
|
undurableScopeRuleRows: [],
|
|
@@ -777,13 +747,6 @@ async function migrateOn(db, dialect, input) {
|
|
|
777
747
|
return completedReport(receipts);
|
|
778
748
|
}
|
|
779
749
|
async function migrateStepsOn(db, dialect, receipts, input) {
|
|
780
|
-
receipts.holderDeathCodeRowsBackfilled += await db.exec(dialect === "mysql"
|
|
781
|
-
? "UPDATE task_run SET error_code = ? WHERE status = 'failed' AND error_code IS NULL AND error = ?"
|
|
782
|
-
: "UPDATE task_run SET error_code = $1 WHERE status = 'failed' AND error_code IS NULL AND error = $2", [RUN_HOLDER_DEATH_CODES.stalled, RUN_STALLED_ERROR]);
|
|
783
|
-
receipts.holderDeathCodeRowsBackfilled += await db.exec(dialect === "mysql"
|
|
784
|
-
? "UPDATE task_run SET error_code = ? WHERE status = 'failed' AND error_code IS NULL AND (error = ? OR error LIKE ?)"
|
|
785
|
-
: "UPDATE task_run SET error_code = $1 WHERE status = 'failed' AND error_code IS NULL AND (error = $2 OR error LIKE $3)", [RUN_HOLDER_DEATH_CODES.orphaned, RUN_ORPHANED_ERROR, `${RUN_ORPHANED_ERROR} (%`]);
|
|
786
|
-
await migrateShadowedRuleKey(db, dialect, receipts);
|
|
787
750
|
await migrateRetiredCardWords(db, dialect, receipts);
|
|
788
751
|
await splitApprovalAskCauseColumns(db, dialect, receipts);
|
|
789
752
|
await reshapeWorkflowParkIndex(db, dialect, receipts);
|
|
@@ -1409,54 +1372,6 @@ async function finishParkIndexShape(db, dialect) {
|
|
|
1409
1372
|
if (typeof name === "string" && name !== conventional)
|
|
1410
1373
|
await db.exec(`ALTER TABLE ${WORKFLOW_PARK_INDEX_TABLE} RENAME CONSTRAINT ${name} TO ${conventional}`);
|
|
1411
1374
|
}
|
|
1412
|
-
const RETIRED_SHADOWED_RULE_KEY = "shadowedRule";
|
|
1413
|
-
export function migrateShadowedRuleDescriptor(text) {
|
|
1414
|
-
let parsed;
|
|
1415
|
-
try {
|
|
1416
|
-
parsed = decodeJsonColumn(text, readNonNullJsonValueColumn, "checkpoint.risk_descriptor (M8 rewrite)");
|
|
1417
|
-
}
|
|
1418
|
-
catch (error) {
|
|
1419
|
-
if (isJsonColumnBodyProblem(error))
|
|
1420
|
-
return { kind: "unreadable", error };
|
|
1421
|
-
throw error;
|
|
1422
|
-
}
|
|
1423
|
-
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
1424
|
-
return { kind: "untouched" };
|
|
1425
|
-
const { [RETIRED_SHADOWED_RULE_KEY]: old, ...rest } = parsed;
|
|
1426
|
-
if (typeof old !== "string")
|
|
1427
|
-
return { kind: "untouched" };
|
|
1428
|
-
const next = Object.hasOwn(rest, "allowRuleShadowed") ? rest : { ...rest, allowRuleShadowed: [{ member: "persisted", entries: [old] }] };
|
|
1429
|
-
return { kind: "rewrite", text: JSON.stringify(next) };
|
|
1430
|
-
}
|
|
1431
|
-
const SHADOWED_RULE_BATCH = 500;
|
|
1432
|
-
async function migrateShadowedRuleKey(db, dialect, receipts) {
|
|
1433
|
-
const like = `%"${RETIRED_SHADOWED_RULE_KEY}"%`;
|
|
1434
|
-
let after = "";
|
|
1435
|
-
for (;;) {
|
|
1436
|
-
const rows = await db.rows(dialect === "mysql"
|
|
1437
|
-
? `SELECT token, ${jsonColumnText(dialect, "risk_descriptor")} FROM checkpoint WHERE ${jsonColumnTextExpr(dialect, "risk_descriptor")} LIKE ? AND token > ? ORDER BY token LIMIT ${SHADOWED_RULE_BATCH}`
|
|
1438
|
-
: `SELECT token, ${jsonColumnText(dialect, "risk_descriptor")} FROM checkpoint WHERE ${jsonColumnTextExpr(dialect, "risk_descriptor")} LIKE $1 AND token > $2 ORDER BY token LIMIT ${SHADOWED_RULE_BATCH}`, [like, after]);
|
|
1439
|
-
for (const r of rows) {
|
|
1440
|
-
const token = String(r.token);
|
|
1441
|
-
after = token;
|
|
1442
|
-
const text = r.risk_descriptor;
|
|
1443
|
-
if (typeof text !== "string")
|
|
1444
|
-
continue;
|
|
1445
|
-
const next = migrateShadowedRuleDescriptor(text);
|
|
1446
|
-
if (next.kind === "unreadable") {
|
|
1447
|
-
receipts.allowRuleShadowRowsUnreadable += 1;
|
|
1448
|
-
continue;
|
|
1449
|
-
}
|
|
1450
|
-
if (next.kind === "untouched")
|
|
1451
|
-
continue;
|
|
1452
|
-
receipts.allowRuleShadowRowsMigrated += await db.exec(dialect === "mysql"
|
|
1453
|
-
? `UPDATE checkpoint SET risk_descriptor = ? WHERE token = ? AND ${jsonColumnTextExpr(dialect, "risk_descriptor")} = ?`
|
|
1454
|
-
: `UPDATE checkpoint SET risk_descriptor = $1 WHERE token = $2 AND ${jsonColumnTextExpr(dialect, "risk_descriptor")} = $3`, [next.text, token, text]);
|
|
1455
|
-
}
|
|
1456
|
-
if (rows.length < SHADOWED_RULE_BATCH)
|
|
1457
|
-
return;
|
|
1458
|
-
}
|
|
1459
|
-
}
|
|
1460
1375
|
const RETIRED_CARD_WORD_PATTERNS = ['%"shadowed"%', '%"governance_unavailable"%'];
|
|
1461
1376
|
const RETIRED_CARD_WORD_BATCH = 500;
|
|
1462
1377
|
function decodeForM18(text, where) {
|
|
@@ -1706,9 +1621,6 @@ export async function inheritPlacedSessionOwners(db, dialect, receipts) {
|
|
|
1706
1621
|
}
|
|
1707
1622
|
function readingFields(r) {
|
|
1708
1623
|
return {
|
|
1709
|
-
holderDeathCodeRowsBackfilled: r.holderDeathCodeRowsBackfilled,
|
|
1710
|
-
allowRuleShadowRowsMigrated: r.allowRuleShadowRowsMigrated,
|
|
1711
|
-
allowRuleShadowRowsUnreadable: r.allowRuleShadowRowsUnreadable,
|
|
1712
1624
|
...(r.workflowParkIndexKey !== undefined ? { workflowParkIndexKey: r.workflowParkIndexKey } : {}),
|
|
1713
1625
|
workflowParkIndexRowsCarried: r.workflowParkIndexRowsCarried,
|
|
1714
1626
|
undurableScopeRuleRowsRemoved: r.undurableScopeRuleRows.length,
|
|
@@ -1759,11 +1671,7 @@ export function logOneTimeMigrations(log, backend, report) {
|
|
|
1759
1671
|
backend,
|
|
1760
1672
|
...readingFields(report),
|
|
1761
1673
|
removableAfter: Object.fromEntries(ONE_TIME_MIGRATIONS.map((w) => [w.id, w.removableAfter])),
|
|
1762
|
-
note: "one-time persisted-data migrations (
|
|
1763
|
-
"holder-death verdict written by an earlier version with only the sentence got the machine-readable code run.stalled / " +
|
|
1764
|
-
"run.orphaned; M7 writes nothing — it is the window of the refusal that keeps a suspended task whose stored allow list was written " +
|
|
1765
|
-
"under an earlier reading from resuming under the current one; M8: parked rows' allow-layer disclosure written by an earlier engine " +
|
|
1766
|
-
"under its old key shadowedRule rewritten to allowRuleShadowed; M9: the workflow park pointer index rebuilt with the key (session, run), " +
|
|
1674
|
+
note: "one-time persisted-data migrations (M9: the workflow park pointer index rebuilt with the key (session, run), " +
|
|
1767
1675
|
"its rows carried over; M10 writes nothing at boot — on the local backend, while its window is open, the first task submitted with a principal " +
|
|
1768
1676
|
"on a session written by an earlier version (which recorded no owner) claims that session for the principal, one session_owner_claimed line per claim; " +
|
|
1769
1677
|
"M11: persisted permission rules whose project scope root is not a complete absolute path — accepted by earlier versions, dropped on every read " +
|
|
@@ -27,9 +27,11 @@ export declare class FileRuleApprovalRecordStore implements RuleApprovalRecordSt
|
|
|
27
27
|
create(record: RuleApprovalRecord): Promise<void>;
|
|
28
28
|
cas(id: string, expectRev: number, next: RuleApprovalRecord): Promise<boolean>;
|
|
29
29
|
/**
|
|
30
|
-
* 一次性迁移 M36(窗口见 `plugins/one-time-migrations.ts` 登记表)在 File
|
|
31
|
-
*
|
|
32
|
-
* `
|
|
30
|
+
* 一次性迁移 M36(窗口见 `plugins/one-time-migrations.ts` 登记表)在 File 店的桶来源之一:本店**导入记录**点名过的每一个属主(逐条记录取、**这里不去重**:
|
|
31
|
+
* 多条记录点名同一属主就重复出现,按桶键去重在退役步)。引擎 File 分区的桶文件按属主名的单向摘要命名,桶的属主不写在文件里;File 腿读的桶集是
|
|
32
|
+
* {@link fileRuleBucketOwners} 取的并集 = 本店导入记录点名的属主 ∪ 引擎 `listBucketOwners().owners`(自 core 7.64.0 起的列桶口:本机属主那只桶与收编标记点名的身份),
|
|
33
|
+
* 所以记录不是 File 腿叫得出桶属主的唯一来源(SQL 店不经记录,直接列规则表)。引擎 `unnamedBuckets` 为什么本步不报、File 侧还剩的缺口,见 `imported-layer-root-retirement.ts` 头注「读哪些桶」。
|
|
34
|
+
* 上一形的记录(Stale 信封)读不出种类 ⇒ 属主读得出就算上(多读一只桶零写,少读一只会漏)。
|
|
33
35
|
* 损坏闸合着 ⇒ 抛(读不全记录就叫不全桶;与本面其余口同一条 fail-closed)。
|
|
34
36
|
*/
|
|
35
37
|
importRecordOwners(): Promise<RuleOwner[]>;
|
|
@@ -96,6 +98,18 @@ export declare class FileRuleImportTicketStore {
|
|
|
96
98
|
}
|
|
97
99
|
/** 三面束在数据根下的目录名(唯一一处;束在第一次装配时建它 —— 没开过规则店的数据根下没有它)。 */
|
|
98
100
|
export declare const FILE_PERMISSION_RULE_DIR = "permission-rules";
|
|
101
|
+
/**
|
|
102
|
+
* M36 File 腿读哪些桶(窗口见 `plugins/one-time-migrations.ts` 登记表;读法见 `imported-layer-root-retirement.ts` 头注「读哪些桶」):
|
|
103
|
+
* 导入记录点名过的属主 ∪ 引擎 File 分区后端列得出名字的属主(本机属主那只桶、收编标记点名的身份)。两源有重 ⇒ 退役步按桶键去重。
|
|
104
|
+
* 引擎列桶口的拒(目录用不了 `bucket_damaged`、列不出 `bucket_unreadable`、坏收编标记)原样抛 ⇒ 起服拒(叫不全桶就不判)。
|
|
105
|
+
*/
|
|
106
|
+
export declare function fileRuleBucketOwners(stores: Pick<FilePermissionRuleStores, "approvals" | "durable">): Promise<readonly RuleOwner[]>;
|
|
107
|
+
/**
|
|
108
|
+
* 这只读桶抛出物是不是引擎 File 分区的**确定性整桶拒**(拒码 `permission_rules.bucket_damaged`:同一份字节每次读都同样拒,读侧零规则、什么都不放行)。
|
|
109
|
+
* 别的都不是:`permission_rules.bucket_unreadable`(一次读失败,带 `errno`;证明不了以后也读不出)、`permission_rules.later_grammar`(更新的引擎写的桶)、
|
|
110
|
+
* 收编标记自己的拒、不带码的抛 —— 一律原样抛、起服拒。按码判,不读句子。
|
|
111
|
+
*/
|
|
112
|
+
export declare function isFileBucketDamaged(e: unknown): boolean;
|
|
99
113
|
/** local 车道的三面束 + 生命周期。`dispose()` 释放 core File durable 分区 provider 的写锁(见 {@link createFilePermissionRuleStores})。 */
|
|
100
114
|
export interface FilePermissionRuleStores extends PermissionRuleStoreBundle {
|
|
101
115
|
durable: FileDurableRulePartitionProvider;
|
|
@@ -2,7 +2,7 @@ import { join } from "node:path";
|
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { readdirSync } from "node:fs";
|
|
4
4
|
import { performance } from "node:perf_hooks";
|
|
5
|
-
import { FileDurableRulePartitionProvider, AppendLog, ensureDir, } from "@sema-agent/core";
|
|
5
|
+
import { FileDurableRulePartitionProvider, PERMISSION_RULES_DAMAGED_BUCKET_CODE, AppendLog, ensureDir, } from "@sema-agent/core";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { DurableRuleScopeSchema, IMPORT_RECORD_KIND, RuleOfferColumn, buildRulePayloadHash, recordOwnerOf, refusedOwnerSentence } from "./permission-rule-store-sql.js";
|
|
8
8
|
import { replayJsonlGuarded } from "../observability/corrupt-read-seat.js";
|
|
@@ -332,6 +332,13 @@ export class FileRuleImportTicketStore {
|
|
|
332
332
|
}
|
|
333
333
|
}
|
|
334
334
|
export const FILE_PERMISSION_RULE_DIR = "permission-rules";
|
|
335
|
+
export async function fileRuleBucketOwners(stores) {
|
|
336
|
+
const listed = stores.durable.listBucketOwners();
|
|
337
|
+
return [...(await stores.approvals.importRecordOwners()), ...listed.owners];
|
|
338
|
+
}
|
|
339
|
+
export function isFileBucketDamaged(e) {
|
|
340
|
+
return typeof e === "object" && e !== null && e.code === PERMISSION_RULES_DAMAGED_BUCKET_CODE;
|
|
341
|
+
}
|
|
335
342
|
export function createFilePermissionRuleStores(root, opts) {
|
|
336
343
|
const dir = join(root, FILE_PERMISSION_RULE_DIR);
|
|
337
344
|
ensureDir(dir);
|
package/dist/plugins/pg-pool.js
CHANGED
|
@@ -3,7 +3,7 @@ import { recordFailOpen } from "../observability/fail-open.js";
|
|
|
3
3
|
import { pollUntilLocked } from "./ensure-schema-lock-policy.js";
|
|
4
4
|
import { RUN_IDENTITY_COLUMNS } from "../identity-source.js";
|
|
5
5
|
import { ensureSchema as ensureSessionSchema } from "./pg-session-storage.js";
|
|
6
|
-
import { ensureSchema as ensureToolResultSchema } from "
|
|
6
|
+
import { ensureSchema as ensureToolResultSchema } from "../stores-sql/tool-result-store-sql.js";
|
|
7
7
|
import { ensureSchema as ensureCostQuotaSchema } from "./pg-cost-quota.js";
|
|
8
8
|
import { ensureSchema as ensureRateLimitSchema } from "./pg-rate-limiter.js";
|
|
9
9
|
import { ensureSchema as ensureBreakerStateSchema } from "./breaker-state-sql.js";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { BaseSessionStorage, type AcquiredSession, type PlacedSessionRow, type SessionHead, type SessionMetadata, type SessionPlacementRecord, type SessionStore, type SessionTreeEntry, type SessionWriteOptions } from "@sema-agent/core";
|
|
2
2
|
import type { Pool, PoolClient } from "pg";
|
|
3
3
|
import type { SessionSummary } from "./store-contracts.js";
|
|
4
|
-
import { type ClientSessionRowWrite, type ReplaySessionRowWrite, type ReplaySessionRowWriteOutcome, type SessionRowPatch, type SessionRowWriteOutcome } from "../session-row.js";
|
|
4
|
+
import { type ClientSessionRowWrite, type ReplaySessionRowWrite, type ReplaySessionRowWriteOutcome, type SessionRowAnswer, type SessionRowPatch, type SessionRowWriteOutcome } from "../session-row.js";
|
|
5
5
|
import { type PlacementAcquireOpts } from "./session-placement.js";
|
|
6
6
|
import { type StagingHandle } from "../session-sync-kernel.js";
|
|
7
7
|
import { type InstructionSourceBaseline } from "../instruction-source-notice.js";
|
|
8
8
|
import type { SessionWorkspace } from "../session-workspace.js";
|
|
9
9
|
import type { RetentionDeclaration } from "@sema-agent/core";
|
|
10
10
|
import { type IndexSpec } from "./ensure-index.js";
|
|
11
|
-
import { type ForkTarget, type ForkToOutcome } from "./session-fork.js";
|
|
11
|
+
import { type ForkPlacement, type ForkTarget, type ForkToOutcome } from "./session-fork.js";
|
|
12
12
|
import { type ExecutionPlacementSeat } from "../execution-placement.js";
|
|
13
13
|
/**
|
|
14
14
|
* PG-dialect DDL for the L1 session log, translated from tidb-pool.ts SCHEMA_STATEMENTS:
|
|
@@ -118,6 +118,17 @@ export declare class PgSessionStore implements SessionStore {
|
|
|
118
118
|
limit: number;
|
|
119
119
|
q?: string;
|
|
120
120
|
}): Promise<SessionSummary[]>;
|
|
121
|
+
/** @see TiDBSessionStore.listSessionRows — the PG twin. */
|
|
122
|
+
listSessionRows(opts: {
|
|
123
|
+
owner?: string;
|
|
124
|
+
includeUnowned?: boolean;
|
|
125
|
+
cursor?: {
|
|
126
|
+
lastActivityAt: string;
|
|
127
|
+
sessionId: string;
|
|
128
|
+
};
|
|
129
|
+
limit: number;
|
|
130
|
+
q?: string;
|
|
131
|
+
}): Promise<Array<SessionRowAnswer<SessionSummary>>>;
|
|
121
132
|
/** @see TiDBSessionStore.sessionSummaryOf — the PG twin (same projection, run-preview subqueries scoped to the id). */
|
|
122
133
|
sessionSummaryOf(sessionId: string): Promise<SessionSummary | undefined>;
|
|
123
134
|
/** @see TiDBSessionStore.listRowOf — the PG twin. */
|
|
@@ -143,8 +154,10 @@ export declare class PgSessionStore implements SessionStore {
|
|
|
143
154
|
/** @see TiDBSessionStore.recordSessionWorkspace — the PG twin (whole-cell overwrite fenced to the occupant; `pgSafeJsonStringify` + `::jsonb`, like every PG JSON write;
|
|
144
155
|
* the general query surface — the pool-wide `DB_QUERY_TIMEOUT_MS` server-side `statement_timeout` bounds it, no per-call client timer). */
|
|
145
156
|
recordSessionWorkspace(sessionId: string, incarnation: string, workspace: SessionWorkspace): Promise<void>;
|
|
146
|
-
/** @see TiDBSessionStore.fork — core 契约 `fork(sourceId, owner?)` = {@link forkTo} 的投影(新铸 uuidv7 目标,`forkByFreshId
|
|
147
|
-
fork(sourceId: string, owner?: string | null
|
|
157
|
+
/** @see TiDBSessionStore.fork — core 契约 `fork(sourceId, owner?, opts?)` = {@link forkTo} 的投影(新铸 uuidv7 目标,`forkByFreshId`;三店同一只;`opts.placement` 进委派分区)。 */
|
|
158
|
+
fork(sourceId: string, owner?: string | null, opts?: {
|
|
159
|
+
placement?: ForkPlacement;
|
|
160
|
+
}): Promise<string | null>;
|
|
148
161
|
/** @see TiDBSessionStore.forkTo — fork 续写的店契约(PG 孪生逐字同义):目标行 meta 先、主键排他;撞已在 ⇒ 回滚后在新视图读目标按属主与 fork 键分类;
|
|
149
162
|
* 读不到 ⇒ 整笔重跑一次,再不行 ⇒ {@link ForkTargetUnsettledError}。 */
|
|
150
163
|
forkTo(sourceId: string, owner: string | null, target: ForkTarget): Promise<ForkToOutcome | null>;
|
|
@@ -320,6 +320,9 @@ export class PgSessionStore {
|
|
|
320
320
|
}
|
|
321
321
|
}
|
|
322
322
|
async listSessions(opts) {
|
|
323
|
+
return (await this.listSessionRows(opts)).map((a) => a.row);
|
|
324
|
+
}
|
|
325
|
+
async listSessionRows(opts) {
|
|
323
326
|
const params = [];
|
|
324
327
|
const ph = (v) => {
|
|
325
328
|
params.push(v);
|
|
@@ -336,7 +339,7 @@ export class PgSessionStore {
|
|
|
336
339
|
const sid = ph(opts.cursor.sessionId);
|
|
337
340
|
where.push(`(sm.updated_at < ${a} OR (sm.updated_at = ${b} AND sm.session_id < ${sid}))`);
|
|
338
341
|
}
|
|
339
|
-
return
|
|
342
|
+
return this.selectListRows({ where, params, limit: opts.limit });
|
|
340
343
|
}
|
|
341
344
|
async sessionSummaryOf(sessionId) {
|
|
342
345
|
return (await this.listRowOf(sessionId))?.row;
|
|
@@ -419,8 +422,8 @@ export class PgSessionStore {
|
|
|
419
422
|
async recordSessionWorkspace(sessionId, incarnation, workspace) {
|
|
420
423
|
await this.pool.query("UPDATE session_meta SET workspace = $1::jsonb WHERE session_id = $2 AND incarnation = $3", [encodeSessionWorkspaceCell(workspace, pgSafeJsonStringify, sessionId), sessionId, incarnation]);
|
|
421
424
|
}
|
|
422
|
-
async fork(sourceId, owner) {
|
|
423
|
-
return forkByFreshId((s, o, t) => this.forkTo(s, o, t), sourceId, owner);
|
|
425
|
+
async fork(sourceId, owner, opts) {
|
|
426
|
+
return forkByFreshId((s, o, t) => this.forkTo(s, o, t), sourceId, owner, opts);
|
|
424
427
|
}
|
|
425
428
|
async forkTo(sourceId, owner, target) {
|
|
426
429
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
@@ -448,7 +451,8 @@ export class PgSessionStore {
|
|
|
448
451
|
try {
|
|
449
452
|
await conn.query("BEGIN");
|
|
450
453
|
try {
|
|
451
|
-
await conn.query("INSERT INTO session_meta (session_id, owner, created_at, updated_at, leaf_id, leaf_seq, incarnation, fork_key
|
|
454
|
+
await conn.query("INSERT INTO session_meta (session_id, owner, created_at, updated_at, leaf_id, leaf_seq, incarnation, fork_key, " +
|
|
455
|
+
"placement_kind, placement_scope, placement_parent_session_id, placement_root_session_id, placement_handle, placed_at) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14)", [target.id, forkOwner, now, now, forkLeafId, rows.length, mintSessionIncarnation(), target.key ?? null, ...placementInsertValues(target.placement, now)]);
|
|
452
456
|
}
|
|
453
457
|
catch (err) {
|
|
454
458
|
if (!isDupKey(err))
|
|
@@ -6,7 +6,7 @@ import { pgSanitizeText } from "./pg-safe-json.js";
|
|
|
6
6
|
import { toIso as iso } from "./sql-row-helpers.js";
|
|
7
7
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
8
8
|
import { createObjectColumnReader, decodeJsonColumn, decodeNullableJsonColumn, foldJsonColumn, isJsonColumnBodyProblem, jsonColumnText, readJsonObjectColumn, readNonNullJsonValueColumn } from "./sql-json-column.js";
|
|
9
|
-
import { RUN_HOLDER_DEATH_CODES, RUN_STALLED_ERROR,
|
|
9
|
+
import { RUN_HOLDER_DEATH_CODES, RUN_STALLED_ERROR, settledLegObservationOf } from "./store-contracts.js";
|
|
10
10
|
import { notifyRunTerminal, runTerminalLogLevel } from "../observability/run-terminal.js";
|
|
11
11
|
import { mysqlDriver, pgDriver, dialectJsonEncoder, SQL_DB_NOW_MS, sqlDbNowMs } from "./sql-driver.js";
|
|
12
12
|
import { isDupKeyError } from "./sql-errors.js";
|
|
@@ -310,7 +310,7 @@ export class SqlRunStore {
|
|
|
310
310
|
status: r.status,
|
|
311
311
|
result: refusing("serve a finished run as if it had produced nothing", () => decodeResultColumn(r.result, String(r.task_id))) ?? null,
|
|
312
312
|
error: r.error ?? null,
|
|
313
|
-
errorCode:
|
|
313
|
+
errorCode: r.error_code ?? null,
|
|
314
314
|
jobId: r.job_id ?? null,
|
|
315
315
|
source: r.source ?? null,
|
|
316
316
|
identity: readRunIdentityCells(r.identity_source, r.identity_scope, r.identity_principal_inc),
|
|
@@ -5,9 +5,9 @@ import { ensurePgMemoryEngineSchema } from "./memory-engine-pg.js";
|
|
|
5
5
|
import { ensurePgMemoryEmbedderMetaSchema } from "./memory-embedder-fingerprint.js";
|
|
6
6
|
import { ensureTiDBMemorySyncSchema, ensureTiDBMemoryHistorySchema } from "./memory-sync-store-tidb.js";
|
|
7
7
|
import { ensurePgMemorySyncSchema, ensurePgMemoryHistorySchema } from "./memory-sync-store-pg.js";
|
|
8
|
-
import { ensureTiDBRosterSchema, ensurePgRosterSchema } from "
|
|
8
|
+
import { ensureTiDBRosterSchema, ensurePgRosterSchema } from "../stores-sql/roster-store-sql.js";
|
|
9
9
|
import { ensureTiDBBackgroundAgentSchema, ensurePgBackgroundAgentSchema } from "../stores-sql/background-agent-store-sql.js";
|
|
10
|
-
import { ensureTiDBMailboxSchema, ensurePgMailboxSchema } from "
|
|
10
|
+
import { ensureTiDBMailboxSchema, ensurePgMailboxSchema } from "../stores-sql/mailbox-store-sql.js";
|
|
11
11
|
import { ensureTiDBTaskAttachmentSchema, ensurePgTaskAttachmentSchema } from "./task-attachment-store.js";
|
|
12
12
|
import { ensureTiDBUsageWindowSchema, ensurePgUsageWindowSchema } from "../stores-sql/usage-window-store-sql.js";
|
|
13
13
|
import { ensureTiDBTaskListSchema, ensurePgTaskListSchema } from "./task-list-store-sql.js";
|
|
@@ -13,10 +13,15 @@
|
|
|
13
13
|
* 吃一只 `Session`):唤醒出来的会话 `getEntry` 在地板之下会回读持久日志,所以判官在压缩过的会话上也看得见整条叶链。
|
|
14
14
|
*
|
|
15
15
|
* ## fork 续写的店契约(本文件下半)
|
|
16
|
-
* 三店同一只私有体 `forkTo(sourceId, owner,
|
|
17
|
-
* local 崩溃中间态 `forking` 只许同键重试补齐 · fork 键此后每个写携带(整段换装经 `carriedRowCells`)。core 契约 `fork(sourceId, owner?)` = {@link forkByFreshId}。
|
|
16
|
+
* 三店同一只私有体 `forkTo(sourceId, owner, target)`:目标行原子新建(唯一创建点)· 撞已在按属主与 fork 键分类({@link classifyForkTarget})·
|
|
17
|
+
* local 崩溃中间态 `forking` 只许同键重试补齐 · fork 键此后每个写携带(整段换装经 `carriedRowCells`)。core 契约 `fork(sourceId, owner?, opts?)` = {@link forkByFreshId}。
|
|
18
|
+
*
|
|
19
|
+
* ## fork 进委派分区(core `SessionStore.fork` 的 `opts.placement`)
|
|
20
|
+
* fork 的创建那一笔就是一次建行:带元组的 fork 与带 placement 的 acquire 落**同一组**元组(六列 / 存档行头,first-write 不可变,`placedAt` 由店铸),
|
|
21
|
+
* 此后这一行欠 placed 行的每一条义务(不上宿主列表 · claim 形 acquire 拒 · 进分区枚举 · release = 真删除)。元组不带属主:行的属主仍是 fork 的属主参数
|
|
22
|
+
* 按 `forkOwnerOf` 的那一读(core 句:元组没有属主)。没声明分区的店照常 fork、不落元组(core 句:忽略合法,拒 fork 不合法)。
|
|
18
23
|
*/
|
|
19
|
-
import { type ForkPoint, type ForkRowShape, type SessionStorage } from "@sema-agent/core";
|
|
24
|
+
import { type ForkPoint, type ForkRowShape, type SessionStorage, type SessionStore } from "@sema-agent/core";
|
|
20
25
|
/** 问引擎:这只(已唤醒的)源会话从哪里拷。SQL 孪生用它;local 店手里就是引擎的 `Session`,直接调 `settledForkOptions`。 */
|
|
21
26
|
export declare function forkPointOf(storage: SessionStorage): Promise<ForkPoint>;
|
|
22
27
|
/** 两只 SQL 孪生整份日志里的一行(两孪生选同一组列):父链两键交引擎挑行,其余三列原样搬进新会话、不读内容。 */
|
|
@@ -33,13 +38,27 @@ export interface ForkLogRow {
|
|
|
33
38
|
*/
|
|
34
39
|
export declare const FORK_LOG_ROW_SHAPE: ForkRowShape<ForkLogRow>;
|
|
35
40
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
41
|
+
* fork 进委派分区时落的元组 —— core `SessionStore.fork` 第三参 `opts.placement` 的那一形,**直接取 core 的型、不复述**(core 当前写作 `SessionPlacement` 去掉属主:行的属主是
|
|
42
|
+
* fork 的属主参数的那一读)。本仓里这个元组型只有这一处定义:三店(local · pg · tidb)、路由店、`forkByFreshId`、引擎面声明的 fork 形参,以及建行绑定值
|
|
43
|
+
* `placementInsertValues`(`session-placement.ts`)都读它 —— core 再改 `fork` 的第三参,型面在这里一处跟着动(`SessionStore.fork` 是可选成员,所以取参数前先 `NonNullable`)。
|
|
44
|
+
*/
|
|
45
|
+
export type ForkPlacement = NonNullable<NonNullable<Parameters<NonNullable<SessionStore["fork"]>>[2]>["placement"]>;
|
|
46
|
+
/**
|
|
47
|
+
* `forkTo` 的目标:调用方给的新会话 id,外加两者之一(或都没有):
|
|
48
|
+
* · `key` —— 服务端拼的不透明串(路由按「源 + 调用方 nonce」派生),存进新行那一格 `fork_key`(SQL)/ `forkKey`(local):一个事实 = 「建这一行的那次 fork 请求的键」;
|
|
49
|
+
* · `placement` —— 新行落进委派分区的元组(见文件头「fork 进委派分区」)。
|
|
50
|
+
* 两者互斥由型面说:带键的是客户端经路由的 fork(一位用户续一只会话,永不 placed —— placement 只走引擎的可信内部链),placed 的是引擎的 fork(后台 fork 子代的转录,
|
|
51
|
+
* 现铸 id、永不带键)⇒ {@link classifyForkTarget} 的重放判(键相等)永远碰不到 placed 目标。都缺 = 非键控、普通的 fork(core 契约的现铸形)。
|
|
38
52
|
*/
|
|
39
|
-
export
|
|
53
|
+
export type ForkTarget = {
|
|
40
54
|
readonly id: string;
|
|
41
55
|
readonly key?: string;
|
|
42
|
-
|
|
56
|
+
readonly placement?: undefined;
|
|
57
|
+
} | {
|
|
58
|
+
readonly id: string;
|
|
59
|
+
readonly placement: ForkPlacement;
|
|
60
|
+
readonly key?: undefined;
|
|
61
|
+
};
|
|
43
62
|
/**
|
|
44
63
|
* fork 键的**唯一**拼法(路由带键 ⇒ `forkTo(…, { id: forkId, key: forkKeyOf(源, forkNonce) })`):服务端拼的不透明串 —— 源 id 与调用方 nonce 的摘要,
|
|
45
64
|
* 定长(远短于 `fork_key` 的 255),源进摘要 ⇒ 「异源同 nonce」拼出不同的键(撞同一只目标即 409,不当重放)。调用方不读它,只靠同键重试同答。
|
|
@@ -78,8 +97,11 @@ export declare class ForkTargetUnsettledError extends Error {
|
|
|
78
97
|
/** 三店的 `forkTo` 形(私有体,经店面 `forkTo` 交出)。 */
|
|
79
98
|
export type ForkToFn = (sourceId: string, owner: string | null, target: ForkTarget) => Promise<ForkToOutcome | null>;
|
|
80
99
|
/**
|
|
81
|
-
* core 契约 `fork(sourceId, owner?) → string | null` = `forkTo(…, { id: uuidv7() })` 的投影(三店同一只):`created` ⇒ 新 id;源不在 ⇒ `null`。
|
|
100
|
+
* core 契约 `fork(sourceId, owner?, opts?) → string | null` = `forkTo(…, { id: uuidv7(), placement? })` 的投影(三店同一只):`created` ⇒ 新 id;源不在 ⇒ `null`。
|
|
101
|
+
* `opts.placement` 原样进目标(落不落由店判:声明了分区的店落,没声明的忽略 —— 各店 `forkTo` 一处)。
|
|
82
102
|
* 新铸的 uuidv7 撞上已在的行(`occupied` / `replayed`)不是一个答案,是不变量破 ⇒ 响亮抛 —— 无键请求永不答 `replayed`。
|
|
83
103
|
*/
|
|
84
|
-
export declare function forkByFreshId(forkTo: ForkToFn, sourceId: string, owner: string | null | undefined
|
|
104
|
+
export declare function forkByFreshId(forkTo: ForkToFn, sourceId: string, owner: string | null | undefined, opts?: {
|
|
105
|
+
placement?: ForkPlacement;
|
|
106
|
+
}): Promise<string | null>;
|
|
85
107
|
//# sourceMappingURL=session-fork.d.ts.map
|
|
@@ -26,9 +26,10 @@ export class ForkTargetUnsettledError extends Error {
|
|
|
26
26
|
this.name = "ForkTargetUnsettledError";
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
export async function forkByFreshId(forkTo, sourceId, owner) {
|
|
29
|
+
export async function forkByFreshId(forkTo, sourceId, owner, opts) {
|
|
30
30
|
const id = uuidv7();
|
|
31
|
-
const
|
|
31
|
+
const placement = opts?.placement;
|
|
32
|
+
const out = await forkTo(sourceId, owner ?? null, placement !== undefined ? { id, placement } : { id });
|
|
32
33
|
if (out === null)
|
|
33
34
|
return null;
|
|
34
35
|
switch (out.outcome) {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
* 店上,带 placement 的 acquire 必须回读到**已持久化**且同一元组身份的行,回读缺失/异组=响亮拒。
|
|
35
35
|
*/
|
|
36
36
|
import { type PlacedSessionRow, type SessionPlacement, type SessionPlacementRecord, type SessionStore } from "@sema-agent/core";
|
|
37
|
+
import type { ForkPlacement } from "./session-fork.js";
|
|
37
38
|
/**
|
|
38
39
|
* 三只持久会话店(SQL 两孪生 + local 后端)的**会话耐久声明**(core `SessionStore.durability`:未 placed 的会话活不活过进程重启)——
|
|
39
40
|
* **单源**:三处声明(两孪生类上的顶层 `durability`、`LocalBackend` 交给店的顶层 `durability`)与委派分区的 {@link SESSION_PLACEMENTS}
|
|
@@ -93,8 +94,9 @@ export declare function placementFromRow(row: PlacementColumns | undefined): Ses
|
|
|
93
94
|
* 消费方对它 fail-closed(永不按年龄收割)。一个「无行」与「另一个租户有行」分不清的 join 不许删东西。
|
|
94
95
|
*/
|
|
95
96
|
export declare function placedRowFromRow(sessionId: string, row: PlacementColumns, lastActivityMs?: number): PlacedSessionRow;
|
|
96
|
-
/** 创建时一次落行的六个绑定值(顺序 = {@link PLACEMENT_SELECT_COLUMNS});无 placement ⇒ 六个 NULL
|
|
97
|
-
|
|
97
|
+
/** 创建时一次落行的六个绑定值(顺序 = {@link PLACEMENT_SELECT_COLUMNS});无 placement ⇒ 六个 NULL。读的只是元组(属主不在元组里 —— 它是行的属主格,建行那一笔另记):
|
|
98
|
+
* 带 placement 的 acquire 与带元组的 fork 两个建行点同调。 */
|
|
99
|
+
export declare function placementInsertValues(placement: ForkPlacement | undefined, placedAt: Date): [string | null, string | null, string | null, string | null, string | null, Date | null];
|
|
98
100
|
/** `acquire` 的 opts 面(core `SessionStore.acquire` 的第二参,窄成本模块要判的两键)。 */
|
|
99
101
|
export interface PlacementAcquireOpts {
|
|
100
102
|
requireExisting?: boolean;
|