# AI Agents 必读（跨 AI 工具通用）

> 本文件适用于：Codex / Claude Code / Cursor / Cline / GitHub Copilot / 任何在本仓库工作的 AI 工具。

---

## 仓库身份（Owner / 默认作者）

- **Owner**：Nancy `<nancyzeng@tvunetworks.com>`
- **默认 UX 交付说明作者**：Nancy（任何 M23 规则卡 / annotation footer 的 "Author / 作者" 字段默认填 Nancy，不要写通用 "UX" 角色名）
- **AI 工作时的身份约定**：AI 是 Nancy 的 plan-owner / executor 代理，**不是独立角色**。所有 AI 写出的 commit / PR / annotation 都视为 Nancy 的署名工作

任何 AI 在生成 attribution（commit author / annotation author / handoff doc 作者行 / Jira reporter 等）时**默认填 Nancy**，除非用户在当前 session 明确指定其他人。

---

## ⛔ Mockup Write Gate（TVU 产品 Figma 写操作 mandatory）— 2026-05-27 新增

任何 AI 工具（不限 Claude Code）在对 **TVU 产品 Figma 文件** 做写操作前——包括但不限于：加 mockup / 改 mockup / 加 UX 交付说明 / 加 jira 组件 / 加注释 / 加 page / 加 tooltip / 调样式——**必须**先完成 4 步：

1. **Read [`docs/internal/mockup-conventions.md`](./docs/internal/mockup-conventions.md) — 按文件顶 §🤖 AI 读取指引 scoped 读**（起手必读段 + 触发 jump，禁全量吞；重点 M0 / M1 / M-COLOR / M-INTEGRITY / M-BIND / **M-LIFECYCLE** / M23 / M29 / M32 / M35 / M43 / M46 / M47）
2. **Read [`docs/internal/design-process.md`](./docs/internal/design-process.md) § Pre-Phase 0（含 § No Open Questions in Deliverables）+ § Stage 0.5 + § Scope Handling + § Delivery Cleanup Gate**（Stage 0.5 含字段长度分布声明，M43 UX-side 镜像；§No Open Questions = 触发器 P 落地：起手扫齐 open questions + 交付物零未决项，禁止贴 Figma）
3. **Read [`docs/internal/figma-component-catalog.md`](./docs/internal/figma-component-catalog.md) 标题列表**（lazy reference，具体 entry 按需 grep）
4. **从 [`docs/site-review-manifest.json`](./docs/site-review-manifest.json) 拿 library fileKey**（不要靠扫产品文件 instance 反推）

**⛔ 写操作全程走 §M-LIFECYCLE 三时点闸**（[`mockup-conventions.md` §M-LIFECYCLE](./docs/internal/mockup-conventions.md)）——任何 create / update / delete：
- **操作前**：create/move 先 probe 目标区防叠加(§I6) · update 先 live 重读做最小 delta(§I5) · delete 先确认目标 + 处理指向它的 connector(§I5/§M23.6)
- **操作后（每批次，不拖到末尾）**：跑 `pnpm audit:mockup-conformance --file <key> --node <触碰节点>`（含 overlap / bilingual-spacing / binding-fidelity 等 8 维）+ `use_figma` connector 正交 probe；违例当场修
- **走查时**：design-walkthrough 三轴全跑、机械维度贴机检 pass/fail、`--node` 覆盖全 session 触碰节点

**触发判定（命中任一即触发）**：
- 用户给了 Figma URL + 任一动词："加 / 改 / 调 / 更新 / 同步 / 推 / 画 / 设计"
- 用户说"加 UX 交付说明 / UX notes / 加 jira 组件 / 走查 / 角色测试 / persona / journey map"
- 用户说"基于昨天的页面修改" / "在上一期 mockup 上加 X" / "clone 这个 page 改 Y" → 额外触发 M46 (Library Instance Iteration Discipline)
- fileKey 命中 TVU 产品文件（典型如 TPC-20220519 `xu7H3ppLyQfa3fOmU8M7iO` / Micro-Apps-20250923 等；非 library 文件均按 TVU 产品文件处理）

**严禁**：
- 用 claude.ai 通用 `figma-use` / `figma-generate-design` skill 替代 TVU 专属硬规则（M23 等会被整段跳过）
- 用 memory cache 替代 mockup-conventions.md 真源（memory 是工具私有缓存，规则演化 memory 会过期）
- "起手只读 STATUS.md，mockup 规则现场拍" → mockup 写操作硬规则前置，不允许现场拍
- 起手用 createFrame 自画 overlay 覆盖既有库 instance → 违 M46 (Library Instance Iteration Discipline)；正路是先 probe instance 可改性
- M23 UX 交付卡里塞 regex / pseudocode / 长代码块 → 违 M23.10 (Audience-Aware Language)
- 把 Persona / out-of-scope 声明 / 未来 roadmap 这类 tangential 内容塞进 UX 卡 → 违 M23.11 (Scope Discipline)
- "本期不动 R list" 误读成 "hide R list" → 违 design-process.md § Scope Handling
- Session 收尾前不走 cleanup → 留下被 supersede 的临时 spec / overlay / code 卡 → 违 design-process.md § Delivery Cleanup Gate
- 调列宽 / 改 cell 内容后只截整表缩略图自检 → 违 M43.2 (Column Width Self-Audit)，必须 zoom-in 每列

**违反信号 → 上一段输出不合格，重做**：
- UX 交付说明卡用了 cream / 浅底 / 单语 / 非 navy `#2B2D42` → M23 违例
- 表格新增字段没在 mockup 里给 3 状态（正常 / 截断 / hover tooltip） → M43 违例
- 自画 RECTANGLE+TEXT 拼 tooltip / button / 注释卡 → M32 Library-First 违例
- 装饰元素 / NEW badge 浮在 page 层不在 mockup frame 内 → M-INTEGRITY §I4 违例
- 改了 text 节点 fontName 但没保留 textStyleId → M47 违例（cell 渲染会变灰 / 错位）

**实证**：
- 2026-05-27 FB-9398（TPC-Service 消费端）：AI 起手只加载 claude.ai 通用 `figma-use` skill，跳过 mockup-conventions.md → UX 交付说明卡用 cream 浅底自由设计 + 单语 → 用户连续两次抓"没用 TVU 设计系统已有规则"
- 2026-05-28 TPC-628（TPC-Service 消费端）：AI 起手 clone FB-9398 后误判 instance 不可改 → 跳到自画 overlay；又把 NEW badge 放 page 层；font fallback 时丢 textStyleId 让 cell 变灰；列宽 rebudget 砍了 Operation 列但没 zoom-in 验证 Edit/Delete/Status 三按钮溢出；收尾时留下 spec 帧 / Display Logic 代码卡 / Persona 卡等冗余 → 用户连续抓 7 次。本次回流加 M46 / M47 / M-INTEGRITY §I4 / M23.10 / M23.11 / M43.2 / Scope Handling / Delivery Cleanup Gate 等规则。

---

## ⛔ Onboarding Gate（第一个项目相关回答前 mandatory）

**任何 AI 在第一个项目相关任务 / 推荐 / 回答前，必须先完成 [`docs/STATUS.md` §起手必读链路](./docs/STATUS.md#起手必读链路) 的两层 onboarding**（该节是链路唯一 SoT，本文件不重复维护清单 — 2026-06-10 P1-07/P1-08 重构）：

- **L-core 全文必读（4 份，~40KB，禁 grep / 跳读）**：FIGMA_AS_SOURCE_OF_TRUTH → STATUS → PROJECT_GOAL → 当前 pickup
- **L-ref 最小集必读 + 命中触发深读**：本文件 §硬规则表 + §Onboarding Gate 是每 session 最小集；tracker §排期原则 / backlog 当前 entry 全文 / meta-rules / working-principles / translation/ 按触发表升级 —— 触发表见 STATUS §L-ref
- **Mockup 任务**：§Mockup Write Gate 4 步前置 + §必读链路 7-10 整链升 mandatory（不受分层影响，仍是硬规则）

**机械执行**：用 TodoWrite / TaskList / 等价机制为 L-core 每项 + 命中的 L-ref 项各建 1 个 todo，逐个 Read 完才能开始回答。**基于 partial L-core 给推荐 = 协议违反**。

**违反信号**（分层版，命中任一 → 停下重读）：
- L-core 没读完就回答（"我已经知道大概了 / 状态简单跳一步"）→ 错
- L-core 或 backlog 当前 task entry 用 grep / 摘要替代全文 Read → 错
- 命中 L-ref 触发条件却只读标题 / 最小集（排期决策没全读 tracker、mockup 没读 §7-10）→ 错
- "memory 兜底替代 SoT" → 错（memory 是 AI 缓存，项目契约真源在仓库）

**历史实证**：2026-05-13 session 10 跳过 PROJECT_GOAL + AGENTS → 首轮推荐缺 4 项硬约束（canonical SoT / plan owner 边界 / working-principles / meta-rules）→ 用户返工纠偏。

---

## AI 响应格式规则（决策点 / 推荐型回答 mandatory）

AI 在面对决策点 / 给用户多选项 / 推荐方案时，响应**必须包含 4 块**（缺一不合格）：

1. **总计划 / 总数字**：当前剩余多少问题 / 总任务清单（含已完成 + 待办）
2. **本次范围**：本轮做了什么 / 影响多少数字
3. **明确推荐**：选哪个，不要"A 或 B 都可以"模糊话；候选 ≥ 2 个时必须排序 + 标默认
4. **推荐理由**：3 条以内核心理由

**违反信号**（命中任一 → 上一条响应不合格，重写）：
- 用户问"推荐哪个" / "还剩多少" / "总计划呢" → 重写
- 用户说"我自己决定" / "你决定" → 默认仍要给推荐；"我没意见"不算合规
- 列了多选项但没排序 / 没标默认 → 重写

**历史实证**：2026-05-20 session 用户多次因为这 4 块缺失追问 / 重发问题（典型："你没告诉我剩下还有多少问题？你推荐解决哪个？为什么"）。

---

## 项目一句话

把 **Figma 已发布 Library**（组件 / Token / 图标 / Styles）做成 **AI 与开发可消费的双向 Figma↔Code 桥**：

- 开发通过 **Element Plus 风格文档站 + npm install** 即可用
- AI 拿 **Figma URL** → 定位代码并 1:1 还原
- AI 拿 **代码页面** → 生成 / 还原 Figma 效果图（DS 代码经 render-verification-manifest 930 条映射 + 唯一库 `YbsPRUVmNdsbN40NNwh1Gn` 可还原；缺的仅"全自动 Code Connect publish"，待 Pro plan——详见 PROJECT_GOAL 能力3）
- AI 拿 **文字 / 链接 / 截图 / 代码任一组合** → 生成符合本规范的：
  - **UX 效果图**（Figma 设计稿 / 截图）
  - **可运行代码网页**（Vue 组件 + 部署）
- 每个 Code 组件可追溯到 **Figma 来源**（哪个组件 / 哪个属性）

详细目标 + 各能力的前置约束（T3/T4 schema 设计要点）：[`docs/PROJECT_GOAL.md`](./docs/PROJECT_GOAL.md)

---

## 必读链路

> **Onboarding 链路唯一 SoT = [`docs/STATUS.md` §起手必读链路](./docs/STATUS.md#起手必读链路)**（L-core 全读 + L-ref 按触发深读）。本节不再维护并行清单（2026-06-10 P1-07 双链路 drift 治理），只登记 **L-ref 的任务触发表** —— 命中触发即把对应真源升为该任务的 mandatory 深读：

| 触发（做什么） | 深读真源 |
|---|---|
| 排期 / 版本决策（"v0.X 含哪些 / 先做哪个 / 该不该上 Tier N"） | [`tracker`](./docs/internal/retrospection/design-spec-canonical-alignment-tracker.md) 全读（最小集 = §排期原则） |
| 写 prompt / 设计机制 / 给推荐方案 | [`docs/meta-rules.md`](./docs/meta-rules.md) 反模式清单 |
| 实现决策：命名 / token / API 形态 / 图标 alias | [`docs/working-principles.md`](./docs/working-principles.md) 9 条原则（0-8）对应条 + [`src/design-system/translation/`](./src/design-system/translation/) 4 文件（`prop-aliases` / `divergences` / `icon-aliases.ts` / `token-aliases.ts`） |
| 数据来源 / 生成链 / 清理规则 | [`docs/PROJECT_MAP.md`](./docs/PROJECT_MAP.md) |
| 历史决策回溯 / "怎么走到这里的" | [`docs/internal/retrospection/`](./docs/internal/retrospection/)（最新日期） |
| 接手 sprint task / 立新 entry | [`docs/internal/backlog.md`](./docs/internal/backlog.md)（当前 entry 全文；新 ID 先 grep 全部已用） |

### Mockup 任务额外必读

> 任何 AI 工具收到"在 TVU 产品 Figma 文件画 UX mockup / 改 mockup / 抽组件入库"类任务时，**除 L-core + 上表命中项外，下列 7-10 整链升 mandatory 全读**（§Mockup Write Gate 的 4 步前置照旧）：
>
> （**此 7-10 链 SoT = 本节**，是 mockup 任务的 scoped 强化清单，有意内联——**不属于 §必读链路开头所指的"并行清单 drift"**，无需归并到 STATUS。）

7. **[`docs/internal/design-process.md`](./docs/internal/design-process.md)** — 通用 process 规则（M22 / Pre-Phase 0 / Stage 0.5 / M11 / M14 / M15 / M16 / M21 / M6 / Lazy Reference Loading）
8. **[`docs/internal/domain-tvu.md`](./docs/internal/domain-tvu.md)** — TVU 业务规则（M3 / M4 / M5 / M7 / M8 / M9）
9. **[`docs/internal/mockup-conventions.md`](./docs/internal/mockup-conventions.md)** — Path A 专属（Figma 真源 / 组件取数优先级 / 库归属验证 / M0 / M1 / M10）
   + **[`docs/internal/figma-technical-reference.md`](./docs/internal/figma-technical-reference.md)**（Figma API quirks，实现时查）
10. **[`docs/internal/figma-component-catalog.md`](./docs/internal/figma-component-catalog.md)** — TVU 已发布库组件目录快速查（mockup 任务起手第一查，避免凭印象造组件）

---

## 硬规则（不可违背）

| # | 规则 | Enforcement 层级 | 违反后果 |
|---|---|---|---|
| 1 | **不修改 Figma**——Figma 是设计师真源 | L4-partial：pre-commit 拦 figma-data/ sync-output 镜像写入；**Figma 端写操作本身无机制可拦（L1）** | 任何 Figma 写操作都是 bug |
| 2 | **不让 AI 按"行业惯例"自由发挥** | L1（AI 自律；登记缺失由 #5 的间接链兜底） | 必须读 translation/ 已登记决策；新决策必须先得到用户确认 |
| 3 | **不创建未登记的 prop / variant / 状态** | L2 间接：无 commit 时拦截，render-verification + published-vs-code 事后抓 drift | 例：Notification 的 `success` 曾是 code 自创 drift；2026-06-12 owner 在 Figma 正式补 `dialog`×`success` 并随发布登记 → 由 drift 转为合法（先 Figma 后 code，符 §"Figma 库 master 变更→code 原子同步契约"） |
| 4 | **颜色硬编码 = bug** | L5：`audit:no-hardcoded-design-tokens`（prepublishOnly + master-push CI） | 必须用 token；token 缺失就新建，不能写 hex |
| 5 | **任何 Figma↔Code 不一致必须先在 translation/ 登记** | L2 间接：`audit:translation-completeness`（L5）只验**已登记**条目；未登记漂移靠 render-drift-gate 事后抓 | 不登记的不一致 = 漂移 |
| 6 | **AI 工具从 Figma URL 生成代码必须用 `src/canonical/*` 作为 SoT，不用 `src/components/*`** | L1（DS 仓内）；consumer 侧 L4-partial（eslint `no-base-component-import`） | `src/components/*` 是实现/base 层，`src/canonical/*` 是 Figma-aligned 桥层（npm 经 `src/index.ts` 导出 canonical）。落 base/legacy → 输出 API 错位。详见 [`src/design-system/translation/divergences.md`](./src/design-system/translation/divergences.md) "Code 端双源" 段 |
| 7 | **代码改动必须走 feature 分支 + PR (non-Owner 约束)；Owner 任何改动均可直 commit master**（2026-05-28 broader Owner override 落地，原 docs-only 例外被升级）| L3 平台：Gitea 分支保护（non-Owner）+ Owner override 政策条款 | 见下方「Git 工作流（强制）」段。Owner 例外见 §"Owner 直 commit master 权限（broader 2026-05-28）" |
| 8 | **组件 demo 必演示 Slot + Boolean 属性（Vue playground + React pilot 双框架）**（owner 2026-07-03 拍板）| **L4**：pre-commit 条件 gate + blocking `audit:demo-slot-boolean`（INFRA-F45 shipped 2026-07-06；`scripts/audit-demo-slot-boolean-coverage.mjs` 从 `components.config.ts` 派生 in-scope=28，静态断言双侧 slot 投影 + boolean live 绑定；staged 命中 demo surface/config/audit 时触发）| 凡有 default/named slot 或 boolean prop 的组件，其 docs demo 必须在 **Vue 与 React 两侧**各演示（a）slot 投影真实内容、（b）至少一个 boolean prop 的 live 切换。理由：slot 投影与 boolean 属性是双框架 CE 最易 silent 破的两条链（实证 INFRA-F43 light-DOM slot 不投影恒空 body 数版本未被发现）。首个 exemplar = PopupBox；全量回填后每个 in-scope 组件双侧达标，audit gate 防回归。|

> **Enforcement 层级图例**（对齐 [`meta-rules.md`](./docs/meta-rules.md) 触发器 K 的 L1→L5 谱系；列加于 2026-06-10 system-review P2-04）：**L1** = 文本规则靠 AI/人自律 · **L2** = 无直接拦截但有事后 audit 可抓 · **L3** = 平台/流程机制 · **L4** = 本地 pre-commit hook（可 `--no-verify` 绕过）· **L5** = prepublishOnly / CI strict gate。**7 条规则强度本不相同**——没有这列时"7 条同等强"是错觉；声称"有 gate 兜底"前先对照此列。

---

## Git 工作流（强制）

`master` 受分支保护，**non-Owner 的任何代码改动必须走 PR**。AI 在本仓库工作时遵循以下决策树：

> **⚠️ Owner 例外**：默认操作者 Owner（Nancy）**可直 commit master、不建分支**——见下方 §"Owner 直 commit master 权限（broader 2026-05-28）"（硬规则 #7 已编码）。本节决策树主要约束 non-Owner，及 Owner 在当前 session 明示"走 PR / 建分支"的情形。

### 改动前：判断该用哪个分支

1. **检查当前分支**：先跑 `git branch --show-current`
2. **如果在 `master`** → 立即建一个新 feature 分支再开始改：
   ```bash
   git checkout -b <type>/<short-desc>
   # type ∈ {feat, fix, docs, chore, refactor, test}
   # 例：fix/design-system-issues、feat/button-loading-state
   ```
3. **如果已经在 feature 分支** → **强默认：复用同一分支**

### 决策默认：**强烈优先复用当前 feature 分支**

边界以**主题**而非"文件 / 页面 / 组件"为单位。同一主题下的所有改动都应该在同一分支里累积 commit。

**判断标准（满足任一即视为同主题，应复用分支）**：
- 都属于同一类性质的工作（都是 bug 修复 / 都是文档调整 / 都是设计系统改进）
- 用户在同一次会话里持续给出指令、没有明确"切换任务"信号
- 用户没有说"这是另一个任务"或类似措辞

**示例**：
- ✅ 在 `fix/design-system-issues` 上修了 Button 的颜色 bug → 接着修 Input 的边框 bug → 接着修 Dropdown 的对齐问题 → 同一分支累积 commit，最后一个 PR
- ✅ 在 `feat/button-loading` 上改了 Button.vue → 发现 BaseSpinner 也要改 → 同一分支继续 commit
- ✅ 在 `docs/onboarding-updates` 上改了 README → 又改了 CONTRIBUTING → 又改了 onboarding 文档 → 同一分支
- ❌ 拆成多个分支 / 多个 PR——这是**反模式**，增加 review 摩擦、破坏改动的语义聚合

### 何时才换分支？

**只有以下情况才切回 master 建新分支**：

1. **用户明确说**："这是另一个任务" / "新开一个分支" / "先把当前的提了，再做下一个"
2. **当前 PR 已经合并**（git log 显示 master 已包含当前分支）→ 下一次改动从 master 重新起点
3. **改动主题完全跨域**：例如当前分支是 `feat/button-loading`（功能开发），用户突然要"更新 CI 配置"（基础设施），且当前主题尚未收尾 → 询问用户"当前分支的功能要先 PR 还是一起？"

**不要主动询问"是否换分支"**。默认就是复用，除非命中上面的硬条件。

### Commit + Push

- Commit message 用 Conventional Commits：`type(scope): description`（如 `feat(button): add loading state`）
- 一个分支可以多个 commit，PR 合并时会汇总
- Push 后把 Gitea 自动返回的 PR 创建链接给用户：
  ```
  http://product-demo.tvustream.com:3001/ux-team/tvu-design-system/compare/master...<分支名>
  ```

### 建 PR 时如何填模板（PR body）

建 PR 时按 [`.gitea/PULL_REQUEST_TEMPLATE.md`](./.gitea/PULL_REQUEST_TEMPLATE.md) 逐段填正文，分两类纪律：

**必须自动填好**（从 diff / 对话可推导，不让 Owner 自己猜）：
- **改动内容**：读本次 diff，逐条列出实际改了什么文件、什么行为
- **改动原因**：从对话上下文 / 关联需求写清楚，关联 Issue 写 `#编号`
- **改动类型**：按改动性质勾选（可多选）
- **备注**：reviewer 需知的点、后续 TODO、未执行项说明

**禁止假填**（只能反映真实结果，否则误导 Owner review）：
- **测试情况 checkbox**：只勾**本次真实跑过并通过**的命令；没跑的留空，并在「备注」写明"未执行：xxx"。绝不能凭"应该会过"就打勾——Owner 见勾即视为已验证。
- **截图 / 录屏**：仅 UI 改动且**真实跑过 app / playground 截取**才贴；纯 docs / 逻辑改动写"不涉及 UI"。不得生成或捏造截图。
- **检查清单**：只勾确实核对过的项。

**Why**：模板的价值是让 Owner 一眼判断该不该合。勾选若不可信 → 比留空更糟（制造虚假安全感）。AI 应把"哪些已验证 / 哪些没验证"如实写出，判断权留给 Owner。

### 直 commit master 时：commit message 写结构化 body

直 commit master 没有 PR 描述兜记录，**commit message 的 body 就是"改了什么 + 测了什么"的唯一载体**——按 [PR 模板](./.gitea/PULL_REQUEST_TEMPLATE.md) 字段精简对齐，让 `git log` / Gitea 提交页一眼可读，与同事走 PR 看到的信息一致、互不冲突。

格式：

```
<type>(<scope>): <一句话 subject>      # subject 仍遵循 Conventional Commits

改动内容：
- <逐条列出实际改了什么文件 / 行为，从 diff 来>
改动类型：feat / fix / docs / refactor / chore …（可多类）
测试：<只写本次真实跑过的，如 pnpm test ✅ 219 passed；没跑的写"未跑：lint/typecheck">
```

**纪律（与 PR 模板同源）**：
- 改动内容 / 类型从 diff 与对话自动填好，别让 Owner 自己猜。
- 测试只写**真实执行**的结果；没跑的如实标"未跑：xxx"，绝不能凭"应该会过"写 ✅——Owner 看 commit 即视为已验证。
- UI 改动有截图就把路径 / 链接放进 body；纯逻辑改动注明"不涉及 UI"。

**Why**：同事 PR 的"改动 + 测试"在 PR 描述里，Owner 直 commit 的在 commit body 里，两条路径记录同一套字段、各自独立——Owner 在 PR 列表和 git log 里都能一眼看出改了什么、测没测，统一可见且不冲突。

### 直 commit master 时：写 changeset（版本日志）

走 PR 有 PR 模板兜结构化记录；**直 commit master（Owner override）没有 PR**，靠 changeset 留每个版本的改动记录。仓库已配 [Changesets](./.changeset/config.json)（`baseBranch: master`），`CHANGELOG.md` 由它按版本自动生成——这就是"按版本知道改了什么"的真源。

**何时写**：本次 commit **影响 npm 发布产物 / consumer 行为**时——`src/**` 组件、API/props、`src/tokens/**`、导出（`index.ts`）、`eslint-plugin/**`、`scripts/` `templates/` 等 consumer-facing 资产。

**何时不写**（写了反而污染版本日志）：纯 `docs/**`、`tests/**`、`playground/**`、`figma-sync/**`、CI / 内部重构等不改变发布产物的改动。

**怎么写**：和实质改动放在**同一个 commit** 里，新增 `.changeset/<short-desc>.md`：

```md
---
"@nancyzeng0210/tvu-design-system": patch
---

<面向 consumer 的一句话：改了什么 + 影响。Breaking 要写迁移说明。>
```

**bump 级别（= 改动类型）**：
- `major` — 破坏性改动（API / prop 重命名或删除、行为不兼容）
- `minor` — 新功能 / 新组件 / 新 prop（向后兼容）
- `patch` — bug 修复 / 视觉对齐 / 小调整

**纪律**：bump 级别和描述据实写，不夸大不缩小——`changeset version` 据此 bump 版本号并汇总进 CHANGELOG，Owner 与 consumer 都按它判断升级影响。发布时 `pnpm changeset:version` 汇总、`pnpm changeset:status` 查待发布项。

### 禁止 AI 做的事

- ❌ 不要自己点合并（PR 必须由人审批后合并）
- ❌ **non-Owner** 不要试图 push 到 master（会被分支保护拒绝）；**Owner 直 commit master 是默认**，见 §"Owner 直 commit master 权限（broader 2026-05-28）"
- ❌ 不要为同一个逻辑改动拆多个分支
- ❌ 不要在没确认主题完成的情况下擅自切回 master

### Owner 直 commit master 权限（broader 2026-05-28）

**2026-05-28 Owner override 升级**：原 docs-only 例外扩到 **任何改动**（含 code / config / schema / scripts / SoT 等）。Owner Nancy 默认 commit 到 master，**不建 feature 分支**，除非用户在当前 session 明示"开分支"。

**触发条件（严格 AND）**：
1. 当前 session 操作者 = Owner (默认 Nancy；见 §"仓库身份")
2. Owner 未在当前 session 明示"建分支" / "走 PR" / "feature branch" 等措辞

**AI 决策树**（在仓库 cwd 改任何文件时）：

```
当前 session 是 Owner 操作？
  └─ YES → Owner 明示要建分支 / PR？
            └─ YES → 走 §"Git 工作流（强制）" feature branch
            └─ NO  → 当前在 master：直 commit；当前在 feature：问 Owner "本次并入当前分支还是切 master 直 commit？"
  └─ NO  → 走常规 feature branch + PR 流程
```

**Why**：
- 单人 owner 项目 + AI plan-owner/executor 代理模式下，feature branch 仅是仪式 (no second reviewer except Owner themselves)
- Owner 已对每个 commit 实质 review (plan owner 审 executor diff + Owner ack)
- 分支保护可为 Owner 设豁免规则 (Gitea 支持)；未设豁免时 Owner 用管理员权限绕过
- 减少 branch / PR / merge 切换 cycle 摩擦

**反例（仍走 feature branch）**：
- 非 Owner 用户改任何文件 → 常规流程保留 review trail
- Owner 明示"这个开分支跑" / "走 PR" → 按 Owner 指令开分支
- AI 在 Owner 没明示授权直 commit 时... 实际不存在此 case（Owner override 是 default，AI 不需要明示授权也直 commit）

**实证**：2026-05-28 BRIDGE-MOCKUP-008 Phase C session — Codex 按旧 docs-only 例外建 `chore/bridge-mockup-008-phase-c-merge` 分支，Owner 反问 "为什么它会弄到分支里面？没道理不知道提交到 master"。本条款升级。

### Docs-only 改动：见上方 broader Owner override（legacy 2026-05-26，已被涵盖）

**本节原 docs-only 例外（2026-05-26 立）已被上方 §"Owner 直 commit master 权限（broader 2026-05-28）" 完全涵盖**——docs-only 只是"任何改动"的子集，规则一律以 §276 broader override 为准，本节不再单独维护触发条件 / 决策树（避免两处改一处忘的 drift）。

**实证（保留）**：2026-05-26 TPC bulk import session，Owner 改 mockup-conventions.md M23 stroke 3→4px 时被 AI 建议走 feature 分支，多绕一层；催生原 docs-only 例外，2026-05-28 被 broader override 吸收。

---

## 元规则：真源单一 + 双层导入（不绑工具 / 不绑模型）

> 本元规则适用于**任何 AI 工具**（Claude Code / Codex / Cursor / Cline / Copilot / 其它）、**任何角色**（plan owner / executor / reviewer）。
> 角色与工具的绑定可变化——当前 Claude Code = plan owner、Codex = executor，但可互换或被替代——**本规则不变**。

详细规则、反模式清单、角色互换条款、Audit/数据产出类 prompt 子规则，统一登记在：

→ **[`docs/meta-rules.md`](./docs/meta-rules.md)**（元规则真源）

任何角色在写 prompt / 设计机制 / 推荐方案前，**必须先过 meta-rules.md 的反模式清单**。命中任一条 → 停下重新设计。

---

## 工作流（约定）

> **角色驱动，工具可换。** 本段使用角色名（`plan owner` / `executor`）而非工具名。
> **当前默认绑定**：`plan owner = Claude Code`、`executor = Codex`。
> **切换方式**：用户在对话里说"把 `<角色>` 换成 `<AI 工具>`"，新工具读 `AGENTS.md` + `docs/meta-rules.md` 即可承担该角色。
> **切换不需要改本文件 / `meta-rules.md` / 任何 prompt 模板**——它们都是角色无关的。如果发现哪条规则绑了具体工具名，应该改成角色名（违反 meta-rules 反模式 #1）。

### 角色定义

| 角色 | 职责 |
|---|---|
| **plan owner** | 写 plan / 设计 prompt / 审 executor 的 diff / 复审是否进入下一阶段 |
| **executor** | 按 plan owner 写的 prompt 严格执行任务 / 跑脚本 / 报告改动与未解决项 |
| **reviewer** | 用户最终拍板（部分情况下 plan owner 兼任审计） |

> 上表是默认骨架。**具体职责按下面 task-type 矩阵微调**——不是 one-size-fits-all。

### Task-type 分工矩阵（mandatory，prompt §Mode 头段必声明）

> 实证来源：P15.1 / P15.2 / P15.2-extend / P16 discovery 四次实跑。Plan owner 凭记忆喂 baseline 数字 = bug 源（P15 §0 算错 38 → reroute / pickup §3 "~48" 歧义被 Codex 抓出）；executor 在 apply 阶段额外 verify spec = 冗余 round trip。
>
> **每个 prompt 必须在 §Mode 段明示 task type**（如 `Mode: Discovery only` / `Mode: Apply deterministic spec` / `Mode: Design options + STOP`）。executor 按对应行执行，plan owner 按对应行 review。

| 任务类型 | Baseline 数字 | 决策 / 分类 | 设计选项 | 代码改动 | 典型实证 |
|---|---|---|---|---|---|
| **Discovery / 调研** | Executor grep 实证 | Executor 按 plan owner 写的机械规则分类 | Executor 列偏差 + STOP | ❌ 不动 | P15.1 / P16 discovery |
| **Apply / 实施**（spec 已定） | Plan owner 写死 | Plan owner 已拍板 | ❌ 不发挥 | Executor 按 spec 改 | P15.2 / P15.2-extend |
| **Design / 设计选项**（多解） | Plan owner 给约束 | — | Executor 列 2-3 选项 + 推荐默认 + STOP | ❌ 不动 | P16b verifier topology |
| **Refactor / API 改造** | Plan owner 实证（写死）| Plan owner 拍板 API 形态 | Plan owner 拍板 | Executor 按 API spec 改 + 跑 vitest | Phase 6.6 dual-form / Phase 6.8 Button canonical |
| **Infrastructure / 工具**（小 CLI / hook）| — | Plan owner 拍板 spec | Plan owner | **Plan owner 可 direct**（path B）| Tier 2-D/E/F / new-backlog.mjs |
| **Audit / 数据扫描产出** | Executor grep | Executor 按 plan owner schema 输出 | — | ❌ 不动 | future audit-mockup-conformance discovery |

### 跨 task-type 不变约束（所有类型都必须遵守）

1. **Executor 永不 commit / push** — prompt 不得含 commit/push 指令，executor verify 后只报 diff + stdout，由 plan owner + 用户 ack 后才 commit
2. **Plan owner 必独立 verify executor 报告**——按 task type 差异化（见下）：
   - Discovery 类：sample 1-2 cluster 重 grep 验分类；不能只 verify 数字加总
   - Apply 类：diff 全审 + git status / git diff --stat 独立 check
   - Design 类：每个 option 独立查可行性，不 rubber-stamp executor 推荐
3. **Plan owner 不直接动 source code / tokens / JSON 数据 / component**——例外仅 Infrastructure 类小工具 + 协作文档 + prompt 文件 + 审计报告 + 复盘文档
4. **决定哪类 task type** 由 plan owner 在 prompt §Mode 段明示；executor 起手第一步是 confirm task type，与 prompt §Mode 不符必 STOP 反馈

### 标准闭环（必须按顺序）

1. plan owner 读项目规则 + audit
2. plan owner 生成 `docs/internal/_prompts/<name>.prompt.md`
3. 用户把 prompt 交给 executor
4. executor 按 prompt 改代码 / 产出文件
5. executor STOP，列出改动和未验证项
6. plan owner 复审 executor diff
7. 用户决定是否进入下一阶段

### 单一决策源模式（当前默认）

为避免 plan owner 与 executor 在对话中互相"补充框架"、反复扩展路线，后续协作默认采用以下边界：

- **plan owner 负责产出一版路线图 / prompt**，并把结构性决策固化到仓库文档
- **executor 不做"加料式评论"**：不在 plan owner 路线图基础上继续发明新轨道、新阶段或新框架
- **executor 只做三件事**：
  1. 检查 prompt 是否有明显 blocker（会误删 / 误 commit / 改 Figma / 范围不可验证 / 与仓库规则冲突）
  2. 执行 prompt 指定任务
  3. 报告改动、验证结果、未解决项
- 如果 executor 不同意 prompt，只指出**会导致失败的 blocker**，不扩展替代路线
- 一旦 `docs/internal/long-term-plan-v2-*.md` 或同等路线图落仓库并经用户确认，本阶段以该文档为准；不要在对话里反复发明新框架

### executor 角色行为约束

- 用户通过 file-based prompt 触发任务：`请按 docs/internal/_prompts/<name>.prompt.md 执行`
- **起手第一步：confirm prompt §Mode 段声明的 task type**，按 task-type 矩阵对应行执行；prompt 缺 §Mode 段 → STOP 反馈让 plan owner 补
- 每个 prompt 末尾会有 "完成后 STOP，等用户审"——**严格遵守 STOP**，不要自行进入下一步
- 关键参数（如 token 值、变体枚举）**先列出来给用户确认**，不要自行决定
- 在单一决策源模式下，执行前只做 blocker 检查；无 blocker 就执行，不再提出额外路线规划
- **永不自行 commit / push**（见跨 task-type 不变约束 #1）

### plan owner 角色行为约束

- 直接读项目文件审 executor 产出
- 设计 prompt 前**强制过 `docs/meta-rules.md` 反模式清单**——命中任一条 → 重新设计，不 fire
- **每个 prompt §Mode 段必明示 task type**（Discovery / Apply / Design / Refactor / Infrastructure / Audit）——见 task-type 矩阵
- **Discovery / Audit 类 prompt 不写死 baseline 数字**——让 executor grep 实证；plan owner 凭记忆喂数字 = bug 源（P15 §0 算错 38 实证）
- **Apply 类 prompt 必写死 spec**（token 名 / CSS 行 / API 形态）——不让 executor 重复 verify
- 任何重大决策（破坏性 API 改造、跨阶段路径选择）必须 propose 给用户拍板
- 默认**不直接修改代码 / 脚本 / tokens / JSON 数据 / 组件文件**——涉及这些改动时，应先生成 executor prompt，除非用户明确授权（Infrastructure 类小工具 path B 例外）
- 可以直接修改协作规则文档、prompt 文件、审计报告和复盘文档；完成后必须 STOP，等用户确认
- **审 executor 产出必独立 verify**——Discovery 类 sample 1-2 重 grep 验分类（不只 verify 数字加总）；Apply 类全 diff 审 + git status 实证；Design 类每 option 独立查可行性

### 共同规则

- 决策必须固化到文档（不能只在对话里口头提）
- 阶段完成后追加复盘到 `docs/internal/retrospection/{date}.md`
- 所有 prompt 版本化保存在 `docs/internal/_prompts/`

### Sprint 收尾 Self-Audit 协议（mandatory）

> **元规则归属**：本协议是 [`docs/meta-rules.md` §触发器 O](./docs/meta-rules.md) "Onboarding 知识 ≠ 实际产品状态（实测优先）" 的具体子规则落地 — sprint shipped 后用实测重审 spec / 实现 / doc，拒绝 "按 spec ship 完即 done" 心智模型。

> **2026-05-27 INFRA-F35 实证立规**：9 项 spec 全 ship 后我自报 "complete"，user 追问 "再 audit" 才暴露 5 个真问题（cleanup --apply 无 extract 不安全 / AGENTS.md stale / Step 10/11 silent failure / sample 5 太小 / backlog 缺 shipped 标识）。凭"按 spec ship 完即 done"心态根本抓不到这些。

**任何 sprint commit/push 完成后，在 user 询问"完成了吗"之前主动跑 3 类扫描**。每个 finding 按 P0/P1/P2 分级 + 估时 explicit 输出，user 拍板要不要修。

| 扫类 | 检查项 | 工具 |
|---|---|---|
| **A. Spec gap** | sprint spec 是否覆盖所有 user 给过的实例 case？(**实测拉一遍**，不凭印象)<br>边界条件 / 默认值是否拍板正确？("default ON" 在哪些 mode 下不安全？)<br>参数（sample size / timeout / threshold）是否拍脑袋而非论证过？ | 重新对照 user 原始 case 列表跑一遍 |
| **B. 实现 bug** | 看自己写的每段代码：为了"快速过关"硬编码 `code: 0` / `return true` / `catch {}` 吞 error？<br>新加的字段引用是否 exist？(例: `c.filename` vs `c.source` 这种 schema 误读)<br>silent failure path 是否暴露？ | code review + unit-level test |
| **C. Doc lag** | grep 该 sprint 涉及的 noun / flag / 命令 across 全 repo doc<br>新引入概念在 AGENTS.md / STATUS.md / working-principles.md 登记？<br>backlog entry 是否标 ✅ shipped？ | `grep -rn '<keyword>' AGENTS.md docs/` |
| **D. Canonical compliance** (INFRA-F37 Phase 2 落地)| canonical/ 内有 inline `__check / __radio / __dot` 等 affordance？native `<button>` / `<input>` 未走 canonical？ | `pnpm audit:canonical-compliance` |
| **E. Hard-rule compliance** (INFRA-F37 Phase 2 落地)| memory `feedback_*.md` 硬规则 (双主题并排 / figma fills `[0]` 不合成 / consumer template inline SVG) 有违例？ | `pnpm audit:hard-rule-compliance` |
| **F. Render-verification coverage** (INFRA-F37 Phase 2 落地)| canonical/ 组件在 `figma-data/normalized/render-verification.report.json` 是否 ≥1 entry？0 entries 即 audit-invisible（PopupBox 类）| `pnpm audit:render-verification-coverage` |
| **G. Figma library vs canonical** (INFRA-F37 Phase 2 落地)| Figma published 但 canonical 缺 wrapper？或 canonical 存在但无 figma-to-code-mapping 注册？ | `pnpm audit:figma-library-vs-canonical` |

**触发**：每次 sprint commit/push 完成（不只"shipped"语义，也包括"做完一波"）。

**不触发例外**：单一小改动 commit（typo fix / 一行 config）· 纯 doc 编辑（doc lag 本身就是 audit 检测对象）。

**机械化执行**：D/E/F/G 4 类 audit script 必须 exit 0 才能进 sprint 收尾 commit。任一 fail → 立 backlog entry 后才能 commit（pre-commit hook 兜底，可 `--no-verify` 绕过但必须留 reason）。

**H. Component-affordances SoT drift**（2026-06-01 落地）：`docs/internal/component-affordances.json`（AI 组合组件语义层，对标图标 affordance）改动、或 `src/canonical/*.vue` props/导出改动后，跑 `pnpm audit:component-affordances`（校验 code_name↔canonical 双向覆盖 + npm_export 与 index.ts 一致 + code_props 真实存在 + 生成的 `.md` 视图未 stale）。已挂 pre-commit 条件 gate（staged 命中 SoT/canonical 时自动跑）。改 JSON 后必须 `pnpm generate:component-affordances` 重生成 `.md`。

**I. Icon canonical-name 规范**（2026-06-06 落地）：`src/canonical|components/*.vue` 里的 `<Icon name="...">` 必须用 registry **canonical 名**（`category/name`，如 `action/close`、`navigation/arrow-dropdown`），不准用短 alias（`close`、`arrow-dropdown` 等）。跑 `pnpm audit:icon-canonical-names`（用 `src/icons/generated/*.ts` 的 name+aliases 做 SoT 确定性解析；catalog 运行时名如 `arrow/down` 识别为合法不误报）。已挂 pre-commit 条件 gate（staged 命中 canonical/component .vue / icon registry / 该 audit 时自动跑，exit 1 拦截）+ `audit:self-audit-phase2` 链。背景：close × 用裸 alias `close` 暴露同类散落 13 处，统一成 canonical 后立此 gate 防回归。

**K. Canonical CE-safe slot guard**（2026-07-08 落地，INFRA-F54）：`src/canonical/*.vue`（CE root）**禁用** `$slots.x` / `useSlots()` 做 slot-presence 检测——`defineCustomElement` 下 `_createVNode()` 建 CE root vnode 只传 props 不传 slot children，故 `$slots` 恒空，`v-if="$slots.x"` 在 web-component/React 构建里恒 false 静默丢 slot（Vue SFC 全绿故潜伏，已两度 ship 坏才被像素截图抓到）。必须用 CE-safe composable `useHasSlot()`（`src/canonical/composables/useHasSlot.ts`：shadow-DOM 查 `host.querySelector(':scope>[slot=x]')` / light-DOM 查 `host._slots[x]` / SFC 回退 `$slots`）。跑 `pnpm audit:canonical-slot-guard`（剥离注释后扫 live `$slots.`/`useSlots(`）。已挂 pre-commit 条件 gate（staged 命中 canonical .vue / 该 audit 时自动跑，exit 1 拦截）+ `audit:self-audit-phase2` 链。注：`src/components/` 的 base 组件用 `useSlots()` 合法（它们永远是嵌套子组件、非 CE root，收编译期 vnode slots），故 audit 只扫 `src/canonical/`。

**J. Token contract**（2026-06-09 落地）：`src/tokens/variables.css` 的 **primitive tier** 必须与 Figma `figma-data/normalized/variables.json` 一致（= `pnpm generate` 跑完零 diff）。改了 variables.css primitive 值 / 跑过 sync 后跑 `pnpm audit:token-contract`（等价断言 generate-tokens 在 place sync 后 byte-identical）。已在 `prepublishOnly` + sync 管线 Step 8.5。primitive tier 从 Figma 同步、semantic/component tier 手写保留（不在本 gate 范围，无上游可对）。

**反模式**：
- ❌ "按 spec 全 ship 完，宣告 done" — 不允许；spec 自己有盲点
- ❌ "下次再 audit" — 不允许；记忆力不可靠，下次起 session 已忘
- ❌ "user 问了再查" — 不允许；user 不应该承担 reviewer 职责
- ❌ "D/E/F/G audit fail 但 finding 是 pre-existing，所以跳过" — 不允许；pre-existing finding 必须有对应 backlog entry，否则即新 drift

### Trigger-Drift 复盘协议（激活层硬化，2026-06-18 新增）

每次用户矫正 / 返工后，固定追问一句：**「哪个触发没点亮？」**

- 先定位失败发生在**激活层**还是内容层：规则/模板存在但没被加载 = 激活层（绝大多数返工属此类）。
- 激活层失败的修法**只允许三类**，禁止以"加一条内容规则"收尾：
  1. 给制品/场景加**唤醒词**（登记进 `docs/WAKE-WORDS.md` A 区）；
  2. 给制品加 **jump 表关键词路由**（`mockup-conventions.md` 顶部表）；
  3. 把埋藏的 canonical 模板**提为一等定义**。
- 修完跑 `node scripts/audit-artifact-routing.mjs` 确认该制品三件齐全（def + route + wakeword）转绿。
- **反模式**：返工后新增第 N 条内容硬规则——只会加重激活层负担（规则越多越易漏触发），是"越自查越频繁"的根因。内容规则只在"真缺规则"（而非"有规则没触发"）时才加。

**真源**：诊断（激活层两层模型 + W1-W5 弱点 + 5 实例）见 `docs/superpowers/specs/2026-06-18-design-system-activation-layer-hardening-design.md`。

### Figma 库 master 变更 → code 原子同步契约（2026-06-12 owner 立规）

> **目标**：设计系统库 = **唯一且实时**的真源；任何 master 变更原子流到 code，**零 drift**。
> **与硬规则 #1 的关系**：#1 默认"不改 Figma"；本契约是其 **sanctioned 例外的完整时序**——改设计系统库 master **前提是显式授权**（同 [`memory figma-write-scope`] 边界澄清：只锁设计系统库、需 owner 授权/拍板；产品文件不在此列）。未授权的 Figma 写仍是 bug。

**端到端时序（authorized 改库后必走，不可乱序 / 不可省步）**：

1. **先只改 Figma**——master 编辑由授权方在 Figma 完成（reusable pattern 入库需 owner 拍板）。
2. **库 publish 单独确认**——Figma Library publish 是**独立动作**，必须显式确认已 publish；未 publish 的改动 sync/consumer 拉不到 = 隐性 drift。（`_`/`.` 前缀 = 不 publish，见下节。）
3. **owner review 满意**——改动 + publish 结果经 owner 确认后，**才**进 code 同步（不在 owner 满意前抢跑同步）。
4. **原子同步所有 code 端契约文件**——一次性、不留半成品：
   - figma-data（extract/normalize）+ catalog + icon SVG → `pnpm sync:figma-library --with-extract`（见下方 14-step pipeline，**禁跳步 / 禁 partial subset**）
   - canonical / render-verification manifest / tests → 随结构变更同步更新
   - Code Connect `.figma.ts` → 当前 deferred（Org/Ent seat 限制；硬规则 #6 + canonical SoT 等价兜底），恢复后纳入本步
   - **consumer 端引用** → **不自动同步**，经 npm 版本（changeset + release）传播；breaking 走 [`migration-protocol.md`](./docs/internal/migration-protocol.md)
5. **验证零 drift**——`audit:figma-vs-sot` / `audit:render-drift-gate` 全绿 = 库与 code 一致。

**反模式**：改了 Figma 没 publish 就当同步完 · 只改 Figma 不同步 code（或反之）留 drift · partial subset 同步（normalized 层 stale，2026-05-27 事故） · 以为 consumer 会自动拿到（实际靠发版传播）。

### 唤醒词："同步 Figma 库"

任何 AI session 收到这句话时，跑 **14-step canonical pipeline**（INFRA-F35 落地 11-step 2026-05-27 起；F35 Phase 4 + Step 12 figma-naming-hygiene + Step 13 icon-worklist；BRIDGE-MOCKUP-008 Phase D + Step 14 figma-vs-sot drift audit 2026-05-28）：

```bash
pnpm sync:figma-library --with-extract
```

完整 chain：extract → cleanup(--apply 默认 with extract) → normalize-variables → component-tokens (含 orphan-purge) → manifest → audit chain (×4) → count consistency verify (硬约束) → diff-report (非阻塞) → icon-worklist (非阻塞) → figma-naming-hygiene (非阻塞) → **icon 管线 [generate:candidates (blocking) + sync:icons (非阻塞)]** → **figma-vs-sot drift audit (blocking; A/B/C exit 1, D/E warning)**。fail-fast — 任一 blocking step 非 0 立刻 stop。

**图标管线默认随 `--with-extract` 跑（INFRA-F38, 2026-05-29）**：拉了新 Figma 数据就会重导图标 SVG + catalog，避免设计师改图标被静默漏（"diff=0" bug）。`generate:candidates` 离线 blocking，`sync:icons` 网络 non-blocking（失败 SUMMARY 可见不阻塞）。`--skip-icons` 显式 opt-out；`--with-icons` 无 extract 时也强制跑（从现有 raw 重导）。

**禁止跳步、禁止只跑 sync:extract + sync:normalize 子集**（2026-05-27 事故：partial subset 让 normalized 层 stale 2 周）。**中断（SIGINT / blocking fail / 网络断）后必须完整重跑整条 pipeline，禁止手工 commit 半成品 figma-data**——Step 2-4 顺序写入无 rollback，幂等重跑即是恢复机制（system-review P2-02）。**禁止"只想同步组件不同步图标"就跳过 icon 管线**——`--with-extract` 默认含图标即是为此（INFRA-F38 之前的静默漏）。

**Phase D opt-out**：`--skip-sot-audit` 跳过 Step 14（SoT-only refactor 场景）。<br>（INFRA-F38 还含 `audit:figma-vs-sot` null-key 显式 warning [Type F] + name-join 兜底 [Type G]，但该改动与并行的 SoT-sharding 重构纠缠在 `audit-figma-vs-sot.mjs`，**随 SoT-sharding commit 落地**，不在 INFRA-F38 图标管线 commit 内。）

### 默认安全 vs 显式破坏性

cleanup 模式 conditional default（不再 one-size-fits-all）：

| 场景 | 命令 | cleanup 默认行为 |
|---|---|---|
| 完整 sync（含 extract）| `pnpm sync:figma-library --with-extract` | 🔴 **apply** — 刚拉的 published manifest 是 fresh，删 stale 安全 |
| 只 re-verify normalized 层 | `pnpm sync:figma-library` | 🟡 **dry-run** — 没 extract，published manifest 可能 stale，默认安全 |
| 强制 dry-run（覆盖默认）| `... --dry-cleanup` | 🟡 always dry |
| 强制 apply（无 extract 但仍想删）| `... --apply-cleanup` | 🔴 always apply（用户已自行确认 published manifest fresh）|

**其它 flags**：
- `--skip-diff-report` — 跳过 Step 10（CI / quick verify 场景）
- `--skip-worklist` — 跳过 Step 11（非 BRIDGE-MOCKUP-008 任务）

### Sync 完后的 review 入口

- `docs/internal/figma-sync-report-<YYYY-MM-DD>.md` — Figma 真改 vs schema-backfill 噪音分类
- `docs/internal/cleanup-unpublished-report.md` — 本次 cleanup 删了 / 会删 哪些 component
- `docs/internal/cleanup-dup-candidates.md` — 同名不同 nodeId 警示（rename 后未 de-publish 旧版的候选）

### Pre-commit hook 自动放行

sync output commit 自动绕过 figma-data/raw/ 写入 block — 只要 staged 含上述任一 report 文件即可，**不需要 `--no-verify`**（INFRA-F35 ⑥）。`chore(figma-sync):` / `feat(figma-sync):` / `fix(figma-sync):` message prefix 推荐但非必需。

### Figma 命名约定 — `_` / `.` 前缀 = 不 publish（团队 + AI 都遵守）

**Figma 官方约定**：`Component name` 以 `_` 或 `.` 开头 → Figma 自动从 publish 排除（Library publish dialog 不显示 / Restrict publishing 自动 ON / consumer 拉不到）。

**用途场景**：
| 场景 | 推荐命名 |
|---|---|
| 临时调研 / WIP / draft | `_Draft/<name>` 或 `_Research/<name>` |
| 内部参考 / 不交付 | `_internal/<name>` |
| 已废弃保留视觉 | `_archived/<name>` 或 `_deprecated/<name>` |
| Page-level 隔离 | 页面名也加 `_` (`_Research` / `_Internal` / `_Drafts`) |

**Sync pipeline 端等价 honor**（INFRA-F35 Phase 1 落地 2026-05-27）：
- `figma-sync/extract.mjs` 起手 filter：`figmaName` 以 `_` / `.` 开头 → **不写 raw/**（源头杜绝调研 noise 进 sync 链）
- `figma-sync/cleanup-unpublished.mjs` defense-in-depth：旧 raw 残留 `_` 前缀也 classify 为 "intentional skip" 不标待删
- 配套约定：未来调研 / 临时 component 一律 `_` 前缀；team / AI 都不需要逐条加 cleanup allowlist

**反模式**：不带 `_` 前缀就把 component 放 `_Research` page — sync 仍会拉、cleanup 会标"非生产页 待删"、Sisyphus 循环。**名字 = source of truth**，page 只辅助 designer 视觉分组。

### 其它要求

- `audit:figma-conformance` / `audit:docs-site` / `audit:published-vs-code` 输出必须能解释；如有未通过项，STOP 并报告，不要继续后续阶段
- 任何 `audit:published-vs-code --auto-suggest-unmapped` 新写入 mapping JSON 的条目，状态必须是 `needs-review`，禁止自动 `approved`

---

## 项目约束（影响所有 AI 工具的任务规划）

> 本段登记**跨工具有效**的项目级约束。任何 AI 工具（Claude Code / Codex / Cursor / Cline / Gemini / 其它）规划任务前必须读这段，按约束评估可行性，不要默认更宽松假设。

- **Figma plan = Professional**（不是 Organization / Enterprise）
  - `figma connect publish` 不可达（需 Org/Ent Developer seat；任何 Code Connect API 调用都会返回 401，已实证——不限工具/协议）
  - DevMode 显代码片段功能不可用（依赖 publish）
  - 当前 Bridge 价值通过以下机制实现：硬规则 #6 + canonical SoT + [`divergences.md`](./src/design-system/translation/divergences.md) "Code 端双源" 段 + 现有 `pnpm sync:figma-library` audit pipeline
  - **失效条件**：用户主动说"升 Org"或"升级 Figma plan"——在那之前所有 Pro 限制生效
  - 详见 [t4-spike-validated 复盘](./docs/internal/retrospection/2026-04-30-t4-spike-validated.md) 阶段 6

- **截图 / 视觉证据交付走脚本文本 + 文件路径，不走对话粘贴大图** — 详见 [`docs/internal/visual-evidence-conventions.md`](./docs/internal/visual-evidence-conventions.md)
  - V1：视觉验收 ground truth 是脚本文本输出（参考 `.f19-visual-audit.mjs`），截图仅在 diff>0 时兜底
  - V2：进会话的截图长边 ≤ 1800px（`sips -Z 1800 *.png`）
  - V3：大图落盘 + `Read`，不剪贴板粘贴
  - V4：撞 2000px 限制 → STOP + 落盘进度 + 新 session
  - 失效条件：所有主流 AI 工具都把图片限制升到 4000px+ 以后——在那之前严格执行

- **Docs site 支持 dark / light theme toggle**（2026-05-08 INFRA-F19 升级）
  - `playground/docs/DocsShell.vue` 提供 toggle 按钮，`provide('docsTheme', ...)` 把当前 theme 下发到所有后代组件
  - `<FigmaMembersGrid>` 默认 `inject('docsTheme')` 跟随全局 toggle —— 切 dark 只渲染 dark variants，切 light 只渲染 light variants（基于 figma 真源 variant.theme axis）
  - **theme 渲染降级链**（与 figma 真源约定一致）：
    - **L1** figma component 有 theme axis → grid 按当前 docsTheme filter 对应 variants
    - **L2** figma 无 theme axis 但 component 用 theme-aware Color Token → 渲染依赖 token 自动响应（CSS 变量随 `data-theme` 切）
    - **L3** figma 无 theme axis 且 token 也无 theme 区分 → 多主题下视觉等同（不视为 bug）
    - 实证 L3：2026-05-08 Rating figma 简化为 token-driven（删 theme axis），多主题下视觉等同
  - 默认主题：dark（`isDark = ref(true)` 初值）
  - 改造 docs page 范式：page 内不再分 "Dark Theme Members" / "Light Theme Members" 两 section，单 grid 跟随全局 toggle 即可；**禁止任何 dark/light 并排展示**（包括手写 demo block 的 dual-card 范式）
  - `<FigmaMembersGrid>` API 不接受任何 theme override prop —— theme 唯一来源是全局 inject('docsTheme')；audit gate 对 page 模板里出现的 `:site-theme=` 任何写法报 error
  - figma 数据 dark/light 不对称（如 notification dark=15 light=14）是 figma 真源决定，**不是 docs site bug**，无需补齐
  - 失效条件：用户主动撤回 toggle —— 在那之前 toggle-aware 严格执行
  - 实证：F19 修复前文档站 shell 有 toggle 但 18 个 page 写死 `:site-theme="'dark'"` 形成半成品 bug；2026-05-08 F19 修复

---

## 当前阶段定位

> ⚠️ **阶段定位真源 = [`docs/STATUS.md`](./docs/STATUS.md)**（版本线分组 + Active 余量 + 当前 sprint）。本节不再镜像版本号/路线图，避免与 STATUS.md 漂移（曾冻结在 "2026-04-28 / v0.1" 长达 ~7 个版本）。当前阶段、已发布版本、下一段排期一律以 STATUS.md 为准。<!-- de-mirror-ok: 元引用，解释 de-mirror 缘起（历史 "v0.1" 漂移案例），非当前版本镜像 -->

---

## 受众

| 角色 | 关注点 |
|---|---|
| 开发（P0 主要使用者） | npm 安装、props/events/slots、可复制代码、TypeScript 类型 |
| 设计（P1 查看者） | 与 Figma 对应关系、变体网格、设计 spec |
| 产品（P1 查看者） | 业务场景示例、何时用哪个组件 |
| QA（P1 查看者） | 状态矩阵、可交互测试、边界条件 |

---

## Quick Reference

| 我想知道 | 看哪里 |
|---|---|
| 项目目标 | `docs/PROJECT_GOAL.md` |
| 项目地图 / 数据流 / 清理规则 | `docs/PROJECT_MAP.md` |
| 实现原则 | `docs/working-principles.md` |
| 当前进度 | `docs/internal/retrospection/`（最新日期） |
| 已做的决策 | `src/design-system/translation/` + working-principles 末尾"决策 Log" |
| 下一步 prompt | `docs/internal/_prompts/` |
| API diff 状态 | `docs/internal/api-diff.md` + `api-diff-patterns.md` |
| 资产清单 | `docs/internal/asset-inventory.md` |
| 组件级映射扫描 | `docs/internal/component-mapping-scan.md` |
| 待补运行时能力 | `docs/internal/runtime-additions.md` |
| Backlog / 已知 bug / 技术债 | `docs/internal/backlog.md` |
| Mockup 通用 process 规则（M22 / Pre-Phase 0 / M11 / M14 / M15 / M16 / M21 / M6）| `docs/internal/design-process.md` |
| TVU 业务规则（M3 / M4 / M5 / M7 / M8 / M9）| `docs/internal/domain-tvu.md` |
| Mockup Path A 专属（Figma 真源 / M0 / M1 / M10）| `docs/internal/mockup-conventions.md` |
| Figma API quirks | `docs/internal/figma-technical-reference.md` |
| TVU 库组件目录（mockup 任务起手查）| `docs/internal/figma-component-catalog.md` |
| 组件内置能力 / 别自拼（AI 设计产品起手查，code + mockup 通用）| `docs/internal/component-affordances.md`（真源 `.json`；对标图标 affordance 层）|
| 系统性 review 报告 | `docs/internal/_reports/systematic-review-<date>.md` |

---

## Team Comms Conventions（团队同步沟通规范）— 2026-05-28 新增

任何由 AI 工具生成、需要团队成员在 Slack / 邮件 / 工单评论区阅读的内容，**必须按目标平台的渲染规则适配 markdown**，不准默认用通用 / 标准 Markdown 然后让人在 Slack 看一堆字面 `**`。

### Slack mrkdwn 规则

| 维度 | Slack 用法 | 别用 |
|---|---|---|
| 加粗 | `*text*`（单星号） | `**text**`（双星号 → 渲染为字面字符）|
| 斜体 | `_text_` | `*text*`（会变加粗）|
| 删除线 | `~text~` | `~~text~~` |
| 行内代码 | `` `text` `` | 同标准 markdown ✓ |
| 代码块 | ` ```text``` ` | 同标准 markdown ✓ |
| 标题 | **不支持** `#` `##` `###` | 用 `*bold text*` 当 section 标题 |
| 无序列表 | 不自动渲染 `*` `-`；用 unicode `•` 或纯文本 | `* item` / `- item` → 字面字符 |
| 嵌套列表 | **不支持**（缩进不渲染） | 改成扁平单层 + 用 `*section title*` 分段 |
| 编号列表 | `1.` `2.` ✓ 自动渲染 | 同标准 ✓ |
| 链接 | 直接粘 URL（auto-link） | `[text](url)` 在某些 Slack 客户端不渲染 |

### 起草 Slack 文案时的硬规则

1. **section 标题**用 `*粗体*` 单独成行（不用 `##`）
2. **bullet** 用 unicode `•` + 单层（不嵌套）
3. **加粗强调**用 `*单星*`（不是 `**双星**`）
4. **链接**直接粘 URL，不用 `[text](url)`
5. **代码 / 字段名**用 `` ` `` 反引号
6. **空行**分段（Slack 渲染会保留）

### 实证

**2026-05-28 TPC-628**：AI 起草 Slack 文案用标准 Markdown（`**bold**` + 嵌套 `◦` bullet + `#` header）。用户抓 "Slack 好像不能直接识别这个 MD 格式"。补救：扁平化 + 单层 `•` + `*bold*` 标题 + 直接粘 URL。**根因**：默认 Markdown != Slack mrkdwn，AI 起草前没问"这条文案发到哪里"。本规则即此回流。

### Acceptance

- [ ] 起草 Slack 文案前确认平台 = Slack（vs Jira / Confluence / email）
- [ ] 嵌套结构扁平化为"`*section title*` + 单层 `•`" 形式
- [ ] 所有加粗为单 `*`
- [ ] URL 直接粘贴不包 markdown link 语法

### Jira 评论规则（2026-06-02 新增）

任何 AI 通过 MCP 写 Jira 评论时遵守：

#### 1. 用 ADF 格式发，不用 markdown

| 维度 | ADF（推荐）| markdown（避免）|
|---|---|---|
| `@mention` | `{"type":"mention","attrs":{"id":"<accountId>","text":"@Name"}}` → 真 mention，被 @ 者收通知 | `@Trevor Yao` 字面字符串，**不触发通知**、不变成链接 |
| 外链 / Figma / 截图 | `{"type":"inlineCard","attrs":{"url":"https://..."}}` → 渲染为 smart link 卡 | 裸 URL，渲染为简单 hyperlink |
| 富格式 | ADF 支持 mention / inlineCard / mediaSingle / panel 等专属节点 | 仅基础 text/bold/italic/list |

**`addCommentToJiraIssue` 必传 `contentFormat: "adf"`**，body 是 ADF JSON。`accountId` 从 `getJiraIssue` 拉评论 / `lookupJiraAccountId` 查到。

#### 2. 默认顶层评论，不强求 threaded reply

当前 MCP `addCommentToJiraIssue` tool schema **不暴露 `parentId` 参数**，所以 AI 写的评论都是**顶层 comment**，**不是某条评论的 threaded reply**。功能上：
- 被 @mention 的人**正常收通知**（threading 不是通知前提）
- 视觉上不串在原评论下面 —— 阅读者需要看时间戳 / @mention 才能关联

若必须 threaded reply 给具体某条评论 → 用户在 Jira UI 手动点 "Reply" 发，不走 AI 自动写。

#### 3. 内容简洁原则

| 场景 | 推荐 wording | 避免 |
|---|---|---|
| 确认改完 | `@<Reviewer> Updated.` + smart link | 4 段含背景重述 / 反提问 / status update / FYI 链 |
| 求 review | `@<Reviewer> Please review.` + link | 自述设计意图 / 不要 prepended"自我总结" |
| Status update | 单行 `Status: done / blocked by X.` | 多段叙事 |
| 反提问 / new scope discussion | **走独立评论**，不混进确认评论 | 把"我更新了 + 我有 followup 问题 + 我猜你想问 X"塞一条 |

**默认假设**：审阅者**已读过历史评论**，不需要 AI 重复背景。只贴**这次的 delta**。

#### 4. 语言：评论正文一律英文

受众 = 英文团队 / PM。**本地与用户对话可用中文，但 Jira / Slack / PR 等对外 comms 一律英文。**

#### 5. 对外发送前先给 owner 过目

AI 通过 MCP 自动发 Jira 评论属 **对外、难撤销** 操作（MCP 无 delete/edit comment——发错只能 owner 在 UI 手删）。**发之前先把草稿给 owner 看、确认后再发，不自作主张。**

#### 6. 交付 review 评论从简模板

求 review 时**只**要：`@PM <feature> — mockup/design updated, please review` + Figma **Section** smart link。**不贴** PRD/文件路径、不堆背景、不自述设计意图。

### Jira 规则的实证

**2026-06-01 V4-1865 / FB-7775**：AI 发评论用 `contentFormat: "markdown"` + `@Trevor Yao` 字面字符串 → mention 没生效（Trevor 没收 mention 通知）；内容含 4 段（致谢 / fix 确认 / Figma link / 反提 LCD touchscreen 问题），用户抓"@用户名没生效 + 太啰嗦，只需 Updated. + link"。补救：用 ADF + accountId 真 mention 重发简洁版 `@Trevor Yao Updated. <smartlink>`；旧啰嗦评论用户 UI 手动删。**根因**：AI 默认 markdown + 把多段意图揉进一条评论，没区分"确认 fix"和"反提新问题"是两件事走两条评论。

### Jira Acceptance

- [ ] 起草 Jira 评论前确认平台 = Jira（vs Slack / Confluence / email）
- [ ] 评论正文为**英文**（受众 = 英文团队 / PM；本地对话用中文不影响对外英文）
- [ ] 对外评论**先给 owner 过目草稿**再发（MCP 无 delete/edit，发错难撤）
- [ ] review 评论从简：`@PM <feature> — mockup updated, please review` + Figma Section smart link；**不贴 PRD/文件路径、不堆背景**

**2026-06-05 Graphics Insertion MC-44 实证**：AI 自动发 review 评论——(1) 未先给 owner 看草稿就发；(2) 堆了交付背景 + PRD 文件路径；(3) 用了 markdown 非 ADF mention。用户纠正"对外回复先给我看 / 从简只让 PM review / 不贴 PRD 路径 / 必须英文"。本次回流 §4-6 + 上列 acceptance。
- [ ] `contentFormat: "adf"` + `accountId` 真 mention（不用 markdown `@Name`）
- [ ] 多于"确认 + link"的内容 → 拆成多条评论（不堆一段）
- [ ] 评论目标若是 reply 到某条评论 → 提示用户在 UI 走 Reply，AI 走顶层 comment

---

## 元说明

- 本文件是**跨 AI 工具的入口**，应保持简短，详细内容指向 `docs/PROJECT_GOAL.md` 和 `docs/meta-rules.md`
- 各 AI 工具的入口文件（如 [`CLAUDE.md`](./CLAUDE.md)、未来的 `GEMINI.md` / `CURSOR.md` 等）应**仅登记该工具自己特有的工程细节**——规则、角色行为约束、元规则统一指向本文件 + `docs/meta-rules.md`
- 修改本文件需谨慎——所有 AI 工具的入口契约都在这
- **修改本文件时不要写工具具体名（"Claude" / "Codex" 等）作为规则主体**——应写"角色名"（plan owner / executor）。当前角色绑定在工作流段顶部明示
