diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6650ab1a..2ae4487d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,8 +1,9 @@ name: Automated Tests -# 注意:本仓库 2026-09-12 尚未初始化 git——本 workflow 在首次 push 到 GitHub 后自动生效。 +# 注意:仓库已初始化 git(尚无远端)——本 workflow 在首次 push 到 GitHub 后自动生效。 # 载体 = ADR-0004(双载体):逻辑冒烟 + 场景探针;gdUnit4 deferred(不使用 gdUnit4-action)。 # 外部 wall-clock 超时(timeout 命令)为 ADR-0004 硬性要求——引擎自身无死锁探测。 +# 路径口径:2026-09-27 三层收敛(7f24b640)后工程在 game/——tests 归 game/tests/、探针在 game/smoke/。 on: push: @@ -19,7 +20,7 @@ jobs: uses: actions/checkout@v4 - name: Run static scan - run: bash tests/static_scan.sh + run: bash game/tests/static_scan.sh smoke: name: Headless smoke (Godot 4.7.2) @@ -33,15 +34,15 @@ jobs: with: version: 4.7.2 - # 逻辑冒烟(run_all.gd 内登记套件 manifest;正式工程落地后生效) + # 逻辑冒烟(run_all.gd 内登记套件 manifest) - name: Run smoke runner (external timeout per ADR-0004) - run: timeout 120s godot --headless --script tests/run_all.gd + run: timeout 120s godot --headless --path game --script res://tests/run_all.gd - # 场景探针(正式工程落地后逐条登记,示例形态): + # 场景探针(逐条登记,示例形态): # - name: Run UI probes # run: | - # timeout 60s godot --headless --path . res://tests/probes/ui_probe.tscn - # timeout 60s godot --headless --path . res://tests/probes/ui_click_probe.tscn + # timeout 60s godot --headless --path game res://smoke/ui_probe.tscn + # timeout 60s godot --headless --path game res://smoke/ui_click_probe.tscn - name: Upload Test Results if: always() diff --git a/CLAUDE.md b/CLAUDE.md index bf114c15..6facbd8b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,7 +19,7 @@ 工作目录 = 切片目录本身(含 `project.godot` 的那一层): - 冒烟(全量 headless 断言):`python tools/run_smoke.py`(包装器三闸:退出码+摘要失败数+SCRIPT ERROR 扫描——脚本错误不计冒烟失败数且静默中断所在函数剩余断言,2026-09-19 台账 84 立闸)。底层命令 = `…console.exe --headless --path . --script res://smoke/smoke_all.gd` -- 场景级探针(呈现层回归):`…console.exe --headless --path . res://smoke/ui_probe.tscn`;另有 `ui_tune_probe.tscn`(数值调整板)、`ui_click_probe.tscn`(合成鼠标事件行为探针) +- 场景级探针(呈现层回归):`…console.exe --headless --path . res://smoke/ui_probe.tscn`;另有 `ui_tune_probe.tscn`(调试浮窗——2026-10-04 迭代 14.5 起原数值调整板收进 debug_overlay)、`ui_click_probe.tscn`(合成鼠标事件行为探针) - 调参期批量工具:`--script res://smoke/adventure_monte_carlo.gd`(全冒险期望扫描)· `--script res://smoke/reward_expectation.gd`(奖励获取期望)——单关直入口口径已退役(2026-09-23 用户拍板),通关率/难度类测量一律走全冒险(原 level_monte_carlo/level_debug 已删) - 数值验证工具:`python tools/balance_verifier.py`(零强化冒险逐关条件通关率+止步节点归因+营地循环爬升战役——采集端 `--script res://smoke/verifier_batch.gd`,报告落 `design/qa/`;元进度换算率标定与曲线调参的自动化评判面,2026-09-22 数值验证工具批;直入口带判定随口径退役暂停,带重锚归曲线调参批) - 交付前验收 = smoke + 全部场景探针全绿(测试细则见 `design/dev/code-conventions.md`) diff --git a/game/README.md b/game/README.md index e35159ad..d1d314aa 100644 --- a/game/README.md +++ b/game/README.md @@ -13,9 +13,9 @@ 1. 用 Godot 4.7.2 打开本目录(含 `project.godot` 的文件夹) 2. 按 F5 运行(主场景 `presentation/main.tscn`) 3. **主入口:`▶ 开始冒险(三关连探:地精洞窟 → 幽暗地域 → 灰矮人矿城)`**——一条命走完三关(冒险结构实现批 2026-09-21:生命/GP/加算区跨关同账、非末关通关发大奖励〔上限提升+血回满+钥石〕、任意战斗倒下冒险终、结算屏出冒险摘要五件事;选路停点可「放弃冒险」(同失败结算,2026-09-21 用户拍板补入口));首关节点链:战→战→赏→战→战→疗→王。唯一试玩入口 = 完整冒险——单关测试直入口(L2/L3)已退役(2026-09-23 用户拍板) -4. `测试用 · 角色数值调整板`:攻击/生命百分比加成(模拟天赋树解锁)+ 批量模拟(输出通关率/承伤期望/败北节点分布) +4. `调试` 角标浮窗(开始界面右下角,`DS_DEBUG=1` 门控——2026-10-04 迭代 14.5 调试整合批:原数值调整板/随机种子框/两层调试三散件收一):攻击/生命百分比加成(模拟天赋树解锁)+ 批量模拟(输出通关率/承伤期望/败北节点分布)+ 两层调试入口 -headless 冒烟(55 项断言,含关卡线性推进/满配通关/裸装败北/回放确定性,约 30 秒): +headless 冒烟(752 项断言〔计数随批增长,现值以最新批末闸读数为准〕,含关卡线性推进/满配通关/裸装败北/回放确定性;2026-10-02 性能报告实测 60.55 秒,报告在 `design/qa/test-perf-report-2026-10-02.md`): ``` Godot_v4.7.2-stable_win64_console.exe --headless --path . --script res://smoke/smoke_all.gd @@ -27,13 +27,13 @@ Godot_v4.7.2-stable_win64_console.exe --headless --path . --script res://smoke/s Godot_v4.7.2-stable_win64_console.exe --headless --path . res://smoke/ui_probe.tscn ``` -数值调整板场景探针(缺陷⑤回归:打开可见性/滑条联动/应用写表/重置/批量模拟全链路): +调试浮窗场景探针(缺陷⑤回归载体沿袭——2026-10-04 迭代 14.5 随批改接浮窗形态:打开可见性〔浮于菜单之上,开始层不隐藏〕/滑条联动/应用写表/重置/批量模拟全链路): ``` Godot_v4.7.2-stable_win64_console.exe --headless --path . res://smoke/ui_tune_probe.tscn ``` -其余七场景探针(九探针全 roster 登记——ui_click_probe 行为链 / ui_input_probe 输入合成 / ui_layout_probe 布局 / shot_probe·fx_probe·fx_shot_probe·board_shot_probe 画面与特效采样,同上式运行)+ 板图校准工具 `smoke/calibrate_boards.gd`(board_calibration.csv 重跑入口,--script 运行): +其余八场景探针(十探针全 roster 登记——ui_click_probe 行为链 / ui_input_probe 输入合成 / ui_layout_probe 布局 / t17_defer_probe 结算演播延迟链回归 / shot_probe·fx_probe·fx_shot_probe·board_shot_probe 画面与特效采样,同上式运行)+ 板图校准工具 `smoke/calibrate_boards.gd`(board_calibration.csv 重跑入口,--script 运行): 全冒险期望扫描(零加成三关连探批量——通关率/止步分布/败退节点;调参期难度读数一律走全冒险口径): @@ -43,15 +43,11 @@ Godot_v4.7.2-stable_win64_console.exe --headless --path . --script res://smoke/a (原关卡期望扫描 level_monte_carlo.gd 走单关直入口口径——满血零上下文进关与真实冒险脱节,随口径退役删除,2026-09-23 用户拍板。) -可选类供给跨种子扫描(playtest-2026-09-12 Top1 复核——每局治疗包/小刀/精工短刀获取数、构成占比对 9:1 配比、"≥3 治疗包"局数分布;单种子坏抽与系统性偏置由此分割): +(原可选类供给跨种子扫描 supply_scan.gd 随可选类道具/库存/供给控制器整体删除而退役——2026-09-15 格面资源批,扫描对象已不存在。) -``` -Godot_v4.7.2-stable_win64_console.exe --headless --path . --script res://smoke/supply_scan.gd -- [N] [seed0] -``` +**日志合规(2026-09-12 用户要求)**:任何模拟运行与真人试玩均落全量 JSONL(user://logs/)——逐操作(op/cell/accepted/round)、逐结算明细行、轮次状态快照、battle_end、level_end。模拟(verifier/adventure_monte_carlo / 调试浮窗批量模拟)一文件多局,run 行携带种子/档位切分局次。 -**日志合规(2026-09-12 用户要求)**:任何模拟运行与真人试玩均落全量 JSONL(user://logs/)——逐操作(op/cell/accepted/round)、逐结算明细行、轮次状态快照、battle_end、level_end。模拟(verifier/adventure_monte_carlo / 调整板批量模拟 / supply_scan)一文件多局,run 行携带种子/档位切分局次。 - -**试玩画像口径(2026-09-19 用户拍板固化——全项目试玩/扫描/面板模拟一律只用以下两档,随机策略口径退役)**:`policy="normal"` = **普通画像·基础定式**(单数字满足规则——满足即标/满足即开,无处可推盲挖边界格、不刷新;教学后正常玩家的下限近似);`policy="perfect"` = **完美画像**(single+subset 全推理零盲挖/卡死刷新——技能上界仪)。实现单一出口 = `smoke/auto_player.gd`(novice_action / perfect_action)经 `smoke/level_autoplay.gd`,调整板批量模拟与各扫描工具自动同口径;战斗层冒烟夹具与调试转储的 `choose_dig` 直调是机制测试夹具、不承载画像语义。分级依据与新旧读数(乱点 0%/5% → 基础定式 65%/90%)见 auto_player.gd 普通策略档节与台账 77。 +**试玩画像口径(2026-09-19 用户拍板固化——全项目试玩/扫描/面板模拟一律只用以下两档,随机策略口径退役)**:`policy="normal"` = **普通画像·基础定式**(单数字满足规则——满足即标/满足即开,无处可推盲挖边界格、不刷新;教学后正常玩家的下限近似);`policy="perfect"` = **完美画像**(single+subset 全推理零盲挖/卡死刷新——技能上界仪)。实现单一出口 = `smoke/auto_player.gd`(novice_action / perfect_action)经 `smoke/level_autoplay.gd`,调试浮窗批量模拟与各扫描工具自动同口径;战斗层冒烟夹具与调试转储的 `choose_dig` 直调是机制测试夹具、不承载画像语义。分级依据与新旧读数(乱点 0%/5% → 基础定式 65%/90%)见 auto_player.gd 普通策略档节与台账 77。 单关诊断工具(level_debug.gd)随单关直入口口径退役(2026-09-23)——败退归因走 balance_verifier 冒险段(层/节点/敌人人读归因)。 战斗级工具(v1 遗产):`dump_battle.gd`(结算流水)/ `monte_carlo.gd`(战斗期望)/ `experiment_density.gd`(密度调参)。 diff --git a/game/tests/README.md b/game/tests/README.md index d807138e..c019bdd2 100644 --- a/game/tests/README.md +++ b/game/tests/README.md @@ -2,9 +2,9 @@ **Engine**: Godot 4.7.2-stable(GDScript 单语言) **Test Framework**: 双载体(ADR-0004)——`--headless --script` 逻辑冒烟 + headless 场景探针;gdUnit4 **deferred**(D2 OQ1 关闭形态,正式 CI 期再议) -**CI**: `.github/workflows/tests.yml`(首次 push 到 GitHub 后自动生效;仓库 2026-09-12 尚未初始化 git) -**Setup date**: 2026-09-12 -**参考实现**: `game/smoke/`(冒烟 628+ 断言 + 九场景探针——正式工程的活样板) +**CI**: `.github/workflows/tests.yml`(首次 push 到 GitHub 后自动生效;仓库已初始化 git、尚未配置远端) +**Setup date**: 2026-09-12(2026-09-27 `7f24b640` 三层收敛:根 tests/ 并入 `game/tests/`、docs 并入 `design/dev/`、production 解散) +**参考实现**: `game/smoke/`(冒烟 752+ 断言 + 十场景探针——正式工程的活样板) ## Directory Layout @@ -21,7 +21,7 @@ tests/ ## Running Tests ```bash -# 逻辑冒烟(双载体之一)——Windows 须用 console 版 exe 取 stdout +# 逻辑冒烟(双载体之一)——Windows 须用 console 版 exe 取 stdout;工作目录 = game/(含 project.godot 那一层) godot --headless --script tests/run_all.gd # 统一入口(CI 调用点) godot --headless --script tests/unit/example_test.gd @@ -32,7 +32,7 @@ godot --headless --path . res://smoke/.tscn timeout 120s godot --headless --script tests/run_all.gd ``` -> 单元/契约套件状态(单元测试与契约层批 2026-09-28):`_suites()` manifest 已登记实跑七套件——data_config(ConfigDB 加载/进度坐标 ceil 解析/fatal 退出码/统一随机流)、battle_settlement(DamageMath 纯函数/DamageController 伤害单据五配方)、contracts(系统间接口契约断言);致命类独立进程 `expect=1`。期望值一律由表读值推导(零玩法数值字面量)、随机只经 RngService 统一流。 +> 单元/契约套件状态(单元测试与契约层批 2026-09-28 立基,后随迭代 7/8 增补):`_suites()` manifest 已登记实跑十五套件——data_config(ConfigDB 加载/进度坐标 ceil 解析/fatal 退出码/统一随机流)、core(魔法道具结构冻结/断点续玩)、battle_settlement(DamageMath 纯函数/DamageController 伤害单据五配方)、contracts(系统间接口契约断言)、presentation(节奏队列/奖励浮层/字体资产/地形瓦片集);致命类独立进程 `expect=1`。期望值一律由表读值推导(零玩法数值字面量)、随机只经 RngService 统一流。 **协议要点**(D2 冒烟协议 + ADR-0004): - 冒烟脚本 `extends SceneTree` 以获得 `quit(code)`;成功 `quit(0)`、失败 `quit(1)` @@ -43,7 +43,7 @@ timeout 120s godot --headless --script tests/run_all.gd ## Test Naming -- **Files**: `[system]_[feature]_test.gd`(领域命名,禁 ID 前缀——docs/code-conventions.md) +- **Files**: `[system]_[feature]_test.gd`(领域命名,禁 ID 前缀——design/dev/code-conventions.md) - **Functions**: `test_[scenario]_[expected]` - **Example**: `reward_roll_test.gd` → `test_power_interval_rolls_within_bounds()` @@ -55,12 +55,12 @@ timeout 120s godot --headless --script tests/run_all.gd | Integration | Integration test OR playtest doc | `tests/integration/[system]/` | | Visual/Feel | Screenshot + lead sign-off | `tests/evidence/` | | UI | Manual walkthrough OR interaction test(场景探针为首选) | `tests/evidence/` | -| Config/Data | Smoke check pass | `production/qa/smoke-*.md` | +| Config/Data | Smoke check pass | `design/qa/` | ## Static Scan(提交前双跑:本地 + CI) `tests/static_scan.sh` 实现 ADR-0004 扫描域 S1–S8 的可执行子集;规则全集与动机见 -`docs/architecture/adr-0004-test-carrier-and-ci.md`。新违规案例必须**先补扫描规则再修码**。 +`design/dev/architecture/adr-0004-test-carrier-and-ci.md`。新违规案例必须**先补扫描规则再修码**。 ## CI diff --git a/game/tests/static_scan.sh b/game/tests/static_scan.sh index f421f395..f1c7c785 100644 --- a/game/tests/static_scan.sh +++ b/game/tests/static_scan.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash # tests/static_scan.sh — ADR-0004 静态扫描域 S1–S8 可执行子集 -# 规则全集与动机:docs/architecture/adr-0004-test-carrier-and-ci.md §Decision 3 +# 规则全集与动机:design/dev/architecture/adr-0004-test-carrier-and-ci.md §Decision 3 # 正式工程(core/ 存在)时执行;否则优雅跳过(工程在 game/core——2026-09-24 转正结构批后仓库根布局)。 -# 纪律:新违规案例必须先补本脚本规则再修码(docs/code-conventions.md 缺陷-规范对照表)。 +# 纪律:新违规案例必须先补本脚本规则再修码(design/dev/code-conventions.md 缺陷-规范对照表)。 set -u cd "$(dirname "$0")/.." diff --git a/game/tests/unit/README.md b/game/tests/unit/README.md index d7d46e47..2e17ac7d 100644 --- a/game/tests/unit/README.md +++ b/game/tests/unit/README.md @@ -1,6 +1,6 @@ # tests/unit/ — 隔离单元测试 -每系统一个子目录(`reward_economy/`、`board_generator/`…)。协议与命名见 `tests/README.md`。 +每系统一个子目录(现行:`data_config/`、`core/`、`battle_settlement/`、`contracts/`、`presentation/`)。协议与命名见 `tests/README.md`。 **活样板**:`example_test.gd`(本目录)——第一个真实测试请以它为模板。 -**参考实现**:`game/smoke/smoke_all.gd`(628+ 条断言的组织方式)。 +**参考实现**:`game/smoke/smoke_all.gd`(752+ 条断言的组织方式)。 diff --git a/sim-data/README.md b/sim-data/README.md index 1b6b5dcc..08e02346 100644 --- a/sim-data/README.md +++ b/sim-data/README.md @@ -10,7 +10,7 @@ ## 历史锚(只读不判) -其余 8 份 `runsum_*.jsonl`,文件名=批+锚名+日期可辨(迭代 8/9/10、numfix 各代)。出度≤2 重建后旧锚结构已失义,仅留换代对照;处置挂中间产物死亡清单随批处理。 +其余 23 份 `runsum_*.jsonl`,文件名=批+锚名+日期可辨(迭代 8/9/10、numfix 各代 + M-4 迭代 11a/11b/12/14 各批)。出度≤2 重建后旧锚结构已失义,仅留换代对照;处置挂中间产物死亡清单随批处理。 ## MC 采集档位表(2026-10-03 用户四档立规——按用途定局数上限,禁惯例继承禁计划书自拟)