Skip to content

0.9.1 — 启动器闭环、卸载体检与文档补齐

Latest

Choose a tag to compare

@nonentity303 nonentity303 released this 07 Oct 01:31
· 5 commits to master since this release

dsh-plugin-manager-pro 0.9.1 — 启动器闭环、卸载体检与文档补齐

一句话:0.9.1 把「装坏了能救」往前推了一步——卸载前先体检、卸载后能清干净、本地写接口有防护、自检有留痕,并把工程文档补齐(架构 / 命令行口径 / CHANGELOG / 英文版)。
主题:启动器与救砖链的命令行闭环 + 卸载侧安全网 + 文档工程化;界面零改版。
版本:dsh-plugin-manager-pro 0.9.1(npm 上的 latest 与本版本的发布日期以 registry / GitHub Release 为准)
发布日期:2026-10-07(npm 发布时刻 2026-10-07T01:23:37Z;npm 与 GitHub Release 附件为同一份字节,sha256 88C182B852AA5CCB73E67EA6298E102935BC39E2B1D755FD046E1D7B7A785643)

本文件可直接作为 GitHub Release 正文使用。

① 版本定位

  • 适用人群:已经用 0.9.0 独立插件页管理插件的用户;本版不改变界面,插件页仍是同一套五个分区。
  • 本版主体是命令行与安全网:启动器卸载闭环(R13)、本地写接口防护(L11)、自检留痕(P1-5)、救援入口与端口分工(R7)、卸载前体检(P1-4)、卸载前清理开机自启(L9),外加 CI 测试工作流与文档补齐。
  • 兼容性:DSH 0.1.6 及以后(在 0.1.7-rc.2 上实测);0.1.6 之前的老引擎请继续用 0.8.2(见 README.md 的引擎兼容性矩阵)。
  • 从 0.9.0 升级是直接替换:dsh plugin --profile web add dsh-plugin-manager-pro@0.9.1 → 重启 dsh web;profile 配置无需手工改动。

② 新增(现在你可以……)

现在你可以…… 说明
一条命令把启动器痕迹清干净 npx dsh-pm-launcher --uninstall:停本 profile 的守护(.open-boot.pid + 锁端口 port+1000 + 进程镜像三重校验,不通过就不动别的进程)→ 删 HKCU\...\Run 下所有 DSHWeb* 自启值(含历史 DSHWebRescue)→ 删两个 .vbs 包装脚本 → 清 pid。幂等(确认无可清理项也 exit 0,退出码三档见 §③),日志保留,引擎 3080 不动
卸载管理器不再留下自启残留 卸载本插件自身前,管理器会先调用包内的 bin/open-boot.mjs --uninstall --profile <profile>(能力探测:旧版本没有该参数就记「已跳过」并继续,不阻断卸载);结果写进卸载报告与操作历史
卸载前先做一次体检 卸载预览顶部给出结论行(安全 / 需注意 / 有风险 + 一句理由),并列出三类检查:① 依赖断裂(dependencies / peerDependencies 为高风险,optionalDependencies / dsh.recommendedDeps 为提示)② 补丁残留(cordis.patch.yml 里与被卸载包关联的开关行 / insert 行,只提示、绝不自动删除)③ service 与端口冲突(同名 service / 同端口声明)
本地写接口有防护 POST /api/boot、/rescue/api/start|fix|stop 需要同源 Origin(同机同端口白名单:127.0.0.1 / localhost / [::1],不按 Host 头派生)+ 页面注入的一次性令牌(X-DSH-PM-Token,48 位 hex、不落盘、每次启动都换、常量时间比较);boot/start 还有单飞闸门(并发第二个 → 409)。第三方网页的 fetch 一律被拒(403/401),本地工具照常可用;读接口(GET /api/status|verify)保持开放
自检留下痕迹 npx dsh-pm-launcher --status 每次都往 <profile>/health.log 追加一行(<ISO> OK|FAIL boot=up@3081 engine=up@3080),并在控制台打印「最近自检:…」;日志保留最近 7 天 / 最多 1000 行
救援入口收敛到一个端口 open-boot 现在是 3081 唯一网页入口:/ 是"打开即启动"页,/rescue 是救援页(含 /rescue/api/*,复用同一套实现)。独立备份入口 npx dsh-pm-rescue 退到 3082,不再与启动器抢端口
多实例 / 测试时换引擎端口 环境变量 DSH_ENGINE_PORT 可覆盖引擎端口(默认 3080 不变,仅测试与多实例用)
每次改动自动跑测试 新增 CI 工作流:push 到 master 与所有 PR 自动跑四套测试;Windows 为门禁(注册表 / shim / 端口归属这类断言只在 Windows 成立),Ubuntu 为实验性(continue-on-error,失败不阻塞合并)
查文档而不是翻源码 新增 docs/ARCHITECTURE.md(三进程 / 槽位契约 / 侧车字段 / 卸载事务)、docs/LAUNCHER.md(命令与退出码 / --uninstall 四步 / 写接口防护 / 故障排查 + 「文档条目 → 代码位置」核对表)、CHANGELOG.md(脚本生成)与英文版 README.en.md;README.md 首屏补上能力对比表与引擎兼容性矩阵

③ 变更(行为变化,先看一眼)

变化 影响与处理
启动页现在也认 localhost 与 [::1] 写接口的同源白名单由"只认 http://127.0.0.1:<端口>"扩为同机同端口的三种等价写法:127.0.0.1 / localhost / [::1]。把浏览器主页写成 http://localhost:3081/ 现在能正常"打开即启动"(此前会被判跨站 → 403)。端口必须与页面地址一致;第三方域名与其他端口一律 403
--uninstall 的退出码改为三档 0 / 1 / 2 0 = 完成(含确认无可清理项)/ 1 = 出错 / 2 = 归属未确认:当系统探测(netstat / tasklist)不可用时,无法判断进程是不是本 profile 的守护 —— 此时不停止任何进程、保留 .open-boot.pid 作为线索、不报"卸载完成"。脚本/自动化请按"只有 0 才算完成"处理
命令行取值不再静默回落默认目标 --profile / --port 取值缺失、以 - 开头(被后面的开关占用)、空白、非数字或越界(端口)→ 用法错误:解析立刻停止、用法打到 stderr、exit 1,且零副作用(不装崩溃日志、不写日志、不动注册表 / pid / 进程)。对三个会改全局自启项的子命令(--uninstall / --install-autostart / --uninstall-autostart),任何未识别的开关或多余位置参数(例如把 --profile 拼成 --profle)同样按用法错误拒绝。新增支持 --profile=<目录> 写法;其余模式(--status 等)仍保持"警告并忽略"以便不打断既有脚本
rescue-daemon 默认端口 3081 → 3082 与启动器同时使用时不再冲突:3081 归 open-boot(唯一网页入口),3082 是独立备份救援入口。如果你曾用 --port 3082 显式起它,现在直接 npx dsh-pm-rescue 即可
/rescue 的归属变了 0.9.0 及更早:救援页只挂在启动器的 / 流程里(或 3082 的服务上)。0.9.1:3081 的 /rescue 与 /rescue/api/* 就绪;3080 上的 /rescue 仍由引擎侧的 host 注册,需要引擎活着
--uninstall-autostart 未安装时退出码 1 → 0 幂等:脚本/自动化可以先无条件执行它,不再需要先探测是否存在
--status 不再是"纯只读" 它会写 health.log(这是自检留痕的设计)。不想要日志文件可以直接删掉该文件,下次 --status 会重新创建
端口被占用时的行为写进帮助 3081/3082 被非本工具进程占用 → 明确报错退出(open-boot 前台 exit 1;若端口上已是本启动器则 exit 0),绝不静默漂移到别的端口;--help 现在写明了 --uninstall 语义与端口分工
界面无变化 插件页、五个分区、行内配置与市场行为与 0.9.0 相同

④ 修复

  • 用 localhost 打开启动页被误判为"跨站"(403):0.9.0 的同源检查只认 http://127.0.0.1:<端口>,于是在自己机器上把主页写成 http://localhost:3081/ 时,"打开浏览器即自动自检 → 修复 → 启动"整条链路失效(页面能打开,但页内的启动请求被 403 拒掉)。现在 localhost 与 [::1] 与 127.0.0.1 等价(必须同端口),第三方域名仍然被拒。
  • --uninstall 在探测受限时会"假报完成":当 netstat / tasklist 被安全策略或受限会话拦下时,工具无法判断某个进程是不是本 profile 的守护,旧行为却仍然走完流程并以 exit 0 打印"卸载完成"。现在这种情况返回 exit 2(归属未确认):不停止任何进程、保留 .open-boot.pid、明确提示人工核对,不再谎报成功。
  • 未知 / 拼错开关会静默回落到"默认目标":三个会改动全局自启项的子命令旧行为是"忽略不认识的参数"——例如把 --profile 拼成 --profle 后,npx dsh-pm-launcher --uninstall --profle D:\somewhere 会忽略那个拼错的开关,转而对默认 profile + 默认端口 3081 动手:停掉真机 3081 的守护、删掉 HKCU\...\Run 下全部 DSHWeb* 自启值,还以 exit 0 报成功;--port 取值非法时同样会静默落回默认端口。现在这三个子命令遇到任何未识别 token 一律用法错误 exit 1 + 零副作用,--port 取值也改为逐个校验(1–65535 的纯数字)。
  • 受限环境(禁止命名管道)下的 pnpm 调用不再直接失败:spawnPnpm 与卸载前的自启清理先走管道捕获,遇到 spawn EPERM(进程根本没启动、无副作用)会退化为 stdio:"ignore" 重试一次并按退出码判定;正常环境行为不变。
  • 启动器测试的顺序敏感 flake 修掉:注册表断言改为解析 name/type/data 后按 name 排序比较(Windows Run 键枚举顺序不固定),另加纯函数单测钉死规则;生产三件套(bin/open-boot.mjs、bin/rescue-daemon.mjs、lib/enginectl.mjs)哈希未因此变化。
  • 文档里的端口与命令口径与实现对齐:README 的端口表 / 工具表 / 救砖速查此前还是 0.9.0 的事实(救援守护默认 3081、与启动器互抢),现已改为 0.9.1 的 3081/3082 分工,并与 docs/LAUNCHER.md 同口径。

⑤ 验证与测试口径

  • 干净树全绿:npm ci → npm test exit 0(四套件:契约 / 渲染 / 集成 / 启动器);启动器套件 348 项断言(其中 19 条在受限会话按沙箱边界 SKIP —— SKIP 既不计通过也不计失败;断言数以发布时 node test-launcher.mjs --strict 的输出为准)。发布前闸门在隔离环境复演过这份候选件:348 checks, 19 skipped(env)、FAIL 0 条。构建可复现:两次 canonical 构建产物同哈希。
  • 写接口防护实测:第三方 Origin → 403(带不带令牌都是);缺/错令牌 → 401;并发三次 → [200, 409, 409];同源(127.0.0.1 或 localhost)+ 正确令牌 → 200;GET /api/status → 200;令牌确为 48 位 hex(来自页面 <meta>)。
  • 命令行取值与未识别参数实测:10 种非法形态(--profile 缺值 / 被开关占用 / 全空白,--port 缺值 / 非数字 / 0 / 65536 / -1,多余位置参数,裸 --)全部 exit 1、stdout 为空、stderr 打用法;同类用例下真机 profile 的进程、health.log、自启 shim 与注册表值均未被改动(零副作用),并以"裸跑 --uninstall 指向临时夹具仍 exit 0"作为对照。
  • 卸载闭环实测:临时 profile 上 --install-autostart 写入 shim → --uninstall exit 0(删两个 .vbs、清 pid)→ 再跑一次仍 exit 0(幂等);清理后无 .vbs / .pid 残留;真机注册表与 3081 pid 全程未变(清理只动本 profile)。
  • 卸载前体检实测(自造夹具):报出 dependency-break[high]、patch-residue[warning] ×2、duplicate-service[info]、duplicate-port[info],结论行 risky;体检全程只读(前后快照一致)。
  • 文档事实核查:README 首屏的 10 条对外主张逐条核对(竞品停止维护公告原文、GitHub API 的 Release 数量、官方宿主服务的 12 个 remote 方法、两个官方包无 bin 字段、dsh-base 的 id: plugin-manager 行、三个 CLI 命令与 bin 字段一致)。
  • 验证边界(如实写):① README 的三张实拍图以 raw.githubusercontent.com 绝对 URL 引用,本机网络分区无法端到端回读,发布推送后按 docs/RELEASING.md §10 用 GitHub contents API 回读确认 200;② 0.9.0 的干净环境装机验收报告(docs/releases/0.9.0-verify.md)里有三条浏览器级断言(截图 / DOM)按契约移交给了后续流程,本说明不声称已取得它们;③ --install-autostart 的注册表写入往返在受限会话里会被安全策略拦下,该路径由提权会话的测试日志覆盖。

⑥ 已知限制

  • 3082 的「默认端口实测」断言在端口被占用时会 SKIP(既不计通过也不计失败):它需要先确认占用者不是本套件自己,当前实现遇到占用就直接跳过。留作后续小改进(先判定占用者是否本套件 → 等待重试 → 仅外部占用才 SKIP)。
  • --install-autostart 目前仅 Windows;macOS/Linux 请用 npx dsh-pm-launcher --supervise 自行挂到系统服务。
  • 客户端 bundle 在引擎启动时加载:安装或升级后必须重启 dsh web(或让启动器重新拉起引擎),否则界面还是旧的。
  • 启停插件/应用场景写入即生效于配置,但运行期生效需重启引擎(界面会在需要重启时提示,不再谎报已生效)。
  • 3080 上的 /rescue 需要引擎活着;引擎起不来时用 3081 的 /rescue 或 3082 的独立服务。
  • 端口被占用时工具不会换端口(这是刻意的:避免把"别人的服务"当成自己的入口)——需要时用 --port 显式指定并同步改浏览器主页。
  • 在可见的启动窗口里看不到引擎日志(引擎输出写在 profile 目录的日志文件;需要全程输出就在终端里跑 npx dsh-pm-boot)。
  • npx dsh-pm-rescue 的 --port 仍是宽容取值:--port 缺失或不是数字时它会回落到默认端口 3082(open-boot 则改为严格校验、直接报用法错误)。这只影响它自己的监听端口:这个守护不读写注册表、不停止任何进程 —— 笔误最多让你以为救援页在某个端口、实际仍在 3082。

⑦ 安装 / 升级 / 回退

# 安装或升级(推荐显式写版本号:绕开 pnpm 11 的 24 小时冷静期)
dsh plugin --profile web add dsh-plugin-manager-pro@0.9.1

# 或用 Release 页的 tarball(离线/自建场景)
dsh plugin --profile web add ./dsh-plugin-manager-pro-0.9.1.tgz

# 重启 web 生效(客户端 bundle 在引擎启动时加载)
dsh web

# 老引擎(0.1.0-rc.6 ~ 0.1.5)或需要回退旧 UI 时
dsh plugin --profile web add dsh-plugin-manager-pro@0.8.2

卸载:

dsh plugin --profile web remove dsh-plugin-manager-pro   # 会先自动清理开机自启/守护/shim
npx dsh-pm-launcher --uninstall-autostart                # 需要时再兜底清一次(幂等)
npx dsh-pm-launcher --uninstall                          # 或一条命令清掉启动器的全部痕迹

双渠道同字节(本版起执行的发布纪律):GitHub Release 的附件不是"本机重新打包"的产物,而是从 registry 下载回来的同一份 tarball(发布核对表 ⑤ 上传 里的「双轨发布必须同字节」硬关卡:先比对 sha256 与字节数,一致后才上传,并留下两边的哈希)。
你可以自己核对:npm pack dsh-plugin-manager-pro@0.9.1 得到的 tgz 与 Release 附件的 sha256 应逐字相同。
背景:0.9.0 的两个渠道曾差 10 字节(Release 附件 217,689 B / a29ead25…,npm 上是 217,699 B / 9cbd3684…)——版本号相同、内容不同,本版起在流程里堵住。

完整文档:docs/ARCHITECTURE.md(架构与槽位契约)、docs/LAUNCHER.md(命令行口径与故障排查)、CHANGELOG.md(版本历史,脚本生成)、README.md / README.en.md(安装、权限与数据范围、引擎兼容性矩阵)、docs/RELEASING.md(发布流程与核对表)。