@sema-agent/settings-schema 1.3.0 → 1.4.1

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/CHANGELOG.md CHANGED
@@ -6,6 +6,90 @@
6
6
  > `@sema-agent/registry-core`(更早还曾是 `@sema-ai/registry-core`)。本档 `0.19.0` 以下各节里的
7
7
  > 包名是**历史记录**,如实保留不追改。
8
8
 
9
+ ## 1.4.1 — 2026-09-02 — 文案 patch(cli [6037]/[6038] 请件)
10
+
11
+ - 复审出处注词族全清:src 12 处+d.ts 同族(`codex …`→`对抗复审 …`,语义零损)——1.4.0 件⑦「52→1」的三族 regex 未含此词族=漏计根因;npm 包注释=对外文案面,壳 bundle hygiene 禁表命中即发布腿红。
12
+
13
+ ## 1.4.0 — 2026-09-02 — settings-schema 批八件(DEBTS-server S-59;新键=minor 按本批成文政策)
14
+
15
+ 七件 = 两把新可选键(①⑥,additive)+ 三件文案/论证面(②③④)+ 一件文档重写(⑤)+ 一件发布物中性化(⑦)。
16
+
17
+ **① `McpServerSpec.contentOrigin?: "local"|"execution"|"external"`(A-075.4 / A-075.111④)** + 新导出
18
+ `MCP_CONTENT_ORIGINS` / `McpContentOrigin`。病:默认 strip 的 zod object 没有该键,部署方写在
19
+ `config.d/mcp.json` 的信任出处声明在本地腿(FileConfigStore)与远端消费腿(readEffectiveWire)各被剥一次,
20
+ 消费方的词表门结构性够不着。修:可选枚举键、无默认(缺席 = 引擎 pre-declaration 行为,fail-closed 全判
21
+ external);表外值 parse 拒(大小写不折——信任词写坏绝不折成合法词)。钉 `test/mcp-content-origin.test.ts`
22
+ 六判据(保值 / 缺席恒缺席 / 拒表外 / 本地 round-trip / wire 透传 / 词表镜像字面量钉——与引擎/消费方的相等由
23
+ 消费方的编译钉+提货门执法,本仓刻意不带引擎依赖轴,钉只拒本地静默改词)。消费方提货后其两条
24
+ `it.fails` 绊线按约翻正(见发布帖点名)。
25
+
26
+ **② `hooks.ts` `SyncHookOutput` 文案(A-075.15)**:「any other exit = non-blocking error (stderr shown to
27
+ the user)」→ 点名消费方真机制——非阻断故障(exit≠0∧≠2 / 超时 / spawn 失败 / 坏 JSON)由 hook-runner 铸
28
+ `hook_non_blocking_failure` 通知(`hook_notice` 帧上任务/fleet 流;stderr 先脱敏后截断 512 字);本包无
29
+ 「展示给用户」的面,用户看到什么取决于其客户端如何渲染该帧。改注不改行为。
30
+
31
+ **③ `LimitsConfig` `.passthrough()` 论证重写(A-075.33)**:原论证依赖「消费方 `^0.x`、脱字号不跨 minor」,
32
+ 1.0.0 改名后消费方段进 1.x(`^1.x` 跨 minor),前提失效。重写为 1.x 语境:键集按消费方发布节奏生长
33
+ (消费方先开键读 env 底、契约层后声明),「认识键→声明键」的窗口由**发包与提货**决定(server 精确 pin /
34
+ cli lockfile 钉住的 `^1.x` 皆需显式提货),与 range 写法无关;默认 strip 会把窗口变成天花板静默回落 env 底。
35
+ **决策与行为零变**(`.passthrough()` 一字未动,`limits-domain-0.19.test.ts` ⑤b 行为钉照旧);补写失效条件
36
+ 与「改回 strip/`.strict()` = 行为面收紧,须走 BREAKING 通道」。同批改 `test/limits-domain-0.19.test.ts` ⑤b
37
+ 注释同口径。
38
+
39
+ **④ README「发版纪律(semver)」1.x 政策成文(A-075.34)**:破坏性(改名/改形/删除/默认值变更/校验收紧
40
+ 或放宽/枚举重排)必 bump **major**;新键/新导出/词表尾插 = **minor**(穷举表消费方提货编译红 = 提货成本,
41
+ 发布走显式表态制点名,不因此升 major——1.2.0/1.3.0 口径,codex 严格 semver 异议原样留档候裁);文案/注释/
42
+ 测试/bug 修复 = **patch**。0.x 规矩撤为历史注记(0.7.1 例外一并归档);CLAUDE.md / ROADMAP /
43
+ docs/CONSUMER-INTEGRATION §9 同步改写;本档 1.0.0 段的旧指路(「1.x 规矩待后续批补」)撤,改指本段。
44
+
45
+ **⑤ `llms.txt` / `llms-full.txt` 重写(A-075.35)**:自 0.1.30(2026-06-23)STALE(15 域时代;错称
46
+ 「无 CHANGELOG、无 git tag」等已烂断言)。无生成脚本,按当前树手写事实版:17 域 / 21 subpath / 31 hook
47
+ 事件 / 7 provider / 五族纯契约(hooks·fleet·scheduler-store·safety-merge-spec·api)全部入档;证据坐标改
48
+ 「文件: 符号」形(行号逐版腐烂);撤 STALE 横幅。防再烂:`test/docs-hygiene.test.ts` D 组把「包版本:」行
49
+ 钉到 package.json、域数/事件数/subpath 数钉到运行时表——**发版 bump 时须同步改两档各一行版本号**。
50
+
51
+ **⑥ `EntitlementRuntimeCaps.allowMemoryOptOut?: boolean`(A-075.99 另半)** + `RUNTIME_CAP_STRICT.
52
+ allowMemoryOptOut = false`。语义对表消费方 `RuntimeCaps.allowMemoryOptOut`(design/383 §3.1):`false` =
53
+ 该 principal 强制留存(opt-out 声明被拒,terminal `memory.capture_optout_denied`);`true` = 显式无限制;
54
+ 缺席 = center 不表态、**不下发键**(三态;隐私轴故障过境契约:resolver 故障 = 键缺席,绝不铸 `false` 替身
55
+ ——`open` 姿态故障放行+具名披露,`governed` 姿态 verdict 缺席拒跑,两臂都以故障为输入)。合成极性 allow*
56
+ 族(`false` 胜,见 RUNTIME_CAP_STRICT)。消费方侧:本地 grant 表优先、center 值其次;其 cap 映射
57
+ (`toCoreRuntimeCaps`)今日**不含**本键,提货后补一行才到引擎——在那之前本键只是「parse 不再剥、wire 承运」
58
+ (窗口如实:center 先发 `false` 而消费方未提货时,引擎仍只读本地 grant 表——与此前「键被静默 strip」相比,多的是 wire 在场 + 成文披露,少的是零;发布协调走表态制点名,消费方提货批同时补映射行与其 contentOrigin 双绊线翻正)。
59
+ 钉 `test/entitlement.test.ts` 末段五格。
60
+
61
+ **⑧ `SAFETY_MERGE_SPEC.sandboxNetwork` 成员级准入 `members`(S-59 件八,cli 上收候件)**:此前 sandboxNetwork
62
+ 是整键类目(global floor 拒/收整块),cli 壳侧「哪个 sandbox 子键算收紧」方向表是临时落点。本版把该表的
63
+ **方向/floor 半场**上收为 11 员闭集 members(全部 `tighten@"local"`,路径形键名:enabled /
64
+ allowUnsandboxedCommands / autoAllowBashIfSandboxed / enableWeakerNestedSandbox / enableWeakerNetworkIsolation /
65
+ network.allowManagedDomainsOnly / network.allowAllUnixSockets / network.allowLocalBinding /
66
+ filesystem.allowManagedReadPathsOnly / filesystem.denyWrite / filesystem.denyRead)。**刻意不入表**(按 1.1.0
67
+ 头注法:未声明成员回落类目 minTrust "global" = 消费方 fail-closed 扣下臂,未来新子键默认被扣):放宽面
68
+ (allowedDomains / allowUnixSockets / allowWrite / allowRead / excludedCommands / ignoreViolations / ripgrep)、
69
+ 可用性硬闸 failIfUnavailable(安全轴收紧但后果=拒启,克隆仓两键 DoS 形,随放宽面同 floor)、
70
+ indeterminate 三条候 cli 对表(httpProxyPort / socksProxyPort / enabledPlatforms,unlisted 即 fail-closed)。
71
+ 布尔成员的**值向极性已建模**(codex 末轮 [high] 采纳——只发方向不发极性会让「按表办事」的消费方在 local
72
+ 层放行 `enabled:false` 这类松极写,比整键现状更松):`MemberAdmission` 增可选 `boolPole {strict, minTrust}`,
73
+ 准入解析改值向(`memberAdmission(类目, 成员, 值?)`,严格相等判极、绝不 truthiness);九个布尔成员行 floor 留在
74
+ 松面 "global" + `boolPole.minTrust:"local"`——**代际安全律**:不识 boolPole 的老 schema 剥掉该键后读到
75
+ tighten@global,对低信任层两极皆扣(fail-closed,只损失低信任收紧的便利,绝不放行松极);两个 deny 数组
76
+ 每种写法都收窄,保持素 tighten@local。红先:双极钉先红(tsc 值参不存在 ×9 + 松极 floor 断言红)→ 建模后绿;
77
+ FROZEN 1.1.0 钉同步断言「1.1.0 消费方看到的剥后视图 = 全布尔 tighten@global」(独立字面量)。
78
+ 类目行五轴(mergeShape/minTrust/tighten/enforcement/seam)一字未动 ⇒ pre-members 消费方整键行为逐字节不变
79
+ (FROZEN 1.1.0 钉演进为「全表相等除 sandboxNetwork;其去 members 后与 1.1.0 字面量相等」——照 FROZEN 1.0.0
80
+ permissions 先例形)。红先:3 新钉先红(members 缺席)→ 加表后 2 旧守钉红(permissions-唯一钉 + 1.1.0 全表钉,
81
+ 证明守钉真在看表)→ 演进后全绿。cli 到货动作:sandboxKeyGate 方向表退役改走 `memberAdmission("sandboxNetwork", 子键)`。
82
+
83
+ **⑦ 发布物内部工艺词中性化(消费方 cli 点名件)**:按其 dist 卫生棘轮三族口径(`board \[\d` /
84
+ `clay (拍|亲|令|裁|定|问责)` / `sema-server\b`)扫**全 src**(不止点名三文件),注释/文档面逐处中性化
85
+ (帖号 → `[ref]`、人名令词 → 「产品裁定/产品令」等角色词、内部仓名 → 「worker 服务/消费方」);另清
86
+ `Clay's decision` 等裸人名形(dist 裸人名现为 0)。**运行期默认值 `image: ….default("sema-server:latest")`
87
+ 一字不动**——成文理由:它是行为面(未显式配 image 的部署实际拉取的镜像名),且是公开镜像名、与 npm 包名
88
+ 同源,非内部工艺词;改它 = 部署可见变更,须走 BREAKING 通道 + 迁移注,不随注释批盲动([5958] 表态原文)。
89
+ 计数(cli 计数法,build 后 literal 视图,三族合计):点名三文件 `dist/types.js` 15→1 / `dist/remote-exec.js`
90
+ 4→0 / `dist/remote-exec.d.ts` 4→0;**全 dist 52→1**,唯一剩余 = 上述默认值行。钉
91
+ `test/docs-hygiene.test.ts` E 组(src 三族零命中、唯一放行行 = 该默认值字面;裸人名零命中)。
92
+
9
93
  ## 1.3.0 — hooks 域加员 `DirectoryAdded`(CC 2.1.219 新事件;`HooksConfig` 拒键病形修复)
10
94
 
11
95
  **`HOOK_EVENTS` 30 → 31:`POST_198_HOOK_EVENTS` **尾插** `DirectoryAdded`(1.2.0 三员声明序逐字节不动;重排 = BREAKING,
@@ -356,8 +440,8 @@ process.exit(tok.length === 0 && erased.length === 0 ? 0 : 1);
356
440
 
357
441
  **不是**「契约进入稳定期 / API 冻结」的语义信号。旧名的 `0.x` 段已走到 `0.19.0`,新名需要一个不与
358
442
  旧段混淆、也不会被 `^0.x` 脱字号规则(0.x 下不跨 minor)拖累的新起点,故直接从 `1.0.0` 开。
359
- ⚠️ README「发版纪律(semver)」一节写的是 `0.x` 破坏性必 bump minor 的旧规矩;`1.x` 段的对应
360
- 规矩(破坏性必 bump major)尚未成文,待后续批补。
443
+ README「发版纪律(semver)」一节当时仍写 `0.x` 破坏性必 bump minor 的旧规矩;`1.x` 段的对应
444
+ 规矩(破坏性必 bump major)已在本档 **Unreleased 段件④** 成文(README 同节改写),此处的指路撤。
361
445
 
362
446
  ### 21 个 subpath 1:1 平移(一个不动)
363
447
 
package/README.md CHANGED
@@ -5,7 +5,8 @@
5
5
  > **这是一次纯改名,不加料**:`0.19.0` → `1.0.0` 之间**零语义变更**——没有字段增删、没有校验收紧
6
6
  > (无 `.strict()` 化)、没有默认值改动、没有行为变化;`exports` 的 **21 个 subpath 一个不动**
7
7
  > (`.` / `./types` / `./node` / `./api/auth` / `./api/wire` …… 逐条 1:1 平移,只换包名前缀)。
8
- > 版号跳到 `1.0.0` **不是**「契约进入稳定期」的语义信号——改名需要一个不与旧 `0.x` 段混淆的新起点而已。
8
+ > 版号跳到 `1.0.0` **不是**「契约进入稳定期」的语义信号——改名需要一个不与旧 `0.x` 段混淆的新起点而已
9
+ > (但自 `1.0.0` 起本包按标准 semver 发版:破坏性 = major,见下文「发版纪律」)。
9
10
  >
10
11
  > **消费方迁移(两步,注意版号段也要动)**:
11
12
  > 1. `package.json` 依赖:`"@sema-agent/registry-core": "^0.19.0"` → `"@sema-agent/settings-schema": "^1.0.0"`。
@@ -129,15 +130,28 @@ local `.env`). This package never carries a credential.
129
130
  Fleet-only domains (`workers`, `hosts`, `systems`) are omitted on a single machine — they resolve to schema
130
131
  defaults. Each `config.d/<domain>.json` is exactly that domain's zod object.
131
132
 
132
- ## 发版纪律(semver)
133
-
134
- - **0.x 破坏性变更必 bump minor**(0.7 → 0.8),不许塞 patch——`^0.7.0` 这类脱字号 range 在 0.x 下
135
- 会自动收 patch,把 BREAKING 塞进 patch = 未 pin 精确版的下游 `npm install` 静默拿到破坏。
136
- - patch 只装:additive 字段、修 bug、文档/测试。commit message 的 `feat!`/`BREAKING` 标记照旧,
137
- 但标记不豁免版号义务。
138
- - **历史注记(0.7.1,2026-07-10)**:0.7.1 携带了两件预协调 BREAKING(撤 governance effective 双写
139
- 镜像、撤 QuotaLease 0.5 `tokens` 别名 shim)——名义上违反本条。当时下游(center/service 1.150.0)
140
- 均已显式迁移、实际破坏面为零,PM 拍板不重发 0.8.0(纯扰动);本段即为该例外的收账与今后的规矩。
133
+ ## 发版纪律(semver,1.x)
134
+
135
+ `1.0.0`(改名)起本包按**标准 semver** 发版;`0.x` 时代的「破坏性变更必 bump minor」规矩**已撤**
136
+ (末条仅作历史注记)。判档看**消费方可见性**,不看 diff 大小:
137
+
138
+ - **破坏性变更必 bump major**:字段/导出改名、改形(retype)、删除、默认值变更、校验收紧或放宽
139
+ (例:`.passthrough()` 默认 strip、宽读 严判)、枚举**重排**——凡是能让一个按上一版契约写的
140
+ 消费方在**运行期**变红、或让同一份配置解析出不同结果的改动;编译期同判,**唯一裁定例外** = 下一条的
141
+ additive 词表尾插(穷举表消费方的编译红按「提货成本」处理,不构成 major,见下条与其留档异议)
142
+ `^1.x` 脱字号**跨 minor**,任何塞进 minor/patch 的破坏都会被未 pin 精确版的下游 `npm install` 静默拿到。
143
+ - **新键 / 新导出 / 词表加词 = minor**(additive):可选键(无默认)、新 subpath、枚举**尾插**新词。
144
+ ⚠️ 「表不动」≠「消费方零感知」:持 `Record<Word, …>` / 穷举 `switch` 的消费方在提货时会编译红——
145
+ 那是**提货成本**,按能力显式表态制 @点名消费方并附迁移句,不因此升 major(1.2.0 / 1.3.0 口径;
146
+ codex 复审持「严格 semver 应升 major」异议,原样留档候裁)。
147
+ - **文案 / 注释 / 测试 / bug 修复 = patch**:不改任何 wire 形、类型面、默认值与校验结果。行为面的
148
+ 「修 bug」若改变了合法输入的解析结果,按上两档判,不按 patch。
149
+ - 契约破坏面动之前先盘 center / server / CLI 三方消费点;commit message 的 `feat!`/`BREAKING` 标记照旧,
150
+ 但标记不豁免版号义务。每版 CHANGELOG 一节,git tag `v<version>` 同名。
151
+ - **历史注记(0.x 时代)**:0.x 下 `^0.7.0` 这类 range 只自动收 patch,故当年规矩是「破坏性必 bump
152
+ minor,patch 只装 additive/修 bug/文档」。0.7.1(2026-07-10)曾携带两件预协调 BREAKING(撤 governance
153
+ effective 双写镜像、撤 QuotaLease 0.5 `tokens` 别名 shim),名义上违反该条;当时下游(center/service
154
+ 1.150.0)均已显式迁移、实际破坏面为零,PM 拍板不重发 0.8.0(纯扰动)。该例外随 1.x 政策一并归档。
141
155
  - 发布(单腿 npmjs,内网腿已废止):`npm run publish:npm`;发后必须 curl 直打 npmjs 复验 shasum。
142
156
 
143
157
  ## 贡献指引
@@ -145,4 +159,4 @@ defaults. Each `config.d/<domain>.json` is exactly that domain's zod object.
145
159
  - 真源 = `sema-agent/sema-settings-schema` org 仓 `main`(2026-08-26 由 sema-registry-core 改名),所有变更直接落 org main(或 PR 进 main);
146
160
  不再向任何个人位/镜像位 push。
147
161
  - 提交门 = `npm run build` + `npx vitest run`;改域/契约后必跑 `npm run e2e`(examples/toc-e2e.mjs)。
148
- - 契约破坏面动之前先盘 center / server / CLI 三方消费点;0.x 破坏性变更必 bump minor(见上节)。
162
+ - 契约破坏面动之前先盘 center / server / CLI 三方消费点;破坏性变更必 bump major(见上节)。
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `api/auth-bridge` — the 鉴权桥 contract: how a WORKER (sema-server / any data-plane service) verifies a
2
+ * `api/auth-bridge` — the 鉴权桥 contract: how a WORKER (the worker service / any data-plane service) verifies a
3
3
  * registry-minted USER access JWT and maps it into its existing `x-agent-principal` identity system.
4
4
  * (REGISTRY-REBUILD-DESIGN §5, M3 — registry half = JWKS already shipped; service half = ONE verifier
5
5
  * middleware implementing the rules below. This file is the schema + normative spec the service copies.)
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `api/auth-bridge` — the 鉴权桥 contract: how a WORKER (sema-server / any data-plane service) verifies a
2
+ * `api/auth-bridge` — the 鉴权桥 contract: how a WORKER (the worker service / any data-plane service) verifies a
3
3
  * registry-minted USER access JWT and maps it into its existing `x-agent-principal` identity system.
4
4
  * (REGISTRY-REBUILD-DESIGN §5, M3 — registry half = JWKS already shipped; service half = ONE verifier
5
5
  * middleware implementing the rules below. This file is the schema + normative spec the service copies.)
@@ -161,7 +161,7 @@ export declare function legacyGovernanceFromRuntime(rawRuntime: unknown): unknow
161
161
  * their audit stream; omitting the callback keeps the resilience but drops the telemetry.
162
162
  *
163
163
  * 0.19.0 加了两个 kind(additive union member —— 用 `switch` 穷举本类型的消费方需补臂):
164
- * `"unknown-keys-dropped"` / `"unread-config-file"`,成案见 {@link droppedKeys}(sema-server
164
+ * `"unknown-keys-dropped"` / `"unread-config-file"`,成案见 {@link droppedKeys}(消费方
165
165
  * #322:配置写了、进程跑着、值没到,而没有任何一个字说出来)。 */
166
166
  export type EffectiveReadWarning = {
167
167
  domain: "hosts";
@@ -198,12 +198,12 @@ export type EffectiveReadWarning = {
198
198
  /**
199
199
  * 一份域文档里被域 schema **丢掉的键**(zod 对象默认 `"strip"`),点号路径形。
200
200
  *
201
- * 成案(sema-server #322 真事故):往 `runtime` 文档里加一个不属于该域的键,两条腿都会把它剥掉,
201
+ * 成案(消费方 #322 真事故):往 `runtime` 文档里加一个不属于该域的键,两条腿都会把它剥掉,
202
202
  * `domainErrors` 空、解析"成功"——配置写了、值没到、零告警。剥除行为本身是**刻意的前向兼容**
203
203
  * (新 center 的新键不该炸老消费方),所以修法不是收紧成 `.strict()`,而是让它**响亮**:
204
204
  * {@link buildEffective} 每域解析成功后调用本函数,非空即发 `"unknown-keys-dropped"` 警告。
205
205
  *
206
- * **嵌套也扫**(codex 复审 F2 真 finding):`{infraCostRates:{toolCalMicroUsd:10}}` 这种**拼错的嵌套
206
+ * **嵌套也扫**(对抗复审 复审 F2 真 finding):`{infraCostRates:{toolCalMicroUsd:10}}` 这种**拼错的嵌套
207
207
  * 键**在顶层看不见(`infraCostRates` 键还在),只看顶层等于对计费面的错键完全失明。故按 raw↔parsed
208
208
  * 的键集逐层对比(对象逐键、数组同长时逐下标),不依赖任何 zod 内省。
209
209
  *
@@ -227,7 +227,7 @@ export declare function carriedUnknownKeys(domain: DomainName, parsed: unknown):
227
227
  /**
228
228
  * 一域的 parse + **静默剥键/静默承运两条告警**(0.19.0)。`buildEffective` 与 `FileConfigStore.getDomain`
229
229
  * 共用这一个判据 —— 此前只有 effective 那条路径有门,而 `getDomain` 是 `exportBundle` 的读法
230
- * (codex 复审 round2 F3:导出一份被剥了键的域再导入 = 持久的配置丢失,而且全程无声)。
230
+ * (对抗复审 复审 round2 F3:导出一份被剥了键的域再导入 = 持久的配置丢失,而且全程无声)。
231
231
  */
232
232
  export declare function parseDomainLoud<K extends DomainName>(domain: K, raw: unknown, onWarning?: (w: EffectiveReadWarning) => void): DomainConfig[K];
233
233
  /** Per-domain READ-corruption policy (0.8.1) — what buildEffective does when a stored domain no longer parses.
@@ -66,7 +66,7 @@ export const DOMAIN_WRITE_ROLE = {
66
66
  // entitlement governs who-can-USE-what (models/skills/mcp/budget/runtime caps) per principal — a governance +
67
67
  // security surface (budget ceilings, bypass kill-switch) on par with systems. Same raised gate.
68
68
  entitlement: "publisher",
69
- // prompts (0.10.19, board [1069]③/[1050]②d): declaration text goes STRAIGHT into the system prompt of
69
+ // prompts (0.10.19, [ref]③/②d): declaration text goes STRAIGHT into the system prompt of
70
70
  // every worker×scenario the binding covers — the same injection surface (and rationale) as skills/mcp,
71
71
  // so the same raised gate. Center had pre-raised this locally per governance precedent; this row is the
72
72
  // contract-side source of truth so every consumer of the shared write gate gets publisher, not editor.
@@ -177,12 +177,12 @@ function collectDropped(raw, parsed, prefix, depth, spared, out) {
177
177
  /**
178
178
  * 一份域文档里被域 schema **丢掉的键**(zod 对象默认 `"strip"`),点号路径形。
179
179
  *
180
- * 成案(sema-server #322 真事故):往 `runtime` 文档里加一个不属于该域的键,两条腿都会把它剥掉,
180
+ * 成案(消费方 #322 真事故):往 `runtime` 文档里加一个不属于该域的键,两条腿都会把它剥掉,
181
181
  * `domainErrors` 空、解析"成功"——配置写了、值没到、零告警。剥除行为本身是**刻意的前向兼容**
182
182
  * (新 center 的新键不该炸老消费方),所以修法不是收紧成 `.strict()`,而是让它**响亮**:
183
183
  * {@link buildEffective} 每域解析成功后调用本函数,非空即发 `"unknown-keys-dropped"` 警告。
184
184
  *
185
- * **嵌套也扫**(codex 复审 F2 真 finding):`{infraCostRates:{toolCalMicroUsd:10}}` 这种**拼错的嵌套
185
+ * **嵌套也扫**(对抗复审 复审 F2 真 finding):`{infraCostRates:{toolCalMicroUsd:10}}` 这种**拼错的嵌套
186
186
  * 键**在顶层看不见(`infraCostRates` 键还在),只看顶层等于对计费面的错键完全失明。故按 raw↔parsed
187
187
  * 的键集逐层对比(对象逐键、数组同长时逐下标),不依赖任何 zod 内省。
188
188
  *
@@ -208,7 +208,7 @@ export function droppedKeys(domain, raw, parsed) {
208
208
  * open-world 域(`.passthrough()`)的**已知键表**:路径 → 该层已知键(`""` = 顶层)。键集从 schema 的
209
209
  * `shape` **单源派生**(手抄一份必然漂),路径表本身是显式的——嵌套只在真有 open-world 子对象的地方登记。
210
210
  *
211
- * 为什么需要它(codex 复审 round2 F2):承运解决了「值到不了」,但没解决「键名拼错了没人说」——
211
+ * 为什么需要它(对抗复审 复审 round2 F2):承运解决了「值到不了」,但没解决「键名拼错了没人说」——
212
212
  * `toolResultsTtlSec`(多一个 s)会完好穿过本包,而消费方只遍历自己的键表,于是那条天花板悄悄没生效。
213
213
  * 承运 + 点名两件一起做:值照送(消费方有权认新键),名照报(拼错的有人说)。
214
214
  *
@@ -247,7 +247,7 @@ export function carriedUnknownKeys(domain, parsed) {
247
247
  /**
248
248
  * 一域的 parse + **静默剥键/静默承运两条告警**(0.19.0)。`buildEffective` 与 `FileConfigStore.getDomain`
249
249
  * 共用这一个判据 —— 此前只有 effective 那条路径有门,而 `getDomain` 是 `exportBundle` 的读法
250
- * (codex 复审 round2 F3:导出一份被剥了键的域再导入 = 持久的配置丢失,而且全程无声)。
250
+ * (对抗复审 复审 round2 F3:导出一份被剥了键的域再导入 = 持久的配置丢失,而且全程无声)。
251
251
  */
252
252
  export function parseDomainLoud(domain, raw, onWarning) {
253
253
  const parsed = parseDomain(domain, raw);
@@ -399,7 +399,7 @@ export function buildEffective(version, getRaw, updatedAt, onWarning) {
399
399
  // prompts (0.10.18, [1064]②): content domain → parseOr(坏形回空默认=「无 prompts 管理」语义;
400
400
  // fail-closed 由 PUBLISH_MODE 发布闸承担,空 bindings 不下发内容,default 不扩权)。
401
401
  prompts: parseOr("prompts", getRaw("prompts")),
402
- // limits (0.19.0, sema-server #322 批1): THROW 档 → parseLoud(坏形绝不静默降级成「没有天花板」)。
402
+ // limits (0.19.0, 消费方 #322 批1): THROW 档 → parseLoud(坏形绝不静默降级成「没有天花板」)。
403
403
  limits: parseLoud("limits", getRaw("limits")),
404
404
  };
405
405
  }
package/dist/file-edit.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * TOC editor helpers — the read/write/VALIDATE surface the desktop/CLI builds its OWN config UX on top of
3
- * (Clay's decision: only the LIB is shared, the TOC builds its own UI). These expose write/validate, not just
3
+ * (product decision: only the LIB is shared, the TOC builds its own UI). These expose write/validate, not just
4
4
  * read, so a single-machine consumer never needs the server's routes.
5
5
  *
6
6
  * Validation uses the SAME zod schemas as the server's parseDomain → identical rules on both sides.
@@ -5,12 +5,12 @@ import { type DomainConfig, type DomainName, type EffectiveConfig } from "./type
5
5
  * **default**域集 of the bundle helpers (`exportBundle`/`readBundle`). 每个被排除的域必须在
6
6
  * {@link NON_PORTABLE_DOMAIN_REASONS} 里有一条成文理由(禁裸排除,#282 件5 附带裁定)。
7
7
  *
8
- * ⚠️ 口径诚实(codex 复审 round1 F4):这是**默认集与本地读取集,不是 API 级硬边界** —— `exportBundle`
8
+ * ⚠️ 口径诚实(对抗复审 复审 round1 F4):这是**默认集与本地读取集,不是 API 级硬边界** —— `exportBundle`
9
9
  * / `readBundle` 的 `domains` 参数可显式传任意 `DomainName`(bundle.ts 不拒非便携域)。把非便携域搬进
10
10
  * bundle 的那条口子归调用方纪律(以及各自域的导出面),不是本常量能挡住的;要不要把 bundle API 收窄到
11
11
  * `PortableDomain` 是一个独立的行为面裁定(#282 未决项,需三问),本批不擅自改。
12
12
  *
13
- * 🔴 **开新顶层域时必须同步登记本表**(成案 = sema-server #322 真事故):域表是**闭集**,不在这里的
13
+ * 🔴 **开新顶层域时必须同步登记本表**(成案 = 消费方 #322 真事故):域表是**闭集**,不在这里的
14
14
  * 域名,`config.d/<域>.json` 不会被读进 effective —— 消费方拿到的是「该域缺席」,和文件不存在**逐字
15
15
  * 同形**。当年 `limits` 域就是这样在单机腿静默丢了一整片限额发布(远端腿同批可用,所以更难看出来)。
16
16
  * 今日的兜底:漏登记的文件会被 {@link FileConfigStore} 的 `"unread-config-file"` 警告点名(fail-loud,
@@ -22,7 +22,7 @@ export type PortableDomain = (typeof PORTABLE_DOMAINS)[number];
22
22
  *
23
23
  * `satisfies Record<Exclude<DomainName, PortableDomain>, string>` 让键集在**编译期**双向咬死:新开一个
24
24
  * 域却不放进 PORTABLE_DOMAINS ⇒ 这里缺行 ⇒ 编译错;把某域改成便携却忘了删行 ⇒ 多余键 ⇒ 编译错。
25
- * (此前是「理由写在注释里」,机器只能做子串匹配——域名出现在文件任何角落都算数,等于没门;codex
25
+ * (此前是「理由写在注释里」,机器只能做子串匹配——域名出现在文件任何角落都算数,等于没门;对抗复审
26
26
  * 复审 round1 F3。)理由要写**为什么它不该被单机/跨部署搬运**,带出处。
27
27
  */
28
28
  export declare const NON_PORTABLE_DOMAIN_REASONS: {
@@ -7,7 +7,7 @@
7
7
  * LOCAL FILE LAYOUT (the TOC owns the root, e.g. `~/.ai-agent/` or a project-local `.ai-agent/`):
8
8
  * <root>/config.d/<domain>.json for every domain in {@link PORTABLE_DOMAINS} — that constant is the
9
9
  * AUTHORITY; do NOT hand-copy the list here (the hand-written enumeration that used to sit
10
- * on this line silently missed `prompts` for three releases — codex 复审 round2 F5).
10
+ * on this line silently missed `prompts` for three releases — 对抗复审 复审 round2 F5).
11
11
  * <root>/.env secret VALUES (KEY=value) — the ONLY file holding secrets; gitignored, never read here.
12
12
  *
13
13
  * Rules:
@@ -30,12 +30,12 @@ import { isDomainName } from "./types.js";
30
30
  * **default**域集 of the bundle helpers (`exportBundle`/`readBundle`). 每个被排除的域必须在
31
31
  * {@link NON_PORTABLE_DOMAIN_REASONS} 里有一条成文理由(禁裸排除,#282 件5 附带裁定)。
32
32
  *
33
- * ⚠️ 口径诚实(codex 复审 round1 F4):这是**默认集与本地读取集,不是 API 级硬边界** —— `exportBundle`
33
+ * ⚠️ 口径诚实(对抗复审 复审 round1 F4):这是**默认集与本地读取集,不是 API 级硬边界** —— `exportBundle`
34
34
  * / `readBundle` 的 `domains` 参数可显式传任意 `DomainName`(bundle.ts 不拒非便携域)。把非便携域搬进
35
35
  * bundle 的那条口子归调用方纪律(以及各自域的导出面),不是本常量能挡住的;要不要把 bundle API 收窄到
36
36
  * `PortableDomain` 是一个独立的行为面裁定(#282 未决项,需三问),本批不擅自改。
37
37
  *
38
- * 🔴 **开新顶层域时必须同步登记本表**(成案 = sema-server #322 真事故):域表是**闭集**,不在这里的
38
+ * 🔴 **开新顶层域时必须同步登记本表**(成案 = 消费方 #322 真事故):域表是**闭集**,不在这里的
39
39
  * 域名,`config.d/<域>.json` 不会被读进 effective —— 消费方拿到的是「该域缺席」,和文件不存在**逐字
40
40
  * 同形**。当年 `limits` 域就是这样在单机腿静默丢了一整片限额发布(远端腿同批可用,所以更难看出来)。
41
41
  * 今日的兜底:漏登记的文件会被 {@link FileConfigStore} 的 `"unread-config-file"` 警告点名(fail-loud,
@@ -49,7 +49,7 @@ const NON_DOMAIN_CONFIG_FILES = new Set(["remote-exec.json"]);
49
49
  *
50
50
  * `satisfies Record<Exclude<DomainName, PortableDomain>, string>` 让键集在**编译期**双向咬死:新开一个
51
51
  * 域却不放进 PORTABLE_DOMAINS ⇒ 这里缺行 ⇒ 编译错;把某域改成便携却忘了删行 ⇒ 多余键 ⇒ 编译错。
52
- * (此前是「理由写在注释里」,机器只能做子串匹配——域名出现在文件任何角落都算数,等于没门;codex
52
+ * (此前是「理由写在注释里」,机器只能做子串匹配——域名出现在文件任何角落都算数,等于没门;对抗复审
53
53
  * 复审 round1 F3。)理由要写**为什么它不该被单机/跨部署搬运**,带出处。
54
54
  */
55
55
  export const NON_PORTABLE_DOMAIN_REASONS = {
@@ -119,7 +119,7 @@ export class FileConfigStore {
119
119
  * FAIL-LOUD 扫描(0.19.0):`config.d/` 里存在、但本地读取集**永远不会读**的 `*.json` 文件,逐个经
120
120
  * `onWarning` 点名(`"unread-config-file"`)。
121
121
  *
122
- * 成案 = sema-server #322:消费方开了新顶层域 `limits` 并发布 `config.d/limits.json`,而本包的域表是
122
+ * 成案 = 消费方 #322:消费方开了新顶层域 `limits` 并发布 `config.d/limits.json`,而本包的域表是
123
123
  * 闭集 —— 文件在、进程跑、限额还是 env 老值,**零告警**(「域缺席」与「文件不存在」在下游逐字同形)。
124
124
  * 修法方向是**响亮,不是收紧**:未登记文件照旧不读(拒收会让一个无害的散落文件打死整个部署),但必须
125
125
  * 说出来。两类分开报,因为处置不同:`not-a-domain` = 名字打错 / 消费方开了本包还不认识的域(要来本包
@@ -185,7 +185,7 @@ export class FileConfigStore {
185
185
  const raw = await this.#readDomainRaw(domain);
186
186
  if (raw === undefined)
187
187
  return undefined; // missing/empty file → domain absent (not schema defaults)
188
- // 0.19.0(codex 复审 round2 F3):与 buildEffective **同一条** parse-and-warn 判据。此前本方法直接
188
+ // 0.19.0(对抗复审 复审 round2 F3):与 buildEffective **同一条** parse-and-warn 判据。此前本方法直接
189
189
  // parseDomain,于是 `exportBundle`(它就是逐域走 getDomain 读的)会把一份携带未知键的域**静默剥**
190
190
  // 成一份"干净"的 bundle —— 再 import 回去就是一次持久的配置丢失,全程零告警。
191
191
  return parseDomainLoud(domain, raw, this.opts.onWarning);
package/dist/fleet.d.ts CHANGED
@@ -324,7 +324,7 @@ export declare function reconcileLease(l: QuotaLease, reported: {
324
324
  /** One principal×model line in a report window(worker 的 fleet 批报腿累计)。0.12.1 语义澄清:早年注写
325
325
  * 「mirrors the worker's modelUsageTracker accumulation」——engine 3.0 计量语义统一后该说法失真:worker 的
326
326
  * per-task modelUsage 面存**未命中输入分量**(与 cacheRead/Write 分列),而**本面 `inputTokens` 是归一化
327
- * 总输入(含 cache)**,两面同名不同义,以本注为准(producer 见 sema-server budget.ts fleet 批报腿)。 */
327
+ * 总输入(含 cache)**,两面同名不同义,以本注为准(producer 见 worker 服务 budget 模块的 fleet 批报腿)。 */
328
328
  export declare const UsageEntry: z.ZodObject<{
329
329
  principal: z.ZodString;
330
330
  model: z.ZodString;
package/dist/fleet.js CHANGED
@@ -236,7 +236,7 @@ export function reconcileLease(l, reported) {
236
236
  /** One principal×model line in a report window(worker 的 fleet 批报腿累计)。0.12.1 语义澄清:早年注写
237
237
  * 「mirrors the worker's modelUsageTracker accumulation」——engine 3.0 计量语义统一后该说法失真:worker 的
238
238
  * per-task modelUsage 面存**未命中输入分量**(与 cacheRead/Write 分列),而**本面 `inputTokens` 是归一化
239
- * 总输入(含 cache)**,两面同名不同义,以本注为准(producer 见 sema-server budget.ts fleet 批报腿)。 */
239
+ * 总输入(含 cache)**,两面同名不同义,以本注为准(producer 见 worker 服务 budget 模块的 fleet 批报腿)。 */
240
240
  export const UsageEntry = z.object({
241
241
  principal: z.string().min(1),
242
242
  model: z.string().min(1),
package/dist/hooks.d.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  * later is pure implementation, never a schema change.
9
9
  *
10
10
  * CONSUMERS
11
- * - service (sema-server): `TaskRequest.settings.hooks` wire face = `HooksConfig` below; the worker-side
11
+ * - service (the worker server): `TaskRequest.settings.hooks` wire face = `HooksConfig` below; the worker-side
12
12
  * hook-runner translates matching entries into core `TaskSpec.hooks` in-process callbacks. Single-user
13
13
  * gate first (requirePrincipal semantics, same as MCP injection ).
14
14
  * - core (engine): per-event input/output shapes for the engine-owned events; `stoppedBy` on settle.
@@ -3670,8 +3670,13 @@ export declare const HookSpecificOutput: z.ZodUnion<[z.ZodObject<{
3670
3670
  export type HookSpecificOutput = z.infer<typeof HookSpecificOutput>;
3671
3671
  /**
3672
3672
  * Synchronous hook JSON output (stdout of a command hook, CC-verbatim). Exit-code semantics ride
3673
- * alongside: exit 0 = success (stdout parsed as this shape when JSON), exit 2 = BLOCKING error (stderr
3674
- * fed back to the model), any other exit = non-blocking error (stderr shown to the user).
3673
+ * alongside: exit 0 = success (stdout parsed as this shape when JSON); exit 2 = BLOCKING error (stderr is fed
3674
+ * back to the model as the block reason / additionalContext, per event); any other exit, a timeout, a spawn
3675
+ * failure or malformed JSON = NON-BLOCKING failure: the run continues, and the consumer's hook-runner forwards
3676
+ * it as a `hook_non_blocking_failure` notice (a `hook_notice` frame on the task/fleet stream carrying hook name,
3677
+ * event, reason, exit code and the stderr text redacted-then-bounded to 512 chars), so the failure is visible
3678
+ * from the task's point of view instead of only in server logs. There is no separate "shown to the user"
3679
+ * surface: what a user sees is whatever their client renders from that notice frame.
3675
3680
  */
3676
3681
  export declare const SyncHookOutput: z.ZodObject<{
3677
3682
  /** Whether the run should continue after the hook (default true). */
package/dist/hooks.js CHANGED
@@ -8,7 +8,7 @@
8
8
  * later is pure implementation, never a schema change.
9
9
  *
10
10
  * CONSUMERS
11
- * - service (sema-server): `TaskRequest.settings.hooks` wire face = `HooksConfig` below; the worker-side
11
+ * - service (the worker server): `TaskRequest.settings.hooks` wire face = `HooksConfig` below; the worker-side
12
12
  * hook-runner translates matching entries into core `TaskSpec.hooks` in-process callbacks. Single-user
13
13
  * gate first (requirePrincipal semantics, same as MCP injection ).
14
14
  * - core (engine): per-event input/output shapes for the engine-owned events; `stoppedBy` on settle.
@@ -505,8 +505,13 @@ export const HookSpecificOutput = z.union([
505
505
  ]);
506
506
  /**
507
507
  * Synchronous hook JSON output (stdout of a command hook, CC-verbatim). Exit-code semantics ride
508
- * alongside: exit 0 = success (stdout parsed as this shape when JSON), exit 2 = BLOCKING error (stderr
509
- * fed back to the model), any other exit = non-blocking error (stderr shown to the user).
508
+ * alongside: exit 0 = success (stdout parsed as this shape when JSON); exit 2 = BLOCKING error (stderr is fed
509
+ * back to the model as the block reason / additionalContext, per event); any other exit, a timeout, a spawn
510
+ * failure or malformed JSON = NON-BLOCKING failure: the run continues, and the consumer's hook-runner forwards
511
+ * it as a `hook_non_blocking_failure` notice (a `hook_notice` frame on the task/fleet stream carrying hook name,
512
+ * event, reason, exit code and the stderr text redacted-then-bounded to 512 chars), so the failure is visible
513
+ * from the task's point of view instead of only in server logs. There is no separate "shown to the user"
514
+ * surface: what a user sees is whatever their client renders from that notice frame.
510
515
  */
511
516
  export const SyncHookOutput = z.object({
512
517
  /** Whether the run should continue after the hook (default true). */
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @sema-agent/settings-schema — the public barrel. ONE source of truth for the config contract shared by
3
- * sema-registry, sema-server, and the TOC desktop/CLI.
3
+ * the config center, the worker service, and the TOC desktop/CLI.
4
4
  */
5
5
  export * from "./types.js";
6
6
  export * from "./hash.js";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @sema-agent/settings-schema — the public barrel. ONE source of truth for the config contract shared by
3
- * sema-registry, sema-server, and the TOC desktop/CLI.
3
+ * the config center, the worker service, and the TOC desktop/CLI.
4
4
  */
5
5
  export * from "./types.js";
6
6
  export * from "./hash.js";
@@ -28,7 +28,7 @@ export interface LocalConfig {
28
28
  requiredEnv: RequiredEnvName[];
29
29
  /** 本次读盘的降级/静默告警(0.19.0)。此前本函数**从不**给 store 挂 `onWarning`,于是单机 lane 的
30
30
  * 默认形是「没有通道 = 没有声音」:域文档里被剥的键、`config.d/` 里永远不会被读的文件,一律静默
31
- * (sema-server #322 的病形)。空数组 = 本次读盘无告警。 */
31
+ * (消费方 #322 的病形)。空数组 = 本次读盘无告警。 */
32
32
  warnings: EffectiveReadWarning[];
33
33
  }
34
34
  /** The ONE canonical local load — the service engine and the client CLI/desktop both call this so they cannot
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * `remoteExec` — the execution-substrate contract (NET-NEW; not part of DOMAIN_SCHEMAS today).
3
3
  *
4
- * Per Clay's decision the exec layer is user-configurable & pluggable. This SCHEMA is a FORWARD-COMPATIBLE
5
- * SUPERSET: it carries both the backends sema-server already implements today AND the TOC single-machine
6
- * backends Clay added (the service implements those in PHASES — host + e2b first, local/remote-docker
7
- * fast-follow). The schema LEADS; runtime support is phased. The discriminator is `provider`:
8
- * FLEET (implemented today, sema-server/src/config.ts):
4
+ * Per the product owner's decision the exec layer is user-configurable & pluggable. This SCHEMA is a
5
+ * FORWARD-COMPATIBLE SUPERSET: it carries both the backends the worker service already implements today AND the
6
+ * TOC single-machine backends the product owner added (the service implements those in PHASES — host + e2b first,
7
+ * local/remote-docker fast-follow). The schema LEADS; runtime support is phased. The discriminator is `provider`:
8
+ * FLEET (implemented today, the worker service's config module):
9
9
  * - `e2b` per-task E2B Firecracker VM (isolated, suspendable). The default code-agent worker.
10
10
  * - `k8s` per-task Kata pod on our k3s (isolated, NOT suspendable). Self-hosted sandbox lane.
11
11
  * - `ssh` a real host over SSH (NOT isolated/suspendable). AI-orchestrated batch deploy.
12
12
  * - `adb` a real device over ADB (NOT isolated/suspendable). On-device APP testing.
13
- * TOC single-machine (Clay; service implements in phases — macOS + Linux first):
13
+ * TOC single-machine (product-owner scope; service implements in phases — macOS + Linux first):
14
14
  * - `host` run tools DIRECTLY on this machine, no container (the TOC default, like a local coding
15
15
  * agent). No isolation. macOS/Linux.
16
16
  * - `local-docker` containers on THIS machine's docker (isolation for parallel/untrusted fan-out).
@@ -25,7 +25,7 @@
25
25
  import { z } from "zod";
26
26
  export declare const RemoteExecSpec: z.ZodDiscriminatedUnion<"provider", [z.ZodObject<{
27
27
  provider: z.ZodLiteral<"host">;
28
- /** Working ROOT for the agent's tools; absent = the workspace/cwd. (≡ sema-server's resolved
28
+ /** Working ROOT for the agent's tools; absent = the workspace/cwd. (≡ the worker service's resolved
29
29
  * `workspaceBase` — the adapter runs each task under `<workdir>/ai-agent-host-<id>`.) */
30
30
  workdir: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
31
31
  /** Optional writable-path allowlist bounding what the host-exec tools may touch (defence for a TOC box). */
@@ -33,7 +33,7 @@ export declare const RemoteExecSpec: z.ZodDiscriminatedUnion<"provider", [z.ZodO
33
33
  /** Shell to spawn (absent = the platform default). */
34
34
  shell: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
35
35
  /** Per-COMMAND timeout (ms) for the host lane — host is long-lived so this bounds a single exec, not the
36
- * task (mirrors e2b/k8s `timeoutMs`; = sema-server's `commandTimeoutMs`). Absent = adapter default. */
36
+ * task (mirrors e2b/k8s `timeoutMs`; = the worker service's `commandTimeoutMs`). Absent = adapter default. */
37
37
  commandTimeoutMs: z.ZodOptional<z.ZodNumber>;
38
38
  }, "strip", z.ZodTypeAny, {
39
39
  provider: "host";
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * `remoteExec` — the execution-substrate contract (NET-NEW; not part of DOMAIN_SCHEMAS today).
3
3
  *
4
- * Per Clay's decision the exec layer is user-configurable & pluggable. This SCHEMA is a FORWARD-COMPATIBLE
5
- * SUPERSET: it carries both the backends sema-server already implements today AND the TOC single-machine
6
- * backends Clay added (the service implements those in PHASES — host + e2b first, local/remote-docker
7
- * fast-follow). The schema LEADS; runtime support is phased. The discriminator is `provider`:
8
- * FLEET (implemented today, sema-server/src/config.ts):
4
+ * Per the product owner's decision the exec layer is user-configurable & pluggable. This SCHEMA is a
5
+ * FORWARD-COMPATIBLE SUPERSET: it carries both the backends the worker service already implements today AND the
6
+ * TOC single-machine backends the product owner added (the service implements those in PHASES — host + e2b first,
7
+ * local/remote-docker fast-follow). The schema LEADS; runtime support is phased. The discriminator is `provider`:
8
+ * FLEET (implemented today, the worker service's config module):
9
9
  * - `e2b` per-task E2B Firecracker VM (isolated, suspendable). The default code-agent worker.
10
10
  * - `k8s` per-task Kata pod on our k3s (isolated, NOT suspendable). Self-hosted sandbox lane.
11
11
  * - `ssh` a real host over SSH (NOT isolated/suspendable). AI-orchestrated batch deploy.
12
12
  * - `adb` a real device over ADB (NOT isolated/suspendable). On-device APP testing.
13
- * TOC single-machine (Clay; service implements in phases — macOS + Linux first):
13
+ * TOC single-machine (product-owner scope; service implements in phases — macOS + Linux first):
14
14
  * - `host` run tools DIRECTLY on this machine, no container (the TOC default, like a local coding
15
15
  * agent). No isolation. macOS/Linux.
16
16
  * - `local-docker` containers on THIS machine's docker (isolation for parallel/untrusted fan-out).
@@ -44,7 +44,7 @@ export const RemoteExecSpec = z.discriminatedUnion("provider", [
44
44
  // ── host: run on THIS machine, no container (TOC default; macOS/Linux). No isolation, no secrets.
45
45
  z.object({
46
46
  provider: z.literal("host"),
47
- /** Working ROOT for the agent's tools; absent = the workspace/cwd. (≡ sema-server's resolved
47
+ /** Working ROOT for the agent's tools; absent = the workspace/cwd. (≡ the worker service's resolved
48
48
  * `workspaceBase` — the adapter runs each task under `<workdir>/ai-agent-host-<id>`.) */
49
49
  workdir: execStr.optional(),
50
50
  /** Optional writable-path allowlist bounding what the host-exec tools may touch (defence for a TOC box). */
@@ -52,7 +52,7 @@ export const RemoteExecSpec = z.discriminatedUnion("provider", [
52
52
  /** Shell to spawn (absent = the platform default). */
53
53
  shell: execStr.optional(),
54
54
  /** Per-COMMAND timeout (ms) for the host lane — host is long-lived so this bounds a single exec, not the
55
- * task (mirrors e2b/k8s `timeoutMs`; = sema-server's `commandTimeoutMs`). Absent = adapter default. */
55
+ * task (mirrors e2b/k8s `timeoutMs`; = the worker service's `commandTimeoutMs`). Absent = adapter default. */
56
56
  commandTimeoutMs: z.number().int().positive().optional(),
57
57
  }),
58
58
  // ── local-docker: containers on this machine's docker (isolated; enables parallel fan-out). No secrets