# Changelog [3.3.3]: https://github.com/Fishsb/dsh-voice-prompt-enhancer/compare/v3.3.2...v3.3.3 [Unreleased]: https://github.com/Fishsb/dsh-voice-prompt-enhancer/compare/v3.5.1...HEAD [3.5.1]: https://github.com/Fishsb/dsh-voice-prompt-enhancer/compare/v3.5.0...v3.5.1 [3.4.2]: https://github.com/Fishsb/dsh-voice-prompt-enhancer/compare/v3.4.1...v3.4.2 [3.4.1]: https://github.com/Fishsb/dsh-voice-prompt-enhancer/compare/v3.4.0...v3.4.1 [3.4.0]: https://github.com/Fishsb/dsh-voice-prompt-enhancer/compare/v3.3.3...v3.4.0 [3.3.2]: https://github.com/Fishsb/dsh-voice-prompt-enhancer/compare/v3.3.1...v3.3.2 [3.3.1]: https://github.com/Fishsb/dsh-voice-prompt-enhancer/compare/v3.3.0...v3.3.1 本项目所有重要变更记录于此文件。 格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循[语义化版本](https://semver.org/lang/zh-CN/)。完整发布说明见 [GitHub Releases](https://github.com/Fishsb/dsh-voice-prompt-enhancer/releases)。 > 实测标注纪律:每条变更须在文末标注「已实测:<方式/等级>」;未实测不得合入(2026-08-24 门禁化)。 > 🗺️ 条目内的 `flow:` 标注为功能链路标签(原 pmg 项目地图 `docs/map/` 已随 pmg 于 2026-09-10 移除,该路径不再存在);agent 开工前先读 [`AGENTS.md`](AGENTS.md)。 ## [Unreleased] - **补上「发布物本身可装载」的实证门禁(验证 · 2026-11-06 · [PE-F01])**:方案第 1 批的另一条判据是「动态安装、profile 安装和刷新加载均通过」。此前所有验证都在**仓库工作区**里做,从未验证过 `npm pack` 出来的 tgz。新增 `RTL-01..05`:真的 `npm pack` 到临时目录、解包,然后**只按 `package.json` 声明**(`main` / `exports["./client"]`)装载 —— 与 DSH 宿主装完插件后做的事一致。判据含:导出面完整且 `apply(ctx)` 可执行、client 工厂契约成立、`files` 白名单生效(发布物不含 `src`/`test`/`scripts`/`docs`/`AGENTS.md`/`release-notes`)、两个产物的模块 id 指向新分层路径且旧扁平名不得复活。**已实测**:`RTL` 5/5;tgz 284589 B / 21 文件;`main=lib/index.cjs`、`exports["./client"]=./lib/client.cjs`;`FORBIDDEN_PRESENT=[]`。用户可见文案、RPC、配置键与安装形态未改。 - **补上「无 Node 模块环境」的实证门禁(验证 · 2026-11-06 · [PE-F01])**:方案第 1 批的完成判据之一是「`plugin-host.js` 仍可在无 Node 模块的环境中求值」「`lib/client.cjs` 仍按官方工厂契约加载」。此前所有测试都用 `new Function(...)` 在 **Node 全局作用域**里求值 —— `require` / `process` / `Buffer` 都还在,产物若偷偷依赖 Node 能力照样跑通,只有真装进 DSH 宿主才会炸。现新增两组隔离沙箱门禁:`HSE-01..05` 用 `vm.createContext(Object.create(null))` 建空上下文求值 host 产物(先自证环境里 require/module/process/Buffer/__dirname 全为 undefined,再求值;`apply()` 注册 12 条 RPC),`CSL-01..05` 用「只有浏览器式 API」的上下文装载 client 产物(只暴露 `window.__ModuleLoader__` / document / localStorage 等,工厂只允许 `require("react")`,返回带 `apply`/`inject` 的插件对象)。两组都带判别力自证(注入 `require` 后必红)。**已实测**:`HSE` 5/5、`CSL` 5/5;门禁链 exit 0(5 PASS · 2 基线接纳 SKIP)。顺带订正一处判据口径:产物**必然**含 `module.exports`(那是打包器的内部模块封装),该条不得判红;判的是「有没有向外部要东西」。用户可见文案、RPC、配置键与安装形态未改。 - **目录分层:`src/client` 按域收进 `domains/`,与 host 半部对齐(架构/命名 · 2026-11-06 · [PE-F01])**:上一批把 `src/host` 收进了 `domains/`,本批把 client 半部对齐:`domains/enhance/{button,bar,components}.cjs`、`domains/voice/{correction,correction-state,filler,hotkey,official-bridge,state,section,index}.cjs`、`domains/settings/{model-config-tab,params-tab,plugins-section,model-main-section,model-settings,shell,fallback-row}.cjs`、`ui/{collapsible-section,marquee-select,navigation}.cjs`、`common/{runtime,state,helpers,constants,i18n,styles,model-helpers}.cjs`,装配入口 `app.cjs`。client 域内的公共件目录取名 `common/` 而非 `shared/`——仓库根已有 `src/shared/contracts/**`,同名会让 `../shared/contracts` 的相对路径产生歧义。件数不变(29 件),产物模块集与磁盘逐件一致(29/29,无孤儿无断链)。**已实测**:`build-client --check` 一致;`build-host --check` 一致(host 未受影响);磁盘 ↔ 产物模块集差集为空(29/29);死代码门禁 R1–R7 全过;门禁链 exit 0(5 PASS · 2 基线接纳 SKIP);完整 `npm test` 952/952。用户可见文案、RPC、配置键与安装形态未改。 - **目录分层:`src/host` 按域收进 `domains/`,历史后缀退役(架构/命名 · 2026-11-05 · [PE-F01])**:目标模式 §三 要求的 `domains/{enhance,voice,models,diagnostics,settings}` 分层此前一直是平铺 20 件,且文件名带 chunk 时代的 `-module` / `-runtime` 后缀(`pure-module.cjs`、`enhance-handlers-module.cjs`、`context-runtime.cjs` 等)。现按职责迁入子目录并去后缀:`domains/enhance/{pure,prompts,pipeline,analyze,retrieve,assemble,generate,commit,runtime,handlers,result,context}.cjs`、`domains/voice/{correction,switch}.cjs`、`domains/models/{chain,constants,rpc}.cjs`、`domains/diagnostics/log.cjs`、`domains/settings/template.cjs`、装配入口 `app.cjs`。件数与物理行**逐值不变**(20 件 / 5581 行),依赖图不变(`app.cjs` 仍是唯一聚合点),产物重建后行为一致。**已实测**:R4 递归后仍报「20 件与装配图可达集一致」;A194-1 改为按分层职责路径判定(旧 `-module`/`-runtime` 后缀复活即红),读数 20 件 / 5581 行;`split-shared-fns` 定位到新路径后 7 函数逐字节相等;prompts 环 20 常量零漂移;门禁链 exit 0(5 PASS · 2 基线接纳 SKIP)。用户可见文案、RPC、配置键与安装形态未改。 - **包身份对齐:`package-lock.json` 仍停在旧名旧版本(修复/发布面 · 2026-11-05 · [PE-F01])**:改名到 `dsh-voice-prompt-enhancer` 后,`package-lock.json` 顶层与 `packages[""]` 仍是 `dsh-prompt-enhancer@3.4.2`。npm 发布读 `package.json` 所以发布物本身没错,但审计、供应链扫描、依赖图工具按 lock 判身份时会读到旧名旧版本,`engines.dsh` 也没镜像进去。现已 `npm install --package-lock-only` 重建,并新增 `PLI-01..05` 门禁锁 name / version / engines.dsh / peer 区间四面相等(含判别力自证)。**已实测**:`test/package-lock-identity.test.cjs` 5/5;完整 `npm test` 952/952;门禁链 exit 0(5 PASS · 2 基线接纳 SKIP);lock 顶层与 root 均为 `dsh-voice-prompt-enhancer@3.5.1`,`engines.dsh = >=0.2.1-rc.1`。用户可见文案、RPC、配置键与安装形态未改。 ## [3.5.1] - 2026-11-05 - **模型默认常量防漂移门禁(维护/门禁 · 2026-11-05 · [PE-F02])**:`src/host/models-constants.cjs`(供 `pure-module` 使用)与 `src/host/models-module.cjs`(供模型 RPC 域使用)各自声明 `DEFAULT_TIMEOUT_MS` / `DEFAULT_MAX_TOKENS` / `DEFAULT_OUTPUT_LIMIT`。两者是不同消费者而非同一逻辑的副本,合并会破坏 `HMM-02` 的逐字冻结基线,故保留两份定义,新增 `HMC-01..03` 一致性断言锁住数值(当前 30000 / 2000 / 8000),任一处分叉即红。**已实测**:`test/host-models-constants-sync.test.cjs` 3/3;完整 `npm test` 947/947(当批);门禁链 exit 0(5 PASS · 2 基线接纳 SKIP)。用户可见文案、RPC、配置键与安装形态未改。已随 v3.5.1 发布(npm `latest`)。 - **执行器根目录随包名迁移,旧目录回退(修复 · 2026-11-05 · [PE-F01])**:`EXECUTOR_ROOT` 此前仍拼旧包名 `dsh-prompt-enhancer`,改名后新装用户与已装用户会落到两个目录。现改为新名优先、旧名回退:已装用户的执行器仍在旧目录下则继续使用,无需重装;全新安装写入新名。**已实测**:`executorDir()` 返回新名路径;`test/sys.test.cjs` 13/13;完整 `npm test` 944/944;门禁链 exit 0(5 PASS · 2 基线接纳 SKIP)。 - **BREAKING: 包名与仓库改名为 dsh-voice-prompt-enhancer(v3.5.0 · 2026-11-05 · [PE-F01])**:npm 包名、GitHub 仓库、cordis entry id/name、RPC 路由前缀统一改为 dsh-voice-prompt-enhancer(原 dsh-prompt-enhancer 已被他人占用,无法发布 npm)。新增 engines.dsh(>=0.2.1-rc.1)与 repository/homepage/bugs,市场可显示宿主要求并自动映射 npm 下载量。配置文件名迁移到新名,首次读取时自动复制旧文件、旧文件保留 .migrated 备份;部署账本与运行目录解析均支持新名优先、旧名回退,已装用户无需手动迁移。旧包名保留在读取候选里,下一版本再整体退役。**已实测**:配置迁移四场景(全新安装/旧用户升级/新旧并存/空目录)全通过;产物重建后 build-host/build-client --check 一致;split-identity 确认 4 面 18 项 identity 唯一;dead-code R1–R7 全过。已随 v3.5.0 发布(npm + GitHub Release)。 - **目标模式:增强生成与提交分离为独立阶段(架构/状态 · 2026-11-04 · [PE-F02])**:原先生成阶段同时产出最终 RPC 结果,`commitEnhanceResult` 虽已有契约实现却未接入线上主链。现新增 `enhance-commit.cjs`,生成阶段只产出 `enhanceCandidate`,随后由 `commit` 阶段统一映射为既有 `{ ok, text, model, fallbackUsed?, truncated?, message? }` 返回;`fallbackUsed`、截断降级、失败消息及四态语义保持原值。内部阶段顺序改为 `analyze → retrieve → assemble → llm → commit`,线上 `enhance/progress.stage` 仍保留既有 `llm` 名称以保持 RPC 兼容。新增 `HEC-01..04` 锁定候选映射、缺候选 fail-closed、产物内联与旧进度名不变。**已实测**:生成/提交/阶段/状态定向 57/57;真实 WSL Web 模型优化写回与撤销原文精确通过;门禁 dead-code R1–R7、RPC 15 条、提示词生成区均通过。用户可见文案、RPC 方法/字段、配置键与安装形态未改。未 bump/tag/发布。 - **目标模式:真实模型质量基线与范围数值保真(质量/提示词 · 2026-11-04 · [PE-F02])**:`quality-baseline.mjs` 新增 `--live` 与 `--voice` 三态入口:默认离线结果保持确定性;`--live` 经真实 DSH `enhance` RPC 与当前模型链跑固定语料,输出真实成功率、事实保留率与过度改写率;`--voice` 在未执行真实麦克风时明确退出 `2`,不把确定性 VAD 测试冒充硬件证据。真实模型首轮测得 `2-4` 被写成 `2 至 4` / `2–4` 且事实保留率 95.8%;随后在纪律层与全部增强模板加入“数字/区间符号/单位/版本号原样保留”硬约束,WSL 重装复测事实保留率达到 100%。短草案 E3 的结构化扩展阈值按其内容形态显式设为 4 倍,事实保真阈值仍为 100%。新增 `QLIVE-01..05`。**已实测**:提示词同步/生成区与 i18n 冻结 68/68;真实模型 6/6 请求成功、事实保留 100%;真实麦克风链路仍因 WSL 无录音设备未验证。用户可见文案、RPC、配置键与安装形态未改。未 bump/tag/发布。 - **目标模式:清理 client 死入口并强化契约对账(维护/契约 · 2026-11-04 · [PE-F01/PE-F02])**:删除重构后零消费者的 `dynamicCordisRunner` 查询、空 `sidebar.footer.action` 服务端占位注册与 `CordisBadgePlaceholder` 组件,死代码白名单同步移除旧符号。正式动态/静态安装契约不变:`lib/client.cjs` 仍按 `window.__ModuleLoader__.load` 自包含工厂注册,`plugin-host.js` 仍零外部 `require`。新增 `CDS-01..04` 反向锁;`contracts.test` 新增配置键集合、默认值对象、四态与降级原因的发布物双向对账。**已实测**:client 装配/死面/设置/测试清单定向 20/20;`lib/client.cjs` 重建成功。用户可见文案、RPC、配置键与安装形态未改。未 bump/tag/发布。 - **目标模式:安装后发布产物一致性校验(安装/验证 · 2026-11-04 · [PE-F01])**:`sync-runtime` 在原有 md5 检查之后新增安装副本逐字比较:`plugin-host.js` 与 `lib/client.cjs` 必须分别等于仓库构建产物;`package.json` 作为 npm 安装元数据不参与静态内容判定(避免局部安装被 npm 正常改写时假红)。该检查直接验证「源码模块化、构建产物自包含、profile 安装实际装载同一产物」的完成定义,不依赖声明或文件存在。**已实测**:WSL 隔离 profile 使用本地 tgz 安装后存在 `plugin-host.js` 与 `lib/client.cjs`;RPC、客户端 UI 与真实模型链均从该安装副本运行。用户可见文案、RPC、配置键和安装方式未改。未 bump/tag/发布。 - **目标模式:修复 WSL Web 设置页装配导致整段空白(修复/装配 · 2026-11-04 · [PE-F02/PE-F04])**:真实 DSH Web 端打开“提示词 · 语音增强”时,`VoiceSection` 收到未定义的 `voiceHotkeyDisplay`,先触发 `TypeError`;修复该注入后,模型链展开又因 `ModelMainSection` 未收到 `FallbackRow` 触发 `ReferenceError`。现由热键模块直接导出 `voiceHotkeyDisplay`、共享运行时统一转发,并在创建模型主区块前实例化 `FallbackRow` 后显式注入;工厂不再依赖词法作用域中的偶然同名变量。回归锁由“设置页工厂存在”提升为真实产物装配渲染、设置内容与模型链行依赖断言。**已实测**:定向设置/装配测试 8/8;WSL 隔离 profile 从本地 tarball 全新安装并重启后,设置页完整渲染模型链与 4 个语音开关,`[data-slot-error]` 与浏览器 console error 均为 0;切换“自动增强”后磁盘 `voice.autoEnhance` 从 `false` 变为 `true` 并恢复;真实模型完成增强写回,撤销精确还原原文。WSL 无录音设备,真实麦克风语音链未验证。用户可见名称、文案、ARIA、CSS 类、槽位 ID、RPC、配置键与安装方式未改。未 bump/tag/发布。 - **目标模式:RPC 调用面全面改为契约键(架构/契约 · 2026-11-04 · [PE-F01/PE-F02/PE-F04])**:宿主注册面与客户端调用面已不再手写具体 RPC 方法名,统一使用 `RPC_METHODS`;客户端 `cloneDefaults()` 也改为直接深拷贝契约默认值,移除最后一块完整配置默认值副本。`rpc-manifest` 与 `pkg-identity` 已同步支持解析 `RPC_METHODS.*`,新增 `RCR-06` 反向锁:除 `lib/contracts.cjs` 外,手改 `src/` / `lib/` 中不得再出现 `host.call('…')`、`api.call('…')` 或 `harness.handle('…')` 形式的方法名字面量。**已实测**:全量 `npm test` 为 **929 tests / 928 pass / 0 fail / 1 skipped / EXIT=0**;RPC/客户端/语音/模型/设置/纠错定向 **257/257**;`rpc-manifest` 仍为 15 条、`pkg-identity` 4 面 18 项无撞;双构建 `--check` 通过。用户可见文案、RPC、配置键与安装形态未改。未 bump/tag/发布/安装/重启。 - **目标模式:统一状态语义并建立离线质量基线(质量/状态 · 2026-11-04 · [PE-F02/PE-F04])**:修正纠错结算的失败优先级——只有 `ok:true` 且 `skipped:true` 的服务端响应才记「因开关跳过」,`ok:false + skipped:true` 不再被错误渲染成跳过;新增 `state-semantics-audit`(6 条)覆盖增强、纠错、清口水词共用的 `changed/unchanged/skipped/failed` 与 degraded 不掩蔽终态。新增 `test/fixtures/quality-baseline/corpus.json`、`scripts/quality-baseline.mjs` 与 `test/quality-baseline.test.cjs`:固定离线语料量化增强事实保留率、过度改写率、纠错误改率/召回率,并复用现有 VAD 与超时预算回归统计通过率。`npm run quality` 实测:增强事实保留 **100%**、过度改写 **0%**、纠错误改 **0%**、纠错召回 **100%**、VAD 自动停/开关回归 **27/27**、时延/预算规则 **8/8**、本地清洗总耗时 **1.2ms**;离线质量单测 3/3。⚠ 该基线不冒充真实模型质量或真麦克风链路,二者仍未验证。用户可见文案、RPC、配置键与安装形态未改。未 bump/tag/发布/安装/重启。 - **目标模式:RPC/错误码/默认值收敛为发布物内契约事实源(架构/契约 · 2026-11-04 · [PE-F01/PE-F02/PE-F04])**:新增 `lib/contracts.cjs`,集中声明 15 条 RPC 的名称、所属半部、参数校验形状、显式无校验理由,以及错误码到既有 i18n 键的映射、结果状态、降级原因、配置键和五模式默认值。`lib/rpc-schema.cjs` 改为从契约表派生(不再手写方法字面量),`scripts/rpc-manifest.mjs` 的 schema 面与无校验声明同源读取;客户端 `ERROR_KEYS` 与常量/默认值改为契约转发,宿主纯函数模块的预算/参数/模板上限也取同一事实源。源码侧 `src/shared/contracts/*` 只做转发,发布包仍只含 `lib/`。新增 `test/rpc-registry-contract.test.cjs`(6 条)锁住「契约 ↔ 线上注册面 ↔ schema ↔ 文档」及「无第二份错误码/默认值」;`host-pure-module` 等价锁改为「契约托管块之外逐字相同 + 旧值与新契约逐项同值」。RPC 名称、参数、返回结构、配置键、用户可见文案与安装形态均未改。**已实测**:契约/配置/语音/纯函数定向 54/54;`client-enhance-flow` + `client-apply-regression` + 契约锁 20/20;`lib.test` 63/63;`p0-stop-bleed` 24/24;`dead-code` R1–R7 全过(R5 112 符号 / R6 14 文件);`build-host --check` / `build-client --check` / `sync-prompts --check` / `rpc-manifest --check` 通过;`gate --accept-unjudged=arch-claims,cards` 为 5 PASS / 0 FAIL / 2 SKIP(arch-claims 36 通过、3 SKIP;cards 为本地治理面缺位 SKIP;退出码 0 来自显式基线接纳,非全判通过)。**未验证**:真实 DSH 页面渲染、真实麦克风语音自动结束、真实模型增强质量(未安装、未重启)。未 bump/tag/发布/安装/重启。 - **目标模式:语音契约下沉发布物,修复安装包缺模块(架构/发布边界 · 2026-11-04 · [PE-F02/PE-F04])**:CHG-350 让 `lib/asr.cjs` 引用了 `src/shared/contracts/voice-config.cjs`,而 npm `files` 白名单只有 `lib/` ⇒ 安装包会缺模块。现将契约实现迁到 `lib/voice-config.cjs`(发布物内自包含),`src/shared/contracts/voice-config.cjs` 仅作源码侧转发;`lib/asr.cjs` 改为 `require('./voice-config.cjs')`。A230-1 的 lib 域清单登记新模块(14 件),R5/R6 基线随合法新增同步为 81/13。新增 `VCONF-07`:锁住运行时模块不得引用 `src/`、契约文件必须落在发布白名单。**已实测**:完整 `npm test` 为 `914 tests / 913 pass / 0 fail / 1 skipped / EXIT=0`(约 710s);`npm pack --dry-run` 已包含 `lib/voice-config.cjs`(20 files / 272.6kB);语音配置/VAD/语音状态/契约定向 47/47;`dead-code` R1–R7 全过;`arch-claims --check` 为 36 通过 / 0 冲突 / 3 SKIP;`split-identity` 与 `shared-fns` 通过;`build-client --check` / `build-host --check` 通过;`gate --accept-unjudged=arch-claims,cards` 为 5 PASS / 0 FAIL / 2 SKIP、退出码 0(基线接纳,非全判通过)。用户可见文案、RPC、配置键、槽位与安装形态未改。未 bump/tag/发布/安装/重启。 - **目标模式:VAD 档位归一收敛到共享契约(架构/契约 · 2026-11-04 · [PE-F02/PE-F04])**:`normalizeVadSilenceMs` 原先在 `lib/asr.cjs`(host)与 `src/client/voice/state-module.cjs`(client)各有一份手写实现;现提升到 `src/shared/contracts/voice-config.cjs`,client 由 `client-runtime` 显式注入、host 直接消费同一实现。合法域与回落值(1–5 秒 / 1000–5000ms 整千倍 / 非法回落契约默认值)逐项不变。新增 `VCONF-06` 锁定 client 契约与 host `sanitizeVoiceCfg` 在同组合法/非法输入上逐项同值。**已实测**:完整 `npm test` 为 `913 tests / 912 pass / 0 fail / 1 skipped / EXIT=0`(约 695s);语音配置/VAD/语音状态/契约定向 47/47;`build-client --check` / `build-host --check` 通过;`dead-code` R1–R7 全过(零 chunk 面仍显式 PASS);`gate --accept-unjudged=arch-claims,cards` 为 5 PASS / 0 FAIL / 2 SKIP、退出码 0(基线接纳,非全判通过)。用户可见文案、RPC、配置键、槽位与安装形态未改。未 bump/tag/发布/安装/重启。 - **目标模式:删除最后一份字符串 chunk,零 chunk 面仍保持 fail-closed(架构/构建 · 2026-11-04 · [PE-F01/PE-F02])**:`src/client/skeleton.js` 已无任何构建/测试消费者(仅历史生成注释),本批删除,`src/client` 与 `src/host` 的字符串 chunk 面归零;源码唯一入口仍是 `src/client/app-module.cjs` 与 `src/host/app-module.cjs`,由 module-bundler 打成自包含产物。`chunk-decode.listChunkFiles` 改为“目录存在且为空 = 合法 0 件;目录缺位 = 抛错”,R7 对零 chunk 面仍显式给出 PASS(`0 个 client chunk`)并保留装配图可构建、两产物可求值的牙齿;新增 CH-05、R7 零 chunk 负控与“扫描目录缺位必红”用例,防删除后门禁空转。`governance-landing-locks` 的 chunk 快照改为磁盘实测注入,不再写死历史 29 件。`arch-claims` 的 S-8 只把索引列作判定、工作区删除(`w/ ?`)不再冒充行尾违约,删除受控文件时仍由索引侧 `text` 判据覆盖。用户可见文案、RPC、配置键、槽位与安装形态均未改。**已实测**:完整 `npm test` 为 `912 tests / 911 pass / 0 fail / 1 skipped / EXIT=0`(约 696s);chunk/契约/布局/治理/死代码/清单定向 97/97;`build-host --check` / `build-client --check` 通过;`dead-code` R1–R7 全过(R7 显式报 0 个 client chunk、装配图可构建、两产物求值通过);`rpc-manifest --check` 仍为 15 条线上方法;`gate --accept-unjudged=arch-claims,cards` 在删除前为 5 PASS / 0 FAIL / 2 SKIP、退出码 0;删除后本地 S-8 的“受控件行尾”读数会把**尚未提交的删除**仍算作受控件(索引尚未更新),以提交后的复跑读数为准。**未验证**:真实 DSH 页面渲染、真实麦克风语音自动结束与真实模型增强质量(未安装、未重启)。未 bump/tag/发布/安装/重启。 - **目标模式:契约层收敛为单一事实源,构建器支持 JSON 模块(架构/契约 · 2026-11-04 · [PE-F01/PE-F02/PE-F04])**:`src/shared/contracts/index.json` 新增 `degraded` 原因清单(检索/判定/文档/历史/网络规划/进度与输出截断),`index.cjs` 以冻结视图导出;`result.cjs` 新增 `postprocessOutcomeOf`,把清口水词、纠错与增强共用的 `status/text/changes/reason/degraded` 归一为一份事实源,`client-runtime` 同步导出。`enhance-runtime.markDegraded` 改为只接纳契约内原因(契约外只写诊断日志,不进用户可见清单);`enhance-result-module` 的失败状态改用 `RESULT_STATUS.FAILED`;client 增强结果映射补传 `skipped`,不再把跳过与改动混同。`module-bundler` 将 `.json` 作为一等模块(构建期 `JSON.parse` 校验、CommonJS 赋值形态内联),非法 JSON fail-closed。RPC 名称/参数/返回结构、配置键与用户可见文案均未改。**已实测**:完整 `npm test` 为 `909 tests / 908 pass / 0 fail / 1 skipped / EXIT=0`(约 635s);契约/构建/结果定向 106/106;`module-bundler` 8/8(含 JSON 正例与非法 JSON 负控);`build-host --check` / `build-client --check` / `sync-prompts --check` / `rpc-manifest --check` 通过;`dead-code` R1–R7 全过;`gate --accept-unjudged=arch-claims,cards` 为 5 PASS / 0 FAIL / 2 SKIP、退出码 0(基线接纳,非全判通过)。**未验证**:真实 DSH 页面渲染、真实麦克风语音自动结束与真实模型增强质量(未安装、未重启)。未 bump/tag/发布/安装/重启。 - **目标模式:修复 client 运行期装配回归并加 apply 级回归锁(修复/测试 · 2026-11-04 · [PE-F01/PE-F02/PE-F04])**:CHG-346 的入口把状态 API facade 误当状态对象传给组件(真实页面 `configState.value` / `voiceCfgState.value` 为 `undefined`),且产物外壳缺少 `styles` facade、以 `localStorage` 键传存储而入口读取 `storage`、组件工厂在 `apply` 前捕获的 `timerSvc` 为 `null`。现入口显式拆分 `configApi/configState`、`voiceApi/voiceCfgState`,统一 `storage` 归一化并显式注入状态与增强会话模块;`timerSvc` 改为基于同一 `timerRef` 的晚绑定代理,`apply` 时同步 timerRef、官方语音桥 timer 与进度轮询/保存防抖;产物外壳补回既有 `styles.insert` 行为(专用 `