Skip to main content

验证流程指南

这份文档假设你没有读过本项目的其它任何文档。它讲的是:怎么在任意宿主的机器上 装配并运行这条技能验证流水线。

配套:技能本身怎么写 → 《技能编写指南.md》;新手照着做 → 《操作手册.md》; 换机器 / 搬到别的宿主 → 《迁移与部署指南.md》;想弄清代码结构 → 《仓库结构说明.md》。 适用前提:个人小团队(≤2 人);不需要联网(除官方校验器对账外);不需要安装任何第三方 Python 包。


一、它是什么,解决什么问题

skillverify 是一条覆盖 Agent Skill 从设计到运行的验证流水线,分五层:

层 命令 查什么 为什么需要它
官方规范 spec frontmatter 6 字段与命名约定 官方校验器只查这些
机械补检 lint 引用、上下文预算、目录卫生、脚本契约、依赖、安全、编码 官方完全不查这些
评测资产 evals 官方 evals/evals.json 与工作区产物(输出质量)+ evals/trigger-queryset.json 与运行记录(会不会被触发) 官方给了硬约定但没有工具;触发这一层官方根本不覆盖
语义评审 review 30 条提示词的判断(描述质量、可验证性、安全性…) 机械层查不了"写得对不对"
交付门禁 deliver 汇总上面的结论,决定能不能交付 防止"带着没查的项交付"

设计前提:宿主无关(不假设特定宿主的目录、不硬编码宿主名)、纯标准库、 强制 UTF-8(Windows 上的 GBK 曾把旧工具链直接打崩)。

退出码(全族统一,便于任何 CI 消费):

码 含义
0 全 PASS(含"不适用")
1 有 FAIL(阻断项)
2 无 FAIL,但有 WARN(需人工判断)或 SKIP(本项未执行)

报告里的判定只有五种:FAIL(阻断)、WARN(人工甄别)、SKIP(本项未执行,不许当成通过)、 INFO(不适用)、PASS。

二、跑起来

不需要 pip 安装也能用(免安装直接跑 repo):

cd <本仓库>
python -m skillverify.cli --help

安装后(可选,见本仓库的打包配置)命令名就是 skillverify:

skillverify --help

Python 版本:discover / check / watch / deliver / hook 需要 ≥3.11 (用标准库 tomllib 解析配置文件);spec / lint / evals / review 在更早版本也能用。

三、技能放在哪里:声明式宿主适配

技能存放位置不写死在代码里,而是读一份声明文件 hosts.toml:

skillverify discover --show-config      # 看当前生效的配置(含来源顺序)
skillverify discover                    # 看发现了哪些技能、每个根命中几个

内置配置(随包分发)里的默认档就是官方跨宿主约定:项目级 <项目>/.agents/skills/、 用户级 ~/.agents/skills/。另外预置了几个兼容档(workbuddy、project-local、 nested-by-category)供参考。

配置覆盖顺序(后者覆盖前者,列表是整体替换而不是拼接):

内置 < ~/.agents/skillverify/hosts.toml < <项目>/.agents/skillverify/hosts.toml < --config <文件>

接入一个新宿主:只改配置,不改代码

假设某宿主把技能放在 .acme-corp/skills/:

# acme.toml
[hosts.acme-corp]
description = "Acme 布局"
project_roots = [".acme-corp/skills", ".agents/skills"]
user_roots = ["~/.acme-corp/skills", "~/.agents/skills"]
trace_dir = ".agents/skillverify"
max_depth = 1
skillverify discover --config acme.toml --host acme-corp
skillverify check    --config acme.toml --host acme-corp

字段含义:project_roots(相对项目目录;绝对路径原样使用)、user_roots(~ 按当前用户主目录展开)、 trace_dir(中央留痕目录)、max_depth(技能根下最多下钻几层找 SKILL.md)。 未知键会直接报错(把 project_roots 拼成单数而静默发现 0 个技能,是这类工具最坏的失败模式)。

不想动配置文件时,用 --root 直接指定技能根(给出后完全替换配置里的根列表):

skillverify discover --root <技能根>

同名技能出现在多个根时,会记 DISC-001 并保留两者(不静默覆盖)——两处并存说明不同宿主 可能加载到不同版本,这是要解决的问题,不是要掩盖的问题。

四、逐层跑

4.1 单个技能

skillverify spec  <技能目录>              # 官方规范(可加 --official 与官方 CLI 对账)
skillverify lint  <技能目录>              # 机械补检
skillverify lint  <技能目录> --scripts    # 额外实测脚本契约(会执行脚本,须显式开启)
skillverify evals <技能目录>              # 两类评测资产:官方 evals.json + 触发查询集

执行层委托官方工具:评测的执行(跑 with/without、算 benchmark、A/B、按结果改进) 由官方 skill-creator(或你的宿主)提供,本项目不自研执行器——只校验它产出的产物形状与口径 (grading.json / timing.json / benchmark.json 的字段、阈值、对账关系)。理由很直接: 官方已有执行层,重复造一个只会与它的产物格式漂移。

要真跑评测:本工具不执行评测。用官方 skill-creator 或你的宿主跑,再把它的入口命令交给 evals --run-with "<命令>" 委托执行(本工具负责限时、报退出码,并在跑完后重新校验产物; 命令失败记 RUN-101 FAIL,绝不写成"不适用")。

evals 同时校验两类资产:官方输出质量评测(evals/evals.json,形状由官方固定)与 触发评测(evals/trigger-queryset.json + evals/trigger-runs.json,本项目约定)。 两类都没有时都会给出 WARN 而不是静默通过——「没有证据」与「证据全绿」必须能区分开。 若技能里还留着旧落点(.verification/trigger-eval/queryset.json),报告会直接给出迁移指引。

4.2 整库批量

4.1b 机械层还会查什么(加固轮新增)

规则 查什么 判定
HYG-006 license 字段是否过长(完整条款该放随包文件) WARN
HYG-007 声明了 license 就该有随包许可文件 WARN
SEC-008 隐藏字符:双向控制符(Trojan Source)/ 零宽字符 代码里双向控制符 FAIL;其余 WARN
SCRIPT-009 声明了 --dry-run 的脚本试跑后不得改动技能目录 改动 → FAIL(在临时副本里验证)
SCRIPT-005 破坏性/有状态操作须有防护旗标(扫全包代码文件);证据给出 file:行(类别):原文 的定位段落 无旗标 → WARN
EVAL-010 断言区分度:跨轮次恒真/恒假的断言 WARN(观测不足 3 次记 INFO)
REV-012 评委校准:判错校准样本 判错 → FAIL(结论不可用);没做 → INFO
skillverify check --root <技能根> --stages all

--stages 可选 all(spec+lint+evals+review)/ both(spec+lint)/ 单阶段。 check 默认 both(日常快查)。未发现任何技能时返回 1——"什么都没检查"不允许看起来像通过。

4.3 挂载前置检查(上宿主之前)

skillverify mount --project <项目> --user-home <用户主目录>          # 查当前生效的宿主档
skillverify mount --project <项目> --skill <技能名>                  # 只查这个技能
skillverify mount --project <项目> --all-hosts                      # 逐个宿主档都查(新接宿主时用)

它在仓库侧能确定的范围里回答「这个技能放到宿主上会不会有问题」:

检查 问的是
MOUNT-001 技能真的落在该宿主档声明的目录里吗(不是「我以为我放进去了」)
MOUNT-002 SKILL.md 可解析、name/description 都读得出来且非空吗(描述为空的技能宿主会跳过)
MOUNT-003 同一宿主档里有没有同名技能(宿主加载哪一份是不确定的)
MOUNT-004 把三种结构损坏的 frontmatter 注入临时副本后,解析器会 fail-loud 吗(不触碰原目录)

它不验证宿主注册表与真实触发匹配——本工具没有宿主 API、也没有宿主运行时,那两件事请在目标 宿主里人工确认。默认只查当前生效的宿主档;配置里的兼容档并不是你在用的布局,拿它们报 「技能不在声明目录里」只会是噪声,所以逐个档验收时要显式 --all-hosts。

4.4 库级检查(把技能集合当整体看)

单技能检查看不见两类问题,它们只在技能一多时才出现:

skillverify discover --project <项目>                       # 顺带打印库级结论
skillverify check --project <项目> --metadata-budget 8000   # 也可以收紧预算
检查 问的是
LIB-001 全部技能的 name+description 加起来多少字符?超过预算没有?宿主启动时会把它们一起读进上下文,超了就会静默丢弃某些技能(不报错、不生效)
LIB-002 有没有两个技能的描述用词高度重合?(触发时互相抢)会点名是哪两个、并列出共同词元

口径写在报告里,别当成官方硬线:预算默认 8000 字符(本项目约定,可用 --metadata-budget 覆盖, 真实上限由你的宿主决定);只计 name+description,不含宿主自身的包装开销; LIB-002 是词面重叠(字符 bigram + 词元,纯离线),不是语义相似度——它只把 "最该人工看一遍的那几对"挑出来,词元太少的描述会被明确排除在比对之外。

4.5 外来技能审计(从别处拿来的技能,用之前)

skillverify audit <技能目录或技能名> --record      # 出审计单并留痕(下次可比对)

它把各阶段的结论组合成一张"要不要用它"的单子:来源(git 远端/提交,能查到就记)、 能力清单(脚本、网络端点、破坏性/有状态操作、疑似硬编码密钥、外部依赖)、 判定明细(spec/lint 的 FAIL/WARN 原样带进来)、内容指纹,以及库内名字近似提示。

退出码:audit 会把 lint 的结论一并带进来,所以默认(不执行脚本)返回 2—— 那表示"脚本契约四项没执行",与 lint 的口径一致;不是审计失败。要连脚本一起实测再加 --scripts (审计外来技能时请先想清楚:那会真的执行对方的脚本)。

能力清单不是从报告文字里猜的:它来自机械层的结构化扫描(security.facts()、 scripts.facts()、deps.facts()),所以 lint 的措辞改了也不会影响审计单。口径写在单子上: 网络端点 = 代码文件里出现且未在 frontmatter 声明的主机;破坏性/有状态操作 = 脚本里的删除/覆盖/ 移动等形态;疑似密钥 = 高置信度特征命中;外部依赖 = Python 脚本导入的第三方模块。

AUDIT-005 有三种判定,别混淆:PASS 表示清单里有内容(值得看);INFO 表示这是纯文档技能、 清单为空(不适用,不影响退出码);SKIP 表示 lint 前置检查失败、清单没生成(未覆盖项)。

再审计同名的技能时,会比对指纹并明确告诉你"内容与上次不同"——别人可以在你审计之后替换内容, 这是审计留痕唯一的意义。审计单里留了一栏「来源与信任级别」由人填写: 工具只保证"同一份内容"与"内容变了"能被认出来,不做行为审计、不做信任分级。

4.6 开发期即时反馈

skillverify watch --root <技能根>              # 轮询(默认 1 秒),变化即复跑
skillverify watch --root <技能根> --once       # 跑一轮就退出(CI 用)
skillverify watch --root <技能根> --json       # 每轮一行 JSON,便于管道消费

只复跑内容指纹变化的技能(指纹取 stat,不读文件内容);刻意不执行脚本 (高频复跑下反复执行脚本既慢又有副作用)。

五、语义评审:三档执行器,一个 schema

30 条提示词(旧体系 29 + 新增 W-17)(D 设计期 / W 编写期 / E 测试期 / R 运行期),每条带 PASS/FAIL 判据与证据要求:

skillverify review prompts                 # 全部 29 条(含判据)
skillverify review prompts --family W      # 只看编写期那 16 条

档 2 · 会话任务包(推荐默认):

skillverify review pack <技能目录>                      # 生成任务包(默认 29 条)
skillverify review pack <技能目录> --prompts W-01,W-02  # 只评指定几条
skillverify review pack <技能目录> --split              # 每条提示词一个 Markdown(便于一条一个调用)

产出三件:<技能名>-review-pack.md(任务书)、<技能名>-review-template.json (预填好 prompt_id 的回写模板,评审者只填结论)、<技能名>-review-manifest.json (记录本轮范围与技能内容指纹)。

把任务书交给任意 LLM 或人——这一步不依赖任何宿主,因为任务包就是 Markdown + JSON。 填好的模板就是回写:

skillverify review collect <填好的 JSON> --skill-dir <技能目录>
skillverify review collect --dir <回写目录> --skill-dir <技能目录>   # 汇总一批
skillverify review status                                            # 看各技能的评审状态与新鲜度

回写 schema(三档共用):

{
  "schema": "skillverify.review/1",
  "skill": "my-skill",
  "reviewer": "你的人名或模型标识",
  "tier": "pack",
  "generated_at": "2026-10-04T10:00:00+08:00",
  "prompt_ids": ["W-01", "W-02"],
  "results": [
    {"prompt_id": "W-01", "verdict": "PASS",
     "evidence": "见 SKILL.md:12 的 description 字段,含 PDF/表单/提取三个关键词",
     "finding": "", "suggestion": ""}
  ]
}

档 1 · 任意 CLI 自动:

skillverify review run <技能目录> --runner "你的评审命令"
skillverify review run <技能目录> --runner "你的评审命令" --prompts W-01,W-13   # 只跑几条
skillverify review run <技能目录> --runner "你的评审命令" --out <回写目录>      # 落盘便于复核
skillverify review run <技能目录> --runner "你的评审命令" --collect            # 顺带写中央记录

它逐条把提示词送上 runner 的 stdin,从 stdout 取回一个 JSON 结论 (围栏或寒暄都能容忍,取不到就报错),组装成与档 2/档 3 完全相同的 skillverify.review/1 回写,再走同一条校验与汇总。

  • 工具不内置 LLM 客户端:一旦内置就得维护各家 API、密钥与重试,而"用哪个模型、怎么提示" 是使用者的事。这里只做机械部分。
  • runner 失败(非零退出 / 超时 / 输出不可解析)不会被写成 NA——那会把"工具坏了"伪装成 "本项不适用"。失败条目直接不产出,并以非零退出码报出来(--allow-partial 可只记 WARN)。
  • 回写的 reviewer 写的就是实际跑的命令:评审必须有签署;中央记录里还会记 tiers(这批结论出自哪一档)。
  • 命令由你提供、以你的权限执行,与 lint --scripts 同类,均需显式开启。 --runner 收的是一个命令字符串:整串用引号包住(--runner "my-llm -m gpt-4");若命令内部还需要引用(例如解释器路径含空格),改用单引号包外层或写一个包装脚本。

档 3 · 人工兜底:手写同一个 JSON 即可,collect 的校验一模一样。

collect 会拦下这些(这就是"评审切实有效"的机械保障):

会被拦下的 判定
reviewer 为空 FAIL(无签署的评审等于没有评审)
证据过短、或没有文件/行号/引用/计数 FAIL(不可定位 = 无法复核)
证据与判据文本高度重合 WARN(复述判据不算证据)
FAIL 没写 finding / NA 没写理由 FAIL
同一提示词出现两条互相冲突的结论 WARN(双评场景,须人工裁决)
声明的提示词有没有结论的 WARN(未覆盖项)

让语义评审独立成一个技能包(可选)

skillverify review skill --out <输出目录>

生成 skillverify-review/ 技能包(SKILL.md + references/ + assets/), 把它放进任意宿主的技能目录即可加载使用——语义评审因此不绑定任何宿主。

执行轮次自证(WS-008,双跑对照必做)

执行层不自研,但**「这轮到底怎么跑的」必须留痕**:在每个 iteration-N/ 下放一份 run-inputs.json(模板见 examples/run-inputs.json),写清四件事:

字段 写什么
isolation 隔离 / 降级 / 未执行——做不到就如实写降级,不许留空
executor 两臂用的命令行(例如各起独立进程、禁用 Skill 工具与 resume)
input_hash 技能目录 + 靶子任务输入的联合哈希(证明输入冻结)
prompt_hashes 两臂提示词哈希(应仅差技能约束行)

另外两个可选字段,登记「断言是什么时候写的」(EVAL-011):

字段 写什么
assertions_added_at 断言写下的时间(ISO 8601,如 2026-10-05T11:00:00+08:00)
outputs_produced_at 本轮产出输出的时间(可选);写了它,报告会给出两者的先后关系
  • 只认这两个显式字段:旧实现靠文件 mtime 猜「断言何时补的」,复制/克隆/重写都会变, 本项目不猜时间——不写就记 INFO(不适用),不报错也不推断;

  • 写了但解析不出 ISO 8601 → EVAL-011 WARN(无法解析的声明等于没声明);

  • 先后关系只登记、不判缺陷:官方明确允许"先跑一轮再补断言",「先写断言再跑」也自有道理, 工具不替使用者选一种流程。

  • 完全没提供 → WS-008 INFO(增强项,不阻断);同一工作区里只提供了一部分 或写了 降级/未执行 → WARN;

  • 标成 降级 / 未执行 → WARN:该轮只能算参考级证据,其 delta 不得当作技能带来的增益。

运行台账(AUDIT-006,可选)

运行期观测没法自动化,但别让台账变成摆设:把 run-log.md(模板 examples/run-log.md) 放进中央留痕目录,audit 会检查两件事——异常观察写了却没写处置、超过 30 天没更新。 有台账才检查;没有记 INFO(不阻断)。 日期请按 YYYY-MM-DD 写(2026-9-5 这种非补零写法也认):一条日期都认不出来时, audit 会记 WARN「陈旧检查未执行」——"没算出来"不等于"很新鲜"。

评委校准(第 0 步,可选但推荐)

任务包里带 4 个答案明确的校准样本(2 应过 / 2 应挂)。先判它们并把结果填进回写的 calibration: 判错 → REV-012 FAIL,本轮结论不可用(评委分不稳);判对 → PASS;判了一部分 → WARN;没做 → INFO。

几条提示词需要的流程材料:review material

有几条提示词评的不是技能文件本身,而是流程产物或技能集合。先让工具把它们摘成材料文件:

skillverify review material <技能目录>                        # 生成到 <技能名>-review-material/
skillverify review material <技能目录> --workspace <工作区目录>  # 显式指定评测工作区
skillverify review material <技能目录> --diff-base HEAD~1       # 指定 description diff 的基线
skillverify review material <技能目录> --blind <旧版> <新版>      # 盲评:两版产物随机落到 A/B
材料 服务的提示词 来源
description-diff.md E-02 git diff <基线> -- SKILL.md(非 git 仓库会说明无法取 diff)
revision-signals.md E-03 工作区里的失败断言 + 人工反馈 + benchmark delta
blind/(blind-A/、blind-B/、mapping.json) E-06 你给的两版产物,随机分配;评审结束前不要看 mapping.json
workspace-digest.md E-07、E-08 工作区各 iteration 的逐次产物与聚合值,摘成一屏数字
adjacency.md W-11 同级技能目录里各邻居的 description 与词面重叠系数(与 LIB-002 同一套口径),并留一栏「边界裁决」给人填

生成不了的项目记 SKIP 并逐条说明缺什么(缺工作区?不是 git 仓库?没给两版产物?同级目录列不出来?)—— 所以退出码常是 2:那是「有材料没生成」的正常信号,不是失败。 唯一的例外是 adjacency.md:同级根本没有别的技能时记 INFO(不适用),因为那时确实没有可比的对象。 adjacency.md 的局限写在材料里:只在同级找邻居,分类嵌套(<root>/<类别>/<技能>/)布局会漏, 那种布局请手工补一份相邻技能清单;词面重叠不是语义相似度,串扰与否仍由 W-11 判。 其余条目只读技能目录本身(SKILL.md、references/、scripts/、evals/),不需要额外准备。 材料不齐时在回写里记 NA 并写明缺什么,不要凭印象给结论。

六、交付门禁

check 是日常检查;deliver 是交付门禁——没有 FAIL 且没有未覆盖项才算通过:

skillverify deliver --root <技能根>                    # 全库
skillverify deliver --root <技能根> --strict           # 连"未覆盖项"也阻断(发行前跑一次)
skillverify deliver --root <技能根> --verbose          # 把未覆盖/待甄别项也逐条打出来
  • FAIL 阻断;
  • WARN 不阻断,但逐条写进交付记录(这就是"需人工书面甄别"的书面痕迹);
  • SKIP 分两类:属"未开启的可选批次/环境能力不足"的记未覆盖项(默认不阻断, --strict 时阻断);其余 SKIP(本项确实没执行,例如前置失败)一律阻断;
  • 语义评审默认参与(含在 --stages all 里);--skip-review 可一键跳过,且留痕为未覆盖项。

交付记录写到中央留痕目录(默认 <项目>/.agents/skillverify/deliver/):

  • latest.json —— 含 rules_hash(证明是哪套规则判的)、git commit/branch/dirty、逐技能结论、 门禁结论(阻断项 / 未覆盖项 / 待甄别项);
  • latest.md —— 人读报告;
  • history.jsonl —— 每次交付追加一行,便于 grep 趋势。

--json 输出的是交付记录本身(含门禁结论),便于 CI 直接消费。

执行器样例(examples/)

执行层不自研,但怎么委托有可以照抄改的模板(纯标准库、支持 --dry-run):

模板 干什么 典型用法
examples/run_evals.py 双臂(with/without skill)各跑一遍、按官方布局建工作区、记实测耗时与 token python examples/run_evals.py --skill <技能> --cmd "claude -p {prompt}"
examples/run_triggers.py 把触发查询集真跑一遍并写 trigger-runs.json python examples/run_triggers.py --skill <技能> --cmd "<判定命令>"
examples/badcase_to_evals.py 把线上坏例子回流成一条 evals.json 用例 python examples/badcase_to_evals.py --skill <技能> --prompt … --expected …

三个都不替你打分——评分与断言是人的判断(见 E-04)。

⚑ 逐条双评(REV-013)

目录里 8 项标 ⚑(W-02/04/05/08/15、E-04/06、R-02):要求两条各自署名的独立结论 (回写里写 by + at;同一人跑两遍不算)。署名缺失记 INFO(未启用),独立署名不足 2 条记 WARN, 两人结论不一致升级为待人工裁决。

注意:本工具不生成"看起来独立"的 A/B 任务包——旧体系那套 A/B 包实测逐字相同、仅包号不同, 独立性全靠人工开两个会话。这里改成机械判定署名,宁可让人真去开第二个会话。

WARN 的裁决留痕(WARN = 人工甄别,不是"记一下就算了")

deliver 记录里的 adjudications 会给出三份清单:pending(没人认领的 WARN)、 void(裁决已失效:证据变了或缺字段)、resolved(已拍板且证据一致)。 裁决写在 <留痕目录>/adjudications.json(模板 examples/adjudications.json), 每条必须带 decision(accept/fix)、reason、by、at 与 evidence_hash。 证据一变,裁决自动回到待裁决——签认只覆盖它当时看过的那一份证据。

误报的出口:豁免通道

skillverify deliver --accept <规则ID> --because "<理由>"

把该规则的阻断项记为「已豁免」(落盘在 gate.waivers),门禁随即放行;缺理由直接拒绝。 这是方案 §6.1「[S] 级书面说明后放行」的落地——显式、有理由、可追溯,不是静默放过。

接到提交上(git hook)

skillverify hook install --project <仓库目录>
skillverify hook status  --project <仓库目录>

装好后每次提交自动执行 deliver --staged(只查本次提交涉及的技能,按目录前缀归属):

  • 存在他人 hook 时拒绝改动,--force 会先备份成 pre-commit.bak 再覆盖;
  • 找不到可执行的 skillverify 时只告警不阻断(SKILLVERIFY_HOOK_STRICT=1 改为故障关闭)—— 一个会把你锁死在"改不动也提交不了"状态的门禁,对两人团队比漏检更糟;
  • 逃生阀:git commit --no-verify、SKILLVERIFY_SKIP=1。

只改非技能文件(例如 README)时不会阻断(本次没有需要检查的技能)。

七、全程演练(照着敲一遍)

下面 18 步用一份本机技能目录把整条流水线走一遍。把 <> 里的占位符换成你自己的路径, 行尾的 # N 是期望退出码,命令上方的整行注释是这一步在干什么。

这一段不是"示意":tests/test_docs.py 会把这块里 <!-- runnable --> 标记的每条命令真跑一遍, 并核对实际退出码与标注一致。所以它既是你照着敲的脚本,也是文档不失效的保证—— 改了命令就必须同步改期望退出码,改不对测试就红。

# 1) 官方规范(离线、不联网):frontmatter 六个字段白名单、name 与父目录名一致、description 非空
skillverify spec "<技能目录>"                                                    # 0
# 2) 机械补检:引用、上下文预算、目录卫生、编码、依赖、安全。默认**不执行**脚本,
#    所以脚本契约四项没跑 → 记 SKIP,退出码为 2(未覆盖项,不是失败)
skillverify lint "<技能目录>"                                                    # 2
# 3) 同一套补检,并**实测脚本契约**:--help 可用、非法参数非零退出且错误走 stderr、重复调用一致
skillverify lint "<技能目录>" --scripts                                          # 0
# 4) 两类评测资产:官方 evals.json(输出质量)+ 触发查询集与运行记录(会不会被触发)
skillverify evals "<技能目录>"                                                   # 0
# 5) 整库发现:按生效配置找出所有技能,看每个技能根命中几个、有没有同名冲突
skillverify discover --project "<项目>" --user-home "<用户主目录>" --root "<技能根>"   # 0
# 6) 打印**生效配置**(内置 < 用户级 < 项目级 < --config 的覆盖顺序)——接入新宿主先看它
skillverify discover --show-config                                               # 0
# 上宿主之前:技能是不是真的落在该宿主档声明的目录里、能不能被读出来、有没有同名冲突
skillverify mount --project "<项目>" --user-home "<用户主目录>" --skill "<技能名>"     # 0
# 7) 外来技能审计:组合各阶段结论 + 来源 + 能力清单 + 内容指纹,出一张决策单(--record 留痕)。
#    再审计时会比对指纹,提示「内容被换过」;明确不做行为审计与信任分级。
#    这里的 2 与第 2 步同源:默认不执行技能自带脚本,脚本契约四项记 SKIP(未覆盖项,不是失败)
skillverify audit "<技能目录>" --project "<项目>" --user-home "<用户主目录>" --record  # 2
# 8) 开发期即时反馈:只有内容指纹变化的技能才复跑;--once 跑一轮就退出(CI 用)。
#    它刻意不执行脚本(高频复跑下反复执行脚本既慢又有副作用)→ 同样记 SKIP,退出码 2
skillverify watch --project "<项目>" --user-home "<用户主目录>" --root "<技能根>" --once   # 2
# 8) 查看语义评审提示词目录(29 条,每条带 PASS/FAIL 判据与证据要求);--family W 只看编写期 16 条
skillverify review prompts --family W                                            # 0
# 9) 档 1 执行器:把提示词逐条喂给你指定的命令,收回与档 2/档 3 同 schema 的回写(这里示范跑 1 条)
skillverify review run "<技能目录>" --runner "<评审命令>" --prompts W-01 --out "<回写目录>"   # 0
# 10) 生成几条提示词需要的**流程材料**:描述修订 diff、修订信号、盲评 A/B、工作区数字摘要
skillverify review material "<技能目录>" --out "<材料目录>" --blind "<盲评旧版>" "<盲评新版>"   # 0
# 11) 档 2 任务包:Markdown 任务书 + **预填好的回写模板** + manifest(含技能内容指纹)
skillverify review pack "<技能目录>" --prompts W-01,W-13 --out "<任务包目录>"        # 0
# ↓ 这一步由人或任意 LLM 完成:把 <任务包目录>/<技能名>-review-template.json 填好
# 12) 校验回写(签署、证据是否可定位、FAIL 有没有写问题…)并汇总进中央记录
skillverify review collect "<回写文件>" --skill-dir "<技能目录>" --project "<项目>" --user-home "<用户主目录>" --root "<技能根>"   # 0
# 13) 看各技能的评审状态与新鲜度:技能在评审后被改过,会提示"需重评"
skillverify review status --project "<项目>" --user-home "<用户主目录>" --root "<技能根>"   # 0
# 14) 整库总检:spec + lint + evals + review 一网打尽(all 含语义评审;--scripts 打开脚本实测)
skillverify check --project "<项目>" --user-home "<用户主目录>" --root "<技能根>" --stages all --scripts   # 0
# 15) 交付门禁:FAIL 阻断交付、WARN 逐条记账、未覆盖项列出来;并写出 latest.json/md 与 history.jsonl
skillverify deliver --project "<项目>" --user-home "<用户主目录>" --root "<技能根>"   # 0
# 16) 把"语义评审"导成一个独立技能包(SKILL.md + references/ + assets/),可放进任意宿主
skillverify review skill --out "<独立技能目录>"                                    # 0
# 17) 装 git hook:提交时只查本次改动涉及的技能,坏技能直接拦住提交
skillverify hook install --project "<项目>"                                       # 0
# 18) 看 hook 装没装、技能包版本对不对
skillverify hook status  --project "<项目>"                                       # 0

分五段看:1–4 单技能逐层检查 | 5–7 整库与开发期反馈 | 8–13 语义评审(含三档执行器)| 14–15 交付门禁 | 16–18 分发与自动化。

退出码里那几个 2,含义都是"有项没跑",不是失败:

  • 第 2 步是 2:没加 --scripts 时脚本契约实测没执行,记 SKIP(未覆盖项)。加上 --scripts(第 3 步)就变成 0。
  • 第 7 步也是 2:watch 刻意不执行脚本,只做静态检查。
  • 若技能没有评测资产,第 4 步会返回 2(EVAL-000 提示"没有任何质量证据")—— "没有 evals"和"evals 全绿"必须能区分开,所以这里不是 0。
  • 第 10 步本次是 0:给了工作区与两版盲评产物,四项材料都产出了。若没给(没跑过评测、不是 git 仓库), 它会记 SKIP 并返回 2——那是「有材料没生成」的正常信号,逐条原因写在报告里。

三条容易踩的:

  • 第 12 步的 --skill-dir 不能省:它把技能目录的内容指纹写进评审记录,技能之后改过就会被判 "记录过期,需重评"(按内容比对,不看文件时间)。第 13 步就是查这个状态。
  • 第 15 步默认把语义评审算进来;只想跳过就加 --skip-review(会留痕为未覆盖项)。
  • 第 16 步产出的技能包可以放进任意宿主的技能目录,语义评审因此不绑定宿主。

八、它不做什么(先说清楚)

  • 不承诺在宿主内自动触发技能激活——跨宿主没有统一机制;本项目给的是 watch(改文件即时复跑)+ git hook(拦提交)+ 技能里的触发词。
  • 不验证宿主注册表:mount 只做仓库侧的挂载前置检查;「宿主技能列表里看不看得见」、「真实触发会不会串扰」要在目标宿主里人工确认。
  • 不内置任何 LLM:语义评审只负责生成任务包、把提示词喂给你指定的命令(档 1)、校验回写、汇总结论。用哪个模型、怎么提示,由你决定。
  • 不做 46 个宿主的路径映射表:官方 clients 页根本没有路径信息;接入宿主请用 hosts.toml 声明。
  • 不引入独立依赖清单:脚本依赖写在脚本里(Python 用 PEP 723;Deno 写 npm:pkg@1.2.3、 带版本的 import 说明符、Ruby bundler/inline 的 gem "x", "1.2.3"——DEP-005 只认这些明确形态)。
  • 不自研评测执行层:evals 只校验资产与产物形状,不执行、不联网。真要跑就把执行委托出去 (evals --run-with <命令>),比如 AgentV——它原生识别官方 evals.json;样例与配合契约见 examples/agentv/README.md 与《操作手册》A4b。代价与密钥由使用者承担,我们只做"起进程 + 限时 + 跑完复校"。
  • 不做密钥评分、域名信誉、混淆对抗这类判据——它们"命中不等于恶意", 本项目只把它们记 WARN,终判交给语义评审。
  • 不用自建哈希清单做历史留痕:改用 git 做单一真源。

九、开发者:跑回归

改了这个工具本身之后,跑回归套件(纯标准库、离线;断言数看输出,本文件不写死):

python -m tests.run_all                # 全部套件
python -m tests.run_all --dogfood      # 额外把仓库里归档的旧技能拉进来跑 dogfood 项
python -m tests.run_all --install      # 连打包的真装检查一起跑(需要网络,约 1 分钟)
python -m tests.test_lint              # 也可以单独跑某一套

套件共 12 个(默认跑 13,--install 加跑打包):spec / lint / discover / automation / evalx / trigger / review / docs / injection / selfcheck(另有 packaging,默认不跑;全套约 1.5 分钟)。

其中 injection 是注入自测:先造一份 spec + lint + 评测 + 触发资产全绿的技能,再对它的独立副本逐个注入 38 处缺陷(含两处库级:评审记录过期、同名技能跨根),要求「期望的规则里至少一条必须报错」且「不许牵连无关规则」。 它证明的是校验器不是瞎的——方向与其它套件相反:那些查「给定坏输入会不会报错」,这个查「本来全绿的技能被动过手脚后一定会被抓住」。

打包相关的两档:默认只做 pyproject.toml 的静态检查(入口点/包列表/package-data glob 是否真的匹配到 data/ 下的运行时数据);加 --install 才真的建 venv、pip install -e .、 在仓库之外的任意目录执行命令,并构建 wheel 检查 data/ 确实进了发布物。

改动交付文档里的命令时,tests.test_docs 会执行《验证流程指南.md》里 <!-- runnable --> 标记的那段演练并要求退出码与标注一致——文档承诺的东西必须真能跑。

十、排障

现象 原因与处置
check 说"未发现任何技能"并返回 1 根列表不对。discover --show-config 看生效配置;或用 --root <技能根> 直接指定
配置报"未知键" 键名拼错了,报错信息里列了允许的键
退出码恒为 2 通常是 SKIP(未执行项):看报告里 [可选批次·未覆盖] 标记与 SKIP 行的说明
报告里出现 DISC-001 同名技能出现在多个根,需你决定哪个是真源
报告里出现 LIB-001(WARN) 库内元数据总量超出预算:宿主可能静默丢弃排在后面的技能。精简描述、合并同类技能,或用 --metadata-budget 按宿主实测值调整
报告里出现 LIB-002(WARN) 两个技能的描述高度重叠,触发时可能互相抢。让每个描述点明本技能独有的能力与边界;确实同类就合并
审计单说「内容与上次审计不同」 技能内容在你审计之后变过。重新过一遍;若你没换过它,就要查是谁换的
报告里出现 DISC-004 技能主文件名大小写不对(写成了 Skill.md 之类)。大小写敏感的系统上它等于不存在:宿主不加载、报错也很难懂。重命名为 SKILL.md
工具说「未发现技能」,但我明明放进去了 先看 SKILL.md 的文件名与位置:名字必须精确是 SKILL.md(或 skill.md),且直接位于技能根下的 <技能名>/ 里
deliver 说"评审记录已过期" 技能在评审后改过;重跑 review pack → 评审 → collect
Windows 终端乱码/崩溃 本项目强制 UTF-8;命令行入口已把 stdout/stderr 切到 UTF-8,无需额外设置
hook 装不上 --project 必须指向 git 仓库;hook status 可先看现状
mount --host 敲错档名 应报「未知宿主档 'x';可用: …」并退出 1。若看到的是 traceback,那是 mount.py 漏导入 ConfigError 的老缺陷(已修;防复发由 test_selfcheck 的「未定义名」守卫看着)
报告说「检测到旧落点」 旧体系把触发查询集放在 .verification/trigger-eval/queryset.json;迁到 evals/trigger-queryset.json(本项目只认单一来源,不回退读旧路径)
evals 返回 2 但官方资产全绿 是 TRIG-000 在提示「没有触发评测证据」;补 evals/trigger-queryset.json + trigger-runs.json 即可

十一、命令与旗标速查(改结果的开关,一个都不藏)

skillverify <命令> --help 永远是权威。下表收的是正文没有逐条讲、但会改变结果的开关—— 放在这里,免得出现"实现了却没人知道"。tests/test_consistency.py 会核对: 每个子命令、每个旗标至少在某份根文档里出现过一次(含本表)。

旗标 属于 作用
--iteration N evals / check / deliver 只看指定那一轮 iteration-N(工作区有多轮时用);指定的号不存在记 WARN,不静默跳过
--workspace 目录 evals / review material 显式指定评测工作区(默认找并列的 <技能名>-workspace/)
--scripts lint / audit / check / deliver 开启脚本契约实测(--help 可用性、非法参数退出码、幂等、输出量)。默认不开:执行技能自带脚本有风险,由你显式打开;deliver --strict 要过含脚本的技能必须带上它(此前 deliver 漏定义这个旗标,"严格模式"对含脚本技能永不可能通过)
--script-timeout 秒 lint / check / watch / deliver 单个脚本实测的超时(默认 10s;另有 120s 全局预算,用尽即记 SKIP)
--run-timeout 秒 evals --run-with 委托执行的那条命令的整体超时(默认 1800s)
--timeout 秒 review run --runner 每条提示词喂给执行器命令的超时(默认 180s)
--desc-overlap 比例 discover / check 库级「描述词面重叠」的提示阈值(默认 0.5);与 --metadata-budget 同属库级口径
--trace check 把这次的 check.md + check.json 落到中央留痕目录(默认只打印)
--no-record deliver 只判定、不写交付记录(CI 里只想拿退出码时用)
--no-store review collect 只校验回写、不写中央评审记录
--no-config audit / mount 忽略用户级/项目级 hosts.toml,只用内置档(排查"是不是我的配置在捣乱")
--fail-closed hook install 找不到可执行的 skillverify 时阻断提交(默认故障开放,等价环境变量 SKILLVERIFY_HOOK_STRICT=1)
--interval 秒 watch 轮询间隔(默认 1s)
--cycles N / --once watch 跑 N 轮后退出;--once 等价 --cycles 1(CI 与测试用)
--blind-seed N review material --blind 固定盲评 A/B 的随机分配(同一份盲评包可复现)
--name 名 review skill 生成"语义评审"独立技能包时的技能名(默认 skillverify-review)
--quiet 多数命令 不打印报告正文。机读场景不要加:它会把 --json 一起静音
--json / --out 文件 多数命令 机读输出 / 报告落盘;两者可同时用(stdout 仍只有 JSON,进度提示一律走 stderr)

Metadata

Release files for skillverify 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for skillverify 0.1.0
File Size Uploaded
skillverify-0.1.0.tar.gz 365.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for skillverify 0.1.0
File Interpreter ABI Platform
skillverify-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 600.0 kB

Release files / skillverify-0.1.0.tar.gz

Download URL skillverify-0.1.0.tar.gz
Size 365.0 kB
Tags Source
SHA-256 checksum
How to use checksums
168e7c75221e40645a7a8beca4711404ef2b60a4a1bf31047d0734325d87a5ad
BLAKE2b-256 checksum
How to use checksums
81a6f352572d999b0953641245af081951034f1974c6ae0c0590752dc88f4e47
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / skillverify-0.1.0-py3-none-any.whl

Download URL skillverify-0.1.0-py3-none-any.whl
Size 235.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
549044e76860c6927ca6fbefd7c195bec5028e20dffc29a4d1f7a9ad9b4854b8
BLAKE2b-256 checksum
How to use checksums
25ca76b745150cd114de9c7f8a5a843b0c41941f77a963b35cfb4b14aa07e031
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page