状态: 已实施(REQ-177~181 全部落地,2026-08-20) 目标: 把 v0.7.5 裁决缓做的"结构组织"中纯本地可行的两项做掉——章节/TOC 入笔记(章节边界 → Markdown 标题层级)+ 术语表入笔记(词汇表块);不依赖云端 AI,与 v0.8.0 AI 精修(REQ-141)并存兼容。 关联: v0.7.5 版本文档(§六 缓做裁决)· REQ-044/064(章节检测已实施)· REQ-077(大纲标题检测已实施)· REQ-046/061(术语表已实施)· REQ-171(规则版本元数据)· REQ-172(黄金语料回归)· v0.8.0(AI 精修接管语义层,本版不做语义级结构)
v0.7.5 §六 缓做六项逐一评估纯本地可行性:
| 缓做项 | 纯本地可行性 | 本版裁决 |
|---|---|---|
| 章节/TOC 入笔记 | ✅ 完全可行(chapter_detect + outline 均已实施,缺"接进笔记") | 做 |
| 术语表入笔记 | ✅ 完全可行(glossary 已实施,缺"接进笔记") | 做 |
| 讲述↔画面时间对齐内联 | 不做(前端工作量独立) | |
| 要点/行动项 | 不做(下批候选) | |
| 摘要/结论 | ❌ 语义层,必须 LLM | v0.8.0 REQ-141 |
| 语义切段 | ❌ 语义层,必须 LLM | v0.8.0 REQ-141 |
用户裁决:章节/TOC + 术语表两项全收;章节标题复用 outline(OCR 大字块/屏标题);术语自动候选直接入笔记(可手动删,不做确认 UI);独立小版本 v0.7.6 发布(不与 v0.8.0 AI 合并)。
filter_note(净化,零改动) structure_note.rs(新增,纯函数)
segments/ocr_blocks ──► NoteFilterResult ──► render_note_structure ──► 带结构的 NoteFilterResult
▲ │
│ ├─ chapters(章节边界,analyze_session_opt 已有)
│ ├─ outline(章节标题,detect_outline_smart 复用)
│ └─ glossary(术语候选,analyze_session_opt 已有)note_filter.rs/concat.rs零改动(零回归)- 新模块
structure_note.rs:纯函数、无 IO、单文件 ≤300 行、显式依赖注入 - 与 v0.8.0 AI 精修兼容:AI 版将来以"结构块数组"重写本层输出,规则版=生成结构块,同一协议(精修=整理不创作原则不受影响)
// structure_note.rs
pub struct NoteStructureConfig {
pub chapter_headings: bool, // 章节标题入笔记(默认 true)
pub glossary_block: bool, // 词汇表块(默认 true)
pub glossary_max_terms: usize, // 词汇表条目上限(默认 20,防噪音)
}
pub fn render_note_structure(
result: &mut NoteFilterResult,
chapters: &[ChapterBoundary],
outline: &[OutlineEntry],
glossary: &[GlossaryCandidate],
config: &NoteStructureConfig,
) -> StructureStats // { chapters, titled_chapters, glossary_terms } 并入 purify_stats章节 → 标题(## 章节 N [MM:SS]):
- 章节边界
time_ms→ 在## 讲述内容内该时刻的段落前插入标题行(段落切分复用concat::split_transcript_paragraphs_with口径,与净化管线一致) - 章节名 = 本边界→下一边界窗口内第一个 outline 条目文本(OCR 大字块/屏标题,复用
outline::detect_outline_smart);无命中 → 占位"章节 N" - 边界落在段内 → 段首插(粗粒度边界,不切段——诚实标注不伪造粒度)
术语表 → 词汇表块(笔记尾部 ## 词汇表):
- 每项
- 术语(画面 ×N / 语音 ×M),按 score 降序,上限glossary_max_terms - 锚点:术语在 kept 段中首次出现处 →
[MM:SS]前缀(回跳语义,复用 REQ-165 锚点风格)
空输入降级(诚实降级):无章节(口播档案)→ 不插标题;无术语 → 不出词汇表;配置全关 → 原样返回。
convert_to_note 与 preview_session_note 在 refresh_screen_points 之后、落库/返回之前调用:
- 装配
SessionDetail(load_note_material 已有 segments/ocr_blocks,补 events——章节真实信号) analyze_session_opt(detail, profile, ...)取 chapters/glossary(profile 从session.profile解析,回退 Lecture)outline::detect_outline_smart(ocr_blocks, &result.ocr_screens, ...)取章节标题render_note_structure(...)重写 markdown + 更新 stats
结构渲染实现方式:章节标题行作为段落数组元素插入(kept → concat::split_transcript_paragraphs_with 复切段落 → 按章节边界在段落间插入 ## 章节 N 行 → concat::assemble_markdown(title, paragraphs, ocr_points) 复用现有组装 → 尾部追加 ## 词汇表 块)。与净化管线段落口径一致(同一阈值配置)。
预览与落库同一管线(REQ-081 契约),结构输出一致性由构造保证。
NoteStructureConfig(chapter_headings / glossary_block / glossary_max_terms)并入 PurifyConfig(嵌套结构字段):复用现有 JSON 校准与装配链(AppState.purify → PurifyEnv),零新装配点;structure_note.rs 消费独立类型,模块边界不破。全关 = v0.7.5 输出逐字节一致。
RULE_VERSION递增:note-rules-0.7.5→note-rules-0.7.6(REQ-171:产物可回答"用哪版规则生成")StructureStats并入purify_statsJSON(前端预览统计卡可显示"章节 ×N / 术语 ×M";旧笔记 NULL 诚实降级)
| REQ | 内容 | 验收要点 | 规划状态 |
|---|---|---|---|
| REQ-177 | 章节入笔记:章节边界 → ## 章节 N [MM:SS] 标题层级;章节名取窗口内 outline 标题(OCR 大字块/屏标题),无命中占位 |
网课档案转笔记带章节标题;边界位置正确(段前插入、段内不切段);口播档案无章节零变化;标题可手动删 | 已排期 |
| REQ-178 | 术语表入笔记:glossary 候选 → 笔记尾部 ## 词汇表 块(- 术语(画面 ×N / 语音 ×M) + [MM:SS] 锚点);自动候选直接入笔记(不强制确认 UI);上限 20 防噪音 |
词汇表块生成正确、排序降序、上限生效、锚点回跳;无术语不出块;块可整体删除 | 已排期 |
| REQ-179 | 结构渲染配置化:NoteStructureConfig(chapter_headings/glossary_block/glossary_max_terms)JSON 可校准(purify_config.json 先例) | 配置全关 = v0.7.5 输出逐字节一致(零回归护栏);JSON 缺失/损坏回退内置默认不阻断 | 已排期 |
| REQ-180 | 结构元数据:StructureStats 并入 purify_stats + RULE_VERSION 递增 note-rules-0.7.6 | 统计与落库一致;旧笔记 NULL 诚实降级 | 已排期 |
| REQ-181 | 黄金语料回归扩展:会话31 夹具 → 期望带结构笔记断言(TDD,先写失败测试) | 新增规则先失败测试再实现;全量回归一键跑;预览/落库双出口逐字节一致 | 已排期 |
- Rust 单测(TDD,AAA 模式):
- 章节插入位置:边界在段前 / 段中 / 无段区域 / 首个边界前(合成会话样本)
- 章节命名:outline 命中取标题 / 未命中占位 / 窗口跨边界归属正确
- 词汇表:排序降序 / 上限截断 / 锚点首现 / 空术语不出块
- 配置:全关输出与 v0.7.5 完全一致(零回归护栏);partial JSON 覆盖语义
- 黄金语料:会话31 样本 → 期望带章节标题 + 词汇表断言(REQ-181)
- 双出口一致:preview_session_note / session_to_note 结构输出逐字节一致
- 前端:
##标题与列表渲染已支持(Markdown 渲染器现有能力)——预计零改动或极小(统计卡加章节/术语计数) - 真机手动验证清单(实施完成后执行):
- 网课会话(会话31)重转笔记:章节标题层级正确、章节名来自画面标题、词汇表块带锚点
- 口播会话转笔记:无章节标题、无词汇表(零变化)
- 旧笔记(rule_version NULL):正常展示不报错
- 回归底线:现有 1053+ 单测全绿 + clippy 新代码零警告 + 前端构建通过
Rust 新增:structure_note.rs(纯函数:章节标题插入 + 词汇表块 + 配置 + stats)· structure_note_tests.rs(16 个单测:插入位置/命名/词汇表/零回归/JSON 往返——审查补 max_terms=0 语义测试)
Rust 修改:commands_session.rs(apply_note_structure 接线函数——convert_to_note 与 preview_session_note 双出口同口径调用;失败不阻断主链路;v0.7.6 审查硬拆:笔记管线迁至新增 commands_session_note.rs,命令注册按定义模块)· commands_ai.rs(审查修复:AI 复核出口补结构渲染——三出口一致)· note_filter.rs(RULE_VERSION → note-rules-0.7.6;FilterStats 加 chapters/titled_chapters/glossary_terms)· purify_config.rs(嵌套 NoteStructureConfig——REQ-179)· note_filter_golden_tests.rs(REQ-181:会话31 结构黄金语料 2 例 + 审查补测"配置开无数据逐字节一致"共 3 例)· lib.rs(mod 注册)
前端:NotePreviewView.tsx(统计卡加章节/词汇表计数)· types.ts(FilterStats 三新字段)
- 摘要/结论、语义切段、要点/行动项、讲述↔画面时间对齐内联——语义层归 v0.8.0 REQ-141;其余为后续批次候选
- TOC 折叠导航(V1.1 REQ-026 范畴)
- 术语确认 UI(自动候选直入笔记,可手动删)
- 章节速览/思维导图(V1.1 REQ-026)
- 任何 AI 调用(本版纯本地,无密钥/授权/成本依赖)