Skip to content

知识库(Knowledge Base)建设方案

状态:待实施(2026-09-01 立项,评估已完成、选型已裁定,尚未动工)。 一句话:把散落在 docs/ / CLAUDE.md / docs/cross-end/ / docs/plans/archive/ 里的 解释性知识收敛成一棵有唯一归属的知识树,用 VitePress 就地渲染成可在手机上读的站点。 裁定独立站,不挂 admin(论证见 §2)。站点源就地放 docs/.vitepress/不新增顶层目录、不搬运任何内容

🔴 本 plan 刻意不定义任何红线(根 CLAUDE.md §4「红线归属规则」: 红线绝不能只存在于会被归档的一次性计划里)。实施中会产生两条不变量, 它们的稳定归属在 §5.3 指定,本文件只留指针。


0. 结论先行

问题结论
这个想法合理吗✅ 合理,且填的是一个真实空白 —— 但瓶颈不是缺阅读界面,是知识层几乎还没写
挂 admin 还是独立站独立站。挂 admin 的三条论据实测全部站不住(§2.1)
要不要先挂 admin 过渡不要。过渡方案的全部前端投入最后都要扔(换栈,非同栈平移,§2.2)
要新建顶层目录吗❌ 不用。VitePress 就地跑 docs/.vitepress/docs/ 已在 layout 白名单里
最有价值的单点设计新鲜度徽章(§5.1)—— 它把「文档腐烂」从不可见变成可见。⚠️ 不依赖站,P2 做成终端输出时价值就已到手
站点生成器为什么不用 React 生态三条硬需求筛,Nextra / Starlight 直接出局,Docusaurus 落选于成本。判据留档在 §4.0,别重开
第一步该做什么不是做站,是把 §3.1 树里第 3 层那 4 条空枝写出来

1. 为什么做:现场盘点

数字为 2026-09-01 本机实测。别信本文的数字过三个月 —— 现算命令在 §9。

1.1 「读了能理解项目怎么运作」的文档只有 5 份

以用户点名的 recommendation-algorithm.md 为标尺分类:

类别文档上架判断
知识型recommendation-algorithm.md(429 行) · architecture.md(339) · vocabulary-domain-knowledge.md(243) · database-tables-overview.md(233) · product.md(202)上架主体,就这 5 份
规范型coding-standards.md · ui-standards.md · ui-component-inventory.md上架,另立一层
字典型database-schema.md(744)上架,当参考手册
Runbookdatabase-operations.md · supabase-backup-restore-runbook.md · smoke-test-runbook.md上架(手机上照着做反而有用)
验证清单docs/verification/ 9 份上架
记述层docs/cross-end/ 66 + docs/plans/archive/ 167 + docs/archive/ 13 = 246 份🚫 不进树,只做可搜索溯源

另有 rvh/docs/ 60 份(含 12 份移动端 Material 3 设计规范)—— 本轮不动(见 §8)。

1.2 真正的知识大半不住在 docs/

这是本次盘点最重要的发现:

  • 双端契约红线正文(RB #5i / #6d / #6e / #9 / #10,约 21.9 KB)住在恒加载的CLAUDE.md §4
  • 同步协议没有全景 —— 散在 §4 五条红线 + 66 份 docs/cross-end/,没有一份「sync 是怎么工作的」
  • 学习循环没有全景 —— 只有 verification/learning-loop.md 这份验证清单(问句,不是解释)
  • 词库 pipeline 没有全景 —— tools/README.md + /vocab-reseed skill + docs/cross-end/24-* 三处拼

⇒ 知识树的价值不在于把已有 5 份换个地方显示,而在于逼出这 4 条空枝

1.3 与 context-budget 那条线合流

verification/context-budget.md 的棘轮要求恒加载区持续瘦身, 而被移出去的「为什么」需要一个可召回的家。目前的家只有两个,都不够:

现有落点为什么不够
记忆库(MEMORY.md 索引,条目个位数)容量与形态都不适合承载「一篇能读懂子系统」的长文
docs/plans/archive/按归档区约定是历史记述、不该当规则读 —— 放进去等于让它消失

知识层就是那个缺失的第三落点。

🔴 但这不是「§4 该减重」的论据。 本方案与 verification/context-budget.md §3 的裁定 A (21.9 KB 双端契约红线正文留在恒加载区,2026-08-30 用户拍板,"同一件事已被裁过三次") 不冲突,也不以此为由重开它。两者的分工写在 §3.2 ④ —— 那一条是本方案的前提,不是它的目标。


2. 选型:独立站,不挂 admin

2.1 挂 admin 的三条论据实测全部站不住

论据实测结论(2026-09-01)
「手机上随时能看」与挂 admin 无关。手机可读来自「部署到公网 + 响应式」,独立站同样有。而且现状是反的admin/app/admin/(dashboard)/layout.tsxflex h-screen + 固定 w-60 侧边栏,无折叠 / 无 Sheet / 无 md:hidden;全 admin 响应式断点仅 34 处,sidebar 0 处。挂上去等于先欠一笔「给 admin 做移动端适配」的债
「已有登录,省事」唯一成立的一条,且只有这一条
「不用另起服务」❌ 反而更贵:三栏布局 / 页内 TOC / 全文搜索 / 代码高亮,在 admin 里每一样都要自己写,而 VitePress 开箱即给

两个额外发现的坑(挂 admin 特有)

  1. 🔴 改文档不会重新部署,且无任何报错.github/workflows/ci-admin.ymlpaths 只有 admin/**;Vercel project lampio-admin 的 Root Directory 也是 admin。 ⇒ 改 docs/** 既不触发 CI 也不触发 Vercel,线上文档永远停在上一次改 admin 代码的时刻。 (绕开它需要「构建期预编译 + 产物入库 + CI 漂移断言」一整套 —— 独立站方案里这套整个不需要。)
  2. 🔴 高频内容管线耦合进低频高危部署。知识库要「不断整理归纳」=高频变更; admin 持 SUPABASE_SERVICE_ROLE_KEY =低频高危。一篇 md 语法坏了、生成脚本崩了, 阻断的是 admin 的整个部署。方向本身就是错的。

2.2 landing 的类比不成立,而且是反的

landing/CLAUDE.md 写明拆分理由:公开访问 + 隔离 service_role 爆炸半径。 知识库两条都不占(私有访问、零后端调用、无密钥)。

更关键的是拆分成本性质不同

landing 拆分(2026-07-19)知识库「先挂后拆」
Next.js → Next.js,同栈平移Next.js → VitePress,换栈
代码页面组件直接搬渲染层全部重写

⇒ 过渡方案的全部前端投入最后都要扔掉,成本 ≈ 最终方案,收益为零。

2.3 对比表

维度挂 admin独立站(docs/.vitepress/
手机可读❌ 要先给 admin 做适配✅ 开箱响应式
三栏 / TOC / 搜索 / 高亮自己写,数百行✅ 免费
部署触发🔴 要绕 paths + root-dir 两个坑✅ 无
访问控制✅ 复用两层鉴权门⚠️ 配一次 Access(§4.2)
与 admin 耦合🔴 内容错误阻断后台部署✅ 隔离
新增顶层目录✅ 无✅ 无(就地,docs/ 已在白名单)
内容源要预编译 + 产物入库✅ 直读

🔑 决定性的一条:写渲染层是持续成本(每加一个能力写一次), 配访问控制是一次性成本

2.4 裁定

直接做独立站,不走过渡。 admin 侧边栏加一行外链指向知识库即可(零成本,两边都有入口)。


3. 体系设计

3.1 层级树

第 3 层是主干,也正好是现在最空的一层(呼应 §1.2):

知识库
├─ 1 产品与定位        docs/product.md
├─ 2 系统全景          桌面端架构 · 移动端架构 · 后端与契约 · 三端关系
├─ 3 核心机制  ★主干(5 条缺 4 条)
│   ├─ 同步协议        ← 待写(散在 CLAUDE.md §4 + 66 份 cross-end)
│   ├─ 学习循环        ← 待写(查词 → 生词 → cloze → SM-2)
│   ├─ 推荐系统        ✅ docs/recommendation-algorithm.md
│   ├─ 词库与归一      ← 待写(pipeline / lemmatizer 四层 / 键空间)
│   └─ 阅读与快照      ← 待写(Multi-Webview / content-script / 快照存取)
├─ 4 领域知识          docs/vocabulary-domain-knowledge.md
├─ 5 数据              表概念地图 · 列级字典 · 迁移史
├─ 6 规范              代码 · UI(桌面 / 移动两套,刻意不合并)
├─ 7 运维              3 份 runbook + 9 份验证清单
└─ 8 决策档案          cross-end 66 + plans/archive 167 —— 只可搜索,不进树

3.2 四条设计约束

① 知识层文档必须成为该知识的唯一真相源。/docs-audit 的第一条判据就是「同一事实在两处并行维护」。 「就某个知识点整理归纳然后挂上去」如果字面执行,就是在造第二本账。 正确动作 = 把知识迁移到知识层,原处(plan / cross-end / CLAUDE.md)改为指针 —— 即 §4「红线归属规则」已在用的那套。🔴 摘要一份挂上去 = 立刻开始漂。

② 记述层不进树,但要可搜索。 246 份 cross-end / plans/archive 是历史记述 (按归档区约定不该当规则读)。进树会稀释知识层;不可搜索又失去溯源能力。 ⇒ sidebar 不列,全文搜索覆盖。

④ 知识层写「解释」,CLAUDE.md §4 留「规则」—— 这两者不是第二本账。

自审时发现的最大风险:写一篇「同步协议全景」时,很容易顺手把 RB #5i/#6d/#6e 的条文 抄进去 —— 那一刻就造出了第二份红线,而且是恒加载区那份的副本,漂了没有任何东西会红。

边界写死如下,/kb skill 第 1 步必须问这个问题:

内容归属
规则做错会出事、每会话都要可见的条文CLAUDE.md §4(不动)
解释系统怎么运作 · 五条红线之间什么关系 · 当初为什么这么定知识层

🔴 知识文档不复述规则条文,只链接过去。 判据:把知识文档删掉,规则是否仍然完整? 必须是「是」。

③ 上架范围 = 全部(整站保护),不做分层公开。 文档不含密钥,但会暴露鉴权判据 / CSP 取舍 / ops 状态规则。 分层判定是持续的认知负担,整站 Access 是一次性配置。


4. 技术方案

4.0 选型:为什么是 VitePress(2026-09-01 裁定)

留档理由:这是个看起来该重开的议题("本体是 React,站却是 Vue,不统一")。 判据写在这里,将来再问时先读本节 —— 别重跑一遍论证。

候选按三条硬需求筛,不按生态偏好筛:

① 内容源在仓库各处、零复制② 428 份无 frontmatter 的 md 直接可用③ 内置三栏 / TOC / 搜索
VitePress ← 选中srcDir 一行✅ 不要求✅ 全内置
Docusaurus(React)path: '../docs'✅ 从文件名 / H1 推断⚠️ 本地搜索靠社区插件
Astro + Starlight✅ content layer glob loaderStarlight 要求 title frontmatter✅ 内置 pagefind
Nextra(与 admin/landing 同栈)内容必须在项目内
  • Nextra 出局:内容必须在 content/ 下 ⇒ 把 §2.1 好不容易绕开的「复制内容源」原样带回来。 (它本是「与 admin / landing 同栈」最漂亮的答案,可惜过不了 ①。)
  • Starlight 出局:246 份记述层不可能逐份补 frontmatter,进不了 collection 就搜不到, 直接废掉 §3.2 ② 的「不进树但可搜索」。
  • Docusaurus 是唯一可行的 React 备选,落选理由是成本不是能力:webpack(本仓其余全 vite)· 依赖重一个量级 · 构建慢 · 本地搜索要挂社区插件 · 默认信息架构偏产品文档站 (版本化 / i18n / 博客)要逐个关掉。

⚠️ 一个反直觉的点,别再按错误直觉重开:换 React 生态node_modules 会更大、不会更小 (Docusaurus 是 webpack + React + MDX 全家桶)。若拿「减少依赖污染」当换栈理由,方向是反的。 (生态常识,未本机实测;真要定,各 pnpm add -D 一次量体积即可。)

🔴 两条配套裁定:源文件必须保持「哪都能读」

VitePress 这个选型只在下面两条都守住时才划算,它们不是自然而然的、要主动守。 共同判据:md 源文件是唯一真相源,站只是它的一种呈现(§3.2 ①「渲染 ≠ 复制」)。

① 主题层零 Vue 代码。 徽章、反向引用等一律走构建期注入transformPageData 钩子 + markdown-it 插件直接产 HTML), 不写 Vue SFC、不做自定义主题组件。这不是将就:这些数据本就在构建期从 git log 算出, 零客户端交互,组件化只会凭空引入一个你不写的语言。 守住它,「生态不统一」就只剩 package.json 里一个名义依赖行 —— 与 better-sqlite3 / esbuild 这些你同样从不直接写的 devDependency 同级。

② 文档只用标准 markdown,不用 VitePress 专有语法。 禁用自定义容器(::: tip / ::: warning)与内嵌 Vue(<script setup> / <ClientOnly>)。 理由是双读性 —— 源文件同时被三方读:

读者读的是用了专有语法会怎样
Claude 新会话仓库里的 .md读到一堆噪音标记
你(编辑器 / GitHub)同一批 .mdGitHub 上显示成乱码般的原始文本
站点访客编译后的 HTML正常 —— 只有这一方是好的

想要提示框效果 ⇒ 用现有的 > 引用块 + emoji(本仓已经这么做,效果也好)。

🔑 两条一起保住的是「零锁定」:哪天弃用 VitePress,删掉 docs/.vitepress/ 就完事, 428 份 md 一个字不用改。这也是 §7 那条「核心价值不依赖站」的技术基础。

⚠️ 各自最可能被无声破坏的时刻:① 在 P5 做徽章样式时顺手 .vue 一下; ② 写新知识文档时顺手 ::: tip 一下。两条都进 check-kb.mjs 的断言(§5.2)。

4.1 站点形态

docs/.vitepress/config.ts      ← 站点配置(srcDir = 仓根)
docs/.vitepress/theme/         ← 自定义主题:新鲜度徽章 + 反向引用

⚠️ srcDir 设成仓根是待验证的首选,不是既定方案(P0 的第一件事就是证伪它)。收益:

  • 实测 docs/ 根层 + verification 共 88 个 md 链接,其中 16 个跨出 docs/../CLAUDE.md / ../rvh/docs/** / ../scripts/README.md …)。srcDir 设仓根后 所有相对链接零改动直接有效(VitePress 原生做 .md 链接转换)。
  • 7 份 CLAUDE.md 一起进站 —— §1.2 指出的最大一块「不住在 docs 里的知识」由此可读。
  • rvh/docs/ 60 份 + scripts/ tools/ supabase/ 的 README 全部可搜索。

代价(2026-09-01 实测):srcDir=仓根意味着 428 份 md 全部进站 (排除 node_modules / build / .dart_tool 后的现数),其中 246 份是记述层docs/plans/archive/ 167 + docs/cross-end/ 66 + docs/cross-end/archive/ 16, 后者上一轮漏数了)。VitePress 默认 fail build on dead link,而归档区必然有大量 指向已删文件的历史链接 ⇒ 首次构建大概率红一片,配平要花时间。

🔁 退路(P0 证伪后走这条)srcDir 收窄回 docs/,只给那 16 个跨出 docs/ 的 链接配 rewrites / ignoreDeadLinks代价 = 7 份 CLAUDE.mdrvh/docs/ 60 份 不进站(§1.2 指出的最大一块知识因此只能靠链接跳回 GitHub)。 这是可接受的降级,不是失败。

配套srcExclude 排掉 rvh/build / dist 等(node_modulesdist 是 VitePress 默认排除项,不用重复配)。

4.2 访问控制 —— ✅ 已定:Vercel + Standard Protection

2026-09-01 已确认:账户为 Hobby 计划,Deployment Protection 可用且已在用 —— lampio-admin / lampio-landing 两个 project 当前都是 Standard Protection。 ⇒ 知识库作为第三个 Vercel project,零新增平台、零额外配置、与现有两个同构。 原备选 Cloudflare Access 降级为不需要。

🔴 一个会静默失效的陷阱:不要给知识库绑自定义域。Standard Protection 覆盖的是 preview 与 generated URL*.vercel.app), 不覆盖自定义域上的 production ⇒ 知识库就用 lampio-kb.vercel.app 这类生成 URL。

🔴 上面这段是错的,2026-09-01 P4 实测推翻(保留原文以免同一个错误被重新推导一遍)

错在把两种 *.vercel.app 当成了一种。 它们是不同的东西:

URL 形态例子Standard Protection 保护它吗
项目生产别名 = production 域lampio-kb.vercel.app不保护
每次部署的 generated URLlampio-5iy6uk1mc-ttfishnets-projects.vercel.app✅ 保护
preview 部署分支/PR 的 URL✅ 保护

判据是**「是不是 production 域」,与它是不是自定义域无关** —— 项目自动分配的那个别名 同样是 production 域。⇒ 「不绑自定义域」这条缓解从来没有生效过,它建立在错误模型上。

实测证据(2026-09-01):设置页显示 Require Log In 开启 + Standard Protection, 而无 cookie 请求 https://lampio-kb.vercel.app/ 返回 200。 —— 这也正是本节下面那条「验收方式不是看设置页」为什么必须坚持:唯一写对了的就是它

正确解法 = 把 Deployment Protection 改成 All Deployments 它保护 production 域,于是绑自定义域反而变安全了 —— 原来那个「绑域名 = 保护失效」 只在 Standard Protection 下成立。这一改同时解掉了 P4 撞上的另一个问题: *.vercel.app 在大陆直连不通(实测 curl 超时返回 000),而「手机上随时能读」 是本方案的主要立项理由之一。⇒ All Deployments + 自定义域(如 kb.lampio.app) 才是终态,两个问题一起解决。

🔴 2026-09-01 再订正:All Deployments 在 Hobby 上不可用。 截图实证 —— 该选项挂着 Upgrade,提示 "available on the Pro plan with Advanced Deployment Protection for $150 per month";Password Protection 同价。 ⇒ 上面写的「正解 = 改一个下拉框」不成立,Hobby 计划下 Vercel 侧没有可用的保护档位 能覆盖 production 域。 ⚠️ 同时有一个尚未解释的矛盾:Standard Protection 自己的描述是 "Protect all except production Custom Domains",而本 project 没有自定义域 —— 照这句话它应该被保护。而实测返回 200。两者必有一错, 裸状态码不足以定案(结论待「看响应体」的复验,见 backlog P0)。 若确认公开:Hobby 下的出路是换承载(本方案 §4.2 原备选 Cloudflare Access, Zero Trust 免费档,且对大陆连通性也更友好),或退回 §4.2 的兜底(本机 pnpm docs:dev + 局域网)。

验收方式不是「看设置页写着什么」,而是:部署后用无痕窗口访问站点 URL, 必须被 Vercel 登录页拦住(见 §7 P3)。手机首次访问需在浏览器登录一次 Vercel 账号, 之后 cookie 保持。

兜底(不部署时):本机 pnpm docs:dev + 局域网 IP,依赖电脑开着 + 同 WiFi。

4.3 渲染细节

现状 / 方案
全仓 md 零 mermaid,全是 ``` 里的 ASCII 图(recommendation-algorithm 22 个代码块)。<pre> 直接可显示,但手机上必然横向滚动。要修就构建期渲染 SVG,别用客户端 mermaid
代码高亮VitePress 自带 shiki,构建期完成,零客户端负担
🔴 主题层零 Vue 代码(§4.0 ①)。任何"页面上多显示一块东西"的需求,先问能不能构建期算完直接注入 HTML —— 到目前为止(徽章 / 反向引用)答案都是能
🔴 markdown 方言只用标准 markdown(§4.0 ②)。::: 容器与内嵌 Vue 一律不用 —— 源文件要同时被 Claude / GitHub / 站点三方读,专有语法只让第三方好看
搜索VitePress 本地搜索(minisearch),构建期建索引。1 个用户不需要 Algolia
反引号路径本仓大量用反引号包仓根相对路径src-tauri/src/db/word_key.rs),它们不是链接。要变可点需自定义 markdown 插件 —— 二期再做
dead link 检查VitePress 默认 fail build on dead link ⇒ 白送一道守卫,比现有 scripts/check-doc-links.mjs 更严。⚠️ 两套并存不是第二本账check-doc-links.mjs 验的是仓库内路径存在性(含 docs/cross-end/ 那些历史写法的负向断言),VitePress 验的是站点路由可达性。职责不同,别去「统一」它们
首页🔴 仓根已有 README.md;srcDir=仓根时 VitePress 会拿它当首页 —— 但那份的受众是 GitHub 访客,不是知识库读者。需单独写一个 VitePress home layout 的 index.md(P3 一并做),不要改 README.md 去迁就站点
搜索结果稀释🔴 246 份记述层进了全文索引后,搜「墓碑」会淹没在 66 份 cross-end 的碎片里,而不是那篇全景。要用本地搜索的 miniSearch 选项给归档区降权或分组。§3.2 ② 说的「不进树但可搜索」,不等于「和知识层平权地搜出来」

5. 机械守卫

判据来自记忆:「它错了的话什么会红?」没答案就先建守卫。

5.1 新鲜度徽章(本方案最有价值的单点设计)

每篇知识文档 frontmatter 记:

yaml
sourceRefs: [src-tauri/src/commands/sync/pull/mod.rs, src-tauri/src/commands/sync/push.rs]
verifiedAt: <commit sha>

构建期比对 git log -1 --format=%H -- <sourceRefs>verifiedAt: 不同 ⇒ 页面顶部显示「源码已变动 N 次,待复核」并列出 commit。

⚠️ frontmatter 只加在知识层那几篇,246 份记述层一份都不动(它们不需要徽章)。 影响面:GitHub 会把 frontmatter 渲染成一个小表格(可接受,不动正文); Claude 读到的是纯文本,而且 sourceRefs 对它是有用信息 —— 直接说明这篇描述哪些代码。

实现方式(已钉死,见 §4.0 ①):两段落地,都不写 Vue ——

阶段形态说明
P2scripts/check-kb.mjs终端 / CI 输出此时还没有站。徽章的全部价值在这一步就已经拿到了
P3+transformPageData 钩子把同一份结论注入页面 HTML只是让它更显眼,不是新增能力

🔑 它把「文档腐烂」从不可见变成可见 —— 这正是 /docs-audit 现在只能靠人翻的那部分。 ⚠️ 上一版这里写的是「渲染成站才拿得到的能力」,那句话是错的:算 git log 不需要站, 站只负责把结论摆在眼前。判据也因此改了 —— 见 §7 的顺序。

5.2 scripts/check-kb.mjs(进根 ci.yml

断言错了会怎样
frontmatter 字段完整sourceRefs 的文档拿不到徽章 ⇒ 静默永远显示「新鲜」
sourceRefs 路径都存在重构改名后徽章比对的是不存在的文件 ⇒ 恒不报警
树索引与文件集一致索引漂移(docs/README.md 已有前科:它是手写索引)
🔴 无 VitePress 专有语法(扫 ::: 容器 / <script setup> / <ClientOnly>md 在 GitHub 与 Claude 眼里变成乱码文本,双读性与零锁定同时作废(§4.0 ②)。⚠️ 扫描范围是全部 md,不只知识层 —— 口子从哪篇开都一样

🔴 上面第二条有个假红陷阱,实现时必须处理:扫描要排除代码块与行内代码, 否则任何「讨论这条规则」的文档都会误报 —— 本 plan 自己就是第一个受害者 (2026-09-01 起草时用裸 grep -E '<script setup>' 自查,当场被 §4.0 ② 的规则描述文本咬中)。 判据是该语法出现在正文里,不是「这个字符串在文件中存在」。 | 🔴 docs/.vitepress/ 下无 .vue 文件 | 生态选型的前提失效(§4.0 ①)。这条同时是 P5 的验收项 |

反向注入实证(按本仓惯例,建闸门时必做):三条各注入一次缺陷,确认会红。

5.3 两条不变量的归属(🔴 不在本 plan 定义)

实施中会产生两条稳定不变量。按 §4「红线归属规则」,它们不能留在本文件 (plan 会归档,归档即从活跃视野消失,而守卫还在依赖它)。落点指定如下:

不变量归属何时写入
知识层文档必须是唯一真相源,迁移后原处留指针(§3.2 ①)docs/README.md §3「写新文档时的约定」Phase 1 完成时
知识文档必须带 sourceRefs + verifiedAt,否则守卫红同上 + scripts/README.md 索引一行Phase 2 完成时

6. Skill 支持

需要一个新 skill /kb —— 但不是用来「整理归纳」(那用普通对话就能做)。 它的价值在于约束产出形状:以下四步机械、每次都要做、且必漏。

  1. 先查真相源 + 判解释/规则 —— 这条知识是否已在别处有归属?有 ⇒ 走「迁移 + 留指针」,不是新写一份。同时过 §3.2 ④ 那道判据:**它是规则还是解释?**规则一律留在 CLAUDE.md §4,知识文档只链接过去
  2. frontmatter 强制 —— title / 层级 / sourceRefs / verifiedAt / status
  3. 原处留指针 —— 从 plan / cross-end / CLAUDE.md 提炼的,原处改成一行链接
  4. 更新树索引 + 跑 check-kb.mjs

扩展两个已有 skill,不新建

skill加什么
/doc-sync-check一步:本次变更命中了哪些知识文档的 sourceRefs
/docs-audit一节:知识层体检 —— stale 篇数 / 树的空枝 / 有没有出现第二本账

⚠️ 新增 skill 有恒定成本description 是恒注入的, 见 verification/context-budget.md C1。 /kb 值不值这笔,Phase 3 落地前再确认一次。


7. 分阶段实施

🔴 顺序是刻意的:先长知识,后做站。 5 篇文章配一个三栏站是投入倒挂 —— 真正的瓶颈是 §3.1 树里那 4 条空枝。

🔑 自审得出的一条判断,它决定了下面的顺序本方案的核心价值(知识整理 + 新鲜度守卫)都不依赖站的存在。 站的增量只有四样 —— 手机可读 / 页内 TOC / 全文搜索 / 徽章更显眼, 其中前三样在编辑器与 GitHub 里都有替代品,第四样也能先做成终端与 CI 的输出。 ⇒ 站是锦上添花,守卫和知识本身才是花。故守卫从原 P2 提到 P1 之后、做站之前。

Phase做什么验收
P1 长知识 ★写 §3.1 第 3 层 4 条空枝中的 1-2 条(建议先「同步协议」——它散得最厉害、收益最大)。走「迁移 + 原处留指针」,不新造摘要;严守 §3.2 ④ 的解释/规则边界新文档能独立读懂;原处(cross-end)已改指针;CLAUDE.md §4 一个字没动纯标准 markdown(§4.0 ②);check-doc-links 绿
P2 守卫frontmatter 约定 + scripts/check-kb.mjs先只做终端输出)+ 三条反向注入实证 + 进 ci.yml三条注入各红一次。此时尚无站,价值已经拿到
P3 骨架docs/.vitepress/config.ts第一件事是验证 srcDir=仓根是否可行(§4.1),不行就走退路;根 package.jsondocs:dev / docs:build本机 pnpm docs:dev 能打开,知识文档可读,记述层搜得到但不在树里
P4 上线建 Vercel project(不绑自定义域,§4.2)→ 部署 → admin sidebar 加外链🔴 无痕窗口访问被 Vercel 登录页拦住;手机登录后可读
P5 打磨徽章样式打磨 / 反向引用 / 反引号路径可点 / ASCII 图转 SVG / /kb skill按需,非必做。🔴 验收含一条docs/.vitepress/不出现任何 .vue 文件(§4.0 ①),全部走构建期注入

P1 + P2 是最小可用集(注意:不含站)。P1 写完再决定要不要继续 —— 如果写了两篇发现「知识树」并没有比现在的 docs/ 更好用,就该停在这里, 沉没成本只有半天,而且那两篇文档本身照样是净收益。


8. 已知风险与待确认

状态
Vercel Deployment Protection已确认可用(Hobby 计划,两个 project 已在用)。陷阱与验收见 §4.2
srcDir=仓根是否可行P3 第一件事就是证伪它(§4.1)。428 份 md 全进站 + dead-link 全跑,配平代价未知。退路已写
VitePress dead-link 首次大批红⚠️ 预期之内。16 个跨 docs/ 链接 + 归档区大量历史路径(~/reading_vocab_helper/...刻意保留的历史写法,见根 CLAUDE.md §9,不要去改)⇒ 只能进 ignoreDeadLinks 白名单
ASCII 图在手机上横向滚动⚠️ 接受(P4 再治)。这是本仓文档的既有形态,不是本方案引入的
rvh/docs/ 60 份🚫 本轮不动。它自成一棵树、从没被体检过(/docs-audit 2026-08-30 才首次扫到),一起做会撑爆范围。srcDir=仓根后它可搜索但不进树
vitepress 依赖落点已定:根 package.json(2026-09-01 用户拍板)。这也是治理成本最低的一条 —— 另两条路都要动控制文件:docs/package.json 会把 docs/ 从 §2 地图里的**「非子项目」变成子项目**(要改地图,且本仓已有 4 个独立 pnpm 项目,这是第 5 个);新建顶层 kb/ 要同时改 scripts/check-repo-layout.mjsALLOWED 与 §2 地图
↳ 连带动作(P3 一并做)⚠️ VitePress 是 Vue 生态 + 自带 vite,而本体是 React + Vite 8:靠 pnpm 嵌套解析共存,产物零影响(devDependency)。生态选型的完整判据见 §4.0,零 Vue 代码是该裁定的前提条件。落地还要 ① 根 eslint.config.js 排除 docs/.vitepress;② 根 tsc -b 不扫它;③ .gitignoredocs/.vitepress/cachedist 已被第 14 行无前导斜杠的规则覆盖,cache 没有)
将来若要对外公开⚠️ 本方案按私有设计(无自定义域 + Standard Protection)。哪天想把知识库当技术博客对外,访问控制与内容分层都要重做 —— 那时是新方案,别在本方案里预留
新增 skill 的恒加载成本⚠️ 见 §6 末

9. 数字现算命令

本文 §1 的份数与行数是 2026-09-01 快照,必然漂移。要现数:

bash
cd /Users/larry/reading-browser
wc -l docs/*.md | sort -rn                          # 根层体量
ls docs/cross-end/*.md docs/plans/archive/*.md docs/archive/*.md | wc -l   # 记述层份数
find rvh/docs -name '*.md' | wc -l                  # 移动端那棵树
grep -ro "sm:\|md:\|lg:" admin/components/admin/*.tsx | wc -l              # admin 响应式密度
node scripts/check-doc-links.mjs                    # 链接悬挂
bash scripts/context-budget.sh                      # 恒加载区趋势

10. 关联