sync: 同步 master(并行会话提交+本批已并件)进出口分支

This commit is contained in:
DKChan committed 2026-10-03 00:55:57 +08:00
commit efa2009880
11 files changed
+508 -20

No files matched your search

+9 -1
View File
@@ -55,10 +55,18 @@
| 爆破工兵包 | 行动点 + 探巢的稀有魔法道具 | aux_items |
| 地精 / 熊地精 / 食人魔酋长 | 首发三敌种(末者为 Boss) | enemy |
| 第一层 · 地精洞窟 | 首关层名 | level_table |
| 封印 | 插旗动作的呈现名——对未开格(巢穴)插旗即实施封印,旗 = 封印印记 | terminology(2026-09-25 用户拍板) |
| 封印 | 插旗动作的呈现名——对未开格(巢穴)插旗即实施封印,旗 = 封印印记 | terminology |
注意:部分魔法道具的现行效果定义绑定已被移除的地形变异类型,其效果定位待后续内容批重定;名称暂按登记保留,重定时随批修订。
另:元进度资源定名**钥石**——每一层关底 Boss 看守他那块区域的钥石,击杀即取走,用于在存档内解锁永久提升(属性 / 怪物遭遇 / 道具池)。2026-09-14 用户拍板,registry 术语登记随元进度设计批补登。
> 旧版参考:../archive/gdd-2026-09-14/game-concept.md
## 版本历史
| 版本 | 日期 | 改动 |
|---|---|---|
| v1.0 | 2026-09-14 | 初版随 GDD 骨架建立:一句话概念、目标受众、世界观命名、术语层级 |
| v1.1 | 2026-09-25 | 术语「封印」定稿(用户拍板):插旗动作呈现名落术语表,出处条目 terminology |
| v1.2 | 2026-10-03 | R3 清账批(gdd_lint 分域随批):术语表日期批注括注迁出至本表 v1.1 行;语义零变更 |
+9 -1
View File
@@ -13,7 +13,7 @@
所以自动战斗不是过场,是阅卷:每一行结算都能指回你刚才的哪一步棋。
### 数值语言(2026-09-18 用户拍板)
### 数值语言
- 游戏内伤害与成长数值一律**整数加减**(小整数加法核——模板 C 骨架 + 模板 A 成长语言):克制修正、奖励、商店与永久强化的属性提升都走"+1/−1 点"式整数;数字小而可读是设计价值,不是待放大的占位。
- **百分比仅保留三处既有粗档修正**(增益池乘区、护甲等级掷点折扣档、暴击倍率)与开发侧测量工具(难度杠杆扫描、通关率带平移);此后新增数值系统默认整数加法,引入百分比须显式修订本条款。
@@ -47,3 +47,11 @@
循环到此闭合:进入一局 → 在棋盘上推理 → 看推理兑现成胜负 → 带着变强(或更痛)的记忆和一个更厚的存档,想进下一个节点、下一张图、下一层、下一局。
> 旧版参考:../archive/gdd-2026-09-14/gdd.md
## 版本历史
| 版本 | 日期 | 改动 |
|---|---|---|
| v1.0 | 2026-09-14 | 初版随 GDD 骨架建立:一场战斗 / 一场冒险 / 死了之后三节 |
| v1.1 | 2026-09-18 | 「数值语言」节定稿(用户拍板:整数加减核、百分比仅三处既有粗档、全局 floor) |
| v1.2 | 2026-10-03 | R3 清账批(gdd_lint 分域随批):节标题日期批注迁出至本表 v1.1 行;语义零变更 |
+5 -4
View File
@@ -32,7 +32,7 @@
| 文件 | 一句话概要 | 状态 |
|---|---|---|
| `战斗结算.md` | 轮末结算的编排与逐行兑现 | 已定稿·自旧体系迁移 |
| `敌人系统.md` | 敌人数据、技能池出招、意图呈现 | 已定稿·自旧体系迁移(2026-09-16 技能池批 v0.5) |
| `敌人系统.md` | 敌人数据、技能池出招、意图呈现 | 已定稿·自旧体系迁移 |
| `增益状态.md` | 增益/减益状态的容器、叠层与衰减 | 已定稿·自旧体系迁移 |
| `地图战斗资源.md` | 格面资源的产出、极性字典与清图奖励封装 | 已定稿·自旧体系迁移 |
| `战斗表现.md` | 战斗动画与演出(旧体系未单独成文) | 范围草案·待设计 |
@@ -50,7 +50,7 @@
| 文件 | 一句话概要 | 状态 |
|---|---|---|
| `元进度.md` | 跨局成长(旧体系未单独成文) | 已定稿·已实现(2026-09-21 实现批,数值 provisional 归设计批标定) |
| `元进度.md` | 跨局成长(旧体系未单独成文) | 已定稿·已实现 |
### 表现与支撑(`systems/表现与支撑/`)
@@ -73,8 +73,8 @@
| `level-map.md` | 关卡画面 UX spec:选路枢纽三停点布局、GP 常驻徽章、交互映射与拍板点 | 占位升格版·视觉终稿后置 |
| `node-reward.md` | 节点奖励屏 UX spec:奖励节点三选一构筑点、可用池与池空直通(切片期过渡形态,随同调实施批退役改写) | v1.0(2026-09-29 本行 2026-09-30 补登) |
| `settlement-summary.md` | 结算总结 UX spec:战斗总结结算(战斗胜利面)与冒险总结结算(冒险终结面)——两面分节的纯呈现轻量 spec | v1.0·纯呈现已实装面成文 |
| `camp.md` | 营地覆盖层 UX spec:三柜台呈现、钥石余额、退役/封存件状态语义(存档级/局外呈现面) | v1.0(2026-09-30 拍板点 4A 落文;9A 视觉终稿实态成文) |
| `shop.md` | 商店覆盖层 UX spec:三商品卡全陈列、GP 余额、购买/离开(中循环节点兑付呈现面) | v1.0(2026-09-30 拍板点 4B 落文) |
| `camp.md` | 营地覆盖层 UX spec:三柜台呈现、钥石余额、退役/封存件状态语义(存档级/局外呈现面) | v1.0 |
| `shop.md` | 商店覆盖层 UX spec:三商品卡全陈列、GP 余额、购买/离开(中循环节点兑付呈现面) | v1.0 |
## 子系统命名对照表(中文规范名 ↔ 英文代号)
@@ -125,3 +125,4 @@
| v0.9 | 2026-09-27 | UX 文档欠账处置批:`ux/` 目录入索引(battle.md / interaction-patterns.md / 新建 level-clear.md);四项欠账处置——player-journey 不建、accessibility-requirements 不另立(改指 HUD框架 基线 + 设置与本地化)、node-reward 挂魔法道具内容重定批(06 登记)、level-clear 建档 |
| v1.0 | 2026-09-27 | 节点图生成立项批(用户拍板立项——06 条目「关卡内结构随机生成」随批改状态):`systems/冒险循环/` 新建 `关卡节点图生成.md` 设计草案 v0.1(图模板/模板池/抽签三概念、三级台阶路线、MC 测量对账条款、五拍板点);文档树补行 + 命名对照表补 `NODE_MAP_GENERATION` 行 |
| v1.1 | 2026-09-27 | 关卡画面 UX spec 建档(关卡画面 UX 批):`ux/` 表补 `level-map.md` 行——选路枢纽三停点布局、GP 常驻徽章、交互映射与 AC 成文,三项设计提案挂 06 待拍板 |
| v1.2 | 2026-10-03 | R3 清账批(gdd_lint 分域随批):四处状态单元格日期批注迁出——敌人系统行事件见敌人系统.md 版本历史 v0.5(技能池批);元进度行见本表 v0.8;camp/shop 行=两文 v1.0 落文(2026-09-30 三裁决执行批);语义零变更 |
+6 -5
View File
@@ -2,7 +2,7 @@
一句话定位:**三关、按关配置的棋盘、一套格面资源池、一套状态表、一套商店配置**——刚好撑起一次完整的"扫雷决策 → 战斗兑现"循环,除此之外一律不做。
> **体例说明(2026-09-17 数值纪律收口批)**:本文件只写内容规模的结构框架——几个维度、各分几档、扩展走什么流程。具体种数、行数与幅度数值一律不在此抄录,事实源为准:数据表读 `game/data/tables/*.tres`,实体登记读 `design/registry/entities.yaml`;现行行数与面值以表和 registry 为准。
> **体例说明**:本文件只写内容规模的结构框架——几个维度、各分几档、扩展走什么流程。具体种数、行数与幅度数值一律不在此抄录,事实源为准:数据表读 `game/data/tables/*.tres`,实体登记读 `design/registry/entities.yaml`;现行行数与面值以表和 registry 为准。
## 关卡
@@ -30,7 +30,7 @@ MVP 不加新敌种,也不做同深度多敌种混搭;敌种扩容走数据
## 战斗道具(格面资源)
**格面资源池**(`data/tables/reward.tres`,现行行数读表为准):结构为格面九型 × 正负两向(十八格——2026-09-20 GP+商店房批九型后现行),加清图奖励槽一类。全部按交付方式当场兑付、不进背包——入背包的"结算窗口选用"类道具(小刀 / 精工短刀 / 治疗包)已随格面资源批整体删除,现行池内无可选类道具、无轮末结算窗口。
**格面资源池**(`data/tables/reward.tres`,现行行数读表为准):结构为格面九型 × 正负两向(十八格),加清图奖励槽一类。全部按交付方式当场兑付、不进背包——入背包的"结算窗口选用"类道具(小刀 / 精工短刀 / 治疗包)已随格面资源批整体删除,现行池内无可选类道具、无轮末结算窗口。
行级语义见[地图战斗资源](systems/战斗循环/地图战斗资源.md)。MVP 不做道具之间的组合协同;扩池走 reward.tres 加行 + registry 登记。
@@ -38,7 +38,7 @@ MVP 不加新敌种,也不做同深度多敌种混搭;敌种扩容走数据
registry 登记 **一套封闭清单**(数据表未建,属待落地内容):显影尘、工兵令、探宝罗盘、探巢摆钟、地穴全图卷、爆破工兵包——四个常规单功能加两个稀有组合。件数与登记现状以 `design/registry/entities.yaml` 为准。MVP 不新增。
待定一句:显影尘与地穴全图卷的原效果绑定已从设计中移除的地形变异类型(见[不做清单](05-不做清单.md));显影尘与地穴全图卷的效果定位均随魔法道具整体重设计归 Alpha(2026-09-20 用户拍板,原待办条目已移除);其余四件定义有效。
待定一句:显影尘与地穴全图卷的原效果绑定已从设计中移除的地形变异类型(见[不做清单](05-不做清单.md));显影尘与地穴全图卷的效果定位均随魔法道具整体重设计归 Alpha;其余四件定义有效。
## 增益与状态
@@ -62,9 +62,9 @@ MVP 不加新状态;扩容走 status_effects.tres 加行 + registry 登记。
垂直切片阶段明确砍掉或推迟的内容,写在这里防止回潮:
- 更多关卡(N>3)——第三关已按扩展批流程落地(行集);三关正式序列已生效(冒险结构实现批 2026-09-21),唯一试玩入口 = 完整冒险(单关测试直入口退役,2026-09-23 用户拍板)
- 更多关卡(N>3)——第三关已按扩展批流程落地(行集);三关正式序列已生效,唯一试玩入口 = 完整冒险
- 精英节点与词缀系统——只预留了字段位,不定义语义(精英怪**设定**已登记预留:迭代 10 奖励重构批——同立绘+附加特征标记+数值更强、钥石掉 1 个预留;实装仍随怪物批)
- 地形变异扩展内容——首批四类型已落地,反制道具与全局作用域排 Alpha(2026-09-20 用户拍板)
- 地形变异扩展内容——首批四类型已落地,反制道具与全局作用域排 Alpha
- 道具/增益之间的组合协同(遗物式联动)
- 战后自动回复——回复只有道具与恢复点两个来源
- 新敌种、新棋盘档位、更高密度、同深度多敌种混搭
@@ -85,3 +85,4 @@ MVP 不加新状态;扩容走 status_effects.tres 加行 + registry 登记。
| v0.7 | 2026-09-20 | **GP+商店房批(与切片代码 / registry / 关卡节点地图 / 冒险结构 / 战斗结算 / 地图战斗资源 / 难度曲线与Boss 同批)**:格面资源池"八型 × 正负两向(十六格)"→"九型 × 正负两向(十八格)"(+gp 金币);新增「商店」小节一行——shop.tres 读表纪律(商品三行 / 掉落参数 / 价格参数,全部 provisional 归曲线调参批);一句话定位句补"一套商店配置" |
| v0.8 | 2026-09-21 | **冒险结构实现批(与切片代码 / registry / 冒险结构 同批)**:层名表 L2/L3 状态行改「正式序列已生效」——首页「开始冒险」三关连探落地(AdventureRunner 编排;测试直入口保留);「更多关卡」行同步;正文零历史叙述纪律下仅状态口径更新,结构框架零改动 |
| v0.9 | 2026-09-21 | **元进度实现批(与切片代码 / registry / 元进度 / 02 / 05 同批)**:「暂不做」节移除「元进度与跨局成长」行——跨局成长首批落地(营地三柜台 / 钥石账本 / 跨局注入,数值 provisional 归元进度设计批标定);新增「一套元进度配置」小节(meta.tres 四行族读表纪律,数值 provisional 归设计批) |
| v1.0 | 2026-10-03 | R3 清账批(gdd_lint 分域随批):五处日期批注括注迁出——体例说明=本表 v0.3 事件;十八格=本表 v0.7 事件;正式序列=本表 v0.8 事件;三处用户拍板事件随行入账:显影尘/地穴全图卷效果定位归 Alpha 且原 06 待办条目移除(2026-09-20 拍板)、单关测试直入口退役且唯一试玩入口=完整冒险(2026-09-23 拍板)、反制道具与全局作用域排 Alpha(2026-09-20 拍板);语义零变更 |
+7
View File
@@ -15,3 +15,10 @@
美术细则(色板、形状语言、图标契约、验收标准)见 `design/art/art-bible.md`(含参考与反参考,见其 §9)。
> 旧版参考:../archive/gdd-2026-09-14/game-concept.md
## 版本历史
| 版本 | 日期 | 改动 |
|---|---|---|
| v1.0 | 2026-09-14 | 初版随 GDD 骨架建立:风格一句话、三条关键词、参考游戏、音频方向占位 |
| v1.1 | 2026-10-03 | gdd_lint 分域批:补版本历史节(R4);本文体系裁散文体,R2 表格占比分域豁免 |
+9 -1
View File
@@ -19,9 +19,17 @@
- **多波战斗**:Peglin 对比报告(2026-09-12)裁下的后置项。单场多波是战斗编排级的改动,波间状态保留规则也要重新定义,排 Alpha 期评估。
- **遗物 / 构筑协同**:同批裁下。先做协同设计再谈加密度,没有协同的纯堆量只会稀释每件道具的存在感。
- **战后回复**:同批裁下。要做得绑定敌方攻击力下调,单独加回复会直接破坏现有数值预期。
- **元进度(钥石解锁 / 跨局成长)**:排 Alpha,首批已落地(2026-09-21 元进度实现批——营地三柜台 / 钥石账本 / 跨局注入,数值 provisional 归设计批标定)。铺量与标定仍是之后的事。
- **元进度(钥石解锁 / 跨局成长)**:排 Alpha,首批已落地(营地三柜台 / 钥石账本 / 跨局注入)。铺量与标定仍是之后的事。
- **反雪球机制**:MVP 不做。等 Alpha 拿到真实测试数据,再决定要不要治滚雪球、怎么治。
- **正式音频、教学引导、战斗动画演出、设置与本地化**:MVP 内的打磨项,一律排后。先验证核心循环,再谈好听好看。
- **连刷 / 换图资金跨战斗携带**:现行规则是每场战斗清零,防滚雪球。是否解禁连刷策略,等实测数据说话。
> 旧版参考:../archive/gdd-2026-09-14/gdd.md
## 版本历史
| 版本 | 日期 | 改动 |
|---|---|---|
| v1.0 | 2026-09-14 | 初版随 GDD 骨架建立:确定不做 / 现阶段不做两节 |
| v1.1 | 2026-09-21 | 元进度实现批:元进度行注首批已落地(营地三柜台 / 钥石账本 / 跨局注入),数值 provisional 归设计批标定 |
| v1.2 | 2026-10-03 | R3 清账批(gdd_lint 分域随批):元进度行日期批注迁出至本表 v1.1 行;语义零变更 |
+1
View File
@@ -429,6 +429,7 @@
- **每次变更必测(轻量闸,headless 秒–分钟级)**:`run_smoke` 全量 + `ui_input_probe`(含呈现层十一断言)。触碰 presentation/ 还需加跑 `ui_click_probe` + `ui_layout_probe`。此三件不涉渲染,任何改动后即可跑。
- **周期内测(重闸,统一周期=样张批/表现批收口 或 固定周检)**:B 档视口截图像素断言(需真渲染进程)、C 档黄金图对比(需视觉冻结后建基准,美术未冻结前基准图会反复重制)、真人实机目检清单(走路/挖掘/朝向/观感类)、MC 大扫描。
- **模拟档触发口径(用户裁定,随测试性能验证批落文)**:MC / balance_verifier 属数值验证工具,仅在数值验证场景触发(锚换代 / 带值拍板 / 迭代出口 / 调参批),不进每次变更闸——功能正确性由冒烟断言承载(统一随机流同种子确定性复放,单次即权威,ADR-0007),不靠模拟次数。MC 日常读数以 normal 档为主(400 局约 8 分钟),perfect 档(约 56 分钟,单局约 7 倍于 normal)仅上界读数需要时跑(带值拍板 / 上界验收);调参会话随跑用 balance_verifier --quick(约 3 分钟)。
**前置依赖**:C 档硬前置=样张批冻结视觉(否则黄金图基准反复作废);B 档可与样张批同窗试点。
@@ -0,0 +1,297 @@
# t17_defer_probe 运行证据(2026-10-02)
- 被测:演播后排窗(T17 用户令「伤害过程演完才切战斗胜利结算窗」)——本修复的定点关联测试
- 断言①(判别性):胜利同帧终局面未开+挂起在案+排播队列在播——旧行为(同帧 flush+开窗)跑此必红
- 断言②:排播放完(waited≈5.5s=15 行 × 0.22s 段内间隔+段间间隔)终局面开启
- 复跑方式:godot --headless --path game res://smoke/t17_defer_probe.tscn(退出码 0=PASS / 2=FAIL)
- 本文件=2026-10-02 master(bb35fdc)实跑原始输出留存
- 毫秒时间戳补测(同日):结算入队=1581 ms · 弹窗可见=7073 ms · **相差=5492 ms**(22 行;AP 耗尽→结算开始=同帧 0ms——核心同步架构,时长全部为逐行演播)
## 原始输出
```
Godot Engine v4.7.2.stable.official.ed1daf0bf - https://godotengine.org
WARNING: Can't change the size of a `SubViewport` with a `SubViewportContainer` parent that has `stretch` enabled. Set `SubViewportContainer.stretch` to `false` to allow changing the size manually.
at: _internal_set_size (scene/main/viewport.cpp:5627)
GDScript backtrace (most recent call first):
[0] _notification (res://presentation/views/battle_stage_view.gd:177)
[1] build_battle_ui (res://presentation/ui_assembler.gd:24)
[2] _build_ui (res://presentation/main.gd:192)
[3] _ready (res://presentation/main.gd:181)
[4] _ready (res://smoke/t17_defer_probe.gd:16)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Attempted to push_back a variable of type 'String' into a TypedArray of type 'Dictionary'.
at: _internal_validate (./core/variant/container_type_validate.h:73)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
ERROR: Condition "!_p->typed.validate(value, "push_back")" is true.
at: push_back (core/variant/array.cpp:285)
GDScript backtrace (most recent call first):
[0] append_row (res://presentation/views/battle_log_view.gd:109)
[1] _consume_row (res://presentation/row_pacer.gd:91)
[2] _process (res://presentation/row_pacer.gd:79)
[t17_defer] PASS — 胜利同帧挂起+排播完开窗 两断言全过(waited=5.5s)
ERROR: 18 RID allocations of type 'PN13RendererDummy14TextureStorage12DummyTextureE' were leaked at exit.
ERROR: 18 RID allocations of type 'PN18TextServerAdvanced22ShapedTextDataAdvancedE' were leaked at exit.
ERROR: 2 RID allocations of type 'PN18TextServerAdvanced12FontAdvancedE' were leaked at exit.
WARNING: 4 RIDs of type "CanvasItem" were leaked.
at: _free_rids (servers/rendering/renderer_canvas_cull.cpp:2735)
WARNING: 102 ObjectDB instances were leaked at exit (run with `--verbose` for details).
at: cleanup (core/object/object.cpp:2536)
ERROR: 1 resources still in use at exit (run with --verbose for details).
at: clear (core/io/resource.cpp:822)
```
+139
View File
@@ -0,0 +1,139 @@
# 现行自动化测试·性能验证报告(2026-10-02)
任务书:`.zcode/plans/test-perf-audit-prompt-2026-10-02.md`(用户委托批——只测量与报告,零改码零改断言)。
执行:独立会话,全程主工作区(master)、全程串行(任一时刻至多一个本会话 Godot 测试进程)。
## 0. 环境与测量前提
- 引擎 `Godot_v4.7.2-stable_win64_console.exe`;cwd=`D:\code\g-plan2`;素材不入 git 照旧。
- **测量期间 master 被并行会话连续落地**(见 §6.3):批次归属两树态——
- **T1 态 = 5e501a6**(18:04 前):#1 冒烟×4、#2 run_all×4、#3/#4/#5 探针批次;
- **T2 态 = 725f0ac**(现行头):#5–#11 全部探针、#14–#16、#12/#13、新码复验均在 725f0ac。
- 绿件在两态下读数一致(冒烟 60.55 vs 62.20s;run_all 12.16 vs 12.75s)——**落地零计时漂移**。
- 并行会话的 Godot 进程(含一个 1GB 窗口化实例)与本项目测量同窗活跃,秒级件上的负载噪声见 §3 波动性。
- 工作区在飞件(`game/core/battle_orchestrator.gd` 注释空白、`game/project.godot` stretch/aspect 行、未跟踪 `game/tests/probe14_test.gd`)**只标旗未触碰**。
## 1. 计时总表
协议:每件先跑 1 次记冷启动,随后正式 3 次取中位;外部 python 计时包装(`%TEMP%\perf-audit-20261002\perf_run.py`),零插桩。#12/#13 按任务书走小样本协议(单跑推算)。
| # | 测试 | 冷启动 | 正式 3 跑 | **中位** | 极差 | 极差% | 判读锚(exit) |
|---|---|---:|---|---:|---:|---:|---|
| 1 | 全量冒烟 `run_smoke` | 61.77 | 60.55 / 61.96 / 60.54 | **60.55s** | 1.42 | 2.3% | 0(636 项 0 失败×4) |
| 2 | run_all 15 套件 | 12.36 | 12.00 / 12.45 / 12.16 | **12.16s** | 0.44 | 3.7% | 0(all green ×4) |
| 3 | ui_probe | 1.82 | 1.82 / 2.05 / 2.69 | **2.05s** | 0.86 | **42.0%** ⚠ | 0 |
| 4 | ui_input_probe | 2.40 | 2.44 / 2.55 / 2.52 | **2.52s** | 0.11 | 4.4% | 0 |
| 5 | ui_click_probe | — | **双态全红,见 §6.1** | — | — | — | 旧态 exit=1 ×3;现行头 240s 看门狗击杀 ×4 |
| 6 | fx_probe | 2.58 | 2.47 / 2.49 / 2.47 | **2.47s** | 0.02 | 0.8% | 0 |
| 7 | ui_layout_probe | 1.75 | 1.73 / 1.74 / 1.75 | **1.74s** | 0.02 | 1.4% | 0 |
| 8 | ui_tune_probe | 9.50 | 9.26 / 9.33 / 9.41 | **9.33s** | 0.15 | 1.6% | 0 |
| 9 | shot_probe(窗口化) | 5.23 | 3.67 / 3.51 / 3.68 | **3.67s** | 0.17 | 4.5% | 0(冷启动+42%=首跑 shader 编译) |
| 9a | └ shot_checker 断言 | 1.26 | 0.86 / 0.89 / 0.88 | **0.88s** | 0.02 | 2.7% | 0(机检面全过) |
| 10 | fx_shot_probe(窗口化) | 6.93 | 6.89 / 6.86 / 6.94 | **6.89s** | 0.08 | 1.1% | 0 |
| 11 | board_shot_probe(窗口化) | 3.36 | 3.28 / 3.30 / 3.44 | **3.30s** | 0.16 | 4.8% | 0 |
| 12 | MC 蒙特卡洛(小样本) | — | N=50×2 策略=100 局 **486.0s** | **4.86s/局** | — | — | 0(100 RUNSUM) |
| 13 | balance_verifier(小样本) | — | --quick 36 局 **173.7s** | **4.83s/局** | — | — | 0 |
| 14a | gdd_lint | 0.53 | 0.31 / 0.31 / 0.31 | **0.31s** | 0.00 | 1.3% | **1 ×4(8/8 文件不通过,见 §6.2)** |
| 14b | doc_link_audit | 0.98 | 0.41 / 0.41 / 0.41 | **0.41s** | 0.00 | 1.0% | 0 |
| 14c | doc_term_audit | 0.41 | 0.38 / 0.38 / 0.39 | **0.38s** | 0.01 | 1.6% | 0 |
| 15 | repo_structure_audit(熵增闸) | 1.10 | 1.07 / 1.04 / 1.06 | **1.06s** | 0.03 | 2.4% | 0 |
| 16 | static_scan.sh | 0.84 | 0.75 / 0.64 / 0.76 | **0.75s** | 0.12 | **16.4%** ⚠ | 0(S1–S8 可执行子集全过) |
与任务书「已知量级」对照:冒烟 ~65s→实测一致;run_all「数十秒级」→实测 12s 更快;窗口化三件「十秒级」→实测 3.3–6.9s 更快;MC「预计最长」→证实(推算满档 ≈65 分钟,见下)。
### #12/#13 满档推算
- **MC**(`-- 50 80000 both min`,100 局实测):normal 档 ≈**1.21s/局**(前 50 局 ~60s),perfect 档 ≈**8.47s/局**(后 50 局 ~423s,≈7 倍——perfect 选路/战斗更充分)。现行 80000 代链各档 400 局满档推算:normal ≈8.1 分钟 + perfect ≈56.5 分钟 ≈ **65 分钟/全档**;单策略 400 局 = 8 / 56 分钟。
- **verifier**(`--quick` 36 局 = (8 冒险+10 战役)×2 画像,173.7s):**4.83s/局**。满档 na=60/k=60 = (60+60)×2 = 240 局 ≈ **19.3 分钟**。
## 2. 冒烟分段耗时与 180s 闸余量
方法注记:管道模式下 GDScript print 为块缓冲(全量退出时才刷,逐行时戳全聚在 60.445s)——段级改用 **`--verbose` 强制行刷**法 2 跑(61.0 / 63.6s,较常态中位膨胀 ≤5%,占比可信);winpty 伪终端在本环境断言失败不可用(备选已试、弃)。verbose 双跑 636/0 全绿、零 SCRIPT ERROR。
**180s 硬闸(ADR-0004,run_smoke.py 外部超时)余量:180 − 60.55 = 119.45s(余 66.9%,冒烟仅用闸的 33.1%)**。分段合计 61.7s ≈ 墙钟,无未计入空洞。verbose 双跑段级极差全部 <10%(最大 5.7%),段占比稳定。
### 最慢 Top10 段(两跑中位;各自验证内容)
| # | 段(smoke_all.gd 行号) | 中位 | 占比 | 验证什么 |
|---|---|---:|---:|---|
| 1 | 冒险结构验收(:277) | **21.30s** | 34.5% | 自动玩家三关完整连探:三层奖励框架行值单点/大奖励兑付/摘要五件事/账本封闭——全冒烟最重的端到端段 |
| 2 | 关卡节点地图·分支节点图 L2(:2818) | **18.58s** | 30.1% | 图合法性校验(正反例)+ 幽暗地域图版行进 |
| 3 | SaveManager 存档读写/迁移/兜底(:3684) | **9.69s** | 15.7% | 存档序列化全链:写盘/读回/版本迁移/兜底/隔离档——纯逻辑段里唯一的重 IO 段 |
| 4 | 关卡节点地图·线性推进(:737) | 3.56s | 5.8% | L1 全链自动推进(战×2→道具→战×2→恢复→Boss) |
| 5 | 遭遇随机化(:1764) | 2.81s | 4.6% | unit_count 区间骰/encounter 流/可回放——大量掷点重放循环 |
| 6 | 商店房三收口(:3201) | 1.00s | 1.6% | 商店经济链(现价/加算区/余额不足拒/离开回选路/收束清零) |
| 7 | 护甲等级掷点(:851) | 0.77s | 1.2% | 查档纯函数+暴击+伤害下限+AC12 分布(批掷点)+棋盘必中 |
| 8 | 行动经济·轮内刷新(:1396) | 0.63s | 1.0% | 方案 A:Active 相位当场换图继续挖 |
| 9 | 敌人技能池(:2439) | 0.46s | 0.7% | 开轮摇号/冷却保底两闸/三乘法链/独立子流 |
| 10 | 棋盘生成(:1035) | 0.32s | 0.5% | 棋盘生成公式面 |
**集中度:Top3 段 = 49.6s,占冒烟 80.4%;Top6 = 93.3%;其余 37 段合计 ~4.2s。** 冒烟耗时本质=三关完整冒险×2 条路径(结构验收+L2 图版)+存档 IO,其余全是亚秒级。
<details><summary>全部 43 段中位明细(秒)</summary>
21.30 冒险结构验收|18.58 分支节点图 L2|9.69 SaveManager|3.56 线性推进|2.81 遭遇随机化|1.00 商店房三收口|0.77 护甲等级掷点|0.63 轮内刷新|0.46 敌人技能池|0.32 棋盘生成|0.24 清图奖励双份兑付|0.22 棋盘布局格边长公式|0.20 轮内刷新 provenance 守卫|0.17 GP escrow 隔离|0.16 GP 冒险钱包到账|0.16 格面资源资格面|0.16 插旗不可逆四情况|0.14 冒险结构 API 闸|0.12 完整战斗回放 L2 熊地精|0.11 极性路由|0.11 攻击类型×护甲克制|0.11 完整战斗回放 L1 地精|0.10 负向字典逐型直验|0.08 地形变异布置段 L2|0.08 主角乘区接线|0.08 地形变异布置段 L1|0.07 fresh 池攻击链|0.06 元进度收束入账与工坊|0.05 五段全序+行型封闭|0.05 旗动作耗尽末点 AP|0.03 PlaytestLogger|0.02 元进度注入可见与白板|0.02 战斗日志视图行格式化|0.01 元进度几何定价与购买|<0.01×9:伤害量值区间/DifficultyTable/格面资源九型/地形变异框架面/格面资源身份面/冒险表/MetaTable 结构/换装护栏/商店房图不变式
</details>
## 3. 波动性标注(极差 >10% 的项)
| 项 | 极差% | 绝对幅度 | 判读 |
|---|---:|---|---|
| ui_probe | 42.0% | 0.86s(1.82→2.69) | 2 秒级件上的绝对小值;测量窗内并行会话 Godot 进程活跃(其 1GB 窗口化实例同机)所致负载噪声,非测试自身不稳 |
| static_scan.sh | 16.4% | 0.12s(0.64→0.76) | 同上,亚秒级件 + 内部多路 grep 子进程对负载敏感 |
| shot_probe 冷启动 | +42% | 5.23 vs 中位 3.67 | 窗口化首跑 GPU shader 编译,单次成本 ~1.6s,后续稳定 |
其余全部件极差 <5%(多数 <3%),段级极差全部 <10%——**环境噪声可控,全部中位读数可作分级依据**。MC/verifier 为小样本单跑协议,无极差数据(协议如此)。
## 4. 分级建议(数据支撑,对照 06 在册「呈现层测试分级与 UI 驱动夹具周期化」条口径)
06 条现行口径(2026-09-26 用户裁):**每次变更必测=run_smoke 全量 + ui_input_probe(触碰 presentation/ 加 ui_click_probe + ui_layout_probe);周期测=B 档视口截图/C 档黄金图/真人目检/MC 大扫描**。实测数据对该口径的支撑与加码:
**A. 每次变更必跑池(headless 全套 ≈87s,单机可承受)**
| 件 | 中位 | 依据 |
|---|---:|---|
| run_smoke 全量 | 60.6s | 闸余量 119s;耗时本质=Top3 段(三关冒险端到端+存档 IO),裁剪空间小、回归价值最高 |
| run_all 15 套件 | 12.2s | 便宜且覆盖公式/状态机/契约/致命类协议 |
| ui_input_probe | 2.5s | 06 条点名必跑,实测仅 2.5s,维持 |
| ui_probe / ui_layout_probe / fx_probe | 1.7–2.5s | 秒级件,触碰 presentation/ 时顺手加跑无负担(06 口径内扩展,建议追认) |
**B. 周期池(维持 06 口径,数据加码)**
| 件 | 中位/推算 | 依据 |
|---|---:|---|
| ui_tune_probe | 9.3s | 探针里最贵(调整板/批量模拟通路),建议触碰调参/模拟通路时跑,否则归周期池尾 |
| 窗口化三件+shot_checker | 3.3–6.9s+0.9s | 单件不贵但需真渲染+桌面弹窗在场,06 裁 B 档=周期(样张/表现批收口窗)——数据支持维持(另见冷启动 shader 编译 +1.6s) |
| MC 大扫描 | **满档 ≈65 分钟**(perfect 档 8.5s/局 7 倍于 normal) | 06 已归周期,数据强支持;如需快速回归可用 50 局/策略小样本 ≈8 分钟 |
| verifier 满档 | **≈19 分钟** | 周期跑;`--quick` 2.9 分钟可作调参会话随跑档 |
| ui_click_probe | — | **修复并重测后再定级**(现状见 §6.1:载体解析错误损坏;修复前旧态常态打满 20000 帧 budget=141s,与其注释自述「常态通关远低于此」相悖——即使修复,141s 级也建议从「触碰 presentation 必跑」降到周期/发布前,待绿态实测重裁) |
**C. 提交钩子级(全件 <1.2s,零负担)**:doc_link_audit 0.41s / doc_term_audit 0.38s / repo_structure_audit 1.06s / static_scan 0.75s——适合挂 pre-commit/pre-push;**gdd_lint(0.31s)挂钩前须先清 §6.2 的 8/8 红账,否则常红无用**。
## 5. 交付与复现
- 本报告零改码达成(计时=外部包装,分段=--verbose 行刷,MC/verifier=文件头用法小样本)。
- 原始日志与逐跑记录:`%TEMP%\perf-audit-20261002\`(results.jsonl + 逐件逐跑 .log,43 段解析在 segments_verbose.json)——系统临时目录,不属仓库。
- verifier 小样本在 design/qa 落过 `balance-verifier-20261002-192230.{md,jsonl}` 两件生成物,计时提取后按中间产物规则已删除(可复现)。
- 复现命令全集(cwd=仓库根):任务书 §三 表格所列即全部;补充两条——分段计时 `godot --headless --verbose --path game --script res://smoke/smoke_all.gd`;MC 小样本 `godot --headless --path game --script res://smoke/adventure_monte_carlo.gd -- 50 80000 both min`。
## 6. 异常与偏差记录(照实记录,未当场改码)
### 6.1 ui_click_probe 双态全红(本批最重要发现)
- **T1 态(5e501a6)**:3 跑 141.0–141.5s(极差 0.3%)exit=1。现象=`循环退出(done=false budget=0)问题=0`——20000 帧 budget 打满未走完全流程,内部零断言失败;伴随 TypedArray push_back 错误刷屏 ~1 万行。**并行会话提交 cd1ed95 的提交信息自证:该 budget 耗尽+typed-array 错误经纯 master 对照=1:1 同源(master 既有,归 T17 在飞批)**。
- **T2 态(b0c5d7e…725f0ac,现行头)**:**载体直接损坏**——`ui_click_probe.gd:343` 解析错误 `Expected statement, found "Indent"`(343–344 行为悬挂代码片段:一行注释后残留 print 尾部实参),脚本加载失败→探针场景无逻辑→**永不 quit、零输出**,4 跑全部 240s 看门狗击杀(wall 241.7s 无计时意义)。值得注意:cd1ed95 自述修复过一处解冲突解析错误,但 343 处仍残留一处。
- 复现:`godot --headless --path game res://smoke/ui_click_probe.tscn`(现行头必然零输出挂死——**探针无自退出护栏,外部超时是唯一防线,正好坐实 ADR-0004 防挂死条款的必要性**)。
- 关联:同窗 ui_probe 判别实验 2.06s 正常(排除环境系统性故障);smoke/run_all 不经此载体故不受扰。
### 6.2 gdd_lint 4 跑全 exit=1:8/8 GDD 文件不通过
规则命中含表格占比(00 号 37%/02 号 84%)、R3 正文修订注记三条、R4 缺「版本历史」节等(07 号亦红)。量级 0.31s 不是问题,**红账本身是问题**——修复责任不在本测量批,建议归并行文档批/T17 在飞批清账后重跑。复现:`python tools/gdd_lint.py`。
### 6.3 测量中途 master 四度落地(并行会话)
18:04 b0c5d7e(演播后排窗修复+t17_defer_probe)→ 18:23 ee00810 → 18:31/18:32 时间戳两笔 → 18:51 c2e4be3/725f0ac(真时间戳)。本批以「两树态归属」方式消化(§0),绿件跨态读数一致(冒烟 60.55→62.20s、run_all 12.16→12.75s,均 <4%)——**T17 演播后排窗批对两闸计时与正确性零漂移**。
### 6.4 环境注记
- 并行会话 Godot 进程同窗活跃(含 18:11 起一个 1GB 窗口化实例长期闲置):本会话侧保持串行铁律不破;秒级件的负载噪声已在 §3 标注。
- 管道 stdout 块缓冲 + winpty 不可用 → 段级耗时走 --verbose 法(§2,膨胀 ≤5% 已量化)。
- 冷启动普遍便宜(除窗口化 shader 编译),「预热 1 次」协议对绝大多数件影响 <5%。
-2
View File
@@ -340,8 +340,6 @@ func _ready() -> void:
and main.settlement.action_economy.phase == "Active":
_play_one_action()
# 排播期/Waiting 等待态=自然流逝(演播秒级、锁随队列空解除)
str(main.settlement.battle_result) if main.settlement != null else "-",
main._row_queue.size(), str(main._deferred_modal != null)])
# T17 适配:战败或放弃二途皆达终局面(放弃=预算耗尽收口路径——见上),断点段前提不变。
await get_tree().process_frame
var bp_file := "user://smoke_click_probe_reset.json"
+26 -6
View File
@@ -36,6 +36,22 @@ MAX_PARA = 240
MIN_TABLE_RATIO = 30
MAX_PAREN_SPAN = 80
# 规则分域(2026-10-03 用户裁「测试要快/要准」优化批):R1/R2 的体裁前提是「规范文」
# (短段+表格化);登记处/清单/概念文的自然形态就是长条目与叙事散文,硬套=自 2026-09-20
# 上线起 8/8 常红零过滤价值(test-perf-report-2026-10-02 §6.2 实证)。R3/R4/R7 不豁免——
# 「provenance 出正文、版本历史在案」对一切体裁有效。
R1_EXEMPT = {
"06-待办清单.md", # 全项目待办登记处:现状/状态/方案长条目为体裁
"07-体验验证清单.md", # 体验验证读数清单:同上
}
R2_EXEMPT = {
"01-核心循环.md", # 循环概念文:叙事散文为体裁
"04-美术音频方向.md", # 美术方向文:同上
"05-不做清单.md", # 清单文:条目散文为体裁
"06-待办清单.md",
"07-体验验证清单.md",
}
DEFAULT_DIR = "design/gdd"
DEFAULT_EXCLUDE = {"game-concept.md", "game-pillars.md", "systems-index.md"}
VERSION_SECTION = "版本历史"
@@ -169,17 +185,21 @@ def lint_file(path):
issues.append(f"R9 节点「{node_name}」直接内容 {node_count} 行(>{MAX_NODE_LINES})——超一页,拆为子节点")
infos.append(f"最大节点直接内容 {max(node_count, 0)} 行")
# R1 段落长度
for p in paras:
if len(p) > MAX_PARA:
issues.append(f"R1 散文段 {len(p)} 字(>{MAX_PARA}): {p[:50]}…")
# R1 段落长度(登记处/清单文分域豁免,见 R1_EXEMPT 注)
fname = Path(path).name
if fname not in R1_EXEMPT:
for p in paras:
if len(p) > MAX_PARA:
issues.append(f"R1 散文段 {len(p)} 字(>{MAX_PARA}): {p[:50]}…")
# R2 表格占比
# R2 表格占比(概念/方向/清单文分域豁免,见 R2_EXEMPT 注)
code_chars = sum(len(l) for l in code_lines)
table_chars = sum(len(l) for l in text.splitlines() if l.strip().startswith("|"))
total = max(len(text) - code_chars, 1)
ratio = int(100 * table_chars / total)
if ratio < MIN_TABLE_RATIO:
if fname in R2_EXEMPT:
infos.append(f"表格占比 {ratio}%(R2 分域豁免)")
elif ratio < MIN_TABLE_RATIO:
issues.append(f"R2 表格占比 {ratio}%(<{MIN_TABLE_RATIO}%)")
else:
infos.append(f"表格占比 {ratio}%")