get-shit-done 跨运行时安全执行:Codex 下 execute-phase 如何对不支持的 worktree 隔离 Fail-Closed
2026/9/8 23:49:37 网站建设 项目流程

get-shit-done 跨运行时安全执行:Codex 下 execute-phase 如何对不支持的 worktree 隔离 Fail-Closed

【免费下载链接】get-shit-doneA light-weight and powerful meta-prompting, context engineering and spec-driven development system for Claude Code by TÂCHES.项目地址: https://gitcode.com/GitHub_Trending/getshi/get-shit-done

导读:本文围绕 get-shit-done(GSD)一次真实修复展开 —— 变更集 .changeset/fix-3360-codex-execute-worktrees.md 记录的#3360/#3365。当 Codex 运行时配合workflow.use_worktrees=true时,因其spawn_agent没有与 Claude CodeAgent(isolation="worktree")等价的能力映射,execute-phase 工作流必须在任何执行器派发前失败关闭(fail closed),而非让本应隔离于 git worktree 的写入代理直接改动主检出。读完后你将理解跨运行时隔离语义缺口、防护在 execute-phase 工作流 中的落地代码与顺序契约,以及如何配置规避、用回归测试守住防线。

背景:execute-phase 的 wave 并行执行与 worktree 隔离

GSD 是一套轻量的规范驱动开发(spec-driven development)方法论与工作流系统。其执行阶段(execute-phase)遵循"协调者协调、不亲自执行"的核心原则:协调器(orchestrator)发现计划 → 分析依赖 → 分组为 wave → 派生执行代理 → 处理检查点 → 收集结果(见 execute-phase.md 头部<core_principle>)。

为了支撑并行执行,工作流默认依赖 git worktree 隔离:每个执行代理(gsd-executor)被派发到独立的worktree-agent-<id>工作树分支上提交,互不踩踏主检出的文件,波次结束后由协调器统一合并回主分支并清理工作树(对应 execute-phase.md 步骤 5.5 的 Worktree cleanup)。

而"子代理派发"本身是运行时特定的。execute-phase.md 的<runtime_compatibility>块 明示:

  • Claude Code:使用Agent(subagent_type="gsd-executor", ...),阻塞至完成并返回结果;
  • Copilot:子代理派发无法可靠返回完成信号,默认顺序内联执行,仅在用户明确要求时才尝试并行;
  • 其他运行时:若Agent/agent工具不可用,同样回退到顺序内联执行,且需在运行时探测工具可用性,而非按运行时名假设。

也就是说,"派发并行隔离代理"这件事,从来都依赖底层运行时提供对应原语。

# execute-phase initialize 步骤读取运行时与 worktree 配置 RUNTIME=$(gsd-sdk query config-get runtime --default claude 2>/dev/null || echo "claude") USE_WORKTREES=$(gsd-sdk query config-get workflow.use_worktrees 2>/dev/null || echo "true")

workflow.use_worktrees默认值为true(docs/CONFIGURATION.md),SDK 配置门禁同样以workflowBool(wf.use_worktrees, true)归一(sdk/src/query/config-gates.ts)。

根因:isolation="worktree"在 Codex 中没有直接映射

问题并不在 GSD 自身,而是跨运行时能力不对齐:

  • Claude CodeAgent(...)/Task(...)支持isolation="worktree"参数,派发出的代理会被放进独立 git worktree;
  • Codex把子代理统一映射到spawn_agent,而spawn_agent不会自动创建或绑定 git worktree

这条差异被固化在安装器内置的 Codex 技能适配头中。在 bin/install.js 的getCodexSkillAdapterHeader映射表 "C. Task() → spawn_agent Mapping" 里:

Task(isolation="worktree")/Agent(isolation="worktree")no direct Codex mapping。Codexspawn_agentdoes not create or bind a git worktree automatically. Workflows that require this isolation must fail closed or use an explicit manual worktree protocol before spawning (#3360)。

这正是 fix-3360-codex-execute-worktrees.md 描述的缺陷根源:若工作流仍假定"代理已被隔离"而直接派发,Codex 下这些写入型代理就会在**主检出(main checkout)**上编辑文件,产生两类风险:

  1. 多个"并行"代理同时写主检出,相互冲突;
  2. 协调器随后的 worktree 合并/清理逻辑找不到对应 worktree,陷入"以为已隔离、实则未隔离"的错误信念。

修复坚持的原则是:当无法兑现文档所承诺的隔离语义时,宁可停下报错,也不在错误假设下继续。

修复落地:任何执行器派发前的 fail-closed 守卫

修复位于 execute-phase 工作流的initialize步骤,在任何执行器派发之前先读运行时与 worktree 配置,再执行守卫:

if [ "$RUNTIME" = "codex" ] && [ "$USE_WORKTREES" != "false" ]; then echo "FATAL: Codex execute-phase worktree isolation is unsupported. Set workflow.use_worktrees=false or use a runtime with Agent isolation=\"worktree\" support." >&2 exit 1 fi # 在派发执行器之前,清扫上次崩溃会话遗留的锁定 worktree(#3707)。 [ "$USE_WORKTREES" != "false" ] && gsd-sdk query worktree.reap-orphans 2>/dev/null || true

拆解它的三个要点:

  • 条件成立才拦:仅当RUNTIME=codexUSE_WORKTREES != "false"exit 1。Codex + 显式关闭 worktree 的组合不受影响;Claude Code 等运行时完全不触发。
  • 派发前置:守卫位于initialize步骤,早于execute_waves内任何Agent()/spawn_agent调用,不做无用派发、不残留半截产物。
  • 报错可操作:FATAL 消息直接给出两条出路 —— 设workflow.use_worktrees=false,或改用支持isolation="worktree"的运行时。

工作流注释点明了"为何宁可 fail closed":

Codex maps subagents tospawn_agent, which has no direct Codex mapping for Claude Code'sisolation="worktree"parameter. Failing closed prevents main-checkout edits while the workflow believes agents are isolated.

配置规避与安全降级路径

对确需在 Codex 下运行 execute-phase 的团队,规避办法是把项目配置的workflow.use_worktrees显式置为false。依据 docs/CONFIGURATION.md:

配置项类型默认值说明
workflow.use_worktreesbooleantruefalse时关闭并行执行的 git worktree 隔离。偏好顺序执行、或环境不支持 worktree 时可关闭(v1.31 起加入)。

项目级USE_WORKTREES=false时,所有执行代理不带isolation="worktree",改在主工作树上执行;execute-phase.md 明确指出此时逐计划决策不再生效。在同波内出现"部分计划保留隔离、部分退化为顺序"的混合场景时,工作流要求退化的计划逐个串行(避免并发写主工作树),保留隔离的计划仍可并行(execute-phase.md 步骤 2.5 与混合模式说明)。

类似"按计划粒度而非一刀切"的工程取舍还出现在同一 initialize 步骤的子模块处理:从.gitmodules解析出SUBMODULE_PATHS后,仅当某计划声明的files_modified与子模块路径相交时才为其关闭隔离(执行器提交协议无法在隔离 worktree 中正确处理子模块提交),与子模块无关的计划照常并行隔离 —— 相比旧版"见.gitmodules即全局关闭",明显更精准。

回归测试:以契约锁住防护时序

为防止后续改动把守卫挪到派发之后、或删掉适配文档的映射说明,仓库提供了回归测试 tests/bug-3360-codex-execute-phase-worktrees.test.cjs。它解析工作流中的<step>块并断言:

  • initialize步骤必须读取运行时配置(含RUNTIME=$(gsd-sdk query config-get runtime --default claude);
  • initialize必须包含 Codex worktree 守卫文案(Codex execute-phase worktree isolation is unsupported);
  • 守卫步骤必须先于任何 worktree 派发指导(guardStepPrecedesWorktreeDispatch: true);
  • Codex 适配头必须记录映射缺口(同时匹配isolation="worktree"no direct Codex mapping)。

测试最终断言契约对象:

{ initializeReadsRuntimeConfig: true, initializeHasCodexWorktreeGuard: true, guardStepPrecedesWorktreeDispatch: true, }

可见测试守住的不仅是"报错文案存在",更是**"先读运行时 → 再拦 Codex worktree → 才允许派发"这一修复时序**。

发布与版本上下文

该修复经 PR #3365 合入,变更集 frontmatter 标记type: Fixed, pr: 3365。在 docs/RELEASE-v1.42.1.md 发布说明中,它被归入 "Codex install and hook migration are safer",描述为 "unsupported execute-phase worktrees are blocked";其行为依据即本变更集。若需在具体项目中验证当前是否已包含该防护,可直接查看工作流守卫段与对应回归测试是否如本文所述存在。

小结

一份寥寥数行的 changeset 背后是一整套可验证的工程防线:能力缺口写进适配映射表(bin/install.js),执行路径在最前置的initialize步骤 fail-closed(execute-phase.md),错误消息给出可操作规避方案,回归测试则把"守卫先于派发"固化为机器可校验的契约(tests/bug-3360-codex-execute-phase-worktrees.test.cjs)。对跨运行时编排系统而言,"没有隔离能力就绝不假装有隔离",比任何绕过技巧都更能保护主检出与并行执行语义的完整性。

【免费下载链接】get-shit-doneA light-weight and powerful meta-prompting, context engineering and spec-driven development system for Claude Code by TÂCHES.项目地址: https://gitcode.com/GitHub_Trending/getshi/get-shit-done

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询