# 迁移与旧版本兼容 本文件处理两件事:**旧技能的迁移**,以及**既有工作区的增量迁移与恢复**。 --- ## 一、迁移状态:v2 为完全重写 > **v2 是「完全重写」,本仓不提供 v1 技能的迁移路径。** > v1 的 `skills/learn-*` 技能包、`install.sh`、`install.ps1` **已从本仓移除**; > 本仓现在是一个 **v2 插件的仓库**,不再是"一叠方法论技能"的分发仓。 **对使用者的三条结论**: 1. **不需要迁移**:v2 的功能**不依赖任何 v1 技能**。装好插件,四个入口与 `/learn` 命令即可用。 2. **旧技能若还在你的本机技能目录里**,它们只是**纯文本引导文案**,不会与插件冲突; 但插件的流程**不走它们**(插件的实现在 `plugin-src/`,与技能文本无关)。 3. **节点字段与工作区路径沿用不变**:`id / title / status / version / updated / tags / sources / links`, 以及 `AGENTS.md` / `index/` / `inbox/` / `knowledge/framework.md` / `knowledge/nodes/` / `data/` / `task/` / `reports/` / `.dsh/skills/` 这一组路径 —— v2 **只增不改**, 既有工作区**不会被重构**。 > 历史说明(**仅备查,不构成迁移指引**):v1 有 10 件技能 > (`learn-scaffold` / `learn-collect` / `learn-distill` / `learn-pipeline` / `learn-index` / > `learn-review` / `learn-upgrade` / `learn-skillify` / `learn-web-collect` / `learn-data`)。 > 其"直接写入知识节点"的能力在 v2 里被**收紧为"产出候选 → 人工裁决 → 再写入"** > (见 §二 第 3 条与 §四 第 4 步)——**这是 v2 与 v1 最实质的分歧**。 --- ## 二、旧假设的审查结论 需求点名要审查三条旧假设。逐条给结论与依据: | 旧假设 | 审查结论 | 依据 | |---|---|---| | 「当前预设无 shell 工具」 | **已推翻**。新版生成的预设**包含** shell 行(按平台二选一)。整理材料、跑校验都要用到它 | 与 shipped `standard` 预设同源的 `tool-bash` / `tool-pwsh` 行(`packages/preset/agent-presets/presets/standard/agent.cordis.yml:45-51`),本插件 `renderAgentComposition` 逐行对齐 | | 「会话原文一定保留」 | **已改为按真实运行能力判断**。日志(`session.events`)是追加写的,但**模型可见的上下文会被压缩**(compaction 写 `surfaceOp:{op:'replace'}`)。故:`historyComplete` 由**是否发生过 replace 压缩**决定,为 false 时报告如实标"部分范围" | `packages/core/session/src/types.ts:426-441`(`SurfaceOp` 定义与用途) | | 「定时任务可以自动升级知识」 | **已收紧**。任何正式知识/规则写入都要过人确认;定时触发只能产出候选 | 本插件 `flows.upgrade` 的 `confirmWrite` 门 + `allowWrite` / `allowBehaviorRules` 双闸 | --- ## 三、既有工作区的增量迁移 ### 语义(三条,代码里硬编码) | 情形 | 动作 | 返回 | |---|---|---| | 目录不存在 | 创建 | `mkdir` | | 文件不存在 | 写入 | `create` | | 文件存在且内容**完全相同** | 不写 | `skip`("内容实际变化才递增版本"就落在这里) | | 文件存在且内容不同,且我方有基线且**基线一致** | 更新 | `update` | | 文件存在且内容不同,我方**无基线或基线不一致** | **不写** | `conflict`(附理由:目标已被他人改动 / 我方无授权覆盖) | `conflict` 会出现在结果清单里(界面与命令输出都有), 理由逐条写明,不会静默吞掉。 ### 幂等性 重复运行「初始预设」的确认步骤:目录已存在 → 无操作;文件内容一致 → `skip`; 同名预设目录已存在且非空 → `createPreset` 直接返回 `ID_TAKEN`,**拒绝创建**, 不覆盖、不改名。 ### 恢复与回滚 | 场景 | 恢复办法 | |---|---| | 创建预设时写了一半 | 预设目录里的文件是逐个原子写的;半成品目录会被下次 `createPreset` 判为"已存在非空"而拒绝。**处理**:确认目录内容后手工删除该目录,再重跑。插件**不替你删** | | 「关联升级」写了一半 | 变更日志在 `.dsh/learn-skills/changes/<批次>.json`,状态字段为 `aborted`。用 `/learn rollback <批次号>` 还原 | | 回滚后想再试 | 批次状态未标 `done`,直接重跑 `/learn upgrade` 即可;已存在的节点会走 `update` 或 `skip` | | 报告保存失败 | 基线**不会**更新(顺序是"先写报告、成功后才落基线")。修好磁盘问题后重跑「沉淀复用」+「保存报告与对比基线」 | | 磁盘满 / 权限不足 | 写入失败被 `failed` 如实列出,`done` 保留已完成项,批次状态标 `aborted`,提示可回滚 | ### 卸载与停用 - 停用(从 profile 的 `dsh.profile.bundles` 移除)或卸载插件后: **界面入口消失,用户创建的知识、报告、预设全部保留**; - 插件只往**工作区内**写:工作簿目录、`.dsh/learn-skills/`(状态)、 `.dsh/preset-bundles/`(★2.1.0 起的预设 bundle 落点)。2.0.0 曾把预设写到 `/preset-bundles/`(工作区之外)—— 那个位置**自 2.1.0 起不再是默认落点**, 但**不迁移、也不删除**已存在的东西。 - 卸载时以上各个目录都**不会**被删除; - 想彻底清理:删 `.dsh/learn-skills/`(插件状态,删掉不影响知识)与 `.dsh/skills/` 里你自己建的技能。**知识节点与报告不要删**。 - ⚠️ 反向的一条:`dsh.profile.bundles` 里若还留着本插件的预设 bundle 依赖 (`@local/dsh-learn-preset-`),而那个目录**在工作区里**已经不存在, 宿主会在启动时提示跳过该 bundle,且**选中该预设的会话会被拒绝恢复**。 正确顺序永远是:先 `dsh plugin --profile

remove <包名>`,再删目录。 ### 旧式目录预设的迁移(DSH 0.1.7-alpha.1 起) 0.1.6-alpha.2 及更早,"预设"是 `/.agent-presets//` 里的 `preset.yml` + `agent.cordis.yml`。0.1.7-alpha.1 删除了读该目录的 `packages/preset/agent-presets`,**这些目录不会再被任何代码读取** —— 预设不会报错,只是从此不再出现在选择器里(文件都还在,是读取方没了)。 迁移一个旧预设(本插件**不自动做**,避免改动你自己写的组合): 1. 在**工作区内**建 bundle 目录 `<工作区>/.dsh/preset-bundles//`, 只放两个文件(官方 SKILL 原文 "exactly two files";旧写法里那个 `AGENTS.md` **没有任何消费者**,见 §二 第 15 条): - `package.json`: ```json { "name": "@local/dsh-agent-preset-", "version": "1.0.0", "private": true, "type": "module", "dsh": { "bundle": { "patch": "./cordis.patch.yml" } } } ``` - `cordis.patch.yml` —— 一行声明,`plugins` 承接原 `agent.cordis.yml` 的**原文**: ```yaml - insert: - id: preset- name: '@deepseek-ai/dsh-agent-preset' config: id: name: '显示名' description: '说明' order: 50 plugins: # 原 agent.cordis.yml 逐行缩进到第 10 列,!!js 原样保留 - id: persona name: '@deepseek-ai/dsh-persona' ``` 2. 安装它 —— **两条路都要过审批**(安装会在 Host 进程执行新代码): `dsh plugin --profile web add link:<该目录绝对路径>`,或在「创造模式」会话里用 `plugin_manager` 的 `install_bundle`; 3. 确认选择器里出现该预设后,再删旧目录。 ⚠️ 缩进是硬要求:`plugins:` 在第 8 列,其子项在第 10 列。`!!js` 表达式 (如 `disabled: !!js process.platform === 'win32'`)**原样保留**,Loader 在子插件 激活时才求值 —— 这也正是 `@deepseek-ai/dsh-agent-preset` 声明 `[EntryGroup.key] = true` 的原因。 --- ## 四、从 v1 工作流升级到 v2 插件的推荐顺序 > 注意:本节讲的是**工作流**的升级顺序,**不是**技能文件的迁移 > (v1 技能已从本仓移除,也无需迁移 —— 见 §一)。 1. 装插件(`dsh plugin --profile web add link:<路径>` 或发布后走 npm),重启 Host; 2. 在目标工作区点一次「初始预设」走完七题(**不覆盖**你既有的一切); 3. 用「沉淀复用」建立**第一份基线**(首次会明确告诉你"无历史基线,本次建立初始基线"); 4. 把原来 `learn-pipeline` 覆盖的活,改成 `/learn distill` → 人工裁决 → `/learn upgrade`; 5. **v1 技能无需清理**(本仓已移除);但你**本机技能目录**里若还留着它们的副本, 它们只是引导文案,可与插件并存 —— 是否清理纯粹是个人整洁度问题,**不影响插件运行**。