Files
dsh_ai1net_server/.workbuddy/memory/2026-09-下2.md
T
admin ce8e6ceed9 chore(工作区): 纳入版本控制基线(回收 411 MB 过程产物)
回收 411 MB(470 M → 58.8 M),全部经回收站,可恢复:
- 待清理/(146.2 M,含 relay 分片 128 M 与 42 项过程目录)
- tmp/(32.4 M,按接续棒命名的过程临时区)
- .workbuddy/tmp/(39.5 M)
- 4 份 workbuddy.db 冗余副本(101 M,09-23 事故的坏副本 / 抢救产物)
- tmp/im16/gw/centrifugo 二进制(63.9 M,可重下)+ 缓存残留

入库范围:常驻规则(CODEBUDDY.md / README.md / state.py)、在途接续入口与
接续包、docs/、交付物/、交接单/、归档/、scripts/、.codebuddy/、
.workbuddy/memory/;共 398 件,其中 >60 KB 的 26 件全为文档。

排除(.gitignore):tmp/、待清理/、运行态日志与缓存、*.db 与 DB 备份整目录、
打包二进制(*.tar.gz / *.tgz)、记忆修复前备份。
2026-09-24 07:51:03 +08:00

370 lines
48 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
# 工作日志 · 2026-09(第 3 片)
> ⚠️ **本目录日志已按【月】分片**(2026-09-15 用户定,单文件 ≤50 KB):同月续片 `2026-09.md` / `2026-09-下.md` / `2026-09-下2.md` / `2026-09-下3.md` / `2026-09-下4.md` / `2026-09-下5.md` / `2026-09-下6.md` / `2026-09-下7.md` / `2026-09-下8.md` / `2026-09-下9.md` / `2026-09-下10.md` / `2026-09-下11.md` / `2026-09-下12.md` / `2026-09-下13.md` / `2026-09-下14.md` / `2026-09-下15.md` / `2026-09-下16.md` / `2026-09-下17.md` / `2026-09-下18.md` / `2026-09-下19.md` / `2026-09-下20.md` / `2026-09-下21.md` / `2026-09-下22.md` / `2026-09-下23.md`
> **写入约定**:一律 append 到**当月最后一片**;该片超 50 KB ⇒ 新建 `2026-09-下N.md`;⛔ **不要再按日新建 `2026-09-DD.md`**。
> **覆盖来源**:2026-09-11.md、2026-09-12.md
> **上一片**:`2026-09-下.md` **下一片**:`2026-09-下3.md`
---
## 档案 53:文档库质量审查与精简(22:04-22:25)
**用户问**:所有文档是否清晰简明无歧义?是否需要精简优化?
**方法**:新建**可复跑**检查器 `dsh-server-docs/scripts/docs-audit.py`(只读,9 类判定:①编号冲突 ②标题号≠文件名号 ③`.bak`残留 ④术语/事实漂移 ⑤体量分布 ⑥引用有效性 ⑦疑似重复(含"子集包含"识别)⑧元信息规范 ⑨非md清单;**编号冲突/悬空引用 → 退出码 1**,可接 CI)。
**P0 发现(真问题)**:
1. **`档案 37`/`38` 各被 2 份档案占用**,且其中 2 份**标题号与文件名号不符**(`37-guest会话取证`标题写 36;`38-实例软件安装共享与网络安边界核查`标题写 37)→ 「档案 37/38」**无法唯一指向**,被引用 **18 处**(靠并行会话各自编号造成)。→ **待用户裁定**,建议字母后缀方案(37a/37b/38a/38b + 修正 18 处引用)
2. **README(入口文档)最陈旧**:域名仍写 `dsh.alotbuy.com`、本机路径写成 `D://AI技能//aliyun-work-space//...`、"下一号 = **17**"(实际 53)、"档案 01-26"。
3. **README 与 INDEX 各维护一份全量档案清单 → 已实际漂移**(两边都自称"单一来源",互相矛盾);**INDEX 复制 1200 字待办摘录 → 已与 03-路线图 漂移**(03 有"熔断实测/源码安装",INDEX 无)。
**已修复 9 项(零风险,已同步 90/90 + 推送 `a6043fb`)**:README 域名/路径/下一号/范围纠错 + **新增「阅读约定」5 条**(两套编号体系、单一来源=INDEX、术语以档案 38 为准、域名以 alotbuy 为准、档案头部格式)+ 从 04 表移除根级 06 + 「单一来源」订正;INDEX 待办摘录→指针;`02-运维手册` 附录 C **重排 C.1→C.8**(原顺序 8,7,1,2,3,6,5,4)+ 加「**历史 vs 现行**」分界(正文为 09-08/09 轨迹,冲突一律以附录与 DEPLOY 为准)。
**判定不改(防过度精简)**:历史档案的旧域名(19 份)/旧术语(4 份)**不回改**(保留当时事实);`archive/` 与 `04-调整方案/01~04`(⊂ archive 全文的**子集摘录**,非重复)保留;`02`(336 行)/`06`(276 行) 手册规范类长文不拆。
**待裁定 4 组**(档案 53 §四):① 37/38 编号冲突 ② 02 正文过时章节(六/八/十二/十四/十五)是否加「历史」前缀或迁 archive ③ 19 份档案缺「状态」行 ④ `SKILL.md` 885 行是否拆分。
**经验(值得复用)**:`scp`+`mv` 同步后必须跑 `docs-sync-check.sh`;**写完新档案立刻复跑 `docs-audit.py`**——本轮它当场抓出我新引入的"档案 53 悬空引用"(已在建档后归零)。
## 档案 54:文档信息架构优化(BRIEF 现状卡 + 机读清单)(22:10-22:35)
**用户问**:文档内容和数量是否太多?是否要归档部分便于 AI 快速读到最关键最新信息?或有别的优化方式?
**实测数据(脚本量出,非估算)**:
- 全库 **88 文件 / 747 KB / 492,285 字符 ≈ 34.5 万 tokens**(AI 无法整体读)
- 分类:档案(04-调整方案,54 份)**234,091 字符 47.6%**|根级长期文档(14)~21.7%|archive(4)13.1%|skills(1,SKILL.md)11.9%|scripts+ops(10)5.7%
- **入口集 7 份 = 78,838 字符 ≈ 5.5 万 tokens,其中 `INDEX.md` 独大 23,813 字符**(导航文件比任何档案都大:它兼做场景表+全量表+变化追踪+归档残留)
- **按"被引用次数"分层 54 份档案:hot 23(≥8 次)/ warm 27(1–7)/ cold 仅 4(0 次)**(cold = 04 删除用户功能、06 登录直达会话窗口、31 插件管理页双Tab、43 root 污染属主自愈)
**结论(重要,纠正直觉)**:**不需要大规模归档** —— 仅 4 份零引用,而 19 被引 24 次、16 被引 17 次、17/18 各 16 次仍在被持续引用。真正瓶颈是**缺摘要层 + 缺机读层**。
**已实施(零风险,已同步 94/94 + 推送 `3adb836`)**:
1. **`BRIEF.md` 现状卡**(AI/人首读层)—— 实测 **3,124 字符 / 67 行 ≈ 2.2K tokens**:一句话定位 + 现行事实表(入口/服务/运行时/隔离/可见面/清理阈值/定时/证书/红线,**每行注明单一来源**)+ 待办 top5 + 高频问题→档案映射 + **4 步读取顺序** + 默认不读清单(archive/scripts/ops/bak/poc)
2. **`scripts/docs-manifest.py` → `docs-manifest.json`**(19 KB):每份文档 编号/标题/状态/日期/字符/行数/**被引用次数/tier(hot|warm|cold|doc)** → 支持 `jq` **先筛后读**
3. README 模块一览把 BRIEF 标「先看这份」+ 阅读约定新增第 0 条;INDEX 头部加「首读 BRIEF」并登记 54
4. **收益**:回答"现在是什么状态/该读哪篇"由 **≈5.5 万 tokens → ≈2–3 千**
**待裁定(档案 54 §四)**:A. `INDEX.md` 瘦身(全量表交给 manifest,目标 ≤10K 字符;**另一会话在用 INDEX,建议先对齐**)B. 23 份 hot 档案补 3 行 TL;DR(人工约 30 分钟)C/D. 4 份 cold 移入 archive(收益小,建议顺手做)、README 明确 archive/skills 默认不读。
**工具沉淀**:`scripts/docs-audit.py`(歧义/编号/引用/重复/体量,退出码非 0 即可接 CI)+ `scripts/docs-manifest.py`(机读清单)。两者已入库并在 BRIEF §6/README 引用。
## 档案 54 第二批:TL;DR + INDEX 摘要层 + 默认不读(22:17-22:40)
**用户**:按照你的建议优化。(我给的顺序:先按现状态用 → A 需对齐 → B 可随时 → C/D 不急)
**已执行**:
- **B|23 份 hot 档案各插入 3 行 TL;DR**(`> **TL;DR**|结论 / 关键 / 状态`,紧接头部):覆盖被引最多的 19(24 次)/16(17)/18(17)/20(16)/10(14)/11·37·38(12–13)等。11 份因插入位置紧邻 `## ` 需补空行(已修)。**效果 = 读第一屏即可判断是否读全文**。
- **A(安全版)|INDEX §二 顶部新增「状态摘要(30 秒视图)」**:按状态计数 + 分层(hot/warm/cold)+ 指向 `docs-manifest.json`;大表标题改「全量清单(明细层 · 按需读)」。**刻意不删原文**(逐行描述系另一会话撰写、且其仍在用 INDEX;删除风险 > 收益)。完整版(压缩描述、明细全交 manifest)仍待裁定。
- **D|README 阅读约定加第 5 条"AI 默认不读"**:`archive/`、`scripts/` `ops/`、`*.bak*`、`04-调整方案/poc/`(约定 6 → 7 条)。
- **C|不立项**:4 份 cold 移入 archive/ 收益小(且 31/43 后续可能被引)→ 留待下次大改顺手做。
**数字自洽处理**:TL;DR 自身新增了档案间引用 → 复算分层 hot 24 / warm 26 / cold 5(原 23/27/4);已把 INDEX 摘要与档案 54 的数字改为**实测值 + "复跑 manifest 即刷新"**说明,避免又造一处漂移源(INDEX 摘要里 55 份 = ✅40+🔄4+🔧1+🧪1+未标记 9,已自洽)。
**第二批后读取成本**:BRIEF 2.2K tokens → INDEX 摘要 ≈0.5K → 命中档案 TL;DR ≈0.2K → 需要才读全文(典型问题合计 ≈5K)。
**踩坑(老坑复发,务必记住)**:
1. `git diff --name-only` 在**中文文件名**下会输出带引号的八进制转义 → 必须加 **`-c core.quotepath=false`**,否则按该清单 scp 只同步到 3 个 ASCII 文件;
2. python 写的 `/tmp/xxx` 与 MSYS tar 的 `/tmp` **不是同一目录** → 清单/tar 一律放**工作区内相对路径**(`tar czf x.tgz -T list.txt` 在仓库目录内执行);27 个文件**逐个 scp 会超时被 SIGTERM**,应**单包 tar 传输**。
**提交**:`8912bfc`(文档库,含 27 文件改动)→ 双端 **94/94** 一致 ✅
## 档案 55:guest 最新会话取证(22:33-23:05)
**用户要求**:分析 guest 的最新对话记录,看有哪些问题需要优化。
**取证对象**:guest 主会话 `session-b83ae69b`(09-10 21:29 创建,**5 turn / 2674 事件 / 13 条用户消息**,末事件 09-11 22:18);对照 5 个会话(含 2 个子代理、2 个 09-11 新会话)。
**根因(决定性,对比 6 个会话的 preset)**:
- **权限档位是"会话创建时播种"的**:09-11 创建的新会话 = `danger-full-access` ✅;**09-10 创建的会话 = `workspace-write`**(b83ae69b / bd54c7cc)
- 本机沙箱后端不可用(内核 5.10 无 Landlock、bwrap 在平台合成根内探测失败)→ dsh **fail-closed 拒绝任何 shell** → 实测 **11 次「no sandbox backend is usable」+ 4 次写策略拒绝**
- **同一会话 22:16:29 用户手动切 `danger-full-access` → 22:16:36 立即 `PLAIN-BASH-WORKS`**,此后 0 次沙箱拒绝 ⇒ **平台侧 `DSH_PERMISSION_MODE` 注入正确,唯一缺口是"既有会话不更新"**
- ⚠️ 纠正一个常见误判:**平台没坏**;用户撞墙是因为他在用一天前创建的会话(我此前也以为"老会话"只是感受问题)
**其它真问题**:
1. **平台"零技能"**:`bundled-skills` 与 guest `home/skills` **均为空** → agent 三次撞 `skill "cordis-plugin-development" is unknown`
2. **无能力清单** → agent 在 **16:48 / 18:21 / 22:14 三轮重复现场探测**,每次撞同样 4 类墙(`/etc` 白名单(`/etc/hostname` not found)/ `web_fetch("127.0.0.1")` 被 SSRF 拒 / skill 不存在 / 写工作区外被拒);用户随之**三次追问"能力是否有变化"**(16:58 / 18:20 / 22:14)
3. **审批摩擦**:`approval/asked` **13 次**(`ask` 策略下每次 bash 都要点)→ 切 `never` 后才顺畅
4. 子代理自述"**继承上下文为空**(无先前轮次与工具输出)"+ 子代理 preset 空(继承主会话当时的 workspace-write)→ 与"是否和本地 dsh 一致"相关,待核
**已确认修好(本轮实测)**:`python3` **MISSING(16:50) → Python 3.12.14(18:22)**(档案 42 的共享运行时 17:19 落地);宿主复测 bwrap 合成根 **`SANDBOX-SHELL-OK`**(档案 23 修复仍有效)。
**产出**:
- 档案 `55-guest最新会话取证与优化项.md`(证据表 + 用户体感链条 + 4 项优化建议;**明确不建议自动改写既有会话档位**——安全语义变更需用户知情)
- **4 个可复用取证脚本入库** `scripts/sess-{probe-schema,analyze,classify-tools,list-presets}.mjs`
- 03 路线图新增 3 条待办(**P1 老会话档位对齐(检测+提示)**、**P1 实例能力清单**、P2 技能投放现状);并写入档案 05 三项 PoC-2 待办的**复核结论**(①不建议做 ②已实现=共享 Cookie+CORS ③作废=被档案 39 封 loopback);BRIEF §3 同步
**关键技术点(会话取证必知)**:会话文件是**多帧 zstd 拼接**(本次 1583 帧)→ 必须按 magic `28 b5 2f fd` 切分逐帧解压;首帧 `session` 含 `cwd/createdAt`,`permission/preset` 帧即该会话档位;`tool/call`→`tool/result` 用 `callId/toolCallId` 配对。
**提交**:文档库 `1e7bbe9` → 双端 **99/99** 一致 ✅
## 档案 56:实例助手(我的文件/能力清单/档位提示)+ 文件下载端点(22:45-23:20)
**用户**:① "按照建议处理"(= 做档案 55 §四.1 档位提示 + §四.2 能力清单)② 追加新问题「**AI 生成的文件看不到、下不了,本机地址浏览器打不开**」→ 我诊断为同一类可用性缺口,**三项一起做**。
**③ 的根因(新发现)**:平台**根本没有读取/下载端点** —— `desktop.ts` 只有 `tree/mkdir/upload/create`;且实例内禁 loopback(档案 39)→ AI 给出的 `/var/lib/...` 绝对路径与 `127.0.0.1:<port>` 链接用户都打不开。
**实现(commit `ebe8075`)**:
1. **档位提示**:新增 `src/supervisor/session-preset.ts`(解析会话文件的多帧 zstd → 取**最后一条** `permission/preset`,跨工作区取最近修改的会话)+ `GET /api/dsh/session-permission`;实例页 stale 时顶部提示条(不自动改档位:安全语义变更需用户知情)
2. **能力清单(人机同源)**:新增 `scripts/gen-capabilities.cjs` → `/opt/dsh/state/capabilities.json` + **`bundled-skills/platform-capabilities/SKILL.md`(平台首个共享技能)**;`GET /api/capabilities`;cron 每日 05:05;内容含**网络边界(写明 127.0.0.1 不可达)**与**「文件交付约定」**(给用户用相对路径 + 提示点右下角「我的文件」)
3. **文件下载**:`UserFs.readFile`(Local 实现;k8s **显式抛 unsupported**,不假装支持未验证路径)+ `GET /api/fs/download`;实例页右下 **📁 我的文件** 面板(浏览 + 一键下载)
4. 注入复用档案 50 的 `proxy.ts injectRecovery`,新脚本 `__dshAssist` 与原 `__dshRecover` **并存**
**验证(实测)**:CI **typecheck+build+42 单测(新增 4 项 readFile 安全测试)通过**;端到端:`session-permission` → `stale=true`;`capabilities` → 200(工具 10 项、python3=3.12.14);`fs/download` → 200 text/markdown;**越界 `../../etc/passwd` → 400 bad_path**;目录 → `not_a_file`;实例首页 35KB 含 `__dshAssist` 与 `__dshRecover`。
**关键技术细节(复用价值高)**:
- 会话文件是**多帧 zstd 拼接** → 按 magic `28 b5 2f fd` 切分逐帧解压(`session-preset.ts` 与 docs 的 `sess-*.mjs` 同一套路)
- **不要用 undici/fetch 覆盖 `Host` 头**(禁用头,会被静默丢弃)→ 验证子域路由必须用 `curl -H 'Host: ...'`
- 实例首页取 HTML:`?token=` 会 **303 → `/` 并下发 `dsh-auth-*`**,必须 `curl -L -c/-b jar` 跟随;另需 `Accept-Encoding: identity`,否则 gzip 会导致注入被跳过(档案 50 老坑)
- 铸造临时 session 做端到端验证:`sha256(token)` 入 `sessions(token_hash,user_id,created_at,expires_at,ip,user_agent)`,用完即删(本轮已用过 3 次,均清理)
**提交**:代码 `ebe8075`(推送 `3b82d31..ebe8075`);文档 `43e4ae9`(`1e7bbe9..43e4ae9`)→ 双端 **100/100** 一致。
**待用户**:硬刷新会话页即可看到右下角两个入口与(如触发)档位提示条;门户 `#/files` 的下载按钮列为 P3。
## 核查:每用户实例的资源配额(23:44-23:58)
用户问「每个用户进程资源给的多少」。纯只读取证(`systemctl show` + 源码 + `free/df`),**未改任何文件**。
**单实例 cgroup 配额**(来自 `src/supervisor/orchestrator.ts#spawnAsUser` 的 `systemd-run --scope`,服务器实测生效值):
| 项 | 值 | 证据 |
|---|---|---|
| MemoryMax | **512 MiB**(536870912)| `systemctl show dsh-*.scope -p MemoryMax` |
| CPUQuota | **150%**(1.5 核;CPUQuotaPerSecUSec=1.500000s)| 同上 |
| TasksMax | **128** | 同上 |
| 磁盘配额 | **无**(ext4 无 prjquota、fstab 无 quota、`quotaon /` 未启用)| `mount` / `df` / `fstab` |
| 磁盘 IO / DevicePolicy | 未设(IOWeight=none、DevicePolicy=auto)| 同上 |
| 全局默认 | MemoryMax=infinity、DefaultTasksMax=11716、DefaultCPUAccounting=no → **限额只来自 scope 参数** | `systemctl show -p Default*` |
- **宿主**:2 vCPU / 1870 MiB RAM / 1024 MiB swap / 40 GiB ext4(用 9.8G、可用 28G);平台编排器自身 133 MiB
- `ISOLATION_MODE=account` 已确认;每实例 = `bwrap`(合成根)+ `setpriv`(独立 uid)+ 独立 scope;`role` 为 `main`/`watchdog` 时**各自一个 scope = 各自 512 MiB**(不共享)
- **当前 2 个实例**:212 MiB(Tasks 13)/ 329 MiB(Tasks 13);`available` 785 MiB
- **并发上限**:内存 1870/512 ≈ 3.6 → **再起 1 个余 273 MiB,第 4 个必 OOM**;**CPU 是更早瓶颈**(150%×2 = 300% > 200%,2 个活跃实例即占满 2 核)
- **内核 OOM 近 30 天 = 0 次**(日志里 8 条命中是 `crash-loop-circuit-open` 熔断与漏扫请求,非内存问题)
**新发现(文档未记载,值得归档)**:宿主 `node -e` 实测 **`heap_size_limit = 960 MiB`**,而 cgroup 只有 512 MiB → **V8 按物理内存(1871 MiB)推算堆上限,感知不到 cgroup 硬限** → 实例内 dsh 不会在 512 MiB 附近提前 GC,会一路涨到**内核 OOM kill(SIGKILL,无优雅退出、无日志)**。建议给实例注入 `NODE_OPTIONS=--max-old-space-size=384` 一类参数(**未实施,待裁定**)。
其余参数均已记载于 档案 16 / 38 / 41、`BRIEF.md`、`01-规划与架构.md`、`DEPLOY-本部署.md`。
## 档案 57:设置面板「用户管理」入口(改名/移位/全员安装)(23:44-00:05)
**用户要求**:把设置里的「平台管理」改名「用户管理」,放到「功能插件」**下面**;**普通用户也要有该入口,里面只有退出按钮**。
**根因(关键)**:提供该分区的 `@dsh-local/portal-entry` **只装在 admin 的 profile**(`dsh.profile.bundles`)→ 普通用户设置面板里**根本没有这个分区** → "没入口就不能退出登录"。故需求 3 不是改显隐条件能解决的,必须同时解决**插件分发**。「功能插件」名称无需改(`business-plugins` 的 label 自 v0.2.0 起即是,档案 38 已做术语统一)。
**改动**:
1. **插件 v0.5.1**(源码在文档库 `04-调整方案/poc/portal-entry/`):section `id: platform→user-management`、`label: 平台管理→用户管理`、**`order: 100→102`**(功能插件=101;官方 models=10 / plugins=15,故 102 排最后);内容按角色分支(admin=门户地址+「打开管理台」+「退出登录」,其余=**仅「退出登录」**),角色取自门户 **`GET /api/auth/me`**(跨子域 CORS 实测 200 + 带 `role`),**探测失败 fail-closed 降级为非管理员**。保持"只导出 apply+inject"(红线 R3)与配色硬编码(v0.4.3 结论:暗色设置面板里 `var()` fallback 永不生效)。
2. **新装器 `scripts/ensure-portal-entry.cjs`**:幂等(已装版本 + dep spec + 是否在 bundles 三判据);姿势沿用 picker 修复版(`.dsh-stage` 暂存 + `chmod 444` + `setpriv` + workspace 加 `-w`);**store 位置自适应**(见坑 1)。
3. 接入 `/usr/local/bin/provision-new-users.sh`(**并首次把该脚本入库** `scripts/provision-new-users.sh`)+ `/etc/cron.d/dsh-maintenance` 加 `04:15` 每日兜底。
4. **未改 TS → 无需 build、无需重启平台**(新 bundle 只在实例重启后加载)。
**三个坑(都值得记)**:
- **`ERR_PNPM_UNEXPECTED_STORE`**:存量 `node_modules` 由 **ws 内旧 store** 链接(`<userRoot>/ws/.local/share/pnpm/store/v3`,`HOME=<ws>` 时代的产物,`.modules.yaml` 记着它),脚本若用 `<home>/.pnpm-store` 会被 pnpm 直接拒绝(需 `pnpm install` 重建全量依赖)。→ 装器改为**读 `.modules.yaml` 的 storeDir 并沿用**,只有全新 profile 才用 `<home>/.pnpm-store`。⚠️ **`ensure-workspace-picker.cjs` 仍有同一隐患**(无条件用 home store)→ **下次 picker 升级必失败**,已列入档案 57 §五.1。
- **首版 tgz 漏 `lib/index.js`** → 全实例 `ERR_MODULE_NOT_FOUND ... /portal-entry/lib/index.js` → 崩溃循环 → 熔断。坏包已隔离 `/opt/dsh/backups/portal-entry-0.5.0-BAD-missing-index.tgz`。教训:构建包一律 `cp -r <源>/. <构建>/` 整目录复制,**打包后强制 `diff` 清单校验**。
- **pnpm 同版本缓存**:同名同版本 tgz 即使内容变了也复用旧包 → 修复必须**升版本号**(0.5.0→0.5.1)。
**验证**:两用户 `✓ v0.5.1(bundles=5,含本插件=true)`;实例重启后正常打印 launch token;首页 client bundle 清单含 `@dsh-local/portal-entry/client.js`(新 `rev=8989…`);`/api/auth/me` 跨子域 200 + `allow-credentials`;DB `admin=admin` / `guest=active`;`provision-new-users.sh` 跑通且幂等 skip。**未做浏览器渲染验证**(本机无 Chromium,装它 ~500MB 成本不成比例)→ 待用户硬刷新确认位置与按钮。
**顺带清理**:24 个 `.bak-*` 堆积 → 移入 `/opt/dsh/backups/repo-bak-20260912/`;确认 **`grep -c $'\r'` 在 MSYS 下是假阳性**(报"36 行含 CR"而两端 md5 完全相同)→ 判行尾要用 `od -c` / `file`。
**产出**:档案 `04-调整方案/57-设置面板用户管理入口与全员安装.md` + INDEX 登记(双端 md5 一致;`docs-audit.py` 复跑无新增问题)。**未提交**(用户未要求 commit/push)。
## 规划/执行分离:建立「交接单」机制 + 首批两单(23:55-00:30)
**用户口径**:「执行任务时间太久 → 这个会话做任务规划,另一个会话执行」。经确认四项参数:**①本会话定位=纯规划**(不 ssh、不改码、不重启)**②交接载体=文档库文件**(`dsh-server-docs/交接单/`)**③首批任务=档案 16 阶段 3/4 + 文档库收尾**(实例内存治理与 MCN 改造不在本批)**④身份档案按默认落定**(我叫「小 D」,用户记作 maogeigei)。
**产出(本地写入,纯规划会话不 scp、不 commit)**:
- `交接单/README.md`(1,867 字符)—— 单子必填 8 段(目标/只读前置/范围/决策点/步骤/验收/回滚/回报格式)+ **执行会话硬要求 7 条** + 规划会话边界 3 条 + 「为什么这样分」(附今日两次并行踩坑证据)
- `交接单/T01-档案16阶段3-4-实例内我的技能.md`(5,448 字符)—— 实例内「我的技能」section 的完整施工单
- `交接单/T02-文档库收尾-编号消歧与INDEX瘦身.md`(7,150 字符)
- 登记落位:`README 模块一览`加「交接单/」一行;`INDEX §六` 加第 8 条落位规则
**规划阶段抓到的两个关键点(执行会话会踩的坑)**:
1. **T01**:档案 16 §六 阶段 4 原文写的验收口径是「按 uid `--dump-config` 复核」,但该口径**已被档案 18 v3 证伪**(`--dump-config` 不反映 bundle/profile patch 层)→ 单子里改为「**加载标记(journald)+ 实例页 UI 实测**」,并顺带把 B5(给两个 bundle 加加载标记)纳入本单"顺手做"。
2. **T02**:字母后缀消歧(37a/37b/38a/38b)**必须同时改两个脚本的 6 处正则** —— 否则 `37a-…` 不匹配 `^(\d+)-`,`docs-manifest.py` 会把 4 份档案判成 `tier=doc`/`num=null`,档案份数与 hot/warm 分层**全部失真**;另需去掉引用正则的 `\b`(否则「档案 37a」匹配不到),并把 `num_map` 键由 int 改字符串。
**规划会话实测基线(回填进单子,替换档案 53/54 的估算)**:
- `INDEX.md` = **25,581 字符 / 181 行**(档案 54 记的 23,813/169 是第二批前的值)
- 旧编号引用 = **25 处 / 12 个文件**(档案 53 估 18 处偏少);`docs-audit.py` 当前:总 103 文件(md 74 / 其他 29)、37 与 38 各 2 份、2 份标题号不符、**无悬空引用**
- 交接单自身已过 audit:【6】无悬空(**注意**:T02 改名后,残留的"裸旧号"会变成悬空引用,含归档后的单子自身 —— 已写入单子)
**待用户**:开 T01 前确认一句「扩展 business-plugins 注册第二个 section(建议 A / 复用现有铺开+探活链路)」还是「新建 `@dsh-local/my-skills`」。
# 2026-09-12 工作日志
## 交接单目录:补「待执行清单」+ 冲突域判定(00:05)
**用户问**:「待执行的任务是不是应该专门找个文件夹存放」。
**答复与落地**(延续 2026-09-11 的规划/执行分离):
- 确认已有专用位置:**`dsh-server-docs/交接单/`**(待执行)+ **`archive/交接单-已完成/`**(完成后 `git mv` 过去,首次完成时创建)。放文档库内的理由:执行会话同机可读、随文档库一起 scp 到 `/opt/dsh/docs`、进 git 历史留痕。
- `交接单/README.md` 新增 **§一 待执行清单**(唯一来源 = 本表):T01 / T02 的状态、一句话、**冲突域**、依赖;原 §一~§四 顺延为 §二~§五。文件 1,867 → **2,806 字符**。
- **新判定(重要)**:`T01` 与 `T02` **冲突域重叠**(都要改 `README.md` / `INDEX.md` / `03-路线图与待办.md`)→ 按 `skills/dsh-change-workflow`「多任务并行调度协议」,**两单必须串行、不可同时开两个执行会话**;建议顺序 = **先 T02(纯文档零风险)→ 再 T01(动码 + 重启实例)**。
- 补**防双源漂移分工**:`03-路线图` 管「还没规划的事」,`交接单/README §一` 管「已规划待执行的事」;同一事项两边都出现时**状态以本表为准**,路线图那行只留指针。
**自检**:`docs-audit.py` → 【6】**无悬空引用**(exit=1 仍来自既有的 37/38 编号冲突,属 T02 范围)。交接单三件:README 2,806 / T01 5,448 / T02 7,428 字符。
**未做**:未 scp、未 commit(延续纯规划边界;服务器镜像落后一格,由执行会话收尾时一并同步)。
## 交接单同步到服务器:核验完成 + T02 基线刷新(07:15-07:25)
**用户要求**:「服务器上没有 `/opt/dsh/docs/交接单`,这个需要同步到服务器」(= 明确要求,本次打破"纯规划不 scp"的自我边界,仅做被要求的这一件事)。
**核查发现(重要)**:到服务器时 **`/opt/dsh/docs/交接单/` 已存在,3 个文件已在位且 mtime = 07:16:41** —— 即**另一个并行会话刚同步过**(就在用户发消息前后)。→ **没有重复覆盖**,改为**逐文件 md5 核验**:三份全部逐字一致(`3f2496e1…` / `18461408…` / `458430a1…`)。
**顺手抓到的两件事**:
1. **T02 基线已过期**:并行会话新增档案 **57-60**(57 设置面板用户管理入口 / **58 实例内存优化与配额下调** / 59 重连反馈加载动画 / 60 分区改名功能管理),均已登记进 INDEX → 复测:INDEX **25,581 → 28,805 字符**(181 → 185 行)、旧编号引用 **25 → 27 处 / 13 文件**、audit 总文件 **103 → 107**(md 78)。已把 T02 内 5 处旧数字刷新,并加「**基线刷新记录**」块 + 「开跑前必须重新取基线,勿沿用旧数字」。
2. **再次印证冲突域**:T01/T02 与并行通道都改 `INDEX.md` / `README.md` / `03-路线图` → **必须串行**(已写进 T02)。
**推送与验收**:只重传 `交接单/T02-…md` 一个文件(scp 绝对本地路径)→ 服务器 md5 与新本机一致 `6bdfd884…`;权限沿用既有(T01/T02 = **600**,README = 644,目录 755)。
`bash scripts/docs-sync-check.sh` → **一致 107 / 差异 0 / 双端一致 ✅**;`docs-audit.py` → **无悬空引用**(exit 1 仍仅来自 37/38 编号冲突,属 T02 范围)。
**待用户/后续**:① 交接单目录权限是否统一到「归档口径」(目录 700 + 三份全 600,与 `04-调整方案/` 一致)—— 未擅自改;② 未 commit/push(按红线)。
## 规划 T03(7 插件整合)+ 并发冲突处置(08:20-08:55)
**用户**:① 「规划 `D:\dshworkspace\plugin_package` 整合成一个插件,可打包后由 admin 整体上传、用户启用即可用」(我先误看了 `dsh-plugin-dev`,用户纠正为 `plugin_package`);② 「两个会话同时执行造成冲突,如何解决比较好」。
### ① T03 单子已产出(`交接单/T03-plugin_package整合为单插件并投放.md`,9,969 字符)
**普查结论(7 包 = 1 宿主壳 + 6 功能页)**:`dsh-plugin-mcn` 是宿主(client 3045 + host 3095 + 9 模块;注册 **25+ 条 `/mcn/api/*` 路由**、`inject=["slots","sessions"]`、`sidebar.footer.action` 入口;提供全局扩展点 **`window.__mcnEntries`**(功能页注册表)与 **`window.__mcnNav`**(`open/openView/back`));douyin 三件 + mcn-schedule + social-workbench + voxemw **全靠往 `__mcnEntries` 注册**,其中 douyin 三件 host 面**只有 9 行空壳**(注释原文"数据复用 mcn 的 `/mcn/api/*`")→ **拆开逐个启用本身就违背设计**。mcn **无 `defineTool`/`tools.register`**(不给 agent 注册工具)。**7 包全无 scripts/build/tgz** → 打包链路要新建。
**P0 清单(6 项,实测定位)**:① `homedir()/.dsh` 硬编码(`mcn/config.js:6,28,68`、`mcn/index.js` 14 处、`mcn-schedule/index.js:11,27,84`)→ 平台须用 `$DSH_HOME`;② 技能路径硬编码 `~/.dsh/skills/mcn-short-video/subskills/*`(12+ 处)→ 只报技能名;③ `spawn("powershell")`(`mcn/index.js:919`)Windows-only → Linux 化;④ MCP `spawn(npx -y myai-mcp)` 每次拉包 → 预装;⑤ `lib/*.bak-20260906` ×2 → 打包剔除;⑥ 整包需 dry-run 上传扫描(P0 须为 0)。
**头号风险 = 新旧包并存 → 重复注册/`duplicate loader entry id` 崩溃循环**(档案 25 前例)→ 写全**四道防线**(全新 loader id / 候选池下架旧包 / 先禁旧再启新 / host 面检测旧 id 拒绝启动)。**决策点 5 个**待用户拍板(social-workbench 实测是 **Windows 本地服务**(`EASEL_DIR`、`.venv/Scripts/easel.exe`、探 `127.0.0.1:7860`)→ 平台必然不可用,建议不进包)。
### ② T02 被并行执行会话完成(我转为核验)
- 4 文件已 `git mv` → 37a/37b/38a/38b;脚本正则**实改 8 处**(比单子列的 6 处多,因键类型连带);**INDEX 28,809 → 7,468 字符**;单子已归档 `archive/交接单-已完成/`。
- **我补修**:归档副本里残留 **3 处**「`档案 3[78]`」示例文本(新正则把 `档案 3[78]` 匹配成裸旧号 `3` → 永久悬空;执行会话修了 2 处、漏了 3 处)→ 改为不带 `档案` 前缀的写法。**结果:`docs-audit.py` 首次 `结论:无 P0 级问题`、退出码 0**;双端 **108/108 一致 ✅**。
- ⚠️ **我犯的错并已还原**:用截断到 200 字符的 `grep` 输出当 `old_string` 去 Edit 长行 → **误替换掉执行会话的记录行首**;已按原文精确还原(`Read` 核对)。**教训:长行 Edit 前必须先用 Read 取全文,禁止用截断内容做锚点。**
### ③ 并发冲突:根因与规则(用户提问的直接答复)
**三次实证**:a) T02 基线数字(INDEX 25,581)被并行新增的档案 57-60 打穿;b) 我把**已被对方归档移走**的 `T02` 又推回服务器("幽灵文件",靠对方同步才清);c) `交接单/README.md` 与 `T01` 均被两会话先后编辑。
**根因**:**「谁在占用」只写在文档里,没有机械信号**;且本库**长期不 commit** → 没有 pull/merge 式冲突检测。
**已落进 `交接单/README.md`**(执行会话加了 §三 第 0 条:mtime/Edit 失败即冲突/改完 commit;我补两块):① **占用声明** —— 「占用者 / 开始」两列 + `mkdir 交接单/.doing-<单号>` 原子占位(存在=有人在做,停手);② **§三 ⑤⑥** —— 推前必复跑 sync-check,报「仅本地」却不是我的改动 = **停手**(幽灵文件);只推自己本次改的文件。
## 评审「三层方案」+ 落地 `scripts/handoff-guard.sh`(08:50-09:15)
**用户**:附上一份分析(根因=并行写无互斥;① §三 第 0 条 ② 文件归属分工表 ③ git commit 常态化;一条经验=用 Edit 不用 Write),问「是否最佳,是否还有更好的方式」。
**我的评审(3 处修正 + 3 个缺口)**
- 修正①:② 分工表**没做到"每文件单一写者"**(`交接单/README.md` 仍是双写)→ 原则应重画为「**每个文件只有一个写者**」,共享文件只允许**单行 Edit** 改自己那一行。
- 修正②:③「改完立即 commit」漏了限定 → **必须只 add 自己改的文件**(禁 `git add -A`,与既有红线一致)。实测本库此刻有 **26 个别人的未提交文件**,`-A` 会把它们一起提交 = 等同"顺手重放别人的文件"。
- 修正③:**锁防"同时",commit 防"丢失/可回溯"** —— commit 拦不住并发,不能替代锁;提案把 ③ 当主线,主线其实是 lock。
- 缺口④:**"迟到的推送"**(把已被别人归档/移走的文件又推回服务器 —— 我今天亲身犯过)提案的三层都拦不住;**唯一有效判据 = 推前复跑对账 + 看「仅本地」清单里有没有不在你推送清单里的文件**。
- 缺口⑤(最大):**服务器侧完全无锁** —— 重启/drain/改 env/铺插件/改 nginx 都是共享资源,**影响在线用户**(档案 58/59 已两次引发报障),而 `systemctl` 不会告诉你 10 分钟前谁重启过 → 只能靠显式锁。已写成 `交接单/README.md §六`(提案,待用户拍板)。
- 缺口⑥:**会话生命周期** —— 一个会话干一整天会把过期事实带进判断(我今天就拿着 INDEX=25,581 的旧断言)→ 单子完成即关会话。
**已落地:`scripts/handoff-guard.sh`(只读预检,110 行)**
- `--claim T03 "exec-session-A"` / `--release T03`:锁的占位与释放(`mkdir` 原子;已存在则**报出占用者**并退出码 1)。
- 开工检查:`MINE="<文件...>" bash scripts/handoff-guard.sh T03`;推送前:再加 `PUSH=1`。
- **关键设计(测试中修正两次)**:**mtime 只作提示、不作判定**(分不清谁改的);**硬判定只有两处** —— ① 别人的占用锁;④ **「仅本地(待推送)」里含未声明文件**(= 幽灵文件信号)。② 越界改动只提示(本库长期脏,作判定就永远红)。
- **四场景实测通过**:重复占位 → 拒绝并报占用者(exit 1)|新占位+释放 ✓|锁冲突 → exit 1 并列出原因|**幽灵探针文件(`交接单/_guard-test.md`)→ exit 1 并点名**|清理后 `PUSH=1` → **放行(双端 110/110 一致)**。测试探针已删,无残留锁。
**同步**:`交接单/README.md` + `scripts/handoff-guard.sh` 双端 md5 一致;`docs-audit.py` → **无 P0 级问题(exit 0)**;双端 **110/110 一致**。
**期间观察**:并行会话又新增 **档案 61**(插件管理页官方插件列表加高与底部留白)→ 该库处于**活跃写入**中,任何写操作前都该跑 guard。
## 待办盘点(09:05,只读核查)
**两处文档漂移(建议由执行会话顺手修)**:
1. **`BRIEF.md:20` 仍写 `scope(512M / 150% / TasksMax 128)`,而档案 58 已把 `MemoryMax` 512 → 384 MiB**(实测 `dsh-114801-*.scope MemoryMax=384 MiB`)→ BRIEF 是"AI/人首读层",这处漂移会直接误导判断;另需补 `NODE_OPTIONS=--max-old-space-size=256` 与 `NODE_COMPILE_CACHE`。
2. **`03-路线图与待办.md` 头部仍是 09-11 21:20 合并版,档案 57-61 完全未登记**;BRIEF §3 待办仍是旧 6 条 → **待办层滞后**(与 T02 修的是同一类问题)。
**当前待办口径(本次答复依据)**:交接单 T01 / T03 待执行(各带决策点,冲突域重叠须串行);`03-路线图 §二`:平台技能投放(P2)/ 门户 `#/files` 下载(P3)/ MCN 平台化(暂缓)/ Cookie 域(暂缓)/ 档案 21 后续(暂缓)/ dsh 升级回归 + 会话 GC(触发式)/ B5 加载标记(顺手做);**待用户拍板**:本机 commit 授权、服务器侧第二把锁(§六)、交接单目录权限统一。
## A/B/C/D 决定落地 + T04 建档 + T03 技能随包设计(09:20-09:50)
**用户角色再确认**:「**你是方案规划 不是执行**」→ 我把 A/B/C/D 全部**落成规划产物**(决定写进单子与约定),落地交执行会话。同时用户给出一条**推翻我建议的新要求**:
> **业务技能要打包进插件里一起安装使用,不要分开管理。**
### T03 重设计:技能随插件包投放(§4.1 新增,约 60 行)
- **可行性依据**:技能发现位在**实例内**(`dsh discoverRoot` 只扫 `$DSH_HOME/skills`;档案 41 §B 实测 rename 即时生效),而插件 host 面**就跑在实例内、以用户 uid 运行** → 插件能自己把技能装到位,不需要平台技能管理面。
- **机制**:包内 `skills/` + `.manifest.json`(名称/版本/文件数/sha256);host 面启动时 `ensureSkills()`:读 manifest → 与 `$DSH_HOME/skills/<name>/.installed.json` 比版本 → **幂等**(一致则跳过)→ 版本不同**全量替换**(档案 11 同语义)→ **不覆盖用户自建同名技能**(跳过+日志+UI 提示)→ 写加载标记。**备选软链方案**(升插件即升技能、零对账)但须先实测 dsh 扫描是否认软链。
- **技能取舍(实测 `mcn-short-video` = 11 MB / 711 文件,其中 9.7 MB 在 `subskills/`)**:✅ 投主技能 + 4 个业务子技能(≈1.5–2 MB);❌ 不投 `browser-harness`(平台无浏览器,档案 38a 实测装不起来)、`参考skills/` 上游全文、`nuwa-skill-main/examples/`、**970 KB 客户样例长图**(标了"若你要留,回一句即改");⚠️ `scripts/mcp-config.json` **实测含 `MYAI_FEISHU_APP_ID=cli_a84d0a47f93e1013` + 私域 URL `maiya-trans.youmanvideo.com`** → 新增 P0#7「技能原文凭据/情报审查」。
- **互斥**:走插件内投后**不得再投平台共享技能层**(同名 rank 抢)。
- 决策 1–5 全部记为**用户 2026-09-12 拍板**;`T01` 决策点 1(扩展现有 business-plugins)**已由并行会话按用户原话写好**(我这边 Edit 失败=检测到它改过,转为只读核对)。
### T04 新建:并发治理落地(A 组)
`交接单/T04-并发治理落地-commit常态化与服务器侧锁.md`:① 文档库 git **基线提交**(⚠️ 需"静态窗口",且**逐条 add、禁 `-A`、不 push**)+ 此后只提自己文件;② 服务器侧第二把锁 `/opt/dsh/state/.op-lock/`(`scripts/op-lock.sh` claim/release/status,接入 guard);③ 交接单目录 700/600。**建议顺序改为 T04 → T03 → T01**(T04 越早做未提交内容越少越干净)。
### 本轮又踩同一个坑(第 3 次):字面量 `档案`+字符类
`docs-audit.py` 的引用正则会把我写的示例 `档案`+`3[78]`/`档案`+`6[01]` 读成**裸旧号**(`3`/`6`)→ 悬空、退出码非 0。**连"警告这条坑的说明本身"都踩了一次**。已写入 `交接单/README §二` 的「写引用/数字两个坑」,并改为不自伤的写法(`档案` + `3[78]` 分离写)。
**产物**:`T03`(更新,加入 §4.1 技能随包)、`T04`(新建)、`交接单/README`(§一 加 T04 行 + 顺序改为 T04→T03→T01 + §二 两个坑)。`docs-audit.py` **无 P0 级问题**;三份文件双端 md5 一致。
## 技能裁剪:从"看着像资料"改为「引用驱动」(09:30-09:45)
**用户**:「参考资料是不需要」→ 我照办前先做了引用扫描,结果**推翻了"参考资料"这个判断**:三类"像资料"的其实是被引用的**功能件**。
| 块 | 体积 | 引用实测 | 定稿 |
|---|---|---|---|
| `mcn-video-prompt/参考skills/`(上游技能全文) | 2.0 MB | **0 引用** | ❌ 剔 ✓(用户所指"参考资料"正是这块) |
| `browser-harness/` | 2.3 MB | 多篇 feature 要求**"浏览器优先"**(`01_获取账号信息.md:12`、`02_获取视频.md:10`) | ❌ 剔**目录**,但**必须同步改文档**(写"平台无浏览器 → 改走 X"),否则死引用 + agent 反复撞墙(档案 55 现象) |
| `nuwa-skill-main/` **主体**(去 examples) | **104 KB / 11 文件** | **被引为"主方法论"**(`03_提炼账号设定.md:81`、`人设卡生成方法.md:186`) | ✅ **保留** |
| `nuwa-skill-main/examples/` | ≈2.4 MB | 引了 `examples/mrbeast-perspective/`,**未引 trump** | ❌ 只剔 `trump-perspective/`;要连 mrbeast 剔就须同改那两行引用 |
| `references/样例/`(svg 19 KB + 长图 **994 KB**) | 992 KB | **`06_生成账号设定卡片.md:67` 写"动手前必须先读"** | ✅ **保留**(**用户说的"参考资料不需要"不覆盖它** —— 它是功能件) |
**裁剪后:11 MB → ≈3 MB**。新增**机械校验**(防"剔完留死引用"):`grep -rIn -E "参考skills|browser-harness|nuwa-skill-main/examples/trump|参考_旧梦留声机" <包>/skills/ | grep -v -E "已移除|无浏览器|不再使用"` → **期望只剩说明行**。已写入 T03 §4.1 + §6.1 验证 + §八 验收 N/O 三项。
**方法论沉淀(可复用)**:**删任何东西之前先扫引用** —— "看起来像参考资料"与"实际被引用"是两件事;这次若按字面执行,会同时打断「生成账号设定卡」与「人设卡生成方法论」两条功能链。
## 技能完整性核查:6 个技能名 → 5 个找到、1 个缺失(09:28-09:35)
**用户问**:「skill 是否和插件整合到一起,找到对应 skill 了吗」→ 做了一次**插件↔技能引用完整性**核查(只读)。
**插件侧引用枚举(7 个包全扫)**:prompt 里出现的 `skills/xxx` 形态共 **6 个技能名**:
| 技能名 | 期望形态 | 源是否找到 |
|---|---|---|
| `mcn-short-video` | 主技能(独立技能目录) | ✅ `C:\Users\Administrator\.dsh\skills\mcn-short-video`(11 MB / 711 文件) |
| `mcn-dou-analysis` / `mcn-script-review` / `mcn-video-prompt` / `mcn-data-insight` | 主技能内 `subskills/` | ✅ 4 个都在(随主技能目录一并投放,**不需要单独投**) |
| **`douyin-top-account`** | 期望在 `subskills/` | ❌ **全盘未找到**:`~/.dsh/skills/mcn-short-video/subskills/` 下只有 5 个(browser-harness + 上述 4 个),`D:\dshworkspace`/`D:\github`/`D:\AI技能` 亦无 |
**引用位置(活的,非注释)**:`mcn/lib/index.js:3085`、`3086`(账号日榜/周报抓取流程,`--period day`)、`mcn/lib/workshop.js:9,22`(榜单落盘口径 + 赛道白名单同源)。
**含义**:**即便技能随包投放,插件的「榜单更新」能力仍会失败**(agent 找不到 `subskills/douyin-top-account`)。→ 已立为 **T03 §五#8**(P0)+ 写进 §六 步骤 2「未确认前不要打包」,三个选项:① 补进包(推荐)② 已废弃 → 改写 `index.js:3085-3086` 与 `workshop.js` 的 prompt 去掉榜单任务 ③ 走 MCP 兜底。
**低优先待核**:技能 `变更日志.md` 提到 `lieflat-charts` 子技能,磁盘上同样不存在 —— 但该文件属**历史记录**,不构成活引用(若要严格,可在打包前顺手核一次)。
## ⚠️ 更正:`douyin-top-account` 并未缺失 —— 是我搜索深度不够(09:35-09:45)
**用户指出**技能完整、在 `C:\Users\Administrator\.dsh\skills\mcn-short-video` → 复核确认**用户对**:
`douyin-top-account` 真实路径 = `subskills/mcn-data-insight/subskills/douyin-top-account/`(含 SKILL.md / README.md / README.en.md)。
**我上一轮的 `find -name "*douyin-top*" -maxdepth 5`(相对 `.dsh`)差一层** → 误判"缺失"。**教训:技能树是多层的,核层级不能用浅 `find`**(已写进 T03 §4.1 提示 + §6.1 验证)。
**真实技能树(实测)**:`mcn-short-video` = **11 MB / 711 文件 / 36 个 `SKILL.md`**
- 主技能 1(`SKILL.md` + `references/` + `references-add/` + `scripts/`)
- 一级子技能 5:`mcn-dou-analysis`(内含 `subskills/nuwa-skill-main`)、`mcn-script-review`、`mcn-video-prompt`、`mcn-data-insight`、`browser-harness`
- **`mcn-data-insight`(869 KB)本身是"技能集索引",下挂 12 个二级子技能**(全部带 SKILL.md):`douyin-top-account` 140K / `douyin-account-diagnosis` 136K / `douyin-rise-ranking` 76K / `douyin-hot-trend` 72K / `douyin-ai-feed` / `douyin-prohibited-word` / `playlet-douyin-feed` / `douyin-weekly-surge` / `douyin-works-crawler` / `douyin-content-surge` / `douyin-daily-hot` / `douyin-search`
- ⇒ 插件 prompt 写 `subskills/douyin-top-account` **少一层**(真路径多 `mcn-data-insight/`)→ 并入 P0#2「只报技能名」一起修(**不是**缺文件)。
- 裁剪后体积更正:11 MB → **≈4.3 MB**(剔 `参考skills` 2.0 + `browser-harness` 2.3 + `nuwa/examples` 2.4)。
## 技能落地方式与撞名规则(T03 §4.2 新增,用户提问定稿)
**Q1 装到 `$DSH_HOME/skills/` 还是"就在插件内目录使用"?**
关键事实:**dsh 技能扫描根是固定集合**(`~/.dsh/skills` rank300 / `.dsh/skills` rank100 / `.agents/skills` rank200 / 平台 `bundledSkillDir`),**插件包目录不在其中** ⇒ "就用插件内目录"= **agent 无法按技能名加载**,只能靠 prompt 给绝对路径。
三方案:**A 复制**(能按名加载;每用户 4.3 MB + 版本对账)|**B 软链**(能按名加载、零副本、升级即生效;**须先实测 dsh 是否跟随 symlink**;用户删/禁会断链)|**C 不落扫描根 + prompt 给包内绝对路径**(零冲突,但用不了 skill 名、用户不可见)。
→ **定稿:B 优先(一条实测命令即可确认)→ 退回 A → C 仅兜底。**
**Q2 同名技能怎么办(三层)**:① 插件 ↔ **用户自建** → **让位**(不覆盖 + 日志 + UI 提示,档案 41 有同名 409 先例)② 插件 ↔ **平台共享层** → **互斥**(本单不投共享层;共享层 rank 更高会压住)③ 插件 ↔ **别的插件** → **owner 标记 + 先到先得 + 冲突报错**:`.installed.json` 记 `owner: <包名>@<版本>` / `skillVersion` / `sha256`;无标记=用户自建→让位、owner=自己→按版本对账、**owner=别的包→拒绝写并报出 owner**。**不建议给技能名加命名空间前缀**(要改所有 prompt 且用户看着怪)。
**T03 现状**:18,851 字符 / 263 行;`docs-audit.py` 无 P0;双端 md5 一致。**§五#8 不再构成开工阻塞**(降级为"并入 P0#2 修")。
## 11:46 状态核查:任务进度 + 冲突治理是否闭环
**用户问**:刚才几个任务执行了吗?多任务并行文档冲突是否已解决?→ 只读实测(不凭记忆):
| 单 | 状态 | 证据 |
|---|---|---|
| T02 | ✅ 完成 + 已归档 | `archive/交接单-已完成/T02-…md` |
| T03 | 🔄 **执行中** | `交接单/.doing-T03` 锁(10:16)OWNER =「exec-session-B(当前会话,接管自 exec-session-A)」;T03 文件仍是我 09:36 的版本 |
| T04 | ⏳ 未开工,但 **①已被并行会话实质完成** | 文档库 HEAD `43e4ae9` → **`b06f7dd`**,09:06–09:28 **5 次提交**(`96f8ef8` 基线含档案 57-61 + T02 收尾 → `be42155` 档案 62 → `b06f7dd` manifest);未提交 **26+ → 13**。**②③ 未做**:`/opt/dsh/state/.op-lock` 不存在;`交接单` 目录仍 **755**、`README.md` **644**、`T04` **644**(T01/T03 已 600;对照 `04-调整方案`=600) |
| T01 | ⏳ 未开工 | 无 `.doing-T01`;文件 mtime 07:22 未变 |
**并行冲突治理:已缓解、未闭环**(四层证据)
1. 机制 ✅(占用锁 / 写者归属 / guard / 收尾四件套 / 会话生命周期,均已写入 `交接单/README`)。
2. **git 检测能力 ✅ 已恢复**(昨天"长期不提交"的根因已被解决)。
3. 实测正证 ✅:这两小时并行新增 **4 份档案(62/64/65/66)+ 2 个新技能目录**(`skills/dsh-decision-method/`、`skills/dsh-feature-first/`),**无内容丢失**;我这边 2 次 Edit 被拦截(= 检测生效而非丢失)。
4. ❌ 未闭环:① 服务器侧锁未做(重启/drain 仍无互斥,**最高危**)② 权限未统一 ③ **新发现:服务器 `/opt/dshs` 有 13 项未提交**(`orchestrator.ts`/`proxy.ts`/`portal.html`/`ensure-biz-plugins.cjs`/新增 `ensure-anysearch-*.cjs`…,HEAD 仍 `ebe8075`)→ **代码侧没有 git 路标,2 小时成果只在服务器工作区** ④ 文档库仍 13 项未提交。
**发现他方一处问题(未越界修)**:`04-调整方案/64-接入AnySearch搜索provider.md` 引用了**不存在的档案号 63**(跳号)→ `docs-audit.py` 退出码非 0。按写者归属(`04-调整方案/` = 执行会话 lane)**我没动**,只在回报里指出。
**T04 已更新为与现实一致**:新增 **§〇 执行进度表**(①✅ 已由并行会话完成 + ②③❌ + **④ 新缺口:平台代码库提交**)、新增 **§五 5.1「平台代码库提交」**(服务器 commit → bundle → 本机 merge,**push 需用户明示**)。**单子范围收窄为 ②③④,顺序 ④ → ② → ③**(代码未提交是当前最高风险)。T04 双端 md5 一致。