/** * config-center wire types — the config-center `/api/config/effective` payload shapes (`CenterModel`, * `CenterSkillManifest`, `CenterMcpServer`, `CenterA2aPeer`, `EffectiveConfig`) plus the per-principal * execution/session-mirror ruling shapes riding the caps view (`ExecutionRuling`/`SessionMirrorRuling`). * Pure type/interface declarations — no runtime logic. Split out of `facade.ts` ([ref] A13, * internal-lossless: the facade re-exports every symbol below unchanged). */ import type { ToolContentOrigin } from "@sema-agent/core"; import type { CollabTemplateWire } from "../capabilities/collab-wire.js"; import type { Autonomy, CommandRule } from "../runtime-governance.js"; export interface CenterModel { name: string; id: string; provider: string; api: "openai-completions" | "anthropic-messages"; baseUrl?: string; apiKeyEnv?: string; /** registry-core 0.10.5 sealed-box 托管密文(浏览器端 crypto_box_seal 封给执行域公钥,center * 只存密文)。执行侧按 publicKeyId 精确选本机私钥解封 → 明文进内存 key 管道(config.modelApiKeys)。 * 互斥语义(契约):与 apiKeyEnv 双设 = sealed 优先,且解封失败**不回落** env 引用(fail-loud,见 * applyEffective)。🔴 ciphertext 绝不进任何日志(registry-core write-only 纪律的执行侧半场)。 */ sealedApiKey?: { ciphertext: string; publicKeyId: string; alg: string; setAt?: string; }; tier?: string; reasoning?: boolean; vision?: boolean; contextWindow?: number; maxTokens?: number; /** [ref]① 1M dual-window (core 1.289 `Model.autoCompactTokens`): an EXPLICIT roster value wins the * contextWindow derivation in toModel (applyAutoCompactWindow). Declared on the type face (codex F5) so the * config-provider local-lane projection carries it — toModel keeps its structural read for older shapes. */ autoCompactTokens?: number; /** [ref] D2 (core 1.226): chars ≈ 1 token for this model's tokenizer, feeding every structural * (non-usage-anchored) token estimate. CJK-heavy models should declare 2–3; absent → env default → core 4. */ charsPerToken?: number; cost?: { input: number; output: number; cacheRead?: number; cacheWrite?: number; }; /** registry-core 0.6.0 配额倍率(models 域 ModelEntry.quotaWeight,缺省=1):weight-at-burn—— * 记账时固化进 UsageEntry.{weightedTokens,quotaWeightAtUse} 与 lease weightedTokens 轴;改倍率只影响 * 此后记账,不回算窗口内历史(registry types.d.ts 同句契约)。 */ quotaWeight?: number; /** * S-188(settings-schema 1.10.0 `ModelEntry.compat`)—— 这条目录条目对 **openai-completions 线路**的 * 兼容声明,上 core `Model.compat`(`OpenAICompletionsCompat` 五键)。真需求 = vLLM / Qwen 类**缺省开 * 思考**的网关:关思考只能靠 `thinkingFormat: "qwen-chat-template"`(`chat_template_kwargs. * enable_thinking=false`),而 `extraBody` 穿不过引擎的 OpenAI 保留键表。 * * 🔴 类型是 `unknown` 而不是那个结构,**刻意的**(与 {@link CenterMcpServer.toolFaces} 逐字同姿):本类型 * 是两条腿的**承载形**(本地 config.d 经 settings-schema 的 `z.unknown()` 解析透明地过来、远端 /effective * 是直读 JSON),判据与坏形处置的单一属主是 `model-compat.ts` 的 `readModelCompat`(`toModel` 在铸 `Model` * 那一刻调它)。在承载形上先写一个结构,等于把同一张判据表抄成两份(而其中一份没有执行力)。 * * ⚠️ 前身两键 `defaultThinking` / `reasoningEffortLevels` 已随本件删除:它们从来没有声明面 —— * settings-schema 的 `ModelEntry` 里没有这两个键,**两条腿**(本地 `parseDomainLoud` / 远端 * `readEffectiveWire`)都把它们当未知键剥掉(1.10.0 夹具实测:`unknown-keys-dropped * {keys:["models.0.defaultThinking","models.0.reasoningEffortLevels"]}`;settings-schema 3.0.0 起同一条 * 告警的坐标是**段数组** `{keys:[["models",0,"defaultThinking"],…]}`,出门形走 `formatConfigPath`), * `mapToServiceEffective` 的 * CLOSED 投影也从未列过它们。留着 = 一份读不到任何东西的类型承诺 + `compat.reasoningEffortLevels` * 之外的第二个写者([ref]:同一语义面禁两个写者)。roster 级 `defaultThinking` 若要真做,归 schema 补键 * 另立单据(见 CHANGELOG 未闭环)。 */ compat?: unknown; /** Generation-tuning passthrough, mirrors core `Model.extraBody` (1.60) — e.g. frequency/presence * penalties that *prevent* degenerate looping. Same category as `cost`/`tier`: logical model metadata, * no secrets. Carried through `toModel()` verbatim. When a center roster replaces the env model this is * the ONLY way to keep per-model tuning that lived in env (`MODEL_FREQUENCY_PENALTY` etc.) — see the * review-gw heterogeneous-roster migration. MUST be static per published version (prompt-cache prefix). */ extraBody?: Record; /** registry-core 0.10.13 ([ref]/[ref]⑤c): per-model behavior-slot mitigation sentences, mirrors core * `Model.promptGuidance` (core 1.303+ assembles them into the volatile tail's per-model position). * Same category as `extraBody`: logical model metadata, carried verbatim — without this projection the * configured sentences parse fine in registry-core but never reach the assembly face ([ref]① 排雷: * the missing leg made every promptGuidance pilot a false control). */ promptGuidance?: string[]; enabled?: boolean; } export type CenterRoleTarget = { model: string; } | { select: unknown; }; /** Skill MANIFEST entry (content is NOT inline — fetched by hash; see `fetchSkillContent`). */ export interface CenterSkillManifest { name: string; description: string; scenarios: string[]; contentHash: string; enabled?: boolean; } /** MCP server registry entry. `envRefs`/`headerRefs` are env-NAME refs (target-key → ENV_NAME), NOT secrets. */ export interface CenterMcpServer { name: string; scenarios: string[]; enabled?: boolean; allowTools?: string[]; /** E23 (shell-host contract): opt THIS server into INBOUND elicitation — it may ask the END USER for input mid-tool-call. * Maps to `McpServerSpec.elicitation`; core advertises the capability ONLY when this is true AND the service wired * `RunnerDeps.onElicit` (MCP_ELICITATION_ENABLED). Default OFF (omitted) — a server cannot pull a human into the * loop unless an operator explicitly opts it in. */ elicitation?: boolean; /** * [ref](core 5.60.0)—— 声明**这台 server 的整套工具**带回来的内容属于哪一类,映射到 * `McpServerSpec.contentOrigin`。`"local"` / `"execution"` ⇒ 这台 server 的调用不再给本会话记忆打 * 「已接触外来内容」标(`execution` 仍留在 `execIsExternalContent` 那只旋钮的射程内);`"external"` 是 * 显式 PIN,而**PIN 不是空操作** —— 它会取消 `trustedTools` 对这台 server 的按名豁免。 * 缺席 ⇒ pre-378 逐字节现行为(协议命名空间一律判 external,fail-closed)。 * * 🔴 **这是信任声明,不是路由提示**:只对部署自己跑的进程/套接字/服务用它。类名是**边界相对**的, * 与传输类型和地址无关(stdio 子进程可以是不可信包,loopback URL 可以是你自己的服务)——core 刻意 * 不按拓扑推断,本层同样不推断。它是**部署面**的键(core 顶注:与 `RunnerDeps` 接线同一权威平面), * 所以它的家在 center 下发这条腿;请求腿那半场的门与结构性兑现见 `task-mcp.ts` * 的 `assertRequestMcpContentOrigin` 顶注。 * * ✅ **两条腿已通**([ref],settings-schema 1.4.0 补键 + config-provider 映射行,2026-09-02;双绊线翻正销账)。 * 病史([ref]③ / [ref]③ / [ref],2026-08-31 双绊线实测更正 —— 本注更旧版那句 * 「远端 /effective.mcp 腿是直读 JSON,今天就通」**不成立**,doc-rot):settings-schema(原 registry-core) * 的 `McpServerSpec` 是默认 strip 的 zod object 且没有 `contentOrigin` 可选键,本地腿在 FileConfigStore 的 * `parseDomainLoud(DOMAIN_SCHEMAS.mcp)`、远端腿在消费端边界 `readEffectiveWire`([ref] 裁B)**各被剥一次**。 * 修在 sema-settings-schema(补同名可选枚举键 + 发包),本仓提货后 `config-provider.ts` 的映射加一行即通; * 两条 `it.fails` 绊线(test/config-center-wire-read.test.ts + test/config-provider.test.ts)在上游到货时 * 自动翻红逼销账。 */ contentOrigin?: ToolContentOrigin; /** B-036 / S-143:声明方自述的分组标签(开集,非空 ≤80;settings-schema 1.7.0 `McpServerSpec.source`)——上 core * `McpServerSpec.source`,由 `wiring_manifest.mcp[].source` 逐字回显。显示用,不进信任轴。 */ source?: string; /** * 件8(core 7.8.0 [ref] §2.7;settings-schema 1.9.0 `McpServerSpec.toolFaces`)—— 这台 server 的 * **per-tool 面覆盖层**,键 = server 的**原始(未加命名空间)**工具名,值 = `{ family?, pathTarget?, * renderHints?, ruleFace? }`。上 core `McpServerSpec.toolFaces`。 * * 🔴 类型是 `unknown` 而不是那个结构,**刻意的**:本类型是两条 center 腿的**承载形**(本地 config.d 经 * settings-schema 的 `z.unknown()` 解析透明地过来、远端 /effective 是直读 JSON),判据与坏形处置的单一 * 属主是 `mcp-tool-faces.ts` 的 `readMcpToolFaces`(`resolveMcpServers` 在铸 spec 那一刻调它)。在承载 * 形上先写一个结构,等于把同一张判据表抄成两份(而其中一份没有执行力)。 */ toolFaces?: unknown; transport: { kind: "stdio"; command: string; args?: string[]; envRefs?: Record; } /** `principalHeader` ([ref]): the header name into which the runner injects the task's authenticated * end-user principal per-task, so a consumer MCP (e.g. oa-mcp) can enforce per-user RBAC. Not a ref — a * literal header name. The runner fills the value (never the model). */ | { kind: "http"; url: string; headerRefs?: Record; principalHeader?: string; }; } /** * DESIGN-269 §2.1 —— A2A peer registry entry (the `CenterMcpServer` sibling). `headerRefs` are env-NAME * refs (header-name → ENV_NAME), **never** literal secrets: the bearer for a peer lives in THIS service's * env, the center only ever stores the NAME. (A2A has a single transport — every peer is an https(s) * endpoint — so unlike MCP there is no transport discriminant; the two ref-carrying shapes collapse to one.) */ export interface CenterA2aPeer { name: string; scenarios: string[]; enabled?: boolean; /** The peer's service URL (also the origin the well-known agent-card path resolves against). */ url: string; /** Explicit agent-card location when the peer does not publish at a well-known path. Set ⇒ used ALONE. */ cardUrl?: string; /** env-NAME refs (header-name → ENV_NAME) resolved from THIS service's env at boot. A peer with ANY * unset ref is SKIPPED wholesale (fail-safe — never dial a peer half-credentialed). */ headerRefs?: Record; /** [ref], same contract as the MCP side: the header name the runner injects the task's authenticated * end-user principal into. Not a ref — a literal header NAME (the runner fills the value, never the model). */ principalHeader?: string; /** Optional allowlist of the peer's skill ids to mount (others are not mounted). */ allowSkills?: string[]; } /** * #A4([ref] 窗三件批 件1;[ref]/[ref] 承诺件)—— READ 容纳面的 center 下发形(`CenterA2aPeer` 的 * 同族:一个 additive 顶层域,server 声明它才不会被静默丢弃)。四个成员逐一对应部署 env 的四键 * (`READ_FACE` / `READ_DENY_PATTERNS` / `READ_DENY_BUILTIN_TIERS` / `READ_DENY_BUILTIN_EXCLUDE`), * 消费半场 = `config-center/read-face.ts` `applyCenterReadFace`。 * * 🔴 **env 显式恒赢**(operator-knob 律,消费侧执法):env 是这台机器的部署主权,center 是组织下发; * 冲突时本机 env 原样保留 + 一条点名 warn。所以本类型描述的是「组织想要什么」,不是「这台机器最终是什么」。 * * 🔴 **只有收敛面,没有旁路面**:`denyPatterns` 的元素与 core `ReadDenyEntry` 同宽(裸串简写 ≡ * `{pattern, caseSensitive:false}`),校验一律交给引擎自己的 `compileReadDeny` / * `resolveReadDenyBuiltins` —— 宿主不自造第二份判定语义(env 腿逐字同款纪律)。 */ export interface CenterReadFace { /** READ 工具面的容纳姿态。缺席=本域不管这一键(env / 引擎默认接管)。 */ face?: "open" | "roots"; /** 部署级 READ deny **追加**表(additive-only,core 内建表永不可缩)。 */ denyPatterns?: Array; /** **内建** deny 表的档位选择(闭集四档);`[]` = 显式空姿态(一档内建都不要)。 */ denyBuiltinTiers?: string[]; /** 按行名删内建条目,在档位选择**之后**生效。 */ denyBuiltinExclude?: string[]; } /** * [ref] 批1 的 wire 面(`EffectiveConfig.limits`)。**全 optional**:缺席 = 本域不管这一键 ⇒ 该键回 env * 基线(非粘,applyRuntimeHot 的 NON-STICKY 同族纪律 —— 「缺席=保上一个 center 值」会把撤回的治理永久冻住)。 * * 🔴 类型是**到货 JSON 的声明**,不是运行时保证(local 腿的 eff 来自原始 JSON):每个键在 stage 侧都 * 逐个验型验域,坏值 ⇒ 整批拒 + 旧值继续服务([ref] 响亮拒)。 */ export interface EffectiveLimits { /** 每 principal 每分钟请求上限;**0 = 关**(关断哨兵,不是缺席)。 */ rateLimitPerMin?: number; /** 每 principal 滚动窗累计花费上限(USD);0 = 无配额。 */ maxPrincipalCostUsd?: number; /** 上面那条配额的窗长(秒);必须 > 0。 */ costQuotaWindowSec?: number; /** 单任务成本/token 天花板;0 = 无天花板。 */ maxTaskCostUsd?: number; maxTaskTokens?: number; /** 基建计价(每项 ≥ 0);缺席 = 不改。 */ infraCostRates?: { toolCallMicroUsd?: number; sandboxSecMicroUsd?: number; egressGbMicroUsd?: number; }; /** 附件孤儿对象 GC 宽限(ms);0 = 关掉该腿。 */ attachmentOrphanGraceMs?: number; /** workspace 单文件读上限(字节,> 0)。 */ workspaceFileMaxBytes?: number; /** 附件单文件上限(字节,≥ 下限)。 */ attachmentMaxBytes?: number; /** 附件 mime 白名单(非空串数组);空数组 = 显式「一个都不许」,与缺席(不设限)不同。 */ attachmentMimeAllowlist?: string[]; /** 未绑定附件 TTL(ms)。 */ attachmentUnboundTtlMs?: number; /** SIGTERM drain 窗(ms)。 */ drainGraceMs?: number; /** run 心跳陈旧窗(秒);必须严格大于活体心跳(跨键不变量,见 config-invariants.ts)。 */ runStaleSec?: number; /** 卸载工具结果的 TTL(秒,> 0)。 */ toolResultTtlSec?: number; } export interface EffectiveConfig { version: number; updatedAt: string; /** [ref]B-6:default/tierGroups/activeTierGroup 收进类型面(registry-core 0.13.0 已声明, * types.d.ts)——此前 wire 面靠「JSON verbatim + 消费方结构读」逃逸,投影/消费两侧 * 各自 as 宽铸。tierGroups 上游是 ZodDefault(合规 center 恒发),但本类型描述的是**到货 JSON** * (含非合规/旧存量 center),故仍标 optional——消费方 resolveActiveTiers 自身容缺。 */ models: { models: CenterModel[]; roles: Record; atModelAllowlist?: string[]; default?: string; tierGroups?: unknown; activeTierGroup?: string; }; /** registry-core 0.7 collab domain (teams' successor) — consumed by the slice-1.5 projection * (projectCollabToWorkflows → registerCollabWorkflows). Both lanes carry it: the remote worker /effective view * ships collab, and local FileConfigStore reads config.d/collab.json (PORTABLE_DOMAINS includes collab). */ collab?: { templates: CollabTemplateWire[]; }; skills?: { skills: CenterSkillManifest[]; }; mcp?: { servers: CenterMcpServer[]; }; /** DESIGN-269 §2.1: center-declared A2A peers. Absent (the shape every center ships today) ⇒ the leg * does not exist for this deployment — `config.a2aPeers` stays undefined, no peer is ever dialed. */ a2a?: { peers: CenterA2aPeer[]; }; /** Center-declared scenarios (composition-as-config; capability stays code-pinned): each entry names a * deploy-registered TOOLSET (`none` / `repo-readonly`) + an optional static prompt (≤4KB, audited at * publish). Restart-to-apply like skills/mcp (baked into the scenario table at boot). Center entries * MAY shadow built-in scenario names (clay 2026-06-11: usability first) — shadows are logged at boot. * Validation/registry live in capabilities/scenarios.ts `centerScenarios`. */ scenarios?: { scenarios: Array<{ name: string; toolset: string; enabled?: boolean; }>; }; /** `runtime` 域 = **限额残余五键**,与 settings-schema `RuntimeConfig` 的键集逐字相等([ref] 件3 对账门 * test/settings-schema-consumption-gates.test.ts 读 dist `RuntimeConfig.shape` 钉集合等式)。全部 center * `.optional()`(center `f95438a`):缺席 = 不管 → 保 env;在场(含显式 0 = "publish OFF")= 覆盖。 * [ref] 批1 起五键全是**热**键(属主 stage-limits,boot+refresh 双腿);`limits` 域是它们的继任发布位 * (两处同现 ⇒ limits 赢,见 {@link EffectiveConfig.limits})。 * * 🔴 治理三件(autonomy / commandPolicy / approvalRequire)**不在这里**([ref] 件3 退役键清除):它们自 * settings-schema 0.6 起住 `governance` 域,0.7.1 撤了 runtime 位的双写镜像;此后 `RuntimeConfig` 是 strip * 的 zod object,两条腿(远端 `readEffectiveWire` / 本地 FileConfigStore→`buildEffective`)都把旧位 strip * 掉、由 `legacyGovernanceFromRuntime` 抬进 governance ⇒ 本仓在 runtime 位上读它们的每一行都是死码。 * 旧类型面上留着这三键,让 `runtime-gates` 重启片一直读着一个生产上恒缺席的位(审批闸收紧静默不生效)。 */ runtime?: { rateLimitPerMin?: number; maxTaskCostUsd?: number; maxTaskTokens?: number; maxPrincipalCostUsd?: number; costQuotaWindowSec?: number; }; /** * [ref] 批1 —— **limitsHttp 组的热更新发布域**([ref] §6 批1)。 * * 🔴 为什么是**新顶层域**而不是往 `runtime` 里加键(亲验,不是推测):registry-core 的 `RuntimeConfig` * 是 zod `"strip"` 对象,`runtime` 里的未知键在**两条腿上都会被静默剥掉**(local 腿实测 * `{rateLimitPerMin:7, toolResultTtlSec:999}` → `{rateLimitPerMin:7}`,零 domainError;remote 腿的 * `readEffectiveWire` 同一 schema)。而**未知顶层域**是 open-world verbatim 透传的(同一实测:顶层 * `limits` 原样到手)——所以这是今天唯一能真的把这些键送到消费端的形,也与 governance 域当初从 * runtime 里拆出去的先例同族。 * * 车道现状(如实):remote 腿即刻可用(center 发什么就到什么);**local 腿(config.d/)暂不可用** —— * `FileConfigStore` 的域表是闭集,`config.d/limits.json` 根本不会被读进 effective。补法在 registry-core * (加 `limits` 域 + PORTABLE_DOMAINS),与 `a2a`/`readFace` 当初的缺口同族;server 侧的消费半场(本键 + * stage + commit)先落地,不在下游自建第二个读盘腿(源头修复纪律)。 * * 与 `runtime` 的**优先级**:五个既有闸键(rateLimitPerMin/maxTaskCostUsd/maxTaskTokens/ * maxPrincipalCostUsd/costQuotaWindowSec)两处都可能出现 ⇒ `limits` 赢(新位是真值,旧位是过渡), * 与 governance/runtime 的读取优先级契约同形。 */ limits?: EffectiveLimits; /** 142-S4(registry-core 0.10.0 第 15 域):center 项目登记簿。wire 面 verbatim JSON — * registry-core `ProjectsConfig` 的形状是 `{projects: Record}`(skills/mcp * 同款域包裹)。[ref]B-8:裸 Record 联合臂随 apply-effective 的宽读一起删(0.13.0 只有包裹形, * 裸形无 producer)。消费=applyEffective → config.projects(displayName/gitRemotes/defaultScopes * 三个 runtime 字段;审计字段不进 ServiceConfig)。 */ projects?: { projects?: Record; }; /** settings-schema 0.6 起治理三件(autonomy/commandPolicy/approvalRequire)的**唯一**承运域(0.7.1 撤 * runtime 位双写镜像;顺序契约当年已走完:消费端先切、center 再撤)。键集与 schema `GovernanceConfig.shape` * 逐字相等([ref] 件3 对账门钉)。消费:autonomy/commandPolicy 逐请求热(`stageRuntimeHot`,boot+refresh); * approvalRequire boot-baked(`stageApprovalGate`,refresh 不写)⇒ 变更由 `runtime-gates` 重启片通告。 * 同一 presence 规则(undefined = 不管 → 保 env / 回基线)。 */ governance?: { autonomy?: Autonomy; commandPolicy?: CommandRule[]; approvalRequire?: string[]; }; /** plugins 域(registry-core 0.5 additive;契约冻结 [ref]②/[ref]/[ref]①,消费半场 2026-07-28 * 开工车):center 只存"插件从哪来"(PluginSpec 引用,永不承载可执行字节);worker 半场在 * capabilities/center-plugins.ts `applyCenterPlugins`(https-only+ALLOW_HOSTS 纵深复验/sha 钉扎/ * 隔离 clone/LKG/撞名让位)。此前本 interface 无此键 ⇒ wire 上的 plugins 被 server 静默丢弃。 */ plugins?: { plugins?: unknown[]; }; /** #A4:READ 容纳面的组织下发域(见 {@link CenterReadFace})。缺席(今天每个 center 都发的形)⇒ * 这条腿对本部署不存在,四键仍由 env / 引擎默认独占。restart-to-apply(boot 期被 `createRunnerDeps` * 捕获),改动经 `read-face` restart 片通告。 */ readFace?: CenterReadFace; /** prompts 域(additive key;双轴 wire=registry-core `EffectivePromptsWire` 或 legacy 平铺形—— * server 侧判形/采用全在 capabilities/center-prompts.ts `validatePromptsDomain`,本 interface 只 * 声明键位存在(unknown:候选门是唯一解释者,这里不复刻形)。 */ prompts?: unknown; } /** (stage7 P5,registry-core 0.8 `execution` 域): the center-resolved per-principal execution * ruling riding the caps view. `required=false` / ruling absent = no enforcement (legacy). `allowedLanes` is * an OPEN value domain (adding one is never BREAKING; consumers tolerate unknown names). Known lane names: * `host`/`e2b`/`k8s`/`ssh`/`adb`/`local-docker`/`device` (the REMOTE_EXEC providers) **plus `in-process`** * — the REMOTE_EXEC-unset fleet posture (OA/review-style workers; named distinctly from the explicit * `host` lane on purpose). ⚠️ Admins writing `required=true` policies must include `in-process` when such * workers should stay admittable — center UI/doc 词表待补齐。 * * 🔴 **`device` 是 per-principal 执行面上最需要写清的一条**(device-executor-lane-v2 §4.1 的 config-center * 行,车A-4 补):它是「在**员工自己的机器**上执行」的那条车道 —— 允许它 ≠ 允许一台云沙箱,而是允许 * 这个 principal 把裁决过的指令投到一台**受管设备**上。⚠️ 但**别把它当设备准入门用**:本 ruling 的 * 粒度是 lane 名,它表达不了 principal×device 绑定,而且 no-ruling 是 **fail-open** 的 * (`runtime-caps-resolver.ts` 的 P 类债)。device lane 的真准入是自建的 fail-closed 查表 * (绑定行 owner 谓词 + 设备 active + presence,§4.3.2)—— center 白名单是**外加**的一层,不是替代。 */ export interface ExecutionRuling { required: boolean; allowedLanes: string[]; /** registry-core 0.10.1-0.10.2:org 会话镜像策略, * execution 域收编字段,center 若把它附在 caps view 的 execution ruling 上则宽读透传(缺席=老 * center/未配置 → undefined,零行为差)。**server 侧只做观测面,不是执法面**——「该镜像而未镜像」 * 的违规发生在数据产生端(壳),server 收不到该信号(论证见 http/server.ts sync/import 的 * session_mirror audit 注释);本字段供 audit 日志/metrics 关联镜像到达与治理态。 */ sessionMirror?: SessionMirrorRuling; } /** 两层形状(registry-core `SessionMirrorPolicy` 的消费侧镜像):`required:false`=便利默认值(壳解析 * 序第三腿);`required:true`=org 治理强制(镜像默认开且不可关,本地覆盖不生效—— * org 压一切)。锁定执法在壳(CC managed-settings 心智,registry-core 域头注「required 的锁今天也是 * CLIENT-SIDE 执法」);service 半场=观测。 */ export interface SessionMirrorRuling { engineUrl: string; required: boolean; } //# sourceMappingURL=types.d.ts.map