@sema-agent/settings-schema 15.1.0 → 16.0.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +226 -0
  2. package/README.md +60 -46
  3. package/conformance/VERSION +1 -1
  4. package/conformance/cases/c16-deep-nesting-205/expected.json +2 -2
  5. package/conformance/cases/c16-deep-nesting-205/meta.json +1 -1
  6. package/conformance/cases/c50-s784-lane-host-legal/expected.json +6 -2
  7. package/conformance/cases/c50-s784-lane-host-legal/input.json +3 -1
  8. package/conformance/cases/c51-s784-lane-e2b-legal/expected.json +6 -2
  9. package/conformance/cases/c51-s784-lane-e2b-legal/input.json +3 -1
  10. package/conformance/cases/c52-s784-lane-k8s-legal/expected.json +6 -2
  11. package/conformance/cases/c52-s784-lane-k8s-legal/input.json +3 -1
  12. package/conformance/cases/c53-s784-lane-ssh-legal/expected.json +6 -2
  13. package/conformance/cases/c53-s784-lane-ssh-legal/input.json +3 -1
  14. package/conformance/cases/c54-s784-lane-adb-legal/expected.json +6 -2
  15. package/conformance/cases/c54-s784-lane-adb-legal/input.json +3 -1
  16. package/conformance/cases/c55-s784-lane-local-docker-legal/expected.json +6 -2
  17. package/conformance/cases/c55-s784-lane-local-docker-legal/input.json +3 -1
  18. package/conformance/cases/c56-s784-lane-device-legal/expected.json +8 -2
  19. package/conformance/cases/c56-s784-lane-device-legal/input.json +5 -2
  20. package/conformance/cases/c57-s784-g1-enabled-no-lane/meta.json +1 -1
  21. package/conformance/cases/c58-s784-g2-multitenant-host/input.json +3 -1
  22. package/conformance/cases/c59-s784-g3-k8s-missing-image/input.json +3 -1
  23. package/conformance/cases/c60-s784-g3-e2b-missing-key/input.json +3 -1
  24. package/conformance/cases/c61-s784-g3-other-lane-key/input.json +3 -1
  25. package/conformance/cases/c62-s784-g7a-session-tidb/input.json +3 -1
  26. package/conformance/cases/c63-s784-host-two-replicas/input.json +3 -1
  27. package/conformance/cases/c64-s784-multitenant-local-store/input.json +3 -1
  28. package/conformance/cases/c65-s784-pg-without-db/input.json +3 -1
  29. package/conformance/cases/c66-s784-memory-backend-mismatch/input.json +3 -1
  30. package/conformance/cases/c66-s784-memory-backend-mismatch/meta.json +1 -1
  31. package/conformance/cases/c68-s784-device-local-store/input.json +6 -1
  32. package/conformance/cases/cli04-env-value-with-newline/expected.json +6 -2
  33. package/conformance/cases/cli04-env-value-with-newline/input.json +3 -1
  34. package/dist/cli.d.ts +1 -1
  35. package/dist/config-d-file.d.ts +41 -5
  36. package/dist/config-d-file.js +105 -22
  37. package/dist/config-document-refusal.d.ts +39 -0
  38. package/dist/config-document-refusal.js +2 -0
  39. package/dist/device-relay.d.ts +21 -0
  40. package/dist/device-relay.js +23 -0
  41. package/dist/env-model-table.d.ts +2 -9
  42. package/dist/env-model-table.js +6 -14
  43. package/dist/execution-lane-index.d.ts +21 -17
  44. package/dist/execution-lane-index.js +28 -20
  45. package/dist/execution-lanes.d.ts +20 -5
  46. package/dist/execution-lanes.js +31 -7
  47. package/dist/file-store.d.ts +30 -3
  48. package/dist/file-store.js +89 -32
  49. package/dist/fleet.d.ts +6 -8
  50. package/dist/fleet.js +5 -7
  51. package/dist/hooks.d.ts +1 -1
  52. package/dist/index.d.ts +2 -1
  53. package/dist/index.js +4 -3
  54. package/dist/migration-receipt.d.ts +1 -1
  55. package/dist/migration-receipt.js +1 -1
  56. package/dist/one-time-migrations.d.ts +1 -1
  57. package/dist/one-time-migrations.js +166 -45
  58. package/dist/remote-exec.js +11 -4
  59. package/dist/safety-merge-spec.d.ts +1 -1
  60. package/dist/safety-merge-spec.js +1 -1
  61. package/dist/types.d.ts +15 -11
  62. package/dist/types.js +100 -49
  63. package/dist/url-shape.d.ts +18 -0
  64. package/dist/url-shape.js +22 -0
  65. package/docs/API-SURFACE.md +18 -7
  66. package/docs/CONFORMANCE.md +1 -7
  67. package/docs/CONSUMER-INTEGRATION.md +4 -4
  68. package/llms-full.txt +27 -25
  69. package/llms.txt +10 -8
  70. package/package.json +1 -1
package/llms-full.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  <!--
2
2
  llms-full.txt — 自包含全文 · 消费方(使用者)视角 · @sema-agent/settings-schema
3
- 重写日期: 2026-10-28 | 包版本: 15.1.0
3
+ 重写日期: 2026-10-30 | 包版本: 16.0.0
4
4
  生成方式: 无生成脚本——按当前树 src/*.ts 导出面 + package.json + README/CHANGELOG 手写事实版。
5
5
  证据约定: 每条"它怎么工作"的断言附 (文件: 符号) 坐标,刻意不用行号(行号逐版腐烂;符号名由
6
6
  typecheck 与 test/package-surface.test.ts、test/docs-hygiene.test.ts 等常驻门钉住)。无证据推断显式标【推断】。
@@ -123,10 +123,10 @@ registry:公网 npmjs,无需私有 registry 配置。
123
123
  · systems:接入/凭据元数据(nonce+路由,永不存凭据值;`SystemStatusEntry` 状态行)。
124
124
  · collab:协作模板(0.7.0 取代 teams;slot 引用 models 目录名;预算 `maxTokens`/`maxCost`)。
125
125
  · workers:`WorkerSpec[]`(fleet 声明;`image` 默认值为公开 worker 镜像名、reconciler 白名单强制;
126
- 7.0.0 两个结构块 `runtime.execution { lane, coords, secretRefs }` / `runtime.store { backend, session, memory, db? }`
126
+ 7.0.0 两个结构块 `runtime.execution { lanes, coords, secretRefs }`(16.0.0 起车道集;此前单值 `lane`)/ `runtime.store { backend, session, memory, db? }`
127
127
  (+ `secretRefs.dbPasswordEnv`),enabled 的 worker 两块必填,按 §4.5b 的词表判;`RESERVED_WORKER_ENV` 拒结构化字段
128
128
  (含车道与店产出的全部 env 名)走 env;`WORKER_RESOURCE_PRESETS`;状态形 `WorkerStatus`/`WorkerCondition`)。
129
- · hosts:机器注册表(`HostEntry`,`approved` 门;`HostProbes`/`HostStatus`)。
129
+ · hosts:机器注册表(`HostEntry`,`approved` 门;`HostProbes`/`HostStatus`;16.0.0 起 `HostStatus.ts` 判 RFC 3339 时刻、加可选 `heartbeatMs` 正整数毫秒,无缺省)。
130
130
  · governance:治理三件 `autonomy`(read-only|ask|plan|auto)/ `commandPolicy`(精确 argv[0],DENY-WINS,
131
131
  拒 glob,见 §8 T5)/ `approvalRequire`。
132
132
  · entitlement:`tiers`(`EntitlementTier`:roster/models/visibleSkills/visibleMcp/visiblePlugins/budget/
@@ -255,26 +255,28 @@ entitlement/execution/limits = `none`;`projects` = `salvage`,整域档位仍 `"t
255
255
  timeoutMs?, memory?, cpu?, s3Snapshot?{ endpoint, bucket?, accessKeyEnv, secretKeyEnv, … } }。
256
256
  - `ssh`:{ host!, port?, username!, privateKeyEnv!, mountPath? }。
257
257
  - `adb`:{ serial!, adbPath?, mountPath? }。
258
- (secret 全 env-NAME ref;exec-bound 串拒 NUL。通过校验 ≠ 目标服务版本已从文件驱动该 provider。)
258
+ (secret 全 env-NAME ref;exec-bound 串拒 NUL 与纯空白〔16.0.0:空串同拒,判官 = 车道坐标的 `isBlankCoordinate`,接受的值不 trim〕。通过校验 ≠ 目标服务版本已从文件驱动该 provider。)
259
259
 
260
260
  --- 4.5b 执行车道 + 存储词表正本(src/execution-lanes.ts,主 barrel + `./execution-lanes`,7.0.0,纯数据) ---
261
261
  - `EXECUTION_LANE_WORDS` / `ExecutionLane`:host · e2b · k8s · ssh · adb · local-docker · device(= 引擎 `REMOTE_EXEC` 收的词,
262
262
  逐字同序;无 `in-process`、无 `remote-docker`)。
263
263
  - `RETIRED_LANE_WORDS`(11.0.0):退役车道**值**的墓碑(`[旧词, 去向车道, 怎么配]`;永久、一跳;今一行 remote-docker → local-docker + DOCKER_HOST);
264
- worker 规格 `runtime.execution.lane` 与车道文件 `provider` 读到退役词即拒,拒句 = `retiredLaneWordRefusal(word)`
264
+ worker 规格 `runtime.execution.lanes` 的一格与车道文件 `provider` 读到退役词即拒,拒句 = `retiredLaneWordRefusal(word)`
265
265
  (带出路;issue 码不变)。
266
- - `EXECUTION_LANES: readonly ExecutionLaneRow[]`:每行 `{ lane, tenantSeparation: "supported"|"single-user-only", requiredEnv,
266
+ - `EXECUTION_LANES: readonly ExecutionLaneRow[]`:每行 `{ lane, tenantSeparation: "supported"|"single-user-only", singleReplica, requiredEnv,
267
267
  requiredSecretEnv, optionalEnv, optionalSecretEnv }`(深冻结;四栏 env 名两两不交、跨车道不交;行内容逐格抄自引擎,
268
- 坐标在每行 JSDoc)。`TENANT_SEPARATION_WORDS`。
268
+ 坐标在每行 JSDoc)。`TENANT_SEPARATION_WORDS`。`singleReplica`(16.0.0):执行目标挂在一个副本上(host:副本自己的文件系统;device:设备连上的那一个副本)——
269
+ 声明了这种车道的 worker 只能一个副本。device 行的非密必需栏 = `DEVICE_RELAY_URL`(16.0.0;设备拨哪里:ws(s) 绝对 URL 或字面 `none`,值判官 `deviceRelayFlaws`,包根)。
269
270
  k8s 行的非密必需栏 = `K8S_SANDBOX_IMAGE` + `K8S_NAMESPACE`(沙箱 pod 所在的命名空间,部署自己声明;服务端的必需 env 门按本行 `requiredEnv ∪ requiredSecretEnv` 拒启)——
270
271
  写 worker 的 k8s 行时 `runtime.execution.coords` 两键都要给,缺一键 ⇒ 写闸 issue、存下来的 workers 文档整域读不出。
271
- - `isBlankCoordinate(value: string): boolean`(包根,15.1.0):必需坐标的值算不算「缺」的**唯一判官** —— 空串或只含空白(`String.prototype.trim` 认的空白)⇒ `true`,带任何非空白字符 ⇒ `false`;
272
+ - `isBlankCoordinate(value: string): boolean`(包根 15.1.0;`./execution-lanes` 子路径 15.2.0,与包根是同一个函数对象 —— 函数体住在零依赖的叶模块,全包一处定义):必需坐标的值算不算「缺」的**唯一判官** —— 空串或只含空白(`String.prototype.trim` 认的空白)⇒ `true`,带任何非空白字符 ⇒ `false`;
272
273
  不 trim 值、不管值的格式(`" sandboxes "` 不是空白)。写闸对所有车道、所有必需坐标读的就是这一只,消费方在自己一侧问同一个问题调它、不抄第二份。
273
- 它只看已经有的字符串值:「这一键根本没设」由调用方先判(写闸对没设的键另有一句 `requires coords.<键>`),据它拒不拒由调用方按键是必需还是可选决定:写闸只对必需坐标据它拒,可选坐标的空串照收(`K8S_RUNTIME_CLASS` 的空串 = 不用 Kata)。(src/execution-lane-index.ts)
274
- - `STORE_BACKENDS`(mysql/pg/local/memory)、`SESSION_BACKENDS`(memory/mysql/auto)、`MEMORY_ENGINE_BACKENDS`(file/pg/tidb)。
275
- - 判据(都在 `WorkerSpec` schema 里,zod issue 的 `path` 指字段、message 带出路):enabled ⇒ 两块必填;coords / secretRefs 键 ⊆
276
- 表[lane] 对应栏、必需键在场且非空白(空串或只含空白按缺);别车道键点名车道;`requirePrincipal` ∧ single-user-only 车道拒(出路按表现算);host ∧ 副本 > 1
277
- 拒;device ⇒ SQL 店且 session ≠ memory;memory 店 ∧ session mysql 拒;记忆引擎 pg/tidb ∧ session memory 拒;SQL 坐标 ⇔ SQL 店;
274
+ 它只看已经有的字符串值:「这一键根本没设」由调用方先判(写闸对没设的键另有一句 `requires coords.<键>`),据它拒不拒由调用方按键是必需还是可选决定:写闸只对必需坐标据它拒,可选坐标的空串照收(`K8S_RUNTIME_CLASS` 的空串 = 不用 Kata)。(src/execution-lanes.ts)
275
+ - `STORE_BACKENDS`(mysql/pg/local/memory)、`SESSION_BACKENDS`(memory/mysql/auto)、`MEMORY_ENGINE_BACKENDS`(file/pg/mysql;16.0.0 起 `tidb` → `mysql`,旧词拒并指路 SS-M12)。
276
+ - 判据(都在 `WorkerSpec` schema 里,zod issue 的 `path` 指字段、message 带出路):enabled ⇒ 两块必填;`runtime.execution.lanes`(16.0.0)有序、去重、非空,首项缺省;
277
+ coords / secretRefs 的每个键归表里某条声明的车道、每条声明车道的必需键在场且非空白(空串或只含空白按缺),有文法的键(`DEVICE_RELAY_URL`)值合文法;归表外车道的键点名车道;
278
+ `requirePrincipal` ∧ 每条 single-user-only 车道各拒一条(出路按表现算);表里有 `singleReplica` 车道 ∧ 副本 > 1 拒(一条,点名这些车道);旧单值 `runtime.execution.lane` 是墓碑(指路 SS-M12);
279
+ device ∈ lanes ⇒ SQL 店且 session ≠ memory;memory 店 ∧ session mysql 拒;记忆引擎 pg/mysql ∧ session memory 拒;SQL 坐标 ⇔ SQL 店;
278
280
  记忆后端配店;多租户 ⇒ SQL 店;6.x 删除项(`sessionBackend` / `memoryBackend` / `runtime.db` /
279
281
  `coords.tidb*` / `tidbPasswordEnv`)读到即拒并指路迁移。`WorkerSpec` 是 ZodEffects(无 `.shape`):名字判据单独导出 `WORKER_NAME`(src/types.ts)。
280
282
 
@@ -401,7 +403,7 @@ entitlement/execution/limits = `none`;`projects` = `salvage`,整域档位仍 `"t
401
403
  `ModelRefusalsSignal` = `{ entries: Record<条目名, ModelEntryRefusalCode>, plane?: ModelPlaneRefusalCode }`;值只码(不带上游
402
404
  id / provider / 坏字段键 / 句子);码闭集真源在本包:`MODEL_ENTRY_REFUSAL_CODES`(`config.model_no_brain` /
403
405
  `config.model_entry_invalid`)、`MODEL_PLANE_REFUSAL_CODES`(`config.default_model_missing` / `config.model_refused_name_minted` /
404
- `config.model_route_endpoint_missing` / `config.gateway_fallback_without_primary`,镜像引擎组拒码表整族),各配 z.enum + 型;
406
+ `config.model_route_endpoint_missing` / `config.gateway_fallback_without_primary` / `config.catalog_replaces_env_models`;16.0.0 退役 summarize 那一码),各配 z.enum + 型;
405
407
  `readModelRefusals(body)` 一只读口两出口(`/health` 体或已 parse 的公告,与 `readEngineSignal` 同一只私有读口)先判形再按
406
408
  闭集收窄,集外码丢、丢到空 ⇒ `undefined`,只答键不判版本;心跳键 `InstanceAnnouncement.modelRefusals` =
407
409
  `ModelRefusalsWire.optional().catch(undefined)` —— 集外码照过、形坏降为缺席,诊断键永不拖垮心跳;`/health` 一侧 `InstanceHealth`
@@ -527,6 +529,13 @@ entitlement/execution/limits = `none`;`projects` = `salvage`,整域档位仍 `"t
527
529
  - `validateDomain`/`validateRemoteExec` → `ValidateResult`(不 throw 用户数据)、`writeDomainFile`/
528
530
  `domainFilePath`、`listRequiredEnvNames` → `RequiredEnvName[]`。
529
531
  - `exportBundle`/`writeBundle`/`readBundle`(`ConfigBundle` 的键 = `PortableDomain`;11.0.0 起三只函数类型层只收可搬域,非便携域在运行期也拒)。
532
+ - `FileConfigStore.read()` → `FileConfigRead`(16.0.0,`./node`;单读口,取代 15.2.0 的 `inspectBundle`):一次读完 `config.d` 里契约读的每一份文档(全部便携域 + retired 域的墓碑文档,每份只读一次),
533
+ 交一个结局 —— 文件层都读得进 ⇒ `{ kind: "effective", effective, warnings }`(effective 与严读 `getEffective()` 逐位同;读侧告警交成数据,不经 `onWarning`);
534
+ 有文档被拒 ⇒ `{ kind: "refused", refusals, version, warnings }`。每条拒 `ConfigDocumentRefusal`(包根的类型,按 `reason` 判别):`{ document, reason, error }`,`reason` ∈ 闭集词 `CONFIG_DOCUMENT_REFUSAL_REASONS`
535
+ (`empty` 空 / 纯空白〔半写〕· `invalid_json` · `not_object`〔`null` / 数组 / 数 / 串 / 布尔〕· `io`〔在场却读不出;只有 ENOENT 是缺席〕· `too_deep`〔16.0.0:嵌得比整棵目录的内容版本能算的深〕·
536
+ `retired_domain`〔retired 域文档带事实;另带 `migration`〕),`error` 与严读抛的是同一句。次序确定:retired 域文档在前,便携域按 `PORTABLE_DOMAINS`。`version` 与 `FileConfigStore.getVersion()` 同一只函数
537
+ (被拒的文档以「坏文档的指纹」参与,与宽容读的坏文件版本哨兵同一只)。读得出却过不了门控域 schema 的拒不在拒单里,照严读抛。
538
+ 旧出口(`readBundle` / `FileConfigStore` 各读口 / `loadRemoteExec` / 命令行 `migrate`)与新口读同一份判据(`config-d-file` 的读数),抛的还是原来那个对象、那句话。(src/bundle.ts;src/config-d-file.ts;src/config-document-refusal.ts)
530
539
  - 目录形一次性迁移:`migrateConfigDirectory(dir, { documents, io, check? })` → `ConfigDirectoryMigration`(闭集 `kind`:`unreadable`〔读不了目录 / 文件,或某份文档是坏文件;`reason`〕·
531
540
  `no-documents`〔覆盖面内一份文档都没有;带回 `entries` 目录清单〕· `refused`〔迁移步拒或整域终判拒;`refused[]` + `why`〕· `noop` · `pending`〔`check: true` 有改动〕· `applied`〔`written` / `removed` 文件名〕)。
532
541
  语义 = 命令行 `migrate` 的那一条(读目录 → 迁 → 整域终判 → 先写后删 → 原子写),命令行是它的渲染器;`documents` = 调用方读的域名集(覆盖面外不读不判不写不删;拼错的名字抛 `TypeError`;
@@ -548,17 +557,10 @@ entitlement/execution/limits = `none`;`projects` = `salvage`,整域档位仍 `"t
548
557
  --- 4.12 迁移工具(主 barrel) ---
549
558
  - 0.5 → 0.7 的迁移工具(`./migrate` 出口:hosts grandfathering、worker.model 归并计划 / 执行 / diff 门、teams → collab)
550
559
  11.0.0 起删除(窗口早过,全生态零生产读点)。
551
- - `migrateWorkersDomain(rawDoc) → { doc, changed, dropped, refused }`(7.0.0,主 barrel,src/migrate-workers.ts):6.x workers 文档
552
- 一次性抬升到两个结构块;纯、幂等(已迁形同一引用返回);`refused`(不进 `doc`,带 `index` / `field` / `original` 逐字原行 ——
553
- 写回 `doc` 前须按 `index` 放回)= 迁不了的 worker
554
- (enabled 而无 `env.REMOTE_EXEC` 不替运维猜车道);终判**逐行**(8.2.0 起迁过的行与没动的行同一只)= 只含这一行的 workers 域读不读得进
555
- (读侧的 `WorkersConfig`,不另抄保留名表),读不进 ⇒ `refused`;整域读侧只剩认不出名字的条目与跨行唯一性两类。文件形 = bin
556
- `npx @sema-agent/settings-schema migrate-workers <workers.json> [--check]`(bin/settings-schema.mjs;有 refused 一字不写)。有删除窗。
557
- 7.0.1 起 CLI stdout 恰两行:结论行 `outcome=<refused|applied|noop|pending> written=<true|false>` + JSON(取最后一行);`changed` / `dropped`
558
- 仅 `written=true` 时存在,没写时是 `wouldChange` / `wouldDrop`。拒因里的迁移指路 = 一个常量(`npx …` 全名形),只给迁移能搬的键(被删旧键、
559
- 车道键、`DB_BACKEND` / `MEMORY_ENGINE` / `MEMORY_ENGINE_BACKEND`),`PORT` / `MODEL_*` 之类不带。8.0.0 起 `--check` 与真跑过同一只
560
- 判定(逐只 refused → noop → 整域终判 → 有改动;`--check` 只决定写不写):整域会被拒的文档 `--check` 也报 `refused` / 退出 1,
561
- `refused[]` 逐条带出被拒项(条目没有字符串名字时 `name` 为 null)。(src/cli.ts;src/execution-lane-index.ts)
560
+ - 7.0.0 的 workers 一次性抬升函数与它的文件形子命令,11.0.0 起已删:6.x workers 行的改写进一次性迁移 SS-M4(`./one-time-migrations` 的
561
+ `migrateStoredDocuments`;目录形 bin `npx @sema-agent/settings-schema migrate <config.d directory>`),逐行终判单立成永久读语义 `readWorkersRows`。
562
+ 16.0.0 再加 SS-M12(15.x workers 行 → 16.0.0 形)。CLI 报告形:stdout 恰两行 —— 结论行 `outcome=<refused|applied|noop|pending> written=<true|false>`
563
+ + JSON(取最后一行;`written=true` 才有 `applied`,没写时是 `wouldApply`)。(src/cli.ts;src/one-time-migrations.ts)
562
564
 
563
565
  --- 4.13 错误契约 ---
564
566
  - **throw**(ZodError 或 Error):`parseDomain`/`buildEffective`/`loadLocalConfig`/`FileConfigStore.get*`
package/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  <!--
2
2
  llms.txt — 消费方(使用者)视角索引 · @sema-agent/settings-schema
3
- 重写日期: 2026-10-28 | 包版本: 15.1.0
3
+ 重写日期: 2026-10-30 | 包版本: 16.0.0
4
4
  生成方式: 无生成脚本——按当前树的 src/*.ts 导出面 + package.json + README/CHANGELOG 手写事实版;
5
5
  每条断言附证据坐标(文件:符号),刻意不用行号(行号随每版腐烂,符号名由 typecheck/test 钉住)。
6
6
  刷新触发: package.json 版号变更(test/docs-hygiene.test.ts D 组钉「包版本:」与 package.json 相等、
@@ -13,8 +13,8 @@ llms.txt — 消费方(使用者)视角索引 · @sema-agent/settings-schema
13
13
  > 依赖 zod ^4.4.0)。它是 sema 栈配置域的**单一真值**:16 个配置域的 zod schema、`EffectiveConfig` 确定性合并、
14
14
  > per-worker roster 解析、跨域引用完整性、`remoteExec` 执行层契约、本地 `config.d/*.json` 读写,外加 hooks /
15
15
  > fleet / scheduler-store / safety-merge-spec / auth·scopes wire 五族纯契约。被 web-admin 产品(舰队管理台)、
16
- > worker 服务、TOC 桌面/CLI 共同消费。**纯被消费**——无服务、永不携带 secret 值;唯一的 bin 是 7.0.0 的一次性迁移
17
- > `npx @sema-agent/settings-schema migrate-workers <file>`。
16
+ > worker 服务、TOC 桌面/CLI 共同消费。**纯被消费**——无服务、永不携带 secret 值;唯一的 bin 是一次性迁移族的目录形
17
+ > `npx @sema-agent/settings-schema migrate <config.d directory>`(11.0.0 起;函数形在 `./one-time-migrations`)。
18
18
  > (package.json: description/exports/engines;README「What's in it」)
19
19
  >
20
20
  > 改名声明:`1.0.0` 起包名 `@sema-agent/settings-schema`;≤`0.19.0` 为 `@sema-agent/registry-core`(冻结)。
@@ -78,6 +78,7 @@ llms.txt — 消费方(使用者)视角索引 · @sema-agent/settings-schema
78
78
  收窄、skills 转 manifest、rosters/entitlement 剥离)。(src/resolve-roster.ts)
79
79
  - 从本地 `config.d/*.json` + `.env` **一把加载**(`loadLocalConfig(root)`,worker 服务与 CLI 共用零漂移);
80
80
  单域坏文件可**容错**(`FileConfigStore.getEffective({tolerant:true})`)。(src/local-load.ts;src/file-store.ts)
81
+ **单读口**(16.0.0):`FileConfigStore.read()`(`./node`)一次读完整个目录,交 effective + 告警,或文件层的类型化拒单 + 版本;每条拒 `{ document, reason, error }`,`reason` ∈ 包根的闭集词 `CONFIG_DOCUMENT_REFUSAL_REASONS`(empty / invalid_json / not_object / io / too_deep / retired_domain;墓碑拒另带 `migration`);次序确定(retired 域在前,便携域按 `PORTABLE_DOMAINS`),严读(`readBundle` / `getEffective`)照旧抛同一句。(src/file-store.ts;src/config-d-file.ts;src/config-document-refusal.ts)
81
82
  - **secret 边界**:密钥字段一律 env-NAME(`ENV_NAME` 正则强制,拒 secret 形状字面量),浏览器端封箱的
82
83
  sealed-box 形(`SealedApiKey`);`collectEnvRefs` 列出全部引用。自由文本写口(`extraBody` / `compat` / `headers` / URL / mcp 参数 / 插件源 / ssh 登录 /
83
84
  worker env / 车道坐标 / 覆盖值)经同一只 `containsSecretToken` 拒 secret 形状;10.0.0 起私钥 PEM 头在串中**任意位置**都拒(此前只认串首;读原文 + 前三层百分号解码),
@@ -86,11 +87,12 @@ llms.txt — 消费方(使用者)视角索引 · @sema-agent/settings-schema
86
87
  - `remoteExec` 执行层契约:6 个 provider(host / local-docker / e2b / k8s / ssh / adb),判别字段 `provider`;
87
88
  每个 provider 词 ⊆ 车道词表(7.0.0 删 `remote-docker`:引擎零读点)。(src/remote-exec.ts: `RemoteExecSpec`)
88
89
  - **执行车道 + 存储的词表正本**(7.0.0,纯数据):`EXECUTION_LANE_WORDS`(host / e2b / k8s / ssh / adb / local-docker / device)、
89
- `EXECUTION_LANES`(每车道 `tenantSeparation`〔supported 行另带依据 `tenantSeparationBasis`:isolation / principal-binding,11.0.0 判别联合〕+ 它读的 env 名四栏)、退役车道值墓碑 `RETIRED_LANE_WORDS` + 拒句 `retiredLaneWordRefusal(word)`(11.0.0)、`STORE_BACKENDS` / `SESSION_BACKENDS` / `MEMORY_ENGINE_BACKENDS`。
90
- 必需坐标的值算不算「缺」的唯一判官 `isBlankCoordinate(value)`(包根,15.1.0:空串或只含空白 ⇒ true;写闸读的同一只,消费方在自己一侧问同一个问题调它;「键没设」由调用方先判,据它拒不拒由调用方按键的必需 / 可选决定〔写闸只对必需坐标据它拒〕;src/execution-lane-index.ts)。
90
+ `EXECUTION_LANES`(每车道 `tenantSeparation`〔supported 行另带依据 `tenantSeparationBasis`:isolation / principal-binding,11.0.0 判别联合〕+ `singleReplica`〔16.0.0〕+ 它读的 env 名四栏;device 行必需 `DEVICE_RELAY_URL`〔16.0.0,值判官 `deviceRelayFlaws`〕)、退役车道值墓碑 `RETIRED_LANE_WORDS` + 拒句 `retiredLaneWordRefusal(word)`(11.0.0)、`STORE_BACKENDS` / `SESSION_BACKENDS` / `MEMORY_ENGINE_BACKENDS`(file / pg / mysql)。
91
+ worker 声明有序车道集 `runtime.execution.lanes`(16.0.0,首项缺省;旧单值 `lane` 是墓碑)。
92
+ 必需坐标的值算不算「缺」的唯一判官 `isBlankCoordinate(value)`(包根与 `./execution-lanes` 子路径同一个函数对象〔包根 15.1.0、子路径 15.2.0〕:空串或只含空白 ⇒ true;写闸读的同一只,消费方在自己一侧问同一个问题调它;「键没设」由调用方先判,据它拒不拒由调用方按键的必需 / 可选决定〔写闸只对必需坐标据它拒〕;src/execution-lanes.ts)。
91
93
  WorkerSpec 的 `runtime.execution` / `runtime.store` 两块按这张表判(写闸 = `WorkerSpec.safeParse`,拒因在 zod issue 里);
92
- 6.x 存量 workers 文档在 `parseDomain` 之前跑一次 `migrateWorkersDomain`(或 bin `npx @sema-agent/settings-schema migrate-workers`;7.0.1 起 stdout = 结论行 `outcome=… written=…` + JSON,没写时 `wouldChange` 取代 `changed`)。
93
- (src/execution-lanes.ts;src/types.ts: `WorkerSpec`;src/migrate-workers.ts)
94
+ 存量 workers 行由一次性迁移改写(6.x 行 SS-M4、15.x 行 SS-M12;`migrateStoredDocuments` / bin `npx @sema-agent/settings-schema migrate <config.d directory>`),逐行终判是读侧的 `readWorkersRows`。
95
+ (src/execution-lanes.ts;src/types.ts: `WorkerSpec`;src/one-time-migrations.ts)
94
96
  - **hooks 契约**:33 个 hook 事件的全集 + owner 表 + 逐事件输入/输出形 + 配置面:hook 条目五种 type(`HOOK_ENTRY_TYPES`,含 `mcp_tool`)与**一只**
95
97
  坏形分类器 `classifyHooksConfig(settingsDoc)`(非守卫事件坏块逐个剔、守卫事件 PreToolUse / PermissionRequest 任何坏处或守卫迹象 ⇒ 整份拒;码 + 坐标 + 坏字段名 `field`(坏块是匹配器 / 条目 ⇒ 它上面出问题的键,块不是对象才缺席;一块多个迹象时先该块自身的迹象(自有守卫事件键;条目自己是匹配器形取 `hooks`),再按文档序找嵌套迹象;匹配器下合形条目列表里的迹象归各条目)、零句子、零 zod 自含;
96
98
  闭包里 JS 内建之外只有一个自由名 `HOOK_EVENTS` —— 整函数抄走的生成器(client-core)须把本包运行期导出 `HOOK_EVENTS`(上游常量)注入抄本作用域,不许贴字面事件表),
@@ -136,7 +138,7 @@ llms.txt — 消费方(使用者)视角索引 · @sema-agent/settings-schema
136
138
  - **fleet 契约**(drain / 实例发现 / 派发策略 / 配额租约 / 用量上报;S-741 重启信号 `RestartSignal` 定义一次,
137
139
  11.0.0 起它是引擎状态,两出口只在 `engineSignal` 里读(`readEngineSignal(body)?.restart`;平铺 `restart` 是方言、不读,平铺读口已删),在场 ⇔ 需要重启;
138
140
  S-768 模型拒因同法定义一次:wire 形 `ModelRefusalsWire` = `{ entries: 名 → 码, plane?: 组拒码 }`(码是开放串),
139
- `readModelRefusals(body)` 一只读口读两出口并按闭集 `MODEL_ENTRY_REFUSAL_CODES`(2)/ `MODEL_PLANE_REFUSAL_CODES`(4)收窄成
141
+ `readModelRefusals(body)` 一只读口读两出口并按闭集 `MODEL_ENTRY_REFUSAL_CODES`(2)/ `MODEL_PLANE_REFUSAL_CODES`(5)收窄成
140
142
  `ModelRefusalsSignal`,集外码 = 没说;心跳 `InstanceAnnouncement.modelRefusals?` 上形坏 / 集外码都不拖垮心跳;缺席读 `version`,
141
143
  老引擎缺席 = 不可知;8.1.0 additive:`RestartSignal.withheld?`、引擎自铸信号的闭形 `EngineSignal` + `readEngineSignal(health)`
142
144
  (`undefined` = 没有这只信号,不是就绪)、服务租约 API 型 `ServingLeaseRequest` / `ServingLeaseResponse`(`granted` / `denied` / `unknown` 三词闭集,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/settings-schema",
3
- "version": "15.1.0",
3
+ "version": "16.0.0",
4
4
  "description": "Sema settings schema — pure config contract (zod domains + effective-config + roster resolution + ref-integrity + remoteExec) shared by sema-web-admin, sema-server, and the TOC desktop/CLI. One source of truth. (Renamed at 1.0.0 from @sema-agent/registry-core — name and docs only, no behavior change; note the range moves 0.19.0 -> 1.0.0, so a dependency must become ^1.0.0. The old names @sema-agent/registry-core <=0.19.0 and @sema-ai/registry-core remain published, frozen, for migration.)",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",