首页
/ gstack 模型行为补丁机制:以 gpt-5.4 覆盖层为例解析 Skill 前导注入链

gstack 模型行为补丁机制:以 gpt-5.4 覆盖层为例解析 Skill 前导注入链

2026-09-06 14:36:50作者:伍霜盼Ellen

gstack 的 model-overlays/ 目录为不同模型家族提供差异化的"行为补丁"(Behavioral Patch)。本文以 model-overlays/gpt-5.4.md 为主体,完整解读其"反冗长协议"(Anti-verbosity protocol)的规则设计,并顺着 解析器实现模型分类模块前导组装代码 讲清这个 15 行的小文件是如何被匹配、继承、拼装进每个 Skill 的系统提示词中生效的。读完后,你将掌握 gstack 的模型轴(model axis)设计:从 --model 参数解析到最终渲染出的 ## Model-Specific Behavioral Patch 区块的完整调用链。

一、gpt-5.4 覆盖层做了什么:完整的反冗长协议

model-overlays/gpt-5.4.md 全文只有 15 行,但每一行都是针对 GPT-5.4 这一具体模型家族的输出行为约束。它的结构分为两部分:

第一部分:继承声明。 文件第一行是 {{INHERIT:gpt}} 指令——这表示 gpt-5.4 的补丁不是从零开始写的,而是在整个 model-overlays/gpt.md(GPT 家族基座)之上追加差异条款,避免逐字重复。这是 gstack 覆盖层体系的"模板继承"语法。

第二部分:附加的反冗长协议。 文件的正文开宗明义——"Your default output mode is too verbose for tools that value terse output. Constrain:"(你的默认输出模式对看重简洁输出的工具来说太冗长了,请约束如下),随后给出六条硬约束:

  1. 状态更新:一行,不是一段。(Status updates: one line, not a paragraph.)
  2. 代码解释只在两种情况下出现:用户主动要求解释,或者代码本身确实反直觉、令人惊讶。
  3. 不要叙述你即将做什么,直接做。(Do not narrate what you are about to do. Just do it.)
  4. 不要把用户的请求复述回去。(Do not repeat the user's request back to them.)
  5. 展示代码变更时,只展示改动行加最小必要上下文。
  6. Markdown 标题不是装饰,只有结构性需要时才使用。

最后还有一条总纲式规则:"Cap answers at the shortest form that contains the answer."(把回答压缩到仍包含答案的最短形式)——如果答案本身就是一条命令,就只回复那一条命令。

这些条款与 gpt.md 基座的内容是互补的。gpt.md 解决的是"完成度偏向"(Completion bias:能修就修完、不要停在半成品)与"做优先于列"(Prefer doing over listing:与其罗列"你可以试试 X、Y、Z",不如自己选一个执行并汇报结果),而 gpt-5.4.md 追加的则是"输出体量偏向"——同一模型家族,不同版本号在输出风格上的已知缺陷不同,补丁就不同。这正是覆盖层按版本细分(gpt 家族基座 + gpt-5.4 版本特化)的设计动机。

二、继承语法如何解析:readOverlay 的递归与保护机制

{{INHERIT:xxx}} 不是文档装饰,而是由 scripts/resolvers/model-overlay.ts 中的 readOverlay() 函数在模板渲染期真正执行的指令。核心逻辑(model-overlay.ts#L25-L44)可以归纳为四条优先级规则:

  1. 精确匹配ctx.model === 'gpt-5.4' 时读取 model-overlays/gpt-5.4.md
  2. INHERIT 指令:如果文件首个非空行匹配正则 /^\s*\{\{INHERIT:([a-z0-9-]+(?:\.[0-9]+)*)\}\}\s*\n/(第 25 行),则先递归读取被继承文件(这里是 gpt.md),再把基座内容拼在本文件剩余内容之前。源码注释直接点明了用途:"This lets gpt-5.4.md build on top of gpt.md without duplication."(第 10 行)
  3. 文件缺失:返回空字符串,优雅降级、不报错。
  4. 未设置 ctx.model:同样返回空字符串。

readOverlay 还带一个 seen 集合做循环引用保护(第 28 行 if (seen.has(model)) return ''; // cycle guard)——如果继承链里出现 a.md 继承 b.mdb.md 又继承 a.md 的环,解析会在环上截断而不是死循环。对于 gpt-5.4 这条链,最终产物就是"gpt.md 全文 + 空行 + 反冗长协议全文"的拼接。

三、渲染产物:附从性包装头与 gpt-5.6-sol 特例

解析出内容后,generateModelOverlay()model-overlay.ts#L46-L70)把裸文本包进一个带优先级的标准区块:

## Model-Specific Behavioral Patch (gpt-5.4)

The following nudges are tuned for the gpt-5.4 model family. They are
**subordinate** to skill workflow, STOP points, AskUserQuestion gates, plan-mode
safety, and /ship review gates. If a nudge below conflicts with skill instructions,
the skill wins. Treat these as preferences, not rules.

(此处为 gpt.md + gpt-5.4.md 拼接后的完整内容)

注意这个包装头里的关键语义:模型补丁是"偏好"而非"规则",凡与 Skill 工作流、STOP 点、AskUserQuestion 门、plan-mode 安全、/ship 审查门冲突时,Skill 指令一律胜出。附从性声明被放在包装头里而不是各文件内部,保证无论覆盖层文件内容怎么写,优先级语义都恒定存在。

源码里还有一个值得注意的特判:当模型是 gpt-5.6-sol 时(第 52-59 行),包装头改用另一套措辞,声明该补丁专门消解 "complete / full / every / exhaustive / 100% / Boil the Ocean" 这类歧义完备性词汇的作用域边界——这与 model-overlays/gpt-5.6-sol.md 中"用户显式任务就是湖(The explicit task is the lake)"的条款一一对应。对比之下,gpt-5.4 走的是通用的"subordinate nudges"措辞。

四、模型名如何落到 gpt-5.4:分类模块与家族启发式

ctx.model 从哪来?scripts/models.ts 定义了 gstack 的完整模型分类(第 18-29 行):claudeopus-4-7fable-5opus-4-8sonnet-5gptgpt-5.4gpt-5.6-solgeminio-series 共 10 个家族,且模型轴与宿主轴(Claude Code / Codex CLI / Cursor 等)相互独立——Claude Code 可以跑任何 Claude 模型,Codex CLI 跑 GPT/o 系列模型。

resolveModel()models.ts#L51-L76)把用户传入的原始模型 ID 归一化到家族名,规则是"精确匹配优先 + 家族启发式兜底":

  • 输入与 ALL_MODEL_NAMES 精确相等时直接返回。这是 gpt-5.6-sol唯一进入路径——源码注释明确警告"不要给 Sol 加家族模式",因为 Terra、Luna 及其他 5.6 变体、带后缀的模型 ID 都不应继承 Sol 的行为画像;
  • 启发式规则:gpt-5.4-minigpt-5.4-turbo 等任何 gpt-5.4-* 后缀变体 → 归入 gpt-5.4 家族,从而命中本文主角这份覆盖层;其余 gpt-* → 归入 gpto3/o4/o1-pro 等 → o-seriesclaude-* → 对应 Claude 家族;gemini-*gemini
  • 未知输入返回 null,由调用方决定报错或回退。

模型来源上,用户可以在生成时显式传 --model;不传则各宿主用自己的默认值。一个特例是 scripts/resolve-codex-generation-model.ts./setup 脚本会从 ${CODEX_HOME:-~/.codex}/config.toml 里探测 Codex 的 model = "..." 配置项并作为显式 --model 传入——所以 Codex 用户只要把 config.toml 里的模型写成 gpt-5.4,gstack 生成出的 Skill 文档就会自动带上本文讨论的这份反冗长补丁。

五、注入位置:前导组装顺序决定了补丁的"环境音"

覆盖层最终被拼进 Skill 的系统提示词前导(preamble)。scripts/resolvers/preamble.ts 第 108-114 行的段落顺序与注释值得逐字读:

AskUserQuestion Format renders BEFORE the model overlay so the pacing rule is the ambient default; the overlay's behavioral nudges land as subordinate patches. Opus 4.7 reads top-to-bottom and absorbs the first pacing directive it hits; reversing this order regresses plan-review cadence (v1.6.4.0 bug).

即:AskUserQuestion 的完整格式规则(Re-ground / ELI10 简化 / RECOMMENDATION: 独立行 / 带完备度打分的选项)必须先于模型覆盖层渲染,这样"逐题提问的节奏规则"先成为环境默认值,覆盖层的行为补丁才以附从身份落下。这段注释同时承认了模型行为的现实:像 Opus 4.7 这样的模型"从上往下读,吸收它撞上的第一条节奏指令",顺序反了就会回归缺陷——而 CHANGELOG.md 中记录的 v1.6.4.0 回归正是 generateModelOverlay 曾渲染在 generateAskUserFormat 上方、导致覆盖层的"批量提问"指令抢跑成默认值,靠重排节数组修复。这也解释了为什么 gpt.md 里专门声明"AskUserQuestion is NOT preamble"——简洁类约束(包括 gpt-5.4 的反冗长协议)不得压缩决策简报的完整格式。

另外从源码结构看,覆盖层的渲染没有 tier 门槛(不像 generateAskUserFormat 只在 tier >= 2 时出现),说明只要 ctx.model 被解析且对应文件存在,任何 tier 的 Skill 都会携带这份模型补丁。

六、测试证据:gpt-5.4 补丁进入了哪些验证链路

仓库测试对这条注入链有多处固化验证,可作追溯入口:

  • test/codex-e2e-plan-format.test.ts 的 touch 文件映射把 model-overlays/gpt.mdmodel-overlays/gpt-5.4.md 同时列为 codex-plan-ceo-format-mode 等 Codex 端到端用例的影响面——当这两份文件任一变更时,plan-ceo/plan-eng 的提问格式端到端测试必须重跑,直接证明 gpt-5.4 补丁参与 Codex 宿主的实际行为验证;
  • test/codex-model-probe.test.ts 模拟了 Codex 在 config.toml 配置 model = "gpt-5.4" 但账号无权限时的探测与降级路径;
  • 同目录还有针对其他家族覆盖层的对称测试(如 test/model-overlay-opus-4-7.test.tstest/model-overlay-gpt-5.6-sol.test.ts),验证 generateModelOverlay 在各模型下的渲染不变量——gpt-5.4 与它们共享同一套 readOverlay 逻辑,测试基础设施一致。

七、小结:一个 15 行文件背后的工程取舍

gstack 对模型差异化的答案是"轻量行为补丁 + 严格附从性",而非重写提示词。以 model-overlays/gpt-5.4.md 为样本可以看到三层设计:

  1. 内容层:每条规则都指向一个可观测的输出行为(状态更新行数、是否复述请求、代码 diff 的上下文宽度),且以"最短形式包含答案"作总上限,约束可执行、可检验;
  2. 结构层{{INHERIT:gpt}} 让版本特化只写增量,基座条款单点维护,继承链带环保护与缺失降级;
  3. 集成层:包装头强制"Skill 胜出"的优先级语义,preamble 中的节顺序保证节奏规则先于补丁成为默认值,模型名解析(精确匹配 + 后缀启发式)确保 gpt-5.4-* 变体都能命中同一份补丁。

如果你想继续深入,建议从 scripts/resolvers/model-overlay.ts 全文(约 70 行)读起,再对照 model-overlays/ 目录下其余九个家族文件,比较不同模型的行为画像差异。

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