- 机制: tools/setup_worktree_userdir.sh 在建区后生成 game/override.cfg(use_custom_user_dir + 唯一名 DungeonSweeper_<区名>_<绝对路径 sha1 前 8>), 主工作区 no-op 保持真实档原位; .gitignore 收 game/override.cfg - 闸壳: run_all_gates.sh 参数解析后先自检/自愈本区隔离, 建不起来 exit 1(fail-closed)——并行批共用一套夹具/日志/截图目录会互相踩盘, 是假红的根源 - 读取面: 新增 tools/godot_user_dir.py 统一解析(有 override→custom dir, 无→默认 appdata/Godot/app_userdata/<config/name>); parity_anchor.py 与 analyze_playtest.py 的硬编码 APPDATA 路径改为调用它 - 流程: process-conventions §1 第 1 条(建区即跑 setup)与 §3 环境基线第 4 条(闸壳自检); iter 技能冷检出三件套→四件套(.zcode/.qoder 两份本机副本已同步, 不入 git) - 系统测试 V3d: 隔离后空 user 目录(无 settings.cfg)使 reduced_motion 取默认 false, 实查暴露 V3d 真实缺陷——测试同步驱动整场战斗后同帧 flush, RowPacer._was_pumping 从未置真, 演播后排窗的 pump_ended 边沿不触发, _end_overlay 永不打开; 旧绿只因本机 settings.cfg reduced=true 让排播走 consume_now 快路绕过队列。补一帧 await process_frame 让泵先观测到非空队列再 flush, 恢复真实边沿路径 - 取证: 隔离空目录下 00 冒烟 17/17、02 单元与集成 62 套全绿、03 探针 --click 全绿; 01 系统测试修正前 70/1 红(仅 V3d)、修正后 reduced=true 与 false 两档均 70/70 绿
27 lines
1.2 KiB
Python
27 lines
1.2 KiB
Python
"""解析 Godot 的 user:// 根目录——与 game/override.cfg 的隔离口径同一份。
|
||
|
||
无 override.cfg(主工作区)→ %APPDATA%/Godot/app_userdata/<project.godot 的 config/name>;
|
||
有 override.cfg(代码面 worktree,由 tools/setup_worktree_userdir.sh 生成)→ %APPDATA%/<custom_user_dir_name>。
|
||
"""
|
||
import os
|
||
import re
|
||
from pathlib import Path
|
||
|
||
|
||
def _project_name(repo_root: Path) -> str:
|
||
text = (Path(repo_root) / "game" / "project.godot").read_text(encoding="utf-8", errors="replace")
|
||
m = re.search(r'^config/name="([^"]*)"', text, re.M)
|
||
return m.group(1) if m else "DungeonSweeperVerticalSlice"
|
||
|
||
|
||
def resolve_user_dir(repo_root: Path) -> Path:
|
||
base = Path(os.environ.get("APPDATA") or (Path.home() / "AppData" / "Roaming"))
|
||
override = Path(repo_root) / "game" / "override.cfg"
|
||
if override.is_file():
|
||
text = override.read_text(encoding="utf-8", errors="replace")
|
||
custom = re.search(r'^config/use_custom_user_dir=true\s*$', text, re.M)
|
||
name = re.search(r'^config/custom_user_dir_name="([^"]*)"', text, re.M)
|
||
if custom and name and name.group(1):
|
||
return base / name.group(1)
|
||
return base / "Godot" / "app_userdata" / _project_name(Path(repo_root))
|