diff --git a/design/engineering/architecture/architecture.md b/design/engineering/architecture/architecture.md index 103be78d..77eb8852 100644 --- a/design/engineering/architecture/architecture.md +++ b/design/engineering/architecture/architecture.md @@ -2,8 +2,8 @@ ## 文档状态 -- 版本:1.32 -- 最近更新:2026-11-03(迭代 50 批后收尾随动——排雷规则件 preview_reveal 只读预览口登记、天赋树 tree_rules 参数字典 API 换代;沿革查 git) +- 版本:1.33 +- 最近更新:2026-11-03(架构审查 P1 余项裁决落文——静态扫描域标题补齐至 S13 并登记 S11/S12/S13 三行、S1/S2 与 S3 行加适用域与维持 warning 的裁定注、S9/S10 缺空面自检登记为已知偏差;上一版 1.32=迭代 50 批后收尾随动(preview_reveal 只读预览口登记、天赋树 tree_rules 参数字典 API 换代);沿革查 git) - 引擎:Godot 4.7.2-stable(GDScript 单语言;2026-09-07 锁定) - 评审模式:solo(`review-mode.txt`,2026-09-12 用户拍板——TD/LP 门禁按 solo 跳过,用户授权架构产出自主推进、迭代期回调) - 覆盖 GDD:现行全集(根索引=`design/gdd/02-系统清单.md`,文档树构成以根索引为准) @@ -279,22 +279,24 @@ 背景事实(run_smoke 头注在案):GDScript 运行时脚本错误不改进程退出码、不计入冒烟失败数、且静默中断所在函数剩余断言——2026-09-19 状态记录 83 实证「309 项 0 失败」实为断言未跑全。这是 SCRIPT ERROR 扫描必须存在于判定层的原因。 -### 静态扫描域 S1–S8 承接清单 +### 静态扫描域 S1–S13 承接清单 静态扫描域规则(2026-09-12 立,沿革见 git commit log;下表为现行事实登记): | # | 规则 | 状态 | |---|---|---| -| S1 | 玩法代码禁 `randomize()`、自建 `RandomNumberGenerator`(D2 Rule 5) | **在位**(硬失败;扫描面 game/core + game/presentation) | +| S1 | 玩法代码禁 `randomize()`、自建 `RandomNumberGenerator`(D2 Rule 5) | **在位**(硬失败;扫描面 game/core + game/presentation)。非产品码三目录(`game/tests`/`game/probe`/`game/sim`)不进本闸与 S2——它们自建且**显式定种**的随机源是合法测量口径(同种子对拍改前改后读数),禁的是不定种形态;适用域分档与无机器闸的理由见 code-conventions §4 第 13 条(2026-11-03 架构审查 P1 余项裁:不扩扫描面,人工评审承载) | | S2 | 禁全局随机函数 `randi()` / `randf()` / `randf_range()`——全局 RNG 绕开 RngService(specialist 补登) | **在位**(与 S1 同段硬失败;实例方法 `.randi()` 排除、`rng-seed-exempt` 豁免注记在案) | -| S3 | core/ 禁 ConfigDB 外 data 表加载(`load(` / `preload(` / `ResourceLoader.load`;schema class_name 直引豁免)(D2 Rule 2) | **在位**(warning 级——class_name 直引误报需人工复核;路径已由裸 `core` 修正为 `game/core`,此前恒零命中静默空转;豁免 config_db.gd 自身=数值单一事实源的正主) | +| S3 | core/ 禁 ConfigDB 外 data 表加载(`load(` / `preload(` / `ResourceLoader.load`;schema class_name 直引豁免)(D2 Rule 2) | **在位**(warning 级——class_name 直引误报需人工复核;路径已由裸 `core` 修正为 `game/core`,此前恒零命中静默空转;豁免 config_db.gd 自身=数值单一事实源的正主)。2026-11-03 架构审查 P1 余项裁**维持 warning 级不升硬**:升硬的前提是先有可靠的直引误报排除判据,该判据未立;本行状态即事实源,禁在别处另列 | | S4 | core/ 禁 `extends Control/Node2D`、禁 `.tscn` preload(D2 Rule 7) | **在位**(硬失败) | | S5 | core/ 禁裸引用 autoload 全局标识符(`ConfigDB` / `RngService` 直接写 = --script 模式 parse error)——构造注入 only(specialist 升格) | **在位**(硬失败;形态=标识符后紧跟 `.` 的成员访问,排除注释行与字符串字面量) | | S6 | core↔core 信号连接只许方法 Callable(禁 lambda 捕获 self);发射者禁持有订阅者反向引用 | **在位**(2026-10-25 落闸:内联 lambda 禁令机器闸——同行与跨行两形态、豁免注记 `s6-signal-exempt`、盘面零存量;「发射者禁反向引用」句静态判据不成熟,归人工评审面承接、不造弱判据) | | S7 | B1 编排唯一性:B2/B3/B4 API 符号命中文件 ⊆ B1 文件集;A2/B3/B4 零相互直调(B1 AC-43) | **在位**(2026-10-25 落闸:符号清单×B1 域文件集,族内自调用豁免、豁免注记 `s7-b1-exempt`、缺位自检;全符号形态盘面零存量) | | S8 | 结算路径 `await` 零命中(B1 结算/编排文件集);字面量扫描 = warning 级 + 人工三要素复核(D2 AC-14 口径) | **在位**(2026-10-25 落闸:B1 域文件集 await 零命中,文件集缺位自检、排除注释与字符串;盘面零存量。本行后半句「字面量扫描=warning 级+人工三要素复核」为独立子项、仍归人工面) | -域外扩充两件(均硬失败在位):**S9** 类型闸(`tools/audit_type_hints.py`,迭代 27 T5——产品码无类型容器/有值返回缺类型/参数缺类型);**S10** 文件头闸(`tools/audit_file_headers.py`——头注 ≤8 行 + 日期/变更叙事黑名单)。 +域外扩充五件(S11/S12/S13 自 2026-09-29 起陆续落闸,本表原先只登记到 S10,2026-11-03 补齐登记面):**S9** 类型闸(`tools/audit_type_hints.py`,迭代 27 T5——产品码无类型容器/有值返回缺类型/参数缺类型;扫描面=产品码三目录);**S10** 文件头闸(`tools/audit_file_headers.py`——头注 `##` 载体+日期/变更叙事黑名单;扫描面=产品码三目录);**S11** 代码注释禁用词闸(扫描面=`game/` 全域 `.gd`/`.tres`/`.md`/`.json`/`.sh`,词表单点取 `design/gdd/术语表.md`);**S12** 效果引擎无状态化旧件零残留闸(扫描面=`game/` 全域 `.gd`/`.tres`,旧符号与旧 id 字面清单为脚本字面值);**S13** 第三方质量规则闸(`tools/gdstyle_gate.py`,钉 gdstyle v0.4.0;扫描面=产品码三目录,存量以 `tools/gdstyle_baseline.txt` 欠账簿登记,判定=基线外新键红、同键数值恶化红)。 + +S11/S12 扫描面覆盖全域,故 sim/probe/tests 的术语与旧件面**在册**;其余十一闸(S1–S10、S13)扫描面止于产品码,非产品码三目录不受约束——分档理由与各目录的运行期承接通道见 code-conventions §4 第 13 条。**防空转自检现行状态**(本文「三层承载与判定原则」要求扫描面为空即判红):S1–S8 与 S11/S12/S13 各自带空面或缺位自检;**S9/S10 现行缺该自检**(`tools/audit_type_hints.py` 与 `tools/audit_file_headers.py` 遇目录不存在时静默零命中并 PASS),属已知偏差,修复归工程改动批、登记在 `reports/审计-全库架构审查-2026-10-29.md` §4.2 标注处。 ### 三层承载与判定原则 diff --git a/design/engineering/code-conventions.md b/design/engineering/code-conventions.md index 7f7f07a9..db31143a 100644 --- a/design/engineering/code-conventions.md +++ b/design/engineering/code-conventions.md @@ -66,12 +66,13 @@ 4. **lambda 捕获循环变量按创建时值**——循环内先落地局部变量再捕获,或用 `bind`。 5. **重命名脚本必须同步 `.uid` 文件**;新增 `class_name` 后必须跑一次编辑器扫描刷新全局类缓存,否则 `--headless --script` 模式解析失败。 6. **`print` 格式占位符与实参类型必须匹配**(`%d` 配 String = 静默输出字面量)。 -7. **语言纪律已机器化为 S9 类型闸**——`tools/audit_type_hints.py`,执行载体=静态扫描域 S9(`game/tests/static_scan.sh`),退出码 0=归零。扫描面=产品码(`game/core`+`game/data`+`game/presentation`;probe/sim/tests 不在扫描面——测量面容器直构是既有惯例)。三规则:R1 无类型容器(显式非参数化 `Dictionary`/`Array` 注解)/R2 有值返回缺返回类型(纯副作用缺 `-> void` 属写法面不入闸)/R3 参数缺类型(`_init` 豁免——构造注入面形态自由)。 +7. **语言纪律已机器化为 S9 类型闸**——`tools/audit_type_hints.py`,执行载体=静态扫描域 S9(`game/tests/static_scan.sh`),退出码 0=归零。扫描面=产品码三目录(`game/core`+`game/data`+`game/presentation`);非产品码三目录的适用域分档见本节第 13 条。三规则:R1 无类型容器(显式非参数化 `Dictionary`/`Array` 注解)/R2 有值返回缺返回类型(纯副作用缺 `-> void` 属写法面不入闸)/R3 参数缺类型(`_init` 豁免——构造注入面形态自由)。 8. **`:= {}` 推断形态不算债**——`var x := {}` 类赋值推断属类型推断合法面,不入 R1 扫描;只有显式写的非参数化容器注解才算无类型容器。 9. **行级白名单通道 `# type-hint: ignore`**——豁免该行不入 S9;豁免理由必须随行注明(现行例:`board_generator` 四函数的 db 参鸭子型——typed 参拒冒烟夹具 `_BoardRowStub` 注入)。 -10. **`# rng-seed-exempt` 标记豁免通道**——S1/S2 随机函数扫描对该行豁免;限定用途=非玩法 RNG 消费面的引擎熵(现行例:组合根种子编辑框空态取 `randi()`——建种子不进玩法封闭流)。 +10. **`# rng-seed-exempt` 标记豁免通道**——S1/S2 随机函数扫描对该行豁免;限定用途=非玩法 RNG 消费面的引擎熵(现行例:组合根种子编辑框空态取 `randi()`——建种子不进玩法封闭流);非产品码三目录自建随机源的定种要求见第 13 条。 11. **`--script` 模式禁裸 autoload 标识符**——`ConfigDB`/`RngService` 等 autoload 名在 `--headless --script` 模式编译器不解析(parse error);产品码与测试夹具一律经节点路径取用(`get_node("/root/…")`/`AUTOLOAD_PATH_*` 常量);静态扫描域 S5 硬失败承载在位。 12. **Variant 参数化现行口径**——账本类字典/数组标注 `Dictionary[Variant, Variant]`/`Array[Variant]` 即合格(满足 R1);元素类型精化列后续事项、不入硬纪律,口径变更须用户裁决后续批次另行写入。 +13. **静态扫描适用域按来源分档(2026-11-03 架构审查 P1 余项裁)**——S 系静态扫描(S1–S13)的扫描面一律止于产品码三目录,`game/tests`/`game/probe`/`game/sim` 不进任何 S 系扫描面;这三目录的可靠性由运行期通道承接,各通道是:`game/tests`=闸 00/01/02(冒烟·单元与集成·系统测试)、`game/probe`=闸 03/04/05(场景探针与渲染 golden;同目录内 `type_glow_shot_probe` 是人工取证件、`probe_ui_util` 是探针共用面,两者不入闸)、`game/sim`=不入 CI,属用户手动发起的调参与数值测量批量。三目录**允许**自建 `RandomNumberGenerator`,条件=**必须显式定种**(改前改后读数要用同种子对拍,这是全项目测量口径);三目录真正禁止的形态是不定种随机——`randomize()` 与全局 `randi()`/`randf()`/`randf_range()`,一旦命中那次运行结果不可复现,读数与取证一并失效。这条对三目录的部分目前**无机器闸**(S1/S2 扫描面不含它们):扩面需给每处合法定种挂 `rng-seed-exempt` 注记、只拦得住新增,2026-11-03 用户裁不扩,改由本条文字+批末独立验收审计的人工评审承载。术语口径:`tools/run_all_gates.sh` 里的「测量面」指 `game/tests`+`game/sim`(影响面选闸用语,`game/probe` 不在其中——改探针必须跑 03/05),与本条分档无关;本文不再用「测量面」统称这三个目录。 --- diff --git a/design/engineering/process-conventions.md b/design/engineering/process-conventions.md index 72fe5a13..a5ce00c5 100644 --- a/design/engineering/process-conventions.md +++ b/design/engineering/process-conventions.md @@ -44,7 +44,7 @@ 5. **涉数值改动先采改前读数**——与改后同随机种子配对比较并写明逐项比对口径;无数值改动禁跑模拟 **实施** -6. **新功能必配新测试**——新增玩法/机制必须配套新测试套件进 `tests/run_all`;没有对应测试的变更不许合并;并按 test-conventions §8 挂进改动—验收对照表,没有对照表行的行为改动同样不许合并 +6. **新功能必配新测试**——新增玩法/机制必须配套新测试套件进 `tests/run_all`;没有对应测试的变更不许合并;并按 test-conventions §8 挂进改动—验收对照表,没有对照表行的行为改动同样不许合并。拆件/重构产出的新 core 件不属新增玩法,由 test-conventions §8.3「新增 core 件的覆盖登记义务」承接(被 tests 面点名,或在能力行申报「经宿主链覆盖」),核对动作归本清单第 10 条的收尾提交 7. **验收改动先行声明**——验收变化(基线换代/探针增改/旧断言改判)预先写进需求卡片,禁事后补 **完成** diff --git a/design/engineering/test-conventions.md b/design/engineering/test-conventions.md index 5d5b95d8..f9727317 100644 --- a/design/engineering/test-conventions.md +++ b/design/engineering/test-conventions.md @@ -99,6 +99,8 @@ **能力清单维护锚(2026-10-29 用户裁改版定稿)**:`game/tests/README.md`「能力清单」是**实现指导+阅读导航+义务声明**——只宣布「要验证什么」,不记「是否已验证/是否跑过」;落地账归现行验收闭合链(改动—验收对照表逐条挂断言+合回前独立验收审计),本清单不承载验证状态。表为四列:能力|系统|真实入口|代表用例(`文件:函数`)。**维护归写卡段,当场入表**:写需求卡片时,本批新增能力当场写入能力行——真实入口取自设计文档已定的入口,代表用例=卡里定死的计划测试(`文件:函数`);受影响存量行(入口/用例名变更)同批更新;能力退役删行。**实现照单落名**:测试函数名以清单为唯一依据,名实不符=卡片没写清=停卡退回。**收尾核对**:批末收尾只核对表上名字与实际落地一致(改名则回表),不刷任何批次字段;实现批禁写该文件的现行红线不变(process-conventions §3 第 11 条),核对义务归收尾提交。三层模型见 §8.9。改动—验收对照表纪律不变:新增或改写的每条断言仍须挂一行(上文「测试侧」);断言改判仍受 §8.4 真实入口口径约束。 +**新增 core 件的覆盖登记义务(2026-11-03 架构审查 P1 余项裁)**:拆件或重构产出的新 core 文件不触发 process-conventions §3 第 6 条「新功能必配新测试」(那条只管新增玩法/机制),因此单由本条承接——新 core 件要么被 `game/tests/` 某套件按文件名或 `class_name` 点名,要么在承接它的能力行「代表用例」里申报「经宿主链覆盖(宿主=<件>)」;两者都无=批末收尾核对时补登。本条**不是覆盖率要求**,与 §7「覆盖率不是目标」同轨:登记的是能力义务的归属,不做文件计数——「每个 core 件必须被点名一次」的机器闸已裁否(它逼出为点名而点名的空套件,且与 §7 正面冲突)。落笔面沿用现行分工:申报行由写卡段入能力清单(实现批禁写该文件),核对归批末收尾提交。 + ### 8.4 真实入口断言(验收闭合的主判据) - **唯一口径(2026-10-24/2026-10-28 用户两裁)**:每个需求点与每个行为改动的验收=一条从真实入口进入的断言,可 grep 定位、在当轮真实跑批中执行并通过。**禁变异类测试**(把生产码或数据表改成错值看断言抓不抓得到);**禁撤销类取证**(回退本批改动或该 hunk 看断言红不红)——两者都是人为制造红,属伪造证据,一律禁止。 diff --git a/reports/审计-全库架构审查-2026-10-29.md b/reports/审计-全库架构审查-2026-10-29.md index d8964eb8..55db487b 100644 --- a/reports/审计-全库架构审查-2026-10-29.md +++ b/reports/审计-全库架构审查-2026-10-29.md @@ -3,6 +3,7 @@ > **性质**:设计讨论段过程稿(审计读数)。`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 四条已裁,逐条裁决与读数订正见各节标注;§五 P2 四项**未处置**、§六待裁点⑦未落文——**本报告禁退役**(「吸收即死」判据未满足:结论未全吸收进权威文档)。 --- @@ -108,6 +109,10 @@ core 内干净,绕过点全在 core 之外: 全部绕过点均显式定种、无 `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 扫描面实况: @@ -127,6 +132,15 @@ core 内干净,绕过点全在 core 之外: 净效果:**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/` 目录内。 +- **本轮新查两处**(审计未列):①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 不升硬**(升硬前提是先有可靠的直引误报排除判据,该判据未立)。 +- **待执行清单(登记处=本节;车道=工程改动批,用户发令走独立 worktree 直改+合回 CI,零需求卡片;估 <0.5 工作日)**: + 1. `game/tests/static_scan.sh`:S8 新增「`game/core/settlement/` 实有文件 ⊆ 清单」反向对账(新段类未登记即红),并把 S7 的 `S7_B1_SET` 与 `S8_FILES` 两份抄本合一为单点变量,订正 `:337` 的「10 个 .gd」文案; + 2. `tools/audit_type_hints.py`/`tools/audit_file_headers.py`:补扫描面空转自检(目录缺失或 `.gd` 数为零即红,口径仿 `static_scan.sh:27-36`); + 3. 上述两条落地后,架构文档 S 表 S8 行与「S9/S10 缺空面自检」的偏差登记句随同批改写(禁文档跑在码前,本轮只登记现状)。 + ### 4.3 S13 豁免常态化 三处豁免全落在体量最大、风险最高的文件上: @@ -137,6 +151,8 @@ core 内干净,绕过点全在 core 之外: | `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 均零命中。 @@ -152,6 +168,13 @@ core 内干净,绕过点全在 core 之外: 低覆盖(仅 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),所以申报行由写卡段入表,本轮规约文字不代写清单内容。 + --- ## 五、P2 — 封装与漂移 @@ -190,6 +213,8 @@ GDScript 无编译期访问检查,私有成员改名不会有任何闸报错 以下均需用户裁定,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 的推理与掷点)还是承认双口径并显式登记(避免读数混用)。四组里①②影响数值验证可信度,③④影响可维护性。