关于 verify
verify 是用于 Consumer 仓库的验证技能,通过共享默认配置和仓库级覆盖项定义检查阶段。钩子与 CI 调用同一配置,涵盖继承、预算、分层和目标路径规则。
主要功能
- 01按阶段配置验证步骤
- 02合并共享默认项与仓库覆盖项
- 03阶段继承及步骤替换或移除
- 04按层级和目标路径跳过步骤
- 05为检查设置预算并执行审计
适用场景
- 01统一本地推送钩子与 CI 检查
- 02为不同阶段安排测试和构建
- 03为特定仓库添加或调整验证步骤
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ timschoch/ skilly --skill verify安装后在 Claude Code 中输入/verify确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/verify.jsonscripts/audit.mjsblock-destructive-git.shblock-invalid-branch-push.shblock-unverified-push.shcheck-branch-name.mjscheck-commit-msg.mjscheck-push-branch.mjsdefault-branch.mjsmerge-config.mjsrun-changed-tests.mjsverify.mjs详细介绍
验证
references/verify.json 保存默认步骤。Sync 会在每个 Consumer 中让这些步骤保持最新。.skilly/verify.json 只保存仓库变更的内容。Hook 和 CI 会调用合并配置中的某个阶段,因此本地门禁和流水线不会对何为通过产生分歧。
用法
node .agents/skills/verify/scripts/verify.mjs <stage> # run the stage
node .agents/skills/verify/scripts/verify.mjs <stage> --steps # resolved steps as JSON, runs nothing
node .agents/skills/verify/scripts/verify.mjs --config # merged config as JSON, runs nothing
在 Consumer 的任意位置都可以运行。退出码为 0 表示通过,2 表示配置或用法错误,其他退出码则表示失败步骤的退出码。
配置
两个文件的结构:
{
"budgetTicket": "https://github.com/owner/repo/issues/1",
"stages": {
"commit": { "budgetSeconds": 10, "steps": [{ "name": "lint-staged", "run": "npx lint-staged", "why": "the reason this step exists" }] },
"push": { "extends": "commit", "budgetSeconds": 120, "steps": [] },
"ci": { "extends": "push", "budgetSeconds": 600, "steps": [] },
"nightly": { "tier": "product", "budgetSeconds": 1800, "steps": [{ "name": "e2e", "run": "npm run e2e", "target": "e2e" }] }
}
}
extends 会累积继承:push 会先运行所有 commit 步骤。只有配置明确指定时,某个阶段才会跳过继承的步骤:
| 字段 | 作用对象 | 效果 |
|---|---|---|
"replaces": "unit (changed)" | 某个步骤 | 此步骤运行时,移除指定步骤。unit 会运行变更的测试,因此每项测试只运行一次 |
"without": ["unit", "e2e smoke"] | 某个阶段 | 移除指定的继承步骤 |
阶段
| 阶段 | 运行内容 | 调用方 |
|---|---|---|
commit | 默认不运行任何内容 | pre-commit 直接调用 lint-staged |
push | 分支名、命名、类型检查、unit (changed) | pre-push Hook |
ci | push、lint、完整 unit、构建、审计、e2e smoke | CI 在 PR 上运行;在某个 PR 会运行 pr 的发布 PR 上也会运行 |
pr | ci,但不运行完整 unit 和 e2e smoke | CI 在带有发布 PR 和 nightly 的产品仓库 PR 上运行 |
nightly | 完整 unit、e2e full、依赖漂移、安全扫描 | 产品层级的 nightly 工作流 |
pr 需要有完整的兜底:每次合并到 main 时,发布 PR 和 nightly 都会运行完整测试套件。只有两者都存在时,setup-repo 的 ci.yml 模板才会选择 pr。
变更的测试
unit (changed) 会运行 scripts/run-changed-tests.mjs:使用 --changed <base> 执行测试命令;如果差异中包含 fullSuiteTriggers 路径,则运行完整测试套件。Vitest 只会跟踪导入关系,而没有测试会导入锁文件或迁移文件。
{ "fullSuiteTriggers": ["drizzle/"] }
| 触发路径 | 匹配内容 |
|---|---|
drizzle/ | Git 根目录下该文件夹中的每个文件 |
package.json | 任意深度下的该文件名 |
vitest.config.* | * 表示单个路径段中的任意字符 |
src/schema.sql | 该路径 |
.skilly/verify.json 中的列表会追加到默认列表;"-package.json" 会移除其中一项。
预算只会发出警告,不会导致失败。因速度慢而失败的门禁会让你学会绕过它,而速度问题消失后,绕过门禁的做法仍会延续。budgetTicket 用于说明超出预算的阶段应在哪里拆分。
覆盖
.skilly/verify.json 会与默认配置合并(scripts/merge-config.mjs)。每个阶段内,步骤按 name 匹配:
| 仓库文件 | 效果 |
|---|---|
{ "name": "lint", "run": "pnpm lint" } | 修改默认的 lint 步骤,同时保留其其他字段 |
"-lint" | 移除默认的 lint 步骤 |
{ "name": "docs", "run": "…" } | 在默认步骤之后添加一个步骤 |
阶段上的 "budgetSeconds": 60 | 替换默认值 |
覆盖 unit 时,每次都必须运行完整测试套件,因为 unit 会替换 unit (changed)。如果覆盖后只在特定条件下运行测试套件,必须设置 "replaces": null。
该文件为可选文件。使用 --config 或 <stage> --steps 检查结果。
层级
.skilly/config.json 中的 tier 默认为 sandbox,层级顺序为 sandbox < tool < product。某个步骤的 tier 表示仓库运行该步骤所需的最低层级;低于此层级时会跳过该步骤。阶段的 tier 对整个阶段应用相同规则:低于此层级时不会运行任何内容,退出码为 0。层级决定兜底范围,而不是标准。
目标
步骤的 target 是相对于仓库根目录的路径;如果路径不存在,就会跳过该步骤。这样,同一个阶段列表就能适用于并非所有仓库都有 e2e/ 或 Dockerfile 的情况。
审计
audit 步骤(scripts/audit.mjs)会在发现任何高危或严重级别的公告时失败。存在 yarn.lock 时会运行 yarn audit(yarn 1),否则运行 npm audit。没有修复版本的公告会加入 .skilly/verify.json 中该步骤的 accept 列表:
{ "stages": { "ci": { "steps": [{ "name": "audit", "accept": [{ "id": "GHSA-vfj7-8cjw-p6xm", "why": "braces, no fix, dev only" }] }] } } }
条目必须包含 id 和 why;缺少其中任意一项都不会接受任何公告。一旦 GitHub 为审计匹配的范围列出修复版本,或审计不再发现该公告,步骤就会失败。届时请将其移除。该步骤绝不会修改此文件,因此本地检查和 CI 得出的结果一致。
钩子脚本
检查项和防护脚本都随此处发布,因此每个 Sync PR 都会更新它们。/setup-repo(setup-project bundle)会为其配置接线;切勿将其中任何脚本复制到仓库中。
| 脚本 | 运行方 | 阻止的操作 |
|---|---|---|
| check-commit-msg.mjs | commit-msg | 不符合 Conventional Commits 规范的提交标题 |
| check-push-branch.mjs | pre-push | 直接推送到主干 |
| check-branch-name.mjs | branch name 步骤 | 不符合 <type>/<description> 格式的分支名 |
| block-destructive-git.sh | Claude Code PreToolUse | reset --hard、clean -f、branch -D、不带参数的 push --force |
| block-invalid-branch-push.sh | Claude Code PreToolUse | Agent 从不合规的分支名推送,即使未安装 git 钩子也会阻止 |
| block-unverified-push.sh | Claude Code PreToolUse | Agent 跳过 push 阶段进行推送 |
添加检查项
检查项必须是一个步骤,绝不能是钩子或工作流中的一行。仅适用于此仓库的检查项只能放在 .skilly/verify.json 中。每个 Consumer 都需要的检查项应放在 hub 的 bundles/workflow/skills/verify/references/verify.json 中。请为其填写 why:步骤变红时会立即打印这段说明,而读者此时最不可能主动查找原因。