mcpField
H
harness-eval

harness-eval

github.com/tech-leads-clubAgent 工作流7.1k100 次安装3 天前更新
代码仓库

关于 harness-eval

Harness Eval 是用于评估代码仓库中 Agent harness 内容的技能,适合需要检查其正确性、冗余度或实用性的团队。它先生成报告,默认不修改文件,并要求用户批准成本较高的评估轨道。

主要功能

  1. 01提取仓库清单与声明
  2. 02脚本检查引用路径和命令
  3. 03可选双评审冗余度评估
  4. 04可选双评审实用性评估
  5. 05检查精简内容的依赖方

适用场景

  1. 01检查 Agent 指南中的路径和命令是否存在
  2. 02评估技能内容是否冗余或值得保留
  3. 03审阅评估报告后再决定是否精简 harness

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tech-leads-club/agent-skills --skill harness-eval

安装后在 Claude Code 中输入/harness-eval确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
claims.schema.json
GLOSSARY.md
judge-prompts.md
PROTOCOL.md
scripts/
doc_scope.py
inventory_extract.py
merge_agreement.py
merge_usefulness.py
slim_fanin.py
surfaces_extract.py
track_a_correctness.py

详细介绍

Harness Eval

运行一次完整的、与技术栈无关的 Harness 评估,并在生成报告后停止。除非用户审阅 Ship/Slim 后明确提出要求,否则不要自动编辑 AGENTS.md 或 skills。

用户问卷(高优先级)

继续之前先停下来询问。 不要跳过这些关卡。不要静默纳入可选文档,也不要启动 B/C 评审。

清点之后的顺序:Q1(如有需要)→ Q2 → 然后执行 Track A(始终运行 A)→ 仅在获批后运行 B/C。

Q1 — 可选项目文档(清点之后)

当 optional-docs-candidates.md 列出可选类型时,在 Q2 / Track A 之前询问:

Inventory found cited project docs outside the agent skill trees.

- **Always in scope:** skill-tree files (`.agents/skills`, `.cursor/skills`, `.claude/skills`)
- **Always excluded:** ADRs / RFCs / decision-record trees (never scored as T2)
- **Optional (default: omit):** see types/paths in `optional-docs-candidates.md`

Include any optional doc types or paths in this run?
Reply with: `none` (default), type ids (e.g. `docs`), and/or specific paths.

只有在用户回答后,才使用 --include-doc-type / --include-doc 重新清点。如果没有可选类型,则跳过 Q1。

Q2 — Tracks B 和 C(Track A 之前——预算)

在 Track A 之前询问,方便用户预先设定预算。接下来始终运行 Track A(确定性流程,约 0 个模型 token)。只有获批后才运行 B/C。

Choose eval scope for this run (before Track A).

| Track | Question | Certainty | Token consumption |
|-------|----------|-----------|-------------------|
| **A — Correctness** | Cited path/command exists? | **Highest** — script only, no LLM. Prefers false negatives over false BROKEN. | **~0 model tokens** (always runs next) |
| **B — Redundancy** | Would an agent rediscover this cheaply without the harness? | **Medium** — dual LLM + plants; Ship only if trap PASS and both agree. Disagree → Hold. Less model-sensitive than C. | **High** — 2 judges × every claim (~N in this inventory). Each may spot-check the repo. |
| **C — Usefulness** | Does this surface change behavior vs theory/demo/overlap? | **Lowest / most subjective** — dual LLM + plants + fan-in; **model-sensitive**. Slim/Mixed need gates; prefer second-model check before large deletes. | **Highest** — 2 judges × every surface (whole files; often dominates the run). |

Notes: Ship (B) ≠ Slim (C). Rediscoverable ≠ useless. A always runs; B/C are optional.

Reply with one of: `A only`, `B`, `C`, or `B+C`.

已知时,从 claims.md 填入声明数量;提取后显示约有 T0+T1+T2 项 Markdown 表面内容(如果尚未运行,则说明“运行 surfaces_extract 后”)。

  • A only: 运行 Track A;展示 04;停止(不运行 B/C 评审)。
  • B: 运行 Track A,然后执行步骤 4–6。
  • C: 运行 Track A,然后执行步骤 7–10(C 不需要 B)。
  • B+C: 运行 Track A,然后执行步骤 4–11。

如果用户在触发消息中已经要求运行 B/C / full eval,则视为已获批准——仍需展示一次 Q2 表格,让用户了解费用。

加载此技能的文件

此技能自包含。协议、脚本和评审提示词均位于此技能目录下(即包含 SKILL.md 的文件夹)。将该目录解析为 SKILL_DIR——绝不要假定其他安装路径。

运行输出(非协议)写入目标仓库的 .harness-eval/runs/<run-id>/。

关键规则

  1. 默认仅报告。 判断 ≠ 修复。
  2. README 不在范围内,既不是测试框架表面,也不是重新发现能力或实用性的证据。
  3. 与技术栈无关。 提示词或方案中绝不硬编码包管理器、数据库、框架或目录布局。发现实际存在的清单(JS、Python、Make/Task、Rust、Go、PHP、Ruby/Rails、Java/Gradle/Maven,以及 bin/*)。
  4. 文档范围。 T2 始终包含 Agent 技能树引用(.agents/skills、.cursor/skills、.claude/skills)。ADR / RFC(决策记录树)始终不纳入 T2 表面。 其他引用的项目文档为可选项——默认省略;在此技能顶部通过 Q1 询问,然后使用 --include-doc-type / --include-doc 重新运行。
  5. 清点后始终运行 Track A(确定性高精度)。宁可漏报,也不要误报 BROKEN。占位符(SPEC_FOLDER、{x}、[feature])绝不判为 BROKEN。绝不使用 str.lstrip('./') 规范化路径。
  6. Track B 和 C 必须先通过 Q2 获得用户批准,且 Q2 须在 Track A 之前。 用户选择加入前,不得启动 B/C 评审者。用户可批准仅运行 B、仅运行 C、同时运行两者,或仅运行 A。
  7. Track B 需要双评审者和植入项。 Judge2 必须盲评(不得读取 Judge1 评分或 trap-key.json)。只有陷阱门禁 PASS 且双评审结果为 REDUNDANT,且 Judge2 成本 ≤ 1 时才可发布。
  8. Track C 需要双评审者和植入项。 盲评的 Judge2 不得读取 08-usefulness-j1.md 或 usefulness-trap-key.json。只有陷阱门禁 PASS、双评审结果为 SLIM/ROUTING-ONLY,且扇入检查 PASS(没有其他测试框架表面将该路径作为 SoT 硬加载——合并时会检查完整技能树,而不仅是 --seed)时才可精简。实用性对模型敏感——在两个评分文件中记录 model: <id>;单次运行中尽量使用相同模型;大规模删除 Slim 内容前,换用第二个模型重新评审。
  9. KEEP / KEEP-CORE 植入项不得是评分材料中已有声明/表面的逐字副本。
  10. 子代理: 使用允许列表中的非 fast 模型(策略允许时优先选用与父代理相同系列的模型)。不得使用 *-fast 模型。
  11. 不得混淆不同轨道。 Track B Ship ≠ Track C Slim。可重新发现 ≠ 无用;有用 ≠ 不冗余。
  12. Slim 应用 / 扇入。 除非在同一变更中更新相应消费者,否则绝不为“被 Slim 扇入阻止”下列出的路径创建存根或删除这些路径(或当 python3 "$SKILL_DIR/scripts/slim_fanin.py" --path <P> 报告存在引用者时)。
  13. Mixed/Slim 应用必须保持自包含。 删除 REPO-DEMONSTRATED / THEORY 内容意味着从测试框架表面删除或压缩这些内容。绝不要用 See app/... / lib/... / test/... 替换围栏中的教学代码片段(或其承载的约定)——这会用代码树指针替换 SoT。评审证据路径只能保留在评分表中;若必须保留会改变行为的约定,则保留一条简短的技能内规则或代码片段。
  14. Mixed 应用是机械操作。 仅有双 MIXED 结果还不够。Merge 会生成 11-mixed-apply.md,其中按 ID 列出 KEEP(来自 Keep-core 列)和 CUT(来自 Slim 列)。应用代理必须只遵循该文件——不得重新评审、重新设计或另行发明与 KEEP 不同的模式。Keep-core/Slim 单元格为空时,跳过该路径(Hold)。

说明

步骤 1:解析 SKILL_DIR

将 SKILL_DIR 设置为包含此 SKILL.md 的目录。验证以下文件存在:

  • $SKILL_DIR/references/PROTOCOL.md
  • $SKILL_DIR/scripts/inventory_extract.py
  • $SKILL_DIR/scripts/track_a_correctness.py
  • $SKILL_DIR/scripts/merge_agreement.py
  • $SKILL_DIR/scripts/surfaces_extract.py
  • $SKILL_DIR/scripts/merge_usefulness.py
  • $SKILL_DIR/scripts/slim_fanin.py
  • $SKILL_DIR/scripts/doc_scope.py

如果缺少任何文件,则技能安装已损坏——停止。

步骤 2:清点 + 声明材料

在目标仓库根目录中:

RUN_ID=$(date -u +%Y-%m-%d)-full
python3 "$SKILL_DIR/scripts/inventory_extract.py" --root . --run-id "$RUN_ID"
# Optional scope: AGENTS.md + one-hop related skills only
# python3 "$SKILL_DIR/scripts/inventory_extract.py" --root . --run-id "$RUN_ID" --seed AGENTS.md

预期在 .harness-eval/runs/$RUN_ID/ 下包含:inventory.json、claims.jsonl、claims.md、trap-key.json、optional-docs-candidates.md(以及 .json)。

步骤 2b:可选文档 — Q1(见顶部)

阅读 optional-docs-candidates.md。如果存在可选类型,则运行用户问卷中的 Q1。仅在获得批准后重新运行清点:

python3 "$SKILL_DIR/scripts/inventory_extract.py" --root . --run-id "$RUN_ID" \
  --include-doc-type docs   # and/or --include-doc path
步骤 2c:跟踪预算 — Q2(见顶部)

在 Track A 之前运行用户问卷中的 Q2。记录答案(A only / B / C / B+C)。除非 B 和/或 C 已获批准,否则不要开始步骤 4 及后续步骤。

步骤 3:Track A(确定性)— 始终运行
python3 "$SKILL_DIR/scripts/track_a_correctness.py" --root . --run-id "$RUN_ID"

预期结果:04-correctness.md(顶部包含术语定义)。抽查 .agents/... 引用是否能正确解析(而不是 agents/...)。

总结 Track A(损坏数量 + 值得注意的集群)。如果 Q2 的答案是 A only,则停止。否则继续执行已获批准的 B 和/或 C 步骤。

步骤 4:Track B — Judge1

阅读 references/judge-prompts.md(Track B Judge1)。启动一个使用允许列表中模型的独立子 Agent,并指定其检查 .harness-eval/runs/$RUN_ID/claims.md。它会写入 05-redundancy-j1.md(包含 model: <id>)。

Judge1 可以读取 inventory.json。不得读取 trap-key.json。

步骤 5:Track B — Judge2(盲评)

阅读 references/judge-prompts.md(Track B Judge2)。启动第二个子 Agent。它会写入 06-blind-scores.md。

Judge2 禁止读取:trap-key.json、05-redundancy-j1.md、07-agreement.md、之前的 agreement 报告。

建议并行执行步骤 4 和 5。

步骤 6:合并 Track B 的一致性结果
python3 "$SKILL_DIR/scripts/merge_agreement.py" --run-dir .harness-eval/runs/$RUN_ID

预期结果:07-agreement.md(Ship/Review/Hold + 这些词的含义)。如果 trap 检查失败:按照 PROTOCOL 修复植入项,为 P00x 重新评分,然后重新合并 — 不要 Ship。

步骤 7:Track C — 表面清单
python3 "$SKILL_DIR/scripts/surfaces_extract.py" --root . --run-id "$RUN_ID"

预期结果:surfaces.md、surfaces.json、usefulness-trap-key.json。

步骤 8:Track C — Usefulness Judge1

阅读 references/judge-prompts.md(Usefulness Judge1)。启动一个使用允许列表中模型的子 Agent(在标题中记录相同的模型 ID)。它会写入 08-usefulness-j1.md。

不得读取 usefulness-trap-key.json。

步骤 9:Track C — Usefulness Judge2(盲评)

阅读 Usefulness Judge2 提示词。为保持一致性稳定,建议使用与步骤 8 相同的模型。它会写入 09-usefulness-j2.md。

禁止读取:usefulness-trap-key.json、08-usefulness-j1.md、10-usefulness-agreement.md,也不得使用 Track B 的 05/06/07 来判断 usefulness 类别。

建议并行执行步骤 8 和 9。

步骤 10:合并 Track C 的一致性结果
python3 "$SKILL_DIR/scripts/merge_usefulness.py" --run-dir .harness-eval/runs/$RUN_ID

预期结果:10-usefulness-agreement.md(Slim/Keep-core/Mixed/Hold + 这些词的含义)、11-mixed-apply.md(每个 Mixed ID 对应的 KEEP/CUT),以及 slim-fanin.json。如果 trap 检查失败:不要 Slim。带有 slim-fanin-blocked 的表面属于 Hold — 不是 Slim apply 候选项。

步骤 11:展示结果

根据 agreement 报告总结(每份报告均以术语定义开头):

  • Track A 损坏数量 → 04-correctness.md
  • Track B trap 检查结果 + Ship/Review/Hold → 07-agreement.md
  • Track C trap 检查结果 + fan-in + Slim/Keep-core/Mixed/Hold → 10-usefulness-agreement.md
  • Mixed 数量大于 0 时,指出 11-mixed-apply.md(这是唯一的 Mixed apply 路径)
  • 指出 Track C 使用的模型 ID,并说明 Slim 对模型敏感
  • 指出任何 Slim fan-in 被阻止 的条目(此处可能会出现种子范围以外的消费者)

除非用户要求应用 Ship/Slim/Mixed,否则停止。应用时:

  • **Slim:**仅处理 Slim 表格中的路径(fan-in PASS);如果路径被 fan-in 阻止,绝不能先将其设为存根而不先更新引用方。
  • **Mixed:**打开 11-mixed-apply.md,并且只根据 ID 执行 KEEP/CUT(规则 12)。绝不能仅根据 Mixed 路径列表重新判断。绝不能用代码树路径指针替代被删除的演示(规则 11)。

示例

示例 1:完整的 harness 评估

用户说:“对这个仓库运行 harness 评估”

操作:清点 → 如有需要则运行 Q1 → Q2(B/C 预算表)→ Track A → 如果获批,则执行步骤 4–11。并行运行 B 的评审,再运行 C 的评审。展示一致性结果(术语见文件)。

示例 2:仅运行 Usefulness(使用已有运行记录)

用户说:“对最近一次 harness-eval 运行记录执行 Track C usefulness”

操作:针对该 RUN_ID 执行步骤 7–11(清点结果必须已存在)。

示例 3:错误的技能

用户说:“setup harness” / “init harness” → harness setup(不是此技能)。用户说:“specify feature” → tlc-spec-driven。

故障排查

陷阱门禁 FAIL(Track B 或 C)

原因:KEEP/KEEP-CORE 植入项是牌组中的重复项,或盲测判定器误判了类别。解决方案:使用技能的固定植入项模板;重新评分植入项;重新合并。

Track A 错误地报告缺少 .agents/...

原因:路径规范化有误。解决方案:技能脚本必须使用 normalize_cite(仅去除 ./)。从 $SKILL_DIR/scripts/ 重新运行 Track A。

子 Agent 受阻

原因:模型缺失/不在允许列表中,或 *-fast 被阻止。解决方案:使用允许列表中的非 fast 模型重新启动。

更改模型后,Track C Slim 看起来不对

预期情况:实用性会受模型影响。在第二个模型上重新运行 C1+C2;Slim 范围的交集是安全的删除集合。

混合应用重写了规范/移除了模块

原因:应用 Agent 根据 Mixed 路径列表重新判断,而没有遵循 KEEP/CUT。解决方案:仅通过 11-mixed-apply.md 应用;如果缺少该文件,重新运行 merge_usefulness.py;如果 Keep-core/Slim 单元格含糊不清,在应用前重新评分这些 ID。

T2 为空 / 技能 references/ 未纳入清单

原因:路径规范化使用了 lstrip("./"),将 .agents/… 转成了 agents/…。解决方案:doc_scope.normalize_rel 必须仅去除 ./ 前缀(与 Track A 的规则相同)。

Track C 中出现了 ADR

原因:旧版清单将所有一跳 docs/** 都视为 T2。解决方案:v1.7+ 不再纳入决策记录目录树;只有用户批准的可选文档类型(绝不包括 ADR/RFC)才能进入 T2。

Slim 存根导致另一个加载该文件的技能出问题

原因:内容存在 OVERLAP/Slim,但未考虑 fan-in——可能是较早的运行,也可能是应用时跳过了门禁。解决方案:恢复清单正文;使用 merge_usefulness.py 重新合并(fan-in 会扫描完整的技能目录树)。使用 slim_fanin.py --path <P> 确认。

缺少脚本

原因:技能文件夹不完整。解决方案:恢复 $SKILL_DIR/scripts/ 和 references/。

评论

支持 Markdown