主题
短语自动高亮 thin-slice(高精度薄片 · v1 验证)
物理仓库:RB(
/Users/larry/reading-browser)。纯 RB 侧,不动 RVH / Supabase / 预装库。 落地后请把本文件复制到docs/plans/archive/phrase-auto-highlight-thinslice-plan.md(CLAUDE.md §8 计划持久化)。
Context(为什么做这个)
现状:阅读页里短语(phrasal verb / idiom)的发现需要 2 个动作(选中文本 → 点"短语"按钮),绝大多数用户根本不知道有这功能。功能初衷是解决"词都认识、合起来傻眼"——即暴露非组合性多词单位。
只读评估(见会话)暴露两个问题:
- 精度:检测是 context-blind 的 surface 匹配,
kind of(basic) 在 "a special kind of" 里被误标。按真实出现次数,约 35% 命中落在 basic 噪声桶(a number of / after all / as long as)。已核实excluded_words里零短语,文档"决定 A(basic 经 excluded_words 默认排除)"实际未落地,noise 确实露给用户。 - 召回:单节点 matcher 漏标率和生词高亮密度强耦合(3.9% → 76%),用户学得越多短语越不准。
本 thin-slice 是最小代价验证:"只自动露出高精度短语,用户到底点不点"。两个白捡的设计红利:
- 精度:用现成的
basictag 当粗过滤,只自动高亮非-basic 的 idiom + phrasal verb,砍掉 35% 噪声桶。basic过滤只放自动路径,选区按钮路径仍匹配全部短语 → 保留"决定 A"的用户捞回意图。 - 召回:把短语扫描插在
highlightVocabulary之前(文本节点还没被生词高亮切碎时跑)→ 绕过 3.8%→76% 的自伤切断,不写跨节点 matcher 就拿到近乎满召回,只剩 ~0.1% 内联标记切断。代价是给 vocab/discovery 的 TreeWalker 加"跳过.rb-phrase内部"。
明确不做(验证通过后才进的后续相):跨节点 block-flatten matcher、RVH pipeline 的"非组合性三档标签"、整页批量 LLM 消歧。
用户已确认的决策
- 自动高亮范围 = 非-basic(is_idiom OR is_phrasal_verb,且非 basic)。
- 验证埋点 = 新建 local-only 小表,可用
rb_db_query直接算 CTR / 误报率。
改动清单
A. Rust:让 matcher 带回 is_basic(不在 Rust 硬筛,交给前端按路径决定)
src-tauri/src/commands/vocabulary/query.rs · match_phrases_in_node_texts + match_phrases_in_text:
- SQL 增
MAX(CASE WHEN je.value='basic' THEN 1 ELSE 0 END) AS is_basic。 phrase_mapvalue(bool,bool)→(bool,bool,bool)(加 is_basic)。match_phrases_in_text命中时把 is_basic 写进PhraseMatch。
src-tauri/src/commands/vocabulary/mod.rs · PhraseMatch struct:加 pub is_basic: bool。 → 选区路径(highlightPhrasesInSelection)拿到该字段但不读,行为不变;自动路径据此过滤。
B. Rust:local-only 埋点表 + 命令(migration v20)
src-tauri/src/db/migrations.rs · 新增 v20(migration-only,不动 baseline,沿 v11 pronunciation_attempts / v16 word_cloze_contexts precedent):
sql
CREATE TABLE phrase_interaction_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT,
action TEXT NOT NULL, -- 'shown' | 'clicked' | 'dismissed'
phrase TEXT, -- clicked/dismissed 时填;shown 为 NULL
count INTEGER, -- shown 时 = 本页自动高亮短语数;其余 NULL
page_url TEXT,
created_at TEXT NOT NULL
);- local-only,不进 Supabase 同步矩阵(在
docs/database-schema.md注明)。 - 含 user 活动 → 加进
clear_learning_data_if_user_changed(红线 5c,沿 word_cloze_contexts 先例)。
新命令 log_phrase_interaction(db, action, phrase, page_url, count)(放 query.rs,DB 写入类),lib.rs generate_handler! 注册。
C. content-script:新全页短语扫描函数
src-tauri/src/content-script/features/phrase-highlight.js · 新 highlightPhrasesOnPage():
- 复用
collectRangeTextNodes的 acceptNode 过滤集(已跳 script/style/textarea +.rb-highlight/.rb-phrase/.rb-popup-root/mark.rb-mark),但 TreeWalker 作用域改document.body、去掉 range 相关判断。 - 一次
invoke('match_phrases_in_node_texts', { texts, maxFrequencyRank:null })(build phrase_map 一次,高效)。 withObserverPaused+ 分批(沿highlightVocabulary的 100 节点/批 +await setTimeout(0)):对每节点perNode[i].filter(m => !m.is_basic)后,复用wrapPhrasesInTextNode(无 clip,offset 直接用 char_start/char_end;sentence 传node.textContent作上下文,供点击侧 explain_phrase)。- 累计 total;
invoke('log_phrase_interaction', { action:'shown', count: total, page_url: location.href })。 - 入口受
state.settings.phraseAutoHighlight门控。
D. content-script:插入 pipeline + 防嵌套
src-tauri/src/content-script/index.js · full-pipeline(初始 L72-90 和 MutationObserver 重跑 L149-156 两处):
js
await loadAndWrapAnnotations();
if (state.settings.phraseAutoHighlight) await highlightPhrasesOnPage(); // ← vocab 之前
await highlightVocabulary();
await highlightDiscoverable();防嵌套(vocab/discovery 不钻进 .rb-phrase 内部,否则 .rb-phrase 里套 .rb-highlight):
src-tauri/src/content-script/features/highlight.js:TreeWalker acceptNode 和highlightTextNode各加一行if (p.closest && p.closest('.rb-phrase')) return REJECT/return;。src-tauri/src/content-script/features/discovery.js:同款 TreeWalker,加同样跳过。 → 效果:短语内的 B1/B2 词不再单独染色,习语作为整体单位呈现(视觉更对)。
E. content-script:埋点接线(复用现有链路,不改 events.js/popup.js 逻辑本体)
- 点击:
events.js现有.rb-phraseclick handler 里,进入handlePhraseLookup前加一发log_phrase_interaction({action:'clicked', phrase})。 - 误报:
popup.jsdismissPhraseHighlight(LLMfit===false路径)里加一发log_phrase_interaction({action:'dismissed', phrase})。 → CTR = clicked / Σshown.count;误报率 = dismissed / clicked(精度真实信号)。
F. settings 开关
src-tauri/src/content-script/features/settings.js:BATCH_KEYS加'phrase_auto_highlight';loadSettings()加state.settings.phraseAutoHighlight = batch.phrase_auto_highlight === 'true'。src-tauri/src/content-script/core/state.js:settings 对象加phraseAutoHighlight: false。- React Settings 页:在
discovery_enabledtoggle 旁加一个"自动高亮短语"开关,写phrase_auto_highlightkey(复用现有 toggle pattern;JSX/aria 文案走src/lib/strings/,红线 S19)。 - 验证窗口默认 ON:在
init_data.sqlsettings 段 seedphrase_auto_highlight='true'(仅为攒数据);任何外部/正式发版前按验证结论再定默认值。
不碰 / 兼容性
- 选区"短语"按钮路径(
toolbar.js handleSelectionPhrases→highlightPhrasesInSelection)零改动:仍匹配全部短语(含 basic),捞回能力不丢。 - 点击消歧链路(
handlePhraseLookup/maybeResolvePhrase/explain_phrase,受contextDisambiguation开关)原样复用。 - 样式
styles.js的.rb-phrase-pv/.rb-phrase-idiom(靛蓝/紫波浪线)已完备,不改。 - 红线核对:#9 normalize 已在 matcher 内(
normalize_phrase);local-only 表不进同步矩阵;无 hex;不新增 webview 协调 useEffect(架构原则 1/2)。
验证(端到端)
/build-check(cargo check + pnpm build)。删本地 dev DB 重跑触发 v20 migration。pnpm tauri dev,开一篇真实长文(如 Wikipedia / Sherlock 文本):- 加载完成后非-basic idiom/PV 自动出波浪下划线;
kind of/a number of/after all(basic)不被自动标。 rb_dom('.rb-phrase')抽查:.rb-phrase内无嵌套.rb-highlight。rb_logs(tail=20)无报错。
- 加载完成后非-basic idiom/PV 自动出波浪下划线;
- 点一个自动高亮短语:popup 正常 +
explain_phrase消歧(fit=false 时下划线消失)。 rb_db_query:SELECT action, COUNT(*) FROM phrase_interaction_log GROUP BY action;应见 shown / clicked / dismissed 行。- Settings 关掉开关 → reload → 无自动高亮;选区按钮仍工作(含 basic)。
- 验证指标:真实读几篇后,
rb_db_query算 CTR = clicked / Σshown.count、误报率 = dismissed / clicked。判据:CTR 是否说明"自动露出硬短语"有真实engagement;误报率反推 basic 过滤够不够。 /arch-check+/code-review+/doc-sync-check(更新database-schema.md加 v20 表 + local-only 标注;migrations 版本表加 v20 行)。
后续相(验证通过才启动,不在本 plan)
- RVH pipeline 产出"非组合性三档标签"(always-idiomatic / context-dependent / mostly-literal)替代粗糙的 basic 代理 → 跨端新会话(CLAUDE.md §9)。
- 跨节点 block-flatten matcher(治 ~0.1% 内联切断 + 选区路径召回)。
- context-dependent 桶的整页批量 LLM 消歧(并入共享
llm_call_log成本看板)。
v2 后续收敛(2026-06-24,逐步收敛 · 不求一次到位)
v21 已落地「非组合性三档」(always/context/literal),自动路径只露
always(根治 v1 41% 误报)。 本轮基于真实埋点数据,逐步收掉残余误报。问题一步步解决,每步独立验证。
埋点诊断(all-v21 数据,clean)
phrase_interaction_log 拉数(2026-06-18 v21 之后,无 v20 旧数据混入):
| 指标 | 数值 |
|---|---|
| 密度 | 489 实例 / 221 页 ≈ 2.2 个/页(克制) |
| CTR | 25 / 489 = 5.1% |
| 误报率(dismissed/clicked) | 7 / 25 = 28% |
| 误报率(dismissed/shown) | 7 / 489 = 1.4% |
7 次 dismiss 拆根因 → 两桶,分别解:
- 桶① boilerplate artifact(2/7):
all right reserve×2 = 版权页脚 "All Rights Reserved" 被 lemma 折叠误命中。与 idiomaticity 无关,是扫描范围问题。→ 本轮第 0 步解决。 - 桶② 真·instance-level 歧义(5/7):
to die for×2 /in the black×2 /so much for×1,全是「always 档习语在具体句里恰好字面义」。类型层静态分档修不掉,只有带上下文判断能解。→ 留下一步。
✅ 第 0 步:自动路径扫描范围收窄到主内容容器(2026-06-24 完成 + 验证)
为什么不绑 reader 模式(用户初始想法):① auto-reader 按域名 opt-in、默认关 → 绝大多数浏览在 live 模式,绑 reader 会让短语高亮在多数场景消失;② 现状 phrase 恰恰只在 live 显示、reader overlay 只重刷 vocab 不刷 phrase → 绑 reader 是「搬家 + 反转」非简化。改用 live DOM 扫描范围收窄,不丢覆盖、不搬家。
改动(仅 1 源文件 + 重建 bundle):
src-tauri/src/content-script/features/phrase-highlight.js:- 新增
findMainContentRoot():按语义容器清单(article/[role=main]/main/.article-content/.entry-content/.story-body/#article-body/.article-body/.content-body/.post-content,与reader.js extractWithHeuristic对齐)找第一个正文字数 ≥ 200(MAIN_CONTENT_MIN_CHARS)的容器;找不到退回document.body(安全侧,行为同旧)。 collectBodyTextNodes()的 TreeWalker 根从document.body改为findMainContentRoot()。- 只影响自动路径:选区「短语」按钮走
collectRangeTextNodes,不动,全档捞回保留。
- 新增
node scripts/build-content-script.mjs重建content-script.jsbundle。
效果:页脚 / 导航 / 侧栏 / 广告里的 boilerplate 从根上不进扫描范围——一刀切掉整个 chrome 噪声类(不只 footer),零延迟零成本。
验证(dev app 实机,rb-debug):
- 测试页 The Happy Prince(americanliterature.com,idiom 丰富)。
- 全文档
.rb-phrase[data-rb-phrase-auto]计数 = 1,且在故事正文(idiomout loud)。 - 同页受控对比(铁证):
<footer class="footer-nav">内 vocabrb-discover有 2 个(vocab 仍扫全 body,证明 footer 可达)、phrase.rb-phrase0 个(phrase 已被限制在正文容器内)。旧逻辑下两者共用同一document.body,vocab 能到 footer 则旧 phrase 必能到 → 现已分道,收窄生效。
边界:本步只解决桶①。正文内桶②(真歧义)原样保留,留下一步。
⏭ 下一步:桶② 正文内真歧义(A→B 流水线 · 决策已敲定 2026-06-24)
已确认数据(2026-06-24 查 dev 库 vocabulary.word_tags):3 个误报短语全部 idiomaticity:always:
in the black["idiom","idiomaticity:always"]so much for["idiom","idiomaticity:always"]to die for["idiom","idiomaticity:always"]
埋点实时核实(2026-06-24,dev 库 phrase_interaction_log):clicked=25 / dismissed=7 / Σshown.count=639 → CTR 3.9%(25/639)、误报率 28%(7/25)。clicks 自上次记录卡在 25 无增长。dismiss 拆桶确认无新惯犯:to die for×2 / in the black×2 / all right reserve×2(桶① boilerplate,第 0 步已解)/ so much for×1。 → 28% 误报 100% 可归因到两个确定性根因(桶① boilerplate + 桶② 这 3 个 mistag),无任何弥散性误报。这是「A 不必等 gate-A 数据」的硬依据。
问题:always 是 type-level 标签(词条整体非组合性),但这 3 个各有常见字面读法,surface 匹配器分不出 → 字面出现被误标:
so much for← "thank you so much for…"(极高频,碾压性字面搭配)to die for← "to die for [a cause]"(为某事而死)in the black← "in the black [coat/car]"(black 作形容词)
根因落在「静态 vs 运行时选址轴」:① 经常字面 = type-level 标错(静态可修);② 通常习语·偶尔字面 = instance-level 残留(只有上下文判断能解)。
rubric 系统性盲区(必须带给 RVH,否则下次 reseed 打回):RVH judge 问的是"这是不是真习语?"(这 3 个答案都是 yes → 给了 ≳90% → always),却没充分加权"这个 surface 串在真实语料里习语义占比多少"。so much for / to die for 都是「高频字面搭配 + 真习语」双重身份串——这是 always-mistag 的系统性陷阱类型,不是 3 个孤例。给 RVH 的核心指令 = judge prompt 显式估计 surface 串的字面搭配频率,识别这类陷阱串。
方案 = A 喂 B 的一条流水线(不是二选一):
方案 A:RVH 预装库把 over-confident 的 always 重判降级
↓
方案 B(= backlog #3「§9 深度短语模式」):context 桶逐句 LLM 二分类,判 true 才高亮已敲定决策(2026-06-24):
| 决策点 | 结论 |
|---|---|
| A 启动时机 | 立即动手,解耦 gate-A。A 是类型层标错的根因修复,不依赖数据量;gate-A 留着测 A 之后的干净数据。 |
in the black 档位 | → context(财经习语真有价值,深度模式能救回) |
to die for 档位 | → context("a dress to die for" 习语本身常见) |
so much for 档位 | → literal("thank you so much for" 字面碾压、习语义罕见到不值得占 LLM 配额;落 literal = 深度模式也不送,"so much for our plans" 永不救回,有意取舍) |
| 第 0 步提交 | ✅ 已提交 commit 2a2e0b3(2026-06-24 16:15,本节"代码未提交"旧述作废) |
- A(RVH 新会话,§9):① 先查 RVH pipeline 按什么规则把这 3 个判成 always(避免下次 reseed 打回);② 修 rubric 的「字面搭配频率」盲区;③ 重判
in the black/to die for→context、so much for→literal;④ additive reseed(word_tags tag 值,无 migration)。详细交接见phrase-noncompositionality-tiering-crossend-plan.md§10。 - B(RB 单开会话,gate-A 重测达标后):复用 backlog #3 两段式(本地框候选 → 含候选句打包送 flash → 判 true 才画),目标桶 = context(含 A 降级进来的 in the black/to die for)。literal(含 so much for)不送 LLM。
- 收益:always 桶维持本地秒出(默认体验零延迟/零成本,只留真习语);context 歧义短语挪进 opt-in LLM 通道、
in the black等真习语义照样救回(财经句判 idiomatic→高亮,"black coat"判 literal→不高亮)。 - 不采用「always 档加载期 LLM 后台回验」:全 App 最高频 LLM 触发点 + 卡加载路径 + 先画后撤跳变,ROI 倒挂。
关键次序洞见:A + reseed 单独就能闭合 gate-A —— 这 3 个移出 always 后立即停止自动高亮,默认层误报从 28% 掉到接近 0 ⚠️ 此预测已被 2026-06-25 gate-A 实测推翻(见下方「gate-A 实测」节):v22 已 demote 222 个,但残余仍 28% 误报,来自别的 surface 陷阱 + lemma 折叠短语。A+v22 reseed 没有闭合 gate-A。B(§9)仍不是 default-on 发版的前置,是 always-only 默认层之上、把 context 桶习语义经 opt-in LLM 救回的独立增强。
落地次序(已敲定):
① 第 0 步 commit 2a2e0b3 ✅(桶① boilerplate 根治,已提交)
↓
② RVH 新会话:A = 重判 3 个 + 审 rubric 字面搭配频率盲区 → additive reseed → 交接确认文档
↓
③ RB 会话:/vocab-reseed 整包覆盖(机械、快)→ 3 个移出 always → gate-A 重测 → 误报应 <10% → 评估 phrase_auto_highlight 默认 on
↓(独立、不阻塞发版)
④ RB 单开会话:B = §9 深度短语模式(context 桶 opt-in flash 消歧救回)② A 必须 RVH 会话(Flutter/Dart + pipeline,§9 隔离);④ B 必须 RB 单开会话。③ reseed 建议独立先做(单独就兑现 gate-A 精度提升),也可并进 ④ 开头。
顺带观察 → 已记 backlog
vocab 高亮仍扫全 body(验证时 footer 里有 rb-discover)。用户倾向也收窄 vocab。独立项,已记入 docs/plans/backlog.md,单独评估/会话推进。
gate-A 实测(2026-06-25,v22 reseed 后)
方法变更:放弃「点击→自动 dismiss」做 FP 信号——实测发现 on-click LLM 兜底不可靠(
on the loose/in a fix等明显误报点击后 15s+ 未被 dismiss,console 无 explain 痕迹),dismissed/clicked会严重低估真实误报。改用 Claude 直接读data-rb-sentence逐条判习语 vs 字面(比 on-click deepseek 更强的 oracle,零 LLM、零等待)。 省 token 技巧:phrase_interaction_log的shown行带count= 该页 always 数 → 开页先查SELECT count … WHERE page_url=… AND action='shown' ORDER BY id DESC LIMIT 1,count=0 直接跳过不走 DOM。
样本(10 篇真实文章,rb-debug 驱动)
| 体裁 | 篇 | always 总数 |
|---|---|---|
| 文学叙事(Longreads ×2) | 2 | 8 |
| 科普带比喻(snexplores) | 1 | 4 |
| 思想随笔(Aeon/Psyche ×3 有产出) | 3 | 6 |
| 干硬体裁(IEEE科技 / Guardian政论×2 / Psyche指南) | 4 | 0 |
always 桶很稀疏:1.8 个/页;干硬体裁(科技/政论/政策/how-to)整篇 0 always(已用 shown count=0 + DB tag 核实 = 真稀疏,非回归——highlightPhrasesOnPage 跑了、这些体裁的习语多是 context 或不在库)。只有文学/叙事/思想随笔有产出。
18 个 always 高亮的质量
| 类别 | 数 | 占比 |
|---|---|---|
| ✅ 干净真习语 | 11 | 61% |
⚠️ 正确但低价值(basic 噪声:no matter what / pay attention) | 2 | 11% |
| ❌ 硬误报(字面误命中) | 5 | 28% |
干净实例:black gold · unsung hero · come out of the closet · at stake · want for nothing · piece of the puzzle · anything goes · pave the way · make do · pan out · at bay。
5 个硬 FP 的根因(双轨,已稳定)
| 短语 | 句子(字面误命中) | 根因类 |
|---|---|---|
on the loose | "grow crops on the loose grit" | 🟠 surface 陷阱 |
for the bird | "matters... for the birds"(真鸟) | 🟠 surface 陷阱 |
to speak of | "refuse to speak of the condition" | 🟠 surface 陷阱 |
in a fix | "bond in a fixed proportion"(fixed→fix) | 🔴 lemma 过度折叠 |
all right reserve | "All rights reserved"(rights→right,正文内嵌版权行) | 🔴 lemma 过度折叠 |
结论(喂下一轮决策)
- gate-A 未达标:v22 后 always-only 真实 FP ≈ 28%(目标 <10%)。A+v22 reseed 没闭合 gate-A(推翻上一节乐观预测)——demote 222 个之后,仍有长尾 surface 陷阱 + lemma 折叠没被覆盖。
- 修复路径不是 §9(§9 只救 context 桶,对这 5 个 always 误报零作用),而是两件 RVH 侧事,且都是 gate-A 必须项:
- idiomaticity retag 第 2 轮:surface 陷阱
on the loose/for the bird/to speak of(+ 同模式 re-scan)→ 降 context。与 v22 同机制(A→B 延续)。 - lemmatizer 资产治理:
fixed→fix/rights→right幻影匹配(backlog 已有条目,本次实测把它从"可选"升为 gate-A 阻塞项)。
- idiomaticity retag 第 2 轮:surface 陷阱
- 低价值 basic(
no matter what/pay attention):非 FP 但噪声,可一并评估降 context。 - 覆盖侧:always 桶"又稀又脏"——多数文章 0-2 个、剩下 1/4 是误报。default-on 前两件 RVH 事都得做。
埋点数据:本次普查记录在 dev 库 phrase_interaction_log(v22 干净基线,用户测前已清表;clicked 数据因 on-click dismiss 不可靠、且我中途点击过几个,不作 FP 依据——FP 以上表 Claude 判定为准)。
gate-A 复测(2026-06-26,v23 reseed 后 — 两轨齐)
v23 合并版(track-① surface 陷阱 demote 249 条 always→context + track-②
in a fix→context /all right reserveprune)reseed 后复测。同法:Claude 逐句读data-rb-sentence判习语 vs 字面,:not()链枚举每页 always 高亮;文学/叙事/思想随笔体裁取样。SHA747f4732…,运行库实测三档 always 2789 / context 3450 / literal 371。
样本(8 篇真实文章,rb-debug 驱动)
Aeon essays ×2(Zhuangzi / global-tax)· Psyche ×2(relationship-OCD 指南=0 / needing-others)· Longreads ×2(Living-in-an-Alive-World=Sibley 观鸟随笔 7 个 / Ramona-Ausubel 访谈)· Texas Highways ×2(Guadalupe 灾后 / Woodlands Mall=0)。
15 个 always 高亮的质量(13 distinct,at stake ×3)
| 类别 | distinct | instance | 占比(instance) |
|---|---|---|---|
| ✅ 干净真习语 | 9 | 11 | 73% |
⚠️ 正确但低价值(话语功能:no matter what/pay attention/for the most part) | 3 | 3 | 20% |
| ❌ 硬误报(字面误命中) | 1 | 1 | 7% |
干净实例:anything goes · pave the way · making do · panned out · at bay · at stake(×3) · want for nothing · piece of the puzzle · come up with。
唯一硬 FP(新发现的同类 surface 陷阱)
| 短语 | 句子(字面误命中) | 根因类 | 当前档 |
|---|---|---|---|
all along | "All along the ravaged river, heavy equipment operators…"(沿河空间义) | 🟠 surface 陷阱(HOMONYM:空间"all along [地点]" vs 习语"自始至终") | always |
与 round-2 已治的 for the bird/to speak of 完全同类,只是 v23 re-scan 没扫到它 → 残留长尾。
结论
- gate-A 达标(卡边):always-only 真实硬 FP ≈ 7%(1/15 instance · 1/13 distinct),从 v22 的 28% → 7%,< 10% 目标。两轨修复在真机生效——上一轮 5 个硬 FP(
on the loose/for the bird/to speak of/in a fix/all rights reserved)全部消失;同句出现的 "for the birds" 不再被高亮(demote 验证)。 - 覆盖没砍过窄:尽管 v23 一次 demote 249 条,always 桶仍 1.9 个/页(≈ 上一轮 1.8);Sibley 观鸟随笔单篇 7 个。文学/叙事/思想随笔有产出,干硬体裁(指南/资讯)仍 0——真稀疏非回归。
- 残留两类(均非阻塞、已知修法):
all along1 个硬 FP:HOMONYM surface 陷阱长尾 → 下一轮(可选 round-3)demote-only always→context,与 round-2 同机制。1 个词,便宜。- 3 个 ⚠️ 低价值话语(
no matter what/pay attention/for the most part):正是 §11.4 已记录的"纯话语功能降 literal"候选,非 FP、非阻塞。
- 默认 on 评估:gate 已过(7%<10%)→ 可评估
phrase_auto_highlight默认 on 进发版。建议把all alongdemote + §11.4 话语子集降 literal 作为一次廉价 round-3(demote-only、零风险)顺手收掉,把 FP 推向 ~0 + 清掉 ⚠️ 噪声,再/或并行 default-on。
埋点数据:dev 库 phrase_interaction_log 含 v22+v23 混合行(本轮 FP 不依赖埋点、以逐句 Claude 判定为准;shown.count 仅用于跳过 0-always 页)。