修复AGC的macOS临时路径兼容 (#125)
规范化配置回归测试的临时根路径 补充跨平台路径比较技术说明与踩坑记录 Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/125 Co-authored-by: menghao <mh18530625731@163.com> Co-committed-by: menghao <mh18530625731@163.com>
This commit was merged in pull request #125.
This commit is contained in:
@@ -3703,6 +3703,7 @@
|
||||
- 处理:GUI 与 `npm run agc:config` 共用系统 AppData `game-creator.config.json`,终端隐藏输入 API Key 并禁止 `--api-key`;更新时保留 `agentLlm`、`editorApi`、`mcpServers` 等其它配置,POSIX 权限维持目录 `0700` / 文件 `0600` 并原子替换。显式 `--config-dir` 必须以 `world.genarrative.ai-game-creator` 为独立叶目录,不能让向导对 `/tmp`、AppData 根或共享目录整体 chmod / 重建 DACL。隐藏输入调用 `stdin.resume()` 后必须记住原 pause 状态,在成功、取消、异常和 `SIGINT / SIGTERM / SIGHUP` 路径恢复 raw mode 并 `pause()`,信号恢复后重发;只移除 `data` listener 会让 `--configure-only`、配置检查失败或 Ctrl+C 保持活动 stdin。缺配置时仅 TTY 人工会话可询问进入向导,非 TTY 立即失败并提示配置命令。
|
||||
- Windows 密钥复制:`mode: 0o600` 和 POSIX `chmod` 在 Windows 上不能代替 DACL。隔离 AppData 目录必须先设置仅当前用户、禁止继承的 DACL;目标配置文件先以空文件创建并收紧 DACL,之后才允许把 API Key 字节写入。先 `copyFile` 再依赖 Rust 只读检查或事后收紧会留下密钥暴露窗口,也可能因继承 ACL 不满足 Runtime 合同而在首次 `--llm-status` 失败。
|
||||
- Windows PowerShell 参数:不要把 DACL 目标路径和目录标记直接追加在 `powershell.exe -Command <script>` 后;Windows Node `spawn` 会让 PowerShell 5.1 把这些值拼入命令文本,带空格的临时路径会被拆分并使 `GetFullPath($args[0])` 失败。当前实现只通过子进程私有环境变量传入路径和布尔值,并由真实 Windows `npm run agc:typecheck` 覆盖 DACL 回归。
|
||||
- 跨平台临时路径比较:macOS 的 `os.tmpdir()` 可返回 `/var/folders/...`,而 `realpath` 会返回同一目录的 `/private/var/folders/...`;Windows 也可存在驱动器号大小写、junction 或链接解析差异。测试安全路径函数时,fixture 期望值必须基于平台原生 `realpath` 后的根目录构造,不能直接与 `mkdtemp` 的逻辑路径字符串严格比较。不能只依赖开发机自带的路径别名;CI 应创建真实父目录、指向它的符号链接(Windows 使用 junction)和不存在的叶目录,断言安全函数返回真实父目录下的叶路径。`realpath` 和全部断言都应放在 `try/finally` 内,确保失败也能清理 fixture。
|
||||
- 超时与进程树:`setTimeout` 后只对直接 Cargo PID 调一次 `kill()` 不是硬超时;Cargo 启动的 CLI / Runner 仍可能持有 stdio,使 `close` 永远不返回,清理阶段也可能无界等待。POSIX 必须创建独立进程组并按负 PID 终止,Windows 必须使用 `taskkill /T`;宽限期后升级强杀,Runner shutdown 和清理另设短硬超时。重复 Ctrl+C 也必须升级,不能一直被自定义 signal handler 吞掉。
|
||||
- 模式拆分:自动化使用默认的 `agc:test:chat`,由脚本投递固定植物塔防需求;正式产物、最新 revision 静态检查和 Runtime 浏览器验收通过后立即收束并清理,不启动持续 preview。`agc:test:chat:manual` 不注入 `--task`,用于多轮 stdin 手工聊天,并保留 preview 直到显式退出;不能用 EOF 或是否存在 `game/index.html` 猜测当前模式。
|
||||
- 验证:覆盖 `--api-key` 拒绝、各平台 AppData 路径、Provider 预设、旧配置节点保留、URL 安全校验、原子写入、POSIX 权限、隐藏输入恢复 pause、Windows 写密钥前 DACL、整棵进程树超时终止、缺配置时 TTY / 非 TTY 分支,以及 `--task` 成功后不进入长期 preview、手工模式仍可持续试玩。测试和错误输出只验证“密钥已配置”状态,不读取或打印密钥本体;源码字符串断言和 Linux 上的 Windows mock 不能替代真实 Windows ACL / `taskkill` 复验。
|
||||
@@ -3863,6 +3864,7 @@
|
||||
- 根因:旧实现调用 `start_local_game_preview` 前就把“项目 + parent run”的授权加入 attempted 集合并清空;首版完成投影与后续专业任务仍在写项目时,启动恰逢项目写锁竞争,catch 只显示错误却无法重试。
|
||||
- 约束:一次性语义应按“成功或确定性终态”消费,不按“函数调用次数”消费。项目写锁竞争保留同一授权并轮询重试;成功、显式 deny 与非瞬时失败才清除。授权需持久化项目路径和 accepted runId,重启恢复时仍必须逐项匹配,切换项目不得继承。
|
||||
- 回归:AppSurface 模拟第一次 `start_local_game_preview` 返回 `项目正在被其他写操作占用`、第二次成功,断言最终渲染游戏区域且启动调用恰为两次;完整 AppSurface 仍需覆盖显式 deny、停止隐藏与项目切换隔离。
|
||||
- CI 时序:生产预览状态每 `1000ms` 轮询一次,回归若也使用 `waitFor` 默认 `1000ms` 上限,会在 CI 负载下于首次 interval 回调附近竞争超时。验证“授权保留期间仍继续轮询”应使用明确 `3000ms` 上限,不改生产轮询周期。合并长测试文件后还要运行全量 ESLint;单纯 autofix 只会排序、不会消除两个分支同时引入的重复 import。
|
||||
|
||||
## 跨窗口 CAS 锁不能用 mtime stale 删除模拟系统互斥(2026-07-30)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user