Prisma

🛡️ Enforcement Rules — Mandatory Gate

6 enforce rules bắt buộc cho MỌI tác vụ tạo/sửa/review/kiểm tra showcase, component, hoặc demo.

Khi nào chạy? TRƯỚC khi code (§1 Pre-work Gate) và SAU khi code (§2 Post-work Audit). Ai trigger? new-showcase.md, component-lifecycle, ds-architect.md — hoặc agent tự trigger khi nhận task liên quan.


§0 — TASK RECEPTION (bắt buộc khi nhận task)

Khi agent nhận BẤT KỲ task nào liên quan showcase/component/demo/docs/style/theme:

  • Tạo mới
  • Sửa / edit / fix
  • Review / kiểm tra / audit
  • Bất kỳ tác vụ tạo HTML/CSS/JS output
  • Sửa docs template (preview-extras.css, components.css, preview HTML trong component-previews.js)
  • Tạo / sửa style (styles/*.json) hoặc theme (themes/*.json)
  • Review / audit docs output

Agent PHẢI tuân thủ flow sau — KHÔNG ĐƯỢC bỏ qua:

text
NHẬN TASK (sửa / tạo mới / review / kiểm tra showcase/component/demo)
  │
  ├─ §1 PRE-WORK GATE (bắt buộc TRƯỚC khi code)
  │   ├─ Đọc enforce-rules.md
  │   ├─ Đọc knowledge-rules.json (query section liên quan)
  │   ├─ Đọc ux-research SKILL.md (§5, §6, §7)
  │   ├─ Check variables.css CỦA SHOWCASE (không phải DS core)
  │   └─ Output: "PRE-WORK GATE ✅ PASSED"
  │
  ├─ THỰC HIỆN CODE
  │   └─ Mỗi quyết định phải cite rule ID (VD: "theo R3, min 44px")
  │
  └─ §2 POST-WORK AUDIT (bắt buộc SAU khi code)
      ├─ ENF-1: Check BS-1→5, R3, T10/T11, F1/F3
      ├─ ENF-2: Scan icon text
      ├─ ENF-3: Check inline components
      ├─ ENF-4: Check preview entry exists (component work)
      ├─ ENF-5: Audit CSS class hardcodes (pseudo-elements, easing, sizing)
      └─ Output: Audit report table
          │
          ├─ ✅ ALL PASS → proceed to /post-change
          └─ ❌ FAIL → STOP → report violations → user review

⚠️ KHÔNG TUÂN THỦ = FAIL = STOP Agent KHÔNG ĐƯỢC tiếp tục code nếu chưa qua Pre-work Gate. Agent KHÔNG ĐƯỢC báo hoàn thành nếu chưa qua Post-work Audit. Nếu audit FAIL → STOP ngay → output report → chờ user review.


§1 — PRE-WORK GATE (chạy TRƯỚC khi code)

// turbo-all

BẮT BUỘC hoàn thành TRƯỚC KHI viết bất kỳ CSS/HTML/JS nào.

Step 1: Đọc UX Rules

text
☐ Đọc ux-research SKILL.md — focus:
  • §5 Component Behavior (states, keyboard, button sizes BS-1→BS-5)
  • §6 Typography (T1 font ≥14px, T10/T11 title sizes)
  • §7 Accessibility (F1 focus ring, F3 focus trap, ARIA patterns)
  • §2 Interaction (6 states, touch targets)

Step 2: Scan DS Component Inventory

bash
## List tất cả components hiện có trong DS core
dir /b "design-system\components md\*.md" | findstr /v "ATOMIC-MAPPING COMPONENT-ROADMAP"

→ Output = DS Component Whitelist — danh sách components đã có. → Ghi nhận whitelist này để dùng ở §2 Post-work Audit (ENF-3).

Step 3: Đọc ATOMIC-MAPPING.md

text
☐ Đọc design-system/components md/ATOMIC-MAPPING.md
  → Biết token mapping cho từng component
  → Biết UI Layer + Density Tier assignment

Output — Pre-work Gate Confirmation:

text
🛡️ PRE-WORK GATE: ✅ PASSED
  ☑ UX Rules đã đọc (§5, §6, §7, §2)
  ☑ DS Components: {N} components available
  ☑ ATOMIC-MAPPING.md đã đọc
  → Proceeding to implementation...

§2 — POST-WORK AUDIT (chạy SAU khi code, TRƯỚC /post-change)

Chạy 5 enforcement checks trên output vừa tạo/sửa.

ENF-1: UX Compliance Check

Audit output đáp ứng UX rules đã đọc ở pre-work:

text
☐ Font-size ≥ 14px cho body/interactive text? (T1)
☐ Heading hierarchy đúng? (T4: h1 → h2 → h3, không skip)
☐ Focus ring dùng var(--ring)? (F1)
☐ ARIA roles/attributes đầy đủ? (F3, B7)
☐ Touch targets ≥ 44×44px? (R3)
☐ Button sizes theo BS-1→BS-5? (§5)
☐ Action group placement đúng? (AG-1→AG-3)
☐ prefers-reduced-motion nếu có animation? (M1)

PASS: Tất cả ☑ → tiếp tục → FAIL: Ghi nhận violations → AUTO-FIX → re-audit

ENF-2: Icon Text Character Ban

TUYỆT ĐỐI KHÔNG dùng text characters làm icon. Tất cả icons PHẢI là SVG.

Blacklist — FORBIDDEN characters:

text
✕ × ▼ ▾ → ← ↑ ↓ ‹ › « » − • ● ○ ■ □ ★ ☆ ✓ ✗ ☰ ⋮ ⋯ ▶ ◀ △ ▽ ◆ ◇

Scan scope: Chỉ check bên trong interactive/icon contexts:

  • <button>, <a>, .icon, .btn, icon containers
  • CSS content: "..." pseudo-elements dùng cho icon
  • KHÔNG flag: Content text (paragraphs, headings, descriptions)

Thay thế đúng:

html
<!-- ❌ SAI — icon text -->
<button class="btn-close">✕</button>
<span class="icon">▼</span>
<a class="nav-link">← Back</a>

<!-- ✅ ĐÚNG — SVG icon -->
<button class="btn-close" aria-label="Close">
  <svg><use href="#ic-close"/></svg>
</button>
<span class="icon"><svg><use href="#ic-chevron-down"/></svg></span>
<a class="nav-link">
  <svg><use href="#ic-arrow-left"/></svg> Back
</a>

PASS: 0 icon text characters found → FAIL: List violations → AUTO-FIX (replace with SVG <use>) → re-audit

ENF-3: Inline Component Prohibition

KHÔNG tự viết component inline nếu component đó:

  • ĐÃ CÓ trong DS core → dùng trực tiếp
  • CHƯA CÓ trong DS core → STOP → báo user → lên kế hoạch tạo mới

Scan scope — áp dụng cho TẤT CẢ contexts:

Context Files cần scan
Showcase showcase/{name}/*.css, showcase/{name}/*.html
Docs template preview-extras.css, components.css, component-previews.js (preview HTML)
Style/theme styles/*.json, themes/*.json — check component token refs cho comp chưa tồn tại

Detection — scan output cho patterns:

text
☐ Có class .dropdown / .modal / .tabs / .select / .dialog / .toast /
  .accordion / .drawer / .popover / .tooltip mà KHÔNG reference DS core?
☐ Có viết CSS cho component behavior (hover states, focus trap, transitions)
  mà DS core đã có sẵn?
☐ Có duplicate CSS rules cho component đã tồn tại trong ATOMIC-MAPPING.md?
☐ [DOCS] Preview HTML trong component-previews.js có tự tạo component
  thay vì dùng DS class/token?
☐ [STYLE/THEME] Token JSON có ref tới component chưa tồn tại trong
  ATOMIC-MAPPING.md? (VD: tạo --comp-xyz-* cho comp chưa có spec)

Decision flow:

text
Component cần dùng?
  │
  ├─ Có trong DS whitelist (Step 2)?
  │   → ✅ Dùng trực tiếp, KHÔNG viết CSS mới
  │
  └─ KHÔNG có trong DS whitelist?
      → ❌ STOP — KHÔNG viết inline workaround
      → Báo user: "Component {X} chưa có trong DS core.
         Đề xuất tạo mới theo component-lifecycle workflow."
      → Chờ user approve → tạo via component-lifecycle

  [DOCS context] Preview HTML tự tạo component markup?
      → ❌ STOP — preview PHẢI dùng DS class patterns
      → Nếu DS chưa có → báo user, KHÔNG viết workaround inline

  [STYLE/THEME context] Token ref tới comp chưa tồn tại?
      → ❌ STOP — tạo comp spec TRƯỚC (component-lifecycle),
         rồi mới tạo tokens

PASS: Tất cả components dùng từ DS core hoặc đã báo user → FAIL: List inline components → STOP → báo user (KHÔNG auto-fix)

ENF-4: Preview Entry Gate

Mỗi component PHẢI có preview entry trong component-previews.js.

📌 Root cause: Checkbox issue — component CSS có top: 1px; left: 5px hardcode nhưng không bị phát hiện vì thiếu preview audit pipeline.

Check:

text
☐ Component có entry trong component-previews.js?
☐ Preview HTML dùng DS tokens (KHÔNG hardcode px/colors)?
☐ build-docs.js output hiển thị "N/52 components have live previews"?
☐ Preview bao gồm đủ states: default, hover, disabled?
☐ Icon dùng icon() helper (Lucide SVG, KHÔNG text emoji)?

Preview HTML token rules:

Property ❌ Hardcode ✅ Token
Spacing/gap gap: var(--spacing-3) gap: var(--spacing-3)
Sizing width: 40px width: calc(var(--spacing) * 10)
Font font-size: var(--font-size-sm) font-size: var(--font-size-sm)
Color color: #666 color: var(--muted-foreground)
Easing ease var(--easing-standard)
Radius border-radius: var(--comp-radius) border-radius: var(--comp-radius)

PASS: Entry exists + 0 hardcodes → FAIL: Missing entry → add to component-previews.js → rebuild docs

ENF-5: CSS Class Hardcode Audit

Audit CSS class definitions trong preview-extras.csscomponents.css cho hardcodes.

📌 Root cause: .checkbox:checked::after { top: 1px; left: 5px } — hardcoded positioning sẽ break khi density scale thay đổi.

Files to audit:

  • design-system/scripts/docs/template/preview-extras.css
  • design-system/scripts/docs/template/components.css

Check mỗi CSS class cho:

text
☐ Pseudo-element positioning: có `position: absolute` + `top/left: Npx`?
  → Fix: dùng `display: grid; place-content: center`
☐ Hardcoded easing: có `ease`, `ease-in-out`, `ease-out` raw?
  → Fix: dùng `var(--easing-standard)`
☐ Hardcoded duration: có `150ms`, `200ms`, `300ms` raw?
  → Fix: dùng `var(--duration-fast-1)`, `var(--duration-normal-2)`, etc.
☐ Hardcoded sizing: có `40px`, `48px`, `20px` raw (KHÔNG trong spacing scale)?
  → Fix: dùng `calc(var(--spacing) * N)` hoặc `var(--spacing-N)`
☐ Missing bg/fg pair: có `background: var(--primary)` mà thiếu `color:`?
  → Fix: thêm `color: var(--primary-foreground)`

Quick scan command:

bash
## Tìm hardcoded px (trừ border-width, shadow, 0px)
Select-String '\d+px' design-system/scripts/docs/template/preview-extras.css | Where-Object { $_ -notmatch 'spacing|radius|border-width|shadow|0px|var\(' }

## Tìm raw easing
Select-String 'ease[^-]|ease;|ease-in-out|ease-out' design-system/scripts/docs/template/preview-extras.css

PASS: 0 hardcodes found → FAIL: List violations → AUTO-FIX → re-audit

ENF-6: Slot Compliance

Mọi component/showcase/demo output PHẢI tuân thủ Figma Slot system.

📌 Source of truth:

  • knowledge/slot-manifest.json — slot registry (R1-R4 grammar)
  • knowledge/slot-convention.md — CSS naming rules (structural vs BEM)
  • design-system/code-connect/code-connect.config.json — Code Connect config
  • design-system/code-connect/slot-api.d.ts — typed slot interfaces
  • design-system/code-connect/preferred-instances.json — preferred Figma instances

Check — Component work (tạo/sửa component .md hoặc preview):

text
☐ Component có `## Slot Map (Figma ↔ Code)` section trong spec .md?
   → Nếu KHÔNG → thêm theo format chuẩn (xem app-bar.md làm mẫu)
☐ Slot names trong spec match slot-manifest.json?
   → Đối chiếu: Figma Slot name + data-slot value + CSS Class
☐ Component có entry trong code-connect.config.json?
   → Nếu KHÔNG → thêm entry mới với slots + template
☐ HTML skeleton/preview dùng data-slot attributes?
   → Mỗi slot element PHẢI có data-slot="{component}-{slot-name}"

Check — Showcase/demo work (tạo/sửa HTML output):

text
☐ HTML output có data-slot attributes cho structural slots?
   → Structural: data-slot cho header, body, footer (nếu component hỗ trợ)
☐ Slot nesting đúng hierarchy (root → structural → inner)?
   → VD: data-slot="card" > data-slot="card-header" > data-slot="card-title"
☐ Không tự tạo slot name mới ngoài slot-manifest.json?
   → Slot name PHẢI tồn tại trong manifest hoặc được đăng ký trước

Check — Style/theme work:

text
☐ Component slot CSS class references (.slot-header, .slot-body, .slot-footer)
   đều tồn tại trong components.css Slot System section?

Decision flow:

text
Component output có slots?
  │
  ├─ Có trong slot-manifest.json?
  │   → ✅ Dùng data-slot values từ manifest
  │
  └─ KHÔNG có trong manifest?
      → ❌ STOP — KHÔNG tự tạo slot name
      → Cập nhật slot-manifest.json TRƯỚC
      → Sau đó thêm Slot Map vào spec .md
      → Sau đó thêm entry vào code-connect.config.json

PASS: Tất cả slots mapped + data-slot present + Code Connect entry exists → FAIL: List missing slots → fix theo flow trên → re-audit


§3 — AUDIT REPORT FORMAT

Sau khi chạy 5 checks, output report theo format:

markdown
### 🛡️ Enforcement Audit Report

**Scope**: {file/folder đã audit}
**Date**: {YYYY-MM-DD}

| Rule | Status | Details |
|------|--------|---------|
| ENF-1 UX Compliance | ✅ PASS / ❌ FAIL | {N violations found} |
| ENF-2 Icon Text Ban | ✅ PASS / ❌ FAIL | {N text icons found} |
| ENF-3 Inline Component | ✅ PASS / ❌ FAIL | {N inline components} |
| ENF-4 Preview Gate | ✅ PASS / ❌ FAIL | {N components missing previews} |
| ENF-5 CSS Hardcode | ✅ PASS / ❌ FAIL | {N hardcoded values in CSS} |
| ENF-6 Slot Compliance | ✅ PASS / ❌ FAIL | {N missing slot maps / data-slot / CC entries} |

#### ENF-4 Violations (nếu có)
| # | Component | File | Issue |
|---|-----------|------|-------|
| 1 | checkbox  | component-previews.js | Missing preview entry |

#### ENF-5 Violations (nếu có)
| # | File | Line | Found | Fix |
|---|------|------|-------|-----|
| 1 | preview-extras.css | 874 | `top: 1px; left: 5px` | `display: grid; place-content: center` |
| 2 | preview-extras.css | 860 | `ease` | `var(--easing-standard)` |

VERDICT: ✅ ALL PASS → proceed to /post-change
         ❌ FAIL → {action required}

Auto-fix Rules

Rule Auto-fixable? Action
ENF-1 ✅ Partial Fix font-size, add ARIA, add focus ring → re-audit
ENF-2 ✅ Yes Replace text char with SVG <use> → re-audit
ENF-3 ❌ No STOP → báo user → chờ approve → tạo component mới
ENF-4 ✅ Yes Add preview entry → rebuild docs → re-audit
ENF-5 ✅ Yes Replace hardcode with token → re-audit
ENF-6 ✅ Yes Add Slot Map + data-slot + CC entry → re-audit

ENF-3 là BLOCKING — không thể auto-fix vì component mới phải đi qua lifecycle đầy đủ (design analysis → token mapping → validation).


Anti-patterns

❌ KHÔNG LÀM ✅ LÀM ĐÚNG
Bỏ qua pre-work gate, code luôn Đọc UX rules + scan DS inventory TRƯỚC
Dùng × làm icon Dùng SVG <use href="#ic-name"/>
Tự viết .custom-select inline Dùng DS select component hoặc báo user
Audit xong FAIL nhưng vẫn commit Fix ALL violations trước khi /post-change
Chỉ fix 1 file, bỏ qua blast radius Scan toàn bộ output cho cùng pattern
Tạo component mà không add preview Add entry vào component-previews.js + rebuild
position: absolute + top/left: Npx cho centering display: grid; place-content: center
Raw ease / ease-in-out trong transition var(--easing-standard)
Tạo component HTML không có data-slot Thêm data-slot cho mọi slot element
Tự nghĩ slot name mới Dùng slot name từ slot-manifest.json
width: 40px; height: 48px hardcode sizing calc(var(--spacing) * N)
Chỉ check preview HTML, bỏ qua CSS class Audit cả preview-extras.css + components.css
Fix 1 file CSS, quên file kia Blast radius: cả preview-extras.css LẪN components.css