news 2026/9/16 18:21:18

网文创作系统的 Story System Phase 1 合同种子层:题材路由、MASTER_SETTING 持久化与运行时注入实战解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
网文创作系统的 Story System Phase 1 合同种子层:题材路由、MASTER_SETTING 持久化与运行时注入实战解析

网文创作系统的 Story System Phase 1 合同种子层:题材路由、MASTER_SETTING 持久化与运行时注入实战解析

【免费下载链接】webnovel-writer基于 Claude Code 的长篇网文辅助创作系统,解决 AI 写作中的「遗忘」和「幻觉」问题,支持 200 万字量级 连载创作。项目地址: https://gitcode.com/GitHub_Trending/we/webnovel-writer

本篇技术指南以 webnovel-writer 项目中 Story System Phase 1 合同种子实施计划 为主体,结合仓库内已落地的源码与测试,系统讲解「题材路由 → 合同聚合 →.story-system持久化 → runtime 注入」四段式最小合同真源如何落地。读者将掌握:合同路径层与三层 merge 规则的设计、题材与调性推理 CSV 的字段语义与回退顺序、统一 CLI 的构建与转发方式,以及context_manager如何把合同种子上游化到genre_profile之前,从而在不破坏既有reference_search.py与写作主流程的前提下,为长篇连载的「遗忘」与「幻觉」问题建立第一道工程防线。

一、背景:为什么 Phase 1 只做「合同种子层」

webnovel-writer 是面向 200 万字量级长篇连载的辅助创作系统。AI 写作在长程上下文中最典型的两个失效模式是「遗忘」(前面立下的设定、调性、禁忌在几十章后被丢弃)与「幻觉」(模型自行编造与题材调性不符的情节)。Story System 的整体思路,是把创作约束沉淀为可读、可校验、可注入的「合同」(contract),而 Phase 1 的目标是建立最小合同真源,不做任何超前设计。

原计划开篇给出的目标非常克制:

在不破坏现有reference_search.pycontext_manager.py与写作主流程的前提下,落地 Story System Phase 1 合同种子层:题材与调性推理.csv、最小MASTER_SETTING/CHAPTER_BRIEF/anti_patterns持久化,以及context_manager的合同读取入口。

对应的技术栈为 Python 3.13、argparse、pytest、CSV(UTF-8 with BOM)、Markdown + JSON 合同文件,以及统一 CLIwebnovel.py,并明确配套两份规格文档:story-system-evolution-spec 与 story-system-pro-max-retrofit-spec。

二、四段式架构与 Phase 边界(Scope Split)

Phase 1 采用「数据层 → 合同聚合器 →.story-system/持久化 → runtime 注入」的四段式架构:

  1. 数据层题材与调性推理.csv等 CSV 参考表,是题材路由的知识源;
  2. 合同聚合器StorySystemEngine完成题材路由、多表检索编排与 anti-pattern 聚合,构造最小合同字典;
  3. 持久化persist_story_seedMASTER_SETTING/chapter_XXX/anti_patterns写入PROJECT_ROOT/.story-system/
  4. runtime 注入context_manager读取合同并注入story_contractsection,extract_chapter_context将其透出到可视化提取结果。

原计划把 Phase 2~5 的内容明确排除在本次实施范围之外,原因在于防止「文件责任边界失真、TDD 粒度失控、阶段产物无法验证」:

  • Phase 2以后会引入VOLUME_BRIEFREVIEW_CONTRACT、大纲履约 diff、review blocking rules;
  • Phase 3会新增CHAPTER_COMMIT与四类 projection writers;
  • Phase 4会新增 canonical event log;
  • Phase 5才能安全降级旧链路。

因此 Phase 1 的退出标准被固定为四条:

  1. PROJECT_ROOT/.story-system/能生成最小MASTER_SETTINGchapter_XXXanti_patterns
  2. context_manager能读取并注入story_contractsection;
  3. genre_profile仍可作为回退层保留(不删除genre-profiles.md);
  4. 文档已明确 Phase 1 的路径语义、schema 与使用方式。

文档边界同步定死:README.md只新增Story System一级段落与基础目录说明,后续 Phase 2/3/4 只能在既有段落下追加,不重写整段结构。

三、文件结构与职责分工

原计划把改动文件划分为「创建」与「修改」两组,并逐一明确职责:

要创建的文件

文件职责
题材与调性推理.csv题材路由种子数据
story_contracts.py合同路径、merge 规则、JSON/Markdown 持久化、marker 安全更新
story_system_engine.py题材路由、多表检索编排、anti-pattern 聚合、最小合同字典构造
story_system.pyCLI 入口,负责query -> build -> render -> persist
测试文件三件套test_story_contracts.py/test_story_system_engine.py/test_story_system_cli.py

要修改的文件

  • config.py:增加.story-system路径属性;
  • context_manager.py:读取合同并注入story_contractsection;
  • extract_chapter_context.py:把story_contract纳入可视化文本/JSON 提取结果;
  • webnovel.py:统一 CLI 挂接story-system子命令;
  • 桥段套路.csv:增加忌讳写法列(落地下线时演化为毒点列,见下文);
  • references/csv/README.md:补充题材表字段文档;
  • README.md / overview.md / commands.md / superpowers README:文档同步。

四、Task 1:合同路径层与最小 merge 规则

Task 1 采用严格的 TDD:先写失败测试,确认ModuleNotFoundError红灯,再实现路径与合并逻辑,回跑转绿后提交。

4.1 路径层:.story-system的目录约定

失败测试锚定三条核心路径约定:根目录、MASTER_SETTING.jsonanti_patterns.json、章节文件。仓库中 story_contracts.py 的实现完全对应,并且作为 Phase 2~4 的扩展点,还预置了volumes_dirreviews_dircommits_direvents_dir四个后续阶段的目录属性:

@dataclass(frozen=True) class StoryContractPaths: project_root: Path @classmethod def from_project_root(cls, project_root: str | Path) -> "StoryContractPaths": return cls(Path(project_root).expanduser().resolve()) @property def root(self) -> Path: return self.project_root / ".story-system" @property def chapters_dir(self) -> Path: return self.root / "chapters" @property def master_json(self) -> Path: return self.root / "MASTER_SETTING.json" @property def anti_patterns_json(self) -> Path: return self.root / "anti_patterns.json" def chapter_json(self, chapter: int) -> Path: return self.chapters_dir / f"chapter_{chapter:03d}.json"

同时,config.py 为DataModulesConfig增加了story_system_dirstory_system_chapters_dirstory_system_master_jsonstory_system_anti_patterns_json四个只读属性,保证路径约定在配置层只有单一真源,避免各调用方各自拼接路径导致漂移。

4.2 三层 merge 规则:locked / append_only / override_allowed

合同合并的核心是「主设定(master)与章节(chapter)两层如何叠加」。原计划定义了三类权限语义:

  • locked:chapter 不得覆盖(master 说了算);
  • append_only:chapter 只能追加,且按条目去重;
  • override_allowed:chapter 可局部覆盖(以 chapter 为准)。

对应的失败测试覆盖了「locked 保持 master 值不被 chapter 冲掉」「append_only 列表顺序拼接去重」「override_allowed 以 chapter 为准」三个断言。仓库实现 story_contracts.py 如下:

def _merge_append_only(master: Dict[str, Any], chapter: Dict[str, Any]) -> Dict[str, List[Any]]: merged: Dict[str, List[Any]] = {} for key in set(master) | set(chapter): seen: List[Any] = [] for source_list in (master.get(key) or [], chapter.get(key) or []): for item in source_list: if item not in seen: seen.append(item) merged[key] = seen return merged def merge_contract_layers(master: Dict[str, Any], chapter: Dict[str, Any] | None) -> Dict[str, Any]: chapter = chapter or {} return { "locked": dict(master.get("locked") or {}), "append_only": _merge_append_only( master.get("append_only") or {}, chapter.get("append_only") or {}, ), "override_allowed": { **(master.get("override_allowed") or {}), **(chapter.get("override_allowed") or {}), }, }

merge_anti_patterns则负责多来源 anti-pattern 的按文本去重,保留首个来源的source_tablesource_id

def merge_anti_patterns(*groups: Iterable[Dict[str, Any]]) -> List[Dict[str, Any]]: seen: set[str] = set() merged: List[Dict[str, Any]] = [] for group in groups: for row in group: text = str(row.get("text") or "").strip() if not text or text in seen: continue seen.add(text) merged.append(dict(row)) return merged

4.3 统一读取约定:read_json_if_exists

原计划特别强调,要在本阶段先落地一个统一读取 helper,供 Phase 2-4 复用,避免后续 projection / runtime builder 各写一套吞错逻辑:

  • read_json_if_exists(path) -> dict | list | None
  • 文件不存在时返回None
  • JSON 格式错误时抛带路径的ValueError

仓库实现 story_contracts.py 与此完全一致,对应的测试test_read_json_if_exists_returns_none_for_missing_filetest_read_json_if_exists_raises_value_error_with_pathtest_read_json_if_exists_loads_valid_json在 test_story_contracts.py 中均已落地。

五、Task 2:题材路由表与合同聚合器

Task 2 的核心是「题材与调性推理」路由表 +StorySystemEngine聚合器。原计划给出了完整的失败测试:用tmp_path / csv真实 CSV 喂给reference_search.search()不 monkeypatch 搜索函数,并要求后续reference_search.search()签名变化时优先同步聚合器封装而非绕过真实接口。

5.1 CSV 字段语义

原计划为 题材与调性推理.csv 定义了字段文档,并计划在 references/csv/README.md 中新增说明:

列名说明
题材/流派路由主标签
题材别名同义词 / 平台黑话
核心调性全局情绪基调
节奏策略开局与兑现节奏
强制禁忌/毒点题材级绝对红线
推荐基础检索表默认基础检索表
推荐动态检索表默认动态检索表

需要注意的是,落地实现与计划存在两处演化(这正是阅读源码能看到的真实差异):

  1. 原计划的强制禁忌/毒点列在仓库中简化为毒点列;
  2. 新增了canonical_genre列(题材规范名,用于与genre-canonical.md的规范题材体系对齐),并去掉了计划中提到的主冲突模板必选爽点基础检索权重动态检索权重四列——聚合器改为依赖裁决规则.csv的冲突裁决权重体系进行排序(见下文 5.3)。

真实种子数据已录入 26 条(GR-001~GR-026),覆盖玄幻退婚流、规则动物园、压抑后爆、都市赘婿流、追妻火葬场、番茄爽文、知乎短篇风、小程序短篇风、穿越流、都市异能、传统修真、末世求生、青春甜宠、悬疑推理、种田经营、娱乐圈、游戏电竞、克苏鲁诡秘、学院流、副本流、西幻冒险、古言权谋、玄幻言情、年代民国、快穿任务、同人衍生等主流流派。以GR-001为例:

编号,适用技能,分类,层级,关键词,意图与同义词,适用题材,大模型指令,核心摘要,详细展开,题材/流派,canonical_genre,题材别名,核心调性,节奏策略,毒点,推荐基础检索表,推荐动态检索表,默认查询词 GR-001,story-system,题材路由,知识补充,玄幻退婚流|退婚流|废材逆袭,退婚打脸怎么写|莫欺少年穷|三年之约怎么立,玄幻|仙侠,先压后爆,耻辱必须转成长线兑现。,退婚或逐出型起手必须先把尊严踩到底,再把反击延迟兑现为长线承诺。,...,玄幻退婚流,玄幻,退婚流|废材逆袭,先压后爆,三章内必须有首次有效反打,打脸不能软收尾|主角还没兑现就被配角代打,命名规则|人设与关系|金手指与设定,桥段套路|爽点与节奏|场景写法,退婚|打脸|废材逆袭

多值列统一使用|(仓库实现实际用[|;;]+正则切分,兼容分号)分隔,文件以utf-8-sig编码读写以兼容 Excel 与 Windows。

5.2 路由命中顺序与回退链

聚合器_route方法的命中顺序被设计为可预测的固定优先级(见 story_system_engine.py):

  1. 关键词/同义词命中keyword_or_alias_match):把关键词意图与同义词题材别名三列合并为别名集,逐一在query + genre归一化文本中做子串匹配;
  2. 显式 genre 回退explicit_genre_fallback):未命中时,若传入--genre,按适用题材/题材/流派/canonical_genre三列的规范名做交集匹配;
  3. 文本推断 genre 回退inferred_genre_fallback):从 query 文本分词推断规范题材(利用resolve_genreGENRE_CANONICAL词表);
  4. 路由失败:全部未命中时抛出StorySystemRoutingError,CLI 以退出码 2 终止,绝不落盘

计划书中的default_seed_fallback(默认首行回退)在落地实现中被替换为显式抛错,避免在题材表中没有匹配行时静默生成错误合同。同时实现还增加了两道防御:

  • is_placeholder_query():识别{章纲目标}这类占位查询,CLI 会向 stderr 输出警告「parse the real chapter goal from the outline」;
  • _validate_explicit_genre_source()--genre参数只接受中文题材名,传入英文 profile key(如rules-mystery)会直接报错退出,防止用genre-profiles.md的英文键污染路由。

对应测试test_story_system_warns_on_placeholder_querytest_story_system_persist_unroutable_exits_without_contracts都在 test_story_system_cli.py 中验证了「退出码 2 + 错误信息 + 不生成.story-system目录」的行为。

5.3 anti-pattern 聚合与裁决层排序

聚合器把三类来源的 anti-pattern 合并:

  1. 路由行自身毒点列(_extract_route_anti_patterns);
  2. 基础检索表命中行的反面写法字段;
  3. 动态检索表命中行的反面写法字段。

字段映射表ANTI_PATTERN_SOURCE_FIELDS把「表名 → 反面字段」建立显式对应(场景写法/写作技法/爽点与节奏/人设与关系/桥段套路/题材与调性推理/命名规则/金手指与设定 均映射到毒点),再经merge_anti_patterns按文本去重。

在 Phase 1 之上,仓库实现进一步引入了裁决层(reasoning layer):从 裁决规则.csv 按题材加载裁决行,依据「冲突裁决」优先级顺序给命中行打_priority_rank,结合章节指令(goal/strand/antagonist_tier/key_entities/must_cover_nodes)计算章节关键词命中分,最终按 0.4/0.6 加权得出_combined_rank_score排序;anti-pattern 也依据「毒点权重」排序,并追加裁决行的「反模式」条目。这套排序结果最终写入source_trace,使每一条注入内容都可溯源到具体表格与编号。

六、Task 3:.story-system持久化与统一 CLI 接入

6.1 持久化写入器与 marker 安全更新

持久化的关键设计是JSON 为真源、Markdown 为投影视图*.json承载完整结构,*.md仅供人读,且必须通过 marker 实现「机器更新 + 人工备注共存」。仓库实现 story_contracts.py 严格落地了计划约束——每个.md文件只允许一组<!-- STORY-SYSTEM:BEGIN/END -->marker,多组直接抛ValueError,避免 Phase 2 以后出现局部覆盖残留:

def write_marked_markdown(path: Path, generated_block: str) -> None: wrapped = f"{MARKER_BEGIN}\n{generated_block.rstrip()}\n{MARKER_END}\n" path.parent.mkdir(parents=True, exist_ok=True) if path.exists(): current = path.read_text(encoding="utf-8") if current.count(MARKER_BEGIN) > 1 or current.count(MARKER_END) > 1: raise ValueError(f"{path} contains multiple STORY-SYSTEM markers") if MARKER_BEGIN in current and MARKER_END in current: before, _, rest = current.partition(MARKER_BEGIN) _, _, after = rest.partition(MARKER_END) path.write_text(f"{before}{wrapped}{after.lstrip()}", encoding="utf-8") return path.write_text(wrapped, encoding="utf-8")

该机制由test_markdown_writer_preserves_manual_notes_outside_markers验证:人工写在 marker 之外的内容(如# 手工说明)必须保留,marker 之内的旧内容必须被替换。

三个渲染器(render_master_markdown/render_anti_patterns_markdown/render_chapter_markdown)分别生成MASTER_SETTING.mdanti_patterns.mdchapter_XXX.md的投影视图,随后由persist_story_seed统一落盘(story_contracts.py):

def persist_story_seed( project_root: Path, master_payload: Dict[str, Any], chapter_payload: Dict[str, Any] | None, anti_patterns: List[Dict[str, Any]], ) -> None: paths = StoryContractPaths.from_project_root(project_root) paths.root.mkdir(parents=True, exist_ok=True) paths.chapters_dir.mkdir(parents=True, exist_ok=True) write_json(paths.master_json, master_payload) write_json(paths.anti_patterns_json, anti_patterns) write_marked_markdown(paths.master_json.with_suffix(".md"), render_master_markdown(master_payload)) write_marked_markdown(paths.anti_patterns_json.with_suffix(".md"), render_anti_patterns_markdown(anti_patterns)) if chapter_payload is not None: chapter_num = int(chapter_payload["meta"]["chapter"]) write_json(paths.chapter_json(chapter_num), chapter_payload) write_marked_markdown(paths.chapter_json(chapter_num).with_suffix(".md"), render_chapter_markdown(chapter_payload))

注意:write_json在仓库实现中经由security_utils.atomic_write_json(path, payload, backup=True)原子写入并自动备份,避免中途崩溃产生半截 JSON——这是计划之外、实现阶段补强的健壮性细节。

6.2 story_system.py CLI 参数

story_system.py 作为独立 CLI 入口,参数如下:

参数类型/默认值说明
query位置参数题材描述或当前意图
--project-rootstr,默认空书项目根目录或工作区根目录;为空时经project_locator.resolve_project_root()自动定位
--genrestr,默认空显式题材(必须为中文名)
--chapterint,默认 0章节号;>0 时同时生成CHAPTER_BRIEF
--persistflag写入PROJECT_ROOT/.story-system/
--formatjson/markdown/both,默认 json输出格式;both同时打印 JSON 与 Markdown 渲染
--csv-dirstr,默认空测试时覆写 CSV 目录;为空时指向references/csv

运行时的防御链(实现阶段补强):占位 query 警告 → 章节执行指令加载(load_chapter_execution_directive,取自大纲章纲目标)→StorySystemEngine.build→ 路由失败以退出码 2 终止且不落盘 → 成功则persist_story_seed落盘 → 按格式渲染输出。

6.3 统一 CLI 转发

统一入口 webnovel.py 通过 argparse 子命令挂接:

p_story_system = sub.add_parser("story-system", help="转发到 story_system.py") p_story_system.add_argument("args", nargs=argparse.REMAINDER)

路由分支在 webnovel.py:

if tool == "story-system": raise SystemExit(_run_script("story_system.py", [*forward_args, *rest]))

关键点是project root 的统一注入:转发前先由resolve_project_root解析真实书项目根目录,并以解析后的绝对路径注入--project-root。对应的测试test_webnovel_story_system_forwards_with_resolved_project_root通过 monkeypatch_run_script断言转发的脚本名与 argv 前缀。这意味着无论用户在哪个工作区执行,合同永远落盘到书项目自己的.story-system/,不会污染工作区。

实际使用命令(来自 commands.md 的命令文档约定):

python -X utf8 "<CLAUDE_PLUGIN_ROOT>/scripts/webnovel.py" \ --project-root "<WORKSPACE_ROOT>" \ story-system "玄幻退婚流" --chapter 1 --persist --format both

说明:--project-root允许传工作区根或书项目根;真实落盘位置始终是PROJECT_ROOT/.story-system/*.json为真源,*.md为投影视图。

七、Task 4:把合同种子接入 context_manager 与 extract_chapter_context

7.1 section 顺序:story_contract 前置

合同必须优先于genre_profile注入,因为合同是「真源」,genre profile 只是「回退层」。测试断言直接验证了这一点:

assert ContextManager.SECTION_ORDER.index("story_contract") < ContextManager.SECTION_ORDER.index("genre_profile")

仓库中 context_manager.py 的SECTION_ORDER确认了该顺序,并在后续演进中进一步前置了runtime_status/latest_commit/prewrite_validation三个运行时 section:

SECTION_ORDER = [ "core", "story_contract", "runtime_status", "latest_commit", "prewrite_validation", "scene", "global", "reader_signal", "genre_profile", "writing_guidance", "plot_structure", "story_skeleton", "memory", "long_term_memory", "preferences", "alerts", ]

7.2 合同加载与注入

计划给出的_load_story_contract读取MASTER_SETTING.jsonchapter_XXX.jsonanti_patterns.json,三份文件全缺时返回空 dict,否则聚合为master_setting/chapter_brief/route/master_constraints/anti_patterns结构并注入pack

仓库实现进一步演进为_build_story_contract_from_runtime(context_manager.py),从RuntimeSourceSnapshot(见 story_runtime_sources.py)读取 Phase 2+ 的master/chapter/volume/review四类运行时合同,anti-patterns 仍直读anti_patterns.json

def _build_story_contract_from_runtime(self, runtime_sources: RuntimeSourceSnapshot) -> Dict[str, Any]: story_root = self.config.story_system_dir return { "master_setting": runtime_sources.contracts.get("master") or {}, "chapter_brief": runtime_sources.contracts.get("chapter") or {}, "volume_brief": runtime_sources.contracts.get("volume") or {}, "review_contract": runtime_sources.contracts.get("review") or {}, "anti_patterns": read_json_if_exists(story_root / "anti_patterns.json") or [], }

随后_assemble_json_payloadSECTION_ORDER组装 payload,story_contract属于EXTRA_SECTIONS(无权重兜底也必然注入)。对应测试test_context_manager_includes_story_contract_section_before_genre_profile在 test_context_manager.py 中验证了sections["story_contract"]["content"]["route"]["primary_genre"]与章节焦点均被正确注入。

7.3 extract_chapter_context 透出与文本渲染

extract_chapter_context.py 的_load_contract_context复用ContextManager组装 payload,并把reader_signal/genre_profile/story_contract/writing_guidance/plot_structure/long_term_memory六类内容统一透出,随后在build_chapter_context_payload中暴露story_contract字段。

文本渲染则新增紧凑的## Story Contract章节:输出主路由题材,并取前 5 条 anti-pattern 以- 红线: ...行展示,让作者在纯文本上下文预览中也能一眼看到题材与禁忌。对应测试test_build_chapter_context_payload_includes_story_contract验证了 payload 结构与 anti-pattern 文本。

八、Task 5:架构文档、命令文档与回归验证

8.1 Phase 1 架构文档的核心约定

原计划要求新建docs/architecture/story-system-phase1.md,至少写清四段,避免代码上线后变成隐式约定:

JSON 真源

  • PROJECT_ROOT/.story-system/MASTER_SETTING.json
  • PROJECT_ROOT/.story-system/anti_patterns.json
  • PROJECT_ROOT/.story-system/chapters/chapter_XXX.json

覆盖规则

  • locked:chapter 不得覆盖;
  • append_only:chapter 只能补充;
  • override_allowed:chapter 可局部覆盖。

运行时读取顺序

  1. chapter brief → 2. master setting → 3. anti-patterns → 4. genre profile fallback(回退层)

迁移边界

  • Phase 1 不引入VOLUME_BRIEF
  • Phase 1 不改写后回写主链(合同是只读输入的约束源,不反向改写正文);
  • genre-profiles.md继续保留为回退层。

README.md与 overview.md 均补入同一句说明:

Story System Phase 1:新增最小合同种子层(MASTER_SETTING/chapter_XXX/anti_patterns),作为context_manager的合同输入前置层。

8.2 回归测试矩阵

Phase 1 的验证分两层:功能层跑目标测试集,回归层跑reference_search.py的既有测试证明没有破坏底层 primitive。原计划给出的完整命令:

python -m pytest \ webnovel-writer/scripts/data_modules/tests/test_story_contracts.py \ webnovel-writer/scripts/data_modules/tests/test_story_system_engine.py \ webnovel-writer/scripts/data_modules/tests/test_story_system_cli.py \ webnovel-writer/scripts/data_modules/tests/test_context_manager.py \ webnovel-writer/scripts/data_modules/tests/test_extract_chapter_context.py \ webnovel-writer/scripts/data_modules/tests/test_webnovel_unified_cli.py \ -q --no-cov python -m pytest webnovel-writer/scripts/tests/test_reference_search.py -q --no-cov

从当前仓库看,test_story_system_cli.py还追加了test_story_system_default_csv_dir_routes_real_genre_seed,直接用真实references/csv目录路由玄幻退婚流,断言route_source != "empty_csv_fallback",防止默认 CSV 路径漂移后「假路由」静默通过——这是对计划「不允许用空表兜底通过测试」约束的延续。

九、从源码看 Phase 1 的演进边界

阅读当前仓库源码可以发现,Phase 1 之后的阶段已在路径层与 CLI 上预留了清晰的扩展点(这些属于实现事实,可作为理解演进方向的依据):

  • StoryContractPaths已声明volumes/reviews/commits/events四类目录属性,分别对应 Phase 2 的VOLUME_BRIEFREVIEW_CONTRACT,Phase 3 的CHAPTER_COMMIT,Phase 4 的 canonical event log;
  • story_contracts.py 新增persist_runtime_contracts,配合chapter_outline_loader.volume_num_for_chapter_from_state落盘 volume 与 review 合同;
  • story_system.py 新增--emit-runtime-contracts开关,经RuntimeContractBuilder(见 runtime_contract_builder.py)在--chapter给定后生成并持久化运行时合同;
  • context_managerstory_contractsection 已扩展为读取四类运行时合同。

这些演进都以 Phase 1 建立的路径约定、merge 规则与read_json_if_exists统一读取 helper 为基础,印证了计划「先做合同种子层,不提前做CHAPTER_COMMIT或 event log」的阶段性约束——阶段边界清晰,后续才能安全演进。

十、Spec Coverage 与后续计划

原计划以 Spec Coverage Check 收尾,明确本计划与 story-system-evolution-spec 的映射:

  • 13.2 Phase 1:合同种子层:题材路由表(Task 2)、最小MASTER_SETTING/CHAPTER_BRIEF(Task 3)、anti_patterns.json(Task 3)、context_manager读取合同(Task 4);
  • 14.1 / 14.1.1 路径解析约束PROJECT_ROOT/.story-system(Task 1/3)、resolve_project_root经 unified CLI 注入(Task 3);
  • 15.3 当前阶段结论:保留 CSV + MD 双体系,不做自动迁移(Task 2);
  • 17.1 文档更新要求:合同 schema / 目录 / 运行流程 / 迁移说明文档(Task 5);
  • 19. 实施建议:明确先做合同种子层,不提前做CHAPTER_COMMIT或 event log(全计划范围)。

原计划还专门做了Placeholder Scan 自查,避免三类偷工减料:没有 "TODO / TBD / 后续补";每个「写测试」步骤都给出可运行测试骨架而非空泛口号;文档更新明确到具体目标文件;Phase 2-4 内容不混入 Phase 1 任务。

Phase 1 稳定后的后续路线(原计划「Next Plan」明确列出):

  1. Phase 2 Contract-First RuntimeVOLUME_BRIEFREVIEW_CONTRACT、写前禁区、履约 diff;
  2. Phase 3 Chapter Commit ChainCHAPTER_COMMIT、accepted/rejected 语义、projection writers;
  3. Phase 4 Event Log + Override Ledger:canonical event log、contract_override/amend_proposal

总结

Story System Phase 1 的价值不在于一次性解决长篇 AI 写作的全部问题,而在于把「题材路由 → 合同聚合 → 持久化 → 运行时注入」这条链路以最小可验证的形态立起来:.story-system/是机器可读的合同真源,三层 merge 规则界定了章节对主设定的修改权限,story_contractsection 在上下文组装中优先于genre_profile注入,anti-pattern 全程带来源溯源。对希望把「创作约束工程化」引入自身网文辅助工具链的开发者而言,本文给出的路径约定、merge 语义、CLI 参数与 TDD 测试骨架,均可直接在 webnovel-writer 仓库中对照源码逐一验证,并作为后续 Contract-First Runtime 扩展的地基。

【免费下载链接】webnovel-writer基于 Claude Code 的长篇网文辅助创作系统,解决 AI 写作中的「遗忘」和「幻觉」问题,支持 200 万字量级 连载创作。项目地址: https://gitcode.com/GitHub_Trending/we/webnovel-writer

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 18:21:16

四大厂商光模块光功率查看命令与阈值解读

1. 光模块光功率查看&#xff1a;为什么这事儿值得花一整篇讲清楚&#xff1f;在机房巡检、割接前检查、故障排查甚至日常值班时&#xff0c;我最常被喊去干的一件事就是&#xff1a;“张工&#xff0c;快看看这个口光衰多少&#xff1f;”——不是看设备有没有亮&#xff0c;而…

作者头像 李华
网站建设 2026/9/16 18:17:26

ECharts词云图配置全解析:从核心参数到实战优化

简介&#xff1a;面向前端开发者的ECharts词云图实战资料包&#xff0c;围绕词云图从数据准备、图表初始化到常用配置项设定给出完整demo&#xff0c;并逐项讲解sizeRange、rotationRange、textRotation、textStyle等核心参数&#xff0c;帮助读者快速做出适配自身项目的词云效…

作者头像 李华
网站建设 2026/9/16 18:16:48

Python3 CSV数据处理全指南:从基础到高级技巧

1. Python3与CSV数据处理基础CSV&#xff08;Comma-Separated Values&#xff09;作为一种轻量级的数据交换格式&#xff0c;在数据分析和日常开发中扮演着重要角色。Python3通过内置的csv模块提供了完整的CSV处理能力&#xff0c;让我们能够高效地读写这种结构化数据。CSV文件…

作者头像 李华
网站建设 2026/9/16 18:16:34

Python零基础入门:语法精讲与开发环境配置

1. Python零基础入门&#xff1a;为什么选择这门语言&#xff1f;2008年我第一次接触Python时&#xff0c;就被它的简洁语法所震撼。当时还在用C写学生管理系统的我&#xff0c;发现用Python只需要1/3的代码量就能完成同样的功能。如今15年过去&#xff0c;Python已经成为全球最…

作者头像 李华