Skip to content

Latest commit

 

History

History
95 lines (65 loc) · 9.21 KB

File metadata and controls

95 lines (65 loc) · 9.21 KB

Knowledge-Skill Grounding — 事实锚定与发布前验收

适用对象:知识型 skill——内容主体是"关于某外部系统的事实"(API 端点/参数/字段、平台行为、CLI 用法、计费规则)的 skill。这类 skill 的核心价值就是事实准确;一条错误契约会让使用者在第一步就撞墙,并让他们怀疑整个 skill(乃至自己的 key/网络)。

本文是 SKILL.md 两大纪律之一 "Verify before you write" 的操作化:那条纪律说"每条技术断言必须 trace 到执行观察",本文回答"具体怎么做、按什么优先级、发布前怎么验收"。

背景教训(已去除项目细节):一个关于外部 API 的知识型 skill 从记忆转写后顺利通过表面 review,但后续 source-grounding 审核发现多条契约断言与实际证据矛盾。错误覆盖路径、参数、字段边界、HTTP method 与响应结构;权威材料其实一直可用,只是写作时没有逐条对照。核心问题不是"记错了哪一项",而是没有为每项事实建立可追溯证据

1. 权威源阶梯(写每条契约前先问:我抄的是哪一级?)

从高到低,能用高的绝不用低的:

级别 为什么
L1 实际运行观察(成功请求/响应、抓包、可复现实验产物) 它是"实际发生过"的直接证据,连参数大小写、字段嵌套层级都可核对
L2 机器可读规范(OpenAPI/JSON Schema/proto,从服务方拉取) 全量、含 required/枚举值;一次拉取可对账全部端点
L3 调用该 API 的生产代码(经过真实运行的) 代码不会说谎,但只覆盖它用到的端点
L4 官方文档/网页 可能过时或与实现不符
L5 记忆/对话转写 禁止直接落稿;必须升级到 L1-L3 验证,或显式标注 未验证——凭记忆

操作规则:

  • 写端点/参数/字段名时,从 L1/L2 复制粘贴,不要手打——转写就是错误注入点(单复数、下划线、家族前缀都是这么错的)。
  • OpenAPI 规范值得专门拉一次:curl <base>/openapi.json 之类通常成本很低,拿到后可以对账文档里每一个 method/路径/required 参数/枚举值。不要只抽查你记得最清楚的那一条。
  • 同名概念跨域要逐个验证:相邻平台/版本里的类似字段(如 created_at vs createdAt)和同名端点最容易凭印象混写。写到"平台 A 和平台 B 都有 X"时,两边各找一条独立证据。

2. 证据边界标注(防"实证"被过度概括)

写"已实证/verified"时,注明实证了什么、没实证什么。例如,一级端点的成功调用不能证明同一家族的嵌套端点使用相同参数;"X 家族实证过"≠"X 家族每个端点都实证过"。

写法示例:

  • 好:参数名 resource_ids(复数;<verified-date> 在单条端点实测;批量端点未验证)
  • 坏:参数用 resource_ids(已实证) ——哪个端点?什么时候?单条还是批量?

3. 发布前:文档示例冒烟(最便宜的正确性闸门)

skill 文档里每一条可执行示例,发布前至少真跑一次(或明确标注为什么跑不了)。这比 eval 便宜一个数量级,却能抓住最伤人的错误——一条看似合理的参数示例可能在第一次真实调用时就被 schema 拒绝,即使它此前在多份文档里互相"印证"。

  • 付费 API 的冒烟成本可控:挑每类端点最便宜的一次真调;免费端点(余额/health)全跑。记录调用次数和实际费用,但不要把私人账单数据写进公开 skill。
  • --help/docstring 里的示例也算文档:修文档时最容易漏的就是脚本内嵌示例(见 §4)。
  • 跑不了的(需要特定环境/危险操作)在示例旁标注前置条件,别让使用者当成"复制即用"。

4. 改一个事实,先 grep 全 skill 目录(不只 .md)

事实的副本藏在四种地方:markdown 文档、脚本 docstring--help/argparse epilog、代码注释。事故案例:参数名错误在所有 .md 里修干净了,但脚本自己的 docstring、库用法示例、--help 输出里还是旧写法——非工程师使用者的第一入口恰恰是 --help。第二轮审核还点名"你修了 A 文件的示例,漏了 B 文件的同型锚点"。

规则:改任何契约/命令/路径前,grep -r 整个 skill 目录列出所有出现处,一次改齐。修完再 grep 一遍确认零残留(排除故意保留的"⚠️ 不要写成 X"警示文本)。

5. 受众环境声明与自包含验收

创建时就写下(并在打包前逐条验收):

  1. 谁用:工程师还是非工程师?后者需要:一键诊断脚本、明确的"照抄可用"命令、错误信息里带下一步动作。
  2. 什么机器:如果受众可能用 Windows(非工程师大概率是),逐条检查 bash-only 语法——见 §6。
  3. 有什么依赖:声明"零依赖(标准库)"就要真零依赖;声明"需要 X"就在上手第一步给安装/检查命令。
  4. 配置怎么给:凭据类配置优先 .env 文件方案(放脚本旁一行搞定,免记 shell 语法,天然跨 OS),其次才是环境变量双语法。
  5. 视角一致:skill 的读者是使用者本人——统一用"你",不要出现"给某某配 key""她问的时候"这类作者视角残留(蒸馏自真实对话的 skill 最容易带进来)。
  6. 环境专属内容隔离:绑定某个仓库/内网环境的内容,集中到一个明确标注适用范围的 reference,主文档只留指针;别让外部使用者读到一半发现命令全跑不了。

6. Windows 兼容速查(受众含 Windows 时逐条过)

陷阱 症状 修法
Python print 含 emoji/中文,stdout 被管道/重定向 中文 Windows(cp936)下 UnicodeEncodeError 崩溃——常在操作已经成功后崩,被误读为操作失败 脚本入口 sys.stdout/stderr.reconfigure(encoding="utf-8", errors="replace")(PEP 528 只保护 console 直连,不保护管道)
export FOO=... PowerShell/cmd 直接报错,第一行就卡死 双语法($env:FOO=...)或推荐 .env 文件方案
python3 命令 Windows 官方安装器只装 python/py;Store alias 还会弹商店 文档标注"Windows 用 python"
单引号包 JSON -j '{...}' cmd/PowerShell 引号规则不同,JSON 被拆散 CLI 支持 -j @file.json 从文件读,文档给 Windows 替代写法
行尾 \ 续行 PowerShell/cmd 不认,整块复制变两条断命令 示例旁标注,或 Windows 版合成一行
shell 变量 $VAR(如 curl 示例) PowerShell 展开为空串、cmd 原样字面传出→静默错误结果(比语法报错更险) curl 兜底段标注"仅 macOS/Linux"
双引号字符串里的 Windows 用户目录 \U 被解释为 Unicode escape 并触发 SyntaxError Python 示例用 r"" 原始字符串或 %USERPROFILE%

7. Guards carry the discipline(纪律内建为工具默认行为)

SKILL.md 的分工原则是"scripts carry the execution, docs carry the understanding";对涉及计费/不可逆操作的 skill 再加一层:把纪律做成工具的默认行为,而不是文档里的叮嘱。前置条件无法确认就 fail-closed;失败结果不能被持久化成成功状态;每次状态变更都留下可审计记录。判据:war story 里每条"教训",问一句"能不能变成 guard 的默认行为?"能变的就别只写在文档里。

8. 发布前多角度审核菜单(大型知识 skill 用)

单一 review 视角抓不全;diff-scope review 抓不到"没改过的行"里的存量错误。对内容量大、要外发的知识型 skill,按领域挑 finder 角度做一轮全量审核(每条 finding 要求可证伪锚点:file:line + 原文摘录 + 复现步骤;再独立对抗验证):

角度 抓什么
api-contract 每条端点/method/参数/字段 vs L1/L2 权威源逐条对账
standalone-acceptance 模拟目标受众在干净机器上照文档逐条走,找"文档说能做但做不到"
平台兼容(如 windows-compat) §6 的清单 + 编码/路径/shell 语法
money-safety 一切可能不知情多花钱的路径(重试风暴/缓存空洞/翻页无上限/计费语义)
doc-consistency 交叉引用断链、同一事实多处表述矛盾、重构后的旧语境残留
package-audit 包内容 vs 源目录 diff、是否发了旧代码(mtime)、垃圾文件、secret 残留
script-deep 并发竞态、损坏输入容错、相对路径 cwd 敏感、exit code 语义

修复后重放同一批 finding 做修复复核(缓存机制下只重跑未完成的验证):已修的会因锚点消失被判"不存在",仍被坐实的就是漏网之鱼。

9. 验证器自身要被证伪测试

"检查器绿灯"只在检查器本身正确时有意义。事故案例:安全扫描的完整性标记(content hash)因为一个路径判断 bug,长期在哈希零字节——标记看起来存在、格式正确、扫描全绿,但它从未真正锚定过任何内容,改内容也不会被发现。直到有人问"这个哈希是什么的哈希",才发现它等于空字符串的 SHA-256。

规则:每个验证器/扫描器要有已知坏样本测试——构造一个"必须被抓住"的输入(含假 secret 的文件、被篡改的内容、坏 frontmatter),断言检查器真的报警。skill-creator 自带 scripts/selftest_validators.py 做这件事;你给自己的 skill 写校验脚本时,同样配一个最小自测。