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

23 KiB
Raw Blame History

name, description, disable-model-invocation
name description disable-model-invocation
evaluate-frozen-replay 将参考作品冻结到 as_of 章号,编排细纲或正文的隔离回放,并生成可审计的逐样本结果。需要验证知识或上下文方案时使用;阻断未来信息、未授权来源和不可接受的候选流入生产。 true

回放评测

本 Skill 定义评测编排边界,不替代统一读取器,也不写正式规划或知识。Writer/冻结合同以 父仓专题-03 为唯一 owner,Gate 裁决以 父仓专题-04 为准,adapter 隔离以 父仓专题-05 为准。Gate A 具体执行参数只认 configs/writer-gate-a-deep-space-v1.json。

本 Skill 是回放编排层,只做冻结、授权、防泄漏审计、回放编排与探针刷新:评分/裁决由 score-content-quality 提供;Claude CLI 调用由 execute-claude-task 提供;CAS/raw 证据由 record-run-evidence 提供;候选检测由 check-content-consistency 提供;冻结快照与只读装载由 freeze-context 提供。依赖箭头只向下,本 Skill 不自带这些实现。

真实参考作品配置由 freeze-context/scripts/load_reference_work.py 在 REPEATABLE READ READ ONLY 事务中从实验库组装;它只取作品元数据、窗级大纲、章级细纲摘要和预注册卡 ID 对应的候选卡历史。候选卡必须标记为 eval_draft,不能当作生产知识检索结果。

来源版本只认原文件证明链:example_reference_work.source_file 必须唯一匹配成功 import task 和未软删 knowledge document,三方文件名一致,文档 file_hash 为 64 位小写 SHA-256,且 import command_id 以该 hash 前 16 位开头。sourceHash=sha256:<hash>,sourceVersion=raw-file-v1:sha256:<hash>;作品 revision 和导入章数不得改变原文件版本。

输入合同

  • reference_work:参考作品标识和版本。
  • as_of:冻结章号,必须是正整数;所有历史证据只能来自绝对章号 <= as_of。
  • snapshot_version:不可变的快照版本。
  • 作品大纲窗口:使用 from_order / to_order,只允许完整窗口 to_order <= as_of。
  • 实体卡和里程碑:必须带可验证的绝对章号;无明确上界的区间不进入快照。
  • 来源合同:每个来源要有 sourceId、sourceVersion、用途授权快照和来源状态。
  • 内容审计合同:leakageAudit.targetFacts.forbiddenFacts 必须登记目标章结构化事实及首见章号;审计结果只允许输出路径和哈希。

冻结规则

  1. 章号支持整数和数字字符串,拒绝布尔值、浮点猜测、空值和无法证明上界的字符串。
  2. 里程碑按绝对章号过滤;未来条目、跨过 as_of 的区间和无章号条目进入 omittedSources,不改写成当前事实。
  3. 窗级大纲按 to_order 过滤并按 from_order 排序;window_no 只是展示字段,不能作为冻结键。
  4. 终态摘要、未来弧线、原始当前态等存储字段不能直接透传;只能保留安全历史并由后续消费方明确标记推导状态。
  5. 任何目标章事实、目标实体清单或目标章标签不得参与规划器侧来源选择。

输出合同

输出是临时 snapshot_manifest:记录来源 ID/版本、SHA-256、字符数、字段裁剪、来源省略和快照版本,不保存原书正文。三臂的 manifest 除卡注入分区外必须字节一致;不一致时整组作废。

授权、来源版本、目标章禁读或内容级泄露检查任一失败,都必须 fail-closed,返回明确的阻断状态,不靠重试绕过。

run_replay.py 会同时审计公共快照和三臂卡注入区。没有 leakageAudit 配置、发现未来章记录、目标事实完整匹配,或原子事件子句达到多强锚点与覆盖率门时,不生成 snapshot_manifest,也不进入 planner。

产物边界

  • 原始 prompt、response、候选、标准事实摘要和完整输入只能留在仓库外受控 raw vault;必须受显式保留授权、租约和迁移回执约束。正式评测每轮结束迁移到受控归档,删除必须另行明确授权。
  • 最终报告只允许评分、摘要、章节定位、失败类别和哈希。
  • 禁止把完整 Prompt/Response、供应商原始响应、原书正文、完整目标细纲、token、密钥或未脱敏授权资料写入 Git 仓库或安全摘要。

编排入口

  • scripts/run_replay.py --mode dry_run:只执行授权、来源、冻结和三臂 manifest 预检,不调用模型;这是首个机制 smoke 入口。
  • freeze-context/scripts/load_reference_work.py:从 PostgreSQL 只读事务组装仓库外临时配置;读取 example_reference_authorization_snapshot 当前原文件版本的最新快照,组装 authorization 外层与 snapshot。缺授权记录仍生成可审计配置,但送入 run_replay 后必须保持 blocked_authorization。
  • scripts/run_replay.py --mode execute:在全部前置门通过后,依次执行三臂 planner、整组 schema、逐臂盲 detector、两个独立盲 judge、rubric 校验、稳定性门和去盲汇总;--output-dir 必须位于仓库外的临时目录。
  • detector 输入输出均为 JSON;输入只有匿名候选 ID、候选和公共冻结到 as_of 的规划上下文,不含 arm 名、cardInjection、cardManifest、任何臂特有卡内容、目标章 proxy 或其他评委结果。卡注入合法性只由确定性预检负责。报告不合约属于系统失败,须在 judge 前失败关闭;合同合法的 failed / needs_evidence 属于候选质量信号,三臂均须保留候选与报告并继续盲评和 Gate,Gate A 只由 C 臂高严重度残留与硬约束覆盖率裁决质量失败。
  • 合法的非 passed 报告在安全 manifest 与 CAS 中只保存按臂分组的 semantic-diagnostic-v1:固定结果枚举、固定原因/区段枚举、调用次数和有界阻断计数。完整报告只留受控 raw 和编排器内存中的 Gate builder 输入;安全输出不得保存错误消息、正文、引文、事实文本、补证查询/原因、任何检测项 ID/字段路径、纠错草稿或模型原始字段。检测器不合约时同样只保存固定闭集诊断并失败关闭。
  • 任一样本发生系统失败、检测器不合约、盲评无效/不稳定、预算或 raw/CAS 失败后,整轮已无法构建完整 Gate 输入,必须立即停止后续样本并进入统一迁移;不得继续调用模型消耗预算,也不得因失败删除本轮诊断 raw。
  • 两个 judge 使用不同 judgeId 和独立无会话进程。第二个 judge 的匿名候选顺序必须与第一个完全相反;任何 rubric 不合约标记 judge_invalid,任一同维差值大于 0.5 标记 judge_unstable,两者都不得标记 completed。
  • 只有三臂 schema 合法、detector 均产出合同合法报告、双 judge rubric 与稳定性门通过,才去盲生成逐维 B-A / C-A 差值矩阵并标记 completed;detector 报告合同合法不等于其质量终态必须为 passed。--detector-bin、--judge-primary-bin、--judge-secondary-bin 可分别指定本地 runner;未指定时复用 --planner-bin,测试只能使用 fake binary。
  • planner、detector、judge 子进程统一受 --timeout-seconds 限制,默认 300 秒;任一超时分别落盘 planner_timeout、detector_timeout、judge_timeout,不得继续进入后续阶段或标记 completed。
  • scripts/write_report.py:从 run_result.json 生成独立严格 schema 的安全摘要,只接受受限标识符、枚举、数字、短安全摘要和 SHA-256;不会读取候选正文,也不会把候选路径以外的原始响应写入报告。

真实作品运行必须绑定不可变授权快照,且 allowedPurpose 包含 offline_evaluation。缺记录、授权过期、用途不符或来源状态无效时保持 blocked_authorization,不得伪造为 licensed。任一模型调用失败都不能跳过对应臂、复用部分结果或改写预注册输入;重跑必须重新执行完整样本合同。

正文 A/B/C 回放

正文 Gate A 固定配置为 configs/writer-gate-a-deep-space-v1.json,预注册深空之影五章:489 战斗、321 人物对话、544 转折、199 信息揭示、523 老角色回归。不得根据候选结果换章、换场景分类或修改冻结点;每个冻结点必须等于 targetChapter-1。

真实五章装配还必须在 commonControls 预注册选择器版本、选择器规范 JSON 的原始字节 SHA-256、inputProvenance=oracle_reference_scaffold 和统一 maxContextChars=140000。五个样本的 A/C 补充原文预算统一预注册为 2000 Unicode code point;loader 在数据库读取前机械核对这些值,不得根据实际文本降低或抬高预算。连续四章基线装不下、A/C 任一臂补充原文不足 2000,或两臂 WriterCreativeInput hash 相同/允许差异为空时均失败关闭。

每个样本必须提供 writerContextInput。仓内基础配置只允许 contentMode=sanitized_contract_fixture,并为 A/C 各提供恰好 2000 code point 的明确脱敏合成补充原文,用于机械证明 WriterContext 合同、章号冻结和创作输入差异;这些文本不得来自原书。loader 装配真实临时配置后必须改为 canonical_frozen_prose。生产 --execute 在创建 vault 或 runner 前拒绝脱敏夹具;脱敏夹具只可由离线测试适配器执行。任何模式都不得把原书全文、完整目标细纲或标准答案写入 Git。

三臂都必须构造并校验完整 WriterContext v1,且固定 mode=diagnostic_only、purpose=evaluation、acceptanceEligible=false。adapter 随后投影 WriterCreativeInput v2;writer 模型只看到创作投影,不看到运行身份、manifest、hash、实验臂或验收状态:

  • A:evidenceStrategy=historical_prose_only,保留连续四章脱敏基线,不放 indexHints,patternReferences 恒空。
  • B:evidenceStrategy=card_index_only,只放 retrievalResult.indexHints 与冻结公共 patternReferences,proseEvidence 为空;这是合同内可审计的诊断基线例外,不是生产旁路。
  • C:evidenceStrategy=card_index_plus_prose,保留连续四章脱敏基线,并放冻结 indexHints、与 B 相同的公共 patternReferences 及配置中的补充原文证据。

A/C 单变量回执在 WriterCreativeInput v2 上比较。正式 Gate A 的 allowedDifferencePaths 必须非空,A/C contextSha256 必须不同,且所有路径只能位于 factConstraints、proseExcerpts 或预注册的 patternReferences;indexHints 等模型不可见字段的差异不能使样本合格。

indexHints 每项只能包含 cardId/name/type/content/sourceId/sourceVersion/asOf,只能用于 diagnostic_only 的 evaluation/diagnostic,不得进入 writer 或 semantic detector 的模型输入。可信组装器只能把经来源回读确认的内容转成 factEvidence / factConstraints;eval_draft 的 content 不能直接成为 supported/pass 依据。所有 asOf 和来源章号不得超过样本冻结点。

卡没有持久化 sourceRefs 时,允许把冻结线内最近三个里程碑章的整章 Canonical block 作为降级回读,但每个引用必须标记 sourceType=card_chapter_proxy,对应 proseEvidence.purpose=card_chapter_proxy,不得冒充精确片段。每个代理章必须实际出现卡规范名或选择器预注册的合法别名,否则失败关闭。

每个样本必须记录 frozenRecentHanCounts 和 targetLengthBasis。篇幅只能使用冻结点前连续四章汉字数,经 calculate_target_chars 复算;Gate A 配置固定 hardEventCount=1、foreshadowingActionCount=0、requiredSceneCount=0,禁止读取目标章实际长度。expectedLength 与 WriterContext 的输出合同必须等于机械目标的正负 30%,再受 2000-10000 边界限制。

newCharacterRatio 定义为:具名 requiredCharacters 中,在 asOfChapter 前无记录的角色比例。真实 loader 必须在同一 REPEATABLE READ READ ONLY 事务内直接扫描冻结历史 Canonical 正文,按名字返回首次命中章和命中章集合,再重算 knownBeforeAsOf/absentBeforeAsOf/newCharacterRatio;卡内容不得参与这个判定。泛称角色不参与猜测;例如第 544 章的“内应”无法确定具体身份,必须记录 newCharacterRatio=null 和 newCharacterRatioStatus=unresolved_generic_role,不得默认成 0。

盲评使用独立的 writer-blind-input-v4 内容边界。输入必须绑定预注册 scenario 和 writer-replay-rubric-v2;三位评委的场景或策略版本不一致时在模型调用前失败关闭。可信 adapter 校验匿名候选 hash、共同细纲和 oracleTruthPack 后,只向 judge 模型投影匿名候选 ID+正文、细纲硬约束/可调节 beat/声明新事实、oracle 断言,以及四个通用指标与当前场景评分策略的定义、判据和分数锚点。模型输入不得包含 indexHints、卡 manifest、evidenceStrategy、真实 A/B/C、各臂 WriterContext、raw 路径、reviewer 身份、任何 hash 或其他评委结果。adapter 可附带从当前候选确定性切出的逐字引文提示,以及当前候选/维度/断言/约束的精确顺序和期望数量;这些提示只降低格式误差,不替代本地完整集、引文和证据绑定校验。模型只返回 blind-judge-draft-v3 的评分、理由、候选引文、受控证据引用、维度排序和 verdict;candidate/input/oracle/report/model-receipt hash 与字符 offset 由 adapter 绑定。映射只保留在编排器内存中,评分完成后才去盲。盲评失败的安全摘要只保存错误码、评委/尝试/调用次数、数组计数和缺失/重复/越界数量,不保存正文、引文、理由或原始字段值。通用维度可跨章节聚合,兼容 ID narrative_tension 只按同一场景类型聚合,禁止跨场景平均后抵消单一类型退化。

正文 dry-run 命令:

PYTHONPATH=.claude/skills/evaluate-frozen-replay/scripts .venv/bin/python -m run_writer_replay \
  --config .claude/skills/evaluate-frozen-replay/configs/writer-gate-a-deep-space-v1.json \
  --dry-run

dry-run 只输出计划、manifest 和上下文摘要,不调用 writer、semantic detector 或 judge,不生成候选正文,也不得声称真实回放完成。--execute 必须在创建 runner、raw vault 或调用模型前校验预算、授权、冻结快照、三角色 profile、schema、prompt、内容模式、调用计划和显式 runtime 认证;任一不一致都失败关闭。默认真实 runtime 只接受最小环境白名单中的 API key、OAuth token 或绑定安全 base URL 的 auth token,不继承全局 Claude 配置目录;认证缺失时返回 blocked_runtime_authentication / RUNTIME_AUTHENTICATION_REQUIRED,不得消耗预算槽位或建立 raw vault。

正式 execute 还必须显式传 --raw-archive-dir <仓外绝对目录>;缺失、相对路径、位于本轮输出目录内或与临时 vault 跨文件系统时,均在建立 vault 和调用模型前失败关闭。运行结束以 rawDisposition.status=migrated 和 raw-vault-migration-receipt-v1 证明产物已迁移,不再以删除后的 closed 作为完成条件。

离线完整链冒烟由 scripts/test_run_writer_replay.py 的单样本三臂 production fake 用例承担:它真实经过 writer 投影、机械门、semantic detector、双评委、raw vault、CAS 和 GateInputBuilder,但所有模型均为本地确定性 fake,不产生费用、不得作为 Gate 样本结果。真实一次调用能力只由 refresh_runtime_probe.py 的合成 writer 探针验证;它不代表 detector/judge 或五样本 Gate 已通过。

预算合同分为不可变的 plannedCalls 和独立安全上限 maxCalls。Gate A 当前预注册 writer 60 次(15 次基础写作 + 最多 45 次篇幅修订)、semantic detector 24 次(15 次基础检测 + 9 次纠错/API 重试余量)、blind judge 45 次(最多三位评委,每位基础调用后最多两个格式纠错/API 重试槽位);各 maxCalls=150、单次 cap $5、总预算 $2250。启动预留只按 plannedCalls * maxBudgetUsdPerCall,即 $645;$2250 是三角色各 150 次安全容量对应的有限执行上限,不是预计消费。本预算授权不等于正式 --execute 授权。每次调用前账本同时检查角色计划槽位、maxCalls、累计实际成本和未执行计划的最坏预留;调用后只能使用可信 ExecutionReceipt.totalCostUsd 结算。缺回执成本、重复/错序结算、单次 cap 或总预算越界均 fail closed,未触发的修订、纠错与第三评计划必须保留在 remainingPlannedCalls。

稳定运行纪律

正式 --execute 会发起长时间、多角色的模型调用,运行方式本身是合同的一部分:

  • 正式 execute 必须由持续等待的前台受控会话运行,全程阻塞到进程自己退出并读到退出码;禁止用 run_in_background 之类后台启动。后台启动会被外部任务管理器在数分钟后按 status=killed 收掉,Python 来不及进入 finally,留下 open raw lease、无 manifest、无费用回执。
  • 禁止用不带 pipefail 的 python ... | tail 捕获退出码:管道退出码默认取最后一个命令(tail)的,Python 的非零码会被静默吞掉,失败关闭看起来像成功。要么开 set -o pipefail,要么直接读 Python 进程退出码。
  • 进程内对外部终止只承诺 SIGTERM / SIGINT 可收口:execute-claude-task 会把两者转成受控异常,编排层再通过 record-run-evidence 迁移 raw、写安全 manifest、把在途且无回执的调用记为 costUnknown=true / failureReason=EXECUTION_COST_UNKNOWN 并禁止后续调用,最后以非零退出。SIGKILL 无法捕获,只能事后靠 raw vault 的迁移恢复与 CAS 扫描收敛残留。
  • 受控终止进入最终迁移后,SIGTERM/SIGINT handler 必须保持 defer/ignore,覆盖 raw migration、CAS 收口和 manifest 原子写入;manifest 发布完成后才恢复调用方原 handler。
  • 单个 raw lease 覆盖整轮串行回放。启动时只按三角色中最长的单次 timeoutSeconds + cleanupMargin 校验剩余租期;每次模型调用前再按当前角色的同一公式复检,复检必须发生在消耗预算槽位和外发调用之前。plannedCalls * timeoutSeconds 是预算/容量安全上界,不是运行时预测,不能因其理论总和超过 24 小时而直接阻断;租期不足时必须在下一笔调用前安全停止、迁移已有 raw 并保留未执行计划。

正文 Gate 输入

Gate 裁决器 writer_gate.py(归属 score-content-quality,本 Skill 只提交逐样本脱敏结果)只信任 gate-input.json.samples[] 的逐样本脱敏结果。有效样本数、作品数、场景覆盖、C 臂硬门统计、C-A 五维增量、退化比例和六类混淆项全部由判定器内部计算;顶层传入的同名聚合值和聚合 confounds 不参与裁决。六类混淆项是:假阴、假阳、泄露、评委不稳定、新角色无卡、场景选择偏差。前五类逐样本汇总;场景选择偏差是集合级混淆项,当评测集 workId 去重少于两个(单作品)或未覆盖全部预注册场景类型(只选部分卡友好场景)时产出 finding,标记样本对「卡是否有效」不具代表性、不得据此得出普适结论;它只作报告标注,不改写任何 Gate 终态。

预算、授权或执行合同不合法时不能生成 Gate 输入。Gate A/B 的终态只能由 score-content-quality 的 writer_gate.py 按父仓专题-04 的唯一顺序产生;本 Skill 只做回放编排,不产生也不改写终态,人工不得改写。

运行探针刷新工具

scripts/refresh_runtime_probe.py 是刷新 executionAuthorization.runtimeProbe 的唯一通道。正式执行门要求探针的 executionProfileSha256 必须等于当前 writer profile 的身份哈希;writer 合同(schema/prompt/模型/CLI/预算)升级后旧探针必然失配,门以 EXECUTE_PROBE_CONTRACT_MISMATCH 失败关闭,此时必须用当前合同重测探针,不得手动改探针值绕过。

  • 输入合同:只读 --config 指定的 base 配置,只用 executionProfiles.writer(探针只验证 writer 合同),不读 semantic/judge,不读 oracleTruthPacks/samples/raw 物料。探针输入是固定、极小、全合成的能力探针 prompt(一段自包含的合成微任务),绝不使用原书全文、真实正文或 raw。
  • 调用合同:Claude 调用经可注入 invoker 发起,默认 invoker = claude_runtime.run_claude(真实调用层是薄薄一层);--dry-run 注入固定假产出,只走通「构建 profile + 重签 + 写文件」链路供冒烟,不发起真实调用。
  • 输出合同:把绑定新合同的探针替换 executionAuthorization.runtimeProbe,并按与门校验逐字节同源的规范自哈希算法重签该探针的 receiptSha256(budget/rawRetention 原样保留、各自自哈希不变),把刷新后的完整配置写到 --output 指定的【新文件】,不就地覆盖原配置,便于 review diff 后再替换。新探针字段集与现有 runtimeProbe 完全一致,不缺不多。
  • 失败关闭:调用失败 / 结构化输出 schema 不过 / 单次成本超冻结 cap / 超 deadline / 回执不可信(模型不匹配、标记错误、非零退出、异常终止、API 错误、身份哈希指向旧合同、输出哈希与产出不一致)→ 不写 successful 探针、不产出刷新配置、退出非零,原配置保持不动。
  • 审计合同:标准输出只记录做了什么(探针身份哈希、结构化输出哈希、回执哈希、成本、是否成功、输出文件),绝不打印完整 prompt/response、raw 路径或供应商原始响应。

离线用法(冒烟,不调模型):

.venv/bin/python .claude/skills/evaluate-frozen-replay/scripts/refresh_runtime_probe.py \
  --config .claude/skills/evaluate-frozen-replay/configs/writer-gate-a-deep-space-v1.json \
  --output /tmp/writer-gate-a-deep-space-v1.probe-refreshed.json \
  --dry-run

真实刷新(经授权后由主代理执行,会发起一次真实 Claude 调用,受 writer profile 单次 cap $5 与冻结 deadline 约束):

.venv/bin/python .claude/skills/evaluate-frozen-replay/scripts/refresh_runtime_probe.py \
  --config .claude/skills/evaluate-frozen-replay/configs/writer-gate-a-deep-space-v1.json \
  --output /tmp/writer-gate-a-deep-space-v1.probe-refreshed.json

刷新成功后必须 review --output 与原配置的 diff(只有 runtimeProbe 段变化),再替换正式配置;替换后跑 python -m run_writer_replay --dry-run 复验加固门放行。