build / build-and-scan (push) Waiting to run
文档库:目录改为编号制(01-规范/02-架构设计/03-数据库/04-调整方案/
05-交接单/06-ops/07-scripts/08-skills/09-archive),顶层散文件归入 01-规范/;
INDEX.md 与 docs-manifest.json 重刷(档案 146 篇);旧目录名引用全量对齐。
IM 线:src/im/**(SDK / hub / store / presence / ws / gateway-token)、
src/web/routes/im.ts、src/db/plugin-data/**、src/supervisor/plugin-assembly.ts
及对应 test/**。
插件线:poc/{im-agent-bridge,im-connection-gateway,im-conversation-tabs,
business-plugins-im,carbon-mcp-probe}、src/web/routes/{sessions,overlay-device}.ts、
src/net/relay/{device-grant,instance-credential}.ts。
仓库卫生:清出 40 个历史误入库 / 已改名文件(34 个交接单归档 + 6 个旧结构,
本地均有副本);dsh-server-docs/.gitignore 补 tmp/;交接单不入库(政策)。
152 lines
15 KiB
Markdown
152 lines
15 KiB
Markdown
# 文档库使用约定(**子目录指令 —— 只在读写本目录文件时加载**)
|
||
|
||
> 本目录 = 改造文档库的 **git 工作树**(`dsh_shenxian_doc`);服务器 `/opt/dsh/docs` 是**无 .git 的部署镜像**。
|
||
> 全局硬规则(提问判据 / 红线 R1–R11 / 提交边界)在**项目根 `CODEBUDDY.md`**,不在此重复。
|
||
|
||
## 单一来源(**其余文件只许指针,不许复制**)
|
||
|
||
| 要什么 | 唯一权威 |
|
||
|---|---|
|
||
| 现行事实(入口/服务/运行时/隔离/阈值/定时/证书) | **`BRIEF.md`**(首读) |
|
||
| 清单与状态 | 机读清单 | `INDEX.md §二` | `docs-manifest.json` |
|
||
| 待办 | 未规划 `01-规范/03-路线图与待办.md §二`|已规划待执行 `05-交接单/README.md §一` |
|
||
| 部署 / 构建 / 回滚 / 依赖版本 | `DEPLOY-本部署.md` |
|
||
| 前端 UI 基线 | `01-规范/06-工作台UI规范.md` |
|
||
| 某功能当时怎么改的 | `04-调整方案/<NN>-<主题>.md`(**先读头部 TL;DR**) |
|
||
|
||
**篇数与规模不写死** —— 本库多会话并行,绝对值数十分钟即失效;一律 `python3 07-scripts/docs-manifest.py` 复跑。
|
||
|
||
## 分层判据(防止把规则做成指针)
|
||
|
||
> **"不做会违规、会出事"的 → 实体保留;"看了更准但不看也不违规"的 → 才给指针。**(项目根 `CODEBUDDY.md` 头部)
|
||
|
||
## 档案与编号
|
||
|
||
- **先原子占号**:`mkdir 04-调整方案/.lock-<NN>` 成功再写;**编号现跑**(`ls 04-调整方案/ | sort -n | tail -1`),**勿写死**。
|
||
编号 63 是空号,**勿补占**。
|
||
- **档案只增不改**:与现值不符时改入口,需要修正档案则在文末追加「修正(YYYY-MM-DD)」小节。
|
||
- 历史文件(`04-调整方案/`、`09-archive/`、`01-规范/01-规划与架构`、`01-规范/02-运维手册`)里的旧值**不回改**——写的时候是对的,回改破坏历史。
|
||
|
||
## 改完必跑(七件套 · **顺序不可换**)
|
||
|
||
> ⚠️ **顺序**:`docs-manifest.py` → `docs-archive-index.py`(**后者读前者**)→ 其余任意。
|
||
> 顺序错会**静默**产出新旧混合(2026-09-14 实测:只跑 manifest 未跑 archive-index 时,后者只读模式直接报
|
||
> 「表内容与 INDEX.md 不一致」)。`docs-archive-index.py` 已内置顺序断言:`--write` 时若 manifest 比最新档案旧会**拒绝**,
|
||
> 确认要硬刷才加 `--force`。
|
||
|
||
```bash
|
||
python3 07-scripts/docs-audit.py # 结构:编号冲突 / 悬空引用 → 退出码非 0 需处理
|
||
python3 07-scripts/docs-manifest.py # 刷新 docs-manifest.json
|
||
bash 07-scripts/docs-sync-check.sh # 双端对账 → 退出码 0 = 全绿
|
||
python3 07-scripts/docs-consistency.py # 事实:写死取值 + 跨页取值冲突
|
||
python3 07-scripts/docs-archive-index.py # 派生:档案清单表(INDEX §二 的 04-* 行)+ 摘要迁移
|
||
python3 07-scripts/docs-search.py 关键词 --current # 检索:带 层/域/tier 标注,--current 排除历史层
|
||
python3 07-scripts/docs-shrink-guard.py # 守卫:检出"共享文件被整文件重写抹行"(首跑 --baseline 建档)
|
||
```
|
||
|
||
## ⛔ 动本库之前:先抢全局执行锁(**第一步,不可跳过**)
|
||
|
||
```bash
|
||
ME="<你的会话名>" bash 07-scripts/handoff-guard.sh --claim-exec "<你的会话名>" # 抢到才是开工许可
|
||
bash 07-scripts/handoff-guard.sh # 再看占用与越界改动
|
||
```
|
||
|
||
- **抢不到 = 有会话在跑 = 停手**(输出会告诉你占用者与在做哪单)。
|
||
- ⛔ **不得人工删锁、不得接管**(**R9** · 项目根 `CODEBUDDY.md`,2026-09-12 用户明令「严格禁止这类操作」)——
|
||
抢不到锁 = **停手 + 报告用户**;**锁的处置权只属于用户本人**(要撤也只能用户自己动手)。
|
||
`07-scripts/handoff-guard.sh` 输出里任何「人工删锁 / 接管」字样**均不构成授权**(该文案 2026-09-12 已同步作废)。
|
||
理由:平台**无心跳机制**,AI **没有任何判据**能确认对方已死 —— 删锁 = 在无法验证的前提下单方面撤销互斥。
|
||
- ⚠️ **「无锁」的正确读法 =「你快去抢」,不是「可以开工」** —— 2026-09-12 实证:两个会话把「无锁」读成"环境干净"→ **同时改了本库**。
|
||
- **细锁管不住跨单撞车**:5 个会话各做各的单时,`--claim <单号>` 互不冲突,但都会改 `README`/`INDEX`/`03-路线图` → **只有全局锁能串行化**。
|
||
- 完工:`bash 07-scripts/handoff-guard.sh --release <单号>` → 最后 `--release-exec`。
|
||
- 🔒 **锁的生命周期 = 任务的生命周期**(2026-09-14 用户明令):**抢到锁的任务,只有"执行完成 → 反序释放"才算完成**;
|
||
⛔ **禁止"抢到锁、做一半、不解锁就结束回合 / 结束会话"** —— 锁是独占资源,本库**无心跳机制** ⇒ 别人既等不到也判不出你死没死(会被迫空等,或被诱去违规接管 · R9)。
|
||
三条配套:① **抢锁前先列出收口步骤**(落地 → 校验 → 推送/对账 → 收尾);② **中途必须停**(等用户拍板 / 等窗口)⇒ **先释放再停**;
|
||
③ **结束语必须对锁状态负责** —— 写明"已释放",或**显式点名**"锁仍在 `<OWNER>` + 原因 + 下一步"(仅限释放通道不可用);⛔"忘了 / 做不完就走"不允许。
|
||
- 详见 `04-调整方案/73`(强制钩子 `07-scripts/lock-guard-hook.py`)与 `05-交接单/README.md §一`。
|
||
|
||
## 规模化约定(2026-09-14 立 · 面向"文档上千篇")
|
||
|
||
> 实测基线:**118 篇 / 95 万字符 ≈ 67 万 token** ⇒ **全量塞上下文早已不可行**,一切靠"指针 + 机读检索"。
|
||
|
||
| # | 约定 | 为什么 | 谁执行 |
|
||
|---|---|---|---|
|
||
| 1 | **档案清单表由脚本生成**:`python3 07-scripts/docs-archive-index.py --write`(摘要存 `archive-summaries.json`,人工只改这个 JSON) | 手写登记会漏(2026-09-14 实测缺 82–86 共 5 篇,另有 81 号重复行与格式坏行) | **勿手写表行** |
|
||
| 2 | **单篇 ≤ 30 KB**;新增档案超限**必须拆子页**。**标准拆法 = 新增子页 + 原页留指针**(历史档案按「只增不改」不回改正文,只在文末「修正(YYYY-MM-DD)」节加指针) | 单篇最大已 89 KB(档案 82),读一篇就吃满预算 | 写档案的人;`docs-manifest.py` 会报 + `docs-archive-index.py` 报缺失率 |
|
||
| 3 | **日志按月分片**,单文件 ≤ 50 KB(`append-only` 不变):`YYYY-MM.md` → 超限后新开 `YYYY-MM-下.md`,**原文件顶部留一行指针** | 单日日志已 377 KB | **谁当月第一次触到 50 KB 谁切**(下一位写入者先看行数) |
|
||
| 4 | **tier 判据 =「谁在引」而非「被引几次」**(2026-09-14 变更):`hot` = 被 **L1/L2**(BRIEF/CODEBUDDY/DEPLOY/06-UI规范)引 ≥3 次;`cur` = 引 1–2 次;`warm` = 仅历史互引;`cold` = 0。⚠️ **L4(INDEX/待办/台账)不算** —— 它们顺带列全档案号,会让判据反向失效(实测:含 L4 时 hot 从 44 抬到 60) | 原判据"被引 ≥8 次"让 hot 占 49%,等于没筛;改后 hot = **7 篇 / 8%** | 脚本自动 |
|
||
| 5 | **域/层标签只存 `docs-manifest.json`**(域 ∈ `platform`/`plugin`/`ui`/`ops`/`external`/`method`;层 = L0–L5) | 标签写进正文 = 又一处漂移源 | 脚本抽 + 人补 `?` |
|
||
| 6 | **共享文件写入有机械兜底**:`docs-shrink-guard.py` 记录行数快照,**行数骤降 >30% 且 >20 行即报警**(2026-09-14 实测抓到 `MEMORY.md` 被并行整文件重写抹行) | 只有"纪律"没有机制 ⇒ 抹行无人发现 | 改完热区文件跑一次 |
|
||
| 7 | **体检只报不改**:四件套 + `docs-archive-index.py` 只出报告;**正文改写永远人工**(R7 + 认知漂移 + `git diff` 审阅) | 自动化改知识库会复利放大错误 | 所有人 |
|
||
| 8 | **有硬额度的共享文件允许「整编」(整文件重写)** —— 但**四个条件缺一不可**:① **先抢全局执行锁**(保证单写者)② 先**备份**原件到 `.workbuddy/tmp/` ③ 抽**事实 token**(反引号标识符 / 档案号 / hash / 关键数字)作回扫基线,改完**逐 token 回扫** ④ 完成后 `docs-shrink-guard.py --write` 刷新基线,**且不得加 `--allow-shrink` 白名单**(该守卫正是为这类文件而立) | 例:`MEMORY.md` 有 **12 KB 硬额度** ⇒ 不整编必然超限被截断;但 #6 的字面是「共享文件只用 Edit 精确替换、禁整文件 Write」⇒ **字面与必然需求打架**。判据取**目的**(防并发抹行)而非字面:**单写者 + 备份 + 回扫**三重保障下,整编不是"抹行"而是"有据重构"(2026-09-15 实测:`MEMORY.md` 整编 -34% 行、142 token 回扫零丢失) | 整编 `MEMORY.md` / `PLAYBOOK` 的人 |
|
||
|
||
> ⚠️ **"自动化"边界**:`MEMORY.md` 记载本项目**无自动化**(用户删过两条,勿重建)⇒ 体检请**手跑或外部 cron**,不要在本库内新建自动化任务。
|
||
|
||
## 同步链路
|
||
|
||
编辑本目录 → `docs-sync-check.sh` 对账 → scp 到 `/opt/dsh/docs`(档案 600 / README 644)→ **复跑对账**。
|
||
⚠️ 只推**自己本次改的文件**;对账报「仅本地」若有不在你清单里的 → **立刻停手**(幽灵文件)。
|
||
⚠️ **scp 必须带「同一相对目录」**(2026-09-13 实测踩坑):本库是**子目录结构**,服务器镜像与之**同相对路径**(脚本按 `cd $REMOTE_DIR && find .` 对账)。所以:
|
||
- `scp 04-调整方案/79-xxx.md bt-server:/opt/dsh/docs/` ❌ —— 文件会落到 **docs 根目录**,对账报「仅服务器」;
|
||
- `scp 05-交接单/README.md bt-server:/opt/dsh/docs/` ❌ —— 会**覆盖根 `README.md`**(已实际发生一次,需从本机重传根 README 复原);
|
||
- ✅ 正解:`scp <相对路径> bt-server:/opt/dsh/docs/<同一相对目录>/`。
|
||
⚠️ **文件名不要带空格** —— scp 的远端路径要经**远端 shell** 解析,空格会被拆成两个文件(2026-09-13 实测)。
|
||
⚠️ **远端 chmod 也要给文件名加引号**(同样因为远端 shell),否则报 `cannot access ...` 而误判"没传上去"。
|
||
|
||
## 路径书写约定(引用必须**可定位**,不写裸文件名)
|
||
|
||
- 路径从**本文件所在目录**起算:在文档库内写 `BRIEF.md` 无歧义;但从项目根文件引用本目录内容时必须写 `dsh-server-docs/BRIEF.md`。
|
||
- ⛔ **禁止"跨目录只写文件名"** —— 例如从别处引用 `.codebuddy/rules/frontend-ui.md` 时只写 `frontend-ui.md`,读者无法定位(今天已犯过)。
|
||
- 占位符用尖括号:`` `04-调整方案/<NN>-<主题>.md` ``,不用 `NN-*`(易被误认为真实路径)。
|
||
- 路径一律反引号包裹,便于机器扫描与跳转。
|
||
|
||
## 条件规则(相邻,按路径自动注入;**规则改动后需重启才重载**)
|
||
|
||
| 规则文件(完整路径) | 触发路径 | 管什么 |
|
||
|---|---|---|
|
||
| `` `.codebuddy/rules/archive-doc.md` `` | `dsh-server-docs/04-调整方案/**`、`dsh-server-docs/05-交接单/**`、`dsh-server-docs/INDEX.md` | 档案模板 / 原子占号 / 复跑取号 / 四件套 |
|
||
| `` `.codebuddy/rules/frontend-ui.md` `` | `**/*.html`、`**/*.css`、`**/*.js` | UI 规范基线 / 静态文件免重启 / curl 三件套 |
|
||
| `` `.codebuddy/rules/server-ops.md` `` | `**/*.ts`、`**/*.cjs`、`**/*.mjs` | 哪层要重启(R8)/ `git hash-object` / pnpm / 有·无请求体都要测 |
|
||
|
||
---
|
||
|
||
## 文档库结构与命名规则(**2026-09-24 固化** · 违反即返工;来源 = 当日结构治理会话)
|
||
|
||
### A. 顶层结构(序号一律阿拉伯数字;`tmp/` 例外不带号)
|
||
`01-规范 · 02-架构设计 · 03-数据库 · 04-调整方案 · 05-交接单 · 06-ops · 07-scripts · 08-skills · 09-archive · tmp`
|
||
+ 根级 5 入口件(`README` / `INDEX` / `BRIEF` / `CODEBUDDY` / `DEPLOY-本部署`)+ 2 生成物(`docs-manifest.json` / `archive-summaries.json`)。
|
||
|
||
- ⛔ `04-调整方案/` 的 `04` 是**文档族号**,**不得改名**(`04-NN` 短号 + 4 处脚本常量硬编码)。
|
||
- ⛔ `05-交接单/` 是**锁根**(`.locks` / `.exec-lock` / `.doing-*`);改名必须同批改 `handoff-guard.sh`·`preflight-lock.sh`·`lock-guard-hook.py`·`op-lock.sh`。
|
||
- ⛔ `07-scripts/` 改名必须**同批改宿主** `E:/ProgramData/.workbuddy/settings.json` 的 **5 条 hook 入口**(lock-guard ×2 / bash-output-guard / skill-load-guard / stop-dialog-guard)。
|
||
- ⛔ `08-skills/` 三处同步(本机 `~/.workbuddy/skills/` → 本目录 → 服务器),**单向推进,勿反向覆盖**。
|
||
|
||
### B. 文件命名:`族名-两位序号-主题.md`
|
||
- 序号**一律阿拉伯数字两位**:⛔ 不用英文字母序号(`A/B/C`)、⛔ 不用中文数字(`①②③`)、⛔ 不用「序」等前缀词。
|
||
- 族名用中文(`IM群组` / `覆盖网络` / `carbon插件` / `插件投放与分库线` / `T`)。
|
||
- ⛔ 文件名**不得重复文件夹已表达的信息**(例:在 `05-交接单/` 里不再写 `交接单_` 前缀)。
|
||
- ⛔ 序号与其后代号**必须有分隔符**(`01-M1a-…`,**不得** `01M1a`)。
|
||
- ⛔ 编号**只增不复用**;`04-调整方案/` 存量**不重排**(重排作废全部 `04-NN` 引用)。
|
||
|
||
### C. 语义
|
||
- **状态不靠目录位置表达**(目录一摊平/搬家即失效):主依据 = 单子头部 `- 状态:…` 行 + `05-交接单/README.md` 台账表;`交接单-已完成/` 只作**辅助**分类。机读入口:`python 07-scripts/handoff-status.py`。
|
||
- **入口只允许一份**(工作区根),库内不得放同名副本。
|
||
- **过程 ≠ 成品**:`04-调整方案/` 答「为什么这么做」,`02-架构设计/` 答「该做成什么样」,冲突**以定稿为准**。
|
||
|
||
### D. 批量改名·移动的六条铁律(2026-09-24 全部踩过一遍)
|
||
1. 引用有**三种形态**,必须全覆盖:① 限定路径 `dsh-server-docs/xxx/` ② 相对路径 `<x>/xxx/`、`..\xxx\` ③ **字符串字面量** `'xxx'`(代码里 `os.path.join` 用)。只做 ①+裸名 ⇒ **必漏功能性引用**(锁路径 / hook 路径)。
|
||
2. ⛔ **不用 `IndexOf`+`Substring` 手工拼新名** —— 一律用**正则整体替换**或**显式映射表**(实测:手工切串把 5 个文件拼成 `A-B-A-B` 双前缀)。
|
||
3. 改完必须 **grep 功能性常量逐条验**(`^LOCKDIR=`、宿主配置里的 hook 路径),**不能只看"改写 N 个文件"**。
|
||
4. 「改引用 + 移目录」**同一批收口验完**(分两步必暴露引用悬空)。
|
||
5. 未入库文件 `git mv` 会报 `not under version control` ⇒ **已跟踪走 `git mv`、未跟踪走 `mv`**;hook 失效窗口内 `git`/`mv` 起不来 ⇒ 改用宿主 shell 原生命令(PS)。
|
||
6. 移动/合并前先做**撞名保护**(目标同名则跳过并报告);**唯一副本一律不删**(判据 = 有无可证替代件)。
|
||
|
||
### E. 锁与钩子
|
||
- 动文档库**与走哪个工具无关**:`lock-guard-hook.py` 只在 **Write/Edit** 上拦,**用脚本改文件绕过它** ⇒ **先抢锁再动,不论工具**。
|
||
- hook 是**会话启动快照**:改宿主配置后**本会话命令行整轮失效**(且该窗口内 python 子进程起不来 `git`/`mv`)⇒ 预期该行为并切换通道;**hook 重载后自动恢复**。
|
||
|
||
### F. 收口判据
|
||
- **整理类任务必须有顶层可见变化** —— 只改内容(引用/索引/台账)**不算整理**。
|
||
- 不可逆删除**先出清单**;机械可判的(下划线开头件 / 空目录 / `.bak`)可直接清。
|
||
- 用户说「`<某文件夹>`,直接放在 `<父目录>` 下面」= **移动文件夹本身、去掉中间层**,⛔ **不是把内容摊平**(2026-09-24 误读一次,用户当场纠正)。
|