# M21 + R6 — Existing pattern reuse 规则诞生复盘 (2026-05-11)

## 背景

US-3 任务："在 TVU SaaS Dashboard 产品文件（Usage Service 产品）新增 Cost per Token Trend dashboard 页"。

- 参考页：`1641:2212` (Growth vs. Last Year / Annual YoY)，sibling 已有 6× `Compare Item/YTD` 卡片网格
- 目标页：`1749:93` (Page 19，空 page)

User 在任务进行中提示："像这个已有本地组件的，若无特殊说明，优先使用本地的组件，因为是新增功能，不是重新设计，已有模块需要直接挪用，否则出现不同页面同一时间的样式差异太大了。这条规则属于通用规则，应该可以更新 Mockup/code-conventions 的相关文件中。"

触发规则诞生流程。

---

## 核心发现 1：sibling page bitmap 偷懒 — authoring artifact vs 视觉合同

probe `Compare Item/YTD` 实测结果：

| 维度 | 实测 |
|---|---|
| 类型 | 普通 COMPONENT（不是 COMPONENT_SET，无变体 / 无 props） |
| 主内容 | `image 12` (865×414 bitmap) + `echarts` (900×420 bitmap) + Mask + 标题 text + `Box/choose` 右上 widget |
| Card shell fills | **白色** `{r:1, g:1, b:1}`（不是 token / 不是 dark） |
| Drop shadow | offset 0,1 / blur 4 / black 0.5 opacity |
| Corner radius | 4 |
| 视觉为何看起来 dark | bitmap 自带 dark bg，shell 是白被盖住 |

**关键洞察**：sibling page 的 "dark cards on dark bg" 是 authoring 偷懒（截图当 card 内容），不是 design-system-driven dark theme。盲目照抄 → 把懒惰原型传染。但用户看到的视觉合同就是 dark，应当对齐**视觉结果**，不对齐 authoring trick。

这个发现把 M21 决策树细化出 1.a / 1.b 两个分支：

- **1.a** — local 数据可 adapt（slot / variant） → 直接 instance
- **1.b** — local 不可 adapt（bitmap / 硬编码） → mirror **视觉壳层**（用户看到的），rebuild internals 用 design system 真组件

---

## 核心发现 2：M21 第一次实战 self-test pass — 配色 (a)→(b) 自纠

第一次提议中 AI 推荐配色路径 **(a) 白卡 + dark page bg**，理由 "业务 dashboard 主流是白底 + 紫色对比好"。

User 拍板前 AI 自审：

- M21 第 1.b 条 "mirror 视觉合同 = 用户**看到**的视觉"
- sibling 用户看到的是 dark cards 不是白卡（被 bitmap 盖住的白 shell 用户看不到）
- 路径 (a) → 与 sibling 视觉割裂（违反 M21）
- 路径 (b) → 与 sibling 视觉对齐

**自纠到 (b) dark 重建**。这次自纠不是 user 提示，是 AI 应用刚立的 M21 规则做的判断。规则的**实战有效性**得到第一次实证：规则不是说辞，规则在指导决策。

教训：写规则当下立刻在当前任务上 *self-test*——如果规则在自己任务里都用不上，说明规则错或者用得不到位。

---

## 核心发现 3：M14 vs M21 张力解法 — 元素位置 vs 整体视觉

冲突点：sibling `Compare Item/YTD` 标题在 card 底部（last child of VERTICAL layout），通用 UX 规范标题在顶部。M21 要 "mirror sibling 视觉"，那标题该放哪？

解法：**M14 优先级 > M21 在元素位置维度**。

- **M14** — 原 mockup 不当 spec，复刻每个元素前问适配性
- **M21** — mirror sibling 视觉合同（整体密度 / 壳层 / 主题）

**张力解析**：

- sibling 标题在底部不是设计意图，是 echarts 输出 + 标题加在底部当 caption 的 authoring 妥协
- M14 要求每个元素重新判定适配性 → 标题放顶部（F-shape reading 通用 UX）
- M21 mirror 的是 *整体视觉密度* + *card shell 几何* + *色彩主题*，**不是**每个元素的精确位置

写进 M21 "与既有规则关系" 段：M14 补充 M21——mirror 视觉合同**不**要求复刻 sibling 任一具体元素尺寸 / 间距。

---

## 核心发现 4：R6 镜像 code-conventions 的真实价值

最初 AI 提议 "不把 R6 镜像进 code-conventions"，理由 "code 侧 Vue import 天然防视觉碎片"。

User 撤回此判断，要求 R6 必须镜像。

反思：AI 提议错在 *假设* code 侧 import 机制 = automatic visual consistency，但 AI 自己脑补的反例实际成立：

- 增 settings 页时不看 profile 页已有的 `<SettingsField>` composable，重新从 canonical 拼 → ❌ 真实场景
- 增 chart 页时绕过 dashboard 已用的 `<ChartCard>` layout 包装器，独立用 raw chart lib → ❌ 真实场景

"import 机制存在 ≠ 自动复用"。code 侧的 anti-pattern 不是技术机制缺失，是 *人/AI 没看 sibling 现状就开搞*——和 mockup 侧反模式根因相同。

R6 镜像进 code-conventions 是对的。规则不能因为"看似不会发生"而省略——AI 没看 sibling 现状这件事在 mockup 和 code 两侧 *都会发生*。

---

## 规则全文落地

- **M21** → [`mockup-conventions.md`](../mockup-conventions.md) §M0 后、M1 前（作为 P1 hard rule）
- **R6** → [`code-conventions.md`](../code-conventions.md) §R5 后、§关联文档 前（作为 P1 hard rule）

---

## 适用边界提醒

M21 / R6 仅 **US-3**（existing product 增量）生效。US-1 / US-2 greenfield 仍按 M2 / R0-R3 走 library 优先，因为基线还没建立，没有"现有 sibling 视觉合同"需要 honor。

这条 scope 区分是规则成立的关键——M21 / R6 不是要推翻 M2 / R0-R3，是**补全 incremental scope 的决策空白**。

---

## 元规则启发

1. **写规则当下 self-test**：新规则首要 acceptance criteria 是它能指导当前任务的决策（这次配色 (a)→(b) 自纠就是 self-test pass）
2. **规则不能假设"机制 = 行为"**：import 机制存在不等于复用行为自动发生；规则要约束行为，不要假设机制保证
3. **scope 显式标注**：M2 与 M21 不冲突的关键是 scope 时序差 (greenfield vs incremental) 写进规则正文，避免后续 AI 误判规则适用范围
