muse-agent-example/docs/write-chapter/step2_setup_chapter2.py
zizi b0bc7a8745 框架: 技能按动作-对象重组 + 先审后入创作闭环
一、技能重组(动作-对象命名)
- 旧目录 clean/confirm/continuation/db/detect/embed/… 重组为
  clean-book-text/decide-candidate/write-next-chapter/access-database/
  check-content-consistency/embed-knowledge/…(git 识别为 rename,内容保持)
- agents/*.md、AGENTS.md/CLAUDE.md 收编、example_skill 登记表同步新名

二、先审后入创作闭环(本次核心)
正文接受从"机械门一过就写正典"改为"机械门+语义审查双通过+用户批准+单事务原子提交",
DB 级兜底,编排层跳步即被硬拒。
- candidate_cas.py + example_candidate_cas(109):持久化 CAS 状态链
- fact_delta.py + example_fact_delta/example_fact_ledger(106):结构化事实增量,
  模型只提六型闭集增量+正文证据引文,仅用户批准的增量随正文同事务入账本
- projection_registry.py + example_projection_run(107):投影登记与恢复
- acceptance_state.py:接受前置实时状态重读
- lesson_registry.py + example_lesson(108):经验升格链,禁止自动升格
- DDL 105:example_candidate 增 semantic_status/semantic_report_sha256
- write_canonical.accept:语义兜底+同事务合并增量+登记投影;
  run_writer_pipeline/persist_writer_run/run_writer_semantic_detector/step2 接入全链
- claude_runtime:兼容新 CLI modelUsage 信息字段

三、审查修复(独立子代理四维审查后)
- 事实增量 propose→approve 翻态正道,不撞唯一键
- 冻结配置探针重刷(CLI 2.1.211→2.1.231 漂移),profileSha256/adapterVersion 再登记
- 可视化合同悬空路径/五六空间矛盾、 SoT 旧技能名漂移、行尾空白清理

测试:离线 65 套 + 真实库集成 5 套(CAS/接受故障注入/事实增量/投影/经验升格)+ 回放 79 项全绿。
创作内容(docs/design、生成正文 artifacts)按"框架与创作分开"未入本提交。
2026-08-14 10:24:08 +08:00

93 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""真写一章 · 阶段二前置:建第 2 章 + 章级细纲(规划落库)。
镜像 step1 的建章 + persist_planning 模式。第 2 章细纲按总纲「舰队生存与机甲养成」
展开,硬骨架接住第 1 章已确立的事实(林深/何岚/薄雾号/左眼黑纹/脑内声音/被称量)。
细纲 payload 形状说明:
- 合同四件套(sourceRef/hardConstraints/adjustableBeats/declaredNewFacts)满足
assemble 的 _outline_contract 与 WriterContext 严格校验;declaredNewFacts 是
{factId,text,sourceRef} 对象(第 1 章 payload 的纯字符串形状只用于不过合同的基线章)。
- chapterGoal/keyEvents/mustAppearEntities/chapterEndHook 是规划侧字段,assemble 会裁剪,
留给人工审查与机械门的锚点映射。
- entities 供 build_retrieval_plan 生成检索查询(新书无卡,检索会诚实返空)。
"""
import sys
from pathlib import Path
SCRIPT_DIR = Path(__file__).resolve().parent
DB_SCRIPTS = SCRIPT_DIR.parents[1] / ".claude" / "skills" / "access-database" / "scripts"
PLANNING_SCRIPTS = SCRIPT_DIR.parents[1] / ".claude" / "skills" / "plan-story" / "scripts"
for p in (str(DB_SCRIPTS), str(PLANNING_SCRIPTS)):
if p not in sys.path:
sys.path.insert(0, p)
from db import connect # noqa: E402
from persist_planning import write_section, confirm_section # noqa: E402
WORK_ID = 12
CHAPTER2_TITLE = "称量"
FINE_OUTLINE_PAYLOAD = {
"targetChapter": 2,
"targetChars": 4000,
"chapterGoal": ("林深带着污染征兆回到主力舰队,被隔离审讯。舰队按黑暗森林逻辑"
"裁决他:武器还是污染源;他主动隐瞒脑内的声音,污染却在加重;"
"机甲「茧」的异种核心露出饥饿,埋下升级线。"),
"hardConstraints": [
"衔接第1章结尾:林深击退异族后回到薄雾号,左眼有扩散的黑纹,脑内留有异族的声音。",
"林深进入主力舰队控制范围,被隔离和审讯;舰队态度体现黑暗森林逻辑(称量他的价值与污染风险)。",
"污染检测查不出异常,林深主动隐瞒脑内的声音;同时污染出现新的恶化征兆。",
"机甲「茧」被舰队封存研究,异种核心表现出对同类核心的饥饿(升级线伏笔:融合更强异种核心)。",
"章末钩子:舰队决定让「茧」与林深执行实战任务——或林深察觉自己已不愿离开链接。",
],
"keyEvents": [
"林深被舰队接走并立即隔离。",
"审讯:军方追问战斗细节与污染状态,何岚作证。",
"污染检测与隐瞒:仪器查不出异常,他没有说出脑内的声音。",
"林深独自面对「茧」,发现核心对异族残骸的反应(饥饿)。",
],
"adjustableBeats": [
"审讯与检测场景的次序和比重可调整。",
"污染恶化的具体表现可调整(须与第1章结尾的左眼黑纹、脑内声音一致)。",
],
"declaredNewFacts": [
{"factId": "fact-ch2-1",
"text": "舰队设特别调查组(军方隔离审讯机构),负责污染裁决。",
"sourceRef": {"sourceId": "outline:volume_1", "sourceVersion": "v1"}},
{"factId": "fact-ch2-2",
"text": "异种核心以同类核心为食:融合更强的异种核心,机甲升级,链接加深。",
"sourceRef": {"sourceId": "outline:volume_1", "sourceVersion": "v1"}},
],
"mustAppearEntities": ["林深", "何岚", "生物机甲茧", "主力舰队"],
"chapterEndHook": ("舰队下达实战调令,让「茧」出击;林深在隔离舱里听见核心"
"满意的搏动——它等到了下一顿。"),
"sourceRef": {"sourceId": "outline:volume_1", "sourceVersion": "v1"},
"entities": [
{"id": "entity-ch2-char-linshen", "type": "character", "name": "林深"},
{"id": "entity-ch2-char-helan", "type": "character", "name": "何岚"},
{"id": "entity-ch2-item-cocoon", "type": "item", "name": "生物机甲茧"},
{"id": "entity-ch2-loc-fleet", "type": "location", "name": "主力舰队"},
],
}
def main():
with connect() as conn:
chapter_id = conn.execute(
"INSERT INTO muse_content_chapter(work_id, title, order_no, status, revision, "
"creator, updater) VALUES (%s,%s,2,'draft',1,'setup','setup') RETURNING id",
(WORK_ID, CHAPTER2_TITLE)).fetchone()[0]
print(f"建第 2 章: id={chapter_id} 《{CHAPTER2_TITLE}》")
conn.commit()
fine = write_section(WORK_ID, section_type="fine_outline", schema_type="outline",
target_chapter=2, payload=FINE_OUTLINE_PAYLOAD)
confirm_section(fine["id"])
print(f"第2章细纲: section id={fine['id']} → confirmed")
print(f"\nCHAPTER2_ID={chapter_id}\nFINE_SECTION_ID={fine['id']}")
if __name__ == "__main__":
main()