验收与验证清单

August 22, 2026 · View on GitHub

配套 docs/00-project-plan.md 的每阶段出口。所有验收项要求实测记录(命令 + 输出),不满足即视为未完成。

0. 环境准备

依赖说明
Rust 工具链rustup + stable;cargo --version 可跑
Xcode Command Line Toolsxcode-select -p 有输出(编译 + dmg 打包)
Node ≥ 20本机已装(开发期探测链用);node --version
dsh本机 /opt/homebrew/lib/node_modules/@deepseek-ai/dsh(0.1.0-rc.8)

1. M0 验证

1.1 M0.1 手动验证 URL 行(直接跑 dsh)

DSH_HOME=${DSH_HOME:-$HOME/.dsh} \
  node /opt/homebrew/lib/node_modules/@deepseek-ai/dsh/lib/bin.js web --port 0

预期:stdout 出现 dsh web: http://127.0.0.1:<随机端口>;浏览器打开该 URL 可看到 dsh UI。Ctrl+C 退出后 pgrep -f "bin.js web" 无残留。

1.2 M0.2 URL 解析原型

node scripts/probe-dsh.mjs            # 期望输出:parsed url + tcp connect ok

用例:① 正常行;② 带 (LAN: ...) 后缀的行;③ 前有噪声行。全部正确提取 http://127.0.0.1:<port> 并 TCP 连通。

1.3 M0.3 Tauri 空壳加载外部 URL

cd dsh-desktop && npm run dev

预期:窗口显示 dsh UI(先本地跑一个 dsh web --port 0 供导航,或空壳直接 navigate 到该 URL)。加载成功即可,不要求生命周期。

1.4 M0.4 WebView 冒烟

在 1.3 的窗口中:发起对话,确认 SSE 流式输出逐字渲染;输入框支持方向键/中文输入/复制粘贴;刷新页面会话仍在。

2. M1 验收(最小可用)

2.1 功能清单

#步骤预期
F1双击启动 app加载页 → 自动出现 dsh UI,无需手动跑 dsh
F2窗口标题/大小合理;无地址栏
F3关闭窗口(或 Cmd+Q)app 退出,pgrep -f "bin.js web" 为空
F4启动后 lsof -iTCP -sTCP:LISTEN -n -P | grep node只有一个 node 监听 127.0.0.1 随机端口
F5日志页可见启动过程行([app] runtime: bundled/PATH[out] dsh web: ...)

2.2 故障注入

#场景操作预期
T1崩溃重启启动后 pkill -9 -f "bin.js web"自动重启,UI 短暂回加载页后恢复;服务可再用
T2崩溃上限连续 pkill -9 5 次第 5 次后停在错误页(显示退出历史),点"重试"恢复
T3启动超时临时把 DSH_HOME 指向不可写目录(或注入假 dsh)60s 内进错误页 E_START_TIMEOUT/E_CHILD_EXITED,显示 stderr
T4双开再启动一个实例第二个实例不出现新窗口/新服务,聚焦已有窗口
T5端口占用(fixed 策略)设置固定端口 3080 并先占用明确错误页,不挂死
T6退出残留正常退出后检查pgrep -f "bin.js web"pgrep -f dsh-desktop 均空

2.3 回归基线(每次改动后跑)

pgrep -f "bin.js web" | wc -l   # 退出后应为 0

3. M2 验收(打包分发)

#步骤预期
P1npm run vendorresources/dsh/resources/node/<arch>/noderuntime-manifest.json 生成
P2体积记录du -sh resources/* target/release/bundle/dmg/*.dmg,对照 docs/03 §4 预算表并回写实测
P3干净环境新建系统用户(或临时改 PATH 为 /usr/bin:/bin)从 Finder 启动 app
P4无 node 依赖干净环境 which node 无结果时 app 仍可启动
P5覆盖安装用新版 dmg 覆盖安装后启动
P6开发态降级删除 resources/npm run dev

4. M3 验收(增强)

#功能验收
S1托盘状态随服务变化(运行中显示端口);"打开主界面/重启服务/退出"三动作正确
S2设置-路径改 DSH_HOME 为另一目录 → 重启服务 → 该目录 profile 生效;日志可见
S3设置-端口自动 ↔ 固定切换,重启服务后生效;固定被占用有明确报错
S4设置-日志环形缓冲行数生效;实时视图滚动正常
S5开机自启开关持久化;系统设置登录项可见;重启系统后自动启动
S6升级替换 app bundle 后首次启动正常(覆盖 R3)
S7安全回归主窗口控制台 window.__TAURI__ 为 undefined;window.__DSH_BOOT__ 存在(dsh 自身)

4.5 Windows 适配验收(Win 10/11 x64)

4.5.1 环境准备

依赖说明
Rust MSVC 工具链rustup + stable,含 MSVC Build Tools(VS2022 "使用 C++ 的桌面开发"工作负载);cargo --version 可跑
WebView2 RuntimeWin11 自带;Win10 需装(NSIS 安装器默认静默引导下载)
Node ≥ 20本机已装(开发期探测链用);node --version
dsh本机 npm i -g @deepseek-ai/dsh(0.1.0-rc.8),或直接 npm run vendor 走 bundled

4.5.2 构建

cd dsh-desktop
npm run vendor        # 生成 resources/node/win32-x64/node.exe + resources/dsh/
npm run build:app     # 前端构建 + tauri build → target/release/bundle/nsis/*.exe

打包格式:MSI 与 NSIS 功能等价,只打一种即可。Windows 默认只产 NSIS(src-tauri/tauri.windows.conf.json 固定 targets: ["nsis"])——实测 NSIS ≈ 4 分钟 / 52 MB,MSI(WiX light)≈ 17 分钟 / 103 MB。如需 MSI:npm run build:app:msi(详见 dsh-desktop/README.md)。

4.5.3 验收清单

#步骤预期
W1双击 exe(或安装后启动)加载页 → 自动出现 dsh UI,无需手动跑 dsh
W2关闭主窗口或托盘"退出"app 退出,tasklist | findstr /i "node.exe" 无残留(排除系统 node)
W3启动后 netstat -ano | findstr LISTENING仅一个 node 监听 127.0.0.1 随机端口
W4设置窗口日志页可见 [app] runtime: bundled/PATH[out] dsh web: ...
W5崩溃重启:启动后 taskkill /F /PID <node pid>自动重启,UI 恢复;服务可再用
W6崩溃上限:连续强制结束 node 5 次第 5 次后停在错误页,点"重试"恢复
W7双开:再启动一个实例第二个实例不出现新窗口/新服务,聚焦已有窗口
W8PATH 探测:删 resources/ 或设 DSH_DESKTOP_NODE/DSH_DESKTOP_DSH启动成功,日志 [app] runtime: PATH;shim(dsh.cmd)正确解析到 bin.js
W9开机自启:设置页打开开关注册表 HKCU\Software\Microsoft\Windows\CurrentVersion\Run 出现 DSH Desktop
W10退出残留:正常退出后tasklist | findstr /i "dsh-desktop node.exe" 均空
W11覆盖安装:用新版 NSIS 安装包覆盖安装后启动首次启动正常(profiles/node_modules 自愈)

回归基线:退出后 tasklist | findstr /i "node.exe" 应为 0 行。

5. 常见问题排查表

症状排查处理
构建失败 failed to read file '.../permissions/path/autogenerated/._default.toml': stream did not contain valid UTF-8工作区位于 ExFAT 卷,文件系统为每个文件生成 ._ AppleDouble 侧车,tauri-build 遍历输出目录时读到已内置解决:构建产物默认落在 src-tauri/target;ExFAT 卷用户设置 CARGO_TARGET_DIR 指向 APFS 卷(见 dsh-desktop/.cargo/config.toml 注释)
启动即错误页 E_RUNTIME_NOT_FOUND[app] runtime: 日志npm run vendor 或检查 PATH
60s 超时看 stderr 尾部DSH_HOME 权限?端口被占?profiles/node_modules 符号链接异常(手动 ls -la ~/.dsh/profiles/node_modules)
白屏WebView 控制台;确认导航端口与 server 端口一致检查 is_remote_dsh_url 端口比对逻辑
退出有残留进程ps -axo pid,ppid,pgid,command | grep -i node查进程组清理分支;确认 spawn 时 process_group(0) 生效
覆盖安装后异常删除 ~/.dsh/profiles/node_modules 再启动dsh 自愈重建;若仍失败则检查 bundle 路径变更
设置不生效检查 app_config_dir()/settings.json 内容与权限确认写路径与读取路径一致(identifier 变更会换目录)

6. 发布前最终检查(个人分发版)

  • npm run build 全链路一次通过,产出 dmg 体积已记录
  • P3 干净环境验证通过(最关键)
  • T1/T2/T6 故障注入回归通过
  • S7 安全回归通过
  • 已知问题与取舍已回写 docs/00-project-plan.md 风险登记表