From b2583f75f5584525f8d0d7e1c037ca93f6e4dcc9 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Sat, 24 Oct 2026 08:35:18 +0800 Subject: [PATCH] =?UTF-8?q?chore(=E5=8F=98=E5=BC=82=E7=B1=BB=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=85=A8=E9=A1=B9=E7=9B=AE=E6=B8=85=E9=99=A4):=20?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E8=A3=81=E2=80=94=E2=80=94=E5=8F=98=E5=BC=82?= =?UTF-8?q?=E9=AA=8C=E8=AF=81/=E5=8F=98=E5=BC=82=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E5=85=A8=E9=A1=B9=E7=9B=AE=E7=A6=81=E7=94=A8=EF=BC=8C=E9=AA=8C?= =?UTF-8?q?=E6=94=B6=E4=B8=80=E5=BE=8B=E5=8F=AA=E8=B5=B0=E6=92=A4=E9=94=80?= =?UTF-8?q?=E8=AF=81=E6=98=8E=E3=80=82AGENTS.md=20=E7=BA=A2=E7=BA=BF?= =?UTF-8?q?=E8=A1=8C=E5=88=A0=E9=99=A4=EF=BC=8B=E5=AF=BC=E8=88=AA=E8=A1=8C?= =?UTF-8?q?=E6=94=B9=E8=AF=8D=EF=BC=9Btest-conventions=20=C2=A76=20?= =?UTF-8?q?=E6=95=B4=E8=8A=82=E9=80=80=E5=BD=B9=EF=BC=88=C2=A77=E2=80=93?= =?UTF-8?q?=C2=A79=20=E9=87=8D=E7=BC=96=E5=8F=B7=E4=B8=BA=20=C2=A76?= =?UTF-8?q?=E2=80=93=C2=A78=EF=BC=8C=E5=AF=B9=E7=85=A7=E8=A1=A8=E7=AC=AC?= =?UTF-8?q?=E5=85=AD=E6=A0=BC=E6=94=B9=E3=80=8C=E6=92=A4=E9=94=80=E8=AF=81?= =?UTF-8?q?=E6=98=8E=E3=80=8D=EF=BC=8C=C2=A78.4=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E8=A1=8C=E4=B8=BA=E8=AF=81=E6=98=8E=E6=94=B9=E6=92=A4=E9=94=80?= =?UTF-8?q?=E5=BC=8F=EF=BC=89=EF=BC=9Bprocess-conventions=20=E6=89=B9?= =?UTF-8?q?=E6=B8=85=E5=8D=95=E7=AC=AC=208=20=E6=9D=A1=E5=88=A0=E9=99=A4?= =?UTF-8?q?=EF=BC=88=E5=90=8E=E7=BB=AD=E6=9D=A1=E7=9B=AE=E9=87=8D=E7=BC=96?= =?UTF-8?q?=E5=8F=B7=EF=BC=89=EF=BC=8B=E9=97=B8=E4=BB=B6=E4=B9=89=E5=8A=A1?= =?UTF-8?q?=E5=8F=A5=E6=94=B9=E4=BA=BA=E5=B7=A5=E7=A1=AE=E8=AE=A4=EF=BC=9B?= =?UTF-8?q?code-conventions/roadmap=20=E5=90=8C=E6=AD=A5=EF=BC=9Bpipeline?= =?UTF-8?q?=5Fgate=20=E5=AF=B9=E7=85=A7=E8=A1=A8=E8=AF=81=E6=98=8E?= =?UTF-8?q?=E6=A0=87=E8=AE=B0=E5=88=A0=E3=80=8C=E5=8F=98=E5=BC=82=E3=80=8D?= =?UTF-8?q?=EF=BC=8B=E6=8A=A5=E9=94=99=E6=96=87=E6=A1=88=E6=94=B9=EF=BC=9B?= =?UTF-8?q?run=5Fall=5Fgates.sh=20=E6=B3=A8=E9=87=8A=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=EF=BC=9B=E6=B8=B8=E6=88=8F=E6=B5=8B=E8=AF=95=E9=9D=A2=208=20?= =?UTF-8?q?=E4=BB=B6=E6=B5=8B=E8=AF=95=E8=AF=AD=E4=B9=89=E6=94=B9=E5=86=99?= =?UTF-8?q?=EF=BC=88layout=5Fprobe/ui=5Fstruct=5Fprobe/save=5Fmanager/save?= =?UTF-8?q?=5Fboot/level=5Fgen=5Fparams/forge=5Ftable/save=5Fmanager.gd/4?= =?UTF-8?q?=20=E4=BB=B6=E8=A1=A8=E5=80=BC=E6=8E=AA=E8=BE=9E=EF=BC=89?= =?UTF-8?q?=E2=80=94=E2=80=94=E7=8E=A9=E6=B3=95=E6=9C=AF=E8=AF=AD=EF=BC=88?= =?UTF-8?q?=E5=9C=B0=E5=BD=A2=E5=8F=98=E5=BC=82/=E5=8F=98=E5=BC=82?= =?UTF-8?q?=E6=A0=BC/=E5=8F=98=E5=BC=82=E8=A7=92=E6=A0=87/=E5=8F=98?= =?UTF-8?q?=E5=BC=82=E6=B1=A0=E7=AD=89=EF=BC=89=E9=80=90=E4=B8=AA=E7=94=84?= =?UTF-8?q?=E5=88=AB=E5=90=8E=E5=85=A8=E6=95=B0=E4=BF=9D=E7=95=99=EF=BC=9B?= =?UTF-8?q?=E6=B4=BB=E5=8D=A1=E3=80=8C=E7=8A=B6=E6=80=81=E9=9D=A2=E6=9D=BF?= =?UTF-8?q?=E7=98=A6=E8=BA=AB=E6=89=B9=E3=80=8D=E5=8F=98=E5=BC=82=E5=88=97?= =?UTF-8?q?=E5=85=A8=E9=87=8F=E6=94=B9=E5=86=99=E4=B8=BA=E6=92=A4=E9=94=80?= =?UTF-8?q?=E8=AF=81=E6=98=8E=E5=8F=A3=E5=BE=84=E3=80=82=E5=85=A8=E5=BA=93?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E6=9C=AF=E8=AF=AD=20grep=20=E9=9B=B6?= =?UTF-8?q?=E6=AE=8B=E7=95=99=EF=BC=9B=E5=85=A8=E9=87=8F=E5=9F=9F=E9=97=B8?= =?UTF-8?q?=E9=AA=8C=E6=94=B6=E9=80=9A=E8=BF=87=EF=BC=88=E5=9B=9E=E6=89=A7?= =?UTF-8?q?=E9=9A=8F=E6=9C=AC=E6=89=B9=E9=87=8D=E8=B7=91=E8=A1=A5=E9=BD=90?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 5 +- design/engineering/code-conventions.md | 2 +- design/engineering/process-conventions.md | 17 +++--- design/engineering/test-conventions.md | 54 ++++++------------- game/core/save_manager.gd | 2 +- game/probe/layout_probe.gd | 6 +-- game/probe/ui_struct_probe.gd | 2 +- .../battle_settlement/roll_multiplier_test.gd | 2 +- .../battle_settlement/seal_polarity_test.gd | 2 +- game/tests/unit/core/board_gen_reward_test.gd | 2 +- .../unit/core/meta_progression_forge_test.gd | 2 +- .../unit/core/save_boot_no_activate_test.gd | 4 +- .../unit/core/save_manager_domain_test.gd | 2 +- .../unit/data_config/forge_table_test.gd | 2 +- .../unit/data_config/level_gen_params_test.gd | 4 +- reports/需求卡片-状态面板瘦身批-2026-10-23.md | 26 ++++----- roadmap.md | 2 +- tools/pipeline_gate.py | 4 +- tools/run_all_gates.sh | 2 +- 体验验证清单.md | 2 +- 20 files changed, 61 insertions(+), 83 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 265f8dbe..4ca004f6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -43,7 +43,7 @@ | 批次开工 / 流程纪律 | `design/engineering/process-conventions.md`——worktree 铁律、五段流水线、批次清单、测试两入口与 MC/闸机细则、像素纪律 | | 流水线段入口 | 技能对照——doc-design=文档设计(兼任反哺点落文)/asset-ingest=美术录入/req-card=写卡/iter-plan=迭代编排/iter=实现(五者均装于项目 `.zcode/skills/`);登记不立技能;批后收尾与中间文档退役=batch-closure(同一目录);格式与状态机权威=`design/engineering/doc-conventions.md` §12 | | 写代码 / 改代码前 | `design/engineering/code-conventions.md`——结构/契约/语言/数值/流程五类硬纪律(反例库 = 同目录 code-conventions-cases.md) | -| 写测试 / 改测试前 | `design/engineering/test-conventions.md`——探针标配 / 回归断言 / 全量验证 / 验收清单落码 / 变异验证 | +| 写测试 / 改测试前 | `design/engineering/test-conventions.md`——探针标配 / 回归断言 / 全量验证 / 验收清单落码 | | 写文档 / 改文档前 | `design/engineering/doc-conventions.md`——白话写作 / 载体分工 / 用语 / 结构骨架 / 会话记录与生命周期 | | 概念切分与互链 | `design/engineering/concept-conventions.md`——概念封装 / 跨文档引用 / 归档与事实源 | | 系统设计 / 增删文档 | `design/gdd/02-系统清单.md`——根索引 + 中文规范名↔英文代号对照 | @@ -61,8 +61,7 @@ - 五段流水线铁律——一切工作按「登记 → 文档设计/美术设计 → 写需求卡片 → 迭代编排 → 实现」推进,段间不自动流转、每段转进由用户发令;编入迭代的卡片必须设计闭合+零待裁点,流水线闸 `tools/pipeline_gate.py` 强制(已注册进 run_all_gates.sh 文档域);实现段零裁断——卡片没写清=上游缺陷,停该卡退回上游,禁内联求裁(process-conventions §2,格式与状态机=doc-conventions §12) - MC/模拟:无数值改动零跑;档位硬闸见 `sim-data/README.md`「MC 采集档位表」,一档只能由用户发起 - 闸机轮次纪律:新码先孤立验证 → 出红只跑红件最小单元 → 长批先最小参数试车 → 开工扫坑册(process-conventions §6) -- 变异验证——新增/改写验收函数必须变异变红才算验收成立;无变异红记录只写「已实现,拦截能力未证」(test-conventions §6) -- **验收闭合**——每个需求点与每个行为改动都要有从真实入口进入的验收断言,撤销该改动能让对应断言变红;禁删断言/放宽阈值换绿;合回前独立验收审计未过则禁止合并(细则=test-conventions §9+iter 技能第 5 步) +- **验收闭合**——每个需求点与每个行为改动都要有从真实入口进入的验收断言,撤销该改动能让对应断言变红;禁删断言/放宽阈值换绿;合回前独立验收审计未过则禁止合并(细则=test-conventions §8+iter 技能第 5 步) - 规则评估——没在真实任务上评估过的规则修订,不算完成。 - 中间产物吸收即死——结论先吸收进权威文档、未决先迁待办清单,文件即删且永不提交(doc-conventions 第 11 节) - **禁写变更记录**——文档与代码文件内一律禁设「版本历史/修订记录/变更记录/修改记录/更新记录/更新日志」节或表格,禁写「本版改了哪些条款」式逐版本叙述与 `# 2026-xx-xx 缺陷修批——` 式行内修订注记;沿革只进 git commit log。版本号可作文档现行身份标记留在文首状态行与正文引用中(doc-conventions 第 5 节,机检闸 gdd_lint R4 反转拦截) diff --git a/design/engineering/code-conventions.md b/design/engineering/code-conventions.md index 129e5771..2777509b 100644 --- a/design/engineering/code-conventions.md +++ b/design/engineering/code-conventions.md @@ -52,7 +52,7 @@ ## 3. 测试纪律 -已独立成文:`design/engineering/test-conventions.md`(探针标配 / 回归断言 / 提交前全量验证 / 验收清单落码规范 / 变异验证)。 +已独立成文:`design/engineering/test-conventions.md`(探针标配 / 回归断言 / 提交前全量验证 / 验收清单落码规范)。 --- diff --git a/design/engineering/process-conventions.md b/design/engineering/process-conventions.md index 5652a31f..a167b774 100644 --- a/design/engineering/process-conventions.md +++ b/design/engineering/process-conventions.md @@ -44,18 +44,17 @@ 5. **涉数值改动先采改前读数**——与改后同随机种子配对比较并写明逐项比对口径;无数值改动禁跑模拟 **实施** -6. **新功能必配新测试**——新增玩法/机制必须配套新测试套件进 `tests/run_all`;没有对应测试的变更不许合并;并按 test-conventions §9 挂进改动—验收对照表,没有对照表行的行为改动同样不许合并 +6. **新功能必配新测试**——新增玩法/机制必须配套新测试套件进 `tests/run_all`;没有对应测试的变更不许合并;并按 test-conventions §8 挂进改动—验收对照表,没有对照表行的行为改动同样不许合并 7. **验收改动先行声明**——验收变化(基线换代/探针增改/旧断言改判)预先写进需求卡片,禁事后补 -8. **验收函数变异验证**——新增/改写的验收函数(冒烟断言/探针自检/闸机判据)必须配一次变异验证:故意把被测件改坏成该类缺陷形态 → 跑最窄那道闸确认变红 → `git checkout` 精确还原;变异点/跑的闸/红输出摘要/还原结论四件记入实现报告变异验证记录表;**无变异红记录的断言不写「已验收」,只写「已实现,拦截能力未证」**(细则见 test-conventions §6);行为改动另做撤销证明(test-conventions §9.4),两类证明都记入实现报告 **完成** -9. **批末按域验收才合并**——在任务 worktree 内跑 `tools/run_all_gates.sh`,**按本批改动域选档**:本批改动触及 `game/`(游戏工程代码、测试、探针、场景)→ `--code`;不触及 `game/` 的一切改动(`design/`、根规则文件、`tools/` 工具脚本、`.zcode/` 配置等)→ `--docs`;同批混触 `game/` 与文档面 → 全量档不带参数。所选域全绿才合回 master。合回前独立验收审计通过(iter 技能第 5 步),未过不合回。该脚本是全部验证闸的**唯一入口、唯一清单与唯一域划分**,闸件增减、分域调整都只改它;**本文与其他文档禁另列闸件清单**(清单散落多处正是 iter27 漏跑 `probe_gate --full` 的成因)。跑完写回执 `game/tests/.gates/receipt.json`(含 `domain` 字段),合回时由 worktree-guard 按 diff 路径推域强制校验(六况拦截:缺回执/quick 模式/回执 commit ≠ HEAD/域不覆盖本次改动/含新增红/master HEAD 非回执 commit 祖先=合并将产出未测内容)。闸件(`tools/` 下机检脚本与闸壳)自身的改动不占合回全量——其质量义务=落批时的变异验证(test-conventions §6),闸真崩溃时合回闸 fail-closed(跑不出回执即拦),不以合回全量为兜底 -10. **合并后主区零复跑**(2026-10-24 用户裁:合回重跑验的是与回执同一份字节,零信息)——合回落地后 code 批只做两件秒级事:`--editor --quit` 重刷类名缓存(在册坑:.godot 缓存不入 git,与合并后代码失配会假红假绿)+冒烟启动确认可开机(合计约 1 分钟);docs 批零动作。全量验证只发生在两处=worktree 批末按域闸、分支并入推进过的 master 后重跑本域闸(§1 第 2 条);「合并将产出未测内容」由合回闸祖先判定前置拦截(§3.9 第六况),master 上永不跑全量 -11. **批次完成后的登记义务**——合回 master 后按 doc-conventions §12.1 推进待办清单条目状态(做完整条删除),涉及迭代编排的在 roadmap 迭代总表与顶部「当前位」节换代——执行入口=项目技能 batch-closure(批后收尾与中间文档退役),跨会话教训写记忆库。批次过程与结论由 git 提交信息承载,禁止再写会话状态文件(见 doc-conventions 第 10 节)。`design/` 与根规则文件(`AGENTS.md`/`roadmap.md`/`待办清单.md`/`体验验证清单.md`)实现批禁写,见 §12 -12. **文档同步闸(实现批禁写文档)**——实现批**禁写 `design/` 整个目录与根规则文件**,要往外交代的东西一律落 `reports/`:实现报告 `reports/iter-实现报告-<日期>.md`(各卡状态+实机目检总清单+遗留读数义务)、代拍板追认单 `reports/iter-代拍板-<日期>.md`、GDD 反哺点清单 `reports/iter-反哺点-<日期>.md`(每条写清哪个文件哪一节、改成什么、依据是什么)。设计权威文档(GDD/art-bible)**任何批都不直改**:用户在会话中逐点裁决后,由非迭代批(工具/规则/文档批)写入 `design/`(执行入口=doc-design 技能),并把反哺条目从 `reports/` 清掉(吸收即死;退役执行=batch-closure 技能)。机械面文档(roadmap 行/术语表/README 工具注)同样归非迭代批在合并前更新。反哺点未落地期间相关 GDD 节视为待反哺,读前先查 `reports/` 与待办清单;需求卡片必列「关联文档同步面」按两层标注 -13. **实机目检归用户,只登记不阻塞**——真人检测项登记进实现报告目检总清单与体验验证清单即完成批内义务;禁把等目检当停工理由或完成前置 -14. **中间产物吸收即死**——细则见 AGENTS.md 硬性红线与 doc-conventions 第 11 节 -15. **改动级验收闭合**——写卡期列需求侧对照表,实现期补实际对照表(测试文件:行),每个行为改动做撤销证明;合回前独立验收审计。细则=test-conventions §9 +8. **批末按域验收才合并**——在任务 worktree 内跑 `tools/run_all_gates.sh`,**按本批改动域选档**:本批改动触及 `game/`(游戏工程代码、测试、探针、场景)→ `--code`;不触及 `game/` 的一切改动(`design/`、根规则文件、`tools/` 工具脚本、`.zcode/` 配置等)→ `--docs`;同批混触 `game/` 与文档面 → 全量档不带参数。所选域全绿才合回 master。合回前独立验收审计通过(iter 技能第 5 步),未过不合回。该脚本是全部验证闸的**唯一入口、唯一清单与唯一域划分**,闸件增减、分域调整都只改它;**本文与其他文档禁另列闸件清单**(清单散落多处正是 iter27 漏跑 `probe_gate --full` 的成因)。跑完写回执 `game/tests/.gates/receipt.json`(含 `domain` 字段),合回时由 worktree-guard 按 diff 路径推域强制校验(六况拦截:缺回执/quick 模式/回执 commit ≠ HEAD/域不覆盖本次改动/含新增红/master HEAD 非回执 commit 祖先=合并将产出未测内容)。闸件(`tools/` 下机检脚本与闸壳)自身的改动不占合回全量——其质量义务=落批时人工确认闸可跑通且判据口径未变,闸真崩溃时合回闸 fail-closed(跑不出回执即拦),不以合回全量为兜底 +9. **合并后主区零复跑**(2026-10-24 用户裁:合回重跑验的是与回执同一份字节,零信息)——合回落地后 code 批只做两件秒级事:`--editor --quit` 重刷类名缓存(在册坑:.godot 缓存不入 git,与合并后代码失配会假红假绿)+冒烟启动确认可开机(合计约 1 分钟);docs 批零动作。全量验证只发生在两处=worktree 批末按域闸、分支并入推进过的 master 后重跑本域闸(§1 第 2 条);「合并将产出未测内容」由合回闸祖先判定前置拦截(§3.9 第六况),master 上永不跑全量 +10. **批次完成后的登记义务**——合回 master 后按 doc-conventions §12.1 推进待办清单条目状态(做完整条删除),涉及迭代编排的在 roadmap 迭代总表与顶部「当前位」节换代——执行入口=项目技能 batch-closure(批后收尾与中间文档退役),跨会话教训写记忆库。批次过程与结论由 git 提交信息承载,禁止再写会话状态文件(见 doc-conventions 第 10 节)。`design/` 与根规则文件(`AGENTS.md`/`roadmap.md`/`待办清单.md`/`体验验证清单.md`)实现批禁写,见 §12 +11. **文档同步闸(实现批禁写文档)**——实现批**禁写 `design/` 整个目录与根规则文件**,要往外交代的东西一律落 `reports/`:实现报告 `reports/iter-实现报告-<日期>.md`(各卡状态+实机目检总清单+遗留读数义务)、代拍板追认单 `reports/iter-代拍板-<日期>.md`、GDD 反哺点清单 `reports/iter-反哺点-<日期>.md`(每条写清哪个文件哪一节、改成什么、依据是什么)。设计权威文档(GDD/art-bible)**任何批都不直改**:用户在会话中逐点裁决后,由非迭代批(工具/规则/文档批)写入 `design/`(执行入口=doc-design 技能),并把反哺条目从 `reports/` 清掉(吸收即死;退役执行=batch-closure 技能)。机械面文档(roadmap 行/术语表/README 工具注)同样归非迭代批在合并前更新。反哺点未落地期间相关 GDD 节视为待反哺,读前先查 `reports/` 与待办清单;需求卡片必列「关联文档同步面」按两层标注 +12. **实机目检归用户,只登记不阻塞**——真人检测项登记进实现报告目检总清单与体验验证清单即完成批内义务;禁把等目检当停工理由或完成前置 +13. **中间产物吸收即死**——细则见 AGENTS.md 硬性红线与 doc-conventions 第 11 节 +14. **改动级验收闭合**——写卡期列需求侧对照表,实现期补实际对照表(测试文件:行),每个行为改动做撤销证明;合回前独立验收审计。细则=test-conventions §8 ## 4. 测试执行两入口铁规(细则) diff --git a/design/engineering/test-conventions.md b/design/engineering/test-conventions.md index a2839595..e4a7e133 100644 --- a/design/engineering/test-conventions.md +++ b/design/engineering/test-conventions.md @@ -48,52 +48,32 @@ 4. **调试注入两层(能力测试与流程体验两分法的落码面)**:自动化测试=测试代码直调核心层写口构造状态(直改数据表行/计数器/存档域,不经 UI、不走正常资源积累流程——冒烟现役做法);人工体验=DebugOverlay/DS_DEBUG 调试面,服务用户目检。清单条目的「怎么测」必须写到数据面粒度:改哪张表哪行、置哪个计数、调哪个核心写口。 5. **换代批旧验证约束同生死**:删除旧数据行/旧实现代码的批次,必须同批摘除只验证旧实现的断言与护栏校验,由新断言替代——旧件断言残留=冒烟假绿来源;合并后冒烟全绿且全仓无旧件残留引用为证。 -## 6. 变异验证——验收函数的拦截能力自证 - -测试绿只证明「当前代码没犯这个错」,不证明「犯了这个错会被抓住」。新增或改写的验收函数(冒烟断言/探针自检/闸机判据)必须配一次变异验证,把拦截能力自证一遍。**无变异红记录的断言不写「已验收」,只写「已实现,拦截能力未证」。** - -行为改动的撤销证明见 §9.4。新增或改写断言用变异验证;修改既有行为用撤销证明。两者不互相代替:变异证明断言能抓这一类缺陷,撤销证明断言真的钉在这次改动上。 - -**操作四步(逐条落实现报告变异验证记录表)**: - -1. **注入**——把被测件改坏成该类缺陷的最小形态(翻装配序、注释一行 `add_child`、把状态源取反、把层 `visible` 置 false)。一次只注入一处;可直接改源码,不必留长期开关。 -2. **跑最窄的那一道闸**——只跑能覆盖该断言的最小单元(单冒烟脚本/单探针/单比对命令),禁跑全套闸(见 process-conventions §6 闸机轮次纪律)。判据:注入后该断言**必须变红**;红在别处而目标断言仍绿=判据没打在缺陷上,按第 4 条处理。 -3. **精确还原**——`git checkout -- <文件>`(不用 `git stash`、不手工回改,防残留)。还原后复跑同一道闸确认回绿,才算本轮闭环。 -4. **记录**——变异点(文件:行)、跑的闸、红输出摘要、还原结论,逐条进实现报告记录表。 - -**变异不红怎么办(二选一,不许含糊带过)**: - -- **改判据**——把断言打到真正的缺陷面上(例:断言「菜单标题可见」只查截图墨色占比时,把菜单层藏起来仍不红——底层棋盘透过标题框照样给出高反差像素;改查 `is_visible_in_tree` 或加 golden 逐像素比对才红)。 -- **如实标注拦截边界**——判据本身只覆盖弱面的(如「只证伪整框空白/整框糊,不证明框里是何内容」),在断言注释与报告里写明边界,并说明强判据由哪一件承担。 - -**判据强弱分层**:同一缺陷面往往需要多件配合——**可见性/状态源类**缺陷由 `is_visible_in_tree`、树序、状态源取值的**运行期断言**抓;**内容/观感类**缺陷由 **golden 逐像素比对**抓;**占比/统计类**判据(墨色占比、纹理幅度)只能兜「整框空白/整框糊/压 busy 纹理」,是补充不是主力。写卡时按此分层配齐,别指望一条断言包打。 - -## 7. 判定三硬闸——闸承载的构造义务(迭代 29 起) +## 6. 判定三硬闸——闸承载的构造义务(迭代 29 起) 任何**新增或改写的闸承载**(闸脚本/批跑编排/探针入口)必须三闸齐备;现行各闸状态登记归架构文档「测试与质量域」节(本文不另列闸件清单): 1. **退出码为唯一权威判据**——输出里的 PASS 串只作附加判据不作判据主体;打印 PASS 后 `quit(1)` 必须判红。 -2. **SCRIPT ERROR / Parse Error 扫描面在位**——GDScript 脚本错误不改进程退出码、不计失败数(机制事实见 §8),错误标记必须扫输出,且判据必须覆盖「跑了但半途脚本错误」态——退出码 0 但输出缺预期签名同样判红(防静默退出)。 +2. **SCRIPT ERROR / Parse Error 扫描面在位**——GDScript 脚本错误不改进程退出码、不计失败数(机制事实见 §7),错误标记必须扫输出,且判据必须覆盖「跑了但半途脚本错误」态——退出码 0 但输出缺预期签名同样判红(防静默退出)。 3. **断言数下限**——零断言的正常返回与断言失败必须区分开(现行做法:`Kit.finish` 零断言返回专用退出码 2,不与「断言失败=1」混用,否则致命类套件的期望码协议会放过空跑)。 - 负面套件(测试目标就是产生错误输出)仅可豁免第 2 闸,且须在 manifest 显式标记,其余两闸照判。 - 子进程输出须经系统命令解释器重定向落盘再读——`OS.execute` 的输出管道在本机恒空。 **新写测试件全类型标注**——新写的测试件(冒烟断言/探针/单测)参数、返回值、容器一律带类型标注,与 S9 对产品码的要求同型;存量不强制清扫,被批次触碰时顺带换代。暂不机器闸(S9 扫描面=产品码,probe/sim/tests 不在扫描面是测量面直构惯例的既有裁量)。 -## 8. 判定可靠性优先于覆盖率(迭代 29 核心命题) +## 7. 判定可靠性优先于覆盖率(迭代 29 核心命题) - 「跑一遍没崩=通过」无效:测试绿只证明**当前代码没犯这个错**,不证明**犯了这个错会被抓住**;断言存在不等于断言执行。 - **脚本错误会静默中断所在函数的剩余断言,而套件仍报全绿**(机制事实):GDScript 无脚本错误陷阱 API,错误不改进程退出码、不计失败数。三处实证:①2026-09-19「309 项 0 失败」实为断言未跑全(状态记录 83);②敌人表行集纪律 10 条断言因定型数组赋值错误从未执行(迭代 29 修复后两条正向见红=夹具本缺锚行);③`Callable` 形参类型写错致解析函数返回 null、后续断言整段蒸发。 -- 由此产生两条义务:**写闸件**按 §7 配三硬闸;**写验收函数**必须自证断言全数执行——变异验证(§6)为主证,反例实证(构造缺陷态改前判绿/改后判红)与零命中自检(扫描面为空即判红)为辅证。 +- 由此产生两条义务:**写闸件**按 §6 配三硬闸;**写验收函数**必须自证断言全数执行——撤销证明(§8.4)为主证,零命中自检(扫描面为空即判红)为辅证。 - **覆盖率不是目标**:行覆盖率度量缺失(Godot 无内建,第三方属新基建,是否引入待办清单在册待裁);现行补洞=零指名单测清单+人工判定,判定可靠性靠上列自证手段,不靠覆盖率数字。 -## 9. 改动级验收闭合(2026-10-21 立) +## 8. 改动级验收闭合(2026-10-21 立) -### 9.1 验收单位是行为改动 +### 8.1 验收单位是行为改动 一个行为改动 = 新增或修改一条函数、一条数据、一处接线、一个生命周期行为、一条玩家可见文案。纯改名、注释、格式化不算行为改动,但必须在对照表里单独列一行写「非行为改动」及判断依据。禁止用「重构」两个字把行为改动藏起来。 -### 9.2 四层与真实入口 +### 8.2 四层与真实入口 - **单元**:不依赖场景树和真实宿主的纯逻辑;测试直接调用被测函数。 - **接口**:模块边界的公开契约——数据表加载、存档与断点、事件载荷、命令接口;测试从公开入口进出。 @@ -102,11 +82,11 @@ 分层不是形式。改动发生在哪一层,验收就必须从那一层的真实入口进入。测试绕过了改动点,就不算这个改动的验收——这正是「断言存在、接线坏了却不红」的来源。 -### 9.3 改动—验收对照表 +### 8.3 改动—验收对照表 需求卡片列需求侧对照表;实现报告列实际对照表。每行至少六格: -| 需求点 | 改动(文件:行/行为) | 验收测试(名称+文件:行+尾缀) | 层级 | 真实入口 | 撤销或变异证明 | +| 需求点 | 改动(文件:行/行为) | 验收测试(名称+文件:行+尾缀) | 层级 | 真实入口 | 撤销证明 | |---|---|---|---|---|---| 实现报告另加「结果」格(绿/红/未过及依据)。两端都要对上: @@ -117,22 +97,22 @@ **验证集清单维护锚(2026-10-22 用户裁)**:`game/tests/验证集清单.md` 是迁移断言全体的冻结参照清单(机器提取生成、只剪切禁改写、出口逐条核对,机制见该文件头注;清单自断言迁移批第 0 步建立时起存在)——清单在册后,任何断言**新增、删除或改判**必须同步该清单,与改动—验收对照表同一条纪律:清单没跟上的断言改动视同未完成。 -### 9.4 撤销证明 +### 8.4 撤销证明 - **修改既有行为**:只撤销该改动(回退该 hunk 或该处接线)→ 跑能覆盖它的最窄测试 → 对应断言必须变红 → 还原 → 复绿。 -- **新增行为**:用 §6 的变异办法把新代码改坏成最小缺陷形态 → 对应断言必须变红。 +- **新增行为**:只撤销该新增(回退该 hunk 或删去该新增段)→ 跑能覆盖它的最窄测试 → 对应断言必须变红 → 还原 → 复绿。 - **撤销后仍然绿**:说明断言没钉在这个改动上,判缺漏;不得用「代码能跑通」代替。 -- 每张任务卡至少一条撤销或变异记录;持久化、生命周期、存档、跨战共享这类接线逐行做。 +- 每张任务卡至少一条撤销证明记录;持久化、生命周期、存档、跨战共享这类接线逐行做。 -### 9.5 禁止削弱测试 +### 8.5 禁止削弱测试 实现期不得为了让测试变绿而删除断言、放宽阈值、缩小扫描面、把真实入口换成下层直调。确需改判据=需求卡片没写清=上游缺陷:停该卡、呈报退回写卡段,不在实现期自行决定。卡片可预先声明允许改动的旧断言及理由;未声明的削弱由独立审计判红。 -### 9.6 测试时机 +### 8.6 测试时机 -不要求 TDD,不要求先红后绿。允许实现后补测试;但补的测试必须通过 §9.4 的撤销证明。实现完再补、补完就绿,不算验收。 +不要求 TDD,不要求先红后绿。允许实现后补测试;但补的测试必须通过 §8.4 的撤销证明。实现完再补、补完就绿,不算验收。 -### 9.7 独立验收审计 +### 8.7 独立验收审计 合并前由没有参与实现的会话或子代理做一次审计。审计只读需求卡片、实际对照表、diff、测试文件和实现报告,自己跑最窄测试抽查,不采信报告里的「已全绿」。审计至少做三件事: @@ -142,6 +122,6 @@ 审计报告落 `reports/iter-验收审计-<日期>.md`,逐行写「通过/缺漏/例外及依据」。未通过不得合并。测试执行两入口铁规不变:审计在迭代 loop 内启动的子代理算 loop;另开会话须用户点名。 -### 9.8 生效与旧卡 +### 8.8 生效与旧卡 本规自 2026-10-21 起对文件名日期不早于该日的需求卡片生效;旧卡不回头改。旧卡在开工前缺对照表的,由写卡段补,补完再开工。 diff --git a/game/core/save_manager.gd b/game/core/save_manager.gd index 01e0dc26..9c09daf3 100644 --- a/game/core/save_manager.gd +++ b/game/core/save_manager.gd @@ -612,7 +612,7 @@ func breakpoint_snapshot() -> Dictionary: # 旧隐式单档一次性迁移(Q1 甲,sv12):src 字节级原样搬运到 dst(零解析零改造——损坏/高版本 # 旧档字节原样落槽 1,读取时由正式进档路径的兜底/拒读链接管,不静默丢数据); -# dst 已存在不重迁(幂等判据——变异④锚点:去判据则重复迁移覆盖槽 1);迁移成功后 src 改名 +# dst 已存在不重迁(幂等判据——判别锚④:去判据则重复迁移覆盖槽 1);迁移成功后 src 改名 # bak 留痕(不删——处置字节留痕,防再次隐式读写)。任一步失败:源保留原地,下次启动重试。 # tmp+rename 原子形态与 write_to_disk 同纪律。生产调用=src/dst/bak 为 旧单档/槽 1/留痕名。 func _migrate_legacy_save(src: String, dst: String, bak: String) -> void: diff --git a/game/probe/layout_probe.gd b/game/probe/layout_probe.gd index f16c8573..25f494ae 100644 --- a/game/probe/layout_probe.gd +++ b/game/probe/layout_probe.gd @@ -69,9 +69,9 @@ func _check_one(label: String, main: Node) -> void: elif not vr.encloses(r): _problems.append("[%s] %s 越视口 %s ⊄ %s" % [label, key, r, vr]) # 判据覆盖边界(如实记录,勿当已拦截):本探针按名点名三区做几何判定, - # 不遍历战斗屏宿主的全部后代。变异验证第二发证——向装配器注入一个全幅 ColorRect - # (挂在 battle_root 的内层根下)时探针仍全绿:「未登记兄弟控件」这一缺陷类不在本探针 - # 拦截面内。要拦它得改为递归遍历全子树找重叠,那是另一套判据(且极易误报容器父子关系), + # 不遍历战斗屏宿主的全部后代——「未登记兄弟控件」(如向装配器塞一个挂在 + # battle_root 内层根下的全幅 ColorRect)这一缺陷类不在本探针拦截面内,探针对此仍全绿。 + # 要拦它得改为递归遍历全子树找重叠,那是另一套判据(且极易误报容器父子关系), # 本探针不设此判据。 var bv: Control = main.board_view if bv == null: diff --git a/game/probe/ui_struct_probe.gd b/game/probe/ui_struct_probe.gd index 4deede60..93141b51 100644 --- a/game/probe/ui_struct_probe.gd +++ b/game/probe/ui_struct_probe.gd @@ -438,7 +438,7 @@ func _save_select_contract(main: Node, tpl: String) -> void: if not has_keystone: problems.append("[savesel] 槽1 钥石徽读数缺失(应=钥石 555)〔sl2〕") # sl3 摘要禁项:断点/种子/「继续」/停点/「 关」(关数形——「通关」无空格不误伤)零命中 - #(裁决 4——零未完冒险读数;词形覆盖=对照表 sl3 变异「断点关数拼进槽卡」的拦截面) + #(裁决 4——零未完冒险读数;词形覆盖=对照表 sl3 缺陷形态「断点关数拼进槽卡」的拦截面) for needle in ["断点", "种子", "继续", "停点", " 关"]: for t in all_texts: if t.contains(needle): diff --git a/game/tests/unit/battle_settlement/roll_multiplier_test.gd b/game/tests/unit/battle_settlement/roll_multiplier_test.gd index 9fb8ecd1..f0c7f5f6 100644 --- a/game/tests/unit/battle_settlement/roll_multiplier_test.gd +++ b/game/tests/unit/battle_settlement/roll_multiplier_test.gd @@ -7,7 +7,7 @@ # 战斗结算 fresh 池攻击链回归(Bug#2——池空时按掷点档位足额兑现) # 协议照单元侧惯例:extends SceneTree+Kit.check 主通道;--script 模式无 autoload, # ConfigDB 显式实例化构造注入(各套自建 RngService——源套掷点隔离形态,宿主不持统一流); -# 表加载失败不中止(沿被迁断言面的源语义——诊断在此展开,表值变异的红由具体断言落,承 G2/G3 同款)。 +# 表加载失败不中止(沿被迁断言面的源语义——诊断在此展开,表值走偏的红由具体断言落,承 G2/G3 同款)。 # 运行:godot --headless --path game --script res://tests/unit/battle_settlement/roll_multiplier_test.gd extends SceneTree diff --git a/game/tests/unit/battle_settlement/seal_polarity_test.gd b/game/tests/unit/battle_settlement/seal_polarity_test.gd index 82b7390e..9ec524b7 100644 --- a/game/tests/unit/battle_settlement/seal_polarity_test.gd +++ b/game/tests/unit/battle_settlement/seal_polarity_test.gd @@ -10,7 +10,7 @@ # 格面资源资格面(揭示事件 resource 标记 + 封锁格身份查询) # 协议照单元侧惯例:extends SceneTree+Kit.check 主通道;--script 模式无 autoload, # ConfigDB 显式实例化构造注入(各套自建 RngService——源套掷点隔离形态,宿主不持统一流); -# 表加载失败不中止(沿被迁断言面的源语义——诊断在此展开,表值变异的红由具体断言落,承 G2/G3/G4 同款)。 +# 表加载失败不中止(沿被迁断言面的源语义——诊断在此展开,表值走偏的红由具体断言落,承 G2/G3/G4 同款)。 # 运行:godot --headless --path game --script res://tests/unit/battle_settlement/seal_polarity_test.gd extends SceneTree diff --git a/game/tests/unit/core/board_gen_reward_test.gd b/game/tests/unit/core/board_gen_reward_test.gd index ea75b84f..d9439042 100644 --- a/game/tests/unit/core/board_gen_reward_test.gd +++ b/game/tests/unit/core/board_gen_reward_test.gd @@ -6,7 +6,7 @@ # 地图战斗资源·伤害量值区间(中点锚 / 域内 / 流动 / 定值不受扰) # 协议照单元侧惯例:extends SceneTree+Kit.check 主通道;--script 模式无 autoload, # ConfigDB/RngService 显式实例化构造注入(统一流 master 种子 42 沿源); -# 表加载失败不中止(沿被迁断言面的源语义——诊断在此展开,表值变异的红由具体断言落,承 G2 同款)。 +# 表加载失败不中止(沿被迁断言面的源语义——诊断在此展开,表值走偏的红由具体断言落,承 G2 同款)。 # 运行:godot --headless --path game --script res://tests/unit/core/board_gen_reward_test.gd extends SceneTree diff --git a/game/tests/unit/core/meta_progression_forge_test.gd b/game/tests/unit/core/meta_progression_forge_test.gd index 7bbe65c2..9296434e 100644 --- a/game/tests/unit/core/meta_progression_forge_test.gd +++ b/game/tests/unit/core/meta_progression_forge_test.gd @@ -8,7 +8,7 @@ # 天赋树六键行为(先手窗/危险直觉限次/守侧五场景/财富之道聚散) # 协议照单元侧惯例:extends SceneTree+Kit.check 主通道;--script 模式无 autoload, # ConfigDB 显式实例化构造注入;表加载失败不中止(沿被迁断言面的源语义——诊断在此展开, -# 表值变异的红由具体断言落,承 G2/G3/G4/G5 同款);全局 class_name(Attunement/EffectEngine/ +# 表值走偏的红由具体断言落,承 G2/G3/G4/G5 同款);全局 class_name(Attunement/EffectEngine/ # EffectContext)裸用(--script 模式全局类在册,G3 先例)。 # 运行:godot --headless --path game --script res://tests/unit/core/meta_progression_forge_test.gd extends SceneTree diff --git a/game/tests/unit/core/save_boot_no_activate_test.gd b/game/tests/unit/core/save_boot_no_activate_test.gd index 27674ed7..4ac1d291 100644 --- a/game/tests/unit/core/save_boot_no_activate_test.gd +++ b/game/tests/unit/core/save_boot_no_activate_test.gd @@ -1,6 +1,6 @@ # tests/unit/core/save_boot_no_activate_test.gd — 卡① sv2/sv3:启动态钉死类级契约 # (无参实例=无激活态、内存=默认合法空态、无激活写盘一律拒绝并返回 false 且盘面零触碰 -# 〔含空路径派生的裸 ".tmp" 退化写目标——拆闸变异的可判别锚〕、MetaProgression.settle_adventure +# 〔含空路径派生的裸 ".tmp" 退化写目标——拆闸缺陷的可判别锚〕、MetaProgression.settle_adventure # 生产链无激活触达写盘被拒、访问器 fail-safe 合法空值、越界槽号拒绝。 # 真实 autoload boot 链断言在冒烟 V2-s1..s4 段——--script 模式无 autoload,本套件为类级 # 白盒面+生产链对照,双落点在实现报告实际对照表对账。) @@ -38,7 +38,7 @@ func _test_no_arg_instance_has_no_activation() -> void: # ② 无激活态写盘一律拒绝并返回 false,盘面零触碰(sv3 类级——真实入口=冒烟 V2-s3 生产链) # 判别锚:空 _path 的退化写目标=裸 ".tmp"(落 res://,拆闸实验实测杂散落点)—— -# 断言先清退化目标再核零新增,闸短路变异(拒绝口旁路、写盘真实发生)必红。 +# 断言先清退化目标再核零新增,闸短路缺陷(拒绝口旁路、写盘真实发生)必红。 func _test_write_rejected_without_target() -> void: var sm := SaveManagerScript.new() var before := {} diff --git a/game/tests/unit/core/save_manager_domain_test.gd b/game/tests/unit/core/save_manager_domain_test.gd index b24e5847..20cc3315 100644 --- a/game/tests/unit/core/save_manager_domain_test.gd +++ b/game/tests/unit/core/save_manager_domain_test.gd @@ -388,7 +388,7 @@ func _smoke_save_slots() -> void: Kit.check("sv6 删槽 2 槽 1 字节不动(位间互隔离)〔卡① sv6〕", FileAccess.get_file_as_bytes(slot_tpl % 1) == slot1_before) - # ③ 新档原语(sv4):非白板旧内容覆盖为全零可玩白板(判别锚:新档禁读旧档——变异可红), + # ③ 新档原语(sv4):非白板旧内容覆盖为全零可玩白板(判别锚:新档禁读旧档——判据撤除即红), # 创建即激活并落盘(生产路径只在空槽调用;本段预置旧内容是对原语白板保证的钉死,超生产面) var fold := FileAccess.open(slot_tpl % 3, FileAccess.WRITE) fold.store_string(JSON.stringify({"version": 7, "meta": {"keystone_balance": 999, diff --git a/game/tests/unit/data_config/forge_table_test.gd b/game/tests/unit/data_config/forge_table_test.gd index ac80b023..a9054b27 100644 --- a/game/tests/unit/data_config/forge_table_test.gd +++ b/game/tests/unit/data_config/forge_table_test.gd @@ -119,7 +119,7 @@ func _has_cat(errs: Array, cat: String) -> bool: return false -# 多字段变异器(lambda 单表达式装不下的用例——命名函数承载) +# 多字段改值器(lambda 单表达式装不下的用例——命名函数承载) func _mut_spear_initial(t) -> void: t.routes[1]["initial_owned"] = true t.routes[1]["prereq_route"] = "" diff --git a/game/tests/unit/data_config/level_gen_params_test.gd b/game/tests/unit/data_config/level_gen_params_test.gd index b6f13733..d99beb67 100644 --- a/game/tests/unit/data_config/level_gen_params_test.gd +++ b/game/tests/unit/data_config/level_gen_params_test.gd @@ -70,10 +70,10 @@ func _test_negative() -> void: _row(2, 9, 0.5, [0.5, 0.2, 0.15, 0.15], 2, 2, 6), _row(3, 13, 0.7, [0.55, 0.15, 0.15, 0.15], 2, 3, 8)] Kit.check("合法三行域校验零错误(夹具自证)〔fv2〕", _table(base).validate().is_empty()) - # ① L1 出口改 2 → 出口恒 1 断言红(变异步同款) + # ① L1 出口改 2 → 出口恒 1 断言红(负样本夹具) var bad_l1_exit := [_row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 2, 4), base[1], base[2]] Kit.check("L1 出口=2 被拒(出口 L1 恒 1 已锁)〔fv2〕", not _table(bad_l1_exit).validate().is_empty()) - # ② 配比合计 0.5 → 合计 1 断言红(变异步同款) + # ② 配比合计 0.5 → 合计 1 断言红(负样本夹具) var bad_ratio := [_row(1, 6, 0.3, [0.2, 0.1, 0.1, 0.1], 1, 1, 4), base[1], base[2]] Kit.check("配比合计 0.5 被拒(四类合计 1 已锁)〔fv2〕", not _table(bad_ratio).validate().is_empty()) # ③ 层深低于下限 diff --git a/reports/需求卡片-状态面板瘦身批-2026-10-23.md b/reports/需求卡片-状态面板瘦身批-2026-10-23.md index 72bdfb6f..00297296 100644 --- a/reports/需求卡片-状态面板瘦身批-2026-10-23.md +++ b/reports/需求卡片-状态面板瘦身批-2026-10-23.md @@ -27,7 +27,7 @@ 2. 跨关概览退役零残留:面板子树零「道具工坊」「天赋树」文案、`_status_data()` 零 workshop/tree/fork_groups 三旧键、真实入口(角标开层)同判据绿; 3. 文案三处换代在位且标题「状态」/「继续」钮定位锚不变(四探针状态面板相关段零红); 4. 只读契约与零动效契约保持全绿(`ui_struct_probe` ⑧:信号连接数=2、源码零 tween/AnimationPlayer——非新增断言,回归线); -5. 变异验证记录表进实现报告;批末重闸按改动域选档全绿+改前改后读数对拍;三份 `reports/` 产出物写齐(T2)。 +5. 撤销证明记录进实现报告;批末重闸按改动域选档全绿+改前改后读数对拍;三份 `reports/` 产出物写齐(T2)。 ## 2. 设计事实源 @@ -106,7 +106,7 @@ | `game/presentation/main.gd` | `_status_data()` 四键→八键投影换代(复用既有·修改) | 行为改动 → 对照表 sv1/sv2/sv3/sv7 | | `game/presentation/views/board_zone_view.gd` | 角标 tooltip 一句换代(复用既有·修改) | 行为改动 → 对照表 sv9 | | `game/presentation/views/level_map_screen.gd` | 角标 tooltip 一句换代(复用既有·修改) | 行为改动 → 对照表 sv9 | -| `game/smoke/smoke_all.gd` | `_status_panel_projection` 断言面换代(复用既有·改写验收函数——变异伴生义务) | 行为改动(断言面)→ 对照表 sv1–sv5/sv8 | +| `game/smoke/smoke_all.gd` | `_status_panel_projection` 断言面换代(复用既有·改写验收函数——验收闭合对照义务) | 行为改动(断言面)→ 对照表 sv1–sv5/sv8 | | `game/smoke/ui_click_probe.gd` | 真实入口补三断言:零旧段+属性行全值+`_status_data()` 直调对拍(复用既有·增步) | 行为改动(断言面)→ 对照表 sv6/sv7 | | `reports/iter-实现报告/代拍板追认单/反哺点`(三份,批末写) | 产出物落位 | 非行为改动 → 对照表 sv10 | @@ -137,14 +137,14 @@ - [ ] 实装两角标 tooltip 换代(`board_zone_view.gd:58`、`level_map_screen.gd:107` →「查看本局冒险进度(只读)」)。可核查结果:全仓「永久强化进度」检索零命中。 - [ ] 实装冒烟 `_status_panel_projection` 换代(`smoke_all.gd:5727-5779` 重写:夹具改八键手拼〔同构口径不变、不依赖 runner〕;断言=余额徽读数+属性行全值+秘宝行含已用尾缀+专长行串+空态句×2+面板子树零旧段文案;原工坊 12 行断言族与天赋树聚合断言按 §8.3 申报删除)。可核查结果:该段绿且含 V1/V2 全部断言。 - [ ] 验收步骤:T 段出口跑一次全套闸(`tools/run_all_gates.sh` 按改动域选档,本批只碰 `game/` → `--code`),期望代码域全绿、`ui_struct_probe` ⑧ 两契约与 click/input/shot 三探针状态面板段零红。 -- [ ] 变异验证(注入→最窄闸见红→`git checkout` 精确还原→记录):①面板 gp 读数改硬编码 `0` → 期望属性行断言红;②「(已用)」尾缀逻辑删 → 期望秘宝行断言红;③面板重加「道具工坊 · 解锁态」段头 → 期望零旧段断言红。记录表进实现报告。 +- [ ] 撤销证明(撤销改动→最窄闸见红→`git checkout` 精确还原→记录):①回退面板 gp 读数投影 hunk → 期望属性行断言红;②回退「(已用)」尾缀逻辑 hunk → 期望秘宝行断言红;③回退旧段退役 hunk(旧段头复现)→ 期望零旧段断言红。记录进实现报告。 ### T2 真实入口断言+产出物落位卡(≈0.25–0.5d,末卡) - [ ] 实装 `ui_click_probe` 状态面板段补三断言(`ui_click_probe.gd:593-621` 段内,角标开层后):①面板子树零「道具工坊」「天赋树」文案;②属性行全串==契约 4 格式 % `run_scope.runner` 五现值(hero_hp/`effective_max_hp()`/`effective_atk()`/`effective_ac()`/gp——`main` 侧投影值层的真链路断言);③`main._status_data()` 直调对拍——返回键集恰为接口块八键(sv7 承载)+curios 逐行 {name, used} 对拍独立oracle(`runner.treasure_inventory.query_inventory(Callable())` 行集 × `db.treasure_item_row().display_name`)+feats 对拍 `HudPresenter.feat_holdings_lines(db, runner.feats_held())`。可核查结果:探针该段绿。 - [ ] 验收步骤:T 段出口跑一次全套闸(`--code`),期望代码域全绿。 -- [ ] 变异验证(注入→最窄闸见红→`git checkout` 精确还原→记录):①还原面板 workshop 段(注入旧段头)→ 期望断言①红(真实入口);②`_status_data()` curios 映射漏 `used` 键 → 期望断言③红(main 侧注入);③`_status_data()` max_hp 错读 `ledger["hero_hp"]` → 期望断言②红(main 侧注入)。记录表进实现报告。 -- [ ] 轻闸全绿后、合并前写齐三份:`reports/iter-实现报告-<完成日>.md`(各卡状态+变异验证记录表+实机目检总清单〔面板观感一条〕+遗留读数义务)/`reports/iter-代拍板追认单-<完成日>.md`(§10 白名单内代拍项留痕)/`reports/iter-反哺点-<完成日>.md`(§6 六条每条一落点+§11 四处推导定值逐条列示供否决)。可核查结果:三文件在 `reports/` 且 §6 同步面每条有落点、§11 定值全部列示。 +- [ ] 撤销证明(撤销改动→最窄闸见红→`git checkout` 精确还原→记录):①回退面板 workshop 段退役 hunk(旧段头复现)→ 期望断言①红(真实入口);②回退 `_status_data()` curios 映射 hunk → 期望断言③红;③回退 `_status_data()` max_hp 投影 hunk → 期望断言②红。记录进实现报告。 +- [ ] 轻闸全绿后、合并前写齐三份:`reports/iter-实现报告-<完成日>.md`(各卡状态+撤销证明记录+实机目检总清单〔面板观感一条〕+遗留读数义务)/`reports/iter-代拍板追认单-<完成日>.md`(§10 白名单内代拍项留痕)/`reports/iter-反哺点-<完成日>.md`(§6 六条每条一落点+§11 四处推导定值逐条列示供否决)。可核查结果:三文件在 `reports/` 且 §6 同步面每条有落点、§11 定值全部列示。 - [ ] 合并前置:独立验收审计(§8.2 末段声明)完成且报告 `reports/iter-验收审计-<完成日>.md` 逐行「通过」——未通过不得合并,缺漏项回炉对应 T 卡。可核查结果:审计报告在 `reports/` 且逐行「通过」。 **估时合计 ≈1–2d**(T0 0.25–0.5+T1 0.5–1+T2 0.25–0.5)。切分预案:T1 内投影与面板可切,但中间态消费键断链(面板读旧键投影已换代),建议 T1 一轮同落;本卡无超软盒预挂面(批小)。**编排注记**:本卡估时低于 iter-plan 四查③硬下限 5 工作日,单独不成迭代——与其他卡同批编入。 @@ -164,16 +164,16 @@ ### 8.2 改动—验收对照表 -> 各断言 desc 统一尾缀〔sv#〕(本表「验收测试」列可 grep 定位);变异/撤销证明逐条对应 T1/T2 变异步。 +> 各断言 desc 统一尾缀〔sv#〕(本表「验收测试」列可 grep 定位);撤销证明逐条对应 T1/T2 撤销步。 -| 需求点 | 改动(文件:行/行为) | 验收测试(名称+文件+尾缀) | 层级 | 真实入口 | 撤销或变异证明 | +| 需求点 | 改动(文件:行/行为) | 验收测试(名称+文件+尾缀) | 层级 | 真实入口 | 撤销证明 | |---|---|---|---|---|---| -| sv1 属性行投影 | `main.gd:1070-1076` 八键投影+`status_panel.gd` 属性行串(契约 4 格式) | 属性行全值投影〔sv1〕 `smoke_all.gd` `_status_panel_projection` 换代 | 集成 | `open_status()` 直喂八键夹具(同构口径) | 变异:面板 gp 硬编码 0(T1 变异步①)→ 本断言红 | -| sv2 秘宝行投影 | `_status_data()` curios 映射+面板秘宝行(受理序+「(已用)」尾缀) | 秘宝行受理序与已用尾缀〔sv2〕 同上 | 集成 | 同 sv1 | 变异:尾缀逻辑删(T1 变异步②)→ 本断言红 | +| sv1 属性行投影 | `main.gd:1070-1076` 八键投影+`status_panel.gd` 属性行串(契约 4 格式) | 属性行全值投影〔sv1〕 `smoke_all.gd` `_status_panel_projection` 换代 | 集成 | `open_status()` 直喂八键夹具(同构口径) | 撤销:回退 gp 读数投影 hunk(T1 撤销步①)→ 本断言红 | +| sv2 秘宝行投影 | `_status_data()` curios 映射+面板秘宝行(受理序+「(已用)」尾缀) | 秘宝行受理序与已用尾缀〔sv2〕 同上 | 集成 | 同 sv1 | 撤销:回退尾缀逻辑 hunk(T1 撤销步②)→ 本断言红 | | sv3 专长行投影 | `_status_data()` feats 透传+面板专长行 join | 专长行串投影〔sv3〕 同上 | 集成 | 同 sv1 | 撤销证明:回退 feats 键接线 hunk → 本断言红 | | sv4 余额徽回归 | `open_status` 余额徽喂值零改动(回归锚) | 余额徽读数=keystone_balance〔sv4〕 同上(沿旧断言族) | 集成 | 同 sv1 | 撤销证明:改余额徽喂值 hunk → 本断言红 | -| sv5 零旧段(隔离档) | `status_panel.gd` 两段整段退役(契约 2) | 面板子树零「道具工坊」「天赋树」文案〔sv5〕 同上 | 集成 | 同 sv1 | 变异:重加工坊段头(T1 变异步③)→ 本断言红 | -| sv6 零旧段+投影值真链路(真实入口) | 同 sv5 面板改动+`_status_data()` 换代+`ui_click_probe.gd:593-621` 补三断言 | 角标开层后零旧段+属性行全值对 runner 五现值+`_status_data()` 直调八键与 curios/feats 对拍〔sv6〕 `ui_click_probe.gd`(T2 新增) | 探针 | `board_zone.status_badge` pressed 真实信号路径 | 变异:旧段回插→断言①红;curios 映射漏 `used` 键→断言③红;max_hp 错读 `ledger["hero_hp"]`→断言②红(T2 变异步) | +| sv5 零旧段(隔离档) | `status_panel.gd` 两段整段退役(契约 2) | 面板子树零「道具工坊」「天赋树」文案〔sv5〕 同上 | 集成 | 同 sv1 | 撤销:回退旧段退役 hunk(T1 撤销步③)→ 本断言红 | +| sv6 零旧段+投影值真链路(真实入口) | 同 sv5 面板改动+`_status_data()` 换代+`ui_click_probe.gd:593-621` 补三断言 | 角标开层后零旧段+属性行全值对 runner 五现值+`_status_data()` 直调八键与 curios/feats 对拍〔sv6〕 `ui_click_probe.gd`(T2 新增) | 探针 | `board_zone.status_badge` pressed 真实信号路径 | 撤销:回退旧段退役 hunk→断言①红;回退 curios 映射 hunk→断言③红;回退 max_hp 投影 hunk→断言②红(T2 撤销步) | | sv7 投影零旧键 | `_status_data()` 三旧键清零(契约 2 数据层面) | `_status_data()` 返回键集=八键〔sv7〕 `ui_click_probe.gd`(sv6 断言③承载,对局中直调) | 探针 | `main._status_data()` 直调(探针对局中,runner 在役) | 撤销证明:回退三旧键清零 hunk → 键集断言红 | | sv8 提示行文案 | `status_panel.gd:22` 文案换代(契约 4) | 提示行=「查看本局冒险进度(只读)」〔sv8〕 `smoke_all.gd` | 集成 | 同 sv1 | 撤销证明:回退文案 hunk → 本断言红 | | sv9 角标 tooltip×2 | `board_zone_view.gd:58`/`level_map_screen.gd:107` 文案换代 | tooltip=新串且全仓「永久强化进度」零命中〔sv9〕 件核(T1 可核查结果)+四探针定位锚回归 | 件核+探针 | 角标节点实查+全套闸 | 撤销证明:回退任一 tooltip hunk → 件核红 | @@ -183,7 +183,7 @@ **闸口径**:轻闸每任务卡出口自跑;批末重闸=`tools/run_all_gates.sh` 按改动域选档(本批只碰 `game/` → `--code`)全绿才合并+改前改后读数对拍。回归措辞:里程碑步(T 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增测试先行孤立验证再并入全套。 -**变异验证伴生**(新增/改写验收函数逐条注入实验,记录表进实现报告):`_status_panel_projection` 为改写函数——三注入已挂 sv1/sv2/sv5(gp 硬编码/尾缀删除/旧段回插);`ui_click_probe` 新增断言——三注入挂 sv6(旧段回插→断言①;main 侧 curios 映射漏 `used` 键→断言③;main 侧 max_hp 错读 `ledger["hero_hp"]`→断言②)。变异不红则改判据或如实标注拦截边界。V4/V5 为既有断言回归线,零新增零改写,不设注入实验。 +**撤销证明伴生(2026-10-24 用户裁:全项目禁做变异类测试,一切验收只走撤销证明)**:`_status_panel_projection` 为改写函数——三撤销步挂 sv1/sv2/sv5(gp 投影回退/尾缀逻辑回退/旧段退役回退);`ui_click_probe` 新增断言——三撤销步挂 sv6(旧段退役回退→断言①;curios 映射回退→断言③;max_hp 投影回退→断言②)。撤销后仍绿=断言没钉在这个改动上,判缺漏。V4/V5 为既有断言回归线,零新增零改写,不设撤销步。 ### 8.3 测试削弱申报(test-conventions §9.5) @@ -219,4 +219,4 @@ **自审六查(2026-10-23 写卡会话)**:①规格覆盖——§1 四项改动/五项完成定义逐条挂 T 卡(投影=T1、面板=T1、tooltip=T1、断言面=T1/T2、产出物=T2),并各指到对照表行(sv1–sv10),无漏项;②步骤扫描——全部步骤一步一动作一可核查结果,函数体零给出(签名+断言已定);③类型一致性——接口块八键名与 T1/冒烟/探针引用逐字一致(balance/hero_hp/max_hp/atk/ac/gp/curios/feats);④审查焦点+改动覆盖——规格暗示的失败模式补挂:只读契约破(V4 回归线+L3)、停点开面板秘宝投影崩(F5 已核+V5 回归)、文案锚破导致探针失明(V3 定位锚不变判据);文件结构图六个行为改动行全部指到对照表行;⑤篇幅比例——规格≈1 屏、任务卡≈实现面 1:1,零函数体、零代码块;⑥落位与复用——零新增文件/数据件,三个新 Label 成员与两处投影复用的「为什么不能复用既有那一个/落点唯一」已在预检节答清,与文件结构图互指一致。 -**grilling 复核记录(2026-10-23,独立子代理对抗复核,不采访用户——可推导定值写依据、真归用户列 §11)**:十审点走查——事实面(F1–F8 行号、§6 四条文档引句、旧段/旧键/旧成员消费点全集、削弱申报、机检 C1/C2)逐条实核全部成立;对照表三方闭合、落位预检互指、待裁点无泄漏均过。判回炉一处:**【阻断】`main._status_data()` 八键投影值层无验收闭合**——v1.0 的 sv1–sv3 全部直喂夹具消费侧、sv7 只断键集、sv6 断言②单盖 GP 且开局零值无判别力,投影映射写坏可全绿合入,违验收闭合红线。随同改:【应修】§11 推导定值的呈报承诺无落点(T2 反哺点产出物补「逐条列示」)、sv6 断言②无变异证明。v1.1 修订内容:①sv6 升格三断言(零旧段+属性行全值对 runner 五现值+`_status_data()` 直调八键与 curios/feats 对拍独立 oracle)——投影值层进真链路断言回路;②sv7 落点自冒烟移探针(直调 `_status_data()` 需 runner 在役,冒烟免 boot 对局);③变异表补 main 侧注入两条(curios 漏 `used` 键→断言③红、max_hp 错读 hero_hp→断言②红);④§11 增第四处推导定值(带的秘宝含已用件);⑤吹毛求疵随手带改——契约 1 加「属性与 GP 合一行」半句与 ledger 直取下标、契约 2 限定「status_panel.gd 内」并明示 camp_overlay_view 同名件零关联、F2/F3/F4/F5 行号订正(±3 行内漂移)、T1 补 HSeparator 保留句、§8.3 保留区间措辞订正。复核结论:修订后零阻断零应修,零待裁点成立。 +**grilling 复核记录(2026-10-23,独立子代理对抗复核,不采访用户——可推导定值写依据、真归用户列 §11)**:十审点走查——事实面(F1–F8 行号、§6 四条文档引句、旧段/旧键/旧成员消费点全集、削弱申报、机检 C1/C2)逐条实核全部成立;对照表三方闭合、落位预检互指、待裁点无泄漏均过。判回炉一处:**【阻断】`main._status_data()` 八键投影值层无验收闭合**——v1.0 的 sv1–sv3 全部直喂夹具消费侧、sv7 只断键集、sv6 断言②单盖 GP 且开局零值无判别力,投影映射写坏可全绿合入,违验收闭合红线。随同改:【应修】§11 推导定值的呈报承诺无落点(T2 反哺点产出物补「逐条列示」)、sv6 断言②无撤销证明。v1.1 修订内容:①sv6 升格三断言(零旧段+属性行全值对 runner 五现值+`_status_data()` 直调八键与 curios/feats 对拍独立 oracle)——投影值层进真链路断言回路;②sv7 落点自冒烟移探针(直调 `_status_data()` 需 runner 在役,冒烟免 boot 对局);③撤销表补 main 侧两条(curios 映射回退→断言③红、max_hp 投影回退→断言②红);④§11 增第四处推导定值(带的秘宝含已用件);⑤吹毛求疵随手带改——契约 1 加「属性与 GP 合一行」半句与 ledger 直取下标、契约 2 限定「status_panel.gd 内」并明示 camp_overlay_view 同名件零关联、F2/F3/F4/F5 行号订正(±3 行内漂移)、T1 补 HSeparator 保留句、§8.3 保留区间措辞订正。复核结论:修订后零阻断零应修,零待裁点成立。 diff --git a/roadmap.md b/roadmap.md index f9a71058..cbeac4ec 100644 --- a/roadmap.md +++ b/roadmap.md @@ -91,7 +91,7 @@ 2. **T0 开工**:建 worktree + 拷素材与导入缓存(冷检出三件套照坑速查)+ `git status` 归属核对(并行遗留只登记不触碰)——**检出工作区零测试,直接开工**(2026-10-22 频率规则;master 经合回闸保证可用)。 3. **循环骨架**:一轮 = 一个任务卡——读卡 → 对事实源 → 实装(验收测试随对应 T 卡同轮落地;**本卡新增/改动的验收测试自己跑绿即收口,没改的不测**)→ 提交(代拍板随 commit 记录)→ 状态记录追加(查撞号)→ 下一轮。单 worktree 多点提交一次合并;轮内禁开第二个 worktree;轮内不跑闸;断点续跑 = `git log` 对任务卡定轮次。 4. **全量闸时机(2026-10-22 频率规则,无例外)**:全量只有批末+合回两个时机,轮内零跑闸(含 `--quick` 中段自检档)——卡内只测自己改的东西;既有「验收测试随卡落地」「调试期出红只重跑红件最小单元」两条保留(闸机轮次纪律见 process-conventions §6)。 -5. **全量域闸**(批末 Tn):`tools/run_all_gates.sh` **按本批改动域跑**(触及 `game/` → `--code`,这是代码域唯一触发;不触及 `game/` 的一切路径 → `--docs`;一次改动同批混触两域 → 不带参数全量),所选域全绿——闸件清单、顺序与域划分只在该脚本里定义,本文件与 AGENTS.md/规约均不另列;改闸件自身(`tools/` 下机检脚本与闸壳)不占合回全量,质量义务=落批时的变异验证;涉核心的 MC 与基线逐位比对、素材批的机检断言另行。 +5. **全量域闸**(批末 Tn):`tools/run_all_gates.sh` **按本批改动域跑**(触及 `game/` → `--code`,这是代码域唯一触发;不触及 `game/` 的一切路径 → `--docs`;一次改动同批混触两域 → 不带参数全量),所选域全绿——闸件清单、顺序与域划分只在该脚本里定义,本文件与 AGENTS.md/规约均不另列;改闸件自身(`tools/` 下机检脚本与闸壳)不占合回全量,质量义务=落批时人工确认闸可跑通且判据口径未变;涉核心的 MC 与基线逐位比对、素材批的机检断言另行。 6. **人闸**(停机交付):真人目检清单 + 代拍板追认清单 + 异步终审触点(样张类)——本循环内唯一必经人审。 7. **异常分级**:L1 自救(一次重试)→ L2 记录继续(连续 3 次同红灯升级)→ L3 停机写报告等用户。 8. **批次完成后的五步登记**:①待办清单条目状态按 doc-conventions §12.1 推进(做完整条删除)②本文件顶部「当前位」三行换代,涉及里程碑移动时同步里程碑表 ③**实现批禁写本文件与 `design/`**(代码实现批只准写 `reports/`),该改哪一行写进 `reports/iter-反哺点-<日期>.md`,由文档批执行 ④阶段变更改 stage.txt ⑤批末闸序列**按本批改动域**全绿留痕(回执 commit 对齐分支尖)。 diff --git a/tools/pipeline_gate.py b/tools/pipeline_gate.py index 61c0127e..f11d25ec 100644 --- a/tools/pipeline_gate.py +++ b/tools/pipeline_gate.py @@ -53,7 +53,7 @@ BANNED_DOC_MARKS = ("design/", "../gdd/", "../registry/", "../research/", "../qa LEDGER_RULE_DATE = (2026, 10, 21) LEDGER_HEADING_RE = re.compile(r"^#{2,4}\s*.*(验收对照表|改动[—\-]验收)") LEDGER_REQUIRED = ("需求点", "改动", "验收测试", "真实入口") -LEDGER_PROOF_MARKS = ("撤销", "变异", "证明") +LEDGER_PROOF_MARKS = ("撤销", "证明") AUDIT_MARK = "验收审计" DATE_RE = re.compile(r"\d{4}-\d{2}-\d{2}") @@ -471,7 +471,7 @@ def check_ledger(text, path, issues): if any(mark in cell for mark in LEDGER_PROOF_MARKS)), None) if proof_hit is None: issues.append((str(path), header_line, "验收对照表缺列", - "缺「撤销或变异证明」列")) + "缺「撤销证明」列")) return idx["证明"] = proof_hit diff --git a/tools/run_all_gates.sh b/tools/run_all_gates.sh index 51183941..a1d2910e 100644 --- a/tools/run_all_gates.sh +++ b/tools/run_all_gates.sh @@ -16,7 +16,7 @@ # 一切非 game 改动的本域验收。 # --quick 全量档的中段自检形态:跳过渲染闸(窗口化,需开显示器)与静态扫描;完成出库禁用。 # 不带参数 = 全量档(两域全跑),触发条件=同批混触 game/ 与文档面。闸件(tools/ 下机检脚本 -# 与闸壳)自身的改动不占合回全量——其质量义务=落批时的变异验证(test-conventions §6); +# 与闸壳)自身的改动不占合回全量——其质量义务=落批时人工确认闸可跑通且判据口径未变; # 闸真崩溃时合回闸 fail-closed(跑不出回执即拦),不以全量为兜底。 # **域划分只在本脚本里定义一处**——文档只写「按改动域跑本脚本」,禁另列闸清单(清单散落多处 # 正是既往漏跑 probe_gate --full 的成因)。 diff --git a/体验验证清单.md b/体验验证清单.md index a16579e2..435dc00d 100644 --- a/体验验证清单.md +++ b/体验验证清单.md @@ -305,7 +305,7 @@ --- -## ㉙ 代码术语刷新与凭证件裁削批——玩家面目检(迭代 31 卡①/卡②;能力验证半=冒烟 1151 项 0 失败+单元 34 套全绿+对拍 120 局真差异 0 行+`feat_vouchers` 39 项全绿+变异六条五红) +## ㉙ 代码术语刷新与凭证件裁削批——玩家面目检(迭代 31 卡①/卡②;能力验证半=冒烟 1151 项 0 失败+单元 34 套全绿+对拍 120 局真差异 0 行+`feat_vouchers` 39 项全绿) > 卡① 是纯重命名批(行为零变化),卡② 删两件凭证、把完美保险改为专长订阅式。机检能证明词面清零、数值零漂移与验收组全绿,但玩家面「旧词是否真的不见了、贴图是否还在、豁免的实际观感」仍要人眼看。登记不阻塞(2026-10-12 真人检测立规)。