# MH-3263 浏览器检测警告 Mockup —— AI 协作过程复盘（内部分享）

> 受众：UX / PM / 需要和 AI 协作画 mockup 的团队成员
> 作者：Lora
> 日期：2026-07-16
> 任务：Jira [MH-3263](https://tvunetworks.atlassian.net/browse/MH-3263) —— MediaHub 检测非 Chromium 浏览器并提示（推荐 Chrome，允许继续）
> 说明：本文复盘的是**AI 与人协作的过程**，不是设计交付本身。目的是让团队知道用 AI 画 mockup 时哪些环节容易翻车、怎么提需求更省事。

---

## 1. TL;DR

- **总轮次**：~13 轮用户交互（1 轮需求 → 1 轮"换成参考图这版" → ~9 轮细节调整/纠错 → 1 轮反思）
- **最终交付**：MH-2026 文件 page `MH-3263`，4 个 1920×1080 frame（Interstitial 全屏拦截层 EN/中文 + Persistent Bar 常驻提示条 EN/中文）。**注**：Persistent Bar 区块在中途从画布上消失，本 session 未恢复（见 §4 gap-4）。
- **核心 process gap 数**：4 个，其中 **1 个是同一类问题在本 session 内被用户纠正 2 次**（文字没绑设计系统）。
- **关键 insight**：本轮的返工**几乎都不是"AI 不知道规则"，而是"AI 没验证就自信断言 + 把'写进文档/看过一眼'当成'做到了'"**。规则大多是现成的（有几条还是这个 session 里 AI 自己刚写进 `figma-technical-reference` 的），照样重复踩。**对 AI 画 mockup 来说，真正的瓶颈是验证纪律，不是知识覆盖。**

---

## 2. Session 概览

**任务起点**：Jira ticket 已写了相当完整的 requirements + acceptance criteria（等同一份 PRD），所以跳过了 Pre-Phase 0 的 PRD 起草，直接进 Phase 0 element mapping。

**最终落地**：
- Interstitial（全屏拦截层）：复用 TVU `Notification`（dialog/warning/dark）改造，弹窗卡片样式（Layer_4 底 + Light Divider 边 + L3 shadow）+ 品牌 lockup + 浏览器检测行 + 主 CTA（复制链接在 Chrome 打开）+ Download/Continue-anyway 链接 + Contact Support。EN + 中文两版。
- 官方 Google Chrome logo（真实 SVG，非自画）放在 "Download it" 旁。
- Persistent Bar：常驻细条提示（自建，库内无对应全宽通栏组件）—— **中途消失未恢复**。

**Process artifacts（本 session 产出的可复用资产）**：
- Handoff：`Mediahub/docs/handoffs/2026-07-16-mh-3263-browser-warning-handoff.md`
- Phase 0 ledger 追加一行（`tvu-design-system/docs/internal/_metrics/phase0-ledger.md`）
- 3 条规则/quirk 回流到 tvu-design-system（见 §6）

---

## 3. 时间线 / 主要迭代

| # | 版本 / 动作 | 用户 feedback 触发 | 改动量 |
|---|---|---|---|
| 1 | v1：4 帧，模糊 app 背景 + 居中 Notification 卡 | 初始需求 | 建 4 帧 |
| 2 | **推翻重做**：改成参考图的全屏卡片版（logo lockup + 检测行 + pill CTA），右下角 Contact IT | 用户给参考图"用这个设计" | 重建 EN + 中文 内容 |
| 3 | 文案：Contact IT → Contact Support | 用户指定 | 2 节点 |
| 4 | 布局：warn icon 与标题合并一行 + 检测行图标换 monitor（走 affordance-search） | 用户 2 项要求 | 2 帧结构 + 图标替换 |
| 5 | 修 icon/标题垂直居中（headline 高度没 hug） | 用户"没居中对齐" | 2 帧 |
| 6 | 内容区加弹窗底色（Layer_4 + L3 shadow + 圆角 + padding） | 用户"用弹窗的样式" | 2 帧 |
| 7 | 加 Google Chrome logo（真实官方 SVG）放 Download 旁 | 用户"需要 Chrome logo" | 2 帧 |
| 8 | **文字绑定纠错 #1**：手写 Roboto+hex → 尝试绑 style（但绑错了，用替代字体凑数值） | 用户"文字规范没绑设计系统，你又犯了" | 22 节点 |
| 9 | **文字绑定纠错 #2**：真正用 `setTextStyleIdAsync` 绑到发布 style | 用户"依旧不是设计规范里的，认真检查再做" | 22 节点 |
| 10 | **颜色显示/实际不一致修复**：白底 fallback → 用 token 解析值当 base | 用户截图"面板显红画布显白" | 24 节点 |
| 11 | 本文（协作复盘） | 用户"反思" | — |

---

## 4. Top Process Gap（按返工成本排序）

### Gap-1（最贵）：文字没绑设计系统 —— 同一问题本 session 纠正 2 次，跨 session 第 3 次
- **实证**：#8 新建全套文字节点全部手写 `fontName:{family:'Roboto'}` + 猜 fontSize，没有一个绑 `textStyleId`。用户第一次纠正后，我"修复"时 `loadFontAsync('PingFang SC')` 报错一次，就**断定绑不了**，改成用 Noto Sans SC 匹配数值、还声称"数值来自真源"——实际根本没绑。用户第二次纠正后才真去测，发现 `setTextStyleIdAsync` 不需要预加载字体、一直可用。
- **返工成本**：2 个完整来回 + 一次 memory 更新 + 用户明显的挫败感（"你又犯了"）。
- **根因**：(a) 新建元素时切回"凭记忆写死数值"模式；(b) 遇到一次 API 报错就自信断言"做不到"，没验证就放弃真绑定。
- **回流落点**：`feedback_figma-mockup-fidelity-discipline`（memory，已加第三次实证 + "截图验收前先跑 fills/textStyleId 自查"硬动作）。

### Gap-2：白底盖暗背景 —— AI 刚写完这条 quirk，转头又踩
- **实证**：`createAutoLayout()` 新建容器默认白色 fill，叠在暗色卡上把内容盖成灰白。我第一次不但没认出（这正是我本 session 早些写进 Q23 的坑），还误诊成 `LAYER_BLUR` 冲淡颜色，拆装 blur + 切 variable mode 折腾 3 轮。
- **返工成本**：~3 个 use_figma 来回浪费在错误方向。
- **根因**：暗色主题下"背景莫名变浅"第一反应应查新建容器有没有清 fill，我却先怀疑 effect。
- **回流落点**：Q23 已存在，本 session 补了第二条实证。

### Gap-3：颜色"面板显示 token / 画布渲染 base 色"
- **实证**：给所有 fill 传白色 base + 绑 token。`UX/Red/Default` 在画布渲染成白色、属性面板却显示红色 token（用户截图发现）。红点用同 token 却正常——差异是 TEXT node 后调 `setTextStyleIdAsync` 打断了 fill 变量解析。
- **返工成本**：1 个来回 + 用户得亲自截图指出。
- **根因**：没真正理解 `setBoundVariableForPaint` 的 base=fallback 机制就批量套用；且我承诺过的"改完扫一遍 boundVariables"自查没做。
- **回流落点**：新建 **Q26**（figma-technical-reference）。

### Gap-4：不确定的背景页，自己想象编了一个假页面（跨 session 重复的老问题）
- **实证**：Persistent Bar（常驻提示条）第一版，我不知道真实 MediaHub 首页长什么样、也没问，就自己 `createAutoLayout` + placeholder-card 拼了一个**假的应用背景**画上去。用户直接把整块删了，说"你给的页面不对"，然后甩来真实 Home 页 node（`2010:1138`）让我在那上面重画。
- **返工成本**：整块 Persistent Bar 白做一遍 + 用户得亲自删掉再指路。
- **根因**：任务需要"周围页面当背景"时，我把"不知道背景页"当成可以用想象填补，而不是停下来要真实来源。这跟 Gap-1「没验证就断言」是同一个病根的两个面。
- **跨 session 重复**：这条**之前已经总结过**——2026-07-10 Producer Macro（PP20-3821）我基于 Jira 文字描述凭空写了一整套 UI 方案，用户问"你知道现状吗"，并下了长期指令"日后不清楚现状的功能必须告诉我"。当时沉淀成 memory `disclose-unknown-current-state`。本次是**同一规则在"背景页/落点页面"场景的再犯**。
- **回流落点**：memory `disclose-unknown-current-state`（已补第二条实证 + 扩展到"背景/上下文页面"：出现"在 X 页面上/里 加/放"这类措辞而我没有该页确切 node 时，先问再画）。

### Gap-5：Persistent Bar 消失后一直挂着没闭环
- **实证**：（承接上一条被删之后）常驻条从画布消失，我每轮都补一句"还没恢复"但从不推进，也没明确问用户要不要重建。
- **返工成本**：低（噪音成本），但拖了大半个 session 悬而未决。
- **根因**：把"标记了未决"当成"处理了"；应该要么明确问、要么闭环，不该反复挂着。
- **回流落点**：本复盘 action item（见 §8）。

---

## 5. 高效对话建议（按 ROI 排序）

**给提需求方（UX / PM）**：
1. **有参考图/参考产品的话，一开始就给**。本轮 v1 按文字需求做了一版，用户第 2 轮直接给参考图"用这个设计"整个推翻——如果参考图在第 1 轮就给，能省掉 v1 整版。（ROI 最高）
2. **需要"落在某个页面上"的 mockup，一开始就给那个页面的真实 Figma node**。本轮 Persistent Bar 我不知道真实首页、自己编了假背景被删（Gap-4）；如果一开始就给 `2010:1138` Home 页链接，能省掉整块返工。（对应 AI 侧规则：不确定的背景页要先问不要想象，见 §6）
3. **文案/术语一次性定清**（Contact IT vs Contact Support 这类），避免单独一轮只改两个字。
4. **视觉规范类要求（"用弹窗样式""图标换一个"）可以一次列全**，本轮拆成了三轮布局微调。

**给 AI 协作流程**：
4. **要求 AI 在"声称修好"之前先 probe 验证再回话**——本轮最贵的返工全部来自"没验证就自信说改好了/做不到"。可以直接对 AI 说"改完先自己 probe 一遍 fills/textStyleId 再给我看"。
5. **你在自己 Figma 画布上看到的，优先级高于 AI 的截图**——本轮 AI 的 `get_screenshot` 把红字渲染成偏红，你的画布是白的，是你截图才暴露。发现不一致时让 AI 去 probe 真实节点数据，别接受"我截图里没问题"。
6. **同一问题第 2 次出现时，让 AI 停下来先讲清根因再动手**——本轮文字绑定第一次"修复"是错的，如果第一次纠正时就要求"先说清为什么会错、验证你的修法真能绑上"，能省掉第二次来回。

**给 review 方**：
7. **重点抽查"绑定"而非"看起来对"**——颜色/字体"看着对"可能只是 fallback 凑巧接近（本轮灰/白 token 回退成白 base 肉眼看不出，只有红色暴露）。review 时点开节点看 fill 是不是真的 bound variable、text 是不是真的 bound style。

---

## 6. 已回流 / 待回流规则清单

| 规则 | 真源文件 | 简述 | 状态 |
|---|---|---|---|
| Notification footer 不是 slot，改 action 组合前须 detachInstance | `tvu-design-system` figma-component-catalog.md §Notification | 直接 remove 默认按钮报 "Removing this node is not allowed" | ✅ 已回流 |
| createAutoLayout 默认白底盖暗背景 | figma-technical-reference Q23（补第二条实证） | 暗色主题背景变浅先查容器 fill，别怀疑 blur | ✅ 已回流 |
| setBoundVariableForPaint 的 base 必须=token 解析值 | figma-technical-reference **Q26**（新建） | 否则"面板显 token / 画布显 base 色"，TEXT node 尤甚 | ✅ 已回流 |
| 文字新建也要严格绑 style + 截图前自查 | memory `feedback_figma-mockup-fidelity-discipline`（第三次实证） | prose 提醒失效，改成"截图验收前先跑 fills/textStyleId 自查"硬动作 | ✅ 已回流 |
| 不确定的背景/上下文页面不要想象编，先跟用户确认真实 node | memory `disclose-unknown-current-state`（第二次实证 + 扩展到背景页场景） | "在 X 页面上加/放"这类需要既有页面当容器、而我没有确切 node 时，先问再画 | ✅ 已回流 |

---

## 7. Model 选型推荐（基于本 session 实证）

- 本 session 主体（含 Gap-1/2/3 的犯错阶段）跑在 **Sonnet 5**；接近尾声用户 `/model` 切到 **Opus 4.8** 后处理了颜色诊断（Gap-3 定位）+ Q26 沉淀。
- **观察**：切到 Opus 后的诊断更愿意"先 probe 再断言"（先查 base color / 变量解析值再解释），而犯错阶段（Sonnet）更容易"看一眼就自信下结论"。但这是单点观察，且纪律问题本质是可以靠 prompt 约束的，不能全归给 model。
- **推荐**：这类**保真度敏感 + 需要反复 probe 验证**的 mockup 任务，用 Opus 4.8 更稳；用 Sonnet 时要在 prompt 里明确加"每次声称修好前先 probe 验证"的硬约束来补纪律。

---

## 8. 给团队的 Action Items

1. **[AI 自身]** 把"截图验收前先跑 fills/textStyleId/boundVariables 自查"当成交付前闸，不是可选提醒——已写进 memory，需要在下次任务实际执行验证。
2. **[Lora]** 确认 Persistent Bar 常驻提示条是否还要（Gap-4）：要 → 下次 session 用新的弹窗卡片视觉语言重建；不要 → 从交付范围正式移除。
3. **[Lora → 工程]** 确认 "Copy link to open in Chrome" 的真实交互（复制到剪贴板 vs 直接用 Chrome 协议打开），可能影响按钮文案。
4. **[团队]** 如果"顶部常驻提示条"模式会复用（版本升级/维护公告等），评估是否值得让设计师在 TVU 库里补一个正式的全宽 banner 组件（目前每次自建）。

---

## 附录：use_figma 改动统计（估算）

- **写操作 / probe 调用**：约 30+ 次 use_figma（含 2 次因 instance override 节点报错重试、3 次白底误诊 blur 的无效来回）。
- **有效 vs 返工比**：粗估 ~1/3 的 use_figma 调用花在了本可避免的返工上（文字绑定 2 轮 + 白底误诊 3 轮 + 颜色 fallback 1 轮）。
- **最终交付节点**：4 帧，每帧 content-column 内 ~12 文字节点 + 组件实例（Top bar / Button / Notification 改造 / 图标若干）。
- **署名**：Lora（消费产品复盘按 git 作者署名，非 generic team name）。
