开源工具扫描代码仓,评估AI助手能否找到测试命令等指令,暴露README完备但实际命令缺失的问题。
AI 编码 Agent 修改仓库的速度比你审核 diff 还要快。速度快不等于检查到位。如果仓库没有暴露一条可供 Agent 运行的命令,Agent 仍然只能靠猜来判断这次修改是否有效。
这个外围系统就是 Harness(驾驭层):围绕模型的一系列指令、Skills、钩子、测试、CI 和防护栏。模型是租来的。Harness 才是你拥有的。Harness Score 是一个小型开源扫描器,从仓库的文件中测量这个 Harness。它不调用模型,扫描时也不会向外部发信。
1.8.1 版本是一个很好的由头来说这个项目,因为它修复了评分可能造成的一种特定谎言。某个仓库明明已有测试,但扫描器说它没有测试运行器。
模型是租来的。Harness 是你的。
两个仓库用同一个编码 Agent,会得到不同的结果。一个有 AGENTS.md 写明了真正的命令,有一条 Agent 可以在修改后运行的测试,还有一套 CI job 来重复这个检查。另一个只有 README,靠下一次会话重新发现约定俗成的规矩。
Harness Score 的存在就是为了让这种差异变得可见。把 Cursor、Claude Code、Devin、Windsurf、Cline、Continue 或其他 AI 编码工具用到的仓库指向它,你会得到一个从 L0 到 L4 的成熟度等级、一个跨六个维度的 108 分制评分,以及一份缺失证据的排名列表。每个未通过的检查都会说明缺了什么、该去哪里找。同一个 commit 在笔记本上和在 CI 里产生的评分一致,因为检查的是文件系统层面的事实:文件是否存在、脚本是否声明、钩子能否解析。这些不是对产品质量的评判。
指南在 paladini.github.io/harness-score。源码在 paladini/harness-score。
六个维度是一套控制系统,而非样式指南:
上下文与指南:一个新会话能否找到命令和边界?
Skills 与命令:可重复的工作流是打包好的,还是只在文档里用文字描述?
钩子与防护栏:在编辑或 shell 运行时有没有任何强制执行的规则,还是每条规则都是可选的?
传感器:是否有测试运行器、linter、类型检查器、格式化工具,以及至少一个真实的测试文件?
CI:是否存在流水线,且是否运行了那些传感器?
卫生度:Agent 会读到的目录树下,密钥、env 文件和许可证标识是否得到了妥善处理?
传感器是 Agent 在任务执行过程中会用到的部分。测试套件不仅仅是人类的安全网。它是 Agent 在写出自信满满的总结之前检查自己修改是否正确的手段。指南里的实操标准是:一套快速的测试套件加一条显而易见的命令。npm test 是大家熟悉的形态。但这并不是唯一的形态。
Harness Score 1.8.1 的诞生源于 @lglucas 的一份公开报告,即 issue #88。那个仓库没有 package.json,但确实有加载 Node 内置运行器的测试文件,CI 用 node --test 运行它们。Node 文档指出那条命令不需要配置文件也不需要依赖(Running tests from the command line)。
SNS-01,即"测试运行器已配置"这一检查项,仍然失败了。它知道如何检测 package.json 里的 test 脚本、Vitest、Jest、pytest、go test 和 cargo test。但它不知道如何检测 require('node:test')。失败信息说没有检测到运行器。这让人去四处寻找一个缺失的框架。而运行器其实已经在那里了。
v1.8.1 在满足以下条件时通过该检查:一个类似测试的 JavaScript 或 TypeScript 文件实际加载了 node:test,包括 import 和 require,以及子路径如 node:test/reporters。证据中会列出 Agent 可以运行的命令:
node:test built-in (node --test), e.g. scripts/test/a.test.js
一个只是文件名叫 a.test.js 的文件仍然不会通过。Jest、Vitest 和 Node 的运行器共用那个文件名,而另一个检查项已经单独为"测试文件存在"打了分。如果测试文件存在但没有任何东西连接运行器,现在失败信息会这样说:
Found 1 test file(s), e.g. a.test.js, but no test runner or standard entry point detected.
只有一行 CI 配置包含 node --test,本身不会通过 SNS-01。"CI 运行了测试"是另一项检查。本地的信号是 node:test 的加载。package.json 中 "test": "node --test" 这个脚本在本次发布之前就已经通过了,现在仍然可以。
这就是一个案例中的产品。当评分能说出 Agent 可以运行什么反馈时,它是有用的。当它凭空捏造出一个缺失的工具时,它是有害的。扫描器的其余部分就是把这个思路应用到了指南、Skills、钩子、linter 和 CI 上。
需要 Node.js 18 或更高版本。不需要 API key。扫描不会安装你的依赖,也不会修改目录树。
确认包版本,然后扫描当前目录:
npx --yes harness-score@1.8.1 --version
npx --yes harness-score@1.8.1 .
--version 应该打印出 1.8.1。如果没有,说明 registry 还没有同步完 GitHub release。等一等再重新 pin 版本,而不要信任没有 pin 版本的 npx harness-score,它可能仍然解析到 1.8.0。
先读未通过的检查,再读总分。一条缺失的测试命令、一条缺失的 linter 和一条缺失的 CI job 是不同的修复。每个检查项上的 remediation 行就是下一步要改的内容,报告中从指南链接过去的部分会指向匹配的章节。
如果你想专门测试 Node 的情况,一个最小化文件就够了。以下是这个项目自身测试所覆盖的形态,不是建议你删掉已有的运行器:
const { test } = require('node:test');
test('ok', () => {});
把它放到一个没有 package.json test 脚本的仓库的 scripts/test/a.test.js 中。在 1.8.1 上,SNS-01 应该通过并提到 node --test。一个从未加载过 node:test 的兄弟文件仍然应该失败,且错误信息应该指明那个文件。
一旦仓库达到了相应水平,你也可以在 CI 上卡一个等级:
- uses: paladini/harness-score@v1
Action tag v1 只在发布版本后才会移动。需要稳定对比时,pin 一个扫描器版本。1.8.0 和 1.8.1 的评分在 SNS-01 上不可互换:一个只有 node:test 的仓库可以在不做任何其他改动的情况下获得那些分数。
高分意味着找到了预期的文件和命令。它不意味着测试覆盖了你关心的行为,不意味着 AGENTS.md 中的规则是真实的,也不意味着有人审核过 diff。扫描器分不清一个好的测试和一个总是通过的测试。
它也不要求你在 AGENTS.md 中写明命令。Remediation 文本要求的是一个显而易见的入口点,以及在 agent 指南中的一条备注。检查本身是在找运行器。把命令写下来仍然是 Agent 到达时第一件会读的事。证据中的 node --test 是扫描器在告诉你那条命令。你的指南里也应该写上它。
不要为了抬高分数而添加空的 Skills、未使用的钩子或你根本不需要的 package.json。对于一个零依赖的 Node 仓库,node --test 是一个真实的入口点。为了满足旧版扫描器而添加 npm 是一个错误的修复方式。这就是本次发布存在的原因。
Harness Score 是测量 AI 编码 Agent 周围系统的一把尺子。v1.8.1 是这把尺子上的一处修正:Node 的内置测试运行器算数了,已经有测试的仓库不会再被告知运行器缺失。无论哪种情况,有用的习惯都是一样的。给 Agent 一条可以检查修改效果的命令,让那条命令保持快速,并让 CI 再次运行它。
如果一个 Agent 今天打开了你的仓库,你希望它在宣称任务完成之前运行的单条命令是什么?
AI 协助披露:我在组织和编辑这篇文章时使用了 AI 协助。扫描器行为、v1.8.1 发布说明、issue #88 和 Node.js 测试运行器文档均已与这些一手来源进行过核对。