工程(注释标记词换代·oracle→判据出处): 用户 2026-11-07 令——判据出处注记的标记词改用项目已有中文名,避免 Oracle 被读成数据库。注释格式句、机检正则、标识符、卡片与登记同步换代;零行为改动。

改动面 112 文件 572+/572-:game/tests/** 与 game/probe/** 共 106 件 545 行 `# oracle:`→`# 判据出处:`;tools/capability_audit.py 正则字面量换中文+ORACLE_*→CRITERION_*/check_oracle_markers→check_criterion_markers/oracle_marked(flagged)→criterion_* 共 11 行;test-conventions.md:119 格式句+:155 措辞;待办清单与需求卡片-QA覆盖余量收口批各 1 处字面量;coverage_enum.py:21 与 camp_scene_layout_test.gd:101 旁支措辞;ui_click_probe.gd 对拍局部变量 oracle→expected 7 处;auto_player.gd 三处 safe_set 真值措辞。不动:历史审计报告两份、test-oracle-anchor 分支名、git 史、生成日志;指针格式/扫描面/判红条件/验收义务全不变。

读数(区内实跑):改前 capability_audit --strict「417 注记函数·红项 0」→改后「417 判据出处注记函数·红项 0」exit=0;新标记 545 行/106 文件,现行义务面 oracle 残留 0(在册沿革除外);diff 自检 game/ 非注释新增行仅 6 行且全在 ui_click_probe.gd 的 expected 变量段;112 改动文件 CRLF=0;py_compile tools/capability_audit.py OK;--docs exit=0【验收通过】无新增红;--gates exit=0(静态扫描绿、闸壳 bash -n ×13 失败 0)。
This commit is contained in:
DKChan committed 2026-11-07 07:11:15 +08:00
1 parent 166114e094
commit 9f21236f80
112 files changed
+572 -572

No files matched your search

+3 -3
View File
@@ -26,7 +26,7 @@ var _cur_settlement = null # 当关 settlement(身份回调读取面——
func _ready() -> void:
# oracle: design/engineering/test-conventions.md:84 (棋盘截图取证——渲染闸采集组)
# 判据出处: design/engineering/test-conventions.md:84 (棋盘截图取证——渲染闸采集组)
# 运行前提=窗口化真渲染面(shot_probe 同款护栏——headless 下 frame_post_draw 永不触发+视口纹理恒空)
if DisplayServer.get_name() == "headless":
print("[board_shot] FAIL — 本探针必须窗口化运行(headless 无渲染面,截图必空);现行事实源=tools/render_gate.sh 取证段")
@@ -182,7 +182,7 @@ func _ready() -> void:
# 判据:环外径像素 ÷ 格边 落 0.82±1px;封印格最外圈 1px 框最暗值与相邻未封印未开格同位框最暗值差 ≤1/255
#(halo 在 0.455×格边归零——格边框不应被压暗;相邻未开格同砖纹理同套瓦片为无封印参照)。
func _seal_evidence(tag: String, view: Node, settlement: Object, off_img: Image, out: String) -> void:
# oracle: design/engineering/test-conventions.md:84 (封印印记像素取证组)
# 判据出处: design/engineering/test-conventions.md:84 (封印印记像素取证组)
var ms = settlement.minesweeper
var seal_cell := Vector2i(-9, -9)
var ref_cell := Vector2i(-9, -9)
@@ -290,7 +290,7 @@ func _probe_identity_lookup(c: Vector2i):
# 双帧逐像素比对:所有变化像素必须落在生效格的内缘带内
# (de < cell÷8——带外含砖心零侵入=禁整格染色/禁越圈);每个生效格须有实绘像素(不空转)。
func _check_dual_frames(tag: String, view, glow_cells: Dictionary, off_img: Image, on_img: Image) -> void:
# oracle: design/engineering/test-conventions.md:56 (判定上报通道——验证函数组)
# 判据出处: design/engineering/test-conventions.md:56 (判定上报通道——验证函数组)
var board = view.board()
if board == null:
_problems.append("%s 双帧比对取板失败(view.board() 为 null)" % tag)
+1 -1
View File
@@ -8,7 +8,7 @@ extends Node
func _ready() -> void:
# oracle: design/gdd/systems/战斗循环/战斗表现.md:148 (结算演出——挖掘期零打扰组)
# 判据出处: design/gdd/systems/战斗循环/战斗表现.md:148 (结算演出——挖掘期零打扰组)
await get_tree().process_frame
var problems: Array = []
+3 -3
View File
@@ -21,7 +21,7 @@ var _problems: Array = []
func _ready() -> void:
# oracle: design/engineering/test-conventions.md:84 (特效截图取证——渲染闸采集组)
# 判据出处: design/engineering/test-conventions.md:84 (特效截图取证——渲染闸采集组)
var args := OS.get_cmdline_user_args()
out_dir = args[0] if args.size() >= 1 and args[0] != "" else "user://qa-fx"
DirAccess.make_dir_recursive_absolute(out_dir)
@@ -108,7 +108,7 @@ func _ready() -> void:
func _snap(tag: String) -> void:
# oracle: design/engineering/test-conventions.md:56 (判定上报通道——验证函数组)
# 判据出处: design/engineering/test-conventions.md:56 (判定上报通道——验证函数组)
await RenderingServer.frame_post_draw
var img: Image = get_viewport().get_texture().get_image()
if img == null or img.is_empty():
@@ -118,7 +118,7 @@ func _snap(tag: String) -> void:
func _fail(msg: String) -> void:
# oracle: design/engineering/test-conventions.md:56 (判定上报通道——验证函数组)
# 判据出处: design/engineering/test-conventions.md:56 (判定上报通道——验证函数组)
_problems.append(msg)
push_error("[fx_shot_probe] FAIL — " + msg)
get_tree().quit(1)
+2 -2
View File
@@ -19,7 +19,7 @@ var _est_reads: Dictionary = {} # 逐档 13/14 板推定读数留痕(label
func _ready() -> void:
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:264 (战斗屏三区几何与棋盘格边长——分辨率档位组)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:264 (战斗屏三区几何与棋盘格边长——分辨率档位组)
await get_tree().process_frame
var main: Node = load("res://presentation/main.tscn").instantiate()
add_child(main)
@@ -59,7 +59,7 @@ func _ready() -> void:
# 一份不变量断言,逐档代入——代码量与档数无关
func _check_one(label: String, main: Node) -> void:
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:264 (单档几何断言组)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:264 (单档几何断言组)
var vr: Rect2 = get_viewport().get_visible_rect()
if vr.size != Vector2(VIEWPORTS[0]["size"]) and vr.size.y < 1.0:
_problems.append("[%s] 逻辑视口退化 %s" % [label, vr.size])
+3 -3
View File
@@ -11,7 +11,7 @@ extends Node
const SEED_L3 := 910212 # 深图固定种子(与 level_map_viewport_probe 同源——图确定性承载)
func _ready() -> void:
# oracle: design/engineering/test-conventions.md:84 (关卡画面截图取证——载入守卫组)
# 判据出处: design/engineering/test-conventions.md:84 (关卡画面截图取证——载入守卫组)
var args := OS.get_cmdline_user_args()
var out_dir := args[0] if args.size() > 0 else "user://"
await get_tree().process_frame
@@ -45,7 +45,7 @@ func _settle() -> void:
func _make_runner(entry: bool, node_id: int):
# oracle: design/engineering/test-conventions.md:84 (判定上报通道——验证函数组)
# 判据出处: design/engineering/test-conventions.md:84 (判定上报通道——验证函数组)
var rng = load("res://core/rng_service.gd").new()
rng.new_adventure(SEED_L3)
var runner = load("res://core/level_runner.gd").new(get_node("/root/ConfigDB"), rng)
@@ -85,7 +85,7 @@ func _deepest_with_outs(screen, runner) -> int:
func _shot(out_dir: String, fname: String) -> void:
# oracle: design/engineering/test-conventions.md:84 (判定上报通道——验证函数组)
# 判据出处: design/engineering/test-conventions.md:84 (判定上报通道——验证函数组)
DirAccess.make_dir_recursive_absolute(out_dir) # 落盘目录自建(save_png 对缺目录静默失败——刷新链不预建)
var img := get_viewport().get_texture().get_image()
var err := img.save_png(out_dir.path_join(fname))
+11 -11
View File
@@ -22,14 +22,14 @@ var _runner # 当前停点的单关 runner(open_choices 驱动随记——
func _check(desc: String, ok: bool) -> void:
# oracle: design/ux/level-map.md:3 (判定上报通道——验证函数组)
# 判据出处: design/ux/level-map.md:3 (判定上报通道——验证函数组)
_checks += 1
if not ok:
_problems.append(desc)
func _ready() -> void:
# oracle: design/ux/level-map.md:3 (关卡画面视口跟随——卷轴视口组)
# 判据出处: design/ux/level-map.md:3 (关卡画面视口跟随——卷轴视口组)
await get_tree().process_frame
await get_tree().process_frame
var host := Control.new()
@@ -62,7 +62,7 @@ func _ready() -> void:
## R1 浅图整幅居中无裁切+画布入视口件承载(画布=视口首子件——setup 注入序)
func _probe_shallow_no_crop(screen, vp) -> void:
# oracle: design/ux/level-map.md:3 (浅层不裁切组)
# 判据出处: design/ux/level-map.md:3 (浅层不裁切组)
_runner = _make_runner_entry(1, SEED_L1)
screen.open_choices(_cand_nodes(_runner), _runner)
await get_tree().process_frame
@@ -81,7 +81,7 @@ func _probe_shallow_no_crop(screen, vp) -> void:
## R5 前置+深图入口停点:锚点=入口组包围盒中心夹紧(spec :101——多入口并列取包围盒居中)
func _probe_deep_entry_clamp(screen, vp) -> void:
# oracle: design/ux/level-map.md:3 (深层入口钳制组)
# 判据出处: design/ux/level-map.md:3 (深层入口钳制组)
_runner = _make_runner_entry(3, SEED_L3)
screen.open_choices(_cand_nodes(_runner), _runner)
await get_tree().process_frame
@@ -175,7 +175,7 @@ func _probe_clamp_bounds_and_columns(screen, vp) -> void:
## R6 拖拽不触发选路提交;阈值另一侧完整点击仍提交(提交语义零改动)
func _probe_drag_no_submit(screen, vp) -> void:
# oracle: design/ux/level-map.md:3 (判定上报通道——验证函数组)
# 判据出处: design/ux/level-map.md:3 (判定上报通道——验证函数组)
# 重建到中段可居中停点(候选=停点出边——候选节点居屏中可拖可达)
var stops := _centerable_stops(screen, vp)
if stops.size() < 3:
@@ -214,7 +214,7 @@ func _probe_drag_no_submit(screen, vp) -> void:
## R2 停点切换后当前节点居中(视口中线投影 x=640±2——视口满屏宽即屏中线)
func _probe_follow_anchor(screen, vp) -> void:
# oracle: design/ux/level-map.md:3 (判定上报通道——验证函数组)
# 判据出处: design/ux/level-map.md:3 (判定上报通道——验证函数组)
var stops := _centerable_stops(screen, vp)
if stops.size() < 3:
_problems.append("R2 可居中停点不足(=%d)" % stops.size())
@@ -230,7 +230,7 @@ func _probe_follow_anchor(screen, vp) -> void:
## R7 平滑滚动有 tween 中间帧;减动效开=位置即达(画布坐标域判定)
func _probe_smooth_scroll_reduced_motion(screen, vp) -> void:
# oracle: design/ux/level-map.md:3 (判定上报通道——验证函数组)
# 判据出处: design/ux/level-map.md:3 (判定上报通道——验证函数组)
var saved_scale: float = UiKit.motion_scale
UiKit.motion_scale = 1.0
var stops := _centerable_stops(screen, vp)
@@ -270,7 +270,7 @@ func _probe_smooth_scroll_reduced_motion(screen, vp) -> void:
## R8 指引件可见性与几何(深图超窗——像素级判据②③)
func _probe_guidance_chrome(screen, vp) -> void:
# oracle: design/ux/level-map.md:3 (判定上报通道——验证函数组)
# 判据出处: design/ux/level-map.md:3 (判定上报通道——验证函数组)
var band_l: Control = vp.get_node_or_null(NodePath("FadeL"))
var band_r: Control = vp.get_node_or_null(NodePath("FadeR"))
var chip: Control = vp.get_node_or_null(NodePath("PanHint"))
@@ -302,7 +302,7 @@ func _probe_shallow_guidance_hidden(screen, vp) -> void:
## 入口停点 runner(defer_entry——选路态挂起、候选=入口节点)
func _make_runner_entry(level_index: int, seed_val: int):
# oracle: design/ux/level-map.md:3 (判定上报通道——验证函数组)
# 判据出处: design/ux/level-map.md:3 (判定上报通道——验证函数组)
var rng = load("res://core/rng_service.gd").new()
rng.new_adventure(seed_val)
var runner = load("res://core/level_runner.gd").new(get_node("/root/ConfigDB"), rng)
@@ -313,7 +313,7 @@ func _make_runner_entry(level_index: int, seed_val: int):
## 中段停点 runner(断点续玩重建——图由种子+参数档重生成同图,零 RNG 消耗)
func _make_runner_at_stop(level_index: int, seed_val: int, node_id: int):
# oracle: design/ux/level-map.md:3 (判定上报通道——验证函数组)
# 判据出处: design/ux/level-map.md:3 (判定上报通道——验证函数组)
var rng = load("res://core/rng_service.gd").new()
rng.new_adventure(seed_val)
var runner = load("res://core/level_runner.gd").new(get_node("/root/ConfigDB"), rng)
@@ -388,7 +388,7 @@ func _extreme_node(pos: Dictionary, nodes: Array, first: bool) -> Dictionary:
func _finish() -> void:
# oracle: design/ux/level-map.md:3 (判定上报通道——验证函数组)
# 判据出处: design/ux/level-map.md:3 (判定上报通道——验证函数组)
if _checks == 0:
_problems.append("零断言执行(断言数下限闸——三硬闸③)")
if _problems.is_empty():
+1 -1
View File
@@ -199,7 +199,7 @@ func _seen_into(node: Node, keys: Array[String]) -> void:
# ---- 落盘(JSONP 式 .js——file:// 页面 <script src> 直载)----
func dump_js() -> void:
# oracle: design/engineering/test-conventions.md:30 (覆盖登记落盘守卫——判定上报通道组)
# 判据出处: design/engineering/test-conventions.md:30 (覆盖登记落盘守卫——判定上报通道组)
var dir := DirAccess.open("res://")
if dir == null:
push_error("[coverage] res:// 打不开,登记未落盘")
+13 -13
View File
@@ -76,14 +76,14 @@ func _seals_text(f: Dictionary) -> String:
# ---- 流程状态位(与可见性是两回事,逐步单独判)----
func _expect_adventure_seal(step: String, expect: bool) -> void:
# oracle: design/engineering/architecture/architecture.md:168 (状态位判据组)
# 判据出处: design/engineering/architecture/architecture.md:168 (状态位判据组)
var got: bool = main.run_scope != null and main.run_scope.is_adventure
if got != expect:
_problems.append("%s:流程状态位 is_adventure 应为 %s,实测 %s" % [step, str(expect), str(got)])
func _expect_exclusive(step: String, expect: String) -> void:
# oracle: design/engineering/architecture/architecture.md:168 (屏级互斥组)
# 判据出处: design/engineering/architecture/architecture.md:168 (屏级互斥组)
var f: Dictionary = _screen_seals()
var pairs := [["菜单", "营地"], ["菜单", "冒险"], ["营地", "冒险"], ["终局", "营地"], ["终局", "菜单"]]
for pair in pairs:
@@ -110,7 +110,7 @@ func _frames(n: int = 2) -> void:
# ---- ① boot:菜单独占 ----
func _step_boot_menu() -> void:
# oracle: design/engineering/test-conventions.md:49 (boot 组)
# 判据出处: design/engineering/test-conventions.md:49 (boot 组)
_expect_exclusive("①boot", "菜单")
_expect_adventure_seal("①boot", false)
if main.ui.modals.menu.debug_overlay != null and main.ui.modals.menu.debug_overlay.visible:
@@ -119,7 +119,7 @@ func _step_boot_menu() -> void:
# ---- ② 菜单 → 营地(真实按钮信号路径)----
func _step_menu_to_camp() -> void:
# oracle: design/ux/camp.md:10 (菜单→营地组)
# 判据出处: design/ux/camp.md:10 (菜单→营地组)
# 营地经进档开层(卡② mn9 新路径——campbtn 已撤;槽模板注入隔离命名空间)
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_camp"):
_problems.append("②菜单→营地:选档层新档钮缺失(新路径驱动中断)")
@@ -130,7 +130,7 @@ func _step_menu_to_camp() -> void:
# ---- ③ 营地 → 菜单(回退路径:篝火二次确认动线——卡④ 营地唯一回菜单出口;选档层随关层收闭同收)----
func _step_camp_back_to_menu() -> void:
# oracle: design/ux/camp.md:22 (营地→菜单组)
# 判据出处: design/ux/camp.md:22 (营地→菜单组)
if main.ui.modals.camp.scene == null:
_problems.append("③营地→菜单:营地场景根句柄缺失〔句柄子容器批 V1〕")
return
@@ -147,7 +147,7 @@ func _step_camp_back_to_menu() -> void:
# ---- 选档界面开合(卡③ sl10):函数直调开层(「进入存档」钮归卡② mn3)→屏级互斥采样→
# 返回钮真实信号路径关闭→ESC 语境不响应(卡⑤ 契约 2 范围外——零实现即断言)。----
func _step_save_select_open_back() -> void:
# oracle: design/gdd/systems/表现与支撑/存档序列化.md:61 (选档开合组)
# 判据出处: design/gdd/systems/表现与支撑/存档序列化.md:61 (选档开合组)
ProbeUiUtil.isolate_save(main, "smoke_screen_flow_savesel", false, false, true)
main.save_manager.slots.attach_slot_template("user://smoke_screen_flow_savesel_slot_%d.json")
var esb: Button = ProbeUiUtil.find_button(main.ui.screens.start_overlay, "进入存档", "prefix")
@@ -194,7 +194,7 @@ func seals_check_single(f: Dictionary) -> bool:
func _step_menu_to_adventure() -> void:
# oracle: design/ux/level-map.md:11 (菜单→冒险组)
# 判据出处: design/ux/level-map.md:11 (菜单→冒险组)
# 开始冒险钮已随三入口化撤出——函数直调中间态(卡② mn10;卡④ 大门两分支换代)
main._start_adventure_from_menu()
await _frames(3)
@@ -208,7 +208,7 @@ func _step_menu_to_adventure() -> void:
# ---- ⑤ 冒险内屏切换:关卡地图屏 ⇄ 战斗屏(屏内两态,屏级仍独占)----
func _step_level_to_battle_and_back() -> void:
# oracle: design/ux/battle.md:57 (冒险内切换组)
# 判据出处: design/ux/battle.md:57 (冒险内切换组)
if not main.ui.modals.run.level_screen.visible:
_problems.append("⑤冒险内切换:前置不在关卡地图屏")
return
@@ -228,7 +228,7 @@ func _step_level_to_battle_and_back() -> void:
# ---- ⑥ 放弃 → 终局(放弃路径=回退路径的非正常出口)----
func _step_abandon_to_end() -> void:
# oracle: design/ux/level-map.md:42 (放弃→终局组)
# 判据出处: design/ux/level-map.md:42 (放弃→终局组)
if main.run_scope == null or main.run_scope.adventure == null:
_problems.append("⑥放弃→终局:前置无冒险实例")
return
@@ -241,7 +241,7 @@ func _step_abandon_to_end() -> void:
# ---- ⑦ 终局 → 菜单(终局出口返回开始界面)----
func _step_end_back_to_menu() -> void:
# oracle: design/ux/settlement-summary.md:24 (终局→菜单组)
# 判据出处: design/ux/settlement-summary.md:24 (终局→菜单组)
if main.ui.modals.run.end_overlay == null or not main.ui.modals.run.end_overlay.visible:
_problems.append("⑦终局→菜单:前置不在终局")
return
@@ -254,7 +254,7 @@ func _step_end_back_to_menu() -> void:
# ---- ③' 营地 Esc 浮窗+HUD(卡⑤——真实键盘合成路径 push_input;四态路由+三出口+语境分支+余额单口)----
func _step_camp_esc_and_hud() -> void:
# oracle: design/ux/camp.md:45 (Esc 段组)
# 判据出处: design/ux/camp.md:45 (Esc 段组)
ProbeUiUtil.isolate_save(main, "smoke_screen_flow_esc", false, false, true)
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_esc"):
_problems.append("[esc] 营地入口缺失(选档层新档钮驱动中断)〔ESC批 V1〕")
@@ -320,7 +320,7 @@ func _step_camp_esc_and_hud() -> void:
# 判的是呈现形态换壳(近全屏面板→居中定尺寸窗壳 720×640):窗几何/场景根留底/遮罩 0.6/关闭钮/
# 互斥单开/ESC 优先序/窗内滚动/生涯同壳——行为面(开合路由)零改,只钉窗壳可观测提交面。
func _step_camp_window_shell() -> void:
# oracle: design/ux/camp.md:45 (窗壳 V1–V8 组)
# 判据出处: design/ux/camp.md:45 (窗壳 V1–V8 组)
ProbeUiUtil.isolate_save(main, "smoke_screen_flow_winshell", false, false, true)
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_screen_flow_winshell"):
_problems.append("[winshell] 营地入口缺失(选档层新档钮驱动中断)〔窗口化批 V1〕")
@@ -478,7 +478,7 @@ func _step_camp_window_shell() -> void:
# 清窗经真实钮(逐窗巡检 visible→钮 pressed——栈 close 恢复账随层清空)
func _close_all_windows(views: Dictionary) -> void:
# oracle: design/ux/camp.md:45 (清窗组)
# 判据出处: design/ux/camp.md:45 (清窗组)
for k: StringName in [&"forge", &"chest", &"dummy", &"board"]:
var w: Control = views[k]
if not w.visible:
+11 -11
View File
@@ -46,7 +46,7 @@ func _ready() -> void:
await get_tree().process_frame
# ① 菜单(启动态)——无帮助文腿(玩法速览牌不在画面,checker 无对应断言段);
# 无副标题件,菜单文字锚只剩标题
# oracle: design/engineering/code-conventions.md:54 模态覆盖层层级规则——boot 态顶层=start_overlay、菜单文字在屏(菜单组)
# 判据出处: design/engineering/code-conventions.md:54 模态覆盖层层级规则——boot 态顶层=start_overlay、菜单文字在屏(菜单组)
# 自检一:boot 态顶层可见全屏层=start_overlay(内容层树遍历——屏壳是容器不当候选:
# camp 壳 boot 态 vis=true 但成员恒隐,裸树遍历自顶向下会先命中透明壳)
var top: Node = null
@@ -83,7 +83,7 @@ func _ready() -> void:
_meta[String(pair[0])] = ProbeUiUtil.label_rect(main.ui.screens.start_overlay, String(pair[1]))
await _snap("menu")
# ①b 设置面(settingsbtn 真实信号路径,开合同款真实钮)
# oracle: design/gdd/systems/表现与支撑/设置与本地化.md:95 最小设置面已兑现:音量/减动效/全屏/退出,载体=独立设置存储+设置界面视图(设置组)
# 判据出处: design/gdd/systems/表现与支撑/设置与本地化.md:95 最小设置面已兑现:音量/减动效/全屏/退出,载体=独立设置存储+设置界面视图(设置组)
var setbtn: Button = ProbeUiUtil.find_button(main.ui.screens.start_overlay, "设置", "prefix")
if setbtn == null:
_problems.append("设置入口缺失(开始层 settingsbtn)")
@@ -103,7 +103,7 @@ func _ready() -> void:
ProbeUiUtil.push_click(main, set_close)
await get_tree().process_frame
# ①c 生涯页(函数直调中间态——卡② mn10:careerbtn 已撤,卡④ 笔记本改挂前无 UI 路径)
# oracle: design/ux/camp.md:45 生涯页与四子界面同壳同形态(生涯组)
# 判据出处: design/ux/camp.md:45 生涯页与四子界面同壳同形态(生涯组)
if true:
main._open_career()
for i in 3:
@@ -123,7 +123,7 @@ func _ready() -> void:
if main.ui.modals.menu.career_overlay.visible or not main.ui.screens.start_overlay.visible:
_problems.append("生涯页关闭后页未隐藏或开始层未恢复")
# ② 营地场景图(进档开层新路径——卡② mn9;截图=可点击场景图形态——卡④ 契约 9 V1 验收载体)
# oracle: design/ux/camp.md:16 营地=可点击场景图(七物件命中区表——场景图形态组)
# 判据出处: design/ux/camp.md:16 营地=可点击场景图(七物件命中区表——场景图形态组)
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_shot_probe_camp"):
_problems.append("营地入口缺失(选档层新档钮——新路径驱动中断)〔句柄子容器批 V1〕")
else:
@@ -132,16 +132,16 @@ func _ready() -> void:
ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"campfire").get_center()) # 收闭改接篝火动线(营地根态无关闭钮——卡④ T5)
await get_tree().process_frame
ProbeUiUtil.push_click(main, main.ui.modals.menu.confirm_dialog._confirm_btn) # 二次确认离场(关层收闭——选档层随收)
# oracle: design/ux/camp.md:22 篝火=离开营地回主菜单、必须二次确认(篝心动线组)
# 判据出处: design/ux/camp.md:22 篝火=离开营地回主菜单、必须二次确认(篝心动线组)
await get_tree().process_frame
# ③ 关卡画面(开始冒险→停点出图——入口停点语义;函数直调中间态 mn10)
# oracle: design/ux/level-map.md:11 入口停点候选数=入口个数(关卡画面出图组)
# 判据出处: design/ux/level-map.md:11 入口停点候选数=入口个数(关卡画面出图组)
main._start_adventure_from_menu()
for i in 4:
await get_tree().process_frame
await _snap("level")
# GP 常驻徽章断言(读数=runner.gp 现值,刷新=写路径回执后重查〔open_choices〕)
# oracle: design/ux/level-map.md:77 GP 常驻徽章=GP 图标+数字(冒险钱包读数;写路径回执后重查)
# 判据出处: design/ux/level-map.md:77 GP 常驻徽章=GP 图标+数字(冒险钱包读数;写路径回执后重查)
var gp_label: Label = ProbeUiUtil.find_label(main.ui.modals.run.level_screen, "◈ ")
if gp_label == null or not gp_label.is_visible_in_tree():
_problems.append("GP 徽章不可见(关卡画面顶栏)")
@@ -150,7 +150,7 @@ func _ready() -> void:
if gp_label.text != expect:
_problems.append("GP 徽章读数不符: %s != %s" % [gp_label.text, expect])
# ④ 战斗(节点一——candidate_rect 命中矩形真点选路提交,ui_click_probe 同款)
# oracle: design/ux/battle.md:122 B 区构建:站桩/明细带/轮次指示(战斗出图与几何锚组)
# 判据出处: design/ux/battle.md:122 B 区构建:站桩/明细带/轮次指示(战斗出图与几何锚组)
if main.ui.modals.run.level_screen != null and main.ui.modals.run.level_screen.visible:
ProbeUiUtil.push_click_at(main, main.ui.modals.run.level_screen.candidate_rect(0).get_center())
for i in 10:
@@ -162,14 +162,14 @@ func _ready() -> void:
_meta["stage_view"] = _node_rect(main.ui.battle.stage)
_meta["board_zone"] = _node_rect(main.ui.battle.board_zone)
# draw calls 真机测量(基线 270→目标 <200;窗口化渲染帧读数,
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:264 同屏 draw calls < 200(战斗屏性能预算组)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:264 同屏 draw calls < 200(战斗屏性能预算组)
# 取值时机=战斗截图同帧后一帧——呈现终态满负荷)
await get_tree().process_frame
var dc := int(Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME))
_meta["battle_draw_calls"] = dc
print("[shot_probe] battle draw_calls=%d(基线 270/目标 <200)" % dc)
# ⑤ 状态面板(战斗屏状态角标真实信号路径;层在战斗屏之上开合)
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:277 模态打开遮挡或输入锁定、关闭逐层恢复(状态面板组)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:277 模态打开遮挡或输入锁定、关闭逐层恢复(状态面板组)
var pb: Button = main.ui.battle.board_zone.status_badge
if pb == null or not pb.visible or pb.disabled:
_problems.append("状态面板入口角标缺失/置灰(战斗屏 board_zone)")
@@ -211,7 +211,7 @@ func _ready() -> void:
func _snap(key: String) -> void:
# oracle: design/engineering/test-conventions.md:84 golden 测试项扩项——截图采集清单扩项、实跑截图冻结(截图采集组)
# 判据出处: design/engineering/test-conventions.md:84 golden 测试项扩项——截图采集清单扩项、实跑截图冻结(截图采集组)
await RenderingServer.frame_post_draw
await RenderingServer.frame_post_draw
var img: Image = get_viewport().get_texture().get_image()
+1 -1
View File
@@ -13,7 +13,7 @@ var _problems: Array = []
func _ready() -> void:
# oracle: design/ux/battle.md:122 (明细带挖掘期收起——T17 视觉扩展时序组)
# 判据出处: design/ux/battle.md:122 (明细带挖掘期收起——T17 视觉扩展时序组)
await get_tree().process_frame
main = load("res://presentation/main.tscn").instantiate()
add_child(main)
+1 -1
View File
@@ -30,7 +30,7 @@ var _hero_pos := Vector2i.ZERO
func _ready() -> void:
# oracle: design/engineering/test-conventions.md:84 (微光截图取证——渲染闸采集组)
# 判据出处: design/engineering/test-conventions.md:84 (微光截图取证——渲染闸采集组)
if DisplayServer.get_name() == "headless":
print("[type_glow_shot] FAIL — 本探针必须窗口化运行(headless 无渲染面,截图必空)")
get_tree().quit(1)
+29 -29
View File
@@ -61,7 +61,7 @@ func _ready() -> void:
if main.ui.modals.menu.debug_overlay.visible:
_problems.append("调试浮窗 boot 自动开(菜单优先失守)")
# ---- 营地购买合成点击路径(选档进档开层→购买→关闭全走真实按钮信号路径;
# oracle: design/gdd/systems/跨局循环/天赋树.md:198 (营地购买段——单币购买只扣钥石组)
# 判据出处: design/gdd/systems/跨局循环/天赋树.md:198 (营地购买段——单币购买只扣钥石组)
# 隔离存档换注 main.meta 保确定性(禁碰真实档 user://save.json);陈旧档段首清理)----
for p0 in ["user://smoke_click_probe_reset.json", "user://smoke_click_probe_reset.json.tmp"]:
if FileAccess.file_exists(p0):
@@ -214,7 +214,7 @@ func _ready() -> void:
if main.ui.modals.camp.scene.visible or not main.ui.screens.start_overlay.visible:
_problems.append("营地关闭后未恢复开始层〔句柄子容器批 V1〕")
# ---- 选档界面行为走查(迭代 33 卡③):sl5 空槽新档链/sl6 有档槽进档链/sl7 删档二次确认双路径
# oracle: design/gdd/systems/表现与支撑/存档序列化.md:61 (选档走查段——激活态建立组)
# 判据出处: design/gdd/systems/表现与支撑/存档序列化.md:61 (选档走查段——激活态建立组)
# /sl8 消费方分派单口/sl12 动线序不回闪。开层=函数直调(「进入存档」钮归卡② mn3——中间态在案);
# 隔离=attach_slot_template 注入命名空间,夹具按槽直写(卡① 注入口)。----
var csel_tpl := "user://smoke_click_probe_savesel_slot_%d.json"
@@ -318,7 +318,7 @@ func _ready() -> void:
_problems.append("[savesel] 关闭后层未隐藏或开始层未恢复(模态栈单口失守)")
# ---- 设置面段(隔离 store 换注禁碰真实 user://settings.cfg;真实按钮信号路径)----
# oracle: design/gdd/systems/表现与支撑/设置与本地化.md:4 (设置面段——最小设置面组)
# 判据出处: design/gdd/systems/表现与支撑/设置与本地化.md:4 (设置面段——最小设置面组)
for p0 in ["user://smoke_click_probe_settings.cfg"]:
if FileAccess.file_exists(p0):
DirAccess.remove_absolute(p0)
@@ -385,7 +385,7 @@ func _ready() -> void:
if ProbeUiUtil.find_button(main.ui.modals.menu.settings_overlay, "退出游戏", "prefix") != null:
_problems.append("设置面仍含退出游戏按钮(二轮 D1——只在一级菜单出现)")
# ---- 生涯页段(入口点击链+关闭回返,真实按钮信号路径;本页只读零写,
# oracle: design/ux/camp.md:45 (生涯页段——同壳同形态组)
# 判据出处: design/ux/camp.md:45 (生涯页段——同壳同形态组)
# 值断言归冒烟投影段与 ui_struct 结构族,此处只验开合路径与零跳转)----
# 生涯页驱动=函数直调中间态(卡② mn10——careerbtn 已撤,卡④ 笔记本改挂前无 UI 路径)
if true:
@@ -640,7 +640,7 @@ func _ready() -> void:
_run_modal_probes_once()
_play_one_action()
# ---- 预算耗尽收口(T17 硬锁批适配):选件变强后 probe 可能活过预算不再战败——断点段前提
# oracle: design/ux/level-map.md:11 (主循环选路段——入口候选组)
# 判据出处: design/ux/level-map.md:11 (主循环选路段——入口候选组)
# (冒险终局面在案)须主动满足。收口驱动:任何停点层逐个推进(复用主循环分支语义)至
# level_screen 选路停点→真实放弃二击→终局面。战斗中则继续 autoplay 打完。
if not _done and not main.ui.modals.run.end_overlay.is_open():
@@ -689,7 +689,7 @@ func _ready() -> void:
_play_one_action()
# 排播期/Waiting 等待态=自然流逝(演播秒级、锁随队列空解除)
# T17 适配:战败或放弃二途皆达终局面(放弃=预算耗尽收口路径——见上),断点段前提不变。
# oracle: design/gdd/systems/表现与支撑/存档序列化.md:180 (断点段——断点域与续玩组)
# 判据出处: design/gdd/systems/表现与支撑/存档序列化.md:180 (断点段——断点域与续玩组)
await get_tree().process_frame
var bp_file := "user://smoke_click_probe_reset.json"
var iso_chk = load("res://core/save_manager.gd").new(bp_file)
@@ -721,7 +721,7 @@ func _ready() -> void:
# ① 战斗收口断点写盘断言保留(上方——冒险流直调中间态 mn10)。
# ---- 大门两分支断言段(卡④ T5 接收——卡② 移交落点;V3 断言面)----
# oracle: design/ux/camp.md:16 (大门段——点大门先出确认组)
# 判据出处: design/ux/camp.md:16 (大门段——点大门先出确认组)
# 驱动=营地场景根点选信号(真实路由)→组合根 _on_camp_object_pressed→确认弹窗。
# 无断点=两出口(是/否);有断点=三出口(set_breakpoint 注入选路停点形——同下方开场行③先例)。
# 判据绑可观测提交面:点大门不直接进冒险(is_adventure 翻转只在 confirmed 后);cancelled 恒=
@@ -746,7 +746,7 @@ func _ready() -> void:
await get_tree().process_frame
# R4 位次真点(营地交互修复批——位次与语义绑定钉):真点前消费方前置读(gate_new 在册)→
# 按类型定位按钮行 child(0) 全局矩形中心真点——位次若错接,此点命中「否」,下方主证(翻转)即红。
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:90 确认弹窗位次定值:推进在左、维持居右(R4 位次真点)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:90 确认弹窗位次定值:推进在左、维持居右(R4 位次真点)
if String(main._confirm_consumer) != "gate_new":
_problems.append("R4 前置:确认消费方非 gate_new(分派面漂移)〔营地交互批 V3〕")
var gate_row := _first_hbox(main.ui.modals.menu.confirm_dialog)
@@ -761,7 +761,7 @@ func _ready() -> void:
if String(main._confirm_consumer) != "":
_problems.append("R4 主证:确认后消费方未清零〔营地交互批 V3〕")
# 开局终态两钉(营地交互修复批——开始层隐藏收一处后的落点断言):
# oracle: design/gdd/systems/冒险循环/关卡节点地图.md:78 关卡开始 → 呈现节点图选路停点(开局终态两钉)
# 判据出处: design/gdd/systems/冒险循环/关卡节点地图.md:78 关卡开始 → 呈现节点图选路停点(开局终态两钉)
# R1=确认后开始层不可见(被测改动特有提交面——修复前该句恒红=「开局被开始层盖住」缺陷本体);
# R2=关卡画面(选路停点)在位(开局终态呈现面,与既有 is_adventure 断言同批缺一即红)
if main.ui.screens.start_overlay.visible:
@@ -865,10 +865,10 @@ func _ready() -> void:
# ---- 模态/tooltip/刷新链一次性覆盖(真实信号路径驱动) ----
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:277 (模态/tooltip 段——遮挡与输入锁组)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:277 (模态/tooltip 段——遮挡与输入锁组)
func _run_modal_probes_once() -> void:
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:277 (判定上报通道——验证函数组)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:277 (判定上报通道——验证函数组)
# ⓪ 玩家面文案真实入口断言(迭代36 卡A wa1——C 区两段头随战斗常驻)
if not _tested_copy and main.ui.battle.info_panel != null and main.ui.battle.info_panel.visible:
_tested_copy = true
@@ -944,7 +944,7 @@ func _run_modal_probes_once() -> void:
rnr.effective_ac(), int(rnr.gp)]
if String(main.ui.modals.run.status_panel._attrs_label.text) != attr_expect:
_problems.append("状态面板属性行投影失真(sv6②——期望 %s 实测 %s)" % [attr_expect, main.ui.modals.run.status_panel._attrs_label.text])
# ③ _status_data() 直调对拍(sv7——键集恰八键+curios/feats 独立 oracle)
# ③ _status_data() 直调对拍(sv7——键集恰八键+curios/feats 独立预期表)
var sd: Dictionary = main.status_data()
var keys := ["balance", "hero_hp", "max_hp", "atk", "ac", "gp", "curios", "feats"]
var keys_ok: bool = (sd as Dictionary).size() == 8
@@ -952,18 +952,18 @@ func _run_modal_probes_once() -> void:
keys_ok = keys_ok and (sd as Dictionary).has(k)
if not keys_ok:
_problems.append("_status_data() 键集≠八键(sv7——实测 %s)" % str((sd as Dictionary).keys()))
var oracle: Array = []
var expected: Array = []
for rec in rnr.treasure_inventory.query_inventory(Callable()):
var rr: Dictionary = rec
oracle.append({"name": String(main.db.crossrun.treasure_items.row_by_id(String(rr.get("item_id", ""))).get("display_name", "")),
expected.append({"name": String(main.db.crossrun.treasure_items.row_by_id(String(rr.get("item_id", ""))).get("display_name", "")),
"used": bool(rr.get("used", false))})
var sd_curios: Array = (sd as Dictionary).get("curios", [])
var curios_ok: bool = (sd_curios as Array).size() == (oracle as Array).size()
var curios_ok: bool = (sd_curios as Array).size() == (expected as Array).size()
if curios_ok:
for i in (oracle as Array).size():
curios_ok = curios_ok and String((sd_curios[i] as Dictionary).get("name", "")) == String((oracle[i] as Dictionary).get("name", "")) and bool((sd_curios[i] as Dictionary).get("used", false)) == bool((oracle[i] as Dictionary).get("used", false))
for i in (expected as Array).size():
curios_ok = curios_ok and String((sd_curios[i] as Dictionary).get("name", "")) == String((expected[i] as Dictionary).get("name", "")) and bool((sd_curios[i] as Dictionary).get("used", false)) == bool((expected[i] as Dictionary).get("used", false))
if not curios_ok:
_problems.append("_status_data().curios 对拍独立 oracle 失守(sv7——实测 %s vs %s)" % [str(sd_curios), str(oracle)])
_problems.append("_status_data().curios 对拍独立预期表失守(sv7——实测 %s vs %s)" % [str(sd_curios), str(expected)])
var feats_expect: Array = load("res://presentation/hud_presenter.gd").feat_holdings_lines(main.db, rnr.feats_held())
if str((sd as Dictionary).get("feats", [])) != str(feats_expect):
_problems.append("_status_data().feats 对拍 feat_holdings_lines 失守(sv7)")
@@ -1045,7 +1045,7 @@ func _labels_with_text(labels: Array, needle: String) -> Array:
func _play_one_action() -> void:
# oracle: design/gdd/systems/排雷循环/排雷玩法.md:236 (判定上报通道——验证函数组)
# 判据出处: design/gdd/systems/排雷循环/排雷玩法.md:236 (判定上报通道——验证函数组)
var settlement = main.run_scope.settlement
if settlement == null:
return # 结算竞态防抖:battle_finished 与本轮动作调度同帧到达时 settlement 可能已被置空(基线既有噪声——加固)
@@ -1086,7 +1086,7 @@ func _play_one_action() -> void:
func _random_unknown_adjacent(minesweeper) -> Vector2i:
# oracle: design/gdd/systems/排雷循环/排雷玩法.md:236 (判定上报通道——验证函数组)
# 判据出处: design/gdd/systems/排雷循环/排雷玩法.md:236 (判定上报通道——验证函数组)
var hero: Vector2i = minesweeper.hero_pos()
var cands: Array = []
for dy in range(-1, 2):
@@ -1102,13 +1102,13 @@ func _random_unknown_adjacent(minesweeper) -> Vector2i:
func _click_stop() -> void:
# oracle: design/gdd/systems/排雷循环/行动经济.md:262 (判定上报通道——验证函数组)
# 判据出处: design/gdd/systems/排雷循环/行动经济.md:262 (判定上报通道——验证函数组)
# 停手走真实点击路径(AP 条「停手」钮 → 组合根 settle_batch——排雷玩法 D1×6① 回归载体)
ProbeUiUtil.push_click(main, main.ui.battle.board_zone.ap_bar._btn_stop)
# ---- T1 D1:锁期/重放断言(每 run 一次,脚本化场景——演播期豁免的断言化承载) ----
# oracle: design/gdd/systems/排雷循环/排雷玩法.md:236 (锁期/重放段——拒绝与锁组)
# 判据出处: design/gdd/systems/排雷循环/排雷玩法.md:236 (锁期/重放段——拒绝与锁组)
# 锁期断言(排播队列活跃=锁面):注入封印击 → 直落被冻结不受理(封印未置)+ `_locked_click`
# 缓存命中且为本注入(「最后一次」语义——注入帧内无并发点击)。
# 重放断言(演播完边沿 pump_ended→_replay_locked_click 重入唯一动作通道):缓存清空 +
@@ -1116,7 +1116,7 @@ func _click_stop() -> void:
# 前提消失守卫:等重放期间出现停点层/战斗收场(注入时点恰逢终结演播)→ 静默弃测不计
# problem(封印动作不杀伤,正常局不触发;断言实现形态取舍在代拍白名单内)。
func _locktest_tick() -> void:
# oracle: design/gdd/systems/排雷循环/排雷玩法.md:236 (判定上报通道——验证函数组)
# 判据出处: design/gdd/systems/排雷循环/排雷玩法.md:236 (判定上报通道——验证函数组)
if _locktest_state == 2:
return
var settlement = main.run_scope.settlement
@@ -1173,7 +1173,7 @@ func _locktest_tick() -> void:
func _locktest_pick_cell(minesweeper) -> Vector2i:
# oracle: design/gdd/systems/排雷循环/排雷玩法.md:236 (判定上报通道——验证函数组)
# 判据出处: design/gdd/systems/排雷循环/排雷玩法.md:236 (判定上报通道——验证函数组)
var hero: Vector2i = minesweeper.hero_pos()
for dy in range(-1, 2):
for dx in range(-1, 2):
@@ -1191,7 +1191,7 @@ func _locktest_pick_cell(minesweeper) -> Vector2i:
# 断言两钉:①覆盖登记件停手键在场(零命中=驱动空转假绿,即红);②相位离开 Active(停手
# 收轮)。前提消失守卫:点击后战局收场(终结演播竞态)→ 静默弃测不计 problem(正常局不触发)。
func _stoptest_tick() -> void:
# oracle: design/gdd/systems/排雷循环/排雷玩法.md:167 (停手=玩家主动收轮——判定上报通道)
# 判据出处: design/gdd/systems/排雷循环/排雷玩法.md:167 (停手=玩家主动收轮——判定上报通道)
if _stoptest_state == 2:
return
var settlement = main.run_scope.settlement
@@ -1228,7 +1228,7 @@ func _stoptest_tick() -> void:
func _stoptest_assert_hit() -> void:
# oracle: design/gdd/systems/排雷循环/排雷玩法.md:167 (停手钮真输入命中登记——判定上报通道)
# 判据出处: design/gdd/systems/排雷循环/排雷玩法.md:167 (停手钮真输入命中登记——判定上报通道)
var stop_btn: Button = main.ui.battle.board_zone.ap_bar._btn_stop
var stop_key := String(_recorder._node_keys.get(stop_btn.get_instance_id(), ""))
if stop_key == "" or not _recorder._hits.has(stop_key):
@@ -1236,7 +1236,7 @@ func _stoptest_assert_hit() -> void:
func _first_hbox(node: Node) -> HBoxContainer:
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:90 (位次真点定位——R4 判据面辅助)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:90 (位次真点定位——R4 判据面辅助)
if node is HBoxContainer:
return node
for ch in node.get_children():
@@ -1247,7 +1247,7 @@ func _first_hbox(node: Node) -> HBoxContainer:
func _report_stall(st: Dictionary) -> void:
# oracle: design/engineering/test-conventions.md:30 (判定上报通道——验证函数组)
# 判据出处: design/engineering/test-conventions.md:30 (判定上报通道——验证函数组)
var why := ""
if st.phase == "Waiting":
why = "结算停滞:Waiting 相位无推进(结算应同步走完——窗口段已删除)"
@@ -1263,7 +1263,7 @@ func _report_stall(st: Dictionary) -> void:
func _dump_state() -> void:
# oracle: design/engineering/test-conventions.md:30 (判定上报通道——验证函数组)
# 判据出处: design/engineering/test-conventions.md:30 (判定上报通道——验证函数组)
var diag: Dictionary = main.run_scope.settlement.diagnostic_snapshot() # 诊断观测面(私有字段零直读)
print(" node_index=%s round=%s phase=%s ap=%s rap=%s" % [
str(main.run_scope.runner.node_index), str(main.run_scope.settlement.round_index),
+1 -1
View File
@@ -88,7 +88,7 @@ func _ratio(a: Color, b: Color) -> float:
func _ready() -> void:
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:281 (UI 文字对比度机检 ≥4.5:1 无区域例外——对比度组)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:281 (UI 文字对比度机检 ≥4.5:1 无区域例外——对比度组)
var problems: Array = []
var pairs := _pairs()
for p in pairs:
+12 -12
View File
@@ -242,7 +242,7 @@ func _ready() -> void:
_pre_fail("目标格选取失败 seal=%s dig=%s forbid=%s reveal=%s" % [seal_t, dig_t, forbid_t, reveal_t])
return
# ---- case① 悬停可挖域:motion → 悬停态到达(金框 + 十字光标)----
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:269 悬停光标三语义随目标切换、已开格路径预览、可挖域常驻微光(case①-③ 输入面)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:269 悬停光标三语义随目标切换、已开格路径预览、可挖域常驻微光(case①-③ 输入面)
_push_motion(_pos(bv, seal_t))
await get_tree().process_frame
if bv.hover_probe() != seal_t:
@@ -271,7 +271,7 @@ func _ready() -> void:
if bv.mouse_default_cursor_shape != Input.CURSOR_ARROW:
_problems.append("case③ 移动光标缺失(%d)" % bv.mouse_default_cursor_shape)
# ---- case④ 右键封印:seal_place 到达组合根 + 核心封印态落位 ----
# oracle: design/gdd/systems/排雷循环/排雷玩法.md:231 封印受理与印记随挖消失(case④/④b)
# 判据出处: design/gdd/systems/排雷循环/排雷玩法.md:231 封印受理与印记随挖消失(case④/④b)
_push_click(_pos(bv, seal_t), MOUSE_BUTTON_RIGHT)
await get_tree().process_frame
if not _has_action(seal_t, "seal_place"):
@@ -285,14 +285,14 @@ func _ready() -> void:
if seal_unit == null or not seal_unit.seal_on:
_problems.append("case④b 封印印记未下发(seal_on=%s)" % ["无单元" if seal_unit == null else str(seal_unit.seal_on)])
# ---- case⑤ 双击 chord:禁入格双左击(核心拒挖零副作用)→ chord_attempted ----
# oracle: design/gdd/systems/排雷循环/排雷玩法.md:236 拒绝三源可辨、任何拒绝零副作用(case⑤ chord)
# 判据出处: design/gdd/systems/排雷循环/排雷玩法.md:236 拒绝三源可辨、任何拒绝零副作用(case⑤ chord)
_push_click(_pos(bv, forbid_t), MOUSE_BUTTON_LEFT)
_push_click(_pos(bv, forbid_t), MOUSE_BUTTON_LEFT)
await get_tree().process_frame
if _chords.is_empty() or _chords[_chords.size() - 1] != forbid_t:
_problems.append("case⑤ chord_attempted 未达(chords=%s)" % [str(_chords)])
# ---- case⑥ 左键挖:dig 到达组合根 + 核心揭格落位 ----
# oracle: design/gdd/systems/排雷循环/排雷玩法.md:231 挖掘受理与揭格落位(case⑥)
# 判据出处: design/gdd/systems/排雷循环/排雷玩法.md:231 挖掘受理与揭格落位(case⑥)
_push_click(_pos(bv, dig_t), MOUSE_BUTTON_LEFT)
await get_tree().process_frame
if not _has_action(dig_t, "dig"):
@@ -301,7 +301,7 @@ func _ready() -> void:
if not ms.is_revealed(dig_t):
_problems.append("case⑥ 核心揭格未落位(目标=%s)" % dig_t)
# ---- case⑦ 英雄精灵世界落位(回归闸):精灵在 SubViewport 世界内,
# oracle: design/ux/battle.md:154 主角站桩立绘带落影、贴脚与缩放档(case⑦-⑩ 呈现落位)
# 判据出处: design/ux/battle.md:154 主角站桩立绘带落影、贴脚与缩放档(case⑦-⑩ 呈现落位)
# 落位 = 格×步距 + 脚底锚(横=格中线/纵=格底往上 25% 线=HERO_GROUND_FRAC 自底边口径——「脚踩
# 格子 1/4 处·从下往上数」;禁带壳层 _svp_container.position 居中偏移——上批误用壳层
# cell_origin 实测右偏 ~7 格+偏离格心,实机截图用户报缺陷)。素材缺位树(hero==null,字形
@@ -368,7 +368,7 @@ func _ready() -> void:
if bv._world.hero.position.distance_to(expect10b) > 0.5:
_problems.append("case⑩ 还原后英雄未复位(pos=%s expect=%s)" % [str(bv._world.hero.position), str(expect10b)])
# ---- case⑪ 贴图缺位回退(字形「人」回归闸):texture 置 null + refresh → 英雄格数字 0 时字形
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:264 棋盘格子与数字完整可见——贴图缺位回退字形保可读(case⑪)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:264 棋盘格子与数字完整可见——贴图缺位回退字形保可读(case⑪)
# 必须回退「人」(数字格仍显数字——回退判据与抑制判据同源);验毕还原纹理重绘。 ----
if bv._world.hero != null:
var hp11: Vector2i = ms.hero_pos()
@@ -385,7 +385,7 @@ func _ready() -> void:
bv._hero_sprite.tex_idle = tex_saved
bv.refresh()
# ---- case⑭ 变异角标(flat_damage 未开格视觉标记;resolver 注入面+落位+复位) ----
# oracle: design/gdd/systems/排雷循环/地形变异.md:154 呈现按 effect/trigger/placement 数据路由、零特判(case⑭ 角标)
# 判据出处: design/gdd/systems/排雷循环/地形变异.md:154 呈现按 effect/trigger/placement 数据路由、零特判(case⑭ 角标)
var mark_t: Vector2i = _pick_forbidden(bv, ms) # 任一未开格(禁入=未开非相邻)
if mark_t.x >= 0:
bv.set_variant_mark_resolver(func(_c): return "flat_damage")
@@ -399,7 +399,7 @@ func _ready() -> void:
else:
_problems.append("case⑭ 无未开格可验(板面异常)")
# ---- case⑮ 视野迷雾(三态呈态/半径圈/移动跟随/开关两态零扰动/提灯插值位;
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:268 视野迷雾:灯光区随移动跟随、开关两态结算逐位一致(case⑮)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:268 视野迷雾:灯光区随移动跟随、开关两态结算逐位一致(case⑮)
# 纯呈现零逻辑——迷雾开关切换前后 minesweeper 状态摘要逐位一致) ----
var fogp: Dictionary = bv.fog_params_probe()
if int(bv.FOG_RADIUS) != 8 or int(fogp["lantern"]) != 0 or not fogp["enabled"]:
@@ -495,7 +495,7 @@ func _ready() -> void:
# attune_param_sum 只读出口→set_fog_glow_bonus〕→视野 +4 生效与卸装复原。
# settlement.attunement 手动注入=模拟 begin_battle enc 注入后的运行态〔注入面本体归
# 冒烟+单测覆盖〕;不重启冒险——case⑯ 起既有板面继续用)
# oracle: design/gdd/systems/跨局循环/元进度.md:156 解锁可见:装配强化下一局生效(case⑮ 装配链)
# 判据出处: design/gdd/systems/跨局循环/元进度.md:156 解锁可见:装配强化下一局生效(case⑮ 装配链)
main.save_manager.meta_state.set_attunement_equipped(["wide_scout_band"])
var p_lantern: Dictionary = main.build_adventure_params(main.save_manager, main.meta)
if not (p_lantern.get("attunement", []) as Array).has("wide_scout_band"):
@@ -514,7 +514,7 @@ func _ready() -> void:
_problems.append("case⑮ 卸装后 dist==R+1 格未复原遮蔽")
main.save_manager.meta_state.set_attunement_equipped([])
# ---- case⑯ 状态面板输入锁语义(R3——开层锁棋盘、关层恢复无残留;真实 push_input
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:277 模态打开输入锁定、关闭逐层恢复(case⑯ R3)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:277 模态打开输入锁定、关闭逐层恢复(case⑯ R3)
# 路径:入口角标本体 press+release 真点击 → 状态面板开;锁期挖掘点击零穿透;「继续」关层后
# 同格挖掘重新到达——锁语义与既有模态同款,无状态残留。置于全 case 之尾:取格若需前沿移位
#(真实点击 move 扩大可挖域),其板面扰动不再波及任何既有断言——域恰 2 枚时 seal_t 带封印+
@@ -570,7 +570,7 @@ func _ready() -> void:
if not _has_action(status_dig, "dig") or not ms.is_revealed(status_dig):
_problems.append("case⑯ 关闭后挖掘未到达(恢复无残留验证失守)")
# ---- case⑰ 未开格类型微光(活板面走查:作用集恒等/开格灭/移动复亮
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:267 类型微光出圈即灭入圈即亮、已开与封锁格恒无微光(case⑰)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:267 类型微光出圈即灭入圈即亮、已开与封锁格恒无微光(case⑰)
# 与出圈灭/相位门控/开关两态零扰动。与冒烟段数据面断言分工:此处走真实点击路径) ----
if not bool(bv.type_glow_probe().get("enabled", false)):
_problems.append("case⑰ 微光默认态非开(生产默认开——Q4 丙案)")
@@ -759,7 +759,7 @@ func _push_release(pos: Vector2, btn: int) -> void:
func _pre_fail(why: String) -> void:
# oracle: design/engineering/test-conventions.md:56 (判定上报通道——验证函数组)
# 判据出处: design/engineering/test-conventions.md:56 (判定上报通道——验证函数组)
push_error("[ui_input_probe] FAIL — " + why)
print("[ui_input_probe] FAIL — " + why)
get_tree().quit(1)
+14 -14
View File
@@ -16,7 +16,7 @@ func _ready() -> void:
await get_tree().process_frame
var problems: Array = []
# ---- 放弃入口(台账 119):默认隐藏(非冒险模式无冒险可放弃——开始层/调试两层)----
# oracle: design/ux/level-map.md:59 放弃冒险入口=边缘动作、任意选路停点承载——非冒险模式无入口(默认隐藏)
# 判据出处: design/ux/level-map.md:59 放弃冒险入口=边缘动作、任意选路停点承载——非冒险模式无入口(默认隐藏)
if main.ui.modals.run.level_screen.abandon_btn == null or main.ui.modals.run.level_screen.abandon_btn.visible:
print("[ui_probe] FAIL — 放弃按钮默认应隐藏(非冒险模式关)")
get_tree().quit(1)
@@ -24,7 +24,7 @@ func _ready() -> void:
# ---- 营地覆盖层(主菜单入口/开合/余额文案/购买禁用态;
# 隔离存档换注 main.meta 保确定性(禁碰真实档 user://save.json——SaveManager 路径注入纪律;
# 营地先行段只换 meta 不换 save_manager——冒险段换注零档在前)----
# oracle: design/ux/camp.md:45 五功能窗统一窗壳、五窗互斥单开、各窗自带关闭钮(营地开合组)
# 判据出处: design/ux/camp.md:45 五功能窗统一窗壳、五窗互斥单开、各窗自带关闭钮(营地开合组)
ProbeUiUtil.isolate_save(main, "smoke_ui_probe_camp", false, false, false)
if not await ProbeUiUtil.open_camp_via_savesel(main, "smoke_ui_probe_camp"):
problems.append("营地入口缺失(选档层新档钮——mn9 新路径驱动中断)〔句柄子容器批 V1〕")
@@ -36,12 +36,12 @@ func _ready() -> void:
problems.append("营地层打开时开始层未隐藏(规范 2.3 遮挡纪律)〔句柄子容器批 V1〕")
else:
# 天赋树子界面(场景点选真实路由——木桩命中区进树界面;卡④ T5 深员改指)
# oracle: design/ux/camp.md:20 木桩命中区→天赋树界面入口(场景点选路由)
# 判据出处: design/ux/camp.md:20 木桩命中区→天赋树界面入口(场景点选路由)
ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"dummy").get_center())
await get_tree().process_frame
if not main.ui.modals.camp.tree.visible:
problems.append("天赋树子界面未打开(场景点选路由中断)〔营地图批 V2〕")
# oracle: design/ux/camp.md:41 钥石余额常驻画面顶部 HUD 栏(余额文案组)
# 判据出处: design/ux/camp.md:41 钥石余额常驻画面顶部 HUD 栏(余额文案组)
if not String(main.ui.modals.camp.tree._balance_label.text).begins_with("钥石"):
problems.append("营地余额文案缺失(%s)〔句柄子容器批 V1〕" % main.ui.modals.camp.tree._balance_label.text)
if main.ui.modals.camp.tree._tree_buy_btns.is_empty():
@@ -57,7 +57,7 @@ func _ready() -> void:
ProbeUiUtil.push_click(main, ProbeUiUtil.find_button(main.ui.modals.camp.tree, "返回营地")) # 真点底栏返回钮→_emit_closed(camp_sub_view_base.gd:66-84)
await get_tree().process_frame
# 秘宝匣子界面(场景点选真实路由——宝箱命中区)
# oracle: design/ux/camp.md:18 宝箱命中区→秘宝匣界面入口
# 判据出处: design/ux/camp.md:18 宝箱命中区→秘宝匣界面入口
ProbeUiUtil.push_click_at(main, main.ui.modals.camp.scene.get_hotspot_rect(&"chest").get_center())
await get_tree().process_frame
if main.ui.modals.camp.treasure._workshop_rows.size() != 12:
@@ -76,7 +76,7 @@ func _ready() -> void:
await get_tree().process_frame
# ---- 入口选路停点(关卡开始即出节点图——level_started 后、首战前弹选路层;
# candidate_rect 命中矩形真点 pick 入口单候选进首战)----
# oracle: design/ux/level-map.md:11 入口停点候选数=入口个数(入口单候选断言)
# 判据出处: design/ux/level-map.md:11 入口停点候选数=入口个数(入口单候选断言)
# ---- 独立性断言(独立屏激活期战斗屏宿主整体隐藏,零透出)----
if not main.ui.modals.run.level_screen.visible:
problems.append("关卡开始未弹入口选路停点(level_screen 应可见)")
@@ -92,7 +92,7 @@ func _ready() -> void:
if not main.ui.screens.battle_root.visible or main.ui.modals.run.level_screen.visible:
problems.append("选路提交战斗节点后未切回战斗屏(屏级互斥恢复失守)")
# ---- 放弃入口·冒险模式可见 + 战斗中按下被拒(真实按钮路径——入口挂选路停点,战斗中拒绝为防御分支)----
# oracle: design/ux/level-map.md:42 放弃冒险(任意选路停点)→ 冒险落幕——战斗域单事务在飞时拒绝
# 判据出处: design/ux/level-map.md:42 放弃冒险(任意选路停点)→ 冒险落幕——战斗域单事务在飞时拒绝
if main.ui.modals.run.level_screen.abandon_btn == null or not main.ui.modals.run.level_screen.abandon_btn.visible:
problems.append("冒险模式放弃按钮未开放(选路停点入口在案)")
else:
@@ -101,7 +101,7 @@ func _ready() -> void:
if main.run_scope.adventure == null or String(main.run_scope.adventure.state) != "running":
problems.append("首战中放弃未被拒(战斗域单事务在飞——state 应保持 running)")
# ---- 既有断言(回归基线;A 区无进度条——节点链进度由关卡画面独立屏承载)----
# oracle: design/ux/battle.md:122 B 区构建组:主角与敌人站桩、明细带挖掘期收起、轮次指示、棋盘与 C 区/秘宝槽、首战进行中
# 判据出处: design/ux/battle.md:122 B 区构建组:主角与敌人站桩、明细带挖掘期收起、轮次指示、棋盘与 C 区/秘宝槽、首战进行中
if main.ui.battle.board_zone.board_view.cells_probe().is_empty():
problems.append("棋盘格未生成(cells=0)")
if main.ui.battle.board_zone.board_view.board() == null:
@@ -119,7 +119,7 @@ func _ready() -> void:
problems.append("B 区敌方站桩未构建(%d 个)" % main.ui.battle.stage.enemy_box.get_child_count())
if main.ui.battle.board_zone.ap_bar._dots.get_child_count() != int(main.db.run.action_economy.ap_per_round):
problems.append("D 区 AP 点阵数量错误(%d)" % main.ui.battle.board_zone.ap_bar._dots.get_child_count())
# oracle: design/gdd/systems/排雷循环/行动经济.md:258 开轮硬重置:行动点回到表值(AP 点阵数=ap_per_round)
# 判据出处: design/gdd/systems/排雷循环/行动经济.md:258 开轮硬重置:行动点回到表值(AP 点阵数=ap_per_round)
if main.ui.battle.board_zone.ap_bar.refresh_remaining_text() == "":
problems.append("D 区弃图刷新按钮文案缺失")
if main.ui.battle.board_zone.toast == null:
@@ -136,7 +136,7 @@ func _ready() -> void:
# E 区无道具面板——四区构建由其余断言覆盖
# ---- 敌方站桩投影(顺位徽标/意图三档动作动画占位——敌人系统×4,全站桩)----
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:275 敌人呈现:意图占位三档可见性——普通攻击零表示、类型级提示(站桩投影组)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:275 敌人呈现:意图占位三档可见性——普通攻击零表示、类型级提示(站桩投影组)
# B 区站桩子件伴随件化(壳层 tooltip 载体)——断言口径见台账 171:
# 伴随件化(壳层 tooltip 载体),穿透明(子件 _name_label/_armor_icon/_intent_badge)改本体
# 探针出口 stage.enemy_body_at(i).name_line_probe()/intent_probe()——呈现口径逐字保持
@@ -163,7 +163,7 @@ func _ready() -> void:
elif not bool(main.ui.battle.stage.hero_standee.portrait_probe().get("has_tex", false)):
problems.append("主角立绘纹理未落位(显示档 hero=144——显示档批)")
# ---- BUG-0001 回归(tooltip 入树后 set_effects 槽位不错位——结算软锁修复沉淀)----
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:274 状态槽图标+层数+剩余次数、悬停见来源(tooltip 回归组)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:274 状态槽图标+层数+剩余次数、悬停见来源(tooltip 回归组)
var slots_row = main.ui.battle.stage.hero_standee.slot_row # BUG-0001 回归随组件迁入站桩(tooltip/槽位错位同源)
var probe_eff: Array = [{"effect_id": "attack_up", "display_name": "增伤", "layers": 1,
"remaining_settlements": 1, "source_class": "safe_cell", "round_index": 1, "effective_value": 50}]
@@ -189,7 +189,7 @@ func _ready() -> void:
# ---- 图标键回归(HUD框架 图标键契约:状态表九行全映射〔定稿 PNG 纹理〕、
# 格面资源 cell_type 九型全映射〔含 gp 键〕;查不到的键 fail-fast + ? 占位
# ——此处钉死映射不残缺,未知键断言由 _icon_tex/_badge_glyph 承担)----
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:274 极性按键级表呈现——状态图标键映射不残缺(图标键回归组)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:274 极性按键级表呈现——状态图标键映射不残缺(图标键回归组)
for eid in ["attack_up", "ac_up", "alert", "weaken", "enrage", "off_guard", "sapped", "empower", "fortify"]:
if not StatusSlotRow.EFFECT_ICON.has(eid) or StatusSlotRow.EFFECT_ICON[eid] == null:
problems.append("状态图标九键纹理映射缺失(%s)" % eid)
@@ -214,7 +214,7 @@ func _ready() -> void:
# ---- L2 单场段(debug_session 单场原语 + 去饱和接口可用性;雾格机制已整体移除,不再断言变体呈现)----
# 单场无用户入口——探针直调 debug_session 原语(battle_created/ready 仍经组合根接线;
# _reset_run_scope 复现 _start_single 的提示去重复位)
# oracle: design/gdd/systems/排雷循环/地形变异.md:156 布置域:变异格全在初始展开区外(L2 布置域组)
# 判据出处: design/gdd/systems/排雷循环/地形变异.md:156 布置域:变异格全在初始展开区外(L2 布置域组)
main.begin_session(false)
main._debug.start_single(2)
await get_tree().process_frame
@@ -237,7 +237,7 @@ func _ready() -> void:
# ---- GP 终局行:summary gp_final 键取数+胜利面板 GP 行呈现(C5:GP 行只上冒险终局面板;
# 断言面 = summary 键,无影子账清零转存)----
# (置于战斗态断言之后——合成收束会灰化站桩并清 settlement 引用,具污染性)
# oracle: design/ux/settlement-summary.md:20 战利品行=GP 增量+总量(冒险终局面板 GP 行组)
# 判据出处: design/ux/settlement-summary.md:20 战利品行=GP 增量+总量(冒险终局面板 GP 行组)
var meta_saved = main.meta.save
for p2 in ["user://smoke_ui_probe_settle_scratch.json", "user://smoke_ui_probe_settle_scratch.json.tmp"]:
if FileAccess.file_exists(p2):
+11 -11
View File
@@ -89,7 +89,7 @@ func _ready() -> void:
# ---- 生涯页:入口=帐篷旁笔记本(卡④ T3 改挂——场景点选信号真实路由→组合根 _open_career)→
# 结构断言族→只读巡检(契约 3)+零动效契约+零跳转契约(提纲 P4 甲)→组合根真实路径关闭。
#(登记序/树序契约统一在全模态 _modal_registry_contract——boot 段跑)----
# oracle: design/ux/camp.md:19 帐篷旁笔记本→生涯记录;生涯页返回钮口径由结构校验兜底(生涯段)
# 判据出处: design/ux/camp.md:19 帐篷旁笔记本→生涯记录;生涯页返回钮口径由结构校验兜底(生涯段)
# 营地语境:开始层全程隐藏(笔记本入口在营地场景根——关生涯回营地不回开始层,卡④ T3 语境分支)
main._camp_pres.open_camp() # 重开营地场景根(笔记本入口语境)
_settle()
@@ -106,7 +106,7 @@ func _ready() -> void:
if main.ui.modals.menu.career_overlay.visible or main.ui.screens.start_overlay.visible:
problems.append("[career] 关闭后页未隐藏或开始层回弹(营地语境分支失守)〔营地图批 V5〕")
# ---- Esc 浮窗结构段(卡⑤——三钮在位且仅三+零动效契约+登记序在册+debug_badge 不波及)----
# oracle: design/ux/camp.md:45 ESC 优先序:有窗先关最上层窗、无窗才进浮窗;各窗自带关闭钮(Esc 段)
# 判据出处: design/ux/camp.md:45 ESC 优先序:有窗先关最上层窗、无窗才进浮窗;各窗自带关闭钮(Esc 段)
main._camp_pres.open_camp()
_settle()
var gpos_gate: Vector2 = main.ui.modals.camp.scene.get_hotspot_rect(&"gate").get_center()
@@ -213,7 +213,7 @@ func _ready() -> void:
_settle()
# ---- 冒险簇(真流推进:开冒险→地图选路态→选战斗节点→战斗 HUD)----
# oracle: design/ux/level-map.md:3 图上点击选路·候选按钮退役(冒险簇选路真点组)
# 判据出处: design/ux/level-map.md:3 图上点击选路·候选按钮退役(冒险簇选路真点组)
ProbeUiUtil.isolate_save(main, "smoke_ui_struct_probe_adv", true, false, true)
main.ui.modals.menu.debug_overlay.seed_edit.text = "42" # 种子钉死(种子框默认为空=非首局随机,结构采样确定性禁依赖默认分支)
main._start_adventure_from_menu()
@@ -243,7 +243,7 @@ func _ready() -> void:
# ---- 图例层(旧模态、首过结构族):ap_bar legend_toggled
# 信号真路径开(board_zone 信号→组合根 _on_legend_toggled→_open_modal)→结构断言族→
# closed 信号真路径关(close()→组合根 _on_modal_closed)。
# oracle: design/gdd/systems/表现与支撑/HUD框架.md:88 图例面板=模态族:统一登记序栈、入栈出栈、关闭逐层恢复(图例组)
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:88 图例面板=模态族:统一登记序栈、入栈出栈、关闭逐层恢复(图例组)
main.ui.battle.board_zone.ap_bar._btn_legend.pressed.emit() # 前提注入(保留 emit):emit 选路路径下 battle_root 未及显示且输入锁在(实证在案),真点不可达——图例开启的真输入承载随「route 信号路径屏幕切换时序」发现一并呈报待裁
_settle()
if not main.ui.modals.run.legend_overlay.visible:
@@ -406,7 +406,7 @@ const _PAUSE_READONLY_SIGNALS: Array[String] = [
func _status_readonly_contract(main: Node) -> void:
# oracle: design/engineering/code-conventions.md:21 视图零核心写调用、依赖单向(status 只读巡检组)
# 判据出处: design/engineering/code-conventions.md:21 视图零核心写调用、依赖单向(status 只读巡检组)
var overlay: Control = main.ui.modals.run.status_panel
var stack: Array = [overlay]
var conn_count := 0
@@ -453,7 +453,7 @@ func _status_zero_motion_contract(main: Node) -> void:
# 清单外零连接。白名单={视图自身 _emit_closed〔返回钮〕, 组合根 _on_career_closed};页内任何
# 购买/导航/写入方向的新连接一律红,须先入册审查。
func _career_readonly_contract(main: Node) -> void:
# oracle: design/engineering/code-conventions.md:21 视图零核心写调用、依赖单向(career 只读巡检组)
# 判据出处: design/engineering/code-conventions.md:21 视图零核心写调用、依赖单向(career 只读巡检组)
var overlay: Control = main.ui.modals.menu.career_overlay
var stack: Array = [overlay]
var conn_count := 0
@@ -500,7 +500,7 @@ func _career_zero_motion_contract(main: Node) -> void:
# _career_registry_contract 的断言(career=状态面板后/确认弹窗前、树序同步)由本全量合同覆盖)
# ⑭选档界面契约(卡③ sl1/sl2/sl3/sl4/sl9——呈现面全部来自喂入数据,视图零自判)
func _save_select_contract(main: Node, tpl: String) -> void:
# oracle: design/gdd/systems/表现与支撑/存档序列化.md:61 三存档位独立文件、激活态由选档界面建立(选档契约组)
# 判据出处: design/gdd/systems/表现与支撑/存档序列化.md:61 三存档位独立文件、激活态由选档界面建立(选档契约组)
var sso: Node = main.ui.modals.menu.save_select_overlay
# sl1 三槽呈现:槽卡计数==3+零滚动容器(禁滚动长列表形态——契约 1)
var rows: VBoxContainer = sso._rows_box
@@ -580,7 +580,7 @@ func _collect_labels(node: Node, out: Array[String]) -> void:
func _modal_registry_contract(main: Node) -> void:
# oracle: design/engineering/code-conventions.md:54 模态覆盖层层级规则——新增覆盖层必须登记 z 序位置(登记序契约组)
# 判据出处: design/engineering/code-conventions.md:54 模态覆盖层层级规则——新增覆盖层必须登记 z 序位置(登记序契约组)
var list: Array = main.ui.flow.stack._list
# ① 登记册序==合同模态序(逐位点名——合同是登记序唯一事实源)
var contract_modals: Array = []
@@ -648,7 +648,7 @@ func _modal_registry_contract(main: Node) -> void:
# ⑬career 零跳转契约(提纲 P4 甲——页内零「前往他处」入口:除「返回」外任何导航钮=红)
func _career_nojump_contract(main: Node) -> void:
# oracle: design/ux/camp.md:19 生涯记录入口与返回钮口径由结构校验兜底——页内零导航入口(零跳转契约组)
# 判据出处: design/ux/camp.md:19 生涯记录入口与返回钮口径由结构校验兜底——页内零导航入口(零跳转契约组)
for nav in ["营地", "商店", "设置", "冒险", "继续上局", "退出", "前往"]:
if ProbeUiUtil.find_button(main.ui.modals.menu.career_overlay, nav, "contains") != null:
problems.append("[career][nojump] 页内出现导航入口「%s」(零跳转违约——生涯纯只读)" % nav)
@@ -658,7 +658,7 @@ func _career_nojump_contract(main: Node) -> void:
# (名行基线离盒底 1px 同型高危写法返修回归闸;
# 内容矩形=StandeeBody.content_rect(),最低绘制元素=底座下缘)
func _standeefit_contract(main: Node) -> void:
# oracle: design/ux/battle.md:154 主角站桩立绘(无框立绘+落影)——站桩内容矩形⊆舞台(站桩适配组)
# 判据出处: design/ux/battle.md:154 主角站桩立绘(无框立绘+落影)——站桩内容矩形⊆舞台(站桩适配组)
var st: Node = main.ui.battle.stage
if st == null or st.hero_standee == null:
problems.append("[standee] 舞台/主角站桩缺失(断言中断)")
@@ -743,7 +743,7 @@ func _in_scroll(c: Control) -> bool:
func _audit(screen: String, roots: Array) -> void:
# oracle: design/engineering/architecture/architecture.md:168 组合根交接面与呈现装配——屏结构审计宿主面(结构审计组)
# 判据出处: design/engineering/architecture/architecture.md:168 组合根交接面与呈现装配——屏结构审计宿主面(结构审计组)
for r in roots:
if r != null and is_instance_valid(r):
_force_layout(r)
+6 -6
View File
@@ -43,7 +43,7 @@ func _ready() -> void:
# ① 全局浮层角标开窗(调试入口=UI 最顶层浮层,任何 UI 不遮挡——
# main 直接子层、LAYER_CONTRACT 末位 float 类;boot 菜单优先不开浮窗,角标真实点击路径开窗;
# 悬浮于菜单之上——开始层不隐藏;树序新基准=登记册末位(确认弹窗之后=绘制序最上))
# oracle: design/engineering/test-conventions.md:49 调试面=DebugOverlay/DS_DEBUG——发布态恒隐无 UI 开启口、开发期临时启用(①开窗层级组)
# 判据出处: design/engineering/test-conventions.md:49 调试面=DebugOverlay/DS_DEBUG——发布态恒隐无 UI 开启口、开发期临时启用(①开窗层级组)
main._show_debug_overlay() # 发布态角标恒隐(main.gd:138 _debug_entry 缺省 false)——角标信号路径已退役(:123 同款先例),开窗经组合根直调承载
await get_tree().process_frame
if not main.ui.modals.menu.debug_overlay.visible:
@@ -57,7 +57,7 @@ func _ready() -> void:
if str(boosted_atk) not in main.ui.modals.menu.debug_overlay.effect_text() or str(boosted_hp) not in main.ui.modals.menu.debug_overlay.effect_text():
problems.append("生效预览未联动(%s)" % main.ui.modals.menu.debug_overlay.effect_text())
# ③ 应用(真实信号路径:apply_requested → 组合根)——E4 后加成零表写,生效断言移至 ⑧ 战斗快照
# oracle: design/engineering/test-conventions.md:49 调试面加成链路:滑条联动/应用/重置、hero 表运行期只读(②③④⑦组)
# 判据出处: design/engineering/test-conventions.md:49 调试面加成链路:滑条联动/应用/重置、hero 表运行期只读(②③④⑦组)
var apply_btn: Button = ProbeUiUtil.find_button(main.ui.modals.menu.debug_overlay, "应用并关闭")
if apply_btn == null:
problems.append("调试浮窗「应用并关闭」钮缺失")
@@ -72,7 +72,7 @@ func _ready() -> void:
ProbeUiUtil.push_click(main, reset_btn)
# ⑤ 批量模拟全链路(N=10——走 level_autoplay 与 headless 扫描同口径;表基线由组合根复位;
# 菜单态上下文未锁定=按钮可点,is_running 语义=模拟在跑〔18卡⑦ 与对局禁用态拆分〕)
# oracle: design/engineering/test-conventions.md:49 调试面批量模拟链路:N=10 输出关卡完成率/剩余 HP/败北节点(⑤组)
# 判据出处: design/engineering/test-conventions.md:49 调试面批量模拟链路:N=10 输出关卡完成率/剩余 HP/败北节点(⑤组)
main.ui.modals.menu.debug_overlay.set_sliders(100, 0)
main.ui.modals.menu.debug_overlay.set_sim_count(10)
# 折叠区控件真输入通道(test-conventions §2——先滚轮滚入可视区再点):sim 钮在滚动列表 boot
@@ -155,7 +155,7 @@ func _ready() -> void:
# ⑨ 对局中可开(18卡⑦ P2 甲/T2 防护——S1+ 停机点回归闸):战斗屏角标真实信号路径开窗;
# 棋盘输入不锁、状态角标不置灰(「默认开×遮挡复活」下必锁死的破约回归面);
# 对局中批量模拟/两层调试两钮禁用;当局数据六项与只读访问器逐项一致;关闭钮真实路径收窗恢复
# oracle: design/engineering/test-conventions.md:49 调试面对局态:不锁棋盘输入/两钮禁用/当局数据只读一致(⑨组)
# 判据出处: design/engineering/test-conventions.md:49 调试面对局态:不锁棋盘输入/两钮禁用/当局数据只读一致(⑨组)
var dbg_badge: Button = main.ui.screens.debug_badge
if dbg_badge == null or dbg_badge.visible:
problems.append("对局中调试浮层角标非恒隐(发布态语义失守——卡⑦ 删写死行批)")
@@ -199,7 +199,7 @@ func _ready() -> void:
_overlay_zero_motion_contract(main, problems)
# ⑩ 种子三分单点断言(18卡⑦ C1——判定只落 _seed_value() 单点;对局态不影响本判定面):
# 显式合法整数全场景优先(含首局)→ 首局(存档布尔 false)恒 42 → 非首局空框引擎熵连抽不全等 42
# oracle: design/engineering/architecture/architecture.md:168 seed_value=组合根公开服务面(⑩种子三分判定单点组)
# 判据出处: design/engineering/architecture/architecture.md:168 seed_value=组合根公开服务面(⑩种子三分判定单点组)
main.ui.modals.menu.debug_overlay.seed_edit.text = "777"
if main.seed_value() != 777:
problems.append("显式种子输入未优先(_seed_value != 777——C1 ①失守)")
@@ -240,7 +240,7 @@ func _ready() -> void:
# 全连接巡检——白名单={视图自身八方法 + 注册面模态编排口 ui.flow.close(closed 外发消费——
# 注册面批把该连接目标从组合根转发壳改为 flow 真方法,机检白名单随批登记同一连接)};
# 当局数据区块=纯标签零连接在此被一并约束(新增任何连接=红须入册审查)。
# oracle: design/engineering/code-conventions.md:21 视图零核心写调用、依赖单向(白名单外零连接巡检组)
# 判据出处: design/engineering/code-conventions.md:21 视图零核心写调用、依赖单向(白名单外零连接巡检组)
func _overlay_readonly_contract(main: Node, problems: Array) -> void:
var overlay: Control = main.ui.modals.menu.debug_overlay
var stack: Array = [overlay]