# INFRA-F46 Fan-out Implementation Plan v2 — docs 框架开关 React islands 铺剩余 21 组件页

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** 把 pilot 已验证的 full-parity React island 范式，从 4 个 pilot 组件铺到剩余 **21 个 in-scope 组件页**（docs 站拨到 React 时每页 demo 区渲染对应组件的 React 版本）。

**Architecture:** 沿用 pilot 范式——每组件页新建 `react-pilot/src/demos/<C>.tsx`（镜像 Vue 页 demo 区 section，含 slot 投影 + boolean live + 交互 parity），配 `<c>-demo.css`（`@import demo-shared.css` + 组件专属类），Vue 页 demo 区用 `<FrameworkDemoRegion :loader="() => import('@demos/<C>')" :locale>` 包裹（API 表留区外）。**并行隔离策略**：subagent 只碰 3 个互不重叠的独立文件，**禁碰共享文件**（`App.tsx` / `PILOT_MAP` / audit 脚本）；共享文件的集成由主线在每批收尾时统一机械重放，杜绝并行冲突。

**Tech Stack:** Vue 3.5 + Vite（docs 构建 `vite.playground.config.ts`）、React 19 + react-dom/client（懒 island，已进 devDeps）、`@vitejs/plugin-react`、TypeScript compiler API + `@vue/compiler-sfc`（确定性 audit）、vitest、playwright。

## Global Constraints

- **组件属性真源 = `src/web-components/components.config.ts`**（F45 `deriveInScope` 派生依据）。每组件的 slot / boolean 演示义务以本 plan §组件真源表为准（该表由 config 确定性导出，非启发式）。
- **F45 硬红线**（AGENTS 硬规则 #8，L4 blocking pre-commit gate）：任何 commit 前 `pnpm audit:demo-slot-boolean` 必须 exit 0。它解析 `App.tsx + react-pilot/src/demos/*.tsx` 合并判定（任一 React 源满足即达标）。
- **parity blocking**（已生效）：`scripts/audit-demo-framework-parity.mjs` 的 `REPORT_ONLY=false`。每组件的 Vue region 英文 section 标题集必须 == React demo 英文 section 标题集，否则 exit 1。
- **一份源两消费**：React demo 内容只写在 `react-pilot/src/demos/*.tsx`，被 docs island 与 standalone gallery（App.tsx）双消费，禁止复制第三份。
- **CSS parity（owner 补的通用约束①）**：Vue 页 demo 区的 bespoke scoped 样式必须抽成共享非 scoped CSS（`demos/<c>-demo.css`），Vue 页 + React demo 都 import；跨页共享类已单一收敛在 `demos/demo-shared.css`（现状已是 canonical 值，见 Task 0），组件专属类进 `<c>-demo.css` 并 `@import './demo-shared.css'`。
- **交互 parity（owner 补的通用约束②）**：React demo 必须镜像 Vue 页交互行为（如 hover 用 JS 切 `status=hover` 而非 CSS `:hover`，需接 mouseenter/leave），不只静态结构。
- **双语**：demo 标签走 `t(en, zh)`（`makeT(locale)`）；parity audit 以英文 section 标题为锚。
- **主题**：island 接 `theme: 'dark'|'light'`，wrapper 内按 `theme==='dark'?'on':'off'` 派生；single theme only（no side-by-side）。
- **图标**：任何图标从 `dist/icons/svg/` 取或用既有 `<Icon>`，禁内联自画 SVG。
- **React 不进发布产物**：demo/react 只在 docs 构建链，npm 包 `vite build` 走 `src/index.ts` 产 Vue-only dist。
- **Commit 纪律**：subagent **不自 commit**；plan owner 复审工作树 diff + reviewer Approved + owner ack 后由 owner `git commit -F` + 三端 push（`git push origin master` 同推 gitea+github）；React demo 视觉改动 commit 需 `VISUAL_COMMIT_APPROVED=1`；`react-pilot/dist` 批量末尾统一重建 commit 一次。
- **reviewer rationale 独立核实**：review demo 报告"结果 OK"≠"理由真实"，rationale 必须独立 grep/Read 实证（防 Codex 编造看似合理约束）。

---

## 组件真源表（config 确定性导出 — subagent 演示义务以此为准）

pilot 已 demo：Button（default slot）、PopupBox（footer slot + closable/closeOnBackdrop/closeOnEscape/showFooter）、Table（striped）、Chart（OUT）。

fan-out 21 页（页 → canonical 组件 → slot/bool）：

| 页 | canonical 组件 | defaultSlot | named slots | boolProps（全量） | F45 | 难度 |
|---|---|---|---|---|---|---|
| Badge | Badge | ✓ | — | — | in | 低 |
| Radio | Radio | ✓ | — | — | in | 低 |
| Pagination | Pagination | — | — | — | **OUT** | 低 |
| Switch | Switch | — | — | — | **OUT** | 低 |
| Checkbox | CheckBox | ✓ | — | `readonly` | in | 中 |
| Input | InputBoxLine, InputBoxFilled | ✗ | — | `readonly`（两者） | in | 中 |
| InputNumber | InputNumber | ✗ | — | `disabled` | in | 中 |
| Slider | Slider | ✗ | — | `disabled, showValue` | in | 中 |
| FormItem | FormItem | ✓ | `label` | `required` | in | 中 |
| Message | Message | ✗ | — | `closable` | in | 中 |
| Notification | Notification | ✗ | — | `closable` | in | 中 |
| Progress | Progress | ✗ | — | `showLabel` | in | 中 |
| Rating | Rating | ✗ | — | `readonly` | in | 中 |
| Pill | PillStatus, PillCounter | ✓/✓ | Status:`count` | Status:`active` | in | 中 |
| Steps | Steps, StepItem | ✓/✗ | — | StepItem:`showLeadingConnector, showTrailingConnector` | in | 中 |
| Tabs | TabList, Tab, TabItem | ✓ | — | TabItem:`disabled` | in | 中 |
| Breadcrumb | Breadcrumb, BreadcrumbItem | ✓/✓ | — | BreadcrumbItem:`showSeparator` | in | 中 |
| Tooltip | Tooltip | ✓ | `content` | `disabled, open` | in | 高 |
| Select | SelectBoxLine, SelectBoxFilled | ✗ | — | `multiple, editable`（两者） | in | 高 |
| DateTime | SelectBox 家族* | ✗ | — | `multiple, editable`* | in | 高 |
| TopBar | TopBar | ✗ | `menu, right-content`（Figma 正式 SLOT）+ `logo/left/search`（code 便利） | `showMenu, showSearchBox` | in | 高 |

\* DateTime/Select 具体涉及哪些 config 组件由 subagent 读对应 `*Page.vue` 的 import + template 确认（都指向 SelectBox 家族）。TopBar F45 slotOk 只要任一 slot 投影即达标。

**Batch 分组**（难度递增 + Batch 1 作范式验证批，绿了再放量）：

- **Batch 1（范式验证批，3）**：Badge, Checkbox, Pagination — 覆盖「slot-only / slot+bool / OUT 纯展示」三形态 + 走通集成流程 + tech-debt#2 gallery 策略。
- **Batch 2（表单/选择，5）**：Input, InputNumber, Slider, FormItem, Radio。
- **Batch 3（反馈/状态，5）**：Message, Notification, Progress, Rating, Pill。
- **Batch 4（导航 + OUT，4）**：Steps, Tabs, Breadcrumb, Switch。
- **Batch 5（复杂交互，4）**：Select, DateTime, Tooltip, TopBar。

---

## §Recipe — 单组件 fan-out 配方（每批 subagent 照抄，参数见各批表）

> 本节是所有 fan-out 组件的 canonical 步骤。每个 subagent 负责 **1 个组件页**，只创建/修改下列 **3 个互不重叠文件**，**严禁**碰 `react-pilot/src/App.tsx`、`scripts/audit-demo-framework-parity.mjs`（PILOT_MAP）、`scripts/audit-demo-slot-boolean-coverage.mjs`、`.husky/pre-commit`（这些由主线统一集成，subagent 碰了会引发并行冲突）。

### R-Files（每组件）
- **Create**: `react-pilot/src/demos/<C>.tsx`
- **Create**: `react-pilot/src/demos/<c>-demo.css`（小写文件名）
- **Modify**: `playground/docs/pages/<C>Page.vue`

### R-Step 1: 读源页，锚定要镜像的 demo section
Read `playground/docs/pages/<C>Page.vue`。列出 `<template>` 中 demo 区的每个 `<section class="docs-section">` 的英文 `<h2 class="docs-section__title">` 文本（`t('En','Zh')` 取 En）。**排除** API 表 / TOC section（那些留在 region 外）。这份英文标题列表是 parity audit 的比对锚——React demo 必须逐字复现。

### R-Step 2: 创建 `demos/<c>-demo.css`
```css
/*
 * <c>-demo.css
 * <C>-page-SPECIFIC demo styles. Imported by both:
 *   - react-pilot/src/demos/<C>.tsx        (React island)
 *   - playground/docs/pages/<C>Page.vue    (via @demos alias)
 * Cross-page shared classes live once in demo-shared.css (INFRA-F46 convergence).
 * Rules here are global (non-scoped): <C>-UNIQUE classes only.
 */
@import './demo-shared.css';

/* ---- <c>-specific styles ---- */
/* 把 <C>Page.vue <style scoped> 里 demo 区的组件专属类搬来（去 scoped）；
   跨页共享类（.docs-section*/.docs-demo*/.docs-demo-card*/.code-block/.coverage-grid* 等）
   不要重复，它们已在 demo-shared.css。 */
```
把 `<C>Page.vue` 原 `<style scoped>` 里**只属于本组件 demo 区**的类迁到此文件（去 scoped）。base 类（`.docs-section`/`.docs-demo`/`.docs-demo-grid`/`.docs-demo-card*` 等 docs.css base）不迁——docs island 由 docs shell 载 docs.css，standalone gallery 侧由 Task 0/6 的 tech-debt#2 策略统一解决。

### R-Step 3: 创建 `demos/<C>.tsx`（镜像 Vue 页 demo 区）
```tsx
import { useState } from 'react'         // 有 bool live / 交互时；无则删
import '@tvu/wc'                          // side-effect: register custom elements（必须）
import { <Wrapper> } from '../wrappers/<Wrapper>'  // 一或多个，见各批表
import type { DemoProps } from './types'
import { makeT } from './types'
import './<c>-demo.css'

export default function <C>Demo({ theme, locale }: DemoProps) {
  const t = makeT(locale)
  // bool live（对每个 config boolProp 建 useState + toggle 控件）：
  // const [readonly, setReadonly] = useState(false)
  return (
    <div className="docs-page">
      {/* 逐个镜像 R-Step 1 列出的 section，英文标题逐字一致 */}
      <section className="docs-section">
        <h2 className="docs-section__title">{t('<En Title>', '<Zh Title>')}</h2>
        {/* 镜像该 section 的 demo 内容：
            - slot 投影：<Wrapper>真内容</Wrapper> 或 named-slot prop 传值（非空）
            - bool live：<Wrapper readonly={readonly} /> + 一个 CheckBox/Switch 驱动 setReadonly
            - 交互 parity：hover 类用 onMouseEnter/Leave 切 status，非 CSS :hover
            - theme：需要时按 theme==='dark'?'on':'off' 派生下发 */}
      </section>
    </div>
  )
}
```
**F45 义务**（in-scope 组件）：demo 中必须对该组件**每个 config boolProp** 有 useState 驱动的 live toggle，且**至少一处 slot 投影**（default slot 有非空 children，或 named slot prop 传非空值）。OUT 组件（Pagination/Switch）无此义务，只需 full-parity 静态/交互镜像。

### R-Step 4: 改 `<C>Page.vue` 接 FrameworkDemoRegion
`<script setup>` 加：
```ts
import FrameworkDemoRegion from '../components/FrameworkDemoRegion.vue'
import '@demos/<c>-demo.css'
```
`<template>` 把 demo 区 section（R-Step 1 锚定的那些）用以下包裹，**API 表 / TOC section 留在包裹器外**：
```html
<FrameworkDemoRegion
  :loader="() => import('@demos/<C>')"
  :locale="(props.locale as 'en-US' | 'zh-CN')"
>
  <!-- demo 区 section 原样保留在这里 -->
</FrameworkDemoRegion>
```
> `locale` 是页 prop（DocsShell 传 `:locale`）。若页 `<style scoped>` 里 demo 专属类已迁到 `<c>-demo.css`，从 scoped 块删除避免重复（base 类保留）。

### R-Step 5: subagent 结构自检（不跑全量工具，避免并行读中间态）
- Read 回 `demos/<C>.tsx` 与 `<C>Page.vue`，**逐字核对**两侧英文 section 标题列表一致（parity 预检）。
- 确认 in-scope 组件每个 boolProp 都有 `useState` + toggle 控件、至少一处 slot 投影（F45 预检）。
- 确认所有图标来自 `<Icon>` 或 `dist/icons/svg/`（无内联 SVG）。
- **报告**给主线：3 个文件 diff + 两侧标题列表 + boolProp/slot 落点清单。**不 commit，不改 App.tsx/PILOT_MAP，不跑 build/audit**（主线集成时统一跑权威闸）。

---

## Task 0: 预备 — 共享层现状确认 + tech-debt 裁定

**Files:**
- Read-only 确认：`react-pilot/src/demos/demo-shared.css`
- （tech-debt#2 视裁定）Modify: `react-pilot/src/App.tsx` 或 `demos/demo-shared.css`

**Interfaces:** Produces：确认 fan-out 的共享 CSS 基线稳定；tech-debt#2/#3 有明确处置。

- [ ] **Step 1: 确认 tech-debt#1 已落地（无需动作）**

Read `react-pilot/src/demos/demo-shared.css`。确认 `.docs-demo-card__summary` 已是 `var(--text-2)`/13px、`.code-block` 已含 `border`+`--r-xl`+`--text-1`+13px/1.7（canonical 值）。backlog 文字 stale，现状即收敛后基线，fan-out 直接继承。

- [ ] **Step 2: tech-debt#2（standalone gallery 缺 docs.css base 类）策略落地**

在 Batch 1 集成后（有真实新 demo 进 gallery 可验证），落地策略：**推荐** = react-pilot gallery 入口（`react-pilot/src/main.tsx` 或 `index.html`）直接 import docs 的 base 样式，或把 base demo 类（`.docs-section`/`.docs-demo`/`.docs-demo-grid`/`.docs-demo-card*`）纳入 `demo-shared.css` 单一真源。选定后 `cd react-pilot && pnpm build` 核实 gallery 不塌陷。**仅影响 standalone gallery，不阻塞 docs island**——可推迟到 Task 6 收尾统一做。

- [ ] **Step 3: tech-debt#3（coverage-chip / token-chip 合并）裁定**

**推荐** = defer（不进本 plan scope）。fan-out 若新组件需要 chip，沿用 `.coverage-chip`（table 风格）或组件专属 chip，不强制合并；合并留作独立低优先清理。

- [ ] **Step 4: 交 plan owner 复审裁定**（Task 0 无代码强制项，owner ack tech-debt#2/#3 处置后进 Batch 1）

---

## Task 1: Batch 1 — 范式验证批（Badge / Checkbox / Pagination）

**目的**：3 个组件覆盖「slot-only / slot+bool / OUT」三形态，先跑通 fan-out 范式在非 pilot 手上的可复现性 + 主线集成流程 + tech-debt#2 gallery 策略，再放量。

**Files（本批产出）:**
- Create: `demos/Badge.tsx` + `badge-demo.css`；`demos/CheckBox.tsx` + `checkbox-demo.css`；`demos/Pagination.tsx` + `pagination-demo.css`
- Modify: `pages/BadgePage.vue`、`pages/CheckboxPage.vue`、`pages/PaginationPage.vue`
- Modify（主线集成）: `react-pilot/src/App.tsx`、`scripts/audit-demo-framework-parity.mjs`

**本批组件参数（其余见 §组件真源表）:**

| 组件 | demo 文件 | wrapper | slot | bool | App.tsx 现卡片 |
|---|---|---|---|---|---|
| Badge | `Badge.tsx` | `Badge` | default | — | Feedback/status Section |
| CheckBox | `CheckBox.tsx` | `CheckBox` | default | `readonly` | Selection Section |
| Pagination | `Pagination.tsx` | `Pagination` | — | —（OUT） | Navigation Section（App.tsx L287） |

- [ ] **Step 1: 并行派 3 个 subagent（各 1 组件，照 §Recipe）**

用 superpowers:subagent-driven-development / dispatching-parallel-agents 并行派 3 个 subagent。每个 subagent prompt = §Recipe 全文 + 该组件参数行 + 本 plan §组件真源表对应行 + Global Constraints。**明确边界**：只碰该组件的 3 个独立文件，禁碰 App.tsx / PILOT_MAP / audit / husky；不 commit；R-Step 5 结构自检后报告。3 组件文件互不重叠 → 同工作树并行安全。

- [ ] **Step 2: 主线复审 3 份 subagent 报告 + 独立核实 rationale**

对每份报告：Read 回 3 个文件，独立核对两侧英文标题一致、boolProp/slot 落点真实存在（防编造）、CSS 迁移正确（专属类进 `<c>-demo.css` + `@import demo-shared.css`，base 类未重复）。

- [ ] **Step 3: 主线集成 App.tsx（加 import + 消费）**

对本批 3 组件，在 `react-pilot/src/App.tsx`：顶部加 `import BadgeDemo from './demos/Badge'`（Checkbox/Pagination 同）；把对应 Section 里的旧卡片替换为 `<BadgeDemo theme={theme} locale="en-US" />`（grep 定位现有卡片行，如 Pagination 在 L287）。保持 F45 面完整（bool/slot 现由 demos/*.tsx 提供）。

- [ ] **Step 4: 主线集成 PILOT_MAP**

在 `scripts/audit-demo-framework-parity.mjs` 的 `PILOT_MAP` 加（key 小写）：
```js
badge: { vue: resolve(__dirname,'..','playground','docs','pages','BadgePage.vue'), react: resolve(__dirname,'..','react-pilot','src','demos','Badge.tsx') },
checkbox: { vue: resolve(__dirname,'..','playground','docs','pages','CheckboxPage.vue'), react: resolve(__dirname,'..','react-pilot','src','demos','CheckBox.tsx') },
pagination: { vue: resolve(__dirname,'..','playground','docs','pages','PaginationPage.vue'), react: resolve(__dirname,'..','react-pilot','src','demos','Pagination.tsx') },
```

- [ ] **Step 5: 主线跑权威双闸 + 类型 + 构建**

Run:
```
pnpm exec vue-tsc --noEmit
pnpm audit:demo-slot-boolean
pnpm audit:demo-framework-parity
pnpm build:playground
```
Expected: 全 exit 0；parity 新增 3 组件行 PASS；F45 exit 0（Badge/CheckBox slot+bool 从 demos 判定，Pagination OUT 不误纳）。**任一 FAIL → 定位到具体组件修（标题不一致 / bool 缺 useState / slot 缺投影），必要时回派该组件 subagent。**

- [ ] **Step 6: tech-debt#2 gallery 策略验证（借本批真实新 demo）**

按 Task 0 Step 2 选定策略实施，`cd react-pilot && pnpm build && cd ..` 核实 gallery 里 3 个新 demo 不塌陷（base 类到位）。

- [ ] **Step 7: playwright 截图核实（抽验 1-2 页 × 双框架 × 双主题）**

临时 playwright 脚本放项目内，`pnpm exec vite preview --outDir playground-dist` 起站，截 Badge + Checkbox 页 `#/component/badge`/`checkbox` × {Vue, React} × {dark, light}。`ls -la` 核实 png 真实存在。Expected：React 态 demo 区渲染完整、主题跟随、Checkbox readonly toggle 可交互。

- [ ] **Step 8: 交 plan owner 复审（本批 checkpoint）**

报告：3 组件 diff stat + 双闸/vue-tsc/build stdout + 截图路径。**owner ack 范式可复现后**进 Batch 2。（本批不单独 commit；见 Task 6 统一 commit；如 owner 要分批 commit 则 owner `git commit -F` + `VISUAL_COMMIT_APPROVED=1` + 三端 push。）

---

## Task 2: Batch 2 — 表单/选择（Input / InputNumber / Slider / FormItem / Radio）

**Files（本批产出）:**
- Create: 5 组 `demos/<C>.tsx` + `<c>-demo.css`（Input/InputNumber/Slider/FormItem/Radio）
- Modify: `pages/{Input,InputNumber,Slider,FormItem,Radio}Page.vue`
- Modify（主线集成）: `App.tsx`、`audit-demo-framework-parity.mjs`

**本批组件参数（其余见 §组件真源表）:**

| 组件 | demo 文件 | wrapper(s) | slot | bool |
|---|---|---|---|---|
| Input | `Input.tsx` | `Input`(InputBoxLine), `InputBoxFilled` | — | `readonly`（两者） |
| InputNumber | `InputNumber.tsx` | `InputNumber` | — | `disabled` |
| Slider | `Slider.tsx` | `Slider` | — | `disabled, showValue` |
| FormItem | `FormItem.tsx` | `FormItem` | default, `label` | `required` |
| Radio | `Radio.tsx` | `Radio` | default | — |

> Input 页涉及 line + filled 两 canonical 组件，两者都要 `readonly` live toggle。FormItem 有 named slot `label`（传非空值）+ default slot。

- [ ] **Step 1: 并行派 5 个 subagent**（照 §Recipe + 本批参数，边界同 Task 1 Step 1）
- [ ] **Step 2: 主线复审 5 份报告 + 独立核实 rationale**（同 Task 1 Step 2）
- [ ] **Step 3: 主线集成 App.tsx**（5 组件 import + 替换对应 Form/Selection Section 卡片）
- [ ] **Step 4: 主线集成 PILOT_MAP**（加 `input`/`inputnumber`/`slider`/`formitem`/`radio` 5 条，格式同 Task 1 Step 4）
- [ ] **Step 5: 主线跑权威双闸 + vue-tsc + build:playground**（命令同 Task 1 Step 5；Expected 全 exit 0，新增 5 行 parity PASS）
- [ ] **Step 6: playwright 抽验**（截 Slider + FormItem 页 × 双框架 × 双主题，核 bool live 交互 + label slot 渲染；ls 核实 png）
- [ ] **Step 7: 交 plan owner 复审（批 checkpoint）**

---

## Task 3: Batch 3 — 反馈/状态（Message / Notification / Progress / Rating / Pill）

**Files（本批产出）:**
- Create: 5 组 `demos/<C>.tsx` + `<c>-demo.css`（Message/Notification/Progress/Rating/Pill）
- Modify: `pages/{Message,Notification,Progress,Rating,Pill}Page.vue`
- Modify（主线集成）: `App.tsx`、`audit-demo-framework-parity.mjs`

**本批组件参数（其余见 §组件真源表）:**

| 组件 | demo 文件 | wrapper(s) | slot | bool |
|---|---|---|---|---|
| Message | `Message.tsx` | `Message` | — | `closable` |
| Notification | `Notification.tsx` | `Notification` | — | `closable` |
| Progress | `Progress.tsx` | `Progress` | — | `showLabel` |
| Rating | `Rating.tsx` | `Rating` | — | `readonly` |
| Pill | `Pill.tsx` | `PillStatus`, `PillCounter` | Status: default + `count` | Status: `active` |

> Message/Notification 是 overlay 类（照 pilot PopupBox 范式：teleport 到真 body、模态定位）。Pill 页涉及 PillStatus + PillCounter 两组件，`active` bool 在 PillStatus。

- [ ] **Step 1: 并行派 5 个 subagent**（照 §Recipe + 本批参数；Message/Notification 提示 subagent 参考 `demos/PopupBox.tsx` 的 overlay/teleport 范式）
- [ ] **Step 2: 主线复审 5 份报告 + 独立核实 rationale**
- [ ] **Step 3: 主线集成 App.tsx**（5 组件 import + 替换 Message/Notification/Feedback Section 卡片）
- [ ] **Step 4: 主线集成 PILOT_MAP**（加 `message`/`notification`/`progress`/`rating`/`pill` 5 条）
- [ ] **Step 5: 主线跑权威双闸 + vue-tsc + build:playground**
- [ ] **Step 6: playwright 抽验**（截 Notification（overlay 居中整页证据）+ Pill 页 × 双框架 × 双主题；ls 核实 png）
- [ ] **Step 7: 交 plan owner 复审（批 checkpoint）**

---

## Task 4: Batch 4 — 导航 + OUT（Steps / Tabs / Breadcrumb / Switch）

**Files（本批产出）:**
- Create: 4 组 `demos/<C>.tsx` + `<c>-demo.css`（Steps/Tabs/Breadcrumb/Switch）
- Modify: `pages/{Steps,Tabs,Breadcrumb,Switch}Page.vue`
- Modify（主线集成）: `App.tsx`、`audit-demo-framework-parity.mjs`

**本批组件参数（其余见 §组件真源表）:**

| 组件 | demo 文件 | wrapper(s) | slot | bool |
|---|---|---|---|---|
| Steps | `Steps.tsx` | `Steps`, `StepItem` | Steps: default | StepItem: `showLeadingConnector, showTrailingConnector` |
| Tabs | `Tabs.tsx` | `TabList`, `Tab`, `TabItem` | default（各） | TabItem: `disabled` |
| Breadcrumb | `Breadcrumb.tsx` | `Breadcrumb`, `BreadcrumbItem` | default（各） | BreadcrumbItem: `showSeparator` |
| Switch | `Switch.tsx` | `Switch` | — | —（OUT） |

> Steps/Tabs/Breadcrumb 是复合组件（父 + item 子件），bool 义务落在子件（StepItem/TabItem/BreadcrumbItem），demo 要对子件的每个 bool 做 live toggle。Switch OUT（无 slot/bool），full-parity 静态+交互镜像即可（照 Pagination 范式）。

- [ ] **Step 1: 并行派 4 个 subagent**（照 §Recipe + 本批参数）
- [ ] **Step 2: 主线复审 4 份报告 + 独立核实 rationale**
- [ ] **Step 3: 主线集成 App.tsx**（4 组件 import + 替换 Navigation/Selection Section 卡片，Switch 在 App.tsx L158）
- [ ] **Step 4: 主线集成 PILOT_MAP**（加 `steps`/`tabs`/`breadcrumb`/`switch` 4 条）
- [ ] **Step 5: 主线跑权威双闸 + vue-tsc + build:playground**
- [ ] **Step 6: playwright 抽验**（截 Tabs + Steps 页 × 双框架 × 双主题，核子件 bool live；ls 核实 png）
- [ ] **Step 7: 交 plan owner 复审（批 checkpoint）**

---

## Task 5: Batch 5 — 复杂交互（Select / DateTime / Tooltip / TopBar）

**Files（本批产出）:**
- Create: 4 组 `demos/<C>.tsx` + `<c>-demo.css`（Select/DateTime/Tooltip/TopBar）
- Modify: `pages/{Select,DateTime,Tooltip,TopBar}Page.vue`
- Modify（主线集成）: `App.tsx`、`audit-demo-framework-parity.mjs`

**本批组件参数（其余见 §组件真源表）:**

| 组件 | demo 文件 | wrapper(s) | slot | bool | 注意 |
|---|---|---|---|---|---|
| Select | `Select.tsx` | `SelectBoxLine`, `SelectBoxFilled` | — | `multiple, editable`（两者） | 下拉 overlay teleport；参考 PopupBox teleport 范式 |
| DateTime | `DateTime.tsx` | SelectBox 家族* | — | `multiple, editable`* | subagent 读 DateTimePage 确认具体 wrapper |
| Tooltip | `Tooltip.tsx` | `Tooltip` | default, `content` | `disabled, open` | overlay；`open` bool live 控显隐、`content` named slot |
| TopBar | `TopBar.tsx` | `TopBar` | `menu`, `right-content`（Figma 正式）+ `logo/left/search`（code 便利） | `showMenu, showSearchBox` | slotOk 任一投影即达标；镜像 TopBarPage 现状 |

> Select/DateTime/Tooltip 都有 overlay/浮层，subagent 参考 `demos/PopupBox.tsx` 的 teleport-to-body 范式确保浮层不困在小盒。TopBar slot 真源已闭环（Figma 2 正式 slot + 3 code 便利，见 plan 头）。

- [ ] **Step 1: 并行派 4 个 subagent**（照 §Recipe + 本批参数）
- [ ] **Step 2: 主线复审 4 份报告 + 独立核实 rationale**
- [ ] **Step 3: 主线集成 App.tsx**（4 组件 import + 替换 Selection/Navigation Section 卡片）
- [ ] **Step 4: 主线集成 PILOT_MAP**（加 `select`/`datetime`/`tooltip`/`topbar` 4 条）
- [ ] **Step 5: 主线跑权威双闸 + vue-tsc + build:playground**
- [ ] **Step 6: playwright 抽验**（截 Select（下拉浮层）+ Tooltip（浮层）+ TopBar 页 × 双框架 × 双主题，核浮层不裁切；ls 核实 png）
- [ ] **Step 7: 交 plan owner 复审（批 checkpoint）**

---

## Task 6: 收尾 — 全量验证 + gallery + dist 重建 + STATUS/backlog + 交付

**Files:**
- Modify: `react-pilot/dist/*`（重建）、`docs/STATUS.md`、`docs/internal/backlog.md`、`docs/internal/STATUS-CHANGELOG.md`

- [ ] **Step 1: tech-debt#2 gallery 策略最终确认**

若 Task 0/1 未收口，此处统一实施 gallery base 类策略，`cd react-pilot && pnpm build` 核实全部 25 个 demo（4 pilot + 21 fan-out）在 standalone gallery 不塌陷。

- [ ] **Step 2: 全 gates 扫一遍**

Run:
```
pnpm exec vue-tsc --noEmit
pnpm vitest run
pnpm audit:demo-slot-boolean
pnpm audit:demo-framework-parity
pnpm build:playground
cd react-pilot && pnpm build && cd ..
```
Expected: 全绿；parity = 4 pilot + 21 fan-out = 25 组件全 PASS；F45 exit 0（28 in-scope 全达标）；react-pilot gallery 不破。

- [ ] **Step 3: sprint 收尾 self-audit**

Run: `pnpm audit:self-audit-phase2`
Expected: exit 0（canonical-compliance / render-coverage / figma-library-vs-canonical / hard-rule-compliance）。

- [ ] **Step 4: 重建 react-pilot/dist（一次性）**

`cd react-pilot && pnpm build && cd ..`（已在 Step 2），确认 `react-pilot/dist` 含全部 fan-out demo（供 DualFrameworkPilot iframe / 部署回退）。

- [ ] **Step 5: 更新 STATUS.md + backlog INFRA-F46 + STATUS-CHANGELOG**

- STATUS：Last updated 改今天 + 摘要（F46 fan-out shipped：21 组件页 full-parity React islands 全接入，parity 25/25 PASS，F45 28-in-scope 绿）。旧摘要 prepend 进 STATUS-CHANGELOG.md。只留 open/blocked 项。
- backlog：INFRA-F46 更新为 fan-out 完成（或删除 open 部分，按 STATUS 只留未完成项原则）；tech-debt#3 若 defer 则单独低优先 entry。

- [ ] **Step 6: sprint 收尾 self-audit 3 类扫描 + 主动输出 finding**

按 AGENTS §Sprint 收尾 Self-Audit：spec gap / 实现 bug / doc lag 三类扫描，主动输出 finding，不等 owner 问。

- [ ] **Step 7: 交 owner 验收（不自 commit）**

汇总：全 gates stdout + 全 playwright 截图路径（ls 核实存在）+ diff stat。**owner ack 后**由 owner commit（`git commit -F` + 三端 push；React demo 视觉改动 `VISUAL_COMMIT_APPROVED=1`；`react-pilot/dist` 重建含在本次 commit）。

- [ ] **Step 8: owner live 终验 fan-out**（照 pilot：`playground-dist` 起 http.server，浏览器拨 React 抽验若干 fan-out 页真交互）+ 给下一步起手 prompt（若有）

---

## Self-Review（plan owner 已跑）

**Spec coverage**：spec §8「fan-out 剩余 in-scope 组件、每 subagent 一组互不重叠、主线复审 diff、照 F45 fan-out 范式」→ Task 1-5 分批 + §Recipe + subagent 边界；§5 parity blocking → 各批 Step 4-5（PILOT_MAP + 权威跑）；§6 F45 连续性 → 各批 Step 5 + Task 6 Step 2；§7.2 foundation no-op → 不在 fan-out scope（DocsShell 已禁用，pilot Task 12 已验）；backlog owner 补的 CSS parity①/交互 parity② → Global Constraints + §Recipe R-Step 2/3；tech-debt#1/#2/#3 → Task 0 + Task 6 Step 1。无 spec 缺口。

**Placeholder scan**：组件属性用 config 确定性表（非 TBD）；§Recipe 给完整可跑骨架 + 精确文件/类命名；PILOT_MAP 集成给 verbatim 代码；DateTime/Select 具体 wrapper 标注「subagent 读 Page 确认」是 port 既有非 TBD。无占位。

**Type consistency**：`DemoProps {theme,locale}` 贯穿所有 demo（同 pilot `demos/types.ts`）；`makeT(locale)`、`FrameworkDemoRegion` props `{loader, locale}`、PILOT_MAP `{vue, react}` 全程一致；boolProps/slot 名逐组件取自 config 表，与 F45 audit 判定同源。

**并行性 & 冲突隔离**：每批内 subagent 各负 1 组件、只碰 3 个互不重叠独立文件（demos/<C>.tsx + <c>-demo.css + <C>Page.vue），F45 按组件判定不互扰 → 同工作树并行安全，无需 worktree；共享文件（App.tsx / PILOT_MAP）由主线在每批 Step 3-4 串行机械集成，权威双闸在 Step 5 集中跑 → 零并行冲突。分批（3→5→5→4→4）让每批 checkpoint 早发现范式偏差、主线 context 可控。
