panatgithub_AnkiHeadingSync/docs/semantic-qa-decisions.md

202 lines
No EOL
5.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Semantic QA Decisions
## Decision Summary
本轮按真实仓库结构锁定如下实现决策:
1. 新功能接入 current manual-sync 主链,不新增平行 sync path。
2. 新增独立内部 `CardType = "semantic-qa"`
3. 语义 QA 使用独立 `semanticQaNoteType` 和独立 mapping key不复用 `basic:...`
4. 语义 QA 的字段映射行为是 basic-like仍然走 title/body 两字段。
5. 触发条件是“标题级别等于当前 QA 标题级别,且标题文本末尾包含配置的 hashtag marker”。
6. 拆卡单位只认一级列表项;只有带缩进子内容的一级项生成卡。
7. 一级列表项同行正文不进入答案;答案只取其缩进子内容。
8. 语义 QA 子卡各自写独立 `<!--ID: noteId-->` marker不共享父标题 marker。
9. 为了兼容当前 backlink 实现新增“显示题面标题”和“backlink 锚点标题”的分离。
10. settings validation 继续沿用当前仓库的 lazy mapping 模式:
- marker 语法与 note type 非空做全局校验
- mapping 结构合法性继续全局校验
- mapping 完整性在“保存 mapping”和“实际同步使用该 note type”时强制校验
## Concrete Decisions
### 1. Internal card type name
使用:
- `semantic-qa`
原因:
- 语义清晰
- 与当前 `basic` / `cloze` 明确区分
- 仍能在实现里被当作 basic-like 类型处理
### 2. Settings shape
新增设置:
- `semanticQaMarker`
- `semanticQaNoteType`
本轮不新增 `semanticQaEnabled`
原因:
- 仓库当前没有其他 feature-toggle 先例
- 触发权已经由 marker + 标题级别共同控制
- 可以在不改变当前 settings 生命周期的前提下完成需求
### 3. Marker syntax validation
合法 marker 语法固定为 hashtag token
- 必须以 `#` 开头
- 后面至少 1 个非空白字符
- 不允许内部再含空白
v1 不支持:
- emoji trigger
- wikilink trigger
- 多 token 组合 trigger
### 4. Parsing integration point
解析入口放在 `CardIndexingService` 内部。
行为:
- 普通 QA 标题:保持一标题一张 `basic`
- 普通 Cloze 标题:保持现状
- 带 semantic marker 的 QA 标题:进入 semantic list parser产出 0..n 张 `semantic-qa`
原因:
- 当前主链的 identity / note type / deck / writeback 都从 `IndexedCard` 起步
- 在这里拆卡,后续 planner/executor/state 都能自然复用
### 5. Semantic child identity strategy
每张 semantic 子卡的稳定 basis 为:
- file path
- 一级列表项的 `blockStartLine`
- 父标题文本
- 子项稳定键
- 子项答案内容
其中子项稳定键采用:
- `normalized child label + occurrence index among same labels within the same semantic heading`
原因:
- 比“全局顺序号”更稳
- 仍然是 deterministic
- 能处理同一父标题下重复 label 的情况
具体做法:
- 把上述信息编码进 semantic 子卡的 `rawBlockText` / `rawBlockHash`
- `syncKey` 仍使用现有 `filePath + blockStartLine + rawBlockHash`
### 6. Marker placement for semantic child cards
每个 semantic 子卡都在自己所属一级列表项区域内独立写 marker。
默认位置:
- 该子项缩进内容的末尾之后
默认缩进:
- 优先复用已有 marker 行缩进
- 否则复用该子项首个子内容行的缩进
- 若仍不可用,则回退到“一级列表项缩进 + 两个空格”
原因:
- 避免多个子卡争用同一父标题尾部 marker 槽位
- 维持 Markdown 列表结构可读性
### 7. Title vs backlink anchor split
为 indexed/state/render 数据增加一个单独字段:
- `backlinkHeadingText`
语义:
- `heading` = 实际题面标题(父标题 + 子项名)
- `backlinkHeadingText` = 原父标题文本(含 semantic marker
原因:
- 题面和 backlink anchor 在语义 QA 下不再相同
- 当前仓库的 backlink 生成严格依赖 heading text
### 8. Question/title format
v1 题面格式固定为:
- 父标题原文
- 换行
- 一级列表项标签文本(去掉列表 marker 本身,保留该项 markdown 文本)
原因:
- 符合“父标题 + 子项名”
- 最大程度贴近用户示例
### 9. Answer/body extraction rule
答案只取:
- 该一级列表项下面的缩进子内容
不包含:
- 一级列表项同行正文
若某一级列表项没有任何缩进子内容:
- 不生成卡
### 10. Preview implementation
preview 只放在 settings 页,且只做 settings-driven fixed sample preview。
不做:
- 当前文件实时扫描
- 编辑器内实时提示
实现方式:
- 复用 semantic list parser
- 对固定样例输入做解析
- 展示 marker 是否合法、会拆出多少张卡、每张卡的题面/答案摘要
## Intentional Deviations From The Prior AI Plan
### 1. 不新增 `semanticQaEnabled`
原因:
- 当前仓库并不依赖 feature-toggle 驱动 settings validity
- marker 已经是足够明确的触发约束
### 2. mapping completeness 不在全局 settings load/save 时强制要求“已经存在”
原因:
- 当前 basic/cloze 也不是这样工作的
- 仓库真实模式是 lazy load fields -> save mapping -> runtime validate when used
### 3. 额外引入 `backlinkHeadingText`
原因:
- 这是当前仓库实现决定的必需项
- prior AI plan 没显式覆盖这个模型缺口