Skip to content

合仓后仓库优化 —— 实施计划

物理仓库:/Users/larry/reading-browser(合仓后单仓,RVH 在 rvh/) 创建:2026-08-29 · 状态:✅ 已完成并归档(13/13,2026-08-30 全阶段收尾 —— 阶段 0/1/2/3/4 全绿) ⚠️ 唯一一项改判:T4-2 不重写 git 历史,走 P5 自带的降级出口(理由见 §1 阶段 4 表下与 §3 T4-2)。 立项自 archive/rvh-merge-plan.md 收尾评估 —— 那份管「合仓怎么做」, 本份管「合仓做完之后,正式功能迭代开始前还欠什么」。


0. Context

RVH 合仓(2026-08-28/29,五阶段十项)的结构性目标全部达成:双端契约有唯一物理归属、 共享资产只剩一份、cross-end-check.shci-rvh.yml 都进了 CI 且绿。这些不可逆的改善不在本计划范围。

本计划处理的是合仓收尾评估当场量出来的四类欠账

  1. token 预算退化 —— 合仓计划自己把「根 CLAUDE.md 先瘦身」定为唯一硬前置, 阶段 1 做到了(73.0 KB → 50.5 KB,-30.8%),但阶段 4 又把它涨回 65.8 KB。 真正严重的是 RVH 单端会话:27.9k → 43.7k tokens(+57%)
  2. 合仓新造的假话 —— 根 CLAUDE.md 两处写着 CHANGELOG.md 是「唯一的 as-built 日志」, 而 rvh/CHANGELOG.md(248 KB,比根的还大)还在独立更新。
  3. 同型的病还剩七个 —— 合仓治好了「cross-end-check.sh 只在特定人的特定机器上手工跑」这一个, 但 sync-verify / ops-verify / privacy-verify / release-verify / migration-verify / learning-loop-verify / db-audit 七个脚本一个都没接 CI(CI=0、package.json=0、skill=0)。
  4. 正在流血的两处 —— 四个 verify 脚本的静默截断缺陷(backlog 已标 🔴 未修)、 rvh-debug MCP 连不上(本会话实测 CONNECTION_CLOSED)。

为什么是现在:以上每一条都会按会话次数持续计费(token)或静默失效(闸门), 功能迭代开始后只会更贵、更难排期。


0.1 关键诊断:token 退化的三个机制性原因

不是「文档写太多」这么简单。逐层挖到底是三条:

原因 1 · 持久记忆库完全空置 —— CLAUDE.md 在兼任记忆库

~/.claude-cli/projects/-Users-larry-reading-browser/memory/   → 空目录
MEMORY.md                                                      → 不存在

记忆系统的设计是「一事一文件 + 按相关性召回」(按需)。这条通道从没启用过, 于是每一条值得长期记住的事实只有一个落点:恒加载CLAUDE.md这就是棘轮的动力源 —— 不存在更便宜的地方,任何新裁定都只能往上加。

对照证据:合仓 T4-4 与 T4-7 都是去重任务,结果都净增(+5.9 KB / +3.4 KB)。 归并掉的是内容,累加上去的是元记述(为什么改判、实测证据、双向指针)—— 那些恰恰是典型的「记忆」而不是「指令」。

原因 2 · 把「红线的稳定归属」和「恒加载」绑死了

CLAUDE.md §4 立的规则(红线必须写进稳定归属、不能只活在会归档的 plan 里)完全正确, 但它被实现成了「稳定归属 = 恒加载文件」。二者本可以分开:

红线需要什么是否要求恒加载
唯一权威位置❌ 任何稳定文件都行
改代码时找得到⚠️ 只需要索引在恒加载处
机械可执行❌ 靠 CI 脚本,与文件位置无关

本仓已经证明分得开:16 条红线正文下沉进 src-tauri/CLAUDE.md,根只留索引行,至今没出事。 只有 4 条双端契约红线是例外 —— 而它们占 21.6 KB(根文件的 33%)。

原因 3 · 按需加载只有一层深,而 RVH 的重量全压在一个子领域

rvh/CLAUDE.md 83.1 KB 里,「跨端 Sync 协议红线」一节 = 57,487 B / 839 行 / 占 69%

⚠️ 这一节的内容质量是好的,别去删。 抽查 RVH #6g / #5d 的形状完全正确: 开头 **契约** → 根 CLAUDE.md §4 #6d(指针,不复述),随后才是 Dart 落点表、 本端独有证据、真机验证记录、守卫 bash。它不是重复,是深度

问题在加载时机rvh/CLAUDE.md 在你碰 rvh/任何文件时注入 —— 改一个 Flutter widget、改一行测试、动一下 pubspec.yaml,都要先付 23.7k tokens, 其中 16.4k 是这次会话根本用不到的 sync 契约细节

P0-1 实测校正(2026-08-29,判定 A)—— 注入的是「祖先链全量」,不是「最深一层」: 触达 rvh/lib/features/sync/**/*.dart 时,rvh/CLAUDE.md(深度 1)与 rvh/lib/features/sync/CLAUDE.md(深度 4)一起注入。 ⇒ 下沉的机制不是层级替换,而是按目录条件命中不碰 sync 目录的会话省下那 57 KB;的会话两份都来、总量不减。

🔑 这不削弱 T2-1,反而给了它一个可量化的判据 —— 关键变量是「多少比例的 RVH 会话 会碰 lib/features/sync/」。实测(2026-08-29):近 3 个月动过 rvh/138 个 commit 里, 碰 lib/features/sync/ 的只有 10 个(7.2%);全历史 30 / 453 = 6.6%。 ⇒ 收益落在约 93% 的 RVH 会话上。

📐 由此得到一条可复用的放置原则(下次再想下沉什么时按它判,别再按"层级替换"想): 把内容放在「需要它的会话集合最窄」的那个深度。推论有两条 —— ① 某子树里多数会话都需要的东西,留在该子树根部才对,下沉反而让它被读两遍; ② 下沉后留在原位的索引行是净增成本(对下沉进去的那些会话而言),所以索引要压到最小。

🔴 顺带订正一处合仓台账:T3-8 的验收记着「去镜像 105415 → 78365 B,-25.7%」, 但这一节 728 行 → 839 行,占比 68% → 69%。字节降的 14% 全部来自 「重述改成指针」,结构上一寸没动。T3-8 正文的目标 <40000 B 没达成,原因就在这里。 归档件不改(历史记述),此处记录供后来会话对照。


0.2 合仓对 token 的真实影响(分场景三种命运)

换算口径 = 合仓评估同一套 CJK 启发式 ≈3.5 B/token,方向可靠、绝对值 ±20%。 复现命令见 §6 附录 A —— 别照抄这些数字当事实。

恒加载 20.0k = 根 CLAUDE.md 18.8k + 12 个根 skill 的 description 1.1k + 全局偏好 0.3k。 scoped skill 不恒注入(本仓工具集里平时没有 rvh:* / admin:*),但 P0-1 实测发现 它与 CLAUDE.md 注入共用同一个触发条件 —— 碰 rvh/ 下任何文件时,8 个 rvh:* skill 一并注册(+0.68k)。下表已计入。

会话类型恒加载按需叠加今天合仓前判定
只改 RB 前端20.0ksrc/ 2.1k22.1k20.7k略涨
只改 RB Rust20.0ksrc-tauri/ 6.2k26.2k20.7k+27%
只改 RVH20.0krvh/ 23.7k + skill 0.68k44.4k27.9k+59% 🔴
改 admin20.0kadmin/ 6.4k26.4k26.9k持平
跨端改契约20.0k6.2k + 23.7k + 0.68k50.6k~48.6k(且两端可能不同步)持平,换来必然同步 ✅

T2-1 落地后的投影(按 P0-1 的祖先链全量口径重算,非层级替换):

RVH 会话占比(实测)今天T2-1 后变化
不碰 lib/features/sync/约 93%44.4k28.6k−36% ✅
lib/features/sync/约 7%44.4k45.0k+1%(多出来的是留在原位的索引)

占比来自 git 实测:近 3 个月动过 rvh/ 的 138 个 commit 中 10 个碰 sync(7.2%); 全历史 30 / 453(6.6%)。复现命令见 §6 附录 A ⑨。 期望值 ≈ −33% —— 这就是 T2-1 值不值得做的全部依据,比立项时的估算更硬。

结论:合仓在它被论证的那个场景(跨端契约)持平且换来了正确性,是真收益; 代价全部落在单端会话上,其中 RVH 单端 +57% 是唯一严重的一处, 且 100% 由原因 3 造成 —— 所以 T2-1 单独做完就能把它拉回合仓前水平


0.3 上下文体系的层级 / 加载时机 / 勾稽关系

┌─ 恒加载(每会话固定 20.0k)──────────────────────────────┐
│  ~/.claude/CLAUDE.md   全局偏好(语言 / 代理端口)            │
│  CLAUDE.md             仓库地图 · 双端契约红线 · git 纪律 · 索引│
│  12 × 根 skill description                                │
│  MEMORY.md             ❌ 不存在 —— 按需召回通道空置(原因 1)  │
└───────────────────────────────────────────────────────┘
        ↓ 触发:用 Read / Edit / Write 碰到该目录下的文件
        ↓ ⚠️ Bash 的 cat / grep 读同一个文件**不触发**(合仓 P0-2 实测的限定)
┌─ 按需叠加(当前只有深度 1,互不相干)─────────────────────┐
│  src/ 2.1k    src-tauri/ 6.2k    rvh/ 23.7k               │
│  admin/ 6.4k  landing/ 1.9k     + 该目录的 scoped skill 描述 │
└───────────────────────────────────────────────────────┘
        ↓ 无自动注入,靠显式 Read
┌─ 文档层(241 份 md / 27 MB)────────────────────────────┐
│  docs/*.md 13 · plans/ 20 活跃 + 162 归档                  │
│  cross-end/ 63 · verification/ 8 · archive/ 12            │
│  rvh/docs/ 62 份(自成一套,未与上面归并)                     │
└───────────────────────────────────────────────────────┘

机械勾稽是健康的(这是本仓的真实优势):check:claude-paths(7 份 CLAUDE.md 全覆盖)+ check-doc-links(悬挂 0)+ cross-end-check.sh(18 ✅ / 0 ❌)都在 CI 里。

断掉的两处:① 「唯一 as-built 日志」是假话(T1-3 修); ② docs/README.md 不存在 —— 13 份根层文档没有索引,而 plans / archive / cross-end / verification / tools / supabase 每个目录都有 README,唯独 docs/ 自己没有(T3-2 补)。


0.4 四个子项目的逻辑关系(决定什么该合、什么该留)

真实拓扑不是「1 主 + 4 卫星」,而是**「1 个契约中枢 + 3 个消费者 + 1 个无关静态站」**:

                supabase/  ← 契约中枢(sync-tables.sql + 12 edge functions)

     ┌──────────────┼───────────────┬──────────────┐
  RB 桌面端        rvh/          admin/        landing/
   (根本体)      (Flutter)      (Next.js)     (Next.js)
     │              │               │              │
  手抄绑定        手抄绑定       编译期绑定        无绑定
  sync.rs   sync_repository_impl  gen-types         —
     └────── 共享 10 表 / 其中 6 表 · SM-2 · 预装库 · lemmatizer ──┘
关系对契约耦合工具链共享合仓判断
RB ⇄ rvh极强✅ 合仓正确
RB ⇄ admin中(同 schema,编译期绑定)✅ 合仓正确
RB ⇄ landing🟡 留在仓里成本近乎为零,但白白触发桌面端 CI(T3-3)
rvh ⇄ admin零(但同一个 Supabase 项目)

结构性观察rvh/admin/ / landing/ 在目录树上平级,性质却不同 —— 前者是另一个产品端,后两者是配套。这一点 §2 仓库地图已写对。 真正的不对称在于 RB 本体散在根目录,这也是根 CLAUDE.md 必须同时扮演 「仓库总图」和「桌面端控制文件」两个角色的根源 —— §2「项目结构」那 6.9 KB 里有相当一部分其实是桌面端专属内容。 本计划不动这个结构(收益不确定、风险高),仅登记为观察。


1. 进度台账

完成一个任务:把 ⬜ 改成 ✅,填日期与 commit 短 SHA。放弃 / 改判的写 ⏭ 并注明原因。 顺序:先跑 P0-1(它决定 T2-1 能不能做),其余阶段之间无硬依赖,可乱序、可分多会话。

阶段 0 · 探针(只读,零风险)

ID任务会话状态日期 / commit
P0-1实测嵌套 CLAUDE.md深度 ≥2 是否仍按需加载必须新开一个判定 A2026-08-29

P0-1 结论(2026-08-29 · 判定 A = 深度 ≥2 仍按需加载):触达 rvh/lib/features/sync/data/repositories/sync_repository_impl.dart 之前 Q1(探针口令)与 Q2(OcrClozeGate)均答不出、控制题 Q0 答得出;之后两题都答得出 —— 深度 4 的 rvh/lib/features/sync/CLAUDE.md 确实随触达按需注入。T2-1 前置成立。

⚠️ 但注入的是祖先链全量,不是最深一层:同一次触达把 rvh/CLAUDE.md(深度 1)与探针 (深度 4)一起注入了。所以 T2-1 的收益口径必须改写为「不碰 lib/features/sync/ 的 RVH 会话省下那 57 KB」,而不是「碰 sync 目录时也只付一份」—— 碰的时候两份都来,总量不减 (还多一次文件读取)。方案仍成立,但 §2 里按「层级替换」估的节省额需按此口径重列。

附带观测:同一次触达还注册了 rvh/.claude/skills/ 下的 8 个 skill(rvh:code-review 等), 即 skill 注册与 CLAUDE.md 注入走同一个「触达 rvh/ 下文件」的触发条件。

阶段 1 · 止血(正在流血的,全是机械活)

ID任务会话状态日期 / commit
T1-1修 4 个 verify 脚本的「变量后接中文标点」静默截断RB2026-08-29
T1-2rvh-debug MCP 连不上(provisioning 缺口)RB2026-08-29
T1-3修根 CLAUDE.md 两处「唯一 as-built 日志」假话RB2026-08-29

T1-2 结论(2026-08-29)pnpm --dir rvh/rvh-debug-mcp install 跑通, postinstall: tsc 产出 rvh/rvh-debug-mcp/dist/index.js(16,615 B);直接 import 该产物 能打印 starting stdio transport / connected,即服务端自身可启动。步骤已补进 rvh/QUICKSTART.md 开头那张表(第 4 行)+ 命令块 + 小节标题「两步」改「三步」,未新建第二份说明协议层验收(2026-08-29 补做):拿 .mcp.json 里那条确切配置(node /Users/larry/reading-browser/rvh/rvh-debug-mcp/dist/index.js)起进程,走 stdio 做完整 JSON-RPC 握手 —— initialize 返回 serverInfo {name: rvh-debug, version: 0.2.0}tools/list 列出 7 个工具rvh_snapshot / rvh_logs / rvh_state / rvh_widget_tree / rvh_navigate_log / rvh_db_query / rvh_supabase_query)。即服务端侧已无缺口: 同一条通路上客户端该拿到的东西都拿得到。

收尾已验(2026-08-29,下一会话开头):新会话启动时 mcp__rvh-debug__* 7 个工具 全部出现在工具集里,CONNECTION_CLOSED 消失。⇒ 根因就是 provisioning (dist/ 从未构建过),装完 + 重启客户端即好,客户端配置一侧无缺口。本条闭环。

T1-1 结论(2026-08-29 · 动态验证已完成,坑 1 已绕过):装了 brew install libpqbrew link --force libpq(psql 18.6 进 PATH)⇒ privacy / ops 的 DB 段真的跑到了, 不是 SKIP 蒙混。29 处 $var${var} 全改完,四个脚本头部补陷阱说明 + 自检命令; 修完全仓 14 个 .sh 扫描均为 0

🔑 四个脚本此前的断点(修前逐个实测)release-verify 死在 R1(R2–R15 从未执行)· privacy-verify 死在 P7 · ops-verify 死在 M3 · migration-verify 死在 D4 之后 (D5–D9 从未执行)。修后各整跑一次:PASS 16 / 17 / 24 / 10,FAIL 0,SKIP 0

捞到 1 个新 FAIL 并当场修掉migration-verify D9 只扫根 CLAUDE.md,而红线 #11 正文 已下沉到 src-tauri/CLAUDE.md(根只留索引),于是 init_data.sql / seed_reference_words.sql 判为「文档没提」—— 文档不窄,是断言指错文件(红线分表时没人回头改它,而它从来没执行过, 所以一直没暴露)。改为扫 CLAUDE.md 家族后转绿。按 docs/verification/README.md 落账: 修好的进 CHANGELOG,backlog.md 里那条 🔴 记录删除,不留报告文件

阶段 2 · 拿回 token 预算(收益最大)

ID任务会话状态日期 / commit
T2-1rvh/CLAUDE.md 的 57 KB 红线节下沉到 rvh/lib/features/sync/RB(见任务内说明)2026-08-29

T2-1 结论(2026-08-29)rvh/CLAUDE.md 83,107 → 30,601 B(−63%),正文进 rvh/lib/features/sync/CLAUDE.md(55,072 B)。搬入内容与原文逐字节 diff 为空(含前言)。 原位留下的索引 1,676 B(≤2 KB 目标达成)+ 顶部一行注入告警;编号对照表按计划留在rvh/CLAUDE.md(2,977 B —— 这是验收里「≤28 KB」没达成的全部原因:那条口径按「整节都搬」估的, 与动作 2「对照表留下」冲突,以离场条件 30k 为准,见下)。 验收:check:claude-paths 绿(清单已加第 7 份)· check-doc-links 绿 · cross-end-check 18 ✅ / 0 ❌离场条件达成:RVH 单端(不碰 sync)44.4k → 29.84k tok(−33%),< 30k。 碰 sync 的那 ~7% 会话 45.58k(+2.7%,即索引 + 对照表被读两遍的净增,计划预估 +1%)。 ⇒ 期望值 ≈ 30.9k(−30%)

顺带修的指针落点(不改内容,只改落点,否则全部悬挂):根 CLAUDE.md 4 条双端契约红线的 「RVH 落地」+ §4 形状说明 + 顶部导航表 · scripts/cross-end-check.sh §人工 checklist 3 · docs/verification/learning-loop.md K7 · rvh/docs/plans/backlog.md · doc-sync-check/SKILL.md · rvh/CLAUDE.md 对照表末两行的「本文件 §跨端契约镜像 backlog」。 「6 份 CLAUDE.md」的三处计数同步改 7 份。 | T2-2 | 删两份通用 Claude Code 教程(67.5 KB)+ 修 7 处引用 | RB | ✅ | 2026-08-29 |

T2-2 结论(2026-08-29):两份删掉(-67.5 KB / 2,904 行)。 ⚠️ 实际引用点比正文列的 8 处多 6 处 —— 正文漏了 rvh/docs/guides/README.md 的 45 / 56 / 102 / 108 / 113 / 182 行(不只表格那两行:「按场景查找」两小节和「学习路径」中级/高级各有 一段是专为指向这两份而写的),以及 rvh/docs/guides/doc-maintenance-guide.md 的 283 / 1751 / 1752。全部一并修掉,删后引用为 0(rvh/CHANGELOG.md:956 历史记述按令未动)。

🔑 正文列的「1 处死过滤」实际是两处,第二处正文没提: rvh/scripts/doc-consistency-check.sh Step 3/6 整步都在查「旧路径引用」—— 文件删掉后这道闸门恒绿且没有对象。已就地改指今天的判据(断言这两份不复活,含引用; 排除 CHANGELOG),不删步、不重编号 —— rvh/docs/plans/backlog.md 有 3 处按 「Step 6」引用它,重编号会造死链。反向注入实证过(塞一处引用 → 当场红,去掉 → 绿)。 这跟 T1-1 修 migration-verify D9 是同一类修法:断言指错对象,不是判据太窄。

验收:残留引用 0(除本文件与 CHANGELOG)· check-doc-links 绿 · check:claude-paths 绿 · cross-end-check 18 ✅ / 0 ❌ · rvh/scripts/doc-consistency-check.sh 6/6 全绿。

阶段 3 · 补闸门与索引

ID任务会话状态日期 / commit
T3-1把 verify 脚本不依赖线上凭据的那部分接进 CIRB2026-08-29

T3-1 结论(2026-08-29):新建 .github/workflows/ci-verify.yml(动作 2 的「二选一」 选了新建,不并进 ci.yml —— 后者是前端 job,pnpm install + vite build 会把一道 <1 分钟的门拖成 3 分钟,而这两个脚本一个 node_modules 都不需要)。未加 paths 过滤 (那是 T3-3,混在一起会让两项的触发效果分不开)。

接了 2 个,不是 3 个migration-verify.sh --max-skip=2 + learning-loop-verify.sh --max-skip=1。 🔴 release-verify.sh 实测后暂缓(正文按静态处数把它排在第一优先,此处按证据改判): 它的 SKIP 数是网络可达性的函数而不是环境常量 —— 同机同码连跑两次,SKIP 分别是 4 和 11 (第二次 latest.json 没取到 ⇒ R7-R11 连带全 SKIP)。给它钉任何 --max-skip 基线都会得到 一道随网络天气变红的门,正是阶段 3 前言那条离场条件要防的东西。接它需要先把网络段与 静态段拆开(R1-R4 那批是零网络的),记为独立一笔。 ✅ 接线的两个前置已经做好、已提交:① release-verify.sh 也拿到了 --max-skip; ② PROXY 的取值从 ${RB_PROXY:-…} 改成 ${RB_PROXY-…} —— 冒号版把显式空串也当 「未设置」塞回默认代理,于是 CI 里根本关不掉代理,每个 curl 都打向不存在的 127.0.0.1:7897 ⇒ 全 SKIP ⇒ 假绿。去掉冒号后 RB_PROXY= 才真的表示直连。

选这两个的判据 = 静态段零网络(读文件 / git / python3)⇒ SKIP 数在 CI 里是常量 ⇒ 基线钉得住。 基线来历(在剥掉 psql / gh / Keychain / 本机存量库的沙箱里实测): migration-verify PASS=8 FAIL=0 SKIP=2(无本机存量库 D5 + 连带 ledger 对照 D6)· learning-loop-verify PASS=7 FAIL=0 SKIP=1(M 段部署态无 psql/凭据)。

反向注入实测 3 次,全部本机完成、当场还原(动作 3 的硬要求): ① 全仓多放一份 sm2-golden-vectors.json 副本 → learning-loop L1 FAIL → exit 1 · ② 改掉 src-tauri/src/db/shipped_migrations.txt 里一个 sha → migration-verify FAIL → exit 1 · ③ RVH_ROOT 指向不存在的路径(判据的对象消失,不是判据变错)→ SKIP 1→3 > 基线 → --max-skip 自身把它判红 → exit 1。第 ③ 条是这道门存在的全部理由: 没有它,一个因缺凭据全 SKIP 的脚本会永远显示绿色 —— 假绿闸门比不接更糟。 三次注入撤销后各复跑一次均回到 exit 0。

⚠️ 顺手修的一处自伤ci-verify.yml 头两版注释里写了脚本的带扩展名全名, 当场把 check-schema-frozen.mjscross-end-check.sh 的 CI 列从 0/1 刷成 1/2 —— 接线矩阵的 CI 列是机械 grep,注释里的一次提及就能把没在跑的脚本标成在跑。 已改写注释并把这条纪律写进 workflow 文件头 + scripts/README.md §2 的读法陷阱 ②。

scripts/README.md 的矩阵已同步重算(T3-2 刚建的那份不能留着旧数): 🔴 三列全 0 11 → 9,并从两类拆成三类 —— 「还没接、该接」4 个 (sync-verify / privacy-verify / ops-verify / db-audit,= 阶段 3 剩余工作面)· 「暂缓、有明确理由」1 个(release-verify)·「刻意手工」4 个(备份 / 拉资产 / 生成映射 / 清测试数据 —— 它们是动作不是判据,没有「应该恒真」的东西可守)。

验收:本机 CI 模拟两步均 exit 0 · 反向注入 3/3 变红 · 不传 --max-skip 时三个脚本行为 逐字不变(本机仍是 0/1/2/3 四态)· check-doc-links 绿 · check-claude-md-paths 对两份 README 绿 · cross-end-check 18 ✅ / 0 ❌ · 全仓 .sh 中文标点扫描仍为 0。 ✅ CI 绿跑:run 33259344385(2026-08-29,双远端已 push)。CI 实测数与沙箱预测逐字相同: migration-verify PASS=8 FAIL=0 SKIP=2 · learning-loop-verify PASS=7 FAIL=0 SKIP=1。

🔑 首跑是红的,而那次红正是这道门的价值证明(run 33259292953):CI 里 SKIP=3 > 基线 2, 多出来的是 D4(指纹清单 vs 发布 tag)—— actions/checkout 默认 depth=1 且不带 tag, D4 在 tag 上 git show 取不到东西只能 SKIP。修的是成因不是基线:抬到 3 等于白白让掉 一条零凭据、真能抓事的判据,故改为 fetch-depth: 0(commit 9ea51b81),基线维持 2。 换句话说 --max-skip 上线第一天就拦下了一次「少验了一条却看起来绿」—— 这正是 §0 第 3 类欠账的病根形状。

T3-1 续(2026-08-29 同日第二轮):又接了 sync-verify.sh --max-skip=1,并把剩下三个 从「还没接」改判为「接不了 / 不该接」—— 这一轮的产出主要是判据不是接线。

🔴 方法论的坑(下一个人会重踩,写在这里):量「哪些检查不依赖凭据」时必须先把 gitignored 的 admin/.env.local 藏起来。四个脚本都会 set -a; . 它(里面有 service_role + anon key),于是本机沙箱里一大片「看起来是静态」的检查其实在拿本机凭据 读线上库。第一次没藏,ops-verifyPASS=19 / SKIP=1,我据此把它推荐成最佳候选; 藏掉之后真实数字是 PASS=0 / SKIP=8 —— 接了就是一道 100% 假绿闸门。 同理要剥掉 psql / gh / Keychain(security) 与 $HOME

四个候选的实测结论

脚本无凭据判定
sync-verify.shPASS=1 SKIP=1已接 —— 唯一零网络零凭据的真断言(N0:shell 表清单 vs Rust PENDING_PUSH_TABLES)。覆盖面只有 1 条,但那条只有这里守
ops-verify.shPASS=0 SKIP=8❌ 接了 = 100% 假绿
privacy-verify.shPASS=7 SKIP=8❌ 那 7 条(P8-P13)全是打 admin.lampio.app 的线上 HTTP,不是静态判据。按 commit 触发 = 让第三方 uptime 决定 CI 红绿,且验的是「已部署的站点」不是「这次改动」。要守它该走 schedule,是另一个设计决定
db-audit.sh无凭据直接退出❌ 纯生产数据巡检,没有静态段,不是 CI 候选

🔑 sync-verify 时抓到一个真缺陷并修掉:它的汇总退出逻辑被抄了三份 —— N1-N7 那两条「无凭据 / psql 连不上」的早退路径各自 printf …; exit 2,绕开文件末尾那份。 后果是 --max-skip唯一会走到的那条 CI 路径上完全无效(沙箱实测:传了 --max-skip=1 仍然 exit 2)。已收敛成单一 finish(),三处调用同一实现。 这与 T1-1 修 migration-verify D9、T2-2 修 doc-consistency-check Step 3/6 同型: 判据本身没错,错在它挂在一条没人走的路径上。

反向注入(本机,当场还原):把 shell 侧表清单抄漂一张(reading_notesreading_notez) → N0 FAIL → exit 1;撤销后 exit 0。另验四种退出路径:本机不传参 exit 0 · 沙箱不传参 exit 2(旧行为不变)· 沙箱 --max-skip=1 exit 0 · 沙箱 --max-skip=0 exit 1。

🔴 三列全 0 9 → 8,且这 8 个现在分类:接不了/不该接 3 · 暂缓有理由 1 · 刻意手工 4。 ✅ 第二轮 CI 绿跑:run 33261136610(sync-verify PASS=1 FAIL=0 SKIP=1,与沙箱预测一致)。 「还没接、该接」这一类现在是空的 —— 阶段 3 的接线工作面到此为止, 剩下的都是「有实测理由不接」或「要先改脚本结构才谈得上接」。 | T3-2 | 补 docs/README.md + scripts/README.md | RB | ✅ | 2026-08-29 | | T3-3 | 根 ci.ymlpaths 过滤 | RB | ✅ | 2026-08-29 |

T3-3 结论(2026-08-29):四个子项目目录(admin/ landing/ rvh/ supabase/) 不再触发根 ci.yml

🔴 paths + ! 取反,不是正文建议的 paths-ignore —— 按实测改判,理由是正文 自己那条风险提示(「写窄了让真该跑的不跑,比 CI 白跑严重得多」): paths-ignore 不支持取反,而 ci.ymlcheck:claude-paths 校验 7 份 CLAUDE.md, 其中 4 份就住在要忽略的目录里admin/CLAUDE.md · landing/CLAUDE.md · rvh/CLAUDE.md · rvh/lib/features/sync/CLAUDE.md)。直接 paths-ignore ⇒ 「只改 rvh/CLAUDE.md」的提交彻底绕开那道门。 改用 paths: ['**', '!admin/**', '!landing/**', '!rvh/**', '!supabase/**', '**/CLAUDE.md']: 以 '**' 起头 + 逐个 ! 排除 = 语义等价 paths-ignore,但能把 CLAUDE.md 再 include 回来; 且不是正文警告的正向白名单(起点是全仓,新目录默认在内,漏不了)。顺序有意义 —— **/CLAUDE.md 必须在三条 ! 之后。各门的输入逐条写进了 ci.yml 文件头,作为将来加新 ! 排除时的自查清单。

实测三次真实 push(短命分支 ci-paths-probe,验完即删,main 未被污染):

探针改了什么CI其它
02b09e7e只加 rvh/ 下一个文件未触发(达成)CI (rvh) ✅ 触发 · CI (cross-end) ✅ 触发
f6a86bc3只加 src-tauri/ 下一个文件触发且 success(run 33261400364CI Rust ✅ 触发
2d0c9c21只改 rvh/CLAUDE.md触发且 success(run 33261448528证明 **/CLAUDE.md 那条捞回来的确生效

探针 ③ 是正文没要求、但本版设计特有的一条:没有它,这次改动会静默地把 4 份 CLAUDE.md 移出守门范围 —— 收窄触发面最容易造的就是这种「省了算力、丢了断言」的暗账。

顺带观察,登记不做ci-verify.yml 目前没有 paths 过滤(T3-1 刻意留白, 免得两项的触发效果分不开)。三次探针里它每次都跑 —— 它 <1 分钟且零依赖安装, 代价可接受;要不要给它也配触发面是独立一笔。

T3-2 结论(2026-08-29):两份索引落地 —— docs/README.md 7,600 B (根层 13 份逐条 + 6 个子目录归属)· scripts/README.md 10,504 B25 个脚本逐条 + scripts/lib/ 4 个共享实现)。 ⚠️ 正文的「25 个脚本」现数为 26 个条目 —— 那 26 里含 scripts/lib/ 目录本身,脚本仍是 25 个。

接线矩阵按附录 A ⑤ 现生成,未手抄;顺带盘出两个读法陷阱(已写进 README §2, T3-1 直接复用这张表时必须带着):① CI=0 ≠ 不在 CI —— 经 package.json 间接进 ci.yml 的有 8 个(check-no-inline-zh/en · check-schema-frozen · set-version · audit-locale-coverage · check-claude-md-paths · check-doc-links · build-content-script); ② CI=1 ≠ 在 CI 里跑 —— scripts/release.sh 那个 1 是 release.yml 的一行注释。 真正被 workflow 直接 run: 的只有 3 个(cross-end-check.sh · check-vocab-asset.sh · gen-latest-json.mjs)。

🔴 三列全 0(没有任何东西在自动执行)= 11 个:6 个 *-verify.sh + db-audit.sh (这 7 个是 T3-1 的工作面)+ 4 个刻意手工的工具(backup-supabase-storage.mjs · fetch-openmoji-assets.sh · gen-word-illustrations.py · reset-dev-data.sh —— 它们没有「应该恒真」的断言,不接 CI 是知情选择)。README 用 🔴 把这两类区分开, 因为分不出「忘了接」与「刻意不接」正是这 11 个长期没人管的成因。

docs/ui-standards.md vs rvh/docs/ui-guidelines/ 已写明是刻意的、不是漂移 (docs/README.md §1 的 🔑 块):两端设计系统不同源(CSS 变量+Tailwind @theme vs Material 3 elevation/color-role/typography),合并会产出一份两边都不能执行的东西; 真正要三端一致的是数据与算法,归属在 CLAUDE.md §4 / §9。未加任何红线锁标记 (README 是索引不是红线归属,本计划刻意不进 /arch-check S28 集合)。

验收:check-doc-links 绿(docs/README.md 已自动进 activeFiles)· node scripts/check-claude-md-paths.mjs docs/README.md scripts/README.md 绿 · cross-end-check 18 ✅ / 0 ❌

遗留(另一笔活,登记备查):这两份 README 的路径校验目前只能手工跑 —— 刻意没有加进 package.jsoncheck:claude-paths 清单,因为那条命令的语义是 「CLAUDE.md 家族」,掺进 README 会让它名不副实。要常态化守门需要一条新的check:readme-paths(或让 check-claude-md-paths.mjs 支持第二个文件集), 与 T3-1 的 CI 接线一并考虑。

阶段 4 · 清理与收口(择期,互不依赖)

ID任务会话状态日期 / commit
T4-1docs-governance-plan.md 一个了结RB2026-08-30
T4-2删 22.3 MB 归档 SQL(改判:不重写历史,走 P5 自带的降级出口)RB2026-08-30
T4-3两份 backlog 分片 + rvh/docs/plans/ 补归档节律RB2026-08-30
T4-4docs/mcp-primer.md 归档(不删)RB2026-08-30

T4-2 改判(2026-08-30):P5 的 ROI 算式在动手前重算已不成立 (.git 实为 328 MB 非 72 MB,目标 blob pack 后 7,941,186 B ⇒ 回收 2.3% 非 10%; 真正的大头是红线 #10 必须保留的预装库 35 blob / 94.21 MB)。 又实测发现两处 P5 没算的代价:仓里还有 feat/admin-ops-console 分支 + GitHub open PR #1 会被一并作废;两个远端 tag 集合不对称(GitHub 11 个 / Gitee 1 个)。 ⇒ 用户选 P5 原文写着的降级路径:仅工作树删除 + docs/archive/README.md 标注不重写历史、11 个 tag 与全部 commit SHA 一律不动。 因此正文那条「先把 tag 风险补进 P5」是条件句、本次判定不适用,归档件未改。 详见 §3 T4-2 的完成记录。

📋 阶段 4 与阶段 3 尾项的交接 promptpost-merge-phase4-handoff.md(2026-08-30 建)—— 那里只装「下一个会话拿什么开工」,不含方案(方案仍以本文件 §3 为唯一真相源)。 它同时记着两条本文件正文没有的信息:① T4-4/T4-3 与 2026-08-29 新建的 docs/README.md / scripts/README.md 的耦合;② 实测确认 P5 没写 tag 那一段, 故 T4-2 的第一步是补方案而不是执行。阶段 4 做完后随本文件一起归档。


2. 冷启动开工指引(新会话先读这段)

你如果是没有上下文的新会话:读 §1 台账找第一个 ⬜ → 读该任务所在阶段的前言 → 读该任务本身(每个都写了「会话 / 前置 / 动作 / 验收 / 回滚」,不需要回看创建它的对话)。

三条硬约束

  • A. P0-1 必须新开一个干净会话做,且不许先读本文件(读了就污染,测出来是假的)。 理由与合仓 P0-2 完全相同。
  • B. T2-1 在 P0-1 判定为「按需」之前不许动手。判定为「恒加载」则 T2-1 作废, 改走 §5「退路」。
  • C. 每个任务做完先跑验收命令,再回写 §1 台账,再提交。 顺序反了会留下 「做没做完看不出来」的状态 —— 那正是 README.md 点名的病。

并行会话纪律

本计划 90% 是文档 / 脚本改动,但 T1-3 / T2-1 碰的是控制文件CLAUDE.md 家族), 命中 CLAUDE.md §8 的枢纽文件清单。动手前自查 git status / git worktree list; 探到并行痕迹就开独立 worktree(Agent(isolation:"worktree"))。 即使不碰枢纽文件,「每完成一个可编译小步就提交」仍是硬要求(路径 B 只认未提交状态,不认文件域)。

禁止事项

禁止为什么
在本文件里定义任何新红线(含锁标记 —— 本行刻意不写那个字符,rg -l 出现即计数)/arch-check S28 基线 = 4,本文件刻意不进那个集合。发现新不变量按 CLAUDE.md §4「红线归属规则」写进稳定归属,这里只留指针
rvh/CLAUDE.md 红线节的内容T2-1 是搬家不是删除。那 57 KB 内容质量是好的(见 §0.1 原因 3)
把 T4-2 与任何其他改动同批提交它要重写 git 历史,必须工作树干净、双远端已同步时单独做
docs/plans/archive/docs/cross-end/ 里的历史记述它们是写作当时的事实记录。只改操作性文件
照本计划末尾去回填 CLAUDE.md §2 文件清单README.md 明令:那两处已于 2026-08-14 撤销,回填 = 把烂账种回去

3. 任务正文

阶段 0 前言

不变量:全程只读,不改任何文件。失败可原地停下,零代价。 离场条件:P0-1 给出判定 A/B/C,写进台账。


P0-1 实测嵌套 CLAUDE.md 深度 ≥2 是否按需加载

会话必须新开一个(不能在写本计划的会话做,上下文已污染)· 前置:无

为什么必须验:本仓所有 CLAUDE.md 实例(admin/ landing/ src/ src-tauri/ rvh/都是深度 1,合仓 P0-2 也只验了深度 1。T2-1 的全部收益建立在 「rvh/lib/features/sync/CLAUDE.md 只在碰该目录(含子目录)下的文件时才注入」上。不通则 T2-1 作废。

🔴 探针设计有两条硬要求,初稿踩过其中一条(2026-08-29 立项当天自查发现并改): ① 答案不能在别的恒加载文件里出现。初稿的 Q2 问「RVH #6g 的四条子规则叫什么」, 而答案 W / P1 / P2 / P3 CLAUDE.md §4 #6d 里就写着 —— 只加载根文件的会话 第 1 步就能答对,测出来是假的通过。这正是合仓 P0-2 结果段留下的那条备注 (「Q1 探针不干净,数字泄漏在根 §2 索引行,下次换探针」)。 ② 口令不能写进任何被提交的文件,否则新会话读一眼计划就知道答案。 所以下面不写字面口令 —— 实施时现取一个全仓 0 命中的随机串。

动作

  1. 取一个全仓 0 命中的随机口令(先验证:grep -rl '<口令>' . | grep -v node_modules | grep -v '^./.git' 无输出)。
  2. 临时探针文件 rvh/lib/features/sync/CLAUDE.md,正文只放一句 「本目录的探针口令是 <口令>」,并在开头注明它是探针、用完即删。 ⚠️ 不要提交它 —— 保持 untracked(顺带一个好处:reset --hard 不会抹掉未跟踪文件)。
  3. 新开会话,把下面的交接 prompt 整段贴过去。
  4. 判定回写台账后,删除探针文件(T2-1 会重新正式建立它)。

三道题的设计(每道都已机械核验过唯一性,见 §6 附录 A ⑧):

答案只出现在第 1 步期望作用
Q0 Tauri CLI 版本CLAUDE.md答得出控制题 —— 答不出说明整个注入机制异常,本次实测作废
Q1 探针口令探针文件(深度 4)答不出主探针
Q2 OCR 采集必经的闸门类名rvh/CLAUDE.md答不出深度 1 对照 —— 用来区分「嵌套完全不加载」与「只加载最近的一层」

交接 prompt(整段复制给新会话,把 <口令> 换成第 1 步取的那个串)

text
这是一次只读实测,别改任何文件,别用 Agent/子会话,别读 docs/plans/ 下的任何文件。
按顺序做四步,每步如实回答。

【第 1 步|先别看任何文件】
不要读取、grep、cat、ls 任何文件。仅凭你此刻上下文里已有的内容回答:
  Q0. 本仓 CLAUDE.md 的「环境信息」里,Tauri CLI 的版本号是多少?
  Q1. rvh/lib/features/sync/ 目录下的控制文件里,写的「探针口令」是什么?
  Q2. RVH 的 OCR 语境采集路径,规定必须经过哪一个闸门类(类名)?
答不出就明确说「上下文里没有,答不出」。不许猜、不许推理、不许"根据常见做法"作答
—— 这一步的价值全在于诚实报告你能不能看见。
同时报告:你此刻上下文里出现了哪几份 CLAUDE.md?

【第 2 步|触达 sync 目录下的文件】
读 rvh/lib/features/sync/data/repositories/sync_repository_impl.dart 的前 20 行。
只读这一个文件。不要读任何 CLAUDE.md 本身,也不要读 docs/plans/ 下的任何文件。

【第 3 步|再答一次】
重新回答 Q1、Q2,并报告:现在上下文里出现了哪几份 CLAUDE.md?

【第 4 步|结论】
判定属于哪一种,一句话说清:
  A. 深度≥2 按需加载 —— 第 1 步 Q1 答不出,第 3 步答得出
  B. 只加载深度 1   —— 第 3 步 Q2 答得出、但 Q1 仍答不出
  C. 恒加载 / 异常   —— 第 1 步 Q1 就答得出,或 Q0 答不出,或其他情况
然后做三件事:
  (a) 把结论回写 docs/plans/post-merge-repo-optimization-plan.md 的 §1 台账 P0-1 那行
      (状态 ✅ + 日期 + 判定字母 + 一句话依据),并同步顶部状态行的 0/13 计数;
  (b) 删掉临时探针文件 rvh/lib/features/sync/CLAUDE.md;
  (c) 提交:
      git add docs/plans/post-merge-repo-optimization-plan.md
      git commit docs/plans/post-merge-repo-optimization-plan.md \
        -m "docs(plans): P0-1 实测 —— 嵌套 CLAUDE.md 判定 <字母>"

背景(读完就够,不必翻别的):本仓 rvh/CLAUDE.md 有 57KB 的 sync 协议红线,占该文件 69%,
但它在你碰 rvh/ 下任何文件时都会注入 —— 改个 UI widget 也要付这笔钱。计划把它下沉一层到
rvh/lib/features/sync/,收益全建立在「深度≥2 仍按需加载」上。这一步就是验证这半句。
判定 B 或 C 则该方案作废,走计划 §5 退路。

验收:台账 P0-1 有判定字母 + 顶部状态行同步 + 探针文件已删 (ls rvh/lib/features/sync/CLAUDE.md 报不存在)。

回滚:删探针文件即可,本任务不改任何既有内容。

阶段 1 前言

不变量:三个任务互不依赖,可任意顺序、可分会话。每个都能独立提交。 离场条件:三项验收全绿。

开工前实测(2026-08-29,本机)—— 两个正文没写的坑

坑 1:psql 没装,而它恰好挡住 T1-1 最有价值的那一步。 陷阱只在那行被执行时才触发(set -u 下当场终止),段落 SKIP 掉就验不到。 而陷阱最多的 privacy-verify(10) / ops-verify(5) 的 DB 段正是靠 psql。 ⇒ 不装 psql 的话,T1-1 只能做到「静态扫描归零」,做不到 「跑起来看有没有从未执行过的段落冒出新 FAIL」—— 而后者才是这条任务的真正收获。 动手前先 brew install libpq 并把它 link 进 PATH(或 brew install postgresql@16)。 装不了就在台账里写明「T1-1 只完成静态部分,动态验证欠 psql」,别默认它做完了。

其余凭据本机齐备(实测):admin/.env.local ✅(privacy / ops 从这里取 URL 与 key)· Keychain lampio-supabase-db ✅ · 本地存量库 ~/Library/Application Support/com.lampio.dev/lampio.db ✅ 55 MB(migration-verify 那条「最有价值的证据」拿得到)· gh ✅(release-verify 的 Release 段)。

坑 2:T1-2 的验收跨会话。 pnpm install 完成后 MCP 不会当场连上 —— 要重启 MCP 才生效(本仓 rb-debug-mcp 同理,见根 CLAUDE.md §2)。 ⇒ 本会话只能验到「dist/index.js 生成了」,「rvh-debug 真的连上」要到下一个会话开头才看得到。 台账照实写,别把「装完了」记成「连上了」。


T1-1 修 4 个 verify 脚本的静默截断

会话:RB · 前置:无 · 来源backlog.md 已记为 🔴,本任务是执行

缺陷set -u 下裸 $var紧跟非 ASCII 字节(全角 、破折号等)会被 bash 并进变量名 → 判为 unbound → 当场终止。与 locale 无关,bash 3.2(macOS 系统 bash)逐字复现。

⚠️ 危害不是报错,是静默截断:脚本半路死掉,前面全绿、后面从来没跑过, 汇总行压根不打印。已经吃过两次 —— cross-end-check.sh 崩在 §B(§E/§D/§F 从未执行, 当时以为"一直是绿的");learning-loop-verify.sh 崩在 M1(M/N 两段从未跑过,修完立刻暴露 2 个真 FAIL)。

当前计数(2026-08-29 本会话实测,与 backlog 记录逐字吻合):

脚本处数
scripts/privacy-verify.sh10
scripts/release-verify.sh10
scripts/ops-verify.sh5
scripts/migration-verify.sh4

动作

bash
# 扫描(对每个脚本跑一次)
perl -ne 'while(/\$([A-Za-z_]\w*)([^\x00-\x7F])/g){print "$.: \$$1\n"}' scripts/<>

逐处 $var${var}。⚠️ 别只修报错那一行 —— 潜伏的那些在「平时走不到的 else 分支」里, 只有按模式全扫才找得全。修完照 cross-end-check.sh / learning-loop-verify.sh 的先例, 在每个脚本头部写死陷阱说明 + 自检命令。

验收

bash
# ① 四个脚本扫描均为 0
for f in privacy-verify release-verify ops-verify migration-verify; do
  echo -n "$f: "; perl -ne 'while(/\$([A-Za-z_]\w*)([^\x00-\x7F])/g){print "x\n"}' scripts/$f.sh | wc -l
done
# ② 每个脚本整跑一次,确认汇总行打印出来了

🔑 真正的收获在第二条:看有没有此前从未执行过的段落冒出新的 FAIL。 改语法本身是次要的 —— 新 FAIL 要按 docs/verification/README.md 的规矩 拆进 CHANGELOG(修好的)/ backlog(待修的)/ 清单的「已知未修」,不要留报告文件

回滚git revert 单条 commit。这四个脚本目前不在任何 CI 里,改坏不阻塞任何流程。


T1-2 修 rvh-debug MCP 连不上

会话:RB(Node 构建,非 Flutter) · 前置:无

现象:本会话启动时 rvh-debug (CONNECTION_CLOSED),其工具 mcp__rvh-debug__* 全部不可用。

根因(2026-08-29 实测,不是代码问题)

rvh/rvh-debug-mcp/dist/          ❌ 不存在
rvh/rvh-debug-mcp/node_modules/  ❌ 不存在

.mcp.json 指向 rvh/rvh-debug-mcp/dist/index.js。对照 rb-debug-mcp/ 两者都在。 ⇒ provisioning 缺口:合仓把源码带了过来,但 dist/ 是 gitignored 产物,没人在新仓里构建过。

动作

bash
pnpm --dir rvh/rvh-debug-mcp install     # package.json 有 postinstall: tsc,装完即构建
ls rvh/rvh-debug-mcp/dist/index.js       # 确认产物在

然后把这一步补进 provisioning 文档 —— rvh/QUICKSTART.md 开头已有「新机器先做这三步」 (local_packages/opencv_dart · .env · assets/icons/,2026-08-29 commit 6f26239a 加的), 本步骤是第四条,落点相同。⚠️ 别新建一份 provisioning 说明,那是第二本账。

验收ls rvh/rvh-debug-mcp/dist/index.js 存在 · 重启 MCP 后 rvh-debug 不再报 CONNECTION_CLOSED · rvh/QUICKSTART.md 里能 grep 到这一步。

回滚:无需回滚(只产生 gitignored 产物 + 一段文档)。


T1-3 修根 CLAUDE.md 两处「唯一 as-built 日志」假话

会话:RB · 前置:无

事实:合仓后仓里有三份 CHANGELOG —— 根 196 KB · rvh/CHANGELOG.md 248 KB(还在独立更新, 比根的还大)· admin/CHANGELOG.md 3 KB。而根 CLAUDE.md 两处仍写着「唯一」:

CLAUDE.md:87   ├── CHANGELOG.md             # 唯一的 as-built 日志
CLAUDE.md:778  | 做过什么、怎么做的(as-built) | CHANGELOG.md —— **唯一**执行日志 |

这与 docs-governance-plan.md P0 抓的那批「控制文件在说假话」同型, 区别是这一处是合仓新造出来的

动作(选低成本那条,不做 CHANGELOG 合并):改口径为「每端各一份」, 两处都写明去处(桌面端 / admin → 根;移动端 → rvh/CHANGELOG.md)。 ⚠️ 真合并 4400+ 行历史代价大、收益低,明确不做 —— 见 §4「不做什么」。

验收grep -n "唯一.*as-built\|唯一.*执行日志" CLAUDE.md 无输出 · pnpm run check:claude-paths 绿 · node scripts/check-doc-links.mjs 绿。

回滚git revert


阶段 2 前言

不变量:这是本计划收益最大的一段。T2-1 搬家不删内容;T2-2 删的是通用教程、不是项目知识。 离场条件:RVH 单端会话开销回到 30k 以下(按 §6 附录 A 复现命令量)。


T2-1 rvh/CLAUDE.md 的 57 KB 红线节下沉

会话:RB 会话即可 —— 依据 CLAUDE.md §9「实践边界」:改 rvh/CLAUDE.md 这类 不需要跑 Flutter 就能验收的改动在 RB 会话做是安全的(验收走 check:claude-paths / check-doc-links,本来就是根侧脚本)。不碰任何 rvh/lib/**.dart 文件。

前置:✅ 已满足 —— P0-1 于 2026-08-29 实测判定 A(commit 6def2e18)。

收益口径(P0-1 校正后,别按"层级替换"想):注入是祖先链全量 ⇒ 本任务是按目录条件命中,不是按层级替换。实测占比:约 93% 的 RVH 会话不碰 lib/features/sync/,它们省下 57 KB(44.4k → 28.6k,−36%);剩下约 7% 两份都注入、 总量持平(+1%,多的是留在原位的索引)。期望值 ≈ −33%。数据与复现见 §0.2 与 §6 附录 A ⑨。

现状

rvh/CLAUDE.md                     83,107 B
  └ 「跨端 Sync 协议红线」一节      57,487 B / 839 行 / 占 69%
      ├ 编号对照表
      ├ 14 条红线(#5b #5d #5e #5f #5g #5h #6b #6c #6d #6e #6f #6g #6h)
      ├ 守卫 bash 代码块            12,433 B(占该节 21.6%)
      └ 跨端契约镜像 backlog

动作

  1. rvh/lib/features/sync/CLAUDE.md,把整节原样搬入(内容一个字不改 —— 它的「契约 → 指针 / 本端落地 / 本端独有」三段式形状是 T3-8 + T4-4 收敛的成果,别动)。
  2. rvh/CLAUDE.md 原位留索引:14 条一行一条(编号 + 一句话 + 「正文在 lib/features/sync/CLAUDE.md」), 照根 CLAUDE.md §4 全量红线索引的写法。编号对照表留在 rvh/CLAUDE.md (它是消歧工具,任何 RVH 会话都可能需要,不该跟着下沉)。 ⚠️ 索引要压到最小(目标 ≤2 KB) —— 祖先链全量注入意味着,对那 7% 会下沉进去的会话来说 索引是净增成本、被读两遍。索引行只给「编号 + 一句话标题 + 去哪找」, 不复述理由、不抄判据;想多写一句时记住它会被收两次费。
  3. rvh/CLAUDE.md 顶部加一行告警,抄根文件那条:走 Bash 干活时注入不触发, 改 sync 代码前请显式读一次 rvh/lib/features/sync/CLAUDE.md
  4. 更新根 CLAUDE.md §4 四条双端契约红线里指向 rvh/CLAUDE.md双向指针 (#5i → RVH #5h · #6d → RVH #6g · #9 → 镜像 backlog · #10 → RVH #5e), 改成指向新位置。⚠️ 这四条的正文不动,只改指针的落点。

验收

bash
wc -c rvh/CLAUDE.md rvh/lib/features/sync/CLAUDE.md   # 前者应 ≤28 KB(含 ≤2 KB 索引),两者之和 ≈ 原 83 KB + 索引
pnpm run check:claude-paths                            # 必须绿(rvh/ 在 ROOTS 里)
node scripts/check-doc-links.mjs                       # 必须绿
bash scripts/cross-end-check.sh                        # 18 ✅ / 0 ❌ 不变

⚠️ check-claude-md-paths.mjs 的文件清单要加第 7 份 —— 该脚本的 ROOTS 与 package.jsoncheck:claude-paths 命令行清单是两处(合仓 T3-7 已在脚本里 留了注释说明"新增子项目要动两处")。不加 = 新文件里的路径不受校验。

回滚git revert 单条 commit(纯文档移动,无代码依赖)。


T2-2 删两份通用 Claude Code 教程

会话:RB · 前置:无

对象

文件体量判据
rvh/docs/guides/claude-code-tips.md41.5 KB通用 Claude Code 使用教程,开头钉着「适用版本:V2.1.29+」
rvh/docs/guides/claude-skill-guide.md26.0 KB通用 Skill 编写教程,同样钉着版本号

为什么删而不是归档:① 它们不是项目知识,是第三方工具的教程, 而该工具每周都在变 —— 钉版本号的教程只会越来越错;② 模型自带这部分知识, 且本环境有 claude-code-guide agent 专门答这类问题;③ 归档只是把腐烂搬个地方。

引用点(删前必须一起改,共 7 处 + 1 处死过滤)

rvh/docs/README.md:85,86,153,154,305,306,427   ← 6 处链接 + 1 处目录树
rvh/docs/guides/README.md:11,12                 ← 表格两行
rvh/.claude/skills/doc-consistency-check/SKILL.md:60  ← grep -v "claude-skill-guide" 过滤,删后成死过滤

⚠️ rvh/CHANGELOG.md:956 也提到它们,但那是历史记述,不要改

验收

bash
grep -rn "claude-code-tips\|claude-skill-guide" --include='*.md' . | grep -v node_modules | grep -v CHANGELOG
# 期望:只剩 docs/plans/archive/ 与 rvh/CHANGELOG.md 里的历史记述
node scripts/check-doc-links.mjs   # 必须绿

回滚git revert(文件在历史里,随时能取回)。


阶段 3 前言

不变量:补的是闸门与索引,不改任何业务行为。 离场条件:新接的 CI 闸门至少绿跑一次(一道恒红的闸门等于没有闸门 —— 本仓 2026-08-18 连红 6 天的教训)。


T3-1 verify 脚本的静态段接进 CI

会话:RB · 前置:T1-1 必须先做完(否则接进 CI 的是一个会静默截断的脚本)

现状(2026-08-29 实测接线矩阵):

脚本CIpackage.jsonskill线上凭据依赖纯静态检查处数
sync-verify.sh000611
ops-verify.sh000165
privacy-verify.sh0002516
release-verify.sh000727
migration-verify.sh0000(只依赖本地库)9
learning-loop-verify.sh000627
db-audit.sh00040

这与合仓前 cross-end-check.sh 的病完全同型:一道只在特定人的特定机器上、 且要靠人记得跑的闸门,按本仓自己的标准不合格。合仓治好了那一个,还剩七个

动作(照 cross-end-check.sh 进 CI 的先例,不要贪多):

  1. 不要求整体上 CI —— 多数确实需要线上凭据。做法是把不依赖凭据的段落抽出来, 优先级按上表最后一列:release-verify(27)· learning-loop-verify(27)· migration-verify(9,且零凭据,最容易)。
  2. 新建 .github/workflows/ci-verify.yml(或并进现有 ci.yml,二选一,别两处都放)。
  3. 必须带「防全 SKIP 假绿」机制 —— 抄 cross-end-check.sh--max-skip=N。 没有这个,一个因缺凭据而全部 SKIP 的脚本会永远显示绿色。

验收:新 workflow 至少绿跑一次(贴 run id 进台账)· 本机跑同样命令结果一致 · 故意注入一个缺陷能让它变红(反向注入实测,不做这一步不算完)。

回滚:删 workflow 文件。


T3-2 补 docs/README.md + scripts/README.md

会话:RB · 前置:无

缺口docs/ 下 13 份根层文档没有索引,而 plans/ archive/ cross-end/verification/ tools/ supabase/ 每个目录都有 READMEscripts/ 25 个脚本同样没有。

动作

  • docs/README.md:13 份根层文档一行一条(做什么用 / 谁在引用它)。 ⚠️ 同时写明「两套 UI 规范是刻意的,不是漂移」 —— docs/ui-standards.md(60 KB, Tailwind/桌面端)与 rvh/docs/ui-guidelines/(193 KB,Material 3/移动端)各管一端、 不合并。不写清楚,下一个人会当成漂移去"修"。
  • scripts/README.md:25 个脚本一行一条 + 接线状态(CI / package.json / skill / 只有文档引用)。 接线矩阵直接用 §6 附录 A 的命令现生成,别手抄。

验收node scripts/check-doc-links.mjs 绿 · 两份 README 里每个提到的路径都存在。

回滚:删文件。


T3-3 根 ci.ymlpaths 过滤

会话:RB · 前置:无 · 来源:合仓评估 §7 已登记(当时判「留着」)

为什么现在改判:合仓前只有 admin/ landing/ 会误触发;合仓后 rvh/ 也进来了, 触发频率翻倍。改 rvh/ 的纯文档 commit 会跑一整套桌面端 CI(Rust 编译 + 前端构建)。

⚠️ 风险提示:改的是桌面端主闸门。paths 写窄了会让真该跑的不跑 —— 比 CI 白跑严重得多。建议用 paths-ignore 列出四个子项目目录,不要paths 正向白名单 (正向名单漏一个新目录就静默失守)。

验收:改 rvh/ 下一个文件推一次 → 桌面端 CI 不触发ci-rvh.yml 触发 · 改 src-tauri/ 下一个文件推一次 → 桌面端 CI 触发。两次都要实测。

回滚git revert


阶段 4 前言

不变量:四项互不依赖,可任意排期。T4-2 有特殊纪律。 离场条件:无(本阶段是清理,不阻塞功能迭代)。


T4-1 给 docs-governance-plan.md 一个了结

会话:RB · 前置:无

现状:该计划 2026-08-14 立项,至今 P0.1 / P0.4 / P0.7 / P1.1 / P1.4 / P1.5 / P3.1 / P3.3 / P3.4 无完成标记,其中 P0.2 与 P3.1 仍标 🔴

它正在变成它自己批判的那种东西 —— 开篇写的正是「状态行与实况冲突,比没有更坏」。

动作:逐项核实真实状态(有些可能已被后续工作顺带做掉,例如 P0.5 已标 ⏭、 P0.6 的前提已随合仓 T4-7 消失)→ 做完的标 ✅ → 仍要做的转 backlog.md → 补顶部状态行 → 归档进 archive/

验收docs/plans/archive/docs-governance-plan.md 要么带完整状态行留在活跃区、 要么已在 archive/node scripts/check-doc-links.mjs 仍绿(归档会造悬挂引用)。

✅ 已完成(2026-08-30):逐项现场重验 18 项 → 归档进 archive/,顶部加「逐项核实结果」表 (判定 + 依据,每条都指得出证据)。

发现的两件事值得留在这里:

  • 两个挂着 🔴 的(P0.2 红线指针指反、P3.1 四个 skill 缺 frontmatter)早在两周前就修好了, 只是没人回来标记 —— 这正是该方案开篇批判的「状态行只在创建时写一次,比没有更坏」原样复发在它自己身上。 P0.1 / P0.4 则是以撤销 / 换写法代替修正(枚举清单整体撤销、skill 触发条件不再抄第二份), 照原文去「做完它」反而会把烂账种回去。
  • 7 条尾巴转 backlog.md §文档治理尾项(eslint 入闸 · admin/AGENTS.md · 4 份文档的日期行 · temp/ 11 份 handoff · Edge Function UA · tools/ 两条)。 其中 UA 那条原文写「×3」,重数是 5 处 / 4 个函数

⚠️ 归档当场造出 1 处悬挂引用backlog.md 新写的那句指向它), 本文件与 post-merge-phase4-handoff.md 里的 4 处 markdown 链接也一并补了 archive/ 前缀。check-doc-linksgit mv 之后、补前缀之前确实红了一次 —— 这道门是有效的。


T4-2 删 22.3 MB 归档 SQL + 重写历史

会话:RB · 前置:🔴 工作树干净 + 双远端已同步 + 无其他会话在动这个仓

对象docs/archive/rvh-schema-export/04-vocabulary-data.sql(22,289,665 B)—— 2026-03 的 4,953 条预装词 INSERT 导出,已被 lampio_dict.db 完全取代。

已立项docs-governance-plan.md P5 写了完整步骤(含 filter-repo 命令), 本任务只是执行它,别在这里重写第二份方案。

⚠️ 必须单独做、不与任何改动同批。⚠️ 重写历史会让所有 tag 的 SHA 变化 —— CLAUDE.md §4 红线 #11 的 shipped_migrations.txt 真相源是发布 tag, 动手前必须确认这一点已被 P5 的方案覆盖(该方案写了就照做,没写就先补上再动)。

验收:按 P5 自带的验收清单。

回滚:动手前打 tag + 本地镜像 clone(照合仓 T3-1 的做法)。

✅ 已完成(2026-08-30)—— 走 P5 自带的降级出口,不重写历史

P5 的 ROI 算式(「.git 共 72 MB,删 7.6 MB ≈ 回收 10%」)在动手前重算已不成立, 用户据此选了 P5 原文写着的降级路径:仅从工作树删除 + docs/archive/README.md 标注。 动作 = git rm docs/archive/rvh-schema-export/04-vocabulary-data.sql + 该 README 补一段说明。

重算出来的三个数(2026-08-30 实测,取代 P5 里那组):

P5 写的实测
.git 总量72 MB328 MB(pack 151.13 MiB × 3 + 松散 175.67 MiB / 4889 对象,未 gc)
目标文件raw 21.3 MB / pack 7.6 MBraw 22,289,665 B,全历史仅 1 个 distinct blob3e42910f),pack 后 7,941,186 B
预装库(真正的大头)「单 blob pack 后 16 MB」按 4 个历史路径名合计 35 blob / 94.21 MB on disk(合仓把 RVH 的历史也带了进来)

⇒ 回收 7.57 MiB / 328 MB ≈ 2.3%(对 gc 后的 pack 也只有 ~5%),不是 10%。 而预装库那 94 MB 是红线 #10 要求保留的必需资产,动不了 —— 即「重写历史」这把刀 砍不到仓库真正的重量所在。

两处 P5 与本任务正文都没算到的代价(本次核实时发现,是选降级的加权项):

  • 仓里不止 main 一条分支feat/admin-ops-console = 01a96d47双远端都有, 且 GitHub 上有 refs/pull/1/head(一个 open PR)。git filter-repo 重写的是所有 ref, 这条分支的 SHA 一样会变,强推后那个 PR 会变成 head 与分支对不上的僵尸状态。
  • 两个远端的 tag 集合本来就不对称:GitHub 有全部 11 个 tag, Gitee 只有 pre-rvh-merge 一个(2026-08-30 git ls-remote 实测)。 所以「双远端 tag 强制同步」不是一条对称操作。

🔑 本任务正文要求的「先确认 P5 覆盖了 tag SHA 风险,没写就补」—— 判定为不适用。 2026-08-30 实测确认 P5 确实没写 tag 那一段(只有 filter-repo 命令 + remote 重加)。 但那条要求是条件句:它防的是「重写历史让红线 #11 的 shipped_migrations.txt 真相源 (发布 tag)换 SHA」。降级路径下 11 个 tag 一个都不动,风险不存在, 故没有补 P5(也因此 §2「不改归档件历史记述」那条纪律本次无例外)。 将来若有人重新捡起重写历史的想法,这一段仍要先补

前后对照

HEADe4d08322本次提交(无 SHA 重写,历史线性追加)
.git328 MB328 MB(不变) —— blob 留在历史里,这是降级的代价
docs/archive/ 工作树21.6 MB312 KB
全部 commit SHA / 11 个 tag / 双远端 / PR #1全部不受触碰

blob 仍可取回:git show e4d08322:docs/archive/rvh-schema-export/04-vocabulary-data.sql

顺带处理rvh/pubspec.lock 有一处 opencv_dart 从 hosted 改回 path 的既有改动 —— 按 rvh/pubspec.yaml 第 202-203 行明令(「仓里提交的是 hosted 那版,本机那次改写属预期噪音, 别提交回去」)还原,未提交。它由本机专属的 pubspec_overrides.yaml 生成, 下次 flutter pub get 还会再出现。

⚠️ 另一处过期前提:交接单记的「4 个未推送 commit,HEAD=55dd9402」到 2026-08-30 已不成立 —— git ls-remote 实测双远端 refs/heads/main 都已是 e4d08322,无需 push。


T4-3 两份 backlog 分片 + rvh/docs/plans/ 补归档节律

会话:RB · 前置:无

现状

docs/plans/backlog.md         253 KB / 72 个顶层条目(含 5+ 条已标 ✅ 未移走)
docs/plans/backlog-archive.md  45 KB
rvh/docs/plans/backlog.md     114 KB
rvh/docs/plans/backlog-archive.md 10 KB
rvh/docs/plans/               29 份 plan,❌ 无 archive/ 目录

任何读 backlog 的会话现在要吃 72k tokens。且根侧 backlog 里已有 5+ 条标着 「RVH 新会话」的跨端条目 —— 两本账实际上已经在互相渗透。

动作:① 分片(docs-governance-plan.md P1.5 已提方案,未执行); ② 把已标 ✅ 的条目移进 backlog-archive.md(保留裁决推理,不删 —— README.md 的规矩); ③ 建 rvh/docs/plans/archive/ 并跑一次批量归档; ④ 跨端条目定一个单一落点(建议根侧 backlog,rvh/ 那份只留指针)。

验收node scripts/check-doc-links.mjs 绿 · 两份 backlog 里 ## ✅ 条目数为 0。

✅ 已完成(2026-08-30)。⚠️ 上面「现状」那五行是 2026-08-29 快照,执行时四行里有三行已漂: 根 backlog 是 255 KB / 72 条 / 只有 4 条 ## ✅(正文写「5+」); rvh/docs/plans/backlog.md114 KB / 35 条,其中 18 条是 ✅ —— 清理面在 RVH 侧比正文描述的大得多, 正文只盯了根侧。只有「29 份 plan、无 archive/」是准的。

结果

文件
docs/plans/backlog.md255,267 B / 72 条124,804 B / 55 条(−51%)
docs/plans/backlog-archive.md44,939 B136,935 B
rvh/docs/plans/backlog.md114,644 B / 35 条56,638 B / 30 条(−51%)
rvh/docs/plans/backlog-archive.md9,977 B95,384 B
rvh/docs/plans/ 活跃 plan29 份,无 archive/25 份 + archive/(4 份 + README)

四个动作的落地形状:

  • ① 分片:搬走的不只是 ## ✅。根侧还搬了三块已结案但体量极大的留痕 —— EPUB 9 条缺陷(47.7 KB,8/9 已闭环)、外部 backlog 第二/三轮逐条裁定(19.9 + 10.8 KB)。 另把「短语自动高亮 B 方案」(24 KB)外迁成 phrase-highlight-followups-plan.md —— 它有阶段编号 + gate 判据 + 跨端接力顺序,形状早已是 plan 不是 backlog 条目。 一个字都没删,全部逐字换位置。这两款判据已写回 README.md 的归档节律。
  • ## ✅ 清零:根侧 4 条 ✅ + 1 条 ❌ 否决、RVH 侧 18 条 ✅,各进本端 backlog-archive.md
  • rvh/docs/plans/archive/:已建 + 写了归档节律 README。只归档了 4 份 —— 判据必须是 RB 会话能机械核实的(app_database.dart 的 schema 版本注释 v53/v57、 rvh/rvh-debug-mcp/dist 与 rvh 侧 tools/ 目录的存在性)。剩 23 份要读 Dart 现状才能判, 按 CLAUDE.md §9 是 RVH 会话的活,已登记成 rvh/docs/plans/backlog.md 的一条待办。 ⚠️ 那 4 份里 rvh-debug-mcp-plan.md 的状态行明写「未启动」而事实早已完成 —— 别照状态行判
  • ④ 跨端落点 = 「谁执行谁持有」(用户 2026-08-30 定,改判了本文件原建议的「根侧统一持有」): 正文只存一份、落在将来真正动手那一端,另一端留指针;两端都要动的(契约类)落根侧。 依据是核实时发现的三处两本账各记一半,而证据更全的那份每次都在执行端 —— 例如 push 75→4,根侧写「71 条没推上去」,RVH 侧早已算出「缺口是 63,扣掉 8 个被错标 'rvh' 的 RB 行」 且把三个诊断分支收敛到了 clean=75。按原建议搬会把更差的那份留下来。 落地:11 条迁往 rvh/docs/plans/backlog.md、1 条真重复合并(保留 RVH 那份)、 规则本体写进两份 backlog 的头部(不是只写在这里 —— plan 会归档,规则不会)。

⚠️ 归档 4 份 rvh plan 当场打破了 pnpm run check:claude-pathsrvh/lib/features/sync/CLAUDE.md 引着 word-cloze-contexts-sync-rvh-plan.md。 已补 archive/ 前缀(连同 rvh/docs/database/schema.md 那处)。 docs/cross-end/17rvh/CHANGELOG.mddocs/plans/archive/rvh-merge-plan.md 里的同名引用 刻意没动 —— 历史记述。


T4-4 docs/mcp-primer.md 归档

会话:RB · 前置:无

判据:19.7 KB 的 MCP 通用入门教程,全仓只有 1 处引用且在归档件里 (docs/plans/archive/rb-debug-mcp-plan.md:9)。

⚠️ 执行时重数为 3 处(2026-08-30):上面这个 1 是 2026-08-29 的快照,此后 T3-2 新建的 ../README.md(根层文档索引)与本文件自身各多引一处。索引那处是真耦合, 归档时必须回改(份数 13→12 + 删行 + archive/ 那行补一句),否则索引说假话。

动作git mv docs/mcp-primer.md docs/archive/ + 在 docs/archive/README.md 登记。 归档不删 —— 与 T2-2 的区别是:这份是自己写的、讲本项目 MCP 设计的材料, 有史料价值;T2-2 那两份是第三方工具的通用教程,只会腐烂。

验收node scripts/check-doc-links.mjs 绿 · docs/archive/README.md 有新条目。

✅ 已完成(2026-08-30)git mvdocs/archive/docs/archive/README.md §其它 加一行; docs/README.md 改 12 份 + 删 Runbook 组那一行 + archive/ 行补提它。两道检查绿。 副产:docs/mcp-primer.md 移走后不再被 check-doc-links 的活跃区扫描(它只扫 docs/*.md 顶层), 但它内部引的 docs/plans/archive/rb-debug-mcp-plan.md 本来就在,无悬挂。


4. 不做什么(明确排除,防止后来会话扩大范围)

不做理由
合并三份 CHANGELOG4400+ 行历史,代价大收益低。T1-3 改口径即可
合并两套 UI 规范Material 3 vs Tailwind 是真的不同,不是漂移。T3-2 里写清楚就够
把根 §4 四条契约红线正文下沉T4-4(合仓)的裁定成立:下沉等于藏进"只有改 Rust 才可见"的地方。且 T2-1 做完已能拿到约 80% 的收益,风险低得多。等 T2-1 落地后再评估是否还需要
统一 RB / RVH 的红线编号合仓 T4-4 已裁定不统一(350 处引用 + 无机械守卫),靠双向指针消歧。别重开
合并两个 debug MCPrb_supabase_queryrvh_supabase_query 确实查同一个 Supabase 项目、是重复实现,但抽公共层的收益 < 破坏两个都能跑的调试链的风险。T1-2 只修连接,不动结构
改 RB 本体散在根目录的结构收益不确定、风险高。§0.4 已登记为观察
rvh/assets/sql/01_create_tables.sql 第三份 schema 真相源合仓评估 §7 已登记为"已知未处理"。cross-end-check.sh §E 现以 Supabase DDL 为仲裁者比两端列集合,机械层已经守住,优先级低

5. 退路(⏭ 已不需要 —— P0-1 判定 A,2026-08-29)

本节保留为历史记述:P0-1 实测判定 A,T2-1 前置成立,下面三条退路都不必走。 保留是因为 B2 从"替代方案"变成了一个可选的补充(见下),别把它连同本节一起忘掉。

原文如下(判定为 B 或 C 时适用)—— T2-1 作废,此时 RVH 单端会话的开销降不下来,可选:

  • B1 折中:把红线节搬到 rvh/docs/sync-contract.md(普通文档,完全不注入), rvh/CLAUDE.md 只留索引 + 一行「改 sync 代码前必读那份」。 收益相同,代价是失去自动注入,完全依赖那行提醒被遵守 —— 比 T2-1 弱,但比现状好。
  • B2 保守:只把 12,433 B 的守卫 bash 代码块移出去(它们是判据规格, 合仓评估 §7 已确认「没有任何东西在执行它们」),正文留原地。收益约 -3.5k tokens。

    🔵 判定 A 之后,B2 变成了 T2-1 的可选补充:把守卫块从下沉后的 lib/features/sync/CLAUDE.md 里再抽进一份普通文档,能让那 7% 的 sync 会话 也降约 3.5k(45.0k → 41.5k)。但本计划不做 —— 那些守卫至今没有任何执行者 (§7 首条),再往外挪一层只会让它们更不可能被接进 CI。 正确顺序是先把它们接进 ci-rvh.yml,再谈搬家

  • B3 不动:接受 43.7k,把本计划其余部分照做。

无论走哪条,结论要写回本文件顶部状态行,别让后来会话按作废的方案开工。


6. 附录 A · 数字复现命令

本文所有数字都是 2026-08-29 的快照。别照抄当事实 —— 合仓评估自己就吃过亏(docs/cross-end/40 的行数一天就从 29/45 漂到 54/73)。

bash
cd /Users/larry/reading-browser

# ① CLAUDE.md 家族体量(token ≈ 字节 / 3.5,CJK 启发式,±20%)
for f in CLAUDE.md src/CLAUDE.md src-tauri/CLAUDE.md rvh/CLAUDE.md admin/CLAUDE.md landing/CLAUDE.md; do
  printf "%-28s %8s B  ≈%5.1fk tok\n" "$f" "$(wc -c < $f)" "$(echo "scale=2; $(wc -c < $f)/3500" | bc)"
done

# ② 根 CLAUDE.md 按节体量
awk '/^## /{if(n){printf "  %-42s %6d B  %4d 行\n",n,b,l} n=$0;b=0;l=0;next}{b+=length($0)+1;l++}
     END{if(n)printf "  %-42s %6d B  %4d 行\n",n,b,l}' CLAUDE.md

# ③ rvh/CLAUDE.md 红线节占比
awk '/^## 🔄 跨端 Sync 协议红线/,/^## 开发流程/' rvh/CLAUDE.md | wc -lc

# ④ skill description 恒注入成本(只有根 12 个是恒注入,scoped 的按需)
ls .claude/skills/*/SKILL.md | wc -l

# ⑤ 脚本接线矩阵(T3-2 的 scripts/README.md 直接用它生成)
for f in $(ls scripts/ | grep -v '^lib$'); do
  printf "%-30s CI=%s pkg=%s skill=%s verif=%s\n" "$f" \
    "$(grep -rl -- "$f" .github/workflows/ 2>/dev/null | wc -l | tr -d ' ')" \
    "$(grep -c -- "$f" package.json)" \
    "$(grep -rl -- "$f" .claude/skills/ rvh/.claude/skills/ admin/.claude/skills/ 2>/dev/null | wc -l | tr -d ' ')" \
    "$(grep -rl -- "$f" docs/verification/ 2>/dev/null | wc -l | tr -d ' ')"
done

# ⑥ 标点陷阱扫描
for f in privacy-verify release-verify ops-verify migration-verify; do
  echo -n "$f: "; perl -ne 'while(/\$([A-Za-z_]\w*)([^\x00-\x7F])/g){print "x\n"}' scripts/$f.sh | wc -l
done

# ⑦ 记忆库是否仍空置
ls -A ~/.claude-cli/projects/-Users-larry-reading-browser/memory/ | wc -l

# ⑧ P0-1 探针的唯一性核验(三道题的答案各自只能出现在一个文件里)
CLAUDE_MDS='CLAUDE.md src/CLAUDE.md src-tauri/CLAUDE.md rvh/CLAUDE.md admin/CLAUDE.md landing/CLAUDE.md'
grep -rl 'Tauri CLI'   $CLAUDE_MDS   # 期望只有 CLAUDE.md          (Q0 控制题)
grep -rl 'OcrClozeGate' $CLAUDE_MDS   # 期望只有 rvh/CLAUDE.md      (Q2 深度1对照)
grep -rl '<口令>' . | grep -v node_modules | grep -v '^./.git'   # 期望:建探针前 0 命中(Q1)

# ⑨ T2-1 收益的关键变量:多少比例的 RVH 会话会碰 lib/features/sync/
#    (祖先链全量注入 ⇒ 收益只在「不碰 sync 目录」的会话上兑现)
echo "近3月 动 rvh/ : $(git log --since=2026-06-01 --oneline -- rvh/ | wc -l)"
echo "近3月 动 sync/: $(git log --since=2026-06-01 --oneline -- rvh/lib/features/sync/ | wc -l)"
echo "全历史 动 rvh/ : $(git log --oneline -- rvh/ | wc -l)"
echo "全历史 动 sync/: $(git log --oneline -- rvh/lib/features/sync/ | wc -l)"

# ⑩ rvh scoped skill 的 description 成本(与 CLAUDE.md 注入共用触发条件)
for d in rvh/.claude/skills/*/SKILL.md; do
  awk '/^---$/{n++;next} n==1' "$d" | awk '/^description:/{f=1} f&&!/^(name|allowed-tools|model):/{print}' | head -20
done | wc -c

7. 已知悬而未决(本计划不解决,登记备查)

状态影响
rvh/CLAUDE.md 里那批守卫 grep 没有任何东西在执行合仓评估 §7 已登记ci-rvh.yml 只跑 analyze + 5 条架构 grep + test。那些块是判据规格不是闸门;真正在守的是每条点名的 Dart 回归测试。接进 CI 是笔独立的活,接上之前别把"grep 写着"当"已经守住"
RVH 的 Dart 格式无机械守卫backlog.md 已记ci-rvh.ymldart format 门 2026-08-29 删除(它在任何能解析本项目依赖的 Flutter 上都会因 tall-style 重写当场红 502 个文件)。要不要做一次全仓重排版待定 —— 做了会冲掉几乎每个 .dart 的 blame,而 blame 正是合仓不用 subtree 保下来的东西
百度 OCR 控制台删应用backlog.md 已记,待用户操作AK/SK 不会自己过期,只要控制台里那个应用还在就还能被计费
记忆库空置(§0.1 原因 1)本计划不解决本计划治的是症状(把已有内容搬到正确的加载层)。要根治棘轮,需要让「值得长期记住但不必每次读」的事实有一个按需召回的落点。建议 T2-1 落地、量到实际收益之后再单独立项 —— 现在就动等于同时改两个变量,量不出哪个起了作用

8. 一句话

合仓是成功的(跨端场景持平却换来必然同步),代价全部落在单端会话上, 而其中 RVH 的 +57% 有单一成因、单一修法。

如果只做一件事,做 T2-1 —— 前置 P0-1 已于 2026-08-29 实测通过(判定 A), 且实测占比把它的收益钉死为「约 93% 的 RVH 会话 −36%,期望值 −33%」。其余按阶段择期。