Files
dsh_ai1net_server/接续包_文档库结构治理_20260924.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

302 lines
32 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-24 06:2x)
> **工作区**:`E:\ProgramData\AIProject\aliyun-dsh-server` **线名**:插件投放与分库线 · 文档库治理(续)
> **性质**:接续包(7 段)。⛔ 本包只涉及 `D:\github\dsh_shenxian\dsh-server-docs` 的**结构与命名**,不含平台代码改动。
> **上棒已被用户纠正一次**(把「移动文件夹」误读为「摊平内容」),本包已把该纠偏写进 §六,⛔ 勿重犯。
---
## §1 目标
把 `dsh-server-docs` 收成「**一眼看懂、机械可维护**」的形态:① 顶层全部带编号且序号一律阿拉伯数字;② 状态可机读(不靠目录位置);③ 无效/重复件清出项目;④ 收尾把未闭环的引用、重号、残渣清干净。
## §2 已完成(本棒 8 项,均有取证)
1. **顶层全编号**:`01-规范` `02-架构设计` `03-数据库` `04-调整方案` `05-交接单` `06-ops` `07-scripts` `08-skills` `09-archive` `tmp`(`tmp` 按用户令**不带号**)。
2. **机制层同批迁移**:宿主 `E:\ProgramData\.workbuddy\settings.json` 内 **5 条 hook 入口** → `07-scripts/`;锁根 `05-交接单/`(`.locks`/`.exec-lock`/`.doing-*`)在 `handoff-guard.sh`·`preflight-lock.sh`·`lock-guard-hook.py`·`op-lock.sh` 的硬编码全部同步。
3. **7 个常驻编号件 → `01-规范/`**;引用改写累计 **112 + 52 + 164** 量级(含 `08-skills/`(库内 + 本机 `~/.workbuddy/skills/`)、工作区 4 个接续入口)。
4. **交接单摊平后又按用户本意恢复**:`05-交接单/交接单-已完成/`(**22 个** = T01–T07 原在 `09-archive/交接单-已完成/` + T08–T21 原在 `05-交接单/archive/交接单-已完成/`)。
5. **序号统一为阿拉伯数字**:`IM群组-A~F` → `01~06`;中文序号 ①②③④ → `01~04`;`覆盖网络-序NN` → `覆盖网络-NN`;`交接单_carbon插件-01M1a…` → `carbon插件-01-M1a…`(去冗余前缀 + 补分隔符,本棒最后一项)。
6. **新增工具**:`07-scripts/handoff-status.py` —— 一条命令出「待执行/已完成/无状态」清单(递归扫子目录,状态取单子头部 `- 状态:` 行,回退取 `05-交接单/README.md` 台账表)。
7. **清出项目**(移入工作区 `归档/`,可恢复):`09-archive/_tmp_r6_s8.md`、`_自动接续简报_20260916.md`、`dsh-improvement-plan-20260909-full.md`、`工作区草案/`、`09-archive/接续包_覆盖网络线_20260916.md`、`09-archive/接续入口_覆盖网络线_20260916.md`(后两者中入口那份是工作区根权威版的过期副本)。
8. **D1–D3 台账/索引**(上一棒):`INDEX.md §二` 刷成 146 行、13 条重复行清零;`04-调整方案/README.md` 纠偏(`01~28` → 146 篇)。
## §3 在途
无未落盘半成品。所有脚本在 `E:\ProgramData\AIProject\aliyun-dsh-server\tmp\`(`_renumber.py` · `_fix_rel.py` · `_renumber2.py` · `_flatten.py` · `_flatten2.py` · `_handoff_no.py` · `_handoff_digit.py` · `_restore_sub.py` · `_carbon_fix.py`),**幂等、可重跑**。
## §4 未完成(按风险低→高;⛔ 均未获授权)
1. **【低】补状态字段**:`handoff-status.py` 实测 **待执行 16 / 已完成 9 / 无状态 15**。这 15 个(`T09`–`T19`、`T21`、carbon 01/03/04 等)**头部无 `- 状态:` 行** ⇒ 按其在 `交接单-已完成/` 的目录归属补写状态行。
2. **【低】订正打架样本**:`T20-观测口径与在册缺陷` 头部写「待执行」,却在 `交接单-已完成/` 里 ⇒ 二选一(改字段或挪目录)。
3. **【低】`T08` 重号**:`T08-执行标记-已释放.md` 与 `T08-集群化落地-兼容单例模式.md` 同号;前者是运行态标记、非单子 ⇒ 建议清出。
4. **【低】残渣**:`05-交接单/.lock-插件投放-②` 陈旧占号锁(非有效锁;有效锁在 `.locks/` 内为 OWNER 文件)。
5. **【中】`04-调整方案/` 存量编号混排**(146 篇:两位 95 + 三位 47 + 4 个字母后缀件 + 5 个真断层 48/63/130/131/132)⇒ 现行口径 **存量不重排、新档三位零填充**(改口径需用户拍板)。
6. **【待授权】** `commit` / `push` 全部未做(本轮 dsh-server-docs 未提交改动量 ≈ 100+ 项,**⛔ 禁 `git add -A`**:同仓还有别的线的在途改动)。
## §5 下一步(动作序列)
① 跑 `state.py`,只读**本线**那段;② 读本包并**重算 md5 校验**;③ `--claim-exec` 抢域锁(域:`dsh-server-docs/05-交接单` + `dsh-server-docs/07-scripts`);④ **只做 §4-1/2/3/4**(均为低风险、可自决)⇒ 完成后重跑 `handoff-status.py`,确认「无状态」显著下降至 0 或仅剩有据可查者;⑤ §4-5 只报告不动;⑥ `--release-exec` 收口。
## §6 关键决定(⛔ 不得推翻重来)
1. **`tmp/` 不带编号**(用户令);`04-调整方案/` **号不动**(`04-NN` 短号 + 4 处脚本常量硬编码)。
2. **序号一律阿拉伯数字**:不用英文字母、不用中文数字。`T` 是族名(序号是数字)、`覆盖网络-`/`carbon插件-` 是族名。
3. 🔴 **纠正上一棒的语义误读(用户原话:「我的意思也没有说要把文件夹删除 合并,不知道你咋理解的」)**:用户说「`<某文件夹>`,直接放在 `<父目录>` 下面」= **移动那个文件夹本身、去掉中间层**,⛔ **不是**把里面文件摊平。⇒ 同义指令再出现时,**先按"移动文件夹"理解**,不确定就问。
4. 🔴 **批量改名的三条铁律**(本棒踩全了):① 引用有三形态必全覆盖(限定路径 `dsh-server-docs/xxx/` · 相对路径 `<x>/xxx/` · 字符串字面量 `'xxx'`)—— 只做 ①+裸名必漏功能性引用(锁/hook 脚本);② ⛔ **不用 `IndexOf`+`Substring` 手工拼新名**(本棒因此把 5 个文件拼成 `覆盖网络-24-覆盖网络-序24-…` 双前缀),一律用正则整体替换或显式映射表;③ **改完必须 grep 功能性常量逐条验**(如 `^LOCKDIR=`),不能只看"改写 N 个文件"。
5. 🔴 **hook 是会话启动时快照**:改宿主 `settings.json` 的 hook 路径后**本会话命令行整轮失效**(实测 `can't open file …dsh-server-docs\scripts\bash-output-guard.py`);且 hook 失效时 **Python 子进程也起不来 `git`/`mv`**(实测 `WinError 2`)⇒ 该窗口内改用 **PowerShell 原生命令**;hook 重载后即恢复。
6. **状态不靠目录位置表达**:主依据 = 单子头部 `- 状态:` 行 + `05-交接单/README.md` 台账表;目录(`交接单-已完成/`)只作辅助分类。
## §7 回滚点
| 对象 | 回滚方式 |
|---|---|
| 顶层目录编号 | 反向重命名 + 重跑 `_tidy.py`/`_renumber.py` 类脚本(幂等);`git mv` 可反向 |
| 宿主 hook 配置 + 5 个机制脚本 | 备份在 `归档/dsh-server-docs-重编号-20260924/` 与 `归档/dsh-server-docs-微调-20260924/`(`*.bak`) |
| 清出项目的档案件 | `归档/dsh-server-docs-清理-20260924/`(可原样搬回) |
| 去重的旧副本 | `归档/dsh-server-docs-去重-20260924/` |
| 文档库 git | `git -C D:/github/dsh_shenxian checkout -- dsh-server-docs/`(⚠️ 连带丢弃别的线在途改动,慎用) |
---
## §8 用户追加令(2026-09-24 06:2x ⇒ **§5 增补,优先级最高**)
> 用户原话:「**接续会话处理完成后,全面检查一遍引用关系,固化规则不要再把项目文件弄得乱七八糟**」。
1. **规则已固化**:`dsh-server-docs/CODEBUDDY.md` 新增「**文档库结构与命名规则**」章(顶层结构 / 命名 / 状态不靠目录 / 批量改名六铁律 / 锁与钩子 / 收口判据);工作区 `.workbuddy/memory/MEMORY.md` 加一条指针。⛔ 后续任何结构改动**先读该章**。
2. **§5 动作序列在 ④ 之后追加一步**(做完 §4-1/2/3/4 必做):
**⑤ 全面引用体检** ——
- 三种形态各查一遍旧目录名/旧文件名残留:限定路径 `dsh-server-docs/`、相对路径、脚本内字符串字面量;
- **功能性常量逐条验**:`grep -n '^LOCKDIR=\|^LOCKEXEC=\|^LOCKSROOT=' 07-scripts/handoff-guard.sh`、宿主 `settings.json` 的 5 条 hook 路径、`.gitignore` 忽略规则;
- 重跑自检三件套:`07-scripts/docs-consistency.py`(rc=0)· `07-scripts/docs-archive-index.py`(只读,应报"一致")· `07-scripts/handoff-status.py`;
- 结果写进本包"完成情况",**有残留未清零即不得收口**。
3. **收口判据**:顶层可见 + 引用零悬空 + 三件套自检全绿。
---
## §9 完成情况(本棒执行棒 · 2026-09-24 06:3x–07:0x · 会话 `文档库治理4`)
**锁**:`--claim-exec "文档库治理4" --domains dsh-server-docs/05-交接单 dsh-server-docs/07-scripts` 抢到 → 收口已 `--release-exec`。口径校验:本包开工前 md5 = `6fd7679eb0888d3816b9d9f07c39d01a` ✅ 相符。
### ① §4-1 状态字段补全(16 件)
机读判据 = `handoff-status.py` 的 `HEAD_STATUS` 正则(内联 `- 日期:… | 状态:` 写法**不匹配** ⇒ 必须拆行)。
- **拆行/插入 13 件**:carbon插件-01、T09–T14、T16–T19、T21(各补 `- 状态:` 行,值 = 单内 §8/§9/§10 回报位置的指针)。
- **改值 3 件(头部旧值与证据打架 ⇒ 按证据改,§4-2 口径)**:
- `T15-presence在线态`:写「待执行」→ **已完成**(证据 = 单内 `§8★ 回报(序⑲ 执行棒 · 已回填 · 2026-09-17 17:28–18:16)`)。
- `T20-观测口径与在册缺陷`(§4-2 指定件):写「⏳ 待执行」→ **已完成**(证据 = §8/§9/§10 三次执行回报已就地回填)。
- `carbon插件-03`:写「⏳ 待执行」→ **已完成**(证据 = 同线 `carbon插件-04`「上游单」行:执行棒④ 照单收官、四件全绿)。
- `carbon插件-04`:**待执行**(规划单,D9/D10 待拍板,§八 回报格式未回填)。
- **结果**:`handoff-status.py` ⇒ **无状态 15 → 0**;已完成 9 → **23**;待执行 16(不变)。
### ② §4-3 T08 重号件清出
`05-交接单/交接单-已完成/T08-执行标记-已释放.md`(运行态标记、非单子,与 `T08-集群化落地-兼容单例模式.md` 同号)⇒ 移入工作区 `归档/dsh-server-docs-清理-20260924/`(可原样搬回)。
### ③ §4-4 残渣占号锁
接续包点名的是 `.lock-插件投放-②`,**实测该文件名为 `①`**;同类空目录另有 3 个 ⇒ 四个均**经核实为空目录**(有效锁在 `.locks/`)后 `rmdir`:`.lock-插件投放-①`、`.lock-02`、`.lock-47`、`.lock-CA2`。现 `05-交接单/` 下 `.lock-*` = 0。
### ④ §5⑤ 全面引用体检
- **功能性常量(逐条验,全对)**:`handoff-guard.sh` `LOCKDIR/LOCKEXEC/LOCKSROOT` 全指 `05-交接单/**` ✅|`preflight-lock.sh` ✅|宿主 `settings.json` 5 条 hook 全指 `07-scripts/` ✅|库 `.gitignore` 2 条指 `05-交接单/**` ✅。
- 🔴 **新发现并已修(上一棒遗留的功能性残留,静默假绿)**:`07-scripts/` 5 个自检脚本 + 库 `CODEBUDDY.md` + 工作区 `.codebuddy/rules/archive-doc.md` 仍指**旧目录名** `调整方案/`(已不存在)⇒ 共修 **21 处**。最严重两处:
- `docs-manifest.py`(档案号/L5 前缀):`startswith('调整方案/')` 恒假 ⇒ manifest 里 147 条 `04-调整方案` 路径**取不到档案号** ⇒ `docs-archive-index.py` 报「档案 0 篇」还判「与 INDEX.md 一致」(**假绿**)。
- `.codebuddy/rules/archive-doc.md` 的 `paths` 含 `dsh-server-docs/交接单/**`(旧名)⇒ 条件规则**静默不生效**。
- **三件套(全绿)**:`docs-consistency.py` rc=0「承诺现行的文件与现行值一致 ✓」|`docs-archive-index.py` rc=0「表内容与 INDEX.md 一致」|`handoff-status.py` rc=0。
- 为使 consistency 达 rc=0:T02 单元格 `「下一号 = **20**」` → `「下一号」写死为 **20**(旧值,已作废)`(破 `下一号 = NN` 形态,旧值语义保留)。
- **散文类旧前缀残留(清单,未改)**:`01-规范/07-实例UI分区登记表.md:52`|`02-架构设计/README.md:5,7,15`|`03-数据库/DB-00:34,41 · DB-01:5 · DB-03:4`|`05-交接单/覆盖网络-25:6`|`08-skills` 5 处(⚠️ 涉三处同步、单向推进,须整批动)。存量 `04-调整方案/` 146 篇内约 1605 行旧前缀(`过程档案不改正文`)⇒ 未动。
### ⑤ 仍需处置(未动,均非本棒授权范围)
1. **生成物待重建**:`docs-manifest.json` 是在旧前缀下生成的;重建后 146 篇才有档案号 ⇒ `python 07-scripts/docs-manifest.py` → `docs-archive-index.py --write`(后者会改 `INDEX.md`,跨线可见 ⇒ 需拍板)。
2. **打架样本残留**:`T02` 台账表写「待执行」但其件在 `交接单-已完成/`(其 D1–D3 交付物已由上一棒落地)⇒ 需二选一(改台账 / 挪件)。
3. **缓存**:工作区 `.workbuddy/cache/docs-lines.json` 仍记旧路径(可再生)。
4. `commit` / `push` 全程未做(未授权)。
### ⑥ 本棒改动清单(回滚点)
16 个状态件(内容行级,见 `tmp/_status_fix.py` 映射表)|`T08-执行标记-已释放.md`(mv,归档可搬回)|4 个空锁目录(rmdir)|7 个功能性件(`07-scripts/{docs-manifest,docs-audit,docs-archive-index,docs-search,docs-consistency}.py` · 库 `CODEBUDDY.md` · 工作区 `.codebuddy/rules/archive-doc.md`)|`T02` 单元格 1 处。脚本 = `tmp/_status_fix.py`、`tmp/_rel_fix.py`、`tmp/_rel_fix2.py`(幂等)。
---
## §9 · 执行记录(接续棒 2 · 会话 `文档库治理5` · 2026-09-24 06:4x–07:0x · 已收口)
> 用户拍板(2026-09-24 06:42):「1、A 2、B 。都按照长期有利的方向处理」
> ⇒ ① A = **只重建 manifest,不动 INDEX** | ② B = **连 08-skills 一起改并三处同步**
### 本棒做了什么
| # | 动作 | 结果 |
|---|---|---|
| 1 | **重建 `docs-manifest.json`**(拍板 ①A) | 档案 **0 → 146 份**;items 251→242(T08 清出 + 目录改名后重新枚举);**INDEX.md 未动**(mtime 仍 06:14,早于本棒) |
| 2 | **散文类旧前缀残留修复**(拍板 ②) | **29 文件 / 74 处**:生效件 4 目录(01-规范 2 · 02-架构设计 3 · 03-数据库 4 · 05-交接单 30)+ 08-skills 12 文件 37 处 ⇒ 精确正则复验**裸旧名 0 处** |
| 3 | **技能三处同步**(拍板 ②) | 库 `08-skills` → 本机 `.workbuddy/skills`(**12/12 一致**)→ 服务器 `/opt/dsh/docs/skills`(**12/12 一致**,`chmod 600 root:root` 已保)⇒ **三处 md5 全同** |
| 4 | **顺带修真悬挂引用** | 库内 `dsh-plugin-diagnose/SKILL.md` 的 `src/host/08-skills/plugin.ts` → `src/host/skills/plugin.ts`(**本机副本原本就是正确值** ⇒ 证明这是改名时的误替换,非真路径) |
### 自检结果
- `docs-consistency.py` **rc=0** ✅(承诺现行一致)
- `handoff-status.py` **rc=0** ✅(无状态 **0** / 待执行 16 / 已完成 23)
- `docs-archive-index.py` **rc=1** —— 报「档案 **146 篇**」+「表与 INDEX 不一致,加 `--write` 刷新」⇒ **这正是拍板 ①A 的预期中间态**(manifest 已重建、INDEX 按拍板未刷)。⚠️ 对比:上一棒是「档案 0 篇还判一致」的**假绿**,本棒起是真检查。
- `docs-audit.py` **rc=1** —— **误报**:它把 `08-skills/**/07-并行调度详解.md` 这类编号开头的技能文档当成「档案 07」(报「编号 01 被 5 份档案占用」等);同一份报告里 **`✓ 无悬空档案号引用`** ⇒ 接续包判据「引用零悬空」**成立**。
### 遗留 / 下一棒待办(按优先级)
1. 🔴 **`docs-archive-index.py --write` 刷 `INDEX.md`** —— 使 §二 表与 manifest 对齐、146 篇档案号入索引。**属跨线可见改动(改 `INDEX.md`)⇒ 需拍板**(本棒按 ①A 未做)。
2. 🔴 **`docs-audit.py` 档案号扫描范围过宽** —— 应限定到 `04-调整方案/`(或排除 `08-skills/**`),否则编号冲突恒报。**这是上一棒「把前缀常量改成 `04-调整方案/`」后暴露出来的既有设计缺陷**(改前扫不到该目录 ⇒ 恒 0;改后扫到了 ⇒ 范围过宽)。
3. ⚠️ **`INDEX.md` 被 git 判为 `Binary files differ`** —— 本棒未动它(mtime 06:14,属既有未提交改动),但该状态可疑(疑含 NUL 或行尾混杂),建议单独取证。
4. ⚠️ **服务器 `/opt/dsh/docs/skills/` 下不在库内 `08-skills` 的技能**(`agent-operating-rules`、`dsh-auto-handoff-chain`、`dsh-feature-first` 等,本机 24 个技能目录 vs 库内 12 个)**未纳入本轮**;本棒只同步了库内 08-skills 的那 12 个文件所在技能。
5. 📌 `05-交接单/交接单-已完成/**`(历史档案)与 `04-调整方案/` 存量约 1605 行**按政策不改**(过程档案不改正文)。
6. 📌 **未 commit / 未 push**(未获授权)。
### 本棒方法论要点(下一棒复用)
- **判「旧名残留」必须用带负向后顾的正则**:`(?<![0-9A-Za-z_/\-])调整方案/` —— ⛔ 直接 `grep "调整方案/"` 会把**正确的新前缀** `04-调整方案/` 一并命中 ⇒ 假阳性(本棒实测:grep 报 14 个文件,精确正则报 0)。
- **判「三处/两端一致」必须忽略行尾**:Windows `
` vs Linux `
` ⇒ `diff` 会整块报差异,但 md5 **逐行相同**。用值比较,别信 `diff` 退出码。
- **同步前先做「归一化比较」定性差异**:把两端各自的前缀反向归一化(`04-调整方案/`→`调整方案/`、`07-scripts/`→`scripts/`、反斜杠形式也算),若归一化后相同 ⇒ 差异纯为改名 ⇒ 可安全整文件同步。
- **库是权威源,本机与服务器是镜像**(本棒实测:本机副本停留在改名之前,库内已改)。
## §10 · 执行记录(接续棒 3 · 会话 `文档库治理6` · 2026-09-24 06:54–07:1x · 已收口)
> 用户令(2026-09-24 06:53):「**都要执行一直到任务处理完毕**」⇒ §9「遗留」1–3 全部执行完毕。
### 做了四件(全部机读通过)
| # | 动作 | 结果 |
|---|---|---|
| 1 | `docs-archive-index.py --write` 刷 `INDEX.md` | **rc=0**「表内容与 INDEX.md 一致」;146 篇档案号入索引;备份 `tmp/INDEX.md.bak` |
| 2 | 修 `docs-audit.py` 档案号提取范围 | 第 61 行改为 `if mf and ("/" not in f or f.startswith("04-调整方案/"))` ⇒ **rc=0「无 P0 级问题」**(改前:全库 md 用文件名前缀取号 ⇒ `08-skills/**/07-并行调度详解.md` 被当档案 07) |
| 3 | **修 `INDEX.md` 内 2 处 NUL 损坏**(git 判 binary 根因) | 两处 `\x004-调整方案/`(`0` 被写成 NUL,行 44 / 214,同一句「2026-09-24 已清出项目」)⇒ 还原为 `04-调整方案/`;现 `NUL 0 / CR 0 / LF 284`,**git 恢复文本判定**(`numstat` 由 `- -` 变 `111 93`) |
| 4 | 技能集合差集取证 | 服务器 **12** = 库内 `08-skills` **12**(§9 里"服务器有库外技能"是**假阳性 grep 的误判**,服务器实测只有 12 个技能目录);本机多出的 12 个(`AI HOT` / `humanizer` / `agent-ui-kit` / `taste-skill` / `workbuddy-*` 等)是**跨项目个人技能**,不属文档库 `08-skills` 管辖 ⇒ **不在本线范围** |
### 自检(**本线首次全绿**)
`docs-consistency` rc=0 | `docs-archive-index` rc=0 | `handoff-status` rc=0(无状态 0 / 待执行 16 / 已完成 23)| `docs-audit` rc=0 | `docs-manifest` rc=0(242 份 / 146 档案)
### 🔴 §11 · 本棒新发现(**超出本棒范围,需拍板**):服务器归档镜像整体仍是「改名前的旧结构」
- **事实**:`/opt/dsh/docs/` 顶层 = `skills/` `交接单/` `scripts/` `archive/` `ops/` `数据库/` `04-调整方案/` + 顶层散文件 `01-规划与架构.md` `02-运维手册.md` `03-路线图与待办.md` `06-工作台UI规范.md` `07-实例UI分区登记表.md`;**本机/库已是** `01-规范/`…`09-archive/`。
- **症状**:`docs-sync-check.sh` 报「一致 146 / 内容不一致 13 / 仅本地 136 / 仅服务器 121」——其中 **「一致 146」全部来自两边同名的 `04-调整方案/`**;其余差异是**目录改名造成的路径不匹配**,非内容差异。
- **已取证(决定风险等级)**:平台代码(`/opt/dshs/src`、`/opt/dshs/lib`、`/opt/dshs-cluster/src`)、`/etc/dshs.env`、systemd unit **均无 `docs/skills` / `DSHS_DOCS` 引用** ⇒ 该目录是**归档位,不是运行时依赖**(唯一命中在 `/opt/dsh/backups/docs-skills/*.bak` 的文档文本里)。
- **但有一处自指耦合**:技能文档自身写死了「服务器归档位在 **`/opt/dsh/docs/skills/<name>/SKILL.md`(root 600)**」⇒ 若把服务器 `skills/` 改名,**必须同步改该约定文本**(涉及本机技能 24 份 + 库 `08-skills` 12 份)。
- **为何需拍板**:① 涉及 **121 个旧名文件**(重命名/移动 + 删旧目录 ⇒ **不可逆**)② 会让三处(库 / 本机 / 服务器)的**技能归档约定**连锁改动 ③ 属「验收面变化」而非本棒既定范围。
### 📌 本棒未做(授权/范围外)
未 commit / 未 push(未获授权)| `04-调整方案/` 存量不动(政策)| 服务器镜像结构改造(见 §11,待拍板)。
## §12 · 执行记录(接续棒 4 · 会话 `文档库治理7` · 2026-09-24 07:04–07:2x · 已收口)
> 用户令(2026-09-24 07:0x):「**A 方案**」= 采纳 §11 的 A(改造服务器归档镜像结构与本机对齐),并按先前口径「**都要执行一直到任务处理完毕**」执行到底。
### 一、A 方案主体:服务器归档镜像结构改造
| # | 动作 | 结果 |
|---|---|---|
| 1 | **全量备份** | `/opt/dsh/backups/docs-pre-restructure-20260924-071007.tar.gz`(1.9 MB / 326 条目) |
| 2 | **打包库镜像** | 289 文件(排除 `.git/` `tmp/` `05-交接单/.locks/`) |
| 3 | **新结构就位** | 解包到 `/opt/dsh/docs/` ⇒ 顶层 = `01-规范`…`09-archive` + 7 个顶层文件,**与本机同形** |
| 4 | **旧结构归档** | 12 项 / **121 文件** `mv` 到 `/opt/dsh/backups/docs-old-structure-20260924-071032/`(⛔ 不是 `rm`) |
| 5 | **权限** | 目录 `700` / 脚本 `755` / 其余 `600`,`root:root` |
| 6 | **双端对账** | `docs-sync-check.sh` ⇒ **双端一致 ✅**(一致 **289** / 内容不一致 **0** / 仅本地 **0** / 仅服务器 **0**) |
**旧结构归档清单**(全在 `backups/docs-old-structure-20260924-071032/`):`skills/` `交接单/` `scripts/` `archive/` `ops/` `数据库/` `.bak-seq17-20260917-164809/` + 顶层散文件 `01-规划与架构.md` `02-运维手册.md` `03-路线图与待办.md` `06-工作台UI规范.md` `07-实例UI分区登记表.md`。
### 二、三分表判定(决定「哪些文件不能丢」)
| 归类 | 数量 | 处置 |
|---|---|---|
| 已一致 | 180 | 不动 |
| 服务器旧版(路径在库、内容不同) | 78 | 解包覆盖为库版本 |
| 改名 / 搬路径 | 0 | —(映射规则已覆盖全部旧路径形态) |
| **真独有**(库内完全没有) | **22** | 其中 5 个 `.bak-seq17-*` 本地备份 + **17 个历史旧档** ⇒ 随旧结构整体归档留档,**零信息丢失** |
**17 个历史旧档**(库内已有新版或已改名的旧版):`archive/工作区草案/*`(3)· `archive/_tmp_r6_s8.md` · `archive/_自动接续简报_20260916.md` · `archive/dsh-improvement-plan-20260909-full.md` · `ops/接续入口_覆盖网络线_20260916.md` · `ops/接续包_覆盖网络线_20260916.md` · `交接单/IM群组-A-房间内核与DB.md` · `交接单/IM群组-D-插件SDK与扩展点契约.md` · `交接单/覆盖网络-序24/25/26/45/46/47`(6)· `交接单/archive/交接单-已完成/T08-执行标记-已释放.md`。
⚠️ **服务器 `交接单/` 下还藏着一层更早的旧结构** `交接单/archive/交接单-已完成/`(12 个 T09–T21)—— 这是改名**之前**的形态残留,随 `交接单/` 一并归档。
### 三、🔴 纠正上一棒的误判(重要)
§11 里写的「**技能文档自身写死了服务器归档位 `/opt/dsh/docs/skills/`**」—— **实测是错的**。逐处取证结果:
- 库内 + 本机技能的功能性引用**本来就用新段名**:`/opt/dsh/docs/08-skills/<name>/SKILL.md`(3 处)、`/opt/dsh/docs/05-交接单/`(1 处)⇒ **改造服务器是把这些引用从「悬挂」变回「正确」**,而不是「改了目录名才要改引用」。
- 真正需要改的是**另一批**:库内 4 处 `/opt/dsh/docs/调整方案/`(`08-skills/dsh-change-workflow/` 2 文件)——已修。
- **教训**:上一棒把「技能正文里的 `/opt/dsh/docs/08-skills/`」误读成「写死旧路径」,是因为**没有逐处打印原文**、只凭「技能文档提到 skills」推断。⇒ 判「自指悬挂」必须**逐处打印匹配上下文**,不能靠印象。
### 四、库内旧名残留终扫与修复(上一棒遗留)
上一棒修的 74 处**漏掉了顶层文件**(`README.md` / `INDEX.md` / `BRIEF.md`)与部分自检脚本。本棒补齐:
| 批次 | 文件 | 处数 |
|---|---|---|
| 第一批 | `README.md`(14)· `INDEX.md`(5)· `BRIEF.md`(1)· `07-scripts/docs-dedupe.py`(1)· `07-scripts/handoff-status.py`(1)· `08-skills/dsh-change-workflow/`(2 文件 3 处) | **25** |
| 第二批 | `01-规范/07-实例UI分区登记表.md` · `02-架构设计/覆盖网络-顶层架构全貌.md` · `05-交接单/覆盖网络-25-实例逐步拉起.md` · `08-skills/{dsh-decision-method,dsh-feature-first,dsh-opensource-release×2}` | **8** |
| 订正 | `07-scripts/handoff-guard.sh:58` 注释里「已知根段」举例 `skills/` → `08-skills/` | 1 |
- 顺带修掉一处**双前缀 bug**:`README.md` 的 `05-交接单/05-交接单/T09–T21` → `05-交接单/T09–T21`。
- **终验**:全库裸旧名 `调整方案/` = **0 处** ✅
- **甄别掉的 6 类假阳性**(记录在技能 §11.2):relay 日志 `host=ops/w-106`|git 仓路径 `HEAD:scripts/x.cjs`|散文「交接单 / 接续包」|`~/.workbuddy/skills/`|`/api/skills/{shared,mine}`|`src/host/skills/plugin.ts`。
### 五、对账脚本修复(`07-scripts/docs-sync-check.sh`)
改造前对账报「仅本地 6 个」,全是**运行态文件**(`tmp/` 4 + `05-交接单/.locks/` 2)—— 属脚本排除清单缺陷。修 3 处(python 分支 `SKIPF/SKIPD`、bash 回退分支、服务器侧 `find`)补齐 `tmp/` 与 `.locks/` 排除 ⇒ 对账方可归零。
### 六、改名后运行时依赖复查(本棒新增,**零引用**)
`systemd` / `/etc/dshs.env` / `crontab` / `/root/.bashrc` / 平台代码(`/opt/dshs/src`、`/opt/dshs/lib`、`/opt/dshs-cluster/{src,lib}`)/ 实例侧 `/opt/dsh/users` —— **全 grep 旧路径,零引用**。唯一命中是 `/opt/dsh/docs-status/文档库状态备注.md` 里的**描述性文本**(非可执行依赖)。
⇒ 结论:`/opt/dsh/docs` 是**纯归档位**,改名不影响运行时。
### 七、技能沉淀(`dsh-knowledge-upkeep` 新增 §11)
新增 **§11「归档镜像结构治理与双端对账」**(+52 行,LF 保持,三处 md5 = `376710effda7ce42ea3ba92038ffbbe8` → 修 audit 告警后更新):三分表判定法 · 负向后顾正则 · 忽略行尾比对 · **改名后必查六项** · 改造安全姿势(全量备份 + `mv` 归档)。
⚠️ 期间踩到一个自造坑并已修:§11 里写的「manifest 报『档案 0 篇』」被 `docs-audit.py` 的【6】交叉引用检查**当成"引用档案号 0"** ⇒ 改写为「输出『0 篇档案』」后 rc 归 0。**教训:写进文档的示例文案会进 lint 扫描面。**
### 八、自检(全绿)
`docs-consistency` **rc=0** | `docs-archive-index` **rc=0**(档案 146 篇)| `handoff-status` **rc=0**(无状态 **0** / 待执行 16 / 已完成 23)| `docs-audit` **rc=0**(无 P0)| `docs-manifest` **rc=0**(files 242)
+ 双端对账 **双端一致 ✅**
### 九、回滚方式(两条,均已在服务器备齐)
```bash
# ① 只回滚结构(保留新结构产物)
ssh [email protected] 'mv /opt/dsh/backups/docs-old-structure-20260924-071032/* /opt/dsh/docs/'
# ② 全量回滚到改造前(原始样子)
ssh [email protected] 'rm -rf /opt/dsh/docs && tar xzf /opt/dsh/backups/docs-pre-restructure-20260924-071007.tar.gz -C /opt/dsh'
```
### 十、未做 / 待办
- **未 commit / 未 push**(未获授权)—— 库内本棒改动:`README.md` `INDEX.md` `BRIEF.md` `docs-manifest.json` `01-规范/07-…` `02-架构设计/覆盖网络-…` `05-交接单/覆盖网络-25-…` `07-scripts/{docs-sync-check.sh,docs-dedupe.py,handoff-status.py,handoff-guard.sh}` `08-skills/*`(7 文件)。
- ⚠️ **`INDEX.md` 被 git 判 `M` 且历史遗留 180 项未提交改动**(含别的线的 `config/*`)—— 建议单独收口提交。
- 📌 服务器 `/opt/dsh/docs-status/文档库状态备注.md` 里写「项目文档正文全部在服务器,本地不保留副本」—— **与现状不符**(本机有完整镜像且双端对账)。该文件属 `docs-status` 线,未动。
## §13 · 执行记录(提交棒 · 会话 `文档库提交1` · 2026-09-24 07:2x · 已收口)
> 用户令(2026-09-24 07:20):「**全部优化完成后 提交到仓库以本地文件为准,提交后仓库要和本地完全一致,不允许有多出的文件夹或文件**」
### 结果:commit `e6207aa` 已双推,仓库 == 本地(status 0 条)
| 项 | 值 |
|---|---|
| commit | `e6207aa6914ff26bee7e999b72db153d00e2d096`(父 `3d8f50e`) |
| 规模 | **239 文件**(M 47 | R 45 | A 107 | D 40) |
| 推送 | SSH 仓 `3d8f50e..e6207aa` + CNB 仓 `3d8f50e..e6207aa`,两者 sha 均 `= e6207aa…` |
| 一致性 | 提交后 `git status` **0 条**;HEAD 中磁盘不存在的文件 **0 个**(= 仓库无「多出」) |
| 双端 | `/opt/dsh/docs` 对账 **289/289 一致** ✅ |
| 自检 | consistency / archive-index(146 篇)/ handoff-status(无状态 0)/ audit 全 **rc=0** |
### 提交前做的三道门禁(下次复用)
1. **敏感扫描**:全量 dry-run 222 条 → 敏感名命中 4(全是 `*-token.ts` / `*credential*.ts` **代码文件**)+ 内容级 2(`src/config.ts` 是**类型声明**、`test/im-gateway-access.test.mjs` 是 `'test-secret-not-a-real-key'` **占位符**)⇒ 逐个取证后判定**无真凭据**。
2. **零丢失核对**:对全部 85 个「被删/改名源」文件,用 **HEAD 内容 md5(归一化行尾)在本地全盘反查** ⇒ 13 个「按文件名找不到」的逐个定性:5 个同内容(在 `tmp/散落临时文件/`、`待清理/中间产物-20260919/`)、1 个是**已更新版**(`ops/接续入口…` → 工作区根)、4 个是**改名+更新**(`交接单/覆盖网络-序24/25/26/45` → `05-交接单/覆盖网络-24/25/26/45`)、1 个已归档(`T08-执行标记`)⇒ **零信息丢失**。
3. **政策边界**:`05-交接单/` 与 `dsh-server-docs/tmp/` 按**用户 2026-09-21 明令**不入库(`.gitignore` 已写「⛔ 别用 git status 判交接单要不要提交」)⇒ `git rm --cached` 清出误入的 `05-交接单/README.md`;给 `dsh-server-docs/.gitignore` 补 `tmp/`(根 `.gitignore` 的 `/tmp/` 只覆盖仓库根)。
### 提醒项(非本棒范围,已报告未动)
- ⚠️ 本次提交**包含别的线的代码落地**:`src/im/**`、`src/db/plugin-data/**`、`src/web/routes/{im,sessions,overlay-device}.ts`、`src/supervisor/plugin-assembly.ts`、`poc/im-*` 等(因用户要求「完全一致」⇒ 全量对齐)。相关线需知晓自己的改动已入库。
- ⚠️ 仓库根的 `core.autocrlf=true` ⇒ add 时对非 `-text` 文件(根级 / `src/` / `config/` / `poc/`)会打印 `LF will be replaced by CRLF` 警告;`dsh-server-docs/**` 已由 `.gitattributes` 标 `-text`(纯 LF),**不受影响**。
- ⚠️ `docs-audit` 报「状态缺失(❓) 15」为既有项,不计入 rc。