# Changelog 本项目版本号遵循 `0.x` 阶段的语义化:`0..`;预发布版本带 `-beta.N` 后缀(面板中显示为 `0.3.0beta1`)。 ## 0.8.4-stable — 六条线上 issue 修复与顾问闭环 > 发布 tag:`v0.8.4-stable`。本版把 GitHub 上**六个仍开着的条目**逐条修掉(#29 ~ #34), > 并在 "顾问给出的结论到底能不能用" 这条链上做了一轮收口。不含协议重写,不改用户模型与权限。 ### 顾问闭环(本版主线) - **按具体主张核对证据**:每条结论只对它**实际引用**的材料负责。未引用的补充材料即使被截断或缺失,也只是警告,不再整体否决报告; 被引用的截断材料仍必须完整定向补读。源码、截图与运行记录**不互相冒充**(内容被读到 ≠ 语义正确 ≠ 真实运行已证实)。 - **前版对照**:同一任务、同一对象的后续改进可以看到**实际已发送过的**改前内容;文件变了只提示"需要比较", 不把"文件不同"说成"采用成功"或"质量提高"。`keep` 合法,且不算验收通过。 - **逐轮交付旁注**:按会话 + 事件序号重建**该轮**的复核状态(已知缺陷 / 待验证 / 仅所列范围 / 没有复核), 不用后续轮次覆盖旧答复,不读"完成了"作裁决,不拦文件分享,也不自动追加模型回合。 ### 修复(对应线上 issue) - **#31 解析被拒时两级兜底不生效** —— `emptyResultReason` 只把 `NO_JSON` 当空产出, `BAD_JSON` / `BAD_OPTIMIZER_SHAPE` 直接落到 `parse-rejected` ⇒ 用户看到"失败:no-packet"。 现在两类同等对待:先重试一次,仍坏则由宿主补一条**如实说明**的兜底条目。真机 429/772 位置上多出来的那个 `}`, 改由**配对括号扫描**取第一段完整对象解决(内含字符串与转义处理,只对贡献报告做**值不变**的单引号恢复,验收报告不修)。 - **#32 顾问无法接受文件输入** —— `prepareAdvisorMaterials` 的失败路径只把 F 编号放进 `evidence`,**没放进 `evidenceIds`**, 于是"我读不到这个文件"这句实话没有合法引用 ⇒ 整份报告被判 `advisor-invalid-citation`。现在失败路径同样登记, 读不到的材料可以正常引用、缺口如实入账;`/po06/api/status` 也不再写死 `readEnabled:false`。 **保留**:声称 `satisfied` 却没有任何**结果类**证据仍然整份拒绝(这条防线不许松)。 - **#30 复核落账失败 + 失败卡片丢弃产出** —— 读痕迹原先按 (路径, 起止行) 去重,同一文件读 5 段会产生 11 行、 撞上 8 行上限 ⇒ `invalid-stage-material`,已经通过的结论被丢掉。现在按**文件版本**(路径+sha256)归并, 同一版本的多段读取合并成一行并保留 `readRanges`;真实多版本不会被吞。失败/中断的卡片同时补上投影三轮投影 (`partialReasoning` / `activities` / `raw`),并把"保留部分内容"的标题改成**只在真拿到内容时才出现**。 - **#33A 非 delivery 下 `requiredScopes` / `requiredReviews` 误拒** —— 这两个参数的**全部**消费方都在 delivery 分支内, 非 delivery 下是纯 no-op,却按硬错误拒掉整次调用(真机某会话 21 连败 0 成功);而 schema 的 enum 又把 8 个值全给, 照 schema 选值必被拒。现在非 delivery 一律放行(且不改写调用方对象),delivery 内的非法值仍被拒, 拒绝理由带上**当前值、允许取值与正确用法**,schema 同步收紧。 - **#33B 英文模式翻译中断** —— 上游抖动(503 / 首字节超时)会让翻译流以 error/aborted 收尾,整轮直接红。 现在:容忍围栏 / 前后散文 / 对象之后的杂尾的翻译 JSON 提取;有界重试(永久性错误与已取消不重试); **每条**失败路径都带 `attempts` 台账,宿主把它写进 wire log 与返回值。 - **#34 顾问无产出时干等满熔断** —— 新增**空闲判死**:只在连续没有任何正文/思考增量与查证事件时才结束(默认 90 秒), 有任何产出即重置。走的是既有的截断路径,"到点不许抹掉已产出内容"的语义原样保留。 这不是总截止(默认仍不设总截止);`DSH_PO06_ADVISOR_STALL_MS=0` 可完全关闭,非法值回落默认。 - **#29 安装分发(文档)** —— 本插件**按设计不发 npm**,插件市场因此回落到 git 安装;README 增加排查表: `schannel: SEC_E_INVALID_TOKEN` 是本机 git 的 TLS/代理问题,`allowBuilds` 提示对本包无效(本包没有任何构建脚本)。 ### 其它 - 测试:**104 套 / 1141 项**全绿(含打包自足性、文档漂移门禁)。新增 `advisor-stall`、`advisor-open-issue-30`、 `open-issues-31-32` 三套针对线上 issue 的回归,另有 parity / pipeline / scope 用例按**新契约**更新。 - 界面作用域静态守卫修掉一处**误报**:`props.sessionId` 与对象字面量的键不再被当成自由引用(判据本身没有放松)。 ## 0.8.3-stable — 解释协议 v3(短协议)与 CI 可移植性 > 发布 tag:`v0.8.3-stable`。本版重写了**发送前那一轮的优化解释协议**:把工程字段从模型手里拿回来, > 让模型专注"读懂你的意图 + 贡献有价值的补充"。同时修掉三处只在特定机器/Node 版本上才暴露的失败。 ### 解释协议 v3(本版主线) - **更短、更专注的协议**:模型只收到「共用核心 + 当前档位 + 薄输出格式」(需要时再加只读/语气/英文段)。 中文普通组合:轻度 596 / 标准 599 / 重度 639 字符——此前是三段叠加的数千字符。 - **输出改为 `intent` / `clarify` / `add` / `ask`**:本轮意图、表达澄清、正向补充与建议、需要反问的点。 条目 ID、来源绑定、状态补丁、逐字引文比对**由宿主负责**,不再要求模型填写这些工程字段。 - **原意权威不变,但不再靠"逐字引文"一刀切**:你的原话独立保留、原样发出;模型产出的澄清与建议**始终是机器建议**, 不会被放进"用户明说"那一类。引文比对仍用于旧格式,且继续按条丢弃而不是整份作废。 - **三档按用途区分**(不再靠条数、字数或问题配额):轻度=把原意讲清楚、消除歧义、指出必要反问; 标准=澄清表达并补足影响结果最大的缺口;重度=围绕已有目标做全方位正向补充、构思与方法,并呈现实质取舍。 - **零增量是合法结果**:没有值得补充的内容时不再硬造条目、也不再因为"空"而重试。 - **旧上限取消**:新路径不再受 12 条 / 300 字 / 提问配额约束;长建议与多条反问完整进入上下文与审查面板。 - **英文模式改用原生英文协议**:不再"自定义译文 + 英文内置协议"叠加;忠实任务翻译与新增建议分开, 代码块、路径、URL、JSON 与精确回话继续逐字保留,用户自己的语言要求原样保留。 - **界面可核对**:详情里同时给出「当前设置的完整组合预览」与「本会话最后一次**实际发送**的协议、字符数与思考档位」, 预览明确标注不是实测请求。拦截浮层继续流式显示新格式的理解、澄清与建议。 - **本机旧默认提示词精确迁移**:只在与内置旧默认**逐字节相同**时替换,替换前原样备份; 真正改过的自定义文本一律保留(并继续接受旧格式输出)。 ### 修复 - **CI 在旧 Node 上必然红(真实缺陷)**:`read-session.mjs` 用具名导入取 zstd 解压 API, 而该 API 是 Node 22.15+/23 才有 ⇒ 在 Node 20 上**整个模块链接失败**,连"优雅报错"的机会都没有。 改为命名空间导入 + 能力探测:有就走原逻辑,没有就如实说明缺什么并跳过(附带静态守卫禁止退回具名导入)。 - **安装检查依赖机器上装了 `dsh`**:装配层验证要跑一次 `--dump-config`,而 CI runner 上没有这个命令 ⇒ 那条"无法验证装配层 ⇒ 阻断"的纪律会把测试夹具一起判死。现在 `dsh` 命令可注入(`--dsh` / `DSH_PO06_DSH`), 单测自带桩命令;同时**只在包确实装上了**才去验证装配层(没装就跳过,不再制造噪声阻断)。 纪律本身没放松:跑不了 `dump-config` 仍然阻断,并新增一条用例钉住它。 ### 工程 - 发版门、CI、套件、变异守卫继续共用同一套计数口径;本轮计数见 `po06/eval/release-check.json`。 ### 未验证 / 不声称的部分 - **没有做专业跑分,也没有"更快"的结论**。协议变短不等于模型更快:思考档位、上下文与任务本身都会影响耗时。 - 新协议**不保证**建议一定更好或更少跑偏;它保证的是"不再把工程字段与逐字引文强加给模型", 以及"机器建议不会冒充用户要求"。实际价值需要你在同一任务上对照三档自行判断。 ## 0.8.2-stable — 英文模式、推理增强(实验性)与发布门修复 > 发布 tag:`v0.8.2-stable`。本版把上一节遗留的 issue 修复(#23 / #25 / #26 / #27 / #14)一并带上, > 并新增英文模式、实验性推理增强,以及一组发布门与文档修复。 ### 新增 - **英文模式(默认关闭)**:面板里与「权限」同款两档滑档。把用户任务、优化策略与辅助文转成英文再送给模型, 界面仍为中文;状态里的要求正文**回到原话语言**(英文那份只作注入口径),关掉英文模式后状态照样可读。 - 逐字保护:代码块、内联代码、`@"路径"`、URL、Windows/POSIX 路径、JSON 字面量与精确回话不参与翻译; - 翻译与辅助**解耦**:过期输入或已取消的请求不会发出去;翻译失败只回落一次,并保留真实失败原因; - 斜杠命令不参与翻译;允许列表内的命令(如 `vmake`)**照旧走拦截审查**(本轮曾因放行条件写错而漏拦,已修并加回归)。 - **不添加答复语言要求**:答复用什么语言由模型按你的话决定;需要中文就在原话里说。 - **推理增强(实验性)**:置于选项面板最底部并单独分界,含多候选择优 / 循环改进 / 混合三种模式与快速-均衡-跟随三档强度; 「推理过程」面板只在开关打开时出现。面板内写明了真实代价:**目前无法确定它能否稳定提升模型能力,但会大幅增加模型工作时间,请谨慎开启**。 ### 工程 - **CI(本版新增)**:`.github/workflows/ci.yml` + `po06/scripts/run-suites.mjs`(与发版门同一条调用方式与计数口径, 受限环境自动选择可写临时目录)。套件与发版门从此在每次推送时自动运行,不再依赖人手。 - **变异守卫修复**:两个变异体的锚点仍写着旧节标签 ⇒ 变异**从未被应用**,而门禁把它报成"未被捕获",方向完全相反。 已修锚点并逐条实测确认会红;门禁现在把「锚点失效(守卫等于不存在)」与「变异未被执行捕获(测试变弱)」分开报。 - **清理**:删除已被内联取代的重复模块(`lib/bash/client.js`、`lib/bash/bash-tool-contract.mjs`); 未接线的 `lib/bash/runtime-integrity.mjs` **保留并写明**,新增用例钉住"一旦接线就会红"。 ### 修复 - **#23 内置 Bash 在 win32 上把 `HOME` 显式指向真实用户目录**(此前落在自带 MSYS2 运行时内**不存在的目录**)。 - 症状:插件内 `git config --global --get ` **永远读到空**——静默返回 1,不报错、不崩、日志里什么都没有; 同一台机器、同一个用户,插件内外是**两份不同的"全局配置"**。 - 根因:spawn 的 env 只有 `{...process.env}` + `PATH`,**没有 `HOME`**;MSYS2 在被非 MSYS 父进程启动时兜底成 `/home/<账户>`,而本私有 root 的 `/` 就是 `po06/runtime` ⇒ 落点 `/runtime/home/`,该目录不存在、也没人创建。 - 修法:`win32` **且**本次运行时来源是**自带 bundle** 时才接管;取值 `DSH_BASH_HOME` → `USERPROFILE` → `HOMEDRIVE`+`HOMEPATH` → `os.homedir()`。Git for Windows / 系统 MSYS2 / `DSH_BASH_PATH` / 显式 `config.bashPath` **一律不动**(它们各自已把 HOME 映射到用户目录)。 - 来源:**PR #23(作者 @deadbushxw)**;本机已复现(`HOME=/home/WestFox`、`git config --global` 返回 1)并验证修复。 - 取舍(如实写明):内置 Bash 不经 ACL 沙箱,交出真实用户目录意味着 `~/.ssh`、`~/.gitconfig`、`~/.netrc` 在其可及范围内。 本版选的是"配置可用性与插件内外一致",**不是隔离**;需要隔离的用户请设 `DSH_BASH_HOME`。 - **#27 按会话拨档位(`bySession`)也写启用意图**。 - 症状:新装后"进会话 → 在面板拨档位",闸门永远 `gate:rollout-off`,界面报"失败:gate:rollout-off", 用户看到的是"插件装了却什么都不做"。 - 根因:面板切档位走的是 `save({ bySession: … })`,而写启用意图的判据只认**顶层** `tier|assist|detail|budget` 四个键(#16 的修法只覆盖了全局那条路)。 - 修法:按会话的档位写入同样补 `enabled:true` + `rollout:{mode:'all'}`;**只开不关**——把某一场设为"关闭" 不代表整个插件要关,那条不写 gate;只改 `framing` 这类非档位项依旧不碰启用意图。 - **#26 发版门同时认两种套件风格**。 - 症状:`check-release.mjs` 恒 FAIL,43 项阻断里 **38 项是"输出无法解析"**。 - 根因:门把每套的**整段 stdout** 当一行 JSON 解析,而仓库里并存两种风格——自研 runner(结束时吐一行 JSON)与 `node:test`(吐 `ℹ pass N` 汇总行)⇒ 后者一律被判为无法解析。 - 修法:新增 `readSuiteSummary()` / `lastJsonObject()`——先试末尾 JSON,再试 `ℹ`/TAP 汇总行;两者都不认才记 unparsable; 并补"自述 fail=0 却非零退出按失败处理"。变异检验与打包演练同样改为末尾 JSON 读法。 - **#25 审计判据读进编译器自己写的【预算不足】降级说明**。 - 症状:发送条目较多的长消息时,前置拦截报"失败:no-packet"(消息按设计原样发出),台账该条 `outcome=audit-failed packetChars=0 packetOverBudget=true packetOverBy=36`;而 11 秒后同一轮的 生产路径却 `committed`、`packetChars=1171` —— 内容本身合格,只有前置那一步被拒。 - 根因:审计规则是 `chars > budget && dropped.length === 0`,而这种情况**恰恰就是** `compose()` 写【预算不足】的唯一场合(必保内容本身超预算、可丢节全空)⇒ 判据漏读自己写下的降级说明, 合规产物必被整包拒收(报错文字里的 "and no explanation" 是假的)。 - 修法:与编译器口径对齐——`overBudget`/`overBy > 0`(说明已写)即视为"有说明", 只有"既没丢条目、又没写说明"才报;并补正反两侧用例,确保判据没被架空。 - **#14 认出 DSH Desktop 的路径形态 profile 位置参数**。 - 症状:桌面端**不传 `--profile`**,把 profile 目录当**位置参数**交给 desktop-host;那些参数含分隔符 ⇒ 被名字正则挡掉 ⇒ `resolveProfileName` 回落默认 `web`,而进程实际跑的是 `desktop`。于是"旧插件是否仍在装配"的判断问的是 **另一个 profile**,双重拦截守卫可能给出相反结论(与 EV-0081/EV-0121 同形:不报错、只给错答案)。 - 修法:裸子命令之后追加一轮**路径形态**候选——取末段并用 `profileExists` 证伪,**不写死 `profiles` 目录名**; `--profile X` / `--profile=X` / 裸子命令的优先级不变。 - 来源:#14(该 PR 基于旧 main,本轮**只移植这一条特性**并补当前基线的回归用例;未整体套用, 以免回退 `reasoningEffort` 等后续改动)。真机 argv 前后对照:修前 `web`/修后 `desktop`。 ### 已知未包含 - **#5 / #12 / #28**:分别疑似扫描器误报、产物已演进的交互建议、推广内容,需答复后关闭,不需要改代码。 ## v0.8.1-stable — 2026/10/03(装配修复版) ### 修复(针对「在 DSH 0.2 上装上了却用不了」的反馈) - **根因:发布产物里的身份标识与包名不一致。** `0.8.0-preview` 的 tgz 中 `package.json` 已是 `@dsh-external/dsh-arbiter-wf`,但 `lib/client.js` 的注册 id、`lib/index.js` 的 `export const name` 与 `PRODUCER_KIND` 仍是旧名 `@dsh-external/dsh-po06`。宿主按包名生成 boot row id 并**只在该 id 下找注册** ⇒ 报 `loaded without registering "@dsh-external/dsh-arbiter-wf"`,**client 半侧整个不激活**(面板、卡片、设置页都不出现)。三处标识连同 `cordis.patch.yml` 的 entry 名一并改正。 - 这与 DSH 版本**无关**:同一份产物在 0.1.7 上同样注册不上。0.7.8 及更早的产物名字一致,所以只有装了 `0.8.0-preview` 的用户会中招。 - 新增 `po06/test/identity.test.mjs`:包名、client 注册 id、`export const name`、`PRODUCER_KIND`、patch entry 名**从 `package.json` 动态取真值**再比对——写死字面量会在下次改名时静默通过。 - **#22 `readTools` 恒报 `no-packet`**:判定是否工具包只用了 `/"ops":/` 子串匹配,混着散文的 JSON 直接漏判。改用流水线同一个 `extractJson`。 - **#17 每次 bash 调用都刷 `/tmp` 警告**:内置 MSYS 运行时缺 `/tmp` 时 `bash.exe` 会打印 `could not find /tmp, please create!`。改为**注册期**与**每次执行入口**都确保存在(执行入口早于运行时探测,避免探测阶段就先刷一遍警告)。 - **#16 面板里把档位从 off 调回可用时插件仍是关的**:`writeSettings` 只透传 `enabled`/`rollout`,没有任何代码路径把 `enabled` 写回 true。改为按档位联动门禁(`tier=off` ⇒ 关闭门禁与 rollout;档位可用 ⇒ 重新启用,已处于白名单模式时不覆盖)。 - **#19 切换会话后悬浮球与拦截面板状态不同步**:两处各持一份 `hold` 状态,只有一个组件能收到事件。改为模块级 hold 桥(写状态 + 派发事件,订阅方采纳),并保证卸载时不再 abort 正在进行的回合。 - **#18 浮层被右侧预览栏压住**:改为**排布**方案——量输入卡片得到「会话窗」边界,浮层整块收在窗内(右缘不越过会话窗右缘),会话列变窄时浮层跟着变窄。右侧栏若是不压缩会话列的**固定浮层**,另有一条保守探测取它的左缘当边界。重算由共享观察器驱动:窗口缩放 + 输入卡片尺寸 + `body` 子节点与 `class/style/subtree` 属性变化(侧栏靠 class 显隐时也生效)。拦截浮层、悬浮球、优化选项弹层、帮助弹层、设置面板五处统一走这套边界。 ### 新能力 - **拦截面板产出层流式显示**:优化进行中就把产出层的中间结果实时画出来,标注「正在生成 · 尚未校验」,只读;校验完成后才切成可编辑的最终报文。此前整块 UI 在生成期间是静止的,成品突然出现。 ### 兼容性(同一份产物同时适配 0.1.7 与 0.2.0-rc.2) - 对 0.2.0-rc.2 的实际产物做了逐成员契约对照:模块加载契约、`dsh.client` 清单、四个插槽、工具与卡片注册、`clientModules`/`systemPrompt`/`sessionProjections`/`webServer`/`agents`/`llm`/`attachments`/`commands` 全部一致;19 个接触包中 14 个的类型声明与 0.1.7 **逐字节相同**,另外 5 个的差异全是**追加或可选参数**,不触本插件调用点。 - 未验证项如实保留:0.2 的插件装配路径是否仍接受本包的 patch + junction 形态、桌面端是否复用 `platform:"web"` 客户端、`session` 中「中断工具调用修复」带来的运行时行为差异。详见 `docs/DSH-0.2-COMPAT.md`。 ## v0.8.0-preview — 2026/10/01(改名首版,未发布 npm) ### 更名与定位 - **插件更名为 `dsh-arbiter-wf`**(原 `@dsh-external/dsh-po06`):对外显示名、包名、以及 bundle 装配条目(`cordis.patch.yml` 的 entry id 与 `name`)一并更新。 **配置与台账文件名不变**(`po06.json`、`po06-state/`、`po06-wire.jsonl`、`po06-advisor-ui.json`、`po06-bash-invocations/`)⇒ **旧设置无需迁移**;内部路由前缀 `/po06/api` 与 `DSH_PO06_*` 环境变量维持兼容。 - 描述(插件列表里那行)改写为当前能力:**把你的话编译成可执行约束 → 治理工作区工具运行时 → 交付前独立复核**。不再出现「0.6 beta / P1–P8」旧口径,也不作性能断言(效果证据待后续跑分)。 ### 新能力 - **独立顾问 `consult_task`**:另一个模型实例只按原始证据与用户原话复核,沿用优化 AI 的模型与思考档位。 - **分阶段专项复核 scope + focus**:形体与装配 / 画面观感 / 代码正确性 / 交互逻辑 / 性能证据 / 交付覆盖 / 自定义。视觉专项只带图像、不混开发历史与源码;代码专项按相关证据筛选、不带图像。 - **交付覆盖核对**:`requiredReviews:[{scope,focus}]` 精确列对象;材料变更、后续源码写入、覆盖不足时旧结论不得当作当前版本通过;**局部通过不等于整体通过**。 - **材料真实传递**:`files` 有界文本、`images` 经宿主附件服务成为真正的图像块;模型图像能力未知或不支持时明确标「未检查」。卡片逐项显示材料状态、片段与宿主侧栏预览。 - **斜杠命令允许列表 `slashReview`**:仅名单内且宿主确认已注册的命令走「拦截 → 优化 → 可编辑确认」;官方命令与未注册命令照旧直发;查不到命令表时退回名单并标注 `verified:false`。 ### 修复(本轮) - **顾问卡片 token 恒显 `Σ — tok`**:卡片优先取了进度记录里的 provider 原始字段,而格式化只认归一化字段。改为在格式化入口容错归一,**历史卡片刷新后一并恢复**;仍不折算、不估算合计。 - **bash 工具描述**:删除未实测的「跑 Windows 原生程序时 pwsh 通常更快更稳」,移到工具描述本体并改按命令性质给判据;保留「两者都能做时优先 bash」并标明属使用经验。 - **Bash 可靠性整改**:取消信号接入准备与执行阶段;每次调用独立输出目录与 UUID 文件;失败也保留 stdout/stderr;退出状态标记回到末尾;进程与 Job 句柄释放;日志按字节窗口读取;运行时探测可取消并短期缓存(成功 5 分钟、失败不缓存)。 - **Bash 诊断纠偏**:调用记录按会话与 UUID 隔离(不再用全局标记 + 年龄断言「上次崩溃」);少输出不等于失败或纯损失;链结构只报风险,不断言吞错。 - 发布产物清理:删除 `po06/runtime` 下混入的 3 个探针残留(未跟踪文件,曾被 `files: ["po06/runtime"]` 打进发布包)。 ### 边界(未验证项,如实保留) - 真实 Win32 Job 行为、脱离父链的 MSYS 子孙清空、真实模型识图效果**均未由本轮测试证明**;fallback 收尾无法证明树清空时明确标注 `not-evaluated`。 - 本条目全部断言来自确定性测试与真机日志,**不含性能跑分结论**(计划后续单独进行)。 ### 自 0.7.8 起的其它改动(原本地开发条目,随本版一并发布) - 修正 bash 工具描述:删除未实测的「pwsh 通常更快更稳」并移回工具描述本体,改按命令性质给判据 + 标注来源的 bash 优先经验;加机器守卫。 - 修复顾问卡片 token 恒显 `Σ — tok`:格式化入口对 provider 原始字段与已归一字段两种形状都容错,历史卡片刷新后一并恢复显示;仍不估算合计。 - 新增斜杠命令允许列表 `slashReview`:仅「名单内且已注册」的命令走拦截与可编辑确认;未注册/官方命令照旧直发,命令表不可用时 fail-closed 不拦截。 - 顾问分阶段专项scope+focus:视觉只审图、不混历史代码,代码按相关证据筛选;卡片显示范围与对象。 - delivery精确scope+focus覆盖核对,同真人请求材料版本/源码写操作变化提示,不把局部通过当整体通过。 - Bash可靠性整改:取消接线、并发输出隔离、保留失败stdout/stderr、末尾退出状态、Job句柄释放、有界日志窗口及可失效探测缓存。 - Bash诊断纠偏:按调用会话记录,少输出不等于失败,链结构只报风险;fallback收尾无法证明树清空时明确标注。 - 新增顾问files/images用途清单:有界UTF-8工程内容与正规图像附件块;能力未知/不支持的图片如实标未检查。 - 顾问卡片材料逐项显示状态、用途、片段与宿主侧栏预览,保存当次内容指纹;不自动扩大文件授权。 - 新增 `consult_task` 独立顾问工具,沿用优化 AI 的模型与思考档位。 - `diagnose_failure` 检查失败尝试的信息增量,给最小区分实验与停止条件。 - `review_result` 对照本轮原话及原始工具证据复核成果,排除主模型正文和先前顾问结论。 - 复用项目根内只读工具;默认 5 分钟截止取消(可调),按会话并发保护,卸载取消在途调用。 - 验收区分满足、不满足、未验证;拒绝伪引用和无证据通过,材料不完整时不认整体通过。 - 新增顾问专用卡片(覆盖代码内嵌子工具):实时阶段、实际思考流、查证记录、规整结论和验收项;支持有界历史回放和中止标识。 - 中止/错误流的局部通过降为未验证,UI 不把部分产出当完整验收。 - 只实现单轮咨询,不含跨轮记忆、强制交付门或自动返工。效果待用户手测。 ## v0.7.8 — 2026/09/29(**主线 · 正式版 · 会话级档位 / 交互框架 / bash 判定**) 作者:啃轮胎的西狐 这一版是三件事叠在一起:**档位终于按会话**、**多了一档会改变语域的协作基调**、**bash 调用开始当场判值不值**。 ### 一、档位改为会话级(修「点一次正常,之后固定」) - **成因**:点档位是**合并**写入,而宿主早先把 `tier` 展开成 assist/detail/budget 后**存了回去**; 于是第二次点击时,新的 `tier` 会与上一次展开的**陈旧三项**合并,读取时那三项盖过新预设 ⇒ 推导档位不变 ⇒ 界面看起来「点了不动」。第一次之所以正常,是因为覆盖是空的、没有残留可覆盖。 - **修法**:**存意图、读取时展开**——设置层只存用户写的 `tier`,展开挪到 `effectiveSettings`; 点档位时**整份替换**该会话的覆盖(不合并),从源头杜绝残留。 - 档位与协作基调都按会话存(`bySession`),全局只作默认值;另修掉两处 early-return 导致「加码只第一轮生效」。 ### 二、新会话首条消息挑错模型(修宿主方法名) - `agentDefaultModel` 的真实方法是 `currentSelection()`,而代码里试的是 `current/read/get/selection`—— **四个全不存在** ⇒ 第③步整段空转 ⇒ 掉到「模型清单第一条」,用与会话无关的模型去优化。 - 修法:把 `currentSelection` 放到候选名首位(实测它返回的正是 `{provider, model}` 形状)。 ### 三、交互框架(协作基调):普通 / 硬邦邦 - **依据**:用户实测——同样字数的正式提示词做不到口语版的效果 ⇒ 起作用的是**语域**,不是信息量。 机制是分布:正式语域采样「专业助手」那一簇(客套、求稳),口语+高唤醒语域采样「把活干出来」那一簇。 - **分工**:骨架归代码(标签 / 语域 / 越权反制行——三条不变量),加码归模型(按本轮实际写,长度自定、定点爆破)。 加码插在中间,**边界行永远在最后**;且必须**引用包内真实条目 id**,写不出引用就整段不采用、退回纯骨架。 - 两类例外保持字面、不许修辞:**未决项**(没拍板的事说清楚)与**防御性限制**(不许做什么、范围边界)。 ### 四、单轮提升(第一次就把事做对) - **任务类自查表**:【完成前自检】节,来自代码持有的任务类知识(第一批:单文件可交互 3D/可视化程序)。 来源是 `project_convention` 而非 human ⇒ 结构上不可能升格成用户要求。 - 质量解释要求落到「**可肉眼判断的维度 + 最低可接受线**」;新增【结构性分叉】规则(选错了后面全要返工的那种选择)。 ### 五、bash 调用质量判定 - **长等待 / 低产出**:耗时与字节当场交回(工具一直知道这两个数,却从没告诉过模型)。 - **链结构**:段数 ≥3 且用了吞错型连接符(`;` `|` `||`)⇒ 点明「中间某段失败了你看不出来」。 - **重武器 + 替代路径**:命中无头浏览器 / 装包 / 网络下载 / 重构建时,直接给能照做的更省做法。 - **崩溃/中止探测器**:调用被外层掐掉时(`AbortError`)工具交不出任何东西,故落「进行中」标记, **下一次调用开头点明「上次没有正常收尾、那次等待是纯损失」**。 ### 六、文档与仓库 - 新增 `docs/0.7.8plan.md`:四个既定突破点 + 更本质的潜在突破 + 单轮表现 + 实施优先级 + 交互框架附录。 - `.gitignore` 补 `po06/runtime/tmp/`(运行期临时目录,此前会被 `files: [runtime]` 带进包)。 **回归**:57 套测试全绿。 ## v0.7.6 — 2026/09/26(**主线 · 正式版 · 长输入与 bash 让位**) 作者:啃轮胎的西狐 两处用户反馈:**几万字提示词必然失败**、**关掉内置 Bash 后系统自带的 bash 也回不来**。 ### 一、修「几万字提示词必然失败」 - **现象**:提示词几万字时,面板报「失败:连不上宿主服务(它可能刚重启)」。 - **根因**(两处叠加):① control-api.js 的 MAX_BODY_BYTES 只有 64KB,而它的注释理由是「设置/指令都很小」—— **这个前提不成立**:readBody 也服务解释端点,而那个 body 里装的是**用户原文**。 中文一字 3 字节 ⇒ 64KB ÷ 3 ≈ **21800 字**即撞墙(实测 39123 字 ≈ 117KB)。 ② 超限分支执行 req.destroy(),**直接销毁 TCP 连接**而不是回 HTTP 错误, 浏览器看到的是「连接断开」,client 归类 unreachable ⇒ **真因被彻底盖掉**。 - **修法**:① 上限 64KB → **2MB**(约 66 万汉字,仍能挡误发的二进制); ② 超限**不再砍连接**,改为如实返回 body-too-large + 实际字节数,由既有调用方回 400,界面可显示真因。 - **顺带**修正同链路另一处旧尺度:session-context.js 的 CTX_MAX_TEXT_CHARS 4000 → 6000、 CTX_BUDGET_TURNS 12000 → 24000(单段不能等于总预算,否则一段吃光预算挤掉其它上下文)。 该常量只作用于「存进会话历史供后续轮次当上下文」的那份文本;**本轮解释走 userText,逐字不截断**。 ### 二、修「非 Windows 平台:关掉内置 Bash 后什么都没有」 - **现象**:系统自带 bash 的用户(觉得原来那个更好)关掉内置 Bash 后,DSH 里彻底没有 bash。 - **根因**:宿主的 @deepseek-ai/dsh-tool-bash 注册的工具名**也是 bash**,而它在 @deepseek-ai/dsh-base/cordis.patch.yml:266 写着 disabled: !!js process.platform === win32 —— **官方只在 Windows 禁用它**,非 win32 平台宿主本来就提供 bash。 而 po06 此前无差别注册同名工具 ⇒ 在 Linux/macOS 上把宿主那份顶掉; 宿主只在装配时注册一次、**被顶掉后不会重试** ⇒ 用户一关内置,表里就再没有 bash。 - **修法**:**让位判据取平台这一静态事实**——hostProvidesBash = process.platform !== win32, 成立则 po06 不注册。于是:非 win32 → 让位(关掉开关即回到宿主那个 bash); win32(宿主被官方禁用)→ 补位(行为不变)。 - **为什么不用「查表里有没有 bash」**:表里只看得到名字、分不清是谁注册的; po06 自己刚注册完再查会把自己认成宿主,判据失明。平台不依赖装配时序。 - 新增 po06/test/bash-yield.test.mjs 钉住让位判据,防止日后改回无差别注册。 ### 三、仓库结构:文档归入 docs/ - 仓库根由 27 项降为 10 项:只留对外门面(README ×2 / LICENSE / CHANGELOG)与必需文件 (package.json / .gitignore / .gitattributes),其余 18 项移入 docs/ 并按用途分组, 新增 docs/README.md 索引。 - 同步修正引用,并**顺带修掉一处早已存在的死链**:README 指向 README-0.5.md, 而该文件上一轮已随 0.5 源码移入 old/0.5/。 - docs/RELEASING.md 补入「发布前核对所有相对链接」一条(步骤 3 的核对 + 清单第 3b 项)—— 这条正是本次整理踩出来的。 **回归**:50 套测试全绿。 ## v0.7.5 — 2026/09/26(**主线 · 正式版 · 档位与仓库结构**) 作者:啃轮胎的西狐 这一版来自两类反馈:**思考档位不生效**(用户实测)与**仓库结构混乱**(外部用户:npm 上是 0.5、Release 是 0.7、而 0.7 在子目录)。 ### 一、思考档位:按模型各配,并真正传给调用 - **根因**:po06 调 llm.stream 时只传 provider/model/temperature/messages,**从不传 reasoningEffort** (宿主契约 types.d.ts:494 有该字段,:355 写明不传则走 provider 默认)。于是每次都按默认档跑, 而默认档下**由模型自己决定要不要思考** ⇒ 用户看到「有时有思考、有时没有」。 插件里其实早有 reasoningEffort 设置项,但它只出现在 migration.js 的迁移清单里,**从未接线**。 - **修法**:新增 effortByModel({ provider/model: effortId },**按模型各配**——不同模型档位划分不同, 且优化模型与会话模型未必是同一个);resolveInterpreterCfg 在**定完路由之后**按该模型查表; 两处 llm.stream(默认路径、工具回落)与工具循环都带上 reasoningEffort。 - **档位来源与官方同源**:读宿主 resolveModelInfo 的 reasoning.efforts,写同一个 reasoningEffort 字段, 不存在第二套档位名。注意宿主 listModels 是白名单返回、**会剥掉 reasoning**,所以档位另走 resolveModelInfo。 - **界面**:优化选项里新增「思考档位」下拉,**两种模式都能配**——选了具体模型就按它查, 「跟随会话模型」就先问 /session-model 再按会话模型查(档位写在真正会被调用的那个模型名下)。 - **实测(对照实验,同模型同输入只差档位)**:off → 思考 0 字 / 7 秒;max → 思考 40589 字 / 63 秒。 ### 二、修「档位选完立刻被覆盖」 - **根因**:键格式三处不一致——前端用 JSON.stringify([provider, model])、后端校验要求键含 /(not-a-route)、 wire.js 查表用 provider/model。于是每次保存都被判非法、丢弃并回默认。 - **修法**:前端改为 provider/model,与后端校验及查表口径统一。 ### 三、修「拦截 UI 不再统计 token」 - **根因**:用量只在解释**完成那一刻**写进进度面,而 client 的阶段一离开 optimizing 就 setProg(null) 并停止轮询 ⇒ 最后那次写入永远拉不到(那行代码与其上方注释的意图**正好相反**)。 - **修法**:轮询放宽到 optimizing 与 review;收尾时把最后一份用量钉在结果上;显示改为「结果优先、进度面兜底」; /interpret 响应也带上 usage。 ### 四、修「调 skill 时漏拦截 + 旧包迟到、新包随后才到」 - **根因**(两处叠加,台账为证):① 去重判据只认**文本逐字相等**,而前置拦截记的是客户端原文、 订阅侧取的是宿主事件文本,**调 skill 时两者形态不一致** ⇒ 去重失配 ⇒ 同一句话被解释两遍; ② 第二遍是 defer 出去的**并发**执行,两遍基于同一旧状态各写一次,**后完成的覆盖先完成的** (台账实测 12:35:39 rev=309 → 12:35:40 rev=307,revision 倒退)。 - **修法**:判据增加**时间窗**维度——刚放行后 15 秒内无论文本是否变形都认定为同一条, 两种跳过在台账里分开记(intercepted-already / intercepted-recently),使「这轮为什么没解释」始终可查。 ### 五、仓库结构整理(回应外部用户反馈) - **仓库根 = 最新版**:0.1~0.6 的历史产物全部移入 old/(38 个 tgz 按主次版本分组 + 0.5 的源码), 根目录不再有任何 .tgz 与旧源码;old/README.md 给出各代简介与三种下载方式。 - **根 package.json 是薄壳**:逐字段从 po06/package.json 派生,main 指向 po06/lib/index.js。 此前它曾是 0.5.x 的完整插件包,而安装入口读的正是仓库根 ⇒ 外部用户按仓库地址装到的是 0.5。 - **新增 RELEASING.md**:仓库结构四条不变量 + 9 步发布流程(每步带核对方法)+ 可照抄的检查清单 + 故障排查表。 - **README 写明安装来源**:唯一正确来源是 Release 附件;npm 上的 @dsh-external/dsh-prompt-optimizer 是 0.5 老包,不要装。 ### 六、其它 - 台账新增 effort / effortRoute:记录每次调用**实际带出去**的档位与作用模型,便于自查(需重启后生效)。 - 回归:49 套测试全绿。 ## v0.7.4 — 2026/09/25(**主线 · 正式版 · 位置无关修复**) 作者:啃轮胎的西狐 修掉一个**只有别人会踩到**的缺陷(外部用户反馈:装上后 bash 跑不起来)。 - **根因**:lib/bash/pg-jobport.mjs 顶部写死了**打包者本机**的绝对路径—— file:///C:/Users/<打包者>/AppData/Roaming/npm/.../dsh-win32-process/lib/index.js ——而且是**顶层 await import**。别人机器上没有这个路径 ⇒ 该 import 抛错 ⇒ 本模块加载失败 ⇒ index.js 的 load('pg-jobport.mjs') 落到 catch ⇒ **每次调用都回「插件运行时模块加载失败」**。 工具在工具表里、却完全跑不动。作者本机因为路径恰好存在,一直测不出来。 - **修法**:① 去掉硬编码,改为**多种候选位置运行时解析**(裸包名 → DSH_CHECKOUT → %APPDATA%/npm → 从宿主入口脚本 argv 推导 → node 同级的全局 node_modules);② **全失败也不抛**, 降级到 spawn + taskkill /T /F 的等价实现(接口与 win32 作业对象版一致); ③ 新增 DSH_BASH_FORCE_FALLBACK=1 强制降级开关,便于自测与排障。 - **实测两条路径**(同一台机器):win32-job 与 fallback-taskkill 均 exitCode=0、输出正确、超时终止有效。 - 顺带清掉产物里的其它本机痕迹:runtime/manifest.json 的 source(D:/other/Git → bundled), 以及调试时遗留在 runtime/tmp/ 的 3 个 json。 ## v0.7.3 — 2026/09/25(**主线 · 正式版 · 开关修复**) 作者:啃轮胎的西狐 修掉 0.7.2 里两个**用户看得见**的缺陷(均由真机复测指出): - **开关关不掉**(严重):设置与 /status 都显示 false,工具表里却还有 bash,而且照样能跑。 · 根因不是某行写错,而是**判据本身**错了:它问的是「模块实例记不记得自己注册过」 (typeof dispose === function,而外层 effect 的返回值靠不住),而不是「工具表里到底有没有」。 · 修法:① 用**布尔标志**记状态,不依赖返回值类型;② 判「有没有」以**工具表实测**优先; ③ 注销之后**再实测一次**确认;④ 关键——**真正的注销器是 bash 内部那个 effect 的 dispose**, 外层包一层拿不到它,改为**拦截 effect、收集内层注销器**。 · 实测往返:true → 表 75 / 含 bash;false → 表 74 / 无 bash,可反复切换。 - **卡片外观与原插件不一致**:内置后 bash 调用卡片回落成宿主的通用工具样式。 · 根因:一个插件的 client 入口**只有一个**,原卡片的注册写在 bash 自己的 client 里, 并入本包后**没有任何地方加载它** ⇒ 那次注册从未执行。 · 修法:把原组件**原样复用**进本插件 client 入口(同一份代码,不另做一套),注册同一个 key:bash; 并补上原插件有、本包缺的 dsh.client.external = [dsh-client-ui-primitives](取宿主终端原语)。 - 新增回归测试 test/bash-toggle.test.mjs(4 项):专守「关掉之后工具**真的**从表里消失」, 以及开→关→开→关 的往返与幂等。 ## v0.7.2 — 2026/09/25(**主线 · 正式版 · 内置 Bash**) 作者:啃轮胎的西狐 - **内置 Bash**:原独立插件 dsh-bash-runtime 的实现与运行时并入本包(lib/bash/ 与 runtime/)—— 装上这一个插件就有 bash,无需再装第二个插件。 · 注册改为**裸 tools.register + 对象根 JSON Schema**:原来依赖宿主的 defineTool / schemastery, 而这两个包在 tgz 装配环境里解析不到 ⇒ 模块 import 整体失败 ⇒ **bash 工具静默消失**。 · **详情面板新增开关**:关掉=**不注册该工具**(模型看不到),不是注册了再拒绝执行; 开关走 onSettingsWritten 钩子按差额同步,**改完即生效**,不需要重启或重载插件。 - 上一版(0.7.1-beta.1)的策略改动全部保留:三档拉开、控制面信息移出上下文、质量解释=结果方向、 可逆实现默认、思维层可读进度。 - **验证**:48 套 / 645 项全绿;check-docs --strict 全绿;卸载独立 bash 插件后内置工具仍可用。 ## v0.7.1-beta.1 — 2026/09/25(**主线 · 预发布 · 策略与呈现修复**) 作者:啃轮胎的西狐 - **三档真正拉开**(`lib/settings.js`):补充程度(700 / 1200 / 2000 字)与自主预算(1 / 2 / 3 个问题) 两个维度逐级递进。此前 `minimal` **从未被任何档位使用**、且 standard 与 heavy 的 detail 相同 ⇒「重度」实际只等于「标准 + 多问 1 个」(用户 2026-09-24 实测反馈后查证属实)。 - **内部控制面信息移出工作上下文**(`lib/compiler.js`):注入头部原先带「任务 `default` · 意图修订 N」, 会被工作模型当成任务语义处理(伪语义与锚定);现已移除,元数据仍留在宿主 state 与 wire 台账里。 - **质量解释改为「结果方向」**(`lib/interpreter.js` 规则 2):不把零件、参数、材质、后期效果逐项列成清单; 一个示例就够,示例不是验收项,同一方向不拆成多条。 - **可逆实现默认**(`lib/interpreter.js` 规则 3):可逆细节写 `implementation_option` 并说明「默认取什么、为什么可逆」; **不可逆的产品方向**(联网与否、交付形式、功能范围、审美取舍)仍只能写 `unknown`。 - **思维层不再显示裸 JSON**(`lib/client.js`):无 reasoning 时把结构化补丁解析成可读产出条目 (中间一版只报「已产出 N 字」=留白,用户反馈「直接没有思考过程了」,同样不可接受)。 - **验证**:48 套 / 645 项全绿;`check-docs --strict` 四条门禁 ✅。 - **未验证(如实登记)**:本版的档位差异是**可测的配置差异**,**不等于效果已被证明**—— 此前的留出评估只跑完 S1(两臂没测出差),等级仍是「实验构建」。 ## v0.6.10 — 2026/09/24(**主线 · 正式版 · 兼容性修复**) 作者:啃轮胎的西狐 - **修掉 0.1.7 的第二处契约破坏:工具结果的消息形状**。上一版(0.6.9)修的是投递消息的 `source.kind`; 发完之后按台账复核,发现**开了「只读工具」的每一轮都断在工具循环第 2 轮**。 证据:`~/.dsh/po06-wire.jsonl` 按部署时点切分——`signal is not defined` 的最后一条在 09-24T00:59Z(部署前), 部署后 4 行 `rounds = 1..2`、`calls = 2`(**修复生效、循环真的跑起来了**),但**全部**带 `llm-error: DeepSeek Messages cannot represent user/tool-result content`(`code: UNSUPPORTED_CONTENT`)。 根因:0.1.7 起工具结果是**一等 `role:'tool'` 消息** (`createToolResultMessage({callId, content, isError})`,内容块**直接**是 content、id 由工厂生成), 而循环仍在造 `role:'user'` + `tool-result` 块并手搓字符串 id。**这条路径此前零测试。** - **形状只在一处决定**:`lib/llm-lib.js` 新增 `toolResultShape(mod)` —— 有 `createToolResultMessage` ⇒ `tool-role`;只有 `createUserMessage` ⇒ `legacy-user-block`;**都没有 ⇒ 不猜**(不造消息、循环自然收敛、 由调用方回落)。`lib/read-tools.js` 的结果消息与"助手请求工具"消息都改走它。 - **顺手修掉一个一直存在的接线缺陷**:`loadLlmLib` 的 `env` 默认空表,而生产调用点从没传过 ⇒ `DSH_PO06_LLM_LIB` 这类显式覆盖**永远读不到**。现在两处调用点都显式传 `{env: process.env, argv1: process.argv[1], cwd: process.cwd()}`。 - **验证**:全套 **46 个测试文件 / 620 项全绿**;变异检验 **221 个 / 40 个源文件 / 漏捕 0**; `check-release` 全绿。新增守卫(`test/read-tools.test.mjs` 8 → 10):工具结果必须是 `role:'tool'` 一等消息、**不得再出现 `tool-result` 块类型**、旧形状退回、形状未知时不造消息; 配套夹具 `test/fixtures/llm-lib-017.mjs`(按 0.1.7 导出对齐的假宿主模块)。 - **未验(如实登记)**:**真机复验**——判据是一次真实拦截后台账里 `toolLoopError` 消失且能拿到包, 这一步只能由人在真实对话里触发;观感类结论需真人看;**专业跑分 / 留出评估仍未完成**(只跑完 S1), B 臂(冻结的 0.4.4 对照)**成本基线仍缺失**。 ## v0.6.9 — 2026/09/24(**主线 · 正式版 · 兼容性与缺陷修复**) > ⚠️ **本版发布当天即被 `0.6.10` 取代**(同日按台账复核抓出 0.1.7 的**第二处**契约变化:工具结果的消息形状)。 > 装最新版请用 `0.6.10`;本条保留作为当时的事实记录。 作者:啃轮胎的西狐 - **适配宿主 `dsh 0.1.7-rc.1` 的会话格式 v4**(**ADR-0087**)。宿主把会话日志升到 v4,而 v4 的**准入校验会明确 拒收**我们过去投递通知用的旧来源名——这不是风格过时,是**写入会话日志那一步会抛错**。 依据读的是宿主源码:`dsh-session-format-v3-to-v4` 里 `if (… || value["kind"] === "plugin") throw new SessionFormatError("format v4 message requires a producer-owned source kind")`。 现在投递来源固定为 **`kind: 'plugin:@dsh-external/dsh-po06'`**(宿主迁移表 `producerKind()` 给第三方插件的规范名), 并去掉 `plugin` 字段。**对两代宿主都成立**:0.1.6 的 v3 对用户消息 kind 不设白名单;"绝不自我触发"那道闸 本来就是正向白名单(只认 `kind === 'user'`),换名字不会漏;0.1.6 界面也从未特判 `kind === 'plugin'`。 - **台账仪器兼容两代形态**:`scripts/dump-wire.mjs` 新增 `producerOf()`——旧形态取 `plugin` 字段、 `plugin:<包名>` 归一到裸包名、真人消息不算插件贡献。**只认一代就等于换宿主后旧台账全读不出来** (仪器报错方向最危险,ADR-0034)。 - **只读工具(「只读工具:开」)链路补齐**,并配 `test/read-tools.test.mjs`(8 项)。 - **验证**:全套 **46 个测试文件 / 618 项全绿**;变异检验 **221 个 / 40 个源文件 / 漏捕 0**(源文件字节还原); `check-release` 全绿(含打包自足性与文档漂移门禁)。新增守卫:投递来源不得再用被 v4 拒收的 `plugin`(静态守卫, 注释里允许也必须讨论"为什么不能这么写")、线缆仪器两代形态单测(旧形态 / 新形态 / 混代台账 / 真人消息排除)。 - **发版过程中抓到并修掉的两处**(都会骗人,所以记下来):① **测试夹具跟不上产物形状**—— `check-install` 的假包 `package.json` 只有 `name`/`version`,而宿主 0.1.7 **在装配前会检查 `dsh.bundle`**, 于是夹具里的包被整块跳过、装配树为空,三条"应放行"用例全红;夹具改成**从仓库那份派生**(只覆盖 `version`) 并补上包根的两份手册。② **一个变异体长期存活**——删掉"缺 `cordis.patch.yml` 就拦"后,用例的三条断言 照样全绿(宿主自己也拦了,装配树本来就是空的);现在断言直接咬住脚本自己的判定出口(`--json` 的 `problems` 必须点名 bundle 层),**不写死正文措辞**。修完 5 个 `checkinstall` 变异全部被抓住。 - **未验(如实登记)**:0.1.7 上的**真实投递**只到"按宿主源码与迁移表改对形状 + 有守卫", 端到端(真模型、真会话)**仍需一次实跑**才作数;观感类结论需真人看;**专业跑分 / 留出评估仍未完成** (只跑完 S1),B 臂(冻结的 0.4.4 对照)**成本基线仍缺失**。 ## v0.6.8-stable — 2026/09/22(**主线 · 正式版**) 作者:啃轮胎的西狐 - **修掉"思考完却拿不到包"(no-packet)**。台账取证:28 条 `noop` 里 **26 条**的原话只有两个字, 同一句话反复重试**每次都空**(有会话连续 16 次)——这不是抖动,是"模型交了空产出,宿主照收"。 现在:① 空产出(空 `ops` / 没吐 JSON)**有界重试一次**(把"你上一轮交了空产出"明确告诉解释层); ② 仍空 ⇒ 宿主补一条**关于这轮原话本身**的待确认条目(`unknown`,不发明要求、不拦下游)⇒ **这一轮必有包**; ③ 条目超单轮上限:**截断记账**(原来整轮作废);④ 销账指向不存在的条目:**逐条丢弃**; ⑤ 用户点「跳过/取消」**不再被记成解析失败**(abort 判定提到解析之前,单列 `empty-completion` 与 `aborted`)。 - **浅色模式**:界面颜色改为**由主题驱动**(一份 token 表、两套取值)。两个真因都修了: ① 主题信号从 `documentElement` 读,而宿主的 token 写在 **`body`** 上 ⇒ 读空 ⇒ 被判成深色 (所以"浅色模式看着跟深色没区别");② token 选择器只覆盖"标记在自身",插件里思维层/折叠体**各自** 带 `data-po06` ⇒ 各自重新声明浅色 ⇒ **深面板里嵌一块浅底**。现在:`body[data-ds-dark-theme]` → 根 `color-scheme` → 文字亮度三级判定(都读不到按浅色),深色规则同时覆盖"自身/祖先/宿主属性"三条路径。 - **语言跟随 DSH**(`zh`/`en`,含 `?` 手册;改设置即时切换、不用刷新)——本版把界面文案全部收口到中英对照, 并给英文适配补了静态+运行时守卫。 - **启用判定修对**(`gate:rollout-off` 调查结论):`rollout` **缺失或写错**时不再把显式 `enabled:true` 的插件**静默关掉**(只有**显式** `{mode:"off"}` 才是不启用);顺带修了 `normalizeRollout` 不幂等 (第二次归一化会把"回落来的 off"洗成"用户显式 off")。`/status` 增加 `gate` **结论分布**, 把"配置意图"与"闸门实际放行"分开显示。 - **修掉一次"配置被重置"的数据丢失**(真机发现:`/status` 显示的设置与文件里写的对不上;随后配置被一次设置写入**重置成默认值**, `settingsVersion`/`enabled`/`rollout` 三个"启用意图"字段被**静默抹掉** ⇒ 插件不再被认作 0.6 自己的配置 ⇒ **明明开着却什么都不做**,也就是用户报的 `gate:rollout-off`)。根因是 **BOM**:Windows 上 PowerShell / 记事本写出的 UTF-8 带 BOM,而设置读路径没剥 BOM(EV-0132 只给 `parseEnableIntent` 补过)⇒ `JSON.parse` 抛 ⇒ 配置被当成"空的" ⇒ `writeSettings` 拿空对象合并后写回一份**只有设置项**的文件。 现在:① 配置读取一律先剥 BOM(`parseJsonText`,设置读路径与 `/status` 共用); ② 万一真的读不出来,先从**最近一份可解析的备份**里把启用意图字段捞回来,并**如实上报** `gateRepaired` / `recoveredGateFrom`; ③ 无论如何都保证 `settingsVersion` 标记在(它只是"这份配置是 0.6 写的",不含任何启用决定)。 守卫:带 BOM 的配置照常读(不许当空配置重写、不许丢字段);坏配置写入后启用意图字段必须从备份恢复。 - **验证**:全套 **46 个测试文件 / 618 项全绿**;新增守卫包括 WCAG 对比度(浅/深两套都算)、 主题信号三级判定、"空产出必有包"、"关档不注入"、"客户端读过的服务必须声明 inject"、BOM 容错与配置字段保全。 - **未验(如实登记)**:观感类结论需真人看;**专业跑分 / 留出评估未完成**(只跑完 S1)——作者的日常实测观察 (DeepSeek-V4.1-Flash + PTC + PowerShell:one-shot 与长任务迭代效果明显强于同环境同提示词,少量项目统计疑似降低 token 消耗)见根 README 的「诚实声明」。 ## v0.6.8-beta.2 — 2026/09/22(已被 `v0.6.8-stable` 取代 · 英文适配 + 对外文本对齐版) 作者:啃轮胎的西狐 - **英文 UI 适配**:界面语言**只跟 DSH 的语言设置**(`设置 → 通用 → 语言`,`zh`/`en`),插件内**不设**语言 开关;客户端文案全部走 `L(中文, English)`(49 条),`?` 用户手册按语言取宿主 `GET /help?lang=zh|en`, 新增 `po06/HELP-0.6.en.md`(带同一 `po06:help-start` 区间标记)并进 `files` 白名单。英文界面不再夹中文。 - **语言探测按真机契约重写(发出后 30 分钟内发现并原地重发)**:`ctx.locale` 是 DSH 的 **LocaleFace 实例** (`dsh-client-locale/lib/client.js` 里 `ctx.provide("locale", locale)`),语言在 `getSnapshot().active`; 第一版按 `v.locale/v.name/v.id/v.language` 猜属性 ⇒ 真机上**永远读不到** ⇒ 恒中文(英文适配等于没做)。 现在:读 `getSnapshot().active`(兼容 `getLocale()/snapshot.active/字符串` 三种形态,拿不到才回中文), 并 `subscribe()` 订阅语言变化 ⇒ **在 DSH 里切语言,插件界面即时跟着换,不用刷新页面**。 > 首发字节(tag 指向 `6f9b972`)已被本次重发取代,tag 与 Release 都指向含本修复的提交;首发字节不再对外。 - **修一次真机白屏崩溃(用户报告:"dsh 突然崩溃"、界面停在 `Failed to load plugins`)**:客户端 `apply()` 读 `ctx.locale`(语言适配)却只声明了 `exports.inject = ['slots']` —— **cordis 对未 inject 的服务 getter 是抛错** (`cannot get property "locale" without inject`),于是客户端 entry 进 `FAILED`、引导层整页白屏。 两条一起修:① `exports.inject = ['slots', 'locale']`(写**服务名**,与宿主客户端插件同一写法); ② 读服务一律走包住的 `readSvc()`,`detectLocale` 也套 try/catch —— 万一某个 profile 没有 locale 服务, 最坏是**用中文兜底**,绝不再整页崩。 > 回归守卫(防同类再犯):① 静态——**代码里读过的每个 `ctx.<服务>` 都必须在 `exports.inject` 里声明**; > ② 运行时——用**照 cordis 语义的 ctx**(未声明的服务读就抛)驱动 `apply()`:没有 locale 服务时要照样注册满 > 3 个插槽、语言回落中文;有 locale 服务时按它定语言。这一版是**同一版本号的第二次原地重发**(首发:缺语言 > 契约修复;次发:缺本次崩溃修复)。 - **README 对外文本与版本对齐**:更正 0.5 线的版本号(**最后发布 `v0.5.0-beta.1`**;仓库内 0.5 源码版本号 `0.5.2-beta.1`,未曾单独发 Release);0.5 的安装不再指向 `releases/latest`(那一页现在是 0.6 线、资产名 不同 ⇒ 404),改为钉 `v0.5.0-beta.1` 直链;英文 README 结构对齐中文(0.6 在前,0.5 设计说明移入附录并 标明边界);两处 README 的 0.6 之前更新日志条目移除,统一指向本文件。 - **测试门禁**:`po06/test/wire.test.mjs` 的两条历史断言按现状改写(覆盖提示词从"全等"改成"以覆盖文件开头 + 追加会话上下文";自检判空的静态定位改成锚在自检独有的分支上,不再被同名的变量声明带偏)⇒ **全套 45 个测试 文件全绿(585 条断言)**,`check-release` 的阻断项从 4 条降到 1 条(只剩变异检验输出解析)。 - **未验**:观感类结论需真人看;真机 + 真模型端到端与效果对比未跑;**本版没有任何"效果更好"的证据**。 ## v0.6.8-beta.1 — 2026/09/22(已被 `v0.6.8-beta.2` 取代 · 对外文本对齐版) 作者:啃轮胎的西狐 - **代码与 `v0.6.7` 等价**(没有新增行为改动);本版按用户要求改用 beta 号发布, 并把**对外可见的文本**(Release 说明、README 中/英、本 CHANGELOG、仓库描述)与这一版对齐。 - **README 的安装方法已按本版真跑一遍**(隔离 home):从 Release 直链下载 ⇒ sha256 与 `SHA256SUMS` 一致 ⇒ 建干净 profile ⇒ `dsh plugin add`(`dependencies` 与 `dsh.profile.bundles` 都写入)⇒ `check-install --expect-version 0.6.8-beta.1` ⇒ **33/33 lib 与仓库逐字节相同 · 装配树含该层 · ✅ 可以开始试了**。 - **未验**:观感类结论需真人看;真机 + 真模型端到端与效果对比未跑;`check-release` 仍因 `wire.test.mjs` 2 条过时断言而阻断;**本版没有任何"效果更好"的证据**。 ## v0.6.3 ~ v0.6.7 — 2026/09/22(**补记**:这几版当时只登记在 `po06/RELEASE-CHECKLIST.md`,没写进本文件) - **v0.6.3** 拦截弹窗拖拽回归修复:入场动画的 `transform` 填充盖住了拖拽写的**内联 transform**(关键帧改成只碰 opacity)。 - **v0.6.4** 位置夹紧不再把面板钉死(面板高于视口时旧式夹紧恒等于 8);引文判据从"整轮作废"改成"只丢那一条并记账"。 - **v0.6.5** 控件栏收成「优化选项」按钮 · **撞 id 改名不再判死整轮**(no-packet 真因:解释层每轮从 `req-1` 起编号, 而旧条目只退场不删除)· **跳过/取消之后真的停**(连接断开 ⇒ AbortSignal ⇒ 提交前闸门 + 模型调用随信号中止)。 - **v0.6.6** 「优化选项」弹层可见(`position: fixed` 却没给坐标 ⇒ 落在看不见的地方)。 - **v0.6.7** 面板控件**铺满整格**且点击范围与视觉重合 · 模型下拉不再白底白字(跟随主题 `color-scheme`)· **DSH 主题副色**克制用在选中/悬停/键盘焦点三处。 ## v0.6.2 — 2026/09/22(**主线**) 作者:啃轮胎的西狐 - **拦截弹窗:功能性区域不再被裁** —— 正文区从 `overflow:hidden` 改成 **`overflow:auto`**,内容装不下时 由**这一处全局滚动**(就是 0.5.x 的那根滑块;细、低调、悬停才明显)。面板本身 `maxHeight: min(78vh,660px)` 并随窗口重新夹紧(自适应);思维层仍是它自己那个固定窗口(内部滚动条隐藏)⇒ 不会回到"两根可见滑块"。 - **交互反馈与极简动效**(注入一小段样式表,卸载即摘):所有插件按钮 130ms 过渡 + 悬停/按下/键盘焦点/禁用态; 浮层入场 140ms 上浮淡入 · 运行中状态灯呼吸 · 思维层新内容 180ms 淡入;`prefers-reduced-motion` 下一律关闭。 - **观感**:圆角 12→14px、阴影更收敛;配色继续沿用 DSH 自己的变量(`--dsw-*`),浅色/深色主题与 DSH 一致。 - **未验**:无截图证据(我无法对 GUI 截图),观感与动效幅度**需真人在真窗口里看一眼**; 全量 45 套 · 44 通过(唯一未过是 `wire.test.mjs` 里 2 条早已过时的断言)。 ## v0.6.1 — 2026/09/22(**主线**:0.6 线,包名 `@dsh-external/dsh-po06`) 作者:啃轮胎的西狐 - **这是主线**:默认分支 `main` 与最新 Release 都是它;0.5 线(`v0.5.x`)保留在下方历史与 tag 里,仍可用但不再更新。 - **每轮独立产生目标,不遗传**:每轮开始把上一轮的条目与待问问题整体退场(`stale`,留档不删除), 本轮的包只由「你这轮的原话 + 本轮读入的会话上下文」重新得出 ⇒ 不会再出现"上一轮早已解决的问题又被要求一次"。 **代价**:长期约束("只交单个文件""别动别的文件夹")也要靠上下文每轮重新看出,别把「上下文」调得太小。 - **界面对齐 0.5**:档位 `关闭/轻度/标准/重度` · 两行控件栏 · `?` 用户手册 · 拦截浮层分**思维层 / 产出层** · 思维层**固定显示范围、无滚动条、正文不截断**(可往回滚,自动跟到最新)。 - **token 计数**:只用 provider **真实上报**的 `入 / 出 / 缓存` 三分量(过千记 `k`/`M`,拿不到就显示 `—`,从不估算)。 - **只读工具那条必现故障的真因(三条)**:解释层标识符笔误 `TOOL_SYSTEM_NOTE is not defined`; 一条写坏的来源引用能弄死整轮(`kind:'tool'/'file'` 的 `toolCallId`/`uri` 只有宿主才有 ⇒ 现在只补宿主能机械核对的事实、其余逐条丢弃并记账); `provenance:'machine'` **从未生效**的顺序缺陷。 - **移除**「条目与结案」面板与其宿主通路(目标每轮自动产生,不再需要人工勾选)。 - **文档**:根 README(中/英)改为以 0.6 为主线并写明 30 秒安装;`po06/README.md` 给出照抄即可的下载+安装+自检; `?` 帮助写明"不遗传"及其代价。 - **未验**:全量 45 套 · 44 通过(唯一未过是 `wire.test.mjs` 里 2 条早已过时的断言);真机 + 真模型端到端与效果对比未跑。 **本版没有任何"效果更好"的证据。** ## v0.5.2-beta.1 — 2026/09/19 作者:啃轮胎的西狐 **交付门(机器替员工验):任何被 present 的网页类交付物,落盘后由宿主侧真机打开一次,写成机器裁决——不再采信模型的"Everything is verified."** 权威定义见 [SPEC.md](SPEC.md) §0⁵。 **病根(会话日志可复核 · `session-7df19a05`)**:工作会话在 **workspace-write** 档下交付前两次尝试 `msedge --headless --screenshot`,两次都是 `SHOT_MISSING` + `Program 'msedge.exe' failed to run: Access is denied`——**它从没见过自己的产物**;随后退回静态检查(标签平衡 / 19 个 script 块 / 0 处外链)并写下 **"Everything is verified."**。而那两个文件里有: 1. **三层着色器拼装 bug**(`mbt-m1a2-sep-v3.html`):① `