# Prompt — INFRA-F19: docs site theme-aware 完整化

> **角色**：executor
> **范围**：修复 docs site 半成品 bug —— shell 已有 theme toggle 但 grid 不响应。让 `FigmaMembersGrid` 跟随全局 toggle，移除 18 个 page 的 `:site-theme="'dark'"` 静态注入，同步 audit gate 与 AGENTS.md 项目约束段。
>
> ⚠️ **不要 commit / 不要 git add**——dirty 累积到 plan owner 视觉验收通过后 commit。
> ⚠️ 完成后 **STOP**，按 §4 完成报告格式回报；§4 必须含完整改动清单段。
> ⚠️ **不扩范围**：文件清单见 §0，**不动 canonical / src/components / figma 真源 / generator / backlog.md / retrospection**。
> ⚠️ **关键参数 plan owner 已定**：inject key、provide 写法、prop API 已写定（见 §0），不要自行重设计。

---

## §0 — Plan owner 已定裁定

### 现状（直接事实）

| 层 | 状态 | 证据 |
|---|---|---|
| `DocsShell.vue` toggle 按钮 + watch isDark → `data-theme` attr | ✅ 已实现 | `DocsShell.vue:248-250 / 448-454 / 560` |
| `FigmaMembersGrid.vue` 按 `siteTheme` prop 过滤 variants | ✅ 已实现 | `FigmaMembersGrid.vue:24-30` |
| 18 个 page 写死 `:site-theme="'dark'"` | ❌ bug | `BadgePage.vue:85` 等 18 处（见 §0.4） |
| `audit-page-t2-sample.mjs:313-321` 强制 page 必须有 `:site-theme="dark|light"` | ❌ 与 F19 目标冲突 | gate 文字 'Cannot statically resolve siteTheme' |
| `AGENTS.md:158-165` 项目约束 "docs site dark-only" | ❌ 文档与代码分叉 | toggle 已加但约束未同步 |

### F19 目标

切到 dark 主题 → 所有 grid 只显示 dark variants（如有 theme axis）；切到 light → 只显示 light variants。无 theme axis 的 page 维持现状（grid fallback 显示全部，[FigmaMembersGrid.vue:25-27](../../../playground/docs/components/FigmaMembersGrid.vue#L25-L27)）。

### figma 数据现状（plan owner 已抽样）

| 类别 | 数量 | 文件 | 切 toggle 时表现 |
|---|---|---|---|
| 有 theme axis 且 dark/light 双向均有 variants | 8 | `checkbox / notification / progress / radio / rating / slider / switch / tooltip` | grid 内容随 toggle 变 |
| 无 theme axis | 9 | `badge / breadcrumbitem / inputnumber / pagination / promptmessage / stepitem / tabitem / table / tablist / topbar` | grid 显示全部 variants（无变化）—— OK，不是 bug |
| 有 theme axis 标记但 dark=0 light=0（**异常**） | 1 | `formitem` | **executor 实施时遇到先报告 §4 未解决项，不自作主张修 figma 数据** |
| dark/light 数量不对称（如 notification 15/14） | 多个 | `notification / progress / rating / slider 等` | 切 light 时 grid 少几张 —— 这是 figma 真源决定，**不是 docs site bug，不需要补齐** |

### 改造文件清单（共 22 个，**不可超出**）

| 文件 | 操作 |
|---|---|
| `playground/docs/DocsShell.vue` | 加 provide('docsTheme', ...) |
| `playground/docs/components/FigmaMembersGrid.vue` | 加 inject('docsTheme', ...)、prop 改 optional、computed 决定 effective theme |
| `playground/docs/pages/BadgePage.vue` | 删 `:site-theme="'dark'"` |
| `playground/docs/pages/CheckboxPage.vue` | 删 `:site-theme="'dark'"`（若有） |
| `playground/docs/pages/NotificationPage.vue` | 删 `:site-theme="'dark'"` |
| `playground/docs/pages/ProgressPage.vue` | 删 `:site-theme="'dark'"` |
| `playground/docs/pages/TooltipPage.vue` | 删 `:site-theme="'dark'"` |
| `playground/docs/pages/<其余有 :site-theme 的 page>.vue` | 删 `:site-theme="'dark'"` |
| `figma-sync/audit-page-t2-sample.mjs` | gate 反转（见 §0.5） |
| `AGENTS.md` | 项目约束段 158-165 重写（见 §0.6） |

**先用 grep 列全 `:site-theme` 出现位置确认 18 个 page 全覆盖**：

```bash
grep -rn "site-theme" playground/docs/pages/
```

→ 如果数量与 plan owner 列出的不一致，§4 报告里写实际清单。

### §0.1 — DocsShell.vue 改动

在 `<script setup>` 顶部加：

```typescript
import { provide, readonly, computed } from 'vue'
// (existing imports)

// Provide reactive docs theme to descendant components (FigmaMembersGrid).
// Components that want to bypass and force a specific theme can still pass
// `:site-theme="'dark'|'light'"` as override.
const docsTheme = computed<'dark' | 'light'>(() => (isDark.value ? 'dark' : 'light'))
provide('docsTheme', readonly(docsTheme))
```

inject key: **字面字符串 `'docsTheme'`**（不创新 Symbol，简单字符串便于多文件查找一致）。

### §0.2 — FigmaMembersGrid.vue 改动

```typescript
import { computed, inject, ref, type Ref } from 'vue'

const props = withDefaults(defineProps<{
  members: DocsFigmaMembers<TProps>
  component: Component
  siteTheme?: 'dark' | 'light'   // ← optional now (移除 default 'dark')
  cellMinWidth?: string
  metaLabel?: (members: DocsFigmaMembers<TProps>, visibleCount: number) => string
}>(), {
  cellMinWidth: '176px',
  // siteTheme: undefined 默认 → 跟随全局 docsTheme
})

const injectedTheme = inject<Readonly<Ref<'dark' | 'light'>>>('docsTheme', ref('dark'))

// effective theme: prop override → fallback to injected global theme
const effectiveTheme = computed<'dark' | 'light'>(() => props.siteTheme ?? injectedTheme.value)

// (existing hasThemeVariants computed unchanged)

const visibleVariants = computed(() => {
  if (!hasThemeVariants.value) {
    return props.members.variants
  }
  return props.members.variants.filter((variant) => variant.theme === effectiveTheme.value)
})
```

**保留 `siteTheme` prop 作为 escape hatch**：未来如有 page 想强制锁单 theme（如对比展示），仍可传 prop override 全局 toggle。F19 不使用此能力，但 API 保留。

### §0.3 — 18 个 page 改动（删 `:site-theme="'dark'"`）

每个 page 找到 `<FigmaMembersGrid ... :site-theme="'dark'" ... />`，**只删这一个 attr**，其它属性不动。

例：

```diff
- <FigmaMembersGrid :members="badgeFigmaMembers" :component="Badge" :site-theme="'dark'" />
+ <FigmaMembersGrid :members="badgeFigmaMembers" :component="Badge" />
```

**保留**：page 内任何 runtime 业务逻辑里的 `theme` 引用（如 `SliderPage.vue` 的 `darkSmallValue` 计算 / `theme === 'dark'` 比较 —— 这些是 runtime demo 数据，与 grid filter 无关，不动）。

**保留**：page 内任何 `theme: 'dark'` 默认值的 API table 文档（如 `NotificationPage.vue:31` `defaultValue: 'dark'`）—— 这是组件 prop 默认值文档，不动。

### §0.4 — page 列表与 :site-theme 出现位置（plan owner 已抽样）

确认包含但**可能不止**这些：

- `BadgePage.vue:85`
- `NotificationPage.vue:117`
- `ProgressPage.vue:68`
- `TooltipPage.vue:76`

请用 grep 确认全 18 个 page 是否都有 `:site-theme="'dark'"` 注入；若部分 page 没有（说明已是 toggle-aware 或漏改），直接跳过即可，§4 报告"实际找到 N 处删除"。

### §0.5 — audit-page-t2-sample.mjs 改动

`figma-sync/audit-page-t2-sample.mjs:313-321` 当前逻辑：

```javascript
const siteThemeMatch = template.match(/:site-theme\s*=\s*["'](?:'|")(dark|light)(?:'|")["']/)
const siteTheme = siteThemeMatch?.[1]
if (!siteTheme) {
  findings.push({
    severity: 'error',
    location: config.pageFile,
    message: 'Cannot statically resolve siteTheme passed to FigmaMembersGrid.',
  })
}
```

改为（**反转语义**：默认无 prop 是 OK = 跟随全局；如果有 prop，必须是 dark|light 字面量 才记录；不再因为缺 prop 报 error）：

```javascript
const siteThemeMatch = template.match(/:site-theme\s*=\s*["'](?:'|")(dark|light)(?:'|")["']/)
const siteTheme = siteThemeMatch?.[1]
// F19: siteTheme prop is now optional (defaults to global docsTheme inject).
// Page may omit the prop entirely → grid follows shell toggle (the new default).
// If the prop is present, it must be a static dark|light literal (escape hatch).
// We no longer error on missing prop; we still record evidence for downstream
// audits to know whether a page locked its grid to a specific theme.
```

且 `createVerdict` 调用对应改：

```javascript
return createVerdict(
  config,
  'alpha-theme-isolation',
  findings.some((finding) => finding.severity === 'error') ? 'fail' : 'pass',
  siteTheme ? 'direct' : 'heuristic',  // 保留 evidenceLevel：传了 prop = direct，跟随全局 = heuristic
  ['generator-output', 'vue-sfc-static-scan'],
  findings,
)
```

→ 改后所有 18 page（删了 prop 后）α verdict = pass + evidenceLevel = heuristic。

**注意**：`themeVariants.length !== members.variants.length` 那条 finding（line 303-309）保留，与 F19 无关。

### §0.6 — AGENTS.md 项目约束段重写

`AGENTS.md:158-165` 现状：

```markdown
- **Docs site 默认 dark-only 显示**（扩展自 `dark-theme-only-monitoring` memory rule）
  - `playground/docs/` 站本身 dark-only 渲染，无 light theme 切换 toggle
  - 改造 docs page 时**禁止**加 `Light Theme Members` / `Light Compare` / 任何同时显示 light variants 的 section
  - Theme-axis 组件（Tooltip / Notification / Switch / Radio / CheckBox / Select 等）在 `<FigmaMembersGrid>` 内用 `:site-theme="'dark'"` 静态注入，filter 后只渲染 dark variants
  - Figma 真源含 light variants 是合规的（generator 输出全部 variants 含 light）但 docs page 只显示 dark
  - 适用范围：所有 `playground/docs/pages/*Page.vue` 改造（Phase A4 + 后续）
  - **失效条件**：用户主动改 docs site 加 light mode toggle —— 在那之前 docs site dark-only 严格执行
  - 实证：commit f9ca71c 时 NotificationPage 改造误延续 BadgePage 含 Dark+Light Members 范式；commit c623544 已 fix；2026-05-06 Phase A4.1 复审用户提醒升级为正式约束
```

改为：

```markdown
- **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）
  - 默认主题：dark（`isDark = ref(true)` 初值）
  - **`:site-theme` prop 仍存在但已是 escape hatch**：page 不应主动注入；只在需要"对比展示"等极少数场景 override 全局 toggle 时使用，使用前先在 backlog 登记理由
  - 改造 docs page 范式：grid 不传 `:site-theme` → 跟随 toggle；page 内不再分 "Dark Theme Members" / "Light Theme Members" 两 section，单 grid 即可
  - 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 修复
```

---

## §1 — 必读输入

按顺序：

1. [`AGENTS.md`](../../../AGENTS.md) — 项目约束段（你将更新它）
2. [`docs/meta-rules.md`](../../meta-rules.md) — 反模式 + 触发器 G（不要 plan owner 抽象设计）
3. [`docs/internal/backlog.md`](../../backlog.md) — 看 INFRA-F19 / INFRA-F20 entry 上下文
4. [`playground/docs/DocsShell.vue`](../../../playground/docs/DocsShell.vue) — 待加 provide
5. [`playground/docs/components/FigmaMembersGrid.vue`](../../../playground/docs/components/FigmaMembersGrid.vue) — 待加 inject
6. [`figma-sync/audit-page-t2-sample.mjs`](../../../figma-sync/audit-page-t2-sample.mjs) — line 311-330 audit gate
7. `playground/docs/pages/*.vue` — 18 个 page，按 §0.4 删 `:site-theme="'dark'"`

---

## §2 — 任务清单（按顺序）

### 任务 2.1 — grep 确认 :site-theme 全覆盖

```bash
grep -rn "site-theme" playground/docs/pages/
grep -rn "siteTheme" playground/docs/components/ playground/docs/
```

把全部出现位置列出来，§4 报告中确认操作覆盖了它们。

### 任务 2.2 — 改 FigmaMembersGrid.vue（先改组件，后批量改 page）

按 §0.2 改造。

### 任务 2.3 — 改 DocsShell.vue

按 §0.1 加 provide。

### 任务 2.4 — 跑 dev 先验机制 OK（**关键中间验证**）

```bash
pnpm dev
```

打开浏览器，进任意一个 **有 theme axis 的 page**（推荐 NotificationPage 或 ProgressPage —— 此时 page 还没改，仍写 `:site-theme="'dark'"`）：

1. 切 toggle —— grid 内容**不应**变化（因 page 显式传 `:site-theme="'dark'"` override 全局）
2. 进任意一个 **无 theme axis 的 page**（如 BadgePage）：切 toggle —— grid 内容**不应**变化（无 theme filter）

→ 这一步验证 inject 机制不破现有 page。

如果切 toggle 反而破坏了 NotificationPage 的 grid 渲染 → 说明 inject 实现错误，停下来报告 plan owner，**不要继续 task 2.5**。

### 任务 2.5 — 批量改 18 个 page

按 §0.3 + grep 结果删 `:site-theme="'dark'"` 静态注入。

### 任务 2.6 — 改 audit-page-t2-sample.mjs

按 §0.5 反转 gate 语义。

### 任务 2.7 — 改 AGENTS.md

按 §0.6 重写项目约束段。

### 任务 2.8 — typecheck

```bash
pnpm exec vue-tsc --noEmit
```

→ 0 错误。

### 任务 2.9 — 跑 audit 全量

```bash
node figma-sync/audit-page-t2-sample.mjs
```

→ 18 个 page α verdict 全 pass（evidenceLevel=heuristic 因 prop 已删）。

### 任务 2.10 — 跑其它 audit baseline regression check

```bash
pnpm audit:figma-conformance
pnpm audit:docs-site
```

→ 不应有新 error；timestamps 之外不应有内容偏离。

### 任务 2.11 — dev 视觉 final（**等 plan owner 截图**，不自评）

```bash
pnpm dev
```

启动后 STOP 等 plan owner：

- 切 dark/light，确认 NotificationPage / ProgressPage / RatingPage / SwitchPage / SliderPage 等 8 个 theme-axis page 的 grid 真随 toggle 变
- 切 dark/light，确认 BadgePage / TablePage 等 9 个 non-theme-axis page 的 grid **不**随 toggle 变（保持显示全部 variants）
- 默认 dark 状态视觉应与 F19 改造前一致（baseline regression）

---

## §3 — 验收清单

- [ ] grep 列出 `:site-theme` 全部出现位置
- [ ] FigmaMembersGrid.vue 加 inject + prop 改 optional + effectiveTheme computed
- [ ] DocsShell.vue 加 provide('docsTheme', readonly(computed(...)))
- [ ] 任务 2.4 中间验证 OK（page 仍 hardcode 时 toggle 不变 grid）
- [ ] 18 个 page 删 `:site-theme="'dark'"`（按 grep 实际数量）
- [ ] audit-page-t2-sample.mjs gate 反转
- [ ] AGENTS.md 项目约束段重写
- [ ] vue-tsc 0 错误
- [ ] audit-page-t2-sample 18 page α 全 pass
- [ ] audit:figma-conformance / audit:docs-site 无新 error
- [ ] dev 启动等 plan owner 视觉确认（不自评）
- [ ] **不动**：canonical / src/components / figma 真源 / generator script / backlog.md / retrospection / translation / package.json
- [ ] 没 commit / 没 git add
- [ ] formitem 异常状态（has-theme=true 但 dark=0 light=0）已在 §4 未解决项中标注（如 dev 时遇到 grid 空白）

---

## §4 — 完成报告

```
## INFRA-F19 docs site theme-aware 完成报告

### 改动文件 (按 prompt 任务的预期 scope)
- playground/docs/DocsShell.vue (改 +X/-Y 行)
- playground/docs/components/FigmaMembersGrid.vue (改 +X/-Y 行)
- playground/docs/pages/<N 个 page>.vue (改 +X/-Y 行 each)
- figma-sync/audit-page-t2-sample.mjs (改 +X/-Y 行)
- AGENTS.md (改 +X/-Y 行)
- docs/internal/t2-sample-audit-report.*.md (重生)

### §4.X 完整改动清单 (All M / A / D, 含 prompt 范围外)
[git status --short 全列表]
[如有范围外改动，标 ⚠️ 解释]

### grep :site-theme 结果（任务 2.1）
[贴 grep 输出]

### FigmaMembersGrid.vue inject 改造 hunk
[贴 diff]

### DocsShell.vue provide 改造 hunk
[贴 diff]

### 任务 2.4 中间验证结果
- NotificationPage 切 toggle: <grid 不变 OK / 异常>
- BadgePage 切 toggle: <grid 不变 OK / 异常>

### 18 page :site-theme 删除清单
[列实际改的 N 个 page，每个 page diff 1 行]

### audit gate 反转 hunk
[贴 audit-page-t2-sample.mjs:311-330 改后 + before/after 对比]

### AGENTS.md 项目约束段 hunk
[贴 diff]

### typecheck
- vue-tsc: 0 错误

### audit verdict
- audit-page-t2-sample 18 page α: <全 pass / 异常>
- audit:figma-conformance: <pass / 偏离>
- audit:docs-site: <pass / 偏离>

### dev 视觉验收
- pnpm dev 启动: <OK / 失败>
- 等 plan owner 切 toggle 截图（executor 不自评）

### 验收 self-check
[逐条 §3 列表勾选]

### 未解决项 / blocker
- formitem 数据异常 (has-theme=true 但 dark=0 light=0): <dev 时表现 / 是否 grid 空白 / 建议>
- 其它发现: [...]
- 无则写"无"

STOP — 等 plan owner 复审 + 视觉验收 → 通过后 plan owner 自己写 retrospection + commit F19。
```

---

## §5 — 严守约束总览

- ⚠️ **不要 commit / 不要 git add**
- ⚠️ §0 文件清单 22 个**不可超出**（不动 backlog.md / retrospection / canonical / src/components / figma 真源 / generator script / translation / package.json）
- ⚠️ §0.1 / §0.2 / §0.5 / §0.6 实现已 plan owner 写定，**不要自行重设计 inject key 名 / provide 写法 / gate 文字**
- ⚠️ 任务 2.4 中间验证**必跑**——验机制后再批量改 page，不要先批量改完再发现 inject 实现错
- ⚠️ §4 完成报告**必须含 §4.X 完整改动清单段**
- ⚠️ dev 视觉**不自评**——启动 dev 后 STOP 等 plan owner
- ⚠️ formitem 数据异常**不要修 figma 真源**——只在 §4 未解决项报告
- ⚠️ 完成 STOP，按 §4 格式回报
