# P2 — Form-input cluster token-rebind（select / input / drop down list / button）

> **触发方式**：用户对 executor 说 `请按 docs/internal/_prompts/p2-form-input-token-rebind.prompt.md 执行`
>
> **角色**：executor (Codex)
> **Plan owner**：Claude Code
> **Mode**：⚠️ **退出 verification mode** — 本任务**显式允许**修改 `src/components/{Select,Input,InputNumber,Button}/**.vue` + `src/canonical/{SelectBoxBase,SelectBoxLine,SelectBoxFilled,InputBoxBase,InputBoxLine,InputBoxFilled,DropDownListSelect,ButtonBridge,InputNumber}.vue` 的 `<style>` 块；user 已 ack（2026-05-19 session）。
> **STOP**：完成后跑回归 + audit，报数字给 plan owner；**不 commit / 不 push**。

---

## 1. 背景 / 起点

- R1 落地后（[`docs/internal/component-attributes-audit.md`](../component-attributes-audit.md)）color-token-mismatch 已分三桶：
  - **non-equivalent**: 606 — **本 prompt 目标**
  - theme-asymmetric: 152 — 不动（等设计师拍板）
  - exact: 0
- 92% finding 落在 4 个组件族：select box / input box / drop down list / button
- Top 10 pair 集中度 74% —— P2 干掉前 10 个 pair 就消化 3/4 工作量

## 2. 任务边界

### 允许的事
- ✅ 修改 `src/components/Select/*.vue` `<style>` 块
- ✅ 修改 `src/components/Input/*.vue` `<style>` 块
- ✅ 修改 `src/components/InputNumber/*.vue` `<style>` 块
- ✅ 修改 `src/components/Button/*.vue` `<style>` 块（即使 audit allowlisted 也可以重 token，但 8-set 设计意图必须保留）
- ✅ 修改 `src/canonical/{SelectBox*,InputBox*,DropDownListSelect,ButtonBridge,InputNumber}.vue` `<style>` 块
- ✅ 修改 `src/components/Select/dropdown-*` 或类似嵌套样式（Drop down List 相关）

### 禁止的事
- ❌ 修改 `src/tokens/variables.css`（token 值是设计师 Figma sync 范畴）
- ❌ 修改 `src/design-system/translation/**`（translation SoT）
- ❌ 修改其他组件（chart / tab / steps / 等）—— 不在本波 scope
- ❌ 改组件的 `<template>` / `<script>` —— 只动 `<style>`
- ❌ 改 `prop` API / events / slots（保 backward compat）
- ❌ commit / push
- ❌ 处理 theme-asymmetric finding（不在本波）
- ❌ 处理 size-drift / padding-drift / gap-drift / opacity-drift / size-mode-mismatch / color-token-missing（这些 category 留待后续 prompt）

## 3. Fix 协议（mandatory 步骤）

### 3.1 加载 finding 清单

读 `figma-data/normalized/component-attributes.audit.json`，过滤：

```js
findings.filter(f =>
  !f.allowlisted &&
  f.category === 'color-token-mismatch' &&
  f.equivalence === 'non-equivalent' &&
  ['select box/filled', 'select box/line', 'input box/filled', 'input box/line',
   'Drop down List/Item', 'Drop down List/Select', 'Drop down List/Cascading',
   'InputNumber', 'Button/dark L', 'Button/dark M', 'Button/dark S',
   'Button/light L', 'Button/light M', 'Button/light S'].some(c => f.component.startsWith(c) || f.component === c)
)
```

按 (codePath, selector, property) groupby —— 每个 group 内同一 (selector, property) 在多 variant 下应该都指向**同一个 Figma cssVar**。如果不是（即不同 variant 要求 code 给同一 selector 不同色），**flag 为 "variant-axis-split-needed"**，不 fix，加进 TODO 列表（这意味着 code 需要新加 modifier class，超出本波 scope）。

### 3.2 选择目标 token

对每个 (codePath, selector, property) group，目标 cssVar 应该用 Figma 那个 `figma.cssVar`（L1 primitive）—— 这是本 R1 主路径的精神：**code 直接用 L1 primitive**，避免再次走 L2 alias 误绑。

例外：
- 如果 Figma `cssVar` 在 `SEMANTIC_TO_PRIMITIVE_EQUIVALENCE` 里某 L2 token 的双 theme 都映射到它 → 改用那个 L2（保持语义清晰）
- 如果 Figma `cssVar` 是 brand 系（`--brand`, `--brand-match`, `--red`, `--blue` 等）—— 这些没 L2 alias，直接用 L1

### 3.3 校验改动

每改一个 (selector, property) 后：
- `git diff <file>` 确认只动了 `<style>` 这一行
- 跑 `pnpm vue-tsc --noEmit` 确认没 type 错（应该不动 type）
- 跑 `pnpm test --run` 单测——确认无回归（特别 `tests/Canonical.test.ts` / `tests/Input.test.ts` / `tests/RemainingCanonicalPages.test.ts`）

### 3.4 重跑 audit 验证

全部改完后：

```bash
pnpm audit:component-attributes
```

期望：non-equivalent 606 → < 100（剩 ~10 组件 99 条 + 难拆 variant-axis-split-needed）。如果 ≥ 200，dump 前 20 个剩余 finding，分析原因（可能改错 token / 或漏 fix 整个 family）。

### 3.5 视觉验证 — 跑 a11y inspector

```bash
pnpm dev &
sleep 5
pnpm exec node scripts/a11y-contrast-inspector.mjs
```

期望：scope=library 数字应**变化**（增或减都可能 — token 改了 contrast 重算）。**这里不要试图把数字压到 0**——contrast 是设计师 Figma token 值改完才解决，不是 P2 范围。只是要确认改动**没让 library scope 暴增 30%+**（如果暴增说明改错方向）。

## 4. STOP 协议

完成后**严格 STOP**，不 commit，报告：

1. `git diff --stat src/components/ src/canonical/` — 改了哪些文件 / 多少行
2. `pnpm audit:component-attributes` 后 non-equivalent 新数字
3. `pnpm test --run` 全 pass
4. `pnpm vue-tsc --noEmit` 全 pass
5. a11y inspector scope=library 数字变化（before / after）
6. **variant-axis-split-needed TODO 列表**（哪些 selector 不能简单 1:1 rebind，因为不同 variant 要不同色——这需要 code 加 modifier，超本波）
7. 你认为还有什么没 fix 干净的（坦诚汇报）

## 5. 不要做的事（再次强调）

- ❌ commit / push（plan owner 复审 + 用户最终拍板 visual diff）
- ❌ 改 token 值 / 改 translation / 改 size / padding / opacity / radius
- ❌ 自创新 token（缺 token 就 TODO 标记）
- ❌ 改其他组件（chart / table / topbar / 等）
- ❌ 在 audit 退出码不 0 的状态下 STOP——必须 exit 0 才报 STOP（除非真有 audit 自身 bug，那就修后再 STOP）

## 6. 后续

- plan owner 审 diff → 复跑 docs site + visual spot-check select/input/dropdown/button 几个关键 variant → 报告给用户
- 用户决定：commit + push（触发 v0.7.0 visual change 走 RC channel 测试）
- variant-axis-split-needed TODO → 单独 backlog entry

---

**完成后 STOP，等 plan owner 决定下一步**。
