日期:2026-06-04
把题材体系收敛到 CSV 已经采用的 15 个 canonical_genre,同时保留 37 个中文题材模板作为初始化阶段的可叠加预设。
一句话原则:
CSV canonical 是主干;模板是预设;套路、形式、平台细分全部标签化。
当前运行链路里,templates/genres/*.md 只被 /webnovel-init 使用:
webnovel-init/SKILL.md 要求用户选题材后按需读取 templates/genres/。init_project.py 按用户传入的 genre 精确读取 templates/genres/{genre}.md,并写入新项目的 设定集/世界观.md。plan/write/query/review 不直接读取这 37 个模板。CSV 层已经相对收敛:
适用题材 只允许 15 个 canonical 或 全部。validate_csv.py 当前可做到 0 errors / 0 warnings。主要漂移点:
templates/genres/ 的 37 个文件名混合了 canonical、平台细分、legacy alias、套路标签和形式标签。reference_search.py 不能解析所有模板名。webnovel-init/SKILL.md 的题材集合仍是混合列表,容易把非 canonical 写进 state.json.project.genre。题材与调性推理.csv 的 题材/流派 实际更像 route_tag,不全是 platform tag。唯一硬枚举继续使用 CSV 方案:
都市 玄幻 仙侠 奇幻 科幻
历史 悬疑 游戏 古言 现言
幻言 年代 种田 快穿 衍生
这些值用于:
适用题材裁决规则.csv 的 题材canonical_genrereference_search.py --genrestate.json.project.genre37 个 templates/genres/*.md 不再被视为硬题材,而是 template preset。
每个 preset 必须声明:
template_namecanonical_genretemplate_typeroute_tagstrope_tagsformat_tagsaliases例子:
template_name,canonical_genre,template_type,route_tags,trope_tags,format_tags,aliases
都市异能,都市,route,都市异能,,,"异能|现代异能"
规则怪谈,悬疑,route,规则怪谈,,,"规则动物园|规则类"
系统流,玄幻,trope,,系统流,,"系统|系统文"
知乎短篇,现言,format,,,知乎短篇,"知乎体|盐选|小程序短篇"
西幻,奇幻,route,西幻,,,"西方奇幻"
用户输入不直接等于硬题材。解析结果应该是结构化对象:
{
"user_genre_label": "知乎短篇风的规则怪谈",
"canonical_genre": "悬疑",
"route_tags": ["规则怪谈"],
"trope_tags": [],
"format_tags": ["知乎短篇"],
"template_presets": ["规则怪谈", "知乎短篇"]
}
webnovel-writer/templates/genres/*.md
webnovel-writer/templates/genres/index.csv
webnovel-writer/scripts/reference_search.py
webnovel-writer/scripts/init_project.py
state.json.project.genre 写 canonical。genre 精确找文件。webnovel-writer/skills/webnovel-init/SKILL.md
webnovel-writer/scripts/validate_csv.py
webnovel-writer/references/csv/genre-canonical.md
题材与调性推理.csv 的 题材/流派 是 route_tag,不是纯 platform tag。webnovel-writer/references/csv/README.md
webnovel-writer/references/index/reference-loading-map.md
reference_search genre resolve 测试。init_project 模板加载测试。templates/genres/ 拆成 canonical/ 和 presets/ 子目录。genre-profiles.md 作为主真源,只保留 fallback 定位。范围:
templates/genres/index.csv。templates/genres/*.md 必须在 index 里有一行。canonical_genre 必须属于 15 个 canonical。不改运行逻辑。
验证:
python -X utf8 webnovel-writer\scripts\validate_csv.py
$env:PYTHONUTF8='1'; python -m pytest webnovel-writer\scripts\data_modules\tests\test_prompt_integrity.py -q --no-cov
范围:
reference_search.py 中增加模板索引加载。resolve_genre() 支持:
验证:
都市异能 -> 都市规则怪谈 -> 悬疑知乎短篇 -> 现言 或按 index 配置值西幻 -> 奇幻系统流 -> 玄幻 默认映射范围:
init_project.py 接收用户原始题材。canonical_genre 与 tags。state.json.project.genre 写 canonical。新增兼容字段:
{
"project": {
"genre": "悬疑",
"genre_label": "知乎短篇风的规则怪谈",
"genre_tags": {
"route": ["规则怪谈"],
"trope": [],
"format": ["知乎短篇"],
"templates": ["规则怪谈", "知乎短篇"]
}
}
}
生成世界观时加载:
兼容策略:
project.genre 是非 canonical,运行时通过 resolver 兼容。验证:
范围:
webnovel-init/SKILL.md
references/csv/genre-canonical.md
references/csv/README.md
验证:
只有前四阶段稳定后再做。
目标结构:
templates/genres/
index.csv
canonical/
都市.md
玄幻.md
...
presets/
都市异能.md
规则怪谈.md
知乎短篇.md
系统流.md
这一步改动范围大,建议单独 PR/commit。
docs(genres): document taxonomy convergence planchore(genres): add template index and normalize headingsfeat(genres): resolve template presets to canonical genresfeat(init): persist canonical genre and genre tagsdocs(genres): update init and csv taxonomy guidancerefactor(genres): split canonical and preset templates风险:state.json.project.genre 从细分名改为 canonical 后,用户肉眼看到的信息变少。
控制:保留 genre_label 和 genre_tags。
风险:系统流、知乎短篇 等默认映射可能有争议。
控制:index 中标注 template_type,并允许 init 交互时让用户确认 canonical。
风险:一次性移动模板会造成路径断裂。
控制:第一阶段只加 index,不移动文件。
风险:CSV route 表的 题材/流派 命名与语义不一致。
控制:先文档改名为 route_tag 语义,代码字段兼容不动,后续再考虑列名迁移。
validate_csv.py 同时校验 CSV 与模板 index。reference_search.py 能解析所有模板名到 canonical。project.genre。