feat(迭代28 T2): boot 链路时序后置条件冒烟段(_smoke_boot_chain 六断言)

挂 _split_tail(协程纪律 await):V2a ConfigDB 就绪+表载/V2b 设置已应用(Master 总线 mute/volume_db+UiKit.motion_scale=settings_store 现值,一致性判据与真实设置文件内容无关)/V2c 启动态菜单可见/V2d 续玩钮态==断点在档态(boot 路径关系判据+隔离新档双向:无断点隐/合成断点显/清断点回隐)/V2e 闲时会话在树/V2f 调试浮窗态==DS_DEBUG 门控(两侧同判据)。存档隔离 attach_path 禁碰真实档。冒烟 1087→1097/0
This commit is contained in:
DKChan committed 2026-10-15 07:07:44 +08:00
1 parent 6f71509421
commit a35581e441
1 file changed
+65
+65
View File
@@ -86,6 +86,7 @@ func _split_tail() -> void:
_smoke_hygiene_gates()
if autoload_ok:
await _smoke_scene_split() # 协程函数必须 await(无 await=发射后不管,首个 await 后即被 quit 截断)
await _smoke_boot_chain()
await _smoke_run_lifecycle()
else:
check(false, "V2/V3 前置:autoload 链未就绪(ConfigDB/SaveManager)")
@@ -237,6 +238,70 @@ func _topmost_visible_layer(main: Node) -> Node:
return best
# ---- boot 链路时序后置条件(迭代 28 T2——装配修复后启动态六断言;只立行为可判断言,不造假时序)----
func _smoke_boot_chain() -> void:
print("--- 迭代28 T2 boot 链路时序后置条件(V2:六断言)---")
var main: Node = load("res://presentation/main.tscn").instantiate()
root.add_child(main)
await process_frame
await process_frame
# ① ConfigDB 就绪且表已载
var db = main.get_node("/root/ConfigDB")
check(db.is_ready and db.hero != null,
"V2a ConfigDB 就绪且表已载(is_ready+hero 表在座)〔装配生命批 V2〕")
# ② 设置已应用(引擎态=settings_store 现值——真实设置文件照读,一致性判据与文件内容无关)
var ss = main.settings_store
var master := AudioServer.get_bus_index("Master")
check(AudioServer.is_bus_mute(master) == (ss.volume_linear <= 0.001)
and is_equal_approx(AudioServer.get_bus_volume_db(master), linear_to_db(maxf(ss.volume_linear, 0.001))),
"V2b 设置已应用·音量(Master mute/volume_db=settings_store 现值 linear=%f)〔装配生命批 V2〕" % ss.volume_linear)
var ui_kit = load("res://presentation/views/ui_kit.gd")
check(ui_kit.motion_scale == (0.5 if ss.reduced_motion else 1.0),
"V2b 设置已应用·减动效(UiKit.motion_scale=%s=settings_store.reduced_motion=%s)〔装配生命批 V2〕" % [
str(ui_kit.motion_scale), str(ss.reduced_motion)])
# ③ 启动态菜单可见
check(main._start_overlay.visible,
"V2c 启动态 _start_overlay.visible=true(boot 后玩家见菜单)〔装配生命批 V2〕")
# ④ 续玩钮可见态==SaveManager 断点在档态
var sm = main.get_node("/root/SaveManager")
# ④-1 boot 路径:boot 时按钮态==真实档断点态(关系判据——与真实档当时内容无关)
var real_bp: bool = sm.has_breakpoint()
check(main._resume_btn.visible == real_bp,
"V2d 续玩钮 boot 态==断点在档态(visible=%s has_breakpoint=%s)〔装配生命批 V2〕" % [
str(main._resume_btn.visible), str(real_bp)])
# ④-2 隔离新档双向(attach 原地重置——绝不碰真实档 user://save.json;刷新单口与 boot 路径同源)
for p in ["user://smoke_boot_chain.json", "user://smoke_boot_chain.json.tmp"]:
if FileAccess.file_exists(p):
DirAccess.remove_absolute(p)
sm.attach_path("user://smoke_boot_chain.json")
main._refresh_resume_button()
check(not sm.has_breakpoint() and not main._resume_btn.visible,
"V2d 续玩钮·无断点态隐藏(visible=%s has_breakpoint=%s)〔装配生命批 V2〕" % [
str(main._resume_btn.visible), str(sm.has_breakpoint())])
sm.set_breakpoint({"level_index": 2, "master_seed": 42})
main._refresh_resume_button()
check(sm.has_breakpoint() and main._resume_btn.visible,
"V2d 续玩钮·有断点态可见(visible=%s has_breakpoint=%s)〔装配生命批 V2〕" % [
str(main._resume_btn.visible), str(sm.has_breakpoint())])
sm.clear_breakpoint()
main._refresh_resume_button()
check(not main._resume_btn.visible,
"V2d 续玩钮·清断点后回隐藏(visible=%s)〔装配生命批 V2〕" % str(main._resume_btn.visible))
# ⑤ 闲时会话(_ready 即建、永非 null、在树)
check(main.run_scope != null and not main.run_scope.is_adventure and main.run_scope.is_inside_tree(),
"V2e run_scope 非空且为闲时会话(is_adventure=false+is_inside_tree)〔装配生命批 V2〕")
# ⑥ DS_DEBUG 门控一致性(未设=浮窗隐藏;设了=启动即开——两侧同一判据)
var debug_on: bool = OS.get_environment("DS_DEBUG") == "1"
check(main.debug_overlay.visible == debug_on,
"V2f 调试浮窗态==DS_DEBUG 门控(visible=%s DS_DEBUG=%s)〔装配生命批 V2〕" % [
str(main.debug_overlay.visible), str(debug_on)])
main.queue_free()
await process_frame
for p in ["user://smoke_boot_chain.json", "user://smoke_boot_chain.json.tmp"]:
if FileAccess.file_exists(p):
DirAccess.remove_absolute(p)
# ---- 会话物化断言(迭代 27 T1 V3——两连局复位/无脏状态残留;原手工复位清单消亡的行为级证明)----
func _smoke_run_lifecycle() -> void:
print("--- 迭代27 T1 会话物化(V3:两连局复位+脏状态不残留)---")