首页
/ get-shit-done v1.39.0-rc.5 技术解读:Codex hooks 配置迁移加固与 --minimal 轻量安装

get-shit-done v1.39.0-rc.5 技术解读:Codex hooks 配置迁移加固与 --minimal 轻量安装

2026-09-08 15:06:35作者:裴麒琰

get-shit-done(下称 GSD)是一套面向 Claude Code / OpenCode / Gemini / Codex 等 AI 编程运行时(runtime)的 meta-prompting、上下文工程与规格驱动开发系统。本文围绕其 v1.39.0-rc.5 预发布版本说明展开,聚焦本版本在 Codex 配置迁移器(hooks migrator)上的正确性加固,并回溯 rc.4 一并带入正式版的 --minimal 轻量安装模式Codex 安装防损坏保护。读完你将能复现预发布安装流程,理解 GSD 如何安全改写 ~/.codex/config.toml 的 hooks 结构,以及如何针对小上下文窗口的本地大模型做裁剪安装。

一、版本背景:next 标签下的预发布节奏

GSD 采用严格的发布流水线:正式版发布前,先在 release 分支上产出 Release Candidate(RC),以 npm 的 next 标签对外发布,供使用者做真实环境验证。v1.39.0-rc.5 即处在这一阶段,其版本说明明确标注:

Pre-release candidate. Published to npm under the next tag.

对应的最新安装入口为:

npx get-shit-done-cc@next

需要说明的是,本仓库已演进至更高的版本号(当前 package.json 中的版本为 1.50.0-canary.0),因此这份 rc.5 说明属于历史快照。但其中涉及的安装器实现(bin/install.js)至今仍是 GSD 的核心交付物,后续版本的所有相关能力都建立在本版本打磨出的正确性地基之上。

rc.5 的内容包含两部分:一是 rc.5 本轮新增的 Codex hooks 迁移器加固(#2809);二是随 rc.4 发布、同样属于本次测试范围的 --minimal 安装标志(#2762)Codex 安装防损坏修复(#2760)

二、rc.5 核心修复:Codex hooks 迁移器的五轮加固(#2809)

2.1 背景:两层嵌套 hooks schema 迁移

Codex 0.124.0 将 hooks 配置从 map 格式迁移到 array-of-tables(AoT)格式,并且 GSD 需要把托管 hook 写成 [[hooks.<Event>]][[hooks.<Event>.hooks]] 的两层嵌套结构。安装器在每次安装/重装/卸载时都要把用户既有配置安全迁移到这一新 schema。rc.4 中的修复(#2760)已经覆盖了 [hooks.<Event>] map 格式与 [[hooks]] 扁平 AoT 格式,而 rc.5 的 #2809 则针对迁移路径上的 五个边界情形 做了收尾加固——这些情形是在五轮 code review 中逐一发现的,全部围绕"TOML 语法解析的严谨性"展开:

发现的问题 修复方式
parseHooksBody 使用裸正则 /^([\w.]+)\s*=/,会静默丢弃连字符键(如 status-message)与任何带引号的 TOML 键 替换为既有的完整 TOML 键解析器 parseTomlKey()
buildNestedBlock 无条件发射 [[hooks.TYPE.hooks]],即使没有任何 handler 字段,也会产生"只有 type = "command"、没有 command"的脏条目 增加守卫:仅含 matcher / 无 handler 字段的段只发射事件条目块
legacyMapSections 的过滤条件是 section.path.startsWith('hooks.'),未检查段数,导致 [hooks.SessionStart.hooks] 这类三段表被误判为事件条目,被当作假的嵌套事件重新发射 改为 section.segments.length === 2(与之前应用于 staleNamespacedAotSections 的修复一致)
缺少对含点号的事件名的回归测试——[[hooks."before.tool"]] 的路径是 2 段,但 split('.') 会得到 3 部分,误判其类型 补充回归测试;带引号含点名称被正确视为单个两段命名空间
安装测试中的 handler 命令路径断言使用正则(/gsd-check-update\.js/),而非精确绝对路径 强化为 assert.strictEqual + path.join(codexHome, 'hooks', 'gsd-check-update.js')

2.2 源码视角:修复为何关键

上述五项修复的本质,是 用真正的 TOML 词法解析取代字符串近似匹配。在 bin/install.js 中可以看到这一整套解析基础设施:

  • parseTomlKeyPath:逐字符解析 TOML 键路径,支持单引号/双引号键、\ 转义与点号分隔,返回语义上的段(segment)数组,例如 [[hooks."before.tool"]] 解析出 ['hooks', 'before.tool']
  • parseTomlKey:在赋值语句(含 =)上提取键名,先排除表头,再走 parseTomlKeyPath,因此 status-message 这类连字符键和 "quoted key" 都能被正确识别——这正是修复表中第一行"弃裸正则、改用 parseTomlKey"的落点;
  • 解析函数注释中明确写到了第三、四行修复的设计动机(见 parseTomlTableSection 相关注释):保留真实的段计数,避免用 split('.') 之类按点号切分的方法误判含点号的带引号键名

2.3 迁移函数的整体守卫逻辑

迁移主入口是 migrateCodexHooksMapFormat,它一次性处理三类遗留形态:

  1. map 格式的 [hooks.TYPE]legacyMapSections 过滤逻辑):要求 !section.arrayhooks. 前缀、且 section.segments.length === 2,并显式排除 Codex 的持久化 hook-trust 命名空间 hooks.state(Codex CLI 0.130.0+ 引入,永不使用 AoT 形态);
  2. 扁平的 [[hooks]] AoT 条目flatAotSections):与 [[hooks.<Event>]] 命名空间形态在同一个 TOML 文件中互斥(hooks 不能同时是数组又是表),因此按 event 键取出事件名并改写成嵌套形态;
  3. 过时的单块 [[hooks.TYPE]]staleNamespacedAotSections):事件条目级直接携带 handler 字段、却没有 [[hooks.TYPE.hooks]] 子表——这是 Codex 0.124.0+ 会拒绝的旧形态。

对于处理结果(buildNestedBlock),它先用 tomlBareKey 对事件名做键名合法性判断(凡含非 [A-Za-z0-9_-] 字符的事件名一律转成带引号键),再执行第二项修复的守卫:只有当确实存在 handler 字段时才发射 [[hooks.TYPE.hooks]] 子表,否则只发射事件条目块,从源头杜绝"有 typecommand"的半成品条目。

最后,迁移块的插入位置也遵循 TOML 语法约束(注释见 bin/install.js):map 格式块插入到首个剩余表之前以保留文件相对顺序,而扁平 AoT 块一律 追加到文件末尾——因为 AoT 不能出现在普通表之前,若插到文件头部会破坏 [features] / [model] 等的相对顺序。

2.4 代码级注意点:#3346 的防呆设计

在迁移逻辑中还有一条值得注意的细节:当遗留 [hooks.<X>] 的正文里显式声明了 event = "..." 时,以该 event 值为事件名叶子键(mapOnlyBlocks 逻辑)。原因在于 Codex pre-AoT 时代会把 <file>:<event>:<line>:<col> 这样的位置标识符写成表键,若原样把路径段当作叶子事件名发射,会产生 Codex 0.124.0+ 拒绝的非法 TOML 键链——这是安装器对"历史配置里藏着非语义键名"的又一次防御。

三、rc.4 新增能力:--minimal 轻量安装标志(#2762)

3.1 作用与适用人群

--minimal(别名 --core-only)只安装支撑主工作流闭环所需的六个核心技能:

new-projectdiscuss-phaseplan-phaseexecute-phasehelpupdate

不安装任何 gsd-* 子代理(subagent)。版本说明给出的冷启动系统提示词开销对比如下:

模式 冷启动系统提示词开销
full(默认) 约 12k tokens
minimal 约 700 tokens

这一模式针对的是 上下文窗口 32K–128K 的本地 LLM:在这类模型上,完整技能面(full surface)的固定提示词开销占比过高,裁剪到 minimal 后可以把宝贵的上下文预算让给实际任务内容。而使用 Sonnet 4.6 / Opus 4.7 的云端模型用户通常并不需要它——完整技能面才是云端模型的正确默认。

3.2 安装清单记录与升级路径

安装清单(manifest)会记录本次安装模式:

mode: "minimal" | "full"

该字段在源码中的写入位置是 writeManifest 的 manifest 对象(bin/install.js),modeoptions.mode === 'minimal' 决定。清单哈希覆盖 get-shit-done/commands/gsd/ 以及各运行时技能目录,用于后续安装时的差异检测。

由于模式被持久化记录,升级/扩容也很直接:在任意时刻运行不带 --minimalgsd update,即可把 minimal 安装扩容到完整技能面,无需重装。

3.3 实现细节与后续演进

bin/install.js 中,参数解析把 --minimal--core-only 视为等价:

const hasMinimal = args.includes('--minimal') || args.includes('--core-only');

安装器帮助文本(bin/install.js)同样声明 --minimal--profile=core 的向后兼容别名,并给出冷启动开销从约 12k 降到约 700 的效果说明;若同时传入 --minimal--profile=<name>,则直接报错退出,二者互斥。

值得注意的是,这套能力在后继版本中已演进为可组合的 profile 体系:在 get-shit-done/bin/lib/install-profiles.cjs 中,PROFILES 定义了 corestandardfull 三档(install-profiles.cjs),支持 --profile=core,audit 取并集的组合安装;MINIMAL_SKILL_ALLOWLIST 直接由 PROFILES.core 派生(install-profiles.cjs)。当前仓库中的 core 档已包含 8 个技能(在 rc.4 的 6 个基础上并入 phasesurface 等),且安装器会记录 profile 并让 gsd update 尊重该选择——这是 rc.4 时代"6 技能严格白名单"向后兼容的自然延伸。

四、rc.4 防御性修复:Codex 安装不再损坏 ~/.codex/config.toml(#2760)

--minimal 之外,rc.4 的另一项重头戏是让 Codex 安装具备"要么成功、要么完好回滚"的事务性语义。版本说明列出的安装器行为包括:

  • 无条件清除遗留的 [agents](单括号)与 [[agents]](sequence)块——无论是否存在 GSD 标记,这两者在当前 Codex TOML schema 中都非法;
  • 沿用用户既有配置形态发射 GSD 托管 hook:若既有配置使用 [[hooks.<Event>]] 命名空间 AoT 形态则沿用之,否则写顶层 [[hooks]]
  • 迁移过程中把遗留 [hooks.<Event>](map 格式)改写为 [[hooks.<Event>]](数组格式)
  • 原子写入:先写临时文件再 renameSync,杜绝半截写入;
  • 写后校验:用严格 TOML 解析器验证写后字节,拒绝重复键、重复表头、值后的尾随字节以及不支持的值类型;
  • 失败回滚:任何写前或写时失败都会恢复安装前快照并以清晰错误中止,而不是"警告后继续"。

这些行为并非纸面承诺,tests/bug-2760-codex-install-defensive.test.cjs 对其做了成体系的回归验证,覆盖场景包括:全新安装发射两层嵌套 AoT schema、保留用户既有 [[hooks.SessionStart]] 条目同时把 GSD 托管 handler 注册进 hooks.json、重装时把扁平 [[hooks]] + event 与单块 [[hooks.SessionStart]](无 .hooks 子表)统一替换为嵌套 schema、卸载后残留状态校验、以及空配置文件的合法性校验。

针对"破坏文件"这一最坏情形,测试还专门模拟了写入失败路径:

  • fs.renameSyncconfigPath 抛错时,断言安装前配置字节原样保留;
  • 当对 .tmp- 目标执行 fs.writeFileSync 抛错时,同样断言快照恢复且无 .tmp- 残留文件(见该测试文件中 #2760 fix 4 — Write-failure rollback (atomic write + snapshot restore) 一节)。

由此,Codex 安装被收敛为一个可证明的原子操作:破坏性写入之前先留快照,写入失败立即还原,写入成功后还有严格 schema 校验兜底

五、rc.5 修复在回归测试中的落点

rc.5 表里第五行提到"handler 命令路径断言改用精确绝对路径",这类测试断言的强化同样可以在仓库中找到对应物。Codex hooks 形态的安装/重装/卸载端到端断言大量出现在 bug-2760-codex-install-defensive.test.cjs 中,其中对 gsd-check-update.js 处理器的校验通过 path.join(codexHome, 'hooks', 'gsd-check-update.js') 组合出的绝对路径来 assert.strictEqual 精确比对,避免正则把相似路径误判为合法安装。rc.4→rc.5 的治理逻辑一脉相承:先让解析器严格,再让测试严格,两端都堵住"看起来对、实际错"的漏洞。

六、安装与验证预发布版本

若你需要在支持 next 标签期间验证该预发布:

# npm 全局安装 next 标签下的最新 RC
npm install -g get-shit-done-cc@next

# npx 一次性执行(不落盘全局)
npx get-shit-done-cc@next

精确锁定本 RC:

npm install -g get-shit-done-cc@1.39.0-rc.5

对安装了 Codex 的用户,建议在升级前备份 ~/.codex/config.toml,安装后留意安装器是否按"既有形态"写回 hook;对本地小上下文模型用户,可用 --minimal(或 --core-only)体验裁剪安装,随后任意时刻运行不带该标志的 gsd update 即可扩容到完整技能面。

七、发布流水线中的"接下来"

按照版本说明,rc.5 之后的发布管理动作完全由发布流水线驱动:

  • 若在正式定稿前还有新修复落入 release 分支,则在发布分支上再次执行 rc,产出 rc.6;
  • 当 RC 稳定后,在 release workflow 上执行 finalize,将 1.39.0 提升到 npm latest 标签。

这种"RC 滚动 + finalize 晋升"的机制保证了正式版只会携带经过多轮审查、且被严格 TOML 解析与故障注入测试覆盖的变更——rc.5 对 Codex hooks 迁移器的五处修复,正是这种质量闸门发挥作用的具体样本。

八、小结:从一次 RC 看安装器的工程底线

v1.39.0-rc.5 体量虽小,却浓缩了安装器类工程最重要的三条原则:

  1. 解析要语义化,不做字符串近似:TOML 键含连字符、引号、点号是常态,只有走 parseTomlKey 这类词法级解析,才能保证迁移不丢键、不误判段(install.js);
  2. 写入要原子化,失败要可回滚:临时文件 + renameSync + 写后严格校验 + 快照恢复,让安装要么改变一切、要么什么都不改变;
  3. 覆盖面要按运行时取舍--minimal 与 profile 体系让"全量技能面"与"低冷启动开销"不再互斥,而是同一安装器在不同上下文预算下的可切换姿态。

对需要深度定制或审计安装器的开发者,bin/install.jsget-shit-done/bin/lib/install-profiles.cjs 及其回归测试 bug-2760-codex-install-defensive.test.cjsinstall-minimal-hooks.test.cjs 是值得逐行研读的范本。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391