Files
dsh_ai1net_server/dsh-server-docs/skills/dsh-knowledge-upkeep/SKILL.md
T
admin bc0dd2c96d docs(dsh-server-docs): mksess 口径校正(DB 直插→PG 直插)+ 技能 dsh-auto-handoff-chain 三处同步建立(序⑰ S1/S2)
- 02-运维手册.md:mksess 命中处补「PG 直插 + 连接串来源」+ D1 勘误指针两行(档案 77 的旧形态说明,正文不改)
- skills/dsh-change-workflow/SKILL.md(146/395/495 三行)、skills/dsh-env-bootstrap/references/常驻规则-快照.md(55 行):同口径校正
- skills/dsh-auto-handoff-chain/:新建文档库副本(SKILL.md v1.3.2 + scripts/chain_report.py),此前该技能三处同步从未建立
- README.md / INDEX.md:登记该技能(技能表 + 「什么时候查什么」+ 技能清单表)

判据:E1 = 0 行、E2 两副本 md5 全同、E3 diff -r = 0 行、E4 登记命中 README 1 / INDEX 2、镜像 47 同值
2026-09-17 17:03:34 +08:00

230 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
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.
---
name: dsh-knowledge-upkeep
description: dsh 平台文档库 / 项目知识的**维护与纠偏方法**。当发现「文档与现状不符」「同一事实多处打架」「知识越积越碎」「AI 忘了某条规则」「要收敛或重构知识库结构」时使用;也用于定期体检。核心 = 六层知识结构(L0-L5)+ **分层判据(实体 vs 指针)** + Lint 四件套 + **漂移处理 SOP** + **自动化的边界(检测可自动,改写不可自动)** + 今天踩过的 5 个反例 + **§8.6「注入预算」维度**(每轮注入有上限 ⇒ 长文件后半段等于不存在;**先重排、后删减**)。**配套:`dsh-feature-first`(谁定什么)· `dsh-decision-method`(怎么定得对)· `dsh-change-workflow`(怎么落地)。**
version: 1.2.0
updated_at: 2026-09-16
agent_created: true
---
# dsh-knowledge-upkeep — 知识库维护方法
> **一句话**:知识库不会自己变好,**只会慢慢变错**。本技能把"纠错"从临时动作变成**可复跑的方法**。
> 素材来源:2026-09-12 全库校验实证(20 项违背 → 0)。
---
## 0. 为什么需要它(实证,不是理论)
| 现象 | 实测 |
|---|---|
| **同一事实被抄很多份** | 现行域名出现在 **21 个文件 / 123 处**;档案"下一号"写在 4 处且**互相打架**(72 / 69 / 53 / 20) |
| **过时值长期存活** | 旧配额活在 15 个文件;实例 MemoryMax 曾同时存在两个"现役值" |
| **权威源头本身是错的** | `BRIEF.md`(首读现状卡)自己带着旧值 → AI 老老实实读了它,读到就是错的 |
| **校验工具查不到** | 原 `docs-audit.py` 只查**结构**(编号/悬空/重复),**不查事实** → 漂移不可见 |
| **规模已超"全量塞入"上限** | 库 = 93 md / 555,533 字符 ≈ **388,873 tokens**;Karpathy 模式实证 **~100 篇就崩**(模型开始略读并给出自信的错误答案)|
---
## 1. 知识结构:六层 + 单一来源
| 层 | 内容 | 唯一权威 | 变更频率 | 送达方式 |
|---|---|---|---|---|
| **L0 不变量** | 架构与机制(为什么这样设计) | `01-规划与架构` + 早期档案 | 年 | 按需 |
| **L1 现行值** | 现在到底是什么(域名/配额/端口/路径/阈值) | **`BRIEF.md`** | 周 | 首读 |
| **L2 规则** | 必须遵守(提问判据/红线/提交边界) | **`CODEBUDDY.md`** | 很少 | **自动注入** |
| **L3 方法** | 怎么想、怎么做 | 3 个 dsh 技能 | 月 | 按需触发 |
| **L4 状态** | 现在在哪(待办、落差) | `交接单/` + `.workbuddy/memory/MEMORY.md` | 天 | **自动注入** |
| **L5 历史** | 怎么变成现在这样 | `04-调整方案/` + `archive/` | **只增不改** | 按需 |
**三条铁律**
1. **每个事实只有一个权威** —— 其余文件**只许写指针,不许复制数字**。
2. **L5 冻结** —— 历史档案里的旧值**不回改**(写的时候是对的,回改破坏历史);需要修正时**在文末追加「修正(YYYY-MM-DD)」小节**,并改 L1 的现值。
3. **校验必须能查"事实一致性"** —— 否则前两条必然失守。
---
## 2. 分层判据:**什么必须实体,什么可以只给指针**
> **"不做会违规、会出事"的 → 实体保留;"看了更准但不看也不违规"的 → 才给指针。**
| 处理 | 内容 |
|---|---|
| **实体保留**(压缩不许删语义) | 提问判据 · 红线 R1–R8 · 提交边界 · 规划/执行分离 · 并发纪律 · **会导致事故的实测事实** · 环境要点 |
| **只给指针** | 平台现状与历史细节 · UI 规范全文 · 档案模板细则 · 某功能的实现内幕 |
⚠️ **指针必须绑定可识别的动作**,否则"去查"不会发生:
`当你要写前端页面 → 先读 06-UI规范`,而不是 `详见 06-UI规范`。
---
## 3. Lint 四件套(可复跑,退出码可接 CI)
```bash
python3 scripts/docs-audit.py # 结构:编号冲突 / 标题号不符 / 悬空引用
python3 scripts/docs-manifest.py # 刷新机读清单 docs-manifest.json(含被引次数/tier)
bash scripts/docs-sync-check.sh # 双端对账(本机 ↔ /opt/dsh/docs)
python3 scripts/docs-consistency.py # 事实:写死取值 + 跨页取值冲突
```
**`docs-consistency.py` 的设计要点**(写它时踩过的坑,别重踩):
- 只查**高置信**模式。首版把「旧域名」「旧配额」当违规 → **几乎全是误报**(库里都是"旧域已 301" / "512M→384M" 的合法表述)。
- **引号感知**:引号内的匹配 = **引用历史**,不是断言,不算违规。
- 判据 = 「**承诺现行**的文件不许含已废止/写死/矛盾的取值」;
**历史豁免**:`04-调整方案/**`、`archive/**`、`01-规划与架构`、`02-运维手册`。
**建议补跑(不在四件套内,但会毁可读性)—— 编码合法性**
```python
for p in all_md: # 用 open(p,'rb').read().decode('utf-8') 整块判,别逐字节
try: open(p,'rb').read().decode('utf-8')
except UnicodeDecodeError as e: print(p, e.start)
```
🔴 **只有几个非法字节也会毁掉整份文件**:自动编码检测判"不是 UTF-8"⇒ 走偏为 GBK ⇒ **整份读出来全乱码**。
(2026-09-16 实测:212 KB 的日志因**开头 2 字节**坏 ⇒ `Read` 全文乱码。处置见 `PLAYBOOK §10.1`。)
---
### 3.1 交接单的「口径指纹」—— 改正文必连带(2026-09-16 实测)
| 项 | 内容 |
|---|---|
| 算法 | `tail -n +4 <单子>.md \| md5sum`(**跳过前 3 行**:标题 / 空行 / 指纹行) |
| 含义 | 前 3 行**不参与** ⇒ 改指纹行本身不破指纹;改**正文任何一字** ⇒ 指纹必变 |
| 引用点 | ① 单子第 3 行 ② 接续包/入口里对它的引用 ③ 记忆(`MEMORY.md` / 日志)里记的值 |
🔴 **改完单子正文的正确收尾顺序**:改正文 → **复算指纹** → 写回第 3 行 → 用脚本**全文 `replace`** 所有引用点(⛔ 别手改)→ 复算自证「实算值 == 三处登记值」。
⚠️ **一次要改多处正文时,先全改完再算一次**(实测改两轮 ⇒ 指纹算三轮 ⇒ 白绕 2 轮工具调用)。
**⛔ 最容易漏的不是单子,而是"单子之外"的过期口径**(本轮真漏过一次):
```bash
grep -rn '<旧口径关键词>' --include='*.md' . # 例:未修 / 待专门一轮 / 已定位、未修
```
- **文件顶部 `>` 摘要块最容易残留** —— 下一棒第一眼读的就是它。
- 单子的**历史章节**(如"§11.6 当时未修")**保留原文 + 加勘误段/标题后缀**,别删 —— 历史可追溯,且不会误导跳读者。
---
## 4. 漂移处理 SOP(发现 → 收敛,五步)
```
① 发现 → 四件套任一项退出码非 0
② 定性 → 真漂移 / 合法历史表述 / 校验器误报 ← **这一步不能跳**
③ 定权威 → 这个事实的**唯一权威**是哪一层哪个文件(见 §1)
④ 收敛 → 改权威文件;其余副本改为指针或删除;写死值改为"复跑取号"
⑤ 复跑+同步 → 四件套全绿 → scp → 复跑 docs-sync-check.sh
```
**② 定性是分水岭**——2026-09-12 首跑报 20 项,逐条看上下文后:
- 真漂移 **≈6 项**(下一号三处矛盾、MemoryMax 两处取值不一致、`maidou`、旧路径、SSH 端口)
- **合法历史 14 项**("旧域已 301" / "512M→384M" 的迁移表述)
⇒ 若不做定性就批量改,会**破坏历史档案**并制造新错误。
---
## 5. 自动化的边界(**重要**)
| 动作 | 可否自动 | 理由 |
|---|---|---|
| **检测**(跑四件套、出报告) | ✅ **可以,且应该** | 只读、零风险、退出码可判定 |
| **刷新派生件**(`docs-manifest.json`) | ✅ 可以 | 纯派生,无人工语义 |
| **改写正文 / 批量替换** | ❌ **不可以** | ① 触 **R7**(批量写入须确认)② **认识论漂移**:LLM 改知识库后,错误会成为后续输入并**复利放大**(LLM Wiki 社区已实证)③ 研究员明确指出:**git diff + 人工审阅才是真正的安全网** |
| **删历史档案里的旧值** | ❌ 不可以 | 违反铁律 2(L5 冻结) |
⇒ **推荐形态**:自动任务**只做"体检 + 出报告"**,**发现违背时通知人**,由人或新会话按 §4 SOP 收敛。
---
## 6. 反例(今天真实踩过,别重犯)
| # | 反例 | 后果 | 规避 |
|---|---|---|---|
| 1 | 校验规则太宽(拿"旧域名"当违规) | 20 项里 14 项误报 → 校验器被忽视 | 只留高置信模式;拿不准就不查,改人工 |
| 2 | 改了**技能工作副本**却忘了**归档副本** | 校验器扫的是归档副本 → 改了等于没改 | 技能两处位置必须同步(md5 一致) |
| 3 | 备份文件 `*.bak-*` 留在**文档库内** | 污染 `docs-sync-check`(算成"仅本地") | 备份放库外,或收尾删掉 |
| 4 | scp 时把 `scripts/x.py` 也推到**根目录** | 服务器多一份同内容副本 → 对账报"仅服务器" | scp 目标路径逐个核对 |
| 5 | 把"下一号"写死在入口文档 | 并行改动 3 次打穿(83→85→87) | 一律"复跑取号" |
| 6 | **只看根目录就说"本机没有这个文件"** | 实际在 `scripts/` 下 → 结论完全相反(今天两次) | 报"不存在/缺失"前先 `find` 全库 |
| 7 | **把问题抛给用户前没确认它还在** | 服务器多余文件已被并行会话清掉 → 问了个**已消失**的问题 | 抛出前重新查一次;状态会被别人改变 |
| 8 | 没顺着 grep 找权威档案就猜文件用途 | 直接读关联档案的 TL;DR 一句话就清楚,比猜快得多 | `grep -rn <文件名> --include="*.md"` → 读那条档案的头部 |
---
## 7. 自检清单(每次动知识库前后)
**动手前**
1. 这个事实的**唯一权威**在哪一层?我是不是正准备在别处复制它?
2. 我要改的是**承诺现行**还是**历史**文件?历史的 → 不回改,追加"修正"小节。
3. 涉及 >10 文件?→ 先出清单(R7)。
**收尾**
4. 四件套**全绿**了吗?
5. 两处技能副本 md5 一致吗?推服务器了吗?
6. 临时/备份产物清了吗?
7. 复数入口都改成"复跑取号"了吗?
---
## 8. 文档的「无效信息」分类与高价值写法(2026-09-16 加)
> **起因**:用户问「AI 会话生成的文档是否有无效信息?是否需要一套方法,写出**简单明了、高价值、且不影响模型阅读**的文档?」
> §4 处理的是「漂移」**一类**;本节把它扩成 **六类无效信息** + **不能删的红线** + **写作形态**。
### 8.1 唯一判据(正反两面)
> **去掉这一行,下一个会话会不会「做错事」或「变慢」?**
> **会 ⇒ 必须留**(还要让它落在首屏);**不会 ⇒ 可删 / 可降级到归档。**
正面用法(决定"值不值得写"):**这行会改变读者的下一步动作吗?** 不会 ⇒ 它只是背景装饰,压缩或删。
⛔ **别把"更简洁"当目标** —— 目标是**行为相关性**。把必要的「为什么」删掉,AI 会在同一处**反复摇摆**,那是负收益。
### 8.2 六类无效信息(2026-09-16 全部亲见,不是理论)
| # | 类型 | 当日实例 | 处置 |
|---|---|---|---|
| 1 | **与可执行体不符** | `stop-dialog-guard.py` 注释写「15 万/120」,代码是 `120000/80` | ⛔ 以**代码 / 实测**为准改注释,不是反过来 |
| 2 | **过期结论仍占"生效位"** | 记忆里「hook 确实在生效(09-13 取证)」——当天已被推翻 | **不删**:标注「已推翻 + 新结论 + 日期」,保留纠偏轨迹 |
| 3 | **同一事实多处重复** | 同一技能在本机 / 文档库 / 镜像三副本 | 收敛到**单一来源**,其余只留指针(§2) |
| 4 | **过程流水挤掉结论** | 日志里「我做了什么」淹没了「现在是什么状态」 | **结论前置**;流水降级到日志 / 附录 |
| 5 | **中间产物混进正式文档** | 项目根 `_tmp_*`、`_中间产物_待清理/`(239 文件) | 集中到归档区,永不进正式文档;收尾清 |
| 6 | **只写"给人看的套话"** | 「这个很重要」「要注意」—— 不含任何判据 | 换成**可执行判据**:什么条件下、做什么动作 |
### 8.3 ⛔ 不能删的红线(「不影响模型阅读」的边界)
**删「结论的装饰」,留「判断的依据」。** 以下五类删了会直接坏事:
1. **判据与阈值**(数字 / 边界条件 / 优先级)
2. **命令原文与路径** —— 删了 AI 得重新试错,这是**最贵的成本**
3. **反例与踩坑**(现象 → 根因)
4. **「为什么」(决策依据)** —— 删了会在同一处反复摇摆
5. **失效 / 作废标注** —— 删了会让旧做法「复活」
### 8.4 高价值文档的形态(动笔前先定这五条)
1. **结论先行** —— 首屏 3 行给判定
2. **状态与流水分离** —— 状态(现在是什么)= 常驻;流水(怎么变的)= 追加 ⇒ **分文件放**
3. **一事实一处** —— 其余给指针
4. **可执行** —— 给命令 / 判据 / 路径;⛔ 不给"建议注意"
5. **排版** —— 按 `dsh-feature-first §5.4`(每节 ≤7 行 / 表格 ≤5 列 / **并列项各占一段**)
### 8.5 自检三问(贴出去之前过一遍)
1. **读者是「下一个会话」**(不是人)—— 它读完能**直接动手**吗?
2. 这份里**有多少行会改变下一步动作**?占比低 ⇒ 该压缩。
3. 我删掉的每一行,**有没有落在 §8.3 的红线**里?
### 8.6 「注入预算」维度 —— 长文件的后半段等于不存在(2026-09-16 加,实测)
> §8.1–§8.5 用「**行为相关性**」判该不该留。另有一条**独立于内容质量**的约束:
> **每轮注入是有上限的** —— 超出上限的部分宿主不会给模型,**效果上等于这段不存在**。
- **实测(2026-09-16)**:用户级 `MEMORY.md` 20,977 B / 11,712 chars,宿主**注入上限 ≈ 4,000 chars**。原排序下窗口只覆盖「钩子配置 + 环境路径」,**整节 `Preferences`(全部行为规则)落在窗口外** ⇒ 规则没写错,是**排序错**。
- **⇒ 判据升级**:一份「每轮都要生效」的文件要同时过 **两条** —— ① 每行都过 §8.1 的判据;② **体量 ≤ 注入上限**(或硬规则必须全部落在窗口内)。超限时**先重排、后删减**:重排零损失,删减有丢规则风险。
- **⛔ 不要用「删内容」解决超限**,正确顺序是:
1. **分类** —— 哪些是「每轮必须生效」(硬规则 / 事故级事实 / 禁令),哪些是「查阅型」(历史细节 / 取证过程 / 个别项目偏好)
2. **把硬规则整体排到最前**,使注入窗口正好覆盖它们
3. 查阅型内容留在窗口外**不算丢失**(本机仍可读),只需在其上方留一行指针
4. 重排仍不够才压措辞 —— 且**受压的必须是查阅型,不得压判据与命令原文**(§8.3)
- **📌 排序契约(防复发)**:文件头必须显式写明「**注入上限 ≈ N 字符;排序即重要性;新增内容按序插入对应小节,⛔ 不要追加到末尾**」。少了这一行,下一次追加就会把重要规则顶出窗口 —— 这是**慢性失效**,没有任何报错。
- **适用面**:一切「每轮注入」的文件 —— `MEMORY.md`、`CODEBUDDY.md`、`.codebuddy/rules/*.md`、各技能的 `description`。
- **可复跑自检**:`wc -c <file>` ÷ ~1.8 ≈ 字符数,与上限比;**更直接的判据 = 看注入块结尾有没有被截断**(结尾被截断 ⇒ 已有内容在静默失效)。