16 KiB
全书解析/拆书(scenario: full_parse | purpose: extraction | 槽位: 分析→extractor)
何时用:没拆过的完整/存量作品。与章后抽取(extraction)的分工:那边是"已有大纲细纲、写新章后抽增量";这边是"什么都没有,从全文逆向解析出规划层与知识面"。
两个子场景(产出归属不同)
| 子场景 | 产出 | 归属与确认 |
|---|---|---|
| 2a 用户存量作品(U7/C8) | 章节结构+逐章细纲+全书大纲+实体/关系/事件+末章 narrative_state | 全为候选,按章审阅确认(产品-03 §3.7);确认后成正式规划与 Local KB,作品才可续写;脱敏红线不适用自有稿 |
| 2b 系统参考书(G3/B1-B2,如封神演义) | 同上解析产物作中间脚手架(拆书证据链,留档、不需逐章确认)+在脚手架上拆范式五型 | 范式卡(脱敏)入 Global,管理员确认=G3 门;脚手架标 internal |
范式五型也是 entity-scope 的型,但与作品实体分两批:作品实体归 Local、范式归 Global 且吃脱敏红线。
元数据驱动
- 规划逆向的结构=
outline/chapter/scene/narrative_state字段合同;实体=各实体型字段合同;范式=五型字段合同+「判据」归型——schema 加字段,解析产出立刻多一列。 - 「细纲」是本仓先行的规划粒度层级(SoT 只有"正式规划项"),连同规划逆向本身都是对产品-03 §3.7 的增补(SoT 全书解析只列章节/实体/关系/事件)——待回填。
编排形态(拆书不是"一个 agent 跑到底")
一本完整的书=成百上千次顺序调用,单个 agent 的上下文装不下也不该装。分层:编排层是 workflow(确定性:分章循环/断点续跑/入库/进度统计——阶段一由主会话或 Workflow 工具驱动,阶段二=muse 功能链+任务调度);循环体才是 agent(extractor 的一次有界任务:输入=第 N 章原文+库里积累的脚手架,输出=本章细纲+实体增量,写回库)。关键约束:
- 状态全在库,不在会话:前 N-1 章的细纲/实体是第 N 章的上下文,必须从库读——这正是 PG 基座先行的原因;
- 断点续跑与幂等:已处理章号落库,重跑某章=按章号覆盖其 draft 行,随时可停可续;
- 顺序性只来自增量判重(新实体要对着已积累实体判重合并),细纲逆推本身章间独立——先顺序跑保正确,并行化留作后续优化;
- 进度每 10 章报一行(章号/新实体数/累计分型统计)。
M3 直调形态(创始人 2026-07-13 拍板,现行):循环体不再派 opus/haiku 子代理,改为 scripts/parse_llm.py 直调 New-API MiniMax-M3(经 llm skill)。
出卡权上移窗级(B4-S3 重构,现行):章级逐章出卡有三同根病(同功撞车/单章证不成跨章公式/间隔数字伪精确),治法=章级只产「范式候选线索」(并入脚手架 pass,正文只过一遍),出卡在窗级聚类归并——同一手法多章多次出现归并成一张母卡+实例章号,间隔章数由实例章号差机械计算(M3 禁自报数字)。跨窗/跨书同手法靠嵌入判重(初筛 ≥0.85 → M3 归并终判 merge/keep,拿不准保留)。大纲窗行(example_parse_outline,幂等键=窗起始章)是出卡窗的唯一切分依据。
放量全流程(每书五步,均 M3):
# ① 章级 pass(细纲+实体+范式候选线索;断点续跑,重跑自动补失败章)
.venv/bin/python .claude/skills/parse-book/scripts/parse_llm.py chapters --work-id 4 --from 1 --to 50
# ② 窗级大纲聚合(每 5–10 万字:多章细纲+正文→阶段大纲;书末残窗无论大小必成窗)
.venv/bin/python .claude/skills/parse-book/scripts/parse_outline.py window --work-id 4
# ③ 窗级聚类出卡(窗=②的窗行;线索+细纲+阶段大纲→母卡;守卫+判重在 parse_ingest cards)
.venv/bin/python .claude/skills/parse-book/scripts/parse_llm.py cards --work-id 4
# ④ 全书拆完:终检(逐窗细纲对账大纲 + 跨段连贯性纵览)
.venv/bin/python .claude/skills/parse-book/scripts/parse_outline.py check --work-id 4
# ⑤ 公共卡三角色审核(番茄作家/起点作家/主编,M3 常设步骤;见 review-cards skill)
.venv/bin/python .claude/skills/review-cards/scripts/review_cards.py review --batch <批次> --work-id 4
# 进度
.venv/bin/python .claude/skills/parse-book/scripts/parse_ingest.py progress
审核纪律:常设审核=M3(已用 opus 金标准校准,偏差 0.45 达标);fable/opus 只做起量前校准与起量后一次总审核(门禁与优化,不进流程循环)。
试拆实测病理档(放量前须知):M3 细纲按比例会写超(治=绝对字数上限+压缩重试);type 一律标 craft 且串型混填(治=合同动态渲染+字段指纹改型+窗级聚类);重跑自噬(治=窗级幂等软删+0 卡不软删,章级判重名录已随 S3 废除);source 偷懒(治=出处由实例机械生成)。parse_ingest 的 patterns 命令是 S3 前章级出卡入口,仅留作回滚保险。
窗行陷阱(放量首日实测):--window 参数变化后重切,旧窗行会按 from_order 占位,新的大窗被「已有大纲跳过」→ 中间章域永远漏出卡(验收期 1–3 章小窗占住 from_order=1,放量 1–34 章大窗被跳过)。换窗参数重切前必须先删该书全部窗行(窗行是可再生中间产物;卡挂「窗起」,cards 重出时按窗软删重出)。
作品面升格执行器 scripts/parse_upgrade.py(命令 windows/run/status):正文按窗抽取 upgrade_book 实体卡。每窗采用“两阶段短事务”:模型/嵌入调用期间不持有业务连接;实体写入和关系写入各自提交 processing marker;最终嵌入必须完整成功,才与 done 在同一短事务提交。窗口输入摘要绑定作品标题、章/块 ID、标题、状态、revision、类型、正文、active schema 合同和当前脚本 SHA。启动时会恢复可精确撤销的 processing;本次窗口第二次失败立即以非零退出并停止当前作品,保留 retryable-clean 断点,人工再次运行才继续。
recover-legacy-failed --preview/--execute 是 fence 引入前 failed 窗的唯一恢复入口:preview 只读输出窗口、六类本窗产物计数、processing 数和确认 SHA;execute 需确认旧进程已结束、同书锁内重算并 exact 匹配,且无 processing、阻断产物计数为 0,才保持 failed 并标为 retryable-clean。计数只豁免能机械证明来源的全书 reset 墓碑:draft 必须同时 deleted=true、updater='upgrade-reset'、status='pending';embedding 还必须 entity_id IS NULL 且自身 deleted=true;alias 必须 deleted=true 且 updater='upgrade-reset'。presence 没有 reset 来源标记,任何本窗行(包括软删墓碑)都阻断;其他软删、活跃行、已有 entity owner,以及任何 card_state/audit 行也都阻断。完整 stateSha 仍覆盖所有 deleted 行,二者不能混淆。不调用模型/嵌入。--redo-window 已禁用,历史修正走人工 backup/reset/rebuild。
登场中性台阶名称边界:名称只能取 debut 章正文唯一实际命中的合法规范名或别名;若只命中旧别名就用旧别名,多个合法名称同时命中、仅命中通用称谓或无法唯一确定时退化为“人物登场/物件登场”等仅类型描述,禁止泄漏未来才形成的规范名。new_card 规范化名称后必须把实际 canonical 与合法 aliases 立即登记到本窗判重索引,不能继续使用模型原始括号名。
嵌入唯一键冲突失败关闭:owner 预检必须覆盖全部 todo hash;写入前锁 draft、全部活向量和 hash owner,复验 pending + upgrade_book、revision、payload hash 与 entity_id 归属。普通嵌入异常、owner 冲突或 payload 漂移都令窗口失败,不打印完成;最终向量写入和 done 必须同事务。任何外部确认、删除、改版或辅助域漂移都禁止补偿覆盖。
同书命令互斥:parse_upgrade.py run/windows、reset_upgrade_work.py 的预览/执行,以及 backup_upgrade_work.py backup/rehearse/restore 均须先取得 scripts/upgrade_work_lock.py 的同租户同作品 PostgreSQL session advisory lock;失败必须在任何业务 SQL、文件 verify/写入、嵌入或 LLM 调用前非零退出。锁由独立 autocommit 连接持有到命令结束,该连接只执行加锁/解锁 SQL;status 只读且不取锁。所有调用方必须导入同一个 upgrade_work_lock(...) context manager,禁止另造不兼容锁键。
升格 work reset 前备份(只读):任何 reset_upgrade_work.py --execute 前,先用单个 REPEATABLE READ READ ONLY 事务导出该作品七域状态;目录必须是 /private/tmp 下尚不存在的新目录。input 摘要在同一快照中绑定不含密码的数据库 identity、Canonical 章节/block 内容、active 窗边界、升格七型 active 字段合同,以及计划参数 MiniMax-M3 + semantic-dedup=true;同时绑定本次实际执行的 backup_upgrade_work.py、reset_upgrade_work.py、parse_upgrade.py、parse_llm.py、embed_drafts.py、upgrade_work_lock.py、llm.py 和本 SKILL 的 fileSha。gitCommit 只记录 HEAD;当代码未提交时不得把它当执行代码身份,确认以 manifest 的 inputSha + codeFiles + confirmationSha 为准。SHA 仅用于发现传输、落盘或误操作造成的意外损坏,不宣称抵抗能同时改写工件和摘要的恶意篡改。命令默认不写数据库、不调用模型,生成后会关闭数据库连接并从磁盘独立复验;任一失败删除本次新建目录并非零退出。
reset preview 不要求备份且只读;execute 必须同时提供 --backup-dir、与 manifest 精确匹配的 --backup-id 和 --confirmation-sha。取得统一同书 advisory lock 后,execute 须在同一业务事务内以 SHARE ROW EXCLUSIVE 按固定顺序锁住 4 个输入源表 muse_content_chapter→muse_content_block→muse_meta_schema→muse_meta_schema_version,再锁 7 个产出表 muse_knowledge_draft→example_upgrade_window→example_upgrade_alias→example_upgrade_presence→example_upgrade_card_state→example_upgrade_audit→example_knowledge_embedding;必须在锁内重算完整 input,并复用 backup_upgrade_work 的七域读取与摘要规则,将当前完整 input 及七域 rowCount/primaryKeySha/contentSha 与已离线复验 manifest exact 比较;任一漂移必须在写入前失败关闭。
reset execute 还必须在同书 advisory lock 内、创建业务连接前重新调用 capture_code_identity:manifest codeFiles 必须包含 reset_upgrade_work.py,并与当前实际完整 codeFiles 逐项一致;reset/parse/embed/llm/skill 任一 fileSha 漂移或集合变化均拒绝。旧备份仍可离线 verify,但缺少 reset fileSha 时不得用于 execute。
目标 upgrade_book draft 的任一向量只要 entity_id 非空,execute 必须失败关闭;reset 只允许软删 entity_id IS NULL 的活向量,统一写入 updater='upgrade-reset',禁止物删。向量范围不要求关联卡当前 active,以便幂等收口旧版 reset 遗留向量;其它作品、其它来源和其它租户不在边界内。提交前必须机械断言 active 升格卡为 0、active 窗全部 pending、alias/presence/state/audit 为 0、目标 draft 活向量为 0;任一失败回滚整个事务。七域备份/恢复合同不变。
# 创建 work 8 七域一致性备份;expected 值进入 input 摘要并机械核对 594 章/116 窗
.venv/bin/python .claude/skills/parse-book/scripts/backup_upgrade_work.py backup --work-id 8 --expected-chapters 594 --expected-windows 116
# 显式指定 /private/tmp 下的新目录
.venv/bin/python .claude/skills/parse-book/scripts/backup_upgrade_work.py backup --work-id 8 --expected-chapters 594 --expected-windows 116 --output-dir /private/tmp/muse-upgrade-work8-before-reset
# 已有备份纯离线复验(不连接数据库、不调用模型)
.venv/bin/python .claude/skills/parse-book/scripts/backup_upgrade_work.py verify --backup-dir /private/tmp/muse-upgrade-work8-before-reset
# 在真实 public 表的单事务中应用七域恢复、逐域读回,最后强制 ROLLBACK;不调整 sequence
.venv/bin/python .claude/skills/parse-book/scripts/backup_upgrade_work.py rehearse --work-id 8 --backup-dir /private/tmp/muse-upgrade-work8-before-reset --confirmation-sha <manifest-confirmationSha>
# 演练通过并取得本次明确确认后才允许提交;backup-id 必须与 manifest 精确一致
.venv/bin/python .claude/skills/parse-book/scripts/backup_upgrade_work.py restore --work-id 8 --backup-dir /private/tmp/muse-upgrade-work8-before-reset --execute --backup-id <manifest-backup_id> --confirmation-sha <manifest-confirmationSha>
backup 在同一只读快照内机械验证 active window_no=1..expected-windows、各窗章域无缝覆盖 Canonical 连续章域,并要求每章至少一个非空 block;任一不符不产备份。恢复前固定先离线 verify,核对 confirmationSha,并在事务内按 manifest 的 expected 值重算 input;work、tenant、数据库 identity 或 Canonical/窗/合同/代码任一漂移均拒绝。恢复内核按备份 ID exact upsert drafts/windows/embeddings;额外 active 窗直接拒绝,reset 后新增升格 draft 及其额外 embedding 只软删;aliases/presence/card_state/audits 按 work 边界先清后插。为避免 updated_at trigger 改写备份时间戳,恢复写段使用事务局部 replica trigger 模式,仍按 drafts→windows→aliases/presence→card_state/audits→embeddings 的父子顺序执行,事务结束自动复原。rehearse 永不调用非事务性的 sequence 调整并强制回滚;restore --execute 还必须同时精确匹配 backup_id + confirmationSha,逐域读回通过后才把 sequence 仅向前推进并提交。
范式线失败关闭(2026-07-21 假绿复盘后现行):parse_outline.py window、parse_llm.py cards、parse_outline.py check 是同一本作品的顺序流水线。普通网络/429/5xx 由 chat_governed 在单模型内短重试后沿 MiniMax-M3 → MiniMax-M2.7 → glm-5.2 → deepseek-v4-flash 降级;整条链耗尽,或功能层结构输出有限重试仍失败,必须立即停止当前作品并保留断点,禁止跳窗/跳型继续。cards 和 check 开始前机械验证大纲窗对全书章域无头部、中部、尾部缝隙;任一缝隙非零退出。补插窗后所有终检按 from_order/to_order 绝对章号排序并重新编号阶段,window_no 只作运行展示号,不得参与时序判断。
步骤(自底向上,与创作期规划的自顶向下互为镜像)
- 静态分章:import skill(规则,LLM 不参与);
- 逐章内环——复用
extract-knowledge的字段 checklist:逆推本章细纲(章目标/关键事件/出场/伏笔动作/钩子)+抽实体增量;上下文=前 N-1 章已积累的细纲与实体(知识库从空增量生长,作品+元数据+知识库+当前章公式在此逐章成立); - 自底向上聚合:章细纲→卷粗纲→主线一句话;伏笔跨章连线(哪章埋哪章收)在聚合时补;
- 2a 补末章 narrative_state;2b 在脚手架上跑范式拆取(判据归型/字段成卡/判重合并例证);
- 汇报:分章数/细纲覆盖率/实体分型统计/(2b)范式分型统计+设计发现。
比例约束(防"摘要化伪装成结构化";创始人已拍板@2026-07-09,权威值在 outline schema 字段说明)
- 章细纲/章正文 ≈ 3–5%(3000 字章→100–150 字);卷粗纲/卷正文 ≈ 0.3–0.5%;主线一句话 ≤50 字。
- 细纲是结构骨架,不是缩写:超比例=机械退回重解析的判据——比例约束的价值不只是省 token,是防解析退化成压缩复述。
脱敏红线(仅 2b 系统级)
只写抽象结构与手法归纳,严禁抄录原文;≥15 连续字与原文重合=违规;每卡带出处(书名+回目+一句话情节定位)。
输出合同
文件版:2a 落 works/<书>/(候选);2b 脚手架落参考书目录、范式卡入 knowledge/范式/(草稿)。PG 版(B2):结构化清单经主会话 db skill 写入(draft)+embed 嵌入。均不提交/不自确认。