{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "ai-code-review-assistant",
  "title": "Ai Code Review Assistant",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/ai-code-review-assistant/AiCodeReviewAssistant.vue",
      "content": "<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { HTMLAttributes } from 'vue'\nimport {\n  Bot,\n  Check,\n  CheckCircle2,\n  CheckCheck,\n  Code2,\n  Copy,\n  Cpu,\n  FileCode2,\n  GitBranch,\n  GitCommit,\n  GitPullRequest,\n  Layers,\n  MessageSquare,\n  RefreshCw,\n  RotateCcw,\n  Send,\n  ShieldCheck,\n  Sparkles,\n  TrendingDown,\n  TrendingUp,\n  X,\n  Zap,\n} from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'\nimport { Separator } from '@/components/ui/separator'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'\n\nexport interface Props {\n  prNumber?: number\n  prTitle?: string\n  authorName?: string\n  authorHandle?: string\n  authorRole?: string\n  authorAvatar?: string\n  sourceBranch?: string\n  targetBranch?: string\n  class?: HTMLAttributes['class']\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  prNumber: 412,\n  prTitle: 'refactor(tokens): migrate to OKLCH perceptual contrast engine',\n  authorName: 'Elena Rostova',\n  authorHandle: 'elena-rostova',\n  authorRole: 'Staff Design Systems Engineer',\n  authorAvatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=96&h=96&fit=crop&crop=face',\n  sourceBranch: 'feature/oklch-engine',\n  targetBranch: 'main',\n})\n\ninterface DiffLine {\n  id: string\n  oldNum?: number\n  newNum?: number\n  type: 'neutral' | 'deletion' | 'addition' | 'hunk'\n  text: string\n  annotationId?: string\n}\n\ninterface ChatMessage {\n  id: string\n  sender: 'ai' | 'user'\n  author: string\n  timestamp: string\n  text: string\n  codeSnippet?: string\n}\n\nconst activeTab = ref('diff')\nconst isApplyingAll = ref(false)\nconst appliedPatches = ref<Set<string>>(new Set())\nconst isChatOpen = ref(false)\nconst chatInput = ref('')\nconst copiedDiff = ref(false)\nconst copiedPatchId = ref<string | null>(null)\n\nconst diffLines = computed<DiffLine[]>(() => [\n  {\n    id: 'hunk-1',\n    type: 'hunk',\n    text: '@@ -32,18 +32,24 @@ packages/shared/styles/tailwind.css',\n  },\n  {\n    id: 'line-32',\n    oldNum: 32,\n    newNum: 32,\n    type: 'neutral',\n    text: '@import \"tailwindcss\";',\n  },\n  {\n    id: 'line-33',\n    oldNum: 33,\n    newNum: 33,\n    type: 'neutral',\n    text: '@import \"tw-animate-css\";',\n  },\n  {\n    id: 'line-34',\n    oldNum: 34,\n    newNum: 34,\n    type: 'neutral',\n    text: '',\n  },\n  {\n    id: 'line-35',\n    oldNum: 35,\n    newNum: 35,\n    type: 'neutral',\n    text: '@theme inline {',\n  },\n  {\n    id: 'line-36',\n    oldNum: 36,\n    newNum: 36,\n    type: 'neutral',\n    text: '  --font-sans: \"Inter\", system-ui, sans-serif;',\n  },\n  {\n    id: 'line-37',\n    oldNum: 37,\n    newNum: 37,\n    type: 'neutral',\n    text: '  --font-mono: \"DM Mono\", monospace;',\n  },\n  {\n    id: 'line-38',\n    oldNum: 38,\n    type: 'deletion',\n    text: '-  --primary-10: color-mix(in srgb, var(--primary) 10%, #ffffff);',\n  },\n  {\n    id: 'line-39',\n    oldNum: 39,\n    type: 'deletion',\n    text: '-  --primary-20: color-mix(in srgb, var(--primary) 20%, #ffffff);',\n  },\n  {\n    id: 'line-40',\n    oldNum: 40,\n    type: 'deletion',\n    text: '-  --primary-hover: hsl(var(--primary-hsl) / 0.85);',\n  },\n  {\n    id: 'line-41',\n    newNum: 38,\n    type: 'addition',\n    text: '+  --primary-hover: oklch(from var(--primary) calc(l * 0.92) c h);',\n  },\n  {\n    id: 'line-42',\n    newNum: 39,\n    type: 'addition',\n    text: appliedPatches.value.has('patch-1')\n      ? '+  --primary-accent: color-mix(in oklab, var(--primary) 10%, transparent); /* [Glia AI Patch Applied] */'\n      : '+  --primary-accent: color-mix(in oklab, var(--primary) 15%, transparent);',\n    annotationId: 'patch-1',\n  },\n  {\n    id: 'line-43',\n    oldNum: 41,\n    newNum: 40,\n    type: 'neutral',\n    text: '  --color-background: var(--background);',\n  },\n  {\n    id: 'line-44',\n    oldNum: 42,\n    newNum: 41,\n    type: 'neutral',\n    text: '  --color-foreground: var(--foreground);',\n  },\n  {\n    id: 'line-45',\n    oldNum: 43,\n    type: 'deletion',\n    text: '-  --muted-border: rgb(229 231 235 / 0.6);',\n  },\n  {\n    id: 'line-46',\n    newNum: 42,\n    type: 'addition',\n    text: '+  --muted-border: oklch(0.92 0.005 240 / 0.8);',\n  },\n  {\n    id: 'line-47',\n    oldNum: 44,\n    newNum: 43,\n    type: 'neutral',\n    text: '  --color-border: var(--border);',\n  },\n  {\n    id: 'line-48',\n    oldNum: 45,\n    newNum: 44,\n    type: 'neutral',\n    text: '  --color-input: var(--input);',\n  },\n  {\n    id: 'line-49',\n    oldNum: 46,\n    type: 'deletion',\n    text: '-  --ring-offset-width: 2px;',\n  },\n  {\n    id: 'line-50',\n    newNum: 45,\n    type: 'addition',\n    text: '+  --color-ring: oklch(from var(--primary) l c h / 0.5);',\n  },\n  {\n    id: 'line-51',\n    newNum: 46,\n    type: 'addition',\n    text: appliedPatches.value.has('patch-2')\n      ? '+  --ring-focus-shadow: 0 0 0 2px var(--color-ring); /* [Glia AI Patch Applied] */'\n      : '+  --ring-focus-shadow: 0 0 0 2px var(--color-ring);',\n    annotationId: 'patch-2',\n  },\n  {\n    id: 'line-52',\n    oldNum: 47,\n    newNum: 47,\n    type: 'neutral',\n    text: '  --color-card: var(--card);',\n  },\n  {\n    id: 'line-53',\n    oldNum: 48,\n    newNum: 48,\n    type: 'neutral',\n    text: '  --color-card-foreground: var(--card-foreground);',\n  },\n  {\n    id: 'line-54',\n    oldNum: 49,\n    newNum: 49,\n    type: 'neutral',\n    text: '}',\n  },\n])\n\nconst chatMessages = ref<ChatMessage[]>([\n  {\n    id: 'msg-1',\n    sender: 'ai',\n    author: 'Glia AI Code Reviewer',\n    timestamp: '2 min ago',\n    text: \"I completed the AST review for PR #412. Migrating to OKLCH perceptual contrast is a massive win. I've pinpointed 2 optimization opportunities to maximize token efficiency and eliminate 20 DOM variables.\",\n  },\n  {\n    id: 'msg-2',\n    sender: 'user',\n    author: 'Elena Rostova',\n    timestamp: '1 min ago',\n    text: 'Why is `color-mix(in oklab, ... 10%, transparent)` better than declaring separate opacity custom properties?',\n  },\n  {\n    id: 'msg-3',\n    sender: 'ai',\n    author: 'Glia AI Code Reviewer',\n    timestamp: 'Just now',\n    text: 'Direct OKLab color-mix calculates the alpha composite on the GPU shader pipeline without registering 20 CSS custom properties in the browser style recalculation tree. This cuts ~1.8 KB from DOM memory while keeping luminance completely linear.',\n    codeSnippet: 'color-mix(in oklab, var(--primary) 10%, transparent)',\n  },\n])\n\nconst allPatchesApplied = computed(() => appliedPatches.value.size === 2)\nconst qualityScore = computed(() => (allPatchesApplied.value ? 99 : 96))\n\nfunction togglePatch(patchId: string) {\n  const next = new Set(appliedPatches.value)\n  if (next.has(patchId)) {\n    next.delete(patchId)\n  } else {\n    next.add(patchId)\n  }\n  appliedPatches.value = next\n}\n\nfunction applyAllPatches() {\n  if (isApplyingAll.value) return\n  isApplyingAll.value = true\n  setTimeout(() => {\n    appliedPatches.value = new Set(['patch-1', 'patch-2'])\n    isApplyingAll.value = false\n  }, 600)\n}\n\nfunction resetPatches() {\n  appliedPatches.value = new Set()\n}\n\nfunction openChatWithTopic(topicText?: string) {\n  isChatOpen.value = true\n  if (topicText) {\n    chatMessages.value.push({\n      id: `user-${Date.now()}`,\n      sender: 'user',\n      author: 'Elena Rostova',\n      timestamp: 'Just now',\n      text: topicText,\n    })\n    setTimeout(() => {\n      chatMessages.value.push({\n        id: `ai-${Date.now()}`,\n        sender: 'ai',\n        author: 'Glia AI Code Reviewer',\n        timestamp: 'Just now',\n        text: `Regarding \"${topicText}\": Our AST lint engine verified that OKLCH relative color syntax produces 7:1 contrast on dark surfaces with zero gamut clipping on Apple Display P3 panels.`,\n      })\n    }, 450)\n  }\n}\n\nfunction handleSendMessage() {\n  const text = chatInput.value.trim()\n  if (!text) return\n  chatMessages.value.push({\n    id: `msg-${Date.now()}`,\n    sender: 'user',\n    author: 'Elena Rostova',\n    timestamp: 'Just now',\n    text,\n  })\n  chatInput.value = ''\n\n  setTimeout(() => {\n    chatMessages.value.push({\n      id: `ai-${Date.now()}`,\n      sender: 'ai',\n      author: 'Glia AI Code Reviewer',\n      timestamp: 'Just now',\n      text: 'Validated against UIPKGE craft standards. The suggested AST refactor is fully backward-compatible with PostCSS fallback polyfills.',\n    })\n  }, 500)\n}\n\nfunction copyRawDiff() {\n  const rawText = diffLines.value.map((l) => `${l.text}`).join('\\n')\n  navigator.clipboard?.writeText(rawText)\n  copiedDiff.value = true\n  setTimeout(() => {\n    copiedDiff.value = false\n  }, 2000)\n}\n\nfunction copyPatchCode(id: string, code: string) {\n  navigator.clipboard?.writeText(code)\n  copiedPatchId.value = id\n  setTimeout(() => {\n    copiedPatchId.value = null\n  }, 2000)\n}\n</script>\n\n<template>\n  <div data-uipkge data-slot=\"ai-code-review-assistant\" :class=\"cn('w-full space-y-6', props.class)\">\n    <!-- Header: Pull Request Info & AI Review Status -->\n    <Card class=\"border-border bg-card shadow-xs\">\n      <CardHeader class=\"pb-4\">\n        <div class=\"flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between\">\n          <div class=\"space-y-2\">\n            <!-- PR Badge & Title -->\n            <div class=\"flex flex-wrap items-center gap-2\">\n              <Badge wrap variant=\"outline\" class=\"gap-1.5 font-mono text-xs\">\n                <GitPullRequest class=\"text-primary size-3.5\" />\n                <span>PR #{{ props.prNumber }}</span>\n              </Badge>\n              <h2 class=\"text-foreground text-base font-bold tracking-tight sm:text-lg\">\n                {{ props.prTitle }}\n              </h2>\n            </div>\n\n            <!-- Meta: Author, Branches, Commit -->\n            <div class=\"text-muted-foreground flex flex-wrap items-center gap-2 text-xs sm:text-sm\">\n              <div class=\"flex items-center gap-1.5\">\n                <Avatar class=\"size-5 border\">\n                  <AvatarImage :src=\"props.authorAvatar\" :alt=\"props.authorName\" />\n                  <AvatarFallback class=\"text-xs\">ER</AvatarFallback>\n                </Avatar>\n                <span class=\"text-foreground font-medium\">{{ props.authorName }}</span>\n                <span class=\"text-muted-foreground\">(@{{ props.authorHandle }})</span>\n              </div>\n\n              <Separator orientation=\"vertical\" class=\"h-3.5\" />\n\n              <div class=\"flex items-center gap-1.5 font-mono text-xs\">\n                <GitBranch class=\"text-primary size-3.5\" />\n                <span class=\"text-foreground font-semibold\">{{ props.targetBranch }}</span>\n                <span class=\"text-muted-foreground\">←</span>\n                <span class=\"text-foreground font-semibold\">{{ props.sourceBranch }}</span>\n              </div>\n\n              <Separator orientation=\"vertical\" class=\"h-3.5\" />\n\n              <div class=\"flex items-center gap-1 font-mono text-xs\">\n                <GitCommit class=\"text-muted-foreground size-3.5\" />\n                <span>8f2a49b</span>\n                <span>·</span>\n                <span class=\"text-success font-medium\">+142</span>\n                <span class=\"text-destructive font-medium\">-68</span>\n              </div>\n            </div>\n          </div>\n\n          <!-- Actions & Review Status -->\n          <div class=\"flex flex-wrap items-center gap-2.5\">\n            <Badge\n              wrap\n              v-if=\"!allPatchesApplied\"\n              variant=\"success\"\n              class=\"border-success/20 bg-success/10 text-success gap-1.5 px-3 py-1 text-xs font-semibold\"\n            >\n              <Sparkles class=\"size-3.5 shrink-0\" />\n              <span>Review Completed · 2 Suggestions · 0 Security Flaws</span>\n            </Badge>\n            <Badge\n              wrap\n              v-else\n              variant=\"success\"\n              class=\"border-success/30 bg-success/15 text-success gap-1.5 px-3 py-1 text-xs font-semibold\"\n            >\n              <CheckCheck class=\"size-3.5 shrink-0\" />\n              <span>All Patches Applied · Ready to Merge</span>\n            </Badge>\n\n            <Button\n              v-if=\"!allPatchesApplied\"\n              size=\"sm\"\n              variant=\"default\"\n              class=\"gap-1.5 text-xs font-medium shadow-xs\"\n              :disabled=\"isApplyingAll\"\n              @click=\"applyAllPatches\"\n            >\n              <RefreshCw v-if=\"isApplyingAll\" class=\"size-3.5 animate-spin\" />\n              <Sparkles v-else class=\"size-3.5\" />\n              <span>{{ isApplyingAll ? 'Applying Patches...' : 'Apply All AI Patches' }}</span>\n            </Button>\n\n            <Button\n              v-else\n              size=\"sm\"\n              variant=\"outline\"\n              class=\"gap-1.5 text-xs font-medium shadow-xs\"\n              @click=\"resetPatches\"\n            >\n              <RotateCcw class=\"size-3.5\" />\n              <span>Reset State</span>\n            </Button>\n\n            <Button\n              size=\"sm\"\n              variant=\"outline\"\n              class=\"gap-1.5 text-xs font-medium shadow-xs\"\n              @click=\"openChatWithTopic()\"\n            >\n              <MessageSquare class=\"size-3.5\" />\n              <span>AI Chat (3)</span>\n            </Button>\n          </div>\n        </div>\n      </CardHeader>\n    </Card>\n\n    <!-- 4 Code Review Health Cards -->\n    <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n      <!-- Card 1: Quality Score -->\n      <Card class=\"border-border bg-card shadow-xs transition-colors\">\n        <CardContent class=\"p-4 sm:p-5\">\n          <div class=\"flex items-center justify-between\">\n            <span class=\"text-muted-foreground text-xs font-medium\">Code Quality Score</span>\n            <div class=\"bg-success/10 text-success flex size-8 items-center justify-center rounded-md\">\n              <CheckCircle2 class=\"size-4\" />\n            </div>\n          </div>\n          <div class=\"mt-3\">\n            <div class=\"text-foreground text-2xl font-bold tracking-tight\">{{ qualityScore }} / 100</div>\n            <p class=\"text-muted-foreground mt-1 text-xs\">\n              Clean Architecture · <span class=\"text-success font-medium\">+14 pts</span> vs baseline\n            </p>\n          </div>\n          <div class=\"text-success mt-3 flex items-center gap-1.5 text-xs font-medium\">\n            <Check class=\"size-3.5\" />\n            <span>0 Anti-patterns · Clean CVA tokens</span>\n          </div>\n        </CardContent>\n      </Card>\n\n      <!-- Card 2: Security & Vulnerability Check -->\n      <Card class=\"border-border bg-card shadow-xs\">\n        <CardContent class=\"p-4 sm:p-5\">\n          <div class=\"flex items-center justify-between\">\n            <span class=\"text-muted-foreground text-xs font-medium\">Security & SAST Check</span>\n            <div class=\"bg-success/10 text-success flex size-8 items-center justify-center rounded-md\">\n              <ShieldCheck class=\"size-4\" />\n            </div>\n          </div>\n          <div class=\"mt-3\">\n            <div class=\"text-foreground text-2xl font-bold tracking-tight\">0 Vulnerabilities</div>\n            <p class=\"text-muted-foreground mt-1 text-xs\">\n              0 Vulnerabilities Detected · <span class=\"text-success font-medium\">Pass</span>\n            </p>\n          </div>\n          <div class=\"text-success mt-3 flex items-center gap-1.5 text-xs font-medium\">\n            <Check class=\"size-3.5\" />\n            <span>OWASP Top 10 validated · Zero leaks</span>\n          </div>\n        </CardContent>\n      </Card>\n\n      <!-- Card 3: Performance & Bundle Impact -->\n      <Card class=\"border-border bg-card shadow-xs\">\n        <CardContent class=\"p-4 sm:p-5\">\n          <div class=\"flex items-center justify-between\">\n            <span class=\"text-muted-foreground text-xs font-medium\">Performance & Bundle Impact</span>\n            <div class=\"bg-warning/10 text-warning flex size-8 items-center justify-center rounded-md\">\n              <Zap class=\"size-4\" />\n            </div>\n          </div>\n          <div class=\"mt-3\">\n            <div class=\"text-foreground text-2xl font-bold tracking-tight\">-4.2 KB (-18%)</div>\n            <p class=\"text-muted-foreground mt-1 text-xs\">Bundle Size Reduction · 14.8 KB → 10.6 KB</p>\n          </div>\n          <div class=\"text-warning mt-3 flex items-center gap-1.5 text-xs font-medium\">\n            <TrendingDown class=\"size-3.5\" />\n            <span>20 CSS variables eliminated from DOM</span>\n          </div>\n        </CardContent>\n      </Card>\n\n      <!-- Card 4: Test Coverage Delta -->\n      <Card class=\"border-border bg-card shadow-xs\">\n        <CardContent class=\"p-4 sm:p-5\">\n          <div class=\"flex items-center justify-between\">\n            <span class=\"text-muted-foreground text-xs font-medium\">Test Coverage Delta</span>\n            <div class=\"bg-info/10 text-info flex size-8 items-center justify-center rounded-md\">\n              <Layers class=\"size-4\" />\n            </div>\n          </div>\n          <div class=\"mt-3\">\n            <div class=\"text-foreground text-2xl font-bold tracking-tight\">+2.4% Coverage</div>\n            <p class=\"text-muted-foreground mt-1 text-xs\">48 new tests · 94.8% total coverage</p>\n          </div>\n          <div class=\"text-success mt-3 flex items-center gap-1.5 text-xs font-medium\">\n            <TrendingUp class=\"size-3.5\" />\n            <span>100% token regression suites pass</span>\n          </div>\n        </CardContent>\n      </Card>\n    </div>\n\n    <!-- Annotated Code Diff Reviewer Card -->\n    <Card class=\"border-border bg-card shadow-xs\">\n      <CardHeader class=\"border-border border-b pb-4\">\n        <div class=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n          <div class=\"space-y-1\">\n            <div class=\"flex flex-wrap items-center gap-2\">\n              <FileCode2 class=\"text-primary size-4 shrink-0\" />\n              <CardTitle class=\"text-foreground font-mono text-sm font-semibold sm:text-base\">\n                packages/shared/styles/tailwind.css\n              </CardTitle>\n              <Badge wrap variant=\"outline\" class=\"font-mono text-xs\"> CSS / Tailwind v4 </Badge>\n              <Badge wrap variant=\"secondary\" class=\"font-mono text-xs\"> +24 -12 lines </Badge>\n            </div>\n            <CardDescription class=\"text-muted-foreground text-xs\">\n              AST parser inspected 162 declarations · 2 optimization nodes annotated\n            </CardDescription>\n          </div>\n\n          <div class=\"flex items-center gap-2\">\n            <Button variant=\"outline\" size=\"sm\" class=\"h-8 gap-1.5 text-xs font-medium shadow-xs\" @click=\"copyRawDiff\">\n              <Check v-if=\"copiedDiff\" class=\"text-success size-3.5\" />\n              <Copy v-else class=\"size-3.5\" />\n              <span>{{ copiedDiff ? 'Copied Raw Diff' : 'Copy Raw Diff' }}</span>\n            </Button>\n          </div>\n        </div>\n      </CardHeader>\n\n      <CardContent class=\"p-4 sm:p-6\">\n        <Tabs v-model=\"activeTab\" class=\"w-full space-y-4\">\n          <TabsList class=\"grid w-full grid-cols-3 sm:inline-flex sm:w-auto\">\n            <TabsTrigger value=\"diff\" class=\"gap-1.5 text-xs\">\n              <Code2 class=\"size-3.5\" />\n              <span>Unified Code Diff</span>\n            </TabsTrigger>\n            <TabsTrigger value=\"rules\" class=\"gap-1.5 text-xs\">\n              <ShieldCheck class=\"size-3.5\" />\n              <span>AST Rule Checks (4)</span>\n            </TabsTrigger>\n            <TabsTrigger value=\"impact\" class=\"gap-1.5 text-xs\">\n              <Cpu class=\"size-3.5\" />\n              <span>Token Matrix &amp; Gamut</span>\n            </TabsTrigger>\n          </TabsList>\n\n          <!-- Tab 1: Visual Unified Code Diff with Inline AI Annotations -->\n          <TabsContent value=\"diff\" class=\"space-y-4 focus-visible:outline-none\">\n            <div\n              class=\"border-border bg-muted/40 flex items-center justify-between rounded-t-md border-x border-t px-3 py-2 text-xs\"\n            >\n              <div class=\"text-muted-foreground flex items-center gap-2\">\n                <span class=\"text-foreground font-medium\">Unified Diff View</span>\n                <span>·</span>\n                <span class=\"text-success font-medium\">+24 additions</span>\n                <span>·</span>\n                <span class=\"text-destructive font-medium\">-12 deletions</span>\n              </div>\n              <span class=\"text-muted-foreground font-mono\">AST Analyzed</span>\n            </div>\n\n            <div\n              class=\"border-border bg-muted/20 overflow-x-auto rounded-b-md border font-mono text-xs leading-relaxed\"\n            >\n              <div class=\"max-w-[620px] min-w-full py-2\">\n                <template v-for=\"line in diffLines\" :key=\"line.id\">\n                  <!-- Hunk Line -->\n                  <div\n                    v-if=\"line.type === 'hunk'\"\n                    class=\"bg-muted/60 text-muted-foreground px-3 py-1 font-mono text-xs font-semibold select-none\"\n                  >\n                    {{ line.text }}\n                  </div>\n\n                  <!-- Diff Code Row -->\n                  <div\n                    v-else\n                    :class=\"\n                      cn(\n                        'flex items-center px-3 py-0.5 transition-colors',\n                        line.type === 'addition' && 'border-success bg-success/10 text-success border-l-2 font-medium',\n                        line.type === 'deletion' &&\n                          'border-destructive bg-destructive/10 text-foreground dark:text-foreground border-l-2 font-medium line-through opacity-85',\n                        line.type === 'neutral' && 'text-muted-foreground border-l-2 border-transparent',\n                      )\n                    \"\n                  >\n                    <!-- Old Line Number -->\n                    <span class=\"text-muted-foreground/50 w-8 shrink-0 pr-2 text-right select-none\">\n                      {{ line.oldNum ?? '' }}\n                    </span>\n                    <!-- New Line Number -->\n                    <span class=\"text-muted-foreground/50 w-8 shrink-0 pr-3 text-right select-none\">\n                      {{ line.newNum ?? '' }}\n                    </span>\n                    <!-- Prefix -->\n                    <span\n                      :class=\"\n                        cn(\n                          'w-4 shrink-0 text-center font-bold select-none',\n                          line.type === 'addition' && 'text-success',\n                          line.type === 'deletion' && 'text-destructive',\n                          line.type === 'neutral' && 'text-transparent',\n                        )\n                      \"\n                    >\n                      {{ line.type === 'addition' ? '+' : line.type === 'deletion' ? '-' : ' ' }}\n                    </span>\n                    <!-- Code Text -->\n                    <span class=\"pl-1 whitespace-pre\">{{ line.text }}</span>\n                  </div>\n\n                  <!-- Inline AI Review Annotation Card #1 (Pinned under line 42) -->\n                  <div\n                    v-if=\"line.annotationId === 'patch-1'\"\n                    class=\"border-warning/40 bg-warning/[0.04] border-warning/30 dark:bg-warning/10] mx-4 my-3 rounded-lg border p-4 text-xs shadow-xs\"\n                  >\n                    <div class=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n                      <div class=\"space-y-1.5\">\n                        <div class=\"flex flex-wrap items-center gap-2\">\n                          <div class=\"bg-warning/20 text-warning flex size-6 items-center justify-center rounded-md\">\n                            <Bot class=\"size-3.5\" />\n                          </div>\n                          <span class=\"text-foreground font-semibold\">Glia AI Code Review · AST Suggestion</span>\n                          <Badge wrap variant=\"warning\" class=\"gap-1 font-semibold\">\n                            <Sparkles class=\"size-3\" />\n                            <span>Performance Optimization · High Impact</span>\n                          </Badge>\n                          <span class=\"text-muted-foreground text-xs\">Confidence 99.4% · AST Node #42</span>\n                        </div>\n\n                        <!-- Explanation -->\n                        <p class=\"text-foreground font-sans text-xs leading-relaxed font-medium\">\n                          Using\n                          <code class=\"bg-muted text-foreground rounded px-1.5 py-0.5 font-mono\"\n                            >color-mix(in oklab, var(--primary) 10%, transparent)</code\n                          >\n                          achieves identical contrast without injecting 20 additional CSS variables into the global DOM.\n                        </p>\n\n                        <!-- Code Preview Replacement -->\n                        <div class=\"border-border/60 bg-muted/50 rounded-md border p-2.5 font-mono text-xs\">\n                          <div class=\"text-muted-foreground mb-1 text-xs select-none\">\n                            Proposed AST Patch Replacement (Line 39):\n                          </div>\n                          <div class=\"text-success font-semibold\">\n                            + --primary-accent: color-mix(in oklab, var(--primary) 10%, transparent);\n                          </div>\n                        </div>\n                      </div>\n\n                      <!-- Action Buttons -->\n                      <div class=\"flex shrink-0 flex-wrap items-center gap-2 self-start sm:self-auto\">\n                        <Button\n                          size=\"xs\"\n                          variant=\"outline\"\n                          class=\"h-7 gap-1 text-xs\"\n                          @click=\"copyPatchCode('patch-1', 'color-mix(in oklab, var(--primary) 10%, transparent)')\"\n                        >\n                          <Check v-if=\"copiedPatchId === 'patch-1'\" class=\"text-success size-3\" />\n                          <Copy v-else class=\"size-3\" />\n                          <span>{{ copiedPatchId === 'patch-1' ? 'Copied' : 'Copy Patch' }}</span>\n                        </Button>\n\n                        <Button\n                          size=\"xs\"\n                          variant=\"outline\"\n                          class=\"h-7 gap-1 text-xs\"\n                          @click=\"\n                            openChatWithTopic(\n                              'Explain why OKLab color-mix avoids DOM stylesheet recalculation overhead',\n                            )\n                          \"\n                        >\n                          <MessageSquare class=\"size-3\" />\n                          <span>Explain in Chat</span>\n                        </Button>\n\n                        <Button\n                          size=\"xs\"\n                          :variant=\"appliedPatches.has('patch-1') ? 'secondary' : 'default'\"\n                          :class=\"appliedPatches.has('patch-1') ? 'border-success/30 text-success font-semibold' : ''\"\n                          class=\"h-7 gap-1 text-xs font-medium shadow-xs\"\n                          @click=\"togglePatch('patch-1')\"\n                        >\n                          <Check v-if=\"appliedPatches.has('patch-1')\" class=\"text-success size-3\" />\n                          <Zap v-else class=\"size-3\" />\n                          <span>{{\n                            appliedPatches.has('patch-1') ? 'Patch Applied ✓' : 'Apply Suggestion (1-Click)'\n                          }}</span>\n                        </Button>\n                      </div>\n                    </div>\n                  </div>\n\n                  <!-- Inline AI Review Annotation Card #2 (Pinned under line 51) -->\n                  <div\n                    v-if=\"line.annotationId === 'patch-2'\"\n                    class=\"border-success/40 bg-success/[0.04] border-success/30 dark:bg-success/10] mx-4 my-3 rounded-lg border p-4 text-xs shadow-xs\"\n                  >\n                    <div class=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n                      <div class=\"space-y-1.5\">\n                        <div class=\"flex flex-wrap items-center gap-2\">\n                          <div class=\"bg-success/20 text-success flex size-6 items-center justify-center rounded-md\">\n                            <ShieldCheck class=\"size-3.5\" />\n                          </div>\n                          <span class=\"text-foreground font-semibold\">Glia AI Code Review · Gamut Engine</span>\n                          <Badge wrap variant=\"success\" class=\"gap-1 font-semibold\">\n                            <CheckCircle2 class=\"size-3\" />\n                            <span>Accessibility &amp; Gamut · WCAG AAA Verified</span>\n                          </Badge>\n                          <span class=\"text-muted-foreground text-xs\">Confidence 98.7% · AST Node #51</span>\n                        </div>\n\n                        <!-- Explanation -->\n                        <p class=\"text-foreground font-sans text-xs leading-relaxed font-medium\">\n                          OKLCH relative gamut mapping guarantees 7:1 contrast ratio across both light and dark themes\n                          with zero perceptual hue shift on wide-gamut displays.\n                        </p>\n\n                        <!-- Code Preview Replacement -->\n                        <div class=\"border-border/60 bg-muted/50 rounded-md border p-2.5 font-mono text-xs\">\n                          <div class=\"text-muted-foreground mb-1 text-xs select-none\">\n                            Verified Relative Color Syntax:\n                          </div>\n                          <div class=\"text-success font-semibold\">\n                            + --ring-focus-shadow: 0 0 0 2px var(--color-ring);\n                          </div>\n                        </div>\n                      </div>\n\n                      <!-- Action Buttons -->\n                      <div class=\"flex shrink-0 flex-wrap items-center gap-2 self-start sm:self-auto\">\n                        <Button\n                          size=\"xs\"\n                          variant=\"outline\"\n                          class=\"h-7 gap-1 text-xs\"\n                          @click=\"\n                            openChatWithTopic(\n                              'How does OKLCH guarantee WCAG AAA contrast without shift on P3 monitors?',\n                            )\n                          \"\n                        >\n                          <MessageSquare class=\"size-3\" />\n                          <span>Explain in Chat</span>\n                        </Button>\n\n                        <Button\n                          size=\"xs\"\n                          :variant=\"appliedPatches.has('patch-2') ? 'secondary' : 'default'\"\n                          :class=\"appliedPatches.has('patch-2') ? 'border-success/30 text-success font-semibold' : ''\"\n                          class=\"h-7 gap-1 text-xs font-medium shadow-xs\"\n                          @click=\"togglePatch('patch-2')\"\n                        >\n                          <Check v-if=\"appliedPatches.has('patch-2')\" class=\"text-success size-3\" />\n                          <Zap v-else class=\"size-3\" />\n                          <span>{{\n                            appliedPatches.has('patch-2') ? 'Patch Applied ✓' : 'Apply Suggestion (1-Click)'\n                          }}</span>\n                        </Button>\n                      </div>\n                    </div>\n                  </div>\n                </template>\n              </div>\n            </div>\n          </TabsContent>\n\n          <!-- Tab 2: AST Rule Verification Suite -->\n          <TabsContent value=\"rules\" class=\"space-y-4 focus-visible:outline-none\">\n            <div class=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n              <div class=\"border-border bg-muted/20 space-y-2 rounded-lg border p-4\">\n                <div class=\"flex items-center justify-between\">\n                  <div class=\"flex items-center gap-2 text-sm font-semibold\">\n                    <ShieldCheck class=\"text-success size-4\" />\n                    <span>Rule 1: Zero Global DOM Pollution</span>\n                  </div>\n                  <Badge wrap variant=\"success\" class=\"text-xs\">Pass · Verified</Badge>\n                </div>\n                <p class=\"text-muted-foreground text-xs leading-relaxed\">\n                  Eliminates 20 static opacity custom properties. All transparency channels are evaluated dynamically in\n                  OKLab color space.\n                </p>\n              </div>\n\n              <div class=\"border-border bg-muted/20 space-y-2 rounded-lg border p-4\">\n                <div class=\"flex items-center justify-between\">\n                  <div class=\"flex items-center gap-2 text-sm font-semibold\">\n                    <Zap class=\"text-success size-4\" />\n                    <span>Rule 2: Perceptual Uniformity (ΔE &lt; 0.8)</span>\n                  </div>\n                  <Badge wrap variant=\"success\" class=\"text-xs\">Pass · Verified</Badge>\n                </div>\n                <p class=\"text-muted-foreground text-xs leading-relaxed\">\n                  OKLCH lightness (L) scale provides mathematical linearity. Step changes in lightness feel uniform to\n                  human perception across all hues.\n                </p>\n              </div>\n\n              <div class=\"border-border bg-muted/20 space-y-2 rounded-lg border p-4\">\n                <div class=\"flex items-center justify-between\">\n                  <div class=\"flex items-center gap-2 text-sm font-semibold\">\n                    <Cpu class=\"text-success size-4\" />\n                    <span>Rule 3: PostCSS Lightning Fallbacks</span>\n                  </div>\n                  <Badge wrap variant=\"success\" class=\"text-xs\">Pass · Verified</Badge>\n                </div>\n                <p class=\"text-muted-foreground text-xs leading-relaxed\">\n                  Tailwind v4 engine generates automated sRGB fallback values for legacy web clients while streaming raw\n                  OKLCH to modern browsers.\n                </p>\n              </div>\n\n              <div class=\"border-border bg-muted/20 space-y-2 rounded-lg border p-4\">\n                <div class=\"flex items-center justify-between\">\n                  <div class=\"flex items-center gap-2 text-sm font-semibold\">\n                    <CheckCircle2 class=\"text-success size-4\" />\n                    <span>Rule 4: WCAG 2.2 AAA Contrast Ratios</span>\n                  </div>\n                  <Badge wrap variant=\"success\" class=\"text-xs\">Pass · 7.1:1 Ratio</Badge>\n                </div>\n                <p class=\"text-muted-foreground text-xs leading-relaxed\">\n                  Background to foreground contrast exceeds the 7:1 ratio threshold required for government and\n                  enterprise accessible software.\n                </p>\n              </div>\n            </div>\n          </TabsContent>\n\n          <!-- Tab 3: Token Matrix & Gamut Breakdown -->\n          <TabsContent value=\"impact\" class=\"space-y-4 focus-visible:outline-none\">\n            <div class=\"border-border overflow-x-auto rounded-lg border\">\n              <div class=\"bg-muted/40 border-border max-w-[480px] min-w-full border-b px-4 py-3 text-xs font-semibold\">\n                Token Architecture Comparison: Legacy vs. OKLCH Engine\n              </div>\n              <div class=\"divide-border max-w-[480px] min-w-full divide-y text-xs\">\n                <div class=\"grid grid-cols-3 p-3 font-medium\">\n                  <span class=\"text-muted-foreground\">Evaluation Metric</span>\n                  <span class=\"text-muted-foreground\">Legacy HSL / sRGB</span>\n                  <span class=\"text-success font-bold\">OKLCH Perceptual Engine</span>\n                </div>\n                <div class=\"grid grid-cols-3 p-3\">\n                  <span class=\"font-medium\">Total Token CSS Bundle</span>\n                  <span class=\"text-muted-foreground font-mono\">14.8 KB</span>\n                  <span class=\"text-success font-mono font-bold\">10.6 KB (-28.4%)</span>\n                </div>\n                <div class=\"grid grid-cols-3 p-3\">\n                  <span class=\"font-medium\">DOM Custom Properties</span>\n                  <span class=\"text-muted-foreground font-mono\">64 variables</span>\n                  <span class=\"text-success font-mono font-bold\">44 variables (-31.2%)</span>\n                </div>\n                <div class=\"grid grid-cols-3 p-3\">\n                  <span class=\"font-medium\">Display P3 Wide Gamut</span>\n                  <span class=\"text-destructive\">Clipping on 14 colors</span>\n                  <span class=\"text-success font-bold\">100% P3 Coverage</span>\n                </div>\n                <div class=\"grid grid-cols-3 p-3\">\n                  <span class=\"font-medium\">Perceptual Uniformity</span>\n                  <span class=\"text-muted-foreground\">Non-linear (HSL shift)</span>\n                  <span class=\"text-success font-bold\">Mathematically Uniform (LCH)</span>\n                </div>\n              </div>\n            </div>\n          </TabsContent>\n        </Tabs>\n      </CardContent>\n    </Card>\n\n    <!-- Interactive AI Review Assistant Chat Panel -->\n    <Card v-if=\"isChatOpen\" class=\"border-primary/30 bg-card shadow-md\">\n      <CardHeader class=\"border-border border-b pb-3\">\n        <div class=\"flex items-center justify-between\">\n          <div class=\"flex items-center gap-2.5\">\n            <div class=\"bg-primary/10 text-primary flex size-8 items-center justify-center rounded-md\">\n              <Bot class=\"size-4\" />\n            </div>\n            <div>\n              <CardTitle class=\"text-sm font-semibold\"\n                >Glia AI Assistant · PR #{{ props.prNumber }} Review Thread</CardTitle\n              >\n              <CardDescription class=\"text-xs\">\n                Contextual code review dialogue with active AST parser &amp; contrast engine\n              </CardDescription>\n            </div>\n          </div>\n          <Button variant=\"ghost\" size=\"xs\" class=\"size-7 p-0\" aria-label=\"Close chat\" @click=\"isChatOpen = false\">\n            <X class=\"size-4\" />\n          </Button>\n        </div>\n      </CardHeader>\n\n      <CardContent class=\"space-y-4 p-4\">\n        <!-- Message History -->\n        <div class=\"max-h-[320px] space-y-3 overflow-y-auto pr-1\">\n          <div\n            v-for=\"msg in chatMessages\"\n            :key=\"msg.id\"\n            :class=\"\n              cn(\n                'flex flex-col gap-1 rounded-lg p-3 text-xs',\n                msg.sender === 'ai'\n                  ? 'border-border/60 bg-muted/40 mr-8 border'\n                  : 'bg-primary/10 text-foreground border-primary/20 ml-8 border',\n              )\n            \"\n          >\n            <div class=\"flex items-center justify-between font-semibold\">\n              <span class=\"flex items-center gap-1.5\">\n                <Bot v-if=\"msg.sender === 'ai'\" class=\"text-primary size-3.5\" />\n                <Avatar v-else class=\"size-4 border\">\n                  <AvatarImage :src=\"props.authorAvatar\" />\n                  <AvatarFallback class=\"text-xs\">ER</AvatarFallback>\n                </Avatar>\n                <span>{{ msg.author }}</span>\n              </span>\n              <span class=\"text-muted-foreground text-xs font-normal\">{{ msg.timestamp }}</span>\n            </div>\n            <p class=\"mt-1 leading-relaxed\">{{ msg.text }}</p>\n            <div\n              v-if=\"msg.codeSnippet\"\n              class=\"border-border/80 bg-muted/80 text-foreground mt-2 rounded p-2 font-mono text-xs select-all\"\n            >\n              {{ msg.codeSnippet }}\n            </div>\n          </div>\n        </div>\n\n        <!-- Preset Prompt Chips -->\n        <div class=\"flex flex-wrap items-center gap-1.5 pt-1\">\n          <span class=\"text-muted-foreground text-xs\">Quick ask:</span>\n          <button\n            type=\"button\"\n            class=\"border-border bg-muted/40 hover:bg-muted text-foreground cursor-pointer rounded-full border px-2.5 py-0.5 text-xs transition-colors\"\n            @click=\"openChatWithTopic('Why is OKLab preferred over sRGB color space?')\"\n          >\n            Why OKLab over sRGB?\n          </button>\n          <button\n            type=\"button\"\n            class=\"border-border bg-muted/40 hover:bg-muted text-foreground cursor-pointer rounded-full border px-2.5 py-0.5 text-xs transition-colors\"\n            @click=\"openChatWithTopic('How does this affect browser performance?')\"\n          >\n            Browser performance impact?\n          </button>\n        </div>\n\n        <!-- Chat Input Field -->\n        <form class=\"flex items-center gap-2 pt-1\" @submit.prevent=\"handleSendMessage\">\n          <input\n            v-model=\"chatInput\"\n            type=\"text\"\n            placeholder=\"Ask Glia AI about this code review or AST transformation...\"\n            class=\"border-input bg-background placeholder:text-muted-foreground focus-visible:ring-ring flex-1 rounded-md border px-3 py-2 text-xs focus-visible:ring-2 focus-visible:outline-none\"\n          />\n          <Button type=\"submit\" size=\"sm\" class=\"gap-1.5 text-xs\">\n            <Send class=\"size-3.5\" />\n            <span>Send</span>\n          </Button>\n        </form>\n      </CardContent>\n    </Card>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/AiCodeReviewAssistant.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/avatar.json",
    "https://uipkge.dev/r/vue/badge.json",
    "https://uipkge.dev/r/vue/button.json",
    "https://uipkge.dev/r/vue/card.json",
    "https://uipkge.dev/r/vue/separator.json",
    "https://uipkge.dev/r/vue/tabs.json"
  ],
  "description": "GitHub PR automated AI code review assistant with AST syntax diff annotations, performance suggestions, and 1-click patch application.",
  "categories": [
    "devops",
    "app",
    "ai"
  ]
}