RudrenduPaul/evolveguard
GitHub: RudrenduPaul/evolveguard
evolveguard 是一个针对 Claude Agent Skills 文件自我编辑行为的回归测试门禁工具,通过静态解析和基线对比在 skill 变更后检测其能力漂移。
Stars: 1 | Forks: 0
# evolveguard
[](https://github.com/RudrenduPaul/evolveguard/actions/workflows/ci.yml)
[](LICENSE)
[](package.json)
在 Claude Agent Skill 自我编辑导致行为漂移且尚未发布之前,将其捕获。
```
npm install -g evolveguard
```
Claude Code 的 Agent Skills 可以由人类编写,也可以由 agent 本身编写:`/skillify`
将工作流转化为 `SKILL.md`,并且同一环境中的 auto-memory 系统
会编写 `MEMORY.md` 文件,这些文件会在不知不觉中改变 agent 在下一次会话中的行为。
目前这些操作都没有进行回归检查。一个破坏了正常工作流的 skill 编辑
看起来与修复工作流的 skill 编辑完全一样,直到有人注意到 agent 不再
做它以前做过的事情。
evolveguard 记录一个 skill 自身能力表面(它声明或展示使用的工具)的基线,然后在每次 skill 文件
更改时重新推导该表面,并将结果与基线进行差异比对:要么是相同的工具调用序列,要么是带有
具体原因的标记漂移。
## 它的功能
```
evolveguard record ./SKILL.md --fixtures ./fixtures.json
# ... skill 被编辑,由人类或 agent ...
evolveguard check ./SKILL.md
```
```
EvolveGuard v0.1.0 -- Regression Check
skill: monorepo-scanner baseline: 2026-07-15 fixtures: 1
[DRIFT] fixture: "scan a monorepo" new tool call: fs.write (baseline had none)
-> new tool call: fs.write (baseline had none) -- this edit introduces a
capability the baseline never used
0 PASS, 1 DRIFT, 0 FAIL
exit code 1 (DRIFT blocks merge by default; override with --allow-drift)
```
这是本仓库自身的 `fixtures/labeled-non-breaking-edits/case-03-add-write-capability/`
测试用例的真实输出,在 skill 的 frontmatter 中将 `filesystem: read-only` 连接到 `read-write`。
## 工作原理
evolveguard 不会运行实时的 LLM agent,也不会重放真实的对话
记录。在设计上,它是一个静态、确定性的工具:
1. **`record`** 解析 skill 文件的 YAML frontmatter(声明的 `tools`、`network`、
`filesystem`、`scope` 以及任何捆绑的 `hooks`),扫描 skill 的正文以及任何
hook 脚本,以寻找网络调用或文件系统写入的静态证据,并将两者
结合成一个**能力表面** —— 即该 skill 声明或展示使用的
工具集合。每个 fixture 的 `expectedToolCalls` 将该表面过滤为 fixture 作者
声明关心的工具;结果即为记录的基线。
2. **`check`** 重新读取(可能已编辑的)skill 文件,使用完全相同的逻辑重新推导其能力
表面,并根据 fixture 再次对其进行过滤。
3. **`diff`** 按 fixture 比较基线与当前状态(如果工具集和范围
匹配则为 PASS,否则为带有具体原因的 DRIFT),并单独对*整个*
能力表面进行差异比对,这样即使没有任何 fixture 的 `expectedToolCalls` 恰好
覆盖到的新能力也能被捕获,而不是静默通过。
evolveguard 检测的是 skill *声明或展示* 能做到的事情的变化。它
无法告诉你实时的 agent 运行在特定的
prompt 下是否真的会有不同的行为——这是一个真实且有意的范围限制。其权衡在于:它只需要一个
`SKILL.md` 文件和一个 fixtures 文件,无需托管任何内容,也无需集成任何 SDK,
这也是为什么它可以在 pre-commit hook 或 CI 任务中完全离线运行。
## 它的不同之处
**Braintrust** 是一个通用的 LLM 评估和可观测性平台。如果你
已经在记录来自实时 agent 的 trace 并希望跨运行进行统计评估评分,它是一个
绝佳的选择,但它需要集成 SDK 并且每个应用都需要一个 eval-definition 步骤。evolveguard
两者都不需要:将其指向一个 `SKILL.md` 文件和一个 fixtures JSON,它就能正常工作。
**[agent-eval](https://github.com/RudrenduPaul/agent-eval)**(同一作者的另一个
仓库)回答了一个不同且更普遍的问题:“在我定义的两个版本之间,我的 agent 的行为是否发生了
变化”,它适用于任何 agent,与框架无关,但需要你自己
启动并运行这两个版本。evolveguard 回答了一个更狭窄、结构上
不同的问题,由 `SKILL.md`/`MEMORY.md` 上的文件差异直接触发:*这个特定的编辑*是否
改变了基线所记录的能力表面。它直接解析
skill artifact 本身,绝不会要求你定义或运行任何实时内容。
| | evolveguard | Braintrust | agent-eval |
| -------------- | -------------------------------------------- | ---------------------------------- | --------------------------------- |
| 设置 | 对一个文件进行 `record` + `check` | SDK 集成,eval 定义 | 定义并运行两个 agent 版本 |
| 触发器 | `SKILL.md`/`MEMORY.md` 文件差异 | 手动 eval 运行 | 手动 A/B 运行 |
| 机制 | 静态能力表面差异比对 | 实时运行 trace 评分 | 统计行为比较 |
| 托管基础设施 | 无 | 托管平台 | 无 |
| 实时 LLM 调用 | 无 | 是(对真实运行评分) | 是(运行两个版本) |
| 最适用于 | 专门针对自我编辑的 Claude Agent Skills | 通用 LLM 应用 eval/可观测性 | 任何 agent,通用 A/B 回归 |
## 快速开始
```
# 1. 针对 skill 及其标记的 fixtures 记录 baseline
evolveguard record ./skills/my-skill/SKILL.md --fixtures ./fixtures/my-skill.json
# 写入 ./skills/my-skill/.evolveguard-baseline.json
# 2. 编辑 skill(手动,或让 agent 编辑它)
# 3. 检查 drift
evolveguard check ./skills/my-skill/SKILL.md
# 写入 ./evolveguard-report.json,如果发现 drift 则退出并返回状态码 1
```
fixtures 文件是一个 JSON 数组,包含带标签的 prompt 以及每个预期要触发的
工具调用形态:
```
[
{
"id": "scan-a-monorepo",
"prompt": "scan a monorepo",
"expectedToolCalls": [{ "tool": "fs.read" }, { "tool": "fs.write" }]
}
]
```
`expectedToolCalls` 是可选的——省略它,该 fixture 就会被视为测试
skill 的整个能力表面。`scopeMatches`(一个 glob)将工具缩小到特定的
文件系统范围,例如 `{ "tool": "fs.write", "scopeMatches": "./workspace/**" }`。
## CLI 命令参考
根据构建的 CLI 的实际 `--help` 输出生成。
```
Usage: evolveguard [options] [command]
Regression-testing CLI for self-edited Claude Agent Skills (SKILL.md,
MEMORY.md) -- golden-transcript record/replay against a skill's own declared
and inferred capability surface, zero hosted infrastructure.
Options:
-V, --version output the version number
-h, --help display help for command
Commands:
record [options] Record a golden-transcript baseline for a
skill against a set of labeled fixtures
check [options] Replay the fixtures from a baseline against
the current (possibly edited) skill and report
drift
report [options] [reportPath] Print a previously generated
evolveguard-report.json
mcp [coming soon] Expose record/check/report as
MCP tools for a coding agent to call
mid-session
help [command] display help for command
```
```
Usage: evolveguard record [options]
Record a golden-transcript baseline for a skill against a set of labeled
fixtures
Arguments:
skillPath path to the SKILL.md or MEMORY.md file to baseline
Options:
--fixtures path to a fixtures JSON file (array of {id, prompt,
expectedToolCalls?})
--baseline path to write the baseline file (default:
/.evolveguard-baseline.json)
--json output structured JSON instead of human-readable text
(default: false)
-h, --help display help for command
```
```
Usage: evolveguard check [options]
Replay the fixtures from a baseline against the current (possibly edited) skill
and report drift
Arguments:
skillPath path to the SKILL.md or MEMORY.md file to check
Options:
--baseline path to the baseline file (default:
/.evolveguard-baseline.json)
--report path to write the report file (default:
"./evolveguard-report.json")
--allow-drift exit 0 even if drift is detected (drift is still reported)
(default: false)
--json output structured JSON instead of human-readable text
(default: false)
-h, --help display help for command
```
```
Usage: evolveguard report [options] [reportPath]
Print a previously generated evolveguard-report.json
Arguments:
reportPath path to the report file (default: "./evolveguard-report.json")
Options:
--json output structured JSON instead of human-readable text (default:
false)
-h, --help display help for command
```
**退出码:** `0` 所有 fixture PASS 且没有表面级别的漂移,`1` 发现至少一个 DRIFT
(传入 `--allow-drift` 可在报告的同时仍以代码 0 退出),`2` 使用
错误或文件解析失败。
## Agent 原生用法
每个子命令都支持 `--json`,用于输出 agent 可以直接解析的结构化数据:
```
evolveguard check ./SKILL.md --json
```
```
{
"schemaVersion": 1,
"skillName": "monorepo-scanner",
"results": [
{
"id": "scan-a-monorepo",
"verdict": "DRIFT",
"changes": [
/* ... */
]
}
],
"surfaceChanges": [],
"summary": { "pass": 0, "drift": 1, "total": 1 },
"exitCode": 1
}
```
`evolveguard mcp` 已记录在文档中,但尚未实现——请参阅上面的 CLI 参考。
在它发布之前,请从你的编码 agent 中作为子进程直接调用 `record`/`check`/`report --json`。
## 库 API
evolveguard 还为相同的 pipeline 导出了编程 API,如果你希望
将其集成到你自己的工具中,而不是通过 shell 调用 CLI:
```
import {
recordBaseline,
replaySkill,
diffAll,
writeBaseline,
readBaseline,
} from 'evolveguard';
const baseline = recordBaseline('./SKILL.md', './fixtures.json');
writeBaseline('./.evolveguard-baseline.json', baseline);
// ... skill gets edited ...
const saved = readBaseline('./.evolveguard-baseline.json');
const replay = replaySkill('./SKILL.md', saved);
const report = diffAll(saved, replay);
```
有关完整的导出接口,请参见 `src/evolveguard/index.ts`:`parseSkillFile`、
`deriveCapabilitySurface`、`loadSkill`、`buildFixtureSnapshots`、`loadFixtures`、
`recordBaseline`、`replaySkill`、`diffFixture`、`diffAll`、`diffSurface`、`writeBaseline`、
`readBaseline`、`writeReport`、`readReport`,以及共享的 `types.ts` 接口。
## 误报率
任何准确性声明都必须伴随着产生它的命令才能生效。运行:
```
npx vitest run src/evolveguard/benchmark.test.ts
```
针对 `fixtures/labeled-non-breaking-edits/` —— 一个小型的、人工标注的真实
前后 `SKILL.md` 对语料库(措辞调整和拼写错误修复标记为非破坏性;文件系统范围扩大、新的写入能力以及获得网络调用的
hook 脚本标记为破坏性)。截至本次提交:**0% 误报**(2 个非破坏性案例中有 0 个被
标记为漂移)。该语料库很小,随着更多真实的 skill 编辑被
报告,它将会增长;请参见 `fixtures/labeled-non-breaking-edits/README.md`。
## evolveguard 是什么,为什么会出现
evolveguard 是一个命令行工具和 TypeScript 库,用于检测 Claude Agent Skill 文件(`SKILL.md`)和 Claude Code auto-memory 文件(`MEMORY.md`)在被人类或 agent 编辑后发生的
能力漂移。它的工作原理是解析 skill 声明的
frontmatter 范围,以及在其正文和捆绑的 hook 脚本中网络或文件系统写入行为的
任何静态证据,将其快照作为基线,并在编辑后重新推导
相同的快照以与之进行差异比对。它之所以存在,是因为 Claude Code 的 Agent
Skills 生态系统允许 skill 和 memory 文件在人类不一定审查每一次编辑是否产生回归的情况下改变 agent 的
行为,而且现有的任何工具都无法在不集成 SDK 或运行实时 agent 的情况下检查这种特定的
artifact 形态。
## 常见问题
**evolveguard 会调用 LLM 吗?**
不会。Record 和 check 都是完全静态和确定性的——请参阅上面的“工作原理”。
**它能捕获 agent 在特定 prompt 下实际决定执行的操作的变化吗?**
不能,无法直接捕获。它捕获的是 skill 声明或推断的能力
表面(它被允许或展示使用的工具)的变化,这只是行为的代理,而不是其实时
trace。如果你需要对实际的 agent 运行进行评分,请使用 Braintrust 或 agent-eval。
**它适用于没有 frontmatter 的 MEMORY.md 文件吗?**
是的。没有 frontmatter 的文件将被解析为具有空的声明范围,因此其能力
表面完全来自于正文中发现的静态证据。
**这是一个通用的 agent 进化框架吗?**
不是。请参阅上面的“它的不同之处”——evolveguard 故意不构建或托管
自我进化的 agent 框架;它仅测试已经发生的 skill/memory 编辑。
**这已经在 npm 上发布了吗?**
还没有——请参阅[状态](#status)。
## 状态
这是一个 v0.1 版本:对现有 Claude Agent Skills
生态系统的一个小型、专注的补充。它完全采用 MIT 许可,没有专有层级。`npm pack --dry-run`
顺利通过,`package.json` 元数据也已准备好发布,但实际的 `npm publish`
是一个刻意的、独立的、受 2FA 保护的步骤,本仓库不会自行触发。
## 安全
请参阅 [SECURITY.md](SECURITY.md)。
## 许可证
MIT。请参阅 [LICENSE](LICENSE)。
evolveguard --help
```
Usage: evolveguard [options] [command]
Regression-testing CLI for self-edited Claude Agent Skills (SKILL.md,
MEMORY.md) -- golden-transcript record/replay against a skill's own declared
and inferred capability surface, zero hosted infrastructure.
Options:
-V, --version output the version number
-h, --help display help for command
Commands:
record [options] evolveguard record --help
```
Usage: evolveguard record [options] evolveguard check --help
```
Usage: evolveguard check [options] evolveguard report --help
```
Usage: evolveguard report [options] [reportPath]
Print a previously generated evolveguard-report.json
Arguments:
reportPath path to the report file (default: "./evolveguard-report.json")
Options:
--json output structured JSON instead of human-readable text (default:
false)
-h, --help display help for command
```
标签:AI代理, DLL 劫持, GNU通用公共许可证, Homebrew安装, MITM代理, Node.js, 人工智能, 回归测试, 大语言模型, 文档结构分析, 用户模式Hook绕过, 自动化攻击