/** * S-111 件③ —— 跨会话入站治理的**三层供给**([ref] §4.4)。 * * 分工(单一属主):**判定归引擎**(`resolveCrossSessionInboundSetting` 的层次收紧 + `judgeCrossSessionInbound` * 的 mode-parity 与 hold 因由,全在 core 的纯函数里);**本仓只供层**。本文件不判、不折、不比较秩—— * 它只回答一个问题:「managed / user / repo 这三层,本部署各自的值从哪里来?」 * * ## 三层来源(逐层如实,缺席也点名) * * | 层 | 引擎语义(CC 对位) | 本仓的源 | 今日状态 | * |---|---|---|---| * | `managed` | `policySettings`(组织/部署强制层) | `CROSS_SESSION_INBOUND` 部署旋钮 | **已接线** | * | `user` | `userSettings`/`flagSettings`(用户自己的层) | `body.settings.crossSessionInbound` | **缺席**,见下 | * | `repo` | `localSettings`/`projectSettings`(仓库层) | 本服务没有项目层 settings 源 | **缺席** | * * ### `user` 层为什么今天缺席(诚实面,不是遗漏) * * 引擎的座位 `RunnerDeps.crossSessionInbound` 是**部署级**的(一个 Runner 单例,getter 无会话上下文), * 而 `crossSessionInbound` 在 CC 里是**每会话**的 settings 值。本服务是「一个 Runner × 多会话」的宿主: * 把某一次提交的 `body.settings.crossSessionInbound` 塞进部署级座位,等于让 A 会话的设置去治理 B 会话的 * 排水——比不接线更糟,且是静默的。可选的补法只有两条,都不在本件射程内: * (a) 引擎开一个**每任务**座(形如既有的 `TaskSpec.autoModeRequested` 意图座)——上游诉求,已留档; * (b) 本仓用 per-run 异步上下文托住层,并保证**每一条** run 腿都建立该上下文——漏一条腿 = * 用户设的 `refuse` 静默失效 = 安全轴 fail-open,不许半接。 * 在 (a)/(b) 落地之前,提交面对这两个键**明拒**(`TASK_SETTINGS_UNSUPPORTED_KEYS`,400 体 `unsupportedKeys` * 逐字列名),而不是「受理但不执行」——在保护型配置上那是静默的假安全;宽容层(RESUME 重放)结构上不读它们。 * * ### 另一件如实:整条车道今日未挂 * * 两个座位在引擎侧都**以 `RunnerDeps.peerDirectory` 在场为前提**(座缺席 ⇒ 跨会话车道整条不挂, * 每个面与 pre-385 构建逐字节相同)。 * * ✅ **7.91.0:目录席已接线**([ref],`boot/runner-deps.ts` 的三合取:会话枚举面 ∧ mailbox 店 ∧ 收件人生命周期面) * —— 旧文字写的是「另一件欠账 …… 就位待命而非生效中」,如实订正:本文件铸的 managed 层在**有席的部署**上 * 真的在治理 drain 点的判决了;缺任一合取项的部署(典型 = 无耐久 mailbox 的单机形)上车道整条不挂,层仍是 * 就位待命。当初那句「目录席到货那天零改动即生效」已兑现:本文件一个字节未改。 */ import type { CrossSessionDialogExpiry, CrossSessionInboundSetting, CrossSessionInboundSettingLayers } from "@sema-agent/core"; /** 引擎层形的层名 —— 从 core 的类型上取,**引擎加一层 = 本文件编译错**(下面两处闭集都锁在这个联合上)。 */ export type CrossSessionInboundLayerName = keyof CrossSessionInboundSettingLayers; /** 层名的运行时闭集(与类型同源:表的键即闭集,表不全 = 编译错)。 */ export declare const CROSS_SESSION_INBOUND_LAYER_NAMES: readonly ["managed", "user", "repo"]; export interface CrossSessionInboundLayerSource { /** 这一层的值在本仓从哪里来(缺席的层写清「为什么没有源」,不留空)。 */ readonly source: string; /** 今天真的接线了吗。`false` = 本仓恒不铸这一层的键(引擎读作「该层未设」)。 */ readonly wired: boolean; } /** * **三层来源登记表** —— 头注那张表的机器可读形,同时是 {@link buildCrossSessionInboundLayers} 的驱动表。 * 一处改、两处同步:把某层翻 `wired: true` 而不给取值臂,构造时**响亮抛**(见下),不会静默铸空层。 */ export declare const CROSS_SESSION_INBOUND_LAYER_SOURCES: Record; /** 本文件读的部署配置切片(与 `ServiceConfig` 的两个可选键同名同形)。 */ export interface CrossSessionSettingsConfig { crossSessionInbound?: CrossSessionInboundSetting; crossSessionDialogExpiry?: CrossSessionDialogExpiry; } /** * 按 {@link CROSS_SESSION_INBOUND_LAYER_SOURCES} 铸引擎层形。 * * 纯数据出参(`build*` 命名律);未接线的层**恒不铸键** —— 引擎把缺席读作「该层未设」,与铸一个 * `undefined` 值不同(后者会让层次解析多走一趟无谓的读)。 */ export declare function buildCrossSessionInboundLayers(cfg: CrossSessionSettingsConfig): CrossSessionInboundSettingLayers; /** * 部署级 `dialogExpiry`(held 跨会话消息等待人审的期限)。未设 ⇒ **不铸键**,由引擎落它自己的缺省 * (`CROSS_SESSION_DIALOG_EXPIRY_DEFAULT` = `"5m"`)—— 本仓不复制上游缺省值,免得两处各写一个数。 * * ⚠️ 同名 CC 键还有**第二个**消费面(转发到远端客户端的审批对话框停靠时长)。本函数只答跨会话这一面; * 停靠面的接线是另一件,今天两者不共享这一个旋钮,发布面如实说明。 */ export declare function crossSessionDialogExpiryOf(cfg: CrossSessionSettingsConfig): CrossSessionDialogExpiry | undefined; //# sourceMappingURL=cross-session-settings.d.ts.map