From a05fd7b8aaa25d12a76a337c607e9b70f75bd473 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Tue, 3 Nov 2026 01:21:18 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9C=80=E6=B1=82=E5=8D=A1=E7=89=87(=E6=9E=B6?= =?UTF-8?q?=E6=9E=84=E5=AE=A1=E6=9F=A53.1+3.2=E6=95=B4=E6=94=B9=E6=89=B9)?= =?UTF-8?q?=20v1.1:=2015=E8=8A=82=E5=85=A8+11=E5=BC=A0T=E5=8D=A1=E4=BC=B0?= =?UTF-8?q?=E6=97=B68=E5=B7=A5=E6=97=A5+=E5=AF=B9=E7=85=A7=E8=A1=A8R1-R15+?= =?UTF-8?q?=E8=83=BD=E5=8A=9B=E8=A1=8C10=E5=A2=9E5=E6=94=B91=E5=88=A0+?= =?UTF-8?q?=E5=89=8A=E5=BC=B1=E7=94=B3=E6=8A=A58=E6=9D=A1+=E9=9B=B6?= =?UTF-8?q?=E5=BE=85=E8=A3=81=E7=82=B9=E5=BC=80=E5=B7=A5=E9=97=A8U0;=20v1.?= =?UTF-8?q?0=E2=86=92v1.1=20=E6=8A=98=E5=85=A5grilling=E4=B8=80=E8=BD=AE19?= =?UTF-8?q?=E6=9D=A1(B1battle=5Ffx=5Fhost=E7=AD=BE=E5=90=8D/B2=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E9=80=82=E9=85=8D11=E5=A4=84/B3=E5=89=8A=E5=BC=B1?= =?UTF-8?q?=E7=94=B3=E6=8A=A57=C2=B78=E6=9D=A1/B4=E6=B3=A8=E5=85=A5?= =?UTF-8?q?=E5=BA=8F/B5manifest+4=E8=A1=8C/B6=E5=8F=A3=E5=BE=84A=E5=9B=9B?= =?UTF-8?q?=E5=A4=84/B7level=5Fgen=5Fparams=5Ftest/B8=E5=9F=BA=E7=BA=BF25?= =?UTF-8?q?=E4=BB=B6=E5=8F=A3=E5=BE=84/B9=E6=96=AD=E8=A8=80=E6=A1=88?= =?UTF-8?q?=E6=8C=82R1+S1-S10)=E5=8F=8A=E8=BF=BD=E8=AE=A4meta=5Fforge=5Fte?= =?UTF-8?q?st:737;=20pipeline=5Fgate=20PASS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/tests/README.md | 21 +- ...€求卡片-架构审查3.1+3.2整改批-2026-11-02.md | 456 ++++++++++++++++++ 2 files changed, 471 insertions(+), 6 deletions(-) create mode 100644 reports/需求卡片-架构审查3.1+3.2整改批-2026-11-02.md diff --git a/game/tests/README.md b/game/tests/README.md index 05e5ce4a..028dafe2 100644 --- a/game/tests/README.md +++ b/game/tests/README.md @@ -74,6 +74,7 @@ tests/ | 专长(奇物)授予与凭证保底 | 奇物 | `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` | +| 节点图参数读表与域单点(三参数驱动产物/生成器侧可行性保留) | 关卡节点图生成 | `NodeMapGenerator.generate()`/`LevelGenParams.validate()` | `node_map_generator_test.gd:_test_gen_params_table_driven`〔架构整改 V6〕;`table_structure_guard_test.gd:_test_level_gen_new_fields`〔架构整改 V7〕 | | 起关/选路/断点重生成同图(集成) | 关卡节点地图×关卡节点图生成×冒险结构 | `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` | @@ -89,7 +90,7 @@ tests/ | 技能池数据面与回放独立 | 敌人系统 | `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()`(变异布置段) | `variant_placement_test.gd:_smoke_variant_placement`;`variant_placement_test.gd:_smoke_global_variant`;`variant_placement_test.gd:_test_pack_min_from_table`〔架构整改 V10〕 | **旅程段四:奖励、经济与局外成长** @@ -97,22 +98,26 @@ tests/ |---|---|---|---| | 清图奖励双份与零路径 | 地图战斗资源 | `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.shop.buy_product()`/`shop.player_request_refresh()`/`LevelRunner.close_wallet()`/`shop.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` | +| GP 钱包/escrow/商店收口/共享池 | 地图战斗资源×商店 | `LevelRunner.shop.buy_product()`/`shop.player_request_refresh()`/`LevelRunner.close_wallet()`/`shop.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`;`level_shop_economy_test.gd:_test_spend_discount_from_rule_key`〔架构整改 V2〕 | +| 货架位数读表(进店与重抽同源) | 商店 | `shop_session` 货架构建(LevelRunner 装配链) | `level_shop_economy_test.gd:_test_shelf_size_from_table`〔架构整改 V9〕 | | 元进度入账与锻造两轴 | 元进度×锻造工坊 | `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` | | 锻造定价与购买闭环(全路线价格梯/多级购买扣款/拒购零副作用) | 锻造工坊 | `ForgeTable.level_price()`/`MetaProgression.forge_buy_level()` | `forge_table_test.gd:_test_price_ladder`;`meta_progression_forge_test.gd:_meta_pricing_and_buy`;`meta_progression_forge_test.gd:_test_forge_buy_reject` | | 锻造与相邻通道隔离(祝福件购买锻造零变化/默认轴与钥匙解耦/甲型切换双轴可感) | 锻造工坊×元进度 | `MetaProgression.forge_select()`/`hero_type_axes()`/商店购买口 | `meta_progression_forge_test.gd:_test_blessing_no_forge_leak`;`meta_progression_forge_test.gd:_test_default_axes_pre_key`;`meta_progression_forge_test.gd:_test_armor_switch_dual_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` | +| 规则键参数读表(六键参数字典校验与激活侧透传) | 天赋树 | `MetaTreeTable.validate()`/`EffectEngine.rebuild()`/`MetaProgression.tree_rules()` | `tree_rules_v11_test.gd:_test_rule_key_params`〔架构整改 V1〕 | | 秘宝结构冻结与 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` | +| 棋盘按参数行出图、数字恒真 | 棋盘生成 | `BoardGenerator.generate()` | `board_generator_test.gd:_test_generate_shape_and_mines`;`board_generator_test.gd:_test_digits_equal_neighbor_mine_count`;`board_generator_test.gd:_test_spawn_edge_from_table`〔架构整改 V8〕 | +| 出生区边长表单点(布雷域基/R₀ 下限/剃雷域半径全由 spawn_edge 导出) | 棋盘生成 | `BoardGenerator.generate()`/`BoardGenTable.validate()` | `board_generator_test.gd:_test_spawn_edge_from_table`〔架构整改 V8〕 | | 同参数同种子逐位复现、异种子不退化 | 棋盘生成 | `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.preview_reveal()` | `minesweeper_rules_test.gd:_test_preview_reveal_readonly`〔架构整改 V14〕 | | 封印不可逆与挖开封印格放行(兑付改判四情况) | 排雷玩法 | `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`;`refresh_feats_test.gd:test_no_feats_baseline` | @@ -142,6 +147,10 @@ tests/ | B 区舞台背景三关变体与连续地面层(按 board_type 选图/地面层高度读布局表/四柱光柱退役) | HUD框架 | `BattleStageView.set_board_type()` | `stage_background_test.gd:_test_background_selection`;`stage_background_test.gd:_test_ground_layer_geometry`;`stage_background_test.gd:_test_beams_retired` | | 战斗屏三区几何与棋盘格边长(分辨率两档×四档板型) | HUD框架 | `BoardView.set_cell_area()`(D 区可用面积 → 格边长);读面 `BoardView.cell_size` | `layout_probe.gd:_ready`;`board_gen_reward_test.gd:_smoke_layout_cell_formula` | | 调参测速批量模拟(逐帧步进与统计读数) | 调参测量 | `TuneSimController.run()`(调试浮窗批量模拟入口) | `tune_sim_batch_parity_test.gd:_init`(配对对拍套件,随测速循环批建) | +| sim 驱动循环单点(缺省零变化与策略/日志回调形态) | 调参测量 | `BattleDriver.drive_round()`(两参缺省与五参回调两形态) | `battle_driver_drive_test.gd:_smoke_drive_round_contract`〔架构整改 V13〕 | +| 模拟玩家 0 格连锁算子(经真实闭包,零盲挖语义保持) | 调参测量×排雷玩法 | `AutoPlayer._deduce()`(经 `perfect_action()` 装配链) | `auto_player_deduce_test.gd:_smoke_zero_chain_rule`〔架构整改 V15〕 | +| 刷新提示文案读表拼接(RAP 不足/轮上限两 toast 零字面量) | HUD框架 | `player_copy_sweep` 源扫描(现役 sweep 机制) | `player_copy_sweep_test.gd:_sweep_refresh_toast_no_literals`〔架构整改 V4〕 | +| 试玩日志器 ap_per_round 必填注入守卫(未注入拒绝开会话) | 表现与支撑 | `PlaytestLogger.start_session()` | `playtest_logger_guard_test.gd:_smoke_required_injection`〔架构整改 V5〕 | | 战斗叙述与终局文案(数值带入/胜负互异) | 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` | | 营地场景图十层铺底与门洞留空呈现 | 营地场景视图 | 进入存档→选档→进档→营地场景屏(`CampSceneView.setup_layers()` 驱动);单元测试载入 `camp_scene_layout.tres` | `shot_probe.gd:_ready`(camp 截图段)〔营地图批 V1〕;`camp_scene_layout_test.gd:_test_layout_hotspot_geometry`〔营地图批 V14〕 | @@ -164,8 +173,9 @@ tests/ | 进度坐标查行:精确命中/向上取整/封顶/警告去重 | 数据配置 | `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` | +| 加载期违规表拒绝:跨表悬空/计数器前缀/真视窄域/效果类型出域 | 数据配置×秘宝×奇物 | `ConfigDB.load_tables()` | `reward_dangling_treasure_test.gd:_init`;`counter_prefix_fatal_test.gd:_assert_rejected`;`treasure_target_violation_test.gd:_init`;`effect_kind_retired_test.gd:_assert_rejected`〔架构整改 V3〕 | +| 表结构守卫:域校验/行序键/跨字段互锁/配额锚 | 数据配置×敌人系统×地形变异×冒险结构 | `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`;`table_structure_guard_test.gd:_test_feat_cap_required`〔架构整改 V12〕 | +| 变异表头域校验(地形变异) | 地形变异 | `VariationTable.validate()` | `table_structure_guard_test.gd:_test_variation_header_domains`〔架构整改 V11〕 | | 难度修饰套乘:空表零行为/套乘生效/越域 clamp | 难度曲线与Boss | `UnitContainer.spawn()`/`ConfigDbResolver.resolve_difficulty_modifiers()` | `table_structure_guard_test.gd:_smoke_difficulty_table`;`config_db_resolver_test.gd:_test_difficulty_clamp` | | Boss 出场门控(每区域恰一 Boss 终点/Boss 节点开战必选 Boss 行集) | 难度曲线与Boss | `NodeMapGenerator.generate()`/`BattleOrchestrator.begin_battle()` | `node_map_generator_test.gd:_test_boss_exit_per_region`;`boss_gate_test.gd:_test_boss_node_spawns_boss_rowset` | | 锻造表 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` | @@ -301,7 +311,6 @@ godot --headless --path . res://probe/.tscn | `skill_rhythm_probe.gd` | 在役(分析工具) | 技能池节奏定位(表侧池快照 + 摇号份额) | 人工读 stdout | | `rhythm_batch.gd` | 在役(批量采集) | 技能池节奏批量读数(06 在册项的机器半边) | 人工/工具 | | `dump_battle.gd` | **在役·一次性** | 打印一场完整战斗的步骤流与棋盘摘要(肉眼验收归因质量) | 人工(用完即止) | -| `experiment_density.gd` | **在役·一次性** | 不同 mine_density 下的推理率/残余挖掘量取数(历史调参用) | 人工(用完即止) | > **纪律**:本表是这些件的唯一在册处。新增手动测量脚本必须同批登记(用途 + 触发方式 + 结果由谁判); > 退役走 `design/engineering/doc-conventions.md` 第 10 节退役规则,禁止「没看见=死件」式清理。 diff --git a/reports/需求卡片-架构审查3.1+3.2整改批-2026-11-02.md b/reports/需求卡片-架构审查3.1+3.2整改批-2026-11-02.md new file mode 100644 index 00000000..26c2adf5 --- /dev/null +++ b/reports/需求卡片-架构审查3.1+3.2整改批-2026-11-02.md @@ -0,0 +1,456 @@ +# 需求卡片:架构审查 3.1+3.2 整改批(2026-11-02) + +来源:待办清单「架构审查优化讨论——全库架构审计读数的逐条裁决与整改分批(2026-10-29 登记,来源=审计发现)」条目 3.1+3.2 部分(**唯一事实源**:reports/处置-架构审查3.1+3.2整改-2026-11-02.md 总判据六条+裁决台账+设计方案甲~庚+取证事实 18 处现址表;设计闭合凭据=该处置记录+五份已落文 GDD,worktree 提交 15352170,文档域闸全绿 cb92ab10)。 +状态:已写卡(v1.1,2026-11-03 成文;v1.1=grilling 对抗复核 9 阻断+10 建议全采纳修订)。改动面:游戏代码+工具代码(sim 面随批,用户裁完整性优先)。 + +## 1. 目标与完成定义 + +**这批做什么**:把 2026-10-29 全库架构审计 §3.1(数值单一事实源被 18 处硬编码击穿)与 §3.2(sim 与 core 四组平行实现)的已裁决事项全部落码——七条设计方案: + +| 方案 | 内容 | 一句话 | +|---|---|---| +| 甲 | 死效果通道退役 | EFFECT_KINDS 摘除 overflow/attack_segments 两名+两处分支删除,50/2/3 兜底随之消失 | +| 乙 | 天赋树规则键参数字典 | 六规则键值从开关 1 改参数字典,效果引擎零字面量,economy_spend 折价自 shop 表收回 | +| 丙 | 关卡节点图参数入表+域并单点 | fork_third_way_pct/fill_rest_first_pct/width_max 入 level_gen_params 逐关行;生成器侧域校验删除并回 schema | +| 丁 | 经济三件 | shop 货架位数 shelf_size 入表、variation pack_min 入表+表头三域校验、feat cap 改必填 | +| 戊 | 出生区入表 | board_gen 表头 spawn_edge 入表,SPAWN_AREA_CELLS 常量退役,几何与护栏全由表值导出 | +| 己 | sim 信息面出口 | MinesweeperRules 新增 preview_reveal 只读口;auto_player 补 0 格连锁算子经真实闭包 | +| 庚 | 驱动循环收敛 | battle_driver.drive_round 升级通用签名(策略回调+日志回调),level_autoplay 驱动循环抄本删除;_pick_token 改读 TIER_RANK | + +外加:A类① 双写 4 处(main.gd 提示文案两处、playtest_logger ap_per_round、config_db_resolver clamp 域);A类② 入表与兜底全删;sim 组 A/B/D 落地、组 C 零改动只确认、组 E 零动作。 + +**什么状态算完**:上表七方案与 A类① 的每一条改动都落码、都有改动—验收对照表(第 8 节)配对的验收断言在当轮真实跑批中通过;代码域闸全绿(冒烟+单元+探针+渲染/静态);改前改后读数对拍零非预期漂移(行为零变化项逐位同,己案预期漂移项按第 5 节申报);两份 reports/ 产出物(实现报告+反哺点清单)写齐。 + +## 2. 设计事实源 + +- **处置记录(输入合同,逐条一致)**:`reports/处置-架构审查3.1+3.2整改-2026-11-02.md`——总判据六条(§一)、裁决台账(§二)、设计方案甲~庚(§三)、取证事实 18 处现址表(§四)、GDD 落文凭据(§五)、不在本卡范围(§六)。 +- **五份已落文 GDD(设计事实源)**: + - `design/gdd/systems/跨局循环/天赋树.md` v0.12——「规则键参数表」节=乙案字段权威(六键参数名与取值域); + - `design/gdd/systems/冒险循环/关卡节点图生成.md` v1.4——丙案三参数 owner(调参表三行); + - `design/gdd/systems/冒险循环/冒险结构.md` v1.4——丁① 货架位数 owner(调参表「货架位数」行); + - `design/gdd/systems/排雷循环/地形变异.md` v1.2——丁② pack_min owner(调参表「连通片下限」行); + - `design/gdd/systems/排雷循环/棋盘生成.md` v1.2——戊案出生区边长 owner(调参表「出生区边长」行+布雷公式指针形态)。 +- **审计背景**:`reports/审计-全库架构审查-2026-10-29.md`(行号已漂移,以处置记录取证现址与本卡第 3 节实查为准)。 + +## 3. 现状事实(2026-11-03 worktree 分支 arch-review-decisions 实查,开工自行复核) + +取证表 18 处现址逐条复核结果(与处置记录差异处已标注): + +| # | 现址(实查) | 值 | 处置方案 | +|---|---|---|---| +| 1 | core/battle_orchestrator.gd:655-656 | `if tree_rules.has("economy_hoard"): drop = int(round(float(drop) * 1.5))` | 乙 | +| 2 | core/node_map_generator.gd:380 | `rg.randf() < 0.35`(岔口第三去路) | 丙 | +| 3 | core/node_map_generator.gd:455 | `rg.randf() < 0.5`(恢复/奖励交替起始骰) | 丙 | +| 4 | core/node_map_generator.gd:361 | `clampi(int(round(branch_density*L)), 1, 24)`(上限 24 不可达) | 丙 | +| 5 | core/effect_engine.gd:154 | `"do": {"kind": "shield", "value": 1}`(posture_bulwark) | 乙 | +| 6 | core/effect_engine.gd:160 | `"do": {"kind": "damage_mult", "value": 50}`(sense_sharp) | 乙 | +| 7 | core/effect_engine.gd:159/162/169/172 | `"value": 2`(两键 cap_per_level ×4 行) | 乙 | +| 8 | core/damage_controller.gd:412 | `int(h.get("value", 50))`(overflow 死通道兜底) | 甲 | +| 9 | core/board_installer.gd:125 | `stream.randi_range(2, int(...pack_max))`(成包下界) | 丁② | +| 10 | core/settlement/combat_segment.gd:63 | `mini(int(h.get("cap", 2)), ... / maxi(1, int(h.get("divisor", 3))))`(attack_segments 死通道;处置记录写 :64,实查 :63——漂移 1 行) | 甲 | +| 11 | core/shop_session.gd:155 | `if shelf.size() >= 3:`(货架位) | 丁① | +| 12 | core/curio_deck.gd:98-106 | `var cap := 99` 死变量+`row.get("cap", 1)`/`else 1` 双兜底 | 丁③ | +| 13 | core/config_db_resolver.gd:118-119 | `clampf(..., 0.1, 10.0)`;失实「GDD Edge Case」注释实查在 :110(处置记录写 :25——漂移;difficulty_table.gd schema 内同款失实注释同族) | A类① | +| 14 | presentation/playtest_logger.gd:16 | `var ap_per_round := 8`(三副本另两处=action_economy.tres=8、action_economy_table.gd schema `= 6`) | A类① | +| 15 | core/node_map_generator.gd:12 | `const MAX_WIDTH := 4` | 丙 | +| 16 | core/node_map_generator.gd:76-99 | `check_params` → `_cp_domain`(域校验 :76-99;`_cp_structural` :104-122 可行性判定 schema 无此判定、**保留**) | 丙 | +| 17 | core/board_data.gd:9 | `const SPAWN_AREA_CELLS := 9`(被 board_gen_table.gd:77/:106 反向引用=跨目录回边) | 戊 | +| 18 | presentation/main.gd:633 与 :636 | 「弃图刷新需 8」「每轮 2 次」(处置记录写 ~:783-790,实查 :633/:636——iter46/48 漂移,正确读表先例在同函数 :625/:629/:664) | A类① | + +其他现状事实(写 T 卡依据): + +- **tree_rules 流**(乙案改造路径):meta_progression.gd:388-401 `tree_rule_keys()` 返回键数组 ← main.gd:198 注入参数面 ← adventure_runner.gd:39/:126/:166/:361(`Array[Variant]`+`is Array` 守卫)→ level_runner.gd:94/:542/:664-665/:733 → battle_orchestrator.gd:351-353 传 `battle_fx_host.gd:182-183`(`rebuild_subscriptions(feats: Array, attunement: Array, tree_rules: Array)` 第三参 typed Array——乙案必须同步改 Dictionary,漏改即每次 begin_battle 运行期崩)→ effect_engine.gd:103-107/:137-139 `_push_tree_rule(rk)` 四分支(:145-174,economy 两键零合成行不入 match)硬编码参数;economy 两键零订阅行,消费点=battle_orchestrator.gd:654 与 shop_session.gd:58-61(`db.run.shop.spend_discount`=0.8,shop.tres:96)+:333 `_rules() -> Array`。meta_tree.tres 三 Fork 行 `effects_a/b` 现为开关值 1。测试侧键数组注入:feat_vouchers_test.gd:168 `["sense_guard"]`、meta_progression_forge_test.gd:737 `["economy_spend"]`、refresh_feats_test.gd:65、round_flow_skill_pool_test.gd:997/1016/1055、effect_port_test.gd:36、trigger_cond_test.gd:116、treasure_effects_test.gd:321(全 `[]` 或键数组);effect_words_t1_test.gd:62/76/111/129 四处 `rebuild([], [], [])`;tree_rules_v11_test.gd:40-77 夹具镜像硬编码值;meta_progression_forge_test.gd:312 `tree_rule_keys()`。sim 侧:adventure_monte_carlo.gd:61-65 三档键数组注入(db 在 :67 才加载——注入序需调整)、level_autoplay.gd:162-163 透传。 +- **甲案死通道**:EFFECT_KINDS(effect_engine.gd:28-66)含 `"attack_segments"`(:29)与 `"overflow"`(:29);`_vtr_do_keys`(effect_engine.gd:430-443)对 do.kind 强校验 EFFECT_KINDS——词表摘名即加载致命。全库 .tres 零行使用此两名(grep 实核)。overflow 施加面=damage_controller.gd:400-415 `_kill_overflow`(调用点 :394,:359 注释提及);attack_segments 消费面=combat_segment.gd:62-70(source_class 名 `fx_streak_segments`,:66 开票)。断言面 grep 全量:tests/unit/core/adventure_feats_test.gd:743 用 kill 事件载荷键 `"overflow": 0`(**事件数据键,非效果类型词**);tests/unit/battle_settlement/round_flow_skill_pool_test.gd:442 排除表含 `"fx_streak_segments"`、:423/:448 注释提「连珠矢」。effect_engine.gd:464「任意真族」注释列 overflow。 +- **戊案面**:SPAWN_AREA_CELLS 引用共 5 处——board_generator.gd:19(target_mine_count 静态公式)、board_data.gd:9(定义)、board_gen_table.gd:77/:106/:107(schema 反向引用);测试引用 4 处——tests/unit/core/board_gen_reward_test.gd:204/:212/:217/:218、board_generator_test.gd:71。board_data.gd:71-79 `spawn_cells()` 硬编码 `range(-1, 2)` 3×3 几何;board_generator.gd:148-152 `_shave_ring` 硬编码 `<= 1 + shave_r`(1=(3−1)/2);board_gen.tres 现无表头字段(:5 起直接 rows)。board_gen_table.gd 已有零哨兵先例:无 @export 初始化即 0 出域。board_generator.gd:24-25 注释声明 db 鸭子型(测量桩注入);sim/calibrate_boards.gd:10-19 FakeDB 桩 `_FakeBoardGen` 只暴露 `resolve_row`,:45-54 rd 行字典透传表行字段(shave/r0_cap 两参数已有同款透传先例)。 +- **丁案面**:shop_table.gd:16 `spend_discount: float = 0.8`+validate :134 域校验;零哨兵先例同文件 price_a/price_b(`= 0.0`,"0 = 未投值即致命域")。variation_table.gd 表头三字段 percent_of_cells/per_level_bonus/pack_max 均 @export 带**非零默认**(5/2/4)且 validate() 零表头校验(grep 实核)。feat_table.gd:41 cap 可选(`if row.has("cap") and ... < 1`),feats.tres 37 行仅 7 行写 cap;config_db_cross_validator.gd:91 注释已登记 cap ∈ [1,99]。curio_deck.gd:30-39 `build()` 的 relic 令牌 feat_id 直源自 feats 活行(常态悬空不可达,断点续玩跨版本时可达)。 +- **庚案面**:battle_driver.gd 全文 38 行——`drive_round(settlement, still_running: Callable = Callable())`(:17)单轮循环:guard=GUARD_ACTIONS(400)、策略=AutoPlayer.choose_dig(plan 一次算定、move+dig 合步提交、move 后查相位/轮次变更即弃 dig)、轮末统一 stop;四调用方全两参形态——dump_battle.gd:30、monte_carlo.gd:74、damage_probe.gd:102/:346、skill_rhythm_probe.gd:58(升级后零改动)。level_autoplay.gd:521-568 `_autoplay_battle(runner, settlement, st, logger)` 外层 round_guard=60 轮循环+内层 action_guard=400/rejects<3 单轮循环,策略=`_decide_act`(:618-624 三档分派 perfect/adv 失误注入/novice),提交=`_submit_intent`(:626-631,kind seal→settle_batch 动作名 seal_place,logger.log_action 带轮号),refresh 走 `player_request_refresh()`,计数 st.rounds/refreshes/seal_placed。logger 会话装配序=先 `start_session` 后设 `ap_per_round`(run_level :39-42、run_adventure :117-120——R5 删默认后守卫即拒、两处会话静默不开,须注入序前置)。测试直接调用 `_autoplay_battle(r, b, st, logger)` 13 处(adventure_feats_test×4、level_shop_economy_test×9)——签名不变则零波及。`_pick_token`(:292-318)字面量 rank match(legendary 4/rare 3/excellent 2/common 1,未知档 0);单点常量=data/schemas/treasure_item_table.gd:44 `TIER_RANK`;消费先例=meta_progression.gd:499。damage_probe.gd 复算面(:196-201 一带)维持,头注自陈「诊断工具·非验收件」,run_all.gd 与 run_all_gates.sh 零引用(grep 实核)。 +- **己案面**:minesweeper_rules.gd `_chain_closure`(:372-384)与 `_chain_reveal_order`(:386-399)私有;唯一公开揭示口 settle_batch(:215)带扣费与事件;`_classify`(:243-262)已示范「挖封印格同口径」模拟封印集形态(sim_seals.erase(c))。auto_player.gd 全 static 无持久成员,查询面=is_revealed/has_seal/reveal_record/current_board/compute_move_path;`_deduce`(:114-152)single+subset 不动点,缺 0 格连锁算子(core 侧 board_generator.gd:204-215 `_apply_chain_rule` 有——口径差异=unknown 不含 safe_set oracle,:80-83 注释在账);novice 档 `_deduce_single`(:55-85)单规则画像。 +- **组 D 面**:experiment_density 引用 6 处——sim/board_generator.gd 无(注释在 **core**/board_generator.gd:23)、data/tables/board_gen.tres:414 调参注释、game/README.md:53 工具行、game/tests/README.md:304 在册行(写卡段已删,见第 7 节 T9)、审计报告两处(过程件不动)+文件本体与 .uid。 +- **能力清单**:`game/tests/README.md` 现行 30 行能力表+覆盖域表在役;本批增改行见第 7 节 T10 与第 8 节对照表「能力行」列。 + +## 4. 设计契约(违反即返工红线) + +- 🔴 **逐条一致**:本卡一切内容与处置记录逐条一致;实现段发现卡面与处置记录冲突=上游缺陷,停卡退回写卡段(L3)。 +- 🔴 **零缺省**(总判据 2):本批新入表字段全部必填、无缺省——表行缺字段=加载期报错;代码禁默默顶默认值。schema 侧落法=@export 零哨兵(int 0 / float 0.0)+validate 域校验出域即拒(shop_table price_a/price_b 先例)。 +- 🔴 **死代码不保留**(总判据 3):甲案两名摘除后禁留兼容别名、禁留注释死分支、禁保留指向死通道的载荷键与排除表成员。 +- 🔴 **sim 零规则副本**(总判据 4):庚案收敛后 `level_autoplay.gd` 禁再持第二轮驱动循环;己案后 sim 禁自算连锁闭包——一律经 `preview_reveal`。 +- 🔴 **数值单一事实源**:本批触碰的每处字面量按处置方案入表或读单点;效果引擎落成后全文件零玩法数值字面量(六键参数全读节点行)。 +- 🔴 **行为零变化面逐位同**:甲/乙/丙/丁/戊/庚六案的现行值迁移(150/1/50/2/0.35/0.5/4/9/3/2/1/80/3/8/2/1.5)与己案的 preview 口径,除己案 auto_player 算子补齐(预期漂移、第 5 节申报)外,全部同种子逐位回归——冒烟与既有测试套零非预期转红;MC 旧锚不重跑(第 5 节)。 +- 🔴 **Core 零 UI 依赖不破**:minesweeper_rules.preview_reveal 为纯查询口(零状态写入、零事件发射);所有改动件保持 `--headless --script` 可跑通。 +- 🔴 **fail-fast**:数据校验错误一律致命中止,无软回退;新增校验全落 schema validate()(加载期)。 +- 🔴 **拆分边界纪律**(结构类卡必填,判据权威=code-conventions §1.1): + - 本批收敛类改动两处,逐件职责语句:①`BattleDriver.drive_round` 通用签名——职责语句「单轮挖掘动作循环的唯一实现:按调用方策略取动作、按统一规则提交、按统一口径记日志与拒绝计数」;单一变化原因=驱动循环语义变化;集体身份=战斗驱动循环单点(battle_driver.gd 文件头自陈身份随之更新)。②节点图域校验并单点——职责语句「参数档合法性判定唯一在 LevelGenParams.validate(加载期)+生成器只留可行性判定 _cp_structural(schema 无此判定的生成器职责)」;单一变化原因=参数域变化;集体身份=参数档校验面(schema 域校验+生成器可行性两级各管一段,禁第三份)。 + - 「过阈值」不构成任何一件的拆分或收拢动机;按纪律拆不出内聚单元 → 停卡呈报走豁免/还债通道,禁硬拆凑绿(写进第 9 节 L3)。 + - 禁为机检文本保留无效成员(第 13 节条款全卡适用)。 + +## 5. 范围边界 + +**收件**(=处置记录全部事项): +- A类①:#1/#2 main.gd 提示文案两处读表拼接(取证表 #18);#13 config_db_resolver clamp 读 DifficultyTable.MULT_MIN/MULT_MAX+失实注释订正;#14 playtest_logger 删默认改必填注入+action_economy_table.gd schema 默认删除(取证异常清单三副本项,卡裁=删默认)。 +- A类②+B类入表:乙(六键参数字典+economy_spend 收回)、丙(三参数入表+域并单点+死上限删除)、丁(三件)、戊(spawn_edge)、#4 死上限 24 删除。 +- 甲:死效果通道整段退役(EFFECT_KINDS 两名+两分支+兜底 50/2/3+载荷键与排除表成员等死面清理)。 +- sim:组 A(庚 案)、组 B(己 案)、组 C(零代码改动,T10 只写确认项)、组 D(experiment_density 删除+引用面处理);组 E 零动作(calibrate_boards FakeDB 模式维持——戊案连带仅 rd 透传一行,见 T3)。 +- 乙案连带(处置记录未点名但不可避免的编译级波及,全列 T1):tree_rules 面从键数组换代参数字典波及的 core/presentation/sim/tests 全部触点。 + +**不收件**(去向已指认): +- B类 CHARGE_LAYER_CAP 死框架——**待办清单专条**(2026-11-02 登记「EffectPort biz_fact 键 charge_layers——无属主数据游离出领域实体的处置」,涉及迭代 49 端口契约,独立走卡)。本卡零触碰 action_economy.gd。 +- sim 标定常量(失误三概率/选路评分)——用户裁接受现状零动作。 +- 审计 P1/P2 四项(闸面缺口/S13 豁免存废/零测试点名四件/架构文档漂移三处)——留待后续讨论段(待办清单条目「本条未闭合余项」)。 +- damage_probe 复算面——按需诊断件维持,零改动(T10 确认项)。 +- MC 重跑——零收件。己案 0 格连锁补齐改变模拟玩家行为(通关率预期上调、旧 MC 锚漂移):重跑归用户按 `sim-data/README.md` MC 采集档位表发起(一档只能由用户发起);本批只在实现报告登记「锚漂移预期+旧锚失效范围」。 +- 组 C 确认以外的 damage_probe / defense_scan / rhythm_batch 等测量件改版。 + +## 6. 关联文档同步面 + +实现批禁写 `design/` 整个目录、两份根流程清单与 `game/tests/README.md`;下表每条的落文义务全部进 `reports/iter-反哺点-<日期>.md`(N=编排段定),由用户裁决后归文档批落文: + +| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务(反哺点清单逐条承载) | +|---|---|---| +| design/engineering/architecture/architecture.md | 己案新增 `MinesweeperRules.preview_reveal` 公开只读口(core 公开 API 面);戊案 SPAWN_AREA_CELLS 常量退役(件表/常量登记面如有登记);庚案 battle_driver 通用签名 | 反哺点清单逐条列:件表行增改内容与依据(处置记录己案「architecture.md 件表行随反哺点落文」)——**机械面文档禁直改** | +| design/gdd/systems/跨局循环/天赋树.md v0.12 | 无陈述变化(规则键参数表已是本批字段权威)——若实现段发现参数表与卡面不一致=上游缺陷停卡 | 反哺点清单写「零反哺」确认行 | +| design/gdd/systems/冒险循环/关卡节点图生成.md v1.4 | 无陈述变化(调参表三行已落) | 同上确认行 | +| design/gdd/systems/冒险循环/冒险结构.md v1.4 | 无陈述变化(货架位数行已落 v1.4;「财富之道两参数归天赋树规则键参数表」句已落) | 同上确认行 | +| design/gdd/systems/排雷循环/地形变异.md v1.2 | 无陈述变化(pack_min 行已落) | 同上确认行 | +| design/gdd/systems/排雷循环/棋盘生成.md v1.2 | 无陈述变化(出生区边长行已落 v1.2) | 同上确认行 | +| design/gdd/systems/冒险循环/奇物.md | 丁③ cap 字段清单行(处置记录丁案明示「奇物.md(cap 字段清单行随卡申报反哺)」——feats 行 cap 改必填后,奇物文档对 cap 的现行陈述(若有「可缺省/缺省按 1」类句)需订正 | 反哺点清单列明:奇物.md 中 cap 相关句的现址行号与订正内容 | +| 术语表 | 无新术语(本批沿用处置记录既定用词:参数字典/只读口/驱动循环单点等仓库现行词) | 确认行「零新增术语」 | + +(机检口径:本表同步义务格无一条写「随批」;所有 design/ 与根规则文件目标格的义务都是「反哺点清单落文」。) + +## 7. 任务卡 T0..T10 + +### 卡前·文件结构图 + +行为改动行标【行为】+对照表行号(第 8 节 R 行);非行为改动标【非行为】。测试件全部为随逻辑写/改的测试代码(需求改动合法面)。 + +``` +数据面(表+schema) + game/data/tables/meta_tree.tres 【行为 R1】三 Fork 行 effects_a/b 开关值 1 → 参数字典 + game/data/schemas/meta_tree_table.gd 【行为 R1】RULE_KEY_PARAMS 常量+_validate_rule_key_params + game/data/tables/shop.tres 【行为 R2/R9】表头 +shelf_size=3、-spend_discount=0.8 + game/data/schemas/shop_table.gd 【行为 R2/R9】+shelf_size(零哨兵+[1,6])/-spend_discount 及其域校验 + game/data/tables/level_gen_params.tres 【行为 R7】三行 × +fork_third_way_pct=35/+fill_rest_first_pct=50/+width_max=4 + game/data/schemas/level_gen_params.gd 【行为 R7】ROW_KEYS+三键+三域校验 + game/data/tables/board_gen.tres 【行为 R8】表头 +spawn_edge=3;:414 调参注释改「出处=退役件 experiment_density.gd(git 历史可考)」【非行为】 + game/data/schemas/board_gen_table.gd 【行为 R8】+spawn_edge(零哨兵+[3,5]奇数)+三处引用改表值导出 + game/data/tables/variation.tres 【行为 R10】表头 +pack_min=2 + game/data/schemas/variation_table.gd 【行为 R10】+pack_min([1,pack_max])+表头三字段域校验 + game/data/tables/feats.tres 【行为 R11】30 行补 cap: 1(7 行已写保持) + game/data/schemas/feat_table.gd 【行为 R11】cap 必填+域 [1,99] + game/data/schemas/action_economy_table.gd 【行为 R5】ap_per_round 删默认(零哨兵化) + game/data/schemas/difficulty_table.gd 【非行为】失实「GDD Edge Case」注释订正(同 #13 族) + +core 层 + game/core/effect_engine.gd 【行为 R1/R3】rebuild/_push_tree_rules/_push_tree_rule 参数化(四分支读参数——economy 两键零合成行不入 match);EFFECT_KINDS 摘两名;:464 族注释改【非行为】 + game/core/battle_orchestrator.gd 【行为 R1】tree_rules 收参 Dictionary;:654-656 economy_hoard 读 mult_pct + game/core/battle_fx_host.gd 【行为 R1 连带】:182 rebuild_subscriptions 第三参 typed Array → Dictionary + game/core/shop_session.gd 【行为 R1/R9】_rules() 返 Dictionary;_spend_discounted 读规则键参数;:155 货架位读表 + game/core/adventure_runner.gd 【行为 R1】_tree_rules 换 Dictionary+两处守卫改 is Dictionary + game/core/level_runner.gd 【行为 R1】同上(:94/:664-665/:542/:733) + game/core/meta_progression.gd 【行为 R1】tree_rule_keys() → tree_rules() -> Dictionary + game/core/node_map_generator.gd 【行为 R7】MAX_WIDTH 删、:361 死上限删、:380/:382/:455 三处读表、_cp_domain 删并回 schema + game/core/board_data.gd 【行为 R8】SPAWN_AREA_CELLS 删;spawn_cells() 几何改 spawn_edge 成员导出;compute_r0 同源 + game/core/board_generator.gd 【行为 R8】target_mine_count/_board_params/_attempt 读 spawn_edge;_shave_ring 半径=(edge−1)/2+r;:23 注释改举例名 calibrate_boards【非行为】 + game/core/board_installer.gd 【行为 R10】:125 成包下界读 pack_min + game/core/curio_deck.gd 【行为 R11】:98-106 死变量删+relic 行悬空 push_error+return false(兜底 1 删) + game/core/damage_controller.gd 【行为 R3】_kill_overflow 改名 _kill_effects+overflow 分支删(reveal_tiles 分支保留)+:359 注释同步 + game/core/settlement/combat_segment.gd 【行为 R3】attack_segments 分支删(:59-70) + game/core/config_db_resolver.gd 【行为 R6】:118-119 clamp 读 DifficultyTable.MULT_MIN/MULT_MAX;:110 失实注释订正【非行为】 + game/core/minesweeper_rules.gd 【行为 R14】+preview_reveal(c) -> Array[Vector2i] + +presentation 层 + game/presentation/main.gd 【行为 R1/R4】:198 tree_rules() 调用(:185 注释同步);:633/:636 两处文案读表拼接 + game/presentation/playtest_logger.gd 【行为 R5】:16 删默认=0;start_session 必填注入守卫 + +sim 层 + game/sim/battle_driver.gd 【行为 R12】drive_round 通用签名(策略回调+日志回调+max_rejects;缺省零变化) + game/sim/level_autoplay.gd 【行为 R12/R13】_autoplay_battle 内层委托 drive_round;_pick_token 改读 TIER_RANK;:39-42/:117-120 注入序前置〔R5 连带〕;:162-163 透传守卫 Dictionary〔R1 类型适配·非行为,T10 确认读数〕 + game/sim/adventure_monte_carlo.gd 【行为 R1 连带·对照表落点=R1】三档注入改参数字典(db 加载序前置)+_tree_rule_dict 断言挂 tree_rules_v11_test〔V1〕 + game/sim/auto_player.gd 【行为 R15】_deduce 补 0 格连锁算子经 preview_reveal;口径注释保持【非行为】 + game/sim/calibrate_boards.gd 【行为 R8 连带】rd 透传一行 spawn_edge(读真表头,零字面量) + game/sim/experiment_density.gd 【删除·组D】连同 .uid + +测试件(随逻辑写/改) + tests/unit/core/tree_rules_v11_test.gd 【行为 R1】夹具参数化++_test_rule_key_params 检查段 + tests/unit/core/meta_progression_forge_test.gd 【行为 R1】:312 tree_rules() 适配+:737 键数组注入改字典+:739-740 期望算式改 discount_pct 推导(申报 8) + tests/unit/core/feat_vouchers_test.gd 【行为 R1】:168 键数组 → 参数字典 + tests/unit/battle_settlement/refresh_feats_test.gd 【非行为】tree_rules: [] → {} + tests/unit/core/treasure_effects_test.gd 【非行为】:321 tree_rules: [] → {} + tests/unit/battle_settlement/round_flow_skill_pool_test.gd 【非行为 R3】[]→{} ×3+:442 排除表 fx_streak_segments 成员删+:423/:448 注释订正 + tests/unit/battle_settlement/effect_port_test.gd 【非行为】[] → {} + tests/unit/battle_settlement/trigger_cond_test.gd 【非行为】[] → {} + tests/unit/core/effect_words_t1_test.gd 【非行为】rebuild 第三参 [] → {} ×4(:62/:76/:111/:129) + tests/unit/core/adventure_feats_test.gd 【行为 R3】:743 载荷键 overflow 删(断言内容不动) + tests/unit/core/node_map_generator_test.gd 【行为 R7】+_test_gen_params_table_driven 检查段 + tests/unit/core/node_map_growth_test.gd 【非行为】手搭夹具补三新键(结构拦截断言不动) + tests/unit/core/board_generator_test.gd 【行为 R8】+_test_spawn_edge_from_table 段+:71 公式对账改 spawn_edge² + tests/unit/core/board_gen_reward_test.gd 【非行为】夹具表补 spawn_edge=3;:204-218 断言改 spawn_edge² 推导(断言强度不减) + tests/unit/core/level_shop_economy_test.gd 【行为 R2/R9】+_test_shelf_size_from_table+_test_spend_discount_from_rule_key 段+:264 迁移断言删(申报 7) + tests/unit/battle_settlement/variant_placement_test.gd 【行为 R10】+_test_pack_min_from_table 段 + tests/unit/data_config/level_gen_params_test.gd 【行为 R7】_row() 构造器补三新键+负样本夹具同步 + tests/unit/core/table_structure_guard_test.gd 【行为 R7/R10/R11】+_test_level_gen_new_fields+_test_variation_header_domains+_test_feat_cap_required + tests/unit/core/minesweeper_rules_test.gd 【行为 R14】+_test_preview_reveal_readonly 段 + tests/unit/presentation/player_copy_sweep_test.gd 【行为 R4】+_sweep_refresh_toast_no_literals 段 + tests/unit/data_config/effect_kind_retired_test.gd 【行为 R3·新增·负面】甲案词表退役加载致命 + tests/unit/core/playtest_logger_guard_test.gd 【行为 R5·新增】未注入拒绝开会话 + tests/unit/core/battle_driver_drive_test.gd 【行为 R12·新增】drive_round 契约 + tests/unit/core/auto_player_deduce_test.gd 【行为 R15·新增】0 格连锁算子 + tests/run_all.gd 【非行为】manifest +4 行(一负面三常规:effect_kind_retired/playtest_logger_guard/battle_driver_drive/auto_player_deduce) + +文档件 + game/README.md:53 【非行为·组D】工具行删 experiment_density + game/tests/README.md 写卡段已同批增改(能力行新增 10 行+既有行更新 5 处+experiment_density 在册行删 1 行)——实现批禁写,批末只核对表上名字与实际落地一致 +``` + +边界说明:一起改的按职责放一起——表+schema 同卡、消费面同卡、验收随对应卡同轮落地。库内大文件(main.gd/battle_orchestrator.gd)不擅自拆。 + +--- + +**T0 基线读数与机检对账**(估时 0.25–0.5 工作日) +取用:无。产出:基线读数入实现报告(后续卡对拍用);本批全部断言面清点确认。 + +- [ ] S13 对账基线:对结构图全部 core/data/presentation 存量触件(25 件,gdstyle 扫描面内;实触存量生产件共 30 件,其余 5 件在 sim/tests 非扫描面)现场跑 gdstyle 记读数(branches/returns/函数长/成员数)为对账基线——`tools/gdstyle_baseline.txt` 既有登记仅 5 键 3 文件,多数件无登记值可读,现场读数即基线(既有登记 2 件照登对账)——第 14 节「只降不升」以此为准 +- [ ] grep 清点四件:`overflow`/`attack_segments`/`fx_streak_segments`/`experiment_density` 全库命中行号清单落实现报告(甲案与 T9 的改前底账) +- [ ] 跑一次冒烟基线:`python tools/run_smoke.py` 全绿读数落实现报告(后续每卡改后对拍基准;不构成验收,验收归第 8 节对照表) +- [ ] 复核取证表 18 处现址与本卡第 3 节逐条一致(漂移即停卡呈报 L3——上游缺陷退写卡段) + +**T1 乙案·规则键参数字典**(估时 1–1.5 工作日) +取用:无(本卡起点)。产出:tree_rules 参数字典形态全库贯通(后续 T7 的 level_autoplay relic 透传消费此形态)。 + +- [ ] meta_tree.tres 三 Fork 行 effects_a/effects_b 值改参数字典——精确行内容(六键全列,对照天赋树.md v0.12 规则键参数表): + - fork_posture:`"effects_a": {"posture_first_strike": {"ap_bonus": 1}}`、`"effects_b": {"posture_bulwark": {"shield": 1}}` + - fork_sense:`"effects_a": {"sense_sharp": {"halve_pct": 50, "cap_per_level": 2}}`、`"effects_b": {"sense_guard": {"ap_refund": 1, "cap_per_level": 2}}` + - fork_economy:`"effects_a": {"economy_hoard": {"mult_pct": 150}}`、`"effects_b": {"economy_spend": {"discount_pct": 80}}` + - (语义注记:mult_pct=150 与现码 1.5 同值、halve_pct=50 与现码 50 同值、discount_pct=80 与 shop 表 0.8 同值——全部行为零变化) +- [ ] meta_tree_table.gd 新增常量与校验——精确签名: + - `const RULE_KEY_PARAMS := {"posture_first_strike": {"ap_bonus": [1, 4]}, "posture_bulwark": {"shield": [1, 9]}, "sense_sharp": {"halve_pct": [1, 99], "cap_per_level": [1, 9]}, "sense_guard": {"ap_refund": [1, 4], "cap_per_level": [1, 9]}, "economy_hoard": {"mult_pct": [101, 300]}, "economy_spend": {"discount_pct": [1, 99]}}`(键集与取值域逐字=天赋树.md v0.12 规则键参数表) + - 新私有校验段 `_validate_rule_key_params(row, nid) -> Array[Variant]`:effects/effects_a/effects_b 中凡 RULE_KEYS 成员的值,必须是 Dictionary、键集恰等 RULE_KEY_PARAMS[键] 的键集(缺参数/多参数即拒)、每值 int 且在闭域内——违例 message 带「缺参数/多参数/越域」判别词 +- [ ] effect_engine.gd:`rebuild(feat_ids, item_ids, tree_rules: Dictionary = {})`;`_push_tree_rules(tree_rules: Dictionary)` 逐键调 `_push_tree_rule(rk, params: Dictionary)`;四分支参数化——posture_first_strike `value: int(params["ap_bonus"])`、posture_bulwark `value: int(params["shield"])`、sense_sharp 两行 when `value: int(params["cap_per_level"])`+do `value: int(params["halve_pct"])`、sense_guard 两行 when `value: int(params["cap_per_level"])`+do `value: int(params["ap_refund"])`(economy 两键零合成行不入 match,维持)——效果引擎零字面量 +- [ ] battle_fx_host.gd:182 `rebuild_subscriptions(feats: Array, attunement: Array, tree_rules: Dictionary) -> void` 第三参类型改(漏改即每次 begin_battle 运行期崩——B1) +- [ ] battle_orchestrator.gd:351-353 收 `Dictionary`;:654-656 改 `var hoard: Dictionary = (_facts.encounter.get("tree_rules", {}) as Dictionary).get("economy_hoard", {})` 命中即 `drop = int(round(float(drop) * float(hoard["mult_pct"]) / 100.0))`(直索引缺键即崩=fail-fast,schema 已保证在键);注释「乘数 provisional 150%」改「乘数读规则键参数 mult_pct」 +- [ ] shop_session.gd:`_rules() -> Dictionary`;`_spend_discounted` 改 `maxi(1, int(floor(float(price) * float(_rules()["economy_spend"]["discount_pct"]) / 100.0)))`(has 判定保留);:50/:56 注释同步 +- [ ] shop_table.gd 删 `spend_discount` 字段+validate :134 域校验;shop.tres 删 :96 行 +- [ ] adventure_runner.gd:39/:126/:166(守卫 `is Dictionary`)/:361+:39 注释同步(树 rule 键集→键集参数字典);level_runner.gd:94/:664-665(类型换 Dictionary)/:542/:733+:69/:664 注释同步(tree_rules:Array → Dictionary);main.gd:198 改 `meta_ref.tree_rules()`(:185 注释同步) +- [ ] meta_progression.gd:388-401:`tree_rule_keys()` 改名 `tree_rules() -> Dictionary`(键=规则键,值=激活侧 effects_* 参数字典原样透传,首遇优先去重语义保持) +- [ ] sim 连带:adventure_monte_carlo.gd——db 加载段(:67-70)前移至 feat_profile 构造之前,新增 `static func _tree_rule_dict(db, keys: Array) -> Dictionary`(扫 meta_tree Fork 行 effects_a/b,命中 keys 集的键取其参数字典),三档注入改 `{"mode": "off", "tree_rules": _tree_rule_dict(db, [...])}`;level_autoplay.gd:162-163 透传守卫改 `is Dictionary`(类型适配·非行为——透传语义经 T10 MC 冒烟确认读数核) +- [ ] 测试适配一(键注入面与消费面四件):meta_progression_forge_test.gd:312 改 `tree_rules()`+:737 `["economy_spend"]` 改 `{"economy_spend": {"discount_pct": 80}}`+:739-740 期望算式 `float(_db.run.shop.spend_discount)` 改 `float(params 字典 discount_pct) / 100.0` 推导(申报 8——断言强度不减,折后价逐位同值);feat_vouchers_test.gd:168 改 `{"sense_guard": {"ap_refund": 1, "cap_per_level": 2}}`;tree_rules_v11_test.gd 夹具从参数字典构造期望合成行+rebuild 第三参传字典 +- [ ] 测试适配二(空形态与 rebuild 第三参面 11 处):refresh_feats_test.gd:65/round_flow_skill_pool_test.gd:997/1016/1055/effect_port_test.gd:36/trigger_cond_test.gd:116/treasure_effects_test.gd:321/effect_words_t1_test.gd:62/76/111/129 的 `tree_rules` 空数组或 rebuild 第三参改空字典 `{}` +- [ ] tree_rules_v11_test.gd 新增 `_test_rule_key_params` 检查段:六键参数域正例全过/缺参数拒/多参数拒/越域拒/非字典拒;并增检 `_tree_rule_dict(db, ["posture_first_strike"])` 返回 `{"posture_first_strike": {"ap_bonus": 1}}`(R1 对照表落点——sim 注入构造面最小断言,B9) +- [ ] 孤立验证新增段 → 出红只跑红件最小单元 → 并入全套(回归措辞:里程碑卡出口跑一次全套闸;卡内修复只做出红最小单元的最窄确认) + +**T2 丙案·节点图参数入表+域并单点**(估时 0.5–0.75 工作日) +取用:无。产出:level_gen_params 三新字段+生成器域校验并单点。 + +- [ ] level_gen_params.gd:ROW_KEYS 追加 `"fork_third_way_pct", "fill_rest_first_pct", "width_max"`;_validate_row_shape 追加三域——fork_third_way_pct float [0,100]、fill_rest_first_pct float [0,100]、width_max int [2,6](域=关卡节点图生成.md v1.4 调参表) +- [ ] level_gen_params.tres 三行各补 `"fork_third_way_pct": 35, "fill_rest_first_pct": 50, "width_max": 4`(percent 形态按 v1.4 调参表域 [0,100]——35/50 与现码 0.35/0.5 同概率语义,消费除 100.0) +- [ ] node_map_generator.gd:删 `const MAX_WIDTH := 4`(:12);:361 `clampi(..., 1, 24)` 改 `maxi(int(round(float(_params["branch_density"]) * float(L))), 1)`(死上限 24 删、下限 1 保留防零岔口与现行为漂移);:380 `< 0.35` 改 `< float(_params["fork_third_way_pct"]) / 100.0`;:382 `>= MAX_WIDTH` 改 `>= int(_params["width_max"])`;:455 `< 0.5` 改 `< float(_params["fill_rest_first_pct"]) / 100.0` +- [ ] node_map_generator.gd:`check_params` 删 `_cp_domain` 调用(改直接 `return _cp_structural(params)`)+删 `_cp_domain` 整函数(:76-99)——域校验唯一落 LevelGenParams.validate(加载期),生成器保留可行性判定 `_cp_structural`(schema 无此判定) +- [ ] node_map_generator_test.gd 追加 `_test_gen_params_table_driven` 检查段:真实表行(row_by_level_index)产图回归同种子逐位;三参数改值夹具(width_max 2→岔口锚点限宽可观测、fork_third_way_pct 0→无三去路图、fill_rest_first_pct 100→填充首节点恒恢复)产出可观测变化断言 +- [ ] table_structure_guard_test.gd 追加 `_test_level_gen_new_fields` 检查段:缺新键行拒(structural 键集闭集)、width_max 越域拒、两 pct 越域拒、表值 35/50/4 全过 +- [ ] tests/unit/data_config/level_gen_params_test.gd:`_row()` 构造器(:24-27)补三新键(`fork_third_way_pct: 35, fill_rest_first_pct: 50, width_max: 4`)——否则 ROW_KEYS 闭集校验拒全部夹具行、:89 起「合法三行」断言整组转红;负样本夹具(bad_keys_row 多塞键等)同步核——多塞键负样本仍须拒、合法行须全过 +- [ ] node_map_growth_test.gd 手搭夹具(:70/:74/:96 一带)补三新键——结构拦截断言与 fatal 子进程不动(回归) + +**T3 戊案·出生区入表**(估时 0.5–1 工作日) +取用:T0 基线读数。产出:spawn_edge 表头单点,SPAWN_AREA_CELLS 退役,跨目录回边(board_gen_table→board_data)解除。 + +- [ ] board_gen_table.gd:`@export var spawn_edge: int = 0`(零哨兵——表头缺字段越域即加载致命);validate 新增域校验 `spawn_edge < 3 or spawn_edge > 5 or spawn_edge % 2 == 0` → domain 错;`_validate_row_constraints` :77 与 `_validate_shave_params` :106-107 的 `BoardData.SPAWN_AREA_CELLS` 全改 `spawn_edge * spawn_edge`(含 :76/:105 注释) +- [ ] board_gen.tres 表头(rows 前)加 `spawn_edge = 3`;:414 调参注释「smoke/experiment_density.gd」改「出处=退役件 experiment_density.gd(git 历史可考)」(不写提交哈希——哈希查 git log,注释只留可读指针) +- [ ] board_data.gd:删 `const SPAWN_AREA_CELLS := 9`(:7-9 注释随行删);新增成员 `var spawn_edge: int = 0`;`spawn_cells()`(:71-79)改 `var half := spawn_edge / 2`+`for dy in range(-half, half + 1)`(spawn_edge=3 时与现 3×3 逐位同——含 in_bounds 过滤);compute_r0()(:98-115)经 spawn_cells 自动同源;:7-8 文件头注释同步 +- [ ] board_generator.gd:`target_mine_count`(:18-20)改 `int(round(float(params.density) * float(int(params.w) * int(params.h) - int(params.spawn_edge) * int(params.spawn_edge))))`;`_board_params`(:36-51)加 `"spawn_edge": int(row.spawn_edge)`(直索引——缺键即崩=fail-fast,schema 与 resolve 注入保证在场);`_attempt`(:103 一带)加 `b.spawn_edge = int(params.spawn_edge)`;`_shave_ring`(:148-152)`<= 1 + shave_r` 改 `<= (int(b.spawn_edge) - 1) / 2 + shave_r`(spawn_edge=3 时逐位同——出生区半径同一事实不二处定义);:22-23 注释「experiment_density.gd 等」改「calibrate_boards.gd」 +- [ ] calibrate_boards.gd(组 E 零动作例外:一行编译级连带)——rd 字典(:45-54 透传段)加 `"spawn_edge": int(db.combat.board_gen.spawn_edge),`(读真表头、零字面量,FakeDB 模式与桩结构不动) +- [ ] 测试:board_generator_test.gd 追加 `_test_spawn_edge_from_table` 检查段(夹具表 spawn_edge=5 → 布雷域基、R₀ 下限、剃雷域半径按 25 格可观测变化;=3 回归逐位同);:71 `from_expr` 对账改 spawn_edge² 推导(夹具 params 补 spawn_edge 键);board_gen_reward_test.gd 夹具表补 `spawn_edge = 3` 成员赋值、:204/:212/:217/:218 的 `BoardData.SPAWN_AREA_CELLS` 改夹具表 `spawn_edge * spawn_edge` 推导(断言强度不减:cap 压线语义保持 9 格) + +**T4 丁案·经济三件**(估时 0.5–1 工作日) +取用:无。产出:shelf_size/pack_min/feat cap 三事实源入表。 + +- [ ] shop_table.gd:`@export var shelf_size: int = 0`(零哨兵)+validate 域校验 `shelf_size < 1 or shelf_size > 6` → domain 错;shop.tres 表头加 `shelf_size = 3` +- [ ] shop_session.gd:155 `if shelf.size() >= 3:` 改 `>= int(db.run.shop.shelf_size)` +- [ ] variation_table.gd:`@export var pack_min: int = 0`(零哨兵)+validate 新增 `_validate_header_domains` 段——pack_min ∈ [1, pack_max]、percent_of_cells ∈ [0, 50](地形变异.md v1.2 调参表)、per_level_bonus ∈ [0, 9]、pack_max ∈ [pack_min, 9](owner 域表述对齐;现表头三字段零校验补齐);variation.tres 表头加 `pack_min = 2` +- [ ] board_installer.gd:125 `stream.randi_range(2, ...)` 改 `stream.randi_range(int(db.combat.variation.pack_min), ...)`(pack_min=2 时逐位同) +- [ ] feat_table.gd :41 cap 校验改必填:`if not row.has("cap")` → domain 错「缺 cap(必填——零兜底)」;`elif int(row.get("cap", 0)) < 1 or > 99` → domain 错(域 [1,99]=config_db_cross_validator.gd:91 在册口径) +- [ ] feats.tres 30 行补 `cap: 1`——批量手法:python 脚本逐行在 `rarity` 行后插 `cap: 1`(仅对无 cap 行;7 行已写保持原值),脚本用后即删(吸收即死);校验=feat_table.validate 全过+`grep -c 'cap' feats.tres` = 37 +- [ ] curio_deck.gd:98-106:删 `var cap := 99` 死变量;relic 分支改 `var row := db.crossrun.feats.row_by_id(feat_id)`+`if row.is_empty(): push_error("[奇物牌库] relic 令牌引用悬空 feat_id=%s(feats 表无此行——配置违约,禁兜底)" % feat_id); return false`,在场行 `return taken.get("relic:" + feat_id, 0) < int(row["cap"])`(直索引——schema 必填保证在键) +- [ ] table_structure_guard_test.gd 追加 `_test_variation_header_domains`+`_test_feat_cap_required` 检查段(域正反例+feats.tres 全行 cap 在场断言);variant_placement_test.gd 追加 `_test_pack_min_from_table` 检查段(夹具 pack_min=3 → 布置产物零 1–2 格连通片可观测断言,真实入口 begin_battle 布置段);level_shop_economy_test.gd 追加 `_test_shelf_size_from_table` 检查段(夹具 shelf_size=5 → 货架五件可观测,真实入口 shop 货架构建)+:264 `spend_discount == 0.8` 迁移断言行删除(申报 7——字段随 T1 退役,表值迁移断言使命终结,等价判据由 `_test_spend_discount_from_rule_key`〔V2〕承接) + +**T5 甲案·死效果通道退役**(估时 0.75–1 工作日) +取用:T0 grep 底账。产出:EFFECT_KINDS 闭面收窄,两名误写加载致命(负面套件)。 + +- [ ] effect_engine.gd EFFECT_KINDS(:29)摘 `"attack_segments"` 与 `"overflow"` 两名;:464「任意真族」注释删 overflow 成员 +- [ ] damage_controller.gd:`_kill_overflow`(:400-415)改名 `_kill_effects(t: Dictionary, target: Dictionary, landed: int) -> void`——`overflow` 分支(:404-415:`if String(h.get("kind", "")) != "overflow": continue` 起至 open_ticket/入队/递归段)删除,reveal_tiles 分支(斩首学者)保留;调用点 :394 改名;:359 注释「击杀发射面拆 _kill_overflow」同步;kill 事件载荷键 `"overflow": landed` 删除(死通道整体退役——全库零订阅行消费此键,grep 实核) +- [ ] combat_segment.gd::59-70 attack_segments 消费段整删(注释 :59-61+for 循环 :62-70)——cap 2/divisor 3/value 0 兜底随之消失;fx_attack_hits 载荷键自此零写零读 +- [ ] 测试清理:adventure_feats_test.gd:743 dispatch 载荷删 `"overflow": 0` 键(断言内容「斩首学者击杀揭示 1 格」不动);round_flow_skill_pool_test.gd :442 排除表删 `"fx_streak_segments"` 成员、:423/:448 注释删「连珠矢」句(段内序断言不动) +- [ ] 新增负面套件 tests/unit/data_config/effect_kind_retired_test.gd(extends SceneTree,沿 counter_prefix_fatal_test.gd 既有形态:user:// 夹具目录复制 feats.tres → 注入 do.kind="overflow" 探针行与 do.kind="attack_segments" 探针行各一 → `ConfigDB.load_tables` → 两探针均被 validate_trigger_row 拒绝(EFFECT_KINDS 出域)→ 违规被放行即 `quit(2)`;全拒 `quit(1)` 语义与既有负面件一致——运行命令注释在文件头) +- [ ] run_all.gd manifest 追加:`{"path": "res://tests/unit/data_config/effect_kind_retired_test.gd", "expect": 1, "negative": true}, # 甲案词表退役——overflow/attack_segments 误写加载致命〔架构整改〕` + +**T6 A类①·双写四处置**(估时 0.5–0.75 工作日) +取用:无。产出:提示文案与 clamp 域读单点,logger 必填注入。 + +- [ ] main.gd:633 `"...(弃图刷新需 8)" % (cost - rap)` 改 `"...(弃图刷新需 %d)" % [cost - rap, cost]`(cost=:629 表读值);:636 `"本轮刷新次数已用完(每轮 2 次)"` 改 `"本轮刷新次数已用完(每轮 %d 次)" % int(db.run.action_economy.refresh_cap_per_round)`(同函数 :625 正确读表先例同款) +- [ ] config_db_resolver.gd:118-119 两处 `0.1, 10.0` 改 `DifficultyTable.MULT_MIN, DifficultyTable.MULT_MAX`(单点=data/schemas/difficulty_table.gd:9-:10);:110 注释「(GDD Edge Case——组合事故非配置事故)」失实句删(GDD 无此节);difficulty_table.gd 同款失实注释(mult_oor_warning 校验处)同步订正 +- [ ] level_autoplay.gd:39-42 与 :117-120 注入序前置——`logger.ap_per_round = int(db.run.action_economy.ap_per_round)` 移到 `logger.start_session(seed_val)` 之前(R5 删默认后守卫拒后开=两处会话静默不开) +- [ ] playtest_logger.gd:16 `var ap_per_round := 8` 改 `var ap_per_round: int = 0`(零缺省);`start_session`(:24)开头加守卫 `if ap_per_round < 1 or ap_per_round > 32: push_error("[试玩日志器] ap_per_round 未注入或越域: %d——组合根必填注入" % ap_per_round); return ""`(:9 返回契约注释同步;_append 空文件守卫已兜住未开会话的 log_* 调用——实核 :172-176) +- [ ] action_economy_table.gd:9 `@export var ap_per_round: int = 6` 删默认(`@export var ap_per_round: int`——零哨兵,表行缺字段越域 [1,32] 加载致命;action_economy.tres 已显式写 8,加载零影响) +- [ ] 新增 tests/unit/core/playtest_logger_guard_test.gd:未注入调 start_session → 返回空串+零文件产出断言;注入 8 → 返回非空路径断言(真实入口=PlaytestLogger.start_session) +- [ ] run_all.gd manifest 追加:`{"path": "res://tests/unit/core/playtest_logger_guard_test.gd", "expect": 0}, # R5 必填注入守卫〔架构整改〕` +- [ ] config_db_resolver_test.gd `_test_difficulty_clamp` 回归(clamp 值 0.1/10.0 不变,来源换常量) + +**T7 庚案·驱动循环收敛+档位排序读表**(估时 0.75–1 工作日) +取用:无。产出:drive_round 驱动循环单点(缺省零变化),level_autoplay 抄本删除。 + +- [ ] battle_driver.gd `drive_round` 升级通用签名——精确签名与契约: + ``` + static func drive_round(settlement, still_running: Callable = Callable(), + act_provider: Callable = Callable(), on_action: Callable = Callable(), + max_rejects: int = 0) -> void + ``` + - act_provider 契约:`func(settlement) -> Dictionary`——返回 `{"kind": "stop"}` 或空字典=停手出环;单步 `{"kind": "move"|"dig"|"seal"|"refresh", "cell": Vector2i}`(refresh 无 cell);合步 `{"kind": "move", "cell": X, "next": {"kind": "dig", "cell": Y}}`(缺省策略适配 AutoPlayer.choose_dig 原生 plan 专用——move 提交后查相位/轮次、变更即断弃 next,与现 :30-33 逐位同) + - 提交分派:move/dig/seal→`minesweeper.settle_batch([{...}])`(seal 提交动作名 seal_place);refresh→`settlement.player_request_refresh()` + - on_action 契约:`func(submit_kind: String, cell: Vector2i, ok: bool, round_index: int)`——submit_kind ∈ {move, dig, seal_place, refresh, stop};轮末统一 stop 也经此回调(accept 取 outcomes[0].accepted);空 Callable=不记日志 + - 循环条件:现 :22-23 四项(活性谓词/Active 相位/同轮/guard>0)+`(max_rejects <= 0 or rejects < max_rejects)`;guard 语义保持「策略回调调用次数 ≤ GUARD_ACTIONS」;ok 时 rejects=0 否则 +1 + - 缺省形态(act_provider 空)=现 :24-34 内联块逐位:`AutoPlayer.choose_dig` plan 一次算定、hero_cell 异位先 move、合步 next=dig、plan 空 break——四调用方(dump_battle:30/monte_carlo:74/damage_probe:102/:346/skill_rhythm_probe:58)两参调用零改动 +- [ ] level_autoplay.gd `_autoplay_battle`(:521-568):外层 round_guard=60 轮循环与 st.rounds 计数保留(属调用方);内层单轮循环整体删,改调 `BattleDriver.drive_round(settlement, func() -> bool: return runner.current_battle() == settlement and settlement.battle_result == "" and settlement.action_economy.phase == "Active" and settlement.round_index == start_round, _act_provider(st), _action_logger(st, logger), 3)`——新增两个静态适配器:`_act_provider(st) -> Callable`(闭包捕获 st:`func(s) -> Dictionary: return _decide_act(st, s)`——策略分派 perfect/novice/slip 全保留在 _decide_act/_apply_normal_slips 原地);`_action_logger(st, logger) -> Callable`(闭包捕获:`func(kind, cell, ok, ri): if logger != null: logger.log_action(kind, cell, ok, {"round": ri}); if ok and kind == "refresh": st.refreshes += 1; elif ok and kind == "seal_place": st.seal_placed += 1`——计数语义与现 :553-561 逐位同);轮末 stop 日志与现 :566-568 同构 +- [ ] level_autoplay.gd `_pick_token`(:292-318):字面量 match rank 表删,改 `var rank: int = int(TreasureItemTable.TIER_RANK.get(String(t.get("tier", "")), 0))`(未知档 0=现 match 落空同语义;316-f 最左 tie-break 逻辑不动) +- [ ] 新增 tests/unit/core/battle_driver_drive_test.gd `_smoke_drive_round_contract` 检查段:①缺省两参调用——同种子同 settlement 下动作序列快照与改前逐位对拍(手搭 settlement 桩沿 seal_polarity_test.gd:240 状态袋先例);②provider 形态——策略回调产出 dig/move/seal_place 各一验证提交与日志回调收到(kind,cell,ok,round)四元组;③max_rejects——策略恒返回被拒动作时第 3 拒后停手出环;④合步 next——move 后相位变更即弃 dig +- [ ] run_all.gd manifest 追加 battle_driver_drive_test(expect 0);adventure_feats_test/level_shop_economy_test 现有 `_autoplay_battle` 调用面回归(签名未变零改动) + +**T8 己案·sim 信息面出口**(估时 0.5–1 工作日) +取用:无。产出:core 只读揭示口+auto_player 0 格连锁算子。 + +- [ ] minesweeper_rules.gd 新增公开只读口——精确签名与语义: + ``` + ## 挖一格→真实翻开集只读预览(sim 信息面出口——与 _classify 同口径:本格封印视为已隐式退役、 + ## 其余封印照挡;复用 _chain_closure 闭包;零状态写入、零事件发射) + func preview_reveal(c: Vector2i) -> Array[Vector2i]: + ``` + 实现:`sim_seals := _seals.duplicate(); sim_seals.erase(c)` → `_chain_closure(c, sim_seals)` → 取闭包中 `cc != c and not _revealed.has(cc)` 的格(F2 口径:新开格集,不含首格与已开格) +- [ ] auto_player.gd `_deduce`(:114-152)补 0 格连锁算子:while-changed 每轮 single+subset 扫描后追加一段——遍历 safe 集中未揭示格,逐格 `for rc in minesweeper.preview_reveal(c): if not safe.has(rc): safe[rc] = true; changed = true`(连锁只经安全格扩散=闭包集全安全,真实玩家挖 c 免费获得的信息面;`_deduce_single` novice 画像不动);:80-83「口径差异=unknown 不含 oracle」注释保持,双口径显式登记补一句「0 格连锁经 preview_reveal 真实闭包(架构整改批补齐——与棋盘生成 _apply_chain_rule 对位)」 +- [ ] 新增 tests/unit/core/auto_player_deduce_test.gd `_smoke_zero_chain_rule` 检查段:手搭棋盘夹具——0 数字区域经一格桥接,远端格与任何已开数字格不邻接(改前约束模型必不证其安全)→ `AutoPlayer._deduce` 后 safe 集含远端格断言;零盲挖语义回归(mines 集不含安全格);真实入口=AutoPlayer._deduce(经 perfect_action 装配链取 minesweeper 实例) +- [ ] minesweeper_rules_test.gd 追加 `_test_preview_reveal_readonly` 检查段:同板同格断言 `preview_reveal(c)` = `settle_batch(dig c)` 后 `revealed_cells()` 差集 ∖ {c}(F2 同口径——不含首格与已开格;封印格在场/挖封印格两形态各一例);调用前后 revealed_cells() 与 seal_count() 零变化(零状态写入);cell_revealed 事件零发射 +- [ ] run_all.gd manifest 追加:`{"path": "res://tests/unit/core/auto_player_deduce_test.gd", "expect": 0}, # R15 0 格连锁算子〔架构整改〕` +- [ ] MC 锚漂移登记:实现报告写明「0 格连锁补齐后 perfect/adv 档通关率预期上调、旧 MC 锚失效;重跑归用户按 MC 采集档位表发起」 + +**T9 组D·experiment_density 退役**(估时 0.25–0.5 工作日) +取用:T0 grep 底账。产出:死测量件清出,引用面归零。 + +- [ ] 删 game/sim/experiment_density.gd 与 experiment_density.gd.uid +- [ ] game/README.md:53 工具行删 experiment_density 引用(`dump_battle.gd(结算流水)/ monte_carlo.gd(战斗期望)` 保留) +- [ ] core/board_generator.gd:23 注释举例名已于 T3 改 calibrate_boards(本卡核对零残留);board_gen.tres:414 注释已于 T3 改「出处=退役件 experiment_density.gd(git 历史可考)」(本卡核对零残留) +- [ ] 全库 grep `experiment_density` 零命中(审计报告 reports/ 两处除外——过程件不动) +- [ ] game/tests/README.md:304 在册行——写卡段已删(见下);实现批批末核对该行确已不在 + +**T10 组C 确认+产出物落位卡**(估时 0.5–0.75 工作日) +取用:全部前卡。产出:批收口两件。 + +- [ ] 组 C 确认项(零代码改动):grep `damage_probe` 于 tests/run_all.gd 与 tools/run_all_gates.sh 零引用;damage_probe.gd 头注「诊断工具·非验收件」自陈在位——两项读数落实现报告 +- [ ] 实机目检总清单(登记不阻塞):①RAP 不足 toast「弃图刷新需 N」显示表值(改 rap_refresh_cost 表值目检文案随动)②本轮刷新用尽 toast「每轮 N 次」同上③散折价 80% 购买价目检(economy_spend 激活,回归性质) +- [ ] 遗留读数义务登记:MC 锚漂移预期(T8)+重跑归用户档位发起 +- [ ] 确认读数:level_autoplay.gd:162-163 透传守卫(R1 类型适配·非行为,B9 申报)——MC 冒烟跑一次 run_adventure relic 模式(tree_rules 字典透传)零报错即透传生效,读数落实现报告 +- [ ] **实现报告** `reports/iter-实现报告-<日期>.md`:各卡状态+实机目检总清单+遗留读数义务+实现决定记录(代拍板白名单逐条回填)+S13 键改前改后对账表(T0 现场基线 25 件逐件核——baseline 既有登记 2 件照登,第 14 节承诺逐件核) +- [ ] **反哺点清单** `reports/iter-反哺点-<日期>.md`:第 6 节同步面表逐条落点(architecture.md 件表行内容、奇物.md cap 句订正、五份 GDD 零反哺确认行、术语零新增确认行) +- [ ] 批末核对:game/tests/README.md 能力行与实际落地名实一致(改名则回表);独立验收审计(见第 8 节末)未过不合并 + +--- + +### 估时汇总 + +T0 0.25–0.5|T1 1–1.5|T2 0.5–0.75|T3 0.5–1|T4 0.5–1|T5 0.75–1|T6 0.5–0.75|T7 0.75–1|T8 0.5–1|T9 0.25–0.5|T10 0.5–0.75。 +区间合计 6.0–9.75 工作日;**精确汇总 8 工作日**(切分预案:若 T1 连带测试适配超 1.5 工日,把 sim 连带两件〔adventure_monte_carlo/level_autoplay 透传〕切出为 T1b 独立半日卡,其余不动;合计超 10 工作日=超软盒,须用户特批标记后方可续批)。 + +## 8. 验证闸(改动—验收对照表) + +测试方式两分法:下表全部走**调试接口验证**(单元/集成套直构夹具与真实入口调用,沿现役 DebugOverlay/DS_DEBUG 门控先例不适用——本批零 UI 装配面);**正常流程体验验证**=实机目检三项(T10 清单,登记不阻塞)。判据全部绑被测改动特有的可观测提交面(合成行参数值/表值驱动的产物差异/驱动序列快照/揭示集逐位);纯静态判据两处(R6/R13)已注记观测面局限。 + +| 需求点 | 改动(文件:行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 | +|---|---|---|---|---|---|---| +| R1 六键参数字典 | meta_tree.tres 三 Fork 行;meta_tree_table.gd 校验;effect_engine 四分支读参;battle_fx_host.rebuild_subscriptions 收 Dictionary;battle_orchestrator/shop_session 消费;meta_progression.tree_rules();adventure_runner/level_runner/main 传参;sim 注入面(adventure_monte_carlo db 前移+_tree_rule_dict+三档换字典;level_autoplay :162-163 透传守卫·类型适配) | tree_rules_v11_test.gd:_test_rule_key_params〔架构整改 V1〕(含 `_tree_rule_dict(db, ["posture_first_strike"])` 最小断言);既有 _smoke_tree_rules/feat_vouchers R2 面回归 | 单元 | `MetaTreeTable.validate()`/`EffectEngine.rebuild()`/`MetaProgression.tree_rules()`/`AdventureMonteCarlo._tree_rule_dict()` | 合成行 do.value=参数字典值(非硬编码);缺参数/越域 validate 返回非空;tree_rules() 返回字典含激活侧参数;_tree_rule_dict 返回 {规则键: 参数字典} | 新增:规则键参数读表(六键参数字典校验与激活侧透传);既有:天赋树购买与六键合成 | +| R2 散折价收回规则键 | shop.tres/-spend_discount;shop_table.gd 删字段;shop_session._spend_discounted 读 discount_pct | level_shop_economy_test.gd:_test_spend_discount_from_rule_key〔架构整改 V2〕 | 单元 | `shop_session.current_price()`(经 LevelRunner 装配链,economy_spend 注入) | 80% 折价值逐位同(表字段退役前后对拍);shop.tres 加载零诊断(字段真删) | 既有:GP 钱包/escrow/商店收口/共享池 | +| R3 死效果通道退役 | effect_engine.gd EFFECT_KINDS 摘两名;damage_controller overflow 分支删;combat_segment attack_segments 分支删;载荷键/排除表成员清理 | effect_kind_retired_test.gd:_assert_rejected〔架构整改 V3〕(负面套件 expect=1 negative=true);adventure_feats_test :743 面与 round_flow 段内序回归 | 单元(负面独立进程) | `ConfigDB.load_tables()`(夹具注入探针行) | 两 kind 探针行加载被拒(EFFECT_KINDS 出域报错文本);round_flow 五段全序断言零转红 | 既有:加载期违规表拒绝:跨表悬空/计数器前缀/真视窄域/效果类型出域 | +| R4 刷新提示文案读表 | main.gd:633/:636 两处拼接读表 | player_copy_sweep_test.gd:_sweep_refresh_toast_no_literals〔架构整改 V4〕+实机目检两项(T10) | 单元(静态扫描)+目检 | `player_copy_sweep` 源扫描(现役 sweep 机制) | 两 toast 格式串零数字字面量、插值位与表字段一一对应(静态判据+评审注记观测面局限:真机文案由目检兜) | 新增:刷新提示文案读表拼接(RAP 不足/轮上限两 toast 零字面量) | +| R5 ap_per_round 必填注入 | playtest_logger.gd 删默认+start_session 守卫;action_economy_table.gd 删 schema 默认;level_autoplay.gd:39-42/:117-120 注入序前置(先设 ap_per_round 再 start_session——守卫拒后开=会话静默不开) | playtest_logger_guard_test.gd:_smoke_required_injection〔架构整改 V5〕 | 单元 | `PlaytestLogger.start_session()` | 未注入返回空串+零文件;注入后返回路径;action_economy.tres 缺该字段夹具 validate 非空 | 新增:试玩日志器 ap_per_round 必填注入守卫(未注入拒绝开会话) | +| R6 clamp 域读单点 | config_db_resolver.gd:118-119 读 MULT_MIN/MULT_MAX;:110 与 difficulty_table.gd 失实注释订正 | config_db_resolver_test.gd:_test_difficulty_clamp(既有回归)+静态判据:resolver 源零 0.1/10.0 字面量(评审注记) | 单元+静态 | `ConfigDbResolver.resolve_difficulty_modifiers()` | clamp 输出域 [0.1,10.0] 逐位同(常量来源切换零值变) | 既有:行集寻址、行序保序与难度乘数 clamp | +| R7 节点图三参数入表+域并单点 | level_gen_params.gd/tres;node_map_generator.gd 四处读表+_cp_domain 删 | node_map_generator_test.gd:_test_gen_params_table_driven〔架构整改 V6〕;table_structure_guard_test.gd:_test_level_gen_new_fields〔架构整改 V7〕;node_map_growth_test 回归 | 单元 | `NodeMapGenerator.generate()`/`LevelGenParams.validate()` | 三参数改值产物可观测变化;缺键/越域 validate 拒;同种子产图回归逐位同 | 新增:节点图参数读表与域单点(三参数驱动产物/生成器侧可行性保留) | +| R8 出生区边长入表 | board_gen.tres+spawn_edge;board_gen_table.gd 零哨兵+三处导出;board_data.gd 常量删+几何导出;board_generator.gd 读表+剃雷域导出;calibrate_boards 一行透传 | board_generator_test.gd:_test_spawn_edge_from_table〔架构整改 V8〕;_test_target_mine_count_single_source 更新回归;board_gen_reward_test 夹具回归 | 单元 | `BoardGenerator.generate()`/`BoardGenTable.validate()` | spawn_edge=5 夹具布雷域基/R₀ 下限/剃雷域半径按 25 格可观测;spawn_edge=3 逐位回归;BoardData.SPAWN_AREA_CELLS 全库零引用 | 新增:出生区边长表单点(布雷域基/R₀ 下限/剃雷域半径全由 spawn_edge 导出);既有:棋盘按参数行出图、数字恒真 | +| R9 货架位数入表 | shop.tres+shelf_size;shop_table.gd 零哨兵+[1,6];shop_session.gd:155 读表 | level_shop_economy_test.gd:_test_shelf_size_from_table〔架构整改 V9〕 | 单元 | `shop_session` 货架构建(经 LevelRunner 装配链) | 夹具 shelf_size=5 → 货架五件可观测;=3 回归逐位同 | 新增:货架位数读表(进店与重抽同源) | +| R10 变异成包下界入表+表头域校验 | variation.tres+pack_min;variation_table.gd 零哨兵+三域校验;board_installer.gd:125 读表 | variant_placement_test.gd:_test_pack_min_from_table〔架构整改 V10〕;table_structure_guard_test.gd:_test_variation_header_domains〔架构整改 V11〕 | 单元 | `BattleOrchestrator.begin_battle()`(变异布置段)/`VariationTable.validate()` | 夹具 pack_min=3 → 产物零 1–2 格片;pack_min 越域/三表头字段越域 validate 拒 | 既有:变异布置门控;新增:变异表头域校验(地形变异) | +| R11 feat cap 必填 | feat_table.gd 必填+[1,99];feats.tres 30 行补 cap:1;curio_deck.gd 死变量删+悬空报错 | table_structure_guard_test.gd:_test_feat_cap_required〔架构整改 V12〕;adventure_feats_test relic 面回归 | 单元 | `FeatTable.validate()`/`curio_deck.cap_ok()` | 缺 cap 行拒/越域拒/37 行全在场;cap_ok 在场行直索引零兜底(悬空 push_error 路径断言) | 既有:表结构守卫:域校验/行序键/跨字段互锁/配额锚 | +| R12 驱动循环收敛 | battle_driver.gd 通用签名;level_autoplay._autoplay_battle 内层委托;抄本删除 | battle_driver_drive_test.gd:_smoke_drive_round_contract〔架构整改 V13〕;adventure_feats_test/level_shop_economy_test _autoplay_battle 面回归 | 单元+集成 | `BattleDriver.drive_round()`(两参缺省与五参回调两形态) | 缺省两参动作序列快照逐位同;provider 形态提交与日志回调四元组;max_rejects=3 第三拒停手;合步 next 相位变更弃 dig | 新增:sim 驱动循环单点(缺省零变化与策略/日志回调形态) | +| R13 档位排序读表 | level_autoplay._pick_token 改读 TreasureItemTable.TIER_RANK | adventure_feats_test 316-f 选件既有断言回归+静态判据:_pick_token 源零 rank 字面量(评审注记) | 单元+静态 | `level_autoplay._pick_token()`(经 run_adventure 三选一链) | 最稀有优先/最左 tie-break 逐位同(读表前后对拍) | 既有:奖励三选一候选/刷新付费/呈现 | +| R14 棋盘揭示预览只读口 | minesweeper_rules.gd +preview_reveal | minesweeper_rules_test.gd:_test_preview_reveal_readonly〔架构整改 V14〕 | 单元 | `MinesweeperRules.preview_reveal()` | preview(c) = settle_batch 挖 c 后 revealed_cells 差集 ∖ {c}(F2 同口径——不含首格与已开格,封印在场/挖封印格两形态同);调用前后 revealed_cells/seal_count 零变化;cell_revealed 零发射 | 新增:棋盘揭示预览只读口(零状态写入/与实挖揭示集同口径);既有:挖/封印合法性与可辨拒绝(拒绝零副作用) | +| R15 0 格连锁算子经真实闭包 | auto_player.gd _deduce 补算子 | auto_player_deduce_test.gd:_smoke_zero_chain_rule〔架构整改 V15〕 | 单元 | `AutoPlayer._deduce()`(经 perfect_action 装配链) | 桥接 0 区域远端格入 safe 集(改前必缺);mines 集零安全格(零盲挖语义保持) | 新增:模拟玩家 0 格连锁算子(经真实闭包,零盲挖语义保持) | + +**零行为改动面的证据义务(不设对照表行的申报)**:上表 R1–R15 覆盖本卡全部带运行期提交面的需求点。两项零行为改动——组 D(experiment_density 删除+引用面清理)与组 C(damage_probe 零改动确认)——无运行期提交面、无能力行可锚,验收=静态判据与确认读数(全库 grep 零命中/闸脚本零引用/头注自陈在位),证据落 T9/T10 步骤与实现报告,由独立验收审计按第 8 节末口径核读数;不为其虚设对照表行与能力行。 + +**闸口径**:重闸=`tools/run_all_gates.sh` 按本批改动域选档(改动含 game/ 下非 .md 行为载体 → `--code`;文档件触面并入同一合并验证——两类都有按闸脚本算法定档);所选域全绿才合并。卡内不写死闸件名单。回归措辞:里程碑卡(T 段)出口跑一次全套闸;卡内修复只做出红最小单元的最窄确认;新增测试/工具先行孤立验证再并入全套。 + +**测试削弱申报**(允许改/删的旧断言全清单;未申报的删改由独立验收审计判红): +1. tree_rules_v11_test.gd 夹具 synth 硬编码值(1/50/2)改参数字典构造——断言结构不变(四键行数对照+validate_trigger_row 零违例),值来源从字面量改参数(R1 的被测面本身)。 +2. board_gen_reward_test.gd:204-218 的 `BoardData.SPAWN_AREA_CELLS` 引用改夹具表 spawn_edge² 推导——cap 压线 9 语义不减(R8)。 +3. board_generator_test.gd:71 from_expr 公式对账改 spawn_edge²——对账强度不减(R8)。 +4. adventure_feats_test.gd:743 dispatch 载荷删 `"overflow": 0` 键——断言内容(斩首学者揭示 1 格)零松动(R3)。 +5. round_flow_skill_pool_test.gd:442 排除表删 `"fx_streak_segments"` 成员——排除面缩窄至死通道不可达成员,段内序断言零松动(R3)。 +6. node_map_growth_test.gd 手搭夹具补三新键——结构拦截与 fatal 断言零松动(R7)。 +7. level_shop_economy_test.gd:264 `spend_discount == 0.8` 迁移断言行删除——字段随 R2 退役后无可断言对象;表值迁移断言的历史使命终结,等价判据(折价 80% 行为)由新增 `_test_spend_discount_from_rule_key`〔V2〕承接,验收强度不减(R2)。 +8. meta_progression_forge_test.gd:739-740 期望值算式 `float(_db.run.shop.spend_discount)` 改经规则键参数 `discount_pct / 100.0` 推导——断言对象从表字段换规则键参数,折后价期望逐位同值,断言强度不减(R1)。 +以上 8 条均为「随被测改动同步的夹具/引用形态迁移」,无一条删除断言或放宽阈值(第 7 条删的是断言对象已消失的迁移断言,行为判据由同值新断言承接)。 + +**独立验收审计**:入口=批末 T10 后、合并前;报告=`reports/iter-验收审计-<日期>.md`;由没参与实现的会话或子代理执行,核对:对照表逐行断言真实存在且在当轮跑批通过、测试削弱申报 6 条之外零删改、第 13 节无效成员零残留、S13 键只降不升对账。未过不合并。 + +## 9. 异常分级 + +- **L1 自救**:测试断言笔误、夹具键名拼写、注释错字——就地改,记录进实现报告。 +- **L2 记录继续**:非行为漂移类小事——表注释与本卡行号 ±3 行内的漂移;测试失败经排查属既有缺陷且与本批改动无因果——登记跳过并报用户。 +- **L3 停机写报告等用户**:①卡面与处置记录/五份 GDD 冲突(上游缺陷,退写卡段);②取证表 18 处现址复核不符(同上);③乙案连带触点发现处置记录未列的第五处以上消费面(行为语义不明,禁代裁);④机检预算互斥=新增件超第 14 节预算且无例外申报=上游缺陷,停卡退回写卡段,禁实现段自行拆件或砍面;⑤拆分边界按第 4 节纪律拆不出内聚单元(凑计数袋禁)=停卡呈报走豁免/还债通道;⑥schema 校验与卡片契约互斥(含第 13 节机检键冲突)=一律停卡呈报,不得自造第三条路;⑦己案 preview 口径与「settle_batch 实挖揭示集差集 ∖ {c}」(B6 定死的 F2 同口径)出现非预期不一致。 + +## 10. 代拍板白名单 + +- 测试内部夹具的命名与组织(状态袋字段、夹具目录名、探针行 desc 文案)。 +- toast/注释中文措辞的微调(数值与字段名不动)。 +- validate 错误 message 的具体文案(判别词「缺参数/多参数/越域/出域」必须保留在 message 内供断言定位)。 +- 表行插入的物理顺序与对齐(.tres 字段顺序不改变语义)。 +- feats.tres 批量补 cap 的脚本实现方式(用后即删)。 +- 测试函数内部辅助函数的拆分(不新增公开面)。 +- 逐卡内「孤立验证→出红最小单元→并入全套」的执行顺序细节。 +超清单的决断记入实现报告「实现决定记录」节。 + +## 11. 待裁点 + +**零待裁点,开工门=U0**——设计方案甲~庚与全部取证处置均已在 2026-11-02 讨论会话由用户逐项裁决(处置记录 §二/§三「已裁或按总判据导出,零待裁点」),五份 GDD 落文闭合。本卡未新增任何备选案。 + +## 12. 落位与可复用性预检 + +**新增文件(4 件,全部测试件)**: +- tests/unit/data_config/effect_kind_retired_test.gd——为什么不能复用:甲案词表退役的负面断言必须独立进程断言退出码(test-conventions §5.6,负面套件禁落现役非负面套件——headless assert 错误扫描假红);counter_prefix_fatal_test.gd 是 feats.tres 注入探针的同形态先例,**复用其夹具模式但不并件**(该件断言的是 counter 前缀与引用闭合,注入探针内容与本件不同,并件会让负面 manifest 语义混乱)。唯一落点:data_config 目录(夹具对象=feats.tres 加载路径);grep 同名零命中。 +- tests/unit/core/playtest_logger_guard_test.gd——playtest_logger 现无任何测试件(grep 零命中);守卫行为是 R5 特有提交面,无法挂靠既有套件的既有能力行。唯一落点 tests/unit/core。 +- tests/unit/core/battle_driver_drive_test.gd——drive_round 契约测试需手搭 settlement 桩与动作序列快照对拍;smoke 族共用面(battle_driver 头注声明)明确「smoke_all 本体不经本面、含回归断言禁并入」——契约测试落单元层新件,不污染 smoke。状态袋复用 seal_polarity_test.gd 的手搓先例模式(引用步骤,不复制代码)。 +- tests/unit/core/auto_player_deduce_test.gd——0 格连锁算子需特构棋盘夹具(0 区域+桥接格),adventure_feats_test 的冒险装配链夹具过重且断言面不同。唯一落点 tests/unit/core。 + +**新增函数/常量(逐条唯一性核查)**: +- `MinesweeperRules.preview_reveal`——grep `preview` 于 minesweeper_rules.gd:现公开面只有 fx_reveal(带状态写入的事件版,:355)——两者语义不同(零写入 vs 真挖),不能复用;命名与 effect_engine PREVIEW 主动件无冲突(跨类)。core 公开 API 净增 1 口,反哺点清单承载。 +- `MetaTreeTable.RULE_KEY_PARAMS`+`_validate_rule_key_params`——schema 内唯一;仓库无第二份参数域表(天赋树.md 规则键参数表=owner,schema=机械承载,两处同源不违规:文档定域、schema 执行)。 +- `MetaProgression.tree_rules()`——`tree_rule_keys()` 改名而非并存(禁别名,第 13 节);grep 全库唯一调用点 main.gd:198+测试两处,全量适配。 +- `LevelAutoplay._act_provider`/`_action_logger`——level_autoplay 文件内静态适配器,唯一;通用形态只在 battle_driver.drive_round 一处。 +- `AdventureMonteCarlo._tree_rule_dict`——sim 内唯一;不散落(level_autoplay 透传不重建字典)。 +- `BoardData.spawn_edge` 成员——唯一出生区边长实例承载;表头单点 board_gen_table.spawn_edge 经行快照注入,无第二处几何定义(`_shave_ring` 半径推导同源)。 +- `VariationTable._validate_header_domains`——表头域校验唯一段;不与行校验混写。 + +**复用既有(不新增)**:负面套件形态=counter_prefix_fatal_test 模式;驱动桩=seal_polarity_test 状态袋模式;能力清单挂靠=既有行追加用例为主(8/16 行新增能力仅 6 行全新);TIER_RANK/TIER 词表/状态袋/gdstyle 基线全部既有件。 + +**分层与交互面**:sim→core 单向(auto_player→preview_reveal;battle_driver→settle_batch/player_request_refresh);core→data schema 方向(config_db_resolver→DifficultyTable.MULT_MIN——与既有 db.combat.* 消费同向,禁反向);presentation→core 只经既有出口(main.gd 读 db.run.action_economy 现役口径不变);RngService 红线零触碰(本批零新增随机源——variation/board_gen 参数全为读表非取数);Core 零 UI 红线零触碰(minesweeper_rules 新口纯查询)。 + +## 13. 禁为机检文本保留无效成员 + +本卡为重构类卡,全卡适用以下条款(code-conventions §1.1 同款):禁止为迎合机检消息文本(含计数、message 判别词、grep 面)而保留或新增无效成员/别名/死分支;`tree_rule_keys()` 改名后旧名禁留兼容壳;EFFECT_KINDS 摘名后禁留注释化成员;`_kill_overflow` 改名后旧名禁留转发壳;`_cp_domain` 删除后禁留空壳调用。机检键与卡片契约互斥时(如 pipeline_gate/gdstyle 消息判据与本卡签名冲突),实现段一律停卡呈报,不得自造第三条路。 + +## 14. 实现规范预算 + +新增 .gd 文件仅 4 个测试件(SceneTree 测试脚本,无公开方法面、无常量成员超限面——gdstyle 对测试件的接口块预算全部余量充足,逐件实数:公开方法 0、类变量 0–2)。新增生产代码为零新文件(全部落在既有件),按「存量触面一查」逐件对账: + +- 接口块预算(改动后公开方法数 ≤20 / 成员变量 ≤15):minesweeper_rules.gd 公开方法 +1(现数远低于 20,T0 读数确认);board_data.gd 成员 +1(spawn_edge);battle_driver.gd 公开方法 +0(单函数签名扩展);meta_tree_table.gd 常量 +1(RULE_KEY_PARAMS——常量不计类变量阈值);其余件公开面零净增(改名/收参不增数)。 +- 单函数分支 ≤8:`_push_tree_rule` 四分支 match(economy 两键零合成行不入 match)——参数化后分支数不变为 4;`drive_round` 分支数:5 kind 分派+合步 next+守卫 ≈7——在限内,T0 读数锁定基线;`_validate_rule_key_params` 分支 ≤6。 +- 迁移函数对账:本批无「自存量文件迁入」函数(改名件 `_kill_overflow`→`_kill_effects` 按同键迁移查 `tools/gdstyle_baseline.txt`——源键 branches/returns 超登记值即随迁拆函数,拆分不改语义)。 +- 存量触面 S13 预期:本批实触存量生产件 30 件,其中 gdstyle 扫描面(core/data/presentation)内 25 件为对账面——S13 键较 T0 现场基线**只降不升**(net 删代码为主:两死分支/域校验函数/字面量表;净增面仅 preview_reveal 与校验段——降不达即检查是否夹带超预算成员,L3 ④兜底);扫描面外 5 件(sim/tests)随批闸口径另计。 +- 指标例外申报:无(零新件超默认阈值;若实现中发现例外,走本卡异常分级 L3 ④停卡,禁就地豁免)。 + +## 15. 拆分边界纪律 + +见第 4 节末「拆分边界纪律」条款(结构类卡必填,卡内写条款、判据定义以 code-conventions §1.1 为权威):两个拆出/收敛单元(drive_round 通用签名、参数域校验并单点)各带职责语句、单一变化原因与集体身份;「过阈值」只作发现信号;拆不出内聚单元停卡呈报(第 9 节 L3 ⑤)。先例=迭代 41 两卡 v1.2(核心数据面契约 7/呈现层契约 9)。