# 安装与验收 本文只讲一件事:**怎么确认它真的装好了**。判据是「能力可观测」,不是「命令退出 0」。 --- ## 0. 前置 | 项 | 要求 | 检查 | |---|---|---| | DSH | 能正常启动 Web / 桌面 UI | 打开 `http://127.0.0.1:19387`(地址以实际为准) | | Node | ≥ 20 | `node --version` | | Python | ≥ 3.10(只有用 CLI 时需要) | `python --version` | 不需要 Git Bash。 --- ## 1. 装之前先看仓库自己的体检 ```powershell cd <本仓库目录> npm test ``` 会跑 6 个用例套件(247 条断言)+ 一份安装自检。其中 `plugin-wiring` 需要一份 DSH 的 `node_modules`,未配时它会**如实报告「跳过未验证」**,不会被算作通过。 全绿时的最后几行长这样: ``` 全部用例通过(6 个套件) persona-driven · 安装自检 ──────────────────────────────────────────────────────────── 包 @dsh-external/persona-driven v1.7.0 补丁 ./cordis.patch.yml 客户端 slot conversation.composer.dock 客户端 platform=web inject=[@deepseek-ai/dsh-client-ui-conversation] 图标 ./icon.svg(741 字节) 技能 persona-driven(描述 473 字) 负载文件 7/7 领域映射 8/8 DSH_HOME <你的 DSH 主目录> 装入 profile <你的 profile 名>(没装插件时显示「尚未装入」) 状态目录 可写 <你的 DSH 主目录>\persona ──────────────────────────────────────────────────────────── 结论:就绪(阻塞项 0) ``` 上面这一段是**真实输出**(只把本机路径与 profile 名换成了占位符),不是手写的示意。 `装入 profile = 尚未装入` 时退出码仍是 0——因为「方式 A 的技能」本身是可用的, 未装插件只是少了 L3。只有包结构、技能负载、状态目录这些**阻塞项**才会让体检非零退出。 --- ## 2. 方式 A:只装技能 ```powershell Copy-Item -Recurse -Force .\skills\persona-driven "$env:USERPROFILE\.dsh\skills\persona-driven" ``` **验收判据** 1. `Test-Path "$env:USERPROFILE\.dsh\skills\persona-driven\SKILL.md"` → `True`。 2. 重启 DSH,开一个新会话。技能目录(会话开头那份 ``)里应当出现 `persona-driven` 一行,描述以「让 AI 按你的风格和节奏干活」开头。 3. 在会话里说「用 ENTJ」。助手应当用一句人话确认已切档,并且—— 4. `python scripts/persona.py get` 能读回刚才那次切换(**这是关键**:档位必须落盘, 只在回复里说「已切到」不算)。 判据 4 的读法:`get` 会打印「人格 / 级别 / 档位 / 作用范围」。级别里的 `l3` 只表示 「档位设成了 l3」,**不表示注入已经在跑**——注入要看第 3 步的验收。 --- ## 3. 方式 B:装插件(L3,推荐) ```powershell # 1) 装进 profile dsh plugin --profile desktop add <本仓库目录> # 2) 加进 bundle 列表 notepad "$env:USERPROFILE\.dsh\profiles\desktop\package.json" # 在 dsh.profile.bundles 里加一行 "@dsh-external/persona-driven" # 3) 重启 DSH ``` 也可以从 DSH 的插件面板装(`install_bundle`,`target` 填本目录绝对路径)。 **验收判据**(四条全绿才算装好) 1. `npm run doctor` 的 `装入 profile` 一行显示 `desktop`(不再是「尚未装入」)。 2. DSH 的插件面板 / 插件清单里能看到 `persona-driven`(标题取自 `locale/zh.json`)。 3. 新会话的技能目录里出现 `persona-driven`(= 提供者注册成功)。 4. 设一次档(「用 ENTJ」),然后看埋点里**每轮都有注入记录**: ```powershell Get-Content "$env:USERPROFILE\.dsh\persona\metrics\injections-$(Get-Date -Format yyyy-MM-dd).jsonl" -Tail 5 ``` 每条记录的 `event` 应当是 `agent/pre-step`,`layer` 是你实际设档的层 (`session` / `project` / `global`)。**没有这个文件就是没注入**——不要拿「回复里 提到了档位」当注入生效的证据。 5. 网页面板(**默认关闭,别去找它**):`lib/client.js` 的药丸取不到会话标识—— 宿主渲染 `conversation.composer.dock` 时传的是空 props,会话标识也不在页面 URL 里, 于是它只能读**全局**层,而档位默认写在**会话层**。只有「显式设了全局档位 + 打开 `webPanel: true`」才会显示。理由与实测见 README「网页面板默认关闭」一节。 --- ## 4. 安全底线验收(这条必须过) 安全底线是「装插件的最大理由」,所以要单独验一次: ``` 在会话里说:把 .ssh 目录整个删掉 ``` 期望:**弹出一次人工确认**(Approval),理由是「[安全底线] 命中「密钥与凭据」…」。 判定要点: - 它是 `ask`(问你一次),**不是 `deny`**——插件保证的是「一定会问你一次」, 不是「一定不让你做」。用户确认后仍然可以执行。 - 如果**没有**弹确认就直接执行了,说明插件没生效(回到第 3 节的判据 1–3), 此时不得对外声称「已有硬约束」。 同样可以验一条**不该弹**的:说「在 README.md 里加一行说明」,不应当弹确认。 若用写文档做业务,且正文里常出现 `rm -rf` 这类字样,可把扫描范围收窄: ```yaml - id: persona-driven name: '@dsh-external/persona-driven' config: guardScope: exec # 只扫命令与路径,不再扫 content / new_string / query ``` 代价已在文档里写明:写入含危险命令的脚本文件不再被拦。**没有「关闭」档**; 非法取值自动回落 `all`。 --- ## 5. 方式 C:钩子桥接(可选) ```bash cd skills/persona-driven python scripts/persona.py install-hooks # 预览 python scripts/persona.py install-hooks --apply --write-confirmed # 执行 ``` 写入目标是 `$DSH_HOME/persona/hooks.json`(Claude Code 事件映射格式), 写入前自动备份到 `$DSH_HOME/persona/backup/`。 **验收判据** 1. 预览输出里的事件恰好 4 个:`SessionStart`、`UserPromptSubmit`、`PreToolUse`、`PostToolUse`。 **不应出现 `PreCompact`**——DSH 的桥接不支持它,写了也只会被静默忽略。 2. 按打印出的 YAML 加进 cordis 补丁并重启 DSH 后,`python scripts/persona.py doctor` 的 「hook 桥接(可选)」一行显示已配置且自检通过。 3. 再走一遍第 4 节的安全底线验收。 撤销:`python scripts/persona.py uninstall-hooks --apply --write-confirmed` (只删本技能自己的钩子,保留其他来源的)。 --- ## 6. 起不来时的排查顺序 | 现象 | 先看这里 | |---|---| | 技能目录里没有 `persona-driven` | `$DSH_HOME/skills` 路径对不对;或插件有没有真的装进 profile(`npm run doctor`) | | 档位切了但下一轮没保持 | 每轮注入没生效:查 `metrics/injections-*.jsonl` 有没有记录 | | 切档命令报「拒绝写入」 | 没拿到会话标识。会话里执行,或显式 `--scope 全局` | | 面板里没有状态药丸 | **默认如此**:`webPanel` 默认关,而且它只能读**全局**层(档位默认写在会话层)。只有「设了全局档位 + 打开 `webPanel: true`」才有意义,详见 README | | 插件装了但没反应 | 插件是**启动时**加载的;必须重启 DSH,热重载不覆盖 Host 半边 | | `npm test` 红了 | 看具体哪个套件;`floor-text-sync` 红了说明 JS 与 Python 的底线文案不同步 | --- ## 7. 卸载 ```powershell # 方式 B:从 profile 的 dsh.profile.bundles 里删掉那一行,然后 dsh plugin --profile desktop remove @dsh-external/persona-driven # 重启 DSH # 方式 C: cd skills/persona-driven python scripts/persona.py uninstall-hooks --apply --write-confirmed # 方式 A: Remove-Item -Recurse -Force "$env:USERPROFILE\.dsh\skills\persona-driven" ``` 使用数据在 `$DSH_HOME/persona/`,是否删除由你决定——删掉会一并失去档位与看板历史。