@sema-agent/server 7.136.0 → 7.137.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 +173 -0
- package/USAGE.md +84 -16
- package/deploy/sema-up/README.md +14 -0
- package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +7 -1
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +7 -1
- package/dist/approval-content-kind.d.ts +6 -0
- package/dist/approval-content-kind.js +7 -0
- package/dist/approval-gate-currency.d.ts +48 -6
- package/dist/approval-gate-currency.js +16 -9
- package/dist/approval-hmac.d.ts +13 -1
- package/dist/approval-hmac.js +1 -1
- package/dist/approval.js +3 -3
- package/dist/auth-bridge.js +2 -2
- package/dist/boot/execution-env.d.ts +24 -1
- package/dist/boot/execution-env.js +69 -6
- package/dist/boot/reapers.d.ts +3 -0
- package/dist/boot/reapers.js +15 -1
- package/dist/boot/resolve-spec.d.ts +4 -0
- package/dist/boot/resolve-spec.js +16 -17
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +3 -1
- package/dist/boot/stage-05-execution-env.js +11 -2
- package/dist/boot/stage-06-runners.d.ts +3 -1
- package/dist/boot/stage-06-runners.js +5 -1
- package/dist/boot/stage-07-capability-layer.d.ts +4 -1
- package/dist/boot/stage-07-capability-layer.js +1 -1
- package/dist/boot/stage-08-reapers.d.ts +4 -1
- package/dist/boot/stage-08-reapers.js +2 -1
- package/dist/boot/stage-09-leader.d.ts +4 -1
- package/dist/boot/stage-10-http-server.d.ts +4 -1
- package/dist/boot/stage-10-http-server.js +3 -2
- package/dist/boot/stores.d.ts +1 -1
- package/dist/broker/broker.d.ts +89 -0
- package/dist/broker/broker.js +287 -0
- package/dist/broker/constants.d.ts +39 -0
- package/dist/broker/constants.js +15 -0
- package/dist/broker/http1.d.ts +111 -0
- package/dist/broker/http1.js +256 -0
- package/dist/broker/lease-book.d.ts +87 -0
- package/dist/broker/lease-book.js +142 -0
- package/dist/broker/lease-file.d.ts +60 -0
- package/dist/broker/lease-file.js +127 -0
- package/dist/broker/main.d.ts +2 -0
- package/dist/broker/main.js +20 -0
- package/dist/capabilities/composite-members.d.ts +2 -1
- package/dist/capabilities/composite-members.js +2 -1
- package/dist/capabilities/engine-capabilities.js +1 -0
- package/dist/capabilities/scenarios.d.ts +23 -8
- package/dist/capabilities/scenarios.js +13 -8
- package/dist/capabilities/skills.d.ts +28 -5
- package/dist/capabilities/skills.js +8 -0
- package/dist/center-credential-renewer.js +5 -1
- package/dist/checkpoint-ctx-seal-m28.d.ts +3 -10
- package/dist/checkpoint-ctx-seal-m28.js +1 -1
- package/dist/checkpoint-identity.d.ts +3 -3
- package/dist/config-catalog.js +9 -6
- package/dist/config-types.d.ts +9 -0
- package/dist/config.d.ts +1 -1
- package/dist/config.js +34 -8
- package/dist/deployment-governance.d.ts +2 -2
- package/dist/deployment-governance.js +7 -9
- package/dist/device-ws-protocol.d.ts +1 -0
- package/dist/device-ws-protocol.js +2 -1
- package/dist/file-history-disclosure.d.ts +4 -2
- package/dist/file-history-disclosure.js +2 -0
- package/dist/hooks/classic-stations.d.ts +11 -54
- package/dist/http/admission.js +10 -7
- package/dist/http/approval-sweeps.js +4 -3
- package/dist/http/caller-trust.d.ts +2 -1
- package/dist/http/caller-trust.js +1 -3
- package/dist/http/checkpoint-ctx.d.ts +48 -7
- package/dist/http/checkpoint-ctx.js +40 -0
- package/dist/http/dispatch.js +15 -10
- package/dist/http/durable-run-leg.d.ts +5 -1
- package/dist/http/durable-run-leg.js +1 -1
- package/dist/http/health-self-report.d.ts +2 -2
- package/dist/http/mcp-remote-text.d.ts +5 -0
- package/dist/http/mcp-remote-text.js +7 -0
- package/dist/http/principal-gate.d.ts +15 -10
- package/dist/http/principal-gate.js +48 -9
- package/dist/http/resume-legs.d.ts +2 -20
- package/dist/http/resume-legs.js +52 -38
- package/dist/http/route-ctx.d.ts +8 -2
- package/dist/http/routes/approvals-assistant.js +18 -4
- package/dist/http/routes/capabilities.js +11 -1
- package/dist/http/routes/mcp-reconnect.d.ts +1 -1
- package/dist/http/routes/mcp-reconnect.js +5 -7
- package/dist/http/routes/runs.js +2 -1
- package/dist/http/routes/session-sync.js +42 -6
- package/dist/http/routes/sessions.js +2 -1
- package/dist/http/routes/tasks.js +8 -6
- package/dist/http/server.d.ts +4 -0
- package/dist/http/stored-body-replay.d.ts +3 -3
- package/dist/http/stored-body-replay.js +6 -1
- package/dist/http/wire-types.d.ts +52 -27
- package/dist/identity-source.d.ts +65 -0
- package/dist/identity-source.js +45 -0
- package/dist/memory-store-refusal.d.ts +3 -3
- package/dist/model-entry-refusal.d.ts +2 -0
- package/dist/model-entry-refusal.js +11 -0
- package/dist/model-select.d.ts +6 -17
- package/dist/model-select.js +0 -3
- package/dist/namespaced-rule-name.d.ts +1 -1
- package/dist/observability/fail-open.d.ts +13 -1
- package/dist/observability/fail-open.js +13 -1
- package/dist/observability/metrics.js +1 -1
- package/dist/observability/run-terminal.js +1 -0
- package/dist/operator-ask.d.ts +2 -2
- package/dist/org-delivery-gate.js +1 -1
- package/dist/org-memory-admission.d.ts +2 -2
- package/dist/org-memory-admission.js +39 -2
- package/dist/parked-decide.js +3 -2
- package/dist/peer-directory.js +2 -0
- package/dist/permission-rule-list.d.ts +2 -2
- package/dist/plugins/checkpoint-store-sql.d.ts +19 -9
- package/dist/plugins/checkpoint-store-sql.js +6 -6
- package/dist/plugins/file-history-store-sql.js +7 -14
- package/dist/plugins/file-run-store.js +8 -2
- package/dist/plugins/k8s-exec-protocol.d.ts +69 -13
- package/dist/plugins/k8s-exec-protocol.js +116 -28
- package/dist/plugins/k8s-pod-delete-failure.d.ts +25 -0
- package/dist/plugins/k8s-pod-delete-failure.js +17 -0
- package/dist/plugins/k8s-pod-reaper.d.ts +112 -0
- package/dist/plugins/k8s-pod-reaper.js +122 -0
- package/dist/plugins/local-checkpoint-store.d.ts +3 -6
- package/dist/plugins/local-checkpoint-store.js +3 -3
- package/dist/plugins/memory-run-store.js +2 -0
- package/dist/plugins/one-time-migrations.d.ts +28 -9
- package/dist/plugins/one-time-migrations.js +48 -5
- package/dist/plugins/permission-rule-store-file.js +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +17 -17
- package/dist/plugins/permission-rule-store-sql.js +16 -17
- package/dist/plugins/pg-pool.js +4 -0
- package/dist/plugins/pg-session-storage.js +2 -2
- package/dist/plugins/remote-env-adb.d.ts +3 -0
- package/dist/plugins/remote-env-adb.js +1 -0
- package/dist/plugins/remote-env-device.d.ts +3 -0
- package/dist/plugins/remote-env-device.js +4 -0
- package/dist/plugins/remote-env-e2b.d.ts +3 -0
- package/dist/plugins/remote-env-e2b.js +1 -0
- package/dist/plugins/remote-env-file-error.d.ts +8 -1
- package/dist/plugins/remote-env-file-error.js +7 -1
- package/dist/plugins/remote-env-host.d.ts +7 -1
- package/dist/plugins/remote-env-host.js +7 -1
- package/dist/plugins/remote-env-k8s.d.ts +137 -10
- package/dist/plugins/remote-env-k8s.js +276 -14
- package/dist/plugins/remote-env-local-docker.d.ts +3 -0
- package/dist/plugins/remote-env-local-docker.js +1 -0
- package/dist/plugins/remote-env-ssh.d.ts +3 -0
- package/dist/plugins/remote-env-ssh.js +1 -0
- package/dist/plugins/run-store-sql.js +10 -4
- package/dist/plugins/session-ownership.d.ts +17 -3
- package/dist/plugins/session-ownership.js +19 -5
- package/dist/plugins/sql-errors.d.ts +23 -2
- package/dist/plugins/sql-errors.js +15 -0
- package/dist/plugins/store-contracts.d.ts +10 -1
- package/dist/plugins/store-fault.d.ts +2 -2
- package/dist/plugins/store-fault.js +4 -2
- package/dist/plugins/tidb-pool.js +7 -0
- package/dist/plugins/tidb-session-store.js +2 -2
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +31 -2
- package/dist/request-value-closure.js +7 -1
- package/dist/rule-entry-list.d.ts +3 -2
- package/dist/rule-entry-list.js +2 -2
- package/dist/rules-consent.js +7 -4
- package/dist/run-local.d.ts +2 -2
- package/dist/runs.js +2 -1
- package/dist/runtime-governance.d.ts +5 -5
- package/dist/sandbox-git-lease.d.ts +49 -0
- package/dist/sandbox-git-lease.js +60 -0
- package/dist/sandbox-git-plane.d.ts +84 -0
- package/dist/sandbox-git-plane.js +105 -0
- package/dist/security.d.ts +16 -4
- package/dist/security.js +8 -3
- package/dist/server-secret-env.d.ts +6 -0
- package/dist/server-secret-env.js +14 -0
- package/dist/session-error-wire.d.ts +14 -6
- package/dist/session-error-wire.js +2 -1
- package/dist/session-policy-wire.d.ts +1 -1
- package/dist/session-policy-wire.js +2 -2
- package/dist/session-sync.d.ts +1 -1
- package/dist/spec-fields.d.ts +43 -13
- package/dist/spec-fields.js +33 -12
- package/dist/stored-request-prompt-profile-m30.d.ts +49 -0
- package/dist/stored-request-prompt-profile-m30.js +25 -0
- package/dist/task-mcp.d.ts +1 -1
- package/dist/task-settings.d.ts +2 -2
- package/dist/tool-approval.d.ts +12 -2
- package/dist/tool-approval.js +8 -3
- package/dist/tool-rule-names.d.ts +5 -0
- package/dist/trace/core-keyset-guard.d.ts +4 -4
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.js +2 -2
- package/dist/trace/ledger-sink.d.ts +4 -5
- package/dist/trace/ledger-sink.js +3 -7
- package/dist/trace/project.d.ts +37 -3
- package/dist/trace/project.js +20 -6
- package/dist/trace/redact.d.ts +18 -6
- package/dist/trace/redact.js +118 -53
- package/dist/trace/self-minted-wire.d.ts +377 -3
- package/dist/trace/self-minted-wire.js +122 -0
- package/dist/trace/wire-projection-faces.d.ts +5 -3
- package/dist/trace/wire-projection-faces.js +7 -3
- package/dist/web-admin-client/apply-effective.js +0 -1
- package/dist/web-admin-client/center-request.d.ts +20 -2
- package/dist/web-admin-client/center-request.js +40 -5
- package/dist/web-admin-client/http-client.js +6 -6
- package/dist/web-admin-client/types.d.ts +5 -5
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +11 -5
- package/package.json +2 -2
- package/wire-changes/server@7.137.0.json +825 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { compileSessionRuleBucket, isGateKind, readSessionRulesShape, unreadableDenyEntries } from "@sema-agent/core";
|
|
2
2
|
import { APPROVAL_GATE_KINDS, ASK_USER_QUESTION_TOOL_NAME, isApprovalGateKind } from "../approval-content-kind.js";
|
|
3
3
|
import { judgeCheckpointIndexCells } from "./checkpoint-index-columns.js";
|
|
4
4
|
import { dialectProtocolJsonEncoder } from "./sql-driver.js";
|
|
@@ -210,7 +210,8 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
210
210
|
removal: "删模式词读法记号的判据与拒臂:`http/stored-body-replay.ts` 的 `permissionModeReadingUnstated`;`http/checkpoint-ctx.ts` 的 `permissionModeReadingStated` / `permissionModeReadingRefusal` / `PERMISSION_MODE_READINGS`、" +
|
|
211
211
|
"`StoredBodyReplayRefusal` 的 `permission_mode_reading` 臂及其日志字段与答复臂、`buildCheckpointCtx` 与 `withPermissionModeRewritten` 两处记号写点" +
|
|
212
212
|
"(后者删后 `resume-legs.ts` `drivePlanReview` 里对它的那一处调用回到只换体的 `{ ...ctx, body }`)、`CheckpointCtx.permissionModeReading`、" +
|
|
213
|
-
"`http/stored-body-replay.ts` 里 `StoredReplayDeployment` 的 `autonomy` 位与 `storedBodyReplayRefusal` 读 `deployment.autonomy` 的那一句(这一位只服务这一问;四个问点传 `deps.config` 整份,home 位还服务 `permissions` 一问,不动)"
|
|
213
|
+
"`http/stored-body-replay.ts` 里 `StoredReplayDeployment` 的 `autonomy` 位与 `storedBodyReplayRefusal` 读 `deployment.autonomy` 的那一句(这一位只服务这一问;四个问点传 `deps.config` 整份,home 位还服务 `permissions` 一问,不动);" +
|
|
214
|
+
"`test/stored-request-prompt-profile-m30.test.ts` 的 SHARED 表里 `StoredBodyReplayRefusal` 那一行(rows 含 M12;M30 的登记行组已先删时该表已不在,这一句无事可做):rows 去掉 M12、整行并入同文件的 SITES(值 = 该行的 files 数组)",
|
|
214
215
|
afterRemoval: "没有响亮臂:删码之后仍停驻、在 7.121.x 及以前写下的行(把 `APPROVAL_TERMINAL_BACKSTOP_MS` 调长的部署,或跳过了带本条的版本直接升的库)在设了 " +
|
|
215
216
|
"`AUTONOMY=plan` 的部署上按体里的原词重放(运维的 plan 不再被按段重钳)—— 升级前把这些停驻的 run 决掉 / 取消,或升级窗内设 `AUTONOMY=read-only`",
|
|
216
217
|
reportKeys: [],
|
|
@@ -428,8 +429,13 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
428
429
|
introducedIn: "7.134.0",
|
|
429
430
|
releasedOn: "2026-10-21",
|
|
430
431
|
removableAfter: "2026-11-20",
|
|
431
|
-
removal: "删 `src/checkpoint-ctx-seal-m28.ts`
|
|
432
|
-
"`http/checkpoint-ctx.ts` 的 `sealStoredCheckpointCtxM28`;`test/checkpoint-ctx-seal-m28.test.ts`
|
|
432
|
+
removal: "删 `src/checkpoint-ctx-seal-m28.ts` 整个文件(`sealCheckpointCtxCredentialsM28`)与起服第 6 段(`src/boot/stage-06-runners.ts`)顶部对 `sealCheckpointCtxCredentialsM28` 的 import 行与对它的那一处调用(连同起服 info 行 `checkpoint_ctx_credentials_sealed`);两孪生共有的 ctx 行改写店腿(`src/plugins/checkpoint-store-sql.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`:「另有各随一条一次性迁移的格」起到「别的文件的行一个都不碰);」止整段删;" +
|
|
433
|
+
"`http/checkpoint-ctx.ts` 的 `sealStoredCheckpointCtxM28`;`test/checkpoint-ctx-seal-m28.test.ts` 整个文件与 `test/checkpoint-ctx-credential-seal-db-integration.test.ts` 里的「[M28] 明文旧行」那一格(它调 `sealStoredCheckpointCtxM28`);" +
|
|
434
|
+
"`test/doc-claims-upgrade-notes.test.ts` ㊵ 组里读这处调用与日志行的三行断言随删(两格本身与其余断言留着;不删就是删码后这两格红):「锚(嵌入方段的每件事实读实现)」格的 `callSites(\"sealCheckpointCtxCredentialsM28\")` 一行;" +
|
|
435
|
+
"「锚(恢复句的每件事实读实现)」格里 guarded 上对 `sealCheckpointCtxCredentialsM28` 调用的断言与对 `logger.info(\"checkpoint_ctx_credentials_sealed\"` 日志行的断言两行;" +
|
|
436
|
+
"`test/stored-request-prompt-profile-m30.test.ts` 里钉起服第 6 段调用次序的那一格(`describe` 名含「起服接线」;M30 删码时才删它,M28 的窗先关,先删 M28 时它要活着)里读 M28 调用位置的 `const m28` 那一行(它用 indexOf 找 `sealCheckpointCtxCredentialsM28` 的调用)与「M28 在那一臂里」「M30 在那一臂里、M28 之后」两条断言,改成只相对 `guard` 比较 M30 的位置;" +
|
|
437
|
+
"依赖本行的格(行一删就红):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 的登记行组已先删时该表已不在,这一句无事可做);" +
|
|
438
|
+
"同族注释(每个半句只归本条或 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-sql.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`)」删;" +
|
|
433
439
|
"**不随本条删**:凭据位密封的常设规则(封口 / 开口 / 闭集 / 读口第四态 / 409 码 / 装配期拒启)",
|
|
434
440
|
afterRemoval: "读口对凭据位上明文的常设拒臂接住:跳过了带本条的版本直接升的库,带明文凭据的停驻行续跑答 409 `conflict.checkpoint_ctx_unsealable`(`reason:\"plaintext\"`)," +
|
|
435
441
|
"行字节不动 —— 出路 = 作为新任务重提(仍停驻的先取消),或升级时先过一次带本条的版本",
|
|
@@ -447,10 +453,46 @@ export const ONE_TIME_MIGRATIONS = [
|
|
|
447
453
|
"(引擎对问答拒收 `sla_timeout`,拒扫腿每拍一条失败,由 `terminal_at_ms` 兜底收割);运维队列行不带卡词。出路 = 升级前答完 / 拒掉停驻的问答,或升级时先过一次带本条的版本",
|
|
448
454
|
reportKeys: ["parkedApprovalCardsBackfilled", "parkedApprovalCardRowsUnreadable", "parkedApprovalCardRowsTooLong"],
|
|
449
455
|
},
|
|
456
|
+
{
|
|
457
|
+
id: "M30",
|
|
458
|
+
introducedIn: "7.137.0",
|
|
459
|
+
releasedOn: "2026-10-25",
|
|
460
|
+
removableAfter: "2026-11-24",
|
|
461
|
+
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`);" +
|
|
462
|
+
"`http/checkpoint-ctx.ts` 的 `rewriteStoredBodyKeys` 与 `CREDENTIAL_SLOT_ROOTS`(若再无别的调用方);两孪生共有的 ctx 行改写店腿(`src/plugins/checkpoint-store-sql.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`:「另有各随一条一次性迁移的格」起到「别的文件的行一个都不碰);」止整段删;" +
|
|
463
|
+
"`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).」," +
|
|
464
|
+
"它的第二参数 `rewriteWindowEnd` 同删(定义处与私有的 `storedBodyReplayArmAnswer` 里 `retired_request_key` 臂上的那一处调用),`StoredBodyReplayRefusal` 的 `retired_request_key` 臂上的必填字段 `rewriteWindowEnd` 同删;" +
|
|
465
|
+
"`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);" +
|
|
466
|
+
"`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 的「出路 = 重提」矛盾;" +
|
|
467
|
+
"改后句:「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)」);" +
|
|
468
|
+
"同族注释(每个半句只归本条或 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-sql.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 没改写到的残留」改成「没有迁移改写的残留」、「洞 = 窗的最后一天(绝对日期)」起到「不手写。」止整段删;" +
|
|
469
|
+
"`http/stored-body-replay.ts` 里 `RETIRED_KEY_REWRITE_MIGRATION` 的 JSDoc 随表删;" +
|
|
470
|
+
"`http/stored-body-replay.ts` 的 `RETIRED_KEY_REWRITE_MIGRATION`(`satisfies Record<RetiredRequestKey, string>`:M30 删后 `promptProfile` 仍是退役键,这张表只能整张删)、" +
|
|
471
|
+
"判据里 `rewriteWindowEnd: migrationWindowEnd(…)` 那一项与 `migrationWindowEnd` 的引入行;`plugins/one-time-migrations.ts` 导出的 `migrationWindowEnd` 在无别的读者时一起删;" +
|
|
472
|
+
"冻结表 `test/api-error-text-freeze.test.ts` 的 `FROZEN_RESULT_BODY_TEMPLATE` 里那一行搬回字面表(删完半句后拒句是整句字面);" +
|
|
473
|
+
"`test/stored-request-prompt-profile-m30.test.ts` 的起服改写组、登记行组、「M28 登记行」组(M28 没先删时它还在:它读本文件顶部的引入与 COMMENTS 表,与登记行组同命)、「M30 起服接线」组(它钉的就是被删的那处调用与起服 info 行)与「M30 的混跑与回滚」组;「M30 的混跑与回滚」组随删:它读登记表头注 M30 段(随本行一起删)与 MIGRATION 7.137.0 节第 4 条(已发布的历史文字,留着不动);doc-claims ㊵ 的「嵌入方一段分清两只迁移的窗」格同样读本行的窗末日,随删(它与 M28 行共读,哪一行先删就先删这一格);「窗关后的残留」组保留,但它里面 (d) 读登记行的 `m30Row()` 用处(期望里的 `rewriteWindowEnd`)与 (d′) 整格随删,`m30Row` 助手随之删;" +
|
|
474
|
+
"`test/checkpoint-ctx-credential-seal-db-integration.test.ts` 的 M30 格与文件头对 `retirePromptProfileRowM30` 的引入行(模块删后这一行不删就是编译红);" +
|
|
475
|
+
"`test/stored-request-prompt-profile-m30.test.ts` 顶部:beforeEach / afterEach 钩子与 store / root 夹具、ctxFiles / bodyOf 助手只服务已删各组 ⇒ 随删;连同已删各组用的引入行一起删(对 `retirePromptProfileM30` 与 `migrationWindowEnd` 的引入、ONE_TIME_MIGRATIONS、vitest 的 beforeEach / afterEach / vi、node:fs、node:path、对 `migrationSectionFor`(`./helpers/migration-section.js`,只服务混跑组)的引入与各 helpers 的引入等;模块与导出删后这几行不删就是编译红),本钉自己的 SITES / SHARED / LOCATORS / COMMENTS 四张表与 codeMentions / commentText / renderComment / checkCommentEdit / checkMintSentence 助手(含 CommentEdit 型)与 LEG_COMMENTS 表及它们的引入(ts / eachNode / parseSource / existsSync)随登记行组删;" +
|
|
476
|
+
"「窗关后的残留」组留下,留下的引入:storedBodyReplayRefusal、storedBodyReplayAnswer、makeConfig、CheckpointCtx 与 vitest 的 describe / expect / it;legacyBody 助手与它用的 TaskRequestBody 也留着;" +
|
|
477
|
+
"`test/doc-claims-upgrade-notes.test.ts` ㊵ 组里读这处调用与日志行的三行断言随删(两格本身与其余断言留着;不删就是删码后这两格红):「锚(嵌入方段的每件事实读实现)」格的 `callSites(\"retirePromptProfileM30\")` 一行;" +
|
|
478
|
+
"「锚(恢复句的每件事实读实现)」格里 guarded 上对 `retirePromptProfileM30` 调用的断言与对 `logger.info(\"checkpoint_ctx_prompt_profile_rewritten\"` 日志行的断言两行。" +
|
|
479
|
+
"**不随本条删**:续跑判据的第四问(退役请求键闭集 `RETIRED_REQUEST_KEYS` / `retiredRequestKeyOf` / `retiredRequestKeyRefusal`,常设)",
|
|
480
|
+
afterRemoval: "续跑判据第四问的常设拒臂接住:跳过了带本条的版本直接升的库(或窗内从没起过本版的部署),体里仍带 `promptProfile` 的停驻行续跑在五个问点上答 409 `checkpoint.unsupported_version`" +
|
|
481
|
+
"(判据 `retired_request_key`,`http/stored-body-replay.ts`)、行字节不动 —— 出路 = 作为新任务重提(`promptLean` 代替 `promptProfile`;仍停驻的先取消),或升级时先过一次带本条的版本并在窗内起服",
|
|
482
|
+
reportKeys: [],
|
|
483
|
+
},
|
|
450
484
|
];
|
|
451
485
|
export function migrationWindowOpen(window, today) {
|
|
452
486
|
return window.removableAfter === null || today <= window.removableAfter;
|
|
453
487
|
}
|
|
488
|
+
export function migrationWindowEnd(id) {
|
|
489
|
+
const row = ONE_TIME_MIGRATIONS.find((w) => w.id === id);
|
|
490
|
+
if (row === undefined)
|
|
491
|
+
throw new Error(`one-time-migrations: the registry has no ${id} row — a sentence that quotes its window outlived the row; delete it with that row`);
|
|
492
|
+
if (row.removableAfter === null)
|
|
493
|
+
throw new Error(`one-time-migrations: ${id} is in the unreleased form (removableAfter: null) — there is no window end to quote yet`);
|
|
494
|
+
return row.removableAfter;
|
|
495
|
+
}
|
|
454
496
|
export const NO_SQL_MIGRATIONS = {
|
|
455
497
|
allowRuleShadowRowsMigrated: 0,
|
|
456
498
|
allowRuleShadowRowsUnreadable: 0,
|
|
@@ -725,8 +767,9 @@ export function oldGrammarEntriesOf(body, rev) {
|
|
|
725
767
|
const toolAllowDropped = (shaped.rules.toolAllow ?? []).filter((e) => earlier.has(e));
|
|
726
768
|
if (toolAllowDropped.length === 0 && body.grammar !== undefined)
|
|
727
769
|
return { toolAllowDropped };
|
|
728
|
-
return { toolAllowDropped, rewritten: { ...body, ...(toolAllow !== undefined ? { toolAllow } : {}), grammar:
|
|
770
|
+
return { toolAllowDropped, rewritten: { ...body, ...(toolAllow !== undefined ? { toolAllow } : {}), grammar: M17_PROVEN_GRAMMAR } };
|
|
729
771
|
}
|
|
772
|
+
const M17_PROVEN_GRAMMAR = 1;
|
|
730
773
|
const RETIRED_BUCKET_PATTERNS = ['%"commandDeny"%', '%"commandAllow"%'];
|
|
731
774
|
async function scanSessionRuleRows(db, dialect, column, patterns, visit) {
|
|
732
775
|
const text = jsonColumnTextExpr(dialect, column);
|
|
@@ -4,7 +4,7 @@ import { readdirSync } from "node:fs";
|
|
|
4
4
|
import { performance } from "node:perf_hooks";
|
|
5
5
|
import { FileDurableRulePartitionProvider, AppendLog, ensureDir, } from "@sema-agent/core";
|
|
6
6
|
import { z } from "zod";
|
|
7
|
-
import { DurableRuleScopeSchema,
|
|
7
|
+
import { DurableRuleScopeSchema, RuleOfferColumn, buildRulePayloadHash, recordOwnerOf, refusedOwnerSentence } from "./permission-rule-store-sql.js";
|
|
8
8
|
import { replayJsonlGuarded } from "../observability/corrupt-read-seat.js";
|
|
9
9
|
import { EDITED_RULE_BREADTH_WARNING_CODES, RULE_APPROVAL_KINDS, RULE_APPROVAL_RECORD_SCHEMA, RULE_APPROVAL_STATES, RULE_BEHAVIORS, readRuleOwner } from "@sema-agent/core";
|
|
10
10
|
const RuleDotSchema = z.object({ actor: z.string().min(1), counter: z.number().int().nonnegative().safe() }).strict();
|
|
@@ -26,7 +26,7 @@ const ApprovalRecordSchema = z
|
|
|
26
26
|
kind: z.enum(RULE_APPROVAL_KINDS),
|
|
27
27
|
state: z.enum(RULE_APPROVAL_STATES),
|
|
28
28
|
candidates: z.array(RuleCandidateSchema),
|
|
29
|
-
offers: z.array(
|
|
29
|
+
offers: z.array(RuleOfferColumn),
|
|
30
30
|
createdAt: z.string(),
|
|
31
31
|
toolCallId: z.string().optional(),
|
|
32
32
|
boundInputHash: z.string().optional(),
|
|
@@ -31,23 +31,23 @@ export declare function writerOfSqlRuleStore(store: DurableRulePartition): Permi
|
|
|
31
31
|
* (下方 `RuleCandidateSchema`;File 店的审批记录读同一只)。
|
|
32
32
|
*/
|
|
33
33
|
export declare const DurableRuleScopeSchema: z.ZodType<RuleScope>;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
},
|
|
34
|
+
/** [ref] §4.1 —— 记录上的 OPTION 结构(core `RuleOffer2`):按 index 引用 `candidates`,绝不携带规则文本副本。
|
|
35
|
+
*
|
|
36
|
+
* 🔴 **形的读法只有 core 的一只**(core 7.56.0 [ref] `readRuleOffer2`;它也是 core 同意入口的记录检查读选项的那一只):不是平记录 / 形不声明的成员 /
|
|
37
|
+
* 下标不是非负安全整数 / 无成员的批 / 段不是串列 / 理由行不恰是段 + 理由 ⇒ `malformed`;种类词或理由词出闭集 ⇒ `unknown_word`。任何一个 problem ⇒ 本列读不出 ⇒
|
|
38
|
+
* 整行 / 整面拒(照本店 JSON 列读回的既有姿势,响亮,不端半截)。本仓不再手写臂表(修前一份逐臂 `.strict()` 的 zod 联合 = 同一个形的第二个读者;
|
|
39
|
+
* 唯一的具名差异是「无成员的批」—— zod 收、读法拒,而 core 的记录检查本来就拒)。成员 disjoint 等语义完整性仍归 core 的读侧检查,店只担保形。
|
|
40
|
+
* 这只 zod 型只是把 core 读法接进本店既有的列读者(`createZodColumnReader`)与记录 schema 的适配,不判任何一格;File 店读本店导出的这一只。 */
|
|
41
|
+
export declare const RuleOfferColumn: z.ZodPipe<z.ZodUnknown, z.ZodTransform<{
|
|
42
|
+
readonly kind: "single";
|
|
43
|
+
readonly candidate: number;
|
|
44
|
+
} | {
|
|
45
|
+
readonly kind: "batch";
|
|
46
|
+
readonly candidates: readonly number[];
|
|
47
|
+
readonly segments?: readonly string[];
|
|
48
|
+
readonly uncoveredSegments?: number;
|
|
49
|
+
readonly uncoveredDetail?: readonly import("@sema-agent/core").UncoveredSegmentDetail[];
|
|
50
|
+
}, unknown>>;
|
|
51
51
|
export declare const PERMISSION_RULE_TABLE = "permission_rule";
|
|
52
52
|
export declare const PERMISSION_RULE_APPROVAL_TABLE = "permission_rule_approval";
|
|
53
53
|
export declare const PERMISSION_RULE_TICKET_TABLE = "permission_rule_ticket";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { applyTombstones, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, foldDelta, isValidDurableScope, parseRuleText, readRowBehavior, screenRuleSyncState, PERMISSION_RULE_WRITER, RULE_ADD_ORIGINS, RULE_APPROVAL_KINDS, RULE_APPROVAL_RECORD_SCHEMA, RULE_APPROVAL_STATES, RULE_BEHAVIORS, RULE_SYNC_DROP_CODES, EDITED_RULE_BREADTH_WARNING_CODES, PERSISTED_RULE_MATCHES,
|
|
3
|
+
import { applyTombstones, assertDeleteDeltaCarriesNoAdd, assertRedemptionNotQuarantined, assertWriteDeltaScopeDurable, foldDelta, isValidDurableScope, parseRuleText, readRowBehavior, screenRuleSyncState, PERMISSION_RULE_WRITER, RULE_ADD_ORIGINS, RULE_APPROVAL_KINDS, RULE_APPROVAL_RECORD_SCHEMA, RULE_APPROVAL_STATES, RULE_BEHAVIORS, RULE_SYNC_DROP_CODES, EDITED_RULE_BREADTH_WARNING_CODES, PERSISTED_RULE_MATCHES, EMPTY_DURABLE_RULE_PARTITION, PERMISSION_RULES_LATER_GRAMMAR_CODE, SESSION_RULES_GRAMMAR, readRuleGrammarStamp, readRuleOwner, principalNameOf, readRuleOffer2, } from "@sema-agent/core";
|
|
4
4
|
import { dialectProtocolJsonEncoder, sqlDbNowMs, SQL_DB_NOW_MS } from "./sql-driver.js";
|
|
5
5
|
import { isMissingColumnError } from "./sql-errors.js";
|
|
6
6
|
import { canonicalJsonStringify } from "@sema-agent/core";
|
|
@@ -90,19 +90,14 @@ const RedeemedDotsSchema = z.record(z.string(), RuleDotSchema);
|
|
|
90
90
|
const RuleEditedSchema = z
|
|
91
91
|
.object({ index: z.number().int().nonnegative().safe(), text: z.string(), at: z.string(), warnings: z.array(z.enum(EDITED_RULE_BREADTH_WARNING_CODES)).optional() })
|
|
92
92
|
.strict();
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
uncoveredDetail: z.array(z.object({ segment: z.string(), reason: z.enum(UNCOVERED_SEGMENT_REASONS) }).strict()).optional(),
|
|
102
|
-
})
|
|
103
|
-
.strict(),
|
|
104
|
-
};
|
|
105
|
-
export const RuleOffer2Schema = z.union([RULE_OFFER2_ARMS.single, RULE_OFFER2_ARMS.batch]);
|
|
93
|
+
export const RuleOfferColumn = z.unknown().transform((raw, ctx) => {
|
|
94
|
+
const read = readRuleOffer2(raw);
|
|
95
|
+
if ("problem" in read) {
|
|
96
|
+
ctx.addIssue({ code: "custom", message: `the stored rule offer does not read (${read.problem})` });
|
|
97
|
+
return z.NEVER;
|
|
98
|
+
}
|
|
99
|
+
return read.offer;
|
|
100
|
+
});
|
|
106
101
|
export const PERMISSION_RULE_TABLE = "permission_rule";
|
|
107
102
|
export const PERMISSION_RULE_APPROVAL_TABLE = "permission_rule_approval";
|
|
108
103
|
export const PERMISSION_RULE_TICKET_TABLE = "permission_rule_ticket";
|
|
@@ -364,7 +359,7 @@ const readTombstonesJson = createZodColumnReader(z.array(RuleTombstoneSchema));
|
|
|
364
359
|
const readQuarantinedJson = createZodColumnReader(z.array(QuarantinedRuleAddRowSchema));
|
|
365
360
|
const readObservedVectorJson = createZodColumnReader(FrontierSchema);
|
|
366
361
|
const readCandidatesJson = createZodColumnReader(z.array(RuleCandidateSchema));
|
|
367
|
-
const readOffersJson = createZodColumnReader(z.array(
|
|
362
|
+
const readOffersJson = createZodColumnReader(z.array(RuleOfferColumn));
|
|
368
363
|
const readRedeemedDotsJson = createZodColumnReader(RedeemedDotsSchema);
|
|
369
364
|
const readEditedJson = createZodColumnReader(RuleEditedSchema);
|
|
370
365
|
async function refusingUnreadableColumns(what, fn) {
|
|
@@ -578,9 +573,13 @@ export class SqlDurableRulePartitionProvider {
|
|
|
578
573
|
this.now = now;
|
|
579
574
|
}
|
|
580
575
|
forPrincipal(principal) {
|
|
581
|
-
if (
|
|
576
|
+
if (principal === undefined || principal === "")
|
|
582
577
|
return EMPTY_DURABLE_RULE_PARTITION;
|
|
583
|
-
|
|
578
|
+
const name = principalNameOf(principal);
|
|
579
|
+
if (name === undefined) {
|
|
580
|
+
throw new Error('the principal given is not a principal name — refusing to resolve a bucket for it; a provided value that names nobody is not "no principal"');
|
|
581
|
+
}
|
|
582
|
+
return new SqlDurableRulePartition(this.db, { kind: "principal", principal: name }, this.now);
|
|
584
583
|
}
|
|
585
584
|
forLocalOwner() {
|
|
586
585
|
return new SqlDurableRulePartition(this.db, { kind: "local-owner" }, this.now);
|
package/dist/plugins/pg-pool.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import pg from "pg";
|
|
2
2
|
import { recordFailOpen } from "../observability/fail-open.js";
|
|
3
3
|
import { pollUntilLocked } from "./ensure-schema-lock-policy.js";
|
|
4
|
+
import { RUN_IDENTITY_COLUMNS } from "../identity-source.js";
|
|
4
5
|
import { ensureSchema as ensureSessionSchema } from "./pg-session-storage.js";
|
|
5
6
|
import { ensureSchema as ensureToolResultSchema } from "./tool-result-store-sql.js";
|
|
6
7
|
import { ensureSchema as ensureCostQuotaSchema } from "./pg-cost-quota.js";
|
|
@@ -32,6 +33,9 @@ export const PG_SCHEMA_STATEMENTS = [
|
|
|
32
33
|
instance_id VARCHAR(64) COLLATE "C",
|
|
33
34
|
job_id VARCHAR(64) COLLATE "C",
|
|
34
35
|
source VARCHAR(64) COLLATE "C",
|
|
36
|
+
-- identity_*: the run's identity tuple (semantics in the MySQL twin, tidb-pool.ts task_run; column definitions' single owner =
|
|
37
|
+
-- src/identity-source.ts RUN_IDENTITY_COLUMNS).
|
|
38
|
+
${RUN_IDENTITY_COLUMNS.pg},
|
|
35
39
|
-- 🔴 **刻意不写 COLLATE C** —— 本表其余字符串列都钉了,只有这一根是例外,理由是实测出来的
|
|
36
40
|
-- (#192,codex 复审 round5;证据 scratchpad/evidence/u6-lower-collate-c.txt):
|
|
37
41
|
-- PG 的 lower() 按**表达式的排序规则**决定大小写映射,而 C 只带 ASCII 映射 ⇒
|
|
@@ -17,7 +17,7 @@ import { BASELINE_IO_DEADLINE_MS, decodeInstructionSource, encodeInstructionSour
|
|
|
17
17
|
import { MANAGED_RETENTION } from "./retention-store-sql.js";
|
|
18
18
|
import { SESSION_META_INCARNATION_COLUMN, carriedIncarnation, headFromRow, incarnationFromCell, mintSessionIncarnation, sessionFaceFromRow } from "../session-incarnation.js";
|
|
19
19
|
import { ensureIndexes } from "./ensure-index.js";
|
|
20
|
-
import { assertFirstOwnerWritable, forkOwnerOf } from "./session-ownership.js";
|
|
20
|
+
import { assertFirstOwnerWritable, forkOwnerOf, isSessionOwnerValue } from "./session-ownership.js";
|
|
21
21
|
import { forkCopyOf, forkPointOf } from "./session-fork.js";
|
|
22
22
|
const isDupKey = isPgUniqueViolation;
|
|
23
23
|
function baselineQuery(text, values) {
|
|
@@ -219,7 +219,7 @@ export class PgSessionStore {
|
|
|
219
219
|
return { session: new StoredSession(storage), sessionId };
|
|
220
220
|
}
|
|
221
221
|
async register(sessionId, owner) {
|
|
222
|
-
if (
|
|
222
|
+
if (!isSessionOwnerValue(owner)) {
|
|
223
223
|
if ((await this.headOf(sessionId)) !== undefined)
|
|
224
224
|
return;
|
|
225
225
|
assertFirstOwnerWritable(sessionId, owner);
|
|
@@ -85,6 +85,9 @@ export declare class RemoteAdbExecutionEnv implements RemoteExecutionEnv {
|
|
|
85
85
|
/** core 7.49.0 [ref]:shell 子进程真拿到的 `CDPATH` 条目 —— 本车道的命令跑在 Android 设备的 shell 里(设备自己的 env),本类不读那份 env ⇒ `"unknown"`(core 契约:说不出就说 unknown,
|
|
86
86
|
* 不许报一张没读过的空表;删除守卫因此对裸 `cd <相对名>` 之后的删除问人,而不是按「没有 CDPATH」放行)。 */
|
|
87
87
|
readonly cdPath: "unknown";
|
|
88
|
+
/** core 7.56.0 [ref]:shell 子进程继承的环境里收不到的条目 —— 本车道 shell 的环境在 Android 设备上**构建**(本进程的 env 从不注入,只有引擎逐次交的 `env`
|
|
89
|
+
* 这条显式授予),没有一条是从本进程继承的 ⇒ `[]`(core 契约:「`[]` when its shell environment is built rather than inherited」)。 */
|
|
90
|
+
readonly withheldEnv: readonly [];
|
|
88
91
|
private readonly cfg;
|
|
89
92
|
private readonly spawnFn;
|
|
90
93
|
private readonly injectedConnectOnce?;
|
|
@@ -89,6 +89,9 @@ export declare class RemoteDeviceExecutionEnv implements RemoteExecutionEnv {
|
|
|
89
89
|
/** core 7.49.0 [ref]:shell 子进程真拿到的 `CDPATH` 条目 —— 本车道的命令跑在设备上(设备自己的 env),本类不读那份 env ⇒ `"unknown"`(core 契约:说不出就说 unknown,
|
|
90
90
|
* 不许报一张没读过的空表;删除守卫因此对裸 `cd <相对名>` 之后的删除问人,而不是按「没有 CDPATH」放行)。 */
|
|
91
91
|
readonly cdPath: "unknown";
|
|
92
|
+
/** core 7.56.0 [ref]:shell 子进程继承的环境里收不到的条目 —— 本车道 shell 的环境在设备上**构建**(本进程的 env 从不注入,只有引擎逐次交的 `env`
|
|
93
|
+
* 这条显式授予),没有一条是从本进程继承的 ⇒ `[]`(core 契约:「`[]` when its shell environment is built rather than inherited」)。 */
|
|
94
|
+
readonly withheldEnv: readonly [];
|
|
92
95
|
/**
|
|
93
96
|
* 🔴 `suspendable: false` 在 core 契约里**同时断言**「工作区在目标上外部持久」(remote-env.ts 的
|
|
94
97
|
* load-bearing 不变量)—— 设备工作区 = 员工机磁盘,真持久 ✅,park-only 降级腿因此合法可用。
|
|
@@ -13,6 +13,7 @@ export const DEVICE_OUTCOME_TO_FILE_ERROR = {
|
|
|
13
13
|
invalid: "invalid",
|
|
14
14
|
is_directory: "is_directory",
|
|
15
15
|
liveness_no_output: "unknown",
|
|
16
|
+
name_too_long: "name_too_long",
|
|
16
17
|
not_directory: "not_directory",
|
|
17
18
|
not_found: "not_found",
|
|
18
19
|
not_supported: "not_supported",
|
|
@@ -35,6 +36,7 @@ export const DEVICE_OUTCOME_TO_EXEC_ERROR = {
|
|
|
35
36
|
invalid: "unknown",
|
|
36
37
|
is_directory: "unknown",
|
|
37
38
|
liveness_no_output: "liveness_no_output",
|
|
39
|
+
name_too_long: "unknown",
|
|
38
40
|
not_directory: "unknown",
|
|
39
41
|
not_found: "unknown",
|
|
40
42
|
not_supported: "shell_unavailable",
|
|
@@ -123,6 +125,7 @@ export class RemoteDeviceExecutionEnv {
|
|
|
123
125
|
cfg;
|
|
124
126
|
homeDir;
|
|
125
127
|
cdPath = "unknown";
|
|
128
|
+
withheldEnv = [];
|
|
126
129
|
capabilities = { isolation: false, suspendable: false, canonicalPathAuthoritative: true };
|
|
127
130
|
externalContentTarget = true;
|
|
128
131
|
hostLocalPaths = false;
|
|
@@ -766,6 +769,7 @@ const OUTCOME_TO_REMOTE_ERROR = {
|
|
|
766
769
|
invalid: "unknown",
|
|
767
770
|
is_directory: "unknown",
|
|
768
771
|
liveness_no_output: "liveness_no_output",
|
|
772
|
+
name_too_long: "unknown",
|
|
769
773
|
not_directory: "unknown",
|
|
770
774
|
not_found: "unknown",
|
|
771
775
|
not_supported: "unsupported",
|
|
@@ -104,6 +104,9 @@ export declare class RemoteContainerExecutionEnv implements RemoteExecutionEnv,
|
|
|
104
104
|
/** core 7.49.0 [ref]:shell 子进程真拿到的 `CDPATH` 条目 —— 本车道的命令跑在 e2b 沙箱里(模板镜像的 env),本类不读那份 env ⇒ `"unknown"`(core 契约:说不出就说 unknown,
|
|
105
105
|
* 不许报一张没读过的空表;删除守卫因此对裸 `cd <相对名>` 之后的删除问人,而不是按「没有 CDPATH」放行)。 */
|
|
106
106
|
readonly cdPath: "unknown";
|
|
107
|
+
/** core 7.56.0 [ref]:shell 子进程继承的环境里收不到的条目 —— 本车道 shell 的环境在沙箱里**构建**(本进程的 env 从不注入,只有引擎逐次交的 `env`
|
|
108
|
+
* 这条显式授予),没有一条是从本进程继承的 ⇒ `[]`(core 契约:「`[]` when its shell environment is built rather than inherited」)。 */
|
|
109
|
+
readonly withheldEnv: readonly [];
|
|
107
110
|
private readonly cfg;
|
|
108
111
|
private readonly sandboxApi;
|
|
109
112
|
/** This lane's own liveness bound — what {@link commandBoundsOf} falls back to when a command's caller stated no bound. */
|
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
import { FileError, type ExecutionError, type RemoteExecutionError } from "@sema-agent/core";
|
|
19
19
|
/** exec 层的错误码 → 文件层的码。只映射**有对应语义**的那些,其余落 `unknown`(诚实降级)。 */
|
|
20
20
|
export declare function fileErrorFromExec(e: ExecutionError | RemoteExecutionError, path?: string): FileError;
|
|
21
|
+
/**
|
|
22
|
+
* core 7.56.0 [ref]:`ENAMETOOLONG` 的**一只读法**(本文件的 stderr 分类器与 host 车道的 errno 映射同调)—— 路径有一段超过 NAME_MAX(按 UTF-8 字节量)⇒
|
|
23
|
+
* `name_too_long`:没有目录装得下这个名字,引擎读站把它读作缺席(与 `not_found` 同读);段都短、只是整条超 PATH_MAX ⇒ `unknown`(那种文件可能存在,从下层目录够得着)。
|
|
24
|
+
* 没有路径可判 ⇒ `unknown`。与 core `NodeExecutionEnv` 同判(按 `/` 与 `\` 切段)。
|
|
25
|
+
*/
|
|
26
|
+
export declare function nameTooLongCode(p: string | undefined): "name_too_long" | "unknown";
|
|
21
27
|
/**
|
|
22
28
|
* shell 命令 exit≠0 时把 **stderr** 分类成 `FileError` 的共享分类器([ref] B6 R2 裁决:k8s 形=正形)。
|
|
23
29
|
*
|
|
@@ -29,7 +35,8 @@ export declare function fileErrorFromExec(e: ExecutionError | RemoteExecutionErr
|
|
|
29
35
|
* 1. 命令缺失形(`command not found` / `applet not found` / `: not found`)→ `unknown` —— 工具不存在
|
|
30
36
|
* 不是文件不存在;probe 族的 not_found fallback 绝不能吞它。
|
|
31
37
|
* 2. 完整硬失败(EIO/ELOOP/ENAMETOOLONG/ENOSPC)→ `unknown` —— 同 k8s 原注:真错不被 read-op 的
|
|
32
|
-
* not_found fallback
|
|
38
|
+
* not_found fallback 吞掉。**例外**(core 7.56.0 [ref]):`ENAMETOOLONG` 且路径有一段超过 NAME_MAX ⇒ `name_too_long`
|
|
39
|
+
* ({@link nameTooLongCode},一只读法,host 车道的 errno 映射同调)—— 那个名字没有目录装得下,是一种「不存在」,不是硬失败。
|
|
33
40
|
*
|
|
34
41
|
* `fallback` 由站点显式给:probe 族(readlink/realpath/stat——"它在吗"类问题)传 `not_found`
|
|
35
42
|
* (空 stderr + exit≠0 的主导原因就是缺文件);mutate 族(mkdir/rm/mktemp)传 `unknown`(诚实降级)。
|
|
@@ -3,11 +3,17 @@ export function fileErrorFromExec(e, path) {
|
|
|
3
3
|
const code = e.code === "aborted" ? "aborted" : "unknown";
|
|
4
4
|
return new FileError(code, e.message, path, e);
|
|
5
5
|
}
|
|
6
|
+
const NAME_MAX_BYTES = 255;
|
|
7
|
+
export function nameTooLongCode(p) {
|
|
8
|
+
return p !== undefined && p.split(/[\\/]/).some((part) => Buffer.byteLength(part, "utf8") > NAME_MAX_BYTES) ? "name_too_long" : "unknown";
|
|
9
|
+
}
|
|
6
10
|
export function classifyFsStderr(stderr, p, fallback = "unknown") {
|
|
7
11
|
const msg = stderr.trim();
|
|
8
12
|
if (/command not found|applet not found|:\s+not found\s*$/im.test(msg))
|
|
9
13
|
return new FileError("unknown", msg, p);
|
|
10
|
-
if (/
|
|
14
|
+
if (/file name too long/i.test(msg))
|
|
15
|
+
return new FileError(nameTooLongCode(p), msg, p);
|
|
16
|
+
if (/input\/output error|too many levels|no space left/i.test(msg))
|
|
11
17
|
return new FileError("unknown", msg, p);
|
|
12
18
|
if (/no such file/i.test(msg))
|
|
13
19
|
return new FileError("not_found", msg, p);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FileError, type InheritEnvPolicy, ExecutionError, RemoteExecutionError, SchedulerError, type SchedulerCapability, type ScheduledIntent, type SchedulerContext, type ScheduledTaskId, type ScheduledTaskSummary, type ExecutionEnv, type RemoteExecutionEnv, type WorkspaceHandle, type FileInfo, type Result, type SymlinkChain, type BoundFileObject, type OutputChunk, type ExecStreamOptions, type RemoteConnectConfig, type SnapshotId, type SessionToken, type VmLifecycleOptions, type ExecutionEnvFactory, BackgroundShellError, type BackgroundShellCapability, type BackgroundShellId, type BackgroundHardKillOutcome, type BackgroundPoll, type BackgroundSpawnOptions } from "@sema-agent/core";
|
|
1
|
+
import { FileError, type InheritEnvPolicy, ExecutionError, RemoteExecutionError, SchedulerError, type SchedulerCapability, type ScheduledIntent, type SchedulerContext, type ScheduledTaskId, type ScheduledTaskSummary, type ExecutionEnv, type RemoteExecutionEnv, type WorkspaceHandle, type FileInfo, type Result, type SymlinkChain, type BoundFileObject, type OutputChunk, type ExecStreamOptions, type RemoteConnectConfig, type SnapshotId, type SessionToken, type VmLifecycleOptions, type ExecutionEnvFactory, BackgroundShellError, type BackgroundShellCapability, type BackgroundShellId, type BackgroundHardKillOutcome, type BackgroundPoll, type BackgroundSpawnOptions, type SecretEnvFinding } from "@sema-agent/core";
|
|
2
2
|
/** Options accepted by `ExecutionEnv.exec` (core does not re-export the type; derive it from the seam). */
|
|
3
3
|
type ExecOpts = Parameters<ExecutionEnv["exec"]>[1];
|
|
4
4
|
/** SIGTERM → grace → SIGKILL (no host isolation). 🔴 宽限的**唯一属主**:本 driver 的 `kill` 梯子用它排升级定时器;会话级收敛
|
|
@@ -101,6 +101,12 @@ export declare class RemoteHostExecutionEnv implements RemoteExecutionEnv, Sched
|
|
|
101
101
|
* {@link hostShell}(win32 上未落定同步抛 —— 修前每条 Bash 的策略链都因此被拒)。
|
|
102
102
|
*/
|
|
103
103
|
get cdPath(): readonly string[];
|
|
104
|
+
/**
|
|
105
|
+
* core 7.56.0 [ref]:shell 子进程继承的环境里**收不到**的条目(名 + 规则,从不带值)—— 与 {@link cdPath} 同一只组合的读面
|
|
106
|
+
* (`server-secret-env.ts` 的 `withheldFromHostSubprocess`:继承组合扣下的发现,减去 `cfg.env` 这条显式授予重供的键)。逐命令的 `options.env`
|
|
107
|
+
* 是引擎自己交的显式授予,它知道(core KL-1963-b 同一残余)。只读:不披露、不计数、不碰 shell。
|
|
108
|
+
*/
|
|
109
|
+
get withheldEnv(): readonly SecretEnvFinding[];
|
|
104
110
|
private readonly workspaceDir;
|
|
105
111
|
private readonly cfg;
|
|
106
112
|
/** Workspace created on disk (lazily, on first use). */
|
|
@@ -11,7 +11,8 @@ import { hostBackgroundShellEnabled, hostExecSpoolEnabled } from "../config.js";
|
|
|
11
11
|
import { IS_WIN32, resolveHostShell, hostShell, pinHostShell, spawnGroupOptions, killTreeHard, killTreeSoft, hardKillGroupNow, collapseWin32EnvKeys, adoptHostForegroundChild } from "./host-platform.js";
|
|
12
12
|
import { BackgroundShellManager, seedMemStream, feedMemStream, drainMemStream } from "./background-shell-support.js";
|
|
13
13
|
import { FileError, NodeExecutionEnv, inheritEnvPolicyProblem, ExecutionError, RemoteExecutionError, RollingTailBuffer, walkSymlinkChain, markTruncated, SchedulerError, BackgroundShellError, } from "@sema-agent/core";
|
|
14
|
-
import { composeHostSubprocessEnv, hostSubprocessEnv } from "../server-secret-env.js";
|
|
14
|
+
import { composeHostSubprocessEnv, hostSubprocessEnv, withheldFromHostSubprocess } from "../server-secret-env.js";
|
|
15
|
+
import { nameTooLongCode } from "./remote-env-file-error.js";
|
|
15
16
|
import { trackEphemeralHostWorkspace, untrackEphemeralHostWorkspace } from "./host-workspace-registry.js";
|
|
16
17
|
const PROVIDER = "host";
|
|
17
18
|
const DEFAULT_COMMAND_TIMEOUT_MS = 30 * 60_000;
|
|
@@ -61,6 +62,9 @@ export class RemoteHostExecutionEnv {
|
|
|
61
62
|
const value = this.childEnv(undefined, undefined).CDPATH;
|
|
62
63
|
return value === undefined || value === "" ? [] : value.split(":");
|
|
63
64
|
}
|
|
65
|
+
get withheldEnv() {
|
|
66
|
+
return withheldFromHostSubprocess({ policy: this.cfg.inheritEnv, allow: [] }, this.cfg.env);
|
|
67
|
+
}
|
|
64
68
|
workspaceDir;
|
|
65
69
|
cfg;
|
|
66
70
|
prepared = false;
|
|
@@ -1331,6 +1335,8 @@ export class RemoteHostExecutionEnv {
|
|
|
1331
1335
|
return new FileError("not_directory", msg, p);
|
|
1332
1336
|
if (code === "EINVAL")
|
|
1333
1337
|
return new FileError("invalid", msg, p);
|
|
1338
|
+
if (code === "ENAMETOOLONG")
|
|
1339
|
+
return new FileError(nameTooLongCode(p), msg, p);
|
|
1334
1340
|
return new FileError("unknown", msg, p);
|
|
1335
1341
|
}
|
|
1336
1342
|
}
|