合并分支 caplist-20261029(能力清单改版——验证账本改实现指导地图)入 master:能力清单四列制义务声明定位(写卡当场入表+实现照单落名+收尾核对,废滞后一个迭代)+test-conventions §8.3/§8.9 改写+capability_audit 双通道判据+pipeline_gate 新增行收紧;收口回执 game/tests/.gates/receipt.json(域=docs 全绿,tree=分支尖内容树)

This commit is contained in:
DKChan committed 2026-10-29 04:06:03 +08:00
commit 6abaf67dd5
6 files changed
+182 -149

No files matched your search

+7 -7
View File
@@ -97,7 +97,7 @@
- **反向**:diff 里每个行为改动至少一行;没有对应行的改动,必须写明「非行为改动」或「由第 X 行覆盖」。
- **测试侧**:新增或改写的每条断言至少挂一行;挂不上的孤儿断言删掉或补挂到需求点。
**能力清单维护锚(2026-10-28 用户裁,2026-10-29 定稿)**:逐断言账本 `game/tests/验证集清单.md` 已随阶段 2「存量断言精简」完成退役——冻结对账基准(基点 `b9260138`/1587 条)与精简对账结果(33 站点并为 7、1587→1561,合回 `87d241c1`)留 git 历史。覆盖索引由 `game/tests/README.md`「能力清单」唯一承担:每行一个能力,给真实入口、2–3 个代表用例(`文件:函数`)与最后验证批次(三层模型见 §8.9)。**维护归写卡段**——增删能力行与刷新「最后验证批次」在写需求卡片时完成,实现批禁写该文件。改动—验收对照表纪律不变:新增或改写的每条断言仍须挂一行(上文「测试侧」);断言改判仍受 §8.4 真实入口口径约束。
**能力清单维护锚(2026-10-29 用户裁改版定稿)**:`game/tests/README.md`「能力清单」是**实现指导+阅读导航+义务声明**——只宣布「要验证什么」,不记「是否已验证/是否跑过」;落地账归现行验收闭合链(改动—验收对照表逐条挂断言+合回前独立验收审计),本清单不承载验证状态。表为四列:能力|系统|真实入口|代表用例(`文件:函数`)。**维护归写卡段,当场入表**:写需求卡片时,本批新增能力当场写入能力行——真实入口取自设计文档已定的入口,代表用例=卡里定死的计划测试(`文件:函数`);受影响存量行(入口/用例名变更)同批更新;能力退役删行。**实现照单落名**:测试函数名以清单为唯一依据,名实不符=卡片没写清=停卡退回。**收尾核对**:批末收尾只核对表上名字与实际落地一致(改名则回表),不刷任何批次字段;实现批禁写该文件的现行红线不变(process-conventions §3 第 11 条),核对义务归收尾提交。三层模型见 §8.9。改动—验收对照表纪律不变:新增或改写的每条断言仍须挂一行(上文「测试侧」);断言改判仍受 §8.4 真实入口口径约束。
### 8.4 真实入口断言(验收闭合的主判据)
@@ -130,25 +130,25 @@
本规自 2026-10-21 起对文件名日期不早于该日的需求卡片生效;旧卡不回头改。旧卡在开工前缺对照表的,由写卡段补,补完再开工。
### 8.9 三层模型(验收意图·覆盖索引·执行证据,2026-10-29 定稿)
### 8.9 三层模型(验收意图·义务清单·执行证据,2026-10-29 定稿)
验收体系分三层,各层各管一件事,互不代行:
| 层 | 载体 | 切分轴 | 一行是什么 |
|---|---|---|---|
| 验收意图 | 系统文档「验收标准」节 | 按 owner 文档 | 一条玩家或系统可观测的判据 |
| 覆盖索引 | `game/tests/README.md`「能力清单」 | 按玩家旅程与系统归属 | 一个能力+真实入口+代表用例(`文件:函数`) |
| 义务清单 | `game/tests/README.md`「能力清单」 | 按玩家旅程与系统归属 | 一条待验证义务:能力+真实入口+代表用例(`文件:函数`) |
| 执行证据 | 测试套件断言 | 按代码归属 | 一条从真实入口进入的断言 |
四条法则:
1. **每格非空**:每个系统文档有验收标准节;每个能力行有真实入口与至少一个代表用例;每条断言挂在某个需求点或能力行上。
2. **每条断言有归属**:孤儿断言删掉或补挂;不建无归属断言。
3. **数量不守恒、覆盖守恒**:三层条数天然不等——一条验收意图可由多个能力承接,一个能力由多条断言覆盖。要守的是两个满射:每条验收意图至少有一个能力行承接,每个能力行至少有一条真实入口断言。数量对账只在批内做,见第 4 条。
4. **无全局对账总账**:不建逐断言账本,不做跨层条数对账;对账只在每批的改动—验收对照表里做(§8.3)。历史教训:阶段 2 退役的逐断言账本正因把索引层与证据层压成一本账而失修。
3. **数量不守恒、承接守恒**:三层条数天然不等——一条验收意图可由多个能力承接,一条能力义务由多条断言覆盖。要守的是两个满射:每条验收意图至少有一条能力义务承接,每条能力义务至少有一条真实入口断言落地。数量对账只在批内做,见第 4 条。
4. **无全局对账总账**:不建逐断言账本,不做跨层条数对账;对账只在每批的改动—验收对照表里做(§8.3)。历史教训:阶段 2 退役的逐断言账本正因把义务清单层与证据层压成一本账而失修。
**维护时序**:能力清单归写卡段维护——写需求卡片时增删能力行、刷新本批受影响行的「最后验证批次」;实现批禁写该文件(process-conventions §3 第 11 条)。规则后果是清单滞后一个迭代:本批实现后的代表用例与「最后验证批次」由下次写卡补齐。实现批的验收义务在改动—验收对照表,不在能力清单。
**维护时序(2026-10-29 改版:废「滞后一个迭代」)**:能力清单归写卡段维护——写需求卡片时当场入表:本批新增能力当场增行(真实入口取自设计文档已定的入口,代表用例=卡内定死的计划测试 `文件:函数`),受影响存量行(入口/用例名变更)同批更新,能力退役删行;实现批禁写该文件(process-conventions §3 第 11 条)。实现照单落名:测试函数名以清单为唯一依据,名实不符=卡片没写清=停卡退回。批末收尾只核对表上名字与实际落地一致(改名则回表),不刷任何批次字段——清单不记「是否已验证/是否跑过」,落地账在改动—验收对照表(§8.3)与独立验收审计(§8.7)。
**文档纯度**:验收意图与能力描述只写玩家或系统可观测面,禁写代码路径(`.gd`/`.py`/`.sh`)、测试文件名、断言名;唯一例外=配置文件索引(`game/data/tables/*.tres` 这类表路径与表名)。规则正文见 doc-conventions §5「禁实现内容」。
**机器闸**:本节的结构由文档域闸「能力审计」机检——GDD 纯度(同款禁实现内容口径)、系统文档验收标准节非空、能力行六列与非空、代表用例(`文件:函数`)与真实入口可核、覆盖域表与能力行对得上;红项按新增红处理。闸件清单与域划分的唯一出处=`tools/run_all_gates.sh` 头部。
**机器闸**:本节的结构由文档域闸「能力审计」机检——GDD 纯度(同款禁实现内容口径)、系统文档验收标准节非空、能力行四列与非空、代表用例(`文件:函数`)与真实入口可核(双通道:代码在或卡在——计划中的用例与入口由需求卡片锚定)、覆盖域表与能力行对得上;红项按新增红处理。闸件清单与域划分的唯一出处=`tools/run_all_gates.sh` 头部。
+79 -81
View File
@@ -43,116 +43,114 @@ tests/
> **分层判据**:能不能在 `--script` 模式下不加载 autoload 就验完?能 = 单元测试;
> 需要两个以上真实系统协同并走落盘/落库 = 集成测试;需要完整项目引导与场景树 = 冒烟/系统/UI 探针。
**能力清单 v2**(2026-10-28 立,2026-10-29 扩面至七段——验证与清单体系整改阶段 1 的覆盖索引:一行=一个玩家或系统可观测的能力,代表用例只给指针、不复制断言细节;原「集成旅程清单」五条跨系统旅程已并入本表。七段=核心四域+排雷循环+表现与支撑+数据配置与跨系统契约,行数随清单生长不在此记账;系统文档逐篇对照见下方「覆盖域表」):
**能力清单**(2026-10-28 立,2026-10-29 改版定稿——验证与清单体系整改的能力义务清单:一行=一个玩家或系统可观测的能力,只宣布「要验证什么」,不记「是否已验证/是否跑过」;定位=实现指导+阅读导航+义务声明,代表用例只给指针、不复制断言细节;原「集成旅程清单」五条跨系统旅程已并入本表。七段=核心四域+排雷循环+表现与支撑+数据配置与跨系统契约,行数随清单生长不在此记账;系统文档逐篇对照见下方「覆盖域表」):
> **与验证集清单的关系**:`tests/验证集清单.md` 已于阶段 2「存量断言精简」完成后删除——冻结对账基准(基点 `b9260138`/1587 条)与精简对账结果(33 站点并为 7、1587→1561,合回 `87d241c1`)留 git 历史。本表是该清单退役后的唯一覆盖索引(维护锚=test-conventions §8.3 清单归属+§8.9 三层模型)。本表不是闸,不替代改动—验收对照表、体验验证清单与静态纪律;每行的唯一事实源仍是 `game/tests/` 下的测试代码。
> **与验证集清单的关系**:`tests/验证集清单.md` 已于「存量断言精简」阶段完成后删除(对账基准与结果留 git 历史)。本表是该清单退役后的唯一能力义务清单(维护锚=test-conventions §8.3 清单归属+§8.9 三层模型)。本表不是闸,不替代改动—验收对照表、体验验证清单与静态纪律;已落地行的唯一事实源是 `game/tests/` 下的测试代码,计划中的行由需求卡片锚定(见维护规则)。
>
> **代表用例口径**:写 `文件:函数`,每行 2–3 个;函数内可含 `Kit.check_quiet` 静默通道(逐断言提取器口径外,test-conventions §5.2 已备案)——本表以函数为锚,不受该工具局限影响。
> **代表用例口径**:写 `文件:函数`,每行 1–3 个;函数内可含 `Kit.check_quiet` 静默通道(逐断言提取器口径外,test-conventions §5.2 已备案)——本表以函数为锚,不受该工具局限影响。计划中的用例=卡内定死的测试名,实现落地后转为代码实锚(机检双通道:代码在或卡在,test-conventions §8.9)。
>
> **维护规则(写卡段维护,实现批禁写本表)**:增删能力行与刷新「最后验证批次」在写需求卡片时完成——本批实现后的代表用例与批次由下次写卡补齐,清单按规则滞后一个迭代(test-conventions §8.9);写卡时核对受影响行:代表用例可 grep、真实入口未绕过改动点、批次列记最近一次覆盖该行的全量域闸回执 commit。全表核对频率与抽样规则归阶段 3。
> **维护规则(写卡段维护,实现批禁写本表)**:写需求卡片时当场入表——本批新增能力当场增行(真实入口取自设计文档已定的入口;代表用例=卡内定死的计划测试 `文件:函数`,实现照单落名,名实不符=卡片没写清=停卡退回);受影响存量行(入口/用例名变更)同批更新;能力退役删行。批末收尾只核对表上名字与实际落地一致(改名则回表),不刷任何批次字段(test-conventions §8.3/§8.9)。
>
> **旅程补录方法**:新旅程=加一行,「系统」列写涉及边界;源=architecture「API 边界」表+「数据流」存档/读档路径+各 GDD 登记的 deferral 集成用例。
>
> 「最后验证批次」列记最近一次覆盖该行的全量域闸回执 commit;存量行初值 `20c13c3a`=存量断言精简 A+B 首批的全量域闸回执,RNG 行随 C 档批刷新为 `fd6cf968`;2026-10-29 扩面行同取 `20c13c3a`——其代表用例文件与函数在该 commit 已存在且随该次全量闸执行。
**旅程段一:开机与存档**
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) | 最后验证批次 | 缺口 |
|---|---|---|---|---|---|
| 存档写盘⇄读回往返保真 | 存档序列化 | `SaveManagerCore.write_to_disk()`/`load_from_disk()` | `save_manager_domain_test.gd:_smoke_save` | `20c13c3a` | — |
| 三槽位隔离与激活失败回滚 | 存档序列化 | `SaveManagerCore.activate_slot()`/`create_slot()`/`delete_slot()` | `save_slot_isolation_test.gd:_test_three_slot_roundtrip_and_isolation`;`save_slot_isolation_test.gd:_test_activate_failure_restores_previous_slot` | `20c13c3a` | — |
| 槽位摘要窥视与坏槽三态 | 存档序列化 | `SaveManagerCore.peek_slot_summary()` | `save_slot_summary_test.gd:_test_peek_three_slots_distinct_values`;`save_slot_summary_test.gd:_test_peek_empty_and_unreadable_states`;`save_slot_summary_test.gd:_test_peek_zero_side_effect` | `20c13c3a` | — |
| 启动态无激活不写盘 | 存档序列化 | `SaveManagerCore.has_write_target()`/`write_to_disk()` | `save_boot_no_activate_test.gd:_test_write_rejected_without_target`;`save_boot_no_activate_test.gd:_test_out_of_range_slots_rejected` | `20c13c3a` | — |
| 旧档迁移链与断点续玩零跳号(集成) | 存档序列化×冒险结构 | `SaveManagerCore.load_from_disk()`(内置迁移链)× `AdventureRunner.resume_adventure()` | `save_rng_roundtrip_test.gd:_test_old_version_save_migrates_and_resumes` | `20c13c3a` | — |
| 存档⇄RNG 快照往返保真(集成) | 存档序列化×RNG 服务×冒险结构 | `AdventureRunner.start_adventure()` → `SaveManagerCore.write_to_disk()`/`load_from_disk()` | `save_rng_roundtrip_test.gd:_test_disk_roundtrip_preserves_breakpoint` | `20c13c3a` | — |
| RNG 统一流派生与取号账本 | RNG 服务 | `RngServiceCore.derive_at()`/`open_stream()`/`counter()` | `rng_service_test.gd:_test_derive_determinism`;`rng_service_test.gd:_test_stream_draw_determinism`;`rng_stream_boot_test.gd:_smoke_initialize` | `fd6cf968` | — |
| 断点片段往返与续玩幂等 | 冒险结构×关卡节点地图 | `LevelRunner.breakpoint_fragment()`/`restore_fragment()`;`AdventureRunner.resume_adventure()` | `breakpoint_resume_test.gd:_init` | `20c13c3a` | — |
| 跨系统附随面:事件日志落盘与断点附随件(集成) | RNG 服务×存档序列化×冒险结构 | `RngServiceCore.new_adventure()`(开事件日志会话);`SaveManagerCore.breakpoint_snapshot()`(断点附随键) | `cross_system_flow_test.gd:_rng_event_log_session`;`cross_system_flow_test.gd:_feats_breakpoint_roundtrip` | `20c13c3a` | 日志面仅此一条会话覆盖 |
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) |
|---|---|---|---|
| 存档写盘⇄读回往返保真 | 存档序列化 | `SaveManagerCore.write_to_disk()`/`load_from_disk()` | `save_manager_domain_test.gd:_smoke_save` |
| 三槽位隔离与激活失败回滚 | 存档序列化 | `SaveManagerCore.activate_slot()`/`create_slot()`/`delete_slot()` | `save_slot_isolation_test.gd:_test_three_slot_roundtrip_and_isolation`;`save_slot_isolation_test.gd:_test_activate_failure_restores_previous_slot` |
| 槽位摘要窥视与坏槽三态 | 存档序列化 | `SaveManagerCore.peek_slot_summary()` | `save_slot_summary_test.gd:_test_peek_three_slots_distinct_values`;`save_slot_summary_test.gd:_test_peek_empty_and_unreadable_states`;`save_slot_summary_test.gd:_test_peek_zero_side_effect` |
| 启动态无激活不写盘 | 存档序列化 | `SaveManagerCore.has_write_target()`/`write_to_disk()` | `save_boot_no_activate_test.gd:_test_write_rejected_without_target`;`save_boot_no_activate_test.gd:_test_out_of_range_slots_rejected` |
| 旧档迁移链与断点续玩零跳号(集成) | 存档序列化×冒险结构 | `SaveManagerCore.load_from_disk()`(内置迁移链)× `AdventureRunner.resume_adventure()` | `save_rng_roundtrip_test.gd:_test_old_version_save_migrates_and_resumes` |
| 存档⇄RNG 快照往返保真(集成) | 存档序列化×RNG 服务×冒险结构 | `AdventureRunner.start_adventure()` → `SaveManagerCore.write_to_disk()`/`load_from_disk()` | `save_rng_roundtrip_test.gd:_test_disk_roundtrip_preserves_breakpoint` |
| RNG 统一流派生与取号账本 | RNG 服务 | `RngServiceCore.derive_at()`/`open_stream()`/`counter()` | `rng_service_test.gd:_test_derive_determinism`;`rng_service_test.gd:_test_stream_draw_determinism`;`rng_stream_boot_test.gd:_smoke_initialize` |
| 断点片段往返与续玩幂等 | 冒险结构×关卡节点地图 | `LevelRunner.breakpoint_fragment()`/`restore_fragment()`;`AdventureRunner.resume_adventure()` | `breakpoint_resume_test.gd:_init` |
| 跨系统附随面:事件日志落盘与断点附随件(集成) | RNG 服务×存档序列化×冒险结构 | `RngServiceCore.new_adventure()`(开事件日志会话);`SaveManagerCore.breakpoint_snapshot()`(断点附随键) | `cross_system_flow_test.gd:_rng_event_log_session`;`cross_system_flow_test.gd:_feats_breakpoint_roundtrip` |
**旅程段二:冒险开局与选路**
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) | 最后验证批次 | 缺口 |
|---|---|---|---|---|---|
| 冒险生命周期:开局受理/三关序列/败北线 | 冒险结构 | `AdventureRunner.start_adventure()`/`continue_to_next_level()` | `adventure_feats_test.gd:_smoke_adventure_api`;`adventure_feats_test.gd:_smoke_adventure` | `20c13c3a` | — |
| 专长(奇物)授予与凭证保底 | 奇物 | `AdventureRunner.present_node_curio()`/`feats_held()` × 效果引擎兑付 | `adventure_feats_test.gd:_smoke_feats`;`feat_vouchers_test.gd:_init` | `20c13c3a` | — |
| 节点图生成合法性与同种子复现 | 关卡节点图生成 | `NodeMapGenerator.generate()`/`validate_output()` | `node_map_generator_test.gd:_test_output_ok`;`node_map_generator_test.gd:_test_reproducible`;`node_map_generator_test.gd:_test_exit_structure` | `20c13c3a` | — |
| 节点图生长递增与无解 fail-fast | 关卡节点图生成 | `NodeMapGenerator.generate()`/`is_fatal()` | `node_map_growth_test.gd:_test_growth`;`node_map_growth_test.gd:_test_fatal_subprocess` | `20c13c3a` | — |
| 起关/选路/断点重生成同图(集成) | 关卡节点地图×关卡节点图生成×冒险结构 | `LevelRunner.start_level()`/`start_level_external()`/`pick_next_node()`;`AdventureRunner.resume_adventure()` | `node_map_determinism_test.gd:_smoke_generated_map_determinism` | `20c13c3a` | — |
| 信息迷雾类型可见性 | 关卡节点地图 | `LevelRunner.type_visible_ids()` | `level_map_type_vis_test.gd:_test_layer_distance`;`level_map_type_vis_test.gd:_test_boss_exempt`;`level_map_type_vis_test.gd:_test_resume_rebuild` | `20c13c3a` | — |
| 关卡表消费侧校验与关卡推进 | 关卡节点地图×数据配置 | `LevelTable.validate_graph()`;`LevelRunner.start_level()` | `level_table_validate_test.gd:_test_positive`;`level_table_validate_test.gd:_test_negative`;`level_shop_economy_test.gd:_smoke_level` | `20c13c3a` | — |
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) |
|---|---|---|---|
| 冒险生命周期:开局受理/三关序列/败北线 | 冒险结构 | `AdventureRunner.start_adventure()`/`continue_to_next_level()` | `adventure_feats_test.gd:_smoke_adventure_api`;`adventure_feats_test.gd:_smoke_adventure` |
| 专长(奇物)授予与凭证保底 | 奇物 | `AdventureRunner.present_node_curio()`/`feats_held()` × 效果引擎兑付 | `adventure_feats_test.gd:_smoke_feats`;`feat_vouchers_test.gd:_init` |
| 节点图生成合法性与同种子复现 | 关卡节点图生成 | `NodeMapGenerator.generate()`/`validate_output()` | `node_map_generator_test.gd:_test_output_ok`;`node_map_generator_test.gd:_test_reproducible`;`node_map_generator_test.gd:_test_exit_structure` |
| 节点图生长递增与无解 fail-fast | 关卡节点图生成 | `NodeMapGenerator.generate()`/`is_fatal()` | `node_map_growth_test.gd:_test_growth`;`node_map_growth_test.gd:_test_fatal_subprocess` |
| 起关/选路/断点重生成同图(集成) | 关卡节点地图×关卡节点图生成×冒险结构 | `LevelRunner.start_level()`/`start_level_external()`/`pick_next_node()`;`AdventureRunner.resume_adventure()` | `node_map_determinism_test.gd:_smoke_generated_map_determinism` |
| 信息迷雾类型可见性 | 关卡节点地图 | `LevelRunner.type_visible_ids()` | `level_map_type_vis_test.gd:_test_layer_distance`;`level_map_type_vis_test.gd:_test_boss_exempt`;`level_map_type_vis_test.gd:_test_resume_rebuild` |
| 关卡表消费侧校验与关卡推进 | 关卡节点地图×数据配置 | `LevelTable.validate_graph()`;`LevelRunner.start_level()` | `level_table_validate_test.gd:_test_positive`;`level_table_validate_test.gd:_test_negative`;`level_shop_economy_test.gd:_smoke_level` |
**旅程段三:战斗结算**
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) | 最后验证批次 | 缺口 |
|---|---|---|---|---|---|
| 伤害公式与掷点乘区 | 战斗结算 | `DamageMath.pool_damage()`/`roll_discount_percent()`/`rolled_component()` | `damage_math_test.gd:_test_pool_damage`;`damage_math_test.gd:_test_roll_discount_percent`;`roll_multiplier_test.gd:_smoke_armor_roll` | `20c13c3a` | — |
| 伤害单据编排与回放 | 战斗结算 | `DamageController.submit()`/`open_ticket()`/`flush()` | `damage_controller_test.gd:_run_recipe_sequence`;`damage_controller_test.gd:_test_five_recipes_and_replay` | `20c13c3a` | — |
| 轮内流与结算五段全序 | 战斗结算 | `BattleOrchestrator.begin_battle()` | `round_flow_skill_pool_test.gd:_smoke_full_battle`;`round_flow_skill_pool_test.gd:_smoke_settlement_segments` | `20c13c3a` | — |
| 技能池数据面与回放独立 | 敌人系统 | `BattleOrchestrator.begin_battle()`(技能池抽号/校验) | `round_flow_skill_pool_test.gd:_smoke_skill_pool_data`;`round_flow_skill_pool_test.gd:_smoke_skill_pool_replay_independence` | `20c13c3a` | — |
| Boss 半血解锁技门控 | 敌人系统 | `BattleOrchestrator.begin_battle()`(Boss 行) | `skill_unlock_test.gd:_test_gate_predicate`;`skill_unlock_test.gd:_test_latch_irreversible` | `20c13c3a` | — |
| 封印与极性路由/不可逆 | 地图战斗资源×战斗结算 | 效果引擎 × `BattleOrchestrator.begin_battle()` | `seal_polarity_test.gd:_smoke_seal_ap_exhausted`;`seal_polarity_test.gd:_smoke_seal_irreversible_quadrants`;`seal_polarity_test.gd:_smoke_polarity_routing` | `20c13c3a` | — |
| 变异布置门控 | 地形变异 | `BattleOrchestrator.begin_battle()`(变异布置段) | `variant_placement_test.gd:_smoke_variant_placement`;`variant_placement_test.gd:_smoke_global_variant` | `20c13c3a` | — |
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) |
|---|---|---|---|
| 伤害公式与掷点乘区 | 战斗结算 | `DamageMath.pool_damage()`/`roll_discount_percent()`/`rolled_component()` | `damage_math_test.gd:_test_pool_damage`;`damage_math_test.gd:_test_roll_discount_percent`;`roll_multiplier_test.gd:_smoke_armor_roll` |
| 伤害单据编排与回放 | 战斗结算 | `DamageController.submit()`/`open_ticket()`/`flush()` | `damage_controller_test.gd:_run_recipe_sequence`;`damage_controller_test.gd:_test_five_recipes_and_replay` |
| 轮内流与结算五段全序 | 战斗结算 | `BattleOrchestrator.begin_battle()` | `round_flow_skill_pool_test.gd:_smoke_full_battle`;`round_flow_skill_pool_test.gd:_smoke_settlement_segments` |
| 技能池数据面与回放独立 | 敌人系统 | `BattleOrchestrator.begin_battle()`(技能池抽号/校验) | `round_flow_skill_pool_test.gd:_smoke_skill_pool_data`;`round_flow_skill_pool_test.gd:_smoke_skill_pool_replay_independence` |
| Boss 半血解锁技门控 | 敌人系统 | `BattleOrchestrator.begin_battle()`(Boss 行) | `skill_unlock_test.gd:_test_gate_predicate`;`skill_unlock_test.gd:_test_latch_irreversible` |
| 封印与极性路由/不可逆 | 地图战斗资源×战斗结算 | 效果引擎 × `BattleOrchestrator.begin_battle()` | `seal_polarity_test.gd:_smoke_seal_ap_exhausted`;`seal_polarity_test.gd:_smoke_seal_irreversible_quadrants`;`seal_polarity_test.gd:_smoke_polarity_routing` |
| 变异布置门控 | 地形变异 | `BattleOrchestrator.begin_battle()`(变异布置段) | `variant_placement_test.gd:_smoke_variant_placement`;`variant_placement_test.gd:_smoke_global_variant` |
**旅程段四:奖励、经济与局外成长**
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) | 最后验证批次 | 缺口 |
|---|---|---|---|---|---|
| 清图奖励双份与零路径 | 地图战斗资源 | `BattleOrchestrator.begin_battle()` → 步骤流行(`source_class=clear_reward`) | `seal_polarity_test.gd:_smoke_clear_reward_chain`;`seal_polarity_test.gd:_smoke_clear_reward_zero_paths` | `20c13c3a` | — |
| 奖励三选一候选/刷新付费/呈现 | 奇物×节点奖励屏 | `AdventureRunner.present_node_curio()`(数据面);奖励节点覆盖层场景(呈现面) | `curio_refresh_paid_test.gd:_init`;`reward_overlay_test.gd:_run` | `20c13c3a` | — |
| GP 钱包/escrow/商店收口/共享池 | 地图战斗资源×商店 | `LevelRunner.buy_product()`/`player_request_refresh()`/`close_wallet()`/`set_shop_pool()` | `level_shop_economy_test.gd:_smoke_gp_wallet`;`level_shop_economy_test.gd:_smoke_shop_room`;`level_shop_economy_test.gd:_smoke_shop_pool` | `20c13c3a` | — |
| 元进度入账与锻造两轴 | 元进度×锻造工坊 | `MetaStateStore.apply_adventure_summary()`/`MetaStateStore.spend_keystone()`/`MetaStateStore.set_forge_route_level()` | `meta_progression_forge_test.gd:_meta_pricing_and_buy`;`meta_progression_forge_test.gd:_smoke_forge_axes` | `20c13c3a` | — |
| 天赋树购买与六键合成 | 天赋树 | `MetaProgression.tree_buy()`/`MetaStateStore.tree_state()`/`MetaStateStore.set_tree_level()` | `meta_progression_forge_test.gd:_smoke_tree`;`meta_progression_forge_test.gd:_smoke_tree_rules`;`tree_rules_v11_test.gd:_init` | `20c13c3a` | — |
| 秘宝结构冻结与 12 件效果 | 秘宝 | `TreasureItems.add_item()`/`query_inventory()`/`validate_use()` | `treasure_items_test.gd:_init`;`treasure_effects_test.gd:_init` | `20c13c3a` | — |
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) |
|---|---|---|---|
| 清图奖励双份与零路径 | 地图战斗资源 | `BattleOrchestrator.begin_battle()` → 步骤流行(`source_class=clear_reward`) | `seal_polarity_test.gd:_smoke_clear_reward_chain`;`seal_polarity_test.gd:_smoke_clear_reward_zero_paths` |
| 奖励三选一候选/刷新付费/呈现 | 奇物×节点奖励屏 | `AdventureRunner.present_node_curio()`(数据面);奖励节点覆盖层场景(呈现面) | `curio_refresh_paid_test.gd:_init`;`reward_overlay_test.gd:_run` |
| GP 钱包/escrow/商店收口/共享池 | 地图战斗资源×商店 | `LevelRunner.buy_product()`/`player_request_refresh()`/`close_wallet()`/`set_shop_pool()` | `level_shop_economy_test.gd:_smoke_gp_wallet`;`level_shop_economy_test.gd:_smoke_shop_room`;`level_shop_economy_test.gd:_smoke_shop_pool` |
| 元进度入账与锻造两轴 | 元进度×锻造工坊 | `MetaStateStore.apply_adventure_summary()`/`MetaStateStore.spend_keystone()`/`MetaStateStore.set_forge_route_level()` | `meta_progression_forge_test.gd:_meta_pricing_and_buy`;`meta_progression_forge_test.gd:_smoke_forge_axes` |
| 天赋树购买与六键合成 | 天赋树 | `MetaProgression.tree_buy()`/`MetaStateStore.tree_state()`/`MetaStateStore.set_tree_level()` | `meta_progression_forge_test.gd:_smoke_tree`;`meta_progression_forge_test.gd:_smoke_tree_rules`;`tree_rules_v11_test.gd:_init` |
| 秘宝结构冻结与 12 件效果 | 秘宝 | `TreasureItems.add_item()`/`query_inventory()`/`validate_use()` | `treasure_items_test.gd:_init`;`treasure_effects_test.gd:_init` |
**旅程段五:排雷循环**
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) | 最后验证批次 | 缺口 |
|---|---|---|---|---|---|
| 棋盘按参数行出图、数字恒真 | 棋盘生成 | `BoardGenerator.generate()` | `board_generator_test.gd:_test_generate_shape_and_mines`;`board_generator_test.gd:_test_digits_equal_neighbor_mine_count` | `20c13c3a` | 出生区零雷与 min_safe_count 下限无生成侧显式断言(现由装板不变式兜) |
| 同参数同种子逐位复现、异种子不退化 | 棋盘生成 | `BoardGenerator.generate()` | `board_generator_test.gd:_test_same_seed_bit_identical`;`board_gen_reward_test.gd:_smoke_board_generator` | `20c13c3a` | — |
| 可推理率与清图可达(合法性先于质量分)、重试有界、降级诚实 | 棋盘生成 | `BoardGenerator.measure_inferability()`/`BoardGenerator.is_clearable()` | `board_generator_test.gd:_test_clearable_and_inferability_selfconsistent`;`board_generator_test.gd:_test_target_mine_count_single_source`;`board_gen_reward_test.gd:_smoke_board_generator` | `20c13c3a` | 三分出口仅 accept_worst 压线一条真跑,accept_best 无构造样本;重试不开新流未断言 |
| 装板与开局免费展开(封锁格无资源、计入清图) | 排雷玩法 | `MinesweeperRules.install_board()` | `minesweeper_rules_test.gd:_test_install_invariants`;`seal_polarity_test.gd:_smoke_resource_surface` | `20c13c3a` | 初始展开未按「出生 3×3∪连通开阔地」集合恰等断言;跨轮不重放未断言 |
| 挖/封印合法性与可辨拒绝(拒绝零副作用) | 排雷玩法 | `MinesweeperRules.settle_batch()` | `minesweeper_rules_test.gd:_test_dig_face_rules`;`minesweeper_rules_test.gd:_test_seal_place`;`minesweeper_rules_test.gd:_test_reject_out_of_catalog` | `20c13c3a` | 资源不足与棋盘面非法双源可分未断言;移动合法性与路径预览无双源断言;同批多意图仲裁未断言 |
| 封印不可逆与挖开封印格放行(兑付改判四情况) | 排雷玩法 | `MinesweeperRules.settle_batch()` | `seal_polarity_test.gd:_smoke_seal_irreversible_quadrants`;`minesweeper_rules_test.gd:_test_seal_place` | `20c13c3a` | 换图重置时封印清零只在刷新路径间接覆盖 |
| AP 扣费、末点耗尽即收轮与战斗收束清零 | 行动经济 | `MinesweeperRules.settle_batch()`(→`ActionEconomy.try_spend()`/`ActionEconomy.notify_combat_end()`) | `seal_polarity_test.gd:_smoke_seal_ap_exhausted`;`round_flow_skill_pool_test.gd:_smoke_full_battle`;`round_flow_skill_pool_test.gd:_smoke_active_refresh` | `20c13c3a` | 清图优先于耗尽的仲裁唯一性无专项断言(末点挖开最后一格场景) |
| 停手转存储备与轮内刷新(上限/AP 不重置/刷新图零清图奖励) | 行动经济 | `BattleOrchestrator.player_request_refresh()`/`MinesweeperRules.settle_batch()` | `round_flow_skill_pool_test.gd:_smoke_active_refresh`;`seal_polarity_test.gd:_smoke_refresh_provenance_guard` | `20c13c3a` | 刷新换图时旧封印零兑付未直验;停手转存率非 100 的参数面未在本域验 |
| 下轮行动点修正排队与兑现 | 行动经济 | `ActionEconomy.pending_ap_delta()`(排队经 `ActionEconomy.queue_ap_delta()`,写入方为效果引擎) | `seal_polarity_test.gd:_smoke_negative_dictionary`;`feat_vouchers_test.gd:_init` | `20c13c3a` | — |
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) |
|---|---|---|---|
| 棋盘按参数行出图、数字恒真 | 棋盘生成 | `BoardGenerator.generate()` | `board_generator_test.gd:_test_generate_shape_and_mines`;`board_generator_test.gd:_test_digits_equal_neighbor_mine_count` |
| 同参数同种子逐位复现、异种子不退化 | 棋盘生成 | `BoardGenerator.generate()` | `board_generator_test.gd:_test_same_seed_bit_identical`;`board_gen_reward_test.gd:_smoke_board_generator` |
| 可推理率与清图可达(合法性先于质量分)、重试有界、降级诚实 | 棋盘生成 | `BoardGenerator.measure_inferability()`/`BoardGenerator.is_clearable()` | `board_generator_test.gd:_test_clearable_and_inferability_selfconsistent`;`board_generator_test.gd:_test_target_mine_count_single_source`;`board_gen_reward_test.gd:_smoke_board_generator` |
| 装板与开局免费展开(封锁格无资源、计入清图) | 排雷玩法 | `MinesweeperRules.install_board()` | `minesweeper_rules_test.gd:_test_install_invariants`;`seal_polarity_test.gd:_smoke_resource_surface` |
| 挖/封印合法性与可辨拒绝(拒绝零副作用) | 排雷玩法 | `MinesweeperRules.settle_batch()` | `minesweeper_rules_test.gd:_test_dig_face_rules`;`minesweeper_rules_test.gd:_test_seal_place`;`minesweeper_rules_test.gd:_test_reject_out_of_catalog` |
| 封印不可逆与挖开封印格放行(兑付改判四情况) | 排雷玩法 | `MinesweeperRules.settle_batch()` | `seal_polarity_test.gd:_smoke_seal_irreversible_quadrants`;`minesweeper_rules_test.gd:_test_seal_place` |
| AP 扣费、末点耗尽即收轮与战斗收束清零 | 行动经济 | `MinesweeperRules.settle_batch()`(→`ActionEconomy.try_spend()`/`ActionEconomy.notify_combat_end()`) | `seal_polarity_test.gd:_smoke_seal_ap_exhausted`;`round_flow_skill_pool_test.gd:_smoke_full_battle`;`round_flow_skill_pool_test.gd:_smoke_active_refresh` |
| 停手转存储备与轮内刷新(上限/AP 不重置/刷新图零清图奖励) | 行动经济 | `BattleOrchestrator.player_request_refresh()`/`MinesweeperRules.settle_batch()` | `round_flow_skill_pool_test.gd:_smoke_active_refresh`;`seal_polarity_test.gd:_smoke_refresh_provenance_guard` |
| 下轮行动点修正排队与兑现 | 行动经济 | `ActionEconomy.pending_ap_delta()`(排队经 `ActionEconomy.queue_ap_delta()`,写入方为效果引擎) | `seal_polarity_test.gd:_smoke_negative_dictionary`;`feat_vouchers_test.gd:_init` |
**旅程段六:表现与支撑**
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) | 最后验证批次 | 缺口 |
|---|---|---|---|---|---|
| 拒绝反馈分面可辨与未知兜底文案 | HUD框架 | `HudPresenter.outcome_text()` | `hud_presenter_test.gd:_test_reject_text_by_reason`;`hud_presenter_test.gd:_test_unknown_reason_fallback`;`hud_presenter_test.gd:_test_accepted_text` | `20c13c3a` | 图标通道(文案+图标双通道)无断言,现仅文案面 |
| 结算明细带逐行呈现与排播节奏 | HUD框架 | `BattleLogView.append_row()`/`RowPacer.pace_delay_for()` | `theme_projection_test.gd:_smoke_battle_log_view`;`player_copy_sweep_test.gd:_sweep_source_names`;`pacing_queue_test.gd:_init` | `20c13c3a` | 减动效开关本体(SettingsStore)无单元/集成断言,仅系统测试与冒烟 |
| 模态覆盖层编排与输入锁 | HUD框架 | `ModalFlow.locks_input()`/`ModalFlow.open_after_playback()` | `modal_flow_test.gd:_init`;`reward_overlay_test.gd:_run` | `20c13c3a` | 输入锁的场景级实例面归探针,纯逻辑面之外无断言 |
| 未开格类型微光(8 邻作用集/五组色相/零玩法写入) | HUD框架 | `BoardView.type_glow_probe()`/`UiKit.glow_group_for_cell_type()` | `theme_projection_test.gd:_smoke_type_glow`;`type_glow_test.gd:_test_grouping_closed`;`type_glow_test.gd:_test_frozen_hue_face` | `20c13c3a` | — |
| UI 全局主题与按钮五态(含对比度锚) | HUD框架 | `UiKit.button()`/`UiKit.primary_button()` | `theme_projection_test.gd:_smoke_global_theme`;`theme_projection_test.gd:_smoke_button_five_states`;`theme_projection_test.gd:_smoke_contrast_inks` | `20c13c3a` | 字号下限(18/14/13px)与纯鼠标可玩无自动化断言 |
| 中文字体随包与字形覆盖 | HUD框架 | `UiKit.load_font()` | `ui_font_asset_test.gd:_init`;`theme_projection_test.gd:_smoke_global_theme` | `20c13c3a` | 多语言切换面未建(体系 P1),现仅单一语言字形覆盖 |
| 地形瓦片套与格面数字可读 | HUD框架 | `TilePalette.digit_ink_mode()`/`TilePalette.normalize_floor_luma()` | `terrain_tile_sets_test.gd:_test_set_completeness`;`terrain_tile_sets_test.gd:_test_hue_domains`;`terrain_tile_sets_test.gd:_test_digit_ink_modes` | `20c13c3a` | 瓦片不入 git,素材缺位时整套 SKIP(空跑不红) |
| 站桩敌人呈现与结算演出落点 | 战斗表现 | `BattleStageView.enemy_standee_center()`/`BattleEndOverlay.open_victory()` | `standee_fx_sweep_test.gd:_init`;`pacing_queue_test.gd:_init` | `20c13c3a` | 死亡灰化碎裂与减动效演出档无断言,归探针与人工目检 |
| 战斗叙述与终局文案(数值带入/胜负互异) | HUD框架 | `BattleNarrator.battle_end_text()`/`BattleNarrator.boss_name()` | `battle_narrator_test.gd:_test_numeric_lines_carry_values`;`battle_narrator_test.gd:_test_end_text_differs_by_result`;`battle_narrator_test.gd:_test_boss_name_uses_boss_rowset` | `20c13c3a` | — |
| 玩家面文案与危险格格面字形 | HUD框架 | `BoardView.rebuild()`/`StatusSlotRow.set_effects()` | `player_copy_sweep_test.gd:_sweep_board_glyph`;`player_copy_sweep_test.gd:_sweep_legend`;`player_copy_sweep_test.gd:_sweep_hero_panel` | `20c13c3a` | 首遇提示的触发时机与「每场至多一次」无断言(教学引导验收仍为待设计) |
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) |
|---|---|---|---|
| 拒绝反馈分面可辨与未知兜底文案 | HUD框架 | `HudPresenter.outcome_text()` | `hud_presenter_test.gd:_test_reject_text_by_reason`;`hud_presenter_test.gd:_test_unknown_reason_fallback`;`hud_presenter_test.gd:_test_accepted_text` |
| 结算明细带逐行呈现与排播节奏 | HUD框架 | `BattleLogView.append_row()`/`RowPacer.pace_delay_for()` | `theme_projection_test.gd:_smoke_battle_log_view`;`player_copy_sweep_test.gd:_sweep_source_names`;`pacing_queue_test.gd:_init` |
| 模态覆盖层编排与输入锁 | HUD框架 | `ModalFlow.locks_input()`/`ModalFlow.open_after_playback()` | `modal_flow_test.gd:_init`;`reward_overlay_test.gd:_run` |
| 未开格类型微光(8 邻作用集/五组色相/零玩法写入) | HUD框架 | `BoardView.type_glow_probe()`/`UiKit.glow_group_for_cell_type()` | `theme_projection_test.gd:_smoke_type_glow`;`type_glow_test.gd:_test_grouping_closed`;`type_glow_test.gd:_test_frozen_hue_face` |
| UI 全局主题与按钮五态(含对比度锚) | HUD框架 | `UiKit.button()`/`UiKit.primary_button()` | `theme_projection_test.gd:_smoke_global_theme`;`theme_projection_test.gd:_smoke_button_five_states`;`theme_projection_test.gd:_smoke_contrast_inks` |
| 中文字体随包与字形覆盖 | HUD框架 | `UiKit.load_font()` | `ui_font_asset_test.gd:_init`;`theme_projection_test.gd:_smoke_global_theme` |
| 地形瓦片套与格面数字可读 | HUD框架 | `TilePalette.digit_ink_mode()`/`TilePalette.normalize_floor_luma()` | `terrain_tile_sets_test.gd:_test_set_completeness`;`terrain_tile_sets_test.gd:_test_hue_domains`;`terrain_tile_sets_test.gd:_test_digit_ink_modes` |
| 站桩敌人呈现与结算演出落点 | 战斗表现 | `BattleStageView.enemy_standee_center()`/`BattleEndOverlay.open_victory()` | `standee_fx_sweep_test.gd:_init`;`pacing_queue_test.gd:_init` |
| 战斗叙述与终局文案(数值带入/胜负互异) | HUD框架 | `BattleNarrator.battle_end_text()`/`BattleNarrator.boss_name()` | `battle_narrator_test.gd:_test_numeric_lines_carry_values`;`battle_narrator_test.gd:_test_end_text_differs_by_result`;`battle_narrator_test.gd:_test_boss_name_uses_boss_rowset` |
| 玩家面文案与危险格格面字形 | HUD框架 | `BoardView.rebuild()`/`StatusSlotRow.set_effects()` | `player_copy_sweep_test.gd:_sweep_board_glyph`;`player_copy_sweep_test.gd:_sweep_legend`;`player_copy_sweep_test.gd:_sweep_hero_panel` |
**旅程段七:数据配置与跨系统契约**
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) | 最后验证批次 | 缺口 |
|---|---|---|---|---|---|
| 全表装载、就绪态与表清单目录对账 | 数据配置 | `ConfigDB.load_tables()`/`ConfigDB.diagnostics_count()` | `config_db_test.gd:_test_manifest_dir_sync`;`rng_stream_boot_test.gd:_smoke_initialize` | `20c13c3a` | 表实↔`data/schemas/` 声明逐字段对账与热重载门(`set_reload_gate()`/`reload()`)均无断言载体 |
| 进度坐标查行:精确命中/向上取整/封顶/警告去重 | 数据配置 | `BoardGenTable.resolve_row()`/`ConfigDbResolver.resolve_enemy_rowset()` | `config_db_test.gd:_test_progress_resolution`;`config_db_resolver_test.gd:_test_band_hit`;`config_db_resolver_test.gd:_test_top_band_clamp` | `20c13c3a` | 实体键(enemy_id)精确匹配不符即致命一面无断言 |
| 行集寻址、行序保序与难度乘数 clamp | 数据配置×难度曲线与Boss | `ConfigDbResolver.resolve_enemy_rowset()`/`ConfigDbResolver.resolve_difficulty_modifiers()` | `config_db_resolver_test.gd:_test_rowset_order_preserved`;`config_db_resolver_test.gd:_test_row_kind_routing`;`config_db_resolver_test.gd:_test_difficulty_clamp` | `20c13c3a` | — |
| 运行期越域致命与进程非 0 退出 | 数据配置 | `BoardGenTable.resolve_row()`/`ConfigDbResolver.resolve_enemy_rowset()` | `config_db_fatal_oob_test.gd:_trigger_oob`;`config_db_resolver_test.gd:_test_request_oob` | `20c13c3a` | 独立进程只验关卡序号 <1 一例;深度 <0 与未播种取号的退出码另由 `core/run_time_fatal_test` 承载 |
| 加载期违规表拒绝:跨表悬空/计数器前缀/真视窄域 | 数据配置×秘宝×奇物 | `ConfigDB.load_tables()` | `reward_dangling_treasure_test.gd:_init`;`counter_prefix_fatal_test.gd:_assert_rejected`;`treasure_target_violation_test.gd:_init` | `20c13c3a` | 「权重和为零」「表文件缺失」两类校验无独立夹具 |
| 表结构守卫:域校验/行序键/跨字段互锁/配额锚 | 数据配置×敌人系统×地形变异×冒险结构 | `EnemyTable.validate()`/`VariationTable.variant_pool()`/`AdventureTable.validate()` | `table_structure_guard_test.gd:_smoke_enemy_bands`;`table_structure_guard_test.gd:_smoke_variation_framework`;`table_structure_guard_test.gd:_smoke_adventure_table` | `20c13c3a` | 冒险表只验零违例,无逐类负样本(其余表有) |
| 难度修饰套乘:空表零行为/套乘生效/越域 clamp | 难度曲线与Boss | `UnitContainer.spawn()`/`ConfigDbResolver.resolve_difficulty_modifiers()` | `table_structure_guard_test.gd:_smoke_difficulty_table`;`config_db_resolver_test.gd:_test_difficulty_clamp` | `20c13c3a` | 修饰行由测试运行时直改表行,正式构建的注入路径无断言 |
| 锻造表 schema 正反与几何价格梯 | 锻造工坊 | `ForgeTable.level_price()`/`ForgeTable.route_rows()` | `forge_table_test.gd:_test_production_rows`;`forge_table_test.gd:_test_price_ladder`;`forge_table_test.gd:_test_negative_cases` | `20c13c3a` | 价格梯只有长剑路线逐级验,其余五路线只验基础价 |
| 系统间契约词表与受理口径:五配方互异/掷点标签成员性/增益布尔受理 | 战斗结算×数据配置×增益状态 | `DamageController.open_ticket()`/`StatusContainer.apply_effect()` | `system_contracts_test.gd:_test_damage_controller_vocabularies`;`system_contracts_test.gd:_test_rng_tag_closure`;`system_contracts_test.gd:_test_status_boolean_acceptance` | `20c13c3a` | 常量互异与标签成员性属纯词表面,无消费侧运行断言;结账政策 B(攒批)不在本件 |
| 敌人技能池跨表链接校验 | 数据配置×敌人系统 | `ConfigDbCrossValidator.validate_skill_pool_links()` | `config_db_cross_validator_test.gd:_test_all_links_valid`;`config_db_cross_validator_test.gd:_test_dangling_skill_id`;`config_db_cross_validator_test.gd:_test_cast_side_mismatch` | `20c13c3a` | 池构成纪律(普攻恰一行/增益妨害各 ≤1/无条件特殊技 ≥1)代码在册但无断言 |
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) |
|---|---|---|---|
| 全表装载、就绪态与表清单目录对账 | 数据配置 | `ConfigDB.load_tables()`/`ConfigDB.diagnostics_count()` | `config_db_test.gd:_test_manifest_dir_sync`;`rng_stream_boot_test.gd:_smoke_initialize` |
| 进度坐标查行:精确命中/向上取整/封顶/警告去重 | 数据配置 | `BoardGenTable.resolve_row()`/`ConfigDbResolver.resolve_enemy_rowset()` | `config_db_test.gd:_test_progress_resolution`;`config_db_resolver_test.gd:_test_band_hit`;`config_db_resolver_test.gd:_test_top_band_clamp` |
| 行集寻址、行序保序与难度乘数 clamp | 数据配置×难度曲线与Boss | `ConfigDbResolver.resolve_enemy_rowset()`/`ConfigDbResolver.resolve_difficulty_modifiers()` | `config_db_resolver_test.gd:_test_rowset_order_preserved`;`config_db_resolver_test.gd:_test_row_kind_routing`;`config_db_resolver_test.gd:_test_difficulty_clamp` |
| 运行期越域致命与进程非 0 退出 | 数据配置 | `BoardGenTable.resolve_row()`/`ConfigDbResolver.resolve_enemy_rowset()` | `config_db_fatal_oob_test.gd:_trigger_oob`;`config_db_resolver_test.gd:_test_request_oob` |
| 加载期违规表拒绝:跨表悬空/计数器前缀/真视窄域 | 数据配置×秘宝×奇物 | `ConfigDB.load_tables()` | `reward_dangling_treasure_test.gd:_init`;`counter_prefix_fatal_test.gd:_assert_rejected`;`treasure_target_violation_test.gd:_init` |
| 表结构守卫:域校验/行序键/跨字段互锁/配额锚 | 数据配置×敌人系统×地形变异×冒险结构 | `EnemyTable.validate()`/`VariationTable.variant_pool()`/`AdventureTable.validate()` | `table_structure_guard_test.gd:_smoke_enemy_bands`;`table_structure_guard_test.gd:_smoke_variation_framework`;`table_structure_guard_test.gd:_smoke_adventure_table` |
| 难度修饰套乘:空表零行为/套乘生效/越域 clamp | 难度曲线与Boss | `UnitContainer.spawn()`/`ConfigDbResolver.resolve_difficulty_modifiers()` | `table_structure_guard_test.gd:_smoke_difficulty_table`;`config_db_resolver_test.gd:_test_difficulty_clamp` |
| 锻造表 schema 正反与几何价格梯 | 锻造工坊 | `ForgeTable.level_price()`/`ForgeTable.route_rows()` | `forge_table_test.gd:_test_production_rows`;`forge_table_test.gd:_test_price_ladder`;`forge_table_test.gd:_test_negative_cases` |
| 系统间契约词表与受理口径:五配方互异/掷点标签成员性/增益布尔受理 | 战斗结算×数据配置×增益状态 | `DamageController.open_ticket()`/`StatusContainer.apply_effect()` | `system_contracts_test.gd:_test_damage_controller_vocabularies`;`system_contracts_test.gd:_test_rng_tag_closure`;`system_contracts_test.gd:_test_status_boolean_acceptance` |
| 敌人技能池跨表链接校验 | 数据配置×敌人系统 | `ConfigDbCrossValidator.validate_skill_pool_links()` | `config_db_cross_validator_test.gd:_test_all_links_valid`;`config_db_cross_validator_test.gd:_test_dangling_skill_id`;`config_db_cross_validator_test.gd:_test_cast_side_mismatch` |
**跨域条件闸**
| 能力 | 系统 | 真实入口 | 代表用例 | 最后验证批次 | 缺口 |
|---|---|---|---|---|---|
| 回放确定性(同种子三变体逐位) | 全玩法链 | `tools/parity_anchor.py`(闸 11 条件闸,按批发起) | `tools/parity_anchor.py`(整件为条件闸) | —(条件闸) | 条件闸未随本批执行 |
| 能力 | 系统 | 真实入口 | 代表用例 |
|---|---|---|---|
| 回放确定性(同种子三变体逐位) | 全玩法链 | `tools/parity_anchor.py`(闸 11 条件闸,按批发起) | `tools/parity_anchor.py`(整件为条件闸) |
**覆盖域表**(`design/gdd/systems/` 逐篇对照——状态三档:已覆盖/部分覆盖/未覆盖;部分与未覆盖行的缺口指待办清单条目,覆盖面提升时同批改本表):
@@ -0,0 +1,46 @@
# 工程改动报告——能力清单改版(验证账本改实现指导地图)
2026-10-29 · 文档设计改动批(用户裁决定稿后发令执行)· worktree 分支 `caplist-20261029` 合回
接收方:待办清单.md「能力清单改版——验证账本改实现指导地图」条(本批完成即整条删除,条目内容 git 历史可考)
## 定位换代(用户裁定,本批不改设计)
能力清单从「覆盖索引+验证账本」改为**实现指导+阅读导航+义务声明**:只宣布「要验证什么」,不记「是否已验证/是否跑过」;落地账归现行验收闭合链(卡片改动—验收对照表逐条挂断言+合回前独立验收审计),那套机制本批不动。废「滞后一个迭代」:写需求卡片时本批新增能力行当场入表,计划测试文件名与函数名卡里定死;实现照单落名,名实不符=卡片没写清=停卡退回;收尾只核对表上名字与实际落地一致(改名则回表),不刷任何批次字段。
## 改动面
| 文件 | 改动 |
|---|---|
| `game/tests/README.md` | 八张能力表(七旅程段+跨域条件闸)瘦身四列:能力|系统|真实入口|代表用例(文件:函数)——删「最后验证批次」「缺口」两列,存量行内容保留、不回溯验证;引区块改写(义务清单定位、维护规则、代表用例口径),删「最后验证批次」整段说明;覆盖域表(含其「缺口」列)按用户裁保留现状不动 |
| `design/engineering/test-conventions.md` | §8.3「能力清单维护锚」整段改写(新定位+四列+写卡当场入表+实现照单落名+收尾核对);§8.9 三层模型中层「覆盖索引」改「义务清单」,法则 3「覆盖守恒」改「承接守恒」并同步措辞,维护时序段删滞后与批次刷新表述,机器闸句改四列+双通道口径 |
| `tools/capability_audit.py` | CAP_COLS 收窄四列(「系统」列纳入非空机检);删「最后验证批次=真实 commit」检查(check_hash/commit_ok/HASH_RE 随删,subprocess 导入随之移除);代表用例与真实入口判据改双通道(见下表);条件闸行豁免保留(按「代表用例」含「条件闸」字样);头部判据清单同步 |
| `tools/pipeline_gate.py` | 对照表「能力行」判据收紧:「新增:<能力名>」同样要求该能力行已在 game/tests/README.md 能力表在场(写卡与入表同 commit;改版前仅核「既有:」) |
| `.zcode/skills/req-card/SKILL.md`(主区直改,不入 git) | 验证闸节增「能力行当场入表」义务:本批新增能力写卡时增行(真实入口取自设计文档已定入口;代表用例=卡内定死的计划测试 `文件:函数` 名);受影响存量行同批更新;能力退役删行;实现照单落名、收尾核对 |
| `.zcode/skills/iter/SKILL.md`(主区直改,不入 git) | 批性质注记更新(能力行增删归写卡段当场入表,「最后验证批次」列已废除);第 5 步账面随批增「能力清单核对」:核对表上名字与实际落地一致、退役能力行已删,名实不符=停卡退回,本批禁代改 README |
| `待办清单.md` | 「能力清单改版——验证账本改实现指导地图」条整条删除(完成即删) |
## 判据变更前后对照
| 判据点 | 改版前 | 改版后 |
|---|---|---|
| 能力表列 | 六列(能力|真实入口|代表用例|最后验证批次|缺口;「系统」列不在机检列) | 四列(能力|系统|真实入口|代表用例),四格全非空机检 |
| 最后验证批次 | 须为可解析 commit(git cat-file),条件闸行豁免 | 列删除、检查随之删除——清单不记「是否已验证/是否跑过」 |
| 代表用例可核 | 单通道:文件在 run_all.gd 套件 manifest 内且文件有 `func 函数名(` | 双通道:代码在(同左)或卡在(文件名或函数名见于 reports/需求卡片*.md——写卡当场入表的计划用例锚);两头都无=红 |
| 真实入口可核 | 单通道:产品码有 `func 方法(` | 双通道:产品码有 `func 方法(` 或方法名见于需求卡片(计划入口锚);两头都无=红。※延伸申报见下 |
| 对照表「能力行」 | 仅「既有:<能力名>」须在能力表可查,「新增:」不核 | 「既有:」与「新增:」都须在场——新增不在表=「写卡须同批把能力行写入能力清单」红 |
| 维护时序 | 清单滞后一个迭代:本批实现的代表用例与批次由下次写卡补齐 | 写卡时当场入表(新增行+受影响存量行更新+退役删行);收尾只核对名字与落地一致,不刷批次字段 |
| 条件闸行豁免 | 「代表用例」或「缺口」含「条件闸」即豁免 | 仅「代表用例」含「条件闸」(缺口列已删) |
**※延伸申报(超出任务清单原文的一处判据延伸,显式呈报待用户追认)**:任务原文只要求「代表用例」改双通道;「真实入口」按原文保持单通道(产品码 `func` 在场)。但用户裁定 ③「受影响存量行(入口/用例名变更)同批更新」与「新增系统的能力行」都在**写卡 commit 点**生效——彼时入口代码尚未落地,单通道必被闸拦(写卡提交被自家闸机拦死,与裁定 ③ 直接矛盾)。故按同一已裁口径「两头都无=红」把卡片通道延伸到入口列:产品码有定义或需求卡片载名,其一即绿。若裁回退,只需还原 `check_entry` 单通道判断(约两行)。
## 验证
- 闸件新判据孤立验证(造红探针,未触库内文件):代表用例双通道两头无=红/卡在=绿/代码在=绿(3/3);对照表「既有:」不在表=红、「新增:」不在表=红(2/2)。
- 文档域闸(`tools/run_all_gates.sh --docs`,提交点钩子与收口跑批同判据各一遍):06 gdd_lint/06b 变更记录节/07 doc_link/08 doc_term/08c 流水线闸/08d 引用可核/08e 能力审计/10 熵增闸全绿无新增红;08e 能力审计读数=系统文档 25 篇 · 能力行 59 · 套件 65 · 覆盖域表 25 行 · 红项 0。
- 收口回执 `game/tests/.gates/receipt.json`:domain=docs、all_green=true、tree=分支尖内容树(不入 git,合回闸按树哈希校验)。
## 边界与遗留
- 本批零游戏代码面改动(未跑代码域闸,符合批令);存量 59 行的代表用例全部经代码通道锚定,行内容未动。
- 全库「最后验证批次」引用面已清零(test-conventions/README/iter 技能三处随本批改写);待办清单另一条「验证与清单体系整改」实况中的「最后验证批次」字样为历史叙述留档,不在本批改写面。
- 主区两个未跟踪旧报告(reports/工程改动报告-存量断言精简C档-2026-10-28.md、reports/盘点-验证与清单体系-2026-10-28.md)按批令未触碰。
+34 -46
View File
@@ -1,18 +1,19 @@
#!/usr/bin/env python3
r"""capability_audit.py — 能力清单、覆盖域表与 GDD 纯度机检(文档域闸件)
职责(test-conventions §8.9 三层模型的机检半边;规则正文=test-conventions §8.9+doc-conventions §5):
职责(test-conventions §8.9 三层模型的机检半边;规则正文=test-conventions §8.3+§8.9+doc-conventions §5):
A 文档纯度:design/gdd 全树现行文档禁写实现细节——代码路径(.gd/.py/.sh)、测试文件名、断言名、
反引号包裹的调用形态(`名字(...)`);唯一例外=配置文件索引(.tres 表路径与表名)。围栏代码块内不扫。
B 验收标准:design/gdd/systems/** 每篇须有非空的「## 验收标准」节(豁免件具名在册,附理由)。
C 能力行结构:game/tests/README.md 能力表六列齐、逐行六格非空。
D 代表用例可核:能力行「代表用例」的每条 `文件:函数`——文件存在、在 run_all.gd 套件 manifest 内、
该文件有 `func 函数名(`。
E 真实入口可核:能力行「真实入口」的每个 `类.方法()`,方法名须在产品码(game/ 除 tests//probe//sim/)
有 `func 方法(`。
F 最后验证批次:真实 commit(git cat-file 可解析);条件闸行豁免。
G 覆盖域表:systems 每篇一行;状态∈{已覆盖,部分覆盖,未覆盖};非未覆盖行的「能力行」非空且每项都能
C 能力行结构:game/tests/README.md 能力表四列齐、逐行四格非空。
D 代表用例可核(双通道):能力行「代表用例」的每条 `文件:函数`——代码在(文件在 run_all.gd 套件
manifest 内且该文件有 `func 函数名(`)或卡在(该文件名或函数名能在 reports/需求卡片*.md 中找到,
供写卡时当场入表的计划用例锚定);两头都无=红(清单挂了无凭证义务)。
E 真实入口可核(双通道):能力行「真实入口」的每个 `类.方法()`——产品码(game/ 除 tests//probe//sim/)
有 `func 方法(`,或该方法名能在 reports/需求卡片*.md 中找到(计划入口同 D 口径);两头都无=红。
F 覆盖域表:systems 每篇一行;状态∈{已覆盖,部分覆盖,未覆盖};非未覆盖行的「能力行」非空且每项都能
对上能力表里的行名;部分/未覆盖行的缺口非空且指待办清单。
条件闸行豁免(代表用例含「条件闸」字样)不参与 D/E。
自检四道(防扫描面空转假绿):系统文档数、能力行数、manifest 套件数、覆盖表行数任一为零 ⇒ exit 2。
@@ -23,7 +24,6 @@ exit:0=绿/1=有红项(--strict)/2=扫描面异常
"""
import argparse
import re
import subprocess
import sys
from pathlib import Path
@@ -32,13 +32,14 @@ GDD_DIR = REPO / "design" / "gdd"
SYS_DIR = GDD_DIR / "systems"
README = REPO / "game" / "tests" / "README.md"
RUN_ALL = REPO / "game" / "tests" / "run_all.gd"
CARDS_DIR = REPO / "reports"
PURITY_RE = re.compile(r"\.(gd|py|sh)\b")
ASSERT_RE = re.compile(r"check_quiet\s*\(|\bcheck\s*\(")
CALL_FORM_RE = re.compile(r"`[A-Za-z_][A-Za-z0-9_.]*\s*\([^`]*\)`")
FENCE_RE = re.compile(r"^\s*```")
CAP_COLS = ("能力", "真实入口", "代表用例", "最后验证批次", "缺口")
CAP_COLS = ("能力", "系统", "真实入口", "代表用例")
COV_COLS = ("系统文档", "能力行", "状态", "缺口")
STATUS_VALUES = ("已覆盖", "部分覆盖", "未覆盖")
@@ -50,7 +51,6 @@ ACCEPT_EXEMPT = {
CASE_RE = re.compile(r"([A-Za-z0-9_\-]+\.gd):([A-Za-z_][A-Za-z0-9_]*)")
ENTRY_RE = re.compile(r"([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)\s*\(\)")
HASH_RE = re.compile(r"^`?([0-9a-f]{7,40})`?$")
reds = []
selfcheck = []
@@ -130,12 +130,11 @@ def product_funcs():
return names
def commit_ok(short, cache):
if short not in cache:
r = subprocess.run(["git", "-C", str(REPO), "cat-file", "-e", short + "^{commit}"],
capture_output=True)
cache[short] = r.returncode == 0
return cache[short]
def cards_corpus():
"""reports/需求卡片*.md 全文拼接(双通道的「卡在」锚面);无卡返回空串。"""
if not CARDS_DIR.is_dir():
return ""
return "\n".join(read(p) for p in sorted(CARDS_DIR.glob("需求卡片-*.md")))
def check_purity():
@@ -172,7 +171,7 @@ def capability_rows():
selfcheck.append("game/tests/README.md 缺失")
return [], []
lines = read(README).splitlines()
cap_tables = list(tables(lines, ("真实入口", "代表用例", "最后验证批次")))
cap_tables = list(tables(lines, ("真实入口", "代表用例")))
cov_tables = list(tables(lines, ("系统文档", "能力行", "状态")))
if not cap_tables:
selfcheck.append("README 能力表未找到")
@@ -181,7 +180,7 @@ def capability_rows():
return cap_tables, cov_tables
def check_capability_rows(cap_tables, suites, funcs):
def check_capability_rows(cap_tables, suites, funcs, cards):
total = 0
names = []
suite_by_base = {}
@@ -206,17 +205,16 @@ def check_capability_rows(cap_tables, suites, funcs):
red(README.relative_to(REPO), no, "能力行结构",
"「%s」行格数不足或空列(%s)" % (name[:16], "/".join(empty) or "列数"))
continue
if "条件闸" in short("代表用例") or "条件闸" in short("缺口"):
if "条件闸" in short("代表用例"):
continue
check_cases(no, name, short("代表用例"), suite_by_base, funcs)
check_entry(no, name, short("真实入口"), funcs)
check_hash(no, name, short("最后验证批次"))
check_cases(no, name, short("代表用例"), suite_by_base, funcs, cards)
check_entry(no, name, short("真实入口"), funcs, cards)
if total == 0:
selfcheck.append("能力表零数据行")
return names
def check_cases(no, name, cell, suite_by_base, funcs):
def check_cases(no, name, cell, suite_by_base, funcs, cards):
chunks = [c.strip().strip("`") for c in re.split(r"[;;]", cell) if c.strip()]
if not chunks:
red(README.relative_to(REPO), no, "代表用例", "「%s」无代表用例" % name[:16])
@@ -228,37 +226,27 @@ def check_cases(no, name, cell, suite_by_base, funcs):
"「%s」格格式应为 `文件.gd:函数`:%s" % (name[:16], chunk[:40]))
continue
fname, fn = m.groups()
# 双通道(test-conventions §8.9):代码在(套件 manifest 内且 func 在文件里)
# 或卡在(文件名/函数名见于 reports/需求卡片*.md——写卡时当场入表的计划用例)。
hits = suite_by_base.get(fname, [])
if not hits:
code_ok = bool(hits) and any(
re.search(r"^(?:static\s+)?func\s+%s\s*\(" % re.escape(fn), read(RUN_ALL.parent / rel), re.M)
for rel in hits)
card_ok = bool(cards) and (fname in cards or fn in cards)
if not code_ok and not card_ok:
red(README.relative_to(REPO), no, "代表用例",
"「%s」%s 不在 run_all.gd 套件 manifest" % (name[:16], fname))
continue
if not any(re.search(r"^(?:static\s+)?func\s+%s\s*\(" % re.escape(fn), read(RUN_ALL.parent / rel), re.M)
for rel in hits):
red(README.relative_to(REPO), no, "代表用例",
"「%s」%s 无 `func %s(`" % (name[:16], fname, fn))
"「%s」%s 无凭证——代码面(manifest+func)与需求卡片均未锚定" % (name[:16], chunk[:40]))
def check_entry(no, name, cell, funcs):
def check_entry(no, name, cell, funcs, cards):
tokens = ENTRY_RE.findall(cell)
if not tokens:
red(README.relative_to(REPO), no, "真实入口", "「%s」无可核的 `类.方法()`" % name[:16])
return
for _, method in tokens:
if method not in funcs:
if method not in funcs and not (cards and method in cards):
red(README.relative_to(REPO), no, "真实入口",
"「%s」方法 %s() 在产品码无定义" % (name[:16], method))
def check_hash(no, name, cell):
m = HASH_RE.match(cell.strip())
if not m:
red(README.relative_to(REPO), no, "最后验证批次",
"「%s」须为 commit 短哈希:%s" % (name[:16], cell[:24]))
return
if not commit_ok(m.group(1), {}):
red(README.relative_to(REPO), no, "最后验证批次",
"「%s」哈希 %s 不解析为 commit" % (name[:16], m.group(1)))
"「%s」方法 %s() 无凭证——产品码无定义且需求卡片未载" % (name[:16], method))
def check_coverage(cov_tables, names):
@@ -328,7 +316,7 @@ def main():
funcs = product_funcs()
if not funcs:
selfcheck.append("产品码零 `func`")
names = check_capability_rows(cap_tables, suites, funcs)
names = check_capability_rows(cap_tables, suites, funcs, cards_corpus())
check_coverage(cov_tables, names)
if selfcheck:
+16 -5
View File
@@ -582,10 +582,19 @@ def check_ledger(text, path, when, issues, root):
issues.append((str(path), i + 1, "能力行格式",
"「能力行」格须写 既有:<能力名>/新增:<能力名>:%s"
% seg[:24]))
elif m.group(1) == "既有" and m.group(2).strip("`").strip() not in cap_names:
issues.append((str(path), i + 1, "能力行不可核",
"既有能力「%s」不在 game/tests/README.md 能力表"
% m.group(2).strip("`").strip()[:24]))
continue
# 2026-10-29 能力清单改版:写卡与入表同 commit——「新增:」同样要求该能力行
# 已在 game/tests/README.md 能力表在场(写卡时当场入表,test-conventions §8.3)。
cap_name = m.group(2).strip("`").strip()
if cap_name not in cap_names:
if m.group(1) == "新增":
issues.append((str(path), i + 1, "新增能力未入表",
"新增能力「%s」不在 game/tests/README.md 能力表——"
"写卡须同批把能力行写入能力清单" % cap_name[:24]))
else:
issues.append((str(path), i + 1, "能力行不可核",
"既有能力「%s」不在 game/tests/README.md 能力表"
% cap_name[:24]))
if rows == 0:
issues.append((str(path), header_line, "验收对照表零行",
"表内没有数据行"))
@@ -601,7 +610,9 @@ def check_cards(root, issues):
C2 判据:全文既无「设计事实源」也无「唯一事实源」者红(两种写法都与库内实态对齐)。
C3 判据:有「改动—验收对照表」节;表头含需求点/改动/验收测试/真实入口+证明列
(2026-10-28 起换代为「判据绑定面」列,并禁「撤销证明/变异证明」列);
至少一行;必填格非空;全文含「验收审计」声明。语义覆盖不在此判。
能力行列(2026-10-29 起)既有与新增的名称都须在 game/tests/README.md 能力表在场
(新增=写卡同批入表,test-conventions §8.3);至少一行;必填格非空;全文含「验收审计」声明。
语义覆盖不在此判。
"""
dirn = root / CARD_DIR
if not dirn.is_dir():
-10
View File
@@ -18,16 +18,6 @@
**状态**:待执行
#### 能力清单改版——验证账本改实现指导地图(2026-10-29 登记,来源=会话提及)
**实况**:用户裁推翻「验证与清单体系整改」阶段 1 定稿中的滞后条款(清单滞后一个迭代属设计后果)。新定位=实现指导+阅读导航,不是验证账本:清单只宣布「要验证什么」,是义务声明,不记「是否已验证/是否跑过」(账归现行验收闭合链——卡片对照表逐条挂断言+合回前独立审计抓「写了没落」)。设计要点:①四列制:能力|系统|真实入口|代表用例(测试文件:函数)——删「最后验证批次」与「缺口」两列(没落地的验证需求不进地图,进待办清单);②废滞后:写需求卡片时本批新增能力行当场入表,计划测试文件名与函数名卡里定死;③实现照单落名:测试函数名以清单为唯一依据,名实不符=卡片没写清,停卡退回;④收尾只核对表上名字与实际落地一致、退役能力删行。改写面:test-conventions §8.3 维护锚与 §8.9 三层模型、game/tests/README.md 能力清单四列重构、req-card/iter 技能同步、pipeline_gate 对照表机检口径(「能力行」列与 capability_audit 口径随本条复核)。
**缺口**:无待裁点;试点=下一张真卡试运行一轮再定稿(规则修订须真实任务评估)。
**改动面**:文档
**状态**:待文档设计
#### 验证与清单体系整改——四方向分阶段推进(2026-10-28 登记,来源=会话提及)
**实况**:用户裁「验证及清单不合理」,经调研定四方向全做、分阶段推进:A 粒度整改(清单从断言级升到能力/行为级,逐断言账本退役)→ B 精简裁断(在新粒度上规则驱动删并)→ C 流程风险分级(P0/P1/P2 验收强度、审计抽样)→ D 文档减肥(待办条目限长、历史归 git);测试有效性度量暂不处理。阶段 0 盘点已毕:验证集清单零机器闸依赖(run_all_gates/hooks/五技能均不引用,仅 test-conventions §8.3 维护锚+2 份过程报告引用),退役无闸改动;但测试名尾缀仅覆盖 28/47 个有断言文件(19 个零尾缀,含 seal_polarity 69 条、variant_placement 42 条、roll_multiplier 35 条),故能力清单只能按「能力→代表用例」建,不要求逐断言尾缀。对照表列改动触 pipeline_gate+req-card/iter 两技能;待办正文压缩不触机检(无长度判据)。盘点明细见 reports/盘点-验证与清单体系-2026-10-28.md。**阶段 1 设计已闭合(2026-10-28 用户四裁点)**:能力清单 v1 落 `game/tests/README.md`——按系统归属与玩家旅程排序,首期核心四域(存档与随机、冒险循环、战斗结算、奖励与经济)29 行+跨域条件闸 1 行,共 30 行,每行真实入口+2–3 个代表用例(`文件:函数`),维护规则为每批收口核对本批受影响行并刷新「最后验证批次」;`design/engineering/test-conventions.md` §8.3 维护锚改写为「验证集清单整册冻结、能力清单承接覆盖索引、阶段 2 精简后删除」;`game/tests/验证集清单.md` 头注同步冻结声明,冻结快照(基点 `b9260138`/1587 条)留作阶段 2 对账基准;`tools/extract_checks.py` 保留为审计工具,不再承担常态同步。**阶段 2 已执行闭合(2026-10-28 C 档合回)**:存量断言精简 C 档 6 组手写断言族并为 7 个表驱动站点(33→7),冻结清单对账 1587→1561,验证集清单随阶段 2 完成退役(覆盖索引归能力清单,维护锚 test-conventions §8.3),删并申报与件核见 reports/工程改动报告-存量断言精简C档-2026-10-28.md;阶段 3–4 待各自设计推进:风险分级与审计抽样规则、条目限长是否入 pipeline_gate 均未定。**2026-10-29 阶段 1 落地定稿(用户三裁)**:①能力清单与覆盖域表落 `game/tests/README.md`,独立成表、不与 GDD 验收标准合并;②GDD 纯度判红——系统与概念文档全文禁写实现细节(代码路径/测试文件名/断言名),唯一例外=配置文件索引(`game/data/tables/*.tres` 表路径与表名);③能力清单维护归写卡段——写需求卡片时增删能力行并刷新「最后验证批次」,实现批禁写该文件(清单按规则滞后一个迭代,属设计后果)。三层模型(验收意图/覆盖索引/执行证据)与四法则落 test-conventions §8.9;落地分五批:①三份规约+AGENTS.md 红线+本条实况(本批);②README 覆盖域表+三域能力行补齐;③`tools/capability_audit.py` 文档域新闸(3a 普通工具入库/3b 接闸+基线,worktree);④pipeline_gate 对照表加「能力行」列+req-card/iter 两技能同步;⑤GDD 存量实现细节清理(28 篇约 98 处,逐处去向表过用户目后落笔)。**2026-10-29 阶段 1 五批全部落地**:①032d923c;②5377b2ce;③`tools/capability_audit.py` 入库 ae3c99e3+接闸上电 915222fa(文档域闸 08e 能力审计,纯度红清零后才上电);④f3263444;⑤GDD 清理 00312e12(30 篇去 124 处实现指证,纯度红 124→0)。阶段 1 收口;阶段 3–4 待各自设计推进。