@@ -0,0 +1,460 @@
# 需求卡片:架构审查 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.2, 2026-11-03 成文;v1.1=grilling 对抗复核 9 阻断+10 建议全采纳修订;v1.2=终审核 3 阻断+1 建议折入——测试适配面闭合判据+S9 参数化泛型形态)。改动面:游戏代码+工具代码(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()(加载期)。
- 🔴 **S9 参数化形态 ** (终审 B12):本批全部新增/改型注解一律参数化泛型(`Dictionary[Variant, Variant]` / `Array[Variant]` , code-conventions §4.12 现行口径)——裸 `Dictionary` /`Array` 注解=S9 R1A 红;参数禁缺类型(R3,`_init` 豁免除外);db 参鸭子型沿 board_generator.gd:24 先例(sim 面不在 S9 扫描面)。
- 🔴 **拆分边界纪律 ** (结构类卡必填,判据权威=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<N>-反哺点-<日期>.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】全文件触点 17 处适配::312 tree_rules()、:322/:330/:340/:342 resume 断言、:608-611 tree_rule_keys() 三行、:632/:644/:661 rebuild 第三参、:695/:725/:755 begin_battle 键数组、:749/:758 encounter 直改、:671/:746 空形态、:737 键数组注入改字典、:739-740 期望算式改 discount_pct 推导(申报 8)
tests/unit/core/feat_vouchers_test.gd 【行为 R1】:168 键数组 → 参数字典+:218/:243/:270 空数组 stale → {}
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 删(断言内容不动)+rebuild 第三参 [] → {} 共 30 处(:592-761 grep 定位逐处)〔形态迁移·申报 9〕
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: Dictionary[Variant, Variant], nid: String) -> 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[Variant, Variant] = {})` ; `_push_tree_rules(tree_rules: Dictionary[Variant, Variant])` 逐键调 `_push_tree_rule(rk: String, params: Dictionary[Variant, Variant])` ;四分支参数化——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[Variant, Variant]) -> void` 第三参类型改(漏改即每次 begin_battle 运行期崩——B1)
- [ ] battle_orchestrator.gd:351-353 收 `Dictionary[Variant, Variant]` ; :654-656 改 `var hoard: Dictionary[Variant, Variant] = (_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[Variant, Variant]` ; `_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[Variant, Variant]` ) /:542/:733+ :69/:664 注释同步(tree_rules:Array → 参数字典);main.gd:198 改 `meta_ref.tree_rules()` ( :185 注释同步)
- [ ] meta_progression.gd:388-401: `tree_rule_keys()` 改名 `tree_rules() -> Dictionary[Variant, Variant]` (键=规则键,值=激活侧 effects_* 参数字典原样透传,首遇优先去重语义保持)
- [ ] sim 连带:adventure_monte_carlo.gd——db 加载段(:67-70)前移至 feat_profile 构造之前,新增 `static func _tree_rule_dict(db, keys: Array[Variant]) -> Dictionary[Variant, Variant]` ( db 参鸭子型沿 board_generator:24 先例——sim 面不在 S9 扫描面;扫 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 第三参改空字典 `{}`
- [ ] 测试适配三(闭合判据=按文件 grep 全量触点,B10/B11):meta_progression_forge_test.gd 全文件 `tree_rules|tree_rule_keys` 触点 17 处(:312/:322/:330/:340/:342/:608/:609/:611/:632/:644/:661/:695/:725/:755/:749/:758/:671/:746/:737 逐一入上两步);adventure_feats_test.gd rebuild 第三参 `[]` → `{}` 共 30 处(:592-761 区间 grep 定位逐处改,断言内容零改动——申报 9);feat_vouchers_test.gd:218/:243/:270 空数组 stale 改 `{}` ;收尾核:`grep -c "tree_rule_keys" game/` 全库零命中+`grep -n "tree_rules" game/tests --include="*.gd"` 逐件过目零键数组残留
- [ ] 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<N>-实现报告-<日期>.md`:各卡状态+实机目检总清单+遗留读数义务+实现决定记录(代拍板白名单逐条回填)+S13 键改前改后对账表(T0 现场基线 25 件逐件核——baseline 既有登记 2 件照登,第 14 节承诺逐件核)
- [ ] **反哺点清单** ` reports/iter<N>-反哺点-<日期>.md`:第 6 节同步面表逐条落点(architecture.md 件表行内容、奇物.md cap 句订正、五份 GDD 零反哺确认行、术语零新增确认行)
- [ ] 批末核对:game/tests/README.md 能力行与实际落地名实一致(改名则回表);独立验收审计(见第 8 节末)未过不合并
- [ ] .uid 收口(终审 S11):` --editor --quit` 一次后确认 4 件新测试件 .uid 已生成随批提交(仓库 .uid 全量入库先例——防合回主区长期 untracked);删除件 experiment_density.gd.uid 确已随 T9 移除
---
### 估时汇总
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)。
9. adventure_feats_test.gd:592-761 rebuild 第三参 ` []` → ` {}` 共 30 处+meta_progression_forge_test.gd:632/:644/:661 同款 3 处——typed 形参迁移的形态适配,断言内容与期望值零改动(R1)。
以上 9 条均为「随被测改动同步的夹具/引用形态迁移」,无一条删除断言或放宽阈值(第 7 条删的是断言对象已消失的迁移断言,行为判据由同值新断言承接)。
**独立验收审计**:入口=批末 T10 后、合并前;报告=` reports/iter<N>-验收审计-<日期>.md`;由没参与实现的会话或子代理执行,核对:对照表逐行断言真实存在且在当轮跑批通过、测试削弱申报 9 条之外零删改、第 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)。