Files
gplan-2/reports/审计-全库架构审查-2026-10-29.md

27 KiB
Raw Permalink Blame History

审计:全库架构审查(2026-10-29)

性质:设计讨论段过程稿(审计读数)。game/ 全目录只读架构审查的发现清单与证据,作为写卡段、工程改动批与文档设计批的输入材料;结论被吸收进权威文档与修复批后按「吸收即死」退役。 范围:core 44 件、presentation 71 件、data 24 schema + 19 表、sim 15 件、probe 19 件、tests 69 件、tools/ 闸件。判据双轨=项目自有规范(design/engineering/architecture/architecture.md v1.24 + 五份工程规约)+ Godot 4.7 最佳实践。 方式:分层依赖方向/数据管线/测试覆盖三路并行静态取证+机械 grep 复核。零测试执行、零引擎运行、零闸执行(测试两入口铁规),全部结论来自静态读盘;下文每条命中均给 文件:行号,抽查原文已核。 处置状态(2026-11-03 更新):§三 P0(3.1/3.2)已随迭代 50 三卡合回(合并提交 8d3a12ec)。§四 P1 四条全部闭合,含三处子项一并落笔:4.1 表 presentation 行(零动作,豁免通道限定用途已在册)、4.2 表 S7 行的私有成员直取面(缺口在册、移交 §5.1,不属 §四)、4.4 末「低覆盖另计四件」(零动作,能力清单已承接)——裁决、读数订正与已落地闸件见各节「2026-11-03」标注。§五 P2 四项未处置、§六待裁点⑦未落文,本报告禁退役(「吸收即死」判据未满足:结论未全吸收进权威文档)。登记位现不在原「架构审查优化讨论」条目(该条随迭代 50 收尾按状态机出口删除),改在待办清单「架构审查余项——闸面缺口、豁免存废、零测试点名与架构文档漂移」(2026-11-03 批次移交新立)。


一、总评

分层骨架是健康的:core 纯逻辑(44 件里 37 件 RefCounted、3 件 Resource,extends Node 仅 4 个 Autoload)、Core 零 UI 八项判据全零命中、core 内 RNG 单点 100% 成立、字符串式信号连接全库 0 处、core 层函数体超 120 行零命中、19 表 ↔ 19 schema 一一对应零孤儿、无循环 preload。

真正的风险不在分层,在三条写了却没闸守的纪律被实际破坏,外加三处守卫面缺口。

  1. 「玩法数值只存 data/tables/」被 18 处硬编码击穿,其中两处是玩家可见的提示文案数字。
  2. game/sim/ 与 game/core/ 存在四组平行实现,直接威胁「模拟读数 = 游戏真实数值」这一前提。
  3. RNG 单点、类型闸、质量闸、结算禁 await 的扫描面都止步于 core/presentation(部分只扫 9 文件显式清单),sim / probe / tests 三层几乎不受约束。

另有封装面(结算段类直取编排器私有成员)与文档漂移(架构文档登记件与盘上实件不一致)两类低危问题。


二、健康面(已逐条核,零问题)

判据 结果 证据口径
Core 零 UI 零命中 res://presentation、Control/Node2D 系、.tscn、$ 节点语法、get_parent() 在 core 全域零命中;core 内 get_node 仅 2 处且均为 Autoload 取依赖
RNG 单点(core 内) 100% 合规 15 处 open_stream + 1 处 pure_stream 全经 RngService;RandomNumberGenerator.new() 在 core 内仅出现在 rng_service.gd 自身
字符串式信号连接 全库 0 处 正则 \.connect\(\s*" 全 game/ 零命中
core 层 await 零命中 4 处匹配全在文件头注释里自述「零 await」
core 超长函数 零命中 函数体 >120 行只在 presentation(board_view._paint_cell 142 行、ui_kit.danger_button 122 行)
表 ↔ schema 一一对应 19 .tres ↔ 19 顶层 schema,零孤儿表、零缺 schema;24 schema 全被消费
resolver / cross_validator 非测试专用 二者都在 ConfigDb._ready → load_tables() 产品路径真实运行
循环 preload 零命中 全仓依赖图 DFS 仅 2 个自环,均在注释文本里
静态闸防空转自检 已内置 S1–S13 各规则自带扫描面文件数为零即判红

三、P0 — 破坏既有纪律,已有实证

3.1 数值单一事实源被击穿(架构原则 2:代码零玩法数值字面量)

判据来自 design/engineering/architecture/architecture.md 架构原则 2 与 code-conventions.md 数值类硬纪律。下表分两类:A 类=用户可观测的玩法数值写死在代码,直接违规;B 类=自标「机制结构常量/产出约束」,是否该入表属待裁,不计违规。

A 类(18 处,直接违规)

# 位置 写死的值 表内真值 / 影响
1 game/presentation/main.gd:787 提示文案「弃图刷新需 8」 action_economy.tres 的 rap_refresh_cost。紧邻 783 行是正确读表的,文案另写一份
2 game/presentation/main.gd:790 提示文案「每轮 2 次」 同表 refresh_cap_per_round。表改了玩家看到的数字不改
3 game/core/battle_orchestrator.gd:883 GP 掉落乘数 1.5 表内无此项;代码注释自认「乘数 provisional 150%」
4 game/core/node_map_generator.gd:380 岔口分支概率 0.35 level_gen_params 表内无此项
5 game/core/node_map_generator.gd:455 rest/reward 排列起始骰 0.5 表内无此项
6 game/core/node_map_generator.gd:361 岔口目标数上限 24 表内无此项
7 game/core/effect_engine.gd:146 天赋「守」盾值 1 表内无此项
8 game/core/effect_engine.gd:152 天赋「锋」伤害减半 50 表内无此项
9 game/core/effect_engine.gd:151/154/161/164 天赋每关限次 2 表内无此项
10 game/core/damage_controller.gd:435 直伤分量默认 50(百分比) 表内无此项,h.get("value", 50) 兜底
11 game/core/battle_orchestrator.gd:507 变体成包大小下界 2 只有上界读表 variation.pack_max
12 game/core/settlement/combat_segment.gd:64 连击分段默认 cap=2 / divisor=3 表内无此项
13 game/presentation/playtest_logger.gd:16 ap_per_round := 8 与 action_economy.tres 同名值逐字重复
14 game/core/config_db_resolver.gd:118-119 clamp 域 0.1 / 10.0 与 difficulty_table.gd 的 MULT_MIN/MULT_MAX 重复但另写一份字面量
15 game/core/curio_deck.gd:98 令牌 cap 兜底 99 config_db_cross_validator.gd:91 注释写 cap ∈ [1,99],schema 无定义
16 game/core/shop_session.gd:155 货架位 3 表内无此项
17 game/sim/level_autoplay.gd:29-34 失误三概率 0.10 / 0.05 / 0.10 直接决定 MC 读数,属模拟口径的一部分
18 game/sim/level_autoplay.gd:410-428 选路评分 30/5/10/80/20 同上

最危险的是 #1 #2:玩家会直接看到错误数字,且没有任何闸能发现「表值与文案数字不一致」。

同族不一致(顺带查出):同调位上限在 core/attunement.gd:14 与 core/meta_progression.gd:476 写 range(1, 4)(上限 3),而 presentation/views/hero_info_panel_view.gd:61/175 写 for i in 4(4 槽)——两处口径已不一致。

B 类(自标结构常量,是否入表待裁,不计违规)

位置 常量 代码自述
game/core/node_map_generator.gd:12 MAX_WIDTH := 4 注释自标「产出约束·宽度=分叉生长」
game/core/action_economy.gd:14 CHARGE_LAYER_CAP := 3 注释自标「机制结构常量,非玩法表值」
game/core/board_data.gd:9 SPAWN_AREA_CELLS := 9 被 data/schemas/board_gen_table.gd:77/106/107 反向引用参与表校验——core 常量成了 data 侧校验的输入
game/core/node_map_generator.gd:83-94 层深下限 6、出口数域 [1,3]、岔口去路域 2/3 与 level_gen_params.gd 的域校验平行,两份域定义

3.2 sim 与 core 平行实现(四组)

game/sim/ 15 件里 10 件是纯驱动器/采集器(调用 core,不重算规则),但有四组平行实现,其中两组直接导致「模拟读数 ≠ 游戏真实数值」。

组 core 侧 sim 侧 后果
① 扫雷推理引擎 board_generator.gd:175/204/217/234/249/265/286(measure_inferability 族,输入含 safe_set oracle) auto_player.gd:114/154/181/188(_deduce 族,输入 no-peek,且不做 0 格连锁算子) 两边可推理率/卡死率不可直接换算。auto_player.gd:80-83 注释自认口径差异
② 伤害掷点期望 damage_math.gd + damage_controller.gd 兑付管线 damage_probe.gd:196-201 自建 base_factor/rolled_base/floor 取整顺序,只在末步复用 pool_damage 探针的 ✓/✗ 比对基于自行重建的中间量
③ 档位排序与驱动循环 treasure_item_table.gd:44 的 TIER_RANK;sim/battle_driver.gd:17 自称「驱动循环单点」 level_autoplay.gd:300-311 另写一份档位排序;level_autoplay.gd:521-575 另写一份驱动循环(守卫阈值还不同:多出 round_guard=60、rejects<3) 被声明为单点的东西存在第二份实现
④ 伪造表喂 core 数值单一事实源 = data/tables/*.tres calibrate_boards.gd:14-19 与 experiment_density.gd:61-66 用 FakeDB 伪造 board_gen 行喂 core 生成器 校准类读数绕开 SSOT(实验用途可理解,但无闸约束其扩散)

四、P1 — 守卫覆盖缺口

4.1 RNG 单点纪律在 core 之外失守,且无闸

core 内干净,绕过点全在 core 之外:

层 位置 形态 是否被闸扫到
presentation main.gd:914 randi() 建种子,行内标 rng-seed-exempt 扫到但被豁免标记排除

上表 presentation 行的处置(2026-11-03):零动作、维持现状。该处在产品码扫描面内,已被行内注记在册豁免,且豁免通道的限定用途已由 code-conventions §4 第 10 条写死=非玩法 RNG 消费面的引擎熵(组合根建种子不进玩法封闭流),与本节「三目录定种自建属合法测量口径」同一条理,不需再动。 | probe | ui_click_probe.gd:20 等 8 处 | RandomNumberGenerator.new() | 不扫 | | sim | calibrate_boards.gd:54、experiment_density.gd:27、damage_probe.gd:274、level_autoplay.gd:388 | 自建 RNG + 显式定种 | 不扫 | | tests | 3 处测试夹具 | 自建 RNG | 不扫 |

全部绕过点均显式定种、无 randomize()(全库零命中),确定性尚存;问题在于没有任何闸防它扩散——S1/S2 扫描面只有 DIR_CORE + DIR_PRES(static_scan.sh:20-21, 88-91)。

2026-11-03 裁(不扩扫描面,改为写说明):

  • 裁决:S1/S2 扫描面保持产品码两目录,不扩 sim/probe/tests。这三目录自建且显式定种的随机源是合法测量口径(改前改后读数要用同种子对拍,属全项目测量前提),把它们判进「玩法代码禁自建 RNG」的闸面,等于给每处合法用法挂 rng-seed-exempt 注记、只拦得住新增——不值其成本。落文=design/engineering/code-conventions.md §4 新增第 13 条(按来源分档:三目录各由哪条运行期通道承接、允许自建的条件是不定种禁止、以及该禁止目前无机器闸只由文字纪律+批末独立验收审计人工评审承载),架构文档 S 表 S1 行加同口径注。
  • 读数订正(2026-11-03 复核):①自建点由本节记的「8 处」降到7 处——game/sim/experiment_density.gd 已随迭代 50 卡片 T9 删除(sim 现 3 处:calibrate_boards/damage_probe/level_autoplay;probe 1 处 ui_click_probe;tests 3 处 board_gen_reward/player_copy_sweep/theme_projection)。②「无 randomize()」要加限定:randomize() 在 game/ 字面命中 2 处,两处均在注释里(core/rng_service.gd:3、presentation/main.gd:756),实际调用零命中,结论不变。③按 S1 原判据(裸 randi()/randf()/randf_range())扫这三目录,非注释命中 0 处。

4.2 静态闸扫描面结构性缺口

game/tests/static_scan.sh 的 S1–S13 扫描面实况:

闸 扫描面 缺口
S1/S2(RNG 单点) core + presentation sim / probe / tests 不扫
S3(core 表加载单点) core —
S4(core 零引擎 UI 依赖) core —
S5(core 禁裸引 Autoload) core —
S6(core 信号禁内联 lambda) core —
S7(B1 编排唯一性) core 不管私有成员直取面(见 5.1)
S8(结算路径禁 await) 9 文件显式清单 新增结算文件忘登记=静默不扫;缺位自检只防删改不防增
S9(类型闸) core + data + presentation sim / probe / tests 不扫
S13(gdstyle 质量闸) core + data + presentation 同上
S11(术语禁用词)/S12(旧件残留) game/ 全域 无缺口

净效果:sim / probe / tests 三层除 S11/S12 外,零类型闸、零质量闸、零 RNG 闸、零 await 闸。

2026-11-03 裁(三面不扩;两处机制修与两处本轮新查):

  • S9/S10/S13 不扩到三层(裁决)。2026-11-03 只读数实跑(三个静态扫描脚本对三层,未修文件、未写基线)给出现存总量 ≈2162 处:S9 类型 1070(sim 158/probe 130/tests 782,其中无类型容器 859)、S10 文件头 117、S13 质量 975(其中「禁调试打印」274+「循环内 await」70——这两类在测试与探针码里是功能需要,不是债)。产品码面 S9/S10 现行归零,扩面即把「归零」这一执法前提换成 1187 项存量红;为三层另建欠账基线会把账从 1 份变 3 份。落文=code-conventions §4 第 13 条写明适用域止于产品码并给出三目录的运行期承接通道。
  • 读数是:S8 现行 14 文件显式清单(static_scan.sh:317),非本节所记 9 文件;同口径 14 文件清单在 S7 另抄一份(:361),两份靠人工同步;绿文案仍报「B1 文件集 10 个 .gd」(:337)与头注 :311 的「共 14 文件」自相矛盾;S8 自检只防「清单内文件缺位」(:319-324)不防「该进的没进」——纯目录域方案已证伪:装板/授予/效果端口/掷格四件结算码在 game/core 根下而非 settlement/ 目录内。
  • S7 行缺口的尾巴(本表 §4.2 里唯一指向 §五的一格):该行写「S7 不管私有成员直取面(见 5.1)」。§四 对 S7 只裁它自己的扫描面与清单形态——扫描面维持 $DIR_CORE、豁免名单与 S8 并成单点 B1_SET(已落地);私有成员直取面不在本节处置范围:它无静态判据可造(GDScript 无编译期访问检查,误报面大),且真要做是改 core/settlement/ 的协作契约=游戏代码=需求改动通道,归 §5.1 与待办清单「架构审查余项」条目之后的讨论段。本节对此格的结论=缺口在册、移交 §5.1,不在 §四 闭合。
  • 本轮新查两处(审计未列):①S9/S10 无扫描面空转自检(tools/audit_type_hints.py:82-83、tools/audit_file_headers.py:64-65 目录不存在即静默 PASS),违背本文「三层承载与判定原则」的零命中自检要求与脚本前言自立的防空转纪律(static_scan.sh:18-19);②S3 是半闸(命中只打 WARNING、不置 fail,static_scan.sh:110)——但这条不是洞:架构文档 S 表 S3 行早已登记「warning 级——class_name 直引误报需人工复核」,属已在册状态。2026-11-03 裁维持 warning 不升硬(升硬前提是先有可靠的直引误报排除判据,该判据未立)。
  • 待执行清单(2026-11-03 同日执行完毕,凭据见下):
    1. game/tests/static_scan.sh:S8 新增「game/core/settlement/ 实有 .gd ⊆ 清单」反向对账(新段类未登记即红)+S7 的 S7_B1_SET 与 S8_FILES 两份 14 文件抄本合一为单点 B1_SET+绿文案「10 个 .gd」改为派生计数(现打「14 个 .gd+settlement/ 目录域已反向对账」)——已落地;
    2. tools/audit_type_hints.py/tools/audit_file_headers.py:补扫描面空转自检(缺目录或零个 .gd 即红,绿时打印扫描面件数供核)——已落地(负证:把面清单改成不存在目录,两件各返回退出码 1;正证:真实面 158 个 .gd 归零 PASS);
    3. 架构文档 S 表同步——S8 行登记单点与反向对账判据、原「S9/S10 缺自检」偏差句改判为已清偿——已落地(凭据=design/engineering/architecture/architecture.md v1.34)。
  • 验证口径:bash game/tests/static_scan.sh 全量 13 条规则绿、退出码 0;车道=会话内独立 worktree 直改+合回远端 CI(零需求卡片,纯闸件面属工程改动)。§四 P1 至此四条全部闭合。

4.3 S13 豁免常态化

三处豁免全落在体量最大、风险最高的文件上:

豁免对象 豁免内容 后果
core/battle_orchestrator.gd S13 全库单文件最大户,成员数阈值 15 豁免(实测键账 50→38 仍豁免) 豁免后 S13 对它恒不约束,成员数再涨无感知
presentation/main.gd 46 个句柄成员 同上
presentation/tune_sim_controller.gd await 使用 同上

2026-11-03 结案(待裁点⑤已无对象,读数过期):本节所记三处豁免已于 2026-10-31 迭代 44 批后收尾清偿(commit 9eedf896「gdstyle 基线 refresh 收账 16→5 键:消失=main.gd49/orchestrator38+文件长 1035/tune_sim await…五键清偿」)。现行基线只剩 5 条键,全在 adventure_runner/level_runner/board_view(tools/gdstyle_baseline.txt:8-12),判定机制是「基线外新键红、同键数值恶化红、只准因还债下降」(同文件 :5)。零动作,不再叠清偿期限——「只降不升+refresh 骤降/抬升双守卫」已在位,加期限属重复建设。

4.4 四个 core 文件零测试点名

判定口径:文件名与 class_name 在 game/tests/ 全域 grep 均零命中。

文件 行数 职责 风险
core/attune_loadout.gd 117 同调配装件:装备中秘宝件对象集唯一所有者 有状态
core/battle_fx_host.gd 179 效果引擎宿主:fx 事件发射面、事实判定、AC/bonus 累积 有状态且在结算路径上
core/meta_state_store.gd 176 存档内元进度数据件(13 写口 + 6 只读投影) 有状态且在存档路径上
core/slot_store.gd 189 存档槽位文件域件(挂载/激活/建删/摘要窥视) 同上

config_domain_combat / config_domain_run / config_domain_crossrun 三个纯持有容器(零方法)零覆盖属可接受。

低覆盖(仅 1 个测试文件点名)另计:hero_stats、skill_lottery、shop_session、curio_deck。

2026-11-03 裁(定性改判+读数订正为 11 件;落文=规约登记义务,不建闸不补空套件):

  • 定性改判:本节「零测试点名」的风险叙述不成立——四件都有有针对性断言,只是不经文件名的通道:MetaStateStore 经 meta_state. 键散布 14 个测试文件、SlotStore 经 .slots.attach_path/attach_slot_template 在 system_test 与 save_slot_isolation/summary/boot_no_activate 四套件、BattleFxHost 经 fx_host() 在 adventure_feats_test.gd:584-661、AttuneLoadout 经 _loadout.set_attunement 在 feat_vouchers_test.gd:80-83。真缺口是没有「按文件登记覆盖」的惯例,不是没测。
  • 读数订正:按本节同口径(game/tests/**/*.gd 全域 grep basename 与 class_name)复跑,core 现 52 件里零点名是 11 件,不是 4 件。分三档:纯零 6 件(attune_loadout 117 行/slot_store 189 行/config_domain_combat·crossrun·presentation·run 四件 7–12 行纯持有容器);只在闸清单出现 4 件(battle_fx_host 232 行〔本节记 179,已涨〕/reward_roller 245/round_cycle 106/battle_refresh_flow 43);只在能力清单文字出现 1 件(meta_state_store 176)。成因读数:后一档三件全是迭代 44/46/49 的拆件产物——「拆件产新件不登记」是复发模式,不是一次性欠账。
  • 裁否两案:①「立每个 core 件必须被点名一次的覆盖闸」——与本文档族的 test-conventions.md §7「覆盖率不是目标:不引入行覆盖率度量;现行补洞=能力清单覆盖域表+人工判定」正面冲突,且会把为点名而点名的空套件逼出来;②「给 11 件补点名套件」——同既有断言重复,属为登记而写码。
  • 落文:design/engineering/test-conventions.md §8.3 新增「新增 core 件的覆盖登记义务」(新 core 件要么被 tests 面点名、要么在能力行申报「经宿主链覆盖(宿主=<件>)」,两者都无=收尾核对补登;明示本条不是覆盖率要求),design/engineering/process-conventions.md §3 第 6 条加承接指向(拆件套的覆盖登记归该义务,核对动作归收尾提交)。
  • 落笔约束:能力清单 game/tests/README.md 本体归写卡段维护、实现批禁写(test-conventions.md §8.3),所以申报行由写卡段入表,本轮规约文字不代写清单内容。
  • 「低覆盖另计四件」的处置(本本节最后一句未落笔项):hero_stats/skill_lottery/shop_session/curio_deck 四件零动作。判据:低覆盖≠无覆盖,四件在能力清单各有代表用例承接(现值:hero_stats→hero_ledger_test 直构断言 rest_heal;skill_lottery 已由审计时点的 1 件升到 2 件——round_flow_skill_pool_test:798/830 与 trigger_cond_test:85/90;shop_session→level_shop_economy_test 经 LevelRunner.shop. 真实入口;curio_deck→pool_case_d 经 AdventureRunner),已满足新落的 §8.3 登记义务(点名或申报经宿主链覆盖二者有一即可)。要提覆盖得由写卡段在后续批次按能力行增补,不属本节闸件范围。

五、P2 — 封装与漂移

5.1 settlement 五段类直读写编排器私有成员

core/settlement/ 五段类作为「提取的方法对象」,直接读写主编排器的下划线私有成员 20+ 处:

  • combat_segment.gd:34/37 写 oc._damage.inject[...];:52/53/58/77/78/80/89/91 读 oc._enemy_system.*;:123 调 oc._damage.flush()
  • grant_segment.gd:96/121/151/178/229/289/333 调 oc._damage.open_ticket(...)
  • aura_segment.gd:15/16 调 oc._emit_composition_effects(...);decay_segment.gd:15 调 oc._status_effects.decay_round()

GDScript 无编译期访问检查,私有成员改名不会有任何闸报错,只会静默断裂。S7 只管 B2/B3/B4 对外 API 符号收敛面,不管这个。

5.2 架构文档与代码漂移

文档位置 文档写的 盘上实况
architecture.md:110 core/hero_ledger.gd「已实装」 该文件不存在;已拆为 hero_stats.gd / gain_journal.gd / gp_wallet.gd / refresh_bank.gd 四件。tests/unit/core/hero_ledger_test.gd:171 显式断言 not FileAccess.file_exists("res://core/hero_ledger.gd"),即代码层已把它当回归禁区
architecture.md:135 battle_orchestrator 1313 行 / 50 成员 实际 1034 行(拆件后未回写)
architecture.md EC8 节 数据配置热重载能力(set_reload_gate 保护 reload()) ConfigDb.reload() 全仓零调用方;且因走 load() 命中引擎资源缓存,即便调用也拿不到磁盘新值。门被 battle_orchestrator.gd:295/861 真实开合,但门后入口是死的

5.3 class_name 级双向依赖

core/config_db.gd → data/schemas/board_gen_table.gd(持有 BoardGenTable 实例)→ core/board_data.gd:9(取 SPAWN_AREA_CELLS)形成跨目录回边。双方均走 class_name 全局引用、未走 preload,不产生解析期死锁,但构成架构层面双向耦合。

同族:core/node_map_generator.gd:10 与 data/schemas/level_table.gd 各持一份 NODE_TYPES 词表(内容同、顺序不同)。

5.4 Autoload 形态不一致

四个 Autoload 里 MetaProgression 是唯一用 get_node("/root/...") 取依赖(meta_progression.gd:26/28)、唯一跨 Autoload 直调、唯一持 Node 引用的;另三个零交叉引用。注释说明是为绕 --script 模式 parse error,但与另外三个的构造注入形态不一致,且隐含 Autoload 加载顺序依赖(ConfigDB 须先 ready)。


六、待裁点

以下均需用户裁定,Agent 不代裁:

2026-11-03 状态:①②③ 已裁、已写卡、已随迭代 50 三卡合回(凭据=reports/处置-架构审查3.1+3.2整改-2026-11-02.md 与合并提交 8d3a12ec);④⑤⑥ 已裁,裁决、读数订正与待执行清单见 §四 的 4.1/4.2/4.3/4.4 各节「2026-11-03」标注;⑦ 未处置——属 §五 P2,讨论段未开工,因此本报告整体尚未闭合。

  1. A 类硬编码 18 处怎么修——按改动四类归属,其中 core/ 与 presentation/ 的玩法数值入表属需求改动(写卡 + 编排),sim/ 两处模拟口径常量属工程改动。两类不能混一批。
  2. B 类结构常量要不要入表——MAX_WIDTH / CHARGE_LAYER_CAP / SPAWN_AREA_CELLS / node_map_generator 的域字面量四组,代码自标「非玩法表值」,但 SPAWN_AREA_CELLS 已被 data 侧校验反向引用,是否算玩法数值需裁。
  3. sim 平行实现的处置口径——是收敛(sim 调 core 的推理与掷点)还是承认双口径并显式登记(避免读数混用)。四组里①②影响数值验证可信度,③④影响可维护性。
  4. 闸面缺口补不补——S1/S2/S9/S13 是否把 sim 纳入扫描面;S8 是否改成目录域而非 9 文件显式清单。
  5. S13 三处豁免的存废——豁免已常态化到最大户文件上,是收回还是登记为长期例外。
  6. 零测试点名的 4 个 core 文件——补测试,还是登记豁免在册。
  7. 文档漂移三处——architecture.md 的 HeroLedger 登记行、battle_orchestrator 行数、EC8 热重载门表述,是否现在就按 doc-design 落回(纯文档面,主区直改)。

七、取证口径备注

  • 全程只读,未跑测试、未跑引擎、未跑闸(测试两入口铁规)。
  • 3.1 表 A 类 18 处中,#1 #2 #3 #4 #5 #6 #7 #8 #9 #10 #13 #14 #15 #17 逐条 sed 取原文核过;其余按同一 grep 口径判定。
  • 「零测试点名」判定词 = 文件 basename 与 class_name 全称,检索面 game/tests/**/*.gd;被当作类型间接引用与有针对性断言已分开计数。
  • static_scan.sh 扫描面结论来自脚本自身变量定义(DIR_CORE / DIR_PRES / SCAN_DIRS)与 S8 的 S8_FILES 显式清单,非推测。