DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

gongyijie85 /

gongyijie85/dsh-design-audit

Verified

DeepSeek Harness 的 UI/UX 审查与优化闭环:无头 Chrome 取证 → 确定性判据(WCAG 2.2 / 平台指南)→ 可粘贴修复 → 复测差值验证

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHubProject homepage
READMESource: main@75feac1b

dsh-design-audit

DSH 的 UI/UX 审查与优化闭环:截图取证 → 确定性设计判据 → CSS 修复 → 复测验证。

为什么做这个(生态定位)

2026-09 的 DSH 插件生态调研结论:

方向 现状
设计生成(从 0 到 1) 已被 deepseek-design(★978,含 Studio/模板市场)覆盖
截图 → UI 还原 已被 agent-vision-toolkit(★1195)覆盖
设计知识清单 uckkk 系列 5 个插件,0–2★(纯参考、无工具化)
审查与优化闭环 空白 ← 本插件做这个

不做生成器、不做还原器:只做"量出问题 → 给出可粘贴的修复 → 证明修好了"。

核心设计决定:测量与判据分离

页面内取证(collect.js)        判据与阈值(checks.js)
  · 几何 / 计算样式             · WCAG 条款号
  · 对比度比值(页面内算)       · 平台指南(44×44)
  · 可访问名称 / 遮挡命中测试    · 分级 + 具体 CSS 修复
  = 全是"量出来的"              = 全是"定下来的"

测量错、判据错可以分别审计,互不掩盖。

机器只做可测量的判断,审美交给模型看图 —— 工具不越界假扮评审官:它把客观证据与截图路径摆好,把"视觉层级/一致性/品牌感/呼吸感"留给模型的视觉复核(报告里显式列为"未覆盖")。

三个工具

工具 作用
design_capture 无头 Chrome 打开 URL/本地 HTML,多视口整页截图 + 采集客观测量值。产物落 <工作区>/.design-audit/<时间戳>/
design_review 跑确定性判据,出分级问题 + 逐元素 CSS 修复 + 自包含 HTML 报告;带 compare 时输出复测差值
design_fix 把问题转成可粘贴的 CSS 补丁(可选直接追加到样式文件,自动备份原文件)

判据覆盖(13 组)

  • 无障碍:对比度(1.4.3)、焦点可见(2.4.7)、目标尺寸(2.5.8)、可访问名称(4.1.2)、图片替代文本(1.1.1)、表单标签(3.3.2)、页面语言(3.1.1)、标题层级、地标区域
  • 排版:字号下限、行高(1.4.12)、行长(measure)、字号/字族阶梯
  • 布局/交互:横向溢出、间距基准网格、色彩数量、图片尺寸预留(CLS)、浮层遮挡(可见 ≠ 可点)
  • 动效(2.3.3,两条独立判据):
    • interaction/reduced-motion —— CSS 动效(animation/transition)缺 @media (prefers-reduced-motion: reduce) 兜底
    • interaction/js-driven-motion —— JS 驱动的动效(GSAP 默认机制=逐帧写内联 transform/opacity、WAAPI、手写 rAF)在 reduce 偏好下仍在动。这类动效不产生任何 CSS 动画,上面那条 CSS 兜底对它无效(animation-duration: 0.01ms !important 管不到 JS 写的内联样式),所以修复建议直接给 JS 侧写法:检测到 GSAP 时给 gsap.matchMedia() 分支,否则给 window.matchMedia 分支

闭环怎么用

design_capture target=... label=before
design_review                            # 出报告 + 问题清单
read_image <首屏截图>                     # 模型做视觉复核(工具刻意不做)
design_fix apply=true cssFile=styles.css # 生成并应用补丁(备份原文件)
design_capture label=after
design_review compare=<before 目录>       # 差值:已修复 / 仍存在 / 新引入

report.md 中 ## 视觉复核 之后的段落在复测时会被保留,便于把模型批注累加进报告; 不传 compare 时,自动基线只认同一个目标的上一次审计(跨目标比较毫无意义)。

实测证据

端到端闭环测试(node test/e2e.mjs,42/42 PASS):

  • before 检出 16 条问题(对比度 / 目标尺寸 / alt / label / lang / 焦点 / 溢出 / 字号 / 行高 / 行长 / 间距 / CLS / 遮挡)
  • 应用自动补丁后:修复 7 条、新引入 0 条,剩余为需改标记的项
  • 横向溢出只在 mobile 视口标出(多视口确实在工作)
  • HTML 类修复被分流,不会污染 .css
  • JS 驱动动效必须报出:单变量 fixture(只有 rAF 动效、没有任何 CSS 动效)报出 interaction/js-driven-motion,同时 CSS 兜底规则不得跟着误报
  • 反向用例不得误报:脚本里已处理 reduced-motion 的页面零告警;断言同时钉住"捕获环境处于 reduce 偏好"这一前提,Chrome 若改了默认值会立刻失败而不是语义悄悄漂移
  • 不许假阴性:单元层直接喂真实 evidence、只翻转"声明过兜底"这一位 —— 声明了却仍有元素在动,必须报出(low 并说明"兜底没盖住"),而不是查到字符串就闭嘴

真实项目验证(BookRank3,4 个页面,数据库指向副本、真实库零改动):

页面 首审 修复后
/ 11(高1/中3/低7) 7(全 low)
/awards 8(高1/中2/低5) 5(全 low)
/new-books 7(高1/中2/低4) 4(全 low)
/publishers 7(高2/中1/低4) 4(全 low)

最低对比度 3.78–3.95:1 → 4.57–4.74:1(越过 AA)。

真实项目揪出的 3 处遮挡(全为既有缺陷,A/B 实测已排除自身改动归因):搜索建议浮层盖住视图切换器、移动端 #sidebar-toggle 整块被顶栏压住、new-books 面包屑被固定顶栏覆盖 —— 三者的 display/opacity/rect 全部"正常",只有元素中心命中测试能发现。

开发过程中被真实使用反推修掉的缺陷

  1. 修复只覆盖最严重实例 → 改逐元素展开

  2. <a><img alt="x"> 被误报无可访问名称 → accname 的 name-from-content 包含内嵌图 alt

  3. 代码块被套用散文行长判据 → pre/code 排除

  4. 行长按容器宽度折算(中文高估约一倍、宽容器短文本必误报)→ 改实测「字符数 ÷ 渲染行数」

  5. 同一选择器在补丁里重复 8 次(相对父级生成导致塌缩)→ 按选择器去重,补丁 11.2KB → 7.6KB

  6. 复测重写 report.md 会抹掉批注 → 保留 ## 视觉复核 段落

  7. 自动基线取到无关页面 → 只认同目标

  8. 可见 ≠ 可点(盲点)→ 新增遮挡命中测试

  9. 差值误报:同一规则"最差元素"漂移时被判成"已修复 + 新引入"(假回归)→ 二次归类为"选择器漂移",单独列出前后元素

  10. 补丁重复块:跨 finding 的同一选择器生成多份(含注释的复合段会绕过归并)→ 全局按选择器归并(flattenCssBlocks),实测 4 条修复 → 2 个选择器 + 1 段原样规则

  11. 动效盲区(假阴性):取证脚本原来只统计计算样式里的 animation/transition,于是 GSAP 那类"逐帧写内联 transform"的页面一条都不报 —— 实测同一页面(整屏 rAF 无限位移、完全无视 prefers-reduced-motion)拿到"问题总数 0",而它旁边只多一个 CSS 过渡元素的对照页却报了 1 条且归因给了那个 CSS 元素。修法:跨时间采样(隔 250ms 比较几何/透明度变化,排除有 CSS 来源的元素),并把该类动效的修复建议从纯 CSS 改成 JS 侧 matchMedia / gsap.matchMedia()

已知边界

  • 只覆盖可测量判据;审美、交互态(hover/focus 视觉)、内容与信息架构、真实性能采样不在范围内(报告里显式列为"未覆盖")
  • SPA 需传 waitFor 指定标志性选择器;元素数 < 20 时会告警"可能只抓到空壳"
  • 遮挡判据用元素中心点命中测试:部分遮挡但中心可点的目标不会报(保守取值,避免误报)
  • 动效判据需要跨时间采样:每次取证多花约 250ms(两视口约 0.5s);采样窗内没动 = 不报,短于采样窗且不重复的一次性动画可能采不到
  • 无头 Chrome 默认就是 prefers-reduced-motion: reduce:因此"观察到在动"实际等价于"该元素无视了 reduce 偏好"——这正是要找的违规。证据里记录该状态(motion.prefersReducedMotion),报告实测值里也会标注
  • 脚本里已经声明 reduce 分支、却仍有元素在动时,判据不会静默放过(那会造成假阴性):降级为 low 并提示"兜底没盖住这些元素"(GSAP 常见原因:补间建在 matchMedia 分支之外)
  • 依赖本机 Chrome/Edge(DSH_DESIGN_BROWSER 可覆盖);零 npm 依赖,只用 Node 内置模块 + 全局 WebSocket(Node ≥ 22)
  • 被审项目若采用"哈希名 + 运行中进程缓存构建清单"的打包方式(如 Flask + dist_url),改完 CSS/JS 都必须重启其服务,否则页面仍加载旧资源(本插件的复测会如实显示"已修复 0")

安装

# 已安装 dsh 命令
dsh plugin --profile web add dsh-design-audit
# 或不经全局安装
npx @deepseek-ai/dsh plugin --profile web add dsh-design-audit

本包是 bundle 形态:package.json 声明 dsh.bundle.patch: ./cordis.patch.yml, patch 里以包名自引用(name: dsh-design-audit)插入插件。 dsh plugin add 会把它写进 profile 的 dependencies + bundles,启动时由 bundles 组合装配。

开发期(本机源码)

dev_inject_plugin dir=D:\plugins\dsh-design-audit   # 运行时注入(改源码即生效)
dev_reload_package packageName=dsh-design-audit     # 源码改动后热重载

一条踩坑记录(留给后来者)

本插件尚未声明 dsh.bundle 时,曾被误写入 dsh.profile.bundles → profile 下次启动硬崩: dsh-app-boot 会对每个 bundles 条目校验 dsh.bundle 声明,缺失即 throw(报错原文: profile bundle "..." declares no dsh.bundle in its package.json)。 现在包已声明 dsh.bundle,bundles 就是正确路径 —— 但这条教训对所有"纯 host 工具型"插件仍然成立: 要么声明 bundle,要么用 patch 装配,不要只往 bundles 里塞名字。

依赖解析:node_modules/@deepseek-ai/dsh-tools 是指向当前 dsh 安装体的 junction(与 dsh-skill-audit / dsh-agent-frugality 同一物化方式)。纯 ESM 直出,无构建步骤。

结构

lib/cdp.js     无头浏览器驱动(CDP over WebSocket,零依赖;含渲染就绪门控)
lib/collect.js 页面内取证脚本(自包含,序列化后注入页面;含遮挡命中测试与动效跨时间采样)
lib/checks.js  判据引擎(纯函数,可单测)
lib/report.js  Markdown / 自包含 HTML 报告(首屏图内嵌可读、整页长图链接存档)
lib/index.js   三个工具的注册与编排
test/e2e.mjs   端到端闭环验证(42 断言,含 JS 动效正/反用例与判据分支单元断言)
test/smoke.mjs CDP 通路冒烟
test/fixtures/ 有意植入缺陷的靶站(含遮挡用例、JS 动效用例、已处理 reduced-motion 的反向用例)
—/ 5

No ratings yet

Verified DSH bundle

Commit 75feac1bad26

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout