dsh-verify
dsh-verify
Agent 自测全过,真实浏览器说出真相。
dsh-verify 是一个轻量、少依赖的验收测试工具,专为 智能体交付的 Web 工件 设计。你编写一份 JSON 规范,描述人类会在浏览器中检查什么;它启动一个真实的 headless Chromium,点击、读取计算样式,并生成一份 HTML 报告外加 0/1 退出码。
它之所以存在,是因为我们曾被坑过——而且我们有证据。
由来(为什么会有它)
我们运行了一个 4 智能体 Web 团队(规范编写者 → 前端开发 → QA → 审查者)。该团队交付了一个带计数器和深色模式切换按钮的演示页面。他们自己的审查报告说:
✅ “所有需求均已满足。未发现问题。”
在真实浏览器中,切换按钮 什么都没做——页面背景从未改变。.dark 类确实由 JavaScript 切换了,但 .dark 的 CSS 规则从未编写。每个智能体自测都通过了,因为页面里没有任何可让智能体运行的东西。没有人打开过真实浏览器。
这就是差距:智能体是根据他们自认为构建的东西来验证,而不是根据用户实际体验来验证。 单元测试和静态检查无法捕获缺失的 CSS 规则。
本仓库并排包含了这个 bug 及其修复——以及区分两者的浏览器驱动证据:
构建 | 智能体的说法 | 真实浏览器的说法 |
| “未发现问题” | ❌ 失败——背景从未改变 |
| 添加了一条 CSS 规则 | ✅ 通过——主题正确切换 |
同样的页面。同样的 JS。缺失一条 CSS 规则。两种不同的裁决。
Related MCP server: Mochi
报告
一份自包含的 HTML 报告——每一步都有通过/失败徽章、选择器和详情,外加截图:

功能
读取 JSON 规范(无需框架、无需配置语言)
托管你的静态目录(或指向任意 URL)
驱动 真实的 headless Chromium(Playwright)
检查人类会检查的内容:文本、类、计算样式、URL、像素
生成一份自包含的 HTML 报告,包含截图和差异图
通过时退出
0,失败时退出1→ 可放入任何 CI为 Claude Code / Cursor / Copilot 提供 MCP 服务器 · AI 起草检查清单 · GitHub Action · DSH 插件
安装
# from npm (CLI)
npm install -g dsh-verify
# as a DeepSeek Harness (DSH) plugin — available in every session of the profile
dsh plugin --profile web add dsh-verify
# or run without installing
npx dsh-verify --help在任何 AI 智能体中使用(MCP)
dsh-verify 附带一个 MCP 服务器,因此 Claude Code、Cursor、Copilot 或任何支持 MCP 的智能体都可以在真实浏览器中验证自己的交付物——无需规范文件:
# register once (Claude Code)
claude mcp add dsh-verify -- npx -y -p dsh-verify dsh-verify-mcp
# or (Cursor / generic MCP client)
# add a stdio server with the command: npx -y -p dsh-verify dsh-verify-mcp然后用普通语言告诉你的智能体:
验证 http://localhost:3000 —— 点击
#dark-toggle,然后检查body的 background-color 是否改变。截图。
智能体会调用 verify_url,并传入一组人类风格的检查项(goto / click / fill / expect_text / expect_class / capture_style / expect_style_changed / expect_url_contains / expect_navigation / expect_console_errors / expect_network_errors / screenshot / expect_screenshot),一个真实的 headless Chromium 会确定性地执行这些检查,然后智能体得到 PASS/FAIL 判定以及一份自包含的 HTML 报告。
MCP 服务器公开的工具:
工具 | 作用 |
| 针对真实 Chromium 运行现有的规范 JSON 文件(或通配符) |
| 针对内联检查列表验证实时 URL——无需文件 |
| AI 根据实时页面 + 你的需求起草检查清单,然后由真实 Chromium 执行 |
| 确认服务器和 Chromium 已就绪 |
没有 LLM 来评判结果——浏览器才是裁判。这正是关键所在。
在 CI 中使用(GitHub Action)
任何工作流中的一个步骤——隔离安装 dsh-verify 和 Chromium(不影响你的项目),运行检查,并将报告作为工件上传:
- uses: 263311487-ux/dsh-verify/.github/actions/dsh-verify@main
with:
spec: demo/fixed.json # spec file or glob
# url: https://staging.example.com # optional override
# out: dsh-verify-out # report output dir (default)本仓库自用该方案:dogfood 工作流 在每次推送时断言修复版构建 通过、缺陷版构建 失败。
视觉回归(像素级截图基线)
修改页面后,让像素告诉你结果——而不是你的眼睛或记忆:
{
"title": "my app",
"serve": "dist",
"steps": [
{ "action": "goto", "path": "/index.html" },
{ "action": "expect_screenshot", "name": "home", "threshold": 0.01 }
]
}首次运行会 创建基线(
out/baselines/home.png)并返回通过。后续运行会逐像素比较真实 Chromium 截图;超过
threshold(默认 1%)的差异会导致构建失败。红色高亮的 差异图 会放入
out/diffs/并嵌入 HTML 报告。预期有变化?刷新基线而不是让它失败:
dsh-verify --spec spec.json --update-baselines。用
"selector"限定区域,用"tolerance"(每通道,默认 10)调整噪声。
Actions:capture_baseline(显式保存基线)、expect_screenshot(与基线比较)。
AI 起草的检查清单(LLM 编写,真实浏览器执行)
不想手写 JSON?dsh-verify gen 会在真实浏览器中了解页面,让 LLM 根据你的需求起草检查清单,然后在真实 Chromium 中执行:
export DEEPSEEK_API_KEY=sk-... # or pass --api-key / --provider openai
dsh-verify gen --url http://localhost:3000 \
--prompt "dark-mode toggle must actually change the background color" \
--rungen: opening http://localhost:3000 in a real browser to learn the page...
gen: page learned (2 buttons, 0 inputs) — drafting checklist...
gen: checklist drafted by deepseek-v4-flash (10 steps) -> dsh-verify.gen.json
gen: executed in real browser -> PASS (10/10)
report: dsh-verify-out/report.htmlAI 只是 起草 检查清单——它从不评判结果。同一个确定性 Chromium 引擎会运行这些步骤,JSON 会写入磁盘,方便你在信任之前进行审查或编辑。
要求 Node >= 18,并安装一个浏览器:npx playwright install chromium。
快速开始
npm install
npx playwright install chromium # one-time browser download
# Run the two demo specs back to back
npm run demo:buggy # → FAIL (exit 1) — missing .dark style caught
npm run demo:fixed # → PASS (exit 0)
# engine self-tests + full CI flow
npm test # node:test suite
npm run ci # tests + fixed PASS + buggy FAIL (as proof of detection)本仓库自己的 CI 正是这样运行的:引擎自测,然后断言修复版构建 通过、缺陷版构建 失败——因此该工具在每次推送时都会自我验证(.github/workflows/ci.yml)。
机器可读输出
node bin/verify.mjs --spec demo/fixed.json --out /tmp/out --json
# {"verdict":"PASS","passed":11,"total":11,"failed":[],"report":"/tmp/out/report.html"}运行多个规范
node bin/verify.mjs --spec 'specs/*.json' --out reports/
# [PASS] specs/home.json (5/5)
# [FAIL] specs/cart.json (4/5)
# ❌ expect_text #total: got "0" want "99"每个规范都会获得自己的 reports/<name>/ 文件夹;仅当 全部 通过时退出码才为 0。
规范格式
顶层字段:title、serve(静态目录)、base(目标 URL)、browser(可选:chromium | firefox | webkit,默认 chromium)、steps。
{
"title": "my app",
"serve": "dist",
"browser": "chromium",
"steps": []
}每次运行可用 --browser firefox 覆盖。
{
"title": "my acceptance check",
"serve": "demo/fixed",
"steps": [
{ "action": "goto", "path": "/index.html" },
{ "action": "click", "selector": "#count-btn", "count": 3 },
{ "action": "expect_text", "selector": "#count-btn", "text": "Clicked: 3" },
{ "action": "capture_style", "selector": "#page", "prop": "backgroundColor", "var": "bg_before" },
{ "action": "click", "selector": "#color-btn" },
{ "action": "expect_class", "selector": "#page", "class": "dark", "present": true },
{ "action": "expect_style_changed", "selector": "#page", "prop": "backgroundColor", "var": "bg_before" },
{ "action": "screenshot", "name": "final-state" }
]
}Actions
操作 | 字段 | 验证内容 |
|
| 导航(若设置了 |
|
| 等待(让 CSS 过渡完成) |
|
| 点击元素,可点击 N 次 |
|
| 填充输入框 |
|
| 可见文本包含/等于目标 |
|
| 类存在(默认)或不存在 |
|
| 将 计算样式 快照到变量中 |
|
| 计算样式与快照不同——这是能捕捉“类切换了但 CSS 从未编写”这一问题的检查 |
|
| 当前 URL 包含目标文本 |
|
| 等待 URL 包含 |
|
| 运行期间无控制台错误(默认期望无错误) |
|
| 无 4xx/5xx 响应或失败的请求(默认期望无错误) |
|
| 将 PNG 保存到报告中 |
|
| 将截图保存为视觉基线 |
|
| 与基线进行像素差异比较;超过 |
capture_style → expect_style_changed 这一对是此项目的核心:它验证用户看到的内容,而不是 DOM 类列表给出的信息。
实况证据
下面两张截图是 dsh-verify 针对同一演示的两个构建输出的真实结果(Chromium,1280×800,点击切换按钮后):
缺陷版构建——点击切换按钮,背景未改变:

修复版构建——点击切换按钮,主题已切换:

Docker(固定 Chromium 版本)
docker build -t dsh-verify .
docker run --rm -v "$PWD:/app" dsh-verify --spec demo/fixed.json --out /app/reports使用 mcr.microsoft.com/playwright:v1.62.1-jammy,因此 Chromium 构建与 Playwright 版本匹配——镜像构建时无需下载浏览器。(已构建并记录;已在本地验证,尚未在 Docker 主机上验证。)
为什么其他方案做不到
在构建之前,我们调研了智能体工具社区。现有的“智能体交付物验证”大多是:
插件/安装冒烟检查——技能是否安装、CLI 是否存在(例如插件发现工具)。
静态 lint / 单元测试——验证智能体编写的代码,而不是用户体验到的行为。
仅截图的智能体——看图片,而不 断言 行为。
它们都不会针对工件运行真实浏览器并回答:“当我点击这个按钮时,用户能看到变化吗?” 这正是 dsh-verify 填补的空白——刻意保持小巧、无框架、输入 JSON 规范、输出浏览器判定。
路线图
expect_console_errors/expect_network_errors— 无控制台错误,无 4xx/失败请求--json用于 CI 日志的判定输出;失败的步骤打印到 stdout多页面流程与
expect_navigation(点击后等待 URL)--specglob (运行多个 spec,一份聚合判定)使用固定版本 Chromium 的 Docker 镜像 (
mcr.microsoft.com/playwright:v1.62.1-jammy)DSH 插件清单 (
dsh plugin add dsh-verify)MCP 服务器 — 从 Claude Code / Cursor / Copilot 进行验证 (
verify_spec/verify_url/generate_and_verify)AI 草拟的检查清单 —
dsh-verify gen(LLM 草拟,确定性浏览器强制执行)GitHub Action — 一步式 CI 验收,带报告工件
视觉回归 — 像素级截图基线 (
capture_baseline/expect_screenshot)多浏览器矩阵 —
--browser/spec.browser: chromium, firefox, webkit (CI 中全部通过)移动端视口
根据自然语言需求生成 AI spec,无需运行中的页面
许可证
MIT
Maintenance
Related MCP Servers
- Alicense-qualityCmaintenanceCode-aware browser testing agent — reads your codebase, understands functionality, tests every element, reports with screenshots. Works as MCP server for Cursor/Claude Code or standalone CLI.2305MIT
- AlicenseBqualityAmaintenanceBrowser automation MCP server with persistent memory for AI assistants, enabling automated web testing and workflow replay with self-healing selectors.543MIT
- AlicenseCqualityAmaintenanceAn MCP server that enables AI agents to autonomously test, debug, and analyze web interfaces visually using Playwright, with 30 tools for screenshots, workflows, performance, and visual comparison.301780ISC
- Flicense-qualityBmaintenanceMCP server that enables AI agents to automate browser testing via Chromium, providing tools for navigation, interaction, and inspection.
Related MCP Connectors
Screenshot, diff, audit and sitemap-capture any web page — 5 MCP tools for AI agents.
AI QA tester — real browsers scan sites for bugs, SEO, perf, and accessibility issues via chat.
Live browser debugging for AI assistants — DOM, console, network via MCP.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/263311487-ux/dsh-verify'
If you have feedback or need assistance with the MCP directory API, please join our Discord server