Files
gplan-2/tools/probe_gate.sh
T

143 lines
7.6 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 轻闸探针正主(2026-10-02 挂死灾害批落籍)——headless 安全段固化,禁再手拼同款 Godot 命令。
# 三闸:①每段 timeout 守卫(挂死=FAIL 不静默)②段前预清+段后清本 game 目录孤儿 Godot
# (按命令行精确匹配本 game 路径,不误杀其他 worktree 会话的合法进程)③末尾残留清点=批末闸(必须 0)。
# 段:ui_input_probe=默认必跑;ui_struct_probe=默认必跑(ui-struct-probe mini-loop 2026-10-05 注册——
# 全 UI 屏结构断言:按钮互压/等宽/出屏/零尺寸/标题屏双列);ui_contrast_probe=默认必跑(UI 设计对齐批
# T2 2026-10-06 注册——UI 文字对比度机检 ≥4.5:1 无区域例外,测点表随批维护);--click=加跑 ui_click_probe 行为走查
# (自退出+退出码闸;超时多半=探针未适配新停点层,归 probe适配批)。
# --full 段(迭代 19 卡① T3 收编 2026-10-08——重闸件):ui_probe/ui_tune_probe/t17_defer_probe/fx_probe
# 四件带断言探针收进(此前游离在一切闸外只能手敲);轻闸默认段断言面零删减零改动(--full 只增不改)。
# 渲染面归 render_gate.sh 正主(窗口化:shot_probe 七屏+fx_shot/board_shot 取证+棋盘 golden 逐像素)——
# 旧头注「shot_probe 禁入本闸……归真人目检」纪律句随三闸口径扩容改写退役(2026-10-07 用户授权=历史偷懒标记)。
# 用法: tools/probe_gate.sh [game目录] [--click] [--full] 缺省 game 目录=脚本所在仓库的 game/(worktree 内自动指向该 worktree)
# 依赖: Git Bash(coreutils timeout/taskkill) + PowerShell;Godot 路径可用环境变量 GODOT_BIN 覆盖。
set -u
G="${GODOT_BIN:-/d/code/godot/Godot_v4.7.2-stable_win64_console.exe}"
REPO="$(cd "$(dirname "$0")/.." && pwd)"
GAME=""; WITH_CLICK=0; WITH_FULL=0
for a in "$@"; do
case "$a" in
--click) WITH_CLICK=1 ;;
--full) WITH_FULL=1 ;;
*) GAME="$a" ;;
esac
done
GAME="${GAME:-$REPO/game}"
GAME_WIN="$(cygpath -m "$GAME")" # Godot --path 需 Windows 形式
TMP="$(mktemp -d /tmp/probegate_XXXXXX)"
trap 'rm -rf "$TMP"' EXIT
_rc=0
orphans() { # 列出命令行含本 game 路径的 Godot 进程 PID(console wrapper+真引擎都算)
printf "Get-CimInstance Win32_Process -Filter \"Name like 'Godot%%'\" | Where-Object { \$_.CommandLine -like '*%s*' } | ForEach-Object { \$_.ProcessId }\n" "$GAME_WIN" > "$TMP/k.ps1"
powershell -NoProfile -ExecutionPolicy Bypass -File "$(cygpath -w "$TMP/k.ps1")" 2>/dev/null | tr -d '\r'
}
kill_orphans() {
local p; for p in $(orphans); do taskkill //F //PID "$p" >/dev/null 2>&1; done
}
# 冷检出刷导入(.godot 不入 git,fresh worktree 首跑一次性付)
if [ ! -f "$GAME/.godot/uid_cache.bin" ]; then
echo "[probe_gate] 冷检出:editor --quit 刷导入(一次性,可到 1-2 分钟)"
timeout 300 "$G" --headless --path "$GAME_WIN" --editor --quit >/dev/null 2>&1
kill_orphans
fi
pre="$(orphans | wc -l | tr -d ' ')"
if [ "$pre" -gt 0 ]; then echo "[probe_gate] 预清本闸残留 Godot×$pre"; kill_orphans; fi
echo "======== ui_input_probe ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://smoke/ui_input_probe.tscn >"$TMP/uip.log" 2>&1
st=$?; kill_orphans
grep -E "PASS|FAIL|问题" "$TMP/uip.log" | head -12
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
echo "[probe_gate] FAIL — ui_input_probe 超时挂死(exit=$st),孤儿已清"; _rc=1
elif ! grep -q "PASS" "$TMP/uip.log"; then
echo "[probe_gate] FAIL — ui_input_probe 未见 PASS(exit=$st)"; _rc=1
fi
echo "======== ui_struct_probe ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://smoke/ui_struct_probe.tscn >"$TMP/stp.log" 2>&1
st=$?; kill_orphans
grep -E "PASS|FAIL" "$TMP/stp.log" | head -12
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
echo "[probe_gate] FAIL — ui_struct_probe 超时挂死(exit=$st),孤儿已清"; _rc=1
elif ! grep -q "PASS" "$TMP/stp.log"; then
echo "[probe_gate] FAIL — ui_struct_probe 未见 PASS(exit=$st)"; _rc=1
fi
echo "======== ui_contrast_probe ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://smoke/ui_contrast_probe.tscn >"$TMP/ctp.log" 2>&1
st=$?; kill_orphans
grep -E "PASS|FAIL" "$TMP/ctp.log" | head -12
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
echo "[probe_gate] FAIL — ui_contrast_probe 超时挂死(exit=$st),孤儿已清"; _rc=1
elif ! grep -q "PASS" "$TMP/ctp.log"; then
echo "[probe_gate] FAIL — ui_contrast_probe 未见 PASS(exit=$st)"; _rc=1
fi
if [ "$WITH_CLICK" -eq 1 ]; then
echo "======== ui_click_probe 行为走查 ========"
timeout 240 "$G" --headless --path "$GAME_WIN" res://smoke/ui_click_probe.tscn >"$TMP/clk.log" 2>&1
st=$?; kill_orphans
grep -E "click_probe" "$TMP/clk.log" | tail -4
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
echo "[probe_gate] FAIL — ui_click_probe 超时(exit=$st):挂死或探针未适配新停点层(归 probe适配批),孤儿已清"; _rc=1
elif [ "$st" -ne 0 ]; then
echo "[probe_gate] FAIL — ui_click_probe 退出码=$st(done=false 或 问题>0)"; _rc=1
fi
fi
# ── --full 收编段(迭代 19 卡① T3 2026-10-08——四件带断言探针入闸;实测时长 ui_probe 17.4s/
# ui_tune_probe 49.6s/t17_defer_probe 63.0s/fx_probe 21.9s,timeout 120=2-7×余量) ──
if [ "$WITH_FULL" -eq 1 ]; then
echo "======== ui_probe(--full 收编) ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://smoke/ui_probe.tscn >"$TMP/flp.log" 2>&1
st=$?; kill_orphans
grep -E "\[ui_probe\]" "$TMP/flp.log" | tail -2
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
echo "[probe_gate] FAIL — ui_probe 超时挂死(exit=$st),孤儿已清"; _rc=1
elif ! grep -q "PASS" "$TMP/flp.log"; then
echo "[probe_gate] FAIL — ui_probe 未见 PASS(exit=$st)"; _rc=1
fi
echo "======== ui_tune_probe(--full 收编) ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://smoke/ui_tune_probe.tscn >"$TMP/flt.log" 2>&1
st=$?; kill_orphans
grep -E "\[tune_probe\]" "$TMP/flt.log" | tail -2
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
echo "[probe_gate] FAIL — ui_tune_probe 超时挂死(exit=$st),孤儿已清"; _rc=1
elif ! grep -q "PASS" "$TMP/flt.log"; then
echo "[probe_gate] FAIL — ui_tune_probe 未见 PASS(exit=$st)"; _rc=1
fi
echo "======== t17_defer_probe(--full 收编) ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://smoke/t17_defer_probe.tscn >"$TMP/fld.log" 2>&1
st=$?; kill_orphans
grep -E "\[t17_defer\]" "$TMP/fld.log" | tail -2
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
echo "[probe_gate] FAIL — t17_defer_probe 超时挂死(exit=$st),孤儿已清"; _rc=1
elif ! grep -q "PASS" "$TMP/fld.log"; then
echo "[probe_gate] FAIL — t17_defer_probe 未见 PASS(exit=$st)"; _rc=1
fi
echo "======== fx_probe(--full 收编) ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://smoke/fx_probe.tscn >"$TMP/flx.log" 2>&1
st=$?; kill_orphans
grep -E "\[fx_probe\]" "$TMP/flx.log" | tail -2
if [ "$st" -eq 124 ] || [ "$st" -eq 137 ]; then
echo "[probe_gate] FAIL — fx_probe 超时挂死(exit=$st),孤儿已清"; _rc=1
elif ! grep -q "PASS" "$TMP/flx.log"; then
echo "[probe_gate] FAIL — fx_probe 未见 PASS(exit=$st)"; _rc=1
fi
fi
echo "======== 残留检查(批末闸) ========"
left="$(orphans | wc -l | tr -d ' ')"
total="$(tasklist 2>/dev/null | grep -ci '^Godot' || true)"
echo "本闸残留 Godot=$left(必须0) 全局 Godot 进程=$total(其他会话的仅报数不算账)"
if [ "$left" -ne 0 ]; then echo "[probe_gate] FAIL — 本闸残留未清零"; kill_orphans; _rc=1; fi
if [ "$_rc" -eq 0 ]; then echo "[probe_gate] 全绿"; else echo "[probe_gate] 存在 FAIL,见上"; fi
exit "$_rc"