RudrenduPaul/evolveguard

GitHub: RudrenduPaul/evolveguard

evolveguard 是一个针对 Claude Agent Skills 文件自我编辑行为的回归测试门禁工具,通过静态解析和基线对比在 skill 变更后检测其能力漂移。

Stars: 1 | Forks: 0

# evolveguard [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/RudrenduPaul/evolveguard/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![Node](https://img.shields.io/badge/node-%3E%3D20.12-brightgreen)](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` 输出生成。
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] 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 ```
evolveguard record --help ``` 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 ```
evolveguard check --help ``` 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 ```
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 ```
**退出码:** `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)。
标签:AI代理, DLL 劫持, GNU通用公共许可证, Homebrew安装, MITM代理, Node.js, 人工智能, 回归测试, 大语言模型, 文档结构分析, 用户模式Hook绕过, 自动化攻击