gstack 模型覆盖层深度解析:opus-4-8.md 行为补丁的继承链、注入机制与验证闭环
本篇技术文章以 model-overlays/opus-4-8.md 为核心对象,完整解读 gstack(Garry Tan 的 Claude Code 工具集)中“模型行为补丁”的设计思想:这个文件如何继承 claude 基础层、如何通过模板解析器注入到每个 skill 会话的 preamble 中、以及它如何被单元测试和 A/B 评测双重锁定。读完后你能掌握 gstack 中模型轴(model axis)与宿主轴(host axis)解耦的机制,并学会为自己的模型家族编写带继承链的行为覆盖层。
一、什么是模型覆盖层(Model Overlay)
gstack 的 23 个 skill 在每次运行时都会生成一段“前置引导(preamble)”,其中包含一个按模型家族定制的行为补丁(Behavioral Patch)。不同模型对指令的敏感度和“通病”不同——例如 Opus 4.8 倾向于逐字面执行指令、对简单步骤也可能过度思考。覆盖层文件就是针对这些已知行为偏差写的“纠偏文案”。
模型家族的分类定义在 scripts/models.ts 中,当前支持的完整列表为:
claude、opus-4-7、fable-5、opus-4-8、sonnet-5、
gpt、gpt-5.4、gpt-5.6-sol、gemini、o-series
该模块的注释明确了一个关键设计原则:host ≠ model。Claude Code 可以运行任意 Claude 模型,Codex CLI 运行 GPT/o 系列,Cursor 和 OpenCode 可以前置多个供应商;生成器不会从宿主自动推断模型,用户可以用 --model 显式传入,否则每个宿主提供自己的 defaultModel(在 docs/ADDING_A_HOST.md 中定义为“生成时未收到显式 --model 时渲染的模型覆盖层,并对照 ALL_MODEL_NAMES 校验”)。
resolveModel() 负责把 CLI 输入归一化为家族名,其优先级规则是:
- 精确匹配:与
ALL_MODEL_NAMES完全一致则原样返回。这是唯一能选中gpt-5.6-sol的路径——Sol 是刻意“仅精确匹配”的,其他 5.6 变体(Terra、Luna 等)不会继承 Sol 的行为画像,而是落入通用gpt家族; - 家族启发式:如
gpt-5.4-mini/gpt-5.4-turbo→gpt-5.4,o3/o4-mini→o-series,claude-opus-4-8(...)前缀 →opus-4-8,其余claude-*→claude; - 未知输入返回
null,由调用方决定报错还是回退。
因此本文主角 opus-4-8.md 的触发方式,是用户以 --model opus-4-8 或 --model claude-opus-4-8(及其后缀变体)启动 skill 生成。
二、opus-4-8.md 全文逐条解读
完整文件(model-overlays/opus-4-8.md)由一行继承指令加三条行为指令组成。注意首行 {{INHERIT:claude}}:解析器会把 model-overlays/claude.md 的全部内容拼接到本文件正文之前,使 opus-4-8 在“Claude 通用纪律”之上叠加 Opus-4.8 专属纠偏,避免重复维护。
继承的基础层:claude.md 的三条纪律
继承自 model-overlays/claude.md,共三条:
- Todo-list discipline(待办纪律):执行多步计划时,每完成一项就单独标记完成,禁止最后批量勾选;若某项被证明不必要,标记为 skipped 并附一行理由。
- Think before heavy actions(重动作前先说明):对复杂操作(重构、迁移、非平凡新功能),执行前先简述方案,让用户可以低成本纠偏,而不是在“飞行中”才发现方向错了。
- Dedicated tools over Bash(专用工具优先于 Shell):优先使用 Read、Edit、Write、Glob、Grep 而非 cat、sed、find、grep,因为专用工具更便宜也更清晰。
指令一:Effort-match the step(算力匹配步骤)
原文核心要求:
简单的文件读取、配置检查、命令查询和机械式编辑不需要深度推理,快速完成即可。把扩展思考(extended thinking)留给真正困难的子问题:架构权衡、隐蔽 bug、安全影响、存在竞争约束的设计决策。对简单步骤过度思考是浪费 token 和时间。
这条指令针对的失效模式是:前沿模型在 trivial 步骤上也进行长篇推理,拉长回合数、抬高成本。gstack 还为它配了可量化的 A/B 评测——test/fixtures/overlay-nudges.ts 中定义了 turnsToCompletion 指标(会话所用总回合数),用“读一个 config.json 回答版本号”这种 trivial prompt 验证“带覆盖层时应比基线更快收敛”(见第四节)。
指令二:Pace questions to the skill(按 skill 节奏提问)
这是该覆盖层中最关键、也有一段真实事故史的一条。原文规则:
如果当前 skill 的文本中任何位置包含
STOP. AskUserQuestion,则每轮只问一个问题——以 tool_use 形式发出问题、停下、等待用户回答、再继续。禁止批量提问。即使某个发现(finding)有“显而易见”的修复方案,它仍然是 finding,写入计划前仍需用户批准。只有当 (a) skill 没有STOP. AskUserQuestion指令,且 (b) 你在开始之前需要多个互不相关的澄清时,才允许一次性批量提问。拿不准时,每轮只问一个。
从 CHANGELOG.md 可以看到这条指令的由来:v1.6.4.0 曾出现“计划评审节奏回归”——当时覆盖层中是“Batch your questions”(批量提问)指令,且 generateModelOverlay 在 generateAskUserFormat 之上渲染,导致模型的“环境默认值”变成了批量提问,/plan-ceo-review、/plan-eng-review 等评审 skill 不再逐个发现暂停提问,而是把所有发现汇总成一份报告一次抛出。修复方式是双管齐下:重排 preamble 中两段的顺序 + 把覆盖层指令改写为“Pace questions to the skill”。因此 test/model-overlay-opus-4-8.test.ts 专门断言:文件必须包含 Pace questions to the skill,且不得再包含 **Batch your questions.**——把一次线上回归永久固化成了回归测试。
指令三:Literal interpretation awareness(字面解读意识)
原文针对的是 Opus 4.8 的一个特性:它逐字面解释指令、不会“静默泛化”。指令要求把它的双刃剑效应锁在安全一侧:
当用户说“修复测试”,要修复这个分支引入或负责的所有失败测试,而不只是第一个(也不包括不相关代码中早已存在的失败)。当用户说“更新文档”,要更新范围内每一处相关文档,而不只是最明显的那一份。读懂请求的完整范围,交付完整范围。如果请求含糊或范围不清,问一次(与其他问题合并),然后彻底执行。
这条指令同样有量化评测锚点:uniqueFilesEdited 指标统计模型实际编辑/写入的唯一文件数,对应“Fix the failing tests”场景下应当触碰全部失败测试文件而非停在第一个(详见下节)。
三、解析器如何加载与包裹覆盖层
加载逻辑全部在 scripts/resolvers/model-overlay.ts 中,值得逐点拆解:
1. 继承链解析。 继承指令由正则识别:
const INHERIT_RE = /^\s*\{\{INHERIT:([a-z0-9-]+(?:\.[0-9]+)*)\}\}\s*\n/;
readOverlay() 是递归函数:若文件首行匹配 {{INHERIT:x}},先递归读取 model-overlays/x.md 并拼在正文之前;seen 集合充当循环保护(cycle guard),防止 A 继承 B、B 继承 A 造成无限递归。文件不存在时静默返回空字符串——优雅降级,不报错。
2. 从属性包裹(subordination wrapper)。 generateModelOverlay() 把解析出的内容包进一个固定标题块 ## Model-Specific Behavioral Patch (opus-4-8),并在前面注入从属声明:
以下提示是为 opus-4-8 模型家族调优的。它们从属于 skill 工作流、STOP 点、AskUserQuestion 门、plan-mode 安全与 /ship 评审门。若下文与 skill 指令冲突,skill 胜出。把它们当作偏好,而非规则。
这段从属语言是包裹器的一部分,与文件内容无关地随每次注入出现——它保证了覆盖层的“建议”地位永远不会盖过 skill 的硬约束(如评审必须暂停确认、/ship 必须过评审门)。唯一例外是 gpt-5.6-sol:它使用一段更长的“范围消歧”前言,专门界定 complete、full、every、100%、Boil the Ocean 这类模糊完整性词汇的边界,但同样声明“具体 skill 步骤、STOP 点、评审门仍然胜出”。
3. 注入位置有讲究。 在 scripts/resolvers/preamble.ts 的组合数组中,generateAskUserFormat(ctx)(tier ≥ 2 时渲染)被刻意放在 generateModelOverlay(ctx) 之前,源码注释解释了原因:
AskUserQuestion Format 渲染在模型覆盖层之前,使“节奏规则”成为环境默认值;覆盖层的行为提示作为从属补丁落地。Opus 4.7 自上而下阅读,会吸收它遇到的第一个节奏指令;颠倒这个顺序会回归计划评审节奏(v1.6.4.0 bug)。
也就是说,“先给通用节奏规则、再给模型补丁”的顺序本身就是一项经过事故验证的工程决策,被 test/preamble-compose.test.ts 等组合测试锁定。
此外,会话 preamble 的 bash 部分会回显 MODEL_OVERLAY: ${ctx.model ?? 'none'}(见 scripts/resolvers/preamble/generate-preamble-bash.ts),且 generate-upgrade-check.ts 中有一次性引导逻辑:首次检测到 .feature-prompted-model-overlay 标记缺失时,会告知用户“模型覆盖层已激活,MODEL_OVERLAY 显示具体补丁”,随后 touch 标记——每个会话最多提示一次。
四、两层验证:门级单测与 A/B 行为评测
gstack 对覆盖层文本的维护采用“测试即契约”策略,共两层。
第一层:门级断言。 test/model-overlay-opus-4-8.test.ts 通过真实调用 generateModelOverlay(ctx) 验证最终产物,关键断言包括:
- 原始文件包含
Pace questions to the skill,且不包含**Batch your questions.**; - 解析输出继承了 claude 基础层(含
Todo-list discipline)与从属声明(subordinate); - 解析输出匹配
STOP. AskUserQuestion且含“每轮一问”语义,并要求问题以tool_use形式发出; - “obvious fix 的发现仍需用户批准”语义存在(
obvious fix+user approval); Effort-match the step与Literal interpretation awareness两条提示保持存在;- 反向断言:直接以
claude模型生成时不得出现Pace questions to the skill——节奏指令属于 opus-4-x 覆盖层专属,不能泄漏到通用 Claude 层。
第二层:A/B 行为评测。 test/fixtures/overlay-nudges.ts 是“覆盖层有效性”的 fixture 注册表,每条 fixture 定义一个可复现的 A/B 实验:同一 prompt 在“覆盖层开/关”两臂各跑 trials(≥3)次,用 typed SDK 结果计算指标并断言通过谓词。与 opus-4-8 同源的三条 Opus 提示在 fixture 注册表中有对应锚点:
| 提示 | 指标 | 通过谓词 |
|---|---|---|
| Effort-match the step | turnsToCompletion(完成回合数,越低越好) |
lowerIsBetter20Pct:开覆盖层臂均值不高于基线 80% |
| Literal interpretation awareness | uniqueFilesEdited(编辑/写入的唯一文件数,越高越好) |
higherIsBetter20Pct:均值至少比基线高 20% |
| Dedicated tools over Bash(claude 层) | bashToolCallCount(全程 Bash 调用数,越低越好) |
lowerIsBetter20Pct |
fixture 在模块加载时即执行 validateFixtures() 校验(id 唯一且仅小写字母数字连字符、trials 为 ≥3 整数、overlay 文件必须存在且路径相对且不含 ..),损坏的 fixture 会在烧 API 费用之前快速失败。值得注意 CHANGELOG 中的实证记录:曾有一条 “Fan out explicitly” 提示在 N=10 试验中显示零提升(模型在“读三个文件”这类任务上本就不会批量并行),最终该提示被删除——gstack 对覆盖层提示采取“用数据说话,无效即移除”的态度,评测 harness 本身被刻意做成参数化的,新增一条提示的评测只需在注册表加一个条目。
五、实操:如何让 skill 使用 opus-4-8 覆盖层
结合仓库内的实际链路,使用方式如下:
- 显式指定模型:以
--model opus-4-8(或 API 模型 ID 前缀claude-opus-4-8)运行 gstack 的 skill 生成流程;resolveModel() 会将其归一化为opus-4-8家族,readOverlay('opus-4-8') 随即按继承链拼装出 claude 基础层 + 三条专属提示的完整补丁文本。 - 宿主默认模型:若不加
--model,由宿主的defaultModel决定;宿主配置中的defaultModel会在生成时对照ALL_MODEL_NAMES校验(见 validateModel(),非法值会得到'xxx' is not a known model. Use claude, opus-4-7, ...的明确报错)。 - 会话内自检:运行中可查看 preamble 回显的
MODEL_OVERLAY: opus-4-8环境变量值确认补丁已注入;覆盖层生效时也会有一次性的功能提示(每会话最多一次)。
适用前提与限制需要说明:覆盖层文本是针对特定模型版本调优的行为文案(opus-4-8 的三条提示均引用了该版本的字面解读与提问节奏特性),更换模型家族时会自动切换到对应的 model-overlays/{family}.md;若目标模型文件缺失,解析器静默返回空字符串而不报错,会话照常进行、只是没有行为补丁。
六、小结:覆盖层机制的三个设计要点
- 继承去重:
{{INHERIT:claude}}+ 递归readOverlay+ 循环保护,让子模型文件只写增量行为差异,维护成本线性可控; - 从属定位:固定包裹器声明覆盖层“偏好而非规则”,且 preamble 组合顺序把通用节奏规则排在模型补丁之前,两处共同防止模型补丁越过 skill 硬约束;
- 证据闭环:门级单测锁定关键措辞(含对旧版 “Batch your questions” 的反向断言),A/B 评测 harness 用回合数、编辑文件数等硬指标验证每条提示是否真正起效,无效提示会被删除——覆盖层文案本身也是被持续回归测试与实验数据约束的工程产物。
对想为自己的模型编写覆盖层的读者,最短路径是:新建 model-overlays/{family}.md,首行视需要写 {{INHERIT:base}},在 scripts/models.ts 的 ALL_MODEL_NAMES 与 resolveModel() 家族启发式中加入该家族,并参照 test/model-overlay-opus-4-8.test.ts 的断言模式为其编写门级测试——这正是 gstack 保证每条行为提示“可追溯、可验证、可回滚”的完整范式。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00