# Draft — T2 sample 4 audit 脚本算法

> Round 1 draft only. This file proposes static audit algorithms and contracts; it does not create `.mjs` scripts.

## 通用：verdict 输出 markdown 格式

All four audits should emit the plan §3.1 verdict shape, then the runner writes one combined report to `docs/internal/t2-sample-audit-report.md`.

````md
# T2 Sample Audit Report

Generated at: 2026-04-30T00:00:00.000Z
Page: BadgePage
Component: Badge

## Summary

| Audit | Verdict | Evidence | Findings |
|---|---|---|---:|
| alpha-theme-isolation | N/A | direct | 0 |
| beta-axis-coverage | pass | heuristic | 0 |
| gamma-runtime-fabrication | pass | direct | 0 |
| delta-token-purity | pass | heuristic | 0 |

## alpha-theme-isolation

```json
{
  "auditId": "alpha-theme-isolation",
  "page": "BadgePage",
  "component": "Badge",
  "verdict": "N/A",
  "evidenceLevel": "direct",
  "evidenceSource": ["generator-output"],
  "findings": [],
  "checkedAt": "2026-04-30T00:00:00.000Z"
}
```
````

Verdict write strategy options:

- Option A: four small scripts plus a report combiner
  - Pros: each audit stays focused; failures isolate cleanly.
  - Cons: more files and npm script wiring.
- Option B: one `audit-page-t2-sample.mjs` runner with four functions
  - Pros: shared parser utilities and one report write.
  - Cons: individual audit ownership less obvious.

Draft 建议倾向 Option B for the Badge sample, with internal function names matching the four audit ids;待 plan owner 拍板。

## α theme isolation

- 脚本文件名:
  - Option A: `figma-sync/audit-page-alpha-theme-isolation.mjs`
    - Pros: explicit.
    - Cons: four long filenames.
  - Option B: `figma-sync/audit-page.alpha.mjs`
    - Pros: compact.
    - Cons: less grep-friendly by audit name.
  - Option C: one combined `figma-sync/audit-page-t2-sample.mjs`
    - Pros: shared static parsing and one report.
    - Cons: less modular.

### 输入读取算法

Preferred for Round 2: static scan, no dev server.

```text
read generated members TS for Badge
  preferred implementation detail:
    import/parse generated object if Node can load TS through existing toolchain
    otherwise read as text and extract object with a small TS-aware parser/transpiler

read BadgePage.vue as text
  find FigmaMembersGrid invocation
  collect the `site-theme` / `:site-theme` expression if present
  if expression is a literal, resolve direct value
  if expression points to a const/ref in script setup, resolve simple literal initializer
  otherwise mark site theme evidence as heuristic and unknown
```

Static scan vs compiled DOM:

- Static SFC scan
  - Pros: fast; no dev server; matches prompt constraint.
  - Cons: cannot prove runtime conditional branches.
- Compiled DOM
  - Pros: closer to what users see.
  - Cons: violates Round 1/Round 2 audit constraint if it needs dev server.

### 判定算法

```text
variants = members.variants
themeVariants = variants where variant.theme is present

if themeVariants.length == 0:
  verdict = 'N/A'
  evidenceSource = ['generator-output']
  findings = info: "No S5 theme field in generated members."
else:
  siteTheme = resolved page-injected theme
  if siteTheme is unknown:
    verdict = 'fail'
    evidenceLevel = 'heuristic'
    finding error: "Cannot statically resolve siteTheme passed to FigmaMembersGrid."
  else:
    renderedVariants = static model of grid filter:
      variants where variant.theme == siteTheme
    if any rendered variant has theme != siteTheme:
      verdict = 'fail'
    else:
      verdict = 'pass'
```

### verdict 写出

- Badge expected: `verdict='N/A'`, `evidenceLevel='direct'`, `evidenceSource=['generator-output']`.
- If theme exists but page theme cannot be resolved statically, downgrade finding evidence to `heuristic`.

### 边界 case

- Component has no `theme` on any variant: write `N/A`, not pass/fail.
- Some variants have `theme` and others do not: fail with `mixed-theme-schema` because S5 must be per-variant once present.
- Page omits `siteTheme` while generated output has theme variants: fail; grid cannot prove isolation.
- `siteTheme` is a computed expression from app shell: mark heuristic; plan owner can decide whether static literal is required for sample pages.

## β figma axis coverage

- 脚本文件名:
  - Option A: `figma-sync/audit-page-beta-axis-coverage.mjs`
  - Option B: `figma-sync/audit-page.beta.mjs`
  - Option C: combined runner `figma-sync/audit-page-t2-sample.mjs`

### 输入读取算法

```text
read generated members axes
  build allowedByCodeProp:
    type -> Set('Circle', 'Rectangle')
    color -> Set('Green', 'Blue', 'Orange', 'Red', 'Black')
    tag -> Set('Filled', 'Line')

read BadgePage.vue
  parse <template> for <Badge ...> and <FigmaMembersGrid ...>
  collect static attributes:
    type="Circle"
    color="Green"
    tag="Filled"
  collect bound literal attrs:
    :color="'Green'"
  collect v-for sources:
    if `v-for="color in badgeColorMembers"` then resolve `badgeColorMembers` in script setup
  collect refs and const arrays:
    const badgeColors = ['Green', ...] as const
    const badgeColor = ref<...>('Green')
  collect simple template interpolation readouts only if they feed component props, not plain text
```

Recommended parser:

- Use `@vue/compiler-sfc` / `@vue/compiler-dom` if already available in project dependencies.
- Avoid regex-only parsing for template structure; regex can still be used for simple script literal collection after AST boundaries are known.

### 判定算法

```text
usedValues = Map<codeProp, Array<{ value, location, evidenceLevel }>>

for each used prop value:
  if value is a known literal:
    if value not in allowedByCodeProp[prop]:
      finding error off-axis value
  else if value is dynamic and unresolved:
    finding warn dynamic value cannot be statically proven

if any error finding:
  verdict = 'fail'
else:
  verdict = 'pass'

evidenceLevel = 'heuristic'
evidenceSource = ['vue-sfc-static-scan', 'generator-output']
```

### verdict 写出

- Include a compact evidence table: prop, used value, location, direct/heuristic.
- Dynamic unresolved values are warnings unless plan owner decides they should fail sample pages.

### 边界 case

- `:color="someRef"` where `someRef` cannot be resolved: warn `heuristic-unresolved-dynamic-prop`.
- `v-bind="variant.props"` inside `FigmaMembersGrid`: treat as generator-covered, not a hand-written prop source.
- Prop value has a registered alias in translation layer: out of scope for Badge sample unless Round 2 explicitly imports alias truth; otherwise warn, do not invent mapping.
- Text like `color = "{{ badgeColor }}"` in readout should not count as component prop usage.

## γ runtime fabrication

- 脚本文件名:
  - Option A: `figma-sync/audit-page-gamma-runtime-fabrication.mjs`
  - Option B: `figma-sync/audit-page.gamma.mjs`
  - Option C: combined runner `figma-sync/audit-page-t2-sample.mjs`

### 输入读取算法

Preferred grid boundary strategy:

- Use explicit wrapper attr: `<section data-figma-members>`.
- Inside the wrapper, generator cells/components must carry `data-figma-source="generator"` and `data-figma-member`.

Alternative:

- Locate `<FigmaMembersGrid>` in `BadgePage.vue`.
- Pros: no extra wrapper in page.
- Cons: cannot inspect internal cells from page static scan unless also reading grid SFC.

Draft 建议: require `data-figma-members` in the grid component root, not page hand-authored sections.

```text
read FigmaMembersGrid.vue template
  verify root/boundary contains data-figma-members
  verify v-for cell root contains data-figma-source="generator"
  verify rendered component receives data-figma-source="generator"

read BadgePage.vue template
  verify FigmaMembersGrid appears in the intended Figma Coverage area
  verify Try It / docs-demo hand-written blocks do not contain data-figma-source="generator"
```

### 判定算法

```text
if FigmaMembersGrid usage missing:
  fail: grid not present

if grid boundary attr missing in grid SFC:
  fail: cannot locate grid block

if any cell/component in grid template lacks generator marker:
  fail: generated cell not mechanically identifiable

if BadgePage has data-figma-source="generator" outside FigmaMembersGrid usage:
  fail: hand-written demo marked as generator output

if Try It controls appear inside grid template:
  fail: runtime fabrication leaked into grid

else pass

evidenceLevel = 'direct'
evidenceSource = ['vue-sfc-template-ast', 'dom-attribute']
```

### verdict 写出

- Findings should include selector-like locations, e.g. `playground/docs/components/FigmaMembersGrid.vue:<template> article[v-for]`.
- If location line numbers are available from compiler AST, include `file:line`.

### 边界 case

- Grid wrapper not found: fail with a single blocking finding; do not guess from card titles.
- Marker appears on hand-written `<Badge>` in Try It: fail because it pollutes generator provenance.
- Grid uses scoped slot for component rendering: require slot root to receive marker from grid slot props, otherwise fail/warn depending on static provability.
- Multiple `FigmaMembersGrid` instances on one page: require each boundary to carry component identity and audit all of them.

## δ token purity

- 脚本文件名:
  - Option A: `figma-sync/audit-page-delta-token-purity.mjs`
  - Option B: `figma-sync/audit-page.delta.mjs`
  - Option C: combined runner `figma-sync/audit-page-t2-sample.mjs`

### 输入读取算法

Files from plan §3.5:

- `src/canonical/Badge.vue`
- `playground/docs/pages/BadgePage.vue`
- `playground/docs/components/FigmaMembersGrid.vue`

```text
for each file:
  read text
  extract all <style> blocks with @vue/compiler-sfc descriptor
  for each style block:
    strip CSS block comments before scanning
    keep line offset mapping to original file
    scan for:
      #[0-9a-fA-F]{3,8}
      rgba?\([^)]*\)
```

CSS comment stripping:

- Preferred: strip comments while preserving newlines, so line numbers remain stable.
- Avoid scanning comments; comments can mention examples and create false failures.

### 判定算法

```text
matches = []

for each style block:
  stripped = stripCssCommentsPreserveLines(style.content)
  scan stripped for hex/rgb literals
  for each match:
    if match is inside allowed token-definition context:
      finding info/warn depending on plan owner decision
    else:
      finding error

if any error:
  verdict = 'fail'
else:
  verdict = 'pass'

evidenceLevel = 'heuristic'
evidenceSource = ['vue-static-css', 'static-css-regex']
```

### CSS 变量定义里的 hex 是否豁免

- Option A: no exemption in these three files
  - Pros: strongest alignment with hard rule #4; component/page CSS never defines raw token values.
  - Cons: token-definition files need a separate audit rule elsewhere.
- Option B: allow `--token: #abc` only in dedicated token source files
  - Pros: practical for `src/tokens/variables.css`.
  - Cons: must define "dedicated token source" in a truth document, not inside this script.
- Option C: allow any CSS variable definition with hex
  - Pros: fewer false positives.
  - Cons: invites local component token definitions and violates project token discipline.

Draft 建议 for this audit: Option A for the three checked files; Option B as a general project rule only if registered separately.

### verdict 写出

- For each match, list file, line, literal, and whether it was in a style block.
- Badge expected: pass.

### 边界 case

- `/* color: #fff */` comment: ignored after comment strip.
- `--local-token: #abc` in `FigmaMembersGrid.vue`: fail under Option A; if plan owner chooses Option B, still fail because file is not a token source.
- `rgb(var(--foo))`: current regex may match `rgb(...)`; decide whether CSS color functions around tokens are allowed. Draft suggests allow only if no numeric literal appears and finding is reviewed as heuristic.
- Hex in `<template>` code examples: out of δ scope because plan §3.5 says extract `<style>` blocks only.

## 关键决策点（plan owner 拍板）

- [ ] 静态扫 vs 编译产物
  - Option A: static SFC scan
    - Pros: obeys prompt, fast, no dev server.
    - Cons: dynamic runtime branches remain heuristic.
  - Option B: compiled DOM
    - Pros: closer to actual render.
    - Cons: violates current "不跑 dev server / 编译" boundary unless plan changes.
- [ ] grid 区块定位策略
  - Option A: `<section data-figma-members>` boundary in grid root
    - Pros: clear γ audit boundary.
    - Cons: grid implementation must include wrapper attr.
  - Option B: `<FigmaMembersGrid>` usage in page
    - Pros: no extra DOM convention.
    - Cons: weaker cell-level proof from page static scan.
- [ ] CSS 变量定义里 hex 是否豁免
  - Option A: no exemption in checked files.
  - Option B: allow only dedicated token source files.
  - Option C: allow any CSS custom property definition.
- [ ] 4 audit 单独跑 vs 合并跑
  - Option A: four scripts.
  - Option B: one combined runner with four functions.
- [ ] 报告 `.md` 路径定稿
  - Option A: `docs/internal/t2-sample-audit-report.md` per plan §3.6.
  - Option B: component-scoped path later, e.g. `docs/internal/audits/badge-t2-sample.md`.
- [ ] Dynamic prop unresolved handling in β
  - Option A: warn only.
  - Option B: fail sample pages until statically resolvable.
- [ ] `variant count` in grid meta
  - Option A: visible count after theme filter.
  - Option B: total source variant count.

## 自检

| 自检项 | 结果 |
|---|---|
| 4 audit 全部沿用 plan §3.1 verdict schema | ✓ |
| 每条 audit 都标 evidenceLevel | ✓ α direct/N-A, β heuristic, γ direct, δ heuristic |
| 每条 audit 都标 evidenceSource | ✓ |
| 静态扫边界 case 已列 | ✓ |
| 不写 `.mjs` 脚本本身 | ✓ |
| 不扩 audit 数量 | ✓ only α/β/γ/δ |
| 不让 audit 跑 dev server / 编译 | ✓ static SFC scan preferred |
| 没自决 | ✓ all strategy choices listed as decision points |
| 没扩范围 | ✓ no implementation files touched |
