
让 AI Agent 交付可信代码为 Novu 单体仓库设计 verifier 验证工作流【免费下载链接】novuThe open-source communication infrastructure for agents and products项目地址: https://gitcode.com/GitHub_Trending/no/novu导读大型开源单体仓库monorepo中由 AI 编码 Agent 提交代码的最大风险不是写错而是声称写完了但实际跑不通。Novu 在其 Cursor 协作体系中用一个名为verifier的 Agent验证者专门解决这个问题它扮演怀疑论者在任何任务被标记为完成之后接管通过确认改动文件 → 运行受影响应用的真实测试 → 静态检查 → OpenAPI 规范校验 → 边缘情况扫描这一串动作把声明完成变成证据驱动地验证完成。本文围绕仓库中的 verifier Agent 定义逐条拆解这套验证流程并结合 apps/api/package.json、apps/worker/package.json、apps/dashboard/package.json 与 .cursor/rules/testing.mdc 中的真实脚本定义说明每条命令背后的执行逻辑与适用边界。读完你既能理解如何复刻一个验证者角色的 Prompt 设计也能掌握 Novu 仓库中单测、E2E 与 OpenAPI 校验的确切用法。verifier 是什么一个专职唱反调的编码 Agent在 Cursor 中Agent 通过 Markdown 文件顶部的 YAML frontmatter 进行声明式注册。verifier 的元数据定义了它的职责边界--- name: verifier description: Validates completed work. Use after tasks are marked done to confirm implementations are functional — runs tests, checks types, and verifies the OpenAPI spec where applicable. model: fast ---三个字段的含义分别是nameAgent 的唯一标识供 Cursor 对话中按名调用description定义何时该用我。注意它把触发时机限定得非常精确——after tasks are marked done任务被标记为完成之后这与普通编码 Agent 形成职责互补model: fast指定该 Agent 默认使用轻量快速模型执行。验证任务大多是机械的 grep、跑命令、核对产物不需要重模型推理fast模型能在降低延迟与成本的同时完成任务。正文第一句直接给出角色内核You are a skeptical validator. Your job is to verify that work claimed as complete actually works.你是一个怀疑论验证者你的工作就是核实那些声称已完成的工作是否真的可用。这是一个刻意设计的对抗性角色定位——与写代码的 Agent 不同verifier 的产出不是新功能而是通过与不通过的判定 待修复问题清单。在 .cursor/agents/impact-checker.md 中可以看到体系化的另一半impact-checker在改动前评估共享代码的爆炸半径blast radius而 verifier 在改动后做功能验收。两者共同构成改前评估风险、改后验证结果的闭环。六步验证流程拆解verifier 被调用时按固定步骤执行下面结合仓库中真实脚本逐一还原每步的执行内容与原理。第一步锁定声称完成的具体范围Identify what was claimed to be completed验证不能从你做了什么开始而应从你声称做了什么开始。verifier 先解析任务结论中的改动声明明确验证对象例如新增了某个 UseCase修改了某个 DTO调整了某条路由再进入下一步去核对物理证据。这一步的价值在于把笼统的完工翻译成可检验的断言清单防止 Agent 自述式交付绕过检验。第二步确认实现文件真实存在且包含预期改动Confirm the implementation files exist and contain the expected changes验证者须核对文件系统事实改动涉及的文件是否真的存在、关键符号类/函数/DTO/枚举是否真的按声明被添加或修改。在 Novu 仓库中这意味着验证者要能区分几个看似相似但互不相关的代码库区域apps/apiNestJS 网关承载 REST API、UseCase 编排与 OpenAPI 生成apps/worker后台任务消费者队列 worker处理通知投递等异步逻辑apps/wsWebSocket 网关apps/dashboardVite React 管理面板支撑库libs/dal数据访问、libs/application-generic业务逻辑、packages/shared共享类型/DTO/枚举。文件层核对通过后才能进入跑测试环节。第三步运行受影响应用的真实测试套件Run the relevant test suite for the affected appAPI/worker:cd apps/api pnpm testorcd apps/worker pnpm testDashboard:cd apps/dashboard pnpm test:e2e(only if dashboard is running)这是整个验证流程的中枢。命令选择遵循按受影响应用匹配原则而非全仓一把梭。API 单测cd apps/api pnpm test在 apps/api/package.json 中展开为cross-env TS_NODE_PROJECTtsconfig.spec.json TS_NODE_TRANSPILE_ONLYtrue NODE_ENVtest \ NOVU_ENTERPRISEtrue CLERK_ENABLEDtrue NODE_OPTIONS--no-experimental-strip-types \ mocha --timeout 15000 --require ts-node/register --exit src/**/*.spec.ts细节值得注意基于Mocha ts-node匹配src/**/*.spec.ts的单元测试文件与 .cursor/rules/testing.mdc 中Mocha for API/worker的约定一致通过NOVU_ENTERPRISEtrue、CLERK_ENABLEDtrue把 Enterprise 与 Clerk 能力纳入测试环境脚本中还声明了对novu/ee-*等 workspace 包的依赖见 apps/api/package.json--timeout 15000与--exit保证长任务与进程都能被妥善收尾还有配套的pretest钩子会先执行pnpm build:metadata生成元数据再开始跑测试。Worker 单测cd apps/worker pnpm test对应 apps/worker/package.json 中基于 Mocha 的命令测试文件 glob 为src/**/**/*.spec.ts并在环境变量中关闭了strictNullChecks以匹配现有代码风格。若涉及端到端通知链路.cursor/rules/testing.mdc 还提示 worker 需先启动pnpm start:worker。Dashboard E2Ecd apps/dashboard pnpm test:e2e实际是playwright test见 apps/dashboard/package.json测试目录约定在apps/dashboard/tests/。verifier 特别标注了前置条件——仅当 dashboard 正在运行时执行因为 Playwright 需要真实页面。仓库中已有可参考的 Playwright 用例例如 manage-workflows.e2e.ts 与 sync-workflow.e2e.ts它们配合 page-object-models 与 utils 组织页面对象与公共操作。第四步用pnpm check做 lint 与类型卫生Runpnpm checkin the affected app to confirm no lint or type errorscheck脚本在三个应用中都指向Biomeapps/api/package.jsoncheck: biome check .apps/worker/package.jsoncheck: biome check .apps/dashboard/package.jsoncheck: biome check .Novu 以 biome.json 为根配置规则集分散在 .cursor/rules 与 biome-plugins 下的.grit规则中biome check会同时覆盖 lint 与格式两类问题因此它充当 verifier 的代码卫生门禁确保改动不引入 lint 违规或格式化漂移。第五步涉及 API 端点改动时校验 OpenAPI 规范For API changes that touch endpoints: runnpm run lint:openapi(requires API running)这一步属于按需深度验证。Novu 的 OpenAPI 文档由运行中的 API 服务实时暴露命令在 apps/api/package.json 中定义为spectral lint http://127.0.0.1:${PORT:-3000}/openapi.yaml解读使用 StoplightSpectral对线上 OpenAPI 文档做规则校验stoplight/spectral-cli在 devDependencies 中声明见 apps/api/package.json目标来自正在运行的服务默认127.0.0.1:3000可用PORT环境变量覆盖因此前置条件必须是API 正在运行——这解释了为什么它被单独列为一步而不是放进普通测试。仓库中 OpenAPI 的构建链路佐证了端点改动会波及规范build:generate会执行generate:swagger运行 exportOpenAPIJSON.ts再执行generate:sdk重新生成内部 SDK见 apps/api/package.json产物包括 swagger-spec.json。也就是说端点签名变更不仅影响服务还会扩散到 SDK 层verifier 的这一校验正是为了把规范漂移扼杀在验收阶段。第六步主动寻找遗漏的边缘情况Look for edge cases that may have been missed测试全绿不代表正确。verifier 被要求在收尾时主动质疑空数组、null/undefined输入、并发竞争、权限边界、环境差异、超出主流 happy path 的输入分支……这些仓库约定都有迹可循——例如 .cursor/agents/impact-checker.md 要求评估改动对下游消费者的影响apps/api/migrations 里大量数据迁移脚本的存在也提醒验证者涉及 MongoDB 模型或数据形态的改动还要考虑历史数据与迁移影响。报告输出只陈述验证过的证据verifier 的报告格式被刻意压缩为三类事实Report: - What was verified and passed # 已验证且通过的内容 - What was claimed but is incomplete or broken # 声称完成但实际缺失/损坏的内容 - Specific issues that need to be addressed # 需要解决的具体问题这种三段式强制验证者把输出限定在可验证事实上通过的项必须能回溯到上文的某条命令如apps/api下pnpm test通过涉及 3 个 spec 文件未通过的项必须给出声明 vs 现实的落差如声称新增了XxxUsecase但对应文件不存在问题清单要具体到可执行——指向具体文件、具体断言或具体命令输出而不是空泛的需要改进。模板之外还有一条总的心理纪律Do not accept claims at face value. Test everything you can.不要轻信任何声明尽可能测试一切可测的。这保证 Agent 的输出始终以工具执行结果为准而非以被验证者的自述为准。这一设计模式如何落地到其他工程团队verifier 模式并不绑定 Cursor 或 Novu它沉淀的是一套可复制的AI 交付质检方法论让验证者与实现者角色分离。写代码的 Agent 倾向于为自己的产出辩护专职的 skeptical validator 则被授权唱反调天然规避了自己验证自己的盲区。把验证动作绑定到真实命令而非口头检查。verifier 清单里的每一步都对应仓库里真实存在的 npm/pnpm 脚本test、check、test:e2e、lint:openapi验证结果因此具有可复现性——这正是它与看图说话式 Code Review的本质区别。按改动范围决定验证深度。不是每次改动都跑全量普通 API 改动跑单测 check动端点再加 OpenAPI 校验动 dashboard 才跑需要起服务的 Playwright E2E。验证成本与风险面匹配才不会被团队弃用。报告结构化、证据化。固定三段式输出让开发者扫一眼就知道哪些已确认、哪些被证伪、下一步修什么。对 Novu 仓库而言这套工作流与仓库自身的工程底座深度咬合单测约定见 .cursor/rules/testing.mdc共享代码的爆炸半径评估见 .cursor/agents/impact-checker.md顶层协作约束见 AGENTS.md如改动packages/需重新构建Enterprise 改动需与社区版解耦等边界。verifier 正是把文档化约束翻译成可执行验证步骤的那个角色——它不负责让代码变得正确而是负责让正确这件事变得可以被证明。【免费下载链接】novuThe open-source communication infrastructure for agents and products项目地址: https://gitcode.com/GitHub_Trending/no/novu创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考