# Consumer Audit Setup — TVU Design System

> Quick guide for installing and running TVU's mockup + code audit tooling in a consumer product (a sibling repo that consumes `@nancyzeng0210/tvu-design-system`).
>
> **Why this exists in the DS repo, not as a separate package**: audits version-lock to the library. When you install `@nancyzeng0210/tvu-design-system@1.0.0`, you get exactly the audit rules that matched the library at that version — no drift, no separate plugin upgrade cycle.

---

## What ships

The main `@nancyzeng0210/tvu-design-system` npm package bundles:

| Tool | Type | Purpose |
|---|---|---|
| `audit-product-code.mjs` | CLI script | Lint consumer source code (R1 inline SVG / R2 hex color / R2S hardcoded spacing/radius / R15 hand-rolled native control / R16 CN+EN mixed string) |
| `audit-mockup-conformance.mjs` | CLI script | **Master gate** — runs all 5 mockup audits below against one file and aggregates pass/fail (`--non-blocking` for 场景 2). Use this as the single mockup entry point. |
| `audit-mockup-integrity.mjs` | CLI script | Lint a Figma mockup file (I1 sibling layout / I2 SECTION overlap / I3 children-bbox wrap / I4 page-level orphan parent) |
| `audit-mockup-colors.mjs` | CLI script | Lint a Figma mockup file (C1 icon path fill bound to Color Variable / C2 hover state / C3 BG vs text grey) |
| `audit-mockup-typography-icon.mjs` | CLI script | Lint a Figma mockup file (typography + icon library binding) |
| `audit-mockup-library-binding.mjs` | CLI script | Lint a Figma mockup file (M0 library instance / M1 Top bar / M30 icon library) |
| `audit-mockup-library-origin.mjs` | CLI script | Lint that mockup instances trace to the published library |
| `eslint-plugin` (subpath export) | ESLint 9 plugin | Overlapping code rules plus stricter import-path rules for editor + CI integration |

All ship inside the same `@nancyzeng0210/tvu-design-system` package via `files: ["dist", "eslint-plugin", "scripts", "templates", ...]` + subpath exports. No separate install needed.

`eslint-plugin` ships three configs: `incremental` (场景 2 report-only warnings), `recommended` (all listed rules as errors), and `strict` (recommended + arbitrary local/CDN SVG icon imports forbidden). Rules: `no-hardcoded-color` · `no-inline-svg` · `icon-from-dist` · `no-base-component-import` · `no-native-element` · `no-hardcoded-spacing`.

---

## Scenario-aware enforcement (read first — pick your wiring)

How strictly you wire these depends on which TVU consumption scenario you're in (see `code-conventions.md §R7` / `ds-enforcement-scenarios-spec.md §2`). **The wiring is not one-size-fits-all** — applying strict full-repo blocking to an existing product mass-flags legacy pre-design-system code and pushes you to "fix" debt you were told not to touch (R6).

| Scenario | What it is | Enforcement wiring |
|---|---|---|
| **场景 3 · Greenfield TVU** | A brand-new product built entirely on TVU | **STRICT / full repo, blocking.** Use `tvuEnforcementStrict` from `eslint.config.fragment.mjs`. Add a `lint` script that lints the whole repo and run it in CI + pre-commit. |
| **场景 2 · Existing-product increment** | Adding/changing a feature in a product that predates the DS | **INCREMENTAL / changed files only / report-only.** Use `tvuEnforcementIncremental` / `tvuEnforcement`, and check **only staged files** via `lint-staged.fragment.json` + a pre-commit hook. Do NOT add a full-repo blocking lint — legacy untouched files stay as-is, local legacy SVG icon imports remain allowed, and warnings must not be promoted to blockers by `--max-warnings=0` (R6). |
| **场景 1 · Non-TVU visual mirror** | Pixel-faithful rebuild of a third-party / non-TVU design | **OFF.** Omit the TVU ESLint layer; the visual source is authoritative, not the DS. |

The template ships the fragments to wire each: [`eslint.config.fragment.mjs`](../templates/consumer-product/eslint.config.fragment.mjs) (the rule layer) + [`lint-staged.fragment.json`](../templates/consumer-product/lint-staged.fragment.json) (the 场景 2 changed-files gate). The `setup-tvu-consumer` skill installs the right wiring for the scenario you declare.

---

## Install (one-time per consumer product)

### 1. npmrc config

Create or append to `.npmrc` in consumer repo root:

```
@nancyzeng0210:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
```

`YOUR_GITHUB_TOKEN` = a [GitHub Personal Access Token](https://github.com/settings/tokens) with `read:packages` scope.

### 2. Install the library

```bash
pnpm add @nancyzeng0210/tvu-design-system
```

This brings the components AND all the audit tooling in one install.

### 3. (Optional) Add npm script shortcuts to consumer `package.json`

```json
{
  "scripts": {
    "audit:code": "node node_modules/@nancyzeng0210/tvu-design-system/scripts/audit-product-code.mjs --dir src",
    "audit:mockup": "node node_modules/@nancyzeng0210/tvu-design-system/scripts/audit-mockup-conformance.mjs --file YOUR_FIGMA_FILE_KEY"
  }
}
```

Replace `YOUR_FIGMA_FILE_KEY` with the consumer's product Figma file key (the string between `/design/` and `/` in the Figma URL).

### 4. Add the ESLint enforcement layer

Spread the shipped fragment into your flat config (place AFTER your Vue/TS blocks — see the fragment header for why):

```js
// eslint.config.mjs
import { tvuEnforcementIncremental, tvuEnforcementStrict } from '@nancyzeng0210/tvu-design-system/templates/consumer-product/eslint.config.fragment.mjs'

export default [
  // ...your existing Vue + TS config blocks...
  tvuEnforcementIncremental, // 场景 2 existing-product increment
  // or tvuEnforcementStrict for 场景 3 greenfield TVU
]
```

Or inline for 场景 2 (equivalent to `tvuPlugin.configs.incremental`):

```js
import tvuPlugin from '@nancyzeng0210/tvu-design-system/eslint-plugin'

export default [
  {
    files: ['**/*.vue', '**/*.{js,jsx,ts,tsx}'],
    plugins: { '@nancyzeng0210/tvu-design-system': tvuPlugin },
    rules: {
      '@nancyzeng0210/tvu-design-system/no-hardcoded-color': 'warn',
      '@nancyzeng0210/tvu-design-system/no-inline-svg': 'warn',
      '@nancyzeng0210/tvu-design-system/icon-from-dist': 'warn',
      '@nancyzeng0210/tvu-design-system/no-base-component-import': 'warn',
      '@nancyzeng0210/tvu-design-system/no-native-element': 'warn',
      '@nancyzeng0210/tvu-design-system/no-hardcoded-spacing': 'warn',
    },
  },
]
```

Rule details: see `node_modules/@nancyzeng0210/tvu-design-system/eslint-plugin/README.md`.

### 5. Wire pre-commit (so violations can't land silently)

The biggest enforcement gap is config that exists but never runs. Wire a pre-commit gate matched to your scenario:

**场景 2 (incremental — recommended for existing products)** — gate changed files only:

```bash
pnpm add -D lint-staged husky
npx husky init                                   # creates .husky/
echo "npx lint-staged" > .husky/pre-commit
```

Merge [`lint-staged.fragment.json`](../templates/consumer-product/lint-staged.fragment.json) into your `package.json` `"lint-staged"` field (or a `.lintstagedrc.json`):

```json
{
  "lint-staged": { "*.{vue,js,jsx,ts,tsx}": "eslint" }
}
```

Inline strict override for 场景 3:

```js
rules: {
  '@nancyzeng0210/tvu-design-system/icon-from-dist': ['error', { forbidArbitrarySvg: true }],
}
```

**场景 3 (greenfield — full repo)** — additionally add a blocking `lint` script and run it in CI:

```json
{ "scripts": { "lint": "eslint .", "audit:code": "node node_modules/@nancyzeng0210/tvu-design-system/scripts/audit-product-code.mjs --dir src" } }
```

> The `setup-tvu-consumer` skill installs the matching wiring automatically once you declare the scenario (see its runbook Step 2.6).

---

## Running the audits

### Code audit (R1/R2/R16)

```bash
pnpm audit:code
# or directly:
pnpm exec node node_modules/@nancyzeng0210/tvu-design-system/scripts/audit-product-code.mjs --dir src
# scenario 2 existing-product increment — report without blocking:
pnpm exec node node_modules/@nancyzeng0210/tvu-design-system/scripts/audit-product-code.mjs --dir src --non-blocking
```

Exit code 0 = no findings, or findings reported under `--non-blocking`. Exit code 1 = findings + listed inline in blocking mode.

To disable a single line: `// AUDIT-IGNORE-R1: <reason>` (or R2 / R16) inline comment.

### Mockup audit — master gate (all 5 sub-audits)

`audit:mockup` now points at the `audit-mockup-conformance.mjs` master gate, which runs all five
mockup audits (integrity / colors / typography-icon / library-binding / library-origin) against one
file and aggregates a single pass/fail. This wires in `library-origin`, which previously had no npm
script and never ran.

Requires `FIGMA_PERSONAL_ACCESS_TOKEN` env (read scope on the product file) for the four live audits;
`library-binding` additionally needs a pre-fetched `figma-data/mockup/<fileKey>.json` (run
`pnpm sync:mockup <fileKey>` from the DS repo) — if absent it reports `⚠️ ERROR (could not run)` in the
summary rather than silently passing.

```bash
export FIGMA_PERSONAL_ACCESS_TOKEN=<your-token>
pnpm audit:mockup                                              # blocking (场景 3 greenfield)
# scenario 2 (existing-product increment) — report without blocking (M21 local visual contract):
pnpm exec node node_modules/@nancyzeng0210/tvu-design-system/scripts/audit-mockup-conformance.mjs --file <fileKey> --non-blocking
```

Pass-through flags: `--node <nodeId>` (narrow scope), `--lib <libKey>` (library-origin). Exit 0 = all
passed (or `--non-blocking`); exit 1 = findings or a sub-audit could not run.

> **Gate placement**: mockup conformance keys off a Figma file, so it runs in the mockup workflow
> (when an AI/designer ships a mockup) and consumer CI — not in a generic pre-commit hook (the DS repo
> has no Figma artifact to gate at commit time).

---

## CI integration (GitHub Actions example)

`.github/workflows/audit.yml` in consumer repo:

```yaml
name: TVU audits

on: [push, pull_request]

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v3
        with: { version: 10 }
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'pnpm'
          registry-url: 'https://npm.pkg.github.com'
          scope: '@nancyzeng0210'

      - run: pnpm install --frozen-lockfile
        env:
          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - run: pnpm audit:code

      - run: pnpm audit:mockup
        env:
          FIGMA_PERSONAL_ACCESS_TOKEN: ${{ secrets.FIGMA_TOKEN }}
```

---

## Quick smoke test (after install)

To verify the install worked end-to-end:

```bash
# 1. Check audit CLI exists
ls node_modules/@nancyzeng0210/tvu-design-system/scripts/audit-product-code.mjs

# 2. Check ESLint plugin loads
node -e "import('@nancyzeng0210/tvu-design-system/eslint-plugin').then(m => console.log('plugin OK:', Object.keys(m.default.rules)))"
# Expected: plugin OK: [ 'no-hardcoded-color', 'no-inline-svg', 'icon-from-dist', 'no-base-component-import', 'no-native-element', 'no-hardcoded-spacing' ]

# 3. Dry-run code audit on a single small dir
pnpm exec node node_modules/@nancyzeng0210/tvu-design-system/scripts/audit-product-code.mjs --dir src --dry-run
```

---

## Troubleshooting

| Symptom | Cause | Fix |
|---|---|---|
| `npm ERR! 401 Unauthorized` on install | npmrc token missing or expired | Regenerate GitHub PAT with `read:packages` scope; update `.npmrc` |
| `Cannot find module '@nancyzeng0210/tvu-design-system/eslint-plugin'` | ESLint config can't resolve subpath export — older ESLint or pnpm | Update to ESLint 9+ and pnpm 9+; check `node --experimental-import-meta-resolve` for resolve issues |
| Mockup audit times out / 401 | Figma API token missing or wrong file key | Verify `FIGMA_PERSONAL_ACCESS_TOKEN` and file key match the actual product file URL |
| ESLint plugin rules don't fire | Plugin loaded but not registered in `plugins:` map | See "Optional but recommended" section above — flat config requires explicit plugins map |

---

## For DS repo maintainer

When the consumer wants to test before v1.0 RC ships (per user 3b decision 2026-05-19):

1. User identifies consumer product repo path (e.g. `~/Documents/AICoding/VS_Code/microapps-console`).
2. DS maintainer (Claude or human) runs install steps above in that repo:
   - Adds `.npmrc` (with user-provided token)
   - `pnpm add @nancyzeng0210/tvu-design-system`
   - Configures `eslint.config.js` if consumer uses ESLint
   - Adds package.json script shortcuts
3. Runs a smoke audit pass: `pnpm audit:code` against current consumer codebase. Expect ~10-50 findings on first run (legacy code never audited before).
4. Document the findings + ack with user before any code changes — findings are signal for consumer to fix, not auto-fix territory.
