# 验证记录(2026-10-17 / 2026-10-18) ## DSH 版本审计与跨版本适配 - 当前桌面端:`0.2.1-rc.2`(`runtime.json` / app.asar;用户已升级)。 - npm `latest`:`0.2.0-rc.2`;`next`:`0.2.1-rc.2`;`alpha`:`0.2.1-alpha.5`。 - 2026-10-18 在 `0.2.1-rc.2` 完成 live 冒烟: - 只含 `pending` 的 `todo_write` 成功,并收到即时 notice; - 设为 `in_progress` 后连续 5 次顶层 `run_code` 调用,收到停滞 notice; - 两轮均无 `format v4` 错误,无需改代码。 - 对 `0.2.1-rc.2` 的 `dsh-session` / `dsh-tools` / `dsh-agent` / `dsh-agent-loop` / `dsh-tool-todo` / `dsh-session-format` 做了包类型审计: - `SESSION_FORMAT_VERSION` 仍为 **4**; - `tools/post-execute` + `additionalContexts`、`agent/pre-step`、`session/event` 均存在; - `todo_write` 仍是整表替换与 `pending/in_progress/completed`; - 因此 0.2.0-rc.2 与 0.2.1-rc.2 共用同一套 hook 和 v4 source kind。 - 跨版本 source kind:新增 `sourceKind: auto`,按 `session.header.version` 自动选择: - `< 4` → `{ kind: 'plugin', plugin: 'task-guard', form: 'notice', summary }` - `>= 4` → `{ kind: 'plugin:task-guard', form: 'notice', summary }` - 测试从 15 增至 **18**,新增 v3/v4 source 选择、强制 `sourceKind`、真实 Cordis v3 waterfall。 - 版本审计详情见 [docs/compatibility.md](./docs/compatibility.md)。 ## 第一次失败:默认硬拦截 第一次安装的版本默认开启了 `requireActive: true`:只要 `todo_write` 的清单里还有 `pending` 而没有 `in_progress`,`tools/pre-execute` 就直接返回 `deny`。 DSH 会把 `deny.reason` 变成工具错误。会话日志里对应的事件是: ```text Error: todo_write 未执行:清单里还有 1 个待办,但没有任何 in_progress 任务。只要还有工作,就必须保持恰好一个任务为 in_progress。请重新提交完整清单:把已完成的阶段标为 completed,并把下一阶段标为 in_progress。 ``` 这会把一次本来合法的计划写入变成错误,模型需要额外一轮修正;在真实任务里看起来就是“装上之后直接运行失败”。 另外,改成 `rejectMissingActive` 之后,bundle 的 `cordis.patch.yml` 仍残留旧的 `requireActive` 字段,加载时会报 “unknown config field”。现在已修复,并加了 patch 配置测试防止再次漂移。 ## 第二次失败:session format v4 的 source kind 第二次安装后,`todo_write` 本身成功,但插件追加 notice 时整轮报错: ```text 本轮运行失败 format v4 message requires a producer-owned source kind ``` 原因:DSH 0.1.7-rc.1 起使用 session format v4,**退役了** 旧的: ```js { kind: 'plugin', plugin: 'task-guard' } ``` 每个消息必须使用 producer-owned kind,即: ```js { kind: 'plugin:task-guard', form: 'notice', summary: '...' } ``` 不能再带 `plugin` 字段。已按官方 v4 迁移规则修复;同类修复可参考 [GanyuanRan/Aegis@29cfbe8](https://github.com/GanyuanRan/Aegis/commit/29cfbe826c6823864ffa345f525acfcdff2d7b2c)。 ## 现在的默认行为 - `rejectMissingActive: false`:`todo_write` 永远以成功结果返回,只在“还有 pending、没有 in_progress”时追加一条插件 notice。 - `blockAfterCalls: 0`:默认不硬拦截任何工具。 - 只有显式配置 `rejectMissingActive: true` 或 `blockAfterCalls: N` 才会产生工具错误。 ## 已验证 ```powershell cd pnpm check ``` 结果:`typecheck` 通过,`build` 通过,18 个测试全部通过。测试覆盖: - 默认模式:`todo_write` 成功 + 追加 notice,不产生错误; - 严格模式:显式 `rejectMissingActive: true` 时才 deny; - 停滞阈值、重复间隔、同一 step 去重、`turn/start` 重置、可选硬拦截; - 在真实 `@deepseek-ai/cordis` `Context` 里加载插件并驱动 `tools/pre-execute`、`tools/post-execute`、`agent/pre-step`、`session/event`; - v4 notice source 是 `{ kind: 'plugin:task-guard', form: 'notice', summary: ... }`; - v3 notice source 是 `{ kind: 'plugin', plugin: 'task-guard', form: 'notice', summary: ... }`(`session.header.version = 3`); - `sourceKind: auto/v3/v4` 选择与非法值校验; - 读取实际的 `cordis.patch.yml`,确认所有字段都是当前代码认识的 `Config`。 另外用隔离的临时 profile 验证过 bundle 组合: ```powershell dsh --profile <临时 profile> --dump-config ``` 能正确解析出: ```yaml - id: task-guard name: dsh-task-guard config: enabled: true locale: zh staleAfterCalls: 5 repeatEveryCalls: 4 blockAfterCalls: 0 rejectMissingActive: false maxListItems: 6 ``` 临时 profile 已删除。 ## Live 测试(已通过) `11:25:51` 插件管理器重新安装成功:`package.json` 的 `dependencies` 和 `dsh.profile.bundles` 都包含 `dsh-task-guard`,junction 存在;`cordis.patch.yml` 没有额外条目,使用的是 bundle 自带的 patch。 实际测试: 1. `todo_write` 只提交一个 `pending`(没有 `in_progress`): - 工具结果成功:`Updated todo list: 1 pending, 0 in progress, 0 completed.` - 随后出现插件 notice: ```text 【todo 同步】清单里还有 1 个待办,但还没有任何 in_progress 任务。请把即将开始的阶段标为 in_progress。 ``` - **没有** `format v4 message requires a producer-owned source kind` 错误。 2. 把该任务改为 `in_progress`,再连续执行 5 次顶层 `read`: - 第 5 次后出现停滞 notice: ```text 【todo 同步】距上次 todo_write 已过 5 次工具调用。 进行中:live test task-guard v4 notice ... ``` - 整轮没有失败。 3. 测试完成后用 `todo_write([])` 清空清单。 结论:v4 source kind 修复生效;默认的 advisory 模式不会打断任务,且即时 notice 与停滞 notice 都能到达模型。 ## npm 发布准备 - `dsh-todo-guard` 已被其他作者占用(`wxlei2004`,0.1.0,2026-09-28),不能覆盖发布。 - 项目已改名为 `dsh-task-guard`(npm 上可用,且与 GitHub 仓库同名)。 - `npm pack --dry-run` 与 `npm publish --dry-run --registry=https://registry.npmjs.org/` 均通过,包内容 10 个文件、约 19.7 kB。 - **账号暂停**:`npm whoami` 已是 `mcviseron`,但发布时使用 recovery code 触发 npm 预防性暂停;暂停期只读,`dsh-task-guard` 仍是 404。恢复时间:**2026-10-20 03:55 UTC / 11:55 北京时间**。暂停期间不要重试 publish。 - 预处理已完成: - `.github/workflows/publish.yml` —— OIDC trusted publishing + provenance;推 `v*` tag 自动发布,手动触发默认 dry-run; - `docs/release.md` —— 首次手动发布、OTP/granular token、staged publishing、Trusted Publisher、npmmirror 同步; - `publishConfig.registry` 固定为 `https://registry.npmjs.org/`。 - 首次 1.0.0 必须手动发布(Trusted Publisher 只能绑定已存在的包);之后在 npmjs.com 配置 `MCviseron/dsh-task-guard` + `publish.yml`,后续 tag 交给 CI。 ## 当前 profile 状态 - 早期 live 测试使用旧包名 `dsh-todo-guard`(plugin id `todo-guard`,source `plugin:todo-guard`)。 - profile 已切换到 `dsh-task-guard`: - `package.json` 的 dependency / `dsh.profile.bundles` → `dsh-task-guard`; - `pnpm-lock.yaml` 与 `node_modules/.pnpm/lock.yaml` → `dsh-task-guard`; - 旧 junction 删除,新 junction `node_modules/dsh-task-guard` 指向本仓库; - `import('dsh-task-guard')` 导出 `name: task-guard`,`pnpm list` 显示 link。 - 用户已升级 DSH 到 `0.2.1-rc.2` 并重启;2026-10-18 的 live 冒烟确认 `task-guard` / `plugin:task-guard` 正常加载,两条 notice 路径均通过。