Skip to content

RVH 预装词库 pipeline → RB 迁移正式 plan(Q3 第二步)

物理位置:~/reading-browser/docs/plans/rvh-vocab-pipeline-migration-plan.md(跨端 plan 统一存 RB,§9) 创建:2026-07-19 · 承接:~/reading-browser/docs/plans/rvh-vocab-pipeline-inventory.md(只读盘点) 性质:正式迁移方案,待用户确认后实施。本 plan 只规划 RB 侧动作;真正改 RVH 仓(移除/改造它那份 pipeline)必须另开 RVH 新会话(§9 会话隔离),清单见 §八。 敏感度:触红线 #10(byte-equal 预装库),比 admin 合仓更敏感 —— 任一步破坏 byte-equal 会触发 sync backfill skip + log::warn + VOCABULARY_SEED_VERSION 失去版本语义。故 §四 / §六给出双端 byte-equal 断言护栏,作为不可跳过的验收闸。 全部跨仓引用用 ~-锚定绝对路径。


一、目标与非目标

目标:把 RVH 预装词库 pipeline(~/reading_vocab_helper/tools/vocabulary_builder_v3/,Dart)lift-and-shift 迁入 RB 仓,消除「RB 产 lemmatizer JSON → 跨仓喂 RVH pipeline → 烤 db → sync 回 RB」的环状 split-brain,使词库内容决策与产出同仓(RB),RVH 降级为纯消费方。

本会话非目标(明确排除):

  • ❌ 不动 RVH 仓任何文件(移除旧 pipeline、删 assets/nlp、改 RVH skill 均属 §八,RVH 新会话做)
  • ❌ 不重写为 Rust/TS(inventory §六结论:ROI 低,Dart 工具能跑就保留)
  • ❌ 不借迁移之机改词库内容(治理规则 / 例句 / tag 一律不动 —— 迁移必须内容 byte-identical,见 §四)
  • ❌ 本 plan 不执行任何动作,仅规划;实施在用户确认后另起

二、当前拓扑(split-brain 环,已实测锚定)

┌─ RB 仓 (~/reading-browser) ──────────────────────────────────────┐
│  build_dict.rs (examples/)                                        │
│    └─ 产出 → src-tauri/assets/nlp/{surface_to_base,base_forms}.json│  ← lemmatizer 权威源
│         (force_as_base + picked/passed/trying correction 已内置)   │     (红线 #5e)
│  sync-rvh-vocabulary.sh                                           │
│    └─ 方向 RVH→RB:cp RVH db → src-tauri/assets/reading_vocab.db   │  ← 消费方(当前)
└──────────────────────────────────────────────────────────────────┘
        │ nlp JSON 跨仓复制(byte-equal)          ▲ db 跨仓复制(byte-equal)
        ▼                                        │
┌─ RVH 仓 (~/reading_vocab_helper) ────────────────────────────────┐
│  assets/nlp/{surface_to_base,base_forms}.json  ← RB 产物的副本     │
│  tools/vocabulary_builder_v3/  (Dart pipeline, 25 bin + lib+data) │  ← 产出方(当前)
│    config.yaml:                                                   │
│      lemmatizer_* → ../../assets/nlp/*.json   (读 RVH 副本)        │
│      app_db       → ../../assets/databases/reading_vocab.db       │
│    generate_db.dart → 把 nlp JSON 烤进 lemma_* 表 + 产 db          │
│    data/kaikki_english.jsonl.gz → symlink ~/Downloads/(457MB,外部) │
│    data/{differentiation,etymology,generated_examples,phrase_*}.json│ ← LLM cache(入仓,沉没成本)
│  assets/databases/reading_vocab.db  ← pipeline 产物, cp 给 RB      │
└──────────────────────────────────────────────────────────────────┘

实测锚定(2026-07-19)

  • ~/reading-browser/src-tauri/assets/nlp/surface_to_base.json~/reading_vocab_helper/assets/nlp/surface_to_base.json byte-equal
  • …/base_forms.json 两端 byte-equal
  • ~/reading-browser/src-tauri/assets/reading_vocab.db~/reading_vocab_helper/assets/databases/reading_vocab.db byte-equal
  • lemma 表契约:lemma_surface_to_base 140,370 行 / lemma_base_forms 101,646 行(sync 脚本硬断言)
  • kaikki 真身:~/Downloads/kaikki.org-dictionary-English.jsonl.gz(457 MB,gitignore + symlink)

环的本质build_dict.rs(RB 产 lemmatizer JSON)→ 副本喂 RVH pipeline → 烤进 db → db sync 回 RB。lemmatizer JSON 是 RB 产物却物理躺在 RVH 且被 RVH 消费;db 是 RVH 产物却最终服务 RB。迁移把 pipeline 移入 RB 后,两个 artifact 都在 RB 内闭环,环打开。


三、目标拓扑(迁移后)

┌─ RB 仓 (~/reading-browser) —— 词库单一事实源 ────────────────────┐
│  examples/build_dict.rs                                           │
│    └─ 产出 → src-tauri/assets/nlp/{surface_to_base,base_forms}.json│
│                              │ (同仓路径, 无跨仓)                   │
│                              ▼                                     │
│  tools/vocabulary_builder_v3/  (迁入)                             │
│    config.yaml:                                                   │
│      lemmatizer_* → ../../src-tauri/assets/nlp/*.json  (同仓)      │
│      app_db       → ../../src-tauri/assets/reading_vocab.db (同仓) │
│    generate_db.dart → 烤 lemma_* + 产 db (直接落 RB asset)         │
│    data/kaikki_english.jsonl.gz → symlink ~/Downloads/(约定位置)   │
│    data/*.json  ← LLM cache (随目录迁入, byte-identical)           │
│  sync-rvh-vocabulary.sh  (方向反转 RB→RVH, 断言不变)              │
│    └─ cp RB db → ~/reading_vocab_helper/assets/databases/…db      │
└──────────────────────────────────────────────────────────────────┘
                              │ db 跨仓复制(byte-equal, RB→RVH)

┌─ RVH 仓 —— 纯消费方 ─────────────────────────────────────────────┐
│  assets/databases/reading_vocab.db  ← 接收 RB 产物                │
│  (无 pipeline; assets/nlp/ 可删 —— 运行时读 db 内 lemma_*)         │
└──────────────────────────────────────────────────────────────────┘

关键收益:lemmatizer JSON 从 build_dict.rs 输出后同仓直接被 pipeline 消费(config 相对路径 ../../src-tauri/assets/nlp/,不再 ../../ 穿仓);db 也同仓产出直落 RB asset。环彻底消除。


四、红线 #10 byte-equal 护栏策略(本 plan 最敏感处)

byte-equal 有两个独立层面,迁移必须分开对待,否则会误触发全量 reseed:

4.1 结构迁移层 = 内容零变更(默认路径)

迁移是 lift-and-shift + 改路径 + 反转 sync不重跑 pipeline、不重产 db。迁移完成后:

  • RB 的 src-tauri/assets/reading_vocab.db 保持迁移前的原字节(不动)
  • sync 脚本反转方向后首次跑 = cp RB db → RVH db,两端仍是迁移前那份字节
  • 验收闸 A(必过):迁移前后 shasum -a 256 三处(迁移前 RVH db、迁移前 RB db、迁移后 RB db、反转 sync 后 RVH db)四者相等
  • 结果:无内容漂移 → 不 bump VOCABULARY_SEED_VERSION → 已安装用户零 reseed

这是核心纪律:结构迁移绝不改一个 db 字节。红线 #10 在结构迁移阶段的语义 = 「搬家不换家具」。

4.2 生产复现层 = 确定性 dry-run(验证 pipeline 迁移无损,非发版)

单独、可选地在 RB 内从迁入的 pipeline 重跑 generate_db.dart(Step 6 单点,读同一批 data/*.json + 同一 nlp JSON),产出 output/reading_vocab.db,与仓内现役 db 对比

  • 理想:内容 diff = 0(vocabulary / lemma_* 全表 diff 空)。SQLite 二进制可能因页布局/rowid 分配非 byte-equal,故用表级内容 diffsqlite3 .dump 或逐表 EXCEPT)而非裸 cmp 作判据。
  • 若表级内容 diff = 0:证明 pipeline 迁移无损、确定性保持 → 迁移合格。但不拿这个新 db 发版(避免仅页布局差异触发的伪 reseed);继续用 4.1 的原字节 db。
  • 若表级内容 diff ≠ 0:说明迁移引入了路径/环境/确定性回归(如 nlp JSON 读错副本、locale 影响排序、绝对路径泄漏)→ 阻断迁移,定位修复,禁止发版。

4.2 是「迁移正确性」的探针,不是「发版动作」。发版走 §八 RVH 新会话之后、下一次真实内容变更时才发生(那时才 bump 版本 + 双端 reseed)。

4.3 lemmatizer 层 byte-equal(红线 #5e 顺带守护)

迁移不改 build_dict.rs、不改 nlp JSON 内容。迁移后 config 指向 ../../src-tauri/assets/nlp/*.json(RB 权威源,非 RVH 副本)。验收闸 B:迁移后 pipeline 读到的 nlp JSON 与迁移前 RVH 副本 byte-equal(本就同源,实测已相等)—— 确保「换读源」没引入差异。


五、迁移步骤(RB 侧,有序)

全程在 ~/reading-browser 仓操作;每步给验证。Step 0–7 全在 RB,不碰 RVH

Step 0 — 预检 & 基线锚定(只读)

bash
cd ~/reading-browser
# 三处基线 SHA(迁移后逐一比对)
shasum -a 256 src-tauri/assets/reading_vocab.db                      # BASE_DB_SHA
shasum -a 256 src-tauri/assets/nlp/surface_to_base.json src-tauri/assets/nlp/base_forms.json
shasum -a 256 ~/reading_vocab_helper/assets/databases/reading_vocab.db  # 应 == BASE_DB_SHA
# 环境就绪
dart --version                                                       # 期望 3.10.x
ls -la ~/Downloads/kaikki.org-dictionary-English.jsonl.gz            # kaikki 真身在
git -C ~/reading-browser status --short                             # 记录已有脏文件, 迁移改动隔离

写下 BASE_DB_SHA 到 plan 执行记录 —— 这是 §4.1 验收闸 A 的锚。

Step 1 — 迁入 pipeline 目录

  • git mv / cp -a~/reading_vocab_helper/tools/vocabulary_builder_v3/ 整目录搬到 ~/reading-browser/tools/vocabulary_builder_v3/
    • lib/ bin/(25 dart + patch_lemmatizer_assets.pydata/(含全部入仓 LLM cache + 词表骨架)config.yaml pubspec.yaml pubspec.lock scripts/ README.md .gitignore
    • 排除(gitignore 已列,不搬):output/ .dart_tool/ data/kaikki_english.jsonl.gz(symlink,Step 4 重建)
    • 决策点(§十 开放问题 Q1):RB 已有 tools/{agid-2016.01.19,wordnet,phrase_eval,build_dict.report.txt}(build_dict 输入 + 短语评测)。迁入的 vocabulary_builder_v3/ 与之平级共存tools/,命名无冲突,建议保留原名整目录迁入
  • cd tools/vocabulary_builder_v3 && dart pub get(用迁入的 pubspec.lock 锁定版本)

验证dart analyze 通过;ls data/*.json 五个 LLM cache 尺寸与 §二锚定一致(differentiation 7MB / etymology 5MB / generated_examples 5MB / phrase_library 3.6MB / phrase_idiomaticity)。

Step 2 — 理顺 lemmatizer 环状接缝(config 路径重定向)

~/reading-browser/tools/vocabulary_builder_v3/config.yaml

key迁移前(RVH 相对)迁移后(RB 相对,同仓)
lemmatizer_surface_to_base../../assets/nlp/surface_to_base.json../../src-tauri/assets/nlp/surface_to_base.json
lemmatizer_base_forms../../assets/nlp/base_forms.json../../src-tauri/assets/nlp/base_forms.json
app_db../../assets/databases/reading_vocab.db../../src-tauri/assets/reading_vocab.db
  • 接缝理顺后的单向链build_dict.rssrc-tauri/assets/nlp/*.json → pipeline config.yaml 读同一文件 → generate_db.dartlemma_*src-tauri/assets/reading_vocab.db环变成线,单一产源。
  • patch_lemmatizer_assets.py:现为 legacy(build_dict.rs 已内置 force_as_base + picked/passed/trying correction,红线 #5e)。迁入但标注「历史修正脚本,当前 build_dict 已内置,勿在常规流程调用」—— 保留作审计锚点,不接入 build_all。

验证(验收闸 B):迁移后 config 指向的 nlp JSON 与 Step 0 基线 SHA 相等(同源,必然相等,防手滑指错文件)。

Step 3 — kaikki 外部 dump 纳管

  • 不入仓(457MB)。约定固定位置:保持 symlink 模式 data/kaikki_english.jsonl.gz -> ~/Downloads/kaikki.org-dictionary-English.jsonl.gz
  • tools/vocabulary_builder_v3/README.md(或 data/KAIKKI.md)文档化:来源 URL(kaikki.org English Wiktionary dump)、期望文件名、ln -s 重建命令、大小校验。gitignore 已含该 symlink 条目(随目录迁入)。
  • 决策点(§十 Q2):是否把 kaikki dump 移到仓内固定路径(如 ~/reading-browser/tools/vocabulary_builder_v3/data/.kaikki/)而非 ~/Downloads。建议维持 ~/Downloads symlink(零拷贝、已 gitignore),仅补文档。

Step 4 — 反转 sync 方向(RVH→RB 改 RB→RVH)

~/reading-browser/scripts/sync-rvh-vocabulary.sh

迁移前迁移后
语义RVH 产 → cp 到 RBRB 产 → cp 到 RVH
SRC~/reading_vocab_helper/assets/databases/reading_vocab.db~/reading-browser/src-tauri/assets/reading_vocab.db
DSTsrc-tauri/assets/reading_vocab.db~/reading_vocab_helper/assets/databases/reading_vocab.db
幂等 cmp -s skip保留保留
4 表白名单断言保留保留不变lemma_base_forms/lemma_meta/lemma_surface_to_base/vocabulary
lemma 行数断言 140370/101646保留保留不变
机器污染检查(audio_local_path/last_accessed_at 全 NULL)保留保留不变
版本提示提示 bump RB VOCABULARY_SEED_VERSION提示 bump RB VOCABULARY_SEED_VERSION RVH 侧版本锚(§八 协调)
  • 断言逻辑对源 db跑(现在源 = RB asset),目标是 RVH。所有 hygiene 断言对源不变,方向反转不削弱护栏。
  • 脚本头注释更新:source/target 互换、方向说明、红线 #10「产出方 RVH→RB」措辞。

Step 5 — 迁移后结构 byte-equal 验证(验收闸 A,§4.1)

bash
# RB asset 未被任何步骤改动 → 应 == BASE_DB_SHA
shasum -a 256 ~/reading-browser/src-tauri/assets/reading_vocab.db          # 期望 == BASE_DB_SHA
# 反转后 sync(RB→RVH),跑一次
bash ~/reading-browser/scripts/sync-rvh-vocabulary.sh                       # 幂等应 "Already in sync"
# 双端 cmp
cmp ~/reading-browser/src-tauri/assets/reading_vocab.db \
    ~/reading_vocab_helper/assets/databases/reading_vocab.db && echo "✅ 双端 db byte-equal"

四者(BASE_DB_SHA / 迁后 RB / 迁后 RVH / sync 幂等结果)全等 → 结构迁移零内容漂移,不 bump 版本。 任一不等 → 停,查哪步误动 db。

Step 6 — 确定性 dry-run(验收闸 §4.2,验证 pipeline 迁移无损,不发版)

bash
cd ~/reading-browser/tools/vocabulary_builder_v3
dart bin/generate_db.dart          # 只跑 Step 6, 读现有 data/*.json + nlp JSON, 产 output/reading_vocab.db
# 表级内容 diff(非裸 cmp —— SQLite 页布局可能差)
sqlite3 output/reading_vocab.db '.dump vocabulary' | sort > /tmp/new_vocab.sql
sqlite3 ~/reading-browser/src-tauri/assets/reading_vocab.db '.dump vocabulary' | sort > /tmp/cur_vocab.sql
diff /tmp/new_vocab.sql /tmp/cur_vocab.sql && echo "✅ vocabulary 内容 diff=0"
# lemma_* 三表同法比对(surface_to_base / base_forms / meta)
  • 内容 diff = 0 → pipeline 迁移无损,确定性保持,接缝正确。丢弃 output/ 的新 db,不发版。
  • 内容 diff ≠ 0 → 迁移回归,定位(多半是 config 路径读错源 / locale 排序 / 绝对路径泄漏),修到 diff=0 才算迁移完成。

Step 7 — 两端 CLAUDE.md + skill 措辞更新(RB 侧部分)

  • RB CLAUDE.md 红线 #10:产出方 RVH pipeline 单点产出 → 改为 RB tools/vocabulary_builder_v3 pipeline 单点产出sync-rvh-vocabulary.sh 方向说明 RVH→RB 改 RB→RVH;lemmatizer JSON「cargo run --example build_dict 产物 + pipeline 构建输入」保留(build_dict 仍在 RB,语义不变,只是消费者从跨仓变同仓)。
  • RB CLAUDE.md 红线 #5e(若有镜像条款):pipeline 位置 RVH→RB 更新;「RB 产 JSON 喂 RVH pipeline」环状描述改为「RB 内闭环」。
  • preinstalled-db-update skill 归属(§十 Q3):该 skill 现在 RVH(~/reading_vocab_helper/.claude/skills/preinstalled-db-update/),orchestrate 整条 pipeline→reseed→RB 交接。pipeline 迁 RB 后,skill 逻辑主体应迁到 RB(触发词「更新预装库/发布词库/reseed」在 RB 执行 dart bin/build_all.dart + 反转 sync 给 RVH + 生成 RVH 交接文档)。本 plan 只在 RB 侧新建/改 skill;删 RVH 旧 skill 属 §八。 迁移期间两端 skill 短暂并存可接受(RVH 旧 skill 会因 pipeline 已迁走而 Step 报错,需在 RVH 会话同步废弃)。
  • RB CHANGELOG.md / docs/README.md / decisions.md:记 pipeline 迁入 ADR(词库产源归位 RB)。

RB 侧不改 RVH 的 CLAUDE.md / skill / assets —— 全列入 §八。


六、双端 byte-equal 验证程序(红线 #10 验收,汇总)

迁移「完成」的判据 = 下列全绿

检查命令通过判据
A(结构·必过)RB db 未变shasum -a256 src-tauri/assets/reading_vocab.db== BASE_DB_SHA
A反转 sync 后双端相等cmp RB_db RVH_db无输出(相等)
Async 幂等再跑 sync-rvh-vocabulary.sh打印 "Already in sync"
B(lemmatizer)config 指向 nlp 源未变shasum -a256 src-tauri/assets/nlp/*.json== Step0 基线
C(确定性·探针)重跑 generate_db 内容无漂移.dump 逐表 diffvocabulary + lemma_* 全 diff=0
D(护栏存活)sync 断言未削弱读脚本4 表白名单 + 140370/101646 + 机器污染检查在

任一红 → 迁移未完成,不提交、不发版。 A/B/C 全绿方可 commit「结构迁移」批(不 bump 版本,不 reseed 用户)。


七、提交与回滚

提交(RB 侧,结构迁移批)

  • feat(vocab-pipeline): lift-and-shift vocabulary_builder_v3 into RB; reverse RVH sync direction
  • 走 RB 提交流程(/code-review 视需要);明确 commit body 声明「db 字节未变、无 reseed、VOCABULARY_SEED_VERSION 不 bump」
  • 不改 RVH 仓 —— RVH 侧动作全在 §八 新会话,独立 commit。

回滚:结构迁移不改 db 字节、不 bump 版本,回滚安全 = git revert RB 迁移批 + 恢复 RVH pipeline 目录(若已 git mv,RVH 侧尚未删则原样还在;若用 git mv 跨仓不可行——见 §十 Q4)。sync 脚本方向回退即恢复 RVH→RB。因结构迁移零内容变更,回滚不涉及用户数据 / reseed。


八、RVH 侧协调清单(必须新会话,§9 会话隔离)

本 plan 不执行下列任何项;实施在 RVH 新会话,以本 plan §三目标拓扑为准。

  • [ ] RVH 移除/归档 ~/reading_vocab_helper/tools/vocabulary_builder_v3(迁出后避免双份漂移;建议 git rm 并在 commit 注明「迁至 RB,见 rvh-vocab-pipeline-migration-plan.md」)
  • [ ] RVH assets/databases/reading_vocab.db 确认为接收 RB 产物(消费方),本地不再产
  • [ ] RVH assets/nlp/{surface_to_base,base_forms}.json:确认 RVH app 运行时只读 db 内 lemma_*、不再需 JSON(红线 #5e:cross-end/13 已折叠)→ 可 git rm 这两个副本;若仍有运行时引用则先解耦再删
  • [ ] 确认 RVH app 运行时只 ATTACH 只读 reading_vocab.db,不依赖 pipeline 在 RVH 仓内(grep vocabulary_builder_v3 无源码引用)
  • [ ] RVH .claude/skills/preinstalled-db-update/ 废弃/迁移:pipeline 已在 RB,该 skill 的 cd tools/vocabulary_builder_v3 步骤在 RVH 会失败 → 迁到 RB(Step 7 已在 RB 建对应 skill)或改为「RVH 仅接收 db」精简版
  • [ ] RVH CLAUDE.md 红线 #10 / #5e:产源 RVH→RB、sync 方向、pipeline 位置措辞更新(与 RB Step 7 对称)
  • [ ] RVH CHANGELOG.md 记 pipeline 迁出
  • [ ] 双端 byte-equal 联测:RVH 会话完成后,RB 端跑 §六 全表 diff 再确认一次两端 db 仍 byte-equal(迁出不应改字节)

九、风险

风险缓解
破坏红线 #10 byte-equal(最严重)§4.1 结构迁移绝不重产 db;§六 验收闸 A 四处 SHA 全等才算过;违反即阻断
重跑 generate_db 内容漂移(确定性回归)§4.2 dry-run 表级 diff 探针;diff≠0 阻断定位(config 路径 / locale 排序 / 绝对路径泄漏三大嫌疑)
lemmatizer 接缝指错源§5 Step2 config 显式改指 src-tauri/assets/nlp/;验收闸 B SHA 比对
kaikki 外部 dump 丢失/换机不可复现§5 Step3 文档化来源+重建命令;维持 gitignore symlink
双份 pipeline 漂移(迁移期 RVH 未删)§八 明确 RVH 新会话 git rm;迁移期不并行跑两端 pipeline
skill 断裂(RVH preinstalled-db-update 失效)Step7 RB 建对应 skill;§八 RVH 废弃旧 skill;迁移期短暂并存已知可接受
误 bump 版本触发全量 reseed结构迁移批 commit body 明令不 bump;发版留到下次真实内容变更

十、开放问题(请用户先确认,再实施)

  • Q1 目录落位:迁入 ~/reading-browser/tools/vocabulary_builder_v3/(与现有 tools/{agid,wordnet,phrase_eval} 平级)—— 认可否?还是想收拢到 tools/vocab/ 子目录统一命名?(建议:保留原名平级迁入,改动最小)
  • Q2 kaikki dump:维持 ~/Downloads symlink + 补文档(建议);还是移到仓内固定路径纳管?
  • Q3 preinstalled-db-update skill:主体迁 RB(建议);RVH 保留精简「仅接收」版还是完全删除?
  • Q4 搬迁方式:跨仓无法 git mv 保留历史 —— 用 cp -a + RVH 侧 git rm(历史留在 RVH 旧 commit,RB 视为新增)即可,还是需要 git filter-repo 迁移子目录历史?(建议:cp -a,不迁历史,简单且够用)
  • Q5 实施时机:本 plan 确认后,RB 侧结构迁移 = 本会话续做还是另起?RVH 侧必新会话(§9)。

附:关键路径速查(~-锚定)

用途路径
RVH pipeline(迁移源)~/reading_vocab_helper/tools/vocabulary_builder_v3/
RB pipeline(迁移目标)~/reading-browser/tools/vocabulary_builder_v3/(新)
lemmatizer 产源~/reading-browser/src-tauri/examples/build_dict.rs
lemmatizer JSON(RB 权威)~/reading-browser/src-tauri/assets/nlp/{surface_to_base,base_forms}.json
RB 预装库 asset~/reading-browser/src-tauri/assets/reading_vocab.db
RVH 预装库 asset~/reading_vocab_helper/assets/databases/reading_vocab.db
sync 脚本~/reading-browser/scripts/sync-rvh-vocabulary.sh
kaikki dump 真身~/Downloads/kaikki.org-dictionary-English.jsonl.gz(457MB, 外部)
RB 版本锚~/reading-browser/src-tauri/src/db/helpers.rs::VOCABULARY_SEED_VERSION
只读盘点~/reading-browser/docs/plans/rvh-vocab-pipeline-inventory.md

十一、RB 侧实施状态(2026-07-19 已完成)

RB 侧结构迁移已实施并提交:commit 6a4d0a8refactor(vocab-pipeline): lift-and-shift …)。

  • ✅ pipeline 迁入 ~/reading-browser/tools/vocabulary_builder_v3/(72 文件镜像 RVH,含全部确定性 LLM cache)
  • ✅ config.yaml 三路径重定向到 ../../src-tauri/assets/(闸 B:nlp 源 SHA 未变,解析到 RB 同仓)
  • ✅ sync 脚本反转 RB→RVH(断言/白名单不变,REPO_ROOT 锚定 cwd 无关)
  • .gitignore 收复:RB 顶层全局 data/ 误伤 → pipeline 内 !data/,跟踪清单逐字节镜像 RVH 72 文件
  • ✅ vocab-reseed skill v2.0.0;CLAUDE.md #10/缓冲池;CHANGELOG
  • 闸 A 通过:迁移前后预装库 SHA 恒为 b2821764adcdc48b5fe919032bb83d19aa608a69455c25f00d4b871034ec1795,双端 byte-equal,未 bump 版本、零 reseed
  • ✅ 闸 C 机械部分:dart analyze No issues found(完整复现型闸 C 推迟到下次真实内容变更 reseed)

RVH 侧 assets/nlp 实测(供 §八 决策):RVH assets/nlp/{surface_to_base,base_forms}.json 不是 clean delete —— Flutter app 运行时已折叠读 db 的 lemma_*lemmatizer_flutter_loader.dart,pubspec 已停 bundle),但仍有 3 个活跃消费方bin/phase0_normalize.dart(红线 #5e 验证工具)、bin/normalize_phrases.darttest/core/nlp/lemmatizer_test_setup.dart。删除会断这些 CLI/测试 → §八「先解耦再删」是待决策项(保留作 fixture / 重构到 db 二选一)。


十二、RVH 会话交接 Prompt(可直接粘贴到新 RVH 会话)

交接 Prompt:Q3 收尾 —— RVH 侧移除旧 vocab pipeline(RB 会话已完成迁移,本会话=RVH 镜像收尾)

⚠️ 会话隔离(CLAUDE.md §9):本任务只改 RVH 仓 ~/reading_vocab_helper,绝不碰 RB 仓 ~/reading-browser。
跨仓引用一律用 ~-锚定绝对路径。所有危险操作(git rm / 删 assets)按 CLAUDE.md 安全规则先 AskUserQuestion。

## 背景

预装词库 pipeline(tools/vocabulary_builder_v3,Dart)已在 RB 会话 lift-and-shift 迁入 RB 仓
(~/reading-browser/tools/vocabulary_builder_v3),RB 成为单一产源,sync 方向反转为 RB→RVH。
RB 侧结构迁移已完成、提交 commit 6a4d0a8、byte-equal 验收全绿
(db 双端 SHA 恒为 b2821764…,零内容变更、零 reseed)。

正式方案 + RVH 协调清单权威源:
  ~/reading-browser/docs/plans/rvh-vocab-pipeline-migration-plan.md(读它,§八 = 本会话任务清单,§十一/十二 = RB 实施状态与本 prompt)

## 本会话任务(执行 plan §八,RVH 侧镜像收尾)

1. 移除 RVH 旧 pipeline:git rm ~/reading_vocab_helper/tools/vocabulary_builder_v3(72 个跟踪文件)。
   commit 注明「迁至 RB,见 rvh-vocab-pipeline-migration-plan.md」。历史留旧 commit,不迁 git 历史(Q4 决策)。

2. ⚠️ assets/nlp/*.json 是「待决策」非「直接删」:已实测 RVH 仍有 3 个活跃消费方——
     - bin/phase0_normalize.dart(红线 #5e 跨端 byte-equal 验证工具,dart:io 读 assets/nlp/*.json)
     - bin/normalize_phrases.dart
     - test/core/nlp/lemmatizer_test_setup.dart(lemmatizer 测试 fixture)
   运行时(Flutter app)已不读 JSON(走 db 的 lemma_* 表,lemmatizer_flutter_loader.dart 已折叠,
   pubspec.yaml 也已停止 bundle assets/nlp)。故删 assets/nlp 会断上述 CLI + 测试。
   → 请 AskUserQuestion 让用户在两条路里选:
     (A) 保留 assets/nlp 作 CLI/测试 fixture(它是 RB build_dict 产物的 byte-equal 副本,小而稳;
         最省事,但双份资产存在需在文档注明「RB 权威、RVH 仅测试镜像」)
     (B) 重构 CLI/测试改从 reading_vocab.db 的 lemma_* 表装载后再删 assets/nlp(彻底去重,工作量大)
   建议 (A)。无论哪条,红线 #5e 双端 byte-equal 验证义务不变(验证脚本见 plan §5e / RVH CLAUDE.md #5e)。

3. 确认 RVH app 运行时只 ATTACH 只读 reading_vocab.db、不依赖 pipeline 在 RVH 仓内:
   grep -rn "vocabulary_builder_v3" lib/ pubspec.yaml —— 已知残留 2 处 doc 注释需更新(非代码依赖):
     - pubspec.yaml:132 「tools/vocabulary_builder_v3 config 路径指向此处」→ 改为「pipeline 已迁 RB」
     - lib/core/utils/example_text_cleaner.dart:11 引用 tools/vocabulary_builder_v3/bin/... → 更新为 RB 路径或删

4. 废弃/精简 RVH skill .claude/skills/preinstalled-db-update/(204 行,orchestrate 整条 pipeline→reseed→交接):
   pipeline 已迁 RB(RB 的 vocab-reseed skill 已升级 v2.0.0 兼任产库)。RVH 此 skill 的
   cd tools/vocabulary_builder_v3 步骤在 RVH 已失效。
   → AskUserQuestion:完全删除,还是改成「RVH 仅接收 RB 产物 + bump _preinstalledVocabVersion」精简版?

5. RVH CLAUDE.md 措辞更新(与 RB 对称):
   - 红线 #5e:pipeline 位置 RVH→RB;「RB 产 JSON 喂 RVH pipeline」环状描述改「RB 内闭环,RVH 纯消费」
   - 若有 #10 镜像 / 「RVH pipeline 单点产出」措辞 → 改「RB pipeline 单点产出,RVH 纯消费」
   - 「项目当前状态」里凡述及 vocabulary_builder_v3 产库流程的,指向 RB
   - _preinstalledVocabVersion=25 版本锚常量本身不动(结构迁移零内容变更,不 reseed);
     仅记「未来 reseed 时该常量与 RB VOCABULARY_SEED_VERSION 双端同步」

6. RVH CHANGELOG.md 记 pipeline 迁出。

7. 更新 RVH memory:project_phrase_library_rvh / project_vocabulary_builder_v3 等提及 pipeline 在 RVH 的
   条目,标注已迁 RB(避免下次会话按旧位置找)。

## 收尾验收(必跑)

双端 byte-equal 联测(迁出不应改任何字节):
  cmp ~/reading_vocab_helper/assets/databases/reading_vocab.db \
      ~/reading-browser/src-tauri/assets/reading_vocab.db   # 必须 byte-equal (SHA b2821764…)
若选了方案 (A),再验 assets/nlp 双端 byte-equal:
  cmp ~/reading_vocab_helper/assets/nlp/surface_to_base.json \
      ~/reading-browser/src-tauri/assets/nlp/surface_to_base.json
  cmp ~/reading_vocab_helper/assets/nlp/base_forms.json \
      ~/reading-browser/src-tauri/assets/nlp/base_forms.json
红线 #5e 归一回归(plan §5e / RVH CLAUDE.md #5e 有完整命令):RB/RVH lemmatize 输出 diff 须为空。

## 红线 / 纪律

- 红线 #10:预装库双端 byte-equal,本次迁出零内容变更,不 bump 版本、不 reseed。任何 cmp 不等即停。
- 红线 #5e:lemmatizer 资产双端 byte-equal 义务照旧(无论 assets/nlp 保留还是重构)。
- 危险操作(git rm / 删 assets/nlp / 删 skill)逐个 AskUserQuestion 确认,列受影响文件、标「不可撤销」。
- 先出计划给用户确认再动手(本会话是执行会话,但删除类操作仍须逐项确认)。