From 51c6cf56f004ed25d6a534c40ace3cbead57ca04 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Mon, 26 Oct 2026 07:06:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E9=80=9A=E5=85=B3=E5=8F=A3=E5=BE=84?= =?UTF-8?q?=E6=8D=A2=E4=BB=A3=C2=B7=E6=8F=90=E5=89=8D=E5=AE=9E=E6=96=BD?= =?UTF-8?q?=E5=8D=A1=E6=89=B9=20T2):=2012=20=E6=B5=8B=E8=AF=95=E6=96=87?= =?UTF-8?q?=E4=BB=B6=2058=20=E5=A4=84=E6=A0=87=E7=AD=BE/=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E9=9A=8F=E5=8A=A8(save=5Fmanager=5Fdomain=208/save=5Fslot=5Fsu?= =?UTF-8?q?mmary=201/adventure=5Ffeats=2015/level=5Fshop=5Feconomy=2012/me?= =?UTF-8?q?ta=5Fprogression=5Fforge=209/reward=5Foverlay=201/cross=5Fsyste?= =?UTF-8?q?m=5Fflow=203/breakpoint=5Fresume=201/save=5Fboot=5Fno=5Factivat?= =?UTF-8?q?e=201/curio=5Frefresh=5Fpaid=202/table=5Fstructure=5Fguard=202/?= =?UTF-8?q?theme=5Fprojection=203)=EF=BC=8B=E4=B8=89=E6=8E=A2=E9=92=88(ui?= =?UTF-8?q?=5Fstruct=20wr2=20=E6=91=98=E8=A6=81=E9=80=90=E5=AD=97=E6=96=AD?= =?UTF-8?q?=E8=A8=80+:446=20=E7=A6=81=E9=A1=B9=E6=B3=A8=E9=87=8A=E6=94=B9?= =?UTF-8?q?=E5=86=99/ui=5Ftune=20wr3+V7/ui=5Fclick=207=20=E6=B3=A8?= =?UTF-8?q?=E9=87=8A)=EF=BC=8BV4-V6=20theme=5Fprojection=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E(=E7=94=9F=E6=B6=AF=E9=A1=B5=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E6=8D=A2=E4=BB=A3+=E9=9B=B6=E6=AE=8B=E7=95=99=E8=B4=9F?= =?UTF-8?q?=E6=96=AD=E8=A8=80/=E8=A7=A3=E9=94=81=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E5=B8=B8=E9=87=8F/=E8=90=A5=E5=9C=B0=E6=9C=80=E8=BF=91?= =?UTF-8?q?=E5=86=92=E9=99=A9=E8=A1=8C=20open=5Fcamp=20=E7=9B=B4=E8=B0=83)?= =?UTF-8?q?=E2=80=94=E2=80=94=E6=96=AD=E8=A8=80=E5=B0=BE=E7=BC=80=E5=8F=A3?= =?UTF-8?q?=E5=BE=84=E6=8D=A2=E4=BB=A3=20Vn(=E9=81=BF=E9=80=80=E5=BD=B9?= =?UTF-8?q?=E8=AF=8D=E8=87=AA=E6=92=9E=20S11);=E9=AA=8C=E8=AF=81=E9=9B=86?= =?UTF-8?q?=E6=B8=85=E5=8D=95=E9=87=8D=E7=94=9F=E6=88=90=201591=20?= =?UTF-8?q?=E6=9D=A1=E5=AF=B9=E8=B4=A6=E9=9B=B6=E5=B7=AE=E5=BC=82;?= =?UTF-8?q?=E6=92=A4=E9=94=80=E8=AF=81=E6=98=8E=20a6-a12=20=E9=80=90?= =?UTF-8?q?=E6=9D=A1=E9=97=AD=E5=90=88(V4/V5/V6/sl2/wr3/V7=20=E5=90=84?= =?UTF-8?q?=E8=87=AA=E7=BA=A2=E2=86=92=E5=A4=8D=E7=BB=BF,ui=5Ftune=20?= =?UTF-8?q?=E5=8F=8C=E7=BA=A2=E9=AA=8C=E8=AF=81=20wr3+V7=20=E7=8B=AC?= =?UTF-8?q?=E7=AB=8B=E9=92=89=E4=BD=8F);=E4=BF=AE=E5=A4=8D=20worktree=20?= =?UTF-8?q?=E7=8E=AF=E5=A2=83=E7=BA=A2=3D=E8=A1=A5=E6=8B=B7=20.import=20?= =?UTF-8?q?=E8=BE=B9=E8=BD=A6=E4=B8=8E=20assets=20=E4=B8=89=E7=9B=AE?= =?UTF-8?q?=E5=BD=95(art=20113=20png+fonts+theme,=E5=9D=91=E5=86=8C?= =?UTF-8?q?=E4=B8=89=E4=BB=B6=E5=A5=97=E5=AE=8C=E6=95=B4=E5=BD=A2=E6=80=81?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/probe/ui_click_probe.gd | 14 +- game/probe/ui_struct_probe.gd | 8 +- game/probe/ui_tune_probe.gd | 7 +- .../integration/cross_system_flow_test.gd | 6 +- game/tests/unit/core/adventure_feats_test.gd | 30 +- .../tests/unit/core/breakpoint_resume_test.gd | 2 +- .../unit/core/curio_refresh_paid_test.gd | 4 +- .../unit/core/level_shop_economy_test.gd | 24 +- .../unit/core/meta_progression_forge_test.gd | 18 +- .../unit/core/save_boot_no_activate_test.gd | 2 +- .../unit/core/save_manager_domain_test.gd | 16 +- .../tests/unit/core/save_slot_summary_test.gd | 2 +- .../data_config/table_structure_guard_test.gd | 4 +- .../unit/presentation/battle_narrator_test.gd | 12 +- .../unit/presentation/reward_overlay_test.gd | 2 +- .../presentation/theme_projection_test.gd | 31 +- game/tests/验证集清单.md | 712 +++++++++--------- 17 files changed, 470 insertions(+), 424 deletions(-) diff --git a/game/probe/ui_click_probe.gd b/game/probe/ui_click_probe.gd index b57d332c..a4da50f5 100644 --- a/game/probe/ui_click_probe.gd +++ b/game/probe/ui_click_probe.gd @@ -31,7 +31,7 @@ var _tested_curio_head := false # 迭代36 卡A——三选一头部旧话清 var _tested_map_cap := false # 迭代36 卡A——地图屏加成帽换代断言(每 run 一次) var _tested_status := false # 状态面板角标开合/守卫断言(每 run 一次) var _tested_map_status := false # 地图屏角标一次性 case(选路态零扰动) -var _inter_confirms := 0 # 大奖励屏确认计数(冒险推进停点——首见确认推进 L2,再见 = L2 通关收口) +var _inter_confirms := 0 # 大奖励屏确认计数(冒险推进停点——首见确认推进 L2,再见 = L2 关卡完成收口) var _settlement_confirms := 0 # 卡⑥ 胜利结算框确认计数(观测面——每场普通战斗胜利恰一) var _route_clicks := 0 # 选路覆盖层点击计数(岔路使用率观测面) var _locktest_state := 0 # T1 D1 锁期/重放断言状态机(0=待注入 1=等重放 2=完结)——每 run 一次 @@ -368,7 +368,7 @@ func _ready() -> void: _problems.append("生涯页关闭后未恢复开始层") # 换回全新零档(营地购买态不泄入后续冒险段——确定性;档案残留下次段首清理兜底) ProbeUiUtil.isolate_save(main, "smoke_click_probe_reset", true, false, true) # 零档换注(继续上局钮已随三入口化撤出——卡② mn8) - main.debug_overlay.set_sliders(400, 200) # 高加成保 L1 可通关——L2 岔路选路段只能经冒险推进到达(单关直入口退役) + main.debug_overlay.set_sliders(400, 200) # 高加成保 L1 可完成——L2 岔路选路段只能经冒险推进到达(单关直入口退役) main.debug_overlay.seed_edit.text = "42" # 种子钉死(种子框默认为空=非首局随机,行为走查确定性禁依赖默认分支) var t1 := Time.get_ticks_msec() main._start_adventure_from_menu() @@ -399,7 +399,7 @@ func _ready() -> void: _problems.append("首格未可点(cells=0)") print("[click_probe] 首格可点计时 %dms(进入战斗屏口径,≤500ms AC)· 场景冷启动 %dms(含 UI 构建 %dms,观测项)" % [ first_cell_ms, t_total, t_ui_ready]) - const ACTION_BUDGET_FRAMES := 20000 # 主循环帧预算(坏态挂死兜底上限——常态通关远低于此;有挂帧证据才收紧,勿让坏态等满预算才报) + const ACTION_BUDGET_FRAMES := 20000 # 主循环帧预算(坏态挂死兜底上限——常态跑完远低于此;有挂帧证据才收紧,勿让坏态等满预算才报) var action_budget := ACTION_BUDGET_FRAMES # P0-2 回归:本 while 循环体缩进必须整体在循环内——continue 落在 # 循环外成解析错误、探针不可加载。bonus 分支保留为体内兄弟分支。 @@ -411,7 +411,7 @@ func _ready() -> void: _seals_placed.clear() continue if main.curio_overlay.visible: - # 三选一停点(CurioPickOverlay——奖励节点/通关兑付共用面,须与硬锁态适配, + # 三选一停点(CurioPickOverlay——奖励节点/关卡完成兑付共用面,须与硬锁态适配, # 未适配则走到即卡死)。两态分派:result 态(兑付反馈——点继续推进)/ # 待选态(点首件+确认)。真实信号路径全线。〔无替换子态——装配不可变契约。〕 # 三选一停点输入锁定断言(停点态断言面:待选/兑付两态共用此层)。 @@ -475,7 +475,7 @@ func _ready() -> void: _seals_placed.clear() continue if main._inter_overlay.visible: - # 大奖励屏(冒险级停点——非末关通关恰一次):首见确认推进 L2(真实按钮信号路径);再见 = L2 已通关,收口 + # 大奖励屏(冒险级停点——非末关的关卡完成恰一次):首见确认推进 L2(真实按钮信号路径);再见 = L2 已关卡完成,收口 if not main._input_locked(): _problems.append("大奖励屏打开时输入未锁定") _inter_confirms += 1 @@ -491,7 +491,7 @@ func _ready() -> void: _problems.append("大奖励确认后未推进到第二关(level_index != 2)") else: _done = true - print("[click_probe] 第二关大奖励屏(L2 通关)——探针收口 · 选路口点击 %d 次" % _route_clicks) + print("[click_probe] 第二关大奖励屏(L2 关卡完成)——探针收口 · 选路口点击 %d 次" % _route_clicks) break _seals_placed.clear() continue @@ -639,7 +639,7 @@ func _ready() -> void: # 驱动设计(0/0 白板局生存性不成立的实证处置——L2 记录进实现报告): # ① 菜单开新局·白板反向=独立短局:0/0 滑条开局断言 L1 开场行零后缀(不开驱动—— # 断言完成后该局被 ② 的开局自然替换,白板局生存性不参与判定); - # ② 局内加算区正向=生存局:400/200 滑条开局保可通关(:363 先例),三选一专选 atk/max_hp + # ② 局内加算区正向=生存局:400/200 滑条开局保可完成(:363 先例),三选一专选 atk/max_hp # 卡(无则任选推进——不触后缀、循环重试);至大奖励屏先 reset_sliders() 再确认进下一层 # ——L2 开场行时点 pct=0 且新档 ov=0,后缀只能归因局内加算区(变异:回退条件 hunk→红); # ③ 断点续玩正向:L2 入口选路停点(bonus 已入账、bonus_pending/bonus_result 皆空——选路停点形) diff --git a/game/probe/ui_struct_probe.gd b/game/probe/ui_struct_probe.gd index 2c7bc0f3..9c687982 100644 --- a/game/probe/ui_struct_probe.gd +++ b/game/probe/ui_struct_probe.gd @@ -431,10 +431,10 @@ func _save_select_contract(main: Node, tpl: String) -> void: else: if not (has_new and not has_load and not has_del): problems.append("[savesel] 行%d 操作集失守(空/坏槽应=仅新档、零进档删档含置灰形态)〔sl4〕" % row_idx) - # sl2 摘要三项逐槽读数:槽1 喂入值逐字(钥石 555/通关 2 局/冒险 7 局) + # sl2 摘要三项逐槽读数:槽1 喂入值逐字(钥石 555/冒险成功 2 局/冒险 7 局) var sum1: Label = sso._summary_labels.get(1) - if sum1 == null or sum1.text != "通关 2 局 · 冒险 7 局": - problems.append("[savesel] 槽1 摘要读数失守(got=%s 应=通关 2 局 · 冒险 7 局)〔sl2〕" % (sum1.text if sum1 else "null")) + if sum1 == null or sum1.text != "冒险成功 2 局 · 冒险 7 局": + problems.append("[savesel] 槽1 摘要读数失守(got=%s 应=冒险成功 2 局 · 冒险 7 局)〔sl2〕" % (sum1.text if sum1 else "null")) var all_texts: Array[String] = [] _collect_labels(sso, all_texts) var has_keystone := false @@ -443,7 +443,7 @@ func _save_select_contract(main: Node, tpl: String) -> void: has_keystone = true if not has_keystone: problems.append("[savesel] 槽1 钥石徽读数缺失(应=钥石 555)〔sl2〕") - # sl3 摘要禁项:断点/种子/「继续」/停点/「 关」(关数形——「通关」无空格不误伤)零命中 + # sl3 摘要禁项:断点/种子/「继续」/停点/「 关」(关数形——摘要「冒险成功 X 局 · 冒险 Y 局」不含「关」字)零命中 #(裁决 4——零未完冒险读数;词形覆盖=对照表 sl3 缺陷形态「断点关数拼进槽卡」的拦截面) for needle in ["断点", "种子", "继续", "停点", " 关"]: for t in all_texts: diff --git a/game/probe/ui_tune_probe.gd b/game/probe/ui_tune_probe.gd index 481cddc7..c02479d9 100644 --- a/game/probe/ui_tune_probe.gd +++ b/game/probe/ui_tune_probe.gd @@ -72,8 +72,11 @@ func _ready() -> void: if main.debug_overlay.is_running(): problems.append("模拟未在预算帧内完成(疑似挂死)") var out: String = main.debug_overlay.output_text() - if not out.contains("通关率"): - problems.append("模拟输出缺通关率") + if not out.contains("关卡完成率"): + problems.append("模拟输出缺关卡完成率") + # 口径换代 V7:胜局统计行措辞钉子(atk+100% 加成档 10 局必有胜局——hp_left_win 非空路径恒出) + if not out.contains("关卡完成剩余 HP 均"): + problems.append("模拟输出缺关卡完成剩余 HP 行〔口径换代 V7〕") if not out.contains("败北节点"): problems.append("模拟输出缺败北节点") if "N=10" not in out: diff --git a/game/tests/integration/cross_system_flow_test.gd b/game/tests/integration/cross_system_flow_test.gd index 8d3a68a5..57e536d5 100644 --- a/game/tests/integration/cross_system_flow_test.gd +++ b/game/tests/integration/cross_system_flow_test.gd @@ -116,14 +116,14 @@ func _save_summary_integration() -> void: var ks_run := 0 for li in range(1, int(_db.level.rows.size()) + 1): ks_run += int(_db.meta_boss_keystone_row(li).get("first_kill", 0)) - Kit.check("摘要集成:冒险驱动满配通关(seed 42)", String(st9.get("result", "")) == "completed") + Kit.check("摘要集成:冒险驱动满配冒险成功(seed 42)", String(st9.get("result", "")) == "completed") Kit.check("集成钥石余额 = ΣBoss 首杀行值(%d——逐杀掉落全源)" % f9.keystone_balance(), f9.keystone_balance() == ks_run) - Kit.check("集成通关次数表全 1", f9.clear_count(1) == 1 and f9.clear_count(2) == 1 and f9.clear_count(3) == 1) + Kit.check("集成关卡完成次数表全 1", f9.clear_count(1) == 1 and f9.clear_count(2) == 1 and f9.clear_count(3) == 1) Kit.check("集成三关首杀标记齐", f9.boss_first_kill_marked(1) and f9.boss_first_kill_marked(2) and f9.boss_first_kill_marked(3)) Kit.check("集成 recent 1 条且 seed 42", f9.recent_summaries().size() == 1 and int(f9.recent_summaries()[0].get("master_seed", -1)) == 42) var st9b: Dictionary = LevelAutoplay.run_adventure(_db, 42, 900, 400) f9.apply_adventure_summary(st9b.get("summary", {})) - Kit.check("第二局后通关次数全 2", f9.clear_count(1) == 2 and f9.clear_count(2) == 2 and f9.clear_count(3) == 2) + Kit.check("第二局后关卡完成次数全 2", f9.clear_count(1) == 2 and f9.clear_count(2) == 2 and f9.clear_count(3) == 2) Kit.check("第二局后余额翻倍(2 × Σ首杀——模拟驱动恒首杀口径)", f9.keystone_balance() == 2 * ks_run) Kit.check("集成 recent 长度 2", f9.recent_summaries().size() == 2) Kit.check("集成写盘成功", f9.write_to_disk()) diff --git a/game/tests/unit/core/adventure_feats_test.gd b/game/tests/unit/core/adventure_feats_test.gd index fedf9f3f..05013fdf 100644 --- a/game/tests/unit/core/adventure_feats_test.gd +++ b/game/tests/unit/core/adventure_feats_test.gd @@ -99,11 +99,11 @@ func _api_mark_node(_node: Dictionary, _info: Dictionary, seq: Array) -> void: seq.append("node_entered") -# ③ 冒险验收断言(映射 冒险结构.md 验收标准——表覆盖/满配通关/种子复现/大奖励/败北线/ +# ③ 冒险验收断言(映射 冒险结构.md 验收标准——表覆盖/满配冒险成功/种子复现/大奖励/败北线/ # 重复拒绝/GP 跨关延续/加算区同账/恢复数学/放弃) -# ③ 冒险验收断言(映射 冒险结构.md 验收标准——表覆盖/满配通关/种子复现/大奖励/败北线/ +# ③ 冒险验收断言(映射 冒险结构.md 验收标准——表覆盖/满配冒险成功/种子复现/大奖励/败北线/ # 重复拒绝/GP 跨关延续/加算区同账/恢复数学/放弃) func _smoke_adventure() -> void: print("--- 冒险结构验收(三关序列 · 大奖励 · 摘要五件事 · 账本封闭)---") @@ -129,11 +129,11 @@ func _smoke_adventure() -> void: cov_miss += 1 Kit.check("生成图每个战斗/Boss 节点经解析链命中敌行集与棋盘行(扫描 %d 节点,缺失 %d)〔fv24〕" % [cov_scan, cov_miss], cov_scan > 0 and cov_miss == 0) - # ② 满配通关 + ④ 三层奖励兑付(三选一恰 2 次 · 回血封顶 · 钥石逐杀 · 候选零重复) + # ② 满配冒险成功 + ④ 三层奖励兑付(三选一恰 2 次 · 回血封顶 · 钥石逐杀 · 候选零重复) var st: Dictionary = autoplay.run_adventure(_db, 42, 900, 400) var sum: Dictionary = st["summary"] - Kit.check("满配通关(42 / atk+900 / hp+400——cleared=true;v2 怪阶梯后旧 200/100 档不再满配)", String(st["result"]) == "completed" and bool(sum.get("cleared", false))) - Kit.check("通关几关 = 3(levels_cleared)", int(sum.get("levels_cleared", -1)) == 3) + Kit.check("满配冒险成功(42 / atk+900 / hp+400——cleared=true;v2 怪阶梯后旧 200/100 档不再满配)", String(st["result"]) == "completed" and bool(sum.get("cleared", false))) + Kit.check("完成几关 = 3(levels_cleared)", int(sum.get("levels_cleared", -1)) == 3) var ks_exp := 0 for li in range(1, int(_db.level.rows.size()) + 1): ks_exp += int(_db.meta_boss_keystone_row(li).get("first_kill", 0)) @@ -151,7 +151,7 @@ func _smoke_adventure() -> void: node_picks += 1 # 奖励节点三选一(每关奖励节点各 1 次) elif (ev as Dictionary).has("curio_resolved"): resolves.append((ev as Dictionary)["curio_resolved"]) - Kit.check("通关三选一恰呈现 2 次、恰兑付 2 次(L1/L2 后——末关不发;resolves 含节点回执另计)", picks.size() == 2 and resolves.size() == 2 + node_picks) + Kit.check("关卡完成三选一恰呈现 2 次、恰兑付 2 次(L1/L2 后——末关不发;resolves 含节点回执另计)", picks.size() == 2 and resolves.size() == 2 + node_picks) # 奖励节点在生成图里是可选路位(旧单链模板的「L1 必经 1 个」形状前提随模板消亡)—— # 接线证明拆两半:图侧每关含 ≥1 奖励节点,行进侧种子扫描内确有经停(扫描零经停=三选一接线不可达) var reward_levels := 0 @@ -242,7 +242,7 @@ func _smoke_adventure() -> void: if rk == "max_hp": hp_acc += int(r.get("value", max_flat)) Kit.check("三选一候选 2–3 枚且零重复(令牌洗牌不放回——kind+tier 复合身份)", cand_ok) - Kit.check("通关部分回血封顶(floor(观测上限×比例) 封顶——购血观测值精确断言,核代码增补)", heal_ok) + Kit.check("关卡完成部分回血封顶(floor(观测上限×比例) 封顶——购血观测值精确断言,核代码增补)", heal_ok) Kit.check("钥石逐杀入账(首杀档位 + 累计逐位)", ks_gain_ok) Kit.check("点选恰兑付选中一件(值=令牌档位表值;未选项零生效)", resolve_ok) var seq: Array = st["encounter_max_hp_seq"] @@ -271,7 +271,7 @@ func _smoke_adventure() -> void: Kit.check("零配 L1 败北种子可达(seed=%s)" % str(lose.get("s", -1)), not lose.is_empty()) if not lose.is_empty(): var sl: Dictionary = lose["st"]["summary"] - Kit.check("L1 败北摘要:未打穿 · 通关 0 关 · 钥石 0 · 止步第 1 层", + Kit.check("L1 败北摘要:未打穿 · 完成 0 关 · 钥石 0 · 止步第 1 层", not bool(sl["cleared"]) and int(sl["levels_cleared"]) == 0 \ and int(sl["keystone_total"]) == 0 and int(sl["stopped_at"]) == 1) var dl: Dictionary = sl.get("defeat", {}) @@ -351,8 +351,8 @@ func _smoke_adventure() -> void: var acc_shop := int(a8.run_ledger.bonus.get("max_hp", -1)) # L1 三选一后 + 商店 3(首件随种子) Kit.check("统一冒险加算区含商店值(max_hp=%d ≥ 商店 3——L1 三选一件值另计)" % acc_shop, acc_shop >= 3) a8._on_level_finished({"result": "victory", "hp": int(r8.hero_hp), "node_index": r8.node_index, - "node_id": r8.current_node_id(), "node_type": "shop"}) # 模拟 L2 通关(victory 载荷直调——非末关) - Kit.check("L2 通关三选一停点在案(直调兑付前——零自动推进)", not a8._curio_pending.is_empty()) + "node_id": r8.current_node_id(), "node_type": "shop"}) # 模拟 L2 关卡完成(victory 载荷直调——非末关) + Kit.check("L2 关卡完成三选一停点在案(直调兑付前——零自动推进)", not a8._curio_pending.is_empty()) Kit.check("未兑付推进拒绝(选择停点零自动推进契约)", not a8.continue_to_next_level()) var l2_cands: Array = a8._curio_pending["candidates"] var l2_pick: Dictionary = l2_cands[0] @@ -361,7 +361,7 @@ func _smoke_adventure() -> void: var expect_acc: int = acc_shop + (int(a8._curio_result.get("value", 0)) if picked2 == "max_hp" else 0) Kit.check("三选一属性件与商店购买同账累加(max_hp=%d = %d + 三选一%s)" % [int(a8.run_ledger.bonus.get("max_hp", -1)), acc_shop, picked2], int(a8.run_ledger.bonus.get("max_hp", -1)) == expect_acc) var max_eff8: int = a8.effective_max_hp() # 账本生效上限含调试浮窗 pct(a8 已 set 400) - Kit.check("通关部分回血封顶(hp %d ≤ 生效上限 %d——血回满语义退役)" % [int(a8.ledger["hero_hp"]), max_eff8], int(a8.ledger["hero_hp"]) <= max_eff8) + Kit.check("关卡完成部分回血封顶(hp %d ≤ 生效上限 %d——血回满语义退役)" % [int(a8.ledger["hero_hp"]), max_eff8], int(a8.ledger["hero_hp"]) <= max_eff8) Kit.check("兑付后推进受理(下一关开始)", a8.continue_to_next_level()) # ⑨ 恢复点数学(接口③封顶公式三读数 + 同式两落点一致) var a9 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(99)) @@ -406,7 +406,7 @@ func _smoke_adventure() -> void: treasure_seen = true break Kit.check("池收缩——40 次重抽零 aux 候选(停点渠道 aux 卡退役,迭代 11 第①批 T7)", not treasure_seen) - # 满血回 0 合法(通关回血封顶口径) + # 满血回 0 合法(关卡完成回血封顶口径) var a12 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(12)) a12.start_adventure(12) var cap := {"payload": {}} @@ -414,7 +414,7 @@ func _smoke_adventure() -> void: var max_full := int(_db.hero.max_hp) + int(a12._base_override.get("max_hp", 0)) a12.ledger["hero_hp"] = max_full a12._on_level_finished({"result": "victory", "hp": max_full, "node_index": 1, "node_id": 1, "node_type": "shop"}) - Kit.check("满血通关回血 0 合法(封顶口径——heal_gained=0 非负溢出)", int(cap["payload"].get("heal_gained", -1)) == 0) + Kit.check("满血关卡完成回血 0 合法(封顶口径——heal_gained=0 非负溢出)", int(cap["payload"].get("heal_gained", -1)) == 0) # ⑬ 奖励节点共享池(同库同池同摘牌;TP0:attack 令牌耗尽后节点域同样零出现) var a13 = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(13)) Kit.check("节点共享池场景:冒险启动(seed 13)", a13.start_adventure(13, {"treasure_unlocked": {"wide_scout_band": true}})) @@ -509,7 +509,7 @@ func _smoke_feats() -> void: if String((t as Dictionary).get("kind", "")) == "relic": deck_relic += 1 Kit.check("专长带入池:5 行 relic 每件 1 张(四级 rarity 直映射)——牌库 102+5=107", deck_relic == 5 and a_r._curio_deck.size() == 107) - # 渠道白名单断言(渠道轴定位:通关渠道只出专长/节点渠道零专长) + # 渠道白名单断言(渠道轴定位:关卡完成渠道只出专长/节点渠道零专长) var feat_seen: Dictionary = {} var node_relic_seen := false for i in 60: @@ -519,7 +519,7 @@ func _smoke_feats() -> void: for t in a_r._draw_curio_candidates("reward_node"): if String((t as Dictionary).get("kind", "")) == "relic": node_relic_seen = true - Kit.check("通关渠道只出专长(60 次重抽 ≥2 种不同 relic——身份键 feat_id 同档可多件)", feat_seen.size() >= 2) + Kit.check("关卡完成渠道只出专长(60 次重抽 ≥2 种不同 relic——身份键 feat_id 同档可多件)", feat_seen.size() >= 2) Kit.check("节点渠道零专长(60 次重抽零 relic——专长在非 Boss 渠道只以专长凭证形态出现)", not node_relic_seen) # T5 专长凭证行为断言(A5 拿到即开 / A6 保底计数——契约④四口径;独立 runner 防污染 a_r 牌库) var a_t = load("res://core/adventure_runner.gd").new(_db, _fresh_rng(91)) diff --git a/game/tests/unit/core/breakpoint_resume_test.gd b/game/tests/unit/core/breakpoint_resume_test.gd index 8ce75e20..e3a180aa 100644 --- a/game/tests/unit/core/breakpoint_resume_test.gd +++ b/game/tests/unit/core/breakpoint_resume_test.gd @@ -96,7 +96,7 @@ func _init() -> void: adr_e._curio_taken["attack"] = 1 # 白盒预置计数(断点附随件往返的判据面——计数不可由加算区反推) adr_e._on_level_finished({"result": "victory", "hp": 30, "node_index": 1, "node_id": 1, "node_type": "shop"}) var cands_e: Array = (adr_e._curio_pending.get("candidates", []) as Array).duplicate() - Kit.check_quiet(not cands_e.is_empty(), "P5 非末关通关三选一停点在案(直调 victory——L1 非末关)") + Kit.check_quiet(not cands_e.is_empty(), "P5 非末关的关卡完成三选一停点在案(直调 victory——L1 非末关)") var sm_f = SaveManagerScript.new(_bp_path) Kit.check_quiet(sm_f.load_from_disk() and sm_f.has_breakpoint(), "P5 选择停点断点在档(选择停点可中断契约)") var bp_f: Dictionary = sm_f.breakpoint_snapshot() diff --git a/game/tests/unit/core/curio_refresh_paid_test.gd b/game/tests/unit/core/curio_refresh_paid_test.gd index 26392adc..b5ac2cad 100644 --- a/game/tests/unit/core/curio_refresh_paid_test.gd +++ b/game/tests/unit/core/curio_refresh_paid_test.gd @@ -23,9 +23,9 @@ func _init() -> void: Kit.check_quiet(adr.curio_stop_pending() == false, "无停点=在途谓词 false") Kit.check_quiet(adr.refresh_curio() == false and adr.refresh_curio_paid() == false, "无停点:免费/付费刷新皆拒绝零副作用") - # ---- ② 免费位优先序 X→Y(白盒造通关停点——smoke_all ⑫ 同构)---- + # ---- ② 免费位优先序 X→Y(白盒造关卡完成停点——smoke_all ⑫ 同构)---- adr._curio_pending = {"candidates": _cands(), "payload": {}} - Kit.check_quiet(adr.curio_stop_pending() == true, "通关停点在途=谓词 true") + Kit.check_quiet(adr.curio_stop_pending() == true, "关卡完成停点在途=谓词 true") adr._attune_refresh_x = 1 adr._attune_refresh_y = 2 Kit.check_quiet(adr.refresh_curio() and adr._attune_refresh_x == 0 and adr._attune_refresh_y == 2, "X 优先消耗(x1y2→x0y2)") diff --git a/game/tests/unit/core/level_shop_economy_test.gd b/game/tests/unit/core/level_shop_economy_test.gd index 0288f789..a0771fe6 100644 --- a/game/tests/unit/core/level_shop_economy_test.gd +++ b/game/tests/unit/core/level_shop_economy_test.gd @@ -1,6 +1,6 @@ # tests/unit/core/level_shop_economy_test.gd — 关卡图与 GP 商店单元测试宿主 # 断言面 = 七套(批 B 断言迁移自 smoke_all.gd,G8 施工组): -# 关卡节点图·生成图推进(满配通关/恢复点公式/败北线/回放确定性/属性覆盖恢复) +# 关卡节点图·生成图推进(满配冒险成功/恢复点公式/败北线/回放确定性/属性覆盖恢复) # 分支节点图(图校验正反/L2·L3 行进与行集定点/混编运行面/真图类型可见性) # GP 冒险钱包·到账(掷定窗口/关级加值) # escrow 隔离(格面兑付入缓冲/破财直验/钱包钳制不透支) @@ -323,15 +323,15 @@ func _smoke_generated_coverage() -> void: # ---- 关卡节点图·生成图推进冒烟(图 = 该关参数档 × 种子)---- func _smoke_level() -> void: - print("--- 关卡节点图·生成图推进(参数档×种子产图·满配通关/恢复公式/败北线/回放确定性)---") + print("--- 关卡节点图·生成图推进(参数档×种子产图·满配冒险成功/恢复公式/败北线/回放确定性)---") var autoplay = load("res://sim/level_autoplay.gd") var hero_base := {"atk": int(_db.hero.atk), "hp": int(_db.hero.max_hp), "ac": int(_db.hero.armor_class)} # 配置基线快照——⑤ 回基线对比用(改表自动跟随,不再硬编码) var nodes1: Array = _level_active_nodes(1) var params1: Dictionary = _db.level_gen_params_row(1) Kit.check("L1 现行起关图取数非空(种子 %d × 参数档 → 节点 %d 颗)" % [ACTIVE_GRAPH_SEED, nodes1.size()], not nodes1.is_empty()) - # ① 满配通关路径(atk+200%/hp+100%——测试面板同源的属性覆盖) + # ① 满配冒险成功路径(atk+200%/hp+100%——测试面板同源的属性覆盖) var win = autoplay.run_level(_db, ACTIVE_GRAPH_SEED, 1, 200, 100) - Kit.check("关卡·满配(atk+200/hp+100)通关(实测:%s @节点 %d)" % [win.result, win.defeat_node_index], win.result == "victory") + Kit.check("关卡·满配(atk+200/hp+100)完成(实测:%s @节点 %d)" % [win.result, win.defeat_node_index], win.result == "victory") # 行进面读数与图读数自洽:路径逐跳为图出边,路径上战斗/Boss 计数 = battles 读数 var by_id1 := _nodes_by_id(nodes1) var path_battles := 0 @@ -339,10 +339,10 @@ func _smoke_level() -> void: var vkind := String(by_id1.get(int(vid), {}).get("type", "")) if vkind == "battle" or vkind == "boss": path_battles += 1 - Kit.check("L1 通关路径逐跳为图出边(入口起步·末节点无出边——句柄轴行进自洽)", _path_in_graph(nodes1, win.visited_ids)) - Kit.check("L1 通关路径战斗/Boss 节点数 = 行进 battles 读数(路径 %d 节点·战斗 %d 颗·battles %d)" % [win.visited_ids.size(), path_battles, int(win.battles)], + Kit.check("L1 关卡完成路径逐跳为图出边(入口起步·末节点无出边——句柄轴行进自洽)", _path_in_graph(nodes1, win.visited_ids)) + Kit.check("L1 关卡完成路径战斗/Boss 节点数 = 行进 battles 读数(路径 %d 节点·战斗 %d 颗·battles %d)" % [win.visited_ids.size(), path_battles, int(win.battles)], path_battles == int(win.battles) and path_battles >= 2) - # 终点恒落最长路径步数:Boss 深度 = 参数档层高,且通关路径末节点即该终点 + # 终点恒落最长路径步数:Boss 深度 = 参数档层高,且关卡完成路径末节点即该终点 var boss_depth1 := -1 for n in nodes1: if String(n.get("type", "")) == "boss": @@ -350,7 +350,7 @@ func _smoke_level() -> void: var last_id := -1 if win.visited_ids.size() > 0: last_id = int(win.visited_ids[win.visited_ids.size() - 1]) - Kit.check("L1 终点 Boss 深度 = 参数档层高 %d 且通关路径末节点落该深度(实测终点深度 %d·末句柄 %d)" % [int(params1.get("layers", -1)), boss_depth1, last_id], + Kit.check("L1 终点 Boss 深度 = 参数档层高 %d 且关卡完成路径末节点落该深度(实测终点深度 %d·末句柄 %d)" % [int(params1.get("layers", -1)), boss_depth1, last_id], boss_depth1 == int(params1.get("layers", -1)) and int(by_id1.get(last_id, {}).get("depth", -1)) == boss_depth1) Kit.check("L1 终点恰一个(大岔口自 L2 起的图侧投影)", _terminal_ids(nodes1).size() == 1 and _ids_of_type(nodes1, "boss").size() == 1) Kit.check("L1 生成图含岔口(出度 ≥2 节点 %d 处)" % _fork_ids(nodes1).size(), _fork_ids(nodes1).size() >= 1) @@ -371,7 +371,7 @@ func _smoke_level() -> void: else: Kit.check("恢复点公式·缺口不足档:回复封顶到缺口 2(实测 %d,比例项 %d)" % [int(rest_narrow["healed"]), expect_pct], int(rest_narrow["healed"]) == mini(expect_pct, 2) and expect_pct > 2) - # ③ 裸装败北路径(atk1/hp10——Roguelike 基线应难以通关) + # ③ 裸装败北路径(atk1/hp10——Roguelike 基线应难以完成) var lose = autoplay.run_level(_db, ACTIVE_GRAPH_SEED, 1, -80, -80) Kit.check("关卡·裸装(atk≈1/hp≈10)败北路径可达(实测:%s)" % lose.result, lose.result == "defeat") Kit.check("败北节点记录在域内(节点 %d,图节点数 %d)" % [lose.defeat_node_index, nodes1.size()], @@ -488,7 +488,7 @@ func _smoke_level_graph() -> void: Kit.check("图校验拒绝:非 Boss 终点(终点恒为 Boss)〔v1〕", _has_err_category(LT.validate_graph(orphan), "structural")) # ④ L2 选路推进:min / max 双路径全通(确定性路径轴——同种子同图,方向轴只换候选取值) var win_min: Dictionary = autoplay.run_level(_db, ACTIVE_GRAPH_SEED, 2, 200, 100, false, null, "normal", "min") - Kit.check("L2·满配 min 路径通关(实测:%s)" % win_min.result, win_min.result == "victory") + Kit.check("L2·满配 min 路径完成(实测:%s)" % win_min.result, win_min.result == "victory") var n2_last := -1 if win_min.visited_ids.size() > 0: n2_last = int(win_min.visited_ids[win_min.visited_ids.size() - 1]) @@ -501,7 +501,7 @@ func _smoke_level_graph() -> void: _path_shop_count(nodes2, win_min.visited_ids) == 1) Kit.check("选路口发生 %d 次(每节点兑付后——零自动推进)" % win_min.choices, win_min.choices >= 3) var win_max: Dictionary = autoplay.run_level(_db, ACTIVE_GRAPH_SEED, 2, 200, 100, false, null, "normal", "max") - Kit.check("L2·满配 max 路径(候选取最大句柄)通关(实测:%s·路径 %s)" % [win_max.result, str(win_max.visited_ids)], win_max.result == "victory") + Kit.check("L2·满配 max 路径(候选取最大句柄)完成(实测:%s·路径 %s)" % [win_max.result, str(win_max.visited_ids)], win_max.result == "victory") var n2_last_max := -1 if win_max.visited_ids.size() > 0: n2_last_max = int(win_max.visited_ids[win_max.visited_ids.size() - 1]) @@ -973,7 +973,7 @@ func _smoke_shop_room() -> void: var shop_run := {} for s in range(42, 92): var r0 = load("res://core/level_runner.gd").new(_db, _fresh_rng(s)) - r0.set_hero_override(900, 400) # 行进段快速通关档(购买断言与百分比轴正交——加算区单独断言) + r0.set_hero_override(900, 400) # 行进段快速完成档(购买断言与百分比轴正交——加算区单独断言) r0.start_level(2, s) var st := _battle_st("normal") var guard := 60 diff --git a/game/tests/unit/core/meta_progression_forge_test.gd b/game/tests/unit/core/meta_progression_forge_test.gd index 967bd3be..93901791 100644 --- a/game/tests/unit/core/meta_progression_forge_test.gd +++ b/game/tests/unit/core/meta_progression_forge_test.gd @@ -159,7 +159,7 @@ func _meta_settle_and_workshop() -> void: var row1: Dictionary = _db.meta_boss_keystone_row(1) var row2: Dictionary = _db.meta_boss_keystone_row(2) # ⑥ 逐杀掉落收束入账(掉落已在冒险内逐杀入账〔summary.keystone_total 含全部〕, - # keystone_drops 明细随摘要归档;首杀标记仍由 apply 逐通关关次置位) + # keystone_drops 明细随摘要归档;首杀标记仍由 apply 逐关卡完成关次置位) var d1: Dictionary = mp.settle_adventure({"result": "failed", "cleared": false, "levels_cleared": 1, "stopped_at": 2, "keystone_total": int(row1.get("first_kill", 0)), "keystone_drops": [{"level": 1, "first": true, "amount": int(row1.get("first_kill", 0))}], @@ -186,21 +186,21 @@ func _meta_settle_and_workshop() -> void: "master_seed": 13}) Kit.check("重复杀第三轮恒定不递减(验收5——无衰减曲线)", not bool(d3["boss_drops"][0].get("first", true)) and int(d3["boss_drops"][0].get("amount", 0)) == int(row1.get("repeat_kill", -1))) - # 混合归因:通关两关 → L1 重复 + L2 首杀(明细随摘要逐笔归档) + # 混合归因:完成两关 → L1 重复 + L2 首杀(明细随摘要逐笔归档) var d4: Dictionary = mp.settle_adventure({"result": "failed", "cleared": false, "levels_cleared": 2, "stopped_at": 0, "keystone_total": int(row1.get("repeat_kill", 0)) + int(row2.get("first_kill", 0)), "keystone_drops": [{"level": 1, "first": false, "amount": int(row1.get("repeat_kill", 0))}, {"level": 2, "first": true, "amount": int(row2.get("first_kill", 0))}], "master_seed": 14}) - Kit.check("两关通关逐关归因:L1 重复档 + L2 首杀档(first_kill 金额)", + Kit.check("两关完成逐关归因:L1 重复档 + L2 首杀档(first_kill 金额)", not bool(d4["boss_drops"][0].get("first", true)) and bool(d4["boss_drops"][1].get("first", false)) and int(d4["boss_drops"][1].get("amount", 0)) == int(row2.get("first_kill", -1))) - # ⑦ 败北零通关摘要:余额只增不减(零入账)、clear_counts 不变 + # ⑦ 败北零关卡完成摘要:余额只增不减(零入账)、clear_counts 不变 var bal_before: int = sv.keystone_balance() var cc1_before: int = sv.clear_count(1) var dz: Dictionary = mp.settle_adventure({"result": "failed", "cleared": false, "levels_cleared": 0, "stopped_at": 1, "keystone_total": 0, "master_seed": 15}) - Kit.check("败北零通关摘要:零入账零标记(钥石只增不减——验收1;败北局 clear_counts 不变)", + Kit.check("败北零关卡完成摘要:零入账零标记(钥石只增不减——验收1;败北局 clear_counts 不变)", dz["boss_drops"].is_empty() and sv.keystone_balance() == bal_before and sv.clear_count(1) == cc1_before) # ⑧ 秘宝解锁服务(V3 钥石购买/V4 条件解锁;注入=直调解锁写口+直置存档生涯计数, # 不走正常资源积累流程——卡片 7.1 测试方式) @@ -217,10 +217,10 @@ func _meta_settle_and_workshop() -> void: and sv_u.keystone_balance() == 0) Kit.check("已解锁重复购买拒绝〔秘宝批 V3〕", not mp_u.buy_treasure_unlock("morning_order")) - Kit.check("条件未达不解锁(远程镐=通关 1 次)〔秘宝批 V4〕", + Kit.check("条件未达不解锁(远程镐=冒险成功 1 次)〔秘宝批 V4〕", mp_u.refresh_treasure_unlocks().is_empty() and not sv_u.item_unlocked("ranged_pick")) sv_u._data["meta"]["adventure_cleared"] = 1 # 直置存档生涯计数(调试注入口径) - Kit.check("远程镐=adventure_cleared≥1 达标恰解锁一次+重复刷新幂等(C6:通关=打通整局冒险)〔秘宝批 V4〕", + Kit.check("远程镐=adventure_cleared≥1 达标恰解锁一次+重复刷新幂等(C6:冒险成功=打通整局冒险)〔秘宝批 V4〕", (mp_u.refresh_treasure_unlocks() as Array).has("ranged_pick") and sv_u.item_unlocked("ranged_pick") and mp_u.refresh_treasure_unlocks().is_empty()) sv_u._data["meta"]["boss_kill_count"] = 3 @@ -230,7 +230,7 @@ func _meta_settle_and_workshop() -> void: Kit.check("天眼单条件不足不解锁(AND 语义——cleared 3 达 boss 4 未达)〔秘宝批 V4〕", not sv_u.item_unlocked("sky_eye")) sv_u._data["meta"]["boss_kill_count"] = 4 - Kit.check("天眼双条件 AND(通关≥3 且 Boss≥4)达标解锁〔秘宝批 V4〕", + Kit.check("天眼双条件 AND(冒险成功≥3 且 Boss≥4)达标解锁〔秘宝批 V4〕", (mp_u.refresh_treasure_unlocks() as Array).has("sky_eye")) sv_u._data["meta"]["vision_used"] = 10 Kit.check("信标网络=真视类工具累计使用≥10(行为计数新域——use_treasure 受理成功累计)〔秘宝批 V4〕", @@ -267,7 +267,7 @@ func _meta_settle_and_workshop() -> void: and int(mp_a.attune_camp_status()["refresh"]["charges"]) == 1) mp_a.settle_adventure({"result": "failed", "cleared": false, "levels_cleared": 1, "stopped_at": 2, "keystone_total": 0, "master_seed": 21}) - Kit.check("通关 1 关 → Slots 恒 0(旧「按击杀 Boss 次数自动涨」条件已删——槽位唯一来源=树点亮)且 Boss 击杀总数=1(计数域保留)〔天赋树批 V14〕", + Kit.check("完成 1 关 → Slots 恒 0(旧「按击杀 Boss 次数自动涨」条件已删——槽位唯一来源=树点亮)且 Boss 击杀总数=1(计数域保留)〔天赋树批 V14〕", Attunement.slots(_db, sv_a) == 0 and sv_a.boss_kill_count() == 1) sv_a.set_tree_level("att_socket1", 1) Kit.check("树上点亮同调位 1 → Slots=1(槽位收编树节点——Q2 裁甲)", diff --git a/game/tests/unit/core/save_boot_no_activate_test.gd b/game/tests/unit/core/save_boot_no_activate_test.gd index 4ac1d291..7f6a60e1 100644 --- a/game/tests/unit/core/save_boot_no_activate_test.gd +++ b/game/tests/unit/core/save_boot_no_activate_test.gd @@ -27,7 +27,7 @@ func _test_no_arg_instance_has_no_activation() -> void: "sv2 无参实例无激活态(路径空/激活号 0/写盘目标空)〔卡① sv2〕") Kit.check_quiet(sm.keystone_balance() == 0 and not sm.has_breakpoint() and sm.adventure_total() == 0 and sm.adventure_cleared() == 0, - "sv2 内存=默认合法空态(钥石/断点/总局数/通关数全零值——访问器 fail-safe)〔卡① sv2〕") + "sv2 内存=默认合法空态(钥石/断点/总局数/冒险成功数全零值——访问器 fail-safe)〔卡① sv2〕") # attach_path 注入任意隔离路径=注入即激活(契约 7 单路径语义——隔离面行为零变化) sm.attach_path("user://smoke_boot_noact_iso.json") Kit.check_quiet(sm.has_write_target() and sm.keystone_balance() == 0, diff --git a/game/tests/unit/core/save_manager_domain_test.gd b/game/tests/unit/core/save_manager_domain_test.gd index d33c1ca2..8e23fd32 100644 --- a/game/tests/unit/core/save_manager_domain_test.gd +++ b/game/tests/unit/core/save_manager_domain_test.gd @@ -78,11 +78,11 @@ func _smoke_save() -> void: w.unlock_item("probe_compass") w.apply_adventure_summary({"result": "failed", "cleared": false, "levels_cleared": 2, "stopped_at": 3, "keystone_total": 3, "master_seed": 99}) - Kit.check("apply 原语入账(钥石 7+3、通关次数 1/1/0)", + Kit.check("apply 原语入账(钥石 7+3、关卡完成次数 1/1/0)", w.keystone_balance() == 10 and w.clear_count(1) == 1 and w.clear_count(2) == 1 and w.clear_count(3) == 0) - Kit.check("首杀标记随通关关卡置位(1/2 有、3 无)", + Kit.check("首杀标记随关卡完成置位(1/2 有、3 无)", w.boss_first_kill_marked(1) and w.boss_first_kill_marked(2) and not w.boss_first_kill_marked(3)) - Kit.check("生涯终身计数随 apply 自增恰一(中止局:总局数 1、通关局数 0——迭代 18 卡④)", + Kit.check("生涯终身计数随 apply 自增恰一(中止局:总局数 1、冒险成功局数 0——迭代 18 卡④)", w.adventure_total() == 1 and w.adventure_cleared() == 0) Kit.check("写盘成功", w.write_to_disk()) var r = sm_script.new(paths[0]) @@ -95,7 +95,7 @@ func _smoke_save() -> void: and r.forge_unlocked_purchases() == ["spear"] and r.forge_weapon() == "spear" and r.forge_armor() == "ward") Kit.check("道具解锁往返相等", r.item_unlocked("probe_compass") and not r.item_unlocked("rope")) - Kit.check("通关次数表往返相等", r.clear_count(1) == 1 and r.clear_count(2) == 1 and r.clear_count(3) == 0) + Kit.check("关卡完成次数表往返相等", r.clear_count(1) == 1 and r.clear_count(2) == 1 and r.clear_count(3) == 0) Kit.check("首杀标记往返相等", r.boss_first_kill_marked(1) and r.boss_first_kill_marked(2) and not r.boss_first_kill_marked(3)) Kit.check("生涯终身计数往返相等(1/0)", r.adventure_total() == 1 and r.adventure_cleared() == 0) @@ -265,11 +265,11 @@ func _smoke_save() -> void: f13b.load_from_disk() f13b.apply_adventure_summary({"result": "completed", "cleared": true, "levels_cleared": 3, "stopped_at": 0, "keystone_total": 0, "master_seed": 1}) - Kit.check("收束自增恰一·通关局(三关全通 cleared=true:总局数+1 且通关局数+1)", + Kit.check("收束自增恰一·冒险成功局(三关全通 cleared=true:总局数+1 且冒险成功局数+1)", f13b.adventure_total() == 1 and f13b.adventure_cleared() == 1) f13b.apply_adventure_summary({"result": "abandoned", "cleared": false, "levels_cleared": 1, "stopped_at": 2, "keystone_total": 0, "master_seed": 2}) - Kit.check("收束自增恰一·中止局(放弃局:仅总局数+1,通关局数不动)", + Kit.check("收束自增恰一·中止局(放弃局:仅总局数+1,冒险成功局数不动)", f13b.adventure_total() == 2 and f13b.adventure_cleared() == 1) # ⑮ 旧档破坏性废弃(契约 4:换代前结构检测=树域废弃重置,禁迁移禁折算)〔V16〕 @@ -321,11 +321,11 @@ func _smoke_save() -> void: var mp13 = load("res://core/meta_progression.gd").new(_db, f13b) mp13.settle_adventure({"result": "failed", "cleared": false, "levels_cleared": 2, "stopped_at": 3, "keystone_total": 0, "master_seed": 3}) - Kit.check("收束链自增·中止局(settle_adventure 真实挂点:总局数+1、通关局数不动)", + Kit.check("收束链自增·中止局(settle_adventure 真实挂点:总局数+1、冒险成功局数不动)", f13b.adventure_total() == 3 and f13b.adventure_cleared() == 1) mp13.settle_adventure({"result": "completed", "cleared": true, "levels_cleared": 3, "stopped_at": 0, "keystone_total": 0, "master_seed": 4}) - Kit.check("收束链自增·通关局(三关全通:总局数+1 且通关局数+1——全链恰一)", + Kit.check("收束链自增·冒险成功局(三关全通:总局数+1 且冒险成功局数+1——全链恰一)", f13b.adventure_total() == 4 and f13b.adventure_cleared() == 2) # 段尾清理(测试文件绝不残留) diff --git a/game/tests/unit/core/save_slot_summary_test.gd b/game/tests/unit/core/save_slot_summary_test.gd index ba9592e7..ae0be20e 100644 --- a/game/tests/unit/core/save_slot_summary_test.gd +++ b/game/tests/unit/core/save_slot_summary_test.gd @@ -46,7 +46,7 @@ func _test_peek_three_slots_distinct_values() -> void: var ps: Dictionary = t.peek_slot_summary(i) Kit.check_quiet(bool(ps.get("readable", false)) and int(ps.get("keystone", -1)) == 200 * i and int(ps.get("cleared", -1)) == i and int(ps.get("total", -1)) == 5 * i, - "sv7 窥视三项逐槽正确·槽 %d(钥石/通关/总局)〔卡① sv7〕" % i) + "sv7 窥视三项逐槽正确·槽 %d(钥石/冒险成功/总局)〔卡① sv7〕" % i) Kit.check_quiet(t.active_slot() == 0 and not t.has_write_target() and t.keystone_balance() == 0, "sv7 窥视不激活不写内存(激活号 0/无写盘目标/内存余额零)〔卡① sv7〕") # 路径注入口同语义(契约 7 注入面) diff --git a/game/tests/unit/data_config/table_structure_guard_test.gd b/game/tests/unit/data_config/table_structure_guard_test.gd index 285d5bad..c180a42c 100644 --- a/game/tests/unit/data_config/table_structure_guard_test.gd +++ b/game/tests/unit/data_config/table_structure_guard_test.gd @@ -93,7 +93,7 @@ func _smoke_adventure_table() -> void: if _db.adventure == null: return Kit.check("AdventureTable.validate() 零违例(全键域检+档位配额结构锚在案)", _db.adventure.validate().is_empty()) - Kit.check("clear_heal_pct ∈ [0,100](%d——通关部分回血比例)" % int(_db.adventure.clear_heal_pct), + Kit.check("clear_heal_pct ∈ [0,100](%d——关卡完成部分回血比例)" % int(_db.adventure.clear_heal_pct), int(_db.adventure.clear_heal_pct) >= 0 and int(_db.adventure.clear_heal_pct) <= 100) for tier in _db.adventure.TIERS: Kit.check("档位配额结构锚(四级 70/25/7/0——迭代 31 卡② 净删两件投放):%s = %d 张" % [tier, int(_db.adventure.TIER_QUOTAS[tier])], @@ -464,7 +464,7 @@ func _smoke_nine_types_gp_stream() -> void: gp_pos = int(row.weight) if String(row.get("reward_id", "")) == "gp_lose": gp_neg = int(row.weight) - Kit.check("奖励字典 18 行(九型×正负 18 格——aux 挖格投放四行已退役 2026-10-01 用户拍板甲:战斗/挖格不掉道具,秘宝唯一来路=三选一共享池〔节点/通关〕;清图槽独立批尾不计)", + Kit.check("奖励字典 18 行(九型×正负 18 格——aux 挖格投放四行已退役 2026-10-01 用户拍板甲:战斗/挖格不掉道具,秘宝唯一来路=三选一共享池〔节点/关卡完成〕;清图槽独立批尾不计)", cell_rows == 18) # 危险格负向直伤当量(负向≈正向 2 倍定价——真人反馈「三雷 3/4 血无后果感」的投值口径) var mine_power := {"heal_backlash": 6, "pierce_snare": 8, "magic_recoil": 8} # 危险格负向直伤当量(抬档值;依据见 numfix 报告) diff --git a/game/tests/unit/presentation/battle_narrator_test.gd b/game/tests/unit/presentation/battle_narrator_test.gd index eb733b9d..e58a8085 100644 --- a/game/tests/unit/presentation/battle_narrator_test.gd +++ b/game/tests/unit/presentation/battle_narrator_test.gd @@ -83,19 +83,19 @@ func _test_boss_name_uses_boss_rowset() -> void: Kit.check("Boss 名与同深度战斗行集名不同(期望「%s」≠「%s」——行类路由可判别)〔fv24〕" % [boss_expect, battle_name], boss_expect != battle_name) -# 关卡完成停点文案族措辞钉子(通关口径换代批):回血行/满血合法态/渠道句/摘要关数行—— -# 「通关」退役后玩家可见面由本组断言钉在新措辞上(撤销证明:回退 battle_narrator 对应行→断言红→复原复绿) +# 关卡完成停点文案族措辞钉子(口径换代批):回血行/满血合法态/渠道句/摘要关数行—— +# 旧措辞退役后玩家可见面由本组断言钉在新措辞上(撤销证明:回退 battle_narrator 对应行→断言红→复原复绿) func _test_level_clear_wording() -> void: var healed: String = NarratorScript.curio_pick_header({"level_index": 1, "heal_gained": 5, "hp_before": 10, "hp_after": 15}) - Kit.check("关卡完成回血行带入回血量与生命区间(实际「%s」)〔通关换代 V1〕" % healed, + Kit.check("关卡完成回血行带入回血量与生命区间(实际「%s」)〔口径换代 V1〕" % healed, healed.contains("关卡完成回血 +5(生命 10 → 15)")) var full_hp: String = NarratorScript.curio_pick_header({"level_index": 1, "heal_gained": 0, "hp_before": 12, "hp_after": 12}) - Kit.check("满血零回血合法态文案(实际「%s」)〔通关换代 V1〕" % full_hp, + Kit.check("满血零回血合法态文案(实际「%s」)〔口径换代 V1〕" % full_hp, full_hp.contains("生命已满——关卡完成回血 0(合法态)")) var node_header: String = NarratorScript.node_curio_header() - Kit.check("奖励节点头部行渠道句点明关卡完成三选一(实际「%s」)〔通关换代 V2〕" % node_header, + Kit.check("奖励节点头部行渠道句点明关卡完成三选一(实际「%s」)〔口径换代 V2〕" % node_header, node_header.contains("与关卡完成专长三选一同库分流")) var summary: String = NarratorScript.adventure_summary_text( {"cleared": false, "result": "failed", "levels_cleared": 1, "stopped_at": 2, "keystone_total": 4, "master_seed": 42}) - Kit.check("冒险摘要完成关数行(实际「%s」)〔通关换代 V3〕" % summary, + Kit.check("冒险摘要完成关数行(实际「%s」)〔口径换代 V3〕" % summary, summary.contains("完成 1 关 · 止步第 2 层") and not summary.contains("通关")) diff --git a/game/tests/unit/presentation/reward_overlay_test.gd b/game/tests/unit/presentation/reward_overlay_test.gd index c619ca07..0f02d1b9 100644 --- a/game/tests/unit/presentation/reward_overlay_test.gd +++ b/game/tests/unit/presentation/reward_overlay_test.gd @@ -1,6 +1,6 @@ extends SceneTree # 三选一覆盖层 UI 直验套件—— -# 守 node_overlay.show_reward_items 的继任共用面;奖励节点三选一与通关三选一共用 CurioPickOverlay, +# 守 node_overlay.show_reward_items 的继任共用面;奖励节点三选一与关卡完成三选一共用 CurioPickOverlay, # 本套件守共用面的「功能存在 ≠ 功能可达」盲区:选择外发/强制确认两段式/结果态。 # 〔无替换子面板路段——装配不可变契约 1,overlay 无 replace 态。〕 # 运行:godot --headless --path game --script res://tests/unit/presentation/reward_overlay_test.gd(expect 0) diff --git a/game/tests/unit/presentation/theme_projection_test.gd b/game/tests/unit/presentation/theme_projection_test.gd index 09bb9178..fc43789c 100644 --- a/game/tests/unit/presentation/theme_projection_test.gd +++ b/game/tests/unit/presentation/theme_projection_test.gd @@ -52,6 +52,7 @@ func _init() -> void: _smoke_diag_button_retired() _status_panel_projection() _career_overlay_projection() + _camp_recent_projection() quit(Kit.finish("theme_projection_test")) @@ -806,6 +807,20 @@ func _all_labels(root: Node) -> Array: return out +# ---- 营地最近冒险行投影(口径换代 V6:完成关数措辞钉子——open_camp 全量重建路径直调; +# 最小档 data=recent 单条 completed 局,其余键缺省走 .get 兜底——与组合根 _camp_data 投影同键面)---- +func _camp_recent_projection() -> void: + print("--- 营地·最近冒险行投影(open_camp 最小档)---") + var camp = load("res://presentation/views/camp_overlay_view.gd").new() + camp.open_camp({"balance": 0, "recent": [ + {"result": "completed", "levels_cleared": 2, "keystone_total": 5, "master_seed": 42}]}) + var recent_text: String = String(camp._recent_list.text) + Kit.check("营地最近冒险行完成关数措辞(实际「%s」)〔口径换代 V6〕" % recent_text, + recent_text.contains("完成 2 关") and not recent_text.contains("通关")) + camp.visible = false + camp.free() + + # ---- 生涯页只读投影一致性(汇总段六类九项逐行 == SaveManager 计数访问器/ # MetaProgression 访问器读数;投影拼装与 HudPresenter.career_data 同构(同访问器族同序)。 # 只读性连接巡检与零动效断言归 ui_struct_probe 呈现侧,本段只管数据面+旧档载入显示 @@ -837,17 +852,27 @@ func _career_overlay_projection() -> void: Kit.check("生涯页开层可见(open_career 直开——零动效路径)", co.visible) Kit.check("总局数投影 = adventure_total() 读数(%s)" % co._total_label.text, String(co._total_label.text) == "2 局") - Kit.check("通关局数投影 = adventure_cleared() 读数(%s)" % co._cleared_label.text, + Kit.check("冒险成功局数投影 = adventure_cleared() 读数(%s)" % co._cleared_label.text, String(co._cleared_label.text) == "1 局(三关全通)") var expect_clears: Array[String] = [] for row in (data["clears"] as Array): expect_clears.append("%s ×%d" % [String(row.get("display_name", "")), int(row.get("count", 0))]) - Kit.check("各关通关次数投影 = clear_count() 逐关读数(%s)" % co._clears_label.text, + Kit.check("各关完成次数投影 = clear_count() 逐关读数(%s)" % co._clears_label.text, String(co._clears_label.text) == " · ".join(expect_clears)) Kit.check("Boss 首杀/总杀投影 = 首杀标记计数 + boss_kill_count()(%s / %s)" % [co._boss_first_label.text, co._boss_kills_label.text], String(co._boss_first_label.text) == "3/3 关" and String(co._boss_kills_label.text) == "4 次") Kit.check("钥石余额徽投影 = keystone_balance() 读数(%s)" % co._keystone_badge.value_label.text, String(co._keystone_badge.value_label.text) == "钥石 %d" % mp.keystone_balance()) + # 口径换代(2026-10-26):行标签换代钉子+生涯页零「通关」残留(负断言兜全页) + var career_label_texts: Array[String] = [] + for career_lbl: Label in _all_labels(co): + career_label_texts.append(String(career_lbl.text)) + var career_labels_joined: String = "|".join(career_label_texts) + Kit.check("生涯页行标签换代(冒险成功局数/各关完成次数)〔口径换代 V4〕", + career_labels_joined.contains("冒险成功局数") and career_labels_joined.contains("各关完成次数")) + Kit.check("生涯页 label 全集零「通关」残留〔口径换代 V4〕", not career_labels_joined.contains("通关")) + Kit.check("秘宝解锁条件标签冒险成功口径(UiKit 单点常量)〔口径换代 V5〕", + UiKit.TREASURE_REQ_LABELS["adventure_cleared"] == "冒险成功") co.visible = false co.free() # 旧档载入显示(完成定义 6):v5 现役档形态(计数域两键不存在)升 v6 → 生涯页正常呈现缺省值 @@ -866,7 +891,7 @@ func _career_overlay_projection() -> void: "count": v5.clear_count(i + 1)}) var co_v5 = load("res://presentation/views/career_overlay.gd").new() co_v5.open_career(data_v5) - Kit.check("旧档载入后生涯页正常显示(v5 升 v6:总局数/通关局数显示 0,既有钥石余额原样呈现)", + Kit.check("旧档载入后生涯页正常显示(v5 升 v6:总局数/冒险成功局数显示 0,既有钥石余额原样呈现)", co_v5.visible and String(co_v5._total_label.text) == "0 局" \ and String(co_v5._cleared_label.text) == "0 局(三关全通)" \ and String(co_v5._keystone_badge.value_label.text) == "钥石 3") diff --git a/game/tests/验证集清单.md b/game/tests/验证集清单.md index 260ab97e..1b7653f1 100644 --- a/game/tests/验证集清单.md +++ b/game/tests/验证集清单.md @@ -1,8 +1,8 @@ # 验证集清单(断言快照·冻结) -> 生成日期:2026-10-26 · 基点 commit:`7d2fbe158fa38d98b917762aa8812a80c8d70aea` · 源:cross_system_flow_test.gd、node_map_determinism_test.gd、save_rng_roundtrip_test.gd、system_test.gd、damage_controller_test.gd、damage_math_test.gd、roll_multiplier_test.gd、round_flow_skill_pool_test.gd、seal_polarity_test.gd、skill_unlock_test.gd、variant_placement_test.gd、source_guard_test.gd、system_contracts_test.gd、adventure_feats_test.gd、board_gen_reward_test.gd、board_generator_test.gd、breakpoint_resume_test.gd、config_db_cross_validator_test.gd、config_db_resolver_test.gd、curio_refresh_paid_test.gd、effect_words_t1_test.gd、feat_vouchers_test.gd、level_map_type_vis_test.gd、level_shop_economy_test.gd、level_table_validate_test.gd、meta_progression_forge_test.gd、minesweeper_rules_test.gd、node_map_generator_test.gd、node_map_growth_test.gd、pool_case_d_test.gd、save_boot_no_activate_test.gd、save_manager_domain_test.gd、save_slot_isolation_test.gd、save_slot_summary_test.gd、settle_segments_test.gd、treasure_effects_test.gd、treasure_items_test.gd、tree_requires_level_test.gd、tree_rules_v11_test.gd、config_db_fatal_oob_test.gd、config_db_test.gd、counter_prefix_fatal_test.gd、forge_table_test.gd、level_gen_params_test.gd、reward_dangling_treasure_test.gd、rng_service_test.gd、rng_stream_boot_test.gd、table_structure_guard_test.gd、treasure_target_violation_test.gd、example_test.gd、battle_narrator_test.gd、forge_workbench_test.gd、hud_presenter_test.gd、level_map_info_fog_test.gd、modal_flow_test.gd、pacing_queue_test.gd、player_copy_sweep_test.gd、reward_overlay_test.gd、standee_fx_sweep_test.gd、terrain_tile_sets_test.gd、theme_projection_test.gd、type_glow_test.gd、ui_font_asset_test.gd、test_kit.gd +> 生成日期:2026-10-26 · 基点 commit:`54395b8b434c2662924947e886c65c7393d88de4` · 源:cross_system_flow_test.gd、node_map_determinism_test.gd、save_rng_roundtrip_test.gd、system_test.gd、damage_controller_test.gd、damage_math_test.gd、roll_multiplier_test.gd、round_flow_skill_pool_test.gd、seal_polarity_test.gd、skill_unlock_test.gd、variant_placement_test.gd、source_guard_test.gd、system_contracts_test.gd、adventure_feats_test.gd、board_gen_reward_test.gd、board_generator_test.gd、breakpoint_resume_test.gd、config_db_cross_validator_test.gd、config_db_resolver_test.gd、curio_refresh_paid_test.gd、effect_words_t1_test.gd、feat_vouchers_test.gd、level_map_type_vis_test.gd、level_shop_economy_test.gd、level_table_validate_test.gd、meta_progression_forge_test.gd、minesweeper_rules_test.gd、node_map_generator_test.gd、node_map_growth_test.gd、pool_case_d_test.gd、save_boot_no_activate_test.gd、save_manager_domain_test.gd、save_slot_isolation_test.gd、save_slot_summary_test.gd、settle_segments_test.gd、treasure_effects_test.gd、treasure_items_test.gd、tree_requires_level_test.gd、tree_rules_v11_test.gd、config_db_fatal_oob_test.gd、config_db_test.gd、counter_prefix_fatal_test.gd、forge_table_test.gd、level_gen_params_test.gd、reward_dangling_treasure_test.gd、rng_service_test.gd、rng_stream_boot_test.gd、table_structure_guard_test.gd、treasure_target_violation_test.gd、example_test.gd、battle_narrator_test.gd、forge_workbench_test.gd、hud_presenter_test.gd、level_map_info_fog_test.gd、modal_flow_test.gd、pacing_queue_test.gd、player_copy_sweep_test.gd、reward_overlay_test.gd、standee_fx_sweep_test.gd、terrain_tile_sets_test.gd、theme_projection_test.gd、type_glow_test.gd、ui_font_asset_test.gd、test_kit.gd > 提取口径:静态 `check(` 调用点,括号配平归集(可跨行);缺省源=三宿主遍历 -> (unit/**+integration/**+system_test.gd)。本基点实测 1583 个静态调用点;行级 +> (unit/**+integration/**+system_test.gd)。本基点实测 1591 个静态调用点;行级 > `grep -c "check("` 是另一口径(含 `func check(` 定义行与注释行),两口径各自浮动, > 禁互相换算(tests/README「断言计数双口径」)。运行时计数大于静态计数=循环展开条目。 > 生成命令:`python tools/extract_checks.py --extract`(可复现;重新生成须 --force; @@ -32,12 +32,12 @@ | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 5 | 119 | "摘要集成:冒险驱动满配通关(seed 42)" | String(st9.get("result", "")) == "completed" | (待填) | | | +| 5 | 119 | "摘要集成:冒险驱动满配冒险成功(seed 42)" | String(st9.get("result", "")) == "completed" | (待填) | | | | 6 | 120 | "集成钥石余额 = ΣBoss 首杀行值(%d——逐杀掉落全源)" ↩ % f9.keystone_balance() | f9.keystone_balance() == ks_run | (待填) | | | -| 7 | 121 | "集成通关次数表全 1" | f9.clear_count(1) == 1 and f9.clear_count(2) == 1 and f9.clear_count(3) == 1 | (待填) | | | +| 7 | 121 | "集成关卡完成次数表全 1" | f9.clear_count(1) == 1 and f9.clear_count(2) == 1 and f9.clear_count(3) == 1 | (待填) | | | | 8 | 122 | "集成三关首杀标记齐" | f9.boss_first_kill_marked(1) and f9.boss_first_kill_marked(2) and f9.boss_first_kill_marked(3) | (待填) | | | | 9 | 123 | "集成 recent 1 条且 seed 42" | f9.recent_summaries().size() == 1 and int(f9.recent_summaries()[0].get("master_seed", -1)) == 42 | (待填) | | | -| 10 | 126 | "第二局后通关次数全 2" | f9.clear_count(1) == 2 and f9.clear_count(2) == 2 and f9.clear_count(3) == 2 | (待填) | | | +| 10 | 126 | "第二局后关卡完成次数全 2" | f9.clear_count(1) == 2 and f9.clear_count(2) == 2 and f9.clear_count(3) == 2 | (待填) | | | | 11 | 127 | "第二局后余额翻倍(2 × Σ首杀——模拟驱动恒首杀口径)" | f9.keystone_balance() == 2 * ks_run | (待填) | | | | 12 | 128 | "集成 recent 长度 2" | f9.recent_summaries().size() == 2 | (待填) | | | | 13 | 129 | "集成写盘成功" | f9.write_to_disk() | (待填) | | | @@ -825,25 +825,25 @@ |---|---|---|---|---|---|---| | 456 | 113 | "序列关数 = 行集关数(三关正式序列生效)" | int(_db.level.rows.size()) == 3 | (待填) | | | | 457 | 130 | "生成图每个战斗/Boss 节点经解析链命中敌行集与棋盘行(扫描 %d 节点,缺失 %d)〔fv24〕" ↩ % [cov_scan, cov_miss] | cov_scan > 0 and cov_miss == 0 | (待填) | | | -| 458 | 135 | "满配通关(42 / atk+900 / hp+400——cleared=true;v2 怪阶梯后旧 200/100 档不再满配)" | String(st["result"]) == "completed" and bool(sum.get("cleared", false)) | (待填) | | | -| 459 | 136 | "通关几关 = 3(levels_cleared)" | int(sum.get("levels_cleared", -1)) == 3 | (待填) | | | +| 458 | 135 | "满配冒险成功(42 / atk+900 / hp+400——cleared=true;v2 怪阶梯后旧 200/100 档不再满配)" | String(st["result"]) == "completed" and bool(sum.get("cleared", false)) | (待填) | | | +| 459 | 136 | "完成几关 = 3(levels_cleared)" | int(sum.get("levels_cleared", -1)) == 3 | (待填) | | | | 460 | 140 | "钥石合计 = ΣBoss 首杀行值(%d——逐杀掉落新口径;断点未注入恒首杀)" ↩ % int(sum.get("keystone_total", -1)) | int(sum.get("keystone_total", -1)) == ks_exp | (待填) | | | | 461 | 142 | "逐杀掉落明细恰 3 笔(L1/L2/L3——additive 摘要键 keystone_drops)" | drops.size() == 3 | (待填) | | | | 462 | 143 | "摘要携带主种子(42)" | int(sum.get("master_seed", -1)) == 42 | (待填) | | | -| 463 | 154 | "通关三选一恰呈现 2 次、恰兑付 2 次(L1/L2 后——末关不发;resolves 含节点回执另计)" | picks.size() == 2 and resolves.size() == 2 + node_picks | (待填) | | | +| 463 | 154 | "关卡完成三选一恰呈现 2 次、恰兑付 2 次(L1/L2 后——末关不发;resolves 含节点回执另计)" | picks.size() == 2 and resolves.size() == 2 + node_picks | (待填) | | | | 464 | 165 | "三关生成图各含 ≥1 奖励节点(节点三选一候选位在图)〔v4〕" | reward_levels == 3 | (待填) | | | | 465 | 169 | "奖励分支点选→三选一候选可取且停点在途(候选 %s 件)" ↩ % str((rw.get("cands", []) as Array).size()) | bool(rw.get("pending", false)) and (rw.get("cands", []) as Array).size() >= 1 | (待填) | | | | 466 | 182 | "奖励三选一点选兑付受理(件=%s)" ↩ % String(rw_pc.get("kind", "")) | rw_pick_ok | (待填) | | | | 467 | 188 | "进战载荷两样=关卡序号+节点深度(实测 depth=%s 句柄=%s)〔v6〕" ↩ % [str(enc_probe.get("node_depth", -1)), str(node_probe.get("id", -1))] | not enc_probe.is_empty() and int(enc_probe.get("node_depth", -1)) == int(node_probe.get("depth", -1)) and int(enc_probe.get("level_index", -1)) == 1 and int(node_probe.get("id", -1)) != int(node_probe.get("depth", -1)) | (待填) | | | | 468 | 197 | "奖励节点兑付回执与经停逐笔相等(context=reward_node——同账计数 %d/%d)" ↩ % [node_resolves, node_picks] | node_resolves == node_picks | (待填) | | | | 469 | 244 | "三选一候选 2–3 枚且零重复(令牌洗牌不放回——kind+tier 复合身份)" | cand_ok | (待填) | | | -| 470 | 245 | "通关部分回血封顶(floor(观测上限×比例) 封顶——购血观测值精确断言,核代码增补)" | heal_ok | (待填) | | | +| 470 | 245 | "关卡完成部分回血封顶(floor(观测上限×比例) 封顶——购血观测值精确断言,核代码增补)" | heal_ok | (待填) | | | | 471 | 246 | "钥石逐杀入账(首杀档位 + 累计逐位)" | ks_gain_ok | (待填) | | | | 472 | 247 | "点选恰兑付选中一件(值=令牌档位表值;未选项零生效)" | resolve_ok | (待填) | | | | 473 | 258 | "各战上限入参 ∈ [基础, 基础+3×件值+购血余量](覆盖值通道——双渠道共享上限 3;模拟档贪心购血合法叠加〔数值修复批 v3.4〕;首战=基础 %d)" ↩ % exp_base | seq_ok | (待填) | | | | 474 | 261 | "同种子两局逐位可复现(summary/上限序列/行进序列/三选一载荷——reward_pick 封闭流)" | st2["summary"] == sum and st2["encounter_max_hp_seq"] == seq and st2["visited_ids"] == st["visited_ids"] and st2["reward_events"] == st["reward_events"] | (待填) | | | | 475 | 271 | "零配 L1 败北种子可达(seed=%s)" ↩ % str(lose.get("s", -1)) | not lose.is_empty() | (待填) | | | -| 476 | 274 | "L1 败北摘要:未打穿 · 通关 0 关 · 钥石 0 · 止步第 1 层" | not bool(sl["cleared"]) and int(sl["levels_cleared"]) == 0 \\ and int(sl["keystone_total"]) == 0 and int(sl["stopped_at"]) == 1 | (待填) | | | +| 476 | 274 | "L1 败北摘要:未打穿 · 完成 0 关 · 钥石 0 · 止步第 1 层" | not bool(sl["cleared"]) and int(sl["levels_cleared"]) == 0 \\ and int(sl["keystone_total"]) == 0 and int(sl["stopped_at"]) == 1 | (待填) | | | | 477 | 278 | "L1 败北败退明细:层号/节点编号/节点类型在案(数值验证取数面 2026-09-22)" | int(dl.get("level_index", -1)) == 1 and int(dl.get("node_id", -1)) >= 0 \\ and String(dl.get("node_type", "")) in ["battle", "boss"] | (待填) | | | | 478 | 287 | "半配(atk+50)L2 败北种子可达(seed=%s)" ↩ % str(half.get("s", -1)) | not half.is_empty() | (待填) | | | | 479 | 290 | "L2 败北摘要:L1 已过(钥石=L1 首杀掉落)· 止步第 2 层" | not bool(sh["cleared"]) and int(sh["levels_cleared"]) == 1 \\ and int(sh["keystone_total"]) == int(_db.meta_boss_keystone_row(1).get("first_kill", 0)) \\ and int(sh["stopped_at"]) == 2 | (待填) | | | @@ -858,11 +858,11 @@ | 488 | 349 | "进店余额 ≥ hp_up L2 首价(%d = 基价 %d + 关卡加成 %d——配置推导)" ↩ % [hp_price + l2_price_bonus, hp_price, l2_price_bonus] | gp0 >= hp_price + l2_price_bonus | (待填) | | | | 489 | 350 | "购买 hp_up 受理(出账 + 加算区)" | r8.buy_product("hp_up") | (待填) | | | | 490 | 352 | "统一冒险加算区含商店值(max_hp=%d ≥ 商店 3——L1 三选一件值另计)" ↩ % acc_shop | acc_shop >= 3 | (待填) | | | -| 491 | 355 | "L2 通关三选一停点在案(直调兑付前——零自动推进)" | not a8._curio_pending.is_empty() | (待填) | | | +| 491 | 355 | "L2 关卡完成三选一停点在案(直调兑付前——零自动推进)" | not a8._curio_pending.is_empty() | (待填) | | | | 492 | 356 | "未兑付推进拒绝(选择停点零自动推进契约)" | not a8.continue_to_next_level() | (待填) | | | | 493 | 359 | "三选一点选兑付受理(候选取首件)" | a8.pick_curio(String(l2_pick.get("kind", "")), String(l2_pick.get("tier", "")), String(l2_pick.get("feat_id", ""))) | (待填) | | | | 494 | 362 | "三选一属性件与商店购买同账累加(max_hp=%d = %d + 三选一%s)" ↩ % [int(a8.run_ledger.bonus.get("max_hp", -1)), acc_shop, picked2] | int(a8.run_ledger.bonus.get("max_hp", -1)) == expect_acc | (待填) | | | -| 495 | 364 | "通关部分回血封顶(hp %d ≤ 生效上限 %d——血回满语义退役)" ↩ % [int(a8.ledger["hero_hp"]), max_eff8] | int(a8.ledger["hero_hp"]) <= max_eff8 | (待填) | | | +| 495 | 364 | "关卡完成部分回血封顶(hp %d ≤ 生效上限 %d——血回满语义退役)" ↩ % [int(a8.ledger["hero_hp"]), max_eff8] | int(a8.ledger["hero_hp"]) <= max_eff8 | (待填) | | | | 496 | 365 | "兑付后推进受理(下一关开始)" | a8.continue_to_next_level() | (待填) | | | | 497 | 368 | "恢复点数学:floor(100×30%)=30 · 封顶缺口 5 · 满血回 0 合法" | int(a9.apply_rest(30, 70, 100)) == 30 and int(a9.apply_rest(30, 95, 100)) == 5 \\ and int(a9.apply_rest(30, 100, 100)) == 0 | (待填) | | | | 498 | 372 | "同一公式两个落点逐位一致(LevelRunner.rest_heal_amount 内置默认)" | int(lr9.rest_heal_amount(30, 70, 100)) == 30 and int(lr9.rest_heal_amount(30, 95, 100)) == 5 | (待填) | | | @@ -874,7 +874,7 @@ | 504 | 398 | "池耗即枯竭(attack/ap 令牌耗尽不出候选——%s)" ↩ % str(draw) | not draw_kinds.has("attack") and not draw_kinds.has("ap") | (待填) | | | | 505 | 399 | "池耗后候选恒 ≥2(稀有档余量——防「三选项全不可选」死角)" | (draw as Array).size() >= 2 | (待填) | | | | 506 | 408 | "池收缩——40 次重抽零 aux 候选(停点渠道 aux 卡退役,迭代 11 第①批 T7)" | not treasure_seen | (待填) | | | -| 507 | 417 | "满血通关回血 0 合法(封顶口径——heal_gained=0 非负溢出)" | int(cap["payload"].get("heal_gained", -1)) == 0 | (待填) | | | +| 507 | 417 | "满血关卡完成回血 0 合法(封顶口径——heal_gained=0 非负溢出)" | int(cap["payload"].get("heal_gained", -1)) == 0 | (待填) | | | | 508 | 420 | "节点共享池场景:冒险启动(seed 13)" | a13.start_adventure(13, {"treasure_unlocked": {"wide_scout_band": true}}) | (待填) | | | | 509 | 431 | "奖励节点共享池:令牌耗尽同样不出候选(同库同池——%s)" ↩ % str(ncands13) | not has_attack13 | (待填) | | | | 510 | 435 | "奖励节点 GP 件入账(钱包「奖励入账」收口——+%d)" ↩ % int(_db.adventure.curio_value("gp", "common")) | a13.apply_node_curio("gp", "common") and int(a13.ledger.get("gp", 0)) == gp13 + int(_db.adventure.curio_value("gp", "common")) | (待填) | | | @@ -898,7 +898,7 @@ | 523 | 502 | "新 schema 构造表 validate 零违例(四级 rarity/cap 字段/词表全过——流派标签已退役零 archetype)" | rt.validate().is_empty() | (待填) | | | | 524 | 506 | "专长带场景:冒险启动(seed 72——注入 5 行临时表)" | a_r.start_adventure(72) | (待填) | | | | 525 | 511 | "专长带入池:5 行 relic 每件 1 张(四级 rarity 直映射)——牌库 102+5=107" | deck_relic == 5 and a_r._curio_deck.size() == 107 | (待填) | | | -| 526 | 522 | "通关渠道只出专长(60 次重抽 ≥2 种不同 relic——身份键 feat_id 同档可多件)" | feat_seen.size() >= 2 | (待填) | | | +| 526 | 522 | "关卡完成渠道只出专长(60 次重抽 ≥2 种不同 relic——身份键 feat_id 同档可多件)" | feat_seen.size() >= 2 | (待填) | | | | 527 | 523 | "节点渠道零专长(60 次重抽零 relic——专长在非 Boss 渠道只以专长凭证形态出现)" | not node_relic_seen | (待填) | | | | 528 | 531 | "A5 专长凭证兑付受理(节点渠道——拿到即开)" | a_t.apply_node_curio("feat_ticket", "excellent") | (待填) | | | | 529 | 537 | "A5 拿到即开——停点候选已替换为专长三选一(全 relic)" | tkt_all_relic | (待填) | | | @@ -1213,10 +1213,10 @@ | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| | 690 | 331 | "L1 现行起关图取数非空(种子 %d × 参数档 → 节点 %d 颗)" ↩ % [ACTIVE_GRAPH_SEED, nodes1.size()] | not nodes1.is_empty() | (待填) | | | -| 691 | 334 | "关卡·满配(atk+200/hp+100)通关(实测:%s @节点 %d)" ↩ % [win.result, win.defeat_node_index] | win.result == "victory" | (待填) | | | -| 692 | 342 | "L1 通关路径逐跳为图出边(入口起步·末节点无出边——句柄轴行进自洽)" | _path_in_graph(nodes1, win.visited_ids) | (待填) | | | -| 693 | 343 | "L1 通关路径战斗/Boss 节点数 = 行进 battles 读数(路径 %d 节点·战斗 %d 颗·battles %d)" ↩ % [win.visited_ids.size(), path_battles, int(win.battles)] | path_battles == int(win.battles) and path_battles >= 2 | (待填) | | | -| 694 | 353 | "L1 终点 Boss 深度 = 参数档层高 %d 且通关路径末节点落该深度(实测终点深度 %d·末句柄 %d)" ↩ % [int(params1.get("layers", -1)), boss_depth1, last_id] | boss_depth1 == int(params1.get("layers", -1)) and int(by_id1.get(last_id, {}).get("depth", -1)) == boss_depth1 | (待填) | | | +| 691 | 334 | "关卡·满配(atk+200/hp+100)完成(实测:%s @节点 %d)" ↩ % [win.result, win.defeat_node_index] | win.result == "victory" | (待填) | | | +| 692 | 342 | "L1 关卡完成路径逐跳为图出边(入口起步·末节点无出边——句柄轴行进自洽)" | _path_in_graph(nodes1, win.visited_ids) | (待填) | | | +| 693 | 343 | "L1 关卡完成路径战斗/Boss 节点数 = 行进 battles 读数(路径 %d 节点·战斗 %d 颗·battles %d)" ↩ % [win.visited_ids.size(), path_battles, int(win.battles)] | path_battles == int(win.battles) and path_battles >= 2 | (待填) | | | +| 694 | 353 | "L1 终点 Boss 深度 = 参数档层高 %d 且关卡完成路径末节点落该深度(实测终点深度 %d·末句柄 %d)" ↩ % [int(params1.get("layers", -1)), boss_depth1, last_id] | boss_depth1 == int(params1.get("layers", -1)) and int(by_id1.get(last_id, {}).get("depth", -1)) == boss_depth1 | (待填) | | | | 695 | 355 | "L1 终点恰一个(大岔口自 L2 起的图侧投影)" | _terminal_ids(nodes1).size() == 1 and _ids_of_type(nodes1, "boss").size() == 1 | (待填) | | | | 696 | 356 | "L1 生成图含岔口(出度 ≥2 节点 %d 处)" ↩ % _fork_ids(nodes1).size() | _fork_ids(nodes1).size() >= 1 | (待填) | | | | 697 | 357 | "进 Boss HP 携带在域内(%d)" ↩ % win.hp_at_boss | win.hp_at_boss >= 1 and win.hp_at_boss <= int(_db.hero.max_hp) * 3 | (待填) | | | @@ -1248,12 +1248,12 @@ | 718 | 479 | "图校验拒绝:回边 1→0(目标深度须严格大于源)〔v1〕" | _has_err_category(LT.validate_graph(cyc), "structural") | (待填) | | | | 719 | 482 | "图校验拒绝:出边指向不存在句柄(悬空致命)〔v1〕" | _has_err_category(LT.validate_graph(dang), "dangling_next") | (待填) | | | | 720 | 488 | "图校验拒绝:非 Boss 终点(终点恒为 Boss)〔v1〕" | _has_err_category(LT.validate_graph(orphan), "structural") | (待填) | | | -| 721 | 491 | "L2·满配 min 路径通关(实测:%s)" ↩ % win_min.result | win_min.result == "victory" | (待填) | | | +| 721 | 491 | "L2·满配 min 路径完成(实测:%s)" ↩ % win_min.result | win_min.result == "victory" | (待填) | | | | 722 | 496 | "L2 min 路径逐跳为图出边·末节点为 Boss(实测路径 %s·末句柄型别 %s)" ↩ % [str(win_min.visited_ids), n2_last_type] | _path_in_graph(nodes2, win_min.visited_ids) and n2_last_type == "boss" | (待填) | | | | 723 | 498 | "L2 min 路径终点深度 = 参数档层高 %d(行进读数 %d——终点落最长路径步数)" ↩ % [int(params2.get("layers", -1)), int(win_min.boss_depth)] | int(win_min.boss_depth) == int(params2.get("layers", -1)) | (待填) | | | | 724 | 500 | "L2 min 路径穿商店恰 1 家(路径句柄 %s 型别计数 = 1——必经恰一店的行进面)" ↩ % str(win_min.visited_ids) | _path_shop_count(nodes2, win_min.visited_ids) == 1 | (待填) | | | | 725 | 502 | "选路口发生 %d 次(每节点兑付后——零自动推进)" ↩ % win_min.choices | win_min.choices >= 3 | (待填) | | | -| 726 | 504 | "L2·满配 max 路径(候选取最大句柄)通关(实测:%s·路径 %s)" ↩ % [win_max.result, str(win_max.visited_ids)] | win_max.result == "victory" | (待填) | | | +| 726 | 504 | "L2·满配 max 路径(候选取最大句柄)完成(实测:%s·路径 %s)" ↩ % [win_max.result, str(win_max.visited_ids)] | win_max.result == "victory" | (待填) | | | | 727 | 509 | "L2 max 路径逐跳为图出边·末节点为 Boss·穿商店恰 1 家" | _path_in_graph(nodes2, win_max.visited_ids) and n2_last_max_type == "boss" and _path_shop_count(nodes2, win_max.visited_ids) == 1 | (待填) | | | | 728 | 512 | "L2 max 与 min 路径分岔(方向轴生效——两路终点句柄 %d / %d 不同)" ↩ % [n2_last, n2_last_max] | n2_last != n2_last_max and win_max.visited_ids != win_min.visited_ids | (待填) | | | | 729 | 519 | "手动驱动:L2 启动(入口战斗直接开打——入口无前置兑付;图 = 参数档 × 种子 %d)" ↩ % ACTIVE_GRAPH_SEED | runner.start_level(2, ACTIVE_GRAPH_SEED) | (待填) | | | @@ -1474,17 +1474,17 @@ | 889 | 173 | "余额 = 累计入账(逐杀掉落合计——无重复加账)" | sv.keystone_balance() == int(row1.get("first_kill", 0)) | (待填) | | | | 890 | 181 | "再通 L1:{first:false, amount=repeat_kill}(首杀标记置位后转小额)" | not bool(drop2.get("first", true)) and int(drop2.get("amount", 0)) == int(row1.get("repeat_kill", -1)) | (待填) | | | | 891 | 187 | "重复杀第三轮恒定不递减(验收5——无衰减曲线)" | not bool(d3["boss_drops"][0].get("first", true)) and int(d3["boss_drops"][0].get("amount", 0)) == int(row1.get("repeat_kill", -1)) | (待填) | | | -| 892 | 195 | "两关通关逐关归因:L1 重复档 + L2 首杀档(first_kill 金额)" | not bool(d4["boss_drops"][0].get("first", true)) and bool(d4["boss_drops"][1].get("first", false)) and int(d4["boss_drops"][1].get("amount", 0)) == int(row2.get("first_kill", -1)) | (待填) | | | -| 893 | 203 | "败北零通关摘要:零入账零标记(钥石只增不减——验收1;败北局 clear_counts 不变)" | dz["boss_drops"].is_empty() and sv.keystone_balance() == bal_before and sv.clear_count(1) == cc1_before | (待填) | | | +| 892 | 195 | "两关完成逐关归因:L1 重复档 + L2 首杀档(first_kill 金额)" | not bool(d4["boss_drops"][0].get("first", true)) and bool(d4["boss_drops"][1].get("first", false)) and int(d4["boss_drops"][1].get("amount", 0)) == int(row2.get("first_kill", -1)) | (待填) | | | +| 893 | 203 | "败北零关卡完成摘要:零入账零标记(钥石只增不减——验收1;败北局 clear_counts 不变)" | dz["boss_drops"].is_empty() and sv.keystone_balance() == bal_before and sv.clear_count(1) == cc1_before | (待填) | | | | 894 | 210 | "条件件误购拒绝(购买件专属——契约 8 分配面)〔秘宝批 V3 反例〕" | not mp_u.buy_treasure_unlock("sky_eye") and not sv_u.item_unlocked("sky_eye") and not mp_u.buy_treasure_unlock("ranged_pick") | (待填) | | | | 895 | 213 | "余额不足购买拒绝且零副作用(余额 10 < 价 25)〔秘宝批 V3〕" | not mp_u.buy_treasure_unlock("twin_loader") and sv_u.keystone_balance() == 10 | (待填) | | | | 896 | 215 | "钥石购买解锁:余额足→解锁态落档+余额扣减正确(价 10)〔秘宝批 V3〕" | mp_u.buy_treasure_unlock("morning_order") and sv_u.item_unlocked("morning_order") and sv_u.keystone_balance() == 0 | (待填) | | | | 897 | 218 | "已解锁重复购买拒绝〔秘宝批 V3〕" | not mp_u.buy_treasure_unlock("morning_order") | (待填) | | | -| 898 | 220 | "条件未达不解锁(远程镐=通关 1 次)〔秘宝批 V4〕" | mp_u.refresh_treasure_unlocks().is_empty() and not sv_u.item_unlocked("ranged_pick") | (待填) | | | -| 899 | 223 | "远程镐=adventure_cleared≥1 达标恰解锁一次+重复刷新幂等(C6:通关=打通整局冒险)〔秘宝批 V4〕" | (mp_u.refresh_treasure_unlocks() as Array).has("ranged_pick") and sv_u.item_unlocked("ranged_pick") and mp_u.refresh_treasure_unlocks().is_empty() | (待填) | | | +| 898 | 220 | "条件未达不解锁(远程镐=冒险成功 1 次)〔秘宝批 V4〕" | mp_u.refresh_treasure_unlocks().is_empty() and not sv_u.item_unlocked("ranged_pick") | (待填) | | | +| 899 | 223 | "远程镐=adventure_cleared≥1 达标恰解锁一次+重复刷新幂等(C6:冒险成功=打通整局冒险)〔秘宝批 V4〕" | (mp_u.refresh_treasure_unlocks() as Array).has("ranged_pick") and sv_u.item_unlocked("ranged_pick") and mp_u.refresh_treasure_unlocks().is_empty() | (待填) | | | | 900 | 227 | "刷新执照=boss_kill_count≥3(阈值读 unlock_requires 行值不硬编)〔秘宝批 V4〕" | (mp_u.refresh_treasure_unlocks() as Array).has("refresh_license") | (待填) | | | | 901 | 230 | "天眼单条件不足不解锁(AND 语义——cleared 3 达 boss 4 未达)〔秘宝批 V4〕" | not sv_u.item_unlocked("sky_eye") | (待填) | | | -| 902 | 233 | "天眼双条件 AND(通关≥3 且 Boss≥4)达标解锁〔秘宝批 V4〕" | (mp_u.refresh_treasure_unlocks() as Array).has("sky_eye") | (待填) | | | +| 902 | 233 | "天眼双条件 AND(冒险成功≥3 且 Boss≥4)达标解锁〔秘宝批 V4〕" | (mp_u.refresh_treasure_unlocks() as Array).has("sky_eye") | (待填) | | | | 903 | 236 | "信标网络=真视类工具累计使用≥10(行为计数新域——use_treasure 受理成功累计)〔秘宝批 V4〕" | (mp_u.refresh_treasure_unlocks() as Array).has("beacon_network") | (待填) | | | | 904 | 241 | "解锁态持久投影一致(reload 面同源读数;5 件=购买 1+条件 4)〔秘宝批 V4〕" | r_n == 5 | (待填) | | | | 905 | 244 | "摘要最新在前 + 元素含掉落明细副本(复盘可归因——验收5)" | rs.size() >= 5 and String(rs[0].get("result", "")) != "" and rs[0].has("boss_drops") and (rs[1] as Dictionary).has("keystone_drops") and int(rs[0].get("master_seed", -1)) == 15 | (待填) | | | @@ -1492,7 +1492,7 @@ | 907 | 258 | "白板档同调位求值 = 0(0 起步裁决)且 Y=0(未购无刷新能力——P1 甲初始 0 同构)" | Attunement.slots(_db, sv_a) == 0 and int(mp_a.attune_camp_status()["refresh"]["charges"]) == 0 | (待填) | | | | 908 | 260 | "满位禁选(Slots 0 时装配拒绝;兼未解锁拒绝前置——直置解锁后下方装配)〔秘宝批 V5〕" | mp_a.toggle_attunement("morning_order") == false | (待填) | | | | 909 | 265 | "Y 升级购买入账(Lv1 → 每冒险 +1 次刷新)" | mp_a.buy_attune_refresh() and sv_a.attune_refresh_level() == 1 and int(mp_a.attune_camp_status()["refresh"]["charges"]) == 1 | (待填) | | | -| 910 | 270 | "通关 1 关 → Slots 恒 0(旧「按击杀 Boss 次数自动涨」条件已删——槽位唯一来源=树点亮)且 Boss 击杀总数=1(计数域保留)〔天赋树批 V14〕" | Attunement.slots(_db, sv_a) == 0 and sv_a.boss_kill_count() == 1 | (待填) | | | +| 910 | 270 | "完成 1 关 → Slots 恒 0(旧「按击杀 Boss 次数自动涨」条件已删——槽位唯一来源=树点亮)且 Boss 击杀总数=1(计数域保留)〔天赋树批 V14〕" | Attunement.slots(_db, sv_a) == 0 and sv_a.boss_kill_count() == 1 | (待填) | | | | 911 | 273 | "树上点亮同调位 1 → Slots=1(槽位收编树节点——Q2 裁甲)" | Attunement.slots(_db, sv_a) == 1 | (待填) | | | | 912 | 275 | "稀有件入普通格拒绝(件档 rank 3 > 装入位序 1——契约 2 档位格校验)〔秘宝批 V5〕" | not mp_a.toggle_attunement("sky_eye") | (待填) | | | | 913 | 277 | "装配持久写入 + 满位禁选(Slots 1 装第二件拒绝)〔秘宝批 V5 换主语〕" | mp_a.toggle_attunement("morning_order") and mp_a.toggle_attunement("twin_loader") == false | (待填) | | | @@ -1763,16 +1763,16 @@ | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1071 | 81 | "apply 原语入账(钥石 7+3、通关次数 1/1/0)" | w.keystone_balance() == 10 and w.clear_count(1) == 1 and w.clear_count(2) == 1 and w.clear_count(3) == 0 | (待填) | | | -| 1072 | 83 | "首杀标记随通关关卡置位(1/2 有、3 无)" | w.boss_first_kill_marked(1) and w.boss_first_kill_marked(2) and not w.boss_first_kill_marked(3) | (待填) | | | -| 1073 | 85 | "生涯终身计数随 apply 自增恰一(中止局:总局数 1、通关局数 0——迭代 18 卡④)" | w.adventure_total() == 1 and w.adventure_cleared() == 0 | (待填) | | | +| 1071 | 81 | "apply 原语入账(钥石 7+3、关卡完成次数 1/1/0)" | w.keystone_balance() == 10 and w.clear_count(1) == 1 and w.clear_count(2) == 1 and w.clear_count(3) == 0 | (待填) | | | +| 1072 | 83 | "首杀标记随关卡完成置位(1/2 有、3 无)" | w.boss_first_kill_marked(1) and w.boss_first_kill_marked(2) and not w.boss_first_kill_marked(3) | (待填) | | | +| 1073 | 85 | "生涯终身计数随 apply 自增恰一(中止局:总局数 1、冒险成功局数 0——迭代 18 卡④)" | w.adventure_total() == 1 and w.adventure_cleared() == 0 | (待填) | | | | 1074 | 87 | "写盘成功" | w.write_to_disk() | (待填) | | | | 1075 | 89 | "读回成功" | r.load_from_disk() | (待填) | | | | 1076 | 90 | "钥石余额往返相等(10)" | r.keystone_balance() == 10 | (待填) | | | | 1077 | 91 | "树域往返相等(tree_nodes/fork_sides——迭代 21 换代承载)" | r.tree_level("sp_hp") == 2 and r.tree_level("sp_hit") == 1 and r.fork_side("fg_posture") == "b" | (待填) | | | | 1078 | 93 | "锻造工坊域往返相等(levels/unlocked/weapon/armor——迭代 23 T5)〔锻造工坊批 V8〕" | r.forge_route_level("spear") == 3 and r.forge_route_level("sword") == 0 and r.forge_unlocked_purchases() == ["spear"] and r.forge_weapon() == "spear" and r.forge_armor() == "ward" | (待填) | | | | 1079 | 97 | "道具解锁往返相等" | r.item_unlocked("probe_compass") and not r.item_unlocked("rope") | (待填) | | | -| 1080 | 98 | "通关次数表往返相等" | r.clear_count(1) == 1 and r.clear_count(2) == 1 and r.clear_count(3) == 0 | (待填) | | | +| 1080 | 98 | "关卡完成次数表往返相等" | r.clear_count(1) == 1 and r.clear_count(2) == 1 and r.clear_count(3) == 0 | (待填) | | | | 1081 | 99 | "首杀标记往返相等" | r.boss_first_kill_marked(1) and r.boss_first_kill_marked(2) and not r.boss_first_kill_marked(3) | (待填) | | | | 1082 | 101 | "生涯终身计数往返相等(1/0)" | r.adventure_total() == 1 and r.adventure_cleared() == 0 | (待填) | | | | 1083 | 103 | "冒险摘要往返相等(1 条,seed 99)" | r.recent_summaries().size() == 1 and int(s0.get("master_seed", -1)) == 99 and int(s0.get("keystone_total", -1)) == 3 | (待填) | | | @@ -1812,8 +1812,8 @@ | 1117 | 248 | "v2 旧断点续玩受理(缺 bonus 附随件走常规重建路径——g 裁 semver 口径)" | adr_v2.resume_adventure(fv2.breakpoint_snapshot(), {"hero_override": {}}) | (待填) | | | | 1118 | 257 | "v5 旧档升 v7:计数域缺省补零且既有余额原样(迁移只增字段不改值——v5→v6→v7 链式)" | f13.load_from_disk() and f13.adventure_total() == 0 and f13.adventure_cleared() == 0 and f13.keystone_balance() == 9 | (待填) | | | | 1119 | 260 | "升档幂等:v7 档写盘再载零漂移(重复迁移零副作用——锻造工坊域同批补齐)" | f13.write_to_disk() and f13.load_from_disk() and int(JSON.parse_string(FileAccess.open(paths[11], FileAccess.READ).get_as_text()).get("version", -1)) == 7 and f13.adventure_total() == 0 and f13.adventure_cleared() == 0 | (待填) | | | -| 1120 | 268 | "收束自增恰一·通关局(三关全通 cleared=true:总局数+1 且通关局数+1)" | f13b.adventure_total() == 1 and f13b.adventure_cleared() == 1 | (待填) | | | -| 1121 | 272 | "收束自增恰一·中止局(放弃局:仅总局数+1,通关局数不动)" | f13b.adventure_total() == 2 and f13b.adventure_cleared() == 1 | (待填) | | | +| 1120 | 268 | "收束自增恰一·冒险成功局(三关全通 cleared=true:总局数+1 且冒险成功局数+1)" | f13b.adventure_total() == 1 and f13b.adventure_cleared() == 1 | (待填) | | | +| 1121 | 272 | "收束自增恰一·中止局(放弃局:仅总局数+1,冒险成功局数不动)" | f13b.adventure_total() == 2 and f13b.adventure_cleared() == 1 | (待填) | | | | 1122 | 283 | "换代前结构存档:树域废弃重置(旧节点 id/fork 侧/forge_levels 旧域残留清退)、钥石余额零折算零变动" | f15.load_from_disk() and f15.keystone_balance() == 33 and f15.tree_nodes().is_empty() and f15.fork_sides().is_empty() | (待填) | | | | 1123 | 288 | "废弃重置后后续购买正常受理(无残留脏节点)" | mp16.tree_buy("sp_hp") and f15.tree_level("sp_hp") == 1 | (待填) | | | | 1124 | 297 | "v6 旧档升 v7:既有域逐位不动(钥石/树/生涯计数零折算——迁移只增不改)〔锻造工坊批 V8〕" | f16.load_from_disk() and f16.keystone_balance() == 21 and f16.tree_level("sp_hp") == 1 and f16.adventure_total() == 4 and f16.adventure_cleared() == 1 | (待填) | | | @@ -1821,8 +1821,8 @@ | 1126 | 307 | "forge_routes 域键集恰四项(无特效域——满级特效本期不做,契约 7)〔锻造工坊批 V8/V11〕" | fr_keys == ["armor", "levels", "unlocked", "weapon"] | (待填) | | | | 1127 | 311 | "levels 六路线键集恰全(sword/spear/staff/light/heavy/ward)〔锻造工坊批 V8〕" | lv_keys == ["heavy", "light", "spear", "staff", "sword", "ward"] | (待填) | | | | 1128 | 316 | "forge_routes_snapshot 值拷贝出户(改快照不渗档)〔锻造工坊批 V8〕" | f16.forge_route_level("sword") == 0 | (待填) | | | -| 1129 | 324 | "收束链自增·中止局(settle_adventure 真实挂点:总局数+1、通关局数不动)" | f13b.adventure_total() == 3 and f13b.adventure_cleared() == 1 | (待填) | | | -| 1130 | 328 | "收束链自增·通关局(三关全通:总局数+1 且通关局数+1——全链恰一)" | f13b.adventure_total() == 4 and f13b.adventure_cleared() == 2 | (待填) | | | +| 1129 | 324 | "收束链自增·中止局(settle_adventure 真实挂点:总局数+1、冒险成功局数不动)" | f13b.adventure_total() == 3 and f13b.adventure_cleared() == 1 | (待填) | | | +| 1130 | 328 | "收束链自增·冒险成功局(三关全通:总局数+1 且冒险成功局数+1——全链恰一)" | f13b.adventure_total() == 4 and f13b.adventure_cleared() == 2 | (待填) | | | ## S137 _smoke_save_slots(行 359–499 · 31 条 · 源 game/tests/unit/core/save_manager_domain_test.gd · 去向:待分类回填) @@ -2061,7 +2061,7 @@ |---|---|---|---|---|---|---| | 1252 | 92 | "db.adventure 已加载(adventure.tres 入 manifest)" | _db.adventure != null | (待填) | | | | 1253 | 95 | "AdventureTable.validate() 零违例(全键域检+档位配额结构锚在案)" | _db.adventure.validate().is_empty() | (待填) | | | -| 1254 | 96 | "clear_heal_pct ∈ [0,100](%d——通关部分回血比例)" ↩ % int(_db.adventure.clear_heal_pct) | int(_db.adventure.clear_heal_pct) >= 0 and int(_db.adventure.clear_heal_pct) <= 100 | (待填) | | | +| 1254 | 96 | "clear_heal_pct ∈ [0,100](%d——关卡完成部分回血比例)" ↩ % int(_db.adventure.clear_heal_pct) | int(_db.adventure.clear_heal_pct) >= 0 and int(_db.adventure.clear_heal_pct) <= 100 | (待填) | | | | 1255 | 99 | "档位配额结构锚(四级 70/25/7/0——迭代 31 卡② 净删两件投放):%s = %d 张" ↩ % [tier, int(_db.adventure.TIER_QUOTAS[tier])] | int(_db.adventure.tier_total(tier)) == int(_db.adventure.TIER_QUOTAS[tier]) | (待填) | | | | 1256 | 101 | "令牌池总量 = 102 张(四级 普通 70/优秀 25/稀有 7/传说 0——迭代 31 卡② 净删两件投放 104→102)〔凭证裁削批 V5〕" | int(_db.adventure.deck_total()) == 102 | (待填) | | | | 1257 | 102 | "数值对(四级换代承袭):小GP 20/大GP 50 · 小增伤 +1/大 +2 · 小生命 +5/大 +10 · 小护甲 +1/大 +2" | int(_db.adventure.curio_value("gp", "common")) == 20 and int(_db.adventure.curio_value("gp", "excellent")) == 50 and int(_db.adventure.curio_value("attack", "common")) == 1 and int(_db.adventure.curio_value("attack", "excellent")) == 2 and int(_db.adventure.curio_value("max_hp", "common")) == 5 and int(_db.adventure.curio_value("max_hp", "excellent")) == 10 and int(_db.adventure.curio_value("armor", "common")) == 1 and int(_db.adventure.curio_value("armor", "excellent")) == 2 | (待填) | | | @@ -2137,7 +2137,7 @@ | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| | 1304 | 452 | "格面资源十型封闭(第九型 gp 九型批 2026-09-20 / 第十型 treasure_item 秘宝内容批 2026-09-29——词表 v1.2)" | RewardTable.CELL_TYPES.size() == 10 and RewardTable.CELL_TYPES.has("gp") and RewardTable.CELL_TYPES.has("treasure_item") | (待填) | | | -| 1305 | 467 | "奖励字典 18 行(九型×正负 18 格——aux 挖格投放四行已退役 2026-10-01 用户拍板甲:战斗/挖格不掉道具,秘宝唯一来路=三选一共享池〔节点/通关〕;清图槽独立批尾不计)" | cell_rows == 18 | (待填) | | | +| 1305 | 467 | "奖励字典 18 行(九型×正负 18 格——aux 挖格投放四行已退役 2026-10-01 用户拍板甲:战斗/挖格不掉道具,秘宝唯一来路=三选一共享池〔节点/关卡完成〕;清图槽独立批尾不计)" | cell_rows == 18 | (待填) | | | | 1306 | 474 | "危险格负向直伤 %s power=%d(卡⑧投值)" ↩ % [rid, int(mine_power[rid])] | int(row.get("power", -1)) == int(mine_power[rid]) | (待填) | | | | 1307 | 487 | "正向 cell 行权重 ≥1 全在池 / 负向行权重恒 0 不入池(正向合计 %d——配置推导)" ↩ % pos_weight | pos_all_in_pool and neg_all_zero | (待填) | | | | 1308 | 489 | "gp 型两行(GP 袋 gp_gain 正向 weight 2 / 破财 gp_loss 负向 weight 0 不入池)" | gp_pos == 2 and gp_neg == 0 | (待填) | | | @@ -2159,483 +2159,501 @@ | 1314 | 13 | "headless SceneTree 协议可用(quit(code) 通道)" | _test_headless_protocol() | (待填) | | | | 1315 | 14 | "命名规范可执行:test_[scenario]_[expected]" | _test_naming_convention_followed() | (待填) | | | -## S167 _test_numeric_lines_carry_values(行 30–35 · 3 条 · 源 game/tests/unit/presentation/battle_narrator_test.gd · 去向:待分类回填) +## S167 _test_numeric_lines_carry_values(行 31–36 · 3 条 · 源 game/tests/unit/presentation/battle_narrator_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1316 | 30 | "休整叙述带入回复量与当前血量(实际「%s」)" ↩ % rest | rest.contains("12") and rest.contains("30") and rest.contains("40") | (待填) | | | -| 1317 | 33 | "商店叙述带入 GP 数(实际「%s」)" ↩ % shop | shop.contains("77") | (待填) | | | -| 1318 | 34 | "奖励行与休整行互异(不是同一句套所有场景)" | NarratorScript.reward_line() != rest | (待填) | | | +| 1316 | 31 | "休整叙述带入回复量与当前血量(实际「%s」)" ↩ % rest | rest.contains("12") and rest.contains("30") and rest.contains("40") | (待填) | | | +| 1317 | 34 | "商店叙述带入 GP 数(实际「%s」)" ↩ % shop | shop.contains("77") | (待填) | | | +| 1318 | 35 | "奖励行与休整行互异(不是同一句套所有场景)" | NarratorScript.reward_line() != rest | (待填) | | | -## S168 _test_end_text_differs_by_result(行 41–47 · 4 条 · 源 game/tests/unit/presentation/battle_narrator_test.gd · 去向:待分类回填) +## S168 _test_end_text_differs_by_result(行 42–48 · 4 条 · 源 game/tests/unit/presentation/battle_narrator_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1319 | 41 | "关卡收束态恒为「关卡通关!」(实际「%s」)" ↩ % level | level == "关卡通关!" | (待填) | | | -| 1320 | 44 | "单场胜负文案互异(胜「%s」/负「%s」)" ↩ % [win, lose] | win != lose | (待填) | | | -| 1321 | 45 | "胜利文案非空(实际「%s」)" ↩ % win | win != "" | (待填) | | | -| 1322 | 47 | "未知结果有兜底文案不吐空串(实际「%s」)" ↩ % unknown | unknown != "" | (待填) | | | +| 1319 | 42 | "关卡收束态恒为「关卡完成!」(实际「%s」)" ↩ % level | level == "关卡完成!" | (待填) | | | +| 1320 | 45 | "单场胜负文案互异(胜「%s」/负「%s」)" ↩ % [win, lose] | win != lose | (待填) | | | +| 1321 | 46 | "胜利文案非空(实际「%s」)" ↩ % win | win != "" | (待填) | | | +| 1322 | 48 | "未知结果有兜底文案不吐空串(实际「%s」)" ↩ % unknown | unknown != "" | (待填) | | | -## S169 _test_phase_text_nonempty(行 52–54 · 2 条 · 源 game/tests/unit/presentation/battle_narrator_test.gd · 去向:待分类回填) +## S169 _test_phase_text_nonempty(行 53–55 · 2 条 · 源 game/tests/unit/presentation/battle_narrator_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1323 | 52 | "相位叙述非空(实际「%s」)" ↩ % t | t != "" | (待填) | | | -| 1324 | 54 | "Boss 在场时叙述带入 Boss 名(实际「%s」)" ↩ % boss | boss.contains("灰矮人石君王") | (待填) | | | +| 1323 | 53 | "相位叙述非空(实际「%s」)" ↩ % t | t != "" | (待填) | | | +| 1324 | 55 | "Boss 在场时叙述带入 Boss 名(实际「%s」)" ↩ % boss | boss.contains("灰矮人石君王") | (待填) | | | -## S170 _test_boss_name_uses_boss_rowset(行 81–82 · 2 条 · 源 game/tests/unit/presentation/battle_narrator_test.gd · 去向:待分类回填) +## S170 _test_boss_name_uses_boss_rowset(行 82–83 · 2 条 · 源 game/tests/unit/presentation/battle_narrator_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1325 | 81 | "Boss 名取自 Boss 行集首行(期望「%s」实际「%s」)〔fv24〕" ↩ % [boss_expect, got] | got == boss_expect | (待填) | | | -| 1326 | 82 | "Boss 名与同深度战斗行集名不同(期望「%s」≠「%s」——行类路由可判别)〔fv24〕" ↩ % [boss_expect, battle_name] | boss_expect != battle_name | (待填) | | | +| 1325 | 82 | "Boss 名取自 Boss 行集首行(期望「%s」实际「%s」)〔fv24〕" ↩ % [boss_expect, got] | got == boss_expect | (待填) | | | +| 1326 | 83 | "Boss 名与同深度战斗行集名不同(期望「%s」≠「%s」——行类路由可判别)〔fv24〕" ↩ % [boss_expect, battle_name] | boss_expect != battle_name | (待填) | | | -## S171 _run(行 27–102 · 13 条 · 源 game/tests/unit/presentation/forge_workbench_test.gd · 去向:待分类回填) +## S171 _test_level_clear_wording(行 90–101 · 4 条 · 源 game/tests/unit/presentation/battle_narrator_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1327 | 27 | "ConfigDb 加载(工作间测试夹具前提)" | false | (待填) | | | -| 1328 | 44 | "锁定态:工作间不可见(forge_workshop 钥匙未点亮)〔锻造工坊批 V13〕" | not ov._forge_workbench.visible and ov._forge_lock_l.visible | (待填) | | | -| 1329 | 46 | "锁定态:两区零行板(占位纪律——零购买路径)〔锻造工坊批 V13〕" | ov._forge_zone_weapon.get_child_count() == 0 and ov._forge_zone_armor.get_child_count() == 0 | (待填) | | | -| 1330 | 52 | "解锁态:工作间可见(钥匙点亮展开)〔锻造工坊批 V13〕" | ov._forge_workbench.visible | (待填) | | | -| 1331 | 53 | "两区各三路线(武器锻造区 3 + 护甲锻造区 3)〔锻造工坊批 V13〕" | ov._forge_zone_weapon.get_child_count() == 3 and ov._forge_zone_armor.get_child_count() == 3 | (待填) | | | -| 1332 | 56 | "六路线行册恰全(sword/spear/staff/light/heavy/ward)〔锻造工坊批 V13〕" | rows.has("sword") and rows.has("spear") and rows.has("staff") and rows.has("light") and rows.has("heavy") and rows.has("ward") | (待填) | | | -| 1333 | 63 | "长剑行:购买钮「锻造 20」(0 级位几何价)+选中钮「当前」禁用〔锻造工坊批 V13〕" | rsw.get("buy_btn") != null and String(rsw.buy_btn.text) == "锻造 20" and not rsw.buy_btn.disabled and rsw.get("select_btn") != null and String(rsw.select_btn.text) == "当前" and rsw.select_btn.disabled | (待填) | | | -| 1334 | 66 | "轻甲行:购买钮「锻造 20」+选中钮「当前」禁用〔锻造工坊批 V13〕" | rli.get("buy_btn") != null and String(rli.buy_btn.text) == "锻造 20" and String(rli.select_btn.text) == "当前" and rli.select_btn.disabled | (待填) | | | -| 1335 | 73 | "长枪行:解锁钮「解锁 200」+无购买钮+无选中钮〔锻造工坊批 V13〕" | rsp.get("unlock_btn") != null and String(rsp.unlock_btn.text) == "解锁 200" and not rsp.unlock_btn.disabled and rsp.get("buy_btn") == null and rsp.get("select_btn") == null | (待填) | | | -| 1336 | 76 | "魔法护甲行:解锁钮「解锁 200」+状态含并联双通道文案(练满轻甲锻造 或 200 钥石直购)〔锻造工坊批 V13〕" | rwa.get("unlock_btn") != null and String(rwa.status_l.text).contains("练满轻甲锻造") and String(rwa.status_l.text).contains("200") | (待填) | | | -| 1337 | 84 | "余额 0:长剑购买钮禁用+长枪解锁钮禁用(余额联动常态防线)〔锻造工坊批 V13〕" | rows.sword.buy_btn.disabled and rows.spear.unlock_btn.disabled | (待填) | | | -| 1338 | 92 | "长剑满级:无购买钮+状态「已满级」+长枪派生解锁出解锁钮消失(练满通道)〔锻造工坊批 V13〕" | rows.sword.get("buy_btn") == null and String(rows.sword.status_l.text) == "已满级" and rows.spear.get("unlock_btn") == null and rows.spear.get("buy_btn") != null | (待填) | | | -| 1339 | 101 | "三意图信号外发(buy=spear/unlock=heavy/select=spear——UI 只发意图)〔锻造工坊批 V13〕" | buys == ["spear"] and unlocks == ["heavy"] and selects == ["spear"] | (待填) | | | +| 1327 | 90 | "关卡完成回血行带入回血量与生命区间(实际「%s」)〔口径换代 V1〕" ↩ % healed | healed.contains("关卡完成回血 +5(生命 10 → 15)") | (待填) | | | +| 1328 | 93 | "满血零回血合法态文案(实际「%s」)〔口径换代 V1〕" ↩ % full_hp | full_hp.contains("生命已满——关卡完成回血 0(合法态)") | (待填) | | | +| 1329 | 96 | "奖励节点头部行渠道句点明关卡完成三选一(实际「%s」)〔口径换代 V2〕" ↩ % node_header | node_header.contains("与关卡完成专长三选一同库分流") | (待填) | | | +| 1330 | 100 | "冒险摘要完成关数行(实际「%s」)〔口径换代 V3〕" ↩ % summary | summary.contains("完成 1 关 · 止步第 2 层") and not summary.contains("通关") | (待填) | | | -## S172 _test_accepted_text(行 20–20 · 1 条 · 源 game/tests/unit/presentation/hud_presenter_test.gd · 去向:待分类回填) +## S172 _run(行 27–102 · 13 条 · 源 game/tests/unit/presentation/forge_workbench_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1340 | 20 | "受理态文案固定为「执行完成。」(实际「%s」)" ↩ % t | t == "执行完成。" | (待填) | | | +| 1331 | 27 | "ConfigDb 加载(工作间测试夹具前提)" | false | (待填) | | | +| 1332 | 44 | "锁定态:工作间不可见(forge_workshop 钥匙未点亮)〔锻造工坊批 V13〕" | not ov._forge_workbench.visible and ov._forge_lock_l.visible | (待填) | | | +| 1333 | 46 | "锁定态:两区零行板(占位纪律——零购买路径)〔锻造工坊批 V13〕" | ov._forge_zone_weapon.get_child_count() == 0 and ov._forge_zone_armor.get_child_count() == 0 | (待填) | | | +| 1334 | 52 | "解锁态:工作间可见(钥匙点亮展开)〔锻造工坊批 V13〕" | ov._forge_workbench.visible | (待填) | | | +| 1335 | 53 | "两区各三路线(武器锻造区 3 + 护甲锻造区 3)〔锻造工坊批 V13〕" | ov._forge_zone_weapon.get_child_count() == 3 and ov._forge_zone_armor.get_child_count() == 3 | (待填) | | | +| 1336 | 56 | "六路线行册恰全(sword/spear/staff/light/heavy/ward)〔锻造工坊批 V13〕" | rows.has("sword") and rows.has("spear") and rows.has("staff") and rows.has("light") and rows.has("heavy") and rows.has("ward") | (待填) | | | +| 1337 | 63 | "长剑行:购买钮「锻造 20」(0 级位几何价)+选中钮「当前」禁用〔锻造工坊批 V13〕" | rsw.get("buy_btn") != null and String(rsw.buy_btn.text) == "锻造 20" and not rsw.buy_btn.disabled and rsw.get("select_btn") != null and String(rsw.select_btn.text) == "当前" and rsw.select_btn.disabled | (待填) | | | +| 1338 | 66 | "轻甲行:购买钮「锻造 20」+选中钮「当前」禁用〔锻造工坊批 V13〕" | rli.get("buy_btn") != null and String(rli.buy_btn.text) == "锻造 20" and String(rli.select_btn.text) == "当前" and rli.select_btn.disabled | (待填) | | | +| 1339 | 73 | "长枪行:解锁钮「解锁 200」+无购买钮+无选中钮〔锻造工坊批 V13〕" | rsp.get("unlock_btn") != null and String(rsp.unlock_btn.text) == "解锁 200" and not rsp.unlock_btn.disabled and rsp.get("buy_btn") == null and rsp.get("select_btn") == null | (待填) | | | +| 1340 | 76 | "魔法护甲行:解锁钮「解锁 200」+状态含并联双通道文案(练满轻甲锻造 或 200 钥石直购)〔锻造工坊批 V13〕" | rwa.get("unlock_btn") != null and String(rwa.status_l.text).contains("练满轻甲锻造") and String(rwa.status_l.text).contains("200") | (待填) | | | +| 1341 | 84 | "余额 0:长剑购买钮禁用+长枪解锁钮禁用(余额联动常态防线)〔锻造工坊批 V13〕" | rows.sword.buy_btn.disabled and rows.spear.unlock_btn.disabled | (待填) | | | +| 1342 | 92 | "长剑满级:无购买钮+状态「已满级」+长枪派生解锁出解锁钮消失(练满通道)〔锻造工坊批 V13〕" | rows.sword.get("buy_btn") == null and String(rows.sword.status_l.text) == "已满级" and rows.spear.get("unlock_btn") == null and rows.spear.get("buy_btn") != null | (待填) | | | +| 1343 | 101 | "三意图信号外发(buy=spear/unlock=heavy/select=spear——UI 只发意图)〔锻造工坊批 V13〕" | buys == ["spear"] and unlocks == ["heavy"] and selects == ["spear"] | (待填) | | | -## S173 _test_reject_text_by_reason(行 36–38 · 2 条 · 源 game/tests/unit/presentation/hud_presenter_test.gd · 去向:待分类回填) +## S173 _test_accepted_text(行 20–20 · 1 条 · 源 game/tests/unit/presentation/hud_presenter_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1341 | 36 | "棋盘面各拒绝原因文案逐类正确(错 %d 项 %s)" ↩ % [bad.size(), str(bad)] | bad.is_empty() | (待填) | | | -| 1342 | 38 | "资源面拒绝文案为「AP 不足。」(实际「%s」)" ↩ % ap | ap == "AP 不足。" | (待填) | | | +| 1344 | 20 | "受理态文案固定为「执行完成。」(实际「%s」)" ↩ % t | t == "执行完成。" | (待填) | | | -## S174 _test_unknown_reason_fallback(行 43–47 · 2 条 · 源 game/tests/unit/presentation/hud_presenter_test.gd · 去向:待分类回填) +## S174 _test_reject_text_by_reason(行 36–38 · 2 条 · 源 game/tests/unit/presentation/hud_presenter_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1343 | 43 | "未知拒绝原因兜底为「动作被拒。」而非空串(实际「%s」)" ↩ % t | t == "动作被拒。" | (待填) | | | -| 1344 | 47 | "棋盘面未知子因兜底带前缀可诊断(实际「%s」)" ↩ % sub | sub.begins_with("棋盘面拒绝: ") | (待填) | | | +| 1345 | 36 | "棋盘面各拒绝原因文案逐类正确(错 %d 项 %s)" ↩ % [bad.size(), str(bad)] | bad.is_empty() | (待填) | | | +| 1346 | 38 | "资源面拒绝文案为「AP 不足。」(实际「%s」)" ↩ % ap | ap == "AP 不足。" | (待填) | | | -## S175 _test_fog_hides_type(行 50–55 · 3 条 · 源 game/tests/unit/presentation/level_map_info_fog_test.gd · 去向:待分类回填) +## S175 _test_unknown_reason_fallback(行 43–47 · 2 条 · 源 game/tests/unit/presentation/hud_presenter_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1345 | 50 | "可见集内节点:图标/类型文字均绘制〔fv2〕" | bool(shown["draw_icon"]) and bool(shown["draw_label"]) | (待填) | | | -| 1346 | 53 | "雾下节点:图标与类型文字均不绘制(显隐语义,非灰化)〔fv2〕" | not bool(fogged["draw_icon"]) and not bool(fogged["draw_label"]) | (待填) | | | -| 1347 | 55 | "雾下非 Boss 节点无 Boss 描边〔fv2〕" | not bool(fogged["boss_border"]) | (待填) | | | +| 1347 | 43 | "未知拒绝原因兜底为「动作被拒。」而非空串(实际「%s」)" ↩ % t | t == "动作被拒。" | (待填) | | | +| 1348 | 47 | "棋盘面未知子因兜底带前缀可诊断(实际「%s」)" ↩ % sub | sub.begins_with("棋盘面拒绝: ") | (待填) | | | -## S176 _test_boss_exempt_and_multi_boss(行 64–72 · 4 条 · 源 game/tests/unit/presentation/level_map_info_fog_test.gd · 去向:待分类回填) +## S176 _test_fog_hides_type(行 50–55 · 3 条 · 源 game/tests/unit/presentation/level_map_info_fog_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1348 | 64 | "多终点:两个 Boss 节点均带 Boss 描边〔fv3〕" | bool(boss_a["boss_border"]) and bool(boss_b["boss_border"]) | (待填) | | | -| 1349 | 66 | "Boss 不入雾:可见集与图标/文字三通道均在〔fv3〕" | bool(boss_a["draw_icon"]) and bool(boss_a["draw_label"]) and bool(boss_b["draw_icon"]) | (待填) | | | -| 1350 | 69 | "Boss 豁免独立于可见集:不在 type_vis 的 Boss 仍出示类型〔fv3〕" | bool(far_boss["draw_icon"]) and bool(far_boss["draw_label"]) | (待填) | | | -| 1351 | 72 | "Boss 豁免不扩散:雾下非 Boss 仍隐类型〔fv3〕" | not bool(fogged_battle["draw_icon"]) | (待填) | | | +| 1349 | 50 | "可见集内节点:图标/类型文字均绘制〔fv2〕" | bool(shown["draw_icon"]) and bool(shown["draw_label"]) | (待填) | | | +| 1350 | 53 | "雾下节点:图标与类型文字均不绘制(显隐语义,非灰化)〔fv2〕" | not bool(fogged["draw_icon"]) and not bool(fogged["draw_label"]) | (待填) | | | +| 1351 | 55 | "雾下非 Boss 节点无 Boss 描边〔fv2〕" | not bool(fogged["boss_border"]) | (待填) | | | -## S177 _test_details_never_shown(行 86–88 · 2 条 · 源 game/tests/unit/presentation/level_map_info_fog_test.gd · 去向:待分类回填) +## S177 _test_boss_exempt_and_multi_boss(行 64–72 · 4 条 · 源 game/tests/unit/presentation/level_map_info_fog_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1352 | 86 | "决策面不消费内容键:携带 enemy_id/reward_id 与不带者输出逐键相等〔fv5〕" | same | (待填) | | | -| 1353 | 87 | "label_text 不含内容值(实际「%s」)〔fv5〕" ↩ % String(b["label_text"]) | not String(b["label_text"]).contains("goblin_secret") and not String(b["label_text"]).contains("reward_secret") | (待填) | | | +| 1352 | 64 | "多终点:两个 Boss 节点均带 Boss 描边〔fv3〕" | bool(boss_a["boss_border"]) and bool(boss_b["boss_border"]) | (待填) | | | +| 1353 | 66 | "Boss 不入雾:可见集与图标/文字三通道均在〔fv3〕" | bool(boss_a["draw_icon"]) and bool(boss_a["draw_label"]) and bool(boss_b["draw_icon"]) | (待填) | | | +| 1354 | 69 | "Boss 豁免独立于可见集:不在 type_vis 的 Boss 仍出示类型〔fv3〕" | bool(far_boss["draw_icon"]) and bool(far_boss["draw_label"]) | (待填) | | | +| 1355 | 72 | "Boss 豁免不扩散:雾下非 Boss 仍隐类型〔fv3〕" | not bool(fogged_battle["draw_icon"]) | (待填) | | | -## S178 _test_label_three_states(行 95–100 · 3 条 · 源 game/tests/unit/presentation/level_map_info_fog_test.gd · 去向:待分类回填) +## S178 _test_details_never_shown(行 86–88 · 2 条 · 源 game/tests/unit/presentation/level_map_info_fog_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1354 | 95 | "当前位文案=「当前位置」〔fv2〕" | String(ScreenScript.node_display(node, 3, [3], true, false)["label_text"]) == "当前位置" | (待填) | | | -| 1355 | 97 | "候选文案=「战斗 · 可选」〔fv2〕" | String(ScreenScript.node_display(node, 3, [3], false, true)["label_text"]) == "战斗 · 可选" | (待填) | | | -| 1356 | 99 | "其余文案=类型名「战斗」〔fv2〕" | String(ScreenScript.node_display(node, 3, [3], false, false)["label_text"]) == "战斗" | (待填) | | | +| 1356 | 86 | "决策面不消费内容键:携带 enemy_id/reward_id 与不带者输出逐键相等〔fv5〕" | same | (待填) | | | +| 1357 | 87 | "label_text 不含内容值(实际「%s」)〔fv5〕" ↩ % String(b["label_text"]) | not String(b["label_text"]).contains("goblin_secret") and not String(b["label_text"]).contains("reward_secret") | (待填) | | | -## S179 _test_big_graph_fit(行 164–190 · 6 条 · 源 game/tests/unit/presentation/level_map_info_fog_test.gd · 去向:待分类回填) +## S179 _test_label_three_states(行 95–100 · 3 条 · 源 game/tests/unit/presentation/level_map_info_fog_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1357 | 164 | "大图夹具规模:≥11 层 × ≥6 槽(实测最大层 %d/最大槽 %d)〔fv8〕" ↩ % [maxl, maxslot] | maxl >= 10 and maxslot >= 5 | (待填) | | | -| 1358 | 170 | "大图拟合:画布 min.x 覆盖最深节点(%.1f ≥ %.1f)〔fv8〕" ↩ % [min_size.x, need_w] | min_size.x >= need_w - 0.01 | (待填) | | | -| 1359 | 172 | "大图拟合:画布 min.y 覆盖最宽层底节点(%.1f ≥ %.1f)〔fv8〕" ↩ % [min_size.y, need_h] | min_size.y >= need_h - 0.01 | (待填) | | | -| 1360 | 180 | "大图布局:全节点方块落在拟合画布内(origin=(%.1f,%.1f) size=(%.1f,%.1f))〔fv8〕" ↩ % [origin.x, origin.y, min_size.x, min_size.y] | all_in | (待填) | | | -| 1361 | 187 | "大图呈现:两个终点 Boss 均有描边标记〔fv8〕" | disp.has(boss_ids[0]) and disp.has(boss_ids[1]) and bool(disp[boss_ids[0]]["boss_border"]) and bool(disp[boss_ids[1]]["boss_border"]) | (待填) | | | -| 1362 | 190 | "大图呈现:入口停点远处战斗节点(句柄 32,层 6)类型入雾〔fv8〕" | not bool(disp[32]["draw_icon"]) | (待填) | | | +| 1358 | 95 | "当前位文案=「当前位置」〔fv2〕" | String(ScreenScript.node_display(node, 3, [3], true, false)["label_text"]) == "当前位置" | (待填) | | | +| 1359 | 97 | "候选文案=「战斗 · 可选」〔fv2〕" | String(ScreenScript.node_display(node, 3, [3], false, true)["label_text"]) == "战斗 · 可选" | (待填) | | | +| 1360 | 99 | "其余文案=类型名「战斗」〔fv2〕" | String(ScreenScript.node_display(node, 3, [3], false, false)["label_text"]) == "战斗" | (待填) | | | -## S180 _init(行 105–140 · 9 条 · 源 game/tests/unit/presentation/pacing_queue_test.gd · 去向:待分类回填) +## S180 _test_big_graph_fit(行 164–190 · 6 条 · 源 game/tests/unit/presentation/level_map_info_fog_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1363 | 105 | "排空前后核心诊断快照逐位一致(AC⑤ 演出关停零分叉)" | snap_before == snap_after | (待填) | | | -| 1364 | 107 | "结算行已产生(断言前提)" | rows_seen.size() > 0 | (待填) | | | -| 1365 | 108 | "排空后队列恒空(flush 完整性)" | main._row_queue.is_empty() | (待填) | | | -| 1366 | 117 | "末信号行原文在明细带(排空不吞行:『%s』)" ↩ % last_text | last_text != "" and main.log_view.parsed_text().contains(last_text) | (待填) | | | -| 1367 | 123 | "常态段间延迟 >0 且 ≥ 段内(%f/%f)" ↩ % [d_on, d_same] | d_on > 0.0 and d_on >= d_same | (待填) | | | -| 1368 | 125 | "减动效段间延迟归零(行不跳过——同帧直落快路)" | main.pace_delay_for("damage", "heal") == 0.0 | (待填) | | | -| 1369 | 135 | "结算标出按行 target_id 解析站桩(id 与名同传——d12)〔wd12〕" | fstage.calls.size() == 1 and fstage.calls[0] == ["goblin_b", "哥布林"] | (待填) | | | -| 1370 | 138 | "跨区弹道按行 target_id 解析站桩(id 与名同传——d12)〔wd12〕" | fstage.calls.size() == 2 and fstage.calls[1] == ["goblin_b", "哥布林"] | (待填) | | | -| 1371 | 140 | "两路解析成功后演出层各接一拍(记参面非空)〔wd12〕" | ffx.calls.size() == 2 | (待填) | | | +| 1361 | 164 | "大图夹具规模:≥11 层 × ≥6 槽(实测最大层 %d/最大槽 %d)〔fv8〕" ↩ % [maxl, maxslot] | maxl >= 10 and maxslot >= 5 | (待填) | | | +| 1362 | 170 | "大图拟合:画布 min.x 覆盖最深节点(%.1f ≥ %.1f)〔fv8〕" ↩ % [min_size.x, need_w] | min_size.x >= need_w - 0.01 | (待填) | | | +| 1363 | 172 | "大图拟合:画布 min.y 覆盖最宽层底节点(%.1f ≥ %.1f)〔fv8〕" ↩ % [min_size.y, need_h] | min_size.y >= need_h - 0.01 | (待填) | | | +| 1364 | 180 | "大图布局:全节点方块落在拟合画布内(origin=(%.1f,%.1f) size=(%.1f,%.1f))〔fv8〕" ↩ % [origin.x, origin.y, min_size.x, min_size.y] | all_in | (待填) | | | +| 1365 | 187 | "大图呈现:两个终点 Boss 均有描边标记〔fv8〕" | disp.has(boss_ids[0]) and disp.has(boss_ids[1]) and bool(disp[boss_ids[0]]["boss_border"]) and bool(disp[boss_ids[1]]["boss_border"]) | (待填) | | | +| 1366 | 190 | "大图呈现:入口停点远处战斗节点(句柄 32,层 6)类型入雾〔fv8〕" | not bool(disp[32]["draw_icon"]) | (待填) | | | -## S181 _sweep_hero_panel(行 47–50 · 2 条 · 源 game/tests/unit/presentation/player_copy_sweep_test.gd · 去向:待分类回填) +## S181 _init(行 105–140 · 9 条 · 源 game/tests/unit/presentation/pacing_queue_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1372 | 47 | "C 区专长段头==「专长」(u1 换代——段头文案钉值)〔wa1〕" | feat_head != null and feat_head.text == "专长" | (待填) | | | -| 1373 | 49 | "C 区属性值提升段头==「属性值提升」(u2 换代——同屏两段同标撞车消除)〔wa1〕" | curio_head != null and curio_head.text == "属性值提升" | (待填) | | | +| 1367 | 105 | "排空前后核心诊断快照逐位一致(AC⑤ 演出关停零分叉)" | snap_before == snap_after | (待填) | | | +| 1368 | 107 | "结算行已产生(断言前提)" | rows_seen.size() > 0 | (待填) | | | +| 1369 | 108 | "排空后队列恒空(flush 完整性)" | main._row_queue.is_empty() | (待填) | | | +| 1370 | 117 | "末信号行原文在明细带(排空不吞行:『%s』)" ↩ % last_text | last_text != "" and main.log_view.parsed_text().contains(last_text) | (待填) | | | +| 1371 | 123 | "常态段间延迟 >0 且 ≥ 段内(%f/%f)" ↩ % [d_on, d_same] | d_on > 0.0 and d_on >= d_same | (待填) | | | +| 1372 | 125 | "减动效段间延迟归零(行不跳过——同帧直落快路)" | main.pace_delay_for("damage", "heal") == 0.0 | (待填) | | | +| 1373 | 135 | "结算标出按行 target_id 解析站桩(id 与名同传——d12)〔wd12〕" | fstage.calls.size() == 1 and fstage.calls[0] == ["goblin_b", "哥布林"] | (待填) | | | +| 1374 | 138 | "跨区弹道按行 target_id 解析站桩(id 与名同传——d12)〔wd12〕" | fstage.calls.size() == 2 and fstage.calls[1] == ["goblin_b", "哥布林"] | (待填) | | | +| 1375 | 140 | "两路解析成功后演出层各接一拍(记参面非空)〔wd12〕" | ffx.calls.size() == 2 | (待填) | | | -## S182 _sweep_narrator(行 57–64 · 7 条 · 源 game/tests/unit/presentation/player_copy_sweep_test.gd · 去向:待分类回填) +## S182 _sweep_hero_panel(行 47–50 · 2 条 · 源 game/tests/unit/presentation/player_copy_sweep_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1374 | 57 | "奖励点头部含「冒险牌库」(u3 机制事实①同库)〔wa4〕" | head.contains("冒险牌库") | (待填) | | | -| 1375 | 58 | "奖励点头部含「属性值提升与补给」(u3 机制事实②渠道分流)〔wa4〕" | head.contains("属性值提升与补给") | (待填) | | | -| 1376 | 59 | "奖励点头部含「同库分流」(u3 机制事实②措辞)〔wa4〕" | head.contains("同库分流") | (待填) | | | -| 1377 | 60 | "奖励点头部零「同权重」旧话(u3 清零)〔wa4〕" | not head.contains("同权重") | (待填) | | | -| 1378 | 61 | "奖励点头部零「同上限」旧话(u3 清零)〔wa4〕" | not head.contains("同上限") | (待填) | | | -| 1379 | 62 | "奖励点头部零「提升池」旧话(u3 清零)〔wa4〕" | not head.contains("提升池") | (待填) | | | -| 1380 | 63 | "专长卡兜底==「专长\\n???」(u11 换代——数据缺行真实兜底路径)〔wa3〕" | String(narrator.feat_card_text({})) == "专长\\n???" | (待填) | | | +| 1376 | 47 | "C 区专长段头==「专长」(u1 换代——段头文案钉值)〔wa1〕" | feat_head != null and feat_head.text == "专长" | (待填) | | | +| 1377 | 49 | "C 区属性值提升段头==「属性值提升」(u2 换代——同屏两段同标撞车消除)〔wa1〕" | curio_head != null and curio_head.text == "属性值提升" | (待填) | | | -## S183 _sweep_legend(行 75–79 · 5 条 · 源 game/tests/unit/presentation/player_copy_sweep_test.gd · 去向:待分类回填) +## S183 _sweep_narrator(行 57–64 · 7 条 · 源 game/tests/unit/presentation/player_copy_sweep_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1381 | 75 | "图例封印行存在(wa5 夹具前提)〔wa5〕" | not seal_row.is_empty() | (待填) | | | -| 1382 | 76 | "图例封印行含「标空」(u4——与「标中」成对)〔wa5〕" | String(seal_row[2] if seal_row.size() > 2 else "").contains("标空") | (待填) | | | -| 1383 | 77 | "图例封印行含「受挖掘惩罚」(u4 雷字清零换代)〔wa5〕" | String(seal_row[2] if seal_row.size() > 2 else "").contains("受挖掘惩罚") | (待填) | | | -| 1384 | 78 | "图例封印行零「插错」(u4 旗族遗留词干清零)〔wa5〕" | not String(seal_row[2] if seal_row.size() > 2 else "").contains("插错") | (待填) | | | -| 1385 | 79 | "图例封印行零「挖雷」(u4 雷字清零)〔wa5〕" | not String(seal_row[2] if seal_row.size() > 2 else "").contains("挖雷") | (待填) | | | +| 1378 | 57 | "奖励点头部含「冒险牌库」(u3 机制事实①同库)〔wa4〕" | head.contains("冒险牌库") | (待填) | | | +| 1379 | 58 | "奖励点头部含「属性值提升与补给」(u3 机制事实②渠道分流)〔wa4〕" | head.contains("属性值提升与补给") | (待填) | | | +| 1380 | 59 | "奖励点头部含「同库分流」(u3 机制事实②措辞)〔wa4〕" | head.contains("同库分流") | (待填) | | | +| 1381 | 60 | "奖励点头部零「同权重」旧话(u3 清零)〔wa4〕" | not head.contains("同权重") | (待填) | | | +| 1382 | 61 | "奖励点头部零「同上限」旧话(u3 清零)〔wa4〕" | not head.contains("同上限") | (待填) | | | +| 1383 | 62 | "奖励点头部零「提升池」旧话(u3 清零)〔wa4〕" | not head.contains("提升池") | (待填) | | | +| 1384 | 63 | "专长卡兜底==「专长\\n???」(u11 换代——数据缺行真实兜底路径)〔wa3〕" | String(narrator.feat_card_text({})) == "专长\\n???" | (待填) | | | -## S184 _sweep_source_names(行 92–104 · 4 条 · 源 game/tests/unit/presentation/player_copy_sweep_test.gd · 去向:待分类回填) +## S184 _sweep_legend(行 75–79 · 5 条 · 源 game/tests/unit/presentation/player_copy_sweep_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1386 | 92 | "状态槽 mine_hit 效果行在座(wa6 夹具前提)〔wa6〕" | slot != null | (待填) | | | -| 1387 | 95 | "状态槽来源注记==「危险格」(u5 换代——meta tooltip 消费半)〔wa6〕" | row_view._tip_label.text.contains("来源:危险格") | (待填) | | | -| 1388 | 98 | "结算表 source_label_map[mine_hit]==「危险格」(u6 换代——ConfigDB 真装载)〔wa7〕" | String(_db.settlement.source_label_map.get("mine_hit", "")) == "危险格" | (待填) | | | -| 1389 | 103 | "战斗日志 mine_hit 来源行含「(危险格)」(u6 消费半——_format_row 生产路径)〔wa7〕" | row_txt.contains("(危险格)") | (待填) | | | +| 1385 | 75 | "图例封印行存在(wa5 夹具前提)〔wa5〕" | not seal_row.is_empty() | (待填) | | | +| 1386 | 76 | "图例封印行含「标空」(u4——与「标中」成对)〔wa5〕" | String(seal_row[2] if seal_row.size() > 2 else "").contains("标空") | (待填) | | | +| 1387 | 77 | "图例封印行含「受挖掘惩罚」(u4 雷字清零换代)〔wa5〕" | String(seal_row[2] if seal_row.size() > 2 else "").contains("受挖掘惩罚") | (待填) | | | +| 1388 | 78 | "图例封印行零「插错」(u4 旗族遗留词干清零)〔wa5〕" | not String(seal_row[2] if seal_row.size() > 2 else "").contains("插错") | (待填) | | | +| 1389 | 79 | "图例封印行零「挖雷」(u4 雷字清零)〔wa5〕" | not String(seal_row[2] if seal_row.size() > 2 else "").contains("挖雷") | (待填) | | | -## S185 _sweep_board_glyph(行 133–142 · 4 条 · 源 game/tests/unit/presentation/player_copy_sweep_test.gd · 去向:待分类回填) +## S185 _sweep_source_names(行 92–104 · 4 条 · 源 game/tests/unit/presentation/player_copy_sweep_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1390 | 133 | "棋盘夹具含挖掘射程内未开危险格(wa8 前提——实测 %d 步)〔wa8〕" ↩ % glow_steps | mine_cell.x >= 0 | (待填) | | | -| 1391 | 139 | "已开危险格 glyph==「危」(u7 换代)〔wa8〕" | u.glyph == "危" | (待填) | | | -| 1392 | 140 | "已开危险格 plate==true(u9 牌载哨兵包含项随动)〔wa8〕" | u.plate == true | (待填) | | | -| 1393 | 141 | "已开危险格 glyph_color==RED_MINE(u7 墨色不随字形换代漂移)〔wa8〕" | u.glyph_color == UiKit.RED_MINE | (待填) | | | +| 1390 | 92 | "状态槽 mine_hit 效果行在座(wa6 夹具前提)〔wa6〕" | slot != null | (待填) | | | +| 1391 | 95 | "状态槽来源注记==「危险格」(u5 换代——meta tooltip 消费半)〔wa6〕" | row_view._tip_label.text.contains("来源:危险格") | (待填) | | | +| 1392 | 98 | "结算表 source_label_map[mine_hit]==「危险格」(u6 换代——ConfigDB 真装载)〔wa7〕" | String(_db.settlement.source_label_map.get("mine_hit", "")) == "危险格" | (待填) | | | +| 1393 | 103 | "战斗日志 mine_hit 来源行含「(危险格)」(u6 消费半——_format_row 生产路径)〔wa7〕" | row_txt.contains("(危险格)") | (待填) | | | -## S186 _sweep_token_scans(行 148–158 · 2 条 · 源 game/tests/unit/presentation/player_copy_sweep_test.gd · 去向:待分类回填) +## S186 _sweep_board_glyph(行 133–142 · 4 条 · 源 game/tests/unit/presentation/player_copy_sweep_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1394 | 148 | "board_view.gd 源零 \\"雷\\" 字面量(u7/u8/u9 哨兵族统一钉住)〔wa8〕" | board_src.count("\\"雷\\"") == 0 | (待填) | | | -| 1395 | 157 | "battle_orchestrator.gd 玩家面字符串字面量零「挖雷」(u13——注释保留面不入域)〔wa12〕" | orch_hits == 0 | (待填) | | | +| 1394 | 133 | "棋盘夹具含挖掘射程内未开危险格(wa8 前提——实测 %d 步)〔wa8〕" ↩ % glow_steps | mine_cell.x >= 0 | (待填) | | | +| 1395 | 139 | "已开危险格 glyph==「危」(u7 换代)〔wa8〕" | u.glyph == "危" | (待填) | | | +| 1396 | 140 | "已开危险格 plate==true(u9 牌载哨兵包含项随动)〔wa8〕" | u.plate == true | (待填) | | | +| 1397 | 141 | "已开危险格 glyph_color==RED_MINE(u7 墨色不随字形换代漂移)〔wa8〕" | u.glyph_color == UiKit.RED_MINE | (待填) | | | -## S187 _init(行 75–132 · 18 条 · 源 game/tests/unit/presentation/standee_fx_sweep_test.gd · 去向:待分类回填) +## S187 _sweep_token_scans(行 148–158 · 2 条 · 源 game/tests/unit/presentation/player_copy_sweep_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1396 | 75 | "站桩 enemy_id 访问器读装载值〔wd12〕" | s1.enemy_id() == "goblin_a" and s2.enemy_id() == "goblin_b" | (待填) | | | -| 1397 | 76 | "同名敌按 id 精确解析(不做名子串撞车)〔wd12〕" | stage._card_by_id("goblin_b") == s2 and stage._card_by_id("goblin_a") == s1 | (待填) | | | -| 1398 | 78 | "空 id / 未登记 id 恒不命中(名兜底归调用点)〔wd12〕" | stage._card_by_id("") == null and stage._card_by_id("no_such") == null | (待填) | | | -| 1399 | 83 | "伤害行按 target_id 命中正确站桩(闪白落点)〔wd12〕" | s2._flash_count == 1 and s1._flash_count == 0 | (待填) | | | -| 1400 | 88 | "弹道落点按 target_id 取站桩中心〔wd12〕" | c_b != null and c_b == c_b_expect | (待填) | | | -| 1401 | 91 | "无 target_id 时按名兜底同旧行为(首命中)〔wd12〕" | c_fallback != null and c_fallback == c_fallback_expect | (待填) | | | -| 1402 | 95 | "蓄力技能(heavy)置 _intent_charge=true〔wd2〕" | s1._intent_charge | (待填) | | | -| 1403 | 97 | "非蓄力攻击技(goblin_slash)零置位〔wd2〕" | not s1._intent_charge | (待填) | | | -| 1404 | 99 | "增益系零置位〔wd2〕" | not s1._intent_charge | (待填) | | | -| 1405 | 101 | "普攻零表示路径复位 _intent_charge〔wd2〕" | not s1._intent_charge | (待填) | | | -| 1406 | 108 | "首开胜利画面创建庆祝句柄〔wd4〕" | first != null and first.is_valid() | (待填) | | | -| 1407 | 111 | "重开胜利画面:旧句柄已 kill、新句柄在位(至多一个活跃)〔wd4〕" | first != null and not first.is_valid() and second != null and second.is_valid() | (待填) | | | -| 1408 | 114 | "close 必杀庆祝句柄(句柄清空)〔wd4〕" | ov.get_meta(&"celebrate_tw", null) == null | (待填) | | | -| 1409 | 119 | "模拟运行期调试入口钮同置灰〔wd5〕" | dbg._dbg_btn.disabled | (待填) | | | -| 1410 | 121 | "模拟收尾调试入口钮恢复(未锁定)〔wd5〕" | not dbg._dbg_btn.disabled | (待填) | | | -| 1411 | 130 | "控制器运行中 is_running()=true(驱动回调内读数)〔wd8〕" | drv.seen == [true, true] | (待填) | | | -| 1412 | 131 | "控制器收尾 is_running()=false〔wd8〕" | not ctrl.is_running() and not panel.running | (待填) | | | -| 1413 | 132 | "两局报告全文注入面板(run 收尾链路完整)〔wd8〕" | String(panel.report) != "" | (待填) | | | +| 1398 | 148 | "board_view.gd 源零 \\"雷\\" 字面量(u7/u8/u9 哨兵族统一钉住)〔wa8〕" | board_src.count("\\"雷\\"") == 0 | (待填) | | | +| 1399 | 157 | "battle_orchestrator.gd 玩家面字符串字面量零「挖雷」(u13——注释保留面不入域)〔wa12〕" | orch_hits == 0 | (待填) | | | -## S188 _init(行 24–34 · 2 条 · 源 game/tests/unit/presentation/terrain_tile_sets_test.gd · 去向:待分类回填) +## S188 _init(行 75–132 · 18 条 · 源 game/tests/unit/presentation/standee_fx_sweep_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1414 | 24 | "前置:表加载零 error" | load_ok and db.diagnostics_count("error") == 0 | (待填) | | | -| 1415 | 34 | "前置:board_gen 词表非空(%d 型)" ↩ % types.size() | types.size() > 0 | (待填) | | | +| 1400 | 75 | "站桩 enemy_id 访问器读装载值〔wd12〕" | s1.enemy_id() == "goblin_a" and s2.enemy_id() == "goblin_b" | (待填) | | | +| 1401 | 76 | "同名敌按 id 精确解析(不做名子串撞车)〔wd12〕" | stage._card_by_id("goblin_b") == s2 and stage._card_by_id("goblin_a") == s1 | (待填) | | | +| 1402 | 78 | "空 id / 未登记 id 恒不命中(名兜底归调用点)〔wd12〕" | stage._card_by_id("") == null and stage._card_by_id("no_such") == null | (待填) | | | +| 1403 | 83 | "伤害行按 target_id 命中正确站桩(闪白落点)〔wd12〕" | s2._flash_count == 1 and s1._flash_count == 0 | (待填) | | | +| 1404 | 88 | "弹道落点按 target_id 取站桩中心〔wd12〕" | c_b != null and c_b == c_b_expect | (待填) | | | +| 1405 | 91 | "无 target_id 时按名兜底同旧行为(首命中)〔wd12〕" | c_fallback != null and c_fallback == c_fallback_expect | (待填) | | | +| 1406 | 95 | "蓄力技能(heavy)置 _intent_charge=true〔wd2〕" | s1._intent_charge | (待填) | | | +| 1407 | 97 | "非蓄力攻击技(goblin_slash)零置位〔wd2〕" | not s1._intent_charge | (待填) | | | +| 1408 | 99 | "增益系零置位〔wd2〕" | not s1._intent_charge | (待填) | | | +| 1409 | 101 | "普攻零表示路径复位 _intent_charge〔wd2〕" | not s1._intent_charge | (待填) | | | +| 1410 | 108 | "首开胜利画面创建庆祝句柄〔wd4〕" | first != null and first.is_valid() | (待填) | | | +| 1411 | 111 | "重开胜利画面:旧句柄已 kill、新句柄在位(至多一个活跃)〔wd4〕" | first != null and not first.is_valid() and second != null and second.is_valid() | (待填) | | | +| 1412 | 114 | "close 必杀庆祝句柄(句柄清空)〔wd4〕" | ov.get_meta(&"celebrate_tw", null) == null | (待填) | | | +| 1413 | 119 | "模拟运行期调试入口钮同置灰〔wd5〕" | dbg._dbg_btn.disabled | (待填) | | | +| 1414 | 121 | "模拟收尾调试入口钮恢复(未锁定)〔wd5〕" | not dbg._dbg_btn.disabled | (待填) | | | +| 1415 | 130 | "控制器运行中 is_running()=true(驱动回调内读数)〔wd8〕" | drv.seen == [true, true] | (待填) | | | +| 1416 | 131 | "控制器收尾 is_running()=false〔wd8〕" | not ctrl.is_running() and not panel.running | (待填) | | | +| 1417 | 132 | "两局报告全文注入面板(run 收尾链路完整)〔wd8〕" | String(panel.report) != "" | (待填) | | | -## S189 _test_set_completeness(行 56–56 · 1 条 · 源 game/tests/unit/presentation/terrain_tile_sets_test.gd · 去向:待分类回填) +## S189 _init(行 24–34 · 2 条 · 源 game/tests/unit/presentation/terrain_tile_sets_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1416 | 56 | "图型 %s 瓦片套完整(16 墙 + %d 地面,缺=%s)" ↩ % [String(bt), variants, str(missing)] | missing.is_empty() | (待填) | | | +| 1418 | 24 | "前置:表加载零 error" | load_ok and db.diagnostics_count("error") == 0 | (待填) | | | +| 1419 | 34 | "前置:board_gen 词表非空(%d 型)" ↩ % types.size() | types.size() > 0 | (待填) | | | -## S190 _test_hue_domains(行 72–82 · 4 条 · 源 game/tests/unit/presentation/terrain_tile_sets_test.gd · 去向:待分类回填) +## S190 _test_set_completeness(行 56–56 · 1 条 · 源 game/tests/unit/presentation/terrain_tile_sets_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1417 | 72 | "图型 %s 抽检样本可读" ↩ % String(bt) | false | (待填) | | | -| 1418 | 77 | "图型 %s 墙顶均值色相在带 %s(实测 %.3f)" ↩ % [String(bt), str(band), float(wall["h"])] | float(wall["h"]) >= float(band[0]) and float(wall["h"]) <= float(band[1]) | (待填) | | | -| 1419 | 79 | "图型 %s 图底分离(墙顶明度 %.3f > 地面 %.3f)" ↩ % [String(bt), wall_v[bt], floor_v[bt]] | wall_v[bt] > floor_v[bt] | (待填) | | | -| 1420 | 82 | "deep_underdark 墙顶更暗于 underdark(更深蓝黑方向)" | float(wall_v["deep_underdark"]) < float(wall_v["underdark"]) | (待填) | | | +| 1420 | 56 | "图型 %s 瓦片套完整(16 墙 + %d 地面,缺=%s)" ↩ % [String(bt), variants, str(missing)] | missing.is_empty() | (待填) | | | -## S191 _test_digit_ink_modes(行 137–159 · 5 条 · 源 game/tests/unit/presentation/terrain_tile_sets_test.gd · 去向:待分类回填) +## S191 _test_hue_domains(行 72–82 · 4 条 · 源 game/tests/unit/presentation/terrain_tile_sets_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1421 | 137 | "图型 %s 数字墨族断言样本可读" ↩ % String(bt) | false | (待填) | | | -| 1422 | 144 | "图型 %s 双峰纹理落牌(亮族 p90 %.2f/均值 %.2f,深族 p90 %.2f/均值 %.2f 均未过门)" ↩ % [ String(bt), float(mode["cr_p90_bright"]), float(mode["cr_mean_bright"]), float(mode["cr_p90_dark"]), float(mode["cr_mean_dark"])] | float(mode["cr_mean_dark"]) < float(TilePaletteScript.DIGIT_INK_CR_MEAN_DARK) | (待填) | | | -| 1423 | 151 | "图型 %s 所选%s 对 p90 ≥%.1f(实测 %.2f)" ↩ % [String(bt), mode_name, float(TilePaletteScript.DIGIT_INK_CR_P90), cr_p90] | cr_p90 >= float(TilePaletteScript.DIGIT_INK_CR_P90) | (待填) | | | -| 1424 | 155 | "图型 %s 所选%s 对均值 ≥%.1f(实测 %.2f)" ↩ % [String(bt), mode_name, mean_gate, cr_mean] | cr_mean >= mean_gate | (待填) | | | -| 1425 | 158 | "图型 %s 呈现模式期望=%s(实测=%s)" ↩ % [String(bt), "色牌" if bool(expect_plate[bt]) else "直画", mode_name] | plate == bool(expect_plate[bt]) | (待填) | | | +| 1421 | 72 | "图型 %s 抽检样本可读" ↩ % String(bt) | false | (待填) | | | +| 1422 | 77 | "图型 %s 墙顶均值色相在带 %s(实测 %.3f)" ↩ % [String(bt), str(band), float(wall["h"])] | float(wall["h"]) >= float(band[0]) and float(wall["h"]) <= float(band[1]) | (待填) | | | +| 1423 | 79 | "图型 %s 图底分离(墙顶明度 %.3f > 地面 %.3f)" ↩ % [String(bt), wall_v[bt], floor_v[bt]] | wall_v[bt] > floor_v[bt] | (待填) | | | +| 1424 | 82 | "deep_underdark 墙顶更暗于 underdark(更深蓝黑方向)" | float(wall_v["deep_underdark"]) < float(wall_v["underdark"]) | (待填) | | | -## S192 _smoke_type_glow(行 214–374 · 24 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) +## S192 _test_digit_ink_modes(行 137–159 · 5 条 · 源 game/tests/unit/presentation/terrain_tile_sets_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1426 | 214 | "V1 微光默认开(Q4 丙案——呈现态布尔缺省 true,生产写入面零显式开)" | bool(snap.get("enabled", false)) | (待填) | | | -| 1427 | 216 | "V1 夹具全集合法九型 ⇒ 清单外登记为空(禁静默空光通道零误报)" | (snap.get("errors", []) as Array).is_empty() | (待填) | | | -| 1428 | 219 | "V1 作用集恒等:微光格集合 == _diggable ∩ 身份可查(期望 %d,实测 %d)" ↩ % [expect.size(), (snap.get("cells", {}) as Dictionary).size()] | _glow_key_set_equal(snap.get("cells", {}), expect) | (待填) | | | -| 1429 | 221 | "V1 夹具前提:英雄未开邻格 ≥5(实测 %d——novice %d 步)" ↩ % [expect.size(), steps] | expect.size() >= 5 | (待填) | | | -| 1430 | 231 | "V1 已开格/r0 出生展开区零微光(S1)%s" ↩ % ("" if opened_leak == "" else "违例:" + opened_leak) | opened_leak == "" | (待填) | | | -| 1431 | 248 | "V2 夹具前提:未开邻格派定 ≥5 型(实测 %d)" ↩ % mapped | mapped >= 5 | (待填) | | | -| 1432 | 257 | "V2 九型→五组逐格映射(attack/defense/action/gp→增益/heal→治疗/pierce→穿刺/blast→群伤/magic→魔法)%s" ↩ % ("" if map_bad == "" else "违例:" + map_bad) | map_bad == "" | (待填) | | | -| 1433 | 271 | "V2 清单外 cell_type 显式登记(errors=%s)" ↩ % str(errs) | errs.has("keystone") | (待填) | | | -| 1434 | 272 | "V2 清单外格零微光(无静默空光——%s 不在作用集)" ↩ % str(bogus_cell) | not (snap.get("cells", {}) as Dictionary).has(bogus_cell) | (待填) | | | -| 1435 | 274 | "V2 清单外格剔除后作用集 = 派定数 −1(%d→%d)" ↩ % [mapped, (snap.get("cells", {}) as Dictionary).size()] | (snap.get("cells", {}) as Dictionary).size() == mapped - 1 | (待填) | | | -| 1436 | 287 | "V1 封锁格零微光(query null ⇒ 天然惰性——%s)" ↩ % str(blocked_cell) | not (snap.get("cells", {}) as Dictionary).has(blocked_cell) | (待填) | | | -| 1437 | 289 | "V1 封锁格零登记(errors 仍仅清单外一条——%s)" ↩ % str(snap.get("errors", [])) | (snap.get("errors", []) as Array).size() == 1 | (待填) | | | -| 1438 | 291 | "V1 封锁格剔除后作用集 = 派定数 −1(实测 %d)" ↩ % (snap.get("cells", {}) as Dictionary).size() | (snap.get("cells", {}) as Dictionary).size() == mapped - 1 | (待填) | | | -| 1439 | 297 | "V1 封锁解除后作用集复位恒等(期望 %d,实测 %d)" ↩ % [expect.size(), (snap.get("cells", {}) as Dictionary).size()] | _glow_key_set_equal(snap.get("cells", {}), expect) | (待填) | | | -| 1440 | 303 | "V7 off 态开关读数=false" | not bool(snap.get("enabled", true)) | (待填) | | | -| 1441 | 304 | "V7 off 态作用集为空(基线保护面)" | (snap.get("cells", {}) as Dictionary).is_empty() | (待填) | | | -| 1442 | 307 | "V7 on 态开关读数=true(复现)" | bool(snap_on.get("enabled", false)) | (待填) | | | -| 1443 | 308 | "V7 off→on 作用集逐位复现(关前 %d 格/开后 %d 格,组号逐位一致)" ↩ % [ (snap_before_off.get("cells", {}) as Dictionary).size(), (snap_on.get("cells", {}) as Dictionary).size()] | _glow_map_equal(snap_on.get("cells", {}), snap_before_off.get("cells", {})) | (待填) | | | -| 1444 | 311 | "V7 off→on 作用集与独立重算期望集恒等(%d 格)" ↩ % (snap_on.get("cells", {}) as Dictionary).size() | _glow_key_set_equal(snap_on.get("cells", {}), expect) | (待填) | | | -| 1445 | 315 | "V7 微光开关零玩法写入(已开集/英雄位/封印数三面对照逐位一致)" | revealed_before == revealed_after and hero_before == ms.hero_pos() and seals_before == ms.seal_count() | (待填) | | | -| 1446 | 328 | "V3 换图 rebuild 后作用集按新板重算(期望 %d,实测 %d——零旧板残留)" ↩ % [expect2.size(), (snap2.get("cells", {}) as Dictionary).size()] | _glow_key_set_equal(snap2.get("cells", {}), expect2) | (待填) | | | -| 1447 | 330 | "V3 换图清清单外登记(rebuild 清零)" | (snap2.get("errors", []) as Array).is_empty() | (待填) | | | -| 1448 | 371 | "契约 1 同板同序列 on/off 两态结算逐位一致(%d 步对照——A 开态/B 关态)%s" ↩ % [seq_steps, diverge] | diverge == "" | (待填) | | | -| 1449 | 374 | "契约 1 对照前提:同序列 ≥5 步(实测 %d)" ↩ % seq_steps | seq_steps >= 5 | (待填) | | | +| 1425 | 137 | "图型 %s 数字墨族断言样本可读" ↩ % String(bt) | false | (待填) | | | +| 1426 | 144 | "图型 %s 双峰纹理落牌(亮族 p90 %.2f/均值 %.2f,深族 p90 %.2f/均值 %.2f 均未过门)" ↩ % [ String(bt), float(mode["cr_p90_bright"]), float(mode["cr_mean_bright"]), float(mode["cr_p90_dark"]), float(mode["cr_mean_dark"])] | float(mode["cr_mean_dark"]) < float(TilePaletteScript.DIGIT_INK_CR_MEAN_DARK) | (待填) | | | +| 1427 | 151 | "图型 %s 所选%s 对 p90 ≥%.1f(实测 %.2f)" ↩ % [String(bt), mode_name, float(TilePaletteScript.DIGIT_INK_CR_P90), cr_p90] | cr_p90 >= float(TilePaletteScript.DIGIT_INK_CR_P90) | (待填) | | | +| 1428 | 155 | "图型 %s 所选%s 对均值 ≥%.1f(实测 %.2f)" ↩ % [String(bt), mode_name, mean_gate, cr_mean] | cr_mean >= mean_gate | (待填) | | | +| 1429 | 158 | "图型 %s 呈现模式期望=%s(实测=%s)" ↩ % [String(bt), "色牌" if bool(expect_plate[bt]) else "直画", mode_name] | plate == bool(expect_plate[bt]) | (待填) | | | -## S193 _smoke_battle_log_view(行 391–422 · 6 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) +## S193 _smoke_type_glow(行 215–375 · 24 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1450 | 391 | "敌方伤害行格式化(baseline 行不读退役 attach)" | enemy_txt.contains("撕咬") and enemy_txt.contains("〔掷 15 vs 护甲 12") | (待填) | | | -| 1451 | 393 | "退役伏击/基线拆行文案不再出现" | not enemy_txt.contains("伏击") and not enemy_txt.contains("基线") | (待填) | | | -| 1452 | 400 | "主角穿刺型暴击行金框(单分量 payload 不触发三分量拆行)" | hero_txt.contains("暴击×") and hero_txt.contains("⚔击杀") and hero_txt.contains("■") | (待填) | | | -| 1453 | 402 | "退役三分量拆行文案不再出现" | not hero_txt.contains(" + 穿刺 ") | (待填) | | | -| 1454 | 408 | "未生效行聚合计数 ×2 呈现" | agg_txt.contains("⚠") and agg_txt.contains("×2") | (待填) | | | -| 1455 | 421 | "行型 %s 格式化落地(解析文本增长)" ↩ % String(row_type) | view.parsed_text().length() > before | (待填) | | | +| 1430 | 215 | "V1 微光默认开(Q4 丙案——呈现态布尔缺省 true,生产写入面零显式开)" | bool(snap.get("enabled", false)) | (待填) | | | +| 1431 | 217 | "V1 夹具全集合法九型 ⇒ 清单外登记为空(禁静默空光通道零误报)" | (snap.get("errors", []) as Array).is_empty() | (待填) | | | +| 1432 | 220 | "V1 作用集恒等:微光格集合 == _diggable ∩ 身份可查(期望 %d,实测 %d)" ↩ % [expect.size(), (snap.get("cells", {}) as Dictionary).size()] | _glow_key_set_equal(snap.get("cells", {}), expect) | (待填) | | | +| 1433 | 222 | "V1 夹具前提:英雄未开邻格 ≥5(实测 %d——novice %d 步)" ↩ % [expect.size(), steps] | expect.size() >= 5 | (待填) | | | +| 1434 | 232 | "V1 已开格/r0 出生展开区零微光(S1)%s" ↩ % ("" if opened_leak == "" else "违例:" + opened_leak) | opened_leak == "" | (待填) | | | +| 1435 | 249 | "V2 夹具前提:未开邻格派定 ≥5 型(实测 %d)" ↩ % mapped | mapped >= 5 | (待填) | | | +| 1436 | 258 | "V2 九型→五组逐格映射(attack/defense/action/gp→增益/heal→治疗/pierce→穿刺/blast→群伤/magic→魔法)%s" ↩ % ("" if map_bad == "" else "违例:" + map_bad) | map_bad == "" | (待填) | | | +| 1437 | 272 | "V2 清单外 cell_type 显式登记(errors=%s)" ↩ % str(errs) | errs.has("keystone") | (待填) | | | +| 1438 | 273 | "V2 清单外格零微光(无静默空光——%s 不在作用集)" ↩ % str(bogus_cell) | not (snap.get("cells", {}) as Dictionary).has(bogus_cell) | (待填) | | | +| 1439 | 275 | "V2 清单外格剔除后作用集 = 派定数 −1(%d→%d)" ↩ % [mapped, (snap.get("cells", {}) as Dictionary).size()] | (snap.get("cells", {}) as Dictionary).size() == mapped - 1 | (待填) | | | +| 1440 | 288 | "V1 封锁格零微光(query null ⇒ 天然惰性——%s)" ↩ % str(blocked_cell) | not (snap.get("cells", {}) as Dictionary).has(blocked_cell) | (待填) | | | +| 1441 | 290 | "V1 封锁格零登记(errors 仍仅清单外一条——%s)" ↩ % str(snap.get("errors", [])) | (snap.get("errors", []) as Array).size() == 1 | (待填) | | | +| 1442 | 292 | "V1 封锁格剔除后作用集 = 派定数 −1(实测 %d)" ↩ % (snap.get("cells", {}) as Dictionary).size() | (snap.get("cells", {}) as Dictionary).size() == mapped - 1 | (待填) | | | +| 1443 | 298 | "V1 封锁解除后作用集复位恒等(期望 %d,实测 %d)" ↩ % [expect.size(), (snap.get("cells", {}) as Dictionary).size()] | _glow_key_set_equal(snap.get("cells", {}), expect) | (待填) | | | +| 1444 | 304 | "V7 off 态开关读数=false" | not bool(snap.get("enabled", true)) | (待填) | | | +| 1445 | 305 | "V7 off 态作用集为空(基线保护面)" | (snap.get("cells", {}) as Dictionary).is_empty() | (待填) | | | +| 1446 | 308 | "V7 on 态开关读数=true(复现)" | bool(snap_on.get("enabled", false)) | (待填) | | | +| 1447 | 309 | "V7 off→on 作用集逐位复现(关前 %d 格/开后 %d 格,组号逐位一致)" ↩ % [ (snap_before_off.get("cells", {}) as Dictionary).size(), (snap_on.get("cells", {}) as Dictionary).size()] | _glow_map_equal(snap_on.get("cells", {}), snap_before_off.get("cells", {})) | (待填) | | | +| 1448 | 312 | "V7 off→on 作用集与独立重算期望集恒等(%d 格)" ↩ % (snap_on.get("cells", {}) as Dictionary).size() | _glow_key_set_equal(snap_on.get("cells", {}), expect) | (待填) | | | +| 1449 | 316 | "V7 微光开关零玩法写入(已开集/英雄位/封印数三面对照逐位一致)" | revealed_before == revealed_after and hero_before == ms.hero_pos() and seals_before == ms.seal_count() | (待填) | | | +| 1450 | 329 | "V3 换图 rebuild 后作用集按新板重算(期望 %d,实测 %d——零旧板残留)" ↩ % [expect2.size(), (snap2.get("cells", {}) as Dictionary).size()] | _glow_key_set_equal(snap2.get("cells", {}), expect2) | (待填) | | | +| 1451 | 331 | "V3 换图清清单外登记(rebuild 清零)" | (snap2.get("errors", []) as Array).is_empty() | (待填) | | | +| 1452 | 372 | "契约 1 同板同序列 on/off 两态结算逐位一致(%d 步对照——A 开态/B 关态)%s" ↩ % [seq_steps, diverge] | diverge == "" | (待填) | | | +| 1453 | 375 | "契约 1 对照前提:同序列 ≥5 步(实测 %d)" ↩ % seq_steps | seq_steps >= 5 | (待填) | | | -## S194 _smoke_level_open_line(行 429–435 · 3 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) +## S194 _smoke_battle_log_view(行 392–423 · 6 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1456 | 429 | "开场行 boosted=true 尾接「(含面板加成)」〔wc1〕" | String(NarratorScript.level_open_line("第一层", 42, 5, 30, true)).contains("(含面板加成)") | (待填) | | | -| 1457 | 431 | "开场行 boosted=false 零后缀(白板局不带)〔wc1〕" | not String(NarratorScript.level_open_line("第一层", 42, 5, 30, false)).contains("(含面板加成)") | (待填) | | | -| 1458 | 433 | "开场行种子/两值带入不受后缀位影响(数值带入回归)〔wc1〕" | String(NarratorScript.level_open_line("第一层", 42, 5, 30, true)).contains("种子 42") and String(NarratorScript.level_open_line("第一层", 42, 5, 30, true)).contains("攻击 5 / 生命 30") | (待填) | | | +| 1454 | 392 | "敌方伤害行格式化(baseline 行不读退役 attach)" | enemy_txt.contains("撕咬") and enemy_txt.contains("〔掷 15 vs 护甲 12") | (待填) | | | +| 1455 | 394 | "退役伏击/基线拆行文案不再出现" | not enemy_txt.contains("伏击") and not enemy_txt.contains("基线") | (待填) | | | +| 1456 | 401 | "主角穿刺型暴击行金框(单分量 payload 不触发三分量拆行)" | hero_txt.contains("暴击×") and hero_txt.contains("⚔击杀") and hero_txt.contains("■") | (待填) | | | +| 1457 | 403 | "退役三分量拆行文案不再出现" | not hero_txt.contains(" + 穿刺 ") | (待填) | | | +| 1458 | 409 | "未生效行聚合计数 ×2 呈现" | agg_txt.contains("⚠") and agg_txt.contains("×2") | (待填) | | | +| 1459 | 422 | "行型 %s 格式化落地(解析文本增长)" ↩ % String(row_type) | view.parsed_text().length() > before | (待填) | | | -## S195 _smoke_global_theme(行 444–539 · 22 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) +## S195 _smoke_level_open_line(行 430–436 · 3 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1459 | 444 | "V1 项目主题挂载(project.godot gui/theme/custom → main_theme.tres)" | th != null | (待填) | | | -| 1460 | 453 | "V1 主题类型覆盖 %s" ↩ % t | type_set.has(t) | (待填) | | | -| 1461 | 455 | "V1 红线 Button 类型词条零接触" | not type_set.has("Button") | (待填) | | | -| 1462 | 463 | "V1 红线 focus 族词条零定义%s" ↩ % ("" if focus_hits == "" else "(违例:" + focus_hits + ")") | focus_hits == "" | (待填) | | | -| 1463 | 467 | "V1 滚动条槽/柄三态词条在位" | vsb.has_theme_stylebox("scroll") and vsb.has_theme_stylebox("grabber") and vsb.has_theme_stylebox("grabber_highlight") and vsb.has_theme_stylebox("grabber_pressed") | (待填) | | | -| 1464 | 470 | "V1 滚动条 scroll_focus 未定义(红线)" | not th.has_stylebox("scroll_focus", "VScrollBar") and not th.has_stylebox("scroll_focus", "HScrollBar") | (待填) | | | -| 1465 | 473 | "V1 滑轨槽/填充/柄词条在位" | hsl.has_theme_stylebox("slider") and hsl.has_theme_stylebox("grabber_area") and hsl.has_theme_stylebox("grabber_area_highlight") and hsl.has_theme_icon("grabber") and hsl.has_theme_icon("grabber_highlight") and hsl.has_theme_icon("grabber_disabled") | (待填) | | | -| 1466 | 479 | "V1 LineEdit 词条在位(含占位色 font_placeholder_color)" | le.has_theme_stylebox("normal") and le.has_theme_color("font_color") and le.has_theme_color("font_placeholder_color") | (待填) | | | -| 1467 | 483 | "V1 SpinBox 箭头词条在位(updown 合并槽)" | sp.has_theme_icon("updown") | (待填) | | | -| 1468 | 486 | "V1 分隔线词条在位" | hsep.has_theme_stylebox("separator") and vsep.has_theme_stylebox("separator") | (待填) | | | -| 1469 | 490 | "V1 TooltipPanel 词条在位" | tpanel.has_theme_stylebox("panel") | (待填) | | | -| 1470 | 491 | "V1 TooltipLabel 词条在位" | tlabel.has_theme_color("font_color") and tlabel.has_theme_font_size("font_size") | (待填) | | | -| 1471 | 499 | "V2 冻结值锚定(已填充段=BG_ROOT #3A2E22,槽=暖石 #B8A582)" | fill_c.is_equal_approx(Color8(58, 46, 34)) and track_c.is_equal_approx(Color8(184, 165, 130)) | (待填) | | | -| 1472 | 502 | "V2 滑轨两段对比 %.2f:1 ≥4.5:1(拖到中点一眼可辨)" ↩ % ratio | ratio >= 4.5 | (待填) | | | -| 1473 | 504 | "V2 滑轨 stylebox 类型均为 StyleBoxFlat" | false | (待填) | | | -| 1474 | 507 | "V3 CheckBox 四态图标非空" | cbx.get_theme_icon("checked") != null and cbx.get_theme_icon("unchecked") != null and cbx.get_theme_icon("checked_disabled") != null and cbx.get_theme_icon("unchecked_disabled") != null | (待填) | | | -| 1475 | 511 | "V3 CheckButton 四态图标非空(与 CheckBox 同套 checked/unchecked 名,4.7 源码实证)" | cbt.get_theme_icon("checked") != null and cbt.get_theme_icon("unchecked") != null and cbt.get_theme_icon("checked_disabled") != null and cbt.get_theme_icon("unchecked_disabled") != null | (待填) | | | -| 1476 | 515 | "V3 PopupMenu 词条存在(弹层预盖)" | pm.has_theme_stylebox("panel") and pm.has_theme_stylebox("hover") and pm.has_theme_font_size("font_size") | (待填) | | | -| 1477 | 519 | "V3 OptionButton 词条存在(预盖)" | ob.has_theme_stylebox("normal") and ob.has_theme_stylebox("hover") and ob.has_theme_stylebox("pressed") and ob.has_theme_color("font_color") | (待填) | | | -| 1478 | 533 | "V4 退役实现零残留(%s)%s" ↩ % [path, "" if bad == "" else "违例:" + bad] | bad == "" | (待填) | | | -| 1479 | 536 | "V6 主题 default_font 非空(挂主题顶掉 custom_font 也不丢中文字形)" | th.default_font != null | (待填) | | | -| 1480 | 539 | "V6 Label 实取字体非空(中文字形防御实证)" | lbl.get_theme_font("font") != null | (待填) | | | +| 1460 | 430 | "开场行 boosted=true 尾接「(含面板加成)」〔wc1〕" | String(NarratorScript.level_open_line("第一层", 42, 5, 30, true)).contains("(含面板加成)") | (待填) | | | +| 1461 | 432 | "开场行 boosted=false 零后缀(白板局不带)〔wc1〕" | not String(NarratorScript.level_open_line("第一层", 42, 5, 30, false)).contains("(含面板加成)") | (待填) | | | +| 1462 | 434 | "开场行种子/两值带入不受后缀位影响(数值带入回归)〔wc1〕" | String(NarratorScript.level_open_line("第一层", 42, 5, 30, true)).contains("种子 42") and String(NarratorScript.level_open_line("第一层", 42, 5, 30, true)).contains("攻击 5 / 生命 30") | (待填) | | | -## S196 _smoke_button_five_states(行 552–624 · 23 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) +## S196 _smoke_global_theme(行 445–540 · 22 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1481 | 552 | "V1 普通钮 %s 样式盒非空" ↩ % st | b.has_theme_stylebox_override(st) | (待填) | | | -| 1482 | 558 | "V1 普通钮 normal/hover/disabled 均为石纹九宫格贴图样式盒" | n_sb is StyleBoxTexture and h_sb is StyleBoxTexture and d_sb is StyleBoxTexture | (待填) | | | -| 1483 | 562 | "V1 普通钮 hover=modulate 提亮(乙案,异于常态 WHITE)" | h_mod != Color.WHITE and h_mod.r > 1.0 | (待填) | | | -| 1484 | 566 | "V1 普通钮 disabled=本族底 α0.45 幽灵化(甲案)" | is_equal_approx(d_mod.a, 0.45) and d_mod.r == 1.0 and d_mod.g == 1.0 | (待填) | | | -| 1485 | 569 | "V1 普通钮 disabled≠pressed(旧错配已修正)" | _sb_content_differs(d_sb, p_sb) | (待填) | | | -| 1486 | 571 | "V1 普通钮 focus 样式盒为扁平环(StyleBoxFlat)" | f_sb is StyleBoxFlat | (待填) | | | -| 1487 | 573 | "V1 焦点环色=INK(与 font_focus_color 同源)" | fsb.border_color == uikit_s.INK | (待填) | | | -| 1488 | 574 | "V1 焦点环宽=2px" | is_equal_approx(fsb.border_width_left, 2.0) and is_equal_approx(fsb.border_width_right, 2.0) and is_equal_approx(fsb.border_width_top, 2.0) and is_equal_approx(fsb.border_width_bottom, 2.0) | (待填) | | | -| 1489 | 577 | "V1 焦点环内缩=1px" | is_equal_approx(fsb.expand_margin_left, -1.0) and is_equal_approx(fsb.expand_margin_top, -1.0) and is_equal_approx(fsb.expand_margin_right, -1.0) and is_equal_approx(fsb.expand_margin_bottom, -1.0) | (待填) | | | -| 1490 | 580 | "V1 焦点环无底(叠加态不遮钮底)" | not fsb.draw_center and fsb.bg_color.a < 0.001 | (待填) | | | -| 1491 | 585 | "V1 主钮 %s 样式盒非空" ↩ % st | pb.has_theme_stylebox_override(st) | (待填) | | | -| 1492 | 589 | "V1 主钮 pressed/disabled=本族平涂(非石纹)" | ppn is StyleBoxFlat and pdd is StyleBoxFlat | (待填) | | | -| 1493 | 591 | "V1 主钮 pressed=烛光黄深档(现行值不动)" | (ppn as StyleBoxFlat).bg_color == Color8(214, 172, 88) | (待填) | | | -| 1494 | 593 | "V1 主钮 disabled=本族底 α0.45 幽灵化" | is_equal_approx((pdd as StyleBoxFlat).bg_color.a, 0.45) | (待填) | | | -| 1495 | 595 | "V1 主钮 disabled≠pressed" | _sb_content_differs(ppn, pdd) | (待填) | | | -| 1496 | 596 | "V1 主钮 hover=提亮档(承现行不动)" | (phv as StyleBoxFlat).bg_color == uikit_s.CANDLE.lightened(0.06) | (待填) | | | -| 1497 | 602 | "V1 危险钮 %s 样式盒非空" ↩ % st | db.has_theme_stylebox_override(st) | (待填) | | | -| 1498 | 605 | "V1 危险钮 pressed/disabled=本族平涂(非石纹,旧错配已修正)" | dpr is StyleBoxFlat and dds is StyleBoxFlat | (待填) | | | -| 1499 | 607 | "V1 危险钮 pressed=深红深档(暗于常态)" | (dpr as StyleBoxFlat).bg_color.r < 180.0 / 255.0 | (待填) | | | -| 1500 | 609 | "V1 危险钮 disabled=本族底 α0.45 幽灵化" | is_equal_approx((dds as StyleBoxFlat).bg_color.a, 0.45) | (待填) | | | -| 1501 | 611 | "V1 危险钮 disabled≠pressed" | _sb_content_differs(dpr, dds) | (待填) | | | -| 1502 | 616 | "V2 红线维持 Button 类型词条零接触" | not th.get_type_list().has("Button") | (待填) | | | -| 1503 | 623 | "V2 红线维持 focus 族词条零定义%s" ↩ % ("" if focus_hits == "" else "(违例:" + focus_hits + ")") | focus_hits == "" | (待填) | | | +| 1463 | 445 | "V1 项目主题挂载(project.godot gui/theme/custom → main_theme.tres)" | th != null | (待填) | | | +| 1464 | 454 | "V1 主题类型覆盖 %s" ↩ % t | type_set.has(t) | (待填) | | | +| 1465 | 456 | "V1 红线 Button 类型词条零接触" | not type_set.has("Button") | (待填) | | | +| 1466 | 464 | "V1 红线 focus 族词条零定义%s" ↩ % ("" if focus_hits == "" else "(违例:" + focus_hits + ")") | focus_hits == "" | (待填) | | | +| 1467 | 468 | "V1 滚动条槽/柄三态词条在位" | vsb.has_theme_stylebox("scroll") and vsb.has_theme_stylebox("grabber") and vsb.has_theme_stylebox("grabber_highlight") and vsb.has_theme_stylebox("grabber_pressed") | (待填) | | | +| 1468 | 471 | "V1 滚动条 scroll_focus 未定义(红线)" | not th.has_stylebox("scroll_focus", "VScrollBar") and not th.has_stylebox("scroll_focus", "HScrollBar") | (待填) | | | +| 1469 | 474 | "V1 滑轨槽/填充/柄词条在位" | hsl.has_theme_stylebox("slider") and hsl.has_theme_stylebox("grabber_area") and hsl.has_theme_stylebox("grabber_area_highlight") and hsl.has_theme_icon("grabber") and hsl.has_theme_icon("grabber_highlight") and hsl.has_theme_icon("grabber_disabled") | (待填) | | | +| 1470 | 480 | "V1 LineEdit 词条在位(含占位色 font_placeholder_color)" | le.has_theme_stylebox("normal") and le.has_theme_color("font_color") and le.has_theme_color("font_placeholder_color") | (待填) | | | +| 1471 | 484 | "V1 SpinBox 箭头词条在位(updown 合并槽)" | sp.has_theme_icon("updown") | (待填) | | | +| 1472 | 487 | "V1 分隔线词条在位" | hsep.has_theme_stylebox("separator") and vsep.has_theme_stylebox("separator") | (待填) | | | +| 1473 | 491 | "V1 TooltipPanel 词条在位" | tpanel.has_theme_stylebox("panel") | (待填) | | | +| 1474 | 492 | "V1 TooltipLabel 词条在位" | tlabel.has_theme_color("font_color") and tlabel.has_theme_font_size("font_size") | (待填) | | | +| 1475 | 500 | "V2 冻结值锚定(已填充段=BG_ROOT #3A2E22,槽=暖石 #B8A582)" | fill_c.is_equal_approx(Color8(58, 46, 34)) and track_c.is_equal_approx(Color8(184, 165, 130)) | (待填) | | | +| 1476 | 503 | "V2 滑轨两段对比 %.2f:1 ≥4.5:1(拖到中点一眼可辨)" ↩ % ratio | ratio >= 4.5 | (待填) | | | +| 1477 | 505 | "V2 滑轨 stylebox 类型均为 StyleBoxFlat" | false | (待填) | | | +| 1478 | 508 | "V3 CheckBox 四态图标非空" | cbx.get_theme_icon("checked") != null and cbx.get_theme_icon("unchecked") != null and cbx.get_theme_icon("checked_disabled") != null and cbx.get_theme_icon("unchecked_disabled") != null | (待填) | | | +| 1479 | 512 | "V3 CheckButton 四态图标非空(与 CheckBox 同套 checked/unchecked 名,4.7 源码实证)" | cbt.get_theme_icon("checked") != null and cbt.get_theme_icon("unchecked") != null and cbt.get_theme_icon("checked_disabled") != null and cbt.get_theme_icon("unchecked_disabled") != null | (待填) | | | +| 1480 | 516 | "V3 PopupMenu 词条存在(弹层预盖)" | pm.has_theme_stylebox("panel") and pm.has_theme_stylebox("hover") and pm.has_theme_font_size("font_size") | (待填) | | | +| 1481 | 520 | "V3 OptionButton 词条存在(预盖)" | ob.has_theme_stylebox("normal") and ob.has_theme_stylebox("hover") and ob.has_theme_stylebox("pressed") and ob.has_theme_color("font_color") | (待填) | | | +| 1482 | 534 | "V4 退役实现零残留(%s)%s" ↩ % [path, "" if bad == "" else "违例:" + bad] | bad == "" | (待填) | | | +| 1483 | 537 | "V6 主题 default_font 非空(挂主题顶掉 custom_font 也不丢中文字形)" | th.default_font != null | (待填) | | | +| 1484 | 540 | "V6 Label 实取字体非空(中文字形防御实证)" | lbl.get_theme_font("font") != null | (待填) | | | -## S197 _smoke_texture_filter(行 631–673 · 9 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) +## S197 _smoke_button_five_states(行 553–625 · 23 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1504 | 631 | "V3 工程设置 default_texture_filter=0(Nearest,翻转面=立绘/瓦片/九宫格 crisp)" | v != null and int(v) == 0 | (待填) | | | -| 1505 | 635 | "V3 白名单在位:暗角 vignette 显式 LINEAR" | vg.texture_filter == CanvasItem.TEXTURE_FILTER_LINEAR | (待填) | | | -| 1506 | 639 | "V3 白名单在位:光柱 beams 显式 LINEAR" | bm.texture_filter == CanvasItem.TEXTURE_FILTER_LINEAR | (待填) | | | -| 1507 | 657 | "T4 光柱带心峰值 α≈0.05(8bit 截断量化下限 12/255,实测 %.5f)" ↩ % max_a | max_a >= 12.0 / 255.0 and max_a <= 0.05 | (待填) | | | -| 1508 | 659 | "T4 光柱带内连续 alpha 过渡像素 %d 个(旧零过渡硬边已修)" ↩ % mid_a | mid_a > 100 | (待填) | | | -| 1509 | 660 | "T4 光柱纵向衰减生效(上半亮度 %.0f > 下半 %.0f 的 2 倍——上亮下暗)" ↩ % [top_sum, bot_sum] | top_sum > bot_sum * 2.0 | (待填) | | | -| 1510 | 664 | "V3 白名单在位:地图渐变 gradient_base 显式 LINEAR" | gb.texture_filter == CanvasItem.TEXTURE_FILTER_LINEAR | (待填) | | | -| 1511 | 669 | "V3 脚影显式 LINEAR 不丢(board_world.gd)" | bw_src.contains("shadow.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR") | (待填) | | | -| 1512 | 672 | "V3 状态图标显式 LINEAR 不丢(status_slot_row.gd)" | ss_src.contains("icon.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR") | (待填) | | | +| 1485 | 553 | "V1 普通钮 %s 样式盒非空" ↩ % st | b.has_theme_stylebox_override(st) | (待填) | | | +| 1486 | 559 | "V1 普通钮 normal/hover/disabled 均为石纹九宫格贴图样式盒" | n_sb is StyleBoxTexture and h_sb is StyleBoxTexture and d_sb is StyleBoxTexture | (待填) | | | +| 1487 | 563 | "V1 普通钮 hover=modulate 提亮(乙案,异于常态 WHITE)" | h_mod != Color.WHITE and h_mod.r > 1.0 | (待填) | | | +| 1488 | 567 | "V1 普通钮 disabled=本族底 α0.45 幽灵化(甲案)" | is_equal_approx(d_mod.a, 0.45) and d_mod.r == 1.0 and d_mod.g == 1.0 | (待填) | | | +| 1489 | 570 | "V1 普通钮 disabled≠pressed(旧错配已修正)" | _sb_content_differs(d_sb, p_sb) | (待填) | | | +| 1490 | 572 | "V1 普通钮 focus 样式盒为扁平环(StyleBoxFlat)" | f_sb is StyleBoxFlat | (待填) | | | +| 1491 | 574 | "V1 焦点环色=INK(与 font_focus_color 同源)" | fsb.border_color == uikit_s.INK | (待填) | | | +| 1492 | 575 | "V1 焦点环宽=2px" | is_equal_approx(fsb.border_width_left, 2.0) and is_equal_approx(fsb.border_width_right, 2.0) and is_equal_approx(fsb.border_width_top, 2.0) and is_equal_approx(fsb.border_width_bottom, 2.0) | (待填) | | | +| 1493 | 578 | "V1 焦点环内缩=1px" | is_equal_approx(fsb.expand_margin_left, -1.0) and is_equal_approx(fsb.expand_margin_top, -1.0) and is_equal_approx(fsb.expand_margin_right, -1.0) and is_equal_approx(fsb.expand_margin_bottom, -1.0) | (待填) | | | +| 1494 | 581 | "V1 焦点环无底(叠加态不遮钮底)" | not fsb.draw_center and fsb.bg_color.a < 0.001 | (待填) | | | +| 1495 | 586 | "V1 主钮 %s 样式盒非空" ↩ % st | pb.has_theme_stylebox_override(st) | (待填) | | | +| 1496 | 590 | "V1 主钮 pressed/disabled=本族平涂(非石纹)" | ppn is StyleBoxFlat and pdd is StyleBoxFlat | (待填) | | | +| 1497 | 592 | "V1 主钮 pressed=烛光黄深档(现行值不动)" | (ppn as StyleBoxFlat).bg_color == Color8(214, 172, 88) | (待填) | | | +| 1498 | 594 | "V1 主钮 disabled=本族底 α0.45 幽灵化" | is_equal_approx((pdd as StyleBoxFlat).bg_color.a, 0.45) | (待填) | | | +| 1499 | 596 | "V1 主钮 disabled≠pressed" | _sb_content_differs(ppn, pdd) | (待填) | | | +| 1500 | 597 | "V1 主钮 hover=提亮档(承现行不动)" | (phv as StyleBoxFlat).bg_color == uikit_s.CANDLE.lightened(0.06) | (待填) | | | +| 1501 | 603 | "V1 危险钮 %s 样式盒非空" ↩ % st | db.has_theme_stylebox_override(st) | (待填) | | | +| 1502 | 606 | "V1 危险钮 pressed/disabled=本族平涂(非石纹,旧错配已修正)" | dpr is StyleBoxFlat and dds is StyleBoxFlat | (待填) | | | +| 1503 | 608 | "V1 危险钮 pressed=深红深档(暗于常态)" | (dpr as StyleBoxFlat).bg_color.r < 180.0 / 255.0 | (待填) | | | +| 1504 | 610 | "V1 危险钮 disabled=本族底 α0.45 幽灵化" | is_equal_approx((dds as StyleBoxFlat).bg_color.a, 0.45) | (待填) | | | +| 1505 | 612 | "V1 危险钮 disabled≠pressed" | _sb_content_differs(dpr, dds) | (待填) | | | +| 1506 | 617 | "V2 红线维持 Button 类型词条零接触" | not th.get_type_list().has("Button") | (待填) | | | +| 1507 | 624 | "V2 红线维持 focus 族词条零定义%s" ↩ % ("" if focus_hits == "" else "(违例:" + focus_hits + ")") | focus_hits == "" | (待填) | | | -## S198 _smoke_contrast_inks(行 682–698 · 9 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) +## S198 _smoke_texture_filter(行 632–674 · 9 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1513 | 682 | "V4 顺位徽标/重甲徽标 GOLD_BRIGHT 对舞台底 %.2f:1 ≥4.5:1" ↩ % r_order | r_order >= 4.5 | (待填) | | | -| 1514 | 684 | "V4 魔法护甲徽标 HERO_BLUE_BRIGHT 对舞台底 %.2f:1 ≥4.5:1" ↩ % r_ward | r_ward >= 4.5 | (待填) | | | -| 1515 | 686 | "V4 RAP 反馈行 STONE_DEEP 对数据板 %.2f:1 ≥4.5:1" ↩ % r_rap | r_rap >= 4.5 | (待填) | | | -| 1516 | 689 | "V4 顺位徽标①②③ 墨=GOLD_BRIGHT(13px 行原位)" | sb_src.contains("HORIZONTAL_ALIGNMENT_LEFT, -1, 13, UiKit.GOLD_BRIGHT") | (待填) | | | -| 1517 | 691 | "V4 魔法护甲徽标墨=HERO_BLUE_BRIGHT" | sb_src.contains("col = UiKit.HERO_BLUE_BRIGHT") | (待填) | | | -| 1518 | 692 | "V4 重甲徽标墨=GOLD_BRIGHT" | sb_src.contains("col = UiKit.GOLD_BRIGHT") | (待填) | | | -| 1519 | 693 | "V4 意图蓄力档判据=分档布尔(standee_body:179 CHARGE_SKILL_IDS 判定;旧 GOLD_DEEP 恒不可达判据清零)〔wd2〕" | sb_src.contains("_intent_charge = pid in CHARGE_SKILL_IDS") and not sb_src.contains("if _intent_col == UiKit.GOLD_DEEP:") | (待填) | | | -| 1520 | 696 | "V4 RAP 反馈行墨=STONE_DEEP(原位行锚定)" | ap_src.contains('UiKit.label("",UiKit.FS_CAPTION, false, UiKit.STONE_DEEP)') | (待填) | | | -| 1521 | 698 | "V4 RAP 反馈行旧墨 STONE_FAINT 清零(含注记面)" | not ap_src.contains("STONE_FAINT") | (待填) | | | +| 1508 | 632 | "V3 工程设置 default_texture_filter=0(Nearest,翻转面=立绘/瓦片/九宫格 crisp)" | v != null and int(v) == 0 | (待填) | | | +| 1509 | 636 | "V3 白名单在位:暗角 vignette 显式 LINEAR" | vg.texture_filter == CanvasItem.TEXTURE_FILTER_LINEAR | (待填) | | | +| 1510 | 640 | "V3 白名单在位:光柱 beams 显式 LINEAR" | bm.texture_filter == CanvasItem.TEXTURE_FILTER_LINEAR | (待填) | | | +| 1511 | 658 | "T4 光柱带心峰值 α≈0.05(8bit 截断量化下限 12/255,实测 %.5f)" ↩ % max_a | max_a >= 12.0 / 255.0 and max_a <= 0.05 | (待填) | | | +| 1512 | 660 | "T4 光柱带内连续 alpha 过渡像素 %d 个(旧零过渡硬边已修)" ↩ % mid_a | mid_a > 100 | (待填) | | | +| 1513 | 661 | "T4 光柱纵向衰减生效(上半亮度 %.0f > 下半 %.0f 的 2 倍——上亮下暗)" ↩ % [top_sum, bot_sum] | top_sum > bot_sum * 2.0 | (待填) | | | +| 1514 | 665 | "V3 白名单在位:地图渐变 gradient_base 显式 LINEAR" | gb.texture_filter == CanvasItem.TEXTURE_FILTER_LINEAR | (待填) | | | +| 1515 | 670 | "V3 脚影显式 LINEAR 不丢(board_world.gd)" | bw_src.contains("shadow.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR") | (待填) | | | +| 1516 | 673 | "V3 状态图标显式 LINEAR 不丢(status_slot_row.gd)" | ss_src.contains("icon.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR") | (待填) | | | -## S199 _smoke_element_details(行 707–726 · 8 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) +## S199 _smoke_contrast_inks(行 683–699 · 9 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1522 | 707 | "T5② BCard 图标槽白图标对比 %.2f:1 ≥3:1(硬约束)" ↩ % r_white | r_white >= 3.0 | (待填) | | | -| 1523 | 710 | "T5② 明度差降档生效(槽对卡面 %.2f:1 < 旧 %.2f:1)" ↩ % [r_new, r_old] | r_new < r_old | (待填) | | | -| 1524 | 712 | "T5② BCard 图标槽落柔和档(SLOT_BACKDROP_SOFT)" | uk_src.contains("UiKit.panel_flat(SLOT_BACKDROP_SOFT, PANEL_BORDER, 0, 1)") | (待填) | | | -| 1525 | 715 | "T5② B 区状态图标槽仍用深档(SLOT_BACKDROP,未误伤)" | ss_src.contains("UiKit.SLOT_BACKDROP") | (待填) | | | -| 1526 | 719 | "T5③ 商店卡片区垂直居中(ALIGNMENT_CENTER)" | shop_src.contains("_cards_box.alignment = BoxContainer.ALIGNMENT_CENTER") | (待填) | | | -| 1527 | 723 | "T5③ 营地三 holder 统一 min 高 336(实测 %d 处)" ↩ % camp_min | camp_min == 3 | (待填) | | | -| 1528 | 725 | "T5③ 营地四栏面板纵向 FILL 等高(实测 %d 处)" ↩ % camp_fill | camp_fill == 4 | (待填) | | | -| 1529 | 726 | "T5③ 三处锁文垂直居中在位" | camp_src.count("SIZE_SHRINK_CENTER") >= 3 | (待填) | | | +| 1517 | 683 | "V4 顺位徽标/重甲徽标 GOLD_BRIGHT 对舞台底 %.2f:1 ≥4.5:1" ↩ % r_order | r_order >= 4.5 | (待填) | | | +| 1518 | 685 | "V4 魔法护甲徽标 HERO_BLUE_BRIGHT 对舞台底 %.2f:1 ≥4.5:1" ↩ % r_ward | r_ward >= 4.5 | (待填) | | | +| 1519 | 687 | "V4 RAP 反馈行 STONE_DEEP 对数据板 %.2f:1 ≥4.5:1" ↩ % r_rap | r_rap >= 4.5 | (待填) | | | +| 1520 | 690 | "V4 顺位徽标①②③ 墨=GOLD_BRIGHT(13px 行原位)" | sb_src.contains("HORIZONTAL_ALIGNMENT_LEFT, -1, 13, UiKit.GOLD_BRIGHT") | (待填) | | | +| 1521 | 692 | "V4 魔法护甲徽标墨=HERO_BLUE_BRIGHT" | sb_src.contains("col = UiKit.HERO_BLUE_BRIGHT") | (待填) | | | +| 1522 | 693 | "V4 重甲徽标墨=GOLD_BRIGHT" | sb_src.contains("col = UiKit.GOLD_BRIGHT") | (待填) | | | +| 1523 | 694 | "V4 意图蓄力档判据=分档布尔(standee_body:179 CHARGE_SKILL_IDS 判定;旧 GOLD_DEEP 恒不可达判据清零)〔wd2〕" | sb_src.contains("_intent_charge = pid in CHARGE_SKILL_IDS") and not sb_src.contains("if _intent_col == UiKit.GOLD_DEEP:") | (待填) | | | +| 1524 | 697 | "V4 RAP 反馈行墨=STONE_DEEP(原位行锚定)" | ap_src.contains('UiKit.label("",UiKit.FS_CAPTION, false, UiKit.STONE_DEEP)') | (待填) | | | +| 1525 | 699 | "V4 RAP 反馈行旧墨 STONE_FAINT 清零(含注记面)" | not ap_src.contains("STONE_FAINT") | (待填) | | | -## S200 _smoke_diag_button_retired(行 733–746 · 7 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) +## S200 _smoke_element_details(行 708–727 · 8 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1530 | 733 | "V6 主区无 build_diag_button 调用残留(旧实现同批清理)" | not main_src.contains("build_diag_button") | (待填) | | | -| 1531 | 735 | "V6 转储入口连接随迁(组合根接浮窗 diagnose_requested 信号)" | main_src.contains("debug_overlay.diagnose_requested.connect(_on_diagnose_pressed)") | (待填) | | | -| 1532 | 737 | "V6 转储编排承接函数在位(dump_diagnosis 卡死取证保留)" | main_src.contains("func _on_diagnose_pressed()") | (待填) | | | -| 1533 | 740 | "V6 build_diag_button 工厂已退役(ui_assembler 零残留)" | not asm_src.contains("build_diag_button") | (待填) | | | -| 1534 | 743 | "V6 调试浮窗 diagnose_requested 信号在位" | dbg_src.contains("signal diagnose_requested") | (待填) | | | -| 1535 | 744 | "V6 浮窗转储钮外发方法在位(纯视图边界)" | dbg_src.contains("_emit_diagnose_requested") | (待填) | | | -| 1536 | 745 | "V6 浮窗诊断转储钮在位(玩家画面角落钮清零后唯一入口)" | dbg_src.contains('UiKit.button("转储")') | (待填) | | | +| 1526 | 708 | "T5② BCard 图标槽白图标对比 %.2f:1 ≥3:1(硬约束)" ↩ % r_white | r_white >= 3.0 | (待填) | | | +| 1527 | 711 | "T5② 明度差降档生效(槽对卡面 %.2f:1 < 旧 %.2f:1)" ↩ % [r_new, r_old] | r_new < r_old | (待填) | | | +| 1528 | 713 | "T5② BCard 图标槽落柔和档(SLOT_BACKDROP_SOFT)" | uk_src.contains("UiKit.panel_flat(SLOT_BACKDROP_SOFT, PANEL_BORDER, 0, 1)") | (待填) | | | +| 1529 | 716 | "T5② B 区状态图标槽仍用深档(SLOT_BACKDROP,未误伤)" | ss_src.contains("UiKit.SLOT_BACKDROP") | (待填) | | | +| 1530 | 720 | "T5③ 商店卡片区垂直居中(ALIGNMENT_CENTER)" | shop_src.contains("_cards_box.alignment = BoxContainer.ALIGNMENT_CENTER") | (待填) | | | +| 1531 | 724 | "T5③ 营地三 holder 统一 min 高 336(实测 %d 处)" ↩ % camp_min | camp_min == 3 | (待填) | | | +| 1532 | 726 | "T5③ 营地四栏面板纵向 FILL 等高(实测 %d 处)" ↩ % camp_fill | camp_fill == 4 | (待填) | | | +| 1533 | 727 | "T5③ 三处锁文垂直居中在位" | camp_src.count("SIZE_SHRINK_CENTER") >= 3 | (待填) | | | -## S201 _status_panel_projection(行 762–792 · 10 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) +## S201 _smoke_diag_button_retired(行 734–747 · 7 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1537 | 762 | "状态面板开层可见(open_status 直开——P4 甲零动效路径)" | po.visible | (待填) | | | -| 1538 | 763 | "余额徽投影 = 快照 balance 读数(sv4 回归锚)〔sv4〕" | String(po._balance_badge.value_label.text) == "钥石 77" | (待填) | | | -| 1539 | 765 | "属性行全值投影 = 契约4 钉值格式逐字(生命/上限/攻击/AC/GP 五现值)〔sv1〕" | String(po._attrs_label.text) == "生命 13/29 · 攻击 7 · 护甲 AC 11 · GP 41" | (待填) | | | -| 1540 | 767 | "秘宝行投影 = 受理序 join+已用件「(已用)」尾缀〔sv2〕" | String(po._curios_label.text) == "青苔密卷 · 锈蚀怀表(已用)" | (待填) | | | -| 1541 | 769 | "专长行投影 = 行串 join〔sv3〕" | String(po._feats_label.text) == "疼痛记忆 ×2 · 双管镐 ×1" | (待填) | | | -| 1542 | 776 | "面板子树零「道具工坊/天赋树」文案(跨关概览退役零残留)〔sv5〕" | stale == "" | (待填) | | | -| 1543 | 777 | "旧段成员退役(_workshop_holder/_tree_label 零残留——契约2 数据/成员层面清零)〔sv5〕" | po.get("_workshop_holder") == null and po.get("_tree_label") == null | (待填) | | | -| 1544 | 784 | "空秘宝态句=「未携带秘宝」〔sv2〕" | String(po2._curios_label.text) == "未携带秘宝" | (待填) | | | -| 1545 | 785 | "空专长态句=「未获专长」〔sv3〕" | String(po2._feats_label.text) == "未获专长" | (待填) | | | -| 1546 | 791 | "提示行=「查看本局冒险进度(只读)」(新定位换代)〔sv8〕" | hint_txt == "查看本局冒险进度(只读)" | (待填) | | | +| 1534 | 734 | "V6 主区无 build_diag_button 调用残留(旧实现同批清理)" | not main_src.contains("build_diag_button") | (待填) | | | +| 1535 | 736 | "V6 转储入口连接随迁(组合根接浮窗 diagnose_requested 信号)" | main_src.contains("debug_overlay.diagnose_requested.connect(_on_diagnose_pressed)") | (待填) | | | +| 1536 | 738 | "V6 转储编排承接函数在位(dump_diagnosis 卡死取证保留)" | main_src.contains("func _on_diagnose_pressed()") | (待填) | | | +| 1537 | 741 | "V6 build_diag_button 工厂已退役(ui_assembler 零残留)" | not asm_src.contains("build_diag_button") | (待填) | | | +| 1538 | 744 | "V6 调试浮窗 diagnose_requested 信号在位" | dbg_src.contains("signal diagnose_requested") | (待填) | | | +| 1539 | 745 | "V6 浮窗转储钮外发方法在位(纯视图边界)" | dbg_src.contains("_emit_diagnose_requested") | (待填) | | | +| 1540 | 746 | "V6 浮窗诊断转储钮在位(玩家画面角落钮清零后唯一入口)" | dbg_src.contains('UiKit.button("转储")') | (待填) | | | -## S202 _career_overlay_projection(行 837–872 · 8 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) +## S202 _status_panel_projection(行 763–793 · 10 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1547 | 837 | "生涯页开层可见(open_career 直开——零动效路径)" | co.visible | (待填) | | | -| 1548 | 838 | "总局数投影 = adventure_total() 读数(%s)" ↩ % co._total_label.text | String(co._total_label.text) == "2 局" | (待填) | | | -| 1549 | 840 | "通关局数投影 = adventure_cleared() 读数(%s)" ↩ % co._cleared_label.text | String(co._cleared_label.text) == "1 局(三关全通)" | (待填) | | | -| 1550 | 845 | "各关通关次数投影 = clear_count() 逐关读数(%s)" ↩ % co._clears_label.text | String(co._clears_label.text) == " · ".join(expect_clears) | (待填) | | | -| 1551 | 847 | "Boss 首杀/总杀投影 = 首杀标记计数 + boss_kill_count()(%s / %s)" ↩ % [co._boss_first_label.text, co._boss_kills_label.text] | String(co._boss_first_label.text) == "3/3 关" and String(co._boss_kills_label.text) == "4 次" | (待填) | | | -| 1552 | 849 | "钥石余额徽投影 = keystone_balance() 读数(%s)" ↩ % co._keystone_badge.value_label.text | String(co._keystone_badge.value_label.text) == "钥石 %d" % mp.keystone_balance() | (待填) | | | -| 1553 | 858 | "v5 现役档升 v6 载入成功(计数域缺省补零)" | v5.load_from_disk() and v5.adventure_total() == 0 and v5.adventure_cleared() == 0 | (待填) | | | -| 1554 | 869 | "旧档载入后生涯页正常显示(v5 升 v6:总局数/通关局数显示 0,既有钥石余额原样呈现)" | co_v5.visible and String(co_v5._total_label.text) == "0 局" \\ and String(co_v5._cleared_label.text) == "0 局(三关全通)" \\ and String(co_v5._keystone_badge.value_label.text) == "钥石 3" | (待填) | | | +| 1541 | 763 | "状态面板开层可见(open_status 直开——P4 甲零动效路径)" | po.visible | (待填) | | | +| 1542 | 764 | "余额徽投影 = 快照 balance 读数(sv4 回归锚)〔sv4〕" | String(po._balance_badge.value_label.text) == "钥石 77" | (待填) | | | +| 1543 | 766 | "属性行全值投影 = 契约4 钉值格式逐字(生命/上限/攻击/AC/GP 五现值)〔sv1〕" | String(po._attrs_label.text) == "生命 13/29 · 攻击 7 · 护甲 AC 11 · GP 41" | (待填) | | | +| 1544 | 768 | "秘宝行投影 = 受理序 join+已用件「(已用)」尾缀〔sv2〕" | String(po._curios_label.text) == "青苔密卷 · 锈蚀怀表(已用)" | (待填) | | | +| 1545 | 770 | "专长行投影 = 行串 join〔sv3〕" | String(po._feats_label.text) == "疼痛记忆 ×2 · 双管镐 ×1" | (待填) | | | +| 1546 | 777 | "面板子树零「道具工坊/天赋树」文案(跨关概览退役零残留)〔sv5〕" | stale == "" | (待填) | | | +| 1547 | 778 | "旧段成员退役(_workshop_holder/_tree_label 零残留——契约2 数据/成员层面清零)〔sv5〕" | po.get("_workshop_holder") == null and po.get("_tree_label") == null | (待填) | | | +| 1548 | 785 | "空秘宝态句=「未携带秘宝」〔sv2〕" | String(po2._curios_label.text) == "未携带秘宝" | (待填) | | | +| 1549 | 786 | "空专长态句=「未获专长」〔sv3〕" | String(po2._feats_label.text) == "未获专长" | (待填) | | | +| 1550 | 792 | "提示行=「查看本局冒险进度(只读)」(新定位换代)〔sv8〕" | hint_txt == "查看本局冒险进度(只读)" | (待填) | | | -## S203 _test_grouping_closed(行 61–79 · 7 条 · 源 game/tests/unit/presentation/type_glow_test.gd · 去向:待分类回填) +## S203 _camp_recent_projection(行 818–819 · 1 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1555 | 61 | "九型封闭:%s → 组%d(期望组%d)" ↩ % [t, got, int(TYPE_EXPECT[t])] | got == int(TYPE_EXPECT[t]) | (待填) | | | -| 1556 | 65 | "清单外值「%s」→ GLOW_NONE(禁静默空光)" ↩ % bad | UiKitScript.glow_group_for_cell_type(bad) == UiKitScript.GLOW_NONE | (待填) | | | -| 1557 | 70 | "两带并存锚定:卡顶带 blast→TG_MAGIC(E5 回滚既存行为未动)" | band_blast == UiKitScript.TG_MAGIC | (待填) | | | -| 1558 | 71 | "两带并存锚定:格面微光 blast→群伤组(与卡顶带刻意不同)" | UiKitScript.glow_group_for_cell_type("blast") == UiKitScript.GLOW_AOE | (待填) | | | -| 1559 | 74 | "glow_color_for_group 群伤组 = TG_GLOW_AOE" | UiKitScript.glow_color_for_group(UiKitScript.GLOW_AOE) == UiKitScript.TG_GLOW_AOE | (待填) | | | -| 1560 | 76 | "glow_color_for_group 无组(GLOW_NONE)→ 全透明" | UiKitScript.glow_color_for_group(UiKitScript.GLOW_NONE) == Color(0, 0, 0, 0) | (待填) | | | -| 1561 | 78 | "glow_color_for_group 越界组号 → 全透明" | UiKitScript.glow_color_for_group(99) == Color(0, 0, 0, 0) | (待填) | | | +| 1551 | 818 | "营地最近冒险行完成关数措辞(实际「%s」)〔口径换代 V6〕" ↩ % recent_text | recent_text.contains("完成 2 关") and not recent_text.contains("通关") | (待填) | | | -## S204 _test_frozen_hue_face(行 88–102 · 5 条 · 源 game/tests/unit/presentation/type_glow_test.gd · 去向:待分类回填) +## S204 _career_overlay_projection(行 852–897 · 11 条 · 源 game/tests/unit/presentation/theme_projection_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1562 | 88 | "实现值锚定:%s = #%02X%02X%02X(色值单点 ui_kit,逐位钉死)" ↩ % [CONST_NAME[g], int(m.r8), int(m.g8), int(m.b8)] | impl_const == m | (待填) | | | -| 1563 | 93 | "冻结色相保持:%s ΔH=%.3f° ≤0.2° 且 ΔS=%.4f ≤0.01(只动明度档)" ↩ % [g, dh * 360.0, ds] | dh <= 0.2 / 360.0 and ds <= 0.01 | (待填) | | | -| 1564 | 98 | "群伤组专项:H 与冻结 #FF2D55 差 %.4f°(零移动)" ↩ % (absf(aoe_m.h - aoe_f.h) * 360.0) | absf(aoe_m.h - aoe_f.h) < 0.001 | (待填) | | | -| 1565 | 100 | "群伤组专项:S 与冻结差 %.4f ≤0.01(8bit 量化噪声级)" ↩ % absf(aoe_m.s - aoe_f.s) | absf(aoe_m.s - aoe_f.s) <= 0.01 | (待填) | | | -| 1566 | 102 | "群伤组专项:V=0.65 明度档( provisional 域内)" | absf(aoe_m.v - 166.0 / 255.0) < 0.002 | (待填) | | | +| 1552 | 852 | "生涯页开层可见(open_career 直开——零动效路径)" | co.visible | (待填) | | | +| 1553 | 853 | "总局数投影 = adventure_total() 读数(%s)" ↩ % co._total_label.text | String(co._total_label.text) == "2 局" | (待填) | | | +| 1554 | 855 | "冒险成功局数投影 = adventure_cleared() 读数(%s)" ↩ % co._cleared_label.text | String(co._cleared_label.text) == "1 局(三关全通)" | (待填) | | | +| 1555 | 860 | "各关完成次数投影 = clear_count() 逐关读数(%s)" ↩ % co._clears_label.text | String(co._clears_label.text) == " · ".join(expect_clears) | (待填) | | | +| 1556 | 862 | "Boss 首杀/总杀投影 = 首杀标记计数 + boss_kill_count()(%s / %s)" ↩ % [co._boss_first_label.text, co._boss_kills_label.text] | String(co._boss_first_label.text) == "3/3 关" and String(co._boss_kills_label.text) == "4 次" | (待填) | | | +| 1557 | 864 | "钥石余额徽投影 = keystone_balance() 读数(%s)" ↩ % co._keystone_badge.value_label.text | String(co._keystone_badge.value_label.text) == "钥石 %d" % mp.keystone_balance() | (待填) | | | +| 1558 | 871 | "生涯页行标签换代(冒险成功局数/各关完成次数)〔口径换代 V4〕" | career_labels_joined.contains("冒险成功局数") and career_labels_joined.contains("各关完成次数") | (待填) | | | +| 1559 | 873 | "生涯页 label 全集零「通关」残留〔口径换代 V4〕" | not career_labels_joined.contains("通关") | (待填) | | | +| 1560 | 874 | "秘宝解锁条件标签冒险成功口径(UiKit 单点常量)〔口径换代 V5〕" | UiKit.TREASURE_REQ_LABELS["adventure_cleared"] == "冒险成功" | (待填) | | | +| 1561 | 883 | "v5 现役档升 v6 载入成功(计数域缺省补零)" | v5.load_from_disk() and v5.adventure_total() == 0 and v5.adventure_cleared() == 0 | (待填) | | | +| 1562 | 894 | "旧档载入后生涯页正常显示(v5 升 v6:总局数/冒险成功局数显示 0,既有钥石余额原样呈现)" | co_v5.visible and String(co_v5._total_label.text) == "0 局" \\ and String(co_v5._cleared_label.text) == "0 局(三关全通)" \\ and String(co_v5._keystone_badge.value_label.text) == "钥石 3" | (待填) | | | -## S205 _test_render_params(行 107–113 · 3 条 · 源 game/tests/unit/presentation/type_glow_test.gd · 去向:待分类回填) +## S205 _test_grouping_closed(行 61–79 · 7 条 · 源 game/tests/unit/presentation/type_glow_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1567 | 107 | "泛光强度 α = 170/255(v2 呈现参数冻结)" | is_equal_approx(UiKitScript.TYPE_GLOW_ALPHA, 170.0 / 255.0) | (待填) | | | -| 1568 | 109 | "带宽 = cell÷8(TYPE_GLOW_BAND_FRAC=0.125)" | is_equal_approx(UiKitScript.TYPE_GLOW_BAND_FRAC, 0.125) | (待填) | | | -| 1569 | 111 | "组号常量域连续(GLOW_NONE=0…GLOW_MAGIC=5)" | UiKitScript.GLOW_NONE == 0 and UiKitScript.GLOW_BUFF == 1 and UiKitScript.GLOW_HEAL == 2 and UiKitScript.GLOW_PIERCE == 3 and UiKitScript.GLOW_AOE == 4 and UiKitScript.GLOW_MAGIC == 5 | (待填) | | | +| 1563 | 61 | "九型封闭:%s → 组%d(期望组%d)" ↩ % [t, got, int(TYPE_EXPECT[t])] | got == int(TYPE_EXPECT[t]) | (待填) | | | +| 1564 | 65 | "清单外值「%s」→ GLOW_NONE(禁静默空光)" ↩ % bad | UiKitScript.glow_group_for_cell_type(bad) == UiKitScript.GLOW_NONE | (待填) | | | +| 1565 | 70 | "两带并存锚定:卡顶带 blast→TG_MAGIC(E5 回滚既存行为未动)" | band_blast == UiKitScript.TG_MAGIC | (待填) | | | +| 1566 | 71 | "两带并存锚定:格面微光 blast→群伤组(与卡顶带刻意不同)" | UiKitScript.glow_group_for_cell_type("blast") == UiKitScript.GLOW_AOE | (待填) | | | +| 1567 | 74 | "glow_color_for_group 群伤组 = TG_GLOW_AOE" | UiKitScript.glow_color_for_group(UiKitScript.GLOW_AOE) == UiKitScript.TG_GLOW_AOE | (待填) | | | +| 1568 | 76 | "glow_color_for_group 无组(GLOW_NONE)→ 全透明" | UiKitScript.glow_color_for_group(UiKitScript.GLOW_NONE) == Color(0, 0, 0, 0) | (待填) | | | +| 1569 | 78 | "glow_color_for_group 越界组号 → 全透明" | UiKitScript.glow_color_for_group(99) == Color(0, 0, 0, 0) | (待填) | | | -## S206 _test_gamma_ladder(行 128–139 · 3 条 · 源 game/tests/unit/presentation/type_glow_test.gd · 去向:待分类回填) +## S206 _test_frozen_hue_face(行 88–102 · 5 条 · 源 game/tests/unit/presentation/type_glow_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1570 | 128 | "阶梯单调:%s 合成亮度 %.4f < 上一档 %.4f(伽马合成空间)" ↩ % [g, lum, prev_lum] | lum < prev_lum | (待填) | | | -| 1571 | 134 | "相邻组模型 CR:%s/%s = %.3f ≥1.20(色弱互辨预判)" ↩ % [order[i], order[i + 1], cr] | cr >= 1.20 | (待填) | | | -| 1572 | 138 | "群伤/魔法线性亮度序:群伤 %.4f < 魔法 %.4f(首版 CIE L* 排反事故的守门)" ↩ % [aoe_lin, magic_lin] | aoe_lin < magic_lin | (待填) | | | +| 1570 | 88 | "实现值锚定:%s = #%02X%02X%02X(色值单点 ui_kit,逐位钉死)" ↩ % [CONST_NAME[g], int(m.r8), int(m.g8), int(m.b8)] | impl_const == m | (待填) | | | +| 1571 | 93 | "冻结色相保持:%s ΔH=%.3f° ≤0.2° 且 ΔS=%.4f ≤0.01(只动明度档)" ↩ % [g, dh * 360.0, ds] | dh <= 0.2 / 360.0 and ds <= 0.01 | (待填) | | | +| 1572 | 98 | "群伤组专项:H 与冻结 #FF2D55 差 %.4f°(零移动)" ↩ % (absf(aoe_m.h - aoe_f.h) * 360.0) | absf(aoe_m.h - aoe_f.h) < 0.001 | (待填) | | | +| 1573 | 100 | "群伤组专项:S 与冻结差 %.4f ≤0.01(8bit 量化噪声级)" ↩ % absf(aoe_m.s - aoe_f.s) | absf(aoe_m.s - aoe_f.s) <= 0.01 | (待填) | | | +| 1574 | 102 | "群伤组专项:V=0.65 明度档( provisional 域内)" | absf(aoe_m.v - 166.0 / 255.0) < 0.002 | (待填) | | | -## S207 _test_probe_api_shape(行 146–153 · 5 条 · 源 game/tests/unit/presentation/type_glow_test.gd · 去向:待分类回填) +## S207 _test_render_params(行 107–113 · 3 条 · 源 game/tests/unit/presentation/type_glow_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1573 | 146 | "probe 键集 = {enabled, cells, errors}" | snap.has("enabled") and snap.has("cells") and snap.has("errors") and snap.size() == 3 | (待填) | | | -| 1574 | 148 | "probe 默认态:enabled=true(Q4 丙案生产默认开)" | bool(snap.get("enabled", false)) | (待填) | | | -| 1575 | 149 | "probe 默认态:作用集空(无板未派生)" | (snap.get("cells", {}) as Dictionary).is_empty() | (待填) | | | -| 1576 | 150 | "probe 默认态:清单外登记空" | (snap.get("errors", []) as Array).is_empty() | (待填) | | | -| 1577 | 152 | "set_type_glow_enabled(false) → probe enabled=false(无板不崩)" | not bool(view.type_glow_probe().get("enabled", true)) | (待填) | | | +| 1575 | 107 | "泛光强度 α = 170/255(v2 呈现参数冻结)" | is_equal_approx(UiKitScript.TYPE_GLOW_ALPHA, 170.0 / 255.0) | (待填) | | | +| 1576 | 109 | "带宽 = cell÷8(TYPE_GLOW_BAND_FRAC=0.125)" | is_equal_approx(UiKitScript.TYPE_GLOW_BAND_FRAC, 0.125) | (待填) | | | +| 1577 | 111 | "组号常量域连续(GLOW_NONE=0…GLOW_MAGIC=5)" | UiKitScript.GLOW_NONE == 0 and UiKitScript.GLOW_BUFF == 1 and UiKitScript.GLOW_HEAL == 2 and UiKitScript.GLOW_PIERCE == 3 and UiKitScript.GLOW_AOE == 4 and UiKitScript.GLOW_MAGIC == 5 | (待填) | | | -## S208 _init(行 16–28 · 6 条 · 源 game/tests/unit/presentation/ui_font_asset_test.gd · 去向:待分类回填) +## S208 _test_gamma_ladder(行 128–139 · 3 条 · 源 game/tests/unit/presentation/type_glow_test.gd · 去向:待分类回填) | 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | |---|---|---|---|---|---|---| -| 1578 | 16 | "随包字体守卫装载非空(res://assets/fonts/ui_font_fusion_pixel_zh_hans.ttf)" | f != null | (待填) | | | -| 1579 | 18 | "中文字形在集(攻/雷/旗/封)" | f.has_char("攻".unicode_at(0)) and f.has_char("雷".unicode_at(0)) \\ and f.has_char("旗".unicode_at(0)) and f.has_char("封".unicode_at(0)) | (待填) | | | -| 1580 | 20 | "中文字形在集(危——已开危险格字形换代前置,迭代36 u12/wa9)" | f.has_char("危".unicode_at(0)) | (待填) | | | -| 1581 | 21 | "ASCII/数字字形在集(A/0/%)" | f.has_char("A".unicode_at(0)) and f.has_char("0".unicode_at(0)) and f.has_char("%".unicode_at(0)) | (待填) | | | -| 1582 | 25 | "中文采样文本宽度 > 0(C6 headless 判据)" | w_cn > 0.0 and w_label > 0.0 | (待填) | | | -| 1583 | 28 | "字体缺失时后续断言跳过(缺位=回归,此行仅占位计数)" | false | (待填) | | | +| 1578 | 128 | "阶梯单调:%s 合成亮度 %.4f < 上一档 %.4f(伽马合成空间)" ↩ % [g, lum, prev_lum] | lum < prev_lum | (待填) | | | +| 1579 | 134 | "相邻组模型 CR:%s/%s = %.3f ≥1.20(色弱互辨预判)" ↩ % [order[i], order[i + 1], cr] | cr >= 1.20 | (待填) | | | +| 1580 | 138 | "群伤/魔法线性亮度序:群伤 %.4f < 魔法 %.4f(首版 CIE L* 排反事故的守门)" ↩ % [aoe_lin, magic_lin] | aoe_lin < magic_lin | (待填) | | | + +## S209 _test_probe_api_shape(行 146–153 · 5 条 · 源 game/tests/unit/presentation/type_glow_test.gd · 去向:待分类回填) + +| 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | +|---|---|---|---|---|---|---| +| 1581 | 146 | "probe 键集 = {enabled, cells, errors}" | snap.has("enabled") and snap.has("cells") and snap.has("errors") and snap.size() == 3 | (待填) | | | +| 1582 | 148 | "probe 默认态:enabled=true(Q4 丙案生产默认开)" | bool(snap.get("enabled", false)) | (待填) | | | +| 1583 | 149 | "probe 默认态:作用集空(无板未派生)" | (snap.get("cells", {}) as Dictionary).is_empty() | (待填) | | | +| 1584 | 150 | "probe 默认态:清单外登记空" | (snap.get("errors", []) as Array).is_empty() | (待填) | | | +| 1585 | 152 | "set_type_glow_enabled(false) → probe enabled=false(无板不崩)" | not bool(view.type_glow_probe().get("enabled", true)) | (待填) | | | + +## S210 _init(行 16–28 · 6 条 · 源 game/tests/unit/presentation/ui_font_asset_test.gd · 去向:待分类回填) + +| 序号 | 行号 | 标签原文 | cond 摘要 | 白话释义 | 处置 | quiet | +|---|---|---|---|---|---|---| +| 1586 | 16 | "随包字体守卫装载非空(res://assets/fonts/ui_font_fusion_pixel_zh_hans.ttf)" | f != null | (待填) | | | +| 1587 | 18 | "中文字形在集(攻/雷/旗/封)" | f.has_char("攻".unicode_at(0)) and f.has_char("雷".unicode_at(0)) \\ and f.has_char("旗".unicode_at(0)) and f.has_char("封".unicode_at(0)) | (待填) | | | +| 1588 | 20 | "中文字形在集(危——已开危险格字形换代前置,迭代36 u12/wa9)" | f.has_char("危".unicode_at(0)) | (待填) | | | +| 1589 | 21 | "ASCII/数字字形在集(A/0/%)" | f.has_char("A".unicode_at(0)) and f.has_char("0".unicode_at(0)) and f.has_char("%".unicode_at(0)) | (待填) | | | +| 1590 | 25 | "中文采样文本宽度 > 0(C6 headless 判据)" | w_cn > 0.0 and w_label > 0.0 | (待填) | | | +| 1591 | 28 | "字体缺失时后续断言跳过(缺位=回归,此行仅占位计数)" | false | (待填) | | | --- -全源共 208 章、1583 条(静态调用点口径)。 +全源共 210 章、1591 条(静态调用点口径)。