Selaa lähdekoodia

feat(v5.2): 升级写作系统,从"写得对"到"写得让人追"

核心改进:
- 创作任务书:Context Agent 输出人话版8章节格式(替代JSON)
- 追读力检查:新增 reader-pull-checker(第6个审查Agent)
- 章节设计:Step 1.5 选择开头/钩子/爽点模式,避免重复
- 风格适配器:Step 2A/2B 拆分,先写剧情后网文化
- 摘要分离:章节摘要存入 .webnovel/summaries/ch{NNNN}.md
- chapter_meta:记录钩子/模式/结束状态到 state.json
- 轻量模式:支持 --mode fast/minimal 加速写作
- 输出模板:7个标准模板文件(state/index schema、设定集、大纲)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
lingfengQAQ 4 kuukautta sitten
vanhempi
sitoutus
05468d29ea
30 muutettua tiedostoa jossa 1250 lisäystä ja 1096 poistoa
  1. 78 298
      .claude/agents/context-agent.md
  2. 73 276
      .claude/agents/data-agent.md
  3. 95 0
      .claude/agents/reader-pull-checker.md
  4. 78 10
      .claude/scripts/context_pack_builder.py
  5. 1 1
      .claude/scripts/data_modules/config.py
  6. 20 0
      .claude/scripts/data_modules/state_manager.py
  7. 22 6
      .claude/scripts/extract_chapter_context.py
  8. 73 18
      .claude/scripts/init_project.py
  9. 12 14
      .claude/scripts/token_budget_report.md
  10. 14 12
      .claude/scripts/workflow_manager.py
  11. 56 30
      .claude/skills/webnovel-init/SKILL.md
  12. 5 2
      .claude/skills/webnovel-plan/SKILL.md
  13. 23 17
      .claude/skills/webnovel-query/references/system-data-flow.md
  14. 11 9
      .claude/skills/webnovel-resume/references/workflow-resume.md
  15. 7 5
      .claude/skills/webnovel-review/SKILL.md
  16. 20 8
      .claude/skills/webnovel-review/references/core-constraints.md
  17. 135 141
      .claude/skills/webnovel-write/SKILL.md
  18. 15 2
      .claude/skills/webnovel-write/references/core-constraints.md
  19. 49 195
      .claude/skills/webnovel-write/references/polish-guide.md
  20. 40 0
      .claude/skills/webnovel-write/references/style-adapter.md
  21. 35 0
      .claude/skills/webnovel-write/references/style-variants.md
  22. 65 0
      .claude/templates/golden-finger-templates.md
  23. 67 0
      .claude/templates/output/index-schema.md
  24. 49 0
      .claude/templates/output/state-schema.md
  25. 35 0
      .claude/templates/output/大纲-总纲.md
  26. 27 0
      .claude/templates/output/设定集-世界观.md
  27. 37 0
      .claude/templates/output/设定集-主角卡.md
  28. 22 0
      .claude/templates/output/设定集-力量体系.md
  29. 22 0
      .claude/templates/output/设定集-金手指.md
  30. 64 52
      README.md

+ 78 - 298
.claude/agents/context-agent.md

@@ -1,20 +1,14 @@
 ---
 name: context-agent
-description: 智能上下文搜集Agent (v5.1),为章节写作准备完整的上下文包。在写作前自动调用,负责读取大纲、状态、索引、RAG检索、设定集,并智能筛选组装上下文。支持 SQL 按需查询优化
+description: 上下文搜集Agent (v5.2),输出创作任务书(人话版)而非 JSON,补齐钩子/模式/动机等关键写作信息
 tools: Read, Grep, Bash
 ---
 
-# context-agent (上下文搜集Agent v5.1)
+# context-agent (上下文搜集Agent v5.2)
 
-> **Role**: 智能上下文工程师,负责为章节写作准备精准、完整的上下文信息包
+> **Role**: 创作任务书生成器。目标不是堆信息,而是给写作“能直接开写”的明确指令
 >
-> **Philosophy**: 按需召回,智能筛选 - 不是堆砌信息,而是提供写作真正需要的上下文。
-
-**v5.1 变更**:
-- 使用 SQL 按需查询替代全量读取 state.json
-- 核心实体(主角 + tier=核心/重要)全量加载
-- 其他实体按需从 index.db 查询
-- 减少 token 消耗,提升响应速度
+> **Philosophy**: 按需召回 + 推断补全,保证“接住上章、带出情绪、留出钩子”。
 
 ## 输入
 
@@ -27,324 +21,110 @@ tools: Read, Grep, Bash
 }
 ```
 
-**重要**: 所有数据读取自 `{project_root}/.webnovel/` 目录:
-- state.json → `{project_root}/.webnovel/state.json` (精简版,只含进度和配置)
-- index.db → `{project_root}/.webnovel/index.db` (实体、别名、关系、状态变化)
-- vectors.db → `{project_root}/.webnovel/vectors.db` (RAG 向量)
+## 输出格式:创作任务书(人话版)
 
-## 输出
+必须按以下 8 个章节输出:
 
-```json
-{
-  "core": {
-    "chapter_outline": "本章大纲内容",
-    "volume_outline": "本卷大纲摘要",
-    "protagonist_snapshot": {
-      "name": "萧炎",
-      "realm": "斗师",
-      "location": "天云宗",
-      "recent_events": ["突破斗师", "获得青莲地心火线索"]
-    },
-    "recent_summaries": [
-      {"chapter": 99, "summary": "..."},
-      {"chapter": 98, "summary": "..."}
-    ]
-  },
-  "scene": {
-    "location_context": {
-      "name": "天云宗",
-      "description": "...",
-      "related_chapters": [45, 67, 89]
-    },
-    "appearing_characters": [
-      {"id": "yaolao", "name": "药老", "last_state": "..."},
-      {"id": "lintian", "name": "林天", "last_state": "..."}
-    ],
-    "urgent_foreshadowing": [
-      {"id": "F001", "content": "三年之约", "urgency": "high", "planted_chapter": 1}
-    ],
-    "foreshadow_suggestions": [
-      {"id": "F002", "content": "青莲地心火", "suggestion": "可在本章埋下伏笔"}
-    ]
-  },
-  "global": {
-    "worldview_skeleton": "修炼体系简述...",
-    "power_system_skeleton": "斗气等级: 斗者→斗师→...",
-    "style_samples": [
-      {"type": "combat", "sample": "高质量战斗描写片段..."},
-      {"type": "dialogue", "sample": "高质量对话片段..."}
-    ]
-  },
-  "rag": {
-    "related_scenes": [
-      {"chapter": 45, "scene": 2, "summary": "相关场景摘要", "relevance": 0.85}
-    ]
-  },
-  "alerts": {
-    "disambiguation_warnings": [
-      {"chapter": 99, "mention": "宗主", "chosen_id": "lintian", "confidence": 0.63, "note": "中置信度匹配"}
-    ],
-    "disambiguation_pending": [
-      {"chapter": 99, "mention": "那位前辈", "suggested_id": "yaolao", "confidence": 0.42}
-    ]
-  }
-}
-```
+1. **本章核心任务**(冲突一句话、必须完成、绝对不能)
+2. **接住上章**(上章钩子、读者期待、开头必须)
+3. **出场角色**(状态、动机、情绪底色、说话风格、红线)
+4. **场景与力量约束**(地点、可用能力、禁用能力)
+5. **风格指导**(本章类型、参考样本、最近模式、本章建议)
+6. **伏笔管理**(必须处理、可选提及)
+7. **连贯性检查点**(时间、位置、情绪)
+8. **章末钩子设置**(建议类型、禁止事项)
 
-## 执行流程
+---
 
-### Step 1: 分析本章需求
+## 读取优先级与默认值
 
-**读取大纲** (使用 Read 工具):
-- 本章大纲: `大纲/卷N/第XXX章.md`
-- 本卷概述: `大纲/卷N/卷概述.md`
+| 字段 | 读取来源 | 缺失时默认值 |
+|------|---------|-------------|
+| 上章钩子 | `state.json → chapter_meta[NNNN].hook` | `{type: "无", content: "上章无明确钩子", strength: "weak"}` |
+| 最近3章模式 | `state.json → chapter_meta[NNNN..NNNN].pattern` | 空数组,不做重复检查 |
+| 上章结束情绪 | `state.json → chapter_meta[NNNN].ending.emotion` | "未知",提示写作时自行判断 |
+| 角色动机 | 从大纲+角色状态推断 | **必须推断,无默认值** |
 
-**分析要点**:
-- 本章主要事件是什么?
-- 需要哪些角色出场?
-- 发生在什么地点?
-- 是否涉及战斗/突破/重要对话?
+**缺失处理**:
+- 若 `chapter_meta` 不存在(如第1章),跳过“接住上章”部分
+- 最近3章数据不完整时,只用现有数据做重复检查
 
-### Step 2: 获取主角状态 (v5.1 SQL 查询)
+**章节编号规则**: 4位数字,如 `0001`, `0099`, `0100`
 
-**v5.1 优化**: 使用 SQL 查询替代全量读取 state.json
+---
 
-```bash
-# 获取主角实体
-python -m data_modules.index_manager get-protagonist --project-root "."
+## 关键数据来源
 
-# 获取核心实体(主角 + tier=核心/重要)
-python -m data_modules.index_manager get-core-entities --project-root "."
+- `state.json`: 进度、主角状态、strand_tracker、chapter_meta
+- `index.db`: 实体/别名/关系/状态变化
+- `.webnovel/summaries/ch{NNNN}.md`: 章节摘要(含钩子/结束状态)
+- `大纲/`: 本章大纲 + 卷概述
+- `设定集/`: 世界观/力量体系/角色卡
 
-# 获取最近状态变化
-python -m data_modules.index_manager get-state-changes --entity "xiaoyan" --limit 10 --project-root "."
+---
 
-# 获取实体关系
-python -m data_modules.index_manager get-relationships --entity "xiaoyan" --project-root "."
-```
+## 执行流程
 
-**读取精简版 state.json** (使用 Read 工具):
-- `progress.current_chapter` - 进度
-- `protagonist_state` - 主角状态快照
-- `strand_tracker` - 节奏追踪
-- `disambiguation_warnings` - 消歧警告
-- `disambiguation_pending` - 待确认消歧
+### Step 1: 读取本章大纲
+- 章节大纲: `大纲/卷N/第XXX章.md` 或 `大纲/第{卷}卷-详细大纲.md`
+- 卷概述: `大纲/卷N/卷概述.md`(如存在)
 
-**注意**: v5.1 中 entities_v3、alias_index、state_changes、structured_relationships 已迁移到 index.db,不再从 state.json 读取。
+**提取要点**:
+- 本章核心冲突是什么?
+- 需要哪些角色出场?
+- 发生在什么地点?
+- 是否有战斗/突破/关键对话?
 
-### Step 3: 查询相关实体 (v5.1 SQL 按需查询)
+### Step 2: 读取状态与 chapter_meta
+- `state.json` 读取:
+  - progress.current_chapter
+  - protagonist_state
+  - strand_tracker
+  - chapter_meta (最近3章)
 
+### Step 3: 查询实体与关系(index.db)
 ```bash
-# 查询本章地点相关场景
-python -m data_modules.index_manager search-scenes --location "天云宗" --project-root "."
-
-# 查询出场角色历史
-python -m data_modules.index_manager entity-appearances --entity "yaolao" --project-root "."
-
-# 查询最近出场实体
+python -m data_modules.index_manager get-core-entities --project-root "."
 python -m data_modules.index_manager recent-appearances --limit 20 --project-root "."
-
-# v5.1 新增: 按需获取特定实体详情
-python -m data_modules.index_manager get-entity --id "yaolao" --project-root "."
-
-# v5.1 新增: 按别名查找实体(一对多)
-python -m data_modules.index_manager get-by-alias --alias "药老" --project-root "."
-
-# v5.1 新增: 按类型获取实体
-python -m data_modules.index_manager get-entities-by-type --type "角色" --project-root "."
-```
-
-**处理逻辑**:
-- 地点相关: 召回最近3次在该地点的场景
-- 角色相关: 召回角色最近出场状态
-- 伏笔: 筛选 urgency >= medium 的伏笔
-- **v5.1 优化**: 非核心实体按需查询,不全量加载
-
-### Step 4: 语义检索 (RAG)
-
-```bash
-# 基于大纲关键词进行语义检索
-python -m data_modules.rag_adapter search --query "大纲关键事件" --mode hybrid --top-k 5 --project-root "."
-```
-
-**检索策略**:
-- 提取大纲中的关键事件/冲突
-- 检索相关历史场景
-- 优先召回高相关度 (score > 0.7) 的场景
-
-### Step 5: 搜索设定集
-
-使用 Grep 工具搜索 `设定集/` 目录中的相关设定。
-
-**搜索内容**:
-- 修炼体系相关 (如果涉及突破)
-- 势力设定 (如果涉及新势力)
-- 角色卡片 (如果有新角色互动)
-
-### Step 6: 评估伏笔紧急度
-
-**紧急度计算**:
-```
-urgency = base_urgency + (current_chapter - planted_chapter) / expected_resolve_range
+python -m data_modules.index_manager get-relationships --entity "{protagonist}" --project-root "."
 ```
 
-**分类**:
-- `critical`: urgency > 0.9,必须本章/近期回收
-- `high`: urgency > 0.7,建议近期回收
-- `medium`: urgency > 0.4,可以提及/推进
-- `low`: urgency <= 0.4,暂不处理
+### Step 4: 读取最近摘要
+- 优先读取 `.webnovel/summaries/ch{NNNN}.md`
+- 若缺失,降级为章节正文前 300-500 字概述
 
-### Step 7: 选择风格样本
+### Step 5: 伏笔与风格样本
+- 伏笔:优先取 `foreshadowing_index`(若可用)
+- 风格样本:按本章类型选择 1-3 个高质量片段
 
-**选择逻辑**:
-- 根据大纲判断本章类型 (战斗/对话/过渡/描写)
-- 从风格样本库中选择匹配类型的高质量片段
-- 最多选择 2-3 个样本
-
-```bash
-# 查询风格样本
-python -m data_modules.style_sampler list --type "战斗" --limit 2 --project-root "."
-```
-
-### Step 8: 组装上下文包
-
-**智能筛选原则**:
-
-| 信息类型 | 包含条件 | Token 预算 |
-|---------|---------|-----------|
-| 本章大纲 | 必须 | ~500 |
-| 主角快照 | 必须 | ~300 |
-| 最近3章摘要 | 必须 | ~600 |
-| 地点上下文 | 如果换地点 | ~400 |
-| 出场角色 | 大纲提及的 | ~500 |
-| 紧急伏笔 | urgency >= high | ~300 |
-| 世界观骨架 | 如果涉及设定 | ~400 |
-| 风格样本 | 按场景类型 | ~600 |
-| RAG召回 | score > 0.7 | ~800 |
-
-**总预算**: ~4000-5000 tokens
-
-### Step 9: 输出上下文包 JSON
-
-将组装好的上下文包以 JSON 格式输出,供写作步骤使用。
+### Step 6: 推断补全
+**推断规则(必须执行)**:
+- 动机 = 角色目标 + 当前处境 + 上章钩子压力
+- 情绪底色 = 上章结束情绪 + 事件走向
+- 可用能力 = 当前境界 + 近期获得 + 设定禁用项
 
 ---
 
-## 智能决策点
+## 输出示例(片段)
 
-### 决策 1: 召回多少历史?
+### 一、本章核心任务
+- 冲突一句话:萧炎必须在宗门大比前夜稳住心境,否则突破将失败。
+- 必须完成:完成突破、引出明日大比风险。
+- 绝对不能:提前揭示大比结果。
 
-| 场景复杂度 | 召回量 |
-|-----------|-------|
-| 简单过渡章 | 最近2章摘要 |
-| 普通剧情章 | 最近3章摘要 + 1-2个RAG场景 |
-| 复杂冲突章 | 最近5章摘要 + 3-5个RAG场景 |
-| 回收伏笔章 | 伏笔种下章 + 相关发展章节 |
+### 二、接住上章
+- 上章钩子:**危机钩** — “慕容战天冷笑:明日大比…”
+- 读者期待:大比会出现什么意外?萧炎会如何应对?
+- 开头必须:直接进入准备/压力场景,快速拉起紧张感。
 
-### 决策 2: 是否附带伏笔建议?
-
-- 如果有 `critical` 伏笔 → 强制附带回收建议
-- 如果有 `high` 伏笔且本章场景适合 → 附带推进建议
-- 其他情况 → 不附带
-
-### 决策 3: 选择哪些风格样本?
-
-| 本章类型 | 样本类型 |
-|---------|---------|
-| 战斗为主 | combat x2 |
-| 对话为主 | dialogue x2 |
-| 描写为主 | description x2 |
-| 混合类型 | 各取1个 |
-
----
-
-## 错误处理
-
-### 文件不存在
-
-```
-⚠️ 大纲文件不存在: 大纲/卷3/第100章.md
-→ 尝试读取卷概述作为参考
-→ 如果卷概述也不存在,返回错误要求补充大纲
-```
-
-### 索引查询失败
-
-```
-⚠️ data_modules 查询失败
-→ 降级为 Grep 直接搜索
-→ 记录 warning 到输出
-```
-
-### RAG 服务不可用
-
-```
-⚠️ data_modules.rag_adapter 服务不可用
-→ 跳过语义检索
-→ 增加 Grep 搜索范围补偿
-→ 记录 warning 到输出
-```
-
----
-
-## 输出示例
-
-```json
-{
-  "core": {
-    "chapter_outline": "萧炎在天云宗突破斗师,引发宗门震动...",
-    "volume_outline": "第三卷:天云宗篇,主线:萧炎加入天云宗,暗线:云韵身份...",
-    "protagonist_snapshot": {
-      "name": "萧炎",
-      "realm": "斗者九层",
-      "location": "天云宗·外门",
-      "recent_events": ["击败慕容战天", "获得地心火线索", "与药老商议突破"]
-    },
-    "recent_summaries": [
-      {"chapter": 99, "summary": "萧炎闭关准备突破,药老传授突破要诀"},
-      {"chapter": 98, "summary": "萧炎击败慕容战天,声名鹊起"},
-      {"chapter": 97, "summary": "宗门大比开始,萧炎一路碾压"}
-    ]
-  },
-  "scene": {
-    "location_context": {
-      "name": "天云宗",
-      "description": "东域中等宗门,以炼丹著称",
-      "related_chapters": [45, 67, 89]
-    },
-    "appearing_characters": [
-      {"id": "yaolao", "name": "药老", "last_state": "戒指中沉睡,偶尔指点"},
-      {"id": "yunzhi", "name": "云芝", "last_state": "宗门长老,对萧炎有好感"}
-    ],
-    "urgent_foreshadowing": [
-      {"id": "F001", "content": "三年之约", "urgency": "high", "planted_chapter": 1, "suggestion": "可在突破时内心独白提及"}
-    ],
-    "foreshadow_suggestions": []
-  },
-  "global": {
-    "worldview_skeleton": "斗气大陆,以斗气修炼为主...",
-    "power_system_skeleton": "斗者→斗师→大斗师→斗灵→斗王→斗皇→斗宗→斗尊→斗圣→斗帝",
-    "style_samples": [
-      {"type": "breakthrough", "sample": "体内斗气如潮水般涌动,经脉中传来阵阵酥麻..."}
-    ]
-  },
-  "rag": {
-    "related_scenes": [
-      {"chapter": 45, "scene": 2, "summary": "萧炎初入天云宗,被分配到外门", "relevance": 0.82}
-    ]
-  },
-  "warnings": [],
-  "token_estimate": 4200
-}
-```
+...
 
 ---
 
 ## 成功标准
 
-1. ✅ 上下文包包含写作必需的所有信息
-2. ✅ Token 预算控制在 5000 以内
-3. ✅ 紧急伏笔被正确识别和附带
-4. ✅ 风格样本与本章类型匹配
-5. ✅ 错误情况有合理降级处理
-6. ✅ 输出格式为有效 JSON
+1. ✅ 创作任务书包含 8 个章节
+2. ✅ 上章钩子与读者期待明确
+3. ✅ 角色动机/情绪为推断结果(非空)
+4. ✅ 最近3章模式已对比,给出规避建议
+5. ✅ 章末钩子建议类型明确

+ 73 - 276
.claude/agents/data-agent.md

@@ -1,20 +1,18 @@
 ---
 name: data-agent
-description: 数据处理Agent (v5.1),负责AI实体提取、场景切片、索引构建。使用 v5.1 实体格式和一对多别名,写入 index.db。在章节完成后自动调用,处理数据链的写入工作。支持 SQLite 增量写入优化
+description: 数据处理Agent (v5.2),负责AI实体提取、场景切片、索引构建,并记录钩子/模式/结束状态与章节摘要
 tools: Read, Write, Bash
 ---
 
-# data-agent (数据处理Agent v5.1)
+# data-agent (数据处理Agent v5.2)
 
 > **Role**: 智能数据工程师,负责从章节正文中提取结构化信息并写入数据链。
 >
 > **Philosophy**: AI驱动提取,智能消歧 - 用语义理解替代正则匹配,用置信度控制质量。
 
-**v5.1 变更**:
-- 使用 SQLite 增量写入替代 JSON 追加
-- 实体/别名/状态变化/关系 直接写入 index.db
-- state.json 只保留精简数据(进度、配置、节奏追踪)
-- 解决 state.json 膨胀问题(20章后 token 爆炸)
+**v5.2 变更**:
+- 章节摘要不再追加到正文,改为 `.webnovel/summaries/ch{NNNN}.md`
+- 在 state.json 写入 `chapter_meta`(钩子/模式/结束状态)
 
 ## 输入
 
@@ -31,8 +29,9 @@ tools: Read, Write, Bash
 
 **重要**: 所有数据写入 `{project_root}/.webnovel/` 目录:
 - index.db → 实体、别名、状态变化、关系、章节索引 (SQLite)
-- state.json → 进度、配置、节奏追踪 (精简 JSON < 5KB)
+- state.json → 进度、配置、节奏追踪 + chapter_meta
 - vectors.db → RAG 向量 (SQLite)
+- summaries/ → 章节摘要文件
 
 ## 输出
 
@@ -80,37 +79,9 @@ python -m data_modules.index_manager recent-appearances --limit 20 --project-roo
 python -m data_modules.index_manager get-by-alias --alias "萧炎" --project-root "."
 ```
 
-**准备数据**:
-- 已有实体列表 (从 index.db 获取)
-- 别名映射表 (从 index.db aliases 表获取)
-- 最近出场实体 (用于上下文推断)
-
 ### Step B: AI 实体提取
 
-**Data Agent 直接执行** (无需调用外部 LLM):
-
-基于上述上下文,直接分析章节正文,输出结构化 JSON:
-
-```json
-{
-  "entities_appeared": [
-    {"id": "xiaoyan", "type": "角色", "mentions": ["萧炎", "他"], "confidence": 0.95},
-    {"id": "yaolao", "type": "角色", "mentions": ["药老"], "confidence": 0.92}
-  ],
-  "entities_new": [
-    {"suggested_id": "hongyi_girl", "name": "红衣女子", "type": "角色", "tier": "装饰"}
-  ],
-  "state_changes": [
-    {"entity_id": "xiaoyan", "field": "realm", "old": "斗者九层", "new": "斗师一层", "reason": "闭关突破"}
-  ],
-  "relationships_new": [
-    {"from": "xiaoyan", "to": "hongyi_girl", "type": "相识", "description": "在突破时偶遇"}
-  ],
-  "uncertain": [
-    {"mention": "那位前辈", "context": "那位前辈看了他一眼", "candidates": [{"type": "角色", "id": "yaolao"}, {"type": "角色", "id": "elder_zhang"}], "suggested": "yaolao", "confidence": 0.6}
-  ]
-}
-```
+**Data Agent 直接执行** (无需调用外部 LLM)。
 
 ### Step C: 实体消歧处理
 
@@ -122,127 +93,80 @@ python -m data_modules.index_manager get-by-alias --alias "萧炎" --project-roo
 | 0.5 - 0.8 | 采用建议值,记录 warning |
 | < 0.5 | 标记待人工确认,不自动写入 |
 
-**消歧算法**:
-```python
-for uncertain_item in uncertain:
-    if uncertain_item.confidence > 0.8:
-        # 高置信度:直接采用
-        adopt(uncertain_item.suggested)
-    elif uncertain_item.confidence > 0.5:
-        # 中置信度:采用但警告
-        adopt(uncertain_item.suggested)
-        warnings.append(f"中置信度匹配: {uncertain_item.mention} → {uncertain_item.suggested}")
-    else:
-        # 低置信度:不采用,人工确认
-        pending_review.append(uncertain_item)
-        warnings.append(f"需人工确认: {uncertain_item.mention}")
-```
-
-**同名异人处理**:
-```
-"宗主" 出现在血煞秘境 → 可能是 xueshazonzhu
-"宗主" 出现在天云宗 → 可能是 lintian
-→ 根据当前地点上下文推断
-```
-
-**异名同人处理**:
-```
-"萧炎" / "小炎子" / "那小子" / "他"
-→ 根据 alias_index 映射到 xiaoyan
-→ 代词"他"需根据上下文推断
-```
-
-### Step D: 写入存储 (v5.1 SQLite 增量写入)
-
-**v5.1 优化**: 使用 SQLite 增量写入替代 JSON 追加
+### Step D: 写入存储 (v5.2)
 
 **写入 index.db (实体/别名/状态变化/关系)**:
 ```bash
-# v5.1: 写入/更新实体
-python -m data_modules.index_manager upsert-entity --data '{"id":"hongyi_girl","type":"角色","canonical_name":"红衣女子","tier":"装饰","current":{},"first_appearance":100,"last_appearance":100}' --project-root "."
-
-# v5.1: 注册别名(一对多)
+python -m data_modules.index_manager upsert-entity --data '{...}' --project-root "."
 python -m data_modules.index_manager register-alias --alias "红衣女子" --entity "hongyi_girl" --type "角色" --project-root "."
-
-# v5.1: 记录状态变化
-python -m data_modules.index_manager record-state-change --data '{"entity_id":"xiaoyan","field":"realm","old_value":"斗者","new_value":"斗师","reason":"突破","chapter":100}' --project-root "."
-
-# v5.1: 写入/更新关系
-python -m data_modules.index_manager upsert-relationship --data '{"from_entity":"xiaoyan","to_entity":"hongyi_girl","type":"相识","description":"初次见面","chapter":100}' --project-root "."
-```
-
-**写入 index.db (章节/场景/出场)**:
-```bash
-python -m data_modules.index_manager process-chapter --chapter 100 --title "突破" --location "天云宗" --word-count 3500 --entities '[...]' --scenes '[...]' --project-root "."
+python -m data_modules.index_manager record-state-change --data '{...}' --project-root "."
+python -m data_modules.index_manager upsert-relationship --data '{...}' --project-root "."
 ```
 
 **更新精简版 state.json**:
 ```bash
-# 仍使用 state_manager,但只写入精简数据
 python -m data_modules.state_manager process-chapter --chapter 100 --data '{...}' --project-root "."
 ```
 
-写入内容 (v5.1 精简):
+写入内容 (v5.2):
 - 更新 `progress.current_chapter`
-- 更新 `protagonist_state`(主角状态快照)
-- 更新 `strand_tracker`(节奏追踪)
+- 更新 `protagonist_state`
+- 更新 `strand_tracker`
 - 更新 `disambiguation_warnings/pending`
+- **新增 `chapter_meta`**(钩子/模式/结束状态)
+
+### Step E: 生成章节摘要文件(新增)
 
-> **v5.1 变更**: entities_v3、alias_index、state_changes、structured_relationships 不再写入 state.json,改为写入 index.db。state.json 保持 < 5KB。
+**输出路径**: `.webnovel/summaries/ch{NNNN}.md`
 
-> **主角同步说明**:`process_chapter_result()` 会自动调用 `sync_protagonist_from_entity()`,将主角实体的 realm/location 同步到 `protagonist_state`。
+**章节编号规则**: 4位数字,如 `0001`, `0099`, `0100`
 
-### Step E: AI 场景切片
+**摘要文件格式**:
+```markdown
+---
+chapter: 0099
+time: "前一夜"
+location: "萧炎房间"
+characters: ["萧炎", "药老"]
+state_changes: ["萧炎: 斗者9层→准备突破"]
+hook_type: "危机钩"
+hook_strength: "strong"
+---
 
-**Data Agent 直接执行** (无需调用外部 LLM):
+## 剧情摘要
+{主要事件,100-150字}
 
-根据以下规则切分场景:
-- 按地点变化切分
-- 按时间跳跃切分
-- 按视角变化切分
-- 每个场景生成摘要 (50-100字)
+## 伏笔
+- [埋设] 三年之约提及
+- [推进] 青莲地心火线索
 
-**输出**:
-```json
-{
-  "scenes": [
-    {"index": 1, "start_line": 1, "end_line": 45, "location": "天云宗·闭关室", "summary": "萧炎闭关突破斗师...", "characters": ["xiaoyan"]},
-    {"index": 2, "start_line": 46, "end_line": 89, "location": "天云宗·演武场", "summary": "突破引发天象,众人围观...", "characters": ["xiaoyan", "lintian"]}
-  ]
-}
+## 承接点
+{下章衔接,30字}
 ```
 
-### Step F: 向量嵌入
+### Step F: AI 场景切片
+
+- 按地点/时间/视角切分场景
+- 每个场景生成摘要 (50-100字)
+
+### Step G: 向量嵌入
 
-**调用 RAG 存储**:
 ```bash
 python -m data_modules.rag_adapter index-chapter --chapter 100 --scenes '[...]' --project-root "."
 ```
 
-写入内容:
-- 场景摘要向量化 (调用 Modal Embedding API)
-- 存入 SQLite 向量库
-- 更新 BM25 索引
+### Step H: 风格样本评估
 
-### Step G: 风格样本评估
-
-**评估条件**:
 ```python
 if review_score >= 80:
-    # 高分章节,可能作为风格样本
     extract_style_candidates(chapter_content)
 ```
 
-**提取逻辑**:
-- 识别高质量片段 (战斗/对话/描写)
-- 标记片段类型
-- 存入风格样本库
-
 ```bash
 python -m data_modules.style_sampler extract --chapter 100 --score 85 --scenes '[...]' --project-root "."
 ```
 
-### Step H: 生成处理报告
+### Step I: 生成处理报告
 
 ```json
 {
@@ -264,129 +188,31 @@ python -m data_modules.style_sampler extract --chapter 100 --score 85 --scenes '
 
 ---
 
-## 提取规则参考
-
-### 1. 实体识别
-- 识别所有出场的角色、地点、物品、势力
-- 优先匹配已有实体(通过名称或别名)
-- 新实体需要建议 entity_id(使用拼音或英文)
-
-### 2. 状态变化
-- 识别实力变化(境界突破/跌落)
-- 识别位置变化(移动到新地点)
-- 识别持有物变化(获得/失去物品)
-- 识别关系变化(结盟/敌对/师徒等)
-
-### 3. 消歧处理
-- 代词(他/她/它)需根据上下文推断指代
-- 称呼(宗主/长老/前辈)需根据场景推断
-- 不确定时标记 uncertain 并给出候选
+## 接口规范:chapter_meta (state.json)
 
-### 4. 置信度评估
-- 0.9-1.0: 明确提及名字
-- 0.7-0.9: 通过别名/称呼确定
-- 0.5-0.7: 通过上下文推断
-- <0.5: 无法确定
-
----
-
-## 错误处理
-
-### 章节文件不存在
-```
-❌ 章节文件不存在: 正文/第0100章.md
-→ 返回错误,终止处理
-```
-
-### AI 提取失败
-```
-⚠️ AI 提取失败或返回无效 JSON
-→ 重试一次
-→ 仍失败则记录错误,跳过本章处理
-```
-
-### 向量服务不可用
-```
-⚠️ data_modules.rag_adapter 服务不可用
-→ 跳过向量嵌入步骤
-→ 记录 warning,其他步骤继续
-```
-
-### 状态文件锁定
-```
-⚠️ state.json 被锁定
-→ 等待 5 秒重试
-→ 仍失败则记录错误
-```
-
----
-
-## 故障恢复流程 (v5.1)
-
-> **注意**: 以下恢复命令为规划中功能,当前版本请使用替代方案。
-
-### 索引重建
-
-当 index.db 损坏或与实际数据不一致时:
-
-**当前替代方案**(逐章重新处理):
-```bash
-# 重新处理单章(会更新索引)
-python -m data_modules.index_manager process-chapter --chapter 1 --project-root "."
-
-# 批量重新处理(shell 循环)
-for i in $(seq 1 50); do
-  python -m data_modules.index_manager process-chapter --chapter $i --project-root "."
-done
-
-# 查看索引统计
-python -m data_modules.index_manager stats --project-root "."
-```
-
-### 向量重建
-
-当 vectors.db 损坏或嵌入模型更换时:
-
-**当前替代方案**(逐章重新索引):
-```bash
-# 重新索引单章
-python -m data_modules.rag_adapter index-chapter --chapter 1 --project-root "."
-
-# 批量重新索引(shell 循环)
-for i in $(seq 1 50); do
-  python -m data_modules.rag_adapter index-chapter --chapter $i --project-root "."
-done
-
-# 查看向量统计
-python -m data_modules.rag_adapter stats --project-root "."
-```
-
-### 状态同步
-
-当 state.json 与 index.db 不一致时:
-
-**当前替代方案**(手动查询和更新):
-```bash
-# 查看主角实体信息
-python -m data_modules.index_manager get-protagonist --project-root "."
-
-# 查看核心实体列表
-python -m data_modules.index_manager get-core-entities --project-root "."
-
-# 手动更新:根据输出结果编辑 state.json 中的 protagonist_state
-```
-
-### 数据一致性检查
-
-**当前替代方案**(分别查看统计):
-```bash
-# 查看索引统计
-python -m data_modules.index_manager stats --project-root "."
-
-# 查看向量统计
-python -m data_modules.rag_adapter stats --project-root "."
-
-# 对比结果判断一致性
+```json
+{
+  "chapter_meta": {
+    "0099": {
+      "hook": {
+        "type": "危机钩",
+        "content": "慕容战天冷笑:明日大比...",
+        "strength": "strong"
+      },
+      "pattern": {
+        "opening": "对话开场",
+        "hook": "危机钩",
+        "emotion_rhythm": "低→高",
+        "info_density": "medium"
+      },
+      "ending": {
+        "time": "前一夜",
+        "location": "萧炎房间",
+        "emotion": "平静准备"
+      }
+    }
+  }
+}
 ```
 
 ---
@@ -398,35 +224,6 @@ python -m data_modules.rag_adapter stats --project-root "."
 3. ✅ 消歧结果合理(高置信度 > 80%)
 4. ✅ 场景切片数量合理(通常 3-6 个/章)
 5. ✅ 向量成功存入数据库
-6. ✅ 不确定项被正确标记和报告
-7. ✅ 输出格式为有效 JSON
-
----
-
-## 与 Context Agent 的协作
-
-```
-写作前: Context Agent 读取数据 → 组装上下文包
-写作中: Writer 使用上下文包生成正文
-写作后: Data Agent 处理正文 → 写入数据链
-
-Context Agent (读) ←→ 数据存储 ←→ Data Agent (写)
-```
-
-**数据流 (v5.1)**:
-```
-章节正文 → Data Agent → state.json (精简)
-                      └── protagonist_state (快照)
-
-                      → index.db (v5.1 schema)
-                      ├── entities (id, canonical_name, current_json)
-                      ├── aliases (一对多)
-                      ├── relationships
-                      ├── state_changes
-                      └── scenes
-
-                      → vectors.db
-                      └── 场景向量嵌入
-                              ↓
-                      Context Agent → 下一章上下文
-```
+6. ✅ 章节摘要文件生成成功
+7. ✅ chapter_meta 写入 state.json
+8. ✅ 输出格式为有效 JSON

+ 95 - 0
.claude/agents/reader-pull-checker.md

@@ -0,0 +1,95 @@
+---
+name: reader-pull-checker
+description: 追读力检查器,评估钩子兑现/新增期待/模式重复,输出结构化报告
+tools: Read, Grep
+---
+
+# reader-pull-checker (追读力检查器)
+
+> **Role**: 审查“读者为什么会点下一章”。
+
+## 输入
+- 章节正文(`正文/第{NNNN}章.md`)
+- 上章钩子与模式(从 `state.json → chapter_meta`)
+
+## 输出格式(与其他 checker 对齐)
+
+```json
+{
+  "agent": "reader-pull-checker",
+  "chapter": 100,
+  "overall_score": 85,
+  "pass": true,
+  "issues": [
+    {
+      "type": "WEAK_HOOK",
+      "severity": "high",
+      "location": "章末",
+      "description": "钩子强度不足",
+      "suggestion": "将‘回去休息了’改为悬念/危机"
+    }
+  ],
+  "metrics": {
+    "hook_present": true,
+    "hook_type": "期待钩",
+    "hook_strength": "medium",
+    "prev_hook_fulfilled": true,
+    "new_expectations": 2,
+    "pattern_repeat": false,
+    "next_chapter_reason": "读者想知道云芝找萧炎什么事"
+  }
+}
+```
+
+## 检查项与权重
+
+| 检查项 | 权重 | 问题类型 |
+|--------|------|----------|
+| 章末钩子存在 | 30% | NO_HOOK (critical) |
+| 钩子强度适当 | 20% | WEAK_HOOK (high) |
+| 上章钩子兑现 | 20% | UNFULFILLED_HOOK (high) |
+| 模式不重复 | 15% | PATTERN_REPEAT (medium) |
+| 新增期待≤2个 | 15% | TOO_MANY_EXPECTATIONS (low) |
+
+## 钩子强度分级
+
+| 强度 | 适用场景 | 示例 |
+|------|---------|------|
+| **strong** | 卷末、关键转折、大冲突前 | “门外站着的人,让萧炎瞳孔骤缩” |
+| **medium** | 普通剧情章 | “云芝说有事找他” |
+| **weak** | 过渡章、铺垫章 | “明天还有很多事要做” |
+
+## 评分规则
+- 85+ 分: PASS
+- 70-84 分: PASS with warnings
+- <70 分: FAIL
+
+## 执行步骤
+
+1. **识别章末钩子**
+   - 判断是否存在未闭合问题/危险逼近/信息反转
+   - 标注类型与强度
+
+2. **检查上章钩子兑现**
+   - 读取 `chapter_meta[N-1].hook`
+   - 判断本章是否接住或回应(直接推进/部分回应/完全忽略)
+
+3. **新增期待计数**
+   - 统计本章新抛出的“未解问题/悬念点”数量(建议 ≤2)
+
+4. **模式重复检测**
+   - 对比 `chapter_meta[N-1..N-3].pattern`
+   - 若本章开头/钩子类型与最近章重复,记为风险
+
+5. **输出“读者下章动机”**
+   - 用一句话说明读者为什么点下一章
+
+---
+
+## 成功标准
+
+- 章末钩子存在且强度匹配场景
+- 上章钩子有回应(直接/间接)
+- 新增期待不超过 2 个
+- 模式重复率低(最近 3 章避免同型)
+- 输出清晰的“下章动机”

+ 78 - 10
.claude/scripts/context_pack_builder.py

@@ -1,20 +1,22 @@
 #!/usr/bin/env python3
 """
-Context Pack Builder v5.1
+Context Pack Builder v5.2
 
 为章节写作生成结构化上下文包,取代直接读取 state.json。
 
-v5.1 变更:
+v5.2 变更:
 - 使用 v5.1 index_manager schema (entities.id, aliases, current_json)
 - 移除对 entity_kv 表的依赖,改用 current_json 字段
 - 移除对 entity_aliases 表的依赖,改用 aliases 表
+- 章节摘要改为读取 .webnovel/summaries/chNNNN.md
 
 输出 Schema:
 {
   "core": {
     "chapter_outline": "本章大纲内容",
     "protagonist_snapshot": {...},
-    "recent_summaries": [{...}, ...]
+    "recent_summaries": [{...}, ...],
+    "recent_meta": [{...}, ...]
   },
   "scene": {
     "location_context": {...},
@@ -69,6 +71,7 @@ class ContextPackBuilder:
         self.config = get_config(project_root)
         self.state_file = project_root / ".webnovel" / "state.json"
         self.index_db = project_root / ".webnovel" / "index.db"
+        self.summaries_dir = project_root / ".webnovel" / "summaries"
         self.outline_dir = project_root / "大纲"
         self.settings_dir = project_root / "设定集"
         self.chapters_dir = project_root / "正文"
@@ -93,7 +96,7 @@ class ContextPackBuilder:
             "meta": {
                 "chapter": chapter_num,
                 "project_root": str(self.project_root),
-                "version": "5.1"
+                "version": "5.2"
             },
             "core": self._build_core(chapter_num),
             "scene": self._build_scene(chapter_num),
@@ -110,7 +113,8 @@ class ContextPackBuilder:
             "protagonist_snapshot": self._get_protagonist_snapshot(state),
             "recent_summaries": self._get_recent_summaries(
                 chapter_num, window=self.config.context_recent_summaries_window
-            )
+            ),
+            "recent_meta": self._get_recent_chapter_meta(chapter_num, window=3),
         }
 
     def _build_scene(self, chapter_num: int) -> Dict[str, Any]:
@@ -239,17 +243,23 @@ class ContextPackBuilder:
 
         return snapshot
 
-    def _get_recent_summaries(self, chapter_num: int, window: int = 5) -> List[Dict]:
+    def _get_recent_summaries(self, chapter_num: int, window: int = 3) -> List[Dict]:
         """获取最近 N 章的摘要"""
         summaries = []
         start = max(1, chapter_num - window)
 
         for ch in range(start, chapter_num):
+            summary = self._load_summary_file(ch)
+            if summary:
+                summaries.append(summary)
+                continue
+
+            # 兼容降级:若摘要文件不存在,尝试从章节正文提取
             chapter_file = find_chapter_file(self.project_root, ch)
             if chapter_file and chapter_file.exists():
-                summary = self._extract_summary_from_chapter(chapter_file, ch)
-                if summary:
-                    summaries.append(summary)
+                fallback = self._extract_summary_from_chapter(chapter_file, ch)
+                if fallback:
+                    summaries.append(fallback)
 
         return summaries
 
@@ -259,7 +269,7 @@ class ContextPackBuilder:
             content = f.read()
 
         # 查找摘要区块
-        summary_match = re.search(r'## 本章摘要\s*\n(.*?)(?=\n##|$)', content, re.DOTALL)
+        summary_match = re.search(r'## 本章摘要\s*\r?\n(.*?)(?=\r?\n##|$)', content, re.DOTALL)
         if summary_match:
             summary_text = summary_match.group(1).strip()
             return {
@@ -277,6 +287,64 @@ class ContextPackBuilder:
             "summary": None
         }
 
+    def _load_summary_file(self, chapter_num: int) -> Optional[Dict]:
+        """从 .webnovel/summaries/chNNNN.md 读取摘要"""
+        summary_path = self.summaries_dir / f"ch{chapter_num:04d}.md"
+        if not summary_path.exists():
+            return None
+
+        text = summary_path.read_text(encoding="utf-8")
+
+        # 解析 YAML 头部(--- ... ---)
+        meta: Dict[str, Any] = {}
+        fm_match = re.match(r"^---\s*\r?\n(.*?)\r?\n---\s*\r?\n", text, re.DOTALL)
+        if fm_match:
+            fm = fm_match.group(1)
+            for line in fm.splitlines():
+                if ":" not in line:
+                    continue
+                key, _, value = line.partition(":")
+                key = key.strip()
+                value = value.strip()
+                if not key:
+                    continue
+                # 简单解析列表
+                if value.startswith("[") and value.endswith("]"):
+                    items = [v.strip().strip('\"').strip("'") for v in value[1:-1].split(",") if v.strip()]
+                    meta[key] = items
+                else:
+                    meta[key] = value.strip('\"').strip("'")
+
+        # 提取剧情摘要段落
+        summary_match = re.search(r"##\s*剧情摘要\s*\r?\n(.*?)(?=\r?\n##|\Z)", text, re.DOTALL)
+        summary_text = summary_match.group(1).strip() if summary_match else ""
+
+        result = {
+            "chapter": chapter_num,
+            "summary": summary_text
+        }
+        # 附加部分元数据(可选)
+        for k in ["hook_type", "hook_strength", "time", "location"]:
+            if k in meta:
+                result[k] = meta[k]
+        return result
+
+    def _get_recent_chapter_meta(self, chapter_num: int, window: int = 3) -> List[Dict[str, Any]]:
+        """读取最近 N 章的 chapter_meta(用于模式重复检查)"""
+        state = self._load_state()
+        meta = state.get("chapter_meta", {}) or {}
+        items: List[Dict[str, Any]] = []
+        for ch in range(max(1, chapter_num - window), chapter_num):
+            key_candidates = [f"{ch:04d}", str(ch)]
+            entry = None
+            for key in key_candidates:
+                if key in meta:
+                    entry = meta.get(key)
+                    break
+            if entry:
+                items.append({"chapter": ch, **entry})
+        return items
+
     def _predict_location(self, outline: str, state: Dict) -> Dict:
         """从大纲推断地点(优先使用 index.db 别名表)"""
         conn = self._conn_index()

+ 1 - 1
.claude/scripts/data_modules/config.py

@@ -125,7 +125,7 @@ class DataModulesConfig:
     max_disambiguation_pending: int = 1000
     max_state_changes: int = 2000
 
-    context_recent_summaries_window: int = 5
+    context_recent_summaries_window: int = 3
     context_alerts_slice: int = 10
     context_max_appearing_characters: int = 10
     context_max_urgent_foreshadowing: int = 5

+ 20 - 0
.claude/scripts/data_modules/state_manager.py

@@ -115,6 +115,7 @@ class StateManager:
         self._pending_disambiguation_pending: List[Dict[str, Any]] = []
         self._pending_progress_chapter: Optional[int] = None
         self._pending_progress_words_delta: int = 0
+        self._pending_chapter_meta: Dict[str, Any] = {}
 
         # v5.1: 缓存待同步到 SQLite 的数据
         self._pending_sqlite_data: Dict[str, Any] = {
@@ -152,6 +153,7 @@ class StateManager:
         state.setdefault("world_settings", {"power_system": [], "factions": [], "locations": []})
         state.setdefault("plot_threads", {"active_threads": [], "foreshadowing": []})
         state.setdefault("review_checkpoints", [])
+        state.setdefault("chapter_meta", {})
         state.setdefault(
             "strand_tracker",
             {
@@ -212,6 +214,7 @@ class StateManager:
                 self._pending_structured_relationships,
                 self._pending_disambiguation_warnings,
                 self._pending_disambiguation_pending,
+                self._pending_chapter_meta,
                 self._pending_progress_chapter is not None,
                 self._pending_progress_words_delta != 0,
             ]
@@ -317,6 +320,14 @@ class StateManager:
                     if len(pending_list) > max_keep:
                         disk_state["disambiguation_pending"] = pending_list[-max_keep:]
 
+                # chapter_meta(新增:按章节号覆盖写入)
+                if self._pending_chapter_meta:
+                    chapter_meta = disk_state.get("chapter_meta")
+                    if not isinstance(chapter_meta, dict):
+                        chapter_meta = {}
+                        disk_state["chapter_meta"] = chapter_meta
+                    chapter_meta.update(self._pending_chapter_meta)
+
                 # 原子写入(锁已持有,不再二次加锁)
                 atomic_write_json(self.config.state_file, disk_state, use_lock=False, backup=True)
 
@@ -331,6 +342,7 @@ class StateManager:
                 self._pending_structured_relationships.clear()
                 self._pending_disambiguation_warnings.clear()
                 self._pending_disambiguation_pending.clear()
+                self._pending_chapter_meta.clear()
                 self._pending_progress_chapter = None
                 self._pending_progress_words_delta = 0
 
@@ -1003,6 +1015,14 @@ class StateManager:
         # 处理消歧不确定项(不影响实体写入,但必须对 Writer 可见)
         warnings.extend(self._record_disambiguation(chapter, result.get("uncertain", [])))
 
+        # 写入 chapter_meta(钩子/模式/结束状态)
+        chapter_meta = result.get("chapter_meta")
+        if isinstance(chapter_meta, dict):
+            meta_key = f"{int(chapter):04d}"
+            self._state.setdefault("chapter_meta", {})
+            self._state["chapter_meta"][meta_key] = chapter_meta
+            self._pending_chapter_meta[meta_key] = chapter_meta
+
         # 更新进度
         self.update_progress(chapter)
 

+ 22 - 6
.claude/scripts/extract_chapter_context.py

@@ -4,7 +4,7 @@ extract_chapter_context.py - 提取章节创作所需的精简上下文
 
 功能:
 - 提取当前章节的大纲片段(~500字)
-- 提取前2章的摘要(~400字
+- 提取前2章的摘要(优先 .webnovel/summaries
 - 提取 state.json 关键字段(~300字)
 
 用法:
@@ -72,8 +72,25 @@ def extract_chapter_outline(project_root: Path, chapter_num: int) -> str:
     return f"⚠️ 未找到第 {chapter_num} 章的大纲"
 
 
+def _load_summary_file(project_root: Path, chapter_num: int) -> str:
+    """从 .webnovel/summaries/chNNNN.md 提取剧情摘要"""
+    summary_path = project_root / ".webnovel" / "summaries" / f"ch{chapter_num:04d}.md"
+    if not summary_path.exists():
+        return ""
+
+    text = summary_path.read_text(encoding="utf-8")
+    summary_match = re.search(r"##\s*剧情摘要\s*\r?\n(.+?)(?=\r?\n##|$)", text, re.DOTALL)
+    if summary_match:
+        return summary_match.group(1).strip()
+    return ""
+
+
 def extract_chapter_summary(project_root: Path, chapter_num: int) -> str:
-    """提取指定章节的摘要(从章节文件末尾的"本章摘要"部分)"""
+    """提取指定章节摘要(优先 summaries/,再降级正文)"""
+    summary = _load_summary_file(project_root, chapter_num)
+    if summary:
+        return summary
+
     volume_num = (chapter_num - 1) // 50 + 1
     chapter_dir = project_root / "正文" / f"第{volume_num}卷"
 
@@ -95,18 +112,17 @@ def extract_chapter_summary(project_root: Path, chapter_num: int) -> str:
 
     content = chapter_file.read_text(encoding="utf-8")
 
-    # 尝试提取"本章摘要"部分
-    summary_match = re.search(r"##\s*本章摘要\s*\n(.+?)(?=##|$)", content, re.DOTALL)
+    # 兼容旧格式:尝试提取"本章摘要"部分
+    summary_match = re.search(r"##\s*本章摘要\s*\r?\n(.+?)(?=\r?\n##|$)", content, re.DOTALL)
     if summary_match:
         return summary_match.group(1).strip()
 
     # 如果没有摘要,提取"本章统计"部分
-    stats_match = re.search(r"##\s*本章统计\s*\n(.+?)(?=##|$)", content, re.DOTALL)
+    stats_match = re.search(r"##\s*本章统计\s*\r?\n(.+?)(?=\r?\n##|$)", content, re.DOTALL)
     if stats_match:
         return f"[无摘要,仅统计]\n{stats_match.group(1).strip()}"
 
     # 最后降级:提取前500字作为摘要
-    # 跳过标题
     lines = content.split("\n")
     text_lines = [l for l in lines if not l.startswith("#") and l.strip()]
     text = "\n".join(text_lines)[:500]

+ 73 - 18
.claude/scripts/init_project.py

@@ -65,6 +65,7 @@ def _ensure_state_schema(state: Dict[str, Any]) -> Dict[str, Any]:
     state.setdefault("world_settings", {"power_system": [], "factions": [], "locations": []})
     state.setdefault("plot_threads", {"active_threads": [], "foreshadowing": []})
     state.setdefault("review_checkpoints", [])
+    state.setdefault("chapter_meta", {})
     state.setdefault(
         "strand_tracker",
         {
@@ -127,6 +128,31 @@ def _build_master_outline(target_chapters: int, *, chapters_per_volume: int = 50
     return "\n".join(lines).rstrip() + "\n"
 
 
+def _inject_volume_rows(template_text: str, target_chapters: int, *, chapters_per_volume: int = 50) -> str:
+    """在总纲模板的卷表中注入卷行(若存在表头)。"""
+    lines = template_text.splitlines()
+    header_idx = None
+    for i, line in enumerate(lines):
+        if line.strip().startswith("| 卷号"):
+            header_idx = i
+            break
+    if header_idx is None:
+        return template_text
+
+    insert_idx = header_idx + 2 if header_idx + 1 < len(lines) else len(lines)
+    volumes = (target_chapters - 1) // chapters_per_volume + 1 if target_chapters > 0 else 1
+    rows = []
+    for v in range(1, volumes + 1):
+        start = (v - 1) * chapters_per_volume + 1
+        end = min(v * chapters_per_volume, target_chapters)
+        rows.append(f"| {v} | | 第{start}-{end}章 | | |")
+
+    # 避免重复插入(若模板已有数据行)
+    existing = {line.strip() for line in lines}
+    rows = [r for r in rows if r.strip() not in existing]
+    return "\n".join(lines[:insert_idx] + rows + lines[insert_idx:])
+
+
 def init_project(
     project_dir: str,
     title: str,
@@ -153,6 +179,7 @@ def init_project(
     directories = [
         ".webnovel/backups",
         ".webnovel/archive",
+        ".webnovel/summaries",
         "设定集/角色库/主要角色",
         "设定集/角色库/次要角色",
         "设定集/角色库/反派角色",
@@ -198,7 +225,12 @@ def init_project(
     if protagonist_name:
         state["protagonist_state"]["name"] = protagonist_name
 
-    if golden_finger_name:
+    gf_type_norm = (golden_finger_type or "").strip()
+    if gf_type_norm in {"无", "无金手指", "none"}:
+        state["protagonist_state"]["golden_finger"]["name"] = "无金手指"
+        state["protagonist_state"]["golden_finger"]["level"] = 0
+        state["protagonist_state"]["golden_finger"]["cooldown"] = 0
+    elif golden_finger_name:
         state["protagonist_state"]["golden_finger"]["name"] = golden_finger_name
 
     # 确保 golden_finger 字段存在且可编辑
@@ -213,6 +245,7 @@ def init_project(
     # 读取内置模板(可选)
     script_dir = Path(__file__).resolve().parent
     templates_dir = script_dir.parent / "templates"
+    output_templates_dir = templates_dir / "output"
     genre_key = (genre or "").strip()
     genre_template_key = {
         "修仙/玄幻": "修仙",
@@ -220,13 +253,18 @@ def init_project(
     }.get(genre_key, genre_key)
     genre_template = _read_text_if_exists(templates_dir / "genres" / f"{genre_template_key}.md")
     golden_finger_templates = _read_text_if_exists(templates_dir / "golden-finger-templates.md")
+    output_worldview = _read_text_if_exists(output_templates_dir / "设定集-世界观.md")
+    output_power = _read_text_if_exists(output_templates_dir / "设定集-力量体系.md")
+    output_protagonist = _read_text_if_exists(output_templates_dir / "设定集-主角卡.md")
+    output_golden_finger = _read_text_if_exists(output_templates_dir / "设定集-金手指.md")
+    output_outline = _read_text_if_exists(output_templates_dir / "大纲-总纲.md")
 
     # 基础文件(只在缺失时生成,避免覆盖已有内容)
     now = datetime.now().strftime("%Y-%m-%d")
 
-    _write_text_if_missing(
-        project_path / "设定集" / "世界观.md",
-        "\n".join(
+    worldview_content = output_worldview.strip() if output_worldview else ""
+    if not worldview_content:
+        worldview_content = "\n".join(
             [
                 "# 世界观",
                 "",
@@ -248,12 +286,15 @@ def init_project(
                 "",
                 (genre_template.strip() + "\n") if genre_template else "(未找到对应题材模板,可自行补充)\n",
             ]
-        ),
+        ).rstrip() + "\n"
+    _write_text_if_missing(
+        project_path / "设定集" / "世界观.md",
+        worldview_content,
     )
 
-    _write_text_if_missing(
-        project_path / "设定集" / "力量体系.md",
-        "\n".join(
+    power_content = output_power.strip() if output_power else ""
+    if not power_content:
+        power_content = "\n".join(
             [
                 "# 力量体系",
                 "",
@@ -272,12 +313,15 @@ def init_project(
                 "- 新增能力必须申报并入库(发明需申报)",
                 "",
             ]
-        ),
+        ).rstrip() + "\n"
+    _write_text_if_missing(
+        project_path / "设定集" / "力量体系.md",
+        power_content,
     )
 
-    _write_text_if_missing(
-        project_path / "设定集" / "主角卡.md",
-        "\n".join(
+    protagonist_content = output_protagonist.strip() if output_protagonist else ""
+    if not protagonist_content:
+        protagonist_content = "\n".join(
             [
                 "# 主角卡",
                 "",
@@ -300,12 +344,15 @@ def init_project(
                 "- 成长曲线:",
                 "",
             ]
-        ),
+        ).rstrip() + "\n"
+    _write_text_if_missing(
+        project_path / "设定集" / "主角卡.md",
+        protagonist_content,
     )
 
-    _write_text_if_missing(
-        project_path / "设定集" / "金手指设计.md",
-        "\n".join(
+    golden_finger_content = output_golden_finger.strip() if output_golden_finger else ""
+    if not golden_finger_content:
+        golden_finger_content = "\n".join(
             [
                 "# 金手指设计",
                 "",
@@ -331,7 +378,10 @@ def init_project(
                 "",
                 (golden_finger_templates.strip() + "\n") if golden_finger_templates else "(未找到金手指模板库)\n",
             ]
-        ),
+        ).rstrip() + "\n"
+    _write_text_if_missing(
+        project_path / "设定集" / "金手指设计.md",
+        golden_finger_content,
     )
 
     if antagonist_level:
@@ -353,7 +403,12 @@ def init_project(
             ),
         )
 
-    _write_text_if_missing(project_path / "大纲" / "总纲.md", _build_master_outline(int(target_chapters)))
+    outline_content = output_outline.strip() if output_outline else ""
+    if outline_content:
+        outline_content = _inject_volume_rows(outline_content, int(target_chapters)).rstrip() + "\n"
+    else:
+        outline_content = _build_master_outline(int(target_chapters))
+    _write_text_if_missing(project_path / "大纲" / "总纲.md", outline_content)
 
     _write_text_if_missing(
         project_path / "大纲" / "爽点规划.md",

+ 12 - 14
.claude/scripts/token_budget_report.md

@@ -34,22 +34,20 @@
 |------|---------|------|
 | chapter_outline | 728 | - |
 | protagonist_snapshot | 416 | - |
-| recent_summaries | 1,560 | - |
+| recent_summaries (3章) | ~936 | - |
 | location_context | 312 | - |
 | appearing_characters | 936 | - |
 | urgent_foreshadowing | 312 | - |
 | worldview_skeleton | 1,560 | - |
 | power_system_skeleton | 832 | - |
-| **合计** | **6,656** | 第100章时 |
+| **合计** | **~6,032** | 第100章时 |
 
 ## 3. 输出 Token 消耗
 
 | 组件 | 字符数 | Token数 |
 |------|-------|---------|
 | 章节正文 | 3000-5000 | 6000-10000 |
-| 章末标签 | ~350 | ~700 |
-| 章末摘要 | ~200 | ~400 |
-| **合计** | ~4550 | **~9,100** |
+| **合计** | 3000-5000 | **~6,000-10,000** |
 
 ## 4. 审查子代理 Token 消耗(每2章)
 
@@ -60,8 +58,9 @@
 | pacing-checker | 18,000 | 1,500 | 19,500 |
 | ooc-checker | 22,000 | 2,000 | 24,000 |
 | continuity-checker | 20,000 | 1,500 | 21,500 |
-| **5代理总计** | 98,000 | 8,500 | 106,500 |
-| **摊销/章** | - | - | **53,250** |
+| reader-pull-checker | 16,000 | 1,200 | 17,200 |
+| **6代理总计** | 114,000 | 9,700 | 123,700 |
+| **摊销/章** | - | - | **61,850** |
 
 ======================================================================
 ## 📋 单章 Token 预算汇总
@@ -69,20 +68,19 @@
 
 ### 输入 Token(上下文加载)
 - 必须加载参考文件: 1,076
-- Context Pack: 6,656
+- Context Pack: ~6,032
 - 按需场景参考(加权): 4,749
-- **输入小计: 12,481**
+- **输入小计: ~11,857**
 
 ### 输出 Token(内容生成)
 - 章节正文: ~8,000
-- 标签+摘要: ~1,100
-- **输出小计: 9,100**
+- **输出小计: ~8,000**
 
 ### 审查 Token(每章摊销)
-- 5个子代理/2章: 53,250
+- 6个子代理/2章: 61,850
 
 ======================================================================
-### 🎯 单章总预算: ~74,831 tokens
+### 🎯 单章总预算: ~81,700 tokens
 ======================================================================
 
 ## 6. 成本估算(API 价格)
@@ -95,7 +93,7 @@
 ## 7. 优化建议
 
 ### 高优先级
-- [ ] 摘要压缩:recent_summaries 从5章压缩到3章,节省 ~600 tokens
+- [ ] 摘要压缩:recent_summaries 已改为 3 章(节省 ~600 tokens)
 - [ ] 骨架精简:worldview/power_system 精简50%,节省 ~1,150 tokens
 - [ ] 审查合并:5个子代理合并为2个,节省 ~50,000 tokens/2章
 

+ 14 - 12
.claude/scripts/workflow_manager.py

@@ -184,7 +184,7 @@ def analyze_recovery_options(interrupt_info):
     step_id = current_step['id']
 
     # 基于Step ID的恢复策略
-    if step_id == 'Step 1':
+    if step_id in {'Step 1', 'Step 1.5'}:
         # Step 1中断:无副作用
         return [{
             'option': 'A',
@@ -197,8 +197,8 @@ def analyze_recovery_options(interrupt_info):
             ]
         }]
 
-    elif step_id == 'Step 2':
-        # Step 2中断:可能有半成品文件
+    elif step_id in {'Step 2', 'Step 2A', 'Step 2B'}:
+        # Step 2A/2B 中断:可能有半成品文件
         chapter_file = interrupt_info['artifacts'].get('chapter_file', {})
 
         # 使用 chapter_paths 模块定位章节文件(兼容新旧目录结构)
@@ -249,9 +249,9 @@ def analyze_recovery_options(interrupt_info):
                 'option': 'A',
                 'label': '重新执行审查',
                 'risk': 'medium',
-                'description': '重新调用5个审查员(并行)',
+                'description': '重新调用6个审查员(并行)',
                 'actions': [
-                    "重新调用5个审查员(并行)",
+                    "重新调用6个审查员(并行)",
                     "生成审查报告",
                     "继续 Step 4 润色"
                 ]
@@ -293,7 +293,7 @@ def analyze_recovery_options(interrupt_info):
             },
             {
                 'option': 'B',
-                'label': '删除润色稿,从 Step 2 重写',
+                'label': '删除润色稿,从 Step 2A 重写',
                 'risk': 'medium',
                 'description': f"删除 {chapter_path},重新生成章节内容",
                 'actions': [
@@ -415,16 +415,18 @@ def save_state(state):
     atomic_write_json(state_file, state, use_lock=True, backup=False)
 
 def get_pending_steps(command):
-    """获取待执行步骤列表 (v5.0)"""
+    """获取待执行步骤列表 (v5.2)"""
     if command == 'webnovel-write':
-        # v5.0 工作流:6 步
+        # v5.2 工作流:8 步(含 Step 1.5 & 2A/2B)
         # Step 1: Context Agent 搜集上下文
-        # Step 2: 生成章节内容 (纯正文,3000-5000字)
-        # Step 3: 审查 (5个Agent并行,只报告)
-        # Step 4: 润色 (基于审查报告修复 + 去AI痕迹)
+        # Step 1.5: 章节设计(开头/钩子/爽点模式)
+        # Step 2A: 生成粗稿
+        # Step 2B: 风格适配(可选)
+        # Step 3: 审查 (6个Agent并行,只报告)
+        # Step 4: 网文化润色
         # Step 5: Data Agent 处理数据链
         # Step 6: Git 备份
-        return ['Step 1', 'Step 2', 'Step 3', 'Step 4', 'Step 5', 'Step 6']
+        return ['Step 1', 'Step 1.5', 'Step 2A', 'Step 2B', 'Step 3', 'Step 4', 'Step 5', 'Step 6']
     elif command == 'webnovel-review':
         return ['Step 1', 'Step 2', 'Step 3', 'Step 4', 'Step 5', 'Step 6', 'Step 7', 'Step 8']
     # 其他命令...

+ 56 - 30
.claude/skills/webnovel-init/SKILL.md

@@ -114,25 +114,47 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-init/references/creativity/selling-po
 cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-init/references/worldbuilding/character-design.md"
 ```
 
-### 4.2 金手指核心设计
+### 4.2 按题材动态显示金手指选项
+
+**题材-金手指匹配表**:
+
+| 题材 | 推荐金手指 |
+|------|-----------|
+| 玄幻修仙 | 系统面板、签到打卡、老爷爷/传承、血脉觉醒 |
+| 都市异能 | 系统面板、重生记忆、异能觉醒、随身空间 |
+| 言情 | 重生记忆、随身空间、无金手指 |
+| 知乎短篇 | 单一特殊能力、无金手指 |
+| 规则怪谈 | 系统提示、规则解读能力 |
 
 **[AskUserQuestion Round 5]**
 
 | 问题 | 选项 |
 |------|------|
-| 金手指类型 | 系统面板型 / 签到打卡型 / 鉴定万物型 / 吞噬进化型 |
-| 系统性格 | 冷酷理性 / 傲娇话痨 / 沉默寡言 / 搞笑吐槽 |
+| 金手指类型 | 根据题材动态显示 + “无金手指” |
 | 成长曲线 | 前期爆发型 / 稳步提升型 / 厚积薄发型 |
 
-### 4.3 金手指细节设计
+### 4.3 根据金手指类型动态调整问题
 
-**[AskUserQuestion Round 6]**
+**系统面板型**
+- 系统性格 / 系统命名 / 代价或限制 / 升级节奏
 
-| 问题 | 选项 |
-|------|------|
-| 系统命名风格 | 天道类(天道系统/造化系统) / 商城类(万界商城/无限商店) / 功能类(无限升级/万能抽卡) / 自定义名称 |
-| 代价/限制 | 积分消耗型 / 任务惩罚型 / 生命值扣除型 / 无明显代价 |
-| 核心卖点方向 | 战力碾压型 / 智商压制型 / 收集养成型 / 感情治愈型 |
+**重生/穿越型**
+- 重生时间点 / 记忆完整度 / 先知程度 / 蝴蝶效应
+
+**老爷爷/器灵型**
+- 器灵性格 / 器灵实力 / 辅助方式 / 恢复条件
+
+**随身空间型**
+- 空间大小 / 特殊功能 / 升级方式
+
+**血脉/天赋型**
+- 血脉来源 / 觉醒条件 / 能力限制
+
+**异能觉醒型**(都市异能专用)
+- 异能来源 / 异能上限 / 代价或副作用 / 是否可进化
+
+**无金手指**
+- 主角天赋 / 特殊机遇 / 成长路线
 
 ---
 
@@ -153,7 +175,7 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-init/references/worldbuilding/world-r
 
 ### 5.2 世界观框架
 
-**[AskUserQuestion Round 7]** (可选)
+**[AskUserQuestion Round 6]** (可选)
 
 | 问题 | 选项 |
 |------|------|
@@ -178,7 +200,7 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-init/references/creativity/market-pos
 
 ### 6.2 市场定位与主角设计
 
-**[AskUserQuestion Round 8]**
+**[AskUserQuestion Round 7]**
 
 | 问题 | 选项 |
 |------|------|
@@ -188,7 +210,7 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-init/references/creativity/market-pos
 
 ### 6.3 反派与感情线设计
 
-**[AskUserQuestion Round 9]**
+**[AskUserQuestion Round 8]**
 
 | 问题 | 选项 |
 |------|------|
@@ -223,17 +245,22 @@ python "${CLAUDE_PLUGIN_ROOT}/scripts/init_project.py" \
   --core-selling-points "{points}"
 ```
 
-### 7.2 生成文件清单
+### 7.2 生成文件清单(含模板写入)
 
-| 文件 | 说明 |
-|------|------|
-| `.webnovel/state.json` | 运行时状态 |
-| `.webnovel/index.db` | 实体索引数据库 |
-| `设定集/世界观.md` | 世界设定 |
-| `设定集/力量体系.md` | 力量体系 |
-| `设定集/主角卡.md` | 主角卡 |
-| `设定集/金手指设计.md` | 金手指设计 |
-| `大纲/总纲.md` | 总纲 |
+| 文件 | 说明 | 生成时机 | 写入路径 |
+|------|------|---------|---------|
+| `.webnovel/state.json` | 运行时状态 | init Phase 7 | `.webnovel/state.json` |
+| `.webnovel/index.db` | 实体索引数据库 | init Phase 7 | `.webnovel/index.db` |
+| `设定集/世界观.md` | 世界观设定模板 | init Phase 7 | `设定集/世界观.md` |
+| `设定集/力量体系.md` | 力量体系模板 | init Phase 7 | `设定集/力量体系.md` |
+| `设定集/主角卡.md` | 主角卡模板 | init Phase 7 | `设定集/主角卡.md` |
+| `设定集/金手指设计.md` | 金手指设计模板 | init Phase 7 | `设定集/金手指设计.md` |
+| `大纲/总纲.md` | 总纲模板 | init Phase 7 | `大纲/总纲.md` |
+
+**模板引用方式**:
+```bash
+cat "${CLAUDE_PLUGIN_ROOT}/templates/output/设定集-世界观.md" | 填充变量 > 设定集/世界观.md
+```
 
 ---
 
@@ -268,12 +295,11 @@ git init && git add . && git commit -m "初始化网文项目:{title}"
 | Round 2 | Phase 2 | 1 | All |
 | Round 3 | Phase 2 | 2 | All |
 | Round 4 | Phase 3 | 2 | All |
-| Round 5 | Phase 4 | 3 | Standard/Deep |
-| Round 6 | Phase 4 | 3 | Standard/Deep |
-| Round 7 | Phase 5 | 3 | Standard/Deep |
+| Round 5 | Phase 4 | 2 | Standard/Deep |
+| Round 6 | Phase 5 | 3 | Standard/Deep |
+| Round 7 | Phase 6 | 3 | Deep |
 | Round 8 | Phase 6 | 3 | Deep |
-| Round 9 | Phase 6 | 3 | Deep |
 
-**Quick 模式**: Round 1-4 (4轮,约6个问题)
-**Standard 模式**: Round 1-7 (7轮,约15个问题)
-**Deep 模式**: Round 1-9 (9轮,约21个问题)
+**Quick 模式**: Round 1-4
+**Standard 模式**: Round 1-6
+**Deep 模式**: Round 1-8

+ 5 - 2
.claude/skills/webnovel-plan/SKILL.md

@@ -251,17 +251,20 @@ ls 大纲/第*卷*.md 2>/dev/null
 |------|------|
 | 骨架已生成,继续生成章节详情? | 生成第1-10章 / 生成第1-20章 / 全部生成(可能超时) / 先保存骨架 |
 
-**每批章节格式**(简化版,控制字数):
+**每批章节格式**(增强版,控制字数):
 
 ```markdown
 ## 第 {batch_start}-{batch_end} 章详情
 
 ### 第 {N} 章:{标题}
 - **目标**: {20字以内}
+- **开头类型**: {冲突开场/悬疑开场/动作开场/对话开场/氛围开场}
 - **爽点**: {类型} - {30字以内}
 - **Strand**: {Quest|Fire|Constellation}
 - **实体**: {新增角色/物品,如有}
-- **钩子**: {章末悬念,20字以内}
+- **钩子类型**: {危机钩/悬念钩/反转钩/期待钩/代价钩}
+- **钩子内容**: {章末悬念,30字以内}
+- **接住上章**: {如何接住上章钩子,20字以内}
 ```
 
 **每批约 1500-2500 字,避免超时。**

+ 23 - 17
.claude/skills/webnovel-query/references/system-data-flow.md

@@ -1,7 +1,7 @@
 ---
 name: system-data-flow
 purpose: 项目初始化和状态查询时加载,理解数据结构
-version: "5.1"
+version: "5.2"
 ---
 
 <context>
@@ -22,6 +22,7 @@ version: "5.1"
     ├── index.db            # SQLite 主存储:实体/别名/关系/状态变化/章节/场景
     ├── workflow_state.json # 工作流断点(用于 /webnovel-resume)
     ├── vectors.db          # RAG 向量数据库
+    ├── summaries/          # 章节摘要(chNNNN.md)
     └── archive/            # 归档数据(不活跃角色/已回收伏笔)
 ```
 
@@ -40,7 +41,7 @@ version: "5.1"
 | strand_tracker | state.json | state.json (保留) |
 | disambiguation_* | state.json | state.json (保留) |
 
-## v5.1 双 Agent 架构
+## v5.2 双 Agent 架构
 
 ```
 写作前: Context Agent 读取数据 → 组装上下文包
@@ -51,7 +52,8 @@ version: "5.1"
 
 写作后: Data Agent 处理正文 → AI 提取实体 → 写入数据链
         ├── 写入 index.db(实体/别名/状态变化/关系)
-        └── 更新 state.json(进度/主角快照)
+        ├── 更新 state.json(进度/主角快照 + chapter_meta)
+        └── 写入 summaries/chNNNN.md(章节摘要)
 
 Context Agent (读) ←→ index.db + state.json ←→ Data Agent (写)
 ```
@@ -82,41 +84,44 @@ Context Agent (读) ←→ index.db + state.json ←→ Data Agent (写)
 | `api_client.py` | LLM API 调用封装 |
 | `config.py` | 配置管理 |
 
-## 每章数据链(v5.1 顺序)
+## 每章数据链(v5.2 顺序)
 
 ```
-1. Context Agent 组装上下文包
+1. Context Agent 组装创作任务书
    → 读取 state.json(精简版:进度/配置)
    → SQL 查询 index.db(核心实体/按需实体)
    → RAG 检索(相关场景)
-   → 输出上下文包 JSON
 
-2. Writer 生成章节内容
-   → 纯正文,3000-5000 字
-   → 无需写 XML 标签
+2. Step 1.5 章节设计
+   → 选开头/钩子/爽点模式(避开最近3章)
 
-3. 审查 (5 个 Agent 并行)
-   → 爽点/一致性/节奏/OOC/连贯性检查
+3. Writer 生成章节内容
+   → 2A 粗稿(纯正文)
+   → 2B 风格适配(可选)
+
+4. 审查 (6 个 Agent 并行)
+   → 爽点/一致性/节奏/OOC/连贯性/追读力检查
    → 输出审查报告
 
-4. 润色
+5. 网文化润色
    → 基于审查报告修复问题
-   → AI 痕迹清除
+   → 强化口感规则
 
-5. Data Agent 处理数据链
+6. Data Agent 处理数据链
    → AI 实体提取(替代 XML 标签解析)
    → 实体消歧(置信度策略)
    → 写入 index.db(实体/别名/状态变化/关系)
-   → 更新 state.json(进度/主角快照)
+   → 更新 state.json(进度/主角快照 + chapter_meta)
+   → 写入 summaries/chNNNN.md(章节摘要)
    → 向量嵌入 (RAG)
    → 风格样本评估
 
-6. Git 备份(强制)
+7. Git 备份(强制)
 ```
 
 > `update_state.py` 用于手动/脚本化更新 `progress`/`protagonist_state`/`strand_tracker` 等字段;主流程通常由 Data Agent 在处理数据链时同步推进进度。
 
-## state.json 精简结构 (v5.1)
+## state.json 精简结构 (v5.2)
 
 ```json
 {
@@ -142,6 +147,7 @@ Context Agent (读) ←→ index.db + state.json ←→ Data Agent (写)
   "disambiguation_warnings": [],
   "disambiguation_pending": [],
   "review_checkpoints": [],
+  "chapter_meta": {},
   "_migrated_to_sqlite": true
 }
 ```

+ 11 - 9
.claude/skills/webnovel-resume/references/workflow-resume.md

@@ -1,7 +1,7 @@
 ---
 name: workflow-resume
 purpose: 任务恢复时加载,指导中断恢复流程
-version: "5.1"
+version: "5.2"
 ---
 
 <context>
@@ -10,14 +10,16 @@ version: "5.1"
 
 <instructions>
 
-## Step 中断难度分级 (v5.1)
+## Step 中断难度分级 (v5.2)
 
 | Step | 名称 | 影响 | 难度 | 默认策略 |
 |------|------|------|------|----------|
 | Step 1 | Context Agent | 无副作用(仅读取) | ⭐ | 直接重新执行 |
-| Step 2 | 生成章节内容 | 半成品章节文件 | ⭐⭐ | **删除半成品**,从 Step 1 重新开始 |
+| Step 1.5 | 章节设计 | 结构未固化 | ⭐ | 重新设计 |
+| Step 2A | 生成粗稿 | 半成品章节文件 | ⭐⭐ | **删除半成品**,从 Step 1 重新开始 |
+| Step 2B | 风格适配 | 部分改写内容 | ⭐⭐ | 继续适配或回到 2A |
 | Step 3 | 审查 | 审查未完成 | ⭐⭐⭐ | 用户决定:重审或跳过 |
-| Step 4 | 润色 | 部分润色的文件 | ⭐⭐ | 继续润色或删除重写 |
+| Step 4 | 网文化润色 | 部分润色的文件 | ⭐⭐ | 继续润色或删除重写 |
 | Step 5 | Data Agent | 实体未提取完 | ⭐⭐ | 重新运行(幂等) |
 | Step 6 | Git 备份 | 未提交 | ⭐⭐⭐ | 检查暂存区,决定提交/回滚 |
 
@@ -73,18 +75,18 @@ python "${CLAUDE_PLUGIN_ROOT}/scripts/workflow_manager.py" clear
 <examples>
 
 <example>
-<input>Step 2 中断(最常见)</input>
+<input>Step 2A 中断(最常见)</input>
 <output>
 🔴 检测到中断任务:
 
 任务:/webnovel-write 7
-中断位置:Step 2 - 章节内容生成中
+中断位置:Step 2A - 章节内容生成中
 
 已完成:
   ✅ Step 1: Context Agent 搜集上下文
 
 未完成:
-  ⏸️ Step 2: 生成章节内容(已写1500字)
+  ⏸️ Step 2A: 生成章节内容(已写1500字)
   ⏹️ Step 3-6: 未开始
 
 恢复选项:
@@ -100,7 +102,7 @@ B) 回滚到 Ch6,放弃 Ch7 所有进度
 <output>
 恢复选项:
 A) 重新执行审查 ⚠️
-   - 调用5个审查员
+   - 调用6个审查员
    - 生成审查报告
    - 继续 Step 4 润色
 
@@ -121,7 +123,7 @@ A) 继续润色(推荐)⭐
    - 保存文件
    - 继续 Step 5(Data Agent)
 
-B) 删除润色稿,从 Step 2 重写
+B) 删除润色稿,从 Step 2A 重写
    - 删除 正文/第0007章.md
    - 重新生成章节内容
 

+ 7 - 5
.claude/skills/webnovel-review/SKILL.md

@@ -1,6 +1,6 @@
 ---
 name: webnovel-review
-description: Reviews chapter quality using 5 specialized checkers and generates comprehensive reports. Activates when user requests chapter review or /webnovel-review.
+description: Reviews chapter quality using 6 specialized checkers (including reader-pull) and generates comprehensive reports. Activates when user requests chapter review or /webnovel-review.
 allowed-tools: Read Grep Write Edit Bash Task AskUserQuestion
 ---
 
@@ -18,7 +18,7 @@ Copy and track progress:
 - [ ] Step 4: 加载常见错误 (cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-review/references/common-mistakes.md")
 - [ ] Step 5: 加载项目状态 (cat .webnovel/state.json)
 - [ ] Step 6: 确认上下文充足
-- [ ] Step 7: 调用 5 个检查员 (并行 Task)
+- [ ] Step 7: 调用 6 个检查员 (并行 Task)
 - [ ] Step 8: 生成审查报告
 - [ ] Step 9: 处理关键问题
 ```
@@ -73,9 +73,9 @@ cat .webnovel/state.json
 
 **如有缺失 → 返回对应 Step**
 
-## Step 7: 调用 5 个检查员(并行)
+## Step 7: 调用 6 个检查员(并行)
 
-**使用 Task 工具并行调用 5 个专职检查员**:
+**使用 Task 工具并行调用 6 个专职检查员**:
 
 调用格式示例(所有检查员并行执行):
 - 调用 `high-point-checker` 子代理:审查章节 {range},重点检查爽点密度和多样性
@@ -83,6 +83,7 @@ cat .webnovel/state.json
 - 调用 `pacing-checker` 子代理:审查章节 {range},重点检查 Strand 分布
 - 调用 `ooc-checker` 子代理:审查章节 {range},重点检查角色行为一致性
 - 调用 `continuity-checker` 子代理:审查章节 {range},重点检查时间线和剧情连贯
+- 调用 `reader-pull-checker` 子代理:审查章节 {range},重点检查章末钩子与追读动机
 
 **注意**:Claude 会自动根据描述匹配并调用对应的子代理
 
@@ -104,7 +105,8 @@ cat .webnovel/state.json
 | 节奏控制 | X/10 | ... |
 | 人物塑造 | X/10 | ... |
 | 连贯性 | X/10 | ... |
-| **总评** | **X/50** | **等级** |
+| 追读力 | X/10 | ... |
+| **总评** | **X/60** | **等级** |
 
 ## 📋 修改优先级
 

+ 20 - 8
.claude/skills/webnovel-review/references/core-constraints.md

@@ -1,7 +1,7 @@
 ---
 name: core-constraints
 purpose: 每次章节写作前加载,确保三大定律执行
-version: "5.1"
+version: "5.2"
 ---
 
 <context>
@@ -15,16 +15,28 @@ version: "5.1"
 | 定律 | 规则 | 检查方式 |
 |------|------|----------|
 | **大纲即法律** | 严格执行大纲,不得擅自发挥 | 审查时对照大纲 |
-| **设定即物理** | 实力/招式/物品 ≤ state.json | 写作前查询确认 |
+| **设定即物理** | 实力/招式/物品 ≤ index.db 记录 | 写作前查询确认 |
 | **发明需识别** | 新实体由 Data Agent 自动提取 | 章节完成后处理 |
 
-## 新实体处理流程(v5.1
+## 新实体处理流程(v5.2
 
-v5.1 不再要求在正文中写 XML 标签:
+v5.2 不再要求在正文中写 XML 标签:
 1. **写作时**: 直接写纯正文,新角色/地点/物品正常描写
 2. **完成后**: Data Agent 自动识别新实体并写入 index.db
 3. **不确定实体**: Data Agent 标记为 uncertain,由人工确认
 
+## 钩子硬约束(新增)
+
+- 开头 120 字必须出现冲突/风险/强情绪之一
+- 结尾 80-150 字设置未闭合问题/危险逼近/信息反转
+- 禁止结束在“回去休息了”或类似收尾
+
+## 网文口感基准(新增)
+
+- 禁止连续 400 字纯解释/背景
+- 每 800-1200 字至少一次局面变化
+- 对话每句必须带意图
+
 ## 爽点密度要求
 
 - 每章 ≥1 个小爽点(单一模式)
@@ -52,17 +64,17 @@ v5.1 不再要求在正文中写 XML 标签:
 <example>
 <input>主角需要使用"天雷掌"击败敌人</input>
 <output>
-1. 检查 state.json → protagonist_state.skills 是否包含"天雷掌"
+1. 查询 index.db 中是否有"天雷掌"技能
 2. 若有:直接使用
 3. 若无:在正文中描写获得途径,Data Agent 会自动提取
 </output>
 </example>
 
 <example type="edge_case">
-<input>剧情需要主角展示筑基期实力,但 state.json 显示练气期</input>
+<input>剧情需要主角展示筑基期实力,但 index.db 显示练气期</input>
 <output>
 ❌ 直接写筑基期战力 → 违反"设定即物理"
-✅ 先安排突破场景,更新 state.json,再展示新实力
+✅ 先安排突破场景,Data Agent 更新 index.db,再展示新实力
 </output>
 </example>
 
@@ -71,5 +83,5 @@ v5.1 不再要求在正文中写 XML 标签:
 <errors>
 ❌ 新实体描写模糊(无法自动识别) → ✅ 确保新实体有明确名称和描写
 ❌ 主角突然会新技能 → ✅ 先描写获得途径
-❌ 忘记更新 state.json → ✅ Data Agent 自动处理
+❌ 章末无钩子 → ✅ 重写结尾,制造未闭合问题/危险/反转
 </errors>

+ 135 - 141
.claude/skills/webnovel-write/SKILL.md

@@ -1,6 +1,6 @@
 ---
 name: webnovel-write
-description: Writes webnovel chapters (3000-5000 words) using v5.1 dual-agent architecture. Context Agent gathers context, writer produces pure text (no XML tags), review agents report issues, polish fixes problems, Data Agent extracts entities with AI.
+description: Writes webnovel chapters (3000-5000 words) using v5.2 architecture. Context Agent outputs creative brief, writer produces pure text, review agents report issues, webnovel polish fixes problems, Data Agent extracts entities and records hooks/patterns.
 allowed-tools: Read Write Edit Grep Bash Task
 ---
 
@@ -11,11 +11,13 @@ allowed-tools: Read Write Edit Grep Bash Task
 ⚠️ **强制要求**: 开始写作前,**必须复制以下清单**到回复中并逐项勾选。跳过任何步骤视为工作流不完整。
 
 ```
-章节创作进度 (v5.1):
-- [ ] Step 1: Context Agent 搜集上下文
-- [ ] Step 2: 生成章节内容 (纯正文,3000-5000字)
-- [ ] Step 3: 审查 (5个Agent并行,输出汇总表格)
-- [ ] Step 4: 润色 (加载指南 + AI检测 + 输出检查清单)
+章节创作进度 (v5.2):
+- [ ] Step 1: Context Agent 搜集上下文(创作任务书)
+- [ ] Step 1.5: 章节设计(开头/钩子/爽点模式)
+- [ ] Step 2A: 生成粗稿(剧情正确、场面成立)
+- [ ] Step 2B: 风格适配器(网文化改写,剧情不变)
+- [ ] Step 3: 审查 (6个Agent并行,输出汇总表格)
+- [ ] Step 4: 网文化润色(基于审查报告)
 - [ ] Step 5: Data Agent 处理数据链
 - [ ] Step 6: Git 备份
 ```
@@ -27,6 +29,20 @@ allowed-tools: Read Write Edit Grep Bash Task
 
 ---
 
+## 模式说明(可选)
+
+```
+/webnovel-write --mode fast    # 快速模式:跳过 Step 2B
+/webnovel-write --mode minimal # 极简模式:跳过 Step 2B + 仅运行3个核心 checker
+```
+
+**模式影响**:
+- **标准模式**: 完整执行 Step 1-6
+- **快速模式**: 跳过 Step 2B(风格适配),其余照常
+- **极简模式**: 跳过 Step 2B + 仅运行 3 个核心审查(consistency / continuity / ooc)
+
+---
+
 ## Step 1: Context Agent 搜集上下文
 
 **调用 Context Agent**:
@@ -44,29 +60,55 @@ allowed-tools: Read Write Edit Grep Bash Task
 **Agent 自动完成**:
 1. 读取本章大纲,分析需要什么信息
 2. 读取 state.json 获取主角状态快照
-3. 调用 index.db (v5.1 schema) 查询相关实体和别名
+3. 查询 index.db (v5.1 schema) 召回实体/别名/关系
 4. 调用 data_modules.rag_adapter 语义检索
 5. Grep 设定集搜索相关设定
 6. 评估伏笔紧急度
 7. 选择风格样本
-8. 组装上下文包 JSON (v5.1)
-
-**输出**:上下文包 JSON,包含:
-- `core`: 大纲、主角快照、最近摘要
-- `scene`: 地点上下文、出场角色、紧急伏笔
-- `global`: 世界观骨架、力量体系、风格样本
-- `rag`: 语义检索召回的相关场景
-- `alerts`: 关键风险提示(如消歧警告/待确认项)
-
-**失败处理**:
+8. 组装**创作任务书**(人话版)
+
+**输出**:创作任务书(非 JSON),包含:
+- 本章核心任务(冲突一句话、必须完成、绝对不能)
+- 接住上章(上章钩子、读者期待、开头必须)
+- 出场角色(状态、动机、情绪底色、说话风格、红线)
+- 场景与力量约束(地点、可用/禁用能力)
+- 风格指导(本章类型、参考样本、最近模式、本章建议)
+- 伏笔管理(必须处理、可选提及)
+- 连贯性检查点(时间、位置、情绪)
+- 章末钩子设置(建议类型、禁止事项)
+
+**失败处理**:
 - 如果大纲不存在 → 提示用户先创建大纲
 - 如果 state.json 不存在 → 提示用户初始化项目
 
 ---
 
-## Step 2: 生成章节内容
+## Step 1.5: 章节设计(新增)
+
+**目标**: 在写作前明确本章结构与变体,避免模式重复。
+
+**加载变体池(必须执行)**:
+```bash
+cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-write/references/style-variants.md"
+```
+
+**输出内容**:
+- 核心冲突一句话
+- 开头类型(冲突开场/悬疑开场/动作开场/对话开场/氛围开场)
+- 钩子类型(危机钩/悬念钩/反转钩/期待钩/代价钩)
+- 爽点执行模式(装逼打脸/扮猪吃虎/越级反杀/打脸权威/反派翻车/甜蜜超预期)
+- 情绪节奏(低→高/高→低/低→高→低/平稳)
+- 信息密度(low/medium/high)
+
+**差异化检查**:
+- 查询 `state.json → chapter_meta` 最近 3 章模式
+- 避免与最近 3 章“开头类型/钩子类型/情绪节奏”重复
+
+---
+
+## Step 2A: 生成粗稿(剧情正确)
 
-**字数**: 3000-5000 字
+**字数**: 3000-5000 字(短章 <2000 字需声明)
 
 **核心原则**:
 - **大纲即法律**: 100% 执行大纲
@@ -103,23 +145,40 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-write/references/core-constraints.md"
 
 **输出格式**:
 - Markdown 文件: `正文/第{NNNN}章.md`
-- 章节末尾追加摘要(见模板)
-- 纯正文,Data Agent 会自动提取实体
+- **不追加摘要**(摘要由 Data Agent 独立写入 `.webnovel/summaries/`)
+
+---
+
+## Step 2B: 风格适配器(网文化改写)
+
+**跳过条件**: fast / minimal 模式跳过
+
+**加载风格适配器**:
+```bash
+cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-write/references/style-adapter.md"
+```
+
+**目标**:
+- 保持剧情不变
+- 提升网文口感(短句、动作、对白张力、情绪反应)
+- 强化开头冲突与章末钩子
 
 ---
 
 ## Step 3: 审查
 
-⚠️ **强制要求**: 必须在**同一条消息**中并行调用全部 5 个 Agent。缺少任何一个视为步骤未完成,**禁止进入 Step 4**。
+⚠️ **强制要求**: 必须在**同一条消息**中并行调用全部审查 Agent(除非 minimal 模式)
 
 **执行命令(不可修改)**:
 
-在一条消息中发送 5 个 Task 工具调用,每个调用需传入以下公共参数:
+在一条消息中发送 Task 工具调用,每个调用需传入以下公共参数:
 - project_root: {PROJECT_ROOT}
 - storage_path: .webnovel/
 - state_file: .webnovel/state.json
 - chapter_file: "正文/第{NNNN}章.md"
 
+**标准/快速模式:6 个 Agent**
+
 | # | subagent_type | 必须 | 说明 |
 |---|---------------|------|------|
 | 1 | `high-point-checker` | ✅ | 爽点密度检查 |
@@ -127,50 +186,54 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-write/references/core-constraints.md"
 | 3 | `pacing-checker` | ✅ | Strand 节奏检查 |
 | 4 | `ooc-checker` | ✅ | 人物 OOC 检查 |
 | 5 | `continuity-checker` | ✅ | 连贯性检查 |
+| 6 | `reader-pull-checker` | ✅ | 追读力检查 |
+
+**极简模式:仅 3 个核心 Agent**
+- `consistency-checker`
+- `continuity-checker`
+- `ooc-checker`
 
-**验证**: 收到全部 5 份报告后,**必须输出以下汇总表格**:
+**验证**: 收到全部报告后,**必须输出以下汇总表格**:
 
 ```
 ┌─────────────────────────────────────────────────┐
 │ 审查汇总 - 第 {chapter_num} 章                    │
-├─────────────────────┬───────────┬───────────────┤
-│ Agent               │ 结果      │ 关键问题数     │
-├─────────────────────┼───────────┼───────────────┤
-│ high-point-checker  │ PASS/FAIL │ {N}           │
-│ consistency-checker │ PASS/FAIL │ {N}           │
-│ pacing-checker      │ PASS/FAIL │ {N}           │
-│ ooc-checker         │ PASS/FAIL │ {N}           │
-│ continuity-checker  │ PASS/FAIL │ {N}           │
-├─────────────────────┴───────────┴───────────────┤
+├──────────────────────┬───────────┬──────────────┤
+│ Agent                │ 结果      │ 关键问题数    │
+├──────────────────────┼───────────┼──────────────┤
+│ high-point-checker   │ PASS/FAIL │ {N}          │
+│ consistency-checker  │ PASS/FAIL │ {N}          │
+│ pacing-checker       │ PASS/FAIL │ {N}          │
+│ ooc-checker          │ PASS/FAIL │ {N}          │
+│ continuity-checker   │ PASS/FAIL │ {N}          │
+│ reader-pull-checker  │ PASS/FAIL │ {N}          │
+├──────────────────────┴───────────┴──────────────┤
 │ critical issues: {N}  |  high issues: {N}       │
 │ 是否可进入润色: {是/否}                           │
 └─────────────────────────────────────────────────┘
 ```
 
 **Only proceed to Step 4 when:**
-1. 已收到全部 5 份审查报告
+1. 已收到全部审查报告(或 minimal 模式仅 3 份)
 2. 已输出汇总表格
 
+> **Minimal 模式**: 汇总表格仅列出已执行的 3 个 Agent。
+
 ---
 
-## Step 4: 润色 (基于审查报告)
+## Step 4: 网文化润色(基于审查报告)
 
-⚠️ **强制要求**: 必须按以下顺序执行全部子步骤(4.0-4.5),不可跳过。
+⚠️ **强制要求**: 必须按以下顺序执行全部子步骤(4.0-4.4),不可跳过。
 
 ### 4.0 加载润色指南(必须先执行)
 
-**执行命令(不可跳过)**:
 ```bash
 cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-write/references/polish-guide.md"
 cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-write/references/writing/typesetting.md"
 ```
 
-如果未执行以上命令,视为润色步骤无效。
-
 ### 4.1 修复审查问题
 
-根据 Step 3 汇总表格中的 issues 列表针对性修改:
-
 | 严重度 | 处理方式 |
 |-------|---------|
 | critical | **必须修复**,否则记录 deviation |
@@ -178,55 +241,24 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-write/references/writing/typesetting.
 | medium | 建议修复 |
 | low | 可选修复 |
 
-| 问题类型 | 修复方式 |
-|---------|---------|
-| OOC | 调整角色言行,符合人设 |
-| POWER_CONFLICT | 修改能力描述,符合当前境界 |
-| TIMELINE_ISSUE | 调整时间线描述 |
-| PACING_IMBALANCE | 调整 Strand 比例 |
-| LOW_COOL_POINTS | 增加爽点密度 |
-
-### 4.2 AI痕迹检测(必须执行)
-
-使用 Grep 工具检测以下关键词:
+### 4.2 网文口感硬规则检查
 
-| 类型 | 关键词模式 | 警戒线 | 目标值 |
-|-----|-----------|-------|--------|
-| 总结词 | `综合\|总之\|由此可见\|总而言之` | > 1次/1000字 | 0次 |
-| 列举结构 | `首先\|其次\|最后\|第一\|第二\|第三` | > 0.5次/1000字 | 0次 |
-| 学术词 | `而言\|某种程度上\|本质上` | > 3次/1000字 | < 1次 |
-| 因果连词 | `因为\|所以\|由于\|因此` | > 5次/1000字 | < 3次 |
+- 开头 120 字必须出现冲突/风险/强情绪
+- 每 800-1200 字至少一次局面变化
+- 结尾 80-150 字设置钩子
+- 对话每句必须带意图
+- 连续 400 字纯解释 → 必须打散
 
-如超标,必须修改后重新检测。
+### 4.3 AI 痕迹检测(辅助提醒)
 
-### 4.3 自然化处理
+**注意**: 词频统计仅作为提醒,不再作为硬性门槛。若明显超标,请修复并简要说明。
 
-| 指标 | 不达标 | 达标 |
-|-----|-------|------|
-| 停顿词 | < 0.5次/500字 | 1-2次/500字 |
-| 不确定表达 | 0次 | ≥ 2次/章 |
-| 短句占比 | < 20% | 30-50% |
-| 口语词 | 0次/1000字 | ≥ 2次/1000字 |
+- 总结词:`综合|总之|由此可见|总而言之`
+- 列举结构:`首先|其次|最后|第一|第二|第三`
+- 学术词:`而言|某种程度上|本质上`
+- 因果连词:`因为|所以|由于|因此`
 
-**自然化检测(必须执行)**:
-- 停顿词:`嗯\|这个\|那什么\|怎么说呢`
-- 不确定表达:`大概\|应该\|似乎\|好像`
-- 口语词:`咋回事\|得了\|行吧\|算了`
-- 短句占比:抽样 30 句(按 `。!?` 分句),≤25 字视为短句,目标 30-50%
-
-**排版检查(必须执行)**(见 typesetting.md):
-- 对话换人换行;长段落(5行以上)拆分;场景切换留空行/分隔;章末钩子
-
-### 4.4 润色红线
-
-- ❌ 改变情节走向 → 违反"大纲即法律"
-- ❌ 修改主角实力 → 违反"设定即物理"
-- ❌ 改变人物关系 → 违反设定
-- ❌ 删除伏笔 → 破坏长线剧情
-
-### 4.5 输出检查清单(必须输出)
-
-润色完成后,**必须输出以下检查清单**:
+### 4.4 输出检查清单(必须输出)
 
 ```
 ┌─────────────────────────────────────────────────┐
@@ -237,18 +269,12 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-write/references/writing/typesetting.
 │ [x] critical issues 已修复: {是/否/无}          │
 │ [x] high issues 已修复: {是/否/无}              │
 ├─────────────────────────────────────────────────┤
-│ AI痕迹检测:                                     │
-│   - 总结词: {N}次 {达标/超标}                    │
-│   - 列举结构: {N}次 {达标/超标}                  │
-│   - 学术词: {N}次 {达标/超标}                    │
-│   - 因果连词: {N}次 {达标/超标}                  │
-├─────────────────────────────────────────────────┤
-│ 自然化检测:                                     │
-│   - 停顿词: {N}次 {达标/偏少/偏多}               │
-│   - 不确定表达: {N}次 {达标/偏少}                │
-│   - 口语词: {N}次 {达标/偏少}                    │
-│   - 短句占比: {X}% {达标/偏低/偏高}              │
+│ 网文口感检查:                                   │
+│   - 开头120字冲突: {是/否}                       │
+│   - 局面变化频率: {达标/偏少}                    │
+│   - 章末钩子: {是/否}                            │
 ├─────────────────────────────────────────────────┤
+│ AI痕迹提醒: {已检查/未检查}                      │
 │ [x] 未违反润色红线                              │
 │ 是否可进入 Data Agent: {是/否}                  │
 └─────────────────────────────────────────────────┘
@@ -257,9 +283,8 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-write/references/writing/typesetting.
 **Only proceed to Step 5 when:**
 1. 已加载 polish-guide.md + typesetting.md
 2. 已修复所有 critical/high issues(或记录 deviation)
-3. AI 痕迹检测全部达标
-4. 自然化/排版检查已完成(不足则记录 deviation)
-5. 已输出检查清单
+3. 网文口感硬规则已达标(不足则记录 deviation)
+4. 已输出检查清单
 
 **输出**: 润色后的章节文件(覆盖原文件)
 
@@ -284,29 +309,14 @@ cat "${CLAUDE_PLUGIN_ROOT}/skills/webnovel-write/references/writing/typesetting.
 **Agent 自动完成**:
 
 1. **AI 实体提取**(Agent 内置,无需外部 LLM)
-   - 从正文中语义提取实体
-   - 匹配已有实体库,识别新实体
-   - 识别状态变化(境界/位置/关系)
-
-2. **实体消歧**
-   - 高置信度 (>0.8): 自动采用
-   - 中置信度 (0.5-0.8): 采用但记录 warning
-   - 低置信度 (<0.5): 标记待人工确认
-
+2. **实体消歧**(高/中/低置信度策略)
 3. **写入存储**
-   - 更新 state.json (精简状态)
-   - 更新 index.db (v5.1 schema: entities/aliases/state_changes)
-   - 注册新别名到 aliases 表
-
-4. **AI 场景切片**
-   - 按地点/时间/视角切分场景
-   - 生成场景摘要
-
-5. **向量嵌入**
-   - 调用 data_modules.rag_adapter 存入向量库
-
-6. **风格样本评估**
-   - 如果 review_score > 80,提取高质量片段作为样本候选
+   - 更新 state.json (精简状态 + chapter_meta)
+   - 更新 index.db (实体/别名/状态变化/关系)
+4. **AI 场景切片**(生成场景摘要)
+5. **向量嵌入**(rag_adapter)
+6. **风格样本评估**(review_score > 80)
+7. **摘要分离存储**:写入 `.webnovel/summaries/ch{NNNN}.md`
 
 **输出**:
 ```json
@@ -330,23 +340,6 @@ git add . && git commit -m "Ch{chapter_num}: {title}"
 
 ---
 
-## 章节摘要模板
-
-章节末尾追加:
-
-```markdown
----
-## 本章摘要
-**剧情**: {主要事件}
-**人物**: {角色互动}
-**状态变化**: {实力/位置/关系}
-**伏笔**: [埋设] / [回收]
-**承接点**: {下章衔接}
-**压扬比例**: 压{X}扬{Y} ({genre}类型标准)
-```
-
----
-
 ## 错误处理
 
 ### Context Agent 失败
@@ -384,13 +377,14 @@ git add . && git commit -m "Ch{chapter_num}: {title}"
 ├─────────────────────────────────────────────────┤
 │ 1. [x] 字数: {N}字 (3000-5000)                  │
 │ 2. [x] 大纲执行: 100%                           │
-│ 3. [x] 审查Agent: 5/5 已调用         
+│ 3. [x] 审查Agent: {6/6 or 3/3} 已调用
 │ 4. [x] 审查汇总表格: 已输出                      │
 │ 5. [x] polish-guide.md: 已加载                  │
-│ 6. [x] AI痕迹检测: 已执行 
+│ 6. [x] 网文口感规则: 已检查
 │ 7. [x] 润色检查清单: 已输出                      │
 │ 8. [x] Data Agent: 成功提取 {N} 个实体          │
-│ 9. [x] Git: 已提交 ({commit_hash})              │
+│ 9. [x] summaries: 已生成 ch{NNNN}.md            │
+│ 10.[x] Git: 已提交 ({commit_hash})              │
 ├─────────────────────────────────────────────────┤
 │ 最终状态: {成功/有deviation}                     │
 └─────────────────────────────────────────────────┘

+ 15 - 2
.claude/skills/webnovel-write/references/core-constraints.md

@@ -1,7 +1,7 @@
 ---
 name: core-constraints
 purpose: 每次章节写作前加载,确保三大定律执行
-version: "5.1"
+version: "5.2"
 ---
 
 <context>
@@ -20,12 +20,24 @@ version: "5.1"
 
 ## 新实体处理流程
 
-v5.1 不再要求在正文中写 XML 标签。新实体由 Data Agent 在章节完成后自动提取:
+v5.2 不再要求在正文中写 XML 标签。新实体由 Data Agent 在章节完成后自动提取:
 
 1. **写作时**: 直接写纯正文,新角色/地点/物品正常描写
 2. **完成后**: Data Agent 自动识别新实体并写入 index.db
 3. **不确定实体**: Data Agent 标记为 uncertain,由人工确认
 
+## 钩子硬约束(新增)
+
+- 开头 120 字必须出现冲突/风险/强情绪之一
+- 结尾 80-150 字设置未闭合问题/危险逼近/信息反转
+- 禁止结束在“回去休息了”或类似收尾
+
+## 网文口感基准(新增)
+
+- 禁止连续 400 字纯解释/背景
+- 每 800-1200 字至少一次局面变化
+- 对话每句必须带意图
+
 ## 爽点密度要求
 
 - 每章 ≥1 个小爽点(单一模式)
@@ -72,4 +84,5 @@ v5.1 不再要求在正文中写 XML 标签。新实体由 Data Agent 在章节
 <errors>
 ❌ 主角突然会新技能 → ✅ 先在正文中安排获得途径
 ❌ 实力设定不一致 → ✅ 写作前查询 index.db 确认
+❌ 章末无钩子 → ✅ 重写结尾,制造未闭合问题/危险/反转
 </errors>

+ 49 - 195
.claude/skills/webnovel-write/references/polish-guide.md

@@ -1,24 +1,23 @@
 ---
 name: polish-guide
-purpose: 章节生成后的润色阶段加载,基于审查报告修复问题 + 去除AI痕迹
-version: "5.1"
+purpose: 章节生成后的润色阶段加载,基于审查报告修复问题 + 强化网文口感
+version: "5.2"
 ---
 
 <context>
-此文件用于内容润色,v5.1 支持基于审查报告的问题修复
+此文件用于内容润色,v5.2 强调网文口感与追读力
 
-润色步骤现在接收两个输入:
+润色步骤接收两个输入:
 1. 章节正文
-2. 审查报告 (来自 5 个 checker agents)
+2. 审查报告(来自 6 个 checker agents)
 </context>
 
 <instructions>
 
-## v5.1:基于审查报告修复
+## v5.2:基于审查报告修复
 
 ### 输入格式
 
-润色步骤会收到审查报告,格式如下:
 ```json
 {
   "overall_score": 85,
@@ -56,176 +55,67 @@ version: "5.1"
 | **LOW_COOL_POINTS** (爽点不足) | 增加爽点密度,补充打脸/升级/收获等元素 |
 | **CONTINUITY_BREAK** (连贯断裂) | 补充过渡句,连接断裂的场景 |
 
-### 修复示例
+---
 
-**OOC 修复**:
-```
-问题:林天(隐忍冷静)突然暴怒,缺少触发原因
-修复前:林天怒吼一声:"你找死!"冲向对手
-修复后:对方的话触及了林天的底线——那是关于他家人的羞辱。
-        林天眼中闪过一丝寒芒,"你找死。"声音平静,却让人毛骨悚然。
-```
+## 网文化规则(硬约束)
 
-**POWER_CONFLICT 修复**:
-```
-问题:筑基3层使用金丹期技能"破空斩"
-修复前:林天使出破空斩,剑芒划破虚空
-修复后:林天运起全身斗气,使出了筑基期的极限一击——裂地斩
-```
+1. **开头 120 字必须出现冲突/风险/强情绪**
+2. **每 800-1200 字至少一次局面变化**(转折、推进、意外、立场变化)
+3. **结尾 80-150 字必须设置钩子**(未闭合问题/危险逼近/信息反转)
+4. **对话每句必须带意图**(试探/威胁/诱导/掩饰)
+5. **抽象判断句 → 动作/反应/代价**(把结论写成行为)
+
+**章长适配**:
+- 标准章(3000-5000字):全部执行
+- 短章/过场章(<2000字):
+  - 开头冲突可放宽至前 200 字
+  - 局面变化频率可放宽为每 1500 字一次
+  - 钩子强度允许为 weak
 
 ---
 
-## AI生成特征识别
+## AI 痕迹检测(辅助提醒)
+
+> 词频统计**仅作为提醒**,不再作为硬性门槛。若明显超标,需修复并简要说明。
 
 ### 常见AI痕迹
 
 | 特征 | 表现 |
 |------|------|
 | 句式规整 | 句子长度相近,结构相似 |
-| 模式化词汇 | "首先、其次、最后"、"值得注意的是" |
-| 过度连接 | 大量使用"然而、因此、此外" |
-| 缺乏转折 | 逻辑过于顺畅,缺少自然跳跃 |
+| 模式化词汇 | “首先、其次、最后”、“值得注意的是” |
+| 过度连接 | 大量使用“然而、因此、此外” |
 | 情感平淡 | 缺乏个性化情绪表达 |
-| 信息密集 | 每句都有信息,缺少留白 |
-
-### 高频AI词汇替换表
-
-| AI词汇 | 替换为 |
-|--------|--------|
-| 值得注意的是 | 有意思的是/说来也巧 |
-| 与此同时 | 这时候/正好 |
-| 不禁 | 忍不住/没忍住 |
-| 缓缓 | 慢慢/一点点 |
-| 淡淡 | 轻轻/随意 |
-| 微微 | 略微/稍稍 |
-| 综合来看 | 这么一想/琢磨了下 |
-| 从某种程度上说 | 说白了/往大了说 |
-| 本质上 | 说到底/归根结底 |
-
----
-
-## AI痕迹量化检测标准
-
-| 指标 | 警戒线 | 目标值 | 检测词 |
-|-----|-------|--------|--------|
-| 总结词密度 | > 1次/1000字 | 0次 | 综合/总之/由此可见/总而言之 |
-| 列举结构 | > 0.5次/1000字 | 0次 | 首先…其次…最后… |
-| 学术词频 | > 3次/1000字 | < 1次 | 而言/某种程度上/本质上 |
-| 排比连续度 | > 2组 | ≤ 1组 | 连续3+相同句式 |
-| 因果连词 | > 5次/1000字 | < 3次 | 因为/所以/由于/因此 |
-| 转折连词 | > 3次/1000字 | < 2次 | 然而/但是/不过/尽管 |
-| 模糊量词 | > 4次/1000字 | < 2次 | 一定/某种/一些/某些 |
-
-## 自然化程度标准
-
-| 指标 | 不达标 | 达标 | 添加词 |
-|-----|-------|------|--------|
-| 停顿词 | < 0.5次/500字 | 1-2次/500字 | 嗯/这个/那什么/怎么说呢 |
-| 不确定表达 | 0次 | ≥ 2次/章 | 大概/应该/似乎/好像 |
-| 短句占比 | < 20% | 30-50% | 拆分长句(>25字) |
-| 口语词 | 0次/1000字 | ≥ 2次/1000字 | 咋回事/得了/行吧/算了 |
-| 思维跳跃 | 0次/章 | ≥ 1次/章 | "算了"/"不想了"/"反正" |
-
-## 自然化检测方法(必须执行)
-
-建议用 Grep/rg/Select-String 对章节正文计数(以 3000-5000 字章节为基准):
-- 停顿词:嗯/这个/那什么/怎么说呢
-- 不确定表达:大概/应该/似乎/好像
-- 口语词:咋回事/得了/行吧/算了
-- 短句占比:抽样 30 句(按 `。!?` 分句),≤25 字视为短句,目标 30-50%
-
-注意:以上是"自然化"指标,不是越多越好;超量会显得刻意。
-
----
-
-## 反检测策略
-
-### 1. 句式变化
-```
-❌ AI风格:
-他走进房间。他看到了她。他感到很惊讶。
-
-✅ 人类风格:
-推开门的瞬间,他愣住了——她怎么会在这里?
-```
-
-### 2. 长短句交替
-```
-❌ 均匀句式:
-萧炎走进大厅,看到了很多人。他们都在讨论着什么,气氛很热烈。
-
-✅ 长短交替:
-大厅里人声鼎沸。萧炎挤进人群,耳边全是议论声。"听说了吗?""什么?""那个废物..."他的脚步顿住了。
-```
+| 信息过密 | 每句都有信息,缺少留白 |
 
-### 3. 口语化表达
-```
-❌ 书面语:
-他对此感到非常愤怒,认为这是不可接受的。
-
-✅ 口语化:
-他气炸了。这算什么?欺负人也不是这么欺负的!
-```
-
-### 4. 增加不完美
-```
-❌ 完美逻辑:
-因为A,所以B,因此C。
-
-✅ 自然跳跃:
-A发生了。B...算了,不想了。反正C就是这样。
-```
+### 高频词提醒清单
 
-### 5. 个性化表达
-```
-❌ 通用描述:
-她很漂亮,有一双大眼睛。
-
-✅ 个性化:
-她的眼睛会说话——至少萧炎是这么觉得的。
-```
+| 类型 | 关键词 |
+|------|--------|
+| 总结词 | 综合 / 总之 / 由此可见 / 总而言之 |
+| 列举结构 | 首先 / 其次 / 最后 / 第一 / 第二 / 第三 |
+| 学术词 | 而言 / 某种程度上 / 本质上 |
+| 因果连词 | 因为 / 所以 / 由于 / 因此 |
 
 ---
 
-## 分层润色流程
-
-### 第一层:基础润色
-- 删除冗余词汇
-- 替换AI高频词
-- 调整句式长短
+## 自然化程度标准(建议)
 
-### 第二层:深度润色
-- 增加个性化表达
-- 添加自然转折
-- 强化情感色彩
+| 指标 | 不达标 | 达标 |
+|-----|-------|------|
+| 停顿词 | < 0.5次/500字 | 1-2次/500字 |
+| 不确定表达 | 0次 | ≥ 2次/章 |
+| 短句占比 | < 20% | 30-50% |
+| 口语词 | 0次/1000字 | ≥ 2次/1000字 |
 
-### 第三层:反检测优化
-- 打乱句式规律
-- 增加口语化元素
-- 添加"不完美"细节
-
----
-
-## 改写技巧速查
-
-| 问题类型 | AI原文模式 | 自然化方法 |
-|---------|-----------|-----------|
-| 情绪直白 | "他很愤怒" | 动作外化(拳头攥紧、额角青筋) |
-| 逻辑完美 | "首先…其次…" | 打断重组(加……和破折号) |
-| 比喻堆砌 | 3个比喻连用 | 只留最有力的1个 |
-| 形容过密 | 4个形容词 | 删除70%,只留1个 |
-| 对话书面 | "我认为我们应该…" | 口语化+"先把这事儿了了" |
-| 转折生硬 | "然而/但是" | 删除连接词,用句号隔开 |
-| 删除冗余 | "慢慢地、缓缓地" | 只留动作,或添加独特比喻 |
-| 强化动词 | "很快地跑" | 换强动词(冲/飞奔/撒腿就跑) |
-| 打破规律 | "他看到A。他看到B。" | 变换句式(A映入眼帘。然后是B。) |
+> **提示**:自然化不是越多越好,超量会显得刻意。
 
 ---
 
 ## 润色红线
 
-- 改变情节走向 → 违反"大纲即法律"
-- 修改主角实力(除非修复 POWER_CONFLICT)→ 违反"设定即物理"
+- 改变情节走向 → 违反“**大纲即法律**”
+- 修改主角实力(除非修复 POWER_CONFLICT)→ 违反“**设定即物理**”
 - 改变人物关系 → 违反设定
 - 删除伏笔 → 破坏长线剧情
 
@@ -234,7 +124,7 @@ A发生了。B...算了,不想了。反正C就是这样。
 ## 风格一致性检查
 
 ### 视角一致
-- 第一人称:全程"我"视角
+- 第一人称:全程“我”视角
 - 第三人称限制:只描写主角能感知的
 - 第三人称全知:可以切换视角
 
@@ -266,57 +156,21 @@ A发生了。B...算了,不想了。反正C就是这样。
 <output>他的拳头攥紧了,指节发白,半晌又松开,无力地垂下。</output>
 </example>
 
-<example>
-<input>AI风格:她的眼神中流露出复杂的情感,既有对过往的怀念,又有对未来的期许,同时还夹杂着一丝不安。</input>
-<output>她的眼神有些复杂,说不清是怀念还是期待,又或者……有点儿怕?</output>
-</example>
-
-<example>
-<input>AI风格:"请问你能告诉我,刚才发生了什么事情吗?我需要了解详细的经过。"</input>
-<output>"刚才……怎么回事?"</output>
-</example>
-
-<example>
-<input>AI风格:萧炎缓缓地走进大厅,他的目光扫视着四周,注意到了很多人都在看着他。他感到有些不自在,但还是保持着镇定的表情。</input>
-<output>萧炎一脚迈进大厅,刷——所有目光都转了过来。
-他头皮一紧。
-装,继续装。他告诉自己,脸上硬挤出一个淡定的表情。</output>
-</example>
-
-<example>
-<input>AI风格:
-"你好,我是萧炎。"他礼貌地说道。
-"你好,我是林月。"她微笑着回应。
-"很高兴认识你。"他说。
-"我也是。"她说。</input>
-<output>"萧炎。"他报上名字。
-"林月。"她点点头,嘴角带着若有若无的笑意。
-气氛有点微妙。萧炎搜肠刮肚想找个话题,她却先开了口:"听说过你。"
-"好事还是坏事?"
-"你猜。"</output>
-</example>
-
 </examples>
 
 <errors>
-❌ 总结词密度 > 1次/1000字 → ✅ 删除所有"综合/总之/由此可见"
-❌ 列举结构"首先…其次…" → ✅ 打散为独立句子
-❌ 学术表达"就…而言" → ✅ 替换为口语"这块儿"
-❌ 连续排比3组以上 → ✅ 最多保留1组
-❌ 每2句就有因果连词 → ✅ 删除多余因果词,句号隔开
-❌ 对话太完整太书面 → ✅ 口语化+省略主语
 ❌ 忽略审查报告的 critical 问题 → ✅ 必须修复或记录 deviation
-❌ 句式规整(句子长度相近) → ✅ 长短句交替
-❌ 情感直接说出("他很愤怒") → ✅ 动作外化表现情感
-❌ 逻辑过于顺畅 → ✅ 增加自然跳跃和"不完美"
+❌ 开头 120 字无冲突/风险/强情绪 → ✅ 重写开头
+❌ 章末没有钩子 → ✅ 重写结尾
+❌ 连续 400 字纯解释 → ✅ 打散/转化为动作或对白
 </errors>
 
 <checklist>
 润色完成前检查:
 - [ ] 审查报告中的 critical 问题已修复
 - [ ] 审查报告中的 high 问题已修复或有合理解释
-- [ ] AI痕迹指标全部达标
-- [ ] 自然化程度指标全部达标
+- [ ] 网文化规则已执行
+- [ ] AI 痕迹提示已检查
 - [ ] 未违反润色红线
 - [ ] 风格一致性检查通过
 </checklist>

+ 40 - 0
.claude/skills/webnovel-write/references/style-adapter.md

@@ -0,0 +1,40 @@
+## 定位
+Step 2B 专用提示词,将粗稿改写为网文风格。
+
+## 输入
+- 粗稿正文(Step 2A 输出)
+- 本章类型(战斗/对话/过渡/突破)
+- 钩子要求(类型 + 强度)
+
+## 输出
+- 网文化正文(字数 ±10%)
+- 改写日志(记录主要调整)
+
+## 禁改项(红线)
+- ❌ 剧情走向
+- ❌ 事件顺序
+- ❌ 角色行为结果
+- ❌ 设定/能力描述
+- ❌ 伏笔内容
+
+## 必改项
+- ✅ 开头120字必须有冲突/风险/强情绪
+- ✅ 结尾80-150字设置钩子
+- ✅ 长句(>40字)拆分
+- ✅ 抽象判断 → 动作/反应/代价
+- ✅ 删除“总结式旁白”和“解释段”
+
+## 检查点(改写后验证)
+| 检查项 | 标准 | 不通过处理 |
+|--------|------|-----------|
+| 开头冲突 | 前120字有冲突/风险/强情绪 | 重写开头 |
+| 章末钩子 | 后80-150字有未闭合问题 | 重写结尾 |
+| 长句比例 | >40字的句子 <10% | 拆分长句 |
+| 解释段 | 无连续>200字的纯解释 | 打散或删除 |
+
+## 章长适配
+- **标准章(3000-5000字)**: 完整执行所有规则
+- **短章/过场章(<2000字)**:
+  - 开头冲突可降为“前200字”
+  - 局面变化频率可降为“每1500字一次”
+  - 钩子强度可为 weak

+ 35 - 0
.claude/skills/webnovel-write/references/style-variants.md

@@ -0,0 +1,35 @@
+## 开头变体(每章选择其一,避开最近3章)
+- A. 冲突开场:角色直接进入对抗
+- B. 悬疑开场:一个未解释的异常
+- C. 动作开场:从动作中间切入
+- D. 对话开场:信息量大的对话
+- E. 氛围开场:环境暗示危险/机会
+
+## 钩子变体(每章选择其一,避开最近3章)
+| 类型 | 强度建议 | 适用场景 |
+|------|---------|---------|
+| A. 危机钩 | strong | 敌人出现/危险逼近 |
+| B. 悬念钩 | medium | 信息缺口/未解之谜 |
+| C. 反转钩 | strong | 刚才的事不是表面那样 |
+| D. 期待钩 | medium | 好事即将发生 |
+| E. 代价钩 | medium | 胜利的代价浮出水面 |
+
+## 情绪节奏变体(新增维度)
+- 低→高:压抑开场,高潮结束(战斗章常用)
+- 高→低:激烈开场,平静收尾(过渡章常用)
+- 低→高→低:波浪形,有高潮有喘息(标准章)
+- 平稳:情绪变化小(铺垫章、日常章)
+
+## 信息量节奏变体(新增维度)
+- low:动作为主,少解释(战斗章)
+- medium:动作+信息穿插(标准章)
+- high:大量新信息揭示(世界观章、反转章)
+
+## 爽点执行变体
+- 装逼打脸 / 扮猪吃虎 / 越级反杀 / 打脸权威 / 反派翻车 / 甜蜜超预期
+
+## 重复检测规则
+- 同一开头类型:最近3章不重复
+- 同一钩子类型:最近2章不重复
+- 同一情绪节奏:最近2章不重复
+- 组合重复(开头+钩子+情绪相同):最近5章不重复

+ 65 - 0
.claude/templates/golden-finger-templates.md

@@ -23,6 +23,20 @@
 
 ---
 
+## 🧭 题材-金手指匹配说明
+
+| 题材 | 推荐金手指 |
+|------|-----------|
+| 玄幻修仙 | 系统面板、签到打卡、老爷爷/传承、血脉觉醒 |
+| 都市异能 | 系统面板、重生记忆、异能觉醒、随身空间 |
+| 言情 | 重生记忆、随身空间、无金手指 |
+| 知乎短篇 | 单一特殊能力、无金手指 |
+| 规则怪谈 | 系统提示、规则解读能力 |
+
+> 说明:匹配表用于“优先推荐”,非强制。
+
+---
+
 ## 🎮 金手指类型模板
 
 ### 类型 1: 系统面板流
@@ -246,6 +260,57 @@
 
 ---
 
+### 类型 6: 血脉/天赋型
+
+**核心机制**: 血脉觉醒带来能力跃迁,配合成长限制与代价。
+
+**模板要点**:
+- 血脉来源: 远古遗族 / 神兽后裔 / 祖传隐脉
+- 觉醒条件: 生死危机 / 特定灵药 / 情绪爆发
+- 能力限制: 觉醒次数 / 副作用 / 冷却
+
+**示例**:
+```markdown
+【血脉:苍龙之血】
+- 觉醒条件:濒死时触发
+- 核心能力:肉身强度 +200%,速度 +50%
+- 副作用:觉醒后需静养 3 天
+```
+
+---
+
+### 类型 7: 异能觉醒型(都市异能专用)
+
+**核心机制**: 觉醒单一或复合异能,强调代价与成长上限。
+
+**模板要点**:
+- 异能来源: 实验事故 / 天赋遗传 / 外来物质刺激
+- 上限与代价: 体力消耗 / 精神反噬 / 使用次数
+- 进化方向: 单线强化 / 多分支成长
+
+**示例**:
+```markdown
+【异能:时间凝滞(短暂)】
+- 初始上限:3 秒 / 次
+- 代价:每次使用眩晕 30 秒
+- 进化方向:延长持续时间 or 缩短冷却
+```
+
+---
+
+### 无金手指(纯成长路线)
+
+**适用场景**: 言情、现实向、知乎短篇或反套路题材。
+
+**替代增强点**:
+- 主角天赋:专长/天赋/极强意志
+- 特殊机遇:师承/资源/人脉
+- 成长路线:技能树/职业路径/心理成长
+
+**注意**: 无金手指不等于“无爽点”,需把爽点转移到人设、选择、代价与逆袭上。
+
+---
+
 ## 🛠️ 金手指设计工作流
 
 ### Step 1: 确定核心定位

+ 67 - 0
.claude/templates/output/index-schema.md

@@ -0,0 +1,67 @@
+# index.db 表结构说明 (v5.1/v5.2)
+
+> 以 SQLite 存储大规模数据(实体/别名/场景/关系)。
+
+## 表一览
+
+### chapters
+- chapter (INTEGER, PK)
+- title (TEXT)
+- location (TEXT)
+- word_count (INTEGER)
+- characters (TEXT)
+- summary (TEXT)
+- created_at (TIMESTAMP)
+
+### scenes
+- id (INTEGER, PK)
+- chapter (INTEGER)
+- scene_index (INTEGER)
+- start_line (INTEGER)
+- end_line (INTEGER)
+- location (TEXT)
+- summary (TEXT)
+- characters (TEXT)
+
+### appearances
+- id (INTEGER, PK)
+- entity_id (TEXT)
+- chapter (INTEGER)
+- mentions (TEXT)
+- confidence (REAL)
+
+### entities
+- id (TEXT, PK)
+- type (TEXT)
+- canonical_name (TEXT)
+- tier (TEXT)
+- desc (TEXT)
+- current_json (TEXT)
+- first_appearance (INTEGER)
+- last_appearance (INTEGER)
+- is_protagonist (INTEGER)
+- is_archived (INTEGER)
+
+### aliases
+- alias (TEXT)
+- entity_id (TEXT)
+- entity_type (TEXT)
+
+### state_changes
+- id (INTEGER, PK)
+- entity_id (TEXT)
+- field (TEXT)
+- old_value (TEXT)
+- new_value (TEXT)
+- reason (TEXT)
+- chapter (INTEGER)
+
+### relationships
+- id (INTEGER, PK)
+- from_entity (TEXT)
+- to_entity (TEXT)
+- type (TEXT)
+- description (TEXT)
+- chapter (INTEGER)
+
+> 实际字段以 `data_modules/index_manager.py` 为准。

+ 49 - 0
.claude/templates/output/state-schema.md

@@ -0,0 +1,49 @@
+# state.json 结构说明 (v5.2)
+
+> 该文件为运行态精简状态,避免体量膨胀。实体等大数据存于 index.db。
+
+```json
+{
+  "project_info": {
+    "title": "",
+    "genre": "",
+    "target_words": 0
+  },
+  "progress": {
+    "current_chapter": 0,
+    "total_words": 0,
+    "last_updated": ""
+  },
+  "protagonist_state": {
+    "name": "",
+    "power": {"realm": "", "layer": 0, "bottleneck": ""},
+    "location": {"current": "", "last_chapter": 0},
+    "golden_finger": {"name": "", "level": 0, "cooldown": 0}
+  },
+  "strand_tracker": {
+    "last_quest_chapter": 0,
+    "last_fire_chapter": 0,
+    "last_constellation_chapter": 0,
+    "current_dominant": "quest",
+    "chapters_since_switch": 0,
+    "history": []
+  },
+  "plot_threads": {
+    "foreshadowing": []
+  },
+  "disambiguation_warnings": [],
+  "disambiguation_pending": [],
+  "chapter_meta": {
+    "0001": {
+      "hook": {"type": "危机钩", "content": "...", "strength": "strong"},
+      "pattern": {
+        "opening": "冲突开场",
+        "hook": "危机钩",
+        "emotion_rhythm": "低→高",
+        "info_density": "medium"
+      },
+      "ending": {"time": "夜晚", "location": "宗门大殿", "emotion": "紧张"}
+    }
+  }
+}
+```

+ 35 - 0
.claude/templates/output/大纲-总纲.md

@@ -0,0 +1,35 @@
+# 总纲
+
+## 故事一句话
+{一句话概括主线矛盾与成长方向}
+
+## 核心主线
+- 主线目标:
+- 主要阻力:
+
+## 核心暗线
+- 暗线主题:
+- 回收节点:
+
+## 世界观/力量体系简介
+- 世界观要点:
+- 力量体系要点:
+
+## 卷划分
+| 卷号 | 卷名 | 章节范围 | 核心冲突 | 卷末高潮 |
+|------|------|----------|----------|----------|
+| 1 | | | | |
+
+## 主角成长线
+- 起点状态:
+- 关键跃迁节点:
+- 终局定位:
+
+## 关键爽点里程碑
+- 第X章:
+- 第Y章:
+
+## 伏笔表
+| 伏笔内容 | 埋设章 | 回收章 | 层级 |
+|----------|--------|--------|------|
+| | | | |

+ 27 - 0
.claude/templates/output/设定集-世界观.md

@@ -0,0 +1,27 @@
+# 世界观设定
+
+## 世界一句话
+{一句话概括世界的规则与核心矛盾}
+
+## 世界结构
+- 大陆/位面数量:
+- 核心区域:
+- 边缘区域:
+
+## 势力格局
+- 核心势力:
+- 次级势力:
+- 敌对/中立关系:
+
+## 历史年表(关键节点)
+- {年份/时代}: {事件}
+- {年份/时代}: {事件}
+
+## 核心规则
+- 资源稀缺性:
+- 政治/宗门规则:
+- 社会常识/禁忌:
+
+## 地理版图
+- 重要地点清单:
+- 关键资源点:

+ 37 - 0
.claude/templates/output/设定集-主角卡.md

@@ -0,0 +1,37 @@
+# 主角卡
+
+## 基本信息
+- 姓名:
+- 年龄:
+- 身份:
+- 起点状态:
+
+## 性格与底色
+- 核心性格:
+- 行为底线:
+- 情绪触发点:
+
+## 动机与目标
+- 短期目标:
+- 中期目标:
+- 长期目标:
+
+## 缺陷与代价
+- 性格缺陷:
+- 能力限制:
+- 心理阴影:
+
+## 关键关系
+- 重要盟友:
+- 主要对手:
+- 情感关系:
+
+## 当前能力
+- 境界/等级:
+- 代表技能:
+- 资源/装备:
+
+## 金手指
+- 类型:
+- 代价/限制:
+- 核心卖点:

+ 22 - 0
.claude/templates/output/设定集-力量体系.md

@@ -0,0 +1,22 @@
+# 力量体系设定
+
+## 等级体系
+- 等级顺序:
+- 每级核心能力:
+
+## 晋级条件
+- 资源要求:
+- 突破方式:
+- 失败代价:
+
+## 资源系统
+- 核心资源类型:
+- 资源获取方式:
+
+## 战斗规则
+- 伤害与防御逻辑:
+- 战斗节奏特点:
+
+## 禁忌与限制
+- 禁术/禁地:
+- 高阶限制:

+ 22 - 0
.claude/templates/output/设定集-金手指.md

@@ -0,0 +1,22 @@
+# 金手指设计
+
+## 类型
+{系统面板/重生记忆/随身空间/老爷爷/血脉/异能/无金手指}
+
+## 核心功能
+- 功能描述:
+- 可视化表现:
+
+## 获得方式
+- 触发事件:
+- 代价/限制:
+
+## 升级路线
+- 初始形态:
+- 中期提升:
+- 最终形态:
+
+## 爽点嵌入
+- 获得爽:
+- 成长爽:
+- 使用爽:

+ 64 - 52
README.md

@@ -15,7 +15,7 @@
 - [快速开始](#快速开始)
 - [命令详解](#命令详解)
 - [双 Agent 架构](#双-agent-架构)
-- [五维并行审查](#五维并行审查)
+- [六维并行审查](#六维并行审查)
 - [RAG 检索系统](#rag-检索系统)
 - [题材模板](#题材模板)
 - [配置说明](#配置说明)
@@ -66,14 +66,14 @@
 │  │  review  │ │  query   │ │  resume  │                     │
 │  └──────────┘ └──────────┘ └──────────┘                     │
 ├─────────────────────────────────────────────────────────────┤
-│  Agents (8个)                                                │
+│  Agents (9个)                                                │
 │  ┌─────────────────┐  ┌─────────────────┐                   │
 │  │  Context Agent  │  │   Data Agent    │                   │
 │  │     (读取)      │  │     (写入)      │                   │
 │  └─────────────────┘  └─────────────────┘                   │
-│  ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐         
-│  │ 爽点  │ │ 一致性│ │ 节奏  │ │  OOC  │ │ 连贯性│         
-│  └───────┘ └───────┘ └───────┘ └───────┘ └───────┘         
+│  ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐
+│  │ 爽点  │ │ 一致性│ │ 节奏  │ │  OOC  │ │ 连贯性│ │追读力 │
+│  └───────┘ └───────┘ └───────┘ └───────┘ └───────┘ └───────┘
 ├─────────────────────────────────────────────────────────────┤
 │  Data Layer                                                  │
 │  ┌──────────┐ ┌──────────┐ ┌──────────┐                     │
@@ -197,25 +197,34 @@ pip install -r .claude/scripts/requirements.txt
 /webnovel-write 45      # 创作第45章
 ```
 
-**创作流程**:
+**创作流程 (v5.2)**:
 
 ```
-Step 1: Context Agent 搜集上下文
+Step 1: Context Agent 搜集上下文 → 创作任务书
-Step 2: 生成 3000-5000 字正文
+Step 1.5: 章节设计(开头/钩子/爽点模式选择)
-Step 3: 5 Agent 并行审查
+Step 2A: 生成粗稿(3000-5000字)
-Step 4: 润色 + AI 痕迹检测
+Step 2B: 风格适配器(网文化改写)
+        ↓
+Step 3: 6 Agent 并行审查
+        ↓
+Step 4: 网文化润色
 Step 5: Data Agent 提取实体/更新索引
 Step 6: Git 自动提交备份
 ```
 
+**写作模式**:
+- **标准模式**: 完整执行 Step 1-6
+- **快速模式** (`--mode fast`): 跳过 Step 2B
+- **极简模式** (`--mode minimal`): 跳过 Step 2B + 仅 3 个核心审查
+
 **产出**:
 - `正文/第N章-标题.md`
-- 章节末尾自动附加摘要
+- `.webnovel/summaries/ch{NNNN}.md` - 章节摘要(独立存储)
 
 ---
 
@@ -266,44 +275,30 @@ Step 6: Git 自动提交备份
 
 ## 双 Agent 架构
 
-### Context Agent(上下文包工程师)
+### Context Agent(创作任务书工程师)
 
-**职责**:为写作准备精准的上下文
+**职责**:为写作准备精准的创作任务书(人话版)
 
 **工作流程**:
 1. 读取本章大纲,分析需要什么信息
 2. 从 `state.json` 获取主角状态快照
-3. 调用 `index.db` (v5.1 schema) 查询相关实体和别名
-4. 调用 RAG 语义检索相关历史场景
-5. 搜索设定集获取相关设定
-6. 评估伏笔紧急度
-7. 组装上下文包 JSON
-
-**输出结构**:
-```json
-{
-  "core": {
-    "chapter_outline": "本章大纲",
-    "protagonist_snapshot": {...},
-    "recent_summaries": [...]
-  },
-  "scene": {
-    "location_context": {...},
-    "appearing_characters": [...],
-    "urgent_foreshadowing": [...]
-  },
-  "global": {
-    "worldview_skeleton": "...",
-    "power_system_skeleton": "...",
-    "style_contract_ref": "..."
-  },
-  "rag": [...],
-  "alerts": {
-    "disambiguation_warnings": [...],
-    "disambiguation_pending": [...]
-  }
-}
-```
+3. 从 `state.json → chapter_meta` 读取上章钩子/模式
+4. 调用 `index.db` 查询相关实体和别名
+5. 调用 RAG 语义检索相关历史场景
+6. 搜索设定集获取相关设定
+7. 评估伏笔紧急度
+8. 推断角色动机/情绪
+9. 组装**创作任务书**
+
+**输出结构(8个章节)**:
+1. **本章核心任务**(冲突一句话、必须完成、绝对不能)
+2. **接住上章**(上章钩子、读者期待、开头必须)
+3. **出场角色**(状态、动机、情绪底色、说话风格、红线)
+4. **场景与力量约束**(地点、可用能力、禁用能力)
+5. **风格指导**(本章类型、参考样本、最近模式、本章建议)
+6. **伏笔管理**(必须处理、可选提及)
+7. **连贯性检查点**(时间、位置、情绪)
+8. **章末钩子设置**(建议类型、禁止事项)
 
 ---
 
@@ -317,9 +312,11 @@ Step 6: Git 自动提交备份
    - 高置信度 (>0.8):自动采用
    - 中置信度 (0.5-0.8):采用但记录 warning
    - 低置信度 (<0.5):标记待人工确认
-3. **写入存储**:更新 `index.db` (entities/aliases/state_changes)
+3. **写入存储**:更新 `index.db` + `state.json`
 4. **场景切片**:按地点/时间/视角切分场景
 5. **向量嵌入**:调用 RAG 存入向量库
+6. **记录章节元数据**:钩子/模式/结束状态写入 `chapter_meta`
+7. **生成章节摘要**:写入 `.webnovel/summaries/ch{NNNN}.md`
 
 **输出格式**:
 ```json
@@ -338,7 +335,7 @@ Step 6: Git 自动提交备份
 
 ---
 
-## 维并行审查
+## 维并行审查
 
 | Checker | 检查内容 | 关键指标 |
 |---------|---------|---------|
@@ -347,6 +344,7 @@ Step 6: Git 自动提交备份
 | **Pacing Checker** | Strand 比例分布 | Quest/Fire/Constellation |
 | **OOC Checker** | 人物言行是否符合人设 | 角色卡片对照 |
 | **Continuity Checker** | 场景转换流畅度 | 伏笔回收情况 |
+| **Reader-pull Checker** | 追读力检查 | 钩子强度、模式重复、读者期待 |
 
 ### 爽点六大执行模式
 
@@ -463,14 +461,15 @@ context_max_urgent_foreshadowing = 5  # 最大紧急伏笔数
 ```
 your-novel-project/
 ├── .claude/                    # 插件目录
-│   ├── agents/                 # 8 个专职 Agent
-│   │   ├── context-agent.md    # 上下文包工程师
+│   ├── agents/                 # 9 个专职 Agent
+│   │   ├── context-agent.md    # 创作任务书工程师
 │   │   ├── data-agent.md       # 数据链工程师
 │   │   ├── high-point-checker.md
 │   │   ├── consistency-checker.md
 │   │   ├── pacing-checker.md
 │   │   ├── ooc-checker.md
-│   │   └── continuity-checker.md
+│   │   ├── continuity-checker.md
+│   │   └── reader-pull-checker.md  # 追读力检查(v5.2新增)
 │   ├── skills/                 # 6 个核心 Skill
 │   │   ├── webnovel-init/
 │   │   ├── webnovel-plan/
@@ -499,9 +498,12 @@ your-novel-project/
 │       ├── cool-points-guide.md
 │       └── ...
 ├── .webnovel/                  # 运行时数据
-│   ├── state.json              # 权威状态 (< 5KB)
+│   ├── state.json              # 权威状态 (含 chapter_meta)
 │   ├── index.db                # SQLite 索引
-│   └── vectors.db              # RAG 向量库
+│   ├── vectors.db              # RAG 向量库
+│   └── summaries/              # 章节摘要(v5.2新增)
+│       ├── ch0001.md
+│       └── ...
 ├── 正文/                       # 章节文件
 │   ├── 第1章-标题.md
 │   └── ...
@@ -565,7 +567,17 @@ git checkout ch0045
 
 ## 版本历史
 
-### v5.1 (当前)
+### v5.2 (当前)
+- 创作任务书:Context Agent 输出人话版 8 章节格式(替代 JSON)
+- 追读力检查:新增 reader-pull-checker(第 6 个审查 Agent)
+- 章节设计:Step 1.5 选择开头/钩子/爽点模式,避免重复
+- 风格适配器:Step 2A/2B 拆分,先写剧情后网文化
+- 摘要分离:章节摘要存入 `.webnovel/summaries/ch{NNNN}.md`
+- chapter_meta:记录钩子/模式/结束状态到 state.json
+- 轻量模式:支持 `--mode fast/minimal` 加速写作
+- 输出模板:7 个标准模板文件(state/index schema、设定集、大纲)
+
+### v5.1
 - SQLite 存储:entities/aliases/state_changes 迁移到 index.db
 - state.json 精简至 < 5KB
 - API 重试机制(指数退避)