# 插件暂存环境测试约束(真实隔离环境验证) 本文档是 dsh-devforge 及本机 DSH 插件交付流程的**项目约束**:插件改动在进入生产 Web Host 之前,必须先通过「隔离 HOME 暂存实例」完成真实环境验证。该方法于 0.7.7 首次验证通过,0.10.0(2026-09-01)复验有效。 ## 一、约束目标 - 单元测试覆盖不了宿主集成环节(面板渲染、设置注册、协议握手、浏览器通道、备份调度),必须有一个**真实运行**的宿主来验收。 - 生产实例(端口 3080)承载真实凭据、飞书桥长连接、会话库与任务 ledger,绝不允许当试验田。 - 暂存实例要做到"真实但隔离":跑的是与生产同一份已安装插件(真实集成),但凭据、会话、调度器状态全部落在独立 HOME(零污染)。 ## 二、硬性约束(红线) 1. **交付流程必须完整走完**:源仓库测试通过 → 中文提交推远端 → 安装到 web profile → **起暂存实例人工过目 → 用户明确确认 → 才允许重启生产** → 关停暂存实例。 2. 禁止跳过暂存验收直接重启生产;`devforge_restart` 只能在用户明确要求后执行。 3. 暂存实例必须使用独立 HOME(隔离凭据与会话库);**禁止与生产共用 HOME 直接 `--patch` 起实例**——loader 只向插件传 schema 内字段,同 HOME 打补丁改插件配置无效,飞书桥仍会连生产凭据。 4. 暂存 overlay 必须显式禁用:桌面宠物(防双实例重复弹窗)和 devforge 飞书桥(同 appId 双 WSClient 长连接会分流事件,属铁律)。 5. 暂存实例固定用 3081 端口,与生产 3080 区分;启动前确认端口空闲。 6. 需要预览飞书卡片效果时不得依赖暂存实例(其无生产凭据),用一次性 node 脚本走 REST 直发预览卡。 ## 三、标准操作流程 ### 3.1 一次性准备(已就绪则跳过) ```bash mkdir -p ~/.dsh-staging/.dsh ln -s ~/.dsh/profiles ~/.dsh-staging/.dsh/profiles # 复用同一份 profile(含刚装的新版插件) ln -s ~/.dsh/bin ~/.dsh-staging/.dsh/bin ``` overlay 补丁固定放在 `~/.dsh/staging.patch.yml`(内容见 3.2)。 ### 3.2 overlay 补丁(staging.patch.yml) ```yaml # 暂存实例 overlay(配合隔离 HOME 使用):禁用桌面宠物,避免双实例重复弹窗 - id: web-ui-pet disabled: true # 硬教训:devforge 飞书桥 schema 默认启用,暂存实例必须显式禁飞书, # 否则同一 appId 双实例长连接分流事件 - id: devforge config: feishu: enabled: false ``` ### 3.3 启动暂存实例 ```bash HOME=/Users/andyfan/.dsh-staging \ DSH_HOME=/Users/andyfan/.dsh-staging/.dsh \ dsh --profile web --patch /Users/andyfan/.dsh/staging.patch.yml --port 3081 --no-open ``` 原理:`os.homedir()` 跟随 `HOME`,全局凭据(dsh-feishu.json 等)、会话库、任务 ledger 全部落进隔离 HOME,绝不触碰生产;`profiles` 软链保证跑的就是生产同款已安装插件。 ### 3.4 验收 ```bash # 确认实例存活与插件版本 curl -s --noproxy '*' http://127.0.0.1:3081/api/dsh-devforge/meta # 期望返回 {"ok":true,"version":"<目标版本>"} ``` 浏览器打开 `http://127.0.0.1:3081`,人工过目本次改动涉及的面板与功能。暂存 GUI 无生产模型配置属正常现象,不影响验收。 ### 3.5 收尾 用户明确确认后:重启生产 Host(`devforge_restart`)→ 确认生产版本 → 关停 3081 暂存实例。 ## 四、已验证的教训 | 教训 | 后果 | 对策 | |------|------|------| | 同 HOME 直接 `--patch` 改插件配置 | 配置不生效,飞书桥仍连生产凭据 | 必须隔离 HOME(红线 3) | | 暂存忘禁飞书桥 | 同 appId 双 WSClient 分流事件 | overlay 显式 `feishu.enabled: false` | | 暂存忘禁桌面宠物 | 双实例重复弹窗 | overlay 显式 `web-ui-pet.disabled` | | 离线验证补丁是否命中 | 起实例才知道错了 | 先 `dsh --profile web --patch X.yml --dump-config` 离线核对 | | 端口被占 | 起在未知端口或失败 | 启动前 `lsof -i :3081 -sTCP:LISTEN` 检查 | | 隔离 HOME 下 pnpm store 错位 | 暂存实例内执行 `dsh plugin add` 报 ERR_PNPM_UNEXPECTED_STORE(store 归属真实用户主目录) | 暂存实例内不要跑插件安装/升级——「插件更新」的 apply 在暂存不可用属预期边界;装包一律在真实用户环境执行,暂存只验 check/面板 | | 暂存忘禁 CNB 加密备份自动同步(0.26.x 新增,2026-09-08 暂存验收发现) | 暂存按 15m 间隔把隔离 store.db 加密推到与生产相同的备份仓库;生产侧「从远端同步(跳过本机)」会取到暂存机器的最新提交,造成跨实例数据污染 | 起暂存后进入「代码仓库 → CNB → 加密备份」点「停用自动同步」(备份配置存于插件自身 store.db settings 域,不走 cordis overlay,patch 覆盖不到);确认横幅变为「自动同步未启用」后再验收,配置中 repo/interval 原样保留不影响生产 | | 依赖 web-ui-pet overlay 判断宠物风险(2026-09-08 复核确认已过时) | web-ui-* 全家桶已不再经 profile 挂载,组合树中不存在该插件;overlay 里的 web-ui-pet 条目变为惰性,照旧书写会造成「已防护」的错觉 | 暂存防宠物以「未挂载」为准:`--dump-config` 全文无任何 web-ui-* 条目即无宠物弹窗风险;overlay 中的 web-ui-pet 条目仅作历史保留,不再是生效防线 | ## 五、上下文注入(0.11.0 起自动生效) 本文档的约束不再依赖模型自觉读取:dsh-devforge 0.11.0 起内置**三层上下文注入**(`src/constraints.ts`,可在天工造梦设置中关闭或调整路径清单)—— 1. **常驻保底**:所有会话无条件注入六条红线摘要与路由指令; 2. **仓库信号**:会话工作目录命中开发仓库路径清单(默认含本仓库工作区)→ 从第一轮起注入本文档全文; 3. **行为信号**:会话出现写文件/bash/git 提交等开发工具动作 → 后续轮次自动升级注入全文。 注入级别只升不降;涉及开发时全文自动在上下文中,模型无需检索。