运行指标驱动的迭代优化循环。适用于通过实验提升可衡量的目标或结果(例如搜索相关性、聚类质量、构建性能、Prompt 质量或行为打分系统等)。
迭代优化循环
运行指标驱动的迭代优化。先明确目标、搭建测量基准框架(Measurement Scaffolding),再通过并行实验收敛至最佳方案。
初始化配置
在本次调用的最开始运行一次(在派发任何 Subagent 之前),并遵循其输出的指令——除非其中某条指令与本 Skill 自身关于询问用户的规则冲突(无论该规则适用于非交互模式还是所有模式;若有冲突,以本 Skill 的规则为准,不发起阻塞式提问)。在同一次调用中不要重复运行;后续若触发本 Skill 或其它 Skill 会单独运行其各自的初始化程序。若环境未安装 Node 运行时,本 Skill 将按默认逻辑正常继续执行。
SKILL_DIR="<absolute path of the directory containing the SKILL.md you just read>";
NODE="$(for c in node nodejs; do command -v "$c" >/dev/null 2>&1 && "$c" -e '' >/dev/null 2>&1 && { echo "$c"; break; }; done)";
if [ -n "$NODE" ]; then
"$NODE" "$SKILL_DIR/scripts/context.mjs" || echo "context script failed; continue with the skill's normal behavior";
else
echo "no Node runtime; continue with the skill's normal behavior";
fi
交互方式
优先使用平台内置的阻塞式提问工具:Claude Code 中使用 AskUserQuestion(如果还没加载 Schema,先调用 ToolSearch 并传参 select:AskUserQuestion)、Codex 中使用 request_user_input、Antigravity CLI (agy) 中 concentrated 使用 ask_question、Pi 中使用 ask_user(需要安装 pi-ask-user 扩展)。只有当 Harness 平台完全没有阻塞式工具或工具调用报错(例如 Codex 的编辑模式)时,才降级为在对话框输出带编号的选项——绝不能仅仅因为需要加载 Schema 就放弃使用工具。切勿静默跳过提问。
输入内容
优化输入(optimization input)是指触发本 Skill 时传入的输入——存在于当前 Prompt 或对话上下文里,不论是用户直接输入的,还是由上游调用 Skill 传递进来的:可以是要优化的具体目标,也可以是优化配置 YAML 文件的路径。
如果未提供任何优化输入,主动询问:“你想要优化什么?请描述你的优化目标,或提供优化配置 YAML 文件的路径。”
产物根目录
本 Skill 会读取 <root>/solutions/ 目录下的经验沉淀。仅在首次拼接 <root>/ 路径时(按下方规则)解析 <root>,严禁提前解析。无论是向 <root>/... 写入数据,还是读取 <root>/solutions/,都算作拼接 <root>/ 路径,因此任一操作都会触发路径解析;只有完全不触碰任何 <root>/ 路径的运行(如纯临时/无仓库流程)才可以跳过;解析后的绝对路径需直接传递给 Subagent,而不是传递配置项本身。
<!-- ce-docs-root:start -->
在拼接任何产物路径前,先解析 CE 产物根目录 <root>。
- 读取
<repo-root>/.compound-engineering/config.local.yaml中的docs_root字段,若无则读取config.yaml;以第一个非空值为准(<repo-root>通过git rev-parse --show-toplevel获取)。若均未配置,则<root>默认维持原样,即docs。 - 校验已配置的值:必须是相对于仓库根目录的相对路径,且经软链接解析后的真实路径必须保留在仓库内部,不能是仓库根目录本身,也不能位于
.git/目录下。若校验失败,直接抛错停止并输出docs_root及其具体值——绝不静默回退到docs。 - 使用
<root>作为唯一的产物存储位置:若目录不存在则创建,所有子路径统一按<root>/<subdir>(带本 Skill 自身的子目录)拼接,切勿同时再去读取docs目录。
<!-- ce-docs-root:end -->
优化配置规范 Schema
参考 Spec Schema 进行校验:
references/optimize-spec-schema.yaml
实验日志 Schema
参考实验日志 Schema 进行状态管理:
references/experiment-log-schema.yaml
快速开始
首次运行建议优先保证信号明确和操作安全,而不是盲目追求最高吞吐量:
- 当指标是客观且测量成本较低时,参考
references/example-hard-spec.yaml - 只有当实际质量依赖语义理解和主观判断时,才使用
references/example-judge-spec.yaml - 建议优先采用
execution.mode: serial且execution.max_concurrent: 1 - 首次运行建议限制规模:设置
stopping.max_iterations: 4和stopping.max_hours: 1 - 在基线和测量框架建立信任之前,尽量不要引入新的外部依赖
- 如果使用 Judge 模式,推荐初始设置为
sample_size: 10、batch_size: 5和max_total_cost_usd: 5
若想了解本 Skill 的适用场景、硬指标与 LLM-as-judge 的选型指南以及启动 Prompt 示例,参阅:
references/usage-guide.md
持久化规范
核心原则:磁盘上的实验日志是唯一的真理来源(Single Source of Truth)。对话上下文绝非持久化存储,仅存在于对话里的结果随时会丢失。
.context/compound-engineering/ce-optimize/<spec-name>/ 下的文件是本地临时状态(Scratch State)。它们会被 Git 忽略,因此可以在同一台机器上跨会话恢复,但除非用户显式导出,否则不会随 Commit、Branch 或 Push 保存。
所有关键状态必须落地到磁盘,严禁仅保留在 Agent 的内存中。
如果你在对话里生成了结果表格,却没有先将这些结果写入磁盘,这就是一个 Bug。 对话展示是给用户看的,磁盘文件才是持久化保障。
核心规则
-
测完立即落盘:测量完成后立刻将单个实验结果写入磁盘——不要等到整批(Batch)结束,也不要等到评估阶段,必须在指标算出的第一时间追加到实验日志文件中,然后再去评估下一个实验。这是防崩溃防丢失的第一铁律。
-
写完必须校验:每次写入实验日志后,重新读取文件确认该记录已存在。这能有效防止静默写入失败。校验通过前不得进入下一个实验。
-
阶段切换与决策前重新读取磁盘:跨阶段转换、批次边界或执行完耗时操作后,绝不信任内存状态。必须从磁盘重新读取实验日志和策略摘要(Strategy Digest)。
-
Phase 3 期间日志仅追加(Append-Only):严禁全量覆盖重写文件。必须采用追加新实验记录的方式;只有在发现新的 Best(最佳解)时才原地更新
best区块。这样能确保即使写入中断也不会丢失已有数据。 -
单实验结果标记(Crash Recovery):每个实验测量结束后,立刻在其 Worktree 中写入一个
result.yaml标记文件。在恢复运行(Resume)时,扫描这些标记即可挽救已测量但尚未记录到主日志的实验。 -
每批次结束生成策略摘要:Agent 在决定下一步尝试什么假设时,读取的是磁盘上的策略摘要(而不是凭内存记忆),且摘要必须在每批次结束、新假设生成前写好。
-
未落盘绝不向用户展示:标准流程永远是:测量 -> 写入磁盘 -> 校验 -> 然后再展示给用户。顺序绝不可颠倒。
强制磁盘检查点
以下是不可动摇的“先写后验”步骤。在每个检查点,Agent 必须写入指定文件,并重新读取文件确认写入成功。
| 检查点 | 写入的文件 | 对应阶段 |
|---|---|---|
| CP-0:Spec 保存 | spec.yaml |
Phase 0,用户确认后 |
| CP-1:基线记录 | experiment-log.yaml(包含 Baseline 的初始状态) |
Phase 1,基线测量完成后 |
| CP-2:假设 Backlog 保存 | experiment-log.yaml(hypothesis_backlog 区块) |
Phase 2,假设生成完成后 |
| CP-3:单次实验结果 | experiment-log.yaml(追加单条实验记录) |
Phase 3.3,每次测量完成后立刻执行 |
| CP-4:批次总结 | experiment-log.yaml(实验结果 + best)与 strategy-digest.md |
Phase 3.5,批次评估结束后 |
| CP-5:最终总结 | experiment-log.yaml(最终完成状态) |
Phase 4,收尾阶段 |
校验步骤的执行标准:
- 使用原生文件写入工具写入文件
- 使用原生文件读取工具重新读取该文件
- 确认预期的内容已成功写入
- 若校验失败,重试写入;若连续失败两次,提示用户并发出警告。
文件路径规范(均在 .context/compound-engineering/ce-optimize/<spec-name>/ 目录下)
| 文件 | 用途 | 写入时机 |
|---|---|---|
spec.yaml |
优化配置规范(运行期间不可变) | Phase 0 (CP-0) |
experiment-log.yaml |
所有实验的全量历史记录 | CP-1 初始化,CP-3 追加,CP-4 更新 |
strategy-digest.md |
用于指导下一轮假设生成的精简经验摘要 | 每次 Batch 结束后的 CP-4 写入 |
<worktree>/result.yaml |
单实验崩溃恢复标记 | 测量结束后立刻写入,先于 CP-3 |
恢复运行(Resume)
当 Phase 0.4 检测到已有运行记录时:
- 从磁盘读取实验日志——以磁盘数据为准
- 扫描各 Worktree 目录,找出拥有
result.yaml标记但尚未在主日志里记录的实验 - 恢复并追加这些“已测量但未记日志”的实验
- 从日志记录断点处继续向下执行
Phase 0:初始化与配置
0.1 确定输入类型
检查输入形式:
- Spec 文件路径(以
.yaml或.yml结尾):直接读取并进行校验 - 优化目标描述:引导用户以交互方式一步步创建 Spec
0.2 加载或创建 Spec
如果提供了 Spec 文件路径:
- 读取该 YAML Spec 文件。由 Orchestrator Agent 原生解析 YAML,无需调用 Shell 脚本解析。
- 严格对照
references/optimize-spec-schema.yaml中validation_rules节的所有规则进行校验(该章节是合法 Spec 的唯一真理来源——不要仅凭记忆去检查部分规则;例如 singleton-rubric 和 exclusive-resources 等条件约束规则仅在该文件定义)。 - 如果有任何规则校验不通过,详细列出具体的失败原因,并要求用户修正后再继续。
如果提供的是目标描述:
-
分析项目结构,搞清楚有哪些指标是可以被量化测量的
-
判断优化目标是定性(Qualitative)还是定量(Quantitative)——这是决定采用
type: hard还是type: judge的最关键一步:使用
type: hard的场景:- 指标是标量数值,且有明确的优化方向(越大越好或越小越好)
- 指标可以被客观准确地测量(构建耗时、测试通过率、延迟、内存占用等)
- 不需要人工主观判断“这个结果到底是好还是坏”
- 示例:缩短构建时间、提高测试覆盖率、降低 API 耗时、减小 Bundle 体积
使用
type: judge的场景:- 结果质量依赖语义理解才能评估
- 需要人工 Review 才能说出“这个方案确实更好”
- 虽然存在代理指标(Proxy Metric),但代理指标容易产生误导(例如“聚类数量变多”并不等于“聚类质量变好”)
- 优化过程可能会产生纸面上指标很好看、实际上却是“劣质/退化方案(Degenerate Solution)”的情况
- 示例:聚类质量、搜索相关性、文本摘要质量、代码可读性、文案润色、推荐相关性
重要提示:如果目标属于定性问题,强烈推荐使用
type: judge。向用户解释:仅靠硬指标会把代理数字优化上去,却无法保证实际质量。向用户展示“三层评估机制”:- 劣质熔断门禁(Degenerate Gates)(硬指标,低成本,快速):拦截明显挂掉的方案——例如“所有元素都被聚到了 1 个类”或“覆盖率 0%”。最先运行,若门禁失败,直接跳过昂贵的 Judge 评估。
- LLM-as-judge(真正的优化目标):对输出进行采样,对照评分标准(Rubric)打分,最后汇总聚合。这才是循环优化的核心。
- 诊断指标(Diagnostics)(仅记录,不充当门禁):分布统计、计数、耗时等——用于辅助分析 Judge 打分发生变化的原因。
如果用户坚持在定性目标上使用
type: hard,可以继续执行,但必须明确警告其结果可能会优化出具备欺骗性的代理指标。 -
设计采样策略(针对
type: judge):引导用户定义分层采样策略。最核心的问题是:“什么 pa
<!-- truncated for translation batch; full body continues in source -->






