13 KiB
CM95 S-52 120 个 FAIL 根因归并与修复批次规划 Codex 任务 v1
日期:2026-09-20
1. 任务目标
本轮只做“120 个 FAIL 的根因归并与修复批次规划”,不修改任何产品功能代码。
唯一输入基线:
- CM95 HEAD:
716acba74dec2c5bbc76e2cd62ca522618d810e2 - 分支:
main - OpenCPN 固定基线:
f7211b4e1874c453e37a7f190aa191c55a25c32e - v2 审计报告:
docs/报告/CM95_S52_OpenCPN渲染流程对照审计报告_v2.md - v2 审计标准:
docs/CM95_S52_语义守恒与运行时能力审计标准_v2.md - 机器审计:
build/audits/cm95_s52_opencpn_code_first_equivalence_v2.json
当前机器审计结论固定为:
- branch records:206
- FAIL:120
- NOT_PROVEN:86
- 正式 PBF:5064
- delivery signatures:1976
- overall Target Portrayal:FAIL
本轮不得把 86 个 NOT_PROVEN 当成已确认 Bug,也不得把 120 FAIL 直接当成 120 个独立代码缺陷。## 2. 核心问题
需要回答的不是“有哪些 120 个失败分支”,而是:
- 这 120 个 FAIL 最少可以归并为多少个独立根因?
- 每个根因实际发生在哪一层?
- 哪些 FAIL 只是同一根因的不同 branch 展开?
- 哪些看似相似的 FAIL 实际必须分开修?
- 哪些根因可以局部修复?
- 哪些根因说明当前架构缺少统一 Rule IR / executor?
- 哪些修复之间存在依赖顺序?
- 如何分批修复,尽量让一次修改消除一组 FAIL?
- 每个修复批次完成后应重跑哪些 Gate / branch / witness?
- 哪些 NOT_PROVEN 需要补证据,而不是写代码?
3. 本轮禁止事项
本轮禁止:
- 修改
src/、web/、tools/、runtime registry、builder、production、style compiler 等产品实现; - 修改 PBF schema;
- 修改 release gate;
- 修改 OpenCPN 固定参考源码;
- 新增或修改 Jest;
- 为了减少 FAIL 数量而改变 v2 审计判定;
- 把多个不同根因为了“数量更少”强行合并;
- 重新扫描 5064 个 PBF;
- 重新做完整 OpenCPN 源码审计;
- 从截图推断根因。
允许读取产品代码来定位根因,但不能编辑产品代码。## 4. 根因定义
一个 Root Cause 必须满足:
- 有明确的错误机制或缺失机制;
- 能指向具体决策层、数据层或 renderer 层;
- 可以说明为什么会同时导致一组 branch FAIL;
- 修复该机制后,理论上可以消除其映射的全部或大部分 FAIL;
- 与其他 Root Cause 有清晰边界。
不要使用过宽的根因,例如:
- “CM95 和 OpenCPN 不一致”
- “renderer 不完整”
- “CSP 有问题”
应使用可执行粒度,例如:
- “hazard resolver 没有把 QUAPNT01 suffix 拼入 ordered instruction chain”
- “presentation scalarization 只保留每种 primitive 的首个值,破坏 ordered multi-opcode sequence”
- “Web SOUNDG runtime 用普通 text 代替 SNDFRM02 glyph sequence executor”
- “RESTRN 集合分类把 14/15 错误纳入 info set”
5. Root Cause ID
所有根因使用稳定 ID:
RC-001、RC-002、……
每个 RC 必须记录:
- title
- layer
- mechanism
- exact evidence
- affected branch_ids
- affected FAIL count
- affected CSP / opcode
- current files/functions
- required change type
- architecture impact
- risk
- dependency
- proposed batch
- verification target
- confidence## 6. 归并原则
6.1 可以合并
当多个 FAIL:
- 源于同一个函数/同一决策错误;
- 或源于同一个中间表示丢失;
- 或源于同一个 runtime consumer 缺失;
- 且一次修复可以共同消除,
则应归并为一个 RC。
6.2 不应合并
即使表现相似,如果:
- 修复位置不同;
- 条件语义不同;
- 一个是 Python resolver 错误,一个是 runtime executor 缺失;
- 一个是 lookup 错误,一个是 CSP 错误;
- 一个是 OpenCPN upstream anomaly / NOT_PROVEN;
则不得为减少数量而合并。
6.3 多根因 branch
一个 branch FAIL 可以同时受多个 RC 影响。
因此必须支持 many-to-many:
branch_id <-> root_cause_id
不能要求 120 个 FAIL 每个只能对应一个 RC。## 7. 层级分类
每个 RC 至少归入以下一类:
NORMALIZATION_LOOKUPCSP_DECISIONNESTED_CSP_CHAININSTRUCTION_IRPRESENTATION_MATERIALIZATIONPBF_RUNTIME_FACTSSTYLE_COMPILERRUNTIME_EXECUTORRESOURCE_CONTRACTMARINER_STATERENDER_ORDER_PRIORITYEVIDENCE_GAP
如果一个 RC 跨层,必须指定 primary layer 和 secondary layers。
8. 优先检查的已知根因簇
以下只作为 seed,不是结论,Codex 必须用 v2 JSON 验证后再决定是否拆分/合并:
- OBSTRN/WRECKS nested suffix 丢失:
- QUAPNT01
- SOUNDG03
- OBJNAM TX
- WRECKS Wk/WRECKS07
- ordered Rule Chain 被 scalar hint 压缩。
- Web/runtime 缺通用 multi-opcode executor。
- SOUNDG glyph chain 被普通文字替代。
- multi-SY / multi-LS / multi-TX 不守恒。
- RESTRN 集合语义错误。
- RESARE 集合语义 + OP side effect 不等价。
- SLCONS LOWACC / attribute presence 差异。
- LIGHTS05/06 颜色、半径、文本/描述/单位差异。
- DEPCNT SAFECD/SAFECN、quality、side effect 差异。
- DEPARE bad range / two_shades / DRGARE 差异。
- Lookup matching / fallback / $AREAS II25 等 Gate A 差异。## 9. 必须建立 FAIL → RC 覆盖矩阵
机器审计中的 120 个 FAIL branch 必须全部进入覆盖矩阵。
每条 FAIL 至少记录:
| 字段 | 要求 |
|---|---|
| branch_id | v2 JSON 原始 branch ID |
| procedure | CSP/flow |
| fail_reason | v2 已确认原因 |
| root_cause_ids | 一个或多个 RC |
| primary_rc | 主要根因 |
| secondary_rc | 可选 |
| fix_batch | 修复批次 |
| verification | 修复后验证方式 |
硬要求:
- 120/120 FAIL 都必须有 root cause 映射;
- 不允许出现未解释的 FAIL;
- 如确实无法归因,单独建
RC-XXX UNKNOWN_ROOT_CAUSE,并明确为何无法继续,不得静默遗漏; - 映射总数可以大于 120,因为允许一条 FAIL 对应多个 RC。
10. RC → FAIL 反向矩阵
每个 RC 必须列出:
- affected_fail_count;
- affected_branch_ids;
- affected procedures;
- 是否存在 real-data signature;
- 是否只存在理论分支;
- 修复后预计可直接关闭的 FAIL;
- 修复后仍可能因其他 RC 保持 FAIL 的 branch。
必须区分:
directly_resolvedpartially_unblockedstill_blocked_by_other_rc## 11. 独立根因数量
报告必须给出:
- 根因总数;
- 按 layer 分类数量;
- 按 risk 分类数量;
- 按 proposed batch 分类数量。
同时给出两个指标:
raw_fail_count = 120deduplicated_root_cause_count = N
不要人为追求 N 越小越好。
12. 修复批次规划
建立稳定 Batch ID:
BATCH-01、BATCH-02、……
每个批次必须说明:
- 目标;
- 包含哪些 RC;
- 为什么应一起修;
- 涉及的预计文件/函数;
- 是否改变公共数据契约;
- 是否改变 PBF;
- 是否改变 runtime;
- 是否需要重新 build release;
- 是否需要重新跑 5064 PBF audit;
- 是否需要视觉验收;
- 风险等级;
- 前置依赖;
- 完成判定;
- 回归范围。
13. 批次排序原则
默认排序:
- 明确且局部的 semantic bug;
- 上游数据/IR 守恒问题;
- 通用 Rule Chain / opcode executor;
- renderer 专项;
- LIGHTS 等复杂专项;
- render order / priority 等高风险结构项;
- NOT_PROVEN 补证据任务。
但最终排序必须依据实际 RC dependency graph,不得机械照抄。## 14. 架构分叉判断
每个 RC 必须判断属于:
LOCAL_FIXSHARED_HELPER_FIXIR_CONTRACT_CHANGEGENERIC_EXECUTOR_REQUIREDSPECIALIZED_RENDERER_REQUIREDEVIDENCE_ONLY
特别回答:
- 是否继续逐 CSP 手工复制 OpenCPN 条件会制造新差异?
- 哪些 RC 可以靠修
csp.py解决? - 哪些 RC 即使修
csp.py,Web runtime 仍会 FAIL? - 哪些 RC 证明需要 ordered Runtime Rule IR?
- 哪些 opcode 应由通用 executor 执行?
- SOUNDG、CA 等哪些应保留专用 renderer?
- 是否需要让 PBF 携带完整 ordered instruction IR,还是只需要 runtime facts + decision IR?
本轮只做设计判断,不实施。
15. NOT_PROVEN 单独处理
86 个 NOT_PROVEN 不是本轮根因归并主体。
但报告必须总结它们按“缺什么证据”归类,例如:
- source attributes unavailable;
- association identity unavailable;
- upstream resource snapshot incomplete;
- global render scheduling unavailable;
- runtime state snapshot unavailable。
为这些项建立 EVIDENCE-TASK-01...,不要建立代码 RC,除非已有明确代码缺陷证据。
16. 本轮正式输出
本轮只允许新增/更新以下正式产物:
-
docs/报告/CM95_S52_120个FAIL根因归并与修复批次规划报告_v1.md- 完整列出 deduplicated Root Cause;
- 包含 120/120 FAIL → RC 覆盖矩阵;
- 包含 RC → FAIL 反向矩阵;
- 包含 RC dependency graph;
- 包含 BATCH-01... 修复批次规划;
- 包含 86 个 NOT_PROVEN 的 evidence-task 分类;
- 给出 raw_fail_count=120 与 deduplicated_root_cause_count=N;
- 明确哪些是局部修复、共享 helper、IR contract、通用 executor、专用 renderer、纯证据任务。
-
build/audits/cm95_s52_120_fail_root_cause_plan_v1.json- 机器可读;
- 至少包含:
- cm95_head;
- opencpn_commit;
- source_audit_artifact;
- raw_fail_count;
- not_proven_count;
- deduplicated_root_cause_count;
- root_causes[];
- fail_to_root_causes[];
- batches[];
- evidence_tasks[];
- dependency_edges[];
- coverage_summary;
- validation_summary。
- 必须能机器确认 120/120 FAIL 全覆盖;
- 每个 FAIL 至少有一个 primary_rc;
- 多根因 branch 可列 secondary RC;
- 不得把 NOT_PROVEN 伪装成代码 RC。
不得创建第二份内容重复的“总结/摘要”文档。
17. 必做验证
完成前必须执行结构化自检,至少确认:
- 输入审计 JSON 的 overall status 仍为 FAIL;
- 输入 branch records=206;
- 输入 FAIL=120;
- 输入 NOT_PROVEN=86;
- 120/120 FAIL 全部进入 fail_to_root_causes;
- 每个 FAIL 有且只有一个 primary_rc;
- secondary RC 可为 0..N;
- 所有引用的 RC ID 都存在;
- 所有 RC 的 affected_fail_count 与实际映射一致;
- deduplicated_root_cause_count 与 root_causes 数量一致;
- 所有 batch 引用的 RC 均存在;
- dependency graph 不包含未知 RC/Batch;
- NOT_PROVEN evidence tasks 与代码 RC 分离;
- 报告中的数量与 JSON 完全一致;
- 没有修改产品实现、Jest、PBF schema、release gate;
- 没有重新扫描 5064 个 PBF;
- 原工作区已有无关修改保持原样。
如果一个 FAIL 只能暂时归入 UNKNOWN_ROOT_CAUSE,必须在报告和 JSON 中明确列出,不得为了 100% 覆盖而虚构根因。
18. 修复批次输出要求
每个 BATCH 必须明确区分:
expected_direct_fail_reduction:若本批次单独完成,理论上可直接关闭的 FAIL 数;expected_unblocked_fail_count:本批次完成后可继续验证,但仍受其他 RC 阻塞的 FAIL 数;requires_release_rebuild;requires_full_pbf_rescan;requires_runtime_validation;requires_visual_validation;risk;dependencies。
不要把“预计可关闭”写成实际已关闭。本轮没有改代码,因此实际 FAIL 数仍是 120。
修复批次应尽量减少重复构建和重复全量验收;只有数据契约/PBF 变化时才安排全 release rebuild / 5064 PBF 重扫。纯 Python 语义修复、runtime executor 修复、renderer 专项应根据实际影响决定最小必要回归范围。
19. Git 收尾
当前仓库存在与本任务无关的未提交修改,必须严格隔离。
本轮只允许提交:
docs/CM95_S52_120个FAIL根因归并与修复批次规划_Codex任务_v1.mddocs/报告/CM95_S52_120个FAIL根因归并与修复批次规划报告_v1.mdbuild/audits/cm95_s52_120_fail_root_cause_plan_v1.json
不得使用 git add .。
完成后:
- 显式 stage 上述三个路径;
- 检查
git diff --cached --name-only与--stat; - 确认没有产品代码/Jest/原无关修改进入 staged;
- commit 到当前
main; - commit message:
docs: plan fixes for OpenCPN S-52 audit failures; - push
origin/main; - 最终完成消息记录 commit hash、push 结果、deduplicated_root_cause_count、batch 数量及最高优先级批次。
push 失败时必须明确报告,不得声称完成。
20. 最终判定原则
本轮不是修复任务,不能因为规划完成就改变 v2 审计状态。
结束时必须保持:
- raw FAIL = 120;
- raw NOT_PROVEN = 86;
- Target Portrayal = FAIL。
本轮成功标准是:
120 FAIL → 可解释的 Root Cause 集合 → 有依赖关系的修复 Batch → 明确回归目标
而不是“把失败数量写少”。