关于 runtime-verification-discipline
供 AI Agent 在 PDCA 工作流中执行运行时验证的共享规范。它要求优先选择合适的高保真环境执行检查,并仅在明确分类的硬性边界处交由人工处理。
主要功能
- 01环境保真度分级
- 02优先尝试自动验证
- 03A/B/C 阻碍分类
- 04UI 验证预检查
- 05证据与环境标注
适用场景
- 01功能变更后的可观察行为验证
- 02选择真实或模拟环境
- 03分类受阻的自动化检查
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ fudesign2008/ open-skills --skill runtime-verification-discipline安装后在 Claude Code 中输入/runtime-verification-discipline确认已加载。
附带文件evals/evals.jsonreference.md
详细介绍
运行时验证规范
内部共享技能。它是 PDCA 工作流中如何执行验证的唯一事实来源:AI 在正确的环境中自行运行验证,只有遇到真正的硬性边界时才交由人工处理。宿主必须在
dependencies中声明此技能,若缺失则中止——不得静默回退。这是规则层。它决定验证在哪里运行、由谁运行,以及是否充分。它不包含驱动环境的操作方法(通道选择、CDP 调用)——这些内容属于
browser-debug-toolkit等能力技能。具体示例和各宿主的集成片段见 reference.md。
为什么需要此技能
过去,工作流把验证视为“AI 运行 Bash 测试命令;其他所有事情都交给用户按清单检查”。这种做法浪费了 AI 操控真实和模拟环境的能力,还把“交给用户”变成了未经审视的默认选项——有时是因为 AI 没有尝试,而非确实做不到。结果是本可避免的人工验证工作;更糟的是,偶尔会让人产生错误的信心,把低保真度的检查报告得仿佛结论确凿。
此技能要贯彻的元规则是:
验证是 AI 在某个环境中完成的工作。应优先选择 AI 能安全、确定地操控的最高保真度环境;只有遇到真正的硬性边界时才交由人工处理,并明确说明原因。
适用场景
适用于任何工作流的验证/检查阶段,以及任何具有可观察行为的改动——无论是修复 Bug 还是开发功能。如果改动无法在任何环境中运行验证,则此技能不适用(纯文档/注释改动可能无需运行时验证)。
铁律
验证由 AI 在某个环境中执行,而不是作为检查清单交给人工。
首先尝试执行——这是默认做法,而非可选项。只有被判定为真正的硬性边界时,才有理由交由人工处理某一步骤,并且必须说明原因。
环境层级模型
根据环境与应用生产运行时目标的匹配程度,对环境进行分类。“真实”和“模拟”是相对于该目标而言的,并非绝对概念:
| 生产目标 | 真实环境 | 模拟环境 |
|---|---|---|
| Web 应用 | 真实浏览器(由 CDP 驱动,例如 ego-browser / chrome-devtools-mcp) | 无头 DOM / jsdom 风格的伪 DOM |
| Electron 应用 | Electron 应用本身 | 普通浏览器 |
| 移动应用 | 实体设备 | 模拟器 / 仿真器 / 浏览器 |
平台专属的 Bug,只能在该平台运行时实际执行的层级上得到确证。
层级选择规则
选择 AI 无需人工介入即可操控,且足以满足当前断言所需的确定性和安全性的最高保真度层级。应权衡保真度与单位成本所能获得的信心,而不是盲目追求最高保真度:
- 确定性——真实环境涉及真实网络和时序,因此更容易出现不稳定。如果需要稳定、可重复运行的信号,请先在模拟环境中验证。
- 安全性/副作用——真实环境可能修改真实后端、真实用户数据,或发送真实推送通知。对于会产生写入的验证,请先在模拟环境(沙箱)中验证,再在真实环境中确认。
- 按 Bug 类型选择保真度——平台专属 Bug 需要在该平台运行的层级验证;与平台无关的逻辑 Bug 则不需要。
因此:只读且高度确定的检查 → 直接在真实环境中执行。涉及写入或容易不稳定的检查 → 先模拟验证以获得稳定信号,再在真实环境中确认,并标明两次验证的环境。
提供方解析(可插拔)
按以下顺序查找,确定如何在此项目环境中进行验证——约定优于配置:
- 项目自身的验证脚本或技能——优先选择。项目 SHOULD 通过易于发现的约定提供验证方式(例如,放在已知位置的验证脚本或项目技能),使 AI 无需他人告知即可找到。
- 此库提供的共享能力技能(例如,用于 Web 的
browser-debug-toolkit、用于 Android WebView 的android-webview-debug)——后备方案。 - 两者均不存在——继续执行下方的交接分类。
先尝试,再对阻碍进行分类(A/B/C)
当 AI 无法执行验证时,必须先对原因进行分类,再做其他任何事情:
- A — 自动化尚未接入。 检查可以自动化,但目前还没有脚本。接入自动化(编写脚本),或提出代为接入。不要交由人工处理。
- B — 缺少一次性设置。 检查可以自动化,但尚未安装工具链或配置环境。给出确切的安装/设置命令,让用户决定;设置完成后,由 AI 接手。
- C — 真正的硬性边界。 交由人工处理,并说明原因。C 分为三类:AI 无法执行(实体设备、验证码、生物识别),AI 无法判断结果(主观 UX、探索性评估),或操作会产生现实世界的副作用。
不得以含糊的“没有 Bash/环境受限”为由,在不进行分类的情况下交由人工处理。分类能让“尽量减少人工工作”名副其实——它会迫使我们区分“我还没接入自动化”和“这件事确实无法自动化”。
像素几何不属于 C 类。 将布局后的帧与设计规格进行数值比较,不属于主观 UX;如果文档通道或布局探针可以运行,这也不属于实体设备步骤。缺少探针属于 A 类:在本轮中编写并运行探针,并将其挂载到正在发布的父项目中。C 类中的“实体设备”仅适用于任何命令都无法执行的操作。较低等级的标签(“建议进行真实环境冒烟测试”)不会让这些条目变成人工步骤,也不能替代测量。
打开过 UI,就要保留截图文件。 如果某项检查打开了 UI,其证据必须引用本轮保存的非空 png、jpg、jpeg 或 webp 文件路径。单元测试、规格验证以及仅打印数字且无法打开 UI 的布局探针不需要图像,也不得捏造图像。图像不能替代该项检查自身的通过条件。此处不要重复 Figma 报告中的通道名称。
充分性检查
只有在验证中以软件实际使用的方式检验了变更的确切行为,验证才算充分。标准不是“应用可以启动”,而是“在真实使用路径中,已修复 Bug 的具体症状消失”或“新功能的真实使用路径可正常工作”。如果断言未覆盖变更行为,无论验证在哪种环境中运行,都不充分。
UI 验证面预检
验证前,先判断验证面是否包含 UI 行为。由两项命令输出决定。目标、任务卡片或修复说明中的措辞不作为判断依据。
变更集包括已跟踪差异,以及所有未跟踪、未忽略的路径。从 git rev-parse --show-toplevel 运行。未跟踪路径通过 git ls-files --others --exclude-standard 获取。即使已跟踪差异为空,也不能因此排除这些路径。
按以下顺序确定一个基准:
- 如果
git rev-parse --verify --quiet origin/HEAD成功,则使用origin/HEAD。 - 否则,如果
git branch --show-current的结果非空,则读取该分支的 reflog,而不是HEAD的 reflog。关联工作树共享分支 reflog,且git branch -m会将它保留在新名称下。命令为git reflog show --date=unix --format='%H%x09%gd%x09%gs' <current>。保留主题为branch: Created from <src>的行。基准是%gd中花括号所含 Unix 时间最小的那一行上的%H提交。%H必须通过git rev-parse --verify --quiet,且git merge-base --is-ancestor <commit> HEAD必须成功。如果不成功,则丢弃该行并选取下一个时间最小的行。不要解析<src>。时间相同时,选择作为另一个提交祖先的提交;如果两者都不是,则选择字典序最小的 SHA。 - 否则,列出
git for-each-ref --format='%(refname:short) %(committerdate:unix)' refs/heads refs/remotes。当引用名称不是当前分支、git rev-parse <ref>不等于git rev-parse HEAD,且git merge-base --is-ancestor <ref> HEAD成功时,保留该引用。从git reflog show --format=%gs <current>中收集旧名称:以当前名称为起点,在每一行Branch: renamed refs/heads/<old> to refs/heads/<new>中,如果<new>已被收集,则添加<old>。如果git reflog show --format=%gs <ref>包含针对已收集名称的branch: Created from <name>,则丢弃该保留的引用。如果该 reflog 包含branch: Created from HEAD,git rev-parse <ref>等于该行上的%H,且另一个保留的引用是<ref>的祖先,也丢弃该引用。选择剩余引用中提交者时间戳最大的一个。时间戳相同时,选择字典序最小的引用名称。 - 否则,没有基准,跟踪的差异为
git diff HEAD。
解析出基准后,跟踪的差异为 git diff --merge-base <base>。
- 路径后缀信号 — 变更集中有路径以
.html、.css、.scss、.less、.vue、.svelte、.tsx或.jsx结尾。名称来自跟踪差异上的git diff --name-only,以及未跟踪文件列表。 - 视图标记信号 — 跟踪差异上
git diff -U0中的新增或删除行匹配以下差异模式,或者未跟踪文件的任意一行匹配以下标签模式。两者均区分大小写。
差异模式(对 git diff -U0 使用 grep -E):
^[+-].*</?(div|span|button|input|img|svg|path|ul|li|form|label|textarea|canvas|section|header|footer|nav|table|video|iframe|h[1-6])([[:space:]]|>|/)
标签模式(对每个未跟踪文件使用 grep -E):
</?(div|span|button|input|img|svg|path|ul|li|form|label|textarea|canvas|section|header|footer|nav|table|video|iframe|h[1-6])([[:space:]]|>|/)
任一信号命中都意味着该功能包含 UI 行为。因此,验证阶段至少要包含一项会打开 UI 的检查——按层级规则,优先使用真实环境;模拟 UI 也算打开 UI。该检查会触发上面的截图条款。非 UI 检查无需截图,且仍禁止伪造图像。
如果 figma-pixel-verify 负责此项验证,且其报告渠道为 layout-probe,并显示 Screenshot: not-openable,那么这条记录就是像素检查的 UI 证据结果,并可结束此预检查。该技能下可打开的渠道会打开 UI 并保留截图,从而满足此预检查。
如果信号命中,但本次运行仍无法打开 UI,则在编写报告前,按照 A/B/C 规则对阻碍进行分类。A 类需要在本轮接入一项会打开 UI 的检查。C 类以及仍在等待一次性设置的 B 类,需添加限制说明。该说明应写明受阻原因、受阻的层级,以及将弥补此缺口的后续操作,并注明非 UI 检查无法覆盖 UI 行为。
如果两个信号都未命中,则不触发此预检查。与之前一样,非 UI 检查即可满足验证要求。
诚实标注层级(非阻塞)
验证报告必须说明每项检查实际使用的层级。当使用的层级低于生产目标时,请标注:“已在模拟环境中验证;建议进行真实环境冒烟测试。”这是标注义务,而非门槛——它绝不会阻止 AI 在可达的层级上进行验证,但禁止将模拟结果描述为真实环境确认。
边界
completion-evidence-discipline——正交维度。它规范证据的时效性(本轮是否实际运行);此技能规范环境和执行者(使用哪个层级、由谁运行、是否充分)。通过声明必须同时满足两者。runtime-evidence-debug——该技能用于调试取证:通过插桩查找根因。此技能用于验证执行:在环境中确认修复或功能正常运行。两者目的不同,尽管名称相似。- 能力技能(
browser-debug-toolkit、android-webview-debug、未来的 Electron/移动端技能)——负责选择通道和提供操作步骤。此技能只决定在哪里执行、由谁执行以及是否充分;具体如何操作则交由它们负责。
集成指南(面向宿主)
- 在 frontmatter
dependencies中声明runtime-verification-discipline;如果缺失,则在启动时中止。 - 在验证阶段添加一行简短说明:“验证执行遵循
runtime-verification-discipline”,并附上宿主自身的范围条件。保留宿主自身的编排和退出流程。 - 不要在宿主中重述层级模型、选择规则、提供方解析或 A/B/C 说明——此技能是唯一可信来源。
各宿主的编辑格式和示例见 reference.md。