主题
29 · 请 RB 产出一个 prune 过的预装库(RVH → RB)
物理仓库位置:
~/reading_vocab_helper/docs/cross-end/29-rvh-prune-reseed-request.md日期:2026-08-25 · 方向:RVH 提请 → RB 整库 reseed 时执行(红线 #10,RVH 纯消费) 数据:29-prune-candidates.tsv(94 行候选 + 判据字段)·29-missing-headwords.txt(90 个缺失词条) 前情:doc 24/25(v26)· doc 27/28(v27)
1. 诉求一句话
v26/v27 修好了 lemmatizer 映射表,但预装库 vocabulary 表一行没动。结果是一半的修复 落不了地:旧的残根词条还在库里,新的正确词形反而没有词条。请在整库 reseed 时一并收掉。
2. 这不是新提案 —— 是 doc 24 §6 那笔"知情取舍"到期
doc 24 §6 当时写得很清楚,为省一次 ~12k 词的 LLM 重译,只重烤 lemma_* 三表,代价是:
- 旧归一结果产生的 headword 仍在(
alwayrathlatyesometimeopusvega…共 91 个)always/rather/during等正确词形在预装库里没有词条- 两者都在下次整库 reseed 时自然收敛
第 3 条是本单要兑现的。但它有一个 RVH 侧的前提不成立,见 §5。
3. 危害已不是理论:它正卡着一个真机实证的缺陷
RVH backlog「P1 — OCR 模糊匹配把 v26 修好的词又改错回去」(2026-08-24 真机实证):
OCR 拍到 "always"
--lemmatize--> always ✅ v26 修对了
--本地 vocabulary 查不到--> 判为 unknown
--OcrFuzzyMatcher 编辑距离 1--> alway ❌ 正是 v26 刚"作废"的那个词条RVH 已修一半(文本分享路径跳过纠错器,commit 95d6d82),OCR 拍照那一半治不了 —— 只要 alway 还在库里当编辑距离 1 的候选,纠错器就会找到它。 prune 是那一半唯一的根治手段。
同理受影响的实测有 36 个词(27 个被改回死词条 + 9 个改成不相干的词如 latter→letter)。
4. 两份清单(已算好,含判据字段,但需要 RB 裁定)
4.1 prune 候选:29-prune-candidates.tsv(94 行)
列:old_headword / cefr / is_phrase / residual_surfaces / best_residual_rank
筛法:取 v26+v27 改动波及的全部旧 target ∩ 预装库词条,列出它残余的 surface 来源 及这些来源里最高的词频排名。best_residual_rank 为空 = 所有残余来源都不在 33 万词频表里。
按 best_residual_rank > 50000(≈现代英语读不到)过滤得 62 个强候选,代表: alway amus ceas chon compos instal laker malus monie oppos poisposses puls purs rais revers robbin trie uninterest unconcern upcome …
4.2 ⚠️ 但这份清单不能直接执行,三个已知问题
- 里面混着真词。
rend(A2 真动词) ·lade(C1) ·wale(C1) ·sooth(C2 古语但真) ·emirate(B2) ·grenadine(C1) ·congratulation(A2 单数) ·crossroad(B1 单数) ·outskirt(B2 单数) ·ourself·oversea·instal(异体拼写) —— 删了就是误伤。 comic strip(B1) 是方法的假阳性:词频表是单词表,短语查不到排名,于是被误判。is_phrase列已标出,短语一律需人工看。uninterest/unconcern/overjoy明确不能删 —— RB doc 28 §7 自己的裁定: 它们仍接收各自的名词复数与动词屈折(uninterests/unconcerns/overjoys), 是合法词条。已在 TSV 的residual_surfaces列体现。
⇒ 判据建议沿用 v26 §4 第二层:删 = 该词在现代英语里不作为独立词条被读到; 不删 = 它仍是某个真实词的规范形。逐条人工过,别按阈值批量执行。
4.3 缺失词条:29-missing-headwords.txt(90 个)
v26/v27 改动的 182 个 surface 里,归一结果没有预装库词条的。含 always ratherduring his us yes latter outer pants clothes opera sometimes innerupstairs outstanding unbiased outdated uninteresting unconcerned overjoyed …
⚠️ 这 90 个同样不能照单全收:
sdkachasiya是噪声,本就该在停用词表里- 约三分之一是专有名词(
vegaswaleskansasjesusmassachusettsnetherlandsphilippinesreutersreynoldsrobbinssearsperkinshickslakerselliscarmencincinnatidalimalisaracaramarafilacolliercolossianscorinthiansthessaloniansphilippiansflindersbates)—— 这块与你们在做的docs/plans/proper-noun-governance-plan.md直接重叠, 该由那套判据统一处理,别在本单里单独决定。
5. 🔴 RVH 侧的前提:光 prune 库还不够
RVH 的预装库导入只 UPSERT、不删 preinstalled 行:
sql
-- app_database.dart 里唯一的 DELETE,只清缓冲池回填行
DELETE FROM vocabulary
WHERE source = 'backfilled' AND word NOT IN (SELECT word FROM learning_entries);
-- 之后是纯 UPSERT⇒ 你们把 alway 从新库拿掉,存量安装照样留着它。doc 24 §6 那句「下次 reseed 自然 收敛」只对全新安装成立。
RVH 已就此立项(backlog「P2 — 预装库 prune 走不通」)并定了节奏:
- 现在~本次 reseed 之前:走 B(内测用户删 app 重装)
- 本次 reseed 落地那一轮:RVH 落 A(改导入逻辑加删除步骤)
⚠️ A 绕不开一个产品决策:learning_entries.word → vocabulary(word) 是 ON DELETE RESTRICT, 且 RVH 的 PRAGMA foreign_keys = ON 是真开的(不同于 RB 的 rusqlite 通道)。 用户生词本里存着 rath 时,删该词条会被 FK 直接拒。三个选项:跳过 / 软删用户行 / 迁移到正确词形。
这正是本单选在整库 reseed 那一轮做的原因:reseed 后 rather 才第一次有词条, 「迁移到正确词形」才第一次可行 —— 在此之前目标词不存在,迁移必撞 FK(doc 24 §9.2 已分析)。
⇒ 请 RB 在 reseed 产出前知会 RVH,两边同轮发版。
6. 建议:并进 proper-noun-governance-plan.md 的 L-C,不要单开一轮
你们那份计划里 L-C 已明确「需整库 reseed(跨端 byte-equal,红线 #10)」,且 §4.3 的 专名重叠说明两件事本就该一起做。单开一轮 reseed 要再付一次 ~12k 词 LLM 重译,不划算。
本单的诉求可以整体作为 L-C 的一个子项:「reseed 时顺带 prune 掉 §4.1 裁定要删的, 并补上 §4.3 裁定要加的」。
7. RVH 侧承诺
- 资产/预装库整包接收,不自行修改任何 lemma 或 vocabulary 数据(红线 #10 / #5e)
- bump
_preinstalledVocabVersion(每次都要,理由见 doc 25 §7) - reseed 落地同轮落 A(导入删除逻辑 + FK 决策)
- 复验:跨端 phase0 byte-equal + 真机验证 P1 的 OCR 那一半确实好了 (分享/拍照含
always的文本,确认不再出现alway)