日期:2026-04-30 范围:webnovel-writer 系统层面问题(与 LLM 模型能力无关) 测试基础:DeepSeek v4pro 在
D:\wk\xiaoshuo\灵石庄上跑完 init / plan / write 第 1-2 章 + 审查 事实校验:本版已对照当前 repo 代码行为与D:\wk\xiaoshuo\灵石庄实际 artifacts 复核,修正了过度归因和不存在的落点 已交付:commitf58d657 fix: align projection writers with real LLM commit schema(schema 漂移系列)
灵石庄项目用 DeepSeek v4pro 跑通 init→plan→write→review→commit 完整链路两章后,对生成产物做端到端审视。本 spec 列出纯系统侧的 8 个未修问题(schema 漂移已在 f58d657 修完),按优先级 P0→P3 排序。每条包含:现状证据、影响、根因、修复方案(具体文件 + 行号)、验收标准、工作量估计。
不在本 spec 范围内:
f58d657 中修复的 schema 漂移问题(state_projection / memory_writer / vector_writer / index_manager schema、protagonist_state 镜像、index 主角识别、entity 别名兜底)9b8976e、entity alias fallback fc63628、安全写入项目经验记忆 d2571d2 等)本节把下方 8 个已验证问题重新编排成可直接实现的工作流。问题本身仍以下方详细 spec 为事实源;这里负责明确顺序、依赖和落点,避免实现时在 prompt、runtime brief、init 模板、review 回流之间来回跳。
Objective:让详细大纲里的章节执行约束进入 chapter_brief 顶层,并在写章任务书中压过 dynamic_context;同时切断 chapter_focus 从 reference summary 继承的误导链路。
Files to change:
webnovel-writer/scripts/chapter_outline_loader.pywebnovel-writer/scripts/story_system.pywebnovel-writer/scripts/data_modules/story_system_engine.pywebnovel-writer/scripts/data_modules/runtime_contract_builder.py(确认不混写 directive 与 review/runtime contract)webnovel-writer/skills/webnovel-write/SKILL.mdConcrete tasks:
chapter_outline_loader.py 增加或扩展 load_chapter_execution_directive(project_root: Path, chapter: int),从 大纲/第{vol}卷-详细大纲.md 提取 goal、obstacles、cost、time_anchor、chapter_span、countdown、cbn、cpns、cen、must_cover_nodes、forbidden_zones、chapter_end_open_question、hook_type、hook_strength、key_entities、strand、antagonist_tier。chapter_directive;找不到章节块时保持老路径兼容。_suggest_chapter_focus():优先使用 chapter_directive.goal;没有 directive 时使用非占位 query;禁止从 dynamic_context[0]["核心摘要"] 派生。webnovel-write/SKILL.md 任务书顺序:本章硬性约束 → CBN/CPNs/CEN → 本章禁区 → 风格指引 → dynamic_context 风格参考。chapter_focus 来源、无 directive 时不抄 reference summary、prompt 顺序人工 fixture。Dependencies:
chapter_outline_loader.py 已能识别 CBN / CPNs / CEN / mandatory_nodes / prohibitions。chapter_directive.goal/key_entities/strand/antagonist_tier,所以本阶段必须先做。Verification/tests:
pytest --no-cov 中新增的 outline/story-system 相关测试通过。chapter_directive.time_anchor、must_cover_nodes、forbidden_zones 存在。dynamic_context 被标注为补充参考且排在 directive 后。Estimated scope/risk:中,约 4-6 小时。主要风险是详细大纲 markdown 标题/字段格式变体导致解析漏抓;需要正则兼容 第1章、第一章、空格变体。
Objective:保证 story-system 收到真实章节目标 query,并在 reference 检索排序中放大章节语义,避免“题材对、场景错”的卡片压过借贷/调查类卡片。
Files to change:
webnovel-writer/scripts/story_system.pywebnovel-writer/scripts/data_modules/story_system_engine.pywebnovel-writer/skills/webnovel-plan/SKILL.mdwebnovel-writer/skills/webnovel-write/SKILL.mdwebnovel-writer/skills/webnovel-review/SKILL.mdConcrete tasks:
story_system.py CLI 入口增加 placeholder query 保护:识别 {章纲目标}、第N章章纲目标、空泛模板文本,输出诊断或降级警告。query。chapter_brief.meta.query 与详细大纲目标,把 placeholder query 标成系统问题。story_system_engine.py 的 query 扩展/表收集/排序附近加入 chapter-aware scoring,输入来自 chapter_directive.goal/key_entities/strand/antagonist_tier。reference_search.py 通用能力,不新增不存在的路由层。Dependencies:
chapter_directive。如果 Phase 2 先做,只能先使用 query 文本,排序收益会明显降低。Verification/tests:
test_story_system_rejects_or_warns_placeholder_query:占位 query 被诊断。test_story_system_reference_matching_prefers_chapter_keywords:借贷类卡片排在论道/丹药/宗门经营泛卡前。dynamic_context 至少有一条与“借据/利息/复利/债”相关。Estimated scope/risk:中,约 4 小时。主要风险是 reference CSV 字段不稳定,需要对 关键词、意图与同义词、适用场景 缺字段做容错。
Objective:减少 init 后空壳设定文件和空目录,避免单主角项目生成 主角组.md,并把事实源集中到已有主角卡、世界观、卷纲等文件。
Files to change:
webnovel-writer/scripts/init_project.pywebnovel-writer/templates/output/设定集-金手指.mdwebnovel-writer/templates/output/复合题材-融合逻辑.mdwebnovel-writer/templates/output/设定集-主角组.mdwebnovel-writer/templates/output/设定集-女主卡.mdwebnovel-writer/skills/webnovel-init/SKILL.mdConcrete tasks:
idea_bank.protagonist_structure 条件生成 主角组.md:仅 主角组、双主角、多主角 类项目生成。heroine_config 条件生成 女主卡.md:无女主 时不生成。角色库/、物品库/、其他设定/ 改为第一次实体增量写入时再创建。Dependencies:
init_project.py、webnovel-init/SKILL.md、模板路径中的生成清单,避免只删模板不改调用方。Verification/tests:
设定集/主角组.md,仍生成 设定集/主角卡.md。无女主 fixture 下不生成 设定集/女主卡.md。金手指设计.md、爽点规划.md、空 角色库/物品库/其他设定 目录。Estimated scope/risk:小,约 2 小时。主要风险是模板文件名和输出文件名不完全一致,需要以 init_project.py 的真实映射为准。
Objective:在 plan/write 边界发现 [待...]、暂名、{占位} 等漂移;同时把 Phase 7 定义为当前卷规划完成后的最小跨卷锚点写回:只在 webnovel-plan 已完成并验证当前卷规划 artifacts 后,向 总纲.md 写回 V+1 的卷名、核心冲突、卷末高潮,以及当前规划产物显式结构化给出的伏笔/开放环。Phase 7 不自动详细规划下一卷。
Files to change:
webnovel-writer/scripts/data_modules/placeholder_scanner.py(新增)webnovel-writer/scripts/webnovel.pywebnovel-writer/skills/webnovel-plan/SKILL.mdwebnovel-writer/skills/webnovel-write/SKILL.mdwebnovel-writer/templates/output/大纲-总纲.mdConcrete tasks:
scan_placeholders(project_root),扫描 大纲/*.md、设定集/*.md 中的 \[待[^\]]*\]、(暂名)、(暂名)、(待补充)、全字段 {占位} / <占位>。webnovel.py 增加 placeholder-scan --project-root <dir> CLI。大纲-总纲.md 模板:init 不预生成 V2-V20 空行。webnovel-plan 成功完成当前卷规划且 artifacts 已完整/通过验证后,向 总纲.md 写回 V+1 的最小跨卷锚点:卷名、核心冲突、卷末高潮。Dependencies:
templates/output/大纲-总纲.md 与 init 生成逻辑。chapter_directive.key_entities 或现有章节实体解析结果,否则只能做全项目扫描,误报风险较高。Verification/tests:
test_placeholder_scanner_finds_pending_marks 覆盖 [待...]、暂名、{占位}。test_write_chapter_blocks_on_pending_related_entity:本章涉及实体有占位则阻断,不涉及则不阻断。test_plan_flow_writes_minimal_next_volume_anchor:完成并验证 V1 规划后只补 V2 的卷名、核心冲突、卷末高潮,不预填 V3-V20 空表,也不生成 V2 详细大纲/beat sheet/timeline。webnovel.py placeholder-scan --project-root <fixture> 返回结构化结果。Estimated scope/risk:中,约 6 小时。主要风险是占位误报和“当前章节涉及实体”判定不准;应优先做警告/阻断分级。
Objective:把 review 抓到的中高严重度 ai_flavor 问题回流到 .story-system/anti_patterns.json,让后续写章 brief 主动避开已发现句式。
Files to change:
webnovel-writer/scripts/data_modules/review_schema.pywebnovel-writer/scripts/data_modules/story_system_engine.pywebnovel-writer/skills/webnovel-review/SKILL.mdwebnovel-writer/skills/webnovel-write/SKILL.mdConcrete tasks:
category == "ai_flavor" 且 severity in {"medium", "high", "critical"} 时追加 anti-pattern。text、source_table="review_extracted"、source_id="ch0002_issue_N"、category、added_at。Dependencies:
.story-system/anti_patterns.json schema,不要破坏 reference 初始化写入的旧字段。Verification/tests:
test_ai_flavor_review_issue_added_to_anti_patterns:中等以上 ai_flavor 被追加。test_anti_pattern_review_feedback_dedupes_evidence:重复 evidence 不重复入库。Estimated scope/risk:小,约 2 小时。主要风险是 review report 保存入口不唯一,需要先定位所有审查持久化路径。
| # | 优先级 | 问题 | 影响面 | 工作量 |
|---|---|---|---|---|
| 1 | P0 | chapter_brief 缺少详细大纲的丰富执行约束 | 每一章质量 | 中 |
| 2 | P0 | 写章 prompt 中 dynamic_context 占主位、大纲约束次要 | 每一章质量 | 小 |
| 3 | P1 | reference 检索对真实章目标感知不足,导致题材路由压过章节语义 | 每一章 brief 相关性 | 中 |
| 4 | P1 | 设定模板批量生成空壳;单主角项目仍生成主角组文件 | init 后用户混淆、占位 noise | 小 |
| 5 | P1 | chapter_focus 字段被错塞 dynamic_context 里的无关 summary |
brief 误导 | 小 |
| 6 | P2 | 设定文件缺少占位/漂移防护(卷纲 [待...] 占位 vs 主角卡已具名) |
plan 阶段不一致 | 小 |
| 7 | P2 | 当前卷完成后缺少 V+1 最小锚点 / 结构化伏笔写回 | 跨卷承诺易脱节 | 中 |
| 8 | P2 | 审查抓到的 ai_flavor 模式不回流 anti_patterns.json |
同类问题反复出现 | 小 |
现状证据:
D:\wk\xiaoshuo\灵石庄\.story-system\chapters\chapter_001.json(136 行)字段构成:
{
"meta": {...},
"override_allowed": {"chapter_focus": "<从 SP-087 卡片抄来>"},
"dynamic_context": [SP-087, NR-077, SY-009, CH-072],
"source_trace": [...],
"reasoning": {...}
}
D:\wk\xiaoshuo\灵石庄\大纲\第1卷-详细大纲.md 的第 1 章节有完整的:目标 / 阻力 / 代价 / 时间锚点 / 倒计时状态 / Strand / 反派层级 / CBN / CPNs / CEN / 必须覆盖节点 / 本章禁区 / 章末未闭合问题 / 钩子类型。
其中 CBN / CPNs / CEN / 必须覆盖节点 / 本章禁区 已能被下游结构化解析器识别,但 chapter brief 本身没有携带目标 / 阻力 / 代价 / 时间锚点 / 倒计时 / 章末未闭合问题等执行约束。
影响:
根因:
当前链路是分裂的:
webnovel-writer/scripts/chapter_outline_loader.py 已能从详细大纲中提取 cbn / cpns / cen / mandatory_nodes / prohibitionswebnovel-writer/scripts/data_modules/runtime_contract_builder.py 也已经消费了这些结构化字段,用于 selected_scenes / must_check / blocking_rulesCHAPTER_BRIEF 本身仍主要来自 story-system 的 dynamic_context + chapter_focus,没有把章节执行约束字段提升为写作主输入问题不是“完全没读详细大纲”,而是只读了结构化骨架,没有把章节执行指令注入 chapter brief 主链。
修复方案:
在现有 webnovel-writer/scripts/chapter_outline_loader.py 能力之上补一层执行约束提取,优先扩展同一模块或新增相邻 helper:
load_chapter_execution_directive(project_root: Path, chapter: int) -> dict大纲/第{vol}卷-详细大纲.md 解析章节 markdown 块,提取字段:
goal / obstacles / cost / time_anchor / chapter_span / countdowncbn / cpns: list[str] / cenmust_cover_nodes: list[str]("必须覆盖节点"行)forbidden_zones: list[str]("本章禁区"行,分号分隔)chapter_end_open_question / hook_type / hook_strengthkey_entities: list[str]、strand、antagonist_tier修改 story-system 持久化的 chapter brief 组装链路(webnovel-writer/scripts/story_system.py + webnovel-writer/scripts/data_modules/story_system_engine.py,并让 runtime_contract_builder.py 继续负责 volume/review runtime contracts):
from chapter_outline_loader import load_chapter_execution_directive
directive = load_chapter_execution_directive(project_root, chapter)
brief["chapter_directive"] = directive # 新增顶层字段
if directive and directive.get("goal"):
# 用大纲目标覆盖从 dynamic_context 抄来的 chapter_focus
brief["override_allowed"]["chapter_focus"] = directive["goal"]
修改写章 skill (webnovel-writer/skills/webnovel-write/SKILL.md) 中 prompt 模板,把 chapter_directive 摆在 dynamic_context 之前,并加显式约束语:
## 本章硬性约束(优先级最高)
- 时间锚点:{directive.time_anchor}
- 倒计时状态:{directive.countdown}
- 必须覆盖节点:{directive.must_cover_nodes}
- 章末必须留下:{directive.chapter_end_open_question}
- 本章禁区(违反即不通过):{directive.forbidden_zones}
验收标准:
def test_chapter_brief_contains_outline_directive(tmp_path):
# 准备测试用大纲文件,写一章节块
outline = tmp_path / "大纲" / "第1卷-详细大纲.md"
outline.parent.mkdir(parents=True)
outline.write_text(SAMPLE_OUTLINE_CHAPTER_1, encoding="utf-8")
# 跑 brief 构建
brief = build_chapter_brief(tmp_path, chapter=1)
# 关键字段必须存在
assert brief["chapter_directive"]["time_anchor"] == "D-Day 清晨"
assert "杂役不能随意离开宗门" in brief["chapter_directive"]["forbidden_zones"][0]
assert len(brief["chapter_directive"]["cpns"]) >= 1
# chapter_focus 来自大纲目标,不是 SP 卡 summary
assert "搞清楚" in brief["override_allowed"]["chapter_focus"]
工作量:中(约 4-6 小时含测试)
现状证据:
webnovel-writer/skills/webnovel-write/SKILL.md 现在已经声明 chapter_focus 仅为 CSV 参考、本章目标以章纲为准,并要求有结构化节点时围绕 CBN→CPNs→CEN 展开。但任务书生成仍没有一个稳定的 chapter_directive 展示模板,dynamic_context 这类 reference 补充容易在实际任务书里比大纲执行约束更显眼。
影响:与 #1 联动 —— 即使 brief 里加了 directive,如果 context-agent / 写章任务书没有明确排序,LLM 仍可能把 generic reference 当成主要写作方向。
修复方案:
修改 webnovel-writer/skills/webnovel-write/SKILL.md prompt 段落顺序:
# 第N章 写作任务验收标准:
人工 review 一次写章 prompt,确认 directive > dynamic_context 顺序与权重。
工作量:小(约 1 小时,纯改 markdown 模板 + 1 个 fixture 测试)
现状证据:
第 1 章 brief 注入:
当前产物表现为:被注入的卡片高度偏向“仙侠通用写法”,与第 1-2 章的借贷调查场景不对位。
影响:每章 brief 中无关知识占位,挤走真正有用的卡片(金融/经济类 reference 完全没出现),同时 chapter_focus 还会被这些误召回卡片继续放大偏差。
根因:
这是两个问题叠加:
webnovel-plan / webnovel-write skill 文档把 story-system 调用写成 story-system "{章纲目标}" ...。灵石庄实际落盘的 MASTER_SETTING.json 里,query 甚至是字面量 "第2章章纲目标",说明运行链路并未稳定传入真实章目标;webnovel-review 则在后续审查中暴露这种弱 query 带来的偏差。webnovel-writer/scripts/data_modules/story_system_engine.py 虽然会把 query 传给 reference_search.py,但检索入口先由题材路由决定推荐表,再做简化 BM25。上游 query 一旦是占位或泛词,结果就会退化为“题材对了、场景不对”。所以根因不是“只按 genre_filter 检索”,而是真实章目标没有稳定进入 query,且现有排序对章节语义的放大不够。
修复方案:
webnovel-writer/skills/webnovel-plan/SKILL.md、webnovel-writer/skills/webnovel-write/SKILL.md 中,把 story-system "{章纲目标}" ... 从占位提示升级为必须先解析真实章目标再调用webnovel-writer/skills/webnovel-review/SKILL.md 的审查输入说明里强调需对照真实 chapter_brief.meta.query / 大纲目标,避免把 placeholder query 产物当正常 briefwebnovel-writer/scripts/story_system.py 入口附近补一层保护:若 query 仍是 {章纲目标}、第N章章纲目标 这类占位文本,给出诊断或降级警告chapter_directive.goal、chapter_directive.key_entities、chapter_directive.strand、chapter_directive.antagonist_tier关键词 / 意图与同义词 / 适用场景 字段做 token overlap 评分webnovel-writer/scripts/data_modules/story_system_engine.py 的 _collect_tables / _expand_query 周边补排序信号:
(genre_match_score * 0.4) + (chapter_keyword_score * 0.6)priority_rank 的卡片优先取章节关键词命中数高的reference_search.py 的通用 BM25 能力,不另造不存在的 genre_router.py验收标准:
def test_story_system_reference_matching_prefers_chapter_keywords():
directive = {"goal": "看穿借据条款的荒谬", "key_entities": ["借据", "利息", "复利"]}
result = StorySystemEngine(csv_dir=fixture_csv_dir).build(
query="看穿借据条款的荒谬 借据 利息 复利",
genre="仙侠",
chapter=1,
)
selected = result["chapter_brief"]["dynamic_context"]
# 借贷类卡片应排在论道类前面
assert selected[0]["编号"] == "FIN-001"
工作量:中(约 4 小时,含一份金融场景 reference 卡片样例)
现状证据:
灵石庄设定集:
金手指设计.md:全是 {占位} 和空字段(信息已在主角卡 §金手指 + 总纲 §创意约束)复合题材-融合逻辑.md:全空(信息已在世界观 §融合逻辑 + 总纲 §复合题材融合)主角组.md:全空,且 state.protagonist_structure="单主角+辅助视角"爽点规划.md:只有 1-5/6-10 两条示例(卷纲 §爽点密度规划已有更详细的)角色库/{次要角色,反派角色,主要角色}/、物品库/、其他设定/:全是空目录影响:
根因:
webnovel-writer/skills/webnovel-init/SKILL.md 里硬编码生成所有模板,没按 idea_bank 的 protagonist_structure / heroine_config / 复合题材标志 做分支。
修复方案:
金手指设计.md —— 信息在主角卡 §金手指复合题材-融合逻辑.md —— 信息在世界观 §复合题材融合(且仅复合题材项目才有意义)爽点规划.md —— 卷纲爽点表是单一事实源主角组.md:仅当 protagonist_structure ∈ {"主角组", "双主角", "多主角"} 时生成女主卡.md:仅当 heroine_config != "无女主" 时生成反派设计.md 始终生成(必填)复合题材-融合逻辑.md(如果保留):仅当 genre_combination 标记非空时生成角色库/ 在第一次 apply_entity_delta 写新角色时创建(按 entity_type/tier 分子目录)物品库/、其他设定/ 同理修改文件:webnovel-writer/scripts/init_project.py、webnovel-writer/templates/output/ 中仍需保留的模板,以及 webnovel-writer/skills/webnovel-init/SKILL.md 生成步骤段。
验收标准:
def test_init_skips_protagonist_group_for_single_protagonist(tmp_path):
init_project(tmp_path, idea_bank={"protagonist_structure": "单主角+辅助视角", ...})
assert not (tmp_path / "设定集" / "主角组.md").exists()
assert (tmp_path / "设定集" / "主角卡.md").exists()
def test_init_skips_dead_template_files(tmp_path):
init_project(tmp_path, idea_bank={...})
for dead in ("金手指设计.md", "爽点规划.md"):
assert not (tmp_path / "设定集" / dead).exists()
工作量:小(约 2 小时)
现状证据:
chapter_002.json:override_allowed.chapter_focus = "文斗场面的张力来自观点击中修行根基。"
这是从 dynamic_context 里 SP-087 卡的 核心摘要 直抄。但第 2 章是"井边对话收集借贷情报",不是文斗场景。
影响:当 LLM 把 chapter_focus 当本章核心方向时,会被误导走偏。
根因:
webnovel-writer/scripts/data_modules/story_system_engine.py 的 _suggest_chapter_focus() 在没有显式大纲目标时,直接返回第一条 dynamic_context 的 核心摘要。由于 reasoning 排序会把 SP-087 这类泛题材卡排到前面,chapter_focus 就被无关 summary 污染;这不是 runtime_contract_builder.py 的行为。
修复方案:
与 #1 联动 —— 一旦 chapter_directive 接入,chapter_focus 取自 directive.goal。没有 directive 时取 query(前提是非占位)或留空,绝不从 dynamic_context 抄。
验收标准:
test_chapter_brief_contains_outline_directive 已涵盖(chapter_focus 来自大纲目标)。补充:
def test_chapter_focus_never_taken_from_dynamic_context_summary(tmp_path):
brief = build_chapter_brief(tmp_path, chapter=99) # 大纲没有第 99 章
# 没大纲时 chapter_focus 应为空字符串或 None,而非 SP 卡 summary
assert brief["override_allowed"].get("chapter_focus", "") == ""
工作量:小(约 30 分钟,包含在 #1 改动里)
现状证据:
第1卷-卷纲.md:25 行:第一位女主(暂名) | 女主 | [待章纲拆分时具体设计] | 第20章起苏云——第一位女主...苏云 人物卡主角卡 / 女主卡是 plan 阶段的某次产出后填好的,卷纲表格停留在较早版本,没有后续一致性检查。
主角卡里还有:
[待补充]:能打但脑子不够用的兄弟型角色(后续卷引入)未来发现这个角色没填,到写到该卷时才暴露。
影响:plan 阶段产出文件之间数据漂移;写章前没提醒导致用户没意识到未填项。
根因:
这不是某条“自动回填流水线失效”,而是当前系统只有“增量写回现有设定集”的流程承诺,没有占位扫描、跨文件一致性检查、也没有写章前的 pending blocker。webnovel-plan/SKILL.md 明确要求“卷纲完成后,把新增设定增量写回现有设定集”,但仓库里没有对应的 placeholder guardrail。
修复方案:
新增 webnovel-writer/scripts/data_modules/placeholder_scanner.py:
大纲/*.md、设定集/*.md 中匹配以下模式的占位:
\[待[^\]]*\](如 [待补充]、[待章纲拆分时具体设计]、[待定])(暂名)、(暂名)、(待补充){占位}、<占位> 块{file, line, context, suggested_fill_phase}在以下流程前加阻断检查:
webnovel-plan 开始或结束时:扫所有 plan 文件,警告但不阻断webnovel-write 开始时:扫当前章节涉及的实体对应的设定文件,有 [待...] 阻断写章加一个 CLI 命令 webnovel.py placeholder-scan --project-root <dir> 让用户主动检查
验收标准:
def test_placeholder_scanner_finds_pending_marks(tmp_path):
f = tmp_path / "大纲" / "第1卷-卷纲.md"
f.write_text("第一位女主(暂名)| [待章纲拆分时具体设计]")
results = scan_placeholders(tmp_path)
assert len(results) == 2
assert any("(暂名)" in r["pattern"] for r in results)
assert any("[待章纲" in r["pattern"] for r in results)
def test_write_chapter_blocks_on_pending_protagonist_card(tmp_path):
# 主角卡有 [待补充] 但本章没涉及该实体 → 不阻断
# 主角卡有 [待补充] 且本章涉及该实体 → 阻断
...
工作量:小(约 2 小时)
现状证据:
大纲/总纲.md:46-62:
| 卷号 | 卷名 | 章节范围 | 核心冲突 | 卷末高潮 |
| 1 | 阎王债 | 第1-50章 | <已填> | <已填> |
| 2 | | 第51-100章 | | |
...
| 20 | | 第951-1000章 | | |
伏笔表只有 2 条核心伏笔 + 1 行空。
影响:plan 阶段的 LLM 没有跨卷视野,每次开新卷都从头规划,可能跟前期承诺/伏笔脱节。
修复方案:
webnovel-plan 已成功完成当前卷规划,且当前卷规划 artifacts 已完整/通过验证卷名、核心冲突、卷末高潮大纲/总纲.md 的下一卷行;若不存在则追加一行webnovel-plan 完成一卷规划时,只追加当前规划输出中显式结构化产出的:
这一路径最贴合写作流:当前卷规划完成时,系统只把必要的跨卷承诺固化到总纲,保留下一卷正式规划时的创作空间。
验收标准:
def test_plan_flow_writes_minimal_next_volume_anchor(tmp_path):
plan_volume(tmp_path, volume=1) # 这里代表 webnovel-plan 完成 V1 规划
# 完成后总纲应自动多了 V2 最小锚点(V3-V20 不存在/不预填)
summary = (tmp_path / "大纲" / "总纲.md").read_text(encoding="utf-8")
assert "| 2 |" in summary
v2_line = [l for l in summary.split("\n") if l.startswith("| 2 |")][0]
assert v2_line.count("|") == 6
assert "第2卷-详细大纲.md" not in list_outline_files(tmp_path)
assert "第2卷-beat-sheet.md" not in list_outline_files(tmp_path)
assert "第2卷-timeline.md" not in list_outline_files(tmp_path)
def test_plan_flow_appends_only_structured_foreshadow_items(tmp_path):
plan_volume(tmp_path, volume=1, structured_foreshadow=[
{"type": "new_foreshadowing", "text": "债契背面的红印仍未解释"},
{"type": "continued_open_loop", "text": "苏云身份与阎王债源头仍未闭合"},
])
summary = (tmp_path / "大纲" / "总纲.md").read_text(encoding="utf-8")
assert "债契背面的红印仍未解释" in summary
assert "苏云身份与阎王债源头仍未闭合" in summary
工作量:中(约 4 小时,包含 webnovel-plan prompt / 流程改动)
现状证据:
灵石庄/.story-system/anti_patterns.json:10 条全部来自 reference 库初始化(GR-011 / NR-077 / CH-072 / SP-087 / RS-002 的"毒点"字段)。
第 2 章审查报告 抓到的 ai_flavor:
这些模式没进入 anti_patterns.json。后续章节没有"上一章已经被点出的句式不要重复"的避雷清单。
修复方案:
webnovel-writer/scripts/data_modules/review_schema.py(或对应处)在持久化审查报告后,新增 hook:
if issue["category"] == "ai_flavor" and issue["severity"] in ("medium", "high", "critical"):
anti_patterns_store.append({
"text": issue["evidence"][:200],
"source_table": "review_extracted",
"source_id": f"ch{chapter:04d}_issue_{issue_idx}",
"category": issue["category"],
"added_at": now_iso(),
})
写章前 brief 注入 anti_patterns 的 text 列表作为"避雷模式"
加去重机制(同一 evidence 不重复入库)
验收标准:
def test_ai_flavor_review_issue_added_to_anti_patterns(tmp_path):
save_review_report(tmp_path, chapter=2, issues=[{
"category": "ai_flavor",
"severity": "medium",
"evidence": "唯一一个知道复利公式的人。唯一一个知道..."
}])
patterns = json.loads((tmp_path / ".story-system" / "anti_patterns.json").read_text())
assert any("唯一一个知道" in p["text"] for p in patterns)
assert any(p["source_id"].startswith("ch0002_") for p in patterns)
工作量:小(约 2 小时)
完成后必须通过:
pytest --no-cov 全过(当前 508 个用例)灵石庄2)—— 验证:
主角组.md、金手指设计.md、复合题材-融合逻辑.md、爽点规划.mdchapter_directive 字段[待补充] 然后写第 50 章(涉及该角色) → 应阻断第1章 vs 第一章),需要兼容。建议在 outline_extractor 用 regex 匹配 第\s*\d+\s*章 全部变体。f58d657)可能在 #1 启用 directive 后有交互:directive 里有 time_anchor,state.protagonist_state 里有 location.last_chapter,两者不应被混写。需在 #1 实现时显式分离命名空间。| 类型 | 例子 | 责任 |
|---|---|---|
| LLM 输出本身的写作瑕疵 | AI 味、习惯动作过密、句式重复 | 审查 agent 已抓 |
| init 时用户未填的项目元数据 | heroine_names 空 | 用户责任,UI 应提示 |
| 模型选型 / 上下文窗口大小 | 一次生成不下大章 → 增量更新 | 模型/平台层 |
| 数据 agent 调用慢(NOT_FOUND 重试) | 见 data_agent_timing.jsonl |
已在 f58d657 修主因 |
chapter_outline_loader.py 先实现 load_chapter_execution_directive(),用最小 fixture 覆盖详细大纲第 1 章字段提取。chapter_directive 接入 story_system.py / story_system_engine.py 的 brief 组装,并让 chapter_focus 优先取 directive.goal。webnovel-write/SKILL.md,把“本章硬性约束 / CBN-CPNs-CEN / 本章禁区”排到 dynamic_context 前。story_system.py 增加 placeholder query 诊断,并同步更新 webnovel-plan、webnovel-write、webnovel-review 三个 skill 的真实 query 要求。story_system_engine.py 增加 chapter-aware reference ranking,用 goal/key_entities/strand/antagonist_tier 影响排序。init_project.py 与 webnovel-init/SKILL.md 的模板生成清单,先完成单主角 / 无女主 / 死模板剪枝测试。placeholder_scanner.py 与 webnovel.py placeholder-scan,先实现全项目扫描,再接入 plan 警告。webnovel-plan/SKILL.md,移除 V2-V20 预生成空行;在当前卷规划完成并验证后,只写回 V+1 的卷名 / 核心冲突 / 卷末高潮,并仅追加当前规划输出显式结构化给出的新伏笔 / 持续开放环。review_schema.py 增加 ai_flavor → anti_patterns.json 回流与去重,再验证下一章 brief 能读到 review-extracted 避雷模式。