Webnovel Writer 6.2.1 项目分析
1. 项目是什么
Webnovel Writer 是一个跑在 Claude Code 上的长篇网文创作插件(Claude Code Plugin,经 Marketplace 安装)。它不是独立的写作 App,而是由 Claude Code 这个宿主驱动的一整套流程、规则与数据管线:
- 8 个 Skill 命令(
/webnovel-init、/webnovel-plan、/webnovel-write、/webnovel-review、/webnovel-query、/webnovel-learn、/webnovel-dashboard、/webnovel-doctor)充当用户入口; - 3 个专职 Subagent(context-agent / reviewer / data-agent)在写章流水线中被
Agent工具调用; - 一套 Python CLI(
scripts/webnovel.py统一入口)负责所有确定性逻辑:项目定位、合同生成、提交、投影、检索、备份、体检; - 一个只读 Web 面板(FastAPI + 预打包 React 前端)用于可视化查看项目状态。
它要解决的核心问题:让 AI 写到几十、几百章之后,依然"记得住设定、接得住伏笔、守得住大纲"。为此它把"写小说"从一次性生成,改造成合同(写前)→ 提交(写后)→ 投影(派生查询视图)的事件溯源式数据链。
一句话定位:一套面向长篇连载的一致性系统,不是写完就忘的一次性生成器。
2. 技术栈与运行形态
| 维度 | 说明 |
|---|---|
| 宿主 | Claude Code(通过 Plugin Marketplace 安装:claude plugin install webnovel-writer@...) |
| 语言 | Python 3.10+(全部确定性逻辑);前端 React + Vite(发布版自带 dist/ 构建产物,无需 npm build) |
| 数据存储 | JSON 文件(合同、commit、state)+ SQLite(index.db 事实索引、vectors.db 向量库)+ Markdown(大纲/正文/设定集/摘要) |
| 外部服务 | Embedding / Rerank API(OpenAI 兼容格式,默认 ModelScope 的 Qwen3-Embedding-8B + Jina Reranker),可不配(自动退化 BM25) |
| 运行时约束 | 所有 CLI 调用统一带 python -X utf8(Windows 编码兼容);sitecustomize.py 防 pytest 插件误载 |
| 版本要点 | v6.0 引入 Story System 全链路;v6.1 运行时加固(doctor/project-status/write-gate/投影重放/hooks);v6.2 面向作者的报告与断点续跑;v6.2.1 修复 Windows 写章提交偶发 WinError 5(文件被短暂占用时自动重试) |
3. 目录结构总览
webnovel-writer-6.2.1/
├── .claude-plugin/marketplace.json # 插件市场元数据(版本 6.2.1)
├── README.md / CHANGELOG.md / docs/ # 文档(architecture/guides/operations/memory 等)
├── sitecustomize.py # 防 pytest 全局插件误载(本机专用)
└── webnovel-writer/ # 插件本体
├── .claude-plugin/plugin.json # 插件声明
├── skills/ # 8 个 Skill(每个含 SKILL.md + references)
│ └── webnovel-write/... # 写章主流程(SKILL.md 385 行,最关键)
├── agents/ # Subagent 定义(context-agent / reviewer / data-agent / deconstruction-agent)
├── hooks/ # Claude Code 运行时钩子(SessionStart 状态提示 + PreToolUse 写入护栏)
├── scripts/ # Python 数据链(唯一事实逻辑层)
│ ├── webnovel.py # 统一 CLI 入口(薄壳,转发)
│ ├── project_locator.py # 项目根定位
│ ├── story_system.py # 合同种子生成 CLI
│ ├── chapter_commit.py # 章节提交 CLI
│ ├── init_project.py / backup_manager.py / archive_manager.py / update_state.py ...
│ └── data_modules/ # 核心业务模块(60+ 文件,~2 万行)
│ ├── webnovel.py # 真正的 CLI 分发器
│ ├── story_system_engine.py / story_contracts.py / runtime_contract_builder.py
│ ├── chapter_commit_service.py / event_projection_router.py
│ ├── *_projection_writer.py(state/index/summary/memory/vector 五路投影)
│ ├── state_manager.py / index_manager.py / rag_adapter.py / context_manager.py
│ ├── memory/ # 长期记忆子系统(store/orchestrator/writer/compactor...)
│ ├── write_gates/ # prewrite/precommit/postcommit 三道闸门
│ ├── project_phase.py / project_status.py / doctor.py / user_report.py / run_ledger.py
├── dashboard/ # 只读可视化面板(server.py + app.py ~30 个只读 API + frontend/dist)
└── references/ # 知识库:37 个题材模板、CSV 规则表(写作技法/爽点节奏/裁决规则...)、审查与润色参考
4. 核心设计理念:真源划分与事件溯源
这是理解整个项目运行逻辑的钥匙。系统把一本书的数据分成三层,写入方向单向、职责互斥:
4.1 三层真源
| 层 | 位置 | 角色 | 谁写 |
|---|---|---|---|
| 写前真源(合同) | .story-system/MASTER_SETTING.json(全书调性/禁忌)、anti_patterns.json、volumes/volume_NNN.json(卷级节奏)、chapters/chapter_NNN.json(章级焦点)、reviews/chapter_NNN.review.json(必查节点/禁区) |
动笔前必须遵守的"合同";缺失则写章阻断 | /webnovel-plan、story-system 命令(每次写章前刷新) |
| 写后真源(提交) | .story-system/commits/chapter_NNN.commit.json(accepted 为定稿事实)、events/chapter_NNN.events.json(事件审计) |
一章写完后"发生了什么"的不可篡改记录 | 仅 chapter-commit 命令(由 /webnovel-write Step 5 驱动) |
| 投影层(read-model) | .webnovel/state.json、index.db、summaries/chNNNN.md、memory_scratchpad.json、vectors.db |
从 commit 派生的查询视图(角色卡、章节索引、摘要、长期记忆、向量) | 仅五路 ProjectionWriter,从 commit 重放生成 |
关键含义:
- state.json 不再是事实来源(v6 之前是),只是投影。任何查询优先读
.story-system/合同与最新 accepted commit。 - 投影是可重放的:
projections replay可以从既有 commit 重新生成全部派生视图,这是修复数据错乱的主要手段。 - 投影执行日志
.webnovel/projection_log.jsonl记录每路投影结果,用来定位"哪一路没同步"。
4.2 防幻觉三定律(写章流程的强制约束)
- 大纲即法律 —— context-agent 强制加载章纲,不擅自发挥;
- 设定即物理 —— reviewer 做一致性审查(能力 ≤ 已有记录);
- 发明需识别 —— data-agent 把新实体/新事实提取入库,不得留在正文里就完事。
4.3 Strand Weave 节奏系统
主线 Quest(~60%)/ 感情线 Fire(~20%)/ 世界观 Constellation(~20%),配合红线(Quest 连超 5 章、Fire 断 10 章、Constellation 断 15 章触发告警)和"追读力"系统(钩子/爽点/微兑现/债务追踪,存于 index.db)。
5. 执行逻辑详解(运行全景)
5.1 总览:数据是怎么流动的
作者(Claude Code 会话)
│ 输入 /webnovel-xxx 命令
▼
Skill(SKILL.md 定义流程)──调用──▶ Subagent(context-agent / reviewer / data-agent)
│ │
│ 调用 Bash 执行确定性逻辑 │ 只读/只写 tmp artifact
▼ ▼
scripts/webnovel.py(统一 CLI)◀── .webnovel/tmp/ 四份 artifact
│ 解析 project_root → 分发给各子模块
▼
合同层(.story-system/) ──▶ CHAPTER_COMMIT ──▶ 五路投影 ──▶ .webnovel/ 派生视图 ──▶ Dashboard(只读)
5.2 运行前提:插件如何被加载
- 用户通过 Marketplace 安装插件后,Claude Code 启动时会加载
webnovel-writer/下的 skills / agents / hooks; - 每个 Skill 的命令里都依赖环境变量
CLAUDE_PLUGIN_ROOT(Claude Code 自动注入,指向插件安装目录),脚本目录统一为${CLAUDE_PLUGIN_ROOT}/scripts; CLAUDE_PROJECT_DIR是当前工作区提示,作为项目根定位的输入之一。- 常见故障根源一:插件未正确安装 →
CLAUDE_PLUGIN_ROOT为空 → 所有 Skill 第一步的环境校验报错。
5.3 项目根定位(project_locator.py)
所有命令第一步都是解析"书项目根目录"——以包含 .webnovel/state.json 的目录为准。解析顺序(resolve_project_root(),scripts/project_locator.py:349):
- 显式
--project-root参数; - 环境变量
WEBNOVEL_PROJECT_ROOT; - 工作区指针文件
.claude/.webnovel-current-project(从 CWD 向上找,到 git 仓库根为止); - 用户级注册表
~/.claude/webnovel-writer/workspaces.json(workspace → 项目根映射;仅在CLAUDE_PROJECT_DIR存在等"有上下文提示"时才允许 last_used 兜底,防误命中); - 从 CWD 逐级向上扫描
.webnovel/state.json(含约定子目录webnovel-project/)。
写指针/注册表的命令是
webnovel.py use <project_root>(cmd_use)。多书项目切换后"找不到项目"类问题,先查这两处指针。
5.4 统一 CLI 入口与命令分发(scripts/webnovel.py → data_modules/webnovel.py)
所有 Python 能力收敛为一个入口,避免 agent 拼命令出错:
python -X utf8 "<CLAUDE_PLUGIN_ROOT>/scripts/webnovel.py" --project-root "<ROOT>" <子命令> [参数]
分发方式(data_modules/webnovel.py 的 main()):
- 自实现命令(
func分发):where/preflight/project-status/doctor/write-gate/projections/user-report/run-ledger/run-log/use/knowledge; - importlib 直调(
_run_data_module):index/state/rag/style/entity/context/memory/migrate—— 统一前置注入--project-root再转发; - 子进程脚本(
_run_script):status/update-state/backup/archive/init/extract-context/story-system/story-events/chapter-commit/memory-contract/project-memory/review-pipeline/master-outline-sync。
设计要点:--project-root 可出现在任意位置(normalize_global_project_root 预处理);init 是例外——它创建项目,不依赖已存在的 project_root。
5.5 项目生命周期阶段机(project_phase.py)
doctor / project-status / write-gate 都是阶段感知的:先扫描项目文件状态推断当前处于哪个阶段,再按阶段给出校验项与"下一步"建议:
no_project → init_scaffolded → init_ready → plan_in_progress
→ chapter_contract_ready → draft_in_progress → ready_to_commit
→ chapter_committed(→ 下一章循环) / projection_failed(需修复)
阶段判定依据:.webnovel/state.json 是否存在与内容、.story-system/commits/ 扫描、正文/ 最新章节、tmp/ artifact 是否齐备(_scan_commits、_latest_draft_chapter 等)。"为什么 doctor 说我现在该做 X"——答案在阶段机里。
5.6 初始化流程(/webnovel-init)
- Skill 用
AskUserQuestion分波次采集(题材、卖点、角色、世界观、力量体系……),可选调用deconstruction-agent拆解参考书; - 过充分性闸门后调用
webnovel.py init(init_project.py,789 行)创建骨架:.webnovel/state.json(含题材/进度/主角快照)、设定集/*(世界观/力量体系/主角卡/反派设计)、大纲/总纲.md、.env.example、.story-system/MASTER_SETTING.json合同种子; - 产出目录即为"书项目根"。
5.7 规划流程(/webnovel-plan)
- 增量细化(不重写总纲):先锁卷级节奏 → 批量拆章 → 时间线硬约束(每章纲带时间字段)→ 新增设定写回设定集;
- 输出
大纲/第N卷-详细大纲.md、第N卷-时间线.md,并调用master-outline-sync写回 V+1 总纲锚点; - 前后各跑一次
placeholder-scan(扫描{章纲目标}、[待...]、暂名等未补齐占位)。
5.8 写章流水线(/webnovel-write)—— 本项目的心脏
skills/webnovel-write/SKILL.md 定义了完整流水线,主流程由 Claude Code 的模型执行、Python CLI 保证确定性关卡。按顺序、禁跳步、失败只补跑失败步骤(不回退)。
准备(预检) ─▶ 准备(刷新合同树) ─▶ Step1 context-agent ─▶ Step2 起草 ─▶ Step3 reviewer
─▶ Step4 润色 ─▶ Step5 data-agent + commit ─▶ Step6 备份
(write-gate 在 3 个自然边界设卡:prewrite / precommit / postcommit)
准备阶段
preflight(校验插件路径、project_root、story_runtime 主链健康)+where(解析项目根)+placeholder-scan(扫占位符);- 刷新合同树:从
state.json初始化快照读题材 →story-system "<本章真实目标>" --genre <题材> --chapter N --persist --emit-runtime-contracts:StorySystemEngine(story_system_engine.py)按关键词/别名在references/csv/题材与调性推理.csv中路由题材行(英文 profile key 会被拒绝——题材必须中文),检索基础表(top1)+ 动态表(top2),加载该题材 reasoning 裁决层,生成 MASTER_SETTING / chapter_brief / anti_patterns;RuntimeContractBuilder从章纲解析chapter_directive(目标/时间锚/章跨度/倒计时/章尾悬念)并生成卷级合同volume_NNN.json与审查合同chapter_NNN.review.json;- 注意:query 传占位符(如
{章纲目标})会被is_placeholder_query检测并警告——必须先从详细大纲解析真实本章目标;
write-gate prewrite:校验合同树齐全(缺 MASTER/volume/chapter/review 四件即阻断)。
Step 1:context-agent 生成写作任务书
- 必须用
Agent工具调用webnovel-writer:context-agent(禁止主流程口头替代); - 其内部:
memory-contract load-context --chapter N一次性取基础包(合同、近期摘要、紧急伏笔、活跃规则、主角快照、记忆包、题材画像摘录)→ 按需深查(实体/规则/时间线)→ 输出五段写作任务书(开篇委托 / 这章的故事 / 这章的人物 / 怎么写更顺 / 收在哪里); - 任务书排序固定:本章硬性约束 → CBN/CPNs/CEN 与必盖节点 → 禁区 → 风格指引 → 动态上下文(仅参考,不得覆盖章纲);
- 上下文严重不足时返回 blocker(不硬编)。
Step 2:起草正文
只依据任务书,写纯正文到 正文/第{NNNN}章-{title}.md,无占位符,默认 2000–2500 字。
Step 3:审查(reviewer + review-pipeline)
- 必须用
Agent工具调用reviewer(只返回 JSON,不写文件):5 个维度逐一检查——setting / timeline / continuity / character / logic,每个维度强制输出 pass 或问题清单(dimension_results),问题必须带 evidence; - 主流程把 JSON 写入
.webnovel/tmp/review_results.json,然后跑review-pipeline --save-metrics:复核计数一致性、生成审查报告/第N章审查报告.md、指标落index.db,并把标准 artifact 覆盖写回同路径; - blocking issue 定点修复后直接进 Step 4(审查只跑一轮);修不了的 blocking 用
AskUserQuestion请用户裁决; --fast只查 setting/timeline/continuity;--minimal跳过 reviewer,但必须覆盖写入 no-review artifact(保证提交链有合法输入)。
Step 4:润色
修复非 blocking issue → 风格适配 → 排版 → Anti-AI 终检(anti_ai_force_check=fail 则不进 Step 5)。只改表达不改事实。reference 区段按需读(Grep 锚点 + Read offset/limit),不全量读。
Step 5:提交(data-agent + CHAPTER_COMMIT + 五路投影)
- data-agent(Agent 工具调用):从正文提取事实,产出三份 artifact 到
.webnovel/tmp/:fulfillment_result.json:planned_nodes / covered_nodes / missed_nodes / extra_nodes(章纲完成度);disambiguation_result.json:pending数组(低置信歧义待人工);extraction_result.json:accepted_events(10 种事件类型:character_state_changed、power_breakthrough、relationship_changed、world_rule_revealed/broken、open_loop_created/closed、promise_created/paid_off、artifact_obtained)+state_deltas(entity_id/field/old/new)+entity_deltas+entities_appeared+scenes+summary_text(100–150 字摘要);- data-agent 只写这三份 tmp artifact,不直接碰任何投影;
write-gate precommit:校验三份 artifact + review_results 存在且 schema 合格;随后跑只读git diff变更面校验(不允许出现插件目录/其他书/其他章节);chapter-commit(chapter_commit.py→ChapterCommitService):- Pydantic 校验四份 artifact;
- 自动判定:
blocking_count>0或missed_nodes非空 或pending非空 → rejected,否则 accepted; - 落盘
.story-system/commits/chapter_NNN.commit.json(含 contract_refs、provenance、outline_snapshot、review/fulfillment/disambiguation/extraction 全量、projection_status); - accepted 时:事件经
EventLogStore.normalize_events规范化后写入events/chapter_NNN.events.json,并检查是否需要生成 amend 提案(override ledger);
- 五路投影(
apply_projection_writers):EventProjectionRouter按事件类型决定哪些投影器必跑(路由表见 4.1),每路结果写入 commit 的projection_status(done / skipped / failed:<原因>),并把执行记录追加到projection_log.jsonl:state:state_deltas →state.json角色快照(锁定字段保护);index:scenes/出场/状态变更 →index.db(章节/场景/实体/关系/别名/追读力等表);summary:summary_text →summaries/chNNNN.md;memory:可跨章复用的事实 →memory_scratchpad.json长期记忆;vector:场景切片 →vectors.db向量化(无 API Key 时 BM25 索引);
write-gate postcommit:确认 projection_status 五项全部 done/skipped、chapter_status 由投影器推进为 committed。
Step 6:Git 备份
backup --chapter N --chapter-title "<标题>"(backup_manager.py):以解析后的 PROJECT_ROOT 为准做章节级 git 备份,支持 rollback / diff / branch / list。禁止从工作区父目录裸 git add(防止把书项目当子模块加错)。
断点续跑与作者友好报告
- 每个关键步骤写
run-ledger record-write-step;重跑同一章先run-ledger write-resume给续跑建议(正文被手改过/已 accepted 时停下询问,不覆盖作者手改); - 过程提示只说"在做什么",技术细节写
.webnovel/logs/run_last.log(run-log命令,脱敏); - 收尾调用
user-report --stage write生成固定三段式报告,总状态四级:已完成 / 部分完成 / 需要你处理 / 未完成(data_modules/user_report.py根据文件与 commit/projection/备份证据判定;chapter-commit rejected、write-gate failed、projection failed 时不得写"已完成")。
5.9 审查命令(/webnovel-review)
对章节范围批量审查(爽点/一致性/节奏/OOC/连贯性/追读力维度),调用 review-pipeline + quality_trend_report.py(趋势统计),同样产出作者友好报告。
5.10 查询命令(/webnovel-query)与知识查询
- 按"查询类型 → 最窄工具"路由:角色历史状态 →
knowledge query-entity-state --at-chapter N;关系 →knowledge query-relationships(KnowledgeQuery支持"实体在第 N 章时的状态/关系"时序查询);规则 →memory-contract query-rules;伏笔 →memory-contract get-open-loops;综合 →memory-contract load-context;静态设定 → Grep/Read 设定集; - 查询真源优先级:写前合同 → 写后 commit → 投影层(state/index 仅 fallback)。
5.11 长期记忆与项目记忆
- 长期记忆(
memory_scratchpad.json,data_modules/memory/包):写前由 orchestrator 组装"记忆包"注入任务书(按紧急度/相关度过滤 + 预算裁剪),写后由 memory 投影沉淀;compactor 负责压缩; - 项目记忆(
.webnovel/project_memory.json):/webnovel-learn把用户认可的好写法(钩子/节奏/对话/微兑现……)归类写入,供后续写章注入; - 运维命令
memory(导出/回填)。
5.12 RAG 检索链路(rag_adapter.py)
vectors.db:场景切片 embedding(OpenAI 兼容接口);bm25_index表:关键词倒排索引(_update_bm25_index,写向量时同步维护);- 检索模式:
hybrid(向量 + BM25 融合)→graph_hybrid(hybrid 基础召回 + 关系子图扩展实体 + 图先验加权)→ 无 Embedding Key 或 401 认证失败时自动退化纯 BM25(degraded_mode_reason会标记embedding_auth_failed,doctor 可查); - Rerank 用 jina-reranker-v3 重排;查询日志落
rag.db; - 配置来自书项目根的
.env(config.py的_load_project_dotenv)。
5.13 可视化面板(/webnovel-dashboard)
dashboard/server.py:uvicorn 启动 FastAPI(默认127.0.0.1:8765),自动开浏览器;项目根解析顺序:CLI >WEBNOVEL_PROJECT_ROOT>.claude指针 > CWD;app.py暴露约 30 个只读 API(/api/entities、/api/relationships、/api/chapters、/api/reading-power、/api/story-runtime/health、/api/commits、/api/files/tree……),path_guard.py把文件访问限制在 PROJECT_ROOT 内;- 前端为预打包
dist/(缺失说明插件安装不完整);watcher.py监听.webnovel/变化实时刷新; - 依赖单独在
dashboard/requirements.txt,失败时提示手动安装。
5.14 Hooks:运行时护栏(hooks/hooks.json)
- SessionStart →
session_start.py:打印项目短状态(最多 8 行/1000 字符,4 秒超时,失败静默),可用WEBNOVEL_DISABLE_SESSION_STATUS_HOOK关闭; - PreToolUse(Write/Edit/Bash) →
guard_runtime_write.py:拦截对受保护文件的直接写:- 保护对象:
.story-system/commits/、.webnovel/index.db、vectors.db、memory_scratchpad.json、projection_log.jsonl(state.json 刻意不保护——有独立备份/重建路径); - 白名单:命令中含
webnovel.py且为chapter-commit/projections retry|replay; - 可被
WEBNOVEL_DISABLE_RUNTIME_GUARD_HOOK关闭。
- 保护对象:
- 含义:"我想直接改 index.db 却被拒绝"是护栏在起作用,正确路径是走 commit / projections 命令或修 tmp artifact 后重新提交。
6. 故障排查指南:从症状推断错误方向
排查总原则(README 也强调):先 preflight 后 doctor,然后按"症状 → 所在流水线环节 → 对应命令/文件"定位。所有 CLI 都是只读查询(除 commit/backup/init),可放心反复跑。
6.0 黄金三命令(任何问题先跑)
python -X utf8 "<CLAUDE_PLUGIN_ROOT>/scripts/webnovel.py" --project-root "<PROJECT_ROOT>" preflight
python -X utf8 "<CLAUDE_PLUGIN_ROOT>/scripts/webnovel.py" --project-root "<PROJECT_ROOT>" project-status --format json
python -X utf8 "<CLAUDE_PLUGIN_ROOT>/scripts/webnovel.py" --project-root "<PROJECT_ROOT>" doctor --format text
重点看:story_runtime.mainline_ready 是否为 true、当前 phase 与"下一步"、projection_status 是否全 done/skipped、index.db/summaries//memory_scratchpad.json 是否正常。
6.1 环境与安装类
| 症状 | 推断方向 | 排查 |
|---|---|---|
Skill 一运行就报 CLAUDE_PLUGIN_ROOT 未设置/目录不存在 |
插件未安装或未启用 | claude plugin list 确认安装;检查插件目录下是否有 scripts/ |
所有 python 命令报编码乱码/UnicodeEncodeError |
Windows 终端编码问题 | 确认命令带 -X utf8;runtime_compat.py 的 enable_windows_utf8_stdio 是统一处理点 |
| 报缺 Python 模块(ModuleNotFoundError: data_modules/...) | 依赖未装或脚本路径不在 sys.path | pip install -r requirements.txt 与 scripts/requirements.txt;确认从 scripts/webnovel.py 入口调用(它会插入 sys.path) |
| pytest 环境怪异 | 全局 pytest 插件冲突 | sitecustomize.py 已设 PYTEST_DISABLE_PLUGIN_AUTOLOAD,检查是否被覆盖 |
6.2 项目根定位类(高频)
| 症状 | 推断方向 | 排查 |
|---|---|---|
FileNotFoundError: ... missing .webnovel/state.json |
定位失败:指针/注册表/目录布局问题 | webnovel.py where 看解析结果;检查 .claude/.webnovel-current-project 指针、~/.claude/webnovel-writer/workspaces.json;多书工作区用 webnovel.py use <root> 重新绑定 |
| 命令作用到了错误的书 | 指针/注册表指向旧项目 | 同上,重跑 use;注意 allow_last_used_fallback 仅在 CLAUDE_PROJECT_DIR 存在时启用 |
| 在书项目外新开会话找不到项目 | "空上下文"定位失败 | 用 --project-root 显式传入或先 use 绑定 |
6.3 合同树类(写前阻断)
| 症状 | 推断方向 | 排查 |
|---|---|---|
write-gate prewrite 失败,报 MASTER_SETTING/volume/chapter/review 缺失 |
合同树没刷新或 plan 未完成 | 重跑 story-system(注意 query 必须传真实本章目标,占位符会告警);/webnovel-plan N 先规划该卷 |
| story-system 报"题材参数必须使用中文名称" | 传了英文 genre key | 改传中文题材名 |
| story-system 路由失败(StorySystemRoutingError) | 关键词没匹配上题材表 | 检查 references/csv/题材与调性推理.csv 的关键词/别名列,换描述词 |
| 章纲目标没生效、写作偏题 | chapter_focus 从 dynamic_context 继承而非 chapter_directive |
检查 chapters/chapter_NNN.json 的 chapter_directive.goal;章纲文件是否含结构化节点 |
6.4 审查与 artifact 类(Step 3/5)
| 症状 | 推断方向 | 排查 |
|---|---|---|
reviewer 输出缺 dimension_results 或计数不一致 |
reviewer 输出不合格(被 review-pipeline 复核拦截) | 重跑 Step 3;review-pipeline 会覆盖写回标准 artifact |
| blocking issue 一直过不去 | 真的事实矛盾,或 reviewer 误判 | 定点修复后直接进 Step 4(不重跑 reviewer);修不了走用户裁决;references/review/blocking-override-guidelines.md |
| precommit gate 报 artifact 缺失/schema 不合格 | data-agent 没写完或字段名不合法 | 检查 .webnovel/tmp/ 三份 JSON;schema 唯一真源是 agents/data-agent.md §7;artifact_validator.py 的校验规则 |
出现 pending 消歧导致 commit rejected |
新实体/别名低置信 | 看 disambiguation_result.json 的 pending 项,人工确认后让 data-agent 补写,重新 commit |
6.5 Commit 类(Step 5.2/5.3)
| 症状 | 推断方向 | 排查 |
|---|---|---|
| commit 是 rejected | blocking_count>0 / missed_nodes 非空 / pending 非空 三者之一 | 读 commits/chapter_NNN.commit.json 的对应字段,逐项修复后重跑 chapter-commit(tmp artifact 还在即可) |
| commit 文件根本没生成 | precommit gate 没过,或 hook 拦截了命令 | 先跑 precommit gate 看错误;确认命令走的是 webnovel.py chapter-commit(白名单外写法会被 guard hook deny) |
| WinError 5 / PermissionError 写文件失败 | Windows 文件被占用(v6.2.1 已加自动重试) | 关闭占用进程(杀毒/编辑器/搜索索引);升级到 6.2.1+ |
6.6 投影类(最需要理解的一类)
| 症状 | 推断方向 | 排查 |
|---|---|---|
projection_status 某项是 failed:<原因> |
该路投影器抛异常 | 读 .webnovel/projection_log.jsonl 对应章节记录;projections retry --chapter N 补跑单章 |
| state/index/summary/memory/vector 某一层数据和正文对不上 | 对应投影没跑或历史失败 | 同上;严重时 projections replay --from-chapter A --to-chapter B 从 commit 全量重放(幂等) |
projection_status 显示 skipped |
该路对本章不是必跑(路由表决定) | 正常现象,非故障;用 story-events --health 看事件链健康 |
| postcommit gate 失败 | 投影未完成或 chapter_status 未推进 | 重跑 projections retry;检查 commit 的 meta.status |
| 直接改 state.json 后行为怪异 | state 只是投影,改了会被下次投影覆盖 | 正确做法:改源头(大纲/合同/commit 事件),再重放投影;update_state.py 提供结构化安全更新(自动备份+原子写) |
投影路由表速记(event_projection_router.py):角色状态变化/突破 → state+memory+vector;关系变化/获得物品 → index+vector;世界规则揭示/打破 → memory+vector;伏笔/承诺类 → memory;rejected commit → 仅 state。
6.7 RAG 类
| 症状 | 推断方向 | 排查 |
|---|---|---|
| 检索结果变差/语义召回失效 | 退化到了 BM25(无 key 或 401) | doctor 的 RAG 检查;rag stats;查 .env 的 EMBED_API_KEY/RERANK_API_KEY;看 degraded_mode_reason |
| vectors.db 表结构报错 | 旧库 schema 需迁移 | 启动时自动迁移(带备份到 backups/vectors.db.schema_migration.*.bak);失败会尝试恢复 |
| 检索慢/无结果 | 向量没建或索引空 | rag index-chapter --chapter N 重建;rag stats 看 chunk 数 |
6.8 Dashboard 类
| 症状 | 推断方向 | 排查 |
|---|---|---|
| 启动报缺模块 | dashboard 依赖没装 | pip install -r dashboard/requirements.txt |
报缺 frontend/dist/index.html |
插件安装不完整(dist 应随插件打包) | 重新安装插件;开发态才需要 npm run build |
| 端口占用 | 8765 被占 | --port 9000 |
| 页面空白/数据缺失 | 数据文件缺失或 PROJECT_ROOT 解析错 | 确认 .webnovel/state.json、index.db 存在;server.py 的解析顺序与 project_locator 一致 |
| 想改数据没有入口 | Dashboard 设计上就是只读 | 改数据走 skill/CLI,不要想从面板改 |
6.9 备份类
| 症状 | 推断方向 | 排查 |
|---|---|---|
| backup 报错或把整个父仓库提交了 | 项目根解析错(未以 PROJECT_ROOT 为准) | 确认 where 输出;backup --list 看历史;回滚用 --rollback N |
| 书目录被当成 submodule/嵌入仓库 | 曾从父目录执行过 git add | 检查 .gitmodules 与父仓库 index,按 git 文档移除 |
6.10 Hook 护栏类
| 症状 | 推断方向 | 排查 |
|---|---|---|
| Write/Edit 被 deny:"blocked a direct edit to Story System/read-model files" | 你在直接改保护文件 | 走正规路径:commit / projections / 先改 tmp artifact 再提交 |
| Bash 命令被 deny:"blocked a direct write or bypass command" | 命令绕过了 webnovel.py 白名单 |
改用 webnovel.py chapter-commit / projections retry 等 |
| 会话开头总打印项目状态 | SessionStart hook | 不需要时设 WEBNOVEL_DISABLE_SESSION_STATUS_HOOK=1;同理 guard 可用 WEBNOVEL_DISABLE_RUNTIME_GUARD_HOOK 关闭(不建议长期关) |
6.11 断点续跑类
| 症状 | 推断方向 | 排查 |
|---|---|---|
| 重跑同一章被要求"停下询问" | run-ledger 检测到正文手改/已 accepted/章纲晚于正文 | 按提示三选一(沿用/重草/只查状态),不要覆盖作者手改 |
| 想知道上次失败在哪一步 | run-ledger 记录 | run-ledger write-resume --chapter N;.webnovel/logs/run_last.log |
| 最终报告状态与实际不符 | user_report 判定逻辑 | 报告基于文件证据(commit 状态、projection_status、备份证据)自动判定,检查对应证据文件 |
7. 关键文件速查表
| 想了解/修改 | 文件 |
|---|---|
| 写章流程定义(步序/闸门/报告契约) | webnovel-writer/skills/webnovel-write/SKILL.md |
| 其他命令流程 | skills/<skill-name>/SKILL.md |
| 三个 subagent 的职责与输出 schema | agents/context-agent.md、reviewer.md、data-agent.md(data-agent §7 是 artifact schema 唯一真源) |
| CLI 全部子命令注册 | scripts/data_modules/webnovel.py |
| 项目根定位 | scripts/project_locator.py |
| 阶段机 | scripts/data_modules/project_phase.py |
| 三道写章闸门 | scripts/data_modules/write_gates/{prewrite,precommit,postcommit}.py |
| 合同生成引擎(题材路由) | scripts/data_modules/story_system_engine.py + references/csv/题材与调性推理.csv |
| 合同落盘与合并规则 | scripts/data_modules/story_contracts.py |
| 提交与投影编排 | scripts/data_modules/chapter_commit_service.py、event_projection_router.py、*_projection_writer.py |
| 投影日志/重放 | scripts/data_modules/projection_log.py、projections.py |
| 事实索引(index.db) | scripts/data_modules/index_manager.py(+ 各 mixin) |
| 角色状态(state.json) | scripts/data_modules/state_manager.py |
| 检索(vectors.db/BM25/图混合) | scripts/data_modules/rag_adapter.py |
| 长期记忆 | scripts/data_modules/memory/、scripts/memory_cli.py |
| 项目体检 | scripts/data_modules/doctor.py |
| 作者友好报告 | scripts/data_modules/user_report.py |
| 断点续跑 | scripts/data_modules/run_ledger.py、run_logger.py |
| 备份 | scripts/backup_manager.py、archive_manager.py |
| Dashboard | dashboard/server.py、app.py、watcher.py、path_guard.py |
| 运行时护栏 | hooks/hooks.json、hooks/guard_runtime_write.py、hooks/session_start.py |
| 设计文档 | docs/architecture/overview.md(真源划分/三定律/节奏)、docs/guides/commands.md(命令详解)、docs/operations/operations.md(运维) |
8. 结语:心智模型一句话版
这本书的"大脑"是 .story-system/(合同+提交),.webnovel/ 只是它的"体检报告";写一章 = 签合同(story-system)→ 干活(三个 agent)→ 过闸(write-gate)→ 交账(chapter-commit)→ 记账(五路投影)→ 存档(backup)。
排查问题时先问三个问题:项目根定位对了吗?(where/preflight)主链健康吗?(mainline_ready)账目平了吗?(projection_status 五项 + projection_log.jsonl)——90% 的故障都能沿这条链找到方向。

浙公网安备 33010602011771号