16 KiB
需求卡片:minesweeper_rules 公开面还债批
来源:待办清单「minesweeper_rules 公开面还债——S13 超标键撤销后的清偿」(2026-11-04 登记,来源=批次移交,优先级=P0;需求性工程条目,证据指认在条目实况)。唯一事实源:该条目实况证据链+本卡第 3 节 2026-11-04 代码级考证(21 公开方法全量调用方盘点,逐方法实查)。 裁决沿革:登记方向=「settle_batch/fx_reveal 族收敛或搬迁」(批次移交在册);2026-11-04 本会话全量盘点后按证据收窄——两族受架构在册边界与职责轴保护不可作收敛点(§3.2),收敛点唯一化=
safe_remaining(无生产消费方公开面收回,§3.3),待用户批卡背书。 验收档:中 版本:v1.0(2026-11-04)
1. 目标与完成定义
把 S13 红键清偿为绿:
game/core/minesweeper_rules.gd公开方法 21→20:safe_remaining公开→私有_safe_remaining(函数体逐字不动);- gdstyle 闸(S13=
quality/max-public-methods,默认上限 20)该文件归绿,零新增基线键; - 游戏行为零变化:私有化=改名,无任何运行期可观测面变化;4 处测试直连点改锚私有面,断言消息与期望值逐字不变。
完成定义:gdstyle 单件读数公开方法 20≤20 且零红键;minesweeper_rules_test 既有断言全数通过;全仓 \.safe_remaining\( 调用形态零残留;--code 域全套闸绿。
2. 设计事实源
需求性工程条目(重构/还债,无设计线):设计事实源=证据指认——待办清单条目实况证据链(tools/gdstyle_baseline.txt 该文件零在册键=S13 键 2026-11-04 用户裁撤销后为活红;git 提交 7f512aa8 归位两法在案)+本卡第 3 节 2026-11-04 代码级复核(file:line 逐条实查)。
3. 现状事实(2026-11-04 代码级考证)
3.1 红键本体
- gdstyle S13 规则=
quality/max-public-methods,默认上限 20(tools/gdstyle.toml头注:阈值取 gdstyle 默认值)。 game/core/minesweeper_rules.gd非下划线公开方法实数 21(_init豁免,与 S9 R3 同口径)::52/:58/:70/:81/:85/:89/:93/:97/:101/:109/:116/:129/:134/:146/:175/:180/:239/:379/:397/:487/:554。tools/gdstyle_baseline.txt该文件零在册键(grep 零命中)——S13 键经用户裁撤销后,红为 NEW 形态活红。
3.2 登记方向考证——settle_batch/fx_reveal 两族为何不可作收敛点
- settle_batch(:239)=架构在册唯一提交入口(architecture.md:105「A2 行」);生产调用方=组合根
main.gd:574/:603 两处。搬迁=改架构在册 API 边界;收敛(合并/缩签名)=改唯一提交口契约,零职责收益。 - fx_reveal(:379)=棋盘状态本体写口:函数体改已开集
_revealed、发cell_revealed(:380-392);消费方=core 件battle_fx_host.gd:185、reward_grant.gd:176。按职责轴(code-conventions §1.1 拆分判据①)是本类本职——搬出=状态暴露或连锁闭包复制(违唯一面)。
3.3 21 公开方法全量调用方盘点(2026-11-04)
排查语料=game/ 全部 .gd 与 .tscn 非注释行;下表「生产调用方实证」=调用形态实查(接收者为 minesweeper 实例)。
| # | 方法(定义行) | 生产调用方实证 | 测量/测试面 | 处置 |
|---|---|---|---|---|
| 1 | current_board(:52) | main.gd:375/:582、board_resolvers.gd:30/:44、battle_orchestrator.gd:701 | sim:7 probe:16 test:52 | 保留 |
| 2 | harmful_variants(:58) | grant_segment.gd:110 | — | 保留 |
| 3 | harmful_adjacent(:70) | grant_segment.gd:359 | — | 保留 |
| 4 | reveal_record(:81) | board_view.gd:494/:564 | sim:1 probe:1 test:1 | 保留 |
| 5 | hero_pos(:85) | main.gd:588 | sim:6 probe:19 test:45 | 保留 |
| 6 | is_revealed(:89) | board_view.gd:303/:475/:490/:535、battle_fx_host.gd:177 | sim:10 probe:23 test:22 | 保留 |
| 7 | has_seal(:93) | reward_grant.gd:174 | sim:7 probe:11 test:7 | 保留 |
| 8 | revealed_cells(:97) | battle_orchestrator.gd:507/:700 | sim:3 probe:1 test:16 | 保留 |
| 9 | safe_remaining(:101) | 生产外部零调用——唯一生产调用=同类 clear_map_cleared(:110) | test:4 | 收敛点:公开→私有 |
| 10 | clear_map_cleared(:109) | main.gd:582 | test:1 | 保留 |
| 11 | remove_mines_in(:116) | reward_grant.gd:187、grant_segment.gd:400 | — | 保留 |
| 12 | is_removed(:129) | board_view.gd:303/:537 | test:3 | 保留 |
| 13 | has_unrevealed(:134) | treasure_interact_controller.gd:123 | test:1 | 保留 |
| 14 | install_board(:146) | board_installer.gd:50 | test:6 | 保留 |
| 15 | seal_count(:175) | battle_orchestrator.gd:508/:701 | test:9 | 保留 |
| 16 | retire_board(:180) | battle_orchestrator.gd:534、battle_refresh_flow.gd:69 | — | 保留 |
| 17 | settle_batch(:239) | main.gd:574/:603 | sim:3 probe:8 test:134 | 保留(§3.2-1) |
| 18 | fx_reveal(:379) | battle_fx_host.gd:185、reward_grant.gd:176 | test:13 | 保留(§3.2-2) |
| 19 | preview_reveal(:397) | 生产零调用——架构在册 sim 信息面出口(architecture.md:105;sim/auto_player.gd:155 消费) | test:6 | 保留(改它必破坏 MC 自动玩家读数连续性) |
| 20 | compute_move_path(:487) | board_hover.gd:122+同类 _do_move(:479) | sim:3 probe:1 test:5 | 保留 |
| 21 | mine_total(:554) | battle_orchestrator.gd:384 | test:2 | 保留 |
结论:20 个公开方法有生产调用方(全数保留);preview_reveal 生产零调用但为架构在册 sim 出口(保留);safe_remaining 生产外部零调用(唯一外部消费面=测试直连)——公开面收回的唯一合法收敛点。
3.4 safe_remaining 本体
- 函数体(:101-106):数未揭示安全格(遍历
_board.safe_cells()对_revealed求余量)。 - 消费面:同类
clear_map_cleared(:110return safe_remaining() == 0)+测试直连 4 组断言 5 处调用表达式(minesweeper_rules_test.gd:56/:89/:93 两处/:94——精确余量断言,无公开可观测面承载精确计数:clear_map_cleared仅 bool)。 - 在案观察(不收件):
_classify(:276-280)有一段内联余量计数,与safe_remaining形态重复——合并无职责依据,不动。
4. 设计契约(🔴 违反即 L3 停机呈报)
- 🔴 游戏行为零变化——私有化=改名,函数体逐字不动;零 RNG/信号/存档/表值触面。
- 🔴 收敛动机纪律——本批收敛对象=「无生产消费方的公开面」收回(职责依据,与死码清退同族);禁以阈值数字为动机合并/收拢/搬迁任何有消费方的公开面(code-conventions §1.1 拆分判据③);禁动 settle_batch/fx_reveal/preview_reveal(§3.2/§3.3 在册理由)。
- 🔴 禁保留无效成员——私有化后禁留公开别名/转发壳/空 getter(code-conventions §1.1 拆分判据⑤)。
- 🔴 测试断言零削弱——4 组断言改锚后检查语义与期望值逐字不变;改锚=内部面直查受控例外(test-conventions §8.2:精确余量计数无公开可观测面可钉),对照表该行注明理由。
- 🔴 MC/模拟零跑——无数值改动;sim/auto_player 零触碰。
- 🔴 实现批禁写
design/整个目录与根规则文件——architecture.md:105 走反哺点清单由文档批落文。 - 🔴 车道铁律——实现走独立 worktree,主区只作合并落点。
5. 范围边界
做:safe_remaining→_safe_remaining 改名(1 处定义+1 处内部调用点+测试 5 处调用表达式改锚)。
不做:
- 其余 20 公开方法零触碰(§3.3 盘点表逐行在册理由);
tools/gdstyle_baseline.txt零编辑(不加键不改键——21→20 低于默认上限自然归绿;基线维护归人工修订经用户批准,本批无需);_classify内联计数与safe_remaining的形态重复不并(§3.4 在案观察);- sim/probe 零触碰。
明示不收件的去向:无。
6. 关联文档同步面
| 文档 | 关联点(本批实现会改变它的哪条陈述) | 同步义务 |
|---|---|---|
design/engineering/architecture/architecture.md |
:105「A2 行」句「公开方法面 19→21(超阈值贴顶——还债归待办清单 P0 条目…)」本批落地后过期 | 实现批禁写——登记进反哺点清单(改现状句:公开方法面 20,safe_remaining 私有化,S13 归绿),用户裁决后归文档批落文 |
game/tests/README.md |
:118-121 排雷玩法四能力行——代表用例均为 _test_* 函数名,本批零改名 |
实现批禁写——批末收尾核对名实一致(零回表预期) |
| 术语表/GDD 各系统文档 | 零关联(纯代码面收敛) | 无同步义务 |
| 待办清单 | 本条目状态推进(已写卡→已编迭代→完成删除) | 流水线各段承载,实现批不碰 |
7. 任务卡
卡前文件结构图(零新增文件):
| 文件 | 职责与改动 | 行为改动 |
|---|---|---|
game/core/minesweeper_rules.gd |
:101 定义改名+:110 调用点同步(函数体逐字不动) | 否(非行为改动——对照表行 1) |
game/tests/unit/core/minesweeper_rules_test.gd |
5 处调用表达式改锚(断言消息与期望值逐字不动) | 否(适配——申报见第 8 节) |
T0 基点读数(≈0.1 工作日)
- gdstyle 单件读数固化:
python tools/gdstyle_gate.py按闸件用法跑game/core/minesweeper_rules.gd——记录红键原文(NEW:公开方法 21)与公开方法计数 - 测试断言基线固化:
minesweeper_rules_test.gd:55-56/:89-94 四组断言现文抄录进实现报告(改锚前后逐字比对锚)
T1 私有化与测试改锚(≈0.25 工作日)
minesweeper_rules.gd:101:func safe_remaining() -> int:→func _safe_remaining() -> int:(:102-106 函数体逐字不动)minesweeper_rules.gd:110:return safe_remaining() == 0→return _safe_remaining() == 0minesweeper_rules_test.gd::56/:89/:93(两处)/:94 调用目标_rules.safe_remaining()→_rules._safe_remaining()——断言消息串与期望表达式逐字不动- 孤立验证:
…console.exe --script res://tests/run_all.gd单测域全绿(重点 minesweeper_rules_test)
T2 验证与落位(≈0.15 工作日)
- gdstyle 单件绿:公开方法 20≤20,该文件零红键
- 零残留 grep:全仓
\.safe_remaining\(零命中;\._safe_remaining\(恰 6 处(:110+测试 5 处) - 里程碑步出口:
tools/run_all_gates.sh --code全绿 - 产出物落位:
reports/iter<N>-实现报告-<日期>.md(各卡状态+受控例外注记+实现决定记录;无实机目检项——改名零玩家可观测提交面)+reports/iter<N>-反哺点-<日期>.md(architecture.md:105 一条)
估时:合计中值 ≈0.5 个工作日(区间 0.4–0.6)。
8. 验证闸(改动—验收对照表)
| # | 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 |
|---|---|---|---|---|---|---|---|
| 1 | 公开面收敛 21→20(S13 归绿) | minesweeper_rules.gd:101/:110 改名 |
gdstyle S13 读数:该文件 NEW 红→零红(20≤20)——落实现报告 | 静态闸 | gdstyle 闸单件直跑 | S13 公开方法计数 21→20=本批特有提交面 | 既有:装板与开局免费展开(封锁格无资源、计入清图) |
| 2 | 行为零变化回归锚 | 同行 1(改名) | minesweeper_rules_test.gd 既有断言全数通过(_test_install_invariants/_test_reveal_advances 等,当轮跑批执行) |
单元 | tests/run_all.gd 单元套件 |
断言期望值零变化(改名后同值同断言)=零行为漂移证据 | 既有:装板与开局免费展开(封锁格无资源、计入清图) |
| 3 | 测试直连改锚(受控例外) | minesweeper_rules_test.gd :56/:89/:93/:94 |
同行 2(改锚后断言在当轮真实跑批执行并通过) | 单元 | 同行 2 | 精确余量计数断言——受控例外注记:精确余量无公开可观测面可钉(clear_map_cleared 仅 bool),理由随本表申报 |
既有:装板与开局免费展开(封锁格无资源、计入清图) |
-
能力行覆盖说明:本批测试函数名零变化——README:118-121 四能力行(装板与开局免费展开/挖/封印合法性与可辨拒绝/棋盘揭示预览只读口/封印不可逆与挖开封印格放行)的用例全部照旧运行;对照表三行选「装板与开局免费展开」为锚(其代表用例
_test_install_invariants直含改锚断言 :56),其余三行由同套件当轮跑批兜底。 -
非行为改动行:私有化改名=非行为改动(判断依据:函数体逐字不动+行 2 断言全绿)。
-
测试方式两分法:本批全部归调试接口验证(单元断言+静态闸读数);无用户目检项(零玩家可观测提交面)。
-
测试削弱申报:测试调用点 5 处改锚——断言期望值与检查语义逐字零变化;无断言删除、无阈值放宽、无扫描面缩小。
-
独立验收审计:
reports/iter<N>-验收审计-<日期>.md,未参与实现的会话或子代理执行,未过不得合并(test-conventions §8.7;验收档中=对照表全量核对+判据绑定面抽查+复跑以远端 CI 现查读数代证)。 -
回归措辞:里程碑步(T2)出口跑一次
--code域全套闸;卡内修复只做出红最小单元的最窄确认。
9. 异常分级
- L1 自救:断言消息占位符顺序微调、空行排版。
- L2 记录继续:措辞级微调(记录进实现报告「实现决定记录」)。
- L3 停机呈报:①改名后 S13 仍红(计数口径与本卡考证不符=上游缺陷,停卡退回写卡段);②发现
safe_remaining生产外部调用方(与 §3.3 盘点矛盾);③机检键与本卡契约互斥(禁改闸件豁免、禁自造第三条路);④全套闸红不可最小单元收敛。
10. 代拍板白名单
- 断言消息串中随改名联动的参数占位写法(保持文案语义)。
- 删除/空行排版微调。
11. 待裁点
零待裁点——收敛点按 §3.3 盘点证据唯一化(safe_remaining);登记方向(settle_batch/fx_reveal 族)的排除分析在册(§3.2);用户批卡即对收窄方向背书。开工门=grilling 复核+用户裁决+迭代编排(编入迭代后估时总量 <5 工作日=冻结待凑批)。
12. 落位与可复用性预检
- 复用面:零新增件——纯改名;禁新增任何转发壳(契约 3)。
- 唯一面:
_safe_remaining唯一落点仍在minesweeper_rules.gd(数剩余安全格=棋盘状态本职,不迁移);grep 同名核查已证safe_remaining(被私有化)与safe_cells(BoardData 方法,另一标识符域)无混淆。 - 分层与交互面:零跨层变化——生产调用方只有同类内部一点(:110);测试直连走受控例外(契约 4);Core 零 UI 依赖不因改名新增绕行;零表值触面。
13. 禁为机检文本保留无效成员
🔴 适用——禁为迎合 S13 消息文本(含计数)保留或新增无效成员/别名/转发壳;改名与机检键互斥时实现段一律停卡呈报,不得自造第三条路。
14. 实现规范预算
零新增文件——三查不适用。存量触面:minesweeper_rules.gd 基线零在册键(grep 已证)——S13 预期 NEW 红→消失(21→20);改名不改函数长/分支/返回数(gdstyle 函数级规则零漂移);测试文件不在 S13 扫描面(产品码三目录外,code-conventions §4.13)。全部触面 S13 键较登记值只降不升(T0/T2 读数步骤承载)。
15. 拆分边界纪律
本卡为收敛类(公开面收回)——无拆出单元(私有化非拆分,无新件)。红线:收敛动机=职责依据(无生产消费方公开面,§3.3 盘点表为证),非阈值数字;禁为凑 20 合并/收拢任何有消费方的公开面;禁把本卡与卡②清退面混装(两卡两事项,编排段可凑批)。