From 2aa8f0cc83e609ee326f4de7dd589264af80723c Mon Sep 17 00:00:00 2001 From: zizi Date: Mon, 20 Jul 2026 17:00:50 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A1=E5=88=92:=20=E6=8B=86=E8=A7=A3?= =?UTF-8?q?=E6=AD=A3=E6=96=87=E6=99=BA=E8=83=BD=E4=BD=93=E5=AE=9E=E9=AA=8C?= =?UTF-8?q?=E5=8F=B0=20v1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plans/2026-07-20-writer-agent-v1.md | 571 ++++++++++++++++++ 1 file changed, 571 insertions(+) create mode 100644 docs/superpowers/plans/2026-07-20-writer-agent-v1.md diff --git a/docs/superpowers/plans/2026-07-20-writer-agent-v1.md b/docs/superpowers/plans/2026-07-20-writer-agent-v1.md new file mode 100644 index 0000000..3ed26c3 --- /dev/null +++ b/docs/superpowers/plans/2026-07-20-writer-agent-v1.md @@ -0,0 +1,571 @@ +# 正文智能体实验台 v1 Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 在参考作品回放环境中实现一套可机械验证的正文智能体:知识卡只承担索引职责,智能体必须顺着卡片证据回读冻结线内的历史原文,再依据大纲、细纲和事实证据生成正文,并经过审查、盲评及 Gate A/B 验收。 + +**Architecture:** 实验链路分为确定性上下文层、无工具写作层、审查收敛层和离线评测层。检索层在只读快照内生成 `RetrievalPlan` 与 `RetrievalManifest`;上下文层区分事实证据和文风证据;写手只接收冻结后的 `WriterContext v1`,不能自行调用工具;候选正文必须通过 detector 和接受前置检查。A/B/C 回放仅用于诊断,任何评测产物都不得进入 Canonical 正文。 + +**Tech Stack:** Python 3.12、标准库 `unittest`、PostgreSQL/psycopg、现有 `.claude/skills` 流程规范、Claude CLI adapter、YAML/JSON 元数据契约。 + +--- + +## 边界与完成定义 + +- 本计划只实现 `agent-example` 的正文实验台,不修改 `muse-cloud`、产品 API、正式状态机或业务数据库结构。 +- v1 只验收“依据细纲生成下一章”的 `continuation` 场景;改写、扩写、润色、纠错、去 AI 味和角色声音仍复用 writer 身份,但不纳入本轮 Gate,不得宣称这些场景已优化完成。 +- 生产化接口、数据库迁移和 UI 入口必须等 Gate B 通过后另立设计与实施计划。 +- 所有冻结规则在可信的检索/组装层执行,不能依赖写手提示词自觉。 +- `抽取卡 -> 原文` 是强制链路:抽取卡若没有可追踪的历史原文来源,不得单独作为正文硬事实。作者已确认的正式设定、Canonical 状态与细纲声明的新事实可以直接成为事实证据,并标为 `declared_new` 或相应来源类型。 +- “完成”至少包含:测试通过、dry-run 通过、真实回放所需配置齐全;没有真实模型回放结果时只能称“实现完成”,不能称 Gate A/B 通过。 + +## 环境准备:固定 worktree 本地依赖 + +- [ ] 在内层 worktree 创建独立虚拟环境,不复用用户主工作树的 `.venv`: + +```bash +cd /private/tmp/agent-example-writer-v1 +uv venv --python 3.12 .venv +uv pip install --python .venv/bin/python -r requirements.txt +.venv/bin/python --version +``` + +- [ ] 后续所有 Python 命令都在 `/private/tmp/agent-example-writer-v1` 执行并使用 `.venv/bin/python`;若 `requirements.txt` 变化,先重装依赖再验证。 + +## 任务 0:回写稳定设计 SoT,标明实验边界 + +> 本任务在已建立的外层独立 worktree `/private/tmp/oh-my-muse-writer-sot`(分支 `feature/writer-agent-sot`)执行并独立提交;后续任务均在当前 `agent-example` worktree `/private/tmp/agent-example-writer-v1` 执行。禁止在用户有未提交改动的外层主工作树直接编辑或提交。 + +**Files:** +- Modify: `/private/tmp/oh-my-muse-writer-sot/design-docs/专题-01-正文建议接受(Accept Suggestion)实现规范.md` +- Modify: `/private/tmp/oh-my-muse-writer-sot/design-docs/专题-03-AI编排上下文与质量评测实现规范.md` +- Modify: `/private/tmp/oh-my-muse-writer-sot/design-docs/专题-04-生成质量门控与创作健康度设计方案.md` +- Modify: `/private/tmp/oh-my-muse-writer-sot/design-docs/专题-05-AI统一交互协议与外部AgentAdapter设计.md` +- Modify: `/private/tmp/oh-my-muse-writer-sot/design-docs/专题-06-元数据驱动的智能体架构.md` +- Modify: `/private/tmp/oh-my-muse-writer-sot/design-docs/专题-07-知识消费契约与质量闭环.md` +- Modify: `/private/tmp/oh-my-muse-writer-sot/design-docs/架构-04-状态机与约束清单.md` +- Modify: `/private/tmp/oh-my-muse-writer-sot/.agents/workflows/ai-development-protocol.md` + +- [ ] 在专题-07 中把“卡是索引,根据卡回读原文”设为正文消费契约,明确卡不能替代原文。 +- [ ] 在专题-03 中补齐 `WriterContext v1`、`WriterOutput v1`、`RetrievalManifest` 和冻结语义。 +- [ ] 在专题-04 中补齐正文五维评分、双盲评、第三评委仲裁、Gate A/B 唯一判定顺序。 +- [ ] 在专题-05 中明确写手 adapter 的无工具、无会话持久化、超时失败关闭边界。 +- [ ] 在专题-06 中登记 generation purpose 的严格 schema、卡索引视图和双证据字段;只引用各 owner 文档,不复制完整定义。 +- [ ] 在专题-01 中补齐编辑后生成新 candidateVersion、重新 detector、`accept_preflight` 与 CAS 接受边界。 +- [ ] 在架构-04 中标注实验态候选不能进入 Canonical,正式接受仍需 CAS 和 detector 绿证据。 +- [ ] 在既有 `.agents/workflows/ai-development-protocol.md` 中沉淀反序验证门禁:清洗/抽卡/范式 -> 正文 Gate B -> 细纲 -> 大纲+设定;正文层固定采用卡索引与原文回读双线。 +- [ ] 按外层 `CLAUDE.md` 检查概念 owner,只在 owner 文档定义,在其他文档放链接和一句话摘要;所有实质修改同步递增版本号和更新日期。 +- [ ] 在文档中明确“本阶段不改 API 契约/DB”;只有 Gate B 通过后的产品化计划才更新 `docs/api-contracts/*` 和 Flyway。 +- [ ] 运行文档一致性检查: + +```bash +cd /private/tmp/oh-my-muse-writer-sot +rg -n "卡是索引|WriterContext v1|acceptanceEligible|Gate A|Gate B|Canonical" \ + 'design-docs/专题-01-正文建议接受(Accept Suggestion)实现规范.md' \ + design-docs/专题-03-AI编排上下文与质量评测实现规范.md \ + design-docs/专题-04-生成质量门控与创作健康度设计方案.md \ + design-docs/专题-05-AI统一交互协议与外部AgentAdapter设计.md \ + design-docs/专题-06-元数据驱动的智能体架构.md \ + design-docs/专题-07-知识消费契约与质量闭环.md \ + design-docs/架构-04-状态机与约束清单.md \ + .agents/workflows/ai-development-protocol.md +``` + +- [ ] Commit: + +```bash +git -C /private/tmp/oh-my-muse-writer-sot add \ + 'design-docs/专题-01-正文建议接受(Accept Suggestion)实现规范.md' \ + design-docs/专题-03-AI编排上下文与质量评测实现规范.md \ + design-docs/专题-04-生成质量门控与创作健康度设计方案.md \ + design-docs/专题-05-AI统一交互协议与外部AgentAdapter设计.md \ + design-docs/专题-06-元数据驱动的智能体架构.md \ + design-docs/专题-07-知识消费契约与质量闭环.md \ + design-docs/架构-04-状态机与约束清单.md \ + .agents/workflows/ai-development-protocol.md +git -C /private/tmp/oh-my-muse-writer-sot commit \ + -m "设计: 固化正文智能体卡索引原文回读契约" +``` + +## 任务 1:建立 WriterContext/WriterOutput 严格契约 + +**Files:** +- Modify: `meta/schemas/generation_context.yaml` +- Modify: `meta/schemas/outline.yaml` +- Modify: `meta/schemas/README.md` +- Create: `.claude/skills/read-context/scripts/writer_contract.py` +- Create: `.claude/skills/read-context/scripts/test_writer_contract.py` + +- [ ] 先写失败测试,覆盖: + - `runId` 不参与 manifest identity;相同输入得到相同 hash。 + - Unicode NFC 归一化后计算偏移和 hash。 + - 汉字数只计算 CJK Unified Ideographs,不以 Markdown 字符数冒充正文长度。 + - 目标长度采用 half-up 取整,且受 min/max 硬边界约束。 + - `evaluation`/`diagnostic` 上下文始终 `acceptanceEligible=false`。 + - 未知字段、缺字段、错误版本号均 fail closed。 + +```bash +.venv/bin/python \ + .claude/skills/read-context/scripts/test_writer_contract.py -v +``` + +- [ ] 实现 `normalize_text()`、`canonical_json()`、`retrieval_identity()`、`han_count()`、`calculate_target_chars()`。 +- [ ] 定义并校验 `WriterContext v1`:大纲定位、细纲硬约束、冻结点、事实证据、文风证据、检索清单、目标长度、用途与接受资格。 +- [ ] 定义并校验 `WriterOutput v1`:正文、claim ledger、evidence requests、新设定声明、候选版本和上下文 hash。 +- [ ] 更新 YAML schema,使字段名、枚举和 Python 校验器一致;将 `generation_context` 从待启用改为实验台启用,并同步 `meta/schemas/README.md` 的状态和实例落点说明。 +- [ ] 测试转绿并检查 schema 可读性。 +- [ ] Commit: + +```bash +git add meta/schemas/generation_context.yaml meta/schemas/outline.yaml meta/schemas/README.md \ + .claude/skills/read-context/scripts/writer_contract.py \ + .claude/skills/read-context/scripts/test_writer_contract.py +git commit -m "实现: 建立正文上下文与输出严格契约" +``` + +## 任务 2:实现确定性的卡检索和冻结原文读取 + +**Files:** +- Modify: `.claude/skills/search/scripts/search.py` +- Modify: `.claude/skills/replay-eval/scripts/load_reference_work.py` +- Create: `.claude/skills/read-context/scripts/retrieve_writer_sources.py` +- Create: `.claude/skills/read-context/scripts/test_retrieve_writer_sources.py` + +- [ ] 先写失败测试,使用 fake repository 覆盖: + - 卡片按 `score DESC, source_version ASC, source_id ASC, source_offset ASC` 稳定排序。 + - 同分检索多次结果一致。 + - `stateAsOf` 只由 `chapter <= asOfChapter` 的里程碑派生。 + - 终态摘要、未来章号、目标章正文和未来来源引用全部被拒绝。 + - 每条抽取卡索引保留 `sourceVersion/sourceRefs/stateAsOf`;正式设定和细纲新事实使用各自的 Canonical 来源引用。 + - 原文读取事务为 `REPEATABLE READ READ ONLY`。 + - 作品生产检索只读 active Canonical entity 和有效 binding,拒绝 draft/eval 卡。 + - 参考作品回放只读预注册的 `upgrade_book` 卡,并固定 `productionRetrievalEligible=false`,不能流入生产仓储适配器。 + +```bash +.venv/bin/python \ + .claude/skills/read-context/scripts/test_retrieve_writer_sources.py -v +.venv/bin/python \ + .claude/skills/replay-eval/scripts/test_load_reference_work.py -v +``` + +- [ ] 从 `search.py` 提取可复用的 `search_cards()`,CLI 继续调用同一实现,避免两套检索语义。 +- [ ] 实现 `CardIndexRepository` 和 `ProseRepository` 协议:作品适配器复用 `search.py` 的授权过滤;回放适配器复用 `load_reference_work.py` 的授权快照、冻结投影和泄露审计;测试使用内存 fake。禁止复制一套旁路 SQL。 +- [ ] 生成 `RetrievalPlan`:从大纲、细纲实体和状态需求确定卡片查询,不允许写手临场改变检索范围。 +- [ ] 抽取卡命中后必须展开 `sourceRefs` 并读取冻结线内原文;没有来源的抽取卡事实标为 `unverifiedIndexHint`,不能单独进入事实证据。正式设定、Canonical 状态和细纲声明的新事实走独立可信来源,不强造历史原文。 +- [ ] 测试转绿。 +- [ ] Commit: + +```bash +git add .claude/skills/search/scripts/search.py \ + .claude/skills/replay-eval/scripts/load_reference_work.py \ + .claude/skills/read-context/scripts/retrieve_writer_sources.py \ + .claude/skills/read-context/scripts/test_retrieve_writer_sources.py +git commit -m "实现: 卡索引驱动冻结原文检索" +``` + +## 任务 3:组装双证据 WriterContext + +**Files:** +- Create: `.claude/skills/read-context/scripts/assemble_writer_context.py` +- Create: `.claude/skills/read-context/scripts/test_assemble_writer_context.py` +- Modify: `.claude/skills/read-context/SKILL.md` + +- [ ] 先写失败测试,覆盖: + - 连续前 4 章全文作为基础 prose evidence;不足 4 章时从第一章开始,不重复。 + - 卡片来源原文作为补充 prose evidence,按来源去重并稳定排序。 + - `factEvidence` 只含冻结后的历史事实、正式设定、Canonical 状态或细纲声明的新事实;`proseEvidence` 只含可引用原文。 + - `evidenceCoverage` 显示细纲实体、关系、物品、地点、力量体系的覆盖和缺口。 + - 同一快照、同一输入生成相同 manifest/context hash。 + - 超出上下文预算时优先保留细纲硬约束、最近原文和高风险事实,裁剪结果可追踪。 + +```bash +.venv/bin/python \ + .claude/skills/read-context/scripts/test_assemble_writer_context.py -v +``` + +- [ ] 实现确定性的 `assemble_context()`,输出 JSON 和可供人审阅的 Markdown manifest。 +- [ ] 将每个事实绑定到证据引用:历史抽取事实必须回到章节、块和字符区间;正式设定、Canonical 状态和细纲新事实必须回到各自不可变版本引用。 +- [ ] 更新 read-context 流程:先计划、再卡索引、再原文回读、最后组装,禁止直接把卡片全文倾倒给写手。 +- [ ] 测试转绿。 +- [ ] Commit: + +```bash +git add .claude/skills/read-context/SKILL.md \ + .claude/skills/read-context/scripts/assemble_writer_context.py \ + .claude/skills/read-context/scripts/test_assemble_writer_context.py +git commit -m "实现: 组装正文事实与文风双证据上下文" +``` + +## 任务 4:收紧无工具写手并实现动态篇幅 + +**Files:** +- Modify: `.claude/agents/writer.md` +- Modify: `.claude/skills/continuation/SKILL.md` +- Modify: `README.md` +- Create: `.claude/skills/continuation/scripts/run_writer.py` +- Create: `.claude/skills/continuation/scripts/test_run_writer.py` + +- [ ] 先写失败测试,fake subprocess 断言: + - adapter 使用 `--tools ""` 和 `--no-session-persistence`。 + - adapter 同时使用 `--print --output-format json --agent writer --model opus`,CLI 参数与当前安装版本一致。 + - 只把 `WriterContext v1` 通过 stdin 交给写手。 + - 超时、非零退出、非 JSON、schema 不符均失败关闭,不产生可接受候选。 + - 输出正文汉字数落在动态目标区间;越界返回结构化失败。 + - claim ledger 的每项包含事实类型、正文偏移、候选文本 hash 和证据引用。 + +```bash +.venv/bin/python \ + .claude/skills/continuation/scripts/test_run_writer.py -v +``` + +- [ ] 从 `writer.md` 移除 `Read/Write/Grep/Glob` 工具声明,明确禁止自行检索和写文件;adapter 以参数列表调用 CLI,禁止 shell 字符串拼接。 +- [ ] 写手提示词把细纲定义为硬骨架,把大纲定义为方向,把 fact evidence 定义为设定约束,把 prose evidence 定义为叙事和文风参考。 +- [ ] 实现动态目标长度:依据细纲场景数、动作/对话/转折权重和前文中位章长计算,不再写死 4000-5000 字。 +- [ ] 要求输出 `claimLedger/evidenceRequests/newSettingDeclarations`,不得静默补设定。 +- [ ] 更新 README 的 writer 能力说明和篇幅口径,删除固定“2500-3500 字”的旧描述,并明确 v1 仅验收 continuation。 +- [ ] 测试转绿。 +- [ ] Commit: + +```bash +git add .claude/agents/writer.md .claude/skills/continuation/SKILL.md README.md \ + .claude/skills/continuation/scripts/run_writer.py \ + .claude/skills/continuation/scripts/test_run_writer.py +git commit -m "实现: 无工具正文写手与动态篇幅控制" +``` + +## 任务 5:实现 detector 硬门和有限收敛循环 + +**Files:** +- Modify: `.claude/agents/detector.md` +- Modify: `.claude/skills/detect/SKILL.md` +- Create: `.claude/skills/detect/scripts/check_writer_candidate.py` +- Create: `.claude/skills/detect/scripts/test_check_writer_candidate.py` +- Create: `.claude/skills/continuation/scripts/run_writer_pipeline.py` +- Create: `.claude/skills/continuation/scripts/test_run_writer_pipeline.py` + +- [ ] 先写失败测试,覆盖: + - 细纲关键事件、角色、伏笔、章末钩子是硬约束,缺一项即不通过。 + - claim ledger 的 Unicode 偏移、候选 hash 和证据引用不匹配即不通过。 + - 新设定未声明或与冻结事实冲突即不通过。 + - evidence request 最多 3 次;重写最多 2 次;达到上限返回稳定失败码。 + - 状态只能通过 CAS 从 `DRAFT -> CHECKING -> PASSED/REJECTED`,并发旧版本不能覆盖新版本。 + - 运行结果临时文件写完并 fsync 后原子替换正式结果。 + +```bash +.venv/bin/python \ + .claude/skills/detect/scripts/test_check_writer_candidate.py -v +.venv/bin/python \ + .claude/skills/continuation/scripts/test_run_writer_pipeline.py -v +``` + +- [ ] 实现机械校验器,模型 detector 只负责无法机械判定的语义项。 +- [ ] 实现“请求证据 -> 重新组装上下文 -> 重写 -> 重审”的有限状态机。 +- [ ] 更新 detector 和 detect 规范,输出结构化 failure codes,保留全部审查轨迹。 +- [ ] 测试转绿。 +- [ ] Commit: + +```bash +git add .claude/agents/detector.md .claude/skills/detect/SKILL.md \ + .claude/skills/detect/scripts/check_writer_candidate.py \ + .claude/skills/detect/scripts/test_check_writer_candidate.py \ + .claude/skills/continuation/scripts/run_writer_pipeline.py \ + .claude/skills/continuation/scripts/test_run_writer_pipeline.py +git commit -m "实现: 正文细纲硬审查与有限收敛循环" +``` + +## 任务 6:实现接受前置检查,隔离评测产物 + +**Files:** +- Modify: `.claude/skills/confirm/SKILL.md` +- Modify: `meta/chains/README.md` +- Create: `.claude/skills/confirm/scripts/check_writer_acceptance.py` +- Create: `.claude/skills/confirm/scripts/test_writer_acceptance.py` + +- [ ] 先写失败测试,覆盖: + - `acceptanceEligible=false` 的诊断/评测候选不可接受。 + - 用户编辑后必须产生新 candidateVersion,并重新跑 detector。 + - `expectedRevision` 不匹配时返回冲突,不覆盖 Canonical。 + - 只有 detector 绿、上下文 hash 一致、候选未过期才能进入 Shadow 待接受态。 + - `accept/merge/discard` 都要求明确确认;接受成功后才允许异步触发抽卡。 + +```bash +.venv/bin/python \ + .claude/skills/confirm/scripts/test_writer_acceptance.py -v +``` + +- [ ] 实现纯函数 preflight,实验台仅验证状态转换,不写正式正文库。 +- [ ] 更新 confirm 和 chain 文档,删除“修改后直接合并”的模糊路径。 +- [ ] 测试转绿。 +- [ ] Commit: + +```bash +git add .claude/skills/confirm/SKILL.md meta/chains/README.md \ + .claude/skills/confirm/scripts/check_writer_acceptance.py \ + .claude/skills/confirm/scripts/test_writer_acceptance.py +git commit -m "实现: 正文候选接受前置检查" +``` + +## 任务 7:建立正文五维量表和盲评仲裁 + +**Files:** +- Modify: `.claude/agents/judge.md` +- Modify: `.claude/skills/eval/SKILL.md` +- Modify: `.claude/skills/quality-gate/SKILL.md` +- Create: `.claude/skills/replay-eval/scripts/writer_rubric.py` +- Create: `.claude/skills/replay-eval/scripts/test_writer_rubric.py` + +- [ ] 先写失败测试,覆盖五维各 0-10 分、0.5 步长: + - 设定与实体保真。 + - 细纲与情节忠实。 + - 文风一致性。 + - 叙事张力。 + - 文笔与可读性。 +- [ ] 测试双评委去盲;同一维两次评分差异 `>0.5` 时启动一次第三评委。 +- [ ] 第三评委后,若三评分中至少一对差值 `<=0.5`,该维取三者中位数;不存在稳定配对则样本标为 `invalid_unstable`,不强行给输赢。 +- [ ] 评委必须逐项标注证据来自细纲、历史原文、卡片还是自行推断,便于识别假阴/假阳。 +- [ ] writer rubric 必须作为独立 profile 接入,不覆盖现有 `fine_outline_replay` profile;运行既有细纲 rubric 回归测试。 + +```bash +.venv/bin/python \ + .claude/skills/replay-eval/scripts/test_writer_rubric.py -v +.venv/bin/python \ + .claude/skills/replay-eval/scripts/test_rubric.py -v +``` + +- [ ] 同步 judge/eval/quality-gate 的维度、阈值和无效样本语义。 +- [ ] 测试转绿。 +- [ ] Commit: + +```bash +git add .claude/agents/judge.md .claude/skills/eval/SKILL.md \ + .claude/skills/quality-gate/SKILL.md \ + .claude/skills/replay-eval/scripts/writer_rubric.py \ + .claude/skills/replay-eval/scripts/test_writer_rubric.py +git commit -m "实现: 正文五维盲评与稳定性仲裁" +``` + +## 任务 8:实现 A/B/C 同条件回放编排 + +**Files:** +- Create: `.claude/skills/replay-eval/scripts/run_writer_replay.py` +- Create: `.claude/skills/replay-eval/scripts/test_run_writer_replay.py` + +- [ ] 先写失败测试,验证三臂唯一变量: + - A:仅历史原文,无卡索引,诊断候选。 + - B:仅冻结卡片索引,不回读原文;卡内容放入 `indexHints` 而非生产 `factEvidence`,用于测“把卡当原文替代品”的诊断候选。 + - C:卡索引 + 原文回读,诊断候选。 + - 三臂共享同一作品、冻结点、大纲、细纲、目标长度、模型版本、采样参数和 detector。 + - 三臂 manifest 清楚记录差异,候选全部 `acceptanceEligible=false`。 + - 任一臂泄露目标章/未来章时整组样本作废。 + - real-run 输出目录不在 `/private/tmp` 时失败关闭,防止原书或候选误入仓库。 + +```bash +.venv/bin/python \ + .claude/skills/replay-eval/scripts/test_run_writer_replay.py -v +.venv/bin/python \ + .claude/skills/replay-eval/scripts/test_run_replay.py -v +``` + +- [ ] 实现 dry-run:只生成计划、manifest 和上下文摘要,不调用模型。 +- [ ] 复用现有 replay-eval 的 `build_snapshot.py`、`check_snapshot.py`、`audit_leakage.py`、`load_reference_work.py` 和授权预检;`run_writer_replay.py` 只增加正文 profile、三臂上下文和 writer/detector/judge 编排,不另造冻结、授权或数据库旁路。 +- [ ] 固定 CLI:`--config`、`--run-id`、`--output-dir`;默认 dry-run,只有显式 `--execute` 才调用模型。real-run 强制 `output-dir` 位于 `/private/tmp`。 +- [ ] 实现 real-run:调用三臂、detector、双盲评和必要的第三评委;原书、候选、完整 prompt/response 只写入显式传入的 `/private/tmp` 运行目录,结构化结果中不得嵌入原文全文。 +- [ ] 测试转绿。 +- [ ] Commit: + +```bash +git add .claude/skills/replay-eval/scripts/run_writer_replay.py \ + .claude/skills/replay-eval/scripts/test_run_writer_replay.py +git commit -m "实现: 正文三臂冻结回放编排" +``` + +## 任务 9:实现 Gate A/B 唯一判定器 + +**Files:** +- Create: `.claude/skills/replay-eval/scripts/writer_gate.py` +- Create: `.claude/skills/replay-eval/scripts/test_writer_gate.py` + +- [ ] 先写表驱动失败测试,固定终态优先级。 +- [ ] Gate A 判定顺序:有效样本 `<5` -> `insufficient_evidence`;否则只要存在 schema 非法、未来泄漏、系统失败、C 臂 detector 高严重度残留或细纲硬约束覆盖率 `<100%` -> `failed`;其余 -> `passed`。 +- [ ] Gate B 判定顺序:Gate A=`insufficient_evidence` -> `insufficient_evidence`;Gate A=`failed` -> `failed`;否则若作品 `<2`、任一作品样本 `<5`、总样本 `<10`、五类场景未覆盖或不稳定样本占比 `>20%` -> `insufficient_evidence`;再判断 C 臂硬约束覆盖率 `<100%`、高严重度残留、文风/叙事张力平均增量 `<-0.25`,或任一维下降 `>0.5` 的样本占比 `>20%`,命中 -> `failed`;再判断 C-A“设定与实体保真”平均增量 `>=0.25` 且正向样本比例 `>=0.60`,达标 -> `passed`;其余 -> `no_gain`。 +- [ ] Gate B 不允许用单章、单作品或只选卡友好场景得出普适结论。 +- [ ] 报告必须列出假阴、假阳、泄露、评委不稳定和新角色无卡等混淆项。 + +```bash +.venv/bin/python \ + .claude/skills/replay-eval/scripts/test_writer_gate.py -v +``` + +- [ ] 实现判定器并测试转绿。 +- [ ] Commit: + +```bash +git add .claude/skills/replay-eval/scripts/writer_gate.py \ + .claude/skills/replay-eval/scripts/test_writer_gate.py +git commit -m "实现: 正文 Gate A B 唯一判定器" +``` + +## 任务 10:预注册 Gate A 样本并完成全量机械验证 + +**Files:** +- Create: `.claude/skills/replay-eval/configs/writer-gate-a-deep-space-v1.json` +- Modify: `.claude/skills/replay-eval/SKILL.md` +- Modify: `docs/2026-07-20-正文智能体正式优化设计与计划.md` + +- [ ] 预注册深空之影 5 个目标章,固定为:第 489 章“圣蒂曼围攻/加特朗战”=战斗;第 321 章“莫妮卡道别与朋友确认”=人物对话;第 544 章“迷途之地内应反水”=转折;第 199 章“赛莉丝身份与联赛锁死真相”=信息揭示;第 523 章“伊蕾莉雅与旧部重逢”=老角色回归。不得根据生成结果换章或改分类。 +- [ ] 每章记录冻结点、目标章、原始大纲/细纲来源、预期长度、主要实体、新角色比例和泄露检查方式。 +- [ ] 更新 replay-eval 流程和正文设计文档,使实际命令、输出路径、Gate 状态与实现一致。 +- [ ] 运行全部新增测试: + +```bash +.venv/bin/python -m unittest discover \ + -s .claude/skills/read-context/scripts -p 'test_*.py' -v +.venv/bin/python -m unittest discover \ + -s .claude/skills/continuation/scripts -p 'test_*.py' -v +.venv/bin/python -m unittest discover \ + -s .claude/skills/detect/scripts -p 'test_*.py' -v +.venv/bin/python -m unittest discover \ + -s .claude/skills/confirm/scripts -p 'test_*.py' -v +.venv/bin/python -m unittest discover \ + -s .claude/skills/replay-eval/scripts -p 'test_*.py' -v +``` + +- [ ] 运行静态检查: + +```bash +git diff --check +if rg -n "TODO|TBD|implement later" \ + .claude/skills/read-context .claude/skills/continuation .claude/skills/detect \ + .claude/skills/confirm .claude/skills/replay-eval meta/schemas; then + echo "发现未完成占位文本" >&2 + exit 1 +fi +``` + +- [ ] 运行不烧模型额度的 dry-run: + +```bash +.venv/bin/python \ + .claude/skills/replay-eval/scripts/run_writer_replay.py \ + --config .claude/skills/replay-eval/configs/writer-gate-a-deep-space-v1.json \ + --dry-run +``` + +- [ ] 检查 dry-run:五个样本均冻结正确、三臂差异仅为证据策略、目标章和未来章读取数为 0、所有候选不可接受。 +- [ ] Commit: + +```bash +git add .claude/skills/replay-eval/SKILL.md \ + .claude/skills/replay-eval/configs/writer-gate-a-deep-space-v1.json \ + docs/2026-07-20-正文智能体正式优化设计与计划.md +git commit -m "验证: 预注册正文 Gate A 回放样本" +``` + +## 任务 11:真实 Gate A 回放和人工复核门 + +**Files:** +- Generated outside repo: `/private/tmp/muse-writer-replay//manifest.json` +- Generated outside repo: `/private/tmp/muse-writer-replay//gate-report.json` +- Generated outside repo: `/private/tmp/muse-writer-replay//raw/` +- Create after sanitization: `docs/replay/-writer-summary.md` + +- [ ] 执行前记录模型版本、价格窗口、随机参数、代码 commit、数据 snapshot identity;任一项缺失则不启动。 +- [ ] 运行真实回放。该步骤会消耗 Claude/MiniMax 调用,执行者在运行前向用户报预算和样本规模。 +- [ ] 获得预算确认后,使用同一 shell 中的固定 `RUN_ID` 执行: + +```bash +RUN_ID="writer-gate-a-$(date -u +%Y%m%dT%H%M%SZ)" +RUN_DIR="/private/tmp/muse-writer-replay/$RUN_ID" +.venv/bin/python .claude/skills/replay-eval/scripts/run_writer_replay.py \ + --config .claude/skills/replay-eval/configs/writer-gate-a-deep-space-v1.json \ + --run-id "$RUN_ID" --output-dir "$RUN_DIR" --execute +.venv/bin/python .claude/skills/replay-eval/scripts/writer_gate.py \ + --run-dir "$RUN_DIR" --summary-output "docs/replay/$RUN_ID-writer-summary.md" +``` + +- [ ] 人工抽查每章三臂的冻结边界、证据引用、细纲执行和评委归因;发现目标章泄露则整批作废并修复后重跑。 +- [ ] 运行 `writer_gate.py` 生成唯一 Gate A 结果;不得手工改状态。 +- [ ] 若 Gate A 为 `passed`,进入任务 12 的 Gate B 多作品预注册;若 `failed/insufficient_evidence`,按 failure code 修正文层,不提前启动细纲智能体。 +- [ ] 最终提交只包含配置、代码和不含原书全文/完整细纲/完整 prompt-response 的评分摘要;原书正文、生成正文和评委原始响应只留在 `/private/tmp/muse-writer-replay//raw/`,不得复制进仓库。 +- [ ] Commit: + +```bash +git add "docs/replay/$RUN_ID-writer-summary.md" +git commit -m "验证: 裁决正文智能体 Gate A" +``` + +## 任务 12:预注册 Gate B 多作品评估集 + +**Files:** +- Create: `.claude/skills/replay-eval/configs/writer-gate-b-v1.json` +- Modify: `.claude/skills/replay-eval/scripts/test_run_writer_replay.py` +- Modify: `.claude/skills/replay-eval/scripts/test_writer_gate.py` + +- [ ] 只有 Gate A=`passed` 才执行本任务;否则保持配置未启用并修正文层。 +- [ ] 固定 2 本书、每书 5 章、总计 10 章,且两书都覆盖五类场景: + - 深空之影 work=8:489 战斗、321 人物对话、544 转折、199 信息揭示、523 老角色回归。 + - 机动风暴 work=4:489 战斗、95 人物对话、450 转折、210 信息揭示、414 老角色回归。 +- [ ] 配置固定每章的 `asOf=targetChapter-1`、作品/source 版本、授权快照、模型、采样参数、篇幅算法、最大预算、臂定义和随机化种子;不得根据 Gate A 或生成结果替换章节。 +- [ ] 增加配置校验测试:作品数、每书样本数、总样本数、场景覆盖、重复章、冻结点和授权任一不符即拒绝。 +- [ ] 增加判定测试:不稳定样本占比、平均退化、单样本大幅退化、保真平均增量和正向比例均按任务 9 的唯一顺序裁决。 + +```bash +.venv/bin/python .claude/skills/replay-eval/scripts/test_run_writer_replay.py -v +.venv/bin/python .claude/skills/replay-eval/scripts/test_writer_gate.py -v +.venv/bin/python .claude/skills/replay-eval/scripts/run_writer_replay.py \ + --config .claude/skills/replay-eval/configs/writer-gate-b-v1.json \ + --dry-run +``` + +- [ ] dry-run 必须证明:10/10 样本冻结正确、两书各 5 章、五类场景全覆盖、目标章/未来章读取数为 0、三臂除证据策略外无差异、所有候选不可接受。 +- [ ] Commit: + +```bash +git add .claude/skills/replay-eval/configs/writer-gate-b-v1.json \ + .claude/skills/replay-eval/scripts/test_run_writer_replay.py \ + .claude/skills/replay-eval/scripts/test_writer_gate.py +git commit -m "验证: 预注册正文 Gate B 多作品评估集" +``` + +## 任务 13:真实 Gate B 回放与正文层最终裁决 + +**Files:** +- Generated outside repo: `/private/tmp/muse-writer-replay//gate-report.json` +- Create after sanitization: `docs/replay/-writer-gate-b-summary.md` +- Modify after result: `docs/2026-07-20-正文智能体正式优化设计与计划.md` + +- [ ] 执行前向用户报告 10 章 x 3 臂 x detector/judge/仲裁的调用上限、模型和预算;没有明确预算记录不启动。 +- [ ] 获得预算确认后运行 Gate B,全量原始输入输出只落 `/private/tmp`: + +```bash +RUN_ID="writer-gate-b-$(date -u +%Y%m%dT%H%M%SZ)" +RUN_DIR="/private/tmp/muse-writer-replay/$RUN_ID" +.venv/bin/python .claude/skills/replay-eval/scripts/run_writer_replay.py \ + --config .claude/skills/replay-eval/configs/writer-gate-b-v1.json \ + --run-id "$RUN_ID" --output-dir "$RUN_DIR" --execute +.venv/bin/python .claude/skills/replay-eval/scripts/writer_gate.py \ + --run-dir "$RUN_DIR" --summary-output "docs/replay/$RUN_ID-writer-gate-b-summary.md" +``` +- [ ] 人工抽查两书各至少 2 章的 manifest、冻结边界、卡到原文指针、claim ledger 和评委归因;发现泄露或控制变量漂移则整批作废。 +- [ ] 由 `writer_gate.py` 生成唯一终态:`passed` / `failed` / `insufficient_evidence` / `no_gain`,不得手工覆盖。 +- [ ] 只有 Gate B=`passed` 才把正文层标为通过并启动“细纲智能体”设计与回放;其余终态继续修正文层或补合法样本。 +- [ ] 将脱敏摘要和终态回写任务 SoT;不提交原书、候选正文、完整细纲、完整 prompt/response 或供应商原始响应。 +- [ ] Commit: + +```bash +git add "docs/replay/$RUN_ID-writer-gate-b-summary.md" \ + docs/2026-07-20-正文智能体正式优化设计与计划.md +git commit -m "验证: 裁决正文智能体 Gate B" +``` + +## 完成检查单 + +- [ ] 设计 SoT、schema、Python 校验器和技能规范字段一致。 +- [ ] 写手无工具、无会话、不能自行绕过冻结检索。 +- [ ] 抽取卡只作为索引;抽取卡承载的既有事实能回到冻结原文,正式设定/Canonical 状态/细纲新事实能回到各自权威版本。 +- [ ] 细纲执行由 detector 硬门保证,不依赖评委事后打分。 +- [ ] 诊断候选与生产候选在契约和状态机上隔离。 +- [ ] A/B/C 回放控制变量完整,包含假阴/假阳分析。 +- [ ] Gate A/B 由唯一判定器输出,单章结果不能宣称正文层完成。 +- [ ] 本计划的正文层最终完成条件是 Gate B=`passed`;Gate A 通过只代表链路可运行。 +- [ ] Gate B 通过前不启动细纲智能体,不修改产品 API/DB/Canonical 主链。