# E2E 验证记录:dsh 0.1.5-rc.2 真机(2026-09-22) > 对照 v0.3.0 的假 ctx 冒烟,本文档记录在**真实 dsh 宿主**里的端到端验证:插件装载、MCP 协议、 > preset 挂载、真实 agent 任务(一次列目录 + 行内 JSON 总结)。结论:**全绿**(v0.3.1)。 ## 环境 - 宿主:`@deepseek-ai/dsh@0.1.5-rc.2`(本机安装,web GUI 常驻 3080) - 测试实例:`dsh --profile dsh-carrot-on-a-stick-e2e --patch ./cordis.yml --no-open --port 3081`(从 shipped 模板新开的 profile,共享 `~/.dsh` 凭证/设置;插件经 `npm pack` tarball 装进 profile) - 客户端:`e2e.mjs`(原生 fetch 的 MCP StreamableHTTP 往返) - token 成本:3 次 `agent_run`,前两次在提示词组装期失败(近零 token),第三次 17.4s 成功 ## 结果(v0.3.1) | 检查 | 结果 | |---|---| | 插件在真实宿主装载,MCP server 监听 8090 | ✅ | | initialize / tools/list(7 工具)/ echo | ✅ | | preset 挂载:`agent_run` 的 toolCalls 非空 | ✅ `calls=pwsh` | | 本地 `userMessage()` 被真实 agent-loop 接受(append 校验通过) | ✅ | | `snapshotEvents()` 事件提取(toolCalls/toolResults/assistantText) | ✅ | | 行内 JSON 总结契约(changes/verification) | ✅ `changes="仅执行了一条列目录命令,未修改任何文件"` | ## 发现与处置 1. **README 安装流程不成立**:loader 以 **profile 目录**为 baseUrl 解析裸包名——在仓库根 `dsh web --patch ./cordis.yml` 找不到本地包。正确姿势:先把包装进 profile(`pnpm -C ~/.dsh/profiles/ add -w `;Windows 下 `file:D:/...` 形式会被 pnpm 拼坏,用 tarball),再 `--patch` 加配置。→ 已改文档。 2. **`dsh_list_tools` 全局注册表为空**:0.1.5+ 模型工具挂在 preset/agent 作用域,不在全局表。→ 工具描述已澄清语义(agent 实际可用工具以 toolCalls 为准);作用域列表需宿主侧 API,留作后续。 3. **存量捞回过度**:真机一次补挂 156 个历史会话(批量持久化写入用户数据)。0.1.5 的 workspaceRegistry 已按 header.cwd 自动索引,该 rc.6 时代 workaround 属过度行为。→ 改为 `reattachOrphans: true` 显式开启,默认关闭。(本次验证已在共享数据里产生过一次补挂——语义与官方 create 流程一致,如需回滚可按工作区 detach。) 4. **`turn/end` 失败必须透出**:模型调用失败时没有任何 assistant 输出,v0.3.0 返回"成功"的空结果。→ `TaskResult.error` 字段 + `turn/end` 非 completed 收场提取 + 无产出兜底;正是它把根因 #5 暴露出来。 5. **`{{model}}` 提示词变量**:`deployment:persona-prefix` 引用 `{{model}}`,其值直接来自 `agent.options.model`——agent-loop **不做**默认解析,默认模型解析发生在 Web 应用层(`agentDefaultModel`)。插件直连 `ctx.agents.create` 时,`provider` 无 `model` 的残缺选择(v0.3.0 默认值正是如此)会让整个 turn 在组装期失败。→ `resolveAgentOptions()`:成对显式配置直接用,否则经 `ctx.agentDefaultModel.currentSelection()` 补全,仍不完整则明确报错;默认 provider 撤空。 6. **池会话不 flush**:官方 `whenIdle` 注释明确"消费者自读存储需自行 flush";不 flush 的话 durable log 只有 header,重启续接丢历史。→ 任务后对池会话与 resume 会话统一 best-effort flush。 ## 附注 - `task_inbox`/`task_result` 走同一 `executeTask` 通道,未单独跑真机(行为差异仅在队列包装)。 - 会话权限行为:spawn 会话 `approval: 'ask'` 下,本次只读列目录的 pwsh 调用未被卡(沙箱默认放行只读);更敏感操作与审批策略的交互仍是 Roadmap 项。