iter52-卡4:迭代52卡④(封印印记法阵化): 着色器参数化绘制换代(环带+十字+环外光圈,半径夹cell_px/2,ui_kit六常量含SEAL_HALO_FRAC补注入源)+seal_mark_layer子件+CellUnit seal_on/fog联动+棋盘侧贴图路径三处退役(seal_mark.png只余战末蜡封)+board_shot_probe封印取证(三关环径0.826全落±1px,英雄格中心非黑); 含产出物三份/审计报告/master归并两笔/收尾笔; 验收档中; 验收审计总判定通过
This commit is contained in:
1 parent
67024cb9ec
commit
122cdeb3d8
28 files changed
+581
-133
No files matched your search
@@ -53,12 +53,13 @@
|
||||
|
||||
## 回答风格规则(只管对话输出;文档写作归 doc-conventions §2–§4)
|
||||
|
||||
### 四条核心原则(按优先级)
|
||||
### 核心原则(按优先级)
|
||||
|
||||
1. **用词封闭**:对话里可用的词=日常汉语+用户先用过的+当场展开过的。展开=先完整描述再给短说法,描述交代三样:指什么对象、怎么运作、带来什么后果。短说法只认两个来源:用户用过的直接跟用;自己提议的必须等用户回话里用过一次才成立。项目文档定过名的词不豁免,对话里首次出现照样先展开。同物同名:同一东西从头到尾一个叫法,不换词;一个词不指两个东西。起名的固定顺序=先描述、再命名、后沿用,禁止颠倒。
|
||||
2. **判断挂依据**:判断=「X 是/不是/造成了/应该」类陈述;每个判断后面必须跟依据。依据只认三种:仓库文件+行号或逐字引用(给行号就必须真读过那几行);本对话的消息号或原话;外部链接。三种都拿不出的判断必须当场标「这是推测」;说不出依据就答「不知道/没查过」,禁止编造。答复形状=结论行→依据清单→细节。
|
||||
3. **简洁**:同一意思只说一遍;能用一句不说两句。硬约束、数字、前提条件不参与压缩;信息完整与简洁冲突时保信息。
|
||||
4. **多角度**:介绍一个物体、一个概念、一个问题,多角度讲清楚;每角度信息点 ≤3 个,禁止违背第 3 条。
|
||||
5. **闸况呈报用闸名**:对话里报验证闸的跑批结果一律用闸名(冒烟测试/系统测试/单元与集成测试/场景探针/渲染闸等),不裸报编号。
|
||||
|
||||
### 简洁细则
|
||||
|
||||
@@ -106,7 +107,7 @@
|
||||
- 车道铁律(2026-10-31 用户裁恢复)——主工作区只作合并落点,一切开发/设计改动走独立 worktree:`git worktree add ../g-plan2-<任务名> -b <任务分支>`(建区即跑 `tools/setup_worktree_userdir.sh`),收口=冻结→件核→并 master→重塑→主区 `git merge --no-ff`→删区(合回即删,2026-09-19 原裁),CI 红不回滚合并——新开修复 worktree(`fix-<任务名>` 分支,免重塑免数卡)修复合回追绿;会话单区(2026-11-04 用户裁)——同一时刻每会话至多一个 worktree 在役,同会话追加事项并入在役区、只做一次合入(一次 CI),合回后用户再发令=新回合另开区,迭代实现批独占回合(细则见 process-conventions §1 第 5 条);主区唯一合法写动作=合并,agent 侧由 worktree-guard 拦主区 Edit/Write 与非 merge 提交;豁免面仅 `.zcode/`、`.qoder/`(不入 git,主区直改);commit 点零钩子检查(pre-commit 直改闸已退役),全量验证归合回后远端 CI(post-merge 钩子推送触发,见「运行与验证」首条);`--no-verify` 仅属用户,agent 禁用(细则见 process-conventions §1)
|
||||
- **仓库根禁止设会话状态文件**(`active.md` 已废除)——现状看 roadmap「当前位」,待办看待办清单,过程看 git 提交信息,产出物看 `reports/`;任何文档禁止另设「当前状态快照」节,两处记同一件事必然漂移(细则见 doc-conventions 第 10 节)
|
||||
- 测试执行两入口铁规——只有迭代 loop 开发与用户点名两个触发入口;其余会话零测试,需测试支撑先请示并注明未跑测
|
||||
- 合回后验证 = 远端 CI 闸全绿(唯一强制验证点;唯一入口、唯一闸清单、唯一域划分与选闸算法仍只在 `tools/run_all_gates.sh`,禁在文档另列;触发与追绿语义见「运行与验证」首条与 process-conventions §1)。开发期手动跑批按需选档(`--code` 关联档选测——02 跑「卡片申报 ∪ diff 推导」并集套件、三件保险恒跑、横切面回落全量——算法只在闸脚本内定义),手动跑不构成验收;全量回归由用户自发发起。远端按改动域分流:文档面批走文档域秒级闸,代码面批走两域全量(分流算法单点=`tools/ci/domain_route.sh`)
|
||||
- 合回后验证 = 远端 CI 闸全绿(唯一强制验证点;唯一入口、唯一闸清单、唯一域划分与选闸算法仍只在 `tools/run_all_gates.sh`,禁在文档另列;触发与追绿语义见「运行与验证」首条与 process-conventions §1)。开发期手动跑批按需选档(`--code` 关联档选测——单元与集成测试跑「卡片申报 ∪ diff 推导」并集套件、三件保险恒跑、横切面回落全量——算法只在闸脚本内定义),手动跑不构成验收;全量回归由用户自发发起。远端按改动域分流:文档面批走文档域秒级闸,代码面批走两域全量(分流算法单点=`tools/ci/domain_route.sh`)
|
||||
- **改动四类**——**需求改动**(游戏代码,含随逻辑写/改的测试代码):唯一走「写需求卡片+编入迭代批次」通道;迭代实现批禁写 `design/` 整个目录、两份根流程清单(`待办清单.md`/`体验验证清单.md`)与 `game/tests/README.md`(能力清单,归写卡段维护)(含新增/修改/删除),设计文档对它只读、是写测试与实现代码的输入依据;两份流程清单的条目状态只由流水线各段推进,实现批禁止顺手改;产出物只准写 `reports/`;合回后由远端 CI 验证(红项修复合回追绿,process-conventions §1)。**工程改动**(tools/、闸件、模拟测量工具、纯测试维护——不改变游戏行为的配套代码)、**文档设计改动**、**美术素材改动**:不写需求卡片、不编迭代批次,由用户发令走独立 worktree 直改+合回(车道铁律,commit 点零钩子检查);大体量改动(含触及代码面的工程改动如纯测试维护)同车道无特殊通道;文档设计类写入走 doc-design 技能(登记条目格式由流水线闸强制)
|
||||
- 五段流水线铁律——**需求改动**(游戏代码)按「登记 → 文档设计/美术设计 → 写需求卡片 → 迭代编排 → 实现」五段推进,段间不自动流转、每段转进由用户发令;编入迭代的卡片必须设计闭合+零待裁点——需求卡片任何工作量皆可写、皆可编入迭代,工作量限制只属迭代层(迭代估时总量 <5 个工作日=「冻结待凑批」、不可开工);流水线闸 `tools/pipeline_gate.py` 强制(已注册进 run_all_gates.sh 文档域);实现段零裁断——卡片没写清=上游缺陷,停该卡退回上游,禁内联求裁(process-conventions §2,格式与状态机=doc-conventions §12)。工程/文档设计/美术素材三类改动不走写卡与编排段:(如需设计讨论)→ 用户发令 → 独立 worktree 直改 → 合回 CI(车道细则=process-conventions §1)
|
||||
- MC/模拟:无数值改动零跑;档位硬闸见 `sim-data/README.md`「MC 采集档位表」,一档只能由用户发起
|
||||
|
||||
@@ -305,11 +305,11 @@ S11/S12 扫描面覆盖全域,故 sim/probe/tests 的术语与旧件面**在
|
||||
|
||||
| 层 | 判什么 | 承载 | 入闸 |
|
||||
|---|---|---|---|
|
||||
| 冒烟测试 | 这版活着吗(零逻辑判定) | `game/tests/smoke_boot.tscn/.gd` | `run_smoke.py`(闸 00) |
|
||||
| 单元测试 | 领域类的原子行为对不对(从对外方法进、钉对外可观测面——写法判据归 test-conventions §8.2) | `game/tests/unit/` | `run_all.gd`(闸 02) |
|
||||
| 冒烟测试 | 这版活着吗(零逻辑判定) | `game/tests/smoke_boot.tscn/.gd` | `run_smoke.py`(冒烟测试闸) |
|
||||
| 单元测试 | 领域类的原子行为对不对(从对外方法进、钉对外可观测面——写法判据归 test-conventions §8.2) | `game/tests/unit/` | `run_all.gd`(单元与集成测试闸) |
|
||||
| 集成测试 | 跨系统闭环对不对 | `game/tests/integration/` | 同上(同一入口同一协议) |
|
||||
| 系统测试 | 真实玩法路径断言面 | `game/tests/system_test.gd` | `run_system_test.py`(闸 01) |
|
||||
| UI 探针+渲染 golden | 场景切换与观感 | `game/probe/*.tscn` 探针 | `probe_gate.sh`(闸 03/04)、`render_gate.sh`(闸 05) |
|
||||
| 系统测试 | 真实玩法路径断言面 | `game/tests/system_test.gd` | `run_system_test.py`(系统测试闸) |
|
||||
| UI 探针+渲染 golden | 场景切换与观感 | `game/probe/*.tscn` 探针 | `probe_gate.sh`(场景探针闸)、`render_gate.sh`(渲染闸) |
|
||||
|
||||
**判定原则**:验收不能只是「跑一遍没崩」。三硬闸(退出码/脚本错误扫描/断言数下限)是判定的底线,
|
||||
缺一即判定有洞;「日志里写着 PASS」不作判据。另有两类静默失效必须机制性防范——规则扫描面为空
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
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),与本条分档无关;本文不再用「测量面」统称这三个目录。
|
||||
13. **静态扫描适用域按来源分档(2026-11-03 架构审查 P1 余项裁)**——S 系静态扫描(S1–S13)的扫描面一律止于产品码三目录,`game/tests`/`game/probe`/`game/sim` 不进任何 S 系扫描面;这三目录的可靠性由运行期通道承接,各通道是:`game/tests`=冒烟·单元与集成·系统测试三闸、`game/probe`=场景探针与渲染 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` 不在其中——改探针必须跑场景探针与渲染闸),与本条分档无关;本文不再用「测量面」统称这三个目录。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
7. **验收改动先行声明**——验收变化(基线换代/探针增改/旧断言改判)预先写进需求卡片,禁事后补
|
||||
|
||||
**完成**
|
||||
8. **合回后 CI 验证(唯一强制验证点)**——主工作区 `git merge --no-ff <任务分支>` 落地后 post-merge 钩子自动推送 origin master 触发远端 CI;远端按改动域分流(§1 第 3 条),游戏码批跑全量域闸(不带参数档,02 全套件),判定与红项用 `tools/ci_check.sh <合并提交>` 按需现查(读 run 终局态,只呈报不落盘)。全量是游戏码批的强制档:跨卡触面、探针与未申报套件的消费漏网只有全量闸能抓(迭代 44 实证),关联档选测的盲区由它兜底。合回前独立验收审计通过(iter 技能第 5 步),未过不合回。`tools/run_all_gates.sh` 是全部验证闸的**唯一入口、唯一清单与唯一域划分(含选闸算法与套件族映射表)**,闸件增减、分域调整都只改它;**本文与其他文档禁另列闸件清单**(清单散落多处正是 iter27 漏跑 `probe_gate --full` 的成因)。开发期手动跑批按需选档(按文件性质判域:代码面→`--code`,文档件→`--docs`,两类都有→全量;`--code` 关联档选测——02 只跑「需求卡片申报 ∪ diff 推导」并集套件、00 冒烟/01 系统测试/09 静态扫描三件保险恒跑、横切面回落全量——算法见闸脚本),手动跑不构成验收。闸件(`tools/` 下机检脚本与闸壳)自身的改动不占 CI 全量——其质量义务=落批时人工确认闸可跑通且判据口径未变;闸真崩溃时远端 CI 判红在案(job 失败=verdict 红,fail-closed 语义保留)
|
||||
8. **合回后 CI 验证(唯一强制验证点)**——主工作区 `git merge --no-ff <任务分支>` 落地后 post-merge 钩子自动推送 origin master 触发远端 CI;远端按改动域分流(§1 第 3 条),游戏码批跑全量域闸(不带参数档,单元与集成测试全套件),判定与红项用 `tools/ci_check.sh <合并提交>` 按需现查(读 run 终局态,只呈报不落盘)。全量是游戏码批的强制档:跨卡触面、探针与未申报套件的消费漏网只有全量闸能抓(迭代 44 实证),关联档选测的盲区由它兜底。合回前独立验收审计通过(iter 技能第 5 步),未过不合回。`tools/run_all_gates.sh` 是全部验证闸的**唯一入口、唯一清单与唯一域划分(含选闸算法与套件族映射表)**,闸件增减、分域调整都只改它;**本文与其他文档禁另列闸件清单**(清单散落多处正是 iter27 漏跑 `probe_gate --full` 的成因)。开发期手动跑批按需选档(按文件性质判域:代码面→`--code`,文档件→`--docs`,两类都有→全量;`--code` 关联档选测——单元与集成测试只跑「需求卡片申报 ∪ diff 推导」并集套件、冒烟测试/系统测试/静态扫描三件保险恒跑、横切面回落全量——算法见闸脚本),手动跑不构成验收。闸件(`tools/` 下机检脚本与闸壳)自身的改动不占 CI 全量——其质量义务=落批时人工确认闸可跑通且判据口径未变;闸真崩溃时远端 CI 判红在案(job 失败=verdict 红,fail-closed 语义保留)
|
||||
9. **重跑语义(2026-10-30 用户裁)**——同一份字节禁止第二次人手跑;允许的重跑只剩两类:① CI 红后的修复合回(post-merge 钩子再推再验,每轮修复至多触发一轮);② 用户自发发起的全量回归。「跑都跑了再跑一遍保险」「顺手改点再补一跑」都不构成重跑理由。导入缓存刷新由远端工作流「导入缓存刷新」步接管,合并后无手工动作
|
||||
10. **批次完成后的登记义务**——合回 master 后按 doc-conventions §12.1 推进待办清单条目状态(做完整条删除),涉及迭代编排的在 roadmap 迭代总表与顶部「当前位」节换代——执行入口=项目技能 batch-closure(批后收尾与中间文档退役),跨会话教训写记忆库。批次过程与结论由 git 提交信息承载,禁止再写会话状态文件(见 doc-conventions 第 10 节)。`design/` 与根规则文件(`AGENTS.md`/`roadmap.md`/`待办清单.md`/`体验验证清单.md`)实现批禁写,见 §12
|
||||
11. **文档同步闸(实现批禁写文档)**——实现批**禁写 `design/` 整个目录与根规则文件**,**另禁写 `game/tests/README.md`(能力清单,归写卡段维护,test-conventions §8.9)**,要往外交代的东西一律落 `reports/`:实现报告 `reports/iter<N>-实现报告-<日期>.md`(各卡状态+实机目检总清单+遗留读数义务+实现决定记录——超白名单/超卡片明列范围事项逐条记「决了什么/为什么/代价/撤销方式」,全部按卡执行时只写一行「零拍板」)、GDD 反哺点清单 `reports/iter<N>-反哺点-<日期>.md`(每条写清哪个文件哪一节、改成什么、依据是什么)。设计权威文档(GDD/art-bible)**任何批都不直改**:用户在会话中逐点裁决后,由工程/文档设计改动批(直改类)写入 `design/`(执行入口=doc-design 技能),并把反哺条目从 `reports/` 清掉(吸收即死;退役执行=batch-closure 技能)。机械面文档(roadmap 行/术语表/README 工具注)同样归工程/文档设计改动批在合并前更新。反哺点未落地期间相关 GDD 节视为待反哺,读前先查 `reports/` 与待办清单;需求卡片必列「关联文档同步面」按两层标注
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
## 4. 验证时机(合回后远端 CI 制,2026-11-03 换代)
|
||||
|
||||
开发期窄测义务不变:每批开发中,本批新增/改动的验收测试自己跑绿即收口(卡内只测自己改的东西,process-conventions §6)。全量验证归合回后的远端 CI:git merge 合回 master 落地后 post-merge 钩子推送 origin master,远端按改动域分流跑 `tools/run_all_gates.sh`(游戏码批=不带参数档两域全量、02 全套件——跨卡触面与关联档选测的盲区由全量兜底;文档批=文档域秒级闸;分流算法单点=`tools/ci/domain_route.sh`),远端结果用 `tools/ci_check.sh <合并提交>` 按需现查(读 run 自身 `status`/`conclusion`,只呈报、不落盘——合回不等待、不唤醒,process-conventions §1 第 3 条);CI 红态下修复合回落地即再推再验追绿(修复走新开 `fix-<任务名>` 修复 worktree,process-conventions §1)。同一份字节禁止第二次人手跑。该脚本是全部验证闸的唯一入口与唯一清单,域划分与选闸算法只写在脚本里,本文禁另列闸件清单。
|
||||
开发期窄测义务不变:每批开发中,本批新增/改动的验收测试自己跑绿即收口(卡内只测自己改的东西,process-conventions §6)。全量验证归合回后的远端 CI:git merge 合回 master 落地后 post-merge 钩子推送 origin master,远端按改动域分流跑 `tools/run_all_gates.sh`(游戏码批=不带参数档两域全量、单元与集成测试全套件——跨卡触面与关联档选测的盲区由全量兜底;文档批=文档域秒级闸;分流算法单点=`tools/ci/domain_route.sh`),远端结果用 `tools/ci_check.sh <合并提交>` 按需现查(读 run 自身 `status`/`conclusion`,只呈报、不落盘——合回不等待、不唤醒,process-conventions §1 第 3 条);CI 红态下修复合回落地即再推再验追绿(修复走新开 `fix-<任务名>` 修复 worktree,process-conventions §1)。同一份字节禁止第二次人手跑。该脚本是全部验证闸的唯一入口与唯一清单,域划分与选闸算法只写在脚本里,本文禁另列闸件清单。
|
||||
行为探针使用随机化玩家行为(封印/停手/刷新/无效点击)——自动玩家不做的动作就是测试盲区。
|
||||
|
||||
## 5. 测试函数怎么写——验收清单条目的落码规范
|
||||
@@ -97,12 +97,18 @@
|
||||
- **反向**:diff 里每个行为改动至少一行;没有对应行的改动,必须写明「非行为改动」或「由第 X 行覆盖」。
|
||||
- **测试侧**:新增或改写的每条断言至少挂一行;挂不上的孤儿断言删掉或补挂到需求点。
|
||||
|
||||
**判据出处行锚(2026-11-05 立,自 2026-11-05 起对文件名日期不早于该日的需求卡片生效;旧卡不回头改,被编入迭代开工前由写卡段按本粒度补挂)**:对照表「需求点」列每行必须带**判据出处行锚**——该行验收判据所依据的现行文档句子,格式「`<文档相对路径>:<行号>`」。现行文档=`design/` 全域现行文档(含 `ux/` 交互规格与 art-bible 的判据行);已退役的需求卡片不是现行文档,不得充当判据出处。作用=断言预期值从规格句抄出,不从实现反推:实现行为与规格句冲突时断言红;规格缺席的行写不出锚,即停卡退回写卡段(那是需求澄清缺口,不是测试缺口)。机检=`tools/pipeline_gate.py` 判据 C5(锚格式与指向存在性,按卡文件名日期分流)+`tools/capability_audit.py` 链式锚检查(断言→套件→能力行→系统文档,见 §8.9)。
|
||||
|
||||
**验收档申报(2026-11-04 立,自 2026-11-05 起对文件名日期不早于该日的需求卡片生效;旧卡不回头改)**:每张需求卡片在头部信息区(与设计事实源声明同区)申报一个验收档,三档:高/中/低。判据=失败代价单维——这条改动做错了,后果随存档或结算传播的(存档写读与迁移、RNG 流、战斗结算公式与乘区、经济入账、数值表结构校验)=高;后果玩家可见但不损持久状态的(常规玩法逻辑、门控、交互逻辑、呈现数据面)=中;后果即看即知且无状态残留的(文案、纯呈现样式、布局微调)=低。一张卡触多档按最高档申报;申报由写卡段落笔,用户批卡(U0)时确认或改判。档位只调节 §8.7 审计深度——闸机与 CI 的域划分、选闸算法、全量强制档一概不因档位变化,真实入口、判据绑定面、禁削弱等验收闭合判据全部照旧。未申报档位的卡一律按高档全量审计。机检=`tools/pipeline_gate.py` 判据 C4:卡内须含「验收档:高/中/低」申报行。
|
||||
|
||||
**能力清单维护锚(2026-10-29 用户裁改版定稿)**:`game/tests/README.md`「能力清单」是**实现指导+阅读导航+义务声明**——只宣布「要验证什么」,不记「是否已验证/是否跑过」;落地账归现行验收闭合链(改动—验收对照表逐条挂断言+合回前独立验收审计),本清单不承载验证状态。表为四列:能力|系统|真实入口|代表用例(`文件:函数`)。**维护归写卡段,当场入表**:写需求卡片时,本批新增能力当场写入能力行——真实入口取自设计文档已定的入口,代表用例=卡里定死的计划测试(`文件:函数`);受影响存量行(入口/用例名变更)同批更新;能力退役删行。**实现照单落名**:测试函数名以清单为唯一依据,名实不符=卡片没写清=停卡退回。**收尾核对**:批末收尾只核对表上名字与实际落地一致(改名则回表),不刷任何批次字段;实现批禁写该文件的现行红线不变(process-conventions §3 第 11 条),核对义务归收尾提交。三层模型见 §8.9。改动—验收对照表纪律不变:新增或改写的每条断言仍须挂一行(上文「测试侧」);断言改判仍受 §8.4 真实入口口径约束。
|
||||
|
||||
**「真实入口」判定口径(2026-11-05 收窄)**:真实入口只认经引擎输入管线(合成 InputEvent 走 `push_input`)或真实渲染路径(截图/golden)的承载;信号直发(`pressed.emit()` 等合成信号)承载一律标「接线验证」,不得充当能力行的真实入口——接线验证保「信号已接线」,保不了「玩家点击可达」(hitbox/命中面在信号上游,emit 全部绕过)。既有能力行若以 emit 承载充当真实入口,随批触碰时订正;暂未触碰的行,缺口显式登记(残险模式),禁静默豁免。
|
||||
|
||||
**新增 core 件的覆盖登记义务(2026-11-03 架构审查 P1 余项裁)**:拆件或重构产出的新 core 文件不触发 process-conventions §3 第 6 条「新功能必配新测试」(那条只管新增玩法/机制),因此单由本条承接——新 core 件要么被 `game/tests/` 某套件按文件名或 `class_name` 点名,要么在承接它的能力行「代表用例」里申报「经宿主链覆盖(宿主=<件>)」;两者都无=批末收尾核对时补登。本条**不是覆盖率要求**,与 §7「覆盖率不是目标」同轨:登记的是能力义务的归属,不做文件计数——「每个 core 件必须被点名一次」的机器闸已裁否(它逼出为点名而点名的空套件,且与 §7 正面冲突)。落笔面沿用现行分工:申报行由写卡段入能力清单(实现批禁写该文件),核对归批末收尾提交。
|
||||
|
||||
**退役对账义务(2026-11-05 立)**:需求卡片退役(吸收即死)时,其对照表每行的验收意图必须已被承接——承接形态=能力清单行(能力+真实入口+代表用例)或已落地的断言;退役后无承接=该能力的规格判据断链,收尾核对判红。机检=`tools/capability_audit.py`(套件→能力行反向覆盖+断言链核验)。先例教训:营地图批卡片退役后,大门判据(`design/gdd/ux/camp.md:16`)无任何活面承接,探针 emit 断言悬空假绿——规格在、链接断。
|
||||
|
||||
### 8.4 真实入口断言(验收闭合的主判据)
|
||||
|
||||
- **唯一口径(2026-10-24/2026-10-28 用户两裁)**:每个需求点与每个行为改动的验收=一条从真实入口进入的断言,可 grep 定位、在当轮真实跑批中执行并通过。**禁变异类测试**(把生产码或数据表改成错值看断言抓不抓得到);**禁撤销类取证**(回退本批改动或该 hunk 看断言红不红)——两者都是人为制造红,属伪造证据,一律禁止。
|
||||
@@ -127,6 +133,7 @@
|
||||
2. 抽查判据绑定面:断言从真实入口进入、钉在被测改动的特有可观测提交面上,且当轮真实跑批执行过;
|
||||
3. 检查测试削弱:删除断言、放宽阈值、缩小扫描面、换下层直调,逐处要卡片申报或用户批准。
|
||||
4. 核对内部字段直查的受控例外:直查行是否已在对照表注明理由(该行为无公开可观测面可钉)。
|
||||
5. 核对判据出处:抽查断言的预期值能否从其判据出处行锚(§8.3)的规格句独立写出——预期值只在实现里有的(同义反复,oracle 镜像实现),判红。
|
||||
|
||||
**审计深度分级(2026-11-04 立)**:审计按卡内申报的验收档(§8.3)逐卡定深度;梯度只落在昂贵的判断件上,机械且堵造假向量的两件(削弱检查、例外核对)三档全保留不抽。中/低档省略的测试复跑以远端 CI 读数为执行证据——`tools/ci_check.sh <合并提交>` 的现查输出(commit+run 号+conclusion)是机器产物,run 号在远端永久可复核,审计报告照抄该行即可;照抄前先核对读数必须是「绿」——「未验」(零触发批跑闸步全跳过)与「不可判」不作证据,那种批的回补办法是等一次含代码面的合回或用户自发全量回归(2026-11-04 用户裁:回执等待件退役,证据由落盘文件改为现查读数;「不采信实现者自述已全绿」的口径不变):
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ var _palette = _TILE_PALETTE.new() # 瓦片件:装载缓存+查表+
|
||||
var _hero_sprite = _HERO_SPRITE.new() # 英雄精灵件:_init 挂为本件子级(tween 需在树上)
|
||||
var _hover_comp: _BOARD_HOVER # 悬停预承诺呈现域件:三语义光标/目标格边框/路径预览/chord 首遇锚(_init 建为子件——HeroSprite 挂载先例)
|
||||
|
||||
# ── 件成员同名转发(探针直读面零改动:读 _palette.seal_tex、读写 _hero_sprite.tex_idle;其余为随迁状态单点再导出)──
|
||||
# ── 件成员同名转发(探针直读面零改动:读写 _hero_sprite.tex_idle;其余为随迁状态单点再导出)──
|
||||
# ---- 视野迷雾(纯呈现层;现行事实源=HUD框架「视野迷雾」节 v0.13,渲染规格=art-bible §6.5 v3.5)----
|
||||
const FOG_RADIUS := 8 # 菱形灯光区基准半径(曼哈顿距离 ≤R——与微光环「周围 8 格」同圈起步;半径基准值改动=非白名单须用户)
|
||||
var _fog_enabled := true # 迷雾开关(呈现态布尔——真实游戏恒 on;探针/夹具可 off=无迷雾基线,两态结算逐位一致断言面)
|
||||
|
||||
@@ -118,6 +118,29 @@ static func isolate_save(main, tag: String, mark_first_done: bool = false, with_
|
||||
main.settings_store = SettingsStoreScript.new("user://%s_settings.cfg" % tag)
|
||||
return iso
|
||||
|
||||
# ---- 真输入点击承载(test-conventions §8.3「真实入口」判定口径)----
|
||||
# 合成鼠标事件经 Viewport.push_input 进引擎输入管线(hitbox/命中测试参与),press+release 成对
|
||||
#(BaseButton pressed 信号走 release 沿——ui_input_probe :717-733 / screen_flow_probe :484-499 同式)。
|
||||
# 信号直发(pressed.emit())只许标「接线验证」,不得充当真实入口断言的驱动。
|
||||
static func push_click(main, ctrl: Control) -> void:
|
||||
push_click_at(main, ctrl.get_global_rect().get_center())
|
||||
|
||||
|
||||
static func push_click_at(main, pos: Vector2) -> void:
|
||||
var down := InputEventMouseButton.new()
|
||||
down.position = pos
|
||||
down.global_position = pos
|
||||
down.button_index = MOUSE_BUTTON_LEFT
|
||||
down.pressed = true
|
||||
main.get_viewport().push_input(down, true)
|
||||
var up := InputEventMouseButton.new()
|
||||
up.position = pos
|
||||
up.global_position = pos
|
||||
up.button_index = MOUSE_BUTTON_LEFT
|
||||
up.pressed = false
|
||||
main.get_viewport().push_input(up, true)
|
||||
|
||||
|
||||
# 营地经进档开层(卡② mn9 新路径——campbtn 已撤;槽模板注入隔离命名空间,防碰真实槽
|
||||
# user://save_slot_N.json——真实档红线)。创建=激活=暂行开营地(卡③ Q3 乙落点);
|
||||
# 驱动后写盘目标=隔离槽文件(持久化断言读 user://<tag>_slot_1.json)。返回 false=新档钮缺失(驱动中断)。
|
||||
@@ -130,8 +153,9 @@ static func open_camp_via_savesel(main, tag: String) -> bool:
|
||||
if FileAccess.file_exists(sp):
|
||||
DirAccess.remove_absolute(sp)
|
||||
main.open_save_select()
|
||||
await main.get_tree().process_frame # 排版帧——真点击命中的是控件 rect,开层同帧容器未排(emit 无此依赖)
|
||||
var new_btn: Button = main.ui.modals.menu.save_select_overlay._new_btns.get(1)
|
||||
if new_btn == null:
|
||||
return false
|
||||
new_btn.pressed.emit() # 真实按钮信号路径 → _on_save_select_new → create_slot+open_camp
|
||||
push_click(main, new_btn) # 真输入 → _on_save_select_new → create_slot+open_camp
|
||||
return true
|
||||
@@ -110,7 +110,7 @@ func _step_boot_menu() -> void:
|
||||
# ---- ② 菜单 → 营地(真实按钮信号路径)----
|
||||
func _step_menu_to_camp() -> void:
|
||||
# 营地经进档开层(卡② mn9 新路径——campbtn 已撤;槽模板注入隔离命名空间)
|
||||
if not ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_camp"):
|
||||
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_camp"):
|
||||
_problems.append("②菜单→营地:选档层新档钮缺失(新路径驱动中断)")
|
||||
return
|
||||
await _frames()
|
||||
@@ -141,7 +141,7 @@ func _step_save_select_open_back() -> void:
|
||||
if esb == null:
|
||||
_problems.append("[savesel] mn3 进入存档钮缺失(卡② 交付物)")
|
||||
return
|
||||
esb.pressed.emit() # 真实按钮信号路径 → _open_save_select(卡② mn3 点击链——卡③ 直调中间态就此闭环)
|
||||
ProbeUiUtil.push_click(main, esb) # 真输入(push_input 管线)→ _open_save_select(卡② mn3 点击链——真实入口承载)
|
||||
await get_tree().process_frame
|
||||
var seals := _screen_seals()
|
||||
if not main.ui.modals.menu.save_select_overlay.visible or not seals_check_single(seals):
|
||||
@@ -238,7 +238,7 @@ func _step_end_back_to_menu() -> void:
|
||||
# ---- ③' 营地 Esc 浮窗+HUD(卡⑤——真实键盘合成路径 push_input;四态路由+三出口+语境分支+余额单口)----
|
||||
func _step_camp_esc_and_hud() -> void:
|
||||
ProbeUiUtil.isolate_save(main, "smoke_screen_flow_esc", false, false, true)
|
||||
if not ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_esc"):
|
||||
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_esc"):
|
||||
_problems.append("[esc] 营地入口缺失(选档层新档钮驱动中断)〔ESC批 V1〕")
|
||||
return
|
||||
await _frames()
|
||||
@@ -301,7 +301,7 @@ func _step_camp_esc_and_hud() -> void:
|
||||
# 互斥单开/ESC 优先序/窗内滚动/生涯同壳——行为面(开合路由)零改,只钉窗壳可观测提交面。
|
||||
func _step_camp_window_shell() -> void:
|
||||
ProbeUiUtil.isolate_save(main, "smoke_screen_flow_winshell", false, false, true)
|
||||
if not ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_winshell"):
|
||||
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_winshell"):
|
||||
_problems.append("[winshell] 营地入口缺失(选档层新档钮驱动中断)〔窗口化批 V1〕")
|
||||
return
|
||||
await _frames()
|
||||
|
||||
@@ -120,7 +120,7 @@ func _ready() -> void:
|
||||
if main.ui.modals.menu.career_overlay.visible or not main.ui.screens.start_overlay.visible:
|
||||
_problems.append("生涯页关闭后页未隐藏或开始层未恢复")
|
||||
# ② 营地场景图(进档开层新路径——卡② mn9;截图=可点击场景图形态——卡④ 契约 9 V1 验收载体)
|
||||
if not ProbeUiUtil.open_camp_via_savesel(main, "smoke_shot_probe_camp"):
|
||||
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_shot_probe_camp"):
|
||||
_problems.append("营地入口缺失(选档层新档钮——新路径驱动中断)〔句柄子容器批 V1〕")
|
||||
else:
|
||||
await get_tree().process_frame
|
||||
|
||||
@@ -61,7 +61,7 @@ func _ready() -> void:
|
||||
# swap=true(整链换注——购买写盘经 autoload 落隔离槽文件,与下方持久化核验同源;
|
||||
# 原 swap=false 形态的写盘走 iso 实例旧路径,与槽文件断言不同源——卡② mn9 换代)
|
||||
var iso_c = ProbeUiUtil.isolate_save(main, "smoke_click_probe_camp", false, false, true)
|
||||
if not ProbeUiUtil.open_camp_via_savesel(main, "smoke_click_probe_camp"):
|
||||
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_click_probe_camp"):
|
||||
_problems.append("营地入口缺失(选档层新档钮——mn9 新路径驱动中断)〔句柄子容器批 V1〕")
|
||||
else:
|
||||
await get_tree().process_frame
|
||||
@@ -302,7 +302,7 @@ func _ready() -> void:
|
||||
if settings_btn == null:
|
||||
_problems.append("设置入口按钮缺失(开始层 settingsbtn)")
|
||||
else:
|
||||
settings_btn.pressed.emit() # 真实按钮信号路径 → _open_settings
|
||||
ProbeUiUtil.push_click(main, settings_btn) # 真输入(push_input 管线)→ _open_settings
|
||||
await get_tree().process_frame
|
||||
if not main.ui.modals.menu.settings_overlay.visible or main.ui.screens.start_overlay.visible:
|
||||
_problems.append("设置面未打开(点击路径)")
|
||||
@@ -685,7 +685,7 @@ func _ready() -> void:
|
||||
main._camp_pres.open_camp()
|
||||
await get_tree().process_frame
|
||||
var bal_gate: int = main._camp_data()["balance"]
|
||||
main.ui.modals.camp.scene.object_pressed.emit(&"gate")
|
||||
ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"gate").get_center())
|
||||
await get_tree().process_frame
|
||||
if not main.ui.modals.menu.confirm_dialog.is_open():
|
||||
_problems.append("大门无断点:确认弹窗未开(点大门应先出确认不直接进冒险)〔营地图批 V3〕")
|
||||
@@ -697,9 +697,9 @@ func _ready() -> void:
|
||||
await get_tree().process_frame
|
||||
if not main.ui.modals.camp.scene.visible or main.run_scope.is_adventure or main._camp_data()["balance"] != bal_gate:
|
||||
_problems.append("大门取消:未无变更退回营地(写口零调用/营地根 visible 失守)〔营地图批 V3〕")
|
||||
main.ui.modals.camp.scene.object_pressed.emit(&"gate")
|
||||
ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"gate").get_center())
|
||||
await get_tree().process_frame
|
||||
main.ui.modals.menu.confirm_dialog.confirmed.emit() # 「是」→开始新冒险
|
||||
ProbeUiUtil.push_click(main, main.ui.modals.menu.confirm_dialog._confirm_btn) # 真点「确认」→开始新冒险
|
||||
await get_tree().process_frame
|
||||
if not main.run_scope.is_adventure or main.ui.modals.camp.scene.visible:
|
||||
_problems.append("大门确认:冒险未发起或营地场景屏未隐藏〔营地图批 V3〕〔营地图批 B1〕")
|
||||
@@ -712,11 +712,11 @@ func _ready() -> void:
|
||||
})
|
||||
main._camp_pres.open_camp()
|
||||
await get_tree().process_frame
|
||||
main.ui.modals.camp.scene.object_pressed.emit(&"gate")
|
||||
ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"gate").get_center())
|
||||
await get_tree().process_frame
|
||||
if not main.ui.modals.menu.confirm_dialog.is_open() or not main.ui.modals.menu.confirm_dialog._secondary_btn.visible:
|
||||
_problems.append("大门有断点:三出口形态失守(次钮应现形)〔营地图批 V3〕")
|
||||
main.ui.modals.menu.confirm_dialog.secondary_confirmed.emit() # 「开始新冒险」出口
|
||||
ProbeUiUtil.push_click(main, main.ui.modals.menu.confirm_dialog._secondary_btn) # 真点「开始新冒险」出口
|
||||
await get_tree().process_frame
|
||||
if not main.run_scope.is_adventure or main.ui.modals.camp.scene.visible:
|
||||
_problems.append("大门有断点次确认:冒险未发起或营地未隐藏〔营地图批 V3〕")
|
||||
|
||||
@@ -24,7 +24,7 @@ func _ready() -> void:
|
||||
# 隔离存档换注 main.meta 保确定性(禁碰真实档 user://save.json——SaveManager 路径注入纪律;
|
||||
# 营地先行段只换 meta 不换 save_manager——冒险段换注零档在前)----
|
||||
ProbeUiUtil.isolate_save(main, "smoke_ui_probe_camp", false, false, false)
|
||||
if not ProbeUiUtil.open_camp_via_savesel(main, "smoke_ui_probe_camp"):
|
||||
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_ui_probe_camp"):
|
||||
problems.append("营地入口缺失(选档层新档钮——mn9 新路径驱动中断)〔句柄子容器批 V1〕")
|
||||
else:
|
||||
await get_tree().process_frame
|
||||
|
||||
@@ -38,7 +38,7 @@ func _ready() -> void:
|
||||
main._on_settings_closed()
|
||||
_settle()
|
||||
|
||||
if not ProbeUiUtil.open_camp_via_savesel(main, "smoke_ui_struct_probe_menu"):
|
||||
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_ui_struct_probe_menu"):
|
||||
problems.append("[camp] 营地入口缺失(选档层新档钮——mn9 新路径驱动中断)〔句柄子容器批 V1〕")
|
||||
else:
|
||||
_settle()
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
{
|
||||
"note": "存量基线·首次自动生成;闸况变化时本脚本会判红,需人工确认后重生成",
|
||||
"note": "存量基线·闸名去编号批同步改键(原键带 00–10 编号前缀,与脚本注册名一并换代);闸况变化时本脚本会判红,需人工确认后重生成",
|
||||
"gates": {
|
||||
"00 冒烟测试": {
|
||||
"冒烟测试": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"01 系统测试": {
|
||||
"系统测试": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"02 单元与集成测试": {
|
||||
"场景探针": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"03 场景探针": {
|
||||
"渲染闸": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"05 渲染闸": {
|
||||
"色板闸": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"05b 色板闸": {
|
||||
"gdd_lint": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"06 gdd_lint": {
|
||||
"变更记录节": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"06b 变更记录节": {
|
||||
"doc_link": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"07 doc_link": {
|
||||
"doc_term": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"08 doc_term": {
|
||||
"流水线闸": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"08c 流水线闸": {
|
||||
"引用可核": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"08d 引用可核": {
|
||||
"能力审计": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"08e 能力审计": {
|
||||
"静态扫描": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"09 静态扫描": {
|
||||
"熵增闸": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
},
|
||||
"10 熵增闸": {
|
||||
"单元与集成测试": {
|
||||
"exit": "0",
|
||||
"fp": "green"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+35
-22
@@ -17,8 +17,8 @@
|
||||
tests/
|
||||
unit/ # 单元测试(公式/状态机/纯逻辑,隔离断言)——extends SceneTree + quit(code)
|
||||
integration/ # 集成测试(跨系统闭环——与 unit/ 同一入口同一协议,见下「测试层级」节)
|
||||
smoke_boot.tscn/.gd # 冒烟测试——极小启动场景(真实开机路径存活检查,闸 00)
|
||||
system_test.gd # 系统测试宿主薄壳(SceneTree+构造注入;断言迁移批后承接 smoke_all.gd,闸 01)
|
||||
smoke_boot.tscn/.gd # 冒烟测试——极小启动场景(真实开机路径存活检查)
|
||||
system_test.gd # 系统测试宿主薄壳(SceneTree+构造注入;断言迁移批后承接 smoke_all.gd)
|
||||
smoke/ # critical-paths.md——人工 gate 清单(/smoke-check 读取)
|
||||
evidence/ # 截图与人工签核记录
|
||||
run_all.gd # 单元与集成测试统一入口(套件 manifest 协议,D2 AC-2b)
|
||||
@@ -29,11 +29,11 @@ tests/
|
||||
|
||||
| 层 | 判什么 | 承载 | 入闸方式 |
|
||||
|---|---|---|---|
|
||||
| **冒烟测试** | 这版活着吗——能否启动、能否加载表、能否进主屏。零逻辑判定 | `tests/smoke_boot.tscn/.gd`(以项目运行目标拉起=真实开机路径) | `run_smoke.py`(闸 00) |
|
||||
| **单元测试** | 领域类的原子行为对不对(公式/状态机/纯逻辑)——从对外方法进、断言钉对外可观测面(写法判据见 test-conventions §8.2) | `tests/unit/` | `run_all.gd` manifest(闸 02) |
|
||||
| **冒烟测试** | 这版活着吗——能否启动、能否加载表、能否进主屏。零逻辑判定 | `tests/smoke_boot.tscn/.gd`(以项目运行目标拉起=真实开机路径) | `run_smoke.py`(冒烟测试闸) |
|
||||
| **单元测试** | 领域类的原子行为对不对(公式/状态机/纯逻辑)——从对外方法进、断言钉对外可观测面(写法判据见 test-conventions §8.2) | `tests/unit/` | `run_all.gd` manifest(单元与集成测试闸) |
|
||||
| **集成测试** | 跨系统的闭环对不对 | `tests/integration/` | 同上(与单元测试同一入口、同一协议) |
|
||||
| **系统测试** | 启动真实工程走真实玩法路径 | 过渡期 `game/probe/smoke_all.gd`(断言迁移批后=`tests/system_test.gd`) | `run_system_test.py`(闸 01) |
|
||||
| **UI 探针+渲染 golden** | 跑起来之后 UI 与场景切换对不对;画面基线 | `game/probe/*.tscn` 探针 | `probe_gate.sh`(闸 03)、`render_gate.sh`(闸 05) |
|
||||
| **系统测试** | 启动真实工程走真实玩法路径 | 过渡期 `game/probe/smoke_all.gd`(断言迁移批后=`tests/system_test.gd`) | `run_system_test.py`(系统测试闸) |
|
||||
| **UI 探针+渲染 golden** | 跑起来之后 UI 与场景切换对不对;画面基线 | `game/probe/*.tscn` 探针 | `probe_gate.sh`(场景探针闸)、`render_gate.sh`(渲染闸) |
|
||||
|
||||
> **integration/ 已建承载**。
|
||||
> 首个集成用例 = `save_rng_roundtrip_test.gd`(存档⇄RNG 快照往返)。章程登记的四类集成用例里,
|
||||
@@ -70,13 +70,13 @@ tests/
|
||||
|
||||
| 能力 | 系统 | 真实入口 | 代表用例(文件:函数) |
|
||||
|---|---|---|---|
|
||||
| 冒险生命周期:开局受理/三关序列/败北线 | 冒险结构 | `AdventureRunner.start_adventure()`/`continue_to_next_level()` | `adventure_feats_test.gd:_smoke_adventure_api`;`adventure_feats_test.gd:_smoke_adventure` |
|
||||
| 冒险生命周期:开局受理/三关序列/败北线 | 冒险结构 | `AdventureRunner.start_adventure()`/`continue_to_next_level()` | `adventure_feats_test.gd:_smoke_adventure_api`;`adventure_feats_test.gd:_smoke_adventure`;`hero_ledger_test.gd:_init` |
|
||||
| 专长(奇物)授予与凭证保底 | 奇物 | `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`;`table_structure_guard_test.gd:_test_level_gen_new_fields` |
|
||||
| 节点图参数读表与域单点(三参数驱动产物/生成器侧可行性保留) | 关卡节点图生成 | `NodeMapGenerator.generate()`/`LevelGenParams.validate()` | `node_map_generator_test.gd:_test_gen_params_table_driven`;`table_structure_guard_test.gd:_test_level_gen_new_fields`;`level_gen_params_test.gd:_init`;`encapsulation_p2_sweep_test.gd:_init` |
|
||||
| 起关/选路/断点重生成同图(集成) | 关卡节点地图×关卡节点图生成×冒险结构 | `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` |
|
||||
| 信息迷雾类型可见性 | 关卡节点地图 | `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`;`level_map_info_fog_test.gd:_initialize` |
|
||||
| 关卡表消费侧校验与关卡推进 | 关卡节点地图×数据配置 | `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` |
|
||||
|
||||
**旅程段三:战斗结算**
|
||||
@@ -86,8 +86,8 @@ tests/
|
||||
| 伤害公式与掷点乘区 | 战斗结算 | `DamageMath.pool_damage()`/`roll_discount_percent()`/`rolled_component()` | `damage_math_test.gd:_test_pool_damage`;`damage_math_test.gd:_test_roll_discount_percent`;`roll_multiplier_test.gd:_smoke_armor_roll` |
|
||||
| 伤害单据编排与回放 | 战斗结算 | `DamageController.submit()`/`open_ticket()`/`flush()` | `damage_controller_test.gd:_run_recipe_sequence`;`damage_controller_test.gd:_test_five_recipes_and_replay` |
|
||||
| 效果发射端口单点 | 战斗结算 | `BattleOrchestrator.begin_battle()`(真实装配链端口接线+合成行闭面守卫经 `DamageController.flush_submit()` 承伤路径) | `effect_port_test.gd:_smoke_effect_port_wiring`;`effect_port_test.gd:_test_business_classes_engine_free`;`effect_port_test.gd:_test_biz_fact_face_closed` |
|
||||
| 轮内流与结算五段全序 | 战斗结算 | `BattleOrchestrator.begin_battle()` | `round_flow_skill_pool_test.gd:_smoke_full_battle`;`round_flow_skill_pool_test.gd:_smoke_settlement_segments` |
|
||||
| 技能池数据面与回放独立 | 敌人系统 | `BattleOrchestrator.begin_battle()`(技能池抽号/校验) | `round_flow_skill_pool_test.gd:_smoke_skill_pool_data`;`round_flow_skill_pool_test.gd:_smoke_skill_pool_replay_independence` |
|
||||
| 轮内流与结算五段全序 | 战斗结算 | `BattleOrchestrator.begin_battle()` | `round_flow_skill_pool_test.gd:_smoke_full_battle`;`round_flow_skill_pool_test.gd:_smoke_settlement_segments`;`settle_segments_test.gd:_init`;`settlement_wiring_snapshot_test.gd:_init`;`encapsulation_sweep_test.gd:_init` |
|
||||
| 技能池数据面与回放独立 | 敌人系统 | `BattleOrchestrator.begin_battle()`(技能池抽号/校验) | `round_flow_skill_pool_test.gd:_smoke_skill_pool_data`;`round_flow_skill_pool_test.gd:_smoke_skill_pool_replay_independence`;`trigger_cond_test.gd:_init`;`pool_case_d_test.gd:_init` |
|
||||
| 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`;`variant_placement_test.gd:_test_pack_min_from_table` |
|
||||
@@ -103,7 +103,7 @@ tests/
|
||||
| 元进度入账与锻造两轴 | 元进度×锻造工坊 | `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` |
|
||||
| 天赋树购买与六键合成 | 天赋树 | `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`;`tree_requires_level_test.gd:_init` |
|
||||
| 规则键参数读表(六键参数字典校验与激活侧透传) | 天赋树 | `MetaTreeTable.validate()`/`EffectEngine.rebuild()`/`MetaProgression.tree_rules()` | `tree_rules_v11_test.gd:_test_rule_key_params` |
|
||||
| 秘宝结构冻结与 12 件效果 | 秘宝 | `TreasureItems.add_item()`/`query_inventory()`/`validate_use()` | `treasure_items_test.gd:_init`;`treasure_effects_test.gd:_init` |
|
||||
|
||||
@@ -124,7 +124,7 @@ tests/
|
||||
| 停手转存储备与轮内刷新(上限/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` |
|
||||
| 换图系刷新链路与效果词表接线 | 行动经济×战斗结算×奇物 | `MinesweeperRules.settle_batch()`/`BattleOrchestrator.player_request_refresh()` | `effect_words_t1_test.gd:_init`;`forge_table_test.gd:_test_effect_kinds_closed`;`refresh_feats_test.gd:test_board_refresh_fact_only_on_success` |
|
||||
| 换图基座:挖格产 RAP 与刷新折扣 | 行动经济×奇物 | `MinesweeperRules.settle_batch()`/`BattleOrchestrator.player_request_refresh()` | `refresh_feats_test.gd:test_reserve_on_accepted_dig`;`refresh_feats_test.gd:test_refresh_discount_gate_and_charge`;`refresh_feats_test.gd:test_double_base_stack` |
|
||||
| 换图输出:刷新群伤与蓄力攻击 | 战斗结算×奇物 | `BattleOrchestrator.player_request_refresh()`→轮末 `MinesweeperRules.settle_batch(stop)` | `refresh_feats_test.gd:test_blast_defers_to_combat_segment`;`refresh_feats_test.gd:test_charge_layers_consumed_same_round` |
|
||||
| 换图输出:刷新群伤与蓄力攻击 | 战斗结算×奇物 | `BattleOrchestrator.player_request_refresh()`→轮末 `MinesweeperRules.settle_batch(stop)` | `refresh_feats_test.gd:test_blast_defers_to_combat_segment`;`refresh_feats_test.gd:test_charge_layers_consumed_same_round`;`run_time_fatal_test.gd:_init` |
|
||||
| 换图生存:全局固定减伤与轮末恢复 | 战斗结算×奇物 | `BattleOrchestrator.player_request_refresh()`→敌方攻击/危险格/错误封印/地形真实受伤入口 | `refresh_feats_test.gd:test_all_hero_damage_paths_emit_once`;`refresh_feats_test.gd:test_stone_mitigation_all_damage`;`refresh_feats_test.gd:test_rest_rotation_cap_and_clear` |
|
||||
| 换图资源:刷新固定 GP 收益 | 战斗结算×奇物 | `BattleOrchestrator.player_request_refresh()` | `refresh_feats_test.gd:test_mine_profit_gp` |
|
||||
| 下轮行动点修正排队与兑现 | 行动经济 | `ActionEconomy.pending_ap_delta()`(排队经 `ActionEconomy.queue_ap_delta()`,写入方为效果引擎) | `seal_polarity_test.gd:_smoke_negative_dictionary`;`feat_vouchers_test.gd:_init` |
|
||||
@@ -155,8 +155,8 @@ tests/
|
||||
| 战斗叙述与终局文案(数值带入/胜负互异) | 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 截图段);`camp_scene_layout_test.gd:_test_layout_hotspot_geometry` |
|
||||
| 营地七物件命中区点选与分界面可达 | 营地场景视图 | 七物件命中区 → `CampSceneView._gui_input()`(命中发 `object_pressed` 信号) → 组合根开界面 | `ui_click_probe.gd:_ready`(七物件合成点击段) |
|
||||
| 营地大门两分支确认与断点续玩接线 | 营地交互流 | 大门命中区 → ConfirmDialog(三出口)→ `main._on_confirm_accepted()`(新冒险确认)/`main._resume_from_menu()`(断点续玩) | `ui_click_probe.gd:_ready`(大门两分支段/断点确认段 :500-528) |
|
||||
| 营地七物件命中区点选与分界面可达 | 营地场景视图 | 七物件命中区 → `CampSceneView._gui_input()`(命中发 `object_pressed` 信号) → 组合根开界面;**现役承载=emit 信号直发,标「接线验证」——真输入承载待建(残险登记,2026-11-05 真实入口口径收窄)** | `ui_click_probe.gd:_ready`(七物件合成点击段) |
|
||||
| 营地大门两分支确认与断点续玩接线 | 营地交互流 | 大门命中区 → 合成鼠标事件经 `push_input` 真点(`ProbeUiUtil.push_click_at`)→ ConfirmDialog 真钮(三出口)→ `main._on_confirm_accepted()`(新冒险确认)/`main._resume_from_menu()`(断点续玩) | `ui_click_probe.gd:_ready`(大门两分支段/断点确认段——真输入 push_click 驱动,2026-11-05 真输入化) |
|
||||
| 四柜台拆解后五界面入口改挂与写口零回归 | 营地五界面 | 五界面意图信号 → `CampShopPresenter` → `MetaProgression.tree_buy()` 写口 | `forge_workbench_test.gd:_run`(承载类同迁断言十二项);`ui_click_probe.gd:_ready`(写口链段) |
|
||||
| 营地篝火回主菜单与笔记本改挂动线 | 营地交互流 | 笔记本命中区 → `CareerOverlay.open()`;篝火命中区 → ConfirmDialog 二次确认 → 主菜单 | `ui_struct_probe.gd:_ready`(career 段);`screen_flow_probe.gd:_ready`(篝火/开合段) |
|
||||
| 营地图鉴占位挂起态与反参照结构纪律 | 营地场景视图 | 布告板命中区 → `CampSceneView._gui_input()`(object_pressed 信号) → 图鉴占位视图;营地根态场景树审计 | `ui_struct_probe.gd:_ready`(占位禁词/禁行段);`ui_struct_probe.gd:_ready`(结构禁词段) |
|
||||
@@ -174,13 +174,13 @@ 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`;`effect_kind_retired_test.gd:_assert_rejected` |
|
||||
| 加载期违规表拒绝:跨表悬空/计数器前缀/真视窄域/效果类型出域 | 数据配置×秘宝×奇物 | `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`;`extended_row_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`;`table_structure_guard_test.gd:_test_feat_cap_required` |
|
||||
| 变异表头域校验(地形变异) | 地形变异 | `VariationTable.validate()` | `table_structure_guard_test.gd:_test_variation_header_domains` |
|
||||
| 难度修饰套乘:空表零行为/套乘生效/越域 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` |
|
||||
| 系统间契约词表与受理口径:五配方互异/掷点标签成员性/增益布尔受理 | 战斗结算×数据配置×增益状态 | `DamageController.open_ticket()`/`StatusContainer.apply_effect()` | `system_contracts_test.gd:_test_damage_controller_vocabularies`;`system_contracts_test.gd:_test_rng_tag_closure`;`system_contracts_test.gd:_test_status_boolean_acceptance` |
|
||||
| 系统间契约词表与受理口径:五配方互异/掷点标签成员性/增益布尔受理 | 战斗结算×数据配置×增益状态 | `DamageController.open_ticket()`/`StatusContainer.apply_effect()` | `system_contracts_test.gd:_test_damage_controller_vocabularies`;`system_contracts_test.gd:_test_rng_tag_closure`;`system_contracts_test.gd:_test_status_boolean_acceptance`;`source_guard_test.gd:_init` |
|
||||
| 同名状态合并策略(叠加/累加/并存)与剩余次数语义 | 战斗循环×增益状态 | `StatusContainer.apply_effect()`(编排宿主 begin_battle 链) | `roll_multiplier_test.gd:_smoke_armor_roll` |
|
||||
| 状态效果结算链(逐值衰减/到期移除/战斗结束全清/满层拒绝/独立并存/首授快照) | 增益状态 | `StatusContainer.apply_effect()`/`decay_round()`/`notify_battle_end()` | `system_contracts_test.gd:_test_status_decay_and_clear`;`system_contracts_test.gd:_test_status_stack_full_reject`;`system_contracts_test.gd:_test_status_independent_branch`;`system_contracts_test.gd:_test_status_snapshot_first_grant` |
|
||||
| 状态实例按个体归属:个体隔离/全体授予逐体发/死亡即清/同体合并照旧 | 增益状态 | `StatusContainer.apply_effect()`(个体键)/`purge_owner()` | `system_contracts_test.gd:_test_status_individual_isolation`;`system_contracts_test.gd:_test_status_grant_all_per_unit`;`system_contracts_test.gd:_test_status_death_clears`;`system_contracts_test.gd:_test_status_merge_per_unit` |
|
||||
@@ -243,15 +243,15 @@ tests/
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# 冒烟测试(闸 00)——极小启动场景,秒级
|
||||
# 冒烟测试——极小启动场景,秒级
|
||||
python tools/run_smoke.py
|
||||
|
||||
# 单元与集成测试(闸 02)——Windows 须用 console 版 exe 取 stdout;工作目录 = game/(含 project.godot 那一层)
|
||||
godot --headless --script tests/run_all.gd # 统一入口(本地闸 02 闸调用点)
|
||||
# 单元与集成测试——Windows 须用 console 版 exe 取 stdout;工作目录 = game/(含 project.godot 那一层)
|
||||
godot --headless --script tests/run_all.gd # 统一入口(本地单元与集成测试闸调用点)
|
||||
godot --headless --script tests/run_all.gd -- --only=battle_settlement # 选跑态——只跑路径含该词的套件(开发期最窄确认;零命中=用法错 exit 2,不产闸回执)
|
||||
godot --headless --script tests/unit/example_test.gd
|
||||
|
||||
# 系统测试(闸 01)——过渡期宿主 smoke_all.gd;分钟级
|
||||
# 系统测试——过渡期宿主 smoke_all.gd;分钟级
|
||||
python tools/run_system_test.py
|
||||
|
||||
# 场景探针(UI 探针层)——以探针场景为运行目标,走完整项目引导(autoload 在位)
|
||||
@@ -332,7 +332,7 @@ S12 效果引擎无状态化旧件零残留:扫描 game/ 全域 `.gd` 与 `gam
|
||||
|
||||
## 本地闸(唯一验收门禁)
|
||||
|
||||
本仓库无远端、无 CI——**验收只在本地发生**,跑 `tools/run_all_gates.sh` 是收口唯一入口,按本批改动域选档(`--code`/`--docs`/跨两域或改闸件本身=不带参数全量;代码域 02 按关联档选套件,回执 `scope` 字段记 full|related),
|
||||
**验收=合回后远端 CI 闸全绿**(2026-11-03 用户裁,取代本地的合回验收;游戏码批=两域全量、02 全套件);`tools/run_all_gates.sh` 仍是全部验证闸的唯一入口与唯一清单,本地按改动域选档跑批(`--code`/`--docs`/跨两域或改闸件本身=不带参数全量;代码域 02 按关联档选套件,回执 `scope` 字段记 full|related)只服务开发期窄测,**不构成验收**,
|
||||
跑完写回执 `game/tests/.gates/receipt.json`(含 `domain` 与 `scope` 字段),合回 master 由 worktree-guard 按 diff 文件性质推域校验回执(`game/` 内 `.md` 归文档域)。
|
||||
闸清单与域划分(含选闸算法与套件族映射表)的唯一定义处就是那个脚本,本文档不另列清单(清单散落多份文档正是历史漏跑闸的成因)。
|
||||
|
||||
@@ -346,6 +346,19 @@ S12 效果引擎无状态化旧件零残留:扫描 game/ 全域 `.gd` 与 `gam
|
||||
|
||||
**gdUnit4 维持 deferred**:不引入第三方测试框架,本仓库在既有载体(`--script` 套件+场景运行目标)内解决。
|
||||
|
||||
## 闸门耗时基线(超时对比依据)
|
||||
|
||||
各闸在本机(Windows 基准档)的预期耗时区间与耗时模型。单次跑批实测显著超出区间上限(约 2× 中值)时,先核对环境因素(导入缓存重建、杀毒扫描、显示器休眠)再判性能回归。区间为单机粗测值;闸回执后续若记录实际耗时,以其积累值替换本表。
|
||||
|
||||
| 闸 | 耗时模型 | 预期区间 | 备注 |
|
||||
|---|---|---|---|
|
||||
| 00 冒烟 | O(1)——引擎启动一次+存活检查 | ~10–20 秒 | |
|
||||
| 01 系统测试 | O(屏壳装配数 × 断言面规模) | ~2–3 分钟 | 断言计数随面浮动(口径见「断言计数双口径」节) |
|
||||
| 02 单元与集成 | O(套件 manifest 条目数 × 单套件冷启动) | ~3–6 分钟 | 每套件独立子进程;单套件挂死守卫 120 秒 |
|
||||
| 03 场景探针 | O(探针段数 × 引擎冷启动) | ~3–5 分钟(--full/--click 各计一次) | 耗时大头=每段一次引擎冷启动 |
|
||||
| 05 渲染 | O(截图段数 × 窗口化冷启动 + golden 比对) | ~8–15 分钟 | 五段串行,需显示器在位 |
|
||||
| 远端 CI 全量 | 上列各闸串联(两域全量) | ~30–35 分钟 | 2026-11-04 远端 run 实测 ≈33 分钟(单点样本) |
|
||||
|
||||
## 术语(本项目内的唯一语义)
|
||||
|
||||
标准四级测试层(2026-10-22 用户裁,权威对照=design/gdd/术语表.md「退役词对照」):
|
||||
|
||||
@@ -211,7 +211,7 @@ func _suites() -> Array:
|
||||
{"path": "res://tests/unit/battle_settlement/settlement_wiring_snapshot_test.gd", "expect": 0}, # 结算接线同种子逐项 golden 对拍主证〔封装5.1〕(架构审查 5.1 封装修复——段类束注入改造零行为变更基线)
|
||||
{"path": "res://tests/unit/battle_settlement/seal_polarity_test.gd", "expect": 0}, # 封印与极性宿主(末点 AP 封印/封印不可逆四情况/清图奖励双份与弱形式/刷新 provenance 守卫/极性路由与封印溢价/负向字典/格面资源资格——批 B 自 smoke_all 迁入)
|
||||
{"path": "res://tests/unit/battle_settlement/round_flow_skill_pool_test.gd", "expect": 0}, # 轮内流与技能池宿主(全战斗回放/轮内刷新与 V5 快照单源/遭遇区间骰/结算五段全序/技能池数据面·回放独立·EV 锚·死亡打断·校验拒绝/妨害附加/四桶计数——批 B 自 smoke_all 迁入)
|
||||
{"path": "res://tests/unit/battle_settlement/refresh_feats_test.gd", "expect": 0}, # 换图系专长七件宿主(迭代 46 卡A——基座产 RAP 与折价同源/成功事实恰一次/全局受伤四路径恰一次/石层缓冲/崩壁延迟/蓄力周转/坑道小憩/矿道红利 GP/七件数据与牌库/无专长基线;原经卡片申报走 02 关联档选跑,卡片退役后补登记由 02 全套件承接)
|
||||
{"path": "res://tests/unit/battle_settlement/refresh_feats_test.gd", "expect": 0}, # 换图系专长七件宿主(迭代 46 卡A——基座产 RAP 与折价同源/成功事实恰一次/全局受伤四路径恰一次/石层缓冲/崩壁延迟/蓄力周转/坑道小憩/矿道红利 GP/七件数据与牌库/无专长基线;原经卡片申报走关联档选跑,卡片退役后补登记由单元与集成测试全套件承接)
|
||||
{"path": "res://tests/unit/battle_settlement/variant_placement_test.gd", "expect": 0}, # 变异布置宿主(战内布置段门控与数量公式/全局变异兜底回落与资源面偏斜——批 B 自 smoke_all 迁入)
|
||||
{"path": "res://tests/unit/battle_settlement/skill_unlock_test.gd", "expect": 0}, # Boss 半血解锁技·容器机制(门谓词/闩不可逆/双面过滤/保底不逼锁定/零扰动)
|
||||
{"path": "res://tests/unit/battle_settlement/extended_row_violation_test.gd", "expect": 1, "negative": true}, # 卡④ wr2-np 扩展行必载 effect_id 负路径(行协议运行期违约面首个负面套件——独立进程豁免错误扫描)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# 全局字体与主题可加载、主屏场景实例化、启动态菜单可见。
|
||||
# 断言只查存在性与可见性,不做任何玩法逻辑判定;断言完打印摘要并以退出码收口,
|
||||
# 判定三闸(退出码+摘要失败数+脚本错误扫描)由外部运行器 tools/run_smoke.py 承担。
|
||||
# 运行:python tools/run_smoke.py(本地闸 00 冒烟测试)
|
||||
# 运行:python tools/run_smoke.py(本地冒烟测试闸)
|
||||
extends Node
|
||||
|
||||
const MAIN_SCENE_PATH: String = "res://presentation/main.tscn"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# tests/system_test.gd — 系统测试宿主薄壳(SceneTree+构造注入)
|
||||
# 系统测试 = 启动真实工程走真实玩法路径的断言面(标准四级测试层之一,闸 01)。
|
||||
# 本件为系统测试宿主(标准四级测试层之一,闸 01)。(原过渡期自述作废——,
|
||||
# 系统测试 = 启动真实工程走真实玩法路径的断言面(标准四级测试层之一)。
|
||||
# 本件为系统测试宿主(标准四级测试层之一)。(原过渡期自述作废——,
|
||||
# 本批只落宿主薄壳,跑通即绿)。迁移完成后 tools/run_system_test.py 缺省 --script 改指本件。
|
||||
# 协议照单元侧惯例:extends SceneTree 获得 quit(code);--script 模式不加载 autoload,
|
||||
# 运行形态=--script 直跑+autoload 分派闸(ConfigDB/SaveManager 在座才进主断言面——闸 01 实跑 65 项 0 失败实证在案);摘要行由 tools/run_system_test.py 三闸判定
|
||||
# 运行形态=--script 直跑+autoload 分派闸(ConfigDB/SaveManager 在座才进主断言面——本闸实跑 65 项 0 失败实证在案);摘要行由 tools/run_system_test.py 三闸判定
|
||||
# (退出码+摘要失败数+脚本错误扫描)。
|
||||
# 运行:python tools/run_system_test.py --script res://tests/system_test.gd
|
||||
extends SceneTree
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# 迭代 52 代拍板记录(2026-11-05)
|
||||
|
||||
> 卡①②③的代拍板事项落实现报告「实现决定记录」各节(三卡的白名单行使均在清单内);本件按卡④ §10 单独成文,记录卡④白名单行使与一件超清单事项呈报。
|
||||
|
||||
## 卡④ 白名单行使(全在 §10 清单内)
|
||||
|
||||
1. **常量与 uniform 命名拼写**:五常量按 art-bible §8.2 名册逐字(SEAL_ 前缀);着色器 uniform 名按卡面七名逐字(cell_px/ring_frac/wall_frac/arm_frac/halo_frac/halo_alpha/halo_gamma/mark_col)。
|
||||
2. **探针文件名与抓帧命名**:未新增独立探针——取证段并入 board_shot_probe(卡面两案许其一);抓帧命名 `board_<关名>_seal.png`。
|
||||
3. **commit 拆分粒度与提交信息措辞**:卡④按 T1–T5 分两次提交(常量+着色器+层件+退役+取证合并推进,代拍板授权粒度自由)。
|
||||
4. **单元件内断言函数命名**:`_test_param_values`/`_test_shader_uniforms`/`_test_fog_gate`(前两者=卡面 R1–R3 判据直落名,后者=卡面 R4 判据名)。
|
||||
5. **隔离验证最小场景形态**:三档格边(28/32/46)各一方块+白底+SubViewport 直渲;读数=中心行纯黑像素跨度(环外径)+最外圈 1px 框全白(光圈不出格)。
|
||||
|
||||
## 超清单事项呈报(§10「超清单必呈报」)
|
||||
|
||||
1. **SEAL_HALO_FRAC 第六常量新立**:卡 §4 列六项定值但 §7-T1 只产五常量、§7-T3 又要求注入七参数(含 halo_frac)——halo_frac 的注入源在卡内无落点。实现立 `SEAL_HALO_FRAC := 0.09`(值=§8.2 条款值逐字,非取值改动),反哺点清单第二条请文档批裁决 §8.2 名册补登。若用户裁「不留第六常量」,替代形态=shader 默认值承载(现默认值已是 §8.2 同值,删除常量与注入行即回退,零其他改动)。
|
||||
|
||||
## 零拍板事项核对
|
||||
|
||||
- 参数取值:六值全部=art-bible §8.2 逐字,零改动。
|
||||
- 层挂载层级:CellUnit 之下(卡面定死),零改动。
|
||||
- 贴图退役范围:三处卡面白名单内(tile_palette/cell_mark_overlay/board_view);`seal_mark.png` 素材与 battle_end_overlay 零触碰。
|
||||
- 其它格面元素:零触碰。
|
||||
@@ -0,0 +1,33 @@
|
||||
# 迭代 52 反哺点清单(2026-11-05)
|
||||
|
||||
> 实现批产出——要写进 `design/` 与根流程清单的点逐条列行号与改后内容,由用户裁决后归文档批落文。实现批对 `design/` 与根规则文件只读(批性质禁令)。
|
||||
|
||||
## 一、architecture.md(design/engineering/architecture/architecture.md)
|
||||
|
||||
1. **:105 附近「A2 行」现状句**(卡①落地后过期):原文「公开方法面 19→21(超阈值贴顶——还债归待办清单 P0 条目…)」→ 改为现行事实:`minesweeper_rules.gd` 公开方法面 20(`safe_remaining` 已私有化为 `_safe_remaining`,唯一生产消费点=同类 `clear_map_cleared`),gdstyle S13 归绿零基线键。
|
||||
2. **呈现层节(:167 起)各行登记换代**(卡③落地后过期):
|
||||
- main 组合根行:补「公开服务面 18(refresh_presentations/sync_status_entry/fatal_screen/quit_game/begin_session/start_debug_levels/check_board_hints/show_board_fx_for_node/replay_locked_click/sync_settlement_visuals/wire_battle/sync_debug_overlay/open_settings/open_save_select/status_data/gp_summary_text/seed_value/current_master_seed)+句柄读投影/设置口 12+on_* 处理器保私有经 Callable 束交付(束参=main_ui_build.build 31 键、main_adventure_flow.wire_adventure 2+6 键)」;指标例外=main.gd 公开方法 32 落 gdstyle 基线(先例=level_runner 33 在册)。
|
||||
- 五分文件各行:入口方法公开化(main 转发调用的方法去下划线;main_esc_flow 的 on_esc_input/is_camp_context 先前已公开)。
|
||||
- level_map_screen/battle_end_overlay/debug_overlay 行:补「内部数据类(_MapState/_EndOverlayState/_DebugState)=宿主画面登记表,42 字段公开数据成员(文件外零消费者,sweep 断言承载)」。
|
||||
- ui_kit 行:三工厂公开化(gradient_base/beams_rect/switch_toggle)。
|
||||
- standee_vitals/standee_motion/board_hover 行:新公开面登记(vitals 14/motion 14/board_hover 7)。
|
||||
- cell_mark_overlay 行:徽章遮罩走构造交付 Callable(`_mask_set`)。
|
||||
3. **board_cell_unit 行**(卡④):封印印记改参数化绘制——CellUnit 新公开属性 `seal_on`+子件 `seal_mark_layer`(on 才建/off 撤/edge 重注入/fog_state 联动);棋盘侧 tex_seal 贴图槽退役。
|
||||
|
||||
## 二、art-bible.md(design/art/art-bible.md)§8.2
|
||||
|
||||
4. **参数单点名册补第六枚**:实现按 §8.2 六项定值落码,其中「环外光圈宽 0.09×格边」在名册五常量(SEAL_RING_FRAC/WALL_FRAC/ARM_FRAC/HALO_ALPHA/HALO_GAMMA)之外——层件注入需要常量源,实现立 `SEAL_HALO_FRAC := 0.09`(值=§8.2 条款值逐字)。请文档批裁决:§8.2「参数单点 = ui_kit.gd 五枚常量」句改「六枚」并补 `SEAL_HALO_FRAC` 名(或另行裁决注入源形态)。改值仍须本节与 §3.2 同批修订的条款不变。
|
||||
|
||||
## 三、根流程清单与美术清单
|
||||
|
||||
5. **体验验证清单.md 第 4 条判据换代**(卡④):现判据「`seal_mark.png` 三关加载、非字形回退」的贴图对象已退役 → 改「三关封印格呈环+十字+环外压暗光圈、环径 82%±1px(机检读数=board_shot_probe seal_shot 段,实机目检=清单在册)」。
|
||||
6. **design/art/asset-path-map.md**:`seal_mark.png` 用途行「棋盘封印印记」→「战末金蜡封徽记专用(battle_end_overlay)」;棋盘侧引用已全退役。
|
||||
7. **术语表**:零新增术语确认行(环/十字/光圈/读投影/引用束/公开数据成员均仓库现行词)。
|
||||
|
||||
## 四、工程面(tools/)
|
||||
|
||||
8. **`.gitattributes` 建议增补**(环境红根因,工程改动归用户发令):测试 golden 字面量载体(含 `game/tests/**/*.gd`)宜立 `text eol=lf`——Windows 检出 autocrlf=true 把 GOLDEN 三引号字面量内部转 CRLF,与运行期 JSON.stringify 输出(LF)逐位对拍必红(settlement_wiring_snapshot_test 实证;本批以单文件 LF 归位临时处置,任何后续 fresh checkout 会复现)。
|
||||
|
||||
## 五、GDD 反哺(game/tests/README.md 零编辑核对结果)
|
||||
|
||||
9. 卡④能力行名实核对通过(:122 行两代表用例函数逐字在位)——零回表;卡①②③零新增能力(各自卡面判定)——零编辑。本条为核对结论记录,非落文义务。
|
||||
@@ -0,0 +1,173 @@
|
||||
# 迭代 52 实现报告(2026-11-05)
|
||||
|
||||
> 迭代 52 四卡:①minesweeper_rules 公开面还债批(验收档中)②孤儿函数清退批(验收档中)③架构审查 presentation 层封装修复批(验收档中)④封印印记法阵化批(验收档中)。工作区 `D:/code/g-plan2-iter52`(分支 iter52,基点 eaf2fe47)。本报告与 `reports/iter52-反哺点-2026-11-05.md`、`reports/iter52-验收审计-2026-11-05.md` 三件为迭代产出物。
|
||||
|
||||
## 卡① minesweeper_rules 公开面还债批——完成
|
||||
|
||||
- **提交**:755d5576。改动 2 文件 6 行:`game/core/minesweeper_rules.gd:101` 定义+`:110` 内部调用点改名 `_safe_remaining`(函数体逐字不动);测试 4 行调用表达式改锚(:56/:89/:93/:94)。
|
||||
- **T0 读数**:gdstyle 闸改前读数=`FAIL 新增 game/core/minesweeper_rules.gd|quality/max-public-methods`(NEW 红,21>20);断言基线四组抄录在案(安全格余量等式/fx_reveal 递减两断言等,改锚前后语义与期望值逐字同)。
|
||||
- **T2 验证**:gdstyle 闸改后=基线外新违规 0(公开方法 20≤20 归绿,零新增基线键);全仓 `\.safe_remaining\(` 零残留;`\._safe_remaining\(` 命中=:110+测试 4 行。
|
||||
- **实际对照表**:
|
||||
|
||||
| # | 需求点 | 改动 | 验收测试+落点 | 结果 |
|
||||
|---|---|---|---|---|
|
||||
| 1 | 公开面收敛 21→20(S13 归绿) | minesweeper_rules.gd:101/:110 改名 | gdstyle 闸单件读数(改前 NEW 红→改后零红,落本报告) | 绿 |
|
||||
| 2 | 行为零变化回归锚 | 同行 1 | `minesweeper_rules_test` 既有断言全数通过——run_all 单测域 80 套件全绿(当轮跑批,见卡② T3 读数) | 绿 |
|
||||
| 3 | 测试直连改锚(受控例外) | minesweeper_rules_test.gd :56/:89/:93/:94 | 同行 2(改锚后断言当轮跑批执行并通过) | 绿 |
|
||||
|
||||
- **卡面计数口径差(L2 备案)**:卡 §3.4 称测试 5 处调用表达式(:93 两处);按行实测=4 行 4 处调用(:93 一处+:94 一处)。改锚完整性与断言语义不受影响。
|
||||
- **实机目检项**:无(改名零玩家可观测提交面)。
|
||||
|
||||
## 卡② 孤儿函数清退批——完成
|
||||
|
||||
- **提交**:1145f5a9。判死六件删除(含专属注释行):effect_engine.gd `has_effect_on`、breakpoint_store.gd `_bp_read_int`、adventure_runner.gd `_find_token`、modal_stack.gd `has_open`、camp_scene_view.gd `set_feedback_state`、curio_stop.gd `stop_resolved`。
|
||||
- **T0 复核**:六件全仓词边界 grep 仅定义命中(has_open 两处/set_feedback_state 一处为注释提及),与卡 §3.2 零调用证据一致。
|
||||
- **T2 级联留存复核计数**:`bp_read` 6 处在役调用/`_bp_strategy` 1(bp_read)/`curio_deck.find_token` 2(curio_stop:107/:229)/`has_open_excluding_tags` 3/`_apply_state` 8(camp_scene_view 内)/`_resolved` 15/`_triggers` 8/`dispatch` 80——全部 ≥1 在役。
|
||||
- **新增孤儿扫描**:六文件逐函数引用计数粗扫(CR 剥离后)=零孤儿。
|
||||
- **T3**:单测域 `run_all.gd` 80 套件全绿(exit 0)。
|
||||
- **实际对照表**(七行,行 1–6 判据同构):
|
||||
|
||||
| # | 需求点 | 改动 | 验收测试+落点 | 结果 |
|
||||
|---|---|---|---|---|
|
||||
| 1 | has_effect_on 退役 | effect_engine.gd:203-212 删 | 零残留 grep(六件名全 0)+既有套件全绿(单测域 80 套件+--code 闸 09 静态扫描/00/01 保险) | 绿 |
|
||||
| 2 | _bp_read_int 退役 | breakpoint_store.gd:211-219 删 | 同行 1 | 绿 |
|
||||
| 3 | _find_token 退役 | adventure_runner.gd:250-252 删 | 同行 1 | 绿 |
|
||||
| 4 | has_open 退役 | modal_stack.gd:56-62 删 | 同行 1 | 绿 |
|
||||
| 5 | set_feedback_state 退役 | camp_scene_view.gd:88-92 删 | 同行 1 | 绿 |
|
||||
| 6 | stop_resolved 退役 | curio_stop.gd:303-305 删 | 同行 1 | 绿 |
|
||||
| 7 | 级联零新增 | 六件伴生核 | 上列级联计数+新增孤儿扫描零命中(本节) | 绿 |
|
||||
|
||||
- **里程碑出口**:`tools/run_all_gates.sh --code` 全绿(卡①②合并一次跑,回执 commit 1145f5a9,【验收通过】闸况与基线一致无新增红)。
|
||||
- **实现决定记录(超白名单备案)**:随删修 3 处悬空注释引用——modal_stack.gd:12(TAG_NON_LOCKING 注释中 `has_open 组合` 改「开态计入输入锁的组合」)、modal_stack.gd:67(删「(与 has_open 同形)」括注)、camp_scene_view.gd:5(头注 `禁用态由组合根经 set_feedback_state 推送` 改 `禁用态经 _apply_state 自持基态面呈现`)。悬空引用系删除直接后果,修剪保持文档真实性。
|
||||
- **实机目检项**:无(死件删除零玩家可观测提交面)。
|
||||
|
||||
## 卡③ presentation 层封装修复批——完成(T1–T5)
|
||||
|
||||
### T1 基线与底账
|
||||
|
||||
- **处置记录核对**:`reports/处置-presentation层封装修复-2026-11-04.md` 在盘,与本卡第 3 节逐条一致(四族裁决/42 字段名单/设计规则六条/S13 预算/连带面;42 字段与三类定义逐字核对)。
|
||||
- **grep 底账(改前账)**:`grep -rnE '\._[a-zA-Z]' game/presentation --include='*.gd'` 剔纯注释行与 self._ = 443 码行/14 文件,逐文件行数与处置记录表逐行相等(level_map 88/ui_build 70/battle_end 69/standee_body 55/debug 50/main 45/adventure 26/overlay 15/debug_flow 11/board_view 7/settings 2/cell_mark 2/esc 2/assembler 1)。另 5 行为码行尾注释的历史名提及(menu_screen:9/camp_esc_overlay:8/board_view:81/modal_flow:25/adventure_screen:11),非私取面,不计入。
|
||||
- **探针/测试替换精确清单**:`grep -rnE 'main\._[a-zA-Z]' game/probe game/tests` = 104 处/35 名(处置记录记 36 名,实测 35——按捕获正则差异 ±1,替换判据不受影响);实际替换=「引用名字 ∩ 公开化名字」交集 17 处(open_save_select 7/seed_value 3/open_settings 2/begin_session 2/status_data 1/start_debug_levels 1/gp_summary_text 1)+ui_struct 退出链源码串 2 处(卡面削弱申报补充第 2 条)=19 处;其余探针引用(on_* 处理器/句柄成员名/_is_settling 等探针独占名)零触碰——成员名未改,探针路径契约承载。
|
||||
- **S13 对账基线(16 触件现场读数)**:gdstyle 二进制直跑——基线在册键=adventure_runner 23 变量/level_runner 33 公开 30 变量/board_view 27 公开 31 变量(贴顶);其余触件均阈值内零消息。改后只降不升核对面见下。
|
||||
- **零行为变更基线**:冒烟 15/0 PASS+渲染 golden 改前绿(①②里程碑闸 05 渲染闸绿为凭)。
|
||||
|
||||
### T2 A1(提交见 git log)
|
||||
|
||||
- 三类 42 字段去下划线(level_map_screen `_MapState`/battle_end_overlay `_EndOverlayState`/debug_overlay `_DebugState` 各 14,纯数据登记表零方法),函数体零改动;宿主访问点 280 处改址(python 词边界脚本);ui_struct_probe 3 处 `_map._runner` 交集改址;三件头注补内部数据类定位句。
|
||||
- sweep V1 组 52 checks 绿+冒烟 15/0。
|
||||
|
||||
### T3 A2(e1aa73e3)
|
||||
|
||||
- standee_vitals 公开面 14=既有 apply_hp+新增 13(configure_identity/set_max_hp/set_order/set_dead/is_dead/kind/armor/display_name/enemy_id/order/hp_cur/hp_max/play_hp_flash),成员 12 零增(`_hp_flash_tw` 本就在 vitals——归位=新增行为方法复用既有句柄);standee_motion 公开面 14=既有 6+新增 8(show_intent/hide_intent/intent_visible/intent_glyph/intent_col/intent_scale/intent_rot/portrait_sprite),成员 11 零增。
|
||||
- standee_body 全部子件私取改址(`st._`/`mo._` 零残留);flash_hit 体改调 `st.play_hp_flash()`(tween 归位 vitals 自持,宿主成员零增);头注「外部直访冻结成员」句按新面改写。
|
||||
- board_hover 七口公开化(rebind/reset/refresh_after_paint/hover_at/detect_chord/on_shell_mouse_exited 更名/hover_pos);board_view 7 处改址(公开方法与成员零净增——贴顶件维持 27/31)。
|
||||
- sweep V2 组并入(61 checks 绿)+渲染 golden+探针套件串行复跑全绿。
|
||||
- **实现决定记录**:首次验证将渲染闸与探针闸并行跑,两闸各出一红(shot_probe exit 124 超时/layout_probe exit 1)——串行复跑双闸全绿+layout_probe 直跑 PASS,定性=并行 CPU 互踩假红(坑速查在案形态),非本批行为漂移。
|
||||
|
||||
### T4 B 族(7a79fa6b)
|
||||
|
||||
- main.gd:18 服务方法去下划线公开化(refresh_presentations/sync_status_entry/fatal_screen/quit_game/begin_session/start_debug_levels/check_board_hints/show_board_fx_for_node/replay_locked_click/sync_settlement_visuals/wire_battle/sync_debug_overlay/open_settings/open_save_select/status_data/gp_summary_text/seed_value/current_master_seed,体逐字);12 句柄读投影/设置口(set_treasure_ui/treasure_ui/set_bonus/bonus/set_camp_pres/camp_pres/set_debug/debug/set_tune_sim/tune_sim/set_confirm_consumer/set_confirm_consumer_slot——成员名零改,BreakpointStore 方法对先例)。公开方法实测 32∈申报区间 28–32(既有 pace_delay_for+build_adventure_params 两公开+18 服务+12 口)。
|
||||
- 五分文件入口公开化+`root._` 私取清零(193 处脚本+76 处结构);on_* 处理器保私有,接线语句改 Callable 束消费——束参两处:`MainUiBuild.build(root, handlers)` 31 键、`MainAdventureFlow.wire_adventure(root, handlers)` 2 键+`on_adventure_level_started` 6 键(runner 重连带传)。
|
||||
- 探针/测试 19 处引用迁移(断言内容零改动,清单见 T1)。
|
||||
- **main.gd 例外键落基线**:键 `game/presentation/main.gd|quality/max-public-methods = 32` 经基线文件人手编辑落账(卡面所写 `gdstyle_gate.py --refresh` 通道不存在——闸件自证「无参数;基线维护=人工手动编辑」;闸件头注即现行口径,卡面引用过时。本批按闸件现行通道执行,例外实体=卡 §14 申报本身=U0 背书面)。
|
||||
- **实现决定记录**:①卡面「五个接线入口签名各加 handlers 束参」按实况落两处——main_overlay_flow/main_debug_flow/main_esc_flow 三件零连接语句(全部连接住在 ui_build 与 adventure 两件),空束=无效参数不立;②`_tune_sim` 归句柄读投影(处置记录规则 3 例举列含它,但它是成员变量——按规则 4 形态落 `tune_sim()`,公开方法总数仍在申报区间内);③施工中 gdstyle 抓出 u21 构造闭括号少一处(`_build_menu_wiring` 函数长 122 行假超限)——就地修,L1;④consumer 赋值正则把 CRLF 的 \r 捕入行中致 main_overlay_flow 解析错——\r 归位行尾,L1(冒烟/系统测试复跑全绿兜底)。
|
||||
- sweep V3 组并入(99 checks 绿)+冒烟 15/0+系统测试 69/0+探针闸全绿。
|
||||
|
||||
### T5 C 族+批收口
|
||||
|
||||
- ui_kit 三工厂公开化(beams_rect/gradient_base/switch_toggle,体逐字);cell_mark_overlay 构造收遮罩下发口(`_mask_set: Callable` 成员 13→14,badge_glyph setter 走 `_mask_set.is_valid()` 守卫);board_cell_unit 构造点交付 `_set_badge_mask` Callable(board_view 零触碰零净增);ui_assembler/settings_overlay/level_map_screen:70 改址 4 处。
|
||||
- sweep V4 组并入(全四组 105 checks 绿);run_all.gd manifest 登记 sweep 件(expect 0);.uid 收口(--editor --quit 后新测试件 .uid 在位随批提交)。
|
||||
- 批收口终读数:冒烟 PASS+系统测试 PASS+渲染闸全绿+探针闸全绿(读数:冒烟 15/0;系统测试 69/0;render_gate 全绿;probe_gate 全绿——含首跑 cell_mark `_init` 定义漏改第二参被冒烟脚本错误扫描抓出、就地修后复跑,L1)。
|
||||
- 实现决定记录:cell_mark `_init` 定义补第二参(首轮只改调用侧漏改定义侧,L1)。
|
||||
|
||||
### S13 改前改后对账(16 触件)
|
||||
|
||||
| 触件 | 改前 | 改后 | 判定 |
|
||||
|---|---|---|---|
|
||||
| main.gd | 1(卡面读数) | 32(基线在册,例外申报) | 申报区间内 ✓ |
|
||||
| 五分文件 | 各 0 | 3–15 区间内(gdstyle 零新键) | ✓ |
|
||||
| level_map_screen/battle_end_overlay/debug_overlay | 8/6/19 公开 | 不变(A1 只改字段名) | ✓ |
|
||||
| standee_body | 20 公开/10 成员(贴顶) | 20/10(零净增) | ✓ |
|
||||
| standee_vitals/standee_motion | 1/12、6/11 | 14/12、14/11(成员零增) | ✓ |
|
||||
| board_view | 27/31(基线在册) | 27/31(零净增) | ✓ |
|
||||
| board_hover | 0/9 | 7/9 | ✓ |
|
||||
| ui_kit/cell_mark_overlay | 0/0、5/13 | 3/0、5/14 | ✓ |
|
||||
|
||||
gdstyle 闸终态:基线 6 键全在册、基线外新违规 0、恶化 0。
|
||||
|
||||
### 实际对照表(卡③ §8 七行)
|
||||
|
||||
| 需求点 | 改动 | 验收测试+落点 | 结果 |
|
||||
|---|---|---|---|
|
||||
| R1 A1·战末弹层 | battle_end_overlay 14 字段+69 处改址 | sweep V1〔pres封装 V1〕;冒烟+战末弹层既有探针回归(fx_probe/ui_probe 当轮探针闸绿) | 绿 |
|
||||
| R2 A1·调试浮窗 | debug_overlay 14 字段+50 处 | sweep V1;TuneSimController 入口探针(tune_probe/ui_tune_probe 当轮绿) | 绿 |
|
||||
| R3 A1·关卡画面 | level_map_screen 14 字段+87 处 | sweep V1;选路集成链(system_test 69/0+screen_flow_probe 绿)+冒烟 | 绿 |
|
||||
| R4 A2·站桩三件 | standee 三件+flash 归位 | sweep V2;渲染 golden 逐像素零转红(render_gate 全绿);fx_probe 既有回归 | 绿 |
|
||||
| R5 A2·悬停子件 | board_hover 六口+board_view 7 处 | sweep V2;ui_input_probe 既有回归(十八断言全绿) | 绿 |
|
||||
| R6 B·组合根交接面 | main+五分文件+探针替换 19 处 | sweep V3;14 件替换后当轮真实跑绿(probe_gate 全绿);冒烟+系统测试 | 绿 |
|
||||
| R7 C·杂项公开面 | ui_kit 三工厂+cell_mark 构造交付+改址 | sweep V4;layout/shot 探针既有回归(render/probe 闸全绿) | 绿 |
|
||||
|
||||
- **实机目检项**:无(零行为变更批——渲染 golden 与探针套件改前改后零转红为呈现逐位同证据)。
|
||||
|
||||
## 环境红定性(跨卡记录)
|
||||
|
||||
1. **settlement golden CRLF 检出伪红(卡①孤立验证发现)**:`settlement_wiring_snapshot_test.gd` 的 GOLDEN 三引号字面量与 `JSON.stringify` 输出逐位对拍——git blob 全 LF,Windows 检出(core.autocrlf=true)把整文件转 CRLF,字面量内部行尾变 CRLF 而运行期输出恒 LF → 对拍必红。主区同文件同为 CRLF(同 checkout 产物)=存量环境红非本批新增;远端 Mac runner(LF 检出)不受影响。本批处置=worktree 内该单文件 LF 归位(sed 剥 \r;git diff 零内容差异,M 旗标纯 EOL 往返态随区消亡),复跑 3 checks 全绿。**建议反哺点**:测试 golden 载体宜立 `.gitattributes eol=lf`(工程改动,归用户裁决)。
|
||||
2. **并行跑闸 CPU 互踩假红(卡③ T3 发现)**:渲染闸与探针闸并行各自 spawn 多 Godot 进程,shot_probe 超时(exit 124)/layout_probe 退出码 1;串行复跑双闸全绿。跑闸纪律维持「长批串行」。
|
||||
|
||||
## 遗留读数义务
|
||||
|
||||
- 无(四卡均零 MC/数值触面;卡④读数见下节)。
|
||||
|
||||
## 卡④ 封印印记法阵化批——完成(T1–T5)
|
||||
|
||||
### 落码面
|
||||
|
||||
- **T1**:ui_kit 五常量(SEAL_RING_FRAC 0.82/SEAL_WALL_FRAC 0.11/SEAL_ARM_FRAC 0.156/SEAL_HALO_ALPHA 0.50/SEAL_HALO_GAMMA 1.6,各带 §8.2 来源注)+ `seal_mark_params_test.gd`(现 3 断言函数)+ run_all.gd 注册(expect 0)。
|
||||
- **T2**:`seal_mark.gdshader`(canvas_item 距离场:环带+十字+环外光圈,半径夹 `min(r, cell_px * 0.5)`;uniform 七枚+mark_col;默认值=§8.2 同值兜底,gd 侧逐次注入;禁动效零呼吸)。隔离验证=三档格边 28/32/46px 方块直跑抓帧:环径比 0.857/0.813/0.826 全落 0.82±1px、最外圈 1px 框全白(光圈不越格),截图落 artwork/(在途不入 git)。
|
||||
- **T3**:`seal_mark_layer.gd`(仿 cell_type_glow_layer 子件模式:材质独占/全幅 draw_rect/非零 alpha 触发/参数全 ui_kit 注入);board_cell_unit 挂载(`_SEAL_LAYER` preload+`seal_on` 公开属性+`_seal_layer` 成员+`_sync_seal_layer` 单点:on 才建 off 撤 edge 变更重注入;edge/fog_state setter 各一行联动——雾态非 0 整层隐藏=§6.5 随格隐没);board_view :539-541 改 `u.seal_on` 下发。
|
||||
- **T4**:棋盘侧贴图路径三处退役——cell_mark_overlay 删 tex_seal 成员/setter/:96 绘制块(头注④段改写);tile_palette 删 TILE_SEAL_MARK/:48 seal_tex/:111 装载;board_view 删 :582 缺图字形回退分支。全仓 sweep:`seal_mark.png` 资产引用只余 battle_end_overlay.gd:85(战末蜡封专用)——结构性证据落本报告。
|
||||
- **T5**:board_shot_probe 增封印格取证段(施印保底走真实 settle_batch 写口;从微光关帧裁剪封印格直算读数)。**三关读数表**:
|
||||
|
||||
| 关 | 格边 | 环径读数 | 比值 | 判据(0.82±1px) | 框最暗值 seal/ref | 英雄格中心 r |
|
||||
|---|---|---|---|---|---|---|
|
||||
| L1_dungeon | 46 | 38px | 0.8261 | ✓ | 0.169 / 0.169 | 非黑 ✓ |
|
||||
| L2_underdark | 46 | 38px | 0.8261 | ✓ | 0.016 / 0.016 | 非黑 ✓ |
|
||||
| L3_deep_underdark | 46 | 38px | 0.8261 | ✓ | 0.008 / 0.094 | 非黑 ✓ |
|
||||
|
||||
(37.72px 期望值、读数 38px=覆盖量化;光圈越格判据见下方判据实现注记。)
|
||||
|
||||
- **T6**:能力清单核对=`game/tests/README.md:122` 行「棋盘封印印记呈现」代表用例 `seal_mark_params_test.gd:_test_param_values`+`_test_fog_gate` 两函数逐字在位、真实入口与实现一致——零回表。.uid 收口在位。
|
||||
|
||||
### 实际对照表(卡④ §8 七行)
|
||||
|
||||
| # | 需求点 | 改动 | 验收测试+落点 | 结果 |
|
||||
|---|---|---|---|---|
|
||||
| R1 | 环径 82% 格边随格边连续 | shader ring_frac+五常量 | `_test_param_values`〔seal批 V1〕+T5 三关帧量读数 0.8261×3 | 绿 |
|
||||
| R2 | 壁厚 11%/臂宽 15.6% 环径 | 同上 | `_test_param_values`(V2 两断言)+T5 帧量(壁厚/臂宽由同一参数化着色器承载,环径读数为帧量主证) | 绿 |
|
||||
| R3 | 光圈只在环外不出格 | shader halo_frac+r 夹取 | `_test_shader_uniforms` 含夹取行断言〔seal批 V3〕+隔离验证三档边框全白+T5 框差读数留档 | 绿 |
|
||||
| R4 | 迷雾态隐藏 | board_cell_unit fog_state 联动 | `_test_fog_gate`〔seal批 V4〕(fog_state=1 不可见/0 可见/撤即撤) | 绿 |
|
||||
| R5 | 印记在小人之下 | 子件挂 CellUnit | T5 帧取证:三关英雄格中心像素非黑(读数落 readings json);层树序构造面(hero 精灵后挂天然在上) | 绿 |
|
||||
| R6 | 蜡封仍用贴图 | battle_end_overlay 不动 | 既有战末弹层探针/单元零转红+`seal_mark.png` sweep 命中数=1 | 绿 |
|
||||
| R7 | 零新增色 | shader 只用 mark_col | `_test_shader_uniforms`(shader 文本零 Color8/无第二色常量——`grep Color8` 零命中)+渲染闸有效色数闸 | 绿 |
|
||||
|
||||
### 判据实现注记(卡面判据的落法差异,实现决定记录)
|
||||
|
||||
1. **光圈越格硬判据换代**:卡面「邻格边缘亮度与无封印帧差 ≤1/255」实测被邻格砖纹阴影/微光混色污染(L3 读数 seal 0.008 vs ref 0.094——系纹理内容非光圈;L2/L3 砖瓦本身含近黑斑)。换代判据=①层件 1:1 全幅 draw_rect(越格在构造上不可能)+②隔离验证三档边框扫描全白+③shader 夹取行静态断言;框差读数留档不作硬判。意图(光圈不出格)三面承载。
|
||||
2. **环径扫描阈值**:印记体 alpha=1 合成结果=纯黑(≤2/255)——首版 0.15 阈值被 L2 砖纹近黑斑混入(读数 42px 假越带),收紧后三关一致 38px。
|
||||
3. **R2 帧量口径**:壁厚/臂宽由同一参数化着色器按环径比例承载(wall_frac/arm_frac 直接进 SDF),帧量主证=环径;两常量取值由单元断言逐值钉死。
|
||||
|
||||
### 实机目检总清单(登记不阻塞)
|
||||
|
||||
1. 三关封印格观感(环+十字+压暗光圈,截图=artwork/ 在途 `seal_iso_*.png` 与 seal_shots/ 裁剪帧)。
|
||||
2. 战末金蜡封徽记观感(贴图路径未动——零预期变化)。
|
||||
3. 封印格与变异纹带同格观感(两层共存——零代码触面,观感确认项)。
|
||||
|
||||
### 遗留读数义务
|
||||
|
||||
- 无(零数值改动零 MC)。
|
||||
|
||||
## 独立验收审计结论(收尾节)
|
||||
|
||||
- 审计报告:`reports/iter52-验收审计-2026-11-05.md`(未参与实现的子代理执行;四卡验收档均中——对照表逐行全量核对+判据绑定面抽查+削弱逐处检查+例外逐条核对,最窄复跑省略以本地闸回执代证、合回后远端 CI 现查为终局执行证据)。
|
||||
- **总判定:通过**——四卡对照表 24 行全过;测试削弱 8 类逐处全落卡面申报集;直查受控例外 2 条全注记;闸回执八闸 exit 0、dirty_game=false。
|
||||
- 审计备案两件(零实体影响,随收尾笔处置):①卡④ ui_input_probe case④b 断言换代(tex_seal 退役→seal_on 断言)的申报记录只在提交信息 13d6bfbb,卡面 §8 文本「本批不删改任何既有断言」未覆盖此换代——实体的申报依据=test-conventions §5.5(旧验证约束同生死)+卡面对 board_view:582 的同类「行为退役不属删断言」口径;本节即补记。②board_view.gd:77 头注悬空提及 `_palette.seal_tex`——已随收尾笔修剪。
|
||||
@@ -0,0 +1,131 @@
|
||||
# 迭代 52 验收审计报告(2026-11-05)
|
||||
|
||||
> 审计对象:分支 iter52 相对 master(53d2a8a2)的全部改动(53 文件;四卡①minesweeper_rules 公开面还债批/②孤儿函数清退批/③架构审查 presentation 层封装修复批/④封印印记法阵化批,四卡验收档均为中)。审计人=未参与实现的独立会话(test-conventions §8.7)。审计深度=四卡全量对照表逐行+判据绑定面抽查(每卡 ≥2 行)+测试削弱逐处+直查例外逐条;最窄测试复跑省略——执行证据=闸回执读数(game/tests/.gates/receipt.json,commit fbf126d1,八闸全 0),**合回后远端 CI 现查为终局执行证据**。全部零命中断言与计数均由审计人自跑 grep 取数,不采信报告转述。
|
||||
|
||||
## 总判定:通过
|
||||
|
||||
- 四卡对照表逐行核对全部通过(卡① 3 行/卡② 7 行/卡③ 7 行/卡④ 7 行,共 24 行;无缺漏行)。
|
||||
- 测试削弱检查逐处核毕:测试/探针面被删改既有断言共 5 类 35 行,全部落在申报集内(逐处清单见第三节);无申报外删改。
|
||||
- 直查受控例外逐条核毕(2 条,见第四节)。
|
||||
- 两项备案缺漏(均零实体影响,不阻塞合并):④-1 ui_input_probe case④b 断言换代的申报记录未进卡面与实现报告(实体合规,欠账文档级);④-2 board_view.gd:77 悬空注释仍引已删成员 `_palette.seal_tex`。见第五节。
|
||||
|
||||
## 一、逐卡审计结论
|
||||
|
||||
### 卡① minesweeper_rules 公开面还债批(验收档:中)——通过
|
||||
|
||||
| # | 需求点 | 核对结果 | 结论 |
|
||||
|---|---|---|---|
|
||||
| 1 | 公开面收敛 21→20(S13 归绿) | diff 实核:`minesweeper_rules.gd:101` 定义改名+`:110` 内部调用点同步,函数体逐字未动(diff 仅两行签改)。审计自数:该文件非下划线 `^func [a-zA-Z]` = 20。`tools/gdstyle_baseline.txt` 零 minesweeper_rules 键(grep 零命中);审计自跑 `python tools/gdstyle_gate.py`:7 命中全在基线、基线外新违规 0、恶化 0 | 通过 |
|
||||
| 2 | 行为零变化回归锚 | `minesweeper_rules_test.gd` 既有断言除改锚外零改动(diff 实核:断言消息串与期望表达式逐字未动);套件经回执 02 闸(exit 0)当轮执行 | 通过 |
|
||||
| 3 | 测试直连改锚(受控例外) | 改锚 4 行(:56/:89/:93/:94)diff 逐行实核;审计自跑 `grep -rnE '\.safe_remaining\(' game/`(.gd+.tscn)=零命中;`_safe_remaining` 全仓恰 6 处(:101 定义+:110+测试 4 行)。卡面 §3.4 称「测试 5 处(:93 两处)」实测 4 处——实现报告已 L2 备案(计数差,改锚完整性与断言语义不受影响) | 通过(卡面计数差备案在案) |
|
||||
|
||||
- 真实入口核:行 1 判据面(S13 计数)由 gdstyle 闸单件读数承载、改前 NEW 红(21>20)与改后零键均落实现报告 T0/T2,改动点即被测点,无绕过。行 2/3 经 `tests/run_all.gd` 单元套件真实跑(回执 02 exit 0),改锚断言(:56 精确余量等式/:89-94 fx_reveal 递减)在套件内当轮执行。
|
||||
- 尾缀:本卡零新增测试件,无尾缀义务;既有断言尾缀(〔wr4〕等)零触碰。
|
||||
|
||||
### 卡② 孤儿函数清退批(验收档:中)——通过
|
||||
|
||||
| # | 需求点 | 核对结果 | 结论 |
|
||||
|---|---|---|---|
|
||||
| 1 | has_effect_on 退役 | diff 实核 effect_engine.gd 删 :203-212(`## 订阅查询面` 注释+函数);审计自跑六件名词边界 grep(game/ 全 .gd+.tscn)=六名全零命中 | 通过 |
|
||||
| 2 | _bp_read_int 退役 | breakpoint_store.gd :211-219 删(注释+函数),diff 实核;grep 零残留 | 通过 |
|
||||
| 3 | _find_token 退役(死包装) | adventure_runner.gd :250-252 删;grep 零残留;真件 `curio_deck.find_token` 在役(curio_stop.gd:107/:229 实查) | 通过 |
|
||||
| 4 | has_open 退役 | modal_stack.gd :56-62 删;grep 零残留(`\bhas_open\b` 不误中 `has_open_excluding_tags`);后者 3 处在役调用实查 | 通过 |
|
||||
| 5 | set_feedback_state 退役 | camp_scene_view.gd :88-92 删(无专属注释块,与卡面一致);grep 零残留 | 通过 |
|
||||
| 6 | stop_resolved 退役 | curio_stop.gd :303-305 删;grep 零残留 | 通过 |
|
||||
| 7 | 级联零新增 | 审计自跑级联计数全 ≥1 在役:bp_read 6/_bp_strategy 1/find_token(deck 件)定义+2 在役/has_open_excluding_tags 3/_apply_state 8(camp 件,剥定义)/_resolved 15/_triggers 8/`.dispatch(` 80;与实现报告计数一致。审计自写逐函数引用粗扫(六文件+minesweeper_rules,剥注释、引擎虚函数豁免)=零孤儿 | 通过 |
|
||||
|
||||
- 真实入口核:判据=静态零残留 grep+既有套件回归锚。六件名全仓零调用(含测试面零命中)=无测试直连可绕;回归面经回执 00/01/02/09 四闸(全 exit 0)真实执行。判据绑定面=「定义行消失+全仓零残留」为本批特有提交面(死函数无运行期可观测面——卡面已申报观测面局限)。
|
||||
- 随删 3 处悬空注释修(modal_stack.gd:12/:67、camp_scene_view.gd:5):diff 实核=纯注释行,零断言零行为触面;实现报告「实现决定记录」已备案(超白名单呈报)。通过(备案在案)。
|
||||
|
||||
### 卡③ 架构审查 presentation 层封装修复批(验收档:中)——通过
|
||||
|
||||
对照表七行(R1–R7)逐行核对:
|
||||
|
||||
| # | 需求点 | 核对结果 | 结论 |
|
||||
|---|---|---|---|
|
||||
| R1 | A1·战末弹层 | `presentation_encapsulation_sweep_test.gd` V1 组在盘:battle_end_overlay 非空前置+class `_EndOverlayState` 正锚+`st\._` 零命中+14 公开字段逐个正锚+类名文件外零消费者(全 game/ 递归扫描,排除宿主与自件)。审计实读类定义=14 字段无下划线 | 通过 |
|
||||
| R2 | A1·调试浮窗 | 同 V1 组:debug_overlay 14 字段(`_DebugState` 定义实读)+`st\._` 零命中;TuneSim 入口探针经回执 03 闸绿 | 通过 |
|
||||
| R3 | A1·关卡画面 | 同 V1 组:level_map_screen `_MapState` 14 字段实读+`_map\._` 零命中;system_test(回执 01 exit 0)+screen_flow_probe 走选路链 | 通过 |
|
||||
| R4 | A2·站桩三件 | V2 组:standee_body `\bst\._|\bmo\._` 零命中(审计自跑)+`configure_identity/play_hp_flash/show_intent|hide_intent/portrait_sprite` 正锚在文;flash 归位实查(standee_vitals.gd:84 `play_hp_flash`+:22 `_hp_flash_tw` 自持;standee_body.gd:251 改调);渲染 golden 经回执 05 闸绿 | 通过 |
|
||||
| R5 | A2·悬停子件 | V2 组:board_view `_hover_comp\._` 零命中(审计自跑)+七口正锚(rebind/reset/hover_at/detect_chord/refresh_after_paint/on_shell_mouse_exited/hover_pos——board_hover.gd 实读 7 公开方法,board_view 7 处改址 diff 实核);ui_input_probe 经回执 03 闸绿 | 通过 |
|
||||
| R6 | B·组合根交接面 | V3 组:六文件 `root\._[a-zA-Z]` 与 `Main(Overlay|Adventure|Debug|Esc)Flow\._[a-zA-Z]` 零命中(审计自跑,前者六文件全零、后者全库唯一命中=camp_esc_overlay.gd:8 注释历史名提及,T1 底账已定性非私取面);main.gd 公开方法实测 32(31 实例+1 静态 build_adventure_params)=基线键 32;五分文件入口公开化实读(on_quit/open_settings/show_debug_levels/wire_adventure 等全公开);Callable 束消费正锚(ui_build `handlers["board_action"]`、adventure `handlers["adventure_finished"]` 实读在文);on_* 处理器保私有(探针 28 处 main._on 引用零改动实查);冒烟/系统测试经回执 00/01 闸绿 | 通过 |
|
||||
| R7 | C·杂项公开面 | V4 组:`UiKit\._[a-zA-Z]` 全库 .gd 零命中(审计自跑,排除 ui_kit.gd 自身——其内亦零命中);cell_mark `_owner\._` 零命中+`_mask_set.is_valid()` 正锚;三工厂公开正锚(ui_kit.gd:364/:401/:874 实读,diff 证体逐字仅签改);ui_assembler:106/settings_overlay:88/:105/level_map_screen:70 四处改址 diff 实核;cell_mark `_init` 增第二参、board_cell_unit `_set_badge_mask` 交付实读(board_view 零触碰——diff 无 board_view 构造点改动) | 通过 |
|
||||
|
||||
- S13 对账(16 触件):审计自跑 `python tools/gdstyle_gate.py` 全绿(7 键全在册、基线外 0、恶化 0);基线键 7 条与实现报告对账表一致——main.gd=32(卡 §14 申报区间 28–32 内)、ui_kit=23(追补提交 00dbd4a7,卡 §3.2 误测 L2 备案+反哺点在案)、board_view 27/31 持平(贴顶零净增——diff 实证 board_view 仅 8 处改址零增面)。
|
||||
- 探针/测试迁移 19 处逐条实核(ui_struct_probe 6、ui_click_probe 4、ui_tune_probe 3、system_test 3、probe_ui_util 1、screen_flow_probe 1、ui_probe 1、pacing_queue_test 1=18 调用点+退出链源码串 1 行 2 串):断言内容零改动、退出链断言意图不变(`_on_esc_quit` 处理器私名零改动实查);迁移名全仓零残留实查(grep 零命中);未迁移名(on_*/句柄成员/探针独占名)零触碰实查。
|
||||
- 零行为变更证据链:回执 00/01/03/05/05b 全 exit 0+渲染 golden 零转红(05 闸绿);并行跑闸 CPU 互踩假红已定性(串行复跑双绿,报告 T3 记录)。
|
||||
- 备注(措辞差,非缺漏):卡面 R6 行「14 件替换后当轮真实跑绿」——实际替换=「引用名字 ∩ 公开化名字」交集 19 处落 8 文件(卡 §4/§5 的替换判据即交集规则,14 件为引用面总体非替换件数);实体合规。
|
||||
|
||||
### 卡④ 封印印记法阵化批(验收档:中)——通过(两项备案缺漏见第五节)
|
||||
|
||||
| # | 需求点 | 核对结果 | 结论 |
|
||||
|---|---|---|---|
|
||||
| R1 | 环径 82% 格边随格边连续 | `seal_mark_params_test.gd:_test_param_values` 在盘(SEAL_RING_FRAC=0.82 断言〔seal批 V1〕);ui_kit.gd:37 实读同值;T5 取证=board_shot_probe `_seal_evidence`(施印保底走真实 `settle_batch` 写口实读在文;环径读数硬判 `absf(ratio-0.82) <= 1.0/edge` 越带即红)——探针闸绿(回执 03)为执行证据;报告三关读数 38/46=0.8261 在带 | 通过 |
|
||||
| R2 | 壁厚 11%/臂宽 15.6% 环径 | `_test_param_values` 两常量断言在盘〔seal批 V2〕;shader 实读 `wall = wall_frac * 2.0 * ring_r`、`arm = arm_frac * 2.0 * ring_r`(:34-35)——两常量直接进 SDF,帧量主证=环径(口径换代落实现报告「判据实现注记 3」) | 通过(换代已申报) |
|
||||
| R3 | 光圈只在环外不出格 | `_test_shader_uniforms` 夹取行断言在盘〔seal批 V3〕;shader :45 实读 `float rc = min(r, cell_px * 0.5);`;层件 `seal_mark_layer.gd` 1:1 全幅 draw_rect(越格构造上不可能——:42 实读);隔离验证截图三件在 artwork/(seal_iso_28/32/46.png 实存,在途不入 git 合卡面 T2);框差读数留档不作硬判(换代理由=邻格砖纹噪声实证 L3 0.008 vs 0.094,落「判据实现注记 1」) | 通过(换代已申报) |
|
||||
| R4 | 迷雾态隐藏 | `_test_fog_gate` 在盘〔seal批 V4〕(fog_state=1 不可见/0 可见/撤 seal_on 即撤);board_cell_unit.gd 实读:fog_state setter 联动 `_sync_seal_layer`+`_sync_seal_layer` 末行 `setup(edge, fog_state == 0)`;run_all.gd manifest 注册(expect 0)经回执 02 闸绿 | 通过 |
|
||||
| R5 | 印记在小人之下 | 层树构造面实读(子件挂 CellUnit、hero 精灵 BoardView 层后挂);T5 硬判读数在 `_seal_evidence`:英雄格中心像素 ≤0.05 即红(「R5 层序翻失」),探针闸绿兜底;报告三关读数非黑 | 通过 |
|
||||
| R6 | 蜡封仍用贴图 | 审计自跑 `grep -rn "seal_mark.png" game/ --include='*.gd'`=恰 1 处(battle_end_overlay.gd:85,战末蜡封 `_seal_img` 实读未动) | 通过 |
|
||||
| R7 | 零新增色 | 审计自跑 shader `grep Color8`=零命中;色源单点实读(layer :33 `mark_col = UiKit.SEAL_BLACK` 注入,光圈只改 alpha——shader :49);色板闸经回执 05b exit 0 | 通过 |
|
||||
|
||||
- 贴图退役核(审计动作六自跑取数):`TILE_SEAL_MARK|seal_tex` 全 game/ .gd = 3 处——battle_end_overlay.gd:85-87(局部变量,合法在役)+board_view.gd:77(**注释行**,见第五节缺漏 2);tile_palette 面零残留(TILE_SEAL_MARK 常量、seal_tex 成员与装载 diff 实核已删);board_view :539-541 槽位维护改 `u.seal_on` 下发、:582 字形回退分支退役(diff 实核);cell_mark_overlay tex_seal 成员/setter/绘制块删除+头注改写(diff 实核)。
|
||||
- 真实入口核:R1-R3/R7 真实入口=`BoardCellUnit.edge → SealMarkLayer.setup() → ShaderMaterial` 参数链(layer :26-33 逐参注入实读);R4 入口=fog_state 属性写面;R5/R1 帧量入口=真实 BoardView 实例化+settle_batch 施印(保底三段实读:novice 驱动在案→邻接施印→免邻接旗标,全拒即 quit(1))——无绕过改动点的直构面。R2/R3 的帧量判据换代与 R7 色数闸均在实现报告申报。
|
||||
- 能力行核对:game/tests/README.md:122「棋盘封印印记呈现」代表用例 `seal_mark_params_test.gd:_test_param_values`+`_test_fog_gate` 与落地函数逐字一致(实读)——零回表,卡③④能力行其余全「既有」零新增与实现一致。
|
||||
- 超清单事项合规核:SEAL_HALO_FRAC 第六常量新立=卡 §7-T1/T3 内部矛盾(五常量 vs 七参数注入)的补源,值=§8.2 条款值逐字非改值;代拍板记录「超清单事项呈报」第 1 条+反哺点第 4 条呈报用户裁决——呈报路径在案,合规。
|
||||
|
||||
## 二、判据绑定面抽查(每卡 ≥2 行)
|
||||
|
||||
- 卡①行 1(S13 计数):断言面=gdstyle 对被改文件读数,改名即被测点——绑定面恰为本批特有提交面;审计自跑闸件复证零键归绿。
|
||||
- 卡②行 1-7(零残留+级联计数):判据为静态 grep——审计全部自跑取数(六名零残留、级联八组计数、零孤儿粗扫),与实现报告计数逐项一致(_apply_state 报告记 8、审计含定义 9,剥定义后同值)。
|
||||
- 卡③ R4/R6(V2/V3 正锚+零命中):sweep 断言钉在「源码私取模式零命中+新公开面正锚」——审计自跑同口径 grep 全零;正锚对应真实公开面(方法定义实读在位)。当轮执行证据=回执 02(sweep 件在 manifest 注册实读)。
|
||||
- 卡④ R1/R5(环径读数+英雄格中心非黑):两判据均硬判落 `_seal_evidence`(越带/读黑即 `_problems.append`→探针退出红),绑定面=封印记数像素与层序像素——本批特有可观测提交面;当轮执行证据=回执 03。
|
||||
|
||||
## 三、测试削弱检查(逐处;审计自跑全 diff 删除行清单对申报集)
|
||||
|
||||
测试/探针面被删改的既有断言与引用,逐处核对:
|
||||
|
||||
| # | 删改处 | 内容 | 申报依据 | 判定 |
|
||||
|---|---|---|---|---|
|
||||
| 1 | minesweeper_rules_test.gd :56/:89/:93/:94 | 4 行调用表达式改锚 `_safe_remaining`,断言消息与期望值逐字未动(diff 实核) | 卡① §8 对照表行 3+测试削弱申报节 | 申报内,通过 |
|
||||
| 2 | 探针/测试 8 件 17 处 `main._x` 引用(open_save_select 7/seed_value 3/open_settings 2/begin_session 2/status_data 1/start_debug_levels 1/gp_summary_text 1) | 引用形态迁移,断言内容零改动(逐文件 diff 实核) | 卡③ §8 削弱申报第 1 条+实现报告 T1 精确清单 | 申报内,通过 |
|
||||
| 3 | ui_struct_probe.gd :144-146 退出链源码串 2 串("MainEscFlow.on_quit(self)"/"root.quit_game()") | 源码串随公开化换代;同函数 `_on_esc_quit` 私名断言零改动(diff 实核) | 卡③ §8 削弱申报补充(v1.1)第 2 条 | 申报内,通过 |
|
||||
| 4 | ui_struct_probe.gd :366-370 `ls._map._runner` 3 处 | A1 字段公开化交集改址,断言内容零改动 | 卡③ T2 底账(实现报告)+交集判据 | 申报内,通过 |
|
||||
| 5 | stage_background_test.gd :164-165/theme_projection_test.gd :626/:651 | `_beams_rect`/`_gradient_base` 旧私名引用随三工厂公开化换代(stage 为源码 contains 断言随名换代,意图不变) | 提交 a8b0b1b2(里程碑闸 02 域抓出,L2 备案「T1 底账漏 enumeration」)+审计任务书申报集 | 申报内(记录载体=提交信息),通过 |
|
||||
| 6 | ui_input_probe.gd case④b(:264-268 删旧纹理槽双分支断言+注释,换 seal_on 落位单断言) | 旧断言只验证已退役的 tex_seal 机制——test-conventions §5.5 换代批旧验证约束同生死(强制摘除,留即假绿源);新断言同入口(case④b 封印落位)同强度(核心落位硬判) | test-conventions §5.5(法条强制)+提交 13d6bfbb;卡④ §8 削弱申报文本与实现报告未列(欠账,见第五节缺漏 1) | 实体合规;申报记录缺口列缺漏 |
|
||||
| 7 | board_view.gd :582 字形回退分支、:539-541 槽位维护、tile_palette 两槽、cell_mark 绘制块 | 生产行为退役(回退对象消失),非删断言 | 卡④ §8 削弱申报(明示「行为退役不属删断言」)+§7-T4 | 申报内,通过 |
|
||||
| 8 | settlement_wiring_snapshot_test.gd | LF 归位处置——审计实核该文件不在 master...HEAD diff(`git diff --name-only | grep settlement` 零命中)=零内容差异,EOL 往返态未进分支;断言零触碰 | 实现报告「环境红定性 1」 | 申报内,通过 |
|
||||
|
||||
- 申报外删改清点:全 diff 测试/探针面删除行清单(35 行)已逐行对号(上表 1-8),无第 9 类;run_all.gd 仅增 2 行 manifest 注册(sweep+params 两新件),零删改;.tscn/.tres/data 零改动;新增行零 `randomize()`/自建 RNG(红线实核)。
|
||||
- 削弱判定总:无断言删除性削弱、无阈值放宽换绿(两处换代的旧判据各有等强度新判据或三面承载,且均系法条/机制强制)、无扫描面缩小(sweep 四组全带非空前置)、无换下层直调(改锚一处为卡①申报的受控例外)。
|
||||
|
||||
## 四、内部字段直查受控例外核对(逐条)
|
||||
|
||||
| 例外 | 直查行 | 理由注记核对 | 判定 |
|
||||
|---|---|---|---|
|
||||
| 卡①对照表行 3(测试改锚精确余量) | minesweeper_rules_test.gd :56/:89/:93-94 `_rules._safe_remaining()` | 对照表行 3 原文含「**受控例外注记**:精确余量无公开可观测面可钉(`clear_map_cleared` 仅 bool),理由随本表申报」——注记在对照表行内 | 通过 |
|
||||
| 卡④ `_test_fog_gate` 直查 `_seal_layer.visible` | seal_mark_params_test.gd :45/:47/:49/:51(`u._seal_layer` 可见性与空判) | 卡面 §8 R4 判据列自身 prescribe「封印子件 `visible == false`」(fog_state/seal_on 均公开属性,唯一内部面=子件 visible);理由注记落测试件 :40-41 头注(「子件可见性无公开可观测面,卡面 R4 断言即 prescribe」) | 通过(注记位置备注:对照表行本体未带「受控例外」标签,卡面判据列即 prescribe+测试件注记承载) |
|
||||
|
||||
## 五、备案缺漏(零实体影响,不阻塞合并;处置建议随条)
|
||||
|
||||
1. **卡④ ui_input_probe case④b 断言换代的申报记录缺口**——旧纹理槽双分支断言(有盘纹理在槽/缺盘字形回退)随 tex_seal 机制退役被替换为 seal_on 落位断言。实体面合规:test-conventions §5.5 强制同生死摘除(留即假绿源)、新断言同入口同强度、执行绿(回执 03)。缺口在记录面:卡④ §8 削弱申报文本仍写「本批不删改任何既有断言」,与该换代字面冲突(§3 现状既列贴图退役,该换代为必然后果——卡面文本自身欠严密);实现报告亦未列此换代,申报记录只在提交信息 13d6bfbb。处置建议:本报告进实现报告收尾节(卡④ §13 义务)即为补记;后续同类批卡面削弱申报节应把「换代批旧验证约束同生死」列为预设条款。
|
||||
2. **board_view.gd:77 悬空注释**——注释仍写「探针直读面零改动:读 `_palette.seal_tex`…」,所指成员已在本批删除,探针引用面亦已随批迁移,注释陈述已失实。卡②同族悬空注释修了 3 处并备案,卡④面这处未清未申报。零行为零断言影响(判据面=资产引用/常量别名/死槽,注释不在其列);grep 级判据不受污染(`TILE_SEAL_MARK|seal_tex` 命中仅此注释+battle_end_overlay 合法局部变量)。处置建议:并入下批最小工程改动或修复批顺手剥(一行注释)。
|
||||
3. (观察,非缺漏)camp_esc_overlay.gd:8 注释提及 `MainEscFlow._on_return_to_menu` 旧私名——T1 底账已定性「历史名提及非私取面」,与缺漏 2 同族但已在案申报,不再列。
|
||||
|
||||
## 六、grep 取数附录(审计自跑取数,命令+结果)
|
||||
|
||||
以下均在 D:\code\g-plan2-iter52 执行(grep 含 .gd;另注处含 .tscn):
|
||||
|
||||
1. 六孤儿名零残留(.gd+.tscn,`\b名\b` 词边界):`has_effect_on`/`_bp_read_int`/`_find_token`/`has_open`/`set_feedback_state`/`stop_resolved` → 全部零命中。
|
||||
2. 级联计数:`bp_read(` 剥定义=6;`_bp_strategy` 剥定义=1;`find_token`=curio_deck.gd:51 定义+curio_stop.gd:107/:229;`has_open_excluding_tags(` 剥定义=3;camp_scene_view `_apply_state(`=9 行(含定义);curio_stop `_resolved`=15;effect_engine `_triggers`=8;`.dispatch(`=80;curio_stop `_pending`=42 行。六文件+minesweeper_rules 逐函数引用粗扫(剥注释、引擎虚函数豁免)=零孤儿。
|
||||
3. safe_remaining:`\.safe_remaining\(`(.gd+.tscn)=0;`_safe_remaining` 全仓=6(:101/:110/:56/:89/:93/:94)。
|
||||
4. 卡③封装主张:六 B 文件 `root\._[a-zA-Z]`=0;standee_body `\bst\._|\bmo\._`=0;board_view `_hover_comp\._`=0;`UiKit\._[a-zA-Z]`(game/ 全 .gd,排除 ui_kit.gd)=0(ui_kit.gd 内亦 0);A1 三文件 `_map\._[a-zA-Z]`/`\bst\._[a-zA-Z]`=0;game/presentation 全目录 `\._[a-zA-Z]`(剔 self._ 与注释行)=0 行。
|
||||
5. main.gd 计数:`^func [a-zA-Z]`=31+`static func build_adventure_params`=1,合计 32=基线键 32;ui_kit `^(static )?func [a-zA-Z]`=23=基线键 23。
|
||||
6. 卡④贴图退役:`seal_mark.png`(game/ .gd)=恰 1(battle_end_overlay.gd:85);`TILE_SEAL_MARK|seal_tex`=3(battle_end_overlay.gd:85-87 局部变量合法在役+board_view.gd:77 注释);shader `Color8`=0;seal_mark 命中文件=7(cell_unit/board_view/seal_mark_layer/battle_end_overlay/cell_mark_overlay/run_all/params_test——前五为改名件与新件本体,后二为测试注册与守门件)。
|
||||
7. 基线:`grep minesweeper_rules tools/gdstyle_baseline.txt`=0;基线 diff 仅 +2 键(main.gd=32、ui_kit=23);`python tools/gdstyle_gate.py`=「命中 7 条,基线内 7 条,基线外新违规 0 条,较登记值恶化 0 条/ok」。
|
||||
8. diff 面:`git diff master...HEAD --name-only` 中 .tscn/.tres/data/ 与 settlement 测试件=零命中;53 文件合计;新增行 `randomize(|RandomNumberGenerator.new`=零命中。
|
||||
|
||||
## 七、闸回执核对(执行证据)
|
||||
|
||||
- 回执:game/tests/.gates/receipt.json——commit=fbf126d1(=分支最后一笔代码+产出物提交)、domain=code、scope=full、dirty_game=false、八闸(冒烟/系统/单元与集成/场景探针/渲染/色板/静态扫描/熵增)exit 全 0、all_green=true、changed_vs_baseline=[]、inherited_red=[]。
|
||||
- 回执 commit 与分支尖(b4b1ee09=并入 master 的合并提交)差一笔;其间差异经逐文件实核全部为 master 侧内容(AGENTS.md/design 文档/闸名去编号批的 baseline.json 键名与 run_all.gd、system_test.gd、smoke_boot.gd 注释行/tools 脚本措辞)——**零断言面、零生产行为面差异**,回执绿态覆盖分支尖游戏码状态。回执内闸名沿用旧编号命名、合并带来的 baseline.json 已换代无编号键名——命名差属 master 侧闸名批时序,非回执内容问题。
|
||||
- 中档不复跑最窄测试:本报告执行读数全部引回执;**合回后远端 CI 现查为终局执行证据**(tools/ci_check.sh 现查合回提交,判据=run 落定后的绿终局且跑闸步真跑过;零触发批不作绿证)。
|
||||
@@ -185,6 +185,7 @@ def capability_rows():
|
||||
def check_capability_rows(cap_tables, suites, funcs, cards):
|
||||
total = 0
|
||||
names = []
|
||||
referenced = set()
|
||||
suite_by_base = {}
|
||||
for rel in suites:
|
||||
suite_by_base.setdefault(Path(rel).name, []).append(rel)
|
||||
@@ -207,13 +208,25 @@ def check_capability_rows(cap_tables, suites, funcs, cards):
|
||||
red(README.relative_to(REPO), no, "能力行结构",
|
||||
"「%s」行格数不足或空列(%s)" % (name[:16], "/".join(empty) or "列数"))
|
||||
continue
|
||||
referenced.update(m.group(1) for m in CASE_RE.finditer(short("代表用例")))
|
||||
if "条件闸" in short("代表用例"):
|
||||
continue
|
||||
check_cases(no, name, short("代表用例"), suite_by_base, funcs, cards)
|
||||
check_entry(no, name, short("真实入口"), funcs, cards)
|
||||
if total == 0:
|
||||
selfcheck.append("能力表零数据行")
|
||||
return names
|
||||
return names, referenced
|
||||
|
||||
|
||||
def check_suite_coverage(suites, referenced):
|
||||
"""链式锚反向覆盖(test-conventions §8.3 退役对账):run_all.gd manifest 的每个套件
|
||||
必须被 ≥1 个能力行「代表用例」引用——断言(尾缀挂卡/挂套件)→套件→能力行→系统文档
|
||||
的链条中,套件未接能力行=卡片退役后验收意图断链(营地图批先例)。"""
|
||||
missing = [rel for rel in suites if Path(rel).name not in referenced]
|
||||
for rel in sorted(missing):
|
||||
red(README.relative_to(REPO), 1, "链式锚",
|
||||
"套件 %s 未被任何能力行「代表用例」引用——断言→套件→能力行→系统文档链条断环" % rel)
|
||||
return missing
|
||||
|
||||
|
||||
def check_cases(no, name, cell, suite_by_base, funcs, cards):
|
||||
@@ -323,7 +336,8 @@ def main():
|
||||
funcs = product_funcs()
|
||||
if not funcs:
|
||||
selfcheck.append("产品码零 `func`")
|
||||
names = check_capability_rows(cap_tables, suites, funcs, cards_corpus())
|
||||
names, referenced = check_capability_rows(cap_tables, suites, funcs, cards_corpus())
|
||||
missing_suites = check_suite_coverage(suites, referenced)
|
||||
check_coverage(cov_tables, names)
|
||||
|
||||
if selfcheck:
|
||||
@@ -331,9 +345,9 @@ def main():
|
||||
for s in selfcheck:
|
||||
print(" ! " + s)
|
||||
|
||||
print("| ── 能力审计:系统文档 %d 篇 · 能力行 %d · 套件 %d · 覆盖域表 %d 行 · 红项 %d"
|
||||
print("| ── 能力审计:系统文档 %d 篇 · 能力行 %d · 套件 %d · 覆盖域表 %d 行 · 链断套件 %d · 红项 %d"
|
||||
% (len(system_docs()), len(names), len(suites),
|
||||
sum(len(r) for _, r in cov_tables), len(reds)))
|
||||
sum(len(r) for _, r in cov_tables), len(missing_suites), len(reds)))
|
||||
for path, line, check, msg in reds:
|
||||
print(" ✗ [%s] %s:%d %s" % (check, path, line, msg))
|
||||
if selfcheck:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# 质量义务=落批人工确认可跑通(run_all_gates.sh 头注既有口径,不在远端重复烧引擎)。
|
||||
# 3. diff 空 → skip。
|
||||
# 判定面说明:game/tests/** 与 game/sim/** 属 game/ 行为载体(.md 除外)→ full,
|
||||
# 与 run_all_gates.sh 关联档口径一致(测量面批 02 照跑全套件)。
|
||||
# 与 run_all_gates.sh 关联档口径一致(测量面批单元与集成测试照跑全套件)。
|
||||
set -u
|
||||
base="${1:-}"
|
||||
head="${2:-HEAD}"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
门①语义检查属设计面人工核对(§4.2 色相语义判域),不在本器执法面。
|
||||
|
||||
用法:
|
||||
# 主用法(闸机 05b 色板闸承载):扫目录,新增色相对 --baseline 判定
|
||||
# 主用法(闸机色板闸承载):扫目录,新增色相对 --baseline 判定
|
||||
python tools/palette_check.py <目录> --baseline <基线目录>
|
||||
# 无基线:只出读数(单张色数/ 近色对计数),不判红
|
||||
python tools/palette_check.py <目录>
|
||||
|
||||
+26
-4
@@ -8,7 +8,7 @@ r"""pipeline_gate.py — 工作流程流水线闸(待办清单条目状态机
|
||||
分档放行)/需求卡片口径(C1 文档义务/C2 设计事实源/C3 改动—验收对照表/C4 验收档申报)+一次交叉核。
|
||||
约束:每红项一行「文件:行号 判据名 一句白话说明」,exit 0=全绿 / 1=有红 / 2=输入件缺失;
|
||||
卡片与报告存在性相对 --repo-root 解析(缺省=本文件上两级);待办清单与 roadmap 均已为新格式
|
||||
(2026-10-18 数据整改批),本闸已注册进 tools/run_all_gates.sh 文档域(08c 流水线闸)。
|
||||
(2026-10-18 数据整改批),本闸已注册进 tools/run_all_gates.sh 文档域(流水线闸)。
|
||||
用法:python tools/pipeline_gate.py [--todo PATH] [--roadmap PATH] [--repo-root PATH]
|
||||
"""
|
||||
import argparse
|
||||
@@ -63,6 +63,9 @@ CAP_README = Path("game/tests/README.md")
|
||||
# C4 验收档申报(2026-11-04 验收强度分级批,生效 2026-11-05;test-conventions §8.3)
|
||||
GRADE_RULE_DATE = (2026, 11, 5)
|
||||
GRADE_RE = re.compile(r"验收档\s*[::]\s*[高中低]")
|
||||
# C5 判据出处行锚(2026-11-05 立;test-conventions §8.3:需求点格须带现行文档判据句锚)
|
||||
ANCHOR_RULE_DATE = (2026, 11, 5)
|
||||
ANCHOR_RE = re.compile(r"([A-Za-z0-9_\-.\\/]+\.(?:md))\s*:\s*(\d+)")
|
||||
# 待办条目正文限长双判据(2026-11-04 立,doc-conventions §12.1:行数抓清单蔓延、字数抓单行堆砌)
|
||||
ENTRY_MAX_LINES = 12
|
||||
ENTRY_MAX_CHARS = 700
|
||||
@@ -498,10 +501,19 @@ def capability_names(root):
|
||||
return names
|
||||
|
||||
|
||||
def check_ledger(text, path, when, issues, root):
|
||||
"""C3 改动—验收对照表结构检查(生效 2026-10-21)。
|
||||
def anchor_valid(root, rel, lineno):
|
||||
"""判据出处行锚有效性:文档存在且行号在行数范围内(相对仓库根解析)。"""
|
||||
p = root / rel.replace("\\", "/")
|
||||
if not p.is_file():
|
||||
return False
|
||||
return 1 <= lineno <= len(p.read_text(encoding="utf-8-sig").splitlines())
|
||||
|
||||
只查:对照表节在不在、表头有没有五个必需列、有没有数据行、必填格空不空。
|
||||
|
||||
def check_ledger(text, path, when, issues, root):
|
||||
"""C3 改动—验收对照表结构检查(生效 2026-10-21);C5 判据出处行锚(生效 2026-11-05)。
|
||||
|
||||
只查:对照表节在不在、表头有没有五个必需列、有没有数据行、必填格空不空;
|
||||
C5=生效日后需求点格须带现行文档行锚且指向存在(test-conventions §8.3)。
|
||||
不判断测试是否真的覆盖改动——那是独立验收审计的职责,机器闸不猜语义。
|
||||
"""
|
||||
lines = text.splitlines()
|
||||
@@ -614,6 +626,16 @@ def check_ledger(text, path, when, issues, root):
|
||||
issues.append((str(path), i + 1, "能力行不可核",
|
||||
"既有能力「%s」不在 game/tests/README.md 能力表"
|
||||
% cap_name[:24]))
|
||||
if when >= ANCHOR_RULE_DATE:
|
||||
point_cell = cells[idx["需求点"]] if idx.get("需求点", 99) < len(cells) else ""
|
||||
anchors = ANCHOR_RE.findall(point_cell)
|
||||
if not anchors:
|
||||
issues.append((str(path), i + 1, "判据出处行锚缺失",
|
||||
"「需求点」格须带判据出处行锚 `<现行文档相对路径>:<行号>`"
|
||||
"(2026-11-05 起,test-conventions §8.3)"))
|
||||
elif not any(anchor_valid(root, rel, int(no)) for rel, no in anchors):
|
||||
issues.append((str(path), i + 1, "判据出处行锚不可核",
|
||||
"锚指向的文档或行号不存在:%s" % point_cell[:40]))
|
||||
if rows == 0:
|
||||
issues.append((str(path), header_line, "验收对照表零行",
|
||||
"表内没有数据行"))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# 渲染闸正主——窗口化自动闸。
|
||||
# 范围(渲染五闸的机器面:shot_probe/golden_compare/board_shot 三件入闸;
|
||||
# fx_probe 逻辑层归 03 场景探针闸;1920 档布局机检面待补)。
|
||||
# fx_probe 逻辑层归场景探针闸;1920 档布局机检面待补)。
|
||||
# 骨架复用 probe_gate:①每段 timeout 守卫(挂死=FAIL 不静默)②段前预清+段后清本 game 目录孤儿
|
||||
# Godot(按命令行精确匹配本 game 路径,不误杀其他 worktree 会话)③末尾残留清点=批末闸(必须 0)。
|
||||
# 段:
|
||||
|
||||
+53
-53
@@ -9,16 +9,16 @@
|
||||
# 跑闸时代码面带着未提交改动,回执会标 dirty_game(验的不是 HEAD 字节)。
|
||||
#
|
||||
# 用法:tools/run_all_gates.sh [--code|--docs|--quick]
|
||||
# --code 只跑代码域闸(00 冒烟测试/01 系统测试/02 单元与集成测试/03 场景探针/
|
||||
# 05 渲染闸/09 静态扫描+10 熵增闸)
|
||||
# --code 只跑代码域闸(冒烟测试/系统测试/单元与集成测试/场景探针/
|
||||
# 渲染闸/静态扫描+熵增闸)
|
||||
# ——本批改动含 game/ 下非 .md 的行为载体(代码/测试脚本/探针/场景/数据表/素材)时用。
|
||||
# 关联档选闸(2026-10-29 用户裁,推广自 2026-10-28 影响面选闸):00 冒烟/01 系统测试/
|
||||
# 09 静态扫描三件保险恒跑不降;03 场景探针与 05 渲染闸维持影响面口径(本批 game/ 改动
|
||||
# 全在测量面 game/tests、game/sim 时记 SKIP);02 单元与集成改「选套件跑」——套件集=
|
||||
# 关联档选闸(2026-10-29 用户裁,推广自 2026-10-28 影响面选闸):冒烟测试/系统测试/
|
||||
# 静态扫描三件保险恒跑不降;场景探针与渲染闸维持影响面口径(本批 game/ 改动
|
||||
# 全在测量面 game/tests、game/sim 时记 SKIP);单元与集成测试改「选套件跑」——套件集=
|
||||
# 需求卡片申报 ∪ diff 推导并集(算法与套件族映射表见脚本中部),横切面(公共件/数据表/
|
||||
# autoload/数值·存档·RNG·结算触面)回落全套件;回执 scope 字段记 full|related。
|
||||
# --docs 只跑文档域闸(06 gdd_lint/07 doc_link/08 doc_term/08c 流水线闸/08d 引用可核/
|
||||
# 08e 能力审计+10 熵增闸)
|
||||
# --docs 只跑文档域闸(gdd_lint/doc_link/doc_term/流水线闸/引用可核/
|
||||
# 能力审计+熵增闸)
|
||||
# ——本批改动只有文档件时用:game/ 内的 .md(README、生成清单)、design/、根规则文件、
|
||||
# tools/ 工具脚本、.zcode/ 配置等一切非代码面改动。
|
||||
# --quick 全量档的中段自检形态:跳过渲染闸(窗口化,需开显示器)与静态扫描;完成出库禁用。
|
||||
@@ -70,7 +70,7 @@ if [ "$DOMAIN" = "code" ] || [ "$DOMAIN" = "full" ]; then
|
||||
fi
|
||||
|
||||
# 控制台编码:本仓库闸件输出中文与 ✅/✗ 符号。Windows GBK 控制台下 python 打印这些字符会抛
|
||||
# UnicodeEncodeError——待办清单/10 两闸直接崩(假红)、09 的 FAIL 行被写成乱码字节(指纹漂移,
|
||||
# UnicodeEncodeError——待办清单/熵增两闸直接崩(假红)、静态扫描的 FAIL 行被写成乱码字节(指纹漂移,
|
||||
# 与基线比必判「红项清单变化」假红)、末尾汇总自身崩掉打不出结论。
|
||||
export PYTHONIOENCODING=utf-8
|
||||
|
||||
@@ -207,10 +207,10 @@ suite_terms_for() { # suite_terms_for <仓库相对路径> → stdout: 套件
|
||||
}
|
||||
|
||||
# ── 关联档选闸(2026-10-29 用户裁,推广自 2026-10-28 影响面选闸)──
|
||||
# 三件保险恒跑不降:00 冒烟/01 系统测试/09 静态扫描(10 熵增闸照旧两域都跑)。
|
||||
# 03 场景探针与 05 渲染闸维持影响面口径:本批 diff 相对 master 分叉点的 game/ 改动若全部落在
|
||||
# 三件保险恒跑不降:冒烟测试/系统测试/静态扫描(熵增闸照旧两域都跑)。
|
||||
# 场景探针与渲染闸维持影响面口径:本批 diff 相对 master 分叉点的 game/ 改动若全部落在
|
||||
# 测量面(game/tests/**、game/sim/**——测试与模拟驱动件,不触场景树与渲染输出)则记 SKIP。
|
||||
# 02 单元与集成改「选套件跑」:套件集=申报 ∪ 推导 取并集——
|
||||
# 单元与集成测试改「选套件跑」:套件集=申报 ∪ 推导 取并集——
|
||||
# 申报:在册需求卡片(本批 diff 触及的 reports/需求卡片*.md ∪ roadmap「进行中」迭代行登记的
|
||||
# 卡片)对照表「验收测试」列提到的测试文件名,按文件名作为 --only 子串词归套件;
|
||||
# 找不到在册卡片则申报集为空并输出注明。
|
||||
@@ -218,9 +218,9 @@ suite_terms_for() { # suite_terms_for <仓库相对路径> → stdout: 套件
|
||||
# 映射不到的文件一律按横切处理。
|
||||
# 横切回落全量:diff 命中 game/data/tables/**、公共件前缀(config_db*/rng_service*/
|
||||
# save_manager*/meta_progression*/main*——main* 覆盖组合根拆件与主场景)、
|
||||
# autoload 注册面(game/project.godot)、或下方横切触面表任一 → 02 跑全部套件。
|
||||
# 测量面批(game/ 改动全在 tests/sim):02 照旧全套件跑(不加过滤)。
|
||||
# 回执 scope 字段:full|related(02 跑子集=related);映射表只在本脚本一处定义。
|
||||
# autoload 注册面(game/project.godot)、或下方横切触面表任一 → 单元与集成测试跑全部套件。
|
||||
# 测量面批(game/ 改动全在 tests/sim):单元与集成测试照旧全套件跑(不加过滤)。
|
||||
# 回执 scope 字段:full|related(单元与集成测试跑子集=related);映射表只在本脚本一处定义。
|
||||
NONBEHAVIOR=0
|
||||
SCOPE="full"
|
||||
ONLY_TERMS=""
|
||||
@@ -231,9 +231,9 @@ if in_domain code; then
|
||||
_behavior="$(echo "$_gfiles" | grep -vE '^(game/tests/|game/sim/)' || true)"
|
||||
if [ -n "$_gfiles" ] && [ -z "$_behavior" ]; then
|
||||
NONBEHAVIOR=1
|
||||
echo "[gates] 影响面选闸:game/ 改动全在测量面(tests/sim)——03 场景探针/05 渲染闸 → SKIP(00/01/09 三件保险恒跑)"
|
||||
echo "[gates] 影响面选闸:game/ 改动全在测量面(tests/sim)——场景探针/渲染闸 → SKIP(冒烟测试/系统测试/静态扫描三件保险恒跑)"
|
||||
fi
|
||||
# ── 02 选套件推导(只对行为面代码文件做——测量面文件不进推导,其验证就是 02/09 自身)──
|
||||
# ── 选套件推导(只对行为面代码文件做——测量面文件不进推导,其验证就是单元与集成测试/静态扫描自身)──
|
||||
_codefiles="$(echo "$_gfiles" | grep -viE '\.md$' | grep -vE '^(game/tests/|game/sim/)' || true)"
|
||||
if [ -n "$_codefiles" ]; then
|
||||
CROSSCUT=0
|
||||
@@ -269,7 +269,7 @@ if in_domain code; then
|
||||
done
|
||||
if [ "$CROSSCUT" -eq 1 ]; then
|
||||
SCOPE="full"
|
||||
echo "[gates] 关联档选闸:diff 命中横切面(公共件/数据表/autoload/数值·存档·RNG·结算触面)——02 回落全部套件"
|
||||
echo "[gates] 关联档选闸:diff 命中横切面(公共件/数据表/autoload/数值·存档·RNG·结算触面)——单元与集成测试回落全部套件"
|
||||
else
|
||||
# 并集去重:推导族词 ∪ 申报测试文件名;并集非空才过滤(映射表保证族词非空,此处双保险)。
|
||||
_union="$(printf '%s\n' $_family_terms $_declared_names | sed '/^$/d' | sort -u | tr '\n' ' ' || true)"
|
||||
@@ -285,12 +285,12 @@ if in_domain code; then
|
||||
echo "[gates] 关联档选闸·申报:未找到在册需求卡片(diff 与 roadmap 进行中行均无),申报集为空——仅按 diff 推导"
|
||||
fi
|
||||
if [ "$SCOPE" = related ]; then
|
||||
echo "[gates] 关联档选闸:02 选套件跑(--only=${ONLY_TERMS})"
|
||||
echo "[gates] 关联档选闸:单元与集成测试选套件跑(--only=${ONLY_TERMS})"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── 代码域起手自检(闸承载:只省烧闸,不做合回判定——真判定在 00–11 与合回 guard)──
|
||||
# ── 代码域起手自检(闸承载:只省烧闸,不做合回判定——真判定在各闸与合回 guard)──
|
||||
if in_domain code; then
|
||||
# worktree 素材同步:素材走 gitignore 不入 git,worktree 冷检出缺件=呈现断言红的环境成因;
|
||||
# 主工作区直跑=脚本内自动无操作。
|
||||
@@ -332,7 +332,7 @@ gate() { # gate <名称> <日志名> <命令...>
|
||||
}
|
||||
|
||||
gate_unit() { # run_all 是 --script 模式,退出码为唯一判据;分片态=多 Godot 进程各跑一片
|
||||
local name="02 单元与集成测试"
|
||||
local name="单元与集成测试"
|
||||
# 关联档选跑:把套件词列表经 --only= 传给 run_all(闸机来源标记 --only-source=gates,
|
||||
# 入口据此打关联档横幅、不落「仅供开发期」免责句);全量态不传任何选跑参数。
|
||||
local -a _user_args=()
|
||||
@@ -396,63 +396,63 @@ gate_unit() { # run_all 是 --script 模式,退出码为唯一判据;分
|
||||
return 0
|
||||
}
|
||||
|
||||
# ══ 代码域(0–5)══
|
||||
# ══ 代码域 ══
|
||||
if in_domain code; then
|
||||
# ── 0. 冒烟测试(极小启动场景:真实开机路径存活检查,零逻辑判定,秒级)──
|
||||
# 三件保险之一(00/01/09):恒跑不降——测量面批也不免(关联档选闸,2026-10-29 用户裁)。
|
||||
gate "00 冒烟测试" "smoke_boot.log" "$PY" "$REPO/tools/run_smoke.py"
|
||||
# ── 1. 系统测试(真实玩法路径断言面;宿主=game/tests/system_test.gd,缺省 --script 由 run_system_test.py 持有)──
|
||||
gate "01 系统测试" "system_test.log" "$PY" "$REPO/tools/run_system_test.py"
|
||||
# ── 2. 单元与集成测试 ──
|
||||
# ── 冒烟测试(极小启动场景:真实开机路径存活检查,零逻辑判定,秒级)──
|
||||
# 三件保险之一(冒烟测试/系统测试/静态扫描):恒跑不降——测量面批也不免(关联档选闸,2026-10-29 用户裁)。
|
||||
gate "冒烟测试" "smoke_boot.log" "$PY" "$REPO/tools/run_smoke.py"
|
||||
# ── 系统测试(真实玩法路径断言面;宿主=game/tests/system_test.gd,缺省 --script 由 run_system_test.py 持有)──
|
||||
gate "系统测试" "system_test.log" "$PY" "$REPO/tools/run_system_test.py"
|
||||
# ── 单元与集成测试 ──
|
||||
gate_unit
|
||||
# ── 3. 场景探针(走查+断言十件一次跑齐;iter27 漏跑断言段事故后固化为无条件整闸)──
|
||||
# ── 场景探针(走查+断言十件一次跑齐;iter27 漏跑断言段事故后固化为无条件整闸)──
|
||||
if [ $NONBEHAVIOR -eq 1 ]; then
|
||||
NAMES+=("03 场景探针"); EXITS+=("SKIP"); LOGS+=("")
|
||||
echo ""; echo "[gates] 03 场景探针 → SKIP(影响面选闸:测量面改动不触场景树与探针断言面)"
|
||||
NAMES+=("场景探针"); EXITS+=("SKIP"); LOGS+=("")
|
||||
echo ""; echo "[gates] 场景探针 → SKIP(影响面选闸:测量面改动不触场景树与探针断言面)"
|
||||
else
|
||||
gate "03 场景探针" "probe.log" bash "$REPO/tools/probe_gate.sh" "$GAME"
|
||||
gate "场景探针" "probe.log" bash "$REPO/tools/probe_gate.sh" "$GAME"
|
||||
fi
|
||||
# ── 5. 渲染面(窗口化,依赖 PIL)──
|
||||
# ── 渲染闸(窗口化,依赖 PIL)──
|
||||
if [ $QUICK -eq 1 ] || [ $NONBEHAVIOR -eq 1 ]; then
|
||||
NAMES+=("05 渲染闸"); EXITS+=("SKIP"); LOGS+=("")
|
||||
echo ""; echo "[gates] 05 渲染闸 → SKIP(--quick 或 影响面选闸:测量面改动不触渲染输出)"
|
||||
NAMES+=("渲染闸"); EXITS+=("SKIP"); LOGS+=("")
|
||||
echo ""; echo "[gates] 渲染闸 → SKIP(--quick 或 影响面选闸:测量面改动不触渲染输出)"
|
||||
else
|
||||
gate "05 渲染闸" "render.log" bash "$REPO/tools/render_gate.sh" "$GAME"
|
||||
gate "渲染闸" "render.log" bash "$REPO/tools/render_gate.sh" "$GAME"
|
||||
fi
|
||||
# ── 5b. 色板闸(§4.1 新色双门②:素材新增色 vs 基线〔token∪素材快照〕近色判红;
|
||||
# ── 色板闸(§4.1 新色双门②:素材新增色 vs 基线〔token∪素材快照〕近色判红;
|
||||
# 门①语义检查属设计面人工核对不入机检;基线刷新=tools/gen_palette_baseline.py,素材批收尾动作)──
|
||||
if [ $QUICK -eq 1 ] || [ $NONBEHAVIOR -eq 1 ]; then
|
||||
NAMES+=("05b 色板闸"); EXITS+=("SKIP"); LOGS+=("")
|
||||
echo ""; echo "[gates] 05b 色板闸 → SKIP(--quick 或 影响面选闸:素材色板面不随测量面改动开闸)"
|
||||
NAMES+=("色板闸"); EXITS+=("SKIP"); LOGS+=("")
|
||||
echo ""; echo "[gates] 色板闸 → SKIP(--quick 或 影响面选闸:素材色板面不随测量面改动开闸)"
|
||||
else
|
||||
gate "05b 色板闸" "palette.log" "$PY" "$REPO/tools/palette_check.py" "$GAME/assets/art" --baseline "$REPO/game/tests/golden/palette_baseline"
|
||||
gate "色板闸" "palette.log" "$PY" "$REPO/tools/palette_check.py" "$GAME/assets/art" --baseline "$REPO/game/tests/golden/palette_baseline"
|
||||
fi
|
||||
fi
|
||||
# ══ 文档域(6–8e)══
|
||||
# ══ 文档域 ══
|
||||
if in_domain docs; then
|
||||
# 全量档(CI 与手动档同判定面)
|
||||
gate "06 gdd_lint" "gdd_lint.log" "$PY" "$REPO/tools/gdd_lint.py"
|
||||
gate "06b 变更记录节" "changelog.log" "$PY" "$REPO/tools/gdd_lint.py" --changelog-only
|
||||
gate "07 doc_link" "doc_link.log" "$PY" "$REPO/tools/doc_link_audit.py" --strict
|
||||
gate "08 doc_term" "doc_term.log" "$PY" "$REPO/tools/doc_term_audit.py" --strict
|
||||
gate "08c 流水线闸" "pipeline.log" "$PY" "$REPO/tools/pipeline_gate.py"
|
||||
gate "08d 引用可核" "doc_ref.log" "$PY" "$REPO/tools/doc_ref_audit.py" --strict
|
||||
gate "08e 能力审计" "capability.log" "$PY" "$REPO/tools/capability_audit.py" --strict
|
||||
gate "gdd_lint" "gdd_lint.log" "$PY" "$REPO/tools/gdd_lint.py"
|
||||
gate "变更记录节" "changelog.log" "$PY" "$REPO/tools/gdd_lint.py" --changelog-only
|
||||
gate "doc_link" "doc_link.log" "$PY" "$REPO/tools/doc_link_audit.py" --strict
|
||||
gate "doc_term" "doc_term.log" "$PY" "$REPO/tools/doc_term_audit.py" --strict
|
||||
gate "流水线闸" "pipeline.log" "$PY" "$REPO/tools/pipeline_gate.py"
|
||||
gate "引用可核" "doc_ref.log" "$PY" "$REPO/tools/doc_ref_audit.py" --strict
|
||||
gate "能力审计" "capability.log" "$PY" "$REPO/tools/capability_audit.py" --strict
|
||||
fi
|
||||
|
||||
# ── 7. 静态扫描(代码域)+ 熵增闸(两域都跑:它查顶层目录/根文件/图像白名单/退役路径,
|
||||
# ── 静态扫描(代码域)+ 熵增闸(两域都跑:它查顶层目录/根文件/图像白名单/退役路径,
|
||||
# 文档批新增或挪动 design/ 下的文件同样会绊它;纯文本扫描,秒级)──
|
||||
if [ $QUICK -eq 0 ]; then
|
||||
if in_domain code; then
|
||||
gate "09 静态扫描" "static_scan.log" bash "$GAME/tests/static_scan.sh"
|
||||
gate "静态扫描" "static_scan.log" bash "$GAME/tests/static_scan.sh"
|
||||
fi
|
||||
gate "10 熵增闸" "entropy.log" "$PY" "$REPO/tools/repo_structure_audit.py"
|
||||
gate "熵增闸" "entropy.log" "$PY" "$REPO/tools/repo_structure_audit.py"
|
||||
else
|
||||
if in_domain code; then
|
||||
NAMES+=("09 静态扫描"); EXITS+=("SKIP"); LOGS+=("")
|
||||
NAMES+=("静态扫描"); EXITS+=("SKIP"); LOGS+=("")
|
||||
fi
|
||||
NAMES+=("10 熵增闸"); EXITS+=("SKIP"); LOGS+=("")
|
||||
echo ""; echo "[gates] 09 静态扫描(代码域)/ 10 熵增闸 → SKIP(--quick)"
|
||||
NAMES+=("熵增闸"); EXITS+=("SKIP"); LOGS+=("")
|
||||
echo ""; echo "[gates] 静态扫描(代码域)/ 熵增闸 → SKIP(--quick)"
|
||||
fi
|
||||
|
||||
# ── 与存量基线比对 ──
|
||||
|
||||
@@ -286,3 +286,11 @@
|
||||
**改动面**:游戏代码
|
||||
|
||||
**状态**:文档设计已闭合+已写卡+已编迭代 52
|
||||
|
||||
#### 测试面真输入化分期与存量断言逐条精锚(2026-11-05 登记,来源=批次移交)
|
||||
|
||||
**实况**:证据=test-conventions §8.3「判据出处行锚」「真实入口判定口径」两条文(本批落);链式锚机检已在闸(capability_audit 链断 0,80 套件全承接)。剩余面=①营地七物件段等 ~40 处 emit 站点仍为接线验证(大门/进档链已于本批真输入化,能力行 :158 残险在案)②存量 996 条断言的判据出处逐条精锚(链式锚已保可核,精锚提升出处粒度)。
|
||||
|
||||
**改动面**:游戏代码
|
||||
|
||||
**状态**:待执行
|
||||
Reference in new issue
Block a user