# Design Process — Shared Conventions

> **通用 process 原则**，path-agnostic，适用于 Path A（Figma mockup）和 Path B（代码生成）。
> 语言 voice-neutral：不说 "画"、不说 "写"，统称 "生成 deliverable" / "采用 source 组件"。
>
> **不包含**：TVU 业务规则（→ [`domain-tvu.md`](./domain-tvu.md)）/ Figma API quirks（→ [`figma-technical-reference.md`](./figma-technical-reference.md)）/ Path 专属细节（→ [`mockup-conventions.md`](./mockup-conventions.md) / [`code-conventions.md`](./code-conventions.md)）。

---

## 完整产品需求设计流程（⓪ Stage 0 + 8 步，Jira 关联型 mockup）— 2026-05-27 新增；2026-06-05 加 ⓪ Stage 0 上游 framing

接到一条 Jira 需求 → 产出完整 mockup + UX 交付物的标准流程。每一步对应已有规则的入口；本节是 top-level overview，细节查对应规则真源。

```
[Jira 需求 FB-xxxx]
       │
       ▼
⓪  Stage 0 上游 framing —— persona + 关键 journey + 边界/异常态清单 + 数据可行性提问，
       │             **用来指导 ③ 怎么建**（不是建完才想）。US-1/2/3 都走；US-3 走 lite 版
       │             （persona + journey + 边界态清单 + 固件/数据提问即可，不必全套 discovery）。
       │             真源：`design-discovery` skill（重设计/新 persona）+ 本文件 § Stage 0.5 + F2-early。
       ▼
⓪.5 Design Quality Contract —— 轻量设计质量合同（M49）：Baseline / Delta / Semantic / Feedback Inventory / UX / Simplicity / Content
       │             先定义"哪些沿用、哪些改、同类语义用什么模式、哪些文案是唯一术语"。
       │             **用来约束 ③ 怎么生成**；⑤⑥⑦ 只验证它是否被满足。
       ▼
①  Page + Sections —— rename/新建 page，命名 `< FB-xxxx > <Title> YYYYMMDD`（M45）；
       │             page 内用 **具名 Section 组织交付物，禁散落 page**。**推荐三段式**：
       │             (a)「Context」Section = PRD + Jira + UX 卡 · (b) **BEFORE** Section · (c) **AFTER** Section；
       │             **BEFORE 与 AFTER 必须各自独立 Section**（便于 dev/QA/PM 版本对比与单独导航），
       │             Section 名带 `BEFORE` / `AFTER` 标识、与 page 对齐；两对照 section 布局须互相
       │             mirror（[`mockup-conventions.md` §I1](./mockup-conventions.md)）。**无 before/after 对比的全新页（US-1/2）单 Section 即可，不强套 BEFORE/AFTER**
       ▼
②  Jira component  —— 加 `Jira requirement` instance + FB-id setRangeHyperlink 真实 URL（M23.8）；
       │             该组件 file-local 不发布 → clone 同文件现成 instance，不 import-by-key 跨文件
       │
       ▼
③  Mockup 主体      —— Phase 0 mapping + library-first 生成（M0 / M32 / M-COLOR / M-INTEGRITY 等）
       │           （含字段 label 业务词化 M44 + cell 溢出 3 状态 M43）
       ▼
④  UX 交付说明      —— M23.0 canonical 规则卡（navy #2B2D42 + 4px #33A4FD 左 stroke + Layout A-逐行双语）
       │           段落覆盖：Why / Changes / Data / Interaction / Acceptance
       ▼
   ——— 以下 ⑤⑥⑦ = 验证 ⓪ Stage 0 的假设是否被满足（对已建产物走查；没产物没法走查）———
       ▼
⑤  设计走查 F1     —— 6-section audit（详见 `skills/design-walkthrough/SKILL.md`）
       │           输出走查 report 卡（沿用 M23 规则卡样式）
       ▼
⑥  Persona 测试 F2 —— F2-late persona simulation 跑视觉 UX 可读性
       │           （详见 `skills/persona-simulation/SKILL.md`）
       ▼
⑦  用户体验地图     —— 5-stage × 5-lens journey map（见下方"§ Stage 0.5 5-stage User Journey Map"）
       │           作为 F2-late 必产物，外化用户全链路
       ▼
⑧  规则回流         —— session 中发现的新规则 / 反模式 → `mockup-conventions.md` / `code-conventions.md` / `design-process.md`
                    不写进 AI memory；不写进 session-private 笔记；真源永远在 repo
```

#### 各步的回流真源

| 步 | 规则真源 |
|---|---|
| ⓪ Stage 0 上游 framing | `design-discovery` skill + 本文件 § Stage 0.5（5-stage journey）+ `persona-simulation` F2-early |
| ⓪.5 Design Quality Contract | 本文件 § M49（Baseline / Delta / Semantic / Feedback Inventory / UX / Simplicity / Content） |
| ① Page 关联 | [`mockup-conventions.md` M45](./mockup-conventions.md#m45--figma-page-命名规范jira-关联型-mockup) |
| ② Jira component | [`mockup-conventions.md` M23.8](./mockup-conventions.md#m238--jira-requirement-annotation-必带超链接m23-extension) |
| ③ Mockup 主体 | 按 `mockup-conventions.md` §🤖 AI 读取指引 scoped 读（起手必读段 + 触发 jump，禁全量吞；重点 M0 / M-COLOR / M-INTEGRITY / M-BIND / M29 / M32 / M35 / M43 / M44） |
| ④ UX 交付说明 | [`mockup-conventions.md` M23](./mockup-conventions.md#m23--ux-交付注释多状态交互流程图格式) |
| ⑤ 设计走查 F1 | [`skills/design-walkthrough/SKILL.md`](../../skills/design-walkthrough/SKILL.md) + 本文件 § Stage 0.5 |
| ⑥ Persona F2 | [`skills/persona-simulation/SKILL.md`](../../skills/persona-simulation/SKILL.md) + 本文件 § Stage 0.5 |
| ⑦ 用户体验地图 | 本文件 § Stage 0.5 "5-stage User Journey Map" |
| ⑧ 规则回流 | [`AGENTS.md` Mockup Write Gate](../../AGENTS.md#mockup-write-gateTVU-产品-Figma-写操作-mandatory) + 本文件 |

#### ⑤ 设计走查 F1 的走查维度 — F1.6 Componentization Compliance（2026-07-01 新增）

F1 走查的既有 6-section audit（详见 [`skills/design-walkthrough/SKILL.md`](../../skills/design-walkthrough/SKILL.md)）之外，新增一条固定走查维度 **F1.6 Componentization Compliance**——验证 [`mockup-conventions.md` M36 / M36.1](./mockup-conventions.md#m361--componentization-discipline-2-instances-必做-file-local-component前期评估--设计执行--走查验证-2026-07-01-新增)"≥2 次模块必做 file-local component"在**走查阶段**被真正落实（M36.1 Phase 3 的落点）：

1. **识别 ≥2 次模块**：查出交付中所有出现 ≥2 次的 UI 模块，列成表（对齐 M0 mapping 的「可重复性」评估列）。
2. **验证已抽组件**：每个 ≥2 次模块必须已是 file-local component（`MicroApp <Product> <Module>`），非平铺独立 frame / 各自 clone。
3. **验证 instance 同源**：所有 instance 引自**同一** component，无版本分裂（不能有的改过、有的没改）。
4. **删 superseded clone**：清理仍残留的旧平铺 clone，收口到"同一语义物只剩一套 component + 其 instances"。

> 缺口来源：componentization 常在设计中被拖到"回头再抽"、走查又无检查项兜底，导致平铺 clone 混进交付（引用档 B 还原实测：Studio Overview 的 KPI ×4 / Quick actions ×3 平铺独立 frame，走查才发现补做）。F1.6 是 M36.1 三段闭环的走查兜底。

#### 跳步规则

- **US-5.S 微改**（单元素 + 单属性，比 US-5 更轻）— 2026-06-12 新增：同时满足 ①只改 1 个 element 的单个属性（图标实例 / 单色 / 单行文案 / 单 token）②不动布局、不加新交互、不加新 state ③不引入新 element。**可跳** ⓪⑤⑥⑦ **+ 起手三道闸（M48 / M49 / M50）**；**必做（不可跳）**：起手显式报档（见下方决策树）→ ③ 改动按 [§交付收尾 4](#交付收尾mockup-完成后必走-2026-06-03-新增) / 本文件 L100-103 标**本次产品需求 delta**（版本对版本，非 AI 迭代轮次）→ 若涉色跑 M-COLOR 检查 → ⑧ 一行 changelog。（三闸的 US-5.S 豁免**在本跳步规则登记**；M48/M49/M50 各自的"起手强制"按本表分档读。）
- **US-5 小调整**（改文案 / 调位置 / 换颜色单点）：可跳 ⓪⑤⑥⑦，但 ①②③④⑧ 不可跳；⓪.5 走 **lite 版**（Keep / Change / Do not touch + Content，如不涉及文案则 Content 写 N/A）
- **US-6 audit only**：只跑 ⑤，结果回 ⑧
- **US-3 增量改既有页**：⓪ 走 **lite 版**（persona + journey + 边界态清单 + 固件/数据提问），其余全走
- **US-1/2 全新需求**：⓪ 走**全套** discovery，9 步全走

#### 起手自判档位（强制：每个任务开工前**显式报档 + 报依据**，不许静默归档）— 2026-06-12 新增

> AI 起手必须输出一行：「本任务判定为 **US-X**，依据：…」。判定靠下面的**客观条件**逐条打勾，不靠"感觉大小"。**判错过的实证**：FB-9398（AI 自行跳 ①⑤⑥⑧）、V4-2285/2286（AI 把该前置步骤当事后验证想缓跑）——所以分档不能赌。

```
任务进来
  ├─ 只审不改？ ───────────────────────────── 是 → US-6（只跑 ⑤ → ⑧）
  ├─ 全新产品 / 全新页？ ──────────────────── 是 → US-1/2（全 9 步 + 全套上游）
  ├─ 在既有页加 / 改 feature？ ─────────────── 是 → US-3（上游 lite，其余全走）
  └─ 小改动 → 微改三条同时满足？
        ① 只改 1 个 element 的单个属性
        ② 不动布局 / 不加新交互 / 不加新 state
        ③ 不引入新 element
        ├─ 三条全 yes 且**都确定** ─────────── US-5.S（跳 ⓪⑤⑥⑦ + 三闸）
        ├─ 是小改但三条有任一明确不满足 ────── US-5（跳 ⓪⑤⑥⑦，三闸走 lite）
        └─ 三条有任一**吃不准** ───────────── 保守兜底 → 上调 US-5（绝不赌微改跳闸）
```

**保守兜底铁律**：微改三条只要有一条无法**确定** yes，一律落 US-5（更重那档）。误判只许偏向"多做流程"，**禁止**偏向"漏环节"；为省事把任务往轻档塞 = 反模式。

#### 反模式

- ❌ 跳 ⓪ → persona / journey / 边界态只在建完后（⑤⑥⑦）才想 → 容易建错方向再返工；空态 / 冲突 / 异常态漏进交付（⑤⑥⑦ 是验证 ⓪ 假设，不是替代 ⓪ 思考）
- ❌ 跳 ⓪.5 → 基于旧版本修改时误删沿用内容；同类模块各用各的样式；新增说明 / 模块越堆越复杂；术语和按钮文案漂移
- ❌ 跳 ① → page 名 `Page 41` 永久残留，搜不到
- ❌ 不建 Section / 交付物散落 page → 多需求页并存时无法整体识别 / 移动 / 折叠；交付物**必须收进具名 Section**（2026-06-03 V4-2312 实证：AI 把 mockup 散在 page、Jira 放 Section 外，用户纠正"之前都是全包进一个 Section"。**FB-10014 细化**：当时"全包进一个 Section"的本意是别散落 page，**不是**字面只允许一个 Section——BEFORE/AFTER 仍须分属不同 Section，见下条）
- ❌ 把 **BEFORE 与 AFTER 塞进同一个 Section** → 对比方（dev / QA / PM）难以并排 review、难单独导航 / 折叠；**BEFORE 与 AFTER 必须分属不同 Section**（2026-06-15 FB-10014 实证：AI 把 BEFORE/AFTER 放进同一 Section，owner 纠正"对比方理应分开看"，并指出此问题已复发数次 → 故升为显式反模式 + 写进步骤①）
- ❌ 跳 ② → mockup 失去 Jira 反向链接
- ❌ 跳 ④ → mockup 没有 UX rationale，dev / QA 凭直觉理解
- ❌ 跳 ⑤⑥⑦ → 同 happy path 走查，长文本 / 异常态 / 多角色场景全漏
- ❌ 跳 ⑧ → 新规则只活在 AI memory，团队同事不可见 → 同类问题反复出现

#### 实证

**2026-05-27 FB-9398**：AI v1 只做了 ②③（不全）+ ④（违 M23）+ ⑦（freelance），跳 ①⑤⑥⑧ → 用户分 4 轮抓回：(1) JIRA 链接没带、Page 名没改、UX 交付没用已有规则；(2) UX panel 重叠、未用规范；(3) cell 溢出未处理、tooltip 自画；(4) 规则只活在本地 memory。本流程总览即此回流，让"完整 8 步"显式化，AI 起手 self-check 不跳步。

**2026-06-05 V4-2285/2286（Embedded Audio Routing）**：原 8 步把 persona / journey / 边界态只列在建后（⑤⑥⑦），AI 据此把它们当"建完才跑的验证"、并以"设计可能因固件变、现在跑 QA 是浪费"为由想缓跑。Owner 纠正："persona/journey 理论上设计之初就该考虑，不是事后；而且 F1/F2-late 大多不依赖固件，缓跑站不住。" 复盘确认：⑤⑥⑦ 放 ③ 之后没错（本质是对已建产物走查），错在缺一个**显式上游 ⓪ Stage 0** 来指导 ③ 怎么建。本次新增 ⓪（US-3 走 lite 版）+ 把 ⑤⑥⑦ 标注为"验证 ⓪ 假设"即此回流。

#### 交付收尾（mockup 完成后必走）— 2026-06-03 新增

1. **JIRA 回复**：
   - **先 review 后发（不擅自发送）**：JIRA 评论及任何对外沟通，**草稿先给 owner 过目、确认后才发**，不发完才告知。
   - **请 PM 确认的是 UX 设计，不是 PRD**：UX 设计师交付的是设计稿；评论里请 PM review/confirm 的对象**对外统一写「the UX design」**，**不写「mockup」也不写「confirm the PRD」**（"mockup" 偏内部术语、易被理解为草稿；PRD 是产品侧文档，非 UX 交付物）。**此措辞收敛自 FB-10014 早期的「UX design / mockup」双写**（2026-07-09 owner 拍板：对外统一 "UX design"）。
   - **FYI = dev owner ∪ 该单已评论过的人**：评论的 FYI **一定要 @ 上将实现该需求的 dev owner**（别只 @ PM），让实现方第一时间看到、便于后续转单衔接；**并把之前在该 ticket 评论过的相关方也一并 FYI**，避免漏看。**具体人员映射属项目特有，记在各 consumer 项目 `docs/decisions/`，不进本真源**（同 step 2 路由转派）。
   - 内容：评论 @PM `UX design updated — please review` + Figma **Section** 链接（inlineCard smart link）；@dev owner / 该单已评论过的相关方 **FYI**。**必用 ADF + accountId 真 mention**（markdown `@Name` 不触发通知）。Slack 名一般 = Jira 名，查不到问用户。内容从简，别堆背景（见 [`AGENTS.md` Team Comms §Jira](../../AGENTS.md)）。
   - **交付后把 Jira assign 给 dev owner**：评论发完后，将该单 assignee 从设计侧转给将实现的 dev（同一 feature 跨端拆单则各归各端 dev），让交接落到具体人、看板责任清晰。**具体人员映射属项目特有（同上路由）**。实证 2026-07-09：CPU 温度告警拆两单交付后各自 assign（LCD 单 → LCD dev / Config-T 单 → Config-T dev）。
   - **实证 2026-06-15 FB-10014**：AI ① 未经 owner 确认直接发评论 ② 措辞写成「confirm the PRD / UX」 ③ FYI 漏了待开发负责人 → owner 纠正三条："发评论前先 Review 再发"、"作为 UX 设计师请 PM 确认效果图而非 PRD"、"FYI 必带待开发负责人"。三条回流于此（具体人员映射属项目特有，留在 consumer 项目路由文档，不进本真源），后续任务复用。
2. **路由转派**：按 scope 把 ticket 转给对应 owner。**人员路由记在各 consumer 项目 `docs/decisions/`**（项目特有，不进本真源）。
3. **Feature design-record**：产出 `docs/specs/YYYY-MM-DD-<jira>-design-record.md`，模板见 [`templates/consumer-product/docs/specs/_feature-design-record.template.md`](../../templates/consumer-product/docs/specs/_feature-design-record.template.md)（顶部 v2 frontmatter + 9 段固定结构）——供追溯 / 迭代 / 其他设计师复用同一逻辑。**所有消费产品需求设计都产出此记录。** frontmatter 是需求溯源索引的数据源，见下条。
4. **Change log / 版本注释 = 产品需求维度（2026-06-04 新增）**：mockup 上的改版记录——无论是 **Figma 内的 changelog 卡**还是 **design-record 的版本段**——**只列产品需求变更**。落笔前按三类过滤：
   - ① **需求变更** → 写（用户/PRD 驱动的设计改动，如「Layer 列表 2/行 → 1/行」）
   - ② **既有行为在新设计里的复现** → **不写**（不是改动，如「Go Live 后面板锁定」本就如此，只是在新布局里重画了）
   - ③ **AI 实现过程 / 走的弯路 / 迭代轮次** → **不写进效果图**（进协作复盘 `docs/retrospects/`，不进给开发/PM 看的 mockup 注释）

   给开发 / PM 的版本管理基于**需求**，不是协作记录；效果图上的 changelog 是需求契约的一部分，掺入实现过程会误导读者。

5. **更新产品功能列表（feature changelog，2026-06-05 新增）**：把本次交付的功能记入该 consumer 产品的【产品上下文 / 功能列表】（如 MicroApps `docs/MICROAPPS_PRODUCT_CONTEXT.md` 的 feature changelog 段）——一条：app + 改版摘要 + PRD / Jira / Figma 链接。产品维度需要一处**滚动总览**，不靠翻 PRD/handoff 逐个找。**这是默认收尾步骤，用户说"收尾"即含此步，不等单独提醒。**

6. **需求溯源索引（Requirement Provenance Index，2026-07-06 新增）**：让「某需求的效果图在哪个设计里做的」可**免全局搜索**双向定位。三条纪律：
   - **两类文档带 v2 frontmatter**：`docs/specs/`（design-record）与 `docs/handoffs/`（handoff）顶部都带 frontmatter（`id`/`title`/`doc_type`/`status`/`target_release?`/`last_updated`/`sources[{type,ref,url?}]`/`figma?`）。模板见 [`_feature-design-record.template.md`](../../templates/consumer-product/docs/specs/_feature-design-record.template.md) / [`_handoff.template.md`](../../templates/consumer-product/docs/handoffs/_handoff.template.md)。
   - **source-agnostic**：主键是 `id`（稳定 slug），**不是 Jira key**——来源（Jira/Slack/Miro/裸版本号/口头）都进 `sources` typed list，`ref` 必填、`url` 可选（链接失效/私有也能靠 ref 找回）。**同一需求的 design-record 与 handoff 用同一 `id`**，索引据此归组。
   - **派生索引，不手维护**：[`build-request-index.mjs`](../../templates/consumer-product/docs/scripts/build-request-index.mjs)（零依赖 Node，scaffold 自带）扫两目录 frontmatter，生成 `docs/REQUEST-INDEX.md`（人读）+ `docs/request-index.json`（机器）。**改动任一 design-record/handoff 后跑 `node docs/scripts/build-request-index.mjs` 重生成；勿手改产物。收尾默认含此步。** AI 起手定位需求先读 `REQUEST-INDEX.md`（此约定已写进 scaffold 自带的 [`docs/README.md`](../../templates/consumer-product/docs/README.md) 「起手先读索引」段；有 `docs/FIGMA_LINKS.md` 等专用起手文档的项目亦可在其顶部复述）。
   - **实证 2026-07-06 TVU Pack**：需求来源多样（83059 是版本号 8.3 非 Jira、有的只从 Slack/Miro 提），且旧 design-record 把 Jira/Figma 散在正文只能 grep、preset-r 逻辑一度只活在 Figma 注释 → 回流本条 + 模板 frontmatter + 生成脚本。

**实证 2026-06-03 V4-2312**：AI 未用真 Jira 组件（自画 fallback）+ 交付物散落 page 不包 Section + JIRA 回复啰嗦 + 多功能无统一设计记录格式 → 用户纠正后回流本节 + M23.8 Jira 组件登记表 + design-record 模板。

**实证 2026-06-04 Graphics Insertion（1 Layer/line）**：AI 在 Figma 改版记录卡里把「8 步流程重建 / Output(PGM) 锁定 / Preview(PVW) 可编辑」等**既有行为 + 自己来回修改的过程**当成「改动」列给开发 → 用户纠正「那是你走的弯路，不是需求改动；需求改动就是右侧 Layer 从一行 2 个变成跟 Producer 里一样一行一个」→ 重写为单条需求维度。

**实证 2026-06-05 Graphics Insertion（MC-44 双预览改版）**：AI 收尾只做了 commit/push/复盘/Jira，**漏更新产品功能列表**；用户问「收尾默认有没有写进功能列表」才补。本步（§交付收尾 #5）即此回流——收尾默认含「更新产品功能列表」，不等用户提醒。

---

## UX 交付物形态 — WYSIWYG 完整界面流（非注释卡讲解）— 2026-06-09 新增

UX 交付（上方 §完整流程 步 ③④ 的产出）的**形态**必须是**浮层叠在真实 App 页上的完整界面流（WYSIWYG，所见即所得）**——把每个交互状态 / 步骤画成完整的产品界面（真实页 + 真实库组件 + 浮层 / 弹窗叠在其上），让 dev / PM 一眼看到"用户实际会看到的画面"。**不是**用一排注释卡 / Build-Scope 卡去"讲"流程。

这是 **UX 设计 vs PRD / 原型文字描述**的本质区别：PRD 用文字"描述"流程，UX mockup 用**界面本身**呈现流程。

| 形态 | 角色 | 怎么用 |
|---|---|---|
| **完整界面流（WYSIWYG）** | UX 交付**主体** | 每个状态 / 步骤一屏完整界面；浮层（popover / modal / toast）叠在真实页上——叠法见 [`figma-technical-reference.md` Q17](./figma-technical-reference.md)（append 到竖向 auto-layout 页须设 `layoutPositioning='ABSOLUTE'`）|
| **注释卡 / 规则卡 / 对比卡（M23）** | 交付**补充** | 只补 rationale / data contract / 方案对比 / 验收——**注解界面，不替代界面** |

### 反模式

- ❌ 用 "Build Scope / 流程说明" 注释卡画廊去"讲"一个本该有完整界面的流程 → reader 看不到真实画面，等于退回 PRD 文字
- ❌ 把状态流程只用文字 bullet 列在一张卡里，不画对应的完整界面屏

### 实证

**2026-06-09 BM-1047 V3 split-wallet**：AI 先用 Build Scope 注释卡"讲"token 计费流程，用户纠"这就是 UX 设计与 PRD / 原型的区别，所见即所得——直接用完整 UI 效果图画流程，不要用卡讲"。推翻注释画廊，重建 **9 屏完整界面流**（顶栏 token 菜单 / Stripe / 成功 / 失败 / 席位 Owner-Finance / 席位 Standard / 低余额告警 / Home 席位制变体）+ 浮层叠真实 App 页 + 注释卡仅补 PRD / 对比。本节即此回流。

### 规范单元 — 1 全景 + 弹窗卡（2026-06-15 精炼回流）

WYSIWYG 流程的**最小规范单元** = **1 张全景（真实 App 页满屏）+ 该状态的弹窗/浮层卡叠在其上**（ABSOLUTE）。不是"为每个浮层单独画一张脱离全景的卡"，也不是"一排注释卡讲流程"。每个交互状态 = 1 全景 + 1 浮层；role×state 等矩阵差异用注释/对比卡（M23）补充，**不替代全景**。

- **实证 2026-06-15 BM-1047 V3**：PM（Paul / Devansh, BM-1044）要求 token 余额从顶栏 chip 移入用户头像下拉。交付即「Standard Conversion 全景页 + user-icon dropdown 浮层叠其上」一屏到位，dev / PM 一眼看到真实画面；下拉的 role×state 矩阵（admin / premium / standard × healthy / low / negative / paused / no-tokens）由 Devansh spec 卡补充。

### Mirror

主要针对 **Path A（Figma mockup）**；Path B 代码生成天然 WYSIWYG（跑起来即真界面），无需此提醒。

---

## Convention Priority Hierarchy

| 级别 | 来源 | 何时引用 |
|---|---|---|
| **P0 最高** | TVU 项目级硬规则（[`AGENTS.md`](../../AGENTS.md) 硬规则 #1-#N）| 任意 TVU 相关任务 |
| **P1** | TVU consumption conventions（本文件 + path-specific conventions）| 消费 TVU 库时 |
| **P2** | `role-ux` skill UX guidance | Pre-Phase 0 / UX 判断 |
| **P3 兜底** | 通用 UX heuristics（Nielsen / WCAG / 平台惯例）| TVU 未覆盖的判断 |

高优先级胜出。TVU 未规定 → P3 兜底，**不停下追问**。

---

## M22 — User Design Intent Acknowledgment（前置 Gate）

任何 deliverable 生成前，先检测用户 brief 是否含 design direction 类语句。

**触发信号词**：`feel like` / `should feel` / `design proposal` / `direction` / `tone` / "感觉像" / "整体方向" / "调性" / "business health" / "commercial feel"

**不触发**：纯 element 清单（"加 button" / "table 加一列"）。

### 必做（任何 Phase 0 mapping 前）

1. AI 复述 user 的 design ask 为 bullet list（原话直引 + 一句话解读）
2. 每条 ask 映射到具体 deliverable decision（color / structure / element 取舍 / information hierarchy）
3. 按 ask 数量分支：
   - **小 ask（< 3 条）**：合并进 Phase 0 mapping，作为上方 "Design intent acknowledgment" 段一起对账
   - **大 ask（≥ 3 条 或 跨全局调性）**：独立 gate — 复述发给 user 确认后才进 Phase 0

### Why

User design ask 是 deliverable 视觉合同的最高优先级输入。跳过 = 把"用户想要什么"降级成"AI 觉得用户想要什么"。

### 优先级关系

**M22 > M21 > M14**：user 显式 design ask override sibling 视觉合同（M21）；override 参考输入（M14）。

---

## M48 — Startup Rule-Coverage Self-Check（起手强制 Gate）— 2026-06-05 新增

任何 mockup / 设计任务起手（**Phase 0 element-mapping 之前**），AI **必须先产出一份「本任务命中的 locked spec + active M-rule 清单」并逐条标注覆盖计划**，作为可 audit 的 deliverable——**不允许凭"我知道规则"的印象直接开建**。

### 必做（产出格式，mandatory）

| 来源 | 命中项（逐条列） | 本任务怎么遵守（一句话落地） |
|---|---|---|
| **handoff / PRD locked spec** | 如「余额=大数字+tokens 小灰」/「expanded state scrolls, height≤775」/「state-label = `frame.y−h−50`」 | … |
| **active M-rule（按场景触发）** | 编号 + 名（M1 / M23.x / M-COLOR / M-INTEGRITY §I1.1 / M32 / M46 / M47 …） | … |
| **state-completeness（首类实体全态，2026-06-15 升起手）** | 每个 first-class entity 列出本任务须覆盖的状态：CRUD / 选择(单·多) / 动作前·中·后 / 后置修改 / edge·错误（含空 / 负 / 暂停 / 无权等）——枚举清单见本文件 §State-Completeness Enumeration | … |

- **locked spec 来源** = handoff / PRD 卡 / 用户当前明确约束。
- **state-completeness 来源** = 本文件 §State-Completeness Enumeration（2026-06-15 起前移：原仅 F2-late + 体验地图必做前置，现同时作为 M48 起手清单一行——起手即枚举全态，避免建到 F2-late 才发现漏态返工；本轮 BM-1047 Devansh dropdown 即 role×state 矩阵，起手枚举可一次盘清 13 态）。
- **M-rule 来源** = [`mockup-conventions.md` §AI 读取指引 Quick Reference](./mockup-conventions.md) 按"触发条件"逐行勾选命中项（不是凭记忆）。
- 主建过程中每完成一个 frame / 区块，对照清单打勾；**交付前清单必须全绿**（未覆盖项必写 rationale）。
- **PRD 业务约束 parity（2026-06-17 新增）**：起手清单须把 PRD 的**业务约束**——**权限 / 角色矩阵**、tier 规则、可见性规则等——当 locked spec **逐条列**，并在建对应 UI（按钮可见性 / 入口归属）前对照。不止 state-completeness。**实证 BM-1047**：按单句指令建下拉按钮、没回查 PRD 权限矩阵 → Premium User（Member）误给 Manage Subscriptions、admin 混"买+分配"，整套按钮权限重构。
- **机械命中项必附 gate 输出（keystone，2026-06-17 新增）**：清单里**机械可判**的命中项（M32 库归属 / M-COLOR / M52 binding / M32.2 三件套 ①② 等）的"打勾"**必须附对应机检 gate 的 pass/fail**，不允许凭印象自填 `✅`——同 [design-walkthrough §0 机械维度证据化](../../skills/design-walkthrough/SKILL.md)。起手"勾了"≠ 已做，自我声明式 checklist 的失效根因正在此。
- **委派边界规则传递（delegation-boundary rule handoff，2026-07-09 新增）**：当把 Figma 写作 / mockup 生成**委派给 subagent** 执行时，M48 self-check 命中的每条 M-rule / locked spec **必须逐条写进 subagent 的执行 spec**（具体到「套用 M23.14 A-逐行：<要求>」这种可执行指令），并显式声明 **[M23.16](./mockup-conventions.md) 规则优先于范本**——禁止只给「复刻范本 / 参照 sibling」这类模糊指令让 subagent 自行 imitation。**实证 2026-07-09 V4-2333**：主线 M48 已列 M23.14 双语行距，但委派写 PRD 时只说「复刻范本」、没把 M23.14 具体要求带过去 → subagent 照范本印象做成被禁的「EN 整组 + ZH 整组」，用户走查抓出。根因 = 自检识别了规则、委派边界把它漏掉（「读了不执行」的委派变体）。

### Why（根因 — 两次实证）

违例的绝大多数**不是规则缺失，而是规则 / locked spec 已存在但起手没主动调用**。加再多细则都堵不住"凭印象开建"——唯一能堵的是把"核对已有规则"从隐性变成**起手强制产出物**：AI 不写清单就完不成起手，核对被外化为可 audit / 可拦截的 trace（同 [M35](./mockup-conventions.md#m35--affordance-category-search-discipline思考产物外化为强制-trace) 把思考外化为 trace 的机制）。

- **2026-06-01 BM-1047**：design-process 完整 8 步只命中 3/8，M45 / M23.8 / M23 / M23.6 / audit 全靠用户走查补。
- **2026-06-05 BM-1047 Stage 4–6**：locked spec「expanded scrolls / 余额 tokens 弱化 / 50px state-label gap」+ M23 §条件标签 z-order + figma-use resize-重置-sizing 等 **~6 处已有明文规则没遵守**，9 轮用户走查兜底。两次同一复发模式 → 抽象为本 Gate。
- **2026-06-08 V4-2285/2286 Embedded Audio Routing**：catalog 早写明「647 icons，直接用，不要 Unicode glyph 替代」+ M32 §icons 已覆盖，仍手搓 `→ Transmitter` 箭头 / `✕` 删除 / `+ Add routing`（AFTER 屏 + 状态帧 S0–S5 共 7×→ / 11×✕ / 7×+Add），用户**第三次**纠正"图标不能手搓"后批量换真组件。典型「规则已存在、起手没把 glyph 扫描列进 self-check」→ 故本 Gate 新增上方「Glyph 自查」必扫项。

### Acceptance

- [ ] 起手 deliverable 含 rule-coverage 清单（locked spec 行 + M-rule 行），非空
- [ ] 交付前清单逐条标"已覆盖"（未覆盖项写 rationale）
- [ ] handoff 记录该清单（供下次 review 反查）
- [ ] **自建件三件套（含自建产品 UI 件时必勾）**：每个自建卡 / 浮层 / 面板列明 ① 真组件（M1 / M32）② 绑 Color Variable（M-COLOR §C1）③ 复用页面 / PRD / sibling 现成措辞，三腿落地——详见 [`mockup-conventions.md` M32.2](./mockup-conventions.md)；治"自建时跳过设计系统起手检查"元根因
- [ ] **Glyph 自查（必扫项）**：交付前在**产品区**扫 Unicode 装饰字符（`→ ← ↑ ↓ ✕ × ＋ + ✓ ✔ ⚠ ▾ ▸ ●` 等），命中即 **M32 §icons 违例**——产品 UI 的图标必为库组件实例（catalog 647 icons），禁手搓 glyph。脚本式扫法：`section.findAll(n=>n.type==='TEXT')` + glyph 正则，按 parent name 区分产品区 vs 注释区（**帧外注释/PRD/journey 卡内的描述性字符不算**）。
- [ ] **字体自查（必扫项，与 Glyph 自查对称）**：交付前在**注释区**（UX 交付卡 / PRD / journey / state-note / spec / changelog 等帧外说明）扫所有 TEXT 的 `fontName.family`，∉ {`Roboto`(EN), `Noto Sans SC`(ZH)} 即 **M23 §字体规范 / M47 违例**——Figma `createText()` 默认 `Inter`，"不主动设" = 自动错（同 Glyph 是"Figma 默认值陷阱"）。**产品 mockup 本体文案豁免**（按库 instance / file-level baseline，见 [`mockup-conventions.md` §342 C4](./mockup-conventions.md)）。脚本式扫法同 Glyph，但产品区/注释区判定**方向相反**：**Glyph 罚产品区、Font 罚注释区**。
- [ ] **机械 gate（必跑）**：上述 Glyph + 字体两类不再只靠人肉扫——已落为 [`scripts/audit-mockup-typography-icon.mjs`](../../scripts/audit-mockup-typography-icon.mjs)，接进 `pnpm audit:consumer-mockup`（与 M-COLOR / M-INTEGRITY 三件套并列），pre-handoff `exit 1` 拦截。半角 `+` / `x` / `×` 因高误报不机械扫，仍靠人肉 Glyph 自查兜底（脚本 footer 已 log，no silent cap）。**综合 pre-handoff 单闸**：`pnpm audit:mockup-conformance --file <fileKey>`（[`audit-mockup-conformance.mjs`](../../scripts/audit-mockup-conformance.mjs)）一次跑全 5 个 mockup audit（typography-icon + colors + integrity + library-binding + library-origin），聚合一个 pass/fail；场景 2 增量加 `--non-blocking`（M21 优先 local 视觉合同，不全量误报 legacy）。
- [ ] **委派 spec 完整性（委派 subagent 写 Figma 时必勾）**：self-check 命中的 M-rule + locked spec 已**逐条写进委派 spec**（非「复刻范本 / 参照 sibling」模糊委派），并声明规则优先于范本（M23.16）

### 反例（命中即起手不合格，重做）

| ❌ | 后果 |
|---|---|
| "规则我都知道，直接开画" | 凭印象漏调用 → 主建后大批走查违例（本 Gate 即此回流） |
| 清单只列 M-rule 不列 locked spec | handoff/PRD 的数值型规范（字号/高度/滚动/留白）最易被跳过 |
| 清单产出了但交付前不回头打勾 | 建的过程偏离清单无人察觉 |
| 产品区图标敲 Unicode glyph（`→`/`✕`/`+`）当图标用 | M32 §icons 违例；2026-06-08 V4-2285/2286 路由列手搓 →/✕/+，用户三次纠正后批量换真组件（见上方 Glyph 自查必扫项） |
| load / 起手后先探查、看结构（`get_metadata` / `use_figma` 勘察），把"读真源 + M48"挪到探查之后 | 探查 = 动手；跳 Step 2 → 下游 M-rule jump（如 M23.14 双语行距）全部失效；2026-07-06 V4-2335 照抄 pre-规则 PRD 范本 `8805:2` 致字号/opacity/行距范式全错 + 建错文件。修法：起手第一动作 = TodoWrite 物化起手协议，探查排在读真源起手段 + 本清单之后 |
| 委派 subagent 写作时只给「复刻范本 / 参照 sibling」，没把 self-check 命中的 M-rule 逐条带进 spec | subagent 照范本印象走、绕过规则；2026-07-09 V4-2333 PRD 双语 A-逐行 被做成禁用的 EN/ZH 分组，用户走查兜底 |

---

## M49 — Design Quality Contract Gate（设计质量合同，前置 + 回归）— 2026-06-11 新增

任何产品设计 / mockup / 代码界面生成任务，在 Phase 0 mapping / 主体生成前，必须先产出一份**轻量 Design Quality Contract**。它不是额外说明卡，而是约束 deliverable 的合同：设计中按它生成，设计后按它回归。

### 机械执行入口（L3）

设计任务起手先生成 kickoff packet，填完后用同一脚本检查；未通过不得进入高保真 mockup / UI 生成：

```bash
pnpm design:kickoff --name <jira-or-feature-name>
pnpm design:kickoff --check docs/internal/_design-kickoffs/<jira-or-feature-name>.md
```

`--check` 会拦截空 `TODO`、缺 section、未勾 ready checklist、关键合同表无真实内容。它不能替代设计判断，但能强制 AI 把分散规则收束成一页可审的入口产物。

### 触发条件

**强制触发**（任一命中）：
- 用户说"基于某版本 / 在上一版上改 / 只改一部分 / 保留其他部分 / 沿用 X"
- 任务包含多个同类模块 / 多个状态 / 多个 action / 多个提示 / 多个卡片 / 多个表格列
- 用户给出设计原则或质量要求：一致性 / 可用性 / 易用性 / less is more / 简洁 / 文案统一
- 设计后走查发现问题，需要修复并防止复发

**lite 触发**：
- US-5 小调整：至少写 `Baseline + Delta + Content/N/A`
- 纯 audit-only：只补 `Semantic + UX + Content`，用于判定现有 deliverable 是否合格

### 必做（产出格式，mandatory）

#### 1. Baseline / Delta Contract

| 字段 | 必填内容 |
|---|---|
| **Source version** | 基于哪个 Figma page / frame / node / 截图 / 代码版本修改 |
| **Keep** | 必须原样沿用的区域 / 内容 / 交互 / 信息层级 |
| **Change** | 本次允许改的内容，逐项列出 |
| **Remove** | 用户明确要求删除的内容；没有明确要求则写 `None` |
| **Do not touch** | 不属于本期范围、但必须继续可见的 sibling area |

规则：`Remove` 为空时，AI 不得删除 / 隐藏 / 折叠 baseline 内容。`Do not touch` 的含义是“不 mutation”，不是“不显示”（见 § Scope Handling）。

#### 2. Semantic Pattern Contract

| 字段 | 必填内容 |
|---|---|
| **semanticRole** | 同类语义，如 destructive action / passive info / warning / editable field / status indicator |
| **instances** | 本任务里出现在哪些模块 / frame / row / card |
| **expectedPattern** | 应使用的组件、variant、icon、token、位置、交互模式 |
| **exceptions** | 不一致是否允许；允许则写原因和 owner/user ack |

规则：同一 `semanticRole` 默认必须使用同一视觉词汇。不同组件 / 样式 / 图标 / 文案若没有 exception，即为 FAIL。

#### 3. Feedback UI Inventory（反馈类控件同源清单）

任何反馈 / 通知 / 状态 / guard / hint UI（例如 success、failed、blocked、low-balance、seat added、locked）必须先拉完整 inventory，不能只做颜色 / 字体 / 链接这类属性级一致性检查。

| 字段 | 必填内容 |
|---|---|
| **feedbackState** | 具体状态 / 触发文案，如 success / failed / blocked / low-balance / seat added / locked |
| **semanticClass** | 只允许四类：toast / inline alert / modal notification / popover hint；其他类必须写 exception |
| **component** | 使用哪个库组件 / 本地既有组件 / instance；同类默认一致 |
| **widthRule** | 同一 semanticClass 的宽度规则 |
| **paddingRule** | 同一 semanticClass 的 padding / spacing 规则 |
| **iconRule** | icon 是否有、用哪个语义、位置 / 尺寸 / token |
| **titleRule** | title 是否有、何时有、字号 / weight / 语义 |
| **bodyRule** | body copy 是否有、长度 / 行数 / 截断 / 文案语气 |
| **actionPattern** | 只允许 no-action / one-action / two-action；其他必须写 exception |
| **exception** | 少数不一致的原因 + owner/user ack |

规则：同一 `semanticClass` 默认必须使用同一 component / width / padding / icon / title / body 规则；只允许 action 数量在 `no-action / one-action / two-action` 内变化。把“这个 guard alert 语义合理”当作豁免理由不合格；必须先证明它属于哪一类反馈控件，以及同类是否同源。

#### 4. UX Principle Contract

| 原则 | 必答问题 |
|---|---|
| **Consistency** | 同类对象是否同位置 / 同组件 / 同状态 / 同文案？ |
| **Usability** | 用户主路径是否清楚？关键动作是否可发现？错误 / 空态是否能继续操作？ |
| **Ease of use** | 是否减少用户记忆负担？是否避免跨区域来回找信息？ |
| **Accessibility / readability** | 层级、对比、可读性、长文本是否被处理？ |

规则：原则不能只写 "Pass"。必须给一句 evidence，例如 "3 个 destructive action 全部使用 red Button + pop confirm"。

#### 5. Simplicity Contract（Less is more）

每新增一个模块 / 卡片 / 状态 / 注释 / 浮层前，必须回答：

| 问题 | Pass 条件 |
|---|---|
| 它是否帮助用户完成当前任务？ | 是，且能说出具体任务 |
| 它是否重复了已有信息？ | 否；若重复，合并或删除 |
| 它能否用已有组件 / 状态 / 文案承载？ | 能则复用，不新增形态 |
| 它是否增加了 dev / PM / QA 理解成本？ | 不增加；若增加，必须有价值说明 |

规则：解释型装饰、重复卡片、为了“看起来完整”新增的模块默认删。Less is more 是交付物质量要求，不是视觉风格偏好。

#### 6. Content Contract

| 字段 | 必填内容 |
|---|---|
| **Concept** | 业务概念 / 状态 / action |
| **Approved wording** | 本期唯一使用的 EN / ZH 文案 |
| **Forbidden alternatives** | 不再使用的近义词 / 旧词 / AI 自创词 |
| **Component text targets** | 出现在哪些按钮、tooltip、empty state、error、table column、annotation |

规则：同一概念只允许一个词。按钮动词、状态名、错误提示、列名、tooltip 文案必须沿用页面 / PRD / sibling 现成措辞；没有现成措辞才新写。

### 设计后回归

任何设计后发现的问题，必须按下表回写，不只局部修：

| 发现的问题 | 回写到哪里 |
|---|---|
| 沿用内容丢失 / 隐藏 / 被重排 | Baseline / Delta Contract |
| 同类模块样式不一致 | Semantic Pattern Contract |
| 反馈类 UI 形态各画各的 / 合理化为“语义不同” | Feedback UI Inventory |
| 主路径难用 / 找不到入口 / 状态不可理解 | UX Principle Contract |
| 模块过多 / 注释过多 / 信息重复 | Simplicity Contract |
| 文案漂移 / 同义词混用 | Content Contract |

修复后必须重新跑同一类回归：看当前问题已修、且没有破坏 `Keep` / `Do not touch` 区域。

### Acceptance

- [ ] 已生成并填写 `design:kickoff` packet；`pnpm design:kickoff --check <packet>` 通过
- [ ] 主体生成前已产出 Design Quality Contract（full 或 lite，按触发条件）
- [ ] `Remove` 为空时，无 baseline 内容被删除 / 隐藏 / 折叠
- [ ] 每个同类 `semanticRole` 都有 expectedPattern；不同表达均有 exception + rationale
- [ ] 反馈类 UI 已先拉 inventory；每个 state 已归类到 toast / inline alert / modal notification / popover hint
- [ ] 同一反馈 `semanticClass` 的 component / width / padding / icon / title / body 规则一致；action 仅在 no-action / one-action / two-action 内变化
- [ ] 新增模块 / 注释 / 状态均通过 Simplicity Contract
- [ ] Content Contract 覆盖按钮、状态、tooltip、empty/error、表格列名等用户可见文案
- [ ] F1 / F2 / journey 走查报告引用本合同逐项验证，而不是只给主观 Pass

### 反例（命中即不合格）

| ❌ | 后果 |
|---|---|
| "只改 T list" 后把 R list 隐藏 / 删除 | 违反 Baseline / Delta + Scope Handling |
| 同类模块 A 用 Badge、B 用自画 chip、C 用文字色表达，仍标 Pass | 违反 Semantic Pattern Contract |
| success / failed / blocked / low-balance 分别自由画 toast、卡片、popover、guard alert，却没有反馈控件 inventory | 违反 Feedback UI Inventory |
| 为了讲清楚加 5 张说明卡，但界面本身没有变清楚 | 违反 Simplicity Contract；UX 交付主体应是 WYSIWYG 完整界面流 |
| `Delete` / `Remove` / `Stop` 混用，未声明语义差异 | 违反 Content Contract |
| 设计后发现问题，只修当前 frame，不回写合同 | 问题会在下一轮复发 |

### 实证

- **2026-05-28 TPC-628**：用户声明"本期不动 R list"，AI 误读为隐藏 R list，导致沿用内容丢失。已有 § Scope Handling 约束"不动 ≠ 不显示"；本 Gate 把 `Keep / Change / Remove / Do not touch` 前置成合同，避免靠事后提醒。
- **2026-06-08 V4-2285/2286**：同一批路由 / 删除 / 添加 affordance 中，AI 因图快手搓 glyph，后来被 M48 + mockup audit 兜住；本 Gate 要求在 semanticRole 层提前声明 expectedPattern，避免建完再扫返工。
- **2026-06-11 owner 回流**：走查曾漏掉"同类模块用了不同样式但 Pass"、"基于旧版改时沿用内容丢失"、"文案不一致"、"过度复杂不符合 Less is more"。根因不是单条 M-rule 缺失，而是缺少设计前的质量合同和设计后的回归映射。
- **2026-06-11 feedback UI 回流**：Claude 走查只做属性级一致性（颜色 / 字体 / 链接 pattern），没有把 success / failed / blocked / low-balance / seat added / locked 等反馈类 UI 拉成同源 inventory；F2 注意到某个 Case 形态不同，却用“guard alert 语义合理”合理化。根因是缺少反馈控件类级 inventory，本规则即此回流。

---

## M50 — One-Page Design Kickoff Packet（起手总控包）— 2026-06-11 新增

M50 是 M49 的**执行外壳**：把分散在 Pre-Phase 0 / M22 / M48 / M49 / M0 / M21 / M43 / F1/F2 的起手要求压成一页可审 packet。任何产品设计任务进入高保真 mockup / UI 生成前，必须先有 M50 packet。

### 机械入口

```bash
pnpm design:kickoff --name <jira-or-feature-name>
pnpm design:kickoff --check docs/internal/_design-kickoffs/<jira-or-feature-name>.md
```

### M50 必含

| Section | 作用 |
|---|---|
| Task Frame | 锁定需求 / 目标 Figma / 场景类型 / source version |
| Open Questions Gate | 一次性扫齐未决项；未答不进草稿 |
| Baseline / Delta Contract | 锁定 Keep / Change / Remove / Do not touch |
| Semantic Pattern Contract | 锁定同类语义的 expectedPattern |
| Feedback UI Inventory | 反馈 / 通知 / 状态 / guard / hint UI 先按 toast / inline alert / modal notification / popover hint 归类，再查同类同源 |
| UX / Simplicity / Content | 把一致性、可用性、Less is more、文案统一转成可验证表 |
| Component / Token / Icon Mapping | 把 M0 / M32 / M-COLOR / M35 起手证据收进一处 |
| Ready Check | 所有起手项勾完才允许进入高保真 |
| Regression Snapshot | 给 M51 记录中途变更 / 设计后问题 |

### Acceptance

- [ ] 起手 packet 由 `pnpm design:kickoff` 生成，不手写自由格式
- [ ] `pnpm design:kickoff --check <packet>` 通过
- [ ] 未通过 check 不准说 "ready for design / ready for walkthrough / ready for handoff"

---

## M51 — Change Control + Regression Snapshot（变更控制 + 回归快照）— 2026-06-11 新增

任何设计中途变更、用户纠正、设计后走查问题，都不能只局部修 frame；必须更新 M50 packet 的 `Regression Snapshot`，说明改动回写到了哪份合同，并重新检查未破坏 baseline。

### 触发条件

- 用户说"不是这样 / 这里要沿用旧版 / 这个太复杂 / 文案不一致 / 这里应该同样式"
- F1 / F2 / journey / 人工走查发现问题
- AI 自己发现当前设计与 M49 contract 冲突
- 中途新增 / 删除 / 合并模块、状态、文案、组件模式

### 必做

| 字段 | 必填 |
|---|---|
| Finding / change | 发现的问题或中途变更 |
| Contract section updated | 回写到 Baseline / Semantic / UX / Simplicity / Content / Component mapping 哪一段 |
| Regression result | Keep 是否仍在；Do not touch 是否未动；同类语义是否一致；文案是否统一 |

### Acceptance

- [ ] 每个 post-design finding 都在 Regression Snapshot 有一行
- [ ] 每个中途 scope / 文案 / pattern 变化都更新原合同，而不是只改可视 frame
- [ ] 修复后重跑 `pnpm design:kickoff --check <packet>`；若仍失败，不进入 handoff

---

## Pre-Phase 0：Product Definition Gate

**触发条件**：用户给的是高层产品 / 页面 brief，element 未列出。

**进入时同步 load `role-ux` skill** — Pre-Phase 0 内的功能假设 / UX flow 提案带上 role-ux 的判断、直播行业惯例、a11y、中英双语文案 discipline。

**不触发**：用户已给完整 element 清单 / 已有 handoff 定义 scope / artifact→deliverable mirror 任务。

### Step A — Intake Gate（3 输入收集，mandatory）

任何消费产品 mockup 任务起手第一步：**先收齐 3 项输入**，再进 Step B。

| # | 项 | 必填 | 说明 |
|---|---|---|---|
| 1 | 参考链接 / 图片 / 文件 | 可选 | 竞品链接、截图、PRD 草稿、Notion / Jira 等任意组合 |
| 2 | 修改到目标 Figma 链接 | **必填** | 完整 `figma.com/design/<fileKey>/...?node-id=<id>` URL，含 node-id 最佳 |
| 3 | 功能需求 | **必填** | 一句话目标 + 关键 user story / 场景 |
| 4 | **当前硬件 / 系统架构 context** | **必填**（产品 / 硬件特性类需求）| 当前实际硬件配置 / 模块数 / 现有功能映射；任务文字（Jira description / brief）里出现"second X" / "third Y" / "extend Z" 等措辞时**强制 ask 用户当前 X / Y / Z 实际是什么状态**，不准凭文字字面推断。一句话锚定"在啥基础上做"。 |

**反模式**：
- 用户只给一句"做个 X 页面"就直接进 5 步流程 → 缺 Figma 落点 + 缺验收锚 → PRD 漂浮在对话里。
- **凭 Jira description 文字字面推断硬件架构**——如把"reuse second internal WiFi module"直推为"硬件有 2 个 WiFi 模块"，实际可能是"Hotspot 模块可切换为 WiFi 客户端"。**实证**：2026-06-01 V4-1865 v1 整轮按错架构画，v2 用户纠正后重做全部 frame。

**输入 #4 的 ask 模板**（产品 / 硬件类需求触发）：
```
开画前确认当前架构 — 一句话答即可：
- 当前 [被改部件] 实际是怎么工作的？（多少个 / 什么状态 / 哪几个）
- 本次需求改变了什么？（拓展 / 替换 / 模式切换 / etc）
```

### Step A.1 · Parent ticket comment thread read（Jira-derived task mandatory）— 2026-06-02 新增

任何由 Jira ticket 触发的 mockup / code 任务，**必须读完 ticket 的完整评论链**（不只 description），并且若 ticket 是从 parent ticket 复制而来（如 V4-* / FB-* / TM3-* / TPC-* 等 cross-project linkage），**必须沿 issuelinks 追到 parent ticket 读完它的全部评论链**。

#### 触发

- 任务 input 含 Jira issue key（V4-/ FB-/ TM3-/ TPC-/ MC- 等）
- ticket description 注明 "Copied from X" / "Source ticket: X" / 含 `<inlineCard>` 引用其他 issue
- ticket `issuelinks.outwardIssue` / `inwardIssue` 非空 → 必读所有 linked tickets 的评论链

#### 为什么必读 parent 评论链

- **V4-* / TM3-* 等工程 ticket 通常从 FB-\* (Feature Backlog) 复制**，复制时**只复制 description，不复制 FB 评论链**
- FB 评论链承载**架构 clarification / 范围讨论 / 边界 case 决策 / 关联模块约束** —— 仅读 description 等于丢失 80% 上下文
- 工程 ticket 内可能只 @ 工程团队，**FB 内的 PM / stakeholder 讨论是另一条线**——双线汇合才是完整 context

#### Acceptance（Pre-Phase 0 自检）

- [ ] 已用 Jira API / MCP 读了 task ticket 完整评论 (`fields: ["comment"]` 全量)
- [ ] 已枚举 `issuelinks` + 沿 outwardIssue / inwardIssue 读完所有 linked ticket 评论
- [ ] 评论链发现的新 context 显式登记进 PRD 草稿（Step B），含 stakeholder 决策 / open question / 跨 ticket 关联约束
- [ ] 评论链与 ticket description 冲突时**显式标记冲突**给用户拍板，不擅自选一边

#### 反模式

- ❌ 只读 V4-* description 就开画 → 丢失 FB-* 评论里的范围扩展 / 架构 clarification
- ❌ 读 V4-* 评论但跳过 FB-* 评论 → 同上
- ❌ "我有 description 了，应该够" → 是 description 不够，是 description 永远不够

#### 实证

**2026-06-01 V4-1865 mockup**：v1 起手只读 V4-1865 description "Reuse second internal WiFi module"，**没读 parent FB-7775 评论链**。错过 3 条关键 context：
1. **2025-07-07** Trevor: "I don't think we have a second internal WiFi module. Where did you hear that?" — 架构早被 Trevor 质疑
2. **2025-10-28** Joshua: "Are you saying you want to disable HotSpot and turn it into a second WiFi?" — 真正架构 v2 才被用户纠正出来；FB 里早确认过
3. **2025-10-29** Trevor: "We can add the toggle on the touchscreen for the users to switch" — LCD 触屏也要加 toggle；handoff 留作 open question，FB 里早拍板

漏读这 3 条造成 v1 整轮按错架构画 + v2 重做 + 后续多轮 walkthrough。**根因不是规则缺失，是漏读 FB 评论链**——本规则即此回流。

#### 工具

```bash
# 用 Jira MCP 拉评论 + linked issues
mcp__claude_ai_Atlassian__getJiraIssue \
  --issueIdOrKey V4-1865 \
  --fields '["summary", "description", "comment", "issuelinks"]'

# 然后沿 issuelinks.outwardIssue.key 追到 parent (e.g. FB-7775)
mcp__claude_ai_Atlassian__getJiraIssue \
  --issueIdOrKey FB-7775 \
  --fields '["summary", "comment"]'
```

#### Mirror

适用于 mockup + code 两路径。`tvu-design-mockup` skill / `tvu-design-code` skill 起手协议都纳入本步。

---

### Step B — PRD 起草 + 写入目标 Figma

**⚠️ 写入前先勘察（Discovery-before-create · 2026-06-16 回流 · 硬规则）**：任何把 PRD / section / 新版本写进 Figma 前，**先只读勘察文件**，按以下三问决定，跳过任一 = 协议违反：
1. **更新 vs 新建**：按名搜文件内已有的 PRD / Spec / 同语义 section（如 `UX · <feature> Spec` / `PRD - <页面>`）——**命中则更新那一个，不新建第二份**。
2. **相对定位**：新版本 / 区块按**现有排布**相对落位（如版本纵向叠 → 新版接最后一版正下方），不凭空挑空白坐标，也不让 subagent 自己挑。
3. **主题 / 样式对齐**：新件主题（明 / 暗模式）+ 标题层级 / 间距 / 命名，**取同类现有件做参照**，不另起一套。

**Acceptance**：
- [ ] 写入前有一次只读勘察（搜过同类件 + 看过版本排布 + 参照过现有样式）
- [ ] 已有同类 PRD / Spec → 更新它而非新建第二份
- [ ] dispatch subagent 写 Figma 时，prompt 显式含「先勘察现有同类件、定更新 vs 新建 + 相对定位 + 主题对齐」，不只说「新建」

**实证 2026-06-16 BM-1047**：AI 直接新建 PRD frame + 新 section 写定稿 PRD，未发现文件里已有正版 PRD `4742:85`（深色、页面左侧）→ 三连错：①新建而非更新 ②放 y20000 离同页 V3 很远 ③浅色不符深色模式。用户连环追问后全返工（删新建 + 移位 + 改样式）。根因 = 创建前未勘察现有资产——figma-use Rule 9 / 资源发现规则已存，但只覆盖**库组件**，未覆盖 **PRD / section / 版本制品**，本条补此缺口。

收齐 3 输入后：

1. **AI 整理 PRD 草稿**（中英双语 UX 说明样式）发到对话里。**PRD 只含需求侧内容**，结构：
   ```
   ## <页面名> / <Page Name>
   ### 需求来源 Source — JIRA（用 Jira 组件嵌入）/ Slack / Miro / 邮件 等：标类型 + 超链接（无链接则贴图/文字）。**须列全需求链上所有相关 ticket（客户 `SEC-*` / 功能 `FB-*` / 开发 `V4-*` 等，以 Jira issuelinks 核全无遗漏），每个 ticket ID + Slack 等外链都 `setRangeHyperlink` 可点击（禁纯文本 ID）；后续新增关联 Jira / Slack 时 update 必须回补 —— 详 `mockup-conventions.md` §M23.8.1**
   ### 需求背景 Background — 为什么做（中英）
   ### 现状 Current State — 改之前的样子（做版本前后对比基线）
   ### 功能需求 Requirements — 本次要做什么（中英）
   ### 验收标准 Acceptance — 怎么算完成
   ### 优先级 & 排期 Priority & Timeline
   ```
   **设计内容不进 PRD**：候选组件映射、Canonical Terms、元素/连接的展示方式、视觉规格等**下沉到 Phase 0 (M0) + 设计稿**，不混进 PRD frame。**实证 2026-06-15 FB-10014**：owner 纠正"PRD 只说清需求背景 + 本次功能需求即可，怎么会把候选组件 / Canonical Terms / 连接清单 / 非目标这些设计内容塞进 PRD"。
2. ⏸ **Gate A**：用户确认 PRD 文本无误（可多轮迭代）
3. **AI 写入目标 Figma**（加载 `figma-use` skill）：
   - **落位约定**：在目标 frame **左侧** 创建独立 frame，命名 `PRD - <页面名>`，宽 **680px**（默认；双语 A-逐行 正文需要更宽，400px 太窄致频繁换行——2026-07-09 V4-2333 回流。若同文件已有 sibling PRD，优先对齐其宽度），Auto Layout vertical
   - 样式沿用 TVU 既有 UX 说明 frame 范式（标题层级 / 段落 / 双语并列）
   - 写完报告 frame node 链接给用户
4. ⏸ **Gate B**：用户确认 Figma 上 PRD frame OK，才进 Step C

**Why PRD 上 Figma**：PRD 固化在设计文件而非对话里 → 跨 session 可查 / 跨人可分享 / 设计交付 + 产品 spec 同位置；中英双语保证 TVU 全球团队可读。

#### Canonical Terms Discipline（2026-06-02 新增）

**设计阶段必产出 Canonical Terms 表**（Phase 0 / 与设计稿同处，**不放进 PRD frame**——PRD 只含需求）—— 反复出现的核心概念每个锚定 **1 个 EN term + 1 个 ZH term**，全 mockup（radio option / hint 文案 / spec card / state label / dev handoff doc）必严格 reference 这张表，**禁止同概念用 synonym 漂移**。

**表结构**：

| Concept | EN canonical | ZH canonical | 不准用的同义词 |
|---|---|---|---|
| Hotspot 模块切到 WLAN 客户端身份 | `WLAN client` | `WLAN 客户端` | ❌ WiFi receiver / WLAN receiver / WiFi 接收器 |
| WiFi 段（Network 页内 section）| `WiFi section` | `WiFi 段` | ❌ WLAN section / WiFi 区 |
| pack 内置 WiFi 模块 | `Onboard WiFi` | `Onboard WiFi`（不译）| ❌ built-in WiFi / 内置 WiFi |

（以上是 V4-1865 实证；每个 task 起手按自身概念列表）

**Acceptance**：
- [ ] 设计阶段（Phase 0，非 PRD frame），Canonical Terms 表 ≥ 3 行（核心概念至少 3 个）
- [ ] 所有 mockup 文本（radio option / hint / state label / spec card）grep 一遍，无表外同义词
- [ ] handoff doc 复用同一张表，dev 看 mockup 与 doc 术语 1:1

**反例 — 2026-06-01 V4-1865**：Trevor approved radio 文案 "Acts as a second WLAN client"（"WLAN client"），但我自己写 F5 hint 时用 "Module is now acting as a WiFi receiver"（"WiFi receiver"）+ PRD §2 "additional WLAN receivers" / "WLAN 接收器"。同一概念 3 种不同 term 漂移。用户 walkthrough v6 抓"Client 和 Receiver 这两个措辞为什么不一样"。修法：所有 receiver → client / 接收器 → 客户端 + 本规则即此回流。

**Why**：mockup 是 dev / QA / PM 跨角色共读契约。同一概念多 term = 视觉上看似不同事物 → 实现时 dev 可能误造两个字段 / 文档里 PM 解释吵 1 小时。Canonical Terms 表是**一次锚定，全 session 通用**的 cross-frame 一致性保险。

**Mirror**：适用 mockup + code 两路径——code-side R-rules 同样 reference PRD 的 Canonical Terms 表，组件 prop 命名 / API 字段 / docstring 都用同 term。

#### No Open Questions in Deliverables（2026-06-02 新增）

**PRD / UX 交付卡 / spec card / handoff doc 等任何 "已交付" 的产物，禁止包含 open questions / TBD / 待 confirm / "待 PM 拍板" / "需 ask Danner" 等未决项**。Open questions 是 **Pre-Phase 0 Step A 阶段的事**，必须在交付前由用户回答完毕。

**适用范围**：
- PRD card / PRD frame
- M23 UX delivery card 所有段（Why / Changes / Mode transitions / Acceptance / 等）
- mockup frame 内嵌注释
- handoff doc 主体段（"Open scope item" 段是例外，见下"允许例外"）

**反模式 wording 黑名单**：
- ❌ `TBD` / `待 confirm` / `待 PM 拍板` / `TODO` / `?` 单字 / `(?)` 不确定标记
- ❌ "Open questions" / "待 confirm 项" / "未决问题" 作为 section heading
- ❌ "可能要 X" / "或许 Y" / "...?" 反问 / "需进一步讨论" / "TBD with X"

**允许例外**（必须显式标注，不混进契约段）：
- ✅ handoff doc 末尾独立 `## Open scope items` 段（**仅** dev / PM 待办追踪用，不影响主体 spec）
- ✅ Jira ticket 评论区（讨论 = open questions 的合法去处）
- ✅ Slack 频道（实时讨论）
- ✅ ad-hoc 笔记 / Notion / 单独 1:1 邮件

**起手 ask 用户 gate（Pre-Phase 0 Step A 必走）**：

PRD 草稿写完之前，AI 必须 **把所有可能的 open questions 一次性扫齐发问**：

```
开画前还要 confirm 这 N 个问题（一句话答即可）：
1. [Q1]?
2. [Q2]?
...
等你 ack 完所有问题，再起 PRD 草稿。
```

⏸ **Gate**：用户必须明确回答 / 拍板每个问题，AI 才能进入 Step B PRD 草稿。**禁止**用户没拍板就写"TBD"绕过。

**反例 — 2026-06-01 V4-1865**：
- v4 Hotspot UX 卡 §7 "Open questions & 待 confirm 项" 段含 4 条 unresolved 项（bonding 行为 / SSID 冲突 / USB 兼容 list / toast 文案）
- v6 §Mode transitions 末尾仍藏 "Toast wording TBD with PM" 一行
- 用户 walkthrough v7 抓"PRD 里不要包含开放性问题，分析需求时让用户回答"
- 修法：删 §7 / 删 §Mode transitions 末尾 TBD 行；用户必须在 Step A 阶段一次性回答这 4 问，AI 才能进 PRD 草稿

**Why**：交付物（PRD / UX 卡 / spec）是**契约**，不是**讨论稿**。Open questions 混进契约的后果：
- Dev 把"TBD"当真，硬实现一个版本，PM 走查时再翻案 → 返工
- QA 把"待 confirm"项漏到 test plan 外 → 上线后才暴露
- 跨部门 onboarding 看不懂"待 PM 拍板"指代谁、什么状态 → 项目知识黑箱

Open questions 的正确去处 = **discussion forum（Jira / Slack）**，与契约文档语义隔离。

**Mirror**：适用 mockup + code 两路径——code spec / API doc / handoff README 同样禁止 open questions / TBD。`mockup-conventions.md M23.11` Scope Discipline 已有"tangential 内容禁止"原则，本规则是其专项扩展（具体到 open questions 类内容）。

---

### Step C — 5 步流程（两个用户 gate，原有内容）

1. AI 提功能假设清单（核心 MVP + 增值，条数按产品复杂度自决）
2. ⏸ **Gate 1**：用户校功能假设，确认 MVP scope 后才进 Step 3
3. AI 提 UX flow 草稿（bullet list；复杂产品升级 ASCII / Mermaid）
4. ⏸ **Gate 2**：用户校 UX flow，确认骨架后才进 Step 5
5. AI 逐 frame/page 拆 element → 进 Phase 0

### Why

高层 brief 跳过 Pre-Phase 0 → element 都对但产品逻辑空洞。Step A/B 把"做什么 + 在哪做"显式锚定，Step C 两个 gate 把产品决策权显式还给用户，AI 做提案辅助而不是越权决定产品内容。

---

## Stage 0.5 — Pre-Design Validation（discovery 完成后、Phase 0 前）

design-discovery 产出 6 项 deliverable 后，进入两项前置验证。**两项均通过才进 Phase 0**。

### 数据可行性 Audit

**触发条件**：design 含 derived metric / chart / 数据展示 element。

见 design-discovery § 3.5——audit 在 discovery session 内完成，结论随 discovery deliverable 一并产出。已确认 feature list 经数据 audit 后才是 Stage 0.5 的合法输入。

**Why**：feature 设计前不确认数据可行性 = 反模式（实证：2026-05-11 SaaS Dashboard Driver attribution + Forecast 在 build 后才被 drop，成本远高于 discovery 阶段剔除）。

### F2-early — IA + Feature List Persona 验证

**输入**：discovery 产出的 IA 层级 + feature list + personas
**触发词**：`discovery done` / "走查 IA" → 触发 design-qa-loop Phase 1
**详见**：`~/.claude/agents/persona-simulation.md` § F2-early

F2-early 找出 IA 结构或 feature 缺口 → 补 feature / 调 IA → 再 F2-early verify → 直到无 🔴 缺口 → 进 Phase 0。

**Why**：IA 和 feature list 的错误在 Phase 0 之前修，成本远低于 post-mockup 修。

### User Journey Map — Jira mockup 标准交付卡（设计阶段必产）+ F2-late 走查复用 — 2026-05-27；2026-07-09 owner 升为标准交付卡

> **2026-07-09 owner 回流（升为一等交付物）**：User Journey Map 不再只是 F2-late 走查产物——它是**需求设计的一等交付卡**。**每个 Jira-linked mockup 必须随 PRD / UX Delivery 卡一并产出 Journey Map 卡**（用本节 canonical 5-stage 格式），**设计阶段即建**：禁走查时才补、禁临时随机生成、**禁只做一个 surface 漏另一个**。放置：交付集内、UX Delivery 卡正下方或同列。实证 2026-07-09 V4-2335/V4-2356（CPU 温度告警双端）：LCD 生成了 Journey、Config-T 漏了——根因是激活层没把 Journey 列进标准交付清单 → 本次回流同步补进 §6-JIRA 交付集（SKILL.md）+ M23 卡族 + jump 表（mockup-conventions.md）。

F2-late persona simulation 走查时**必产出 5-stage × 5-lens user journey map** 作为可视化交付物，外化用户从认知到排障的全链路触点 + 痛点 + 机会点。

#### ⚠️ State-Completeness Enumeration（F2-late + 体验地图 必做前置，2026-06-04 新增；2026-06-15 起亦为 M48 起手清单强制一行）

journey map / 体验地图**不能只画 happy-path 旅程**——必须先做一遍**状态完备性枚举**，把产品的**全生命周期状态 + 转换 + edge/错误态**列全，再据此检查 mockup 是否每个状态都有交付表达。**漏状态 = 交付缺陷**，不是"以后再补"。

**枚举清单（每个 first-class entity 必过）**：
1. **CRUD 全态**：Create / Read / Edit(Update) / Delete 每项都有显式 mockup 落点或 state diagram（参 M-LIFECYCLE-CRUD）
2. **选择/多选态**：单选 / 多选 / 全不选 的交互与视觉
3. **核心动作前后态**：关键操作（如 take / apply / cut / publish）的**前态 → 中间态 → 后态**，含触发条件
4. **后置修改态**：操作生效后（如推流/上线后）如何**修改 / 撤销 / 切换**
5. **edge / 错误态**：空数据 / 断流 / 冲突 / 二次确认 / 失败回滚

**Acceptance**：
- [ ] 枚举清单逐项标 ✅有图 / 🟡注释说明 / 🔴缺失；🔴 项必须在 report 顶部列为 priority gap
- [ ] 体验地图的 Pain Points lens 必含"哪些状态当前 mockup 未表达"
- [ ] 不允许只交"happy-path 旅程描述"当 journey map 通过

**反例 — 2026-06-04 Graphics Insertion MC-44**：体验地图做成 6 段描述性 happy-path 旅程，F2 只查视觉可读性，**完全没枚举状态空间** → Input/建/编辑/选(单多)Layer→PVW→PGM→推流后改切 等大量交互状态全缺失却"走查通过"。用户抓"这么多流程缺失，为什么用体验地图检查竟没发现"。根因：把 journey map 当文档而非 gap-finding 审计；F1 虽抓到 1 条 CRUD-Update gap 但没扩成完整枚举。本规则即此回流。

#### 标准 5 阶段（按业务通用顺序）

| Stage | 含义 |
|---|---|
| **1. Awareness** | 用户首次接触功能 / 入口；建立认知 |
| **2. Consideration** | 用户决定要不要用 / 在多个选项之间筛选 |
| **3. Pairing / Onboarding** | 用户首次执行操作 / 接入数据 / 完成配置 |
| **4. Daily Ops** | 日常使用 / 巡检 / 重复任务 |
| **5. Troubleshoot** | 异常排障 / 跨工具协作 / escalation |

**业务可重命名 Stage**（保持 5 段不变）：
- 内容创作类：Awareness → Plan → Create → Publish → Engage
- 售前类：Awareness → Inquiry → Demo → Negotiate → Close
- 运维类（默认）：Awareness → Consideration → Pairing → Daily Ops → Troubleshoot

#### 标准 5 个 Lens（每 Stage 必答）

| Lens | 答什么 |
|---|---|
| **Actions** | 用户在该 Stage 实际做什么操作？（动词为主） |
| **Touchpoints** | 经过哪些产品入口 / 页面 / 弹窗 / 工具？ |
| **Thoughts** | 用户脑内独白（用户原话感）："这台设备到底在哪个区？" |
| **Pain Points** | 现状什么地方卡？什么信息缺？什么操作冗余？ |
| **Opportunities** | 本期 mockup ✅ 命中 / 🟡 下一期 / 🔴 未覆盖 |

#### 输出格式（Figma + 文档双形态）

**Figma 端**：用 M23.0 canonical 规则卡（navy 底 + 4px 蓝左 stroke），bullet 列举每 Stage × 每 Lens；或用 5×5 表格（Stage 顶行 / Lens 左列）。

**文档端（如果走查 report 文档化）**：

```markdown
## User Journey Map — <Feature Name>

| Lens \ Stage | 1. Awareness | 2. Consideration | 3. Pairing | 4. Daily Ops | 5. Troubleshoot |
|---|---|---|---|---|---|
| Actions       | ...          | ...               | ...         | ...           | ...              |
| Touchpoints   | ...          | ...               | ...         | ...           | ...              |
| Thoughts      | "..."        | "..."             | "..."       | "..."         | "..."            |
| Pain Points   | ...          | ...               | ...         | ...           | ...              |
| Opportunities | ✅ / 🟡 / 🔴 | ...               | ...         | ...           | ...              |
```

#### Personas × Journey 矩阵

走查至少跑 **2-3 个不同 Persona**（参考 `~/.claude/agents/persona-simulation.md` 推荐的 TVU 默认 persona 集：SRE / PM / L2 Support / CFO 等）。**每个 Persona 跑一遍 5-stage journey**，命中点 / 未覆盖点分别标注。

#### Acceptance（F2-late 验收）

- [ ] 至少 2 personas × 5 stages × 5 lenses 全覆盖
- [ ] 每 Stage 至少 1 个 ✅ 本期命中点
- [ ] 至少 1 个 🟡 下一期候选（避免 happy-path bias）
- [ ] 长文本 / 异常态 / 跨页面跳转场景至少出现在 Pain Points 或 Touchpoints 一次

#### Why

Persona simulation 不画 journey map = 走查只看单帧 happy path，跨阶段断裂感（如 Awareness 看到 / Pairing 又看不到 / Troubleshoot 跨工具丢失上下文）永远暴露不出来。Journey map 把"时间维度"显式化，是 F2-late 的核心交付物，不是 nice-to-have。

#### 实证

**2026-05-27 FB-9398**：v1 走查时只在 mockup 边上画了笼统 "F1 + Persona" 卡，缺 5-stage × 5-lens 表 → 用户在反馈 #2 里要求"角色用户测试（应该包含完整的用户体验地图）"。v2 补完整 5×5 矩阵 → 用户认可。本规则即此回流。

### Field-Length Distribution 声明（UX-side 镜像 [M43](./mockup-conventions.md#m43--constrained-cell-text-overflow-wrap-vs-ellipsis--hover-reveal)）— 2026-05-27 新增

PRD / discovery 阶段引入**任一新字段**展示到 fixed-width 容器（table cell / chip / card title / etc.）时，UX 必须在进 Phase 0 前**显式声明**：

| 维度 | 必答项 |
|---|---|
| **典型长度** | p50 字符数（含中英） |
| **p95 长度** | 95 分位长度 — 决定容器宽度下限 |
| **最长理论值** | enum 全集最长 / 自由文本最大长度 |
| **可复制语义** | 是否 ID / IP / URL 等需保留完整给用户复制？ → 走 M29 Form 1（hug + copy icon），**不走** M43 ellipsis |
| **截断业务影响** | 用户因看不全而误判 → 必须配 hover tooltip + 长文本 sample；纯展示性 → ellipsis 即可 |

**触发对话模板**：
> "新字段 `<name>` 的长度分布是？(p50 / p95 / max) 是否可复制？长文本截断会不会影响业务判断？"

**为什么前置到 Stage 0.5**：等到 mockup 画完才问"截断怎么办"，每个 mockup 都要补 3 状态 frame + 找 dev 补 truncation detection。Stage 0.5 一句话明确字段语义，下游 mockup / code / persona simulation 全部沿用。

**Persona simulation 联动**：F2-late 走查时**必检查长文本场景下的 journey**，不只跑短文本 happy path。典型 anti-pattern：用户因 cell 截断看不全 region 名 → 切窗到详情页验证 → journey 断裂。

---

## Phase 0：Element-to-Source Mapping（前置硬规则）

多 element 任务（**≥ 3 个 element**）**必须**在生成 deliverable 之前产出 mapping table。trivial 单 element 调整可省。

### Lookup 序列（按序）

1. grep source index（path-specific：Figma catalog / code `src/canonical/` / `dist/icons/svg/`）
2. 每个 element 至少 2-3 个同义词 / casing 变体尝试
3. 仍 miss → path-specific 深度搜索（Figma MCP / 文件内 component_set）
4. 全 miss → 标注 ⚠️ 真 gap，发给用户拍板

### 输出格式（mandatory table）

| Element | Source reference | Path-specific detail | Status |
|---|---|---|---|
| top bar | `Top bar`（TVU library）| Figma key / code canonical / icon SVG | ✅ verified |
| status badge | `Badge`（TVU library）| ... | 🟡 skeleton → 需验 variants |
| （真缺件）| catalog + source 全 miss | n/a | ⚠️ 真 gap → 用户拍板 |

### 处理流程

1. AI 产出整张 table
2. 发给用户校验（gap 决策 / 🟡 验证路径）
3. 用户确认后才开始生成 deliverable
4. 生成中新发现 element → **回 Phase 0** 补行，**禁止**现场判断 "source 缺件"

### Why

前置 mapping 让所有 gap 一次暴露，用户一次决策。同时把 source catalog 系统性 exercise（🟡 skeleton 顺手升级 ✅ verified，反哺 catalog 质量）。

---

## Library-First + Evidence Discipline

任何 "source 没有 X" 的论断必须来自**实证搜索**，不能凭直觉。

1. 至少试 **2-3 个同义词 / 不同 casing** 搜索
2. 检查**所有可用 source**（path-specific：Figma catalog + library / code `dist/icons/` + `src/canonical/` + Figma MCP fallback）
3. **验证一个 sample instance** 看 variants / properties

只有所有路径都确认无结果，才能宣布 "source 缺件 → 自制候选"。

### 不构成充分证据

- "我搜了一下没看到" — 不够
- 仅 1 次负向搜索 — 不够
- 没验 sample instance variants — 不够

---

## M6 — Reusable Pattern Marking

识别到 reusable pattern（跨 frame/page 重复出现的 element 组合）时：

1. **不**自动提取到 design system 库
2. 标注 🟡 入库候选（候选名 + 预期 props / variants + 出现位置）
3. deliverable 收尾给用户候选清单
4. 用户拍板后再决定是否入库

⚠️ M6 不是 Library-First Discipline 的逃生口——合法自制候选 = 经过实证搜索后确认 source 缺件的 element。

---

## M11 — Self-audit Discipline

### M11.1 — Probe-based 自查（4 步法）

每次自查必须按 4 步走，**禁止靠肉眼"看起来对就过"**：

1. probe reference（原 deliverable / source component）的 N 个代表性元素拿数值
2. probe 自己实现的同一元素拿数值
3. 字段级 diff（geometry / fills / opacity / variable bindings / variant name / child count）
4. 任何 mismatch = bug 或刻意 deviation **必须解释**

跳过任何一步，自查不算自查。

### M11.2 — Visual Verification Discipline

- 所有视觉验收必走高分辨率截图或放大查看
- **缩略图禁止做 spec 判断**（小字号在缩图下无法判读）
- 关键属性（opacity / variable bindings / variant / dimensions）创建后必 probe 数值二次确认
- 验收截图发给用户时附 probe 关键字段值（不只截图）

### M11.3 — Inverse-question 视觉元素

对每个明显视觉 element 强制问："**这在折叠态 / 其它角色 / 其它断点下还成立吗？删掉它会有 visible 损失吗？**" 答"看不出损失" → 重新审视，可能是误植或冗余。

---

## M14 — Reference Input Adaptation（复刻前问适配性）

任何**非 spec 的参考输入**都是 input、不是 constraint：

- 原 deliverable（上一版本产物）
- 用户发的截图（数据样例 / 风格参考 / sibling snapshot）
- Competitor / market reference

复刻每个 element 前必须**双问**：

1. "这在当前需求所有状态 / 角色 / 断点下都成立吗？"
2. "这是 user 想要的 spec，还是 user 顺手给的参考？"

不成立 / 仅是参考 → 改造或删掉，**不照抄**。

### 高频被误抄字段（优先警觉）

| 字段 | 误抄场景 |
|---|---|
| **Color** | 截图当 data 参考时最易被当色板抄（2026-05-11 SaaS Dashboard chart 紫 vs 绿）|
| **Chart type** | 截图里的 chart 类型 ≠ 当前需求的 chart 类型 |
| **Layout 密度** | 截图里 card padding / gap ≠ 当前页面密度要求 |
| **Placeholder text / opacity** | 库组件 default 未评估直接保留 |

### Context 维度检查（generic 表）

复刻 element 前**必问该 element 在 reference 中 attach 到什么 context**：

| Context 维度 | Probe 方法 | Mismatch → |
|---|---|---|
| **IA level**（一级 / N 级 page）| top bar active menu / sub-nav 是否含父级返回 | 级别绑定 element 不 mirror |
| **Persona**（reference 服务谁 / new page 服务谁）| reference 的 user story → 实际 target persona | persona 不匹配的 element 重判 |
| **时间窗 / 业务状态**（live / draft / archived）| reference 的 state 标识 / status badge | state-bound element 重判 |
| **设备 / 断点**（desktop 1920 / 1440 / mobile）| reference 帧宽 + responsive variant | 断点不同的 element 重设计，不 scale-copy |
| **语言 / 本地化** | reference 的语言版本 | 文案长度差异元素重布局 |

Mismatch → 重判该 element，**不照抄**。任何未来出现的级别绑定 element 都被此 generic 维度自然覆盖，**不需要逐个加进规则**（举一反三）。

### 与既有规则关系

- **M22 > M14**：user 显式 design ask 是 spec，可正当 override 参考输入
- **M14 + M21 双层防线**：M14 防"参考输入当 spec"，M21 防"sibling 视觉合同没 probe"

### M14.1 — Icon 按 use-case 语义选，不按 name 字面匹配

库 icon 命名空间（如 TVU `icon/Arrow/*`）常并列**视觉相似但语义不同**的 variants。选 icon 必须按 **use-case 语义**，不是字面 name 匹配。

**典型陷阱（Arrow namespace）**：

| Variant | 视觉 | 语义 use-case |
|---|---|---|
| `icon/Arrow/Left_1` / `Right_1` / `Left_2` / `left_2` / `right_2` | 大箭头（fat shaft + filled head）— `_1` / `_2` 序号区分 visual variants | **Back / Return / Direction action**（如 toolbar back button）|
| `icon/Arrow/Previous` / `Next` | 小 chevron `‹ ›`（细线）| **Navigation step**（如 sidebar collapse toggle / breadcrumb / pagination prev-next） |
| `icon/Arrow/Sorting` | 上下双箭头 | **Table column sort indicator** |
| `icon/Arrow/Dropdown` | 单向 chevron-down | **Dropdown / select trigger** |
| `icon/Arrow/Double up` / `Double down` | 双 chevron 叠加 | **Expand-all / Collapse-all（如 card list 折叠按钮）** |

**Mandatory check**：

1. 用 `search_design_system` 拿到全 variants 列表后，**先看 Figma file 的 swap menu** 里 variant 命名（通常 designer 在 master 里写好语义提示），不要凭"`Left` 看上去像 `‹`"机械匹配
2. 文字命名歧义时 import 1 个 sample instance 视觉 verify

**违例 history**：2026-05-14 Plan B sidebar 折叠 toggle / 4 处 breadcrumb，第一版用 `icon/Arrow/Left` 渲染出大箭头（back-arrow 视觉）— 实际应该用 `icon/Arrow/Previous`（chevron-left 视觉）。语义错配在 6 处。Search menu 里 Previous / Next / Left / Right 并列，直接对比命名即可识别。

**Why**：工程师术语（"left arrow" → 任何指左的图标）≠ 设计师术语（`Left` = directional action，`Previous` = navigational step）。两套术语不会自动对齐 — 必须靠人主动看命名 + 视觉双重 verify（参 M24 token mapping table 同源思路）。

---

## M15 — Source 未实证不得宣告"不存在"

搜索 source 须**多 casing / 多同义词 / 至少 3 词**才能下结论：

- "Radio" 0 hit ≠ source 无 radio（实际名 `radio` 小写）
- "Tooltip" 0 hit ≠ source 无 Tooltip（实际名 `Tooltips` 复数）
- "Operation List" 0 hit ≠ source 无（实际名 `Drop down List/Select Type=Operation List`）
- **"icon/Arrow/Left / Right 未发布"** 0 search 即定论 ≠ source 无（实际 TVU UX Design System 库一直有 key `503af6b...` / `a135a51...`，2025-11 更新）— 2026-05-14 实证

1 次 negative 不够。多渠道搜索 + import sample instance 验 variants 双重验证。

### M15.1 — 继承前会话 handoff doc 的"library debt"声明，必 re-verify

继续 prior session 工作时（如 increment / retrofit / refactor），若读到 handoff doc 中含 `BRIDGE-XXX` 或 "library 未发布 / 等待补单" 类 debt claim：

- **不要** 直接信任，作为前提推进
- **必须** 重跑 `search_design_system` 多 casing 验证一次
- 若 search 找到 → handoff doc 立即纠正 + ledger entry 留痕 + 修复 mockup
- 若 search 仍 0 hit → 才能继续按 debt 处理

**Why**: 库在持续更新，prior session 的 "未发布" claim 可能已过期。stale claim 在 session 间传递就会变成"接受的事实"，永远 fallback 自画。

**违例 history**: 2026-05-14 Plan B retrofit session 信 prior session 写的 `BRIDGE-MOCKUP-003: icon/Arrow/Left / Right 未发布 → 用 Unicode ‹/›`，未 re-verify。后续用户指出库实际有 → search_design_system 1 次 hit → BRIDGE-MOCKUP-003 stale 1 个 session。

---

## M16 — Deliverable Defaults Must Be Evaluated

Source component default values = 预览用占位（dropdown 默认 "Option 1/2/3"、Button 默认 text、默认 icon、多余 variant 等）。

### 采用 source component 后必做（不是必改）

评估每项 default（placeholder text / 默认 icon / variant property）：

- 默认值**符合**当前需求 → **可保留**
- 默认值**不符**需求 → **必须 override**

### 反模式（违规）

采用 source component 后**不评估**，直接交付 placeholder 当真实内容。

### Why

区分 **"未改"（可能合理）** 和 **"未评估"（始终不合理）**。一刀切"必须改"会引出本不必要的 override，component instance 失去与 source 同步的意义。

### M16.1 — Multi-state spec mockup：默认态 + 越权态双 frame 覆盖

Spec mockup（给开发 / PM / 跨团队 ship 的设计文档，含 list / state-machine 类 component）**必须**同时含两类 frame：

| 类别 | 必须画 | 反例 |
|---|---|---|
| **规则默认态** | 体现规则约束下的默认 UX（如 accordion 默认只 selected expanded） | 只画此一类 = reader 不知 user diverge 时会怎样 |
| **User-override 态** | 体现用户主动越权后系统应当的表现（如 user 手动 expand 多个、user 全 collapse、user 触达 cap 边界） | 只画此一类 = reader 不知道默认规则是什么 |

**Why:** Spec mockup 是开发实现 reference。只画默认态 → 开发遇到 user override 场景没参考 → 自由发挥导致与规则脱节。两类必须配对出现。

**Acceptance:**
- 任何含 state-machine / interactive list 的 deliverable 至少包含 1 default + 1 override frame
- frame 名命名必含 state 字段（如 `M5 · default accordion`、`M-MultiExp · user manual expand`、`M8 · user all-collapse`），不允许只标 frame 编号
- State-label 必显式说明该 frame 是 default 还是 override（与 M22 design intent 衔接）

**实证**（2026-05-26 Video Sync Phase B）：原 spec 含 M5（默认 accordion: 1 expanded + 1 collapsed）但缺 user override 帧。用户提出 bein sports case 需 2 syncs 并行（user 主动 expand 2 个）→ 加 M-MultiExp + M8（全 collapse）两 override 帧后才完整。

---

## M21 — Existing Product Incremental Local Reuse

### 触发场景

US-3（existing product 增 / 改 / 删 feature），product 已有 working 的 local pattern / component。

**不触发**：US-1 / US-2 greenfield、artifact→deliverable mirror、US-5 trivial、US-6 audit。

### 与 Library-First 关系（不冲突，时序差）

| 时序 | scope | 优先级 |
|---|---|---|
| 视觉基线**建立期** | US-1 / US-2 greenfield | Library-First: source > file-local > 自制 |
| 基线**已建立后**增量 | US-3 existing | **M21**: existing local > source 重建 > 自制 |

### 决策树

> ⚠️ **前置 M22 check**：若 user design ask（M22）与 sibling visual contract 显式冲突 → M22 胜出，跳过第 1 步。

1. Product 已有等价 local pattern → **优先复用**
   - data / props 可适配 → 复用 + override 内容
   - 不可适配 → mirror 视觉 / 结构 shell（圆角 / padding / 标题位 / 密度），按当前需求重建 internals
2. Product 没有但 source / library 有 → 按 Library-First Discipline
3. 都没有 → 按 Library-First 例外（自制候选）

### 起手 mandatory probe — Sibling Visual Contract

US-3 进 Phase 0 前，先 probe sibling page / module 的 visual contract，每条 probe 出**数值 / keyword**：

| 维度 | Probe 方法 |
|---|---|
| Color palette | source 取 sibling 的 fills + variable bindings（主色 / accent / status token 名）|
| Component type | sibling 使用的 component 类型（chart type / card type / etc.）|
| Typography | font family / size / weight |
| Icon style | stroke vs fill / stroke width |
| 视觉密度 | card padding / gap 数值 |
| Header structure | 顶部结构 / widget 槽位置 |

probe 输出**单起一段**放 Phase 0 mapping table 上方，命名 `Sibling visual contract`。后续每个 element decision 必须 reference 这段；偏离必须**显式解释**——**user design ask（M22）是 override 唯一合法源**。

### 例外（user 显式 override）

- local component 有已知 bug 需替换
- 跨产品级 design refresh
- user 明确说"用新版替换旧 local"

**澄清 — pre-design-system 不视为 bug**：pre-design-system 时代的违反 = 合规的历史范式，增量任务继续 mirror，不做 in-place 修正。需用户显式发起独立任务。

### Why

消除"同产品同时间窗口跨页面视觉割裂"。sibling page 视觉风格是用户对产品的认知合同，新 deliverable 背离 → 产品碎片化。

### M21.1 — 建新 component 优先 clone existing functional row + mutate variant

当 existing product 内已有 functional 的 row / card / panel mockup 元素，需要为它建 component（如 component_set 含多 variant）时：

| 路径 | 适用 | 风险 |
|---|---|---|
| ✅ **Clone + Mutate**：clone 现有 functional element → mutate 派生各 variant | 默认路径 | 继承源 element 的潜在 bug（如裸 hex stroke）—— **必先过 M42 Clone Gate** |
| ❌ **From-scratch 重建** | 仅在现有 element 已被废弃 / 视觉契约要求全重时 | 视觉细节漏复刻（fill var binding / stroke direction / corner radius / shadow / 间距）—— 高频翻车 |

**Why:** Existing functional mockup 已通过 review 含正确视觉契约（layout / token binding / spacing）。Clone 自动继承这些隐性细节；from-scratch 必须人工复刻每条，漏一个就破坏视觉一致性。

**Acceptance:**
- 建 component 起手必声明："derive from `<source_element_id>`" 或 "from-scratch with rationale"
- Clone 路径必绑 M42 Clone Gate（probe brand-color paint bindings）—— 不能盲 clone 把源 bug 放大到 N variants
- From-scratch 路径必含视觉契约 probe table（M21 §"起手 mandatory probe — Sibling Visual Contract" 5 row）

**实证**（2026-05-26 Video Sync Phase B Step 2）：12 variants 全从 5 个 anchor row 派生（clone + mutate），结构正确性 99% 继承自源。但源 row 有裸 hex stroke bug → 12 variants 全部继承 → M42 Clone Gate 缺位 → 直到 walkthrough audit 才发现。

### M21.2 — Feature Iteration Color Contract（功能迭代色值合同）

> **元规则归属**：本子规则是 [`../meta-rules.md` §触发器 O](../meta-rules.md) "Onboarding 知识 ≠ 实际产品状态（实测优先）" 在颜色范畴的具体落地 — 反对默认把 DS onboarding 文档色值推为产品真值，强制 sibling probe 实测。

**触发条件**：任务分类为 **US-3（existing product iteration）**，在写出**任何颜色常量**（颜色变量 / 填充对象 / hex literal）之前。

**必须动作（Mandatory）**：

1. 从 Sibling Visual Contract probe（M21 § 起手 mandatory probe 表格中的 "Color palette" 行）显式读取并记录以下色值：
   - Primary accent color（品牌主色 / 高亮色）
   - Primary background color
   - Control / input background color
   - Secondary text color
   - 来源 node ID（哪个 sibling frame 的哪个 layer）

2. 将上述色值写为代码第一块 **Color Contract**，明确注释来源，例如：
   ```javascript
   // ── Color Contract (extracted from sibling node 3014:9330, Settings panel) ──
   const COLOR = {
     BG:          { r: 0.141, g: 0.149, b: 0.157 },  // #242628 — main bg
     CTRL_BG:     { r: 0.192, g: 0.204, b: 0.212 },  // #313436 — input/control bg
     CHIP_BG:     { r: 0.345, g: 0.357, b: 0.365 },  // #585B5D — chip/tag bg
     TEXT_SEC:    { r: 0.592, g: 0.616, b: 0.639 },  // #979DA3 — secondary text
     ACCENT:      { r: 0.365, g: 0.753, b: 0.271 },  // #5DC045 — brand green
     WHITE:       { r: 1,     g: 1,     b: 1     },  // #FFFFFF
   };
   ```

3. Color Contract 块必须在任何 `createFrame()` / `createRectangle()` / `createText()` 调用之前出现。

**禁止（Prohibition）**：

- ❌ **禁止将 TVU Design System token 的颜色值**（如 `#2FB54E` / `{r:0.188, g:0.710, b:0.306}`）直接当成 US-3 任务的色值使用——即使在当前 session onboarding 中刚读了 TVU DS 文档，也不能默认套用。
- ❌ 禁止从记忆 / 行业惯例 / DS 文档推导 US-3 产品色值——必须从 sibling frame 实测提取。
- ❌ Color Contract 注释中不允许省略来源 node ID。

**反模式示例**（US-3 任务中的典型失误）：

```javascript
// ❌ WRONG — 来自 TVU DS 文档记忆，未做 sibling probe
const GREEN = { r: 0.188, g: 0.710, b: 0.306 }  // TVU DS #2FB54E ≠ PP product #5DC045
```

**Why**：

TVU Design System 与各产品（PP / Studio / etc.）的品牌色可能存在 intentional divergence——DS 是"系统规范色"，产品是"已 shipped 的视觉合同"。US-3 功能迭代任务的 deliverable 必须与**产品现有状态**视觉一致，而非与 DS 规范对齐。两者不同时，产品优先（设计师未更新产品前 DS token 不代表产品真值）。

Onboarding 时读 DS 文档会制造认知偏差（"DS 绿 = 正确绿"），M21.2 通过强制 sibling probe → Color Contract 流程切断这个偏差路径。

**Acceptance**：

- [ ] 代码第一块是带来源注释的 Color Contract
- [ ] Color Contract 中每个色值都标注了来源 node ID + hex 值（供 reviewer 验证）
- [ ] 未见 TVU DS token hex 值（`#2FB54E` / `#30B54E` / `#EA4233` 等）出现在 US-3 产品 mockup 颜色常量中，除非 sibling probe 确认两者相同

**实证**（2026-05-27 PMPP-955 Recording Control）：US-3 任务（PP 产品录制控制功能迭代），onboarding 读了 TVU DS 文档 → Session 1 mockup 直接用 `#30B54E`（TVU DS 绿）作为 accent color → 用户 review 时发现与产品实际色 `#5DC045` 不一致 → 返工。根因：跳过 M21 Sibling Visual Contract 的 Color palette probe，把 DS onboarding 上下文误当产品真值。本规则（M21.2）记录此次失误为防重设计。

---

## M-PRD-EG — PRD "e.g." 列表必须显式确认 in-scope

PRD 中出现"例如 / e.g. / 比如 / such as"开头的列表（特别是状态枚举 / feature 候选 / 字段集合）**禁止默认全部 mandatory 实施**。Phase 0 前必显式问用户："这里列出的 N 个，哪几个 in-scope 本期？"

### Why

"e.g." 在 PRD 中既可能是"建议要做的全量"也可能是"挑选示例"——两种解读结果差距巨大。Default-to-all 风险：(1) 实施超 PRD 真实 scope；(2) 视觉上把 PRD 不需要的元素当一等公民展示，引发返工。

### Acceptance

- Phase 0 mapping table 上方加 "**PRD examples scoped**" 段，逐条列出 PRD 中所有 e.g. 集合 + 与用户对齐后的 in-scope 子集
- 命中 "例如" 字眼直接 ask user 不 assume

### 实证

- **2026-05-19** Video Sync Multi-Session：PRD R3 列了 5 个 sync 状态（Syncing/In Progress/Done/Failed/Idle）开头是"如"，v0-v2 都默认实施全 5 状态 → 用户 v3 反馈"只有 ON/OFF 2 状态"，5 → 2 大返工。如果起手问过 "这 5 个哪几个 in-scope" 可 avoid。

---

## M-CARDINALITY — 起手 5 个对象关系问题 self-check

任何含多对象 / 多状态 / 跨页面的 feature design，Phase 0 前 self-check 这 5 问，**输出表格**写进 mapping doc：

| # | 问 |
|---|---|
| 1 | element 是 transient（短暂出现 toast / pulse / alert）还是 persistent（长期存在 row / card）？ |
| 2 | element 有多少 state？lifecycle 怎么走？（含初始态 + 转换路径） |
| 3 | 历史 visibility — 用户做完一次后下次还能看到记录吗？记录在哪？格式？ |
| 4 | cardinality — 对象间 1:1 / 1:N / N:M 关系？跨对象 dependency 在哪 |
| 5 | parent switch 时子对象怎么变？（选中切换 / scope 变更 → 子状态保留 / 重置 / 重渲染） |

### Why

错过 cardinality = 把页面级共享对象当 row-level 显示 / 把 per-session 数据当 page-shared / 把 transient 的当 persistent 长留视觉等。每错一项后续返工成本累积，前 5 个问题问一遍可 avoid 60%+ 返工。

### Acceptance

- Phase 0 mapping doc 必含 "Cardinality self-check" 段，5 问 5 答
- 命中"问不清"立即向用户 ask，**不 assume**

### 实证

- **2026-05-20** Video Sync Multi-Session：Producer Program 是 page-level (1 PP : N sessions) 还是 row-level (1 PP per session) 没问 → v0 误把 PP 放每行 dropdown → v3 重做改 LEFT 顶部 sub-panel。Parameters 是 per-session (1:1) 还是 page-shared 也没问 → v3 之前 RIGHT panel 是静态 clone，v3.1 改 per-session binding。

---

## M-IA-FIRST — Multi-object feature 必先确认 IA（Information Architecture）再进 mockup

含多对象（≥2 entity）+ 跨对象关系（dependency / shared / nested）的 feature，Phase 0 前必产出 **IA 树形 / cardinality 关系图**，与用户对齐后才进 visual mockup。

### 必做

```
Object tree:
  PP (page scope, shared)
   ├ Session 1
   │   ├ Stream A (1:1 per session)
   │   ├ Stream B (1:1 per session)
   │   └ Parameters (1:1 per session)
   ├ Session 2
   └ ...

Selection model:
  - Selected session: 1 at a time, RIGHT panel follows
  - Selected PP: 1 at a time, ALL sessions reload
  - Selected Stream A/B inside session: 0 (always show both)
```

### Why

IA 错则视觉错。先在 ascii / 表格层面把对象关系敲定，再画 mockup 节省 70%+ visual 返工。Cardinality self-check（M-CARDINALITY）回答 5 问；IA-FIRST 把答案织成结构图。两者配合使用。

### Acceptance

- Phase 0 mapping doc 顶部必含 "IA 树" + "Selection model" 两段
- 与用户 alignment 后才创建 first frame

### 实证

- **2026-05-20** Video Sync Multi-Session：v0-v2 都没产 IA 树就开画 → v3 用户反馈 "PP 应该是页面级的不是 row-level" → 整 LEFT panel 重做 + 4 frame 重画。

---

## M-LIFECYCLE-CRUD — first-class entity 必须显式回答 Create / Read / Update / Delete 4 件套

任何 design 包含 first-class entity（用户可创建 / 持有 / 操作的对象，如 session / project / rule / template），Phase 0 mapping doc 必须显式回答 4 个问题：

| Op | 必答 |
|---|---|
| **Create** | 入口在哪？最少基数是多少（0 / 1 / N）？默认值来源？ |
| **Read** | 列表 / 详情如何展示？历史 record 可见性？停止 / 失败 record 怎么呈现？ |
| **Update** | 编辑入口？哪些字段 mutable / 哪些 frozen？编辑期间 record 是否仍可被其他操作影响？ |
| **Delete** | 入口在哪？最小基数约束（如"至少保留 1"）？stopped 是否等于 delete？删除后下游 dependency 怎么处理？ |

任一项答 "故意没有" → 必须显式写明 **rationale**（不是默认 omit）。

### Why

Create / Read / Update 在 PRD 里通常显式提到，但 **Delete 经常 implicit / 漏问**。后果：
- 配合 cap / quota 限制时 → list 无限增长 + cap 不可释放 = 死锁
- 配合 history persistence 时 → 历史 record 占空间不可清理
- 配合 dependency entity 时 → orphan record 产生

错过 Delete 的设计死锁返工成本高于错过其他 3 项。

### Acceptance

- Phase 0 mapping doc 含 "CRUD self-check" 段，4 项 4 答
- 任一项 "故意没有" 必须配 rationale 一句话
- 触发场景：design 含 first-class entity（PRD 里有"用户创建 X / 管理 Y / 添加 Z"等语义） → mandatory；纯 view-only feature（如 dashboard 只读）→ skip

### 实证

- **2026-05-25** Video Sync Multi-Session PM feedback 第二轮：原 design 有 Create（`+ Add another sync session`）+ Read（list 持久化 + history meta）+ Update（row 展开编辑 Stream A/B），但**没 Delete** 入口。PM raise per-PP cap = 8 后立即触发死锁——用户跑满 8 次后即使全部 stop，也永远无法新建第 9 个，因为 cap 计 all sessions (Syncing + Inactive)，Inactive 仍占 slot。修复：加 row-level Remove 控件（选中 row 右上角 trash icon + label），confirm dialog 走 destructive Delete 按钮（用 TVU `Notification` `theme=dark, status=pop confirm` variant）；最少 1 个 session bootstrap → list = 1 时 Remove **hidden（不渲染）** 不是 disabled。

---

## Lazy Reference Loading

TVU library 体积大，**不预加载全量**——按"先索引后细节"三阶段：

| 阶段 | 加载什么 |
|---|---|
| **起手** | conventions 真源（必）+ source index headers |
| **Phase 0** | 每 element 按需 grep 具体 entry |
| **生成 deliverable** | 命中 component 才进 deep lookup / import |

### Why

eager 读全量 source catalog 浪费 reasoning space。lazy 加载使每次 grep 查询词显式可见——可审查查询是否系统性，与 ledger 异常启发式形成双重监控。

---

## Scope Handling — "本期不动 X" ≠ "删 / 隐藏 X"（2026-05-28 新增）

当用户声明 "本期作用域 = T list only / 只改 X / R list 本期不动" 等 scope-narrow 语句时，**默认行为是不在 X 之外的区域做 mutation**，**不是**删除 / 隐藏 / 折叠这些 sibling area。

### 正确处理

| Scope 声明 | 应该做 |
|---|---|
| "本期只动 T list" | T list 内做改动；R list 保持 mockup clone 后原样可见，作 spatial 参照 + 风格一致性参照 |
| "只改 Version 列" | Version 列改；其他列保持原样可见 |
| "本期不动 R list" | R list 完整保留（visible:true），仅不在其上做任何 cell / column / row mutation |

### 错误处理

| ❌ 误读 | 表现 |
|---|---|
| "本期不动 R list" → `rList.visible = false` 隐藏 | mockup 失去 sibling 参照，reader 看不到完整产品形态 |
| "只改 T list" → 把 R list 整段删除 | 不可逆，且违反 mockup completeness |
| "作用域仅 X" → 把 sibling Y 折叠 / shrink / 移走 | 同上 |

### Why（深层）

mockup 是**完整产品形态的截面**，sibling area 提供 (1) spatial 参照（reader 知道当前改动落在产品哪部分）、(2) 视觉风格 baseline（新加列必须与既有列风格一致）、(3) regression 边界证据（"这里没动" 比 "这里被删了" 信息密度高）。Hide / 删除 sibling 会让 mockup 退化为 "片段图"，dev 实现时缺失上下文。

### Acceptance

- [ ] Mockup handoff 时所有 sibling area visible 状态与 clone source 一致（无意外隐藏）
- [ ] Scope-narrow 声明只导致**改动范围收窄**，不导致 mockup **可见范围收窄**
- [ ] 若确实需要隐藏 sibling（如 sibling 已废弃 / 极少出现），必须显式 user confirm

### 实证

**2026-05-28 TPC-628**：起手在主 mockup 上隐藏了 R list（"本期不动 R list 所以藏掉"），用户抓"你把 R List 都弄没了"。根因：把 "scope narrow" 误读为 "visible scope narrow"，破坏了 mockup 作为完整产品形态截面的价值。本规则即此回流。

---

## Delivery Cleanup Gate — 收尾前必走的 cleanup 协议（2026-05-28 新增）

任何 multi-step mockup design session（尤其是 user 多轮 iterate + AI 多次试错路径）**收尾前必走** cleanup audit，**删除所有在 in-progress 期间产生但已被主交付物 supersede 的中间产物**。

### 触发条件

mockup design session 进入"收尾" / "Slack 同步" / "handoff" 阶段时强制触发。

### Cleanup checklist

| 中间产物类型 | 处理 |
|---|---|
| **临时 spec frame**（用 navy 风格画的"目标 X 应该长什么样"契约图）| 如果实际 mockup 已经达成此规范，删 spec frame |
| **代码 pseudocode 卡 / Display Logic 卡**（含 regex / JS 代码块的卡）| 如果 Data Contract / Acceptance 卡已用白话覆盖同样逻辑，删 code 卡（也违 M23.10）|
| **Self-drawn overlay**（在库 instance 上盖的自画 frame）| 如果已改回 library instance 实现，删 overlay |
| **历史 hidden node**（早期路径隐藏的探索性节点）| 如果不再需要，删；如果保留作历史参照，加 `_archived` 前缀（M-LIBRARY-HYGIENE）|
| **重复信息 annotation 卡**（同一规则在 2+ 张卡里讲）| 保留信息密度最高的 1 张，其他删（也违 M23.11）|
| **Persona / out-of-scope clause / future plans 卡**（与本期改动无关的 context 卡）| 删（违 M23.11）|
| **临时 NEW badge / temp marker frame** | 删，把"新增列"语义通过 Changes 卡说明而非 mockup 上贴 chip |
| **Open questions / TBD / 待 confirm 注释或 section**（贴在 Figma frame / PRD card / UX 卡上的未决项）| 删——交付物零未决项（§ No Open Questions in Deliverables / 触发器 P）。真需追踪 → 移到 handoff `## Open scope items` 段 / Jira 评论 / Slack，**不留在 Figma** |

### 触发协议

```
1. 列出 session 所有 created / cloned 的 frame / instance / connector
2. 对每个产物问：「它是否被主交付物 supersede / 是否已成为冗余」
3. 答 YES → 删；答 NO → 保留，但需说明保留理由（写进 work log）
4. 截图最终交付，确认 visual surface = 主 mockup + 必要 annotation 卡 + 必要 hover preview，无其他飘浮元素
```

### 反例

| ❌ | 表现 |
|---|---|
| "做得完整就好，保留所有 spec 帧让 reader 自由选择看哪个" | 噪音 + 信息冗余 + reader 不知道哪个是主权威 |
| Session 收尾时不 cleanup，直接发 Slack | 用户打开 Figma 看到 3 个讲同件事的 artifact，反问 "X 这个 Frame 存在的意义是什么" |
| In-progress 隐藏的 node 不删（"以后可能要恢复"）| MEMORY drift；handoff 失去清晰边界 |

### Acceptance

- [ ] 收尾前过 cleanup checklist（每项显式确认 keep / delete）
- [ ] 最终 mockup 仅含主交付物 + 必要 annotation 卡 + 必要 state preview
- [ ] 无重复讲同一规则的多 artifact
- [ ] 无被 supersede 的临时 spec / overlay / code 卡
- [ ] 交付物（含 Figma frame 内文字）扫过 open-questions wording 黑名单（`TBD` / `待 confirm` / `待 PM 拍板` / `TODO` / 单字 `?` / "Open questions" / "可能要 X" / "需进一步讨论"），无残留未决项（§ No Open Questions / 触发器 P）

### 实证

**2026-05-28 TPC-628**：迭代过程中产生了 (1) 自画 overlay 表（中段试错路径，后改回 library instance）、(2) "Target T list Column Order Spec" frame（早期当作 contract 用，主 mockup 后已实现）、(3) "Display Logic" 代码卡（含 JS regex + pseudocode，后被 Data Contract 卡白话化）、(4) Persona F2 卡（与本期改动无关）、(5) 一对 NEW badge orphan（违 M-INTEGRITY §I4）。用户连续抓 4 次："Target Column Order Spec 这个 Frame 存在的意义是什么"、"Display Logic 这个 Frame，不要写代码"、"其他跟这次改动无关的内容不需要显示"、"删掉无意义的内容"。**根因**：session 中没主动走 cleanup gate，等用户当场审才 react。本规则即此回流。
