# 设计系统「系统一致性 + 完整性」维度审核 — 2026-06-12

> **性质**：诊断报告（只读）+ **可复用尺子**。源码级修复等 owner 逐条 ack。
> **方法**：4 个 subagent 并行审，每维带 file:line 实证；外部锚定 Ant Design / Element Plus / Polaris / Material / Carbon；硬纪律 = **字段/机制存在 ≠ 失效模式被覆盖**（本 session 早先犯过，本审核刻意防）。
> **缘起**：[`process-gap-report-2026-06-11.md`](./process-gap-report-2026-06-11.md) 那次 review 只比对了两条轴——**生命周期流程**（design-process 8 步）+ **单产物正确性**（render-verification 查"组件 vs 它自己的 Figma 节点"）。owner 实际撞到的痛（跨变体对齐、跨组件同语义一致）属于**第三条轴：系统横向一致性**，不在原 checklist → 只能反应式撞。本审核补这条轴，并把尺子落进仓库做未来比对基线。

---

## 第一节：15 维一致性尺子 + 覆盖度矩阵

> ✅ 有机制且抓得住失效模式 · 📝 部分（有字段/机制但漏失效模式）· ❌ 无

| 维度 | 核对什么 | 外部锚点 | TVU 现状 | 核心缺口（漏抓什么） | 建议落点 | 优先级 |
|---|---|---|---|---|---|---|
| **D1** 跨变体像素对齐/间距 | 同组件各变体之间对齐/间距是否一致 | Material states matrix | 📝 | verifier 只"每变体 vs 自己 Figma 节点"，**从不跨兄弟变体比对**；Button 8-set(~3200) deferred audit-invisible | `scripts/audit-cross-variant-parity.mjs`（跨 size/state 轴比对不变属性） | **High** |
| **D2** 跨组件同语义 IA/布局 | 同语义结构（label+控件行等）在不同组件是否同布局 | Carbon/Polaris | ❌ | F2-early 只验单设计 IA；M49 语义合同只单任务内；affordances 只描述能力不描述跨组件结构契约 | affordances.json 加 `semantic_layout_class` + `audit-semantic-layout-parity.mjs` | **High** |
| **D3** Figma→code 原子同步 | master 变更后所有 code 契约零 drift | Material/Carbon design-code parity | 📝 | **canonical .vue 不被 sync 重生成**；`audit:figma-library-vs-canonical` **不在 prepublishOnly** → canonical 漂移可发布进 npm | **package.json 加 1 行**把该 audit 进 prepublishOnly | **High** |
| **D4** 交互态一致性 | 同类组件 hover/focus/disabled/active 同范式 | Material states | 📝 | R9 是 L1 纯自律、CSS linter 未写；Checkbox/Radio 实证 mouse-only 无键盘/aria（CANONICAL-013 未修）；hover CI 不真触发 | 扩 `audit-component-affordances` check-D 闸 `:hover`/`:focus-visible`/`[disabled]` | **High** |
| **D5** 命名一致性 | 同概念跨组件/prop/event/token 同名 | — | 📝 | **Rating 独用 `update:value`**（其余 modelValue/status）；CheckBox/Radio/Switch 发 `update:status` 但 alias 文档写 modelValue（自相矛盾）；2 个 icon guard（category-enum/leaf-kebab）spec-only 未实现 | 实现 2 icon guard 进 prepublishOnly；event 命名 lint + 文档 Rating 决策 | **High** |
| **D6** a11y 范式一致性 | 同类组件 focus/ARIA/键盘同做法 | Carbon/Polaris | 📝 | 无共享 a11y 范式 spec；**`Table.vue:32` `<th>` 缺 `scope`**；**`Tooltip.vue:38` anchor `aria-hidden` = 键盘不可达（hover-only）**；selector 3 套键盘范式无统辖 | 2 处源码 1-行修 + `a11y-patterns.md` + 跨组件 pattern test | **High** |
| **D8** API 公约一致性 | prop/event/slot 命名、受控、size、布尔默认跨组件统一 | Element ConfigProvider / Ant | 📝 | **主题 prop 名分裂**：11 个 `darkTheme:'on'\|'off'` vs 6 个 `theme:'dark'\|'light'`，**FormItem 独用大写 `'Dark'\|'Light'`**（consumer footgun）；size 大小写跨层不一；无 ConfigProvider、无命名约定文档 | 跨组件 theme/size lint + 修 FormItem 大小写 + CONTRIBUTING 加 4 条公约 | **Medium** |
| **D9** ⭐ 运行态数据态范式 | empty/loading/error/0-data/无权限/超长 | **Ant Exception Page spec + Empty/Skeleton/Result** | 📝 | **无 Empty/Skeleton/Spin/Result 组件、无范式文档、无 gate**；只有零散补丁（M43 超长/M29 空 cell/Switch·Button loading prop/PillStatus）；PROJECT_GOAL:86 显式 scope-out | `runtime-state-patterns.md`（每数据容器组件各态用什么范式） | **High** |
| **D10** UX 文案/内容一致性 | 术语/标签/错误语气/大小写 | **Polaris voice&tone** | 📝 | vocabulary.md 是英语学习词库非风格指南；M44/M33/M49 都"单任务防漂移"；无产品级 voice/tone/大小写/错误公式 | `content-style-guide.md`（1-2 页，AI 起手加载） | **Medium** |
| **D11** 选用指引 | 何时用哪个组件（do/don't） | Polaris/Carbon/Element | 📝 | **好消息**：affordances.json 34 组件全有 `when_to_use`+`do_not_hand_compose`，知识已强；真缺口仅**没在 docs 站露出** + "Use Cases" tab 规划未建 | 把 JSON 的 when_to_use 渲染到组件页（无需新写知识） | **Med-Low** |
| **D12** 组合/页面级范式 | 表单/Table+Pagination/master-detail | Ant Pro / PROJECT_GOAL T4b | 📝 | affordances.json 有 composition 数据但**没进 npm manifest**（compositionSupport 字段纯规划）；Table+Pagination 零 demo | manifest 加 compositionSupport（数据现成搬入）+ Table+Pagination demo | **Med-Low** |
| **D13** 主题对等性 | 每组件 dark+light 都验、无破一主题的 token | Ant theming / Material | 📝 | PromptMessage dark "已知错但豁免"（gate 假绿）；PillStatus light 无 Figma 源未验；**semantic tier token 不在 token-contract 闸内**；Button 8-set 无主题验证 | token-contract 加 semantic tier 双主题 parity 检查 + PromptMessage 拆 dark/light token | **High** |
| **D14** i18n/文本膨胀 | EN↔ZH 长度差撑布局；内置串本地化 | Element/Ant locale | 📝 | **DS 内置 aria-label 硬编码英文**（Remove option/Clear value/Pagination）→ ZH 产品读屏念英文；无 ZH-locale 测试 | SelectBox/Pagination 加 `ariaLabels` prop + 1 个 ZH-locale 测试 fixture | **Med-high** |
| **D15** 组件成熟度标注 | 逐组件 stable/experimental/deprecated | **Carbon/Atlassian per-component status** | ❌ | consumer 无法从包知道哪个组件稳定/实验/废弃；API_STABILITY 的 `@experimental` 保留未用；roadmap P0-2 已识别未解 | affordances.json 加 `maturity` 字段（区别于现有 verified/skeleton）+ docs 站 badge + @experimental JSDoc | **High** |

**统计**：2 条全无（D2 / D15）、12 条部分。**High 9 条**（D1/D2/D3/D4/D5/D6/D9/D13/D15）。

---

## 第二节：立即可做的源码级 quick-fix（低风险，待 owner 逐条拍）

> 审核顺手捞到的具体 bug / 一行修，**都未动**（源码改动比文档风险高，且个别涉 API 行为，逐条等 ack）：

| # | 修什么 | 位置 | 风险 | 类型 |
|---|---|---|---|---|
| Q1 | `audit:figma-library-vs-canonical` 加进 `prepublishOnly` —— **让 D3 同步契约真正闭环**（否则 canonical 漂移可发布进 npm） | `package.json:50` | 极低（加 1 行） | 闸补全 |
| Q2 | `<th>` 加 `scope="col"`（WCAG 1.3.1） | `Table.vue:32` | 极低（1 行） | a11y bug |
| Q3 | Tooltip anchor 去 `aria-hidden` + 加 `tabindex=0`/键盘触发（现 hover-only，键盘不可达） | `Tooltip.vue:38` | 中（改交互行为，需测） | a11y bug |
| Q4 | 2 个 icon guard（`audit:icon-category-enum` / `audit:icon-leaf-kebab`）实现并进 prepublishOnly（spec 已定 §7 未实现） | 新 scripts | 低 | 闸补全 |
| Q5 | FormItem 主题值大小写 `'Dark'\|'Light'`→`'dark'\|'light'` 对齐其余组件 | `FormItem.vue:13` | 中（API 行为，0.x breaking 可接受，记 CHANGELOG） | API 一致性 |
| Q6 | Rating `update:value` 事件命名决策（normalize 成 modelValue 还是文档化保留） | `Rating.vue` | 中（API 决策） | API 一致性 |

**我的建议**：Q1/Q2 立即做（清晰低风险、Q1 还闭环你刚立的契约）；Q3/Q4 值得做（a11y + 闸）；Q5/Q6 是 v1.0 前该拍的 API 一致性决策，建议合到一次 API 规整。

---

## 第三节：较大缺口（需建机制，owner-gated）

- **D9 运行态范式**（High）：建 `runtime-state-patterns.md`——每个数据容器组件（Table/Chart/Select）的 loading/empty/error/0-data/无权限用什么范式（共享 slot 约定 / 专用组件 / 页面级 PromptMessage+Notification）。视频 SaaS 高频态，AI 消费方现在各自发明。
- **D2 跨组件同语义布局**（High）：affordances.json 加 `semantic_layout_class` + 新 audit 脚本扫同语义组件 flex 方向/gap token/对齐是否一致。
- **D15 成熟度标注**（High）：affordances.json 加 `maturity` 字段 + docs badge，v1.0 前该有（roadmap P0-2 已识别）。
- **D13 主题对等闸**（High）：token-contract 加 semantic tier 双主题 parity，堵"加了 light override 忘 dark default"类漏。
- **D1 跨变体 parity**（High）：新 audit 脚本跨变体比对不变属性。

---

## 第四节：B3 / B5 复核（前次 review 的两条，并入重判）

- **B5（增量 IA 兼容）= D2** → **❌ 确认真缺口 High。前次我降级判错了**（用 F2-early 存在就判覆盖，但 F2-early 验单设计 IA，不管跨组件结构一致）。owner 当时坚持是对的。
- **B3（QA 验收绑 UX 卡）** → 折进 **D1/D4**。M23 确有 Acceptance 字段（前次我说"已覆盖"那点没错），但它不强制"跨变体/跨组件像素核对"——真缺口是 D1/D4 的 gate，不是"给 M23 加字段"。B3 作为独立项关闭，能力并入 D1/D4。

---

## 第五节：把尺子落进流程（防再反应式撞）

本 15 维清单接进 [`design-spec-process-review.prompt.md`](../_prompts/design-spec-process-review.prompt.md) 作为**第二条核对轴**（系统一致性），与原 12 个生命周期环节并列。今后任何"规范+流程完整性 review"对两条轴都比对，不再只靠 owner 撞到才发现。

> ⚠️ **2 个执行缺口（2026-06-12 owner 实测暴露，下个 session 必修）**：
> 1. **D1-D15 没接进 per-mockup F1 走查流程**——只接进了 system-level review prompt + 躺在本报告里。owner 说"按 design review 检查这个 mockup"时跑的是 design-process Step ⑤ F1 走查（`~/.claude/agents/design-walkthrough.md`），**它不引用 D1-D15** → D1 跨变体 / D2 跨组件 / D9 运行态（owner 原始痛）日常走查根本不查。必须把 mockup-reviewable 维度（D1/D2/D6/D9/D13）回流进 F1 走查 + 走查 agent。
> 2. **rule-registry 的 `fires_on` 必须双向核对**：不只"规则声明触发点"，还要"触发点真运行的东西（agent/gate/prompt）确实加载它"——否则"加了不用"（本报告自己就是活样本）。

---

## 第六节：design-review 框架第三轴 —— 视觉设计质量（visual-quality）盲区

> **2026-06-12 owner 实测发现**：用"按 TVU design review 流程检查"查 mockup，结果只查了 token/组件/pattern 一致性 + 类级同源；**横向对比只做"结构同源"没做"视觉权重"**。

**根因**：F1 走查 + D1-D15 **两条轴都偏「结构/系统一致性」**；缺第三条轴 **「视觉设计质量 / design-critique」**——senior 设计师走查时查的东西。

**已反应式撞到的 3 个盲区（同属此轴）**：
1. 字段 parity
2. 控件同源 inventory（控件是否复用同源组件）
3. **信息密度 + 强调预算 + 视觉权重**（横向对比缺"视觉权重"维度）

**几乎肯定还有更多**（一个个撞 = 反应式病复发）。**正解 = 建一把 design-critique 维度尺子**（与 D1-D15 同形），外锚：visual hierarchy / 信息密度（data-ink ratio, Tufte; density 档位 like Material）/ emphasis budget（强调预算：有限的"响亮"额度，处处强调=无重点）/ 视觉权重平衡 / 留白·节奏·分组（Gestalt proximity）/ 可扫描性（F/Z-pattern）/ 渐进披露 / 层级对比（非 a11y contrast）。建完**回流进 F1 走查流程**（同上方执行缺口 #1）。

**状态**：TODO，下个 session。归入 rule-registry P1 的"把维度接进 F1 走查"那一步一并处理（让走查同时跑系统一致性轴 + 视觉质量轴）。
