Files
dsh_shenxian/dsh-server-docs/04-调整方案/55-guest最新会话取证与优化项.md
T
admin 5ad755116e chore(docs): 文档库并入代码仓(R4 选 a)+ 索引/台账跟进
1) dsh-server-docs/ 从工作区(原 E:\...\aliyun-dsh-server\dsh-server-docs)**整体并入本仓**,
   保留目录名 ⇒ 仓库内 dsh-server-docs/... 的相对引用天然继续有效;旧目录(含其 .git)已归档到
   工作区 _中间产物_待清理/,未随本提交带入。
2) .gitattributes:新增 `dsh-server-docs/** -text` —— 原文档库是 `* -text` + autocrlf=false,
   必须保持纯 LF,否则会被本仓的 CRLF 规则翻掉。
3) 活引用里的绝对路径已全部改到新位置(docs 的 INDEX / README / scripts / skills + 用户级 skills
   + ~/.workbuddy/settings.json 的 hooks);历史档案(04-调整方案/、archive/)按「只增不改」未动。
   ⚠️ hooks 路径改动需「完全重启会话」才生效(配置是会话启动快照)。
4) 交接单/T08:新增 §16「生产整体切换执行记录」(形态 / 落地动作 / **4 个只有真上线才暴露的真 bug** /
   验收证据 / 回滚命令 / 残留项);台账 T08 行 → 已完成并归档;03-路线图 §二 登记 T08 收尾项。
5) 统一称谓:**「本机」只指跑 WorkBuddy 的开发机**,47 / 106 一律写「远程服务器」。
2026-09-15 18:47:13 +08:00

100 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 55 · guest 最新会话取证与优化项(2026-09-11)
- 日期:2026-09-11
- 状态:🔍 **取证完成(本档只记录,未改码)**;4 项优化建议待裁定
- 触发:用户要求「分析 guest 的最新对话记录,看看有哪些问题需要优化」
- 分析对象:`users/4092b965…/home/sessions/…ws-MCN短视频创作--/`
- **主会话 `session-b83ae69b`**(创建 09-10 21:29,**5 turn / 2674 事件 / 13 条用户消息**,最后事件 09-11 22:18)
- 对照:`session-bd54c7cc`(09-10 12:12,12 turn)、`5e540bc4`(09-11 22:17)、`8cdf723e`(21:58)、两个子代理会话(16:48 / 16:51)
- 方法:解压 zstd 多帧 → 解析 JSONL 事件流 → 分类统计(脚本见 §五,只读)
---
## 一、结论速览
**用户感知的"平台能力反复变化、bash 用不了",根因不是平台没修好,而是**:**权限档位是"会话创建时播种"的 —— 平台默认已改(档案 33),但 09-10 创建的老会话仍停在 `workspace-write`(本机沙箱后端不可用 → 任何 shell 被 fail-closed 拒绝),必须用户在 UI 手动切换。**
| 级 | 问题 | 证据 | 现状 |
|---|---|---|---|
| **P1** | **老会话不跟随平台权限默认档位** | 主会话 preset=`workspace-write`(09-10 播种),**11 次沙箱拒绝 + 4 次写拒绝**;22:16:29 用户手动切 `danger-full-access` → **22:16:36 立刻 `PLAIN-BASH-WORKS`**(此后 0 次沙箱拒绝) | ⏳ 待裁定(建议"检测 + 显式提示") |
| **P1** | **平台"零技能"**:`bundled-skills` 与 guest `home/skills` **均为空** | agent 在 16:48 / 18:21 / 22:14 三次尝试 `skill cordis-plugin-development` → `unknown or no longer available` | ⏳ 待裁定 |
| **P2** | **没有"能力清单",agent 反复现场探测** | 三个时点(16:48 / 18:21 / 22:14)近乎相同的探测批次,每次撞同样 4 类墙;用户随之三次追问"能力有变化吗"(16:58 / 18:20 / 22:14) | ⏳ 待裁定 |
| **P2** | **`127.0.0.1` 误导** | agent 三次 `web_fetch("127.0.0.1")` → `resolves to a non-public IP address`(SSRF 防护);而平台文档/代码里到处是 `127.0.0.1:3080` | ⏳ 待裁定 |
| **P3** | 审批摩擦 | `approval/asked` 13 次(`ask` 策略下每次 bash 都要点);用户切 `never` 后才顺畅 | 现状可接受(安全设计) |
**已确认修好(本轮实测)**:`python3` 从 **MISSING(16:50)→ Python 3.12.14(18:22)**(档案 42 的共享运行时于 17:19 落地);宿主层复测 bwrap 合成根 **`SANDBOX-SHELL-OK`**(档案 23 的符号链接修复仍有效)。
---
## 二、决定性证据:档位是"会话级"的
| 会话 | 创建时间 | preset | 结果 |
|---|---|---|---|
| `5e540bc4` | **09-11 22:17** | **danger-full-access** ✅ | 新会话自动拿到平台新默认 |
| `8cdf723e` | 09-11 21:58 | **danger-full-access** ✅ | 同上 |
| **`session-b83ae69b`**(本次分析) | **09-10 21:29** | `workspace-write` →(22:16 手动)`danger-full-access` | 整个白天 bash 被拒 |
| `session-bd54c7cc` | 09-10 12:12 | `workspace-write` →(手动)`danger-full-access` | **同样被手动切过一次** |
| 子代理(16:48 / 16:51) | 09-11 16:48 | preset 空、`sandbox=workspace-write` | 继承主会话当时档位 |
→ 平台侧 `DSH_PERMISSION_MODE=danger-full-access` **已正确注入**(实测实例进程 env),orchestrator 也有注释说明(内核无 Landlock + bwrap 探测在容器内失败 → 用 `danger-full-access` 避免 fail-closed)。**唯一缺口 = 已存在的会话不会更新**。
**为什么"沙箱不可用"而不是"降级运行"**:dsh 的语义是 **fail-closed** —— `workspace-write` 要求真沙箱后端,本机(内核 5.10,无 Landlock;bwrap 在平台合成根内探测失败)拿不到 → **拒绝执行任何 shell**,而不是放宽执行。
---
## 三、用户侧的体感链条(为什么他三次追问"能力有没有变化")
```
09-10 21:29 建会话(当时平台默认 workspace-write)
↓
09-11 16:47 「看看有哪些功能和权限尝试所有方式」
→ agent 探测:bash 被沙箱拒绝 ×3、写工作区外被拒、web_fetch 127.0.0.1 被拒、skill 不存在
↓ 16:58 用户:「没办法执行 bash命令了吗」
↓ 18:20 用户:「看看能力是否有变化」(同一批探测,撞同一批墙)
↓ 22:14 用户:「在确认下现在能力边界有变化吗」(又一次)
→ 22:16:29 用户在 UI 切 danger-full-access + never(approval)
→ 22:16:36 起 bash 全部成功、视频级抓取跑通
```
**结论**:这不是"能力不稳定",而是**同一会话的档位没跟上平台演进**,而 agent 与用户都无法从界面上直接看出"当前档位会导致哪些操作被拒"。→ 优化方向 = **把这件事变得可见、可自检**,而不是让 agent 每次现场试错。
---
## 四、优化建议(按性价比排序,均未实施)
| # | 建议 | 做法(低风险优先) | 解决什么 |
|---|---|---|---|
| **1** | **老会话档位对齐(检测 + 显式提示,不自动改)** | 编排器在 `/api/dsh/enter` 时读该会话首帧 `permission/preset`,若与平台默认不一致 → 在页面顶部提示「此会话创建于 09-10,档位仍是 `workspace-write`(沙箱不可用 → bash 会被拒),是否切换为 `danger-full-access`?」(一键切换,用户决策) | 直接消除 11 次沙箱拒绝的复发;避免"静默能力差异" |
| **2** | **实例能力清单(自检)** | 新增一个**平台注入的能力说明**(实例内 `SKILL`/文档或门户页),内容:可读/可写范围(`/etc` 白名单、`ws` 可写、`profiles` 只读)、**网络边界**(禁 `127.0.0.0/8`、外网通)、可用工具与**已注册技能清单**(当前为空)、权限档位含义。BRIEF 里也加一行指针 | agent 不再现场试错(本次 3 轮探测的浪费);用户不再反复追问 |
| **3** | **技能投放现状对齐** | 明确"平台当前无技能"是有意为之还是遗漏:`bundled-skills` 空 + 个人技能空 → 若期望可用,投放共享技能(档案 10/11/40 机制已就绪);若暂不投放,则在能力清单里写明 | 消除 `unknown skill` 类失败(3 次) |
| **4** | **避免把 `127.0.0.1` 当作可达入口** | 能力清单/governor 文档里明确"实例内不可访问宿主 loopback(档案 39)";给 agent 的运行时上下文里不出现可用 `127.0.0.1:3080` 的暗示 | 消除 3 次 SSRF 拒绝 |
**不建议做的**:自动改写既有会话的档位(等于把受限会话静默提升为完全权限,属安全语义变更,必须用户知情)。
---
## 五、方法与可复用脚本
分析脚本(本轮临时产物,建议沉淀到 `scripts/`):
| 脚本 | 用途 |
|---|---|
| `probe-schema.mjs` | 解压 zstd 多帧 → 事件类型直方图 + 样本结构(先摸 schema) |
| `analyze-guest.mjs` | 会话画像:元信息 / 档位 / 用户消息 / 12 类错误模式扫描 / 工具清单 |
| `classify-bash.mjs` | 逐次工具结果分类(沙箱拒绝 / 文件策略拒绝 / 命令错误 / OK)+ 审批事件 |
| `list-presets.mjs` | **批量对比各会话的 preset / sandbox / approval**(本次定位根因的关键) |
> 关键经验:**会话文件是"多帧 zstd 拼接"**(本次 1583 帧),必须按 magic `28 b5 2f fd` 切分逐帧解压;`session` 首帧含 `cwd/createdAt/agentPreset`,`permission/preset` 帧即该会话的权限档位。
---
## 六、待裁定
请选择要做的项(可组合):
1. **做 §四.1**(老会话档位检测 + 提示)—— 我建议**优先**,它直接对应"用户反复追问能力"的根因;
2. **做 §四.2**(能力清单/自检)—— 与 1 配套,一起做效果最好;
3. **§四.3 技能投放**:你定"平台要不要投放技能";
4. **§四.4** 可并入 2 一次做掉。
> 本档未改任何平台代码与配置;脚本中未保留任何会话正文(仅统计与截断片段)。