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 一律写「远程服务器」。
15 KiB
37a · guest 会话取证与平台缺陷清单(MCN短视频创作)
- 日期:2026-09-11
- 触发:用户要求「看看 guest 用户的 MCN短视频创作 工作区的对话记录,能发现哪些问题」
- 状态:🔍 取证完成(本档只记录缺陷,不含代码改动)
- 关联:档案 32(同一方法,mcntimo 工作区)、档案 33(沙箱默认档位已改)、档案 21(guest 卡顿排查,服务端侧)、档案 23(实例内能力限制核查)
TL;DR|结论:从 guest 的「MCN短视频创作」会话反查平台缺陷清单(只记录缺陷,不含代码改动)。 关键:含 P0/P1 分级与证据;方法可复用于其他工作区(同档案 32)。 状态:🔍 取证完成
一、取证范围
| 项 | 值 |
|---|---|
| 用户 | guest = 4092b965-2f68-4977-9989-68b3966f7df0(uid 100002,dsh-eeccbc638afc46bdb663) |
| 工作区 | ws/MCN短视频创作(workspace id 7f9fd72c-1cf3-49f3-bb72-ba3de28a16fe) |
| 主会话 | session-bd54c7cc-7620-4cf3-9bff-9084bcc5ae88,4190 行 / 2.8 MB 明文 / 1.3 MB zstd |
| 副会话 | session-b83ae69b-...,5 行(空会话,见 P2-3) |
| 时间跨度 | 2026-09-10 12:12 → 09-11 14:52(CST) |
| 规模 | 12 turns / 106 steps / 111 tool calls(bash 100、web_search 2、web_fetch 3、write 3、edit 3) |
| 任务 | 单一诉求:获取抖音热门短视频榜单,以及围绕它的能力追问 |
产出物(工作区,agent 手写脚本抓取):
scripts/douyin_hot.py、scripts/douyin_hot_videos.py、scripts/probe_shape.py;
data/douyin_hot_2026-09-10_2148.{md,json}(97 行)、data/douyin_hot_2026-09-11_1447.{md,json}(52 行)、data/douyin_videos_2026-09-10_2154.{md,json}(75 行)。
产出质量本身可用(含话题名/热度/播放量/最高排名/首次出现时间/搜索链接)。问题不在产出,在下述代价、路径与平台缺口。
二、新增 P0
P0-1 · 存量会话不会被迁移到新档位 —— 全平台 10/10 会话仍卡在 workspace-write
档案 33 把新会话默认档位改为 danger-full-access(env 注入已落地:spawn.ts ALLOWED_ENV + orchestrator.ts baseEnv,已核实)。
但权限档位是会话级播种(会话创建时一次性写入 permission/preset / sandbox/mode / approval/policy 三条种子事件,resume 不重播)。实测全平台:
总会话=10 workspace-write=10 danger-full-access=0
即 10 个存量会话(含 admin 自己在 mcntimo / mcnworkspace / maiyamcn 的)全部仍是 workspace-write,只要它们被 resume 并执行 shell,就会撞上「sandbox backend is unusable → 拒绝执行」。guest 这条会话就是已经真实踩中的样本。
- 缺口:平台没有任何 UI/文案提示「老会话需新开一个会话才生效」。用户唯一能得到这条信息的渠道是让 AI 去分析自己的会话日志(本次就是这么发现的)。
- 候选方向:① 会话列表给旧档位会话打标记 + 一键「在新档位继续」;② 门户
enter时对旧档位会话做一次性重播种(改会话数据,需评估);③ 最低成本:产品文案层提示。
P0-2 · 平台零技能投放:用户在 MCN 工作区里「无技能可用」
| 位置 | 实况 |
|---|---|
guest $DSH_HOME/home/skills/ |
0 项 |
admin $DSH_HOME/home/skills/ |
0 项 |
全员共享只读层 /var/lib/dshs/bundled-skills/ |
0 项 |
各工作区 ws/*/ 内容 |
guest 只有 data/ + scripts/(无 SKILL.md、无素材库、无项目结构) |
| agent preset | standard(无业务技能) |
平台已建成技能机制(档案 10 共享只读层 + 档案 11 管理面 API/静态页),但一个技能都没投放。后果在会话里体现得非常直接:
- 用户开的是「MCN短视频创作」工作区,却没有任何 MCN 技能被加载 → agent 只能从零 hand-roll 抖音抓取脚本、反复试错(100 次 bash 中相当一部分是抓取路径试错)。
- 用户第 7 问「为什么需要写代码,不能获取后直接展示内容吗」、第 9 问「有安装网络搜索工具吗 比如 deepseek 搜索」——都是**「本该有技能/数据源,却没投放」**的症状。
- 应投放而未投放:MCN 短视频创作技能(脚本/分镜/账号分析)、RedFox 数据源(日榜/飙升榜/账号诊断,本平台已有 API Key 与 7 赛道口径)、
mcn-data-insight系列技能。
这是本次取证最重的产品结论:不是能力不够,是已有能力没有接到用户面前。
三、修正档案 32 的两条结论
修正 1 · 「沙箱不可用」不是恒定状态,同一会话内会翻转
档案 32 结论为「bwrap 已装但 dsh 后端探测仍判不可用」,并附「实例内嵌套 bwrap 失败」。本次拿到同一会话内前后对比的强证据:
| 时间 | 同一会话内的实测 | bash |
|---|---|---|
| 09-10 12:12–12:13(turn 1) | id / uname / read /etc/passwd / touch /tmp / mounts 全部正常返回 |
✅ 可用 |
| 09-10 13:47:03 与 13:47:28(turn 2) | Error: sandbox mode "workspace-write" ... no sandbox backend is usable on this host; refusing to run the command unconfined. |
❌ 全拒 |
二者之间只隔一次 session/end-seed(13:46:07)→ 会话 resume(13:46:59),无用户侧改动。
另:本次在服务器以 guest uid 模拟实例内做嵌套 bwrap 实测 → NESTED_BWRAP_OK(bubblewrap 0.4.0),与档案 32 的「失败」相反。
→ 结论修订为:「后端可用性」是时序/环境相关,不是确定性不可用(与实例 respawn、平台 bwrap 挂参变化有关,同期平台确实改过实例内挂载:turn 1 $HOME 只读 → 09-11 变可写)。
→ 因为档案 33 已让新会话绕开沙箱,该问题当前不阻塞新会话;但对存量会话仍是硬阻塞(见 P0-1),根因仍未定位。
修正 2 · 沙箱报错丢失根因细节,并把「关掉沙箱」写进了报错文案
@deepseek-ai/dsh-sandbox/lib/index.js:185 的报错支持附加 Runner failure: ${detail}。但本次会话日志中 Runner failure 命中 0 次 —— 模型拿到的只有那句脱敏后的通用文案。
后果链(会话内实际发生):
- 模型无法判断根因 → 只能猜 → 主动发起提权申请:
approval/askedreason = "The sandbox backend is unavailable on this host so every shell command is refused; full access is the only mode that lets me run curl to fetch the Douyin hot list you asked for." - 用户 7 秒内点了「允许一次」(
allowed-once)。 - 6 秒后用户自己又跑了一次
/permission danger-full-access(command/run,source: user)→approval/policy同步变为never。
→ 官方沙箱的 fail-closed 设计是对的,但报错文案("otherwise switch the consumer to danger-full-access")等于手把手教模型申请降级安全档位;再叠加「根因细节丢失」,模型没有别的选择。这与档案 32 的判断一致,本次补上机制性证据。
四、P1
| # | 问题 | 证据(会话内) |
|---|---|---|
| P1-1 | 模型被切到实验模型,且切换事件无法审计 | model/selection → deepseek-v4-flash-vision-exp,reasoningEffort high→max(13:47:50 / 13:47:53,turn 2 中途)。model/selection 事件无 source 字段 → 无法判定是用户切、平台切还是自动切。后续整段会话跑在实验模型上 |
| P1-2 | 智能体把「用户手动提权」误报为「平台能力增强」 | turn 11 用户问「看看现在能力有增强吗」→ agent 结论「能力确实有增强…核心是 bash 从『完全不可用』变成『可用』🟢 最大增强」。实际是 turn 2 用户自己跑了 /permission danger-full-access(command/run source=user,就在同一份日志里) |
| P1-3 | 联网抓取路径不可持续,全靠「绕」 | ① 抖音官方视频接口要签名 → Unsupported path(Janus) / HTTP 200 空 body;② tophub.today → 403 检测到异常访问行为;③ 最终靠伪装 Baiduspider UA 拿 SSR 页再正则扒 HTML(脆弱的爬虫 hack),并退回 GitHub 第三方镜像(时效差 3 小时,agent 自陈「镜像最后更新 18:49,我抓的是官方 21:47」) |
| P1-4 | 平台 web_search 可用但没人知道 | 官方 dsh-web-search-deepseek 已装且实测可用(web/deepseek-search-llm-request 3 次)。但前 8 轮 agent 一直用 curl/python 硬抓,第 9 轮用户主动问「有安装网络搜索工具吗」才开始用。111 次工具调用里 web_search 只有 2 次 |
| P1-5 | 用户感知「卡」的原始证据(补充档案 21) | 用户第 13 问「感觉对话过程卡吗」→ agent 用日志算出:69 步、平均 7.8s/步、中位 5.0s、最慢 81.1s、模型总生成 8m58s;单次 bash 最长 1m19s;turn 3 单轮 4m50s。档案 21 已证服务端全链路不慢(TTFT 1.0–3.5s),本次补上「用户侧体感来自哪 69 步 / 哪 111 次工具调用」的实测数据 —— 卡顿主因是工具调用轮次过多,而轮次过多的直接原因是「技能未投放 + 数据源未接入」(P0-2 / P1-3),不是网络 |
| P1-6 | 会话导出产物用户打不开 | 用户点过 /export(command/done → "Session log download requested.")。格式是 .jsonl.zstd 追加式多帧,zstdDecompressSync 只解第一帧;连 agent 自己都踩了这个坑(流式解压失败: Unknown frame descriptor → 改用魔数 28 B5 4D FD 逐帧解出 1632 帧)。用户拿到的是一个无法阅读的文件 |
| P1-7 | 环境基线太弱,MCN 场景几乎不可用(量化档案 23 的「可优化」项) | agent 自统计 35 处失败/受限,含:Python 3.6.8 + pip 9.0.3(al8 自带)、rg / jq / ffmpeg 缺失、无任何浏览器(chromium/chrome/firefox 全 MISSING,Playwright 落地需 300MB + 11 个系统库缺失且 /usr 只读无 sudo 装不上)、/usr+/etc 只读、无 sudo。档案 23 已把这些列为「可优化」,本次量化了它们实际烧掉的轮次(100 次 bash 中约 1/3 耗在补环境与绕路径) |
| P1-8 | 过度承诺后自我推翻,浪费用户轮次 | agent 先推荐装 Playwright,实测后自我否定:「我之前推荐它,根本没算过这笔账」;并承认「我上一条的说法确实站不住脚」(把第三方镜像数据当成实时数据) |
五、P2
| # | 问题 | 证据 |
|---|---|---|
| P2-1 | 会话列表出现空会话残留 | session-b83ae69b:仅 4 条事件(preset/mode/policy + end-seed),0 个 turn,13:29 创建、21:26 才结束,挂 8 小时 |
| P2-2 | 平台缓存污染用户工作区 | ws/.npm/_cacache、ws/.npm/_logs、ws/.cache/pip/、ws/workspace-scoped-picker-0.1.4.tgz 均落在工作区根部,会出现在门户 #/files 列表里 |
| P2-3 | 工作区根存在平台 bundle .tgz |
ws/workspace-scoped-picker-0.1.4.tgz(09-11 15:00 更新)。档案 35 已修 ws-cleanup 误删,建议确认该 picker 包也在豁免口径内(当前豁免逻辑按「profile 的 file: 引用」动态判定,需回归验证) |
| P2-4 | 工具报错噪音,指向不存在路径 | rg: /opt/dshs: No such file、rg: /var/log: No such file(实例内看不到平台目录,agent 反复试) |
| P2-5 | 文档内部不一致:README 档案清单落后 8 个档案 | docs/README.md 的「档案清单」表止于 28-用户数据清理策略,29–35 全部缺失;而 docs/INDEX.md 是全的(到 04-35)。README 自称「档案清单只在本文件维护」,与该「单一来源约定」已失效(本次只在 INDEX + docs-status 维持,未擅自重排 README) |
六、安全观察(平台挡住了,但值得记录)
guest(普通租户)在会话中主动做了横向/越权探测,全部被平台层挡住:
| 探测动作 | 结果 |
|---|---|
ls /var/lib/dshs/users/ |
Permission denied ✅ |
touch /etc/dsh-probe、touch /usr/local/lib/node_modules/@deepseek-ai/dsh/probe |
Read-only file system ✅ |
ls /root、/home/admin、/home/www、/home/dsh-cce6d1cdb376430480f0 |
不存在 / 不可访问 ✅(bwrap 只暴露自己的用户根) |
sudo |
不可用(/etc/sudo.conf 属主 uid 65534、未 setuid)✅ |
ps -eo user,pid,cmd |
可看到进程列表(bwrap 只 --unshare-pid,未做 PID 视图隔离)⚠️ |
curl http://127.0.0.1:3080/ (门户) |
返回 200,可读到门户首页 HTML ⚠️(仅静态首页,无数据泄漏) |
内网端口扫描 3080/80/443/888/8765/58888/32022 |
可探测,返回状态码与 Server 头 ⚠️ |
env | grep -iE 'api_key|token|secret'、读 $DSH_HOME/.credentials.yaml |
agent 主动做了脱敏打印;扫描会话全文:0 处明文凭据 ✅ |
起本地监听 python3 -m http.server 39777 |
成功(127.0.0.1 绑定 OK)+ pip install / npm 出网均可用 ⚠️(与既有「实例共享宿主网络、出网未全封」结论一致) |
结论:数据面与文件面隔离有效;网络面(内网侧)与审计面是缺口 —— 上述探测没有任何阻断、限速或审计上报。
七、建议行动项(按优先级)
| # | 行动 | 说明 |
|---|---|---|
| 1 | 投放技能到 bundled-skills(P0-2) |
最高性价比:MCN 短视频创作 + mcn-data-insight 系列。技能机制已就绪、watch 即时生效、无需重启 |
| 2 | 存量会话档位提示/迁移(P0-1) | 10/10 会话受害;最低成本先做 UI 标记 +「新开一个会话」文案 |
| 3 | 接 RedFox 数据源到平台(P1-3/P1-4) | 替代「伪装爬虫 UA 扒抖音」这条不可持续路径;已有 API Key 与 7 赛道口径 |
| 4 | 补环境基线(P1-7,延续档案 23) | 最低集:rg / jq / ffmpeg / Python 3.8+;评估基线镜像方案 |
| 5 | 会话导出给可读格式(P1-6) | 导出时转 .md 或解开的 .jsonl |
| 6 | model/selection 补 source 字段(P1-1) |
属官方行为,只做记录与观测;先确认实验模型是否为预期 |
八、取证方法补充(相对档案 32 的新坑)
- 服务器
/tmp下存在package.json("type":"module") → 在/tmp放分析脚本必须用.cjs扩展名,否则require is not defined in ES module scope。(本次踩坑) - 会话日志里
tool/result的报错常被|| echo兜住,表面看不出失败 → 分析时要按「错误特征词」扫全文并统计位置分布,而不是只看退出码。 request/header每条含完整 system prompt + 工具表,体量大(占 2.8MB 相当比例)→ 提取时按type过滤,勿全量 dump。- 分析脚本本地写好 → scp → 远端
node执行最稳(内层引号转义会在ssh '...'里坏掉)。