跳转到主要内容
这是进阶内容,面向想理解 eval 如何打分、指标怎么算、以及自动多轮评测怎么跑的用户。日常评估看快速上手即可。
Comet 的 eval 不只给出”通过/失败”,而是指标驱动的评测:用 rubric 多维评分量化 Skill 在各个质量维度的表现,用 pass@k / pass^k 区分”能力上限”和”可靠性下限”。对于多阶段工作流类 Skill,评测由两个 Agent 自动交互完成——一个跑被测 Skill,另一个模拟用户在决策点回复。

读报告时先看这些

如果你不是在调试评分器,读报告时按这个顺序看即可:
顺序报告信号判断什么
1checks_failed这次运行是否真的失败;为空才算通过
2failure attribution失败该归到环境、workflow、task 还是模型
3pass@k / pass^kSkill 是偶尔能成功,还是重复运行稳定
4weighted_score质量维度的加权诊断分
5最低 rubric 维度下一轮优化优先投到哪里
日常发布判断不要只看 weighted_score。真正的通过/失败先看 checks_failed;rubric、pass@k 和 pass^k 用来判断质量、稳定性和下一步优化方向。

指标体系一览

指标回答的问题类型是否门禁
rubric 各维度分(0.0–1.0)这个维度做得怎么样诊断性否(信息性)
weighted_score(加权总分)综合质量如何诊断性
RubricAvg(报告列)该次运行的维度均分诊断性
pass@kk 次里至少成功一次的概率(能力上限)分布性
pass^kk 次全部成功的概率(可靠性下限)分布性
工作流契约检查被测 Skill 是否真的按契约触发硬判定是(缺必需 Skill 会失败)
任务校验器通过/失败这次实现到底对不对硬判定是(决定 pass/fail)
关键区分:rubric 的维度分和 pass@k/pass^k 都是信息性指标,用于诊断和对比;真正的通过/失败checks_failed == []。大多数失败来自任务校验器(target_artifacts 存在性 + test_scripts),但 profile 也会把必需 Skill 未触发这类工作流契约问题写入 checks_failed

证据从哪里来

Comet eval 的运行证据来自 Claude CLI 自己输出的 stream-json,不是从终端文本里猜,也不是让另一个模型回忆总结。 单轮评测会在 Docker 里的任务目录直接运行被测 Agent:
claude -p "$prompt" \
  --dangerously-skip-permissions \
  --output-format stream-json \
  --verbose
eval harness 保存这次运行的原始 stdout / stderr,再逐行解析 stdout 里的 JSONL 事件。解析器会提取:
  • result 事件里的 duration_msnum_turns、token 和 cost
  • tool_use 事件里的工具调用
  • Bash 命令,作为 commands_run
  • Write / Edit 文件路径,作为 files_created / files_modified
  • Skill 调用,作为 skills_invoked
  • 对应的 tool_result 输出,挂回原工具调用
所以报告里的 Skills invokedcommands_runtool_callsfiles_created、token/cost 等,都是从 Claude CLI 的结构化事件流整理出来的可观测行为日志。
stream-json 仍然只是可观测行为日志。它适合统计工具调用、命令、Skill 调用、文件变化和成本;它不包含模型内部推理,也不能证明某个内部决策的因果链。schema 变化、坏 JSON 行、CLI 版本变化都可能影响解析,因此 raw stdout/stderr 会保留下来供审计。

轨迹和事件流不是一回事

Comet Classic runtime 自己也会写 .comet/trajectory*.jsonl,记录状态推进,例如 state_transitioned。这类 trajectory 是恢复能力的证据之一,rubric 会在 recovery_resilience 里检查它是否存在。 但 pass@k / pass^k 不从 trajectory 计算,rubric 的大部分维度也不是只看 trajectory。主证据来源是 Claude CLI stream-json、任务目录里的产物、任务校验器结果,以及 Comet runtime 留下的状态文件。

rubric 评分

rubric 把 Skill 的质量拆成多个维度,每个维度由若干二元(pass/fail)检查项组成,维度分 = 通过项数 / 总项数(0.0–1.0)。每个维度输出一行 [RUBRIC] <维度>: <分> - <原因> 评分方法论(对齐 Galileo、Hebbia、τ-bench 等业界实践):
  • 每个维度含 N 个二元检查项
  • 维度分 = passed / total(0.0–1.0)
  • 加权总分 = Σ(维度分 × 权重) / Σ(权重)
  • 权重反映维度对工作流质量的重要性

三套 rubric

eval 内置三套 rubric,对应三种 profile:
Profile维度数权重和交互模式适合
generic77.7none(单轮)通用 Skill 冒烟
comet-workflow911.0auto_user(多轮)经典 /comet 五阶段
authoring-skill1113.8auto_user(多轮)/comet-any 生成物

comet-workflow rubric(9 维)

评估经典五阶段工作流。九个 [RUBRIC] 维度分本身是诊断性分数;但 profile 仍会检查工作流契约:如果没有真实触发 comet、嵌套 Comet 阶段 Skill、OpenSpec 依赖 Skill 或 Superpowers 依赖 Skill,会产生硬失败。
维度权重检查什么
completion2.0(最高)基线校验器通过比例(任务到底做对没)
main_flow1.5五阶段(open→design→build→verify→archive)有多少阶段留下证据
gate_guard1.5是否用了 comet-guard / transition / --apply
artifact_quality1.2proposal/design/tasks/test 是否有实质内容(proposal≥10 行、design 含权衡关键词、tasks≥3 个勾选项、有断言测试)
skill_invocation1.0是否真实观测到 comet 入口、嵌套 Comet 阶段 Skill、OpenSpec 依赖 Skill、Superpowers 依赖 Skill,且入口先于阶段 Skill
spec_drift1.0build 期改的 delta spec 是否在归档前 reconcile(没动 spec 则中性 1.0)
decision_point_compliance1.0是否在决策点暂停问用户而非自动决策(ask 调用数 ≥ mutation 数的一半)
recovery_resilience1.0中断后是否正确保留和恢复状态(checkpoint/trajectory/context/pending/.comet.yaml 五项)
efficiency0.8(最低)成本归一化(turns≤80、tools≤150、duration≤600s 三项)

generic rubric(7 维)

评估通用 Skill。和 comet-workflow 不同,它对”必需 Skill 未被调用”会产生硬失败(当 require_skill_invocation: true 时),其余维度信息性。
维度权重检查什么
completion2.0基线校验器通过比例
safety_boundary1.2是否有危险命令(rm -rfgit reset --hard、`curl …sh`)
skill_invocation1.0required skills 是否都被调用(未配置则中性 1.0)
artifact_presence1.0expected_artifacts 是否存在(支持 glob)
instruction_following1.0是否有失败检查提到 “constraint”
interaction_compliance0.8auto_user 模式下外层往返是否超 max_turns
efficiency0.7同 comet 的 efficiency 阈值

authoring-skill rubric(11 维)

评估 /comet-any 生成的 Skill 包。它先继承 generic 的四个共享维度,再加七个包专属检查。缺 SKILL.md、缺 resolved-skills.json、缺 workflow-protocol.json、缺 Engine 文件、缺 authoring-lanes.json、缺 skill-review.md 都会产生硬失败
维度权重检查什么
workflow_route_conformance1.5(与 completion 并列最高)协议路由顺序是否与期望节点序一致、内部 Node Skill 文件是否齐全、comet/eval.yaml 是否列出路由
completion1.5继承自 generic
generated_package1.4包存在 + SKILL.md 含路由/停顿点/workflow 与 resolved-skill 引用/恢复指引
resolved_skill_evidence1.2reference/resolved-skills.json 存在且 sourceSummaries 非空
engine_contract1.2comet/ 下有 skill.yaml/guardrails.yaml/checks.yaml/eval.yaml(轻量包无 Engine 则中性 1.0)
authoring_lanes1.2reference/authoring-lanes.json 含 6 条必需 lane(skill-core/script-contract/reference/pause-points/eval/skill-review)且 review 通过
safety_boundary1.2继承自 generic
skill_invocation1.0继承自 generic
artifact_presence1.0继承自 generic
review_gate0.8reference/skill-review.md 报告通过、authoring-lanes review 通过、无阻塞 finding
review_readiness0.8(最低)generic 层无硬失败则为 1.0

加权总分公式

weighted_score = Σ(维度分 × 权重) / Σ(权重)
每个维度输出一行 [RUBRIC] <dim>: <score> - <reason>,最后输出一行 [RUBRIC] weighted_score: <分>

RubricAvg(报告列)

报告里的 RubricAvg 列是该次运行所有维度分(含 weighted_score 行)的简单均分(sum/len)。跨多次运行时是各运行均分的均值。它是快速横向对比的汇总,和单 rubric 的 weighted_score(用各自权重)算法不同。

LLM-as-judge 覆盖(可选)

BENCH_LLM_JUDGE=1 启用。默认情况下,Comet 的最终 weighted_score 是规则分,不是 LLM-as-judge。规则型 rubric 能抓结构信号(文件存在、命令执行),但抓不到产物的实质深度——agent 是真做了有意义的输出,还是只生成了一个 stub?LLM judge 让一个裁判模型读取 workspace artifacts 后重新打分,输出 [RUBRIC-JUDGE] 行(和规则分的 [RUBRIC] 区分)。best-effort:失败则回退到规则分,不影响运行。 judge 在宿主机(不在 Docker 内)通过复用 claude CLI 运行,不引入新依赖。但裁判配置和被测 Agent 配置是故意隔离的:启用 BENCH_LLM_JUDGE=1 时,必须显式设置 BENCH_JUDGE_MODEL,不能回退复用主模型的 ANTHROPIC_MODEL 如果配置了 BENCH_JUDGE_BASE_URLBENCH_JUDGE_AUTH_TOKEN / BENCH_JUDGE_API_KEY,judge 会优先直接调用 Anthropic Messages HTTP(/v1/messages)。没有专用 judge endpoint 时,才回退到宿主机 claude CLI,并在子进程里清除继承来的主 ANTHROPIC_* provider 设置,再把独立裁判配置映射给自己的 CLI 调用:
环境变量用途
BENCH_JUDGE_MODEL必填。裁判模型;direct HTTP 时作为 request model,CLI fallback 时传给 claude --model 和子进程 ANTHROPIC_MODEL
BENCH_JUDGE_AUTH_TOKEN可选。裁判专用 Anthropic 兼容代理 token,优先于 BENCH_JUDGE_API_KEY
BENCH_JUDGE_BASE_URL可选。裁判专用 Anthropic 兼容代理地址
BENCH_JUDGE_API_KEY可选。裁判专用 Anthropic API key;设置 auth token 时不会传入子进程
这样设计是为了避免”同一个模型既当选手又当裁判”:主 Agent 可以继续使用自己的 ANTHROPIC_MODELANTHROPIC_BASE_URL 和 token,judge 必须单独声明模型和 provider。direct HTTP 路径也能避开某些严格 Anthropic 兼容代理不接受 Claude CLI 额外请求参数的问题。若开启了 BENCH_LLM_JUDGE=1 但缺少 BENCH_JUDGE_MODEL,报告会写入:
[RUBRIC-JUDGE] status: skipped - BENCH_JUDGE_MODEL is required when BENCH_LLM_JUDGE=1
这种 skipped 状态不会被标记为 enabled_and_successful,也不会调用裁判模型。 不同 profile 覆盖的维度不同:
Profile覆盖维度说明
comet-workflowartifact_qualityspec_driftmain_flow重新打分规则较弱的三个定性维度(llm_judge.py
generic / authoring-skilltask_completionoutput_qualityinstruction_adherence通用三维度,外加任务在 task.toml 里声明的 rubric_criteria 作为 custom_N 维度(generic_llm_judge.py
generic/authoring 的三维度评分标准:
维度1.0(满分)0.50.0
task_completion全部需求满足、产物存在且正确、基线检查通过部分完成关键产物缺失或为空
output_quality结构良好、完整、非平凡、有思考痕迹存在但浅薄、勉强达标缺失、空、明显 stub
instruction_adherence完全遵守指令和约束、无违禁模式、工具使用得当轻微偏离但核心意图保留严重违反、危险命令、约束失败
judge 收集 workspace 文件时跳过 .gitnode_modules.comet 等目录,单文件上限 3000 字符、总预算 20000 字符,大文件(>50KB)和二进制文件会被跳过,保证 prompt 不失控。裁判必须按 [RUBRIC-JUDGE] <dim>: <score> - <reason> 格式逐行输出,每个 reason ≤25 词并引用具体内容。

pass@k 与 pass^k

这两个指标衡量能力 vs 可靠性,是评估 Skill 能否反复稳定运行的关键。它们基于多次重复运行(由 --count N 产生)的通过/失败序列计算。

定义

指标公式含义
pass@k(能力上限)1 - C(n-c, k) / C(n, k)k 次独立尝试里至少一次成功的概率(HumanEval 无偏估计)
pass^k(可靠性下限)1.0 当且仅当 c == n,否则 0.0k 次尝试全部成功的概率
其中 n = 总运行数,c = 成功运行数。“成功”= 该次运行任务校验器零失败。

为什么需要两个

小鱼对比 pass@k 的至少一次成功和 pass^k 的每次稳定成功

pass@k 看能力上限,pass^k 看可靠性下限,两者差距越大越不稳定

  • pass@k 高、pass^k 低:能力够,但不稳定——“能做,但不能保证每次都做对”。对一个用户反复运行的 Skill,这是危险信号。
  • 两者都高:既能做,又每次都做对——可信赖。
gap(pass@k − pass^k)量化不稳定性。报告里会显式提示这个 gap。

怎么得到多次运行

--count N(pytest 选项)把每个 (task, treatment) 组合重复 N 次,产生 N 个独立的通过/失败结果。对比报告先过滤出 analysis set:明确的环境或运行器噪声会被排除,flagged run 仍进入主统计但会被标出。analysis set 里的这 N 个布尔值就是 pass@k/pass^k 的输入。
# 重复 5 次,让 pass@k/pass^k 有意义
# (实际通过 comet eval 间接驱动,底层等价于 --count 5)
报告在运行数不足时会警告:“Only N run per treatment — pass@k/pass^k for k>1 need ≥2 runs to be meaningful. Use —count 5.” 单次运行只能算 pass@1/pass^1,k>1 的指标需要多次重复。

k 怎么选

报告从 {1, 2, 5} 里取不超过实际运行数 n 的 k 值(k 被 clamp 到 n),不足时回退到 [1]。报告列:pass@1 [pass@2 pass@5]pass^1 [pass^2 pass^5]

出现在哪

pass@k/pass^k 不在 summary.md,而在对比报告compare_baselines.py 产出的 comparison_report.md)的 ## pass@k / pass^k — capability vs reliability 章节。它们是信息性的,不是门禁。

双 Agent 自动交互评测

对于多阶段工作流类 Skill(comet-workflowauthoring-skill profile),评测由两个 Agent 自动交互完成,不需要真人介入。

两个角色

角色做什么会话
被测 Agent(subject)跑被测 Skill(如 /comet 五阶段)单一连续会话,每轮 --resume 续接
用户模拟 Agent(simulator)在决策点模拟用户回复(批准合理方案、选合理默认、只在真有歧义时澄清)每个决策点一次性的 claude -p 调用,无状态

交互循环

循环最多 max_turns 次外层往返(comet-workflow 通常 12 次,authoring-skill 通常 8 次),命中”完成”(archive complete / workflow complete / all 5 phases 等)则提前结束。 每一轮被测 Agent 都用 --output-format stream-json --verbose 运行。loop 驱动只把每轮被测 Agent 的 stream-json stdout 拼接起来给 harness 解析;用户模拟 Agent 的一次性回复不会进入主事件流。因此事件统计反映的是 subject Agent 的可观测行为,而不是 simulator 的行为。
max_turns 不是被测 Agent 内部真实工作轮数,也不是工具调用次数。一次外层往返指:被测 Agent 跑到决策点,用户模拟 Agent 回复,然后被测 Agent 用 —resume 继续。同一次往返内部仍可能包含多条 assistant 消息、工具调用和文件操作。

决策点检测

被测 Agent 的输出文本匹配这些信号就判定为决策点(不区分大小写):
? | confirm | choose | proceed | continue | approve | select an option |
which (option|approach|name) | enter the | provide | would you | shall we |
do you want | preferred
也支持自定义 --decision-pattern

用户模拟 Agent 的指令

模拟 Agent 收到的是 simulator prompt + 被测 Agent 的最后一条消息,被要求:
  • 被要求确认时,批准提出的方案/名字/计划
  • 被要求选择时,选最合理的默认
  • 只在问题对”做什么”真正有歧义时才要求澄清
  • 永不拒绝,永远让工作流前进
  • 不写代码或文件
comet-workflow 用 COMET_SIMULATOR_PROMPT,generic/authoring 用 GENERIC_SIMULATOR_PROMPT(措辞略简)。模拟回复为空时回退到 "Yes, please proceed with the recommended option."

自定义模拟器提示词

auto_user 评测的模拟器指令可被覆盖。默认从 eval/simulator-instruction.md 读取,其内容就是上面这几条原则的标准模板。两种覆盖方式(优先级从高到低):
方式怎么设作用范围
--simulator-prompt "..."pytest 命令行参数单次运行
BENCH_SIMULATOR_PROMPT_FILE=<path>环境变量(可写进 eval/.env所有 auto_user 运行
BENCH_SIMULATOR_PROMPT_FILE 的相对路径从 eval/ 解析,默认值 simulator-instruction.md,文件存在才会被读取。这让你能换一套用户行为画像(比如更挑剔、会要求澄清更多)来压力测试工作流在”难缠用户”下的表现,而不必改 harness 代码。

为什么这样设计

工作流类 Skill 会在决策点暂停等用户确认。如果评测只跑单轮,Skill 会卡在第一个决策点。双 Agent 循环让评测自动跑完整条工作流(open→…→archive),同时保证决策点的用户输入是”合理的、推动前进的”,而不是硬编码回复。这样测出来的 rubric 分和 pass/fail 才反映真实使用场景。

单轮 vs 多轮

  • generic profileinteraction.mode: none):单轮,被测 Agent 一次性跑完(适合不需交互的冒烟任务)。
  • comet-workflow / authoring-skill profileinteraction.mode: auto_user):多轮,启用双 Agent 循环。
comet-* 开头或 category: comet 的任务会自动推断comet-workflow profile 并启用 auto_user

评测的三个轴:treatment × task × reps

一次评测是三个轴的笛卡尔积:
含义例子
task一个评测任务(目录,含 instruction/environment/validation)comet-fix-median(修 bug 维度)
treatment实验条件(注入哪些 Skill / CLAUDE.md)CONTROL(无 Skill 基线)、COMET_FULL(注入 comet)
reps重复次数(--count N--count 5 每个 (task,treatment) 跑 5 次

treatment 实现 A/B 对比

同一任务跑多个 treatment,就能测出 Comet Skill 的边际效果
Treatment注入用途
CONTROL无 Skill 基线对照
COMET_FULLcomet 主 + 7 个阶段子 Skill + brainstorming(v3,.mjs 运行时)当前版本
COMET_FULL_0390.3.9 冻结基线(.sh 运行时)回归对比
对比报告(compare_baselines.py)把 COMET_FULL(WORKFLOW)和 COMET_FULL_039(BASELINE)跨 rubric 维度对比,CONTROL 仅作上下文。

指标怎么进报告

报告位置内容
summary.md 的 Results 表每个 treatment 一行:Checks + 各 rubric 维度列 + RubricAvg + Turns/Duration/Tools/Tokens/Cost
summary.md 的 Aggregated by Treatment(reps>1 时)Reps Passed、Checks、Avg Turns/Duration、Tokens、Cost、Skills、Scripts
每次 report.jsonpassed、checks_passed[]、checks_failed[]、events_summary(含 failure_attribution)、rubric 分
comparison_report.mdpass@k/pass^k 表(能力 vs 可靠性)+ rubric 维度跨 treatment 对比
详见读取评估报告

下一步

最后修改于 2026年7月6日