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 一律写「远程服务器」。
100 lines
7.9 KiB
Markdown
100 lines
7.9 KiB
Markdown
# 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 一次做掉。
|
||
|
||
> 本档未改任何平台代码与配置;脚本中未保留任何会话正文(仅统计与截断片段)。
|