{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "fine-tuning-job-monitor",
  "title": "Fine Tuning Job Monitor",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/fine-tuning-job-monitor/FineTuningJobMonitor.vue",
      "content": "<script setup lang=\"ts\">\nimport { ref, computed, type HTMLAttributes } from 'vue'\nimport {\n  Activity,\n  AlertCircle,\n  Bot,\n  Check,\n  CheckCircle2,\n  Clock,\n  Copy,\n  Cpu,\n  Database,\n  Download,\n  Gauge,\n  Loader2,\n  Rocket,\n  Save,\n  ShieldCheck,\n  Sliders,\n  Sparkles,\n  TrendingDown,\n  XCircle,\n} from 'lucide-vue-next'\nimport { cn } from '@/lib/utils'\nimport { Badge } from '@/components/ui/badge'\nimport { Button } from '@/components/ui/button'\nimport { Card, CardHeader, CardTitle, CardDescription, CardContent } from '@/components/ui/card'\nimport { Progress } from '@/components/ui/progress'\nimport { Separator } from '@/components/ui/separator'\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'\n\nexport interface CheckpointRecord {\n  id: string\n  epoch: number\n  step: number\n  totalSteps: number\n  trainLoss: number\n  valLoss: number\n  size: string\n  filename: string\n  createdAgo: string\n  isBest?: boolean\n  status: 'saved' | 'best' | 'evaluating'\n}\n\nexport interface LossReading {\n  step: number\n  trainLoss: number\n  valLoss?: number\n  isProjected?: boolean\n  label?: string\n}\n\nexport interface FineTuningJobMonitorProps {\n  jobId?: string\n  baseModel?: string\n  fineTunedModelName?: string\n  status?: string\n  currentEpoch?: number\n  totalEpochs?: number\n  progressPercent?: number\n  currentStep?: number\n  totalSteps?: number\n  trainingLoss?: number\n  initialLoss?: number\n  validationLoss?: number\n  learningRate?: string\n  gpuCluster?: string\n  gpuUtilization?: number\n  vramUsage?: string\n  tokensPerSec?: number\n  elapsedTime?: string\n  etaRemaining?: string\n  trainingDataset?: string\n  trainingExamples?: number\n  validationExamples?: number\n  totalTokens?: string\n  batchSize?: number\n  microBatchSize?: number\n  gradAccumSteps?: number\n  contextLength?: number\n  optimizer?: string\n  loraRank?: number\n  loraAlpha?: number\n  loraDropout?: number\n  checkpoints?: CheckpointRecord[]\n  lossData?: LossReading[]\n  class?: HTMLAttributes['class']\n}\n\nconst defaultLossData: LossReading[] = [\n  { step: 0, trainLoss: 1.84, valLoss: 1.92, label: 'Init' },\n  { step: 25, trainLoss: 1.32, valLoss: undefined },\n  { step: 50, trainLoss: 0.95, valLoss: 1.02, label: 'Warmup Done' },\n  { step: 75, trainLoss: 0.915, valLoss: undefined },\n  { step: 100, trainLoss: 0.892, valLoss: 0.945, label: 'Epoch 1 (Ckpt #1)' },\n  { step: 125, trainLoss: 0.79, valLoss: undefined },\n  { step: 150, trainLoss: 0.71, valLoss: 0.748, label: 'Step 150' },\n  { step: 175, trainLoss: 0.64, valLoss: undefined },\n  { step: 200, trainLoss: 0.584, valLoss: 0.612, label: 'Epoch 2 (Ckpt #2)' },\n  { step: 225, trainLoss: 0.535, valLoss: undefined },\n  { step: 250, trainLoss: 0.495, valLoss: 0.52, label: 'Step 250' },\n  { step: 275, trainLoss: 0.46, valLoss: undefined },\n  { step: 300, trainLoss: 0.435, valLoss: 0.468, label: 'Epoch 3 (Ckpt #3)' },\n  { step: 320, trainLoss: 0.412, valLoss: 0.458, label: 'Step 320 (Live)' },\n  // Projected points\n  { step: 360, trainLoss: 0.395, valLoss: undefined, isProjected: true },\n  { step: 400, trainLoss: 0.38, valLoss: 0.415, isProjected: true, label: 'Epoch 4 (Proj)' },\n  { step: 450, trainLoss: 0.365, valLoss: undefined, isProjected: true },\n  { step: 500, trainLoss: 0.355, valLoss: 0.39, isProjected: true, label: 'Epoch 5 (Target)' },\n]\n\nconst defaultCheckpoints: CheckpointRecord[] = [\n  {\n    id: 'ckpt-3',\n    epoch: 3,\n    step: 300,\n    totalSteps: 500,\n    trainLoss: 0.435,\n    valLoss: 0.468,\n    size: '1.2 GB LoRA',\n    filename: 'adapter_model_step300.safetensors',\n    createdAgo: '24m ago',\n    isBest: true,\n    status: 'best',\n  },\n  {\n    id: 'ckpt-2',\n    epoch: 2,\n    step: 200,\n    totalSteps: 500,\n    trainLoss: 0.584,\n    valLoss: 0.612,\n    size: '1.2 GB LoRA',\n    filename: 'adapter_model_step200.safetensors',\n    createdAgo: '1h 44m ago',\n    isBest: false,\n    status: 'saved',\n  },\n  {\n    id: 'ckpt-1',\n    epoch: 1,\n    step: 100,\n    totalSteps: 500,\n    trainLoss: 0.892,\n    valLoss: 0.945,\n    size: '1.2 GB LoRA',\n    filename: 'adapter_model_step100.safetensors',\n    createdAgo: '3h 02m ago',\n    isBest: false,\n    status: 'saved',\n  },\n]\n\nconst props = withDefaults(defineProps<FineTuningJobMonitorProps>(), {\n  jobId: '#ft-job-2026-0842',\n  baseModel: 'Meta Llama 3.3 70B Instruct',\n  fineTunedModelName: 'llama-3.3-70b-uipkge-expert-v2',\n  status: 'Training in Progress · Epoch 3 of 5 · 64% Complete',\n  currentEpoch: 3,\n  totalEpochs: 5,\n  progressPercent: 64,\n  currentStep: 320,\n  totalSteps: 500,\n  trainingLoss: 0.412,\n  initialLoss: 1.84,\n  validationLoss: 0.458,\n  learningRate: '1.5e-5',\n  gpuCluster: '8× NVIDIA H100 80GB SXM5',\n  gpuUtilization: 100,\n  vramUsage: '76.4 GB / 80 GB',\n  tokensPerSec: 3480,\n  elapsedTime: '4h 18m 22s',\n  etaRemaining: '2h 25m',\n  trainingDataset: 'uipkge_synthetic_sfc_pairs.jsonl',\n  trainingExamples: 42500,\n  validationExamples: 4250,\n  totalTokens: '153.8M tokens',\n  batchSize: 32,\n  microBatchSize: 4,\n  gradAccumSteps: 8,\n  contextLength: 4096,\n  optimizer: 'AdamW (beta1=0.9, beta2=0.95)',\n  loraRank: 64,\n  loraAlpha: 128,\n  loraDropout: 0.05,\n})\n\nconst activeLossData = computed(() => props.lossData ?? defaultLossData)\nconst activeCheckpoints = computed(() => props.checkpoints ?? defaultCheckpoints)\n\nconst copiedJobId = ref(false)\nconst copiedDataset = ref(false)\nconst isDownloadingWeights = ref(false)\nconst isCancelling = ref(false)\nconst isJobCancelled = ref(false)\nconst deployingCkptId = ref<string | null>(null)\nconst activeNotification = ref<{ title: string; message: string; type: 'success' | 'info' | 'destructive' } | null>(\n  null,\n)\nconst selectedStepIndex = ref<number | null>(13) // Default to step 320\n\nfunction showNotification(title: string, message: string, type: 'success' | 'info' | 'destructive' = 'success') {\n  activeNotification.value = { title, message, type }\n  setTimeout(() => {\n    if (activeNotification.value?.title === title) {\n      activeNotification.value = null\n    }\n  }, 4000)\n}\n\nfunction copyJobId() {\n  if (typeof navigator !== 'undefined' && navigator.clipboard) {\n    navigator.clipboard.writeText(props.jobId)\n    copiedJobId.value = true\n    setTimeout(() => {\n      copiedJobId.value = false\n    }, 2000)\n  }\n}\n\nfunction copyDatasetName() {\n  if (typeof navigator !== 'undefined' && navigator.clipboard) {\n    navigator.clipboard.writeText(props.trainingDataset)\n    copiedDataset.value = true\n    setTimeout(() => {\n      copiedDataset.value = false\n    }, 2000)\n  }\n}\n\nfunction handleDownloadWeights() {\n  if (isDownloadingWeights.value) return\n  isDownloadingWeights.value = true\n  setTimeout(() => {\n    isDownloadingWeights.value = false\n    showNotification(\n      'Weights Download Triggered',\n      'LoRA adapter weights (adapter_model.safetensors, 1.2 GB) download initialized with SHA-256 verification.',\n    )\n  }, 900)\n}\n\nfunction handleCancelJob() {\n  if (isCancelling.value || isJobCancelled.value) return\n  isCancelling.value = true\n  setTimeout(() => {\n    isCancelling.value = false\n    isJobCancelled.value = true\n    showNotification(\n      'Job Cancellation Dispatched',\n      'SIGTERM gracefully sent to GPU cluster. Last checkpoint #3 preserved.',\n      'destructive',\n    )\n  }, 700)\n}\n\nfunction handleDeployToPlayground(ckpt: CheckpointRecord) {\n  deployingCkptId.value = ckpt.id\n  setTimeout(() => {\n    deployingCkptId.value = null\n    showNotification(\n      'Checkpoint Deployed to Playground',\n      `Checkpoint Epoch ${ckpt.epoch} (Step ${ckpt.step}) has been loaded into the interactive testing playground with zero cold-start latency.`,\n    )\n  }, 1000)\n}\n\n// SVG Telemetry Loss Curves Math\n// Total steps: 0..500. Loss scale: 0.00..2.00\n// ViewBox: 740 x 220\n// Padding: left=45, right=695 (usable width=650), top=25 (loss=2.00), bottom=190 (loss=0.00) (usable height=165)\nconst svgWidth = 740\nconst padLeft = 45\nconst padRight = 695\nconst usableW = padRight - padLeft\nconst padTop = 25\nconst padBottom = 190\nconst usableH = padBottom - padTop\n\nfunction mapX(step: number): number {\n  return padLeft + (step / props.totalSteps) * usableW\n}\n\nfunction mapY(loss: number): number {\n  // loss 0.00 -> 190, loss 2.00 -> 25\n  const clamped = Math.max(0, Math.min(2.0, loss))\n  return padBottom - (clamped / 2.0) * usableH\n}\n\nconst targetLossY = computed(() => mapY(0.4))\nconst currentStepX = computed(() => mapX(props.currentStep))\n\n// Separate historical points from projected points\nconst historicalPoints = computed(() => activeLossData.value.filter((d) => !d.isProjected))\nconst projectedPoints = computed(() => {\n  const proj = activeLossData.value.filter((d) => d.isProjected)\n  const lastHist = historicalPoints.value[historicalPoints.value.length - 1]\n  return lastHist ? [lastHist, ...proj] : proj\n})\n\nconst trainPathHistoric = computed(() => {\n  const pts = historicalPoints.value\n  if (!pts.length) return ''\n  let path = `M ${mapX(pts[0].step)},${mapY(pts[0].trainLoss)}`\n  for (let i = 1; i < pts.length; i++) {\n    const prev = pts[i - 1]\n    const curr = pts[i]\n    const x0 = mapX(prev.step)\n    const y0 = mapY(prev.trainLoss)\n    const x1 = mapX(curr.step)\n    const y1 = mapY(curr.trainLoss)\n    const cx = (x0 + x1) / 2\n    path += ` C ${cx},${y0} ${cx},${y1} ${x1},${y1}`\n  }\n  return path\n})\n\nconst trainAreaHistoric = computed(() => {\n  const pts = historicalPoints.value\n  if (!pts.length) return ''\n  const firstX = mapX(pts[0].step)\n  const lastX = mapX(pts[pts.length - 1].step)\n  return `${trainPathHistoric.value} L ${lastX},${padBottom} L ${firstX},${padBottom} Z`\n})\n\nconst trainPathProjected = computed(() => {\n  const pts = projectedPoints.value\n  if (!pts.length) return ''\n  let path = `M ${mapX(pts[0].step)},${mapY(pts[0].trainLoss)}`\n  for (let i = 1; i < pts.length; i++) {\n    const prev = pts[i - 1]\n    const curr = pts[i]\n    const x0 = mapX(prev.step)\n    const y0 = mapY(prev.trainLoss)\n    const x1 = mapX(curr.step)\n    const y1 = mapY(curr.trainLoss)\n    const cx = (x0 + x1) / 2\n    path += ` C ${cx},${y0} ${cx},${y1} ${x1},${y1}`\n  }\n  return path\n})\n\nconst valPointsHistoric = computed(() => activeLossData.value.filter((d) => !d.isProjected && d.valLoss !== undefined))\n\nconst valPathHistoric = computed(() => {\n  const pts = valPointsHistoric.value\n  if (!pts.length) return ''\n  let path = `M ${mapX(pts[0].step)},${mapY(pts[0].valLoss!)}`\n  for (let i = 1; i < pts.length; i++) {\n    const prev = pts[i - 1]\n    const curr = pts[i]\n    const x0 = mapX(prev.step)\n    const y0 = mapY(prev.valLoss!)\n    const x1 = mapX(curr.step)\n    const y1 = mapY(curr.valLoss!)\n    const cx = (x0 + x1) / 2\n    path += ` C ${cx},${y0} ${cx},${y1} ${x1},${y1}`\n  }\n  return path\n})\n\nconst valPointsProjected = computed(() => {\n  const list = activeLossData.value.filter((d) => d.valLoss !== undefined && d.isProjected)\n  const lastValHist = valPointsHistoric.value[valPointsHistoric.value.length - 1]\n  return lastValHist ? [lastValHist, ...list] : list\n})\n\nconst valPathProjected = computed(() => {\n  const pts = valPointsProjected.value\n  if (!pts.length) return ''\n  let path = `M ${mapX(pts[0].step)},${mapY(pts[0].valLoss!)}`\n  for (let i = 1; i < pts.length; i++) {\n    const prev = pts[i - 1]\n    const curr = pts[i]\n    const x0 = mapX(prev.step)\n    const y0 = mapY(prev.valLoss!)\n    const x1 = mapX(curr.step)\n    const y1 = mapY(curr.valLoss!)\n    const cx = (x0 + x1) / 2\n    path += ` C ${cx},${y0} ${cx},${y1} ${x1},${y1}`\n  }\n  return path\n})\n</script>\n\n<template>\n  <div data-slot=\"fine-tuning-job-monitor\" :class=\"cn('mx-auto w-full max-w-6xl space-y-6', props.class)\">\n    <!-- Header Section -->\n    <div class=\"flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between\">\n      <div class=\"space-y-1.5\">\n        <div class=\"flex flex-wrap items-center gap-2.5\">\n          <div class=\"flex items-center gap-2.5\">\n            <div\n              class=\"border-info/30 bg-info/10 text-info text-info flex size-10 items-center justify-center rounded-xl border shadow-xs\"\n            >\n              <Bot class=\"size-5\" />\n            </div>\n            <div>\n              <div class=\"flex flex-wrap items-center gap-2\">\n                <h1 class=\"text-foreground font-mono text-xl font-bold tracking-tight break-all sm:text-2xl\">\n                  {{ fineTunedModelName }}\n                </h1>\n                <button\n                  type=\"button\"\n                  class=\"bg-muted hover:bg-muted/80 text-muted-foreground hover:text-foreground border-border/80 inline-flex min-h-6 items-center gap-1 rounded-md border px-2 py-0.5 font-mono text-xs transition-colors\"\n                  :title=\"'Copy Job ID: ' + jobId\"\n                  @click=\"copyJobId\"\n                >\n                  <span class=\"text-foreground font-medium\">{{ jobId }}</span>\n                  <Check v-if=\"copiedJobId\" class=\"text-success size-3\" />\n                  <Copy v-else class=\"size-3 opacity-70\" />\n                </button>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <div class=\"text-muted-foreground flex flex-wrap items-center gap-x-3 gap-y-1 text-xs\">\n          <div class=\"flex items-center gap-1.5\">\n            <span class=\"text-muted-foreground\">Base Model:</span>\n            <span class=\"text-foreground font-medium\">{{ baseModel }}</span>\n          </div>\n          <span>·</span>\n          <!-- Live Status Badge -->\n          <div class=\"flex items-center gap-1.5\">\n            <span v-if=\"!isJobCancelled\" class=\"relative flex size-2\">\n              <span class=\"bg-info absolute inline-flex h-full w-full rounded-full opacity-75\" />\n              <span class=\"bg-info relative inline-flex size-2 rounded-full\" />\n            </span>\n            <span v-else class=\"bg-destructive size-2 rounded-full\" />\n            <span :class=\"['font-medium', isJobCancelled ? 'text-destructive' : 'text-info']\">\n              {{ isJobCancelled ? 'Job Cancelled by Operator' : status }}\n            </span>\n          </div>\n          <span>·</span>\n          <div class=\"flex items-center gap-1\">\n            <Clock class=\"size-3.5\" />\n            <span class=\"tabular-nums\">Elapsed: {{ elapsedTime }}</span>\n            <span class=\"text-muted-foreground\">· ETA {{ etaRemaining }}</span>\n          </div>\n        </div>\n      </div>\n\n      <!-- Action Buttons -->\n      <div class=\"flex flex-wrap items-center gap-2.5\">\n        <Button\n          variant=\"ghost\"\n          size=\"sm\"\n          :disabled=\"isCancelling || isJobCancelled\"\n          class=\"text-muted-foreground hover:bg-destructive/10 hover:text-destructive h-8.5 gap-1.5 text-xs font-medium\"\n          @click=\"handleCancelJob\"\n        >\n          <XCircle :class=\"['size-3.5', isCancelling ? 'animate-spin' : '']\" />\n          <span>{{ isJobCancelled ? 'Cancelled' : isCancelling ? 'Cancelling...' : 'Cancel Job' }}</span>\n        </Button>\n\n        <Button\n          aria-label=\"Download attachment\"\n          variant=\"default\"\n          size=\"sm\"\n          :disabled=\"isDownloadingWeights\"\n          class=\"h-8.5 gap-2 text-xs font-medium shadow-xs\"\n          @click=\"handleDownloadWeights\"\n        >\n          <Download :class=\"['size-3.5', isDownloadingWeights ? 'animate-bounce' : '']\" />\n          <span>{{ isDownloadingWeights ? 'Preparing Archive...' : 'Download Weights / LoRA Adapter' }}</span>\n        </Button>\n      </div>\n    </div>\n\n    <!-- Notification Toast Banner -->\n    <div\n      v-if=\"activeNotification\"\n      :class=\"[\n        'flex items-center justify-between gap-x-2 rounded-lg border p-3 text-xs shadow-xs transition-colors',\n        activeNotification.type === 'destructive'\n          ? 'border-destructive/30 bg-destructive/10 text-destructive'\n          : 'border-border bg-card text-card-foreground',\n      ]\"\n      role=\"status\"\n    >\n      <div class=\"flex items-center gap-2.5\">\n        <CheckCircle2 v-if=\"activeNotification.type === 'success'\" class=\"text-success size-4 shrink-0\" />\n        <AlertCircle v-else class=\"text-destructive size-4 shrink-0\" />\n        <div>\n          <span class=\"text-foreground font-semibold\">{{ activeNotification.title }}: </span>\n          <span class=\"text-muted-foreground\">{{ activeNotification.message }}</span>\n        </div>\n      </div>\n      <Button\n        aria-label=\"Dismiss notification\"\n        variant=\"ghost\"\n        size=\"icon-sm\"\n        class=\"text-muted-foreground hover:text-foreground size-6\"\n        @click=\"activeNotification = null\"\n      >\n        <span class=\"text-xs\">✕</span>\n      </Button>\n    </div>\n\n    <!-- 4 Training Telemetry Cards -->\n    <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n      <!-- 1. Current Training Loss -->\n      <Card class=\"border-border bg-card text-card-foreground shadow-xs\">\n        <CardHeader class=\"pb-2\">\n          <div class=\"flex items-center justify-between gap-2\">\n            <div class=\"flex min-w-0 items-center gap-2\">\n              <div\n                class=\"border-info/20 bg-info/10 text-info flex size-8 shrink-0 items-center justify-center rounded-lg border\"\n              >\n                <Activity class=\"size-4\" />\n              </div>\n              <CardTitle class=\"truncate text-sm font-medium\">Training Loss</CardTitle>\n            </div>\n            <Badge wrap variant=\"outline\" class=\"font-mono text-xs tabular-nums\">\n              Step {{ currentStep }}/{{ totalSteps }}\n            </Badge>\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-2.5 pt-1\">\n          <div class=\"flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5\">\n            <div class=\"flex items-baseline gap-1.5\">\n              <span class=\"text-foreground font-mono text-3xl font-bold tracking-tight tabular-nums\">\n                {{ trainingLoss.toFixed(3) }}\n              </span>\n              <span class=\"text-muted-foreground text-xs font-normal\">cross-entropy</span>\n            </div>\n            <div class=\"text-success flex items-center gap-1 text-xs font-semibold\">\n              <TrendingDown class=\"size-3.5\" />\n              <span class=\"tabular-nums\">-77.6%</span>\n            </div>\n          </div>\n\n          <div class=\"border-border/60 border-t pt-2 text-xs\">\n            <div class=\"text-muted-foreground flex flex-wrap items-center justify-between gap-x-2 gap-y-0.5\">\n              <span>Initial Loss:</span>\n              <span class=\"text-foreground font-mono font-medium tabular-nums\">{{ initialLoss.toFixed(3) }}</span>\n            </div>\n            <p class=\"text-muted-foreground mt-0.5 text-xs\">Target convergence corridor: &lt; 0.450</p>\n          </div>\n        </CardContent>\n      </Card>\n\n      <!-- 2. Validation Loss -->\n      <Card class=\"border-border bg-card text-card-foreground shadow-xs\">\n        <CardHeader class=\"pb-2\">\n          <div class=\"flex items-center justify-between gap-2\">\n            <div class=\"flex min-w-0 items-center gap-2\">\n              <div\n                class=\"border-success/20 bg-success/10 text-success flex size-8 shrink-0 items-center justify-center rounded-lg border\"\n              >\n                <ShieldCheck class=\"size-4\" />\n              </div>\n              <CardTitle class=\"truncate text-sm font-medium\">Validation Loss</CardTitle>\n            </div>\n            <Badge wrap variant=\"success\" class=\"shrink-0 text-xs\">Generalizing</Badge>\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-2.5 pt-1\">\n          <div class=\"flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5\">\n            <div class=\"flex items-baseline gap-1.5\">\n              <span class=\"text-foreground font-mono text-3xl font-bold tracking-tight tabular-nums\">\n                {{ validationLoss.toFixed(3) }}\n              </span>\n              <span class=\"text-muted-foreground text-xs font-normal\">eval set</span>\n            </div>\n            <span class=\"text-success text-success text-xs font-medium tabular-nums\"> +0.046 gap </span>\n          </div>\n\n          <div class=\"border-border/60 border-t pt-2 text-xs\">\n            <div class=\"text-muted-foreground flex items-center justify-between gap-x-2\">\n              <span>Overfitting Status:</span>\n              <span class=\"text-success font-medium\">No Overfitting</span>\n            </div>\n            <p class=\"text-muted-foreground mt-0.5 text-xs\">Evaluated every 50 steps on 4,250 rows</p>\n          </div>\n        </CardContent>\n      </Card>\n\n      <!-- 3. Learning Rate -->\n      <Card class=\"border-border bg-card text-card-foreground shadow-xs\">\n        <CardHeader class=\"pb-2\">\n          <div class=\"flex items-center justify-between gap-2\">\n            <div class=\"flex min-w-0 items-center gap-2\">\n              <div\n                class=\"border-chart-1/20 bg-chart-1/10 text-chart-1 flex size-8 shrink-0 items-center justify-center rounded-lg border\"\n              >\n                <Gauge class=\"size-4\" />\n              </div>\n              <CardTitle class=\"truncate text-sm font-medium\">Learning Rate</CardTitle>\n            </div>\n            <Badge wrap variant=\"outline\" class=\"shrink-0 font-mono text-xs\">Cosine</Badge>\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-2.5 pt-1\">\n          <div class=\"flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5\">\n            <div class=\"flex items-baseline gap-1.5\">\n              <span class=\"text-foreground font-mono text-3xl font-bold tracking-tight tabular-nums\">\n                {{ learningRate }}\n              </span>\n              <span class=\"text-muted-foreground text-xs font-normal\">AdamW</span>\n            </div>\n            <span class=\"text-muted-foreground text-xs font-medium tabular-nums\">Decay active</span>\n          </div>\n\n          <div class=\"border-border/60 border-t pt-2 text-xs\">\n            <div class=\"text-muted-foreground flex items-center justify-between gap-x-2\">\n              <span>Schedule:</span>\n              <span class=\"text-foreground font-medium\">Cosine Decay (10% warmup)</span>\n            </div>\n            <p class=\"text-muted-foreground mt-0.5 text-xs\">Peak: 1.5e-4 · Min: 1.0e-6</p>\n          </div>\n        </CardContent>\n      </Card>\n\n      <!-- 4. GPU Compute Cluster -->\n      <Card class=\"border-border bg-card text-card-foreground shadow-xs\">\n        <CardHeader class=\"pb-2\">\n          <div class=\"flex items-center justify-between gap-2\">\n            <div class=\"flex min-w-0 items-center gap-2\">\n              <div\n                class=\"border-warning/20 bg-warning/10 text-warning flex size-8 shrink-0 items-center justify-center rounded-lg border\"\n              >\n                <Cpu class=\"size-4\" />\n              </div>\n              <CardTitle class=\"truncate text-sm font-medium\">GPU Compute Cluster</CardTitle>\n            </div>\n            <Badge wrap variant=\"success\" class=\"shrink-0 text-xs tabular-nums\"> {{ gpuUtilization }}% Utilized </Badge>\n          </div>\n        </CardHeader>\n        <CardContent class=\"space-y-2.5 pt-1\">\n          <div class=\"flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5\">\n            <div>\n              <span class=\"text-foreground text-lg font-bold tracking-tight sm:text-xl\">\n                {{ gpuCluster }}\n              </span>\n            </div>\n          </div>\n\n          <div class=\"space-y-1\">\n            <Progress :model-value=\"gpuUtilization\" class=\"[&_[data-slot=progress-indicator]]:bg-success h-1.5\" />\n            <div class=\"text-muted-foreground flex items-center justify-between gap-x-2 text-xs\">\n              <span\n                >VRAM: <span class=\"text-foreground font-mono font-medium tabular-nums\">{{ vramUsage }}</span></span\n              >\n              <span class=\"font-mono tabular-nums\">{{ tokensPerSec.toLocaleString() }} tok/s</span>\n            </div>\n          </div>\n        </CardContent>\n      </Card>\n    </div>\n\n    <!-- Training & Validation Loss SVG Trend Curve -->\n    <Card class=\"border-border bg-card text-card-foreground shadow-xs\">\n      <CardHeader class=\"pb-3\">\n        <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n          <div class=\"space-y-1\">\n            <div class=\"flex items-center gap-2\">\n              <Activity class=\"text-primary size-4\" />\n              <CardTitle class=\"text-base font-semibold\">Training & Validation Loss Convergence</CardTitle>\n            </div>\n            <CardDescription class=\"text-xs\">\n              Dual-series loss trajectory across {{ totalSteps }} gradient steps. Solid lines represent observed loss;\n              dashed lines denote projected cosine decay trajectory.\n            </CardDescription>\n          </div>\n\n          <!-- Legend & Metrics -->\n          <div class=\"flex flex-wrap items-center gap-3\">\n            <div class=\"text-muted-foreground flex flex-wrap items-center gap-3 text-xs\">\n              <div class=\"flex items-center gap-1.5\">\n                <span class=\"bg-info size-2.5 rounded-full\" />\n                <span class=\"text-foreground font-medium\">Training Loss ({{ trainingLoss.toFixed(3) }})</span>\n              </div>\n              <div class=\"flex items-center gap-1.5\">\n                <span class=\"bg-success size-2.5 rounded-full\" />\n                <span class=\"text-foreground font-medium\">Validation Loss ({{ validationLoss.toFixed(3) }})</span>\n              </div>\n              <div class=\"flex items-center gap-1.5\">\n                <span class=\"border-destructive bg-destructive h-0.5 w-3 border-b border-dashed\" />\n                <span class=\"text-muted-foreground\">Target (&lt; 0.400)</span>\n              </div>\n            </div>\n          </div>\n        </div>\n      </CardHeader>\n\n      <CardContent class=\"space-y-4\">\n        <!-- SVG Chart Canvas Area -->\n        <div class=\"bg-muted/20 border-border/60 relative w-full overflow-x-auto rounded-lg border p-2 sm:p-4\">\n          <svg class=\"h-64 w-full max-w-[600px] min-w-full\" :viewBox=\"`0 0 ${svgWidth} 220`\" preserveAspectRatio=\"none\">\n            <defs>\n              <linearGradient id=\"grad-train-loss-vue\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n                <stop offset=\"0%\" stop-color=\"var(--color-sky-500, #0ea5e9)\" stop-opacity=\"0.28\" />\n                <stop offset=\"100%\" stop-color=\"var(--color-sky-500, #0ea5e9)\" stop-opacity=\"0.0\" />\n              </linearGradient>\n            </defs>\n\n            <!-- Shaded Target Convergence Zone (Loss 0.00 to 0.40 -> Y: 190 to 157) -->\n            <rect\n              :x=\"padLeft\"\n              :y=\"targetLossY\"\n              :width=\"usableW\"\n              :height=\"padBottom - targetLossY\"\n              fill=\"var(--color-emerald-500, #10b981)\"\n              fill-opacity=\"0.05\"\n              rx=\"4\"\n            />\n\n            <!-- Horizontal Grid Lines -->\n            <line\n              :x1=\"padLeft\"\n              y1=\"25\"\n              :x2=\"padRight\"\n              y2=\"25\"\n              stroke=\"currentColor\"\n              class=\"text-border/40\"\n              stroke-width=\"1\"\n            />\n            <line\n              :x1=\"padLeft\"\n              y1=\"66\"\n              :x2=\"padRight\"\n              y2=\"66\"\n              stroke=\"currentColor\"\n              class=\"text-border/40\"\n              stroke-width=\"1\"\n            />\n            <line\n              :x1=\"padLeft\"\n              y1=\"107\"\n              :x2=\"padRight\"\n              y2=\"107\"\n              stroke=\"currentColor\"\n              class=\"text-border/40\"\n              stroke-width=\"1\"\n            />\n            <line\n              :x1=\"padLeft\"\n              y1=\"148\"\n              :x2=\"padRight\"\n              y2=\"148\"\n              stroke=\"currentColor\"\n              class=\"text-border/40\"\n              stroke-width=\"1\"\n            />\n            <line\n              :x1=\"padLeft\"\n              :y1=\"targetLossY\"\n              :x2=\"padRight\"\n              :y2=\"targetLossY\"\n              stroke=\"var(--color-rose-500, #f43f5e)\"\n              stroke-width=\"1.5\"\n              stroke-dasharray=\"4 4\"\n            />\n            <line\n              :x1=\"padLeft\"\n              :y1=\"padBottom\"\n              :x2=\"padRight\"\n              :y2=\"padBottom\"\n              stroke=\"currentColor\"\n              class=\"text-border/40\"\n              stroke-width=\"1\"\n            />\n\n            <!-- Y-Axis Scale Labels -->\n            <text :x=\"padLeft - 8\" y=\"29\" text-anchor=\"end\" class=\"fill-muted-foreground font-mono text-xs\">2.00</text>\n            <text :x=\"padLeft - 8\" y=\"70\" text-anchor=\"end\" class=\"fill-muted-foreground font-mono text-xs\">1.50</text>\n            <text :x=\"padLeft - 8\" y=\"111\" text-anchor=\"end\" class=\"fill-muted-foreground font-mono text-xs\">1.00</text>\n            <text :x=\"padLeft - 8\" y=\"152\" text-anchor=\"end\" class=\"fill-muted-foreground font-mono text-xs\">0.50</text>\n            <text\n              :x=\"padLeft - 8\"\n              :y=\"targetLossY + 4\"\n              text-anchor=\"end\"\n              class=\"fill-destructive font-mono text-xs font-semibold\"\n            >\n              0.40\n            </text>\n            <text :x=\"padLeft - 8\" :y=\"padBottom + 4\" text-anchor=\"end\" class=\"fill-muted-foreground font-mono text-xs\">\n              0.00\n            </text>\n\n            <!-- Current Step 320 Vertical Indicator Line -->\n            <line\n              :x1=\"currentStepX\"\n              y1=\"20\"\n              :x2=\"currentStepX\"\n              :y2=\"padBottom\"\n              stroke=\"var(--color-sky-500, #0ea5e9)\"\n              stroke-width=\"1.5\"\n              stroke-dasharray=\"2 3\"\n            />\n\n            <!-- Training Loss Area & Solid Line (Observed) -->\n            <path :d=\"trainAreaHistoric\" fill=\"url(#grad-train-loss-vue)\" />\n            <path\n              :d=\"trainPathHistoric\"\n              fill=\"none\"\n              stroke=\"var(--color-sky-500, #0ea5e9)\"\n              stroke-width=\"2.5\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n            />\n\n            <!-- Training Loss Projected Line (Dashed) -->\n            <path\n              :d=\"trainPathProjected\"\n              fill=\"none\"\n              stroke=\"var(--color-sky-500, #0ea5e9)\"\n              stroke-width=\"2\"\n              stroke-dasharray=\"4 4\"\n              stroke-opacity=\"0.6\"\n              stroke-linecap=\"round\"\n            />\n\n            <!-- Validation Loss Curve (Observed Solid Emerald) -->\n            <path\n              :d=\"valPathHistoric\"\n              fill=\"none\"\n              stroke=\"var(--color-emerald-500, #10b981)\"\n              stroke-width=\"2.5\"\n              stroke-linecap=\"round\"\n              stroke-linejoin=\"round\"\n            />\n\n            <!-- Validation Loss Projected Line (Dashed Emerald) -->\n            <path\n              :d=\"valPathProjected\"\n              fill=\"none\"\n              stroke=\"var(--color-emerald-500, #10b981)\"\n              stroke-width=\"2\"\n              stroke-dasharray=\"4 4\"\n              stroke-opacity=\"0.6\"\n              stroke-linecap=\"round\"\n            />\n\n            <!-- Validation Loss Checkpoint Nodes (Observed) -->\n            <g v-for=\"pt in valPointsHistoric\" :key=\"'val-' + pt.step\">\n              <circle\n                :cx=\"mapX(pt.step)\"\n                :cy=\"mapY(pt.valLoss!)\"\n                r=\"4\"\n                class=\"stroke-background fill-success cursor-pointer stroke-2 transition-transform hover:scale-125\"\n                @mouseenter=\"selectedStepIndex = activeLossData.findIndex((d) => d.step === pt.step)\"\n              />\n            </g>\n\n            <!-- Training Loss Interactive Point Markers -->\n            <g v-for=\"(pt, idx) in historicalPoints\" :key=\"'train-' + pt.step\">\n              <circle\n                :cx=\"mapX(pt.step)\"\n                :cy=\"mapY(pt.trainLoss)\"\n                :r=\"pt.step === currentStep ? 5 : 3\"\n                :class=\"[\n                  'stroke-background cursor-pointer stroke-2 transition-transform hover:scale-150',\n                  pt.step === currentStep ? 'fill-info ring-info ring-2' : 'fill-info',\n                ]\"\n                @mouseenter=\"selectedStepIndex = idx\"\n              />\n            </g>\n\n            <!-- Current Step Marker Pin Top Flag -->\n            <g :transform=\"`translate(${currentStepX - 44}, 10)`\">\n              <rect width=\"88\" height=\"18\" rx=\"4\" class=\"dark:fill-info fill-sky-600\" />\n              <text x=\"44\" y=\"13\" text-anchor=\"middle\" class=\"fill-white font-mono text-xs font-semibold\">\n                Step 320 / 500\n              </text>\n            </g>\n          </svg>\n\n          <!-- X-Axis Step Milestones -->\n          <div class=\"mt-2 grid grid-cols-2 gap-2 text-xs sm:grid-cols-4 lg:grid-cols-7\">\n            <div\n              v-for=\"(pt, idx) in activeLossData.filter((d) => d.label)\"\n              :key=\"idx\"\n              :class=\"[\n                'rounded p-1.5 text-center transition-colors',\n                selectedStepIndex === activeLossData.indexOf(pt)\n                  ? 'bg-muted border-border/80 border shadow-2xs'\n                  : 'bg-muted/30 border border-transparent',\n              ]\"\n            >\n              <p class=\"text-foreground font-mono text-xs font-semibold tabular-nums\">Step {{ pt.step }}</p>\n              <p class=\"text-muted-foreground truncate text-xs\">{{ pt.label }}</p>\n              <div class=\"mt-0.5 flex items-center justify-center gap-1 font-mono text-xs tabular-nums\">\n                <span class=\"text-info\">{{ pt.trainLoss.toFixed(3) }}</span>\n                <span v-if=\"pt.valLoss\" class=\"text-success\"> / {{ pt.valLoss.toFixed(3) }} </span>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <!-- Metric Summary Strip -->\n        <div class=\"grid grid-cols-2 gap-3 text-xs sm:grid-cols-3 lg:grid-cols-5\">\n          <div class=\"border-border bg-muted/30 rounded-lg border p-2.5\">\n            <span class=\"text-muted-foreground\">Step Progress</span>\n            <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">\n              {{ currentStep }} / {{ totalSteps }} ({{ progressPercent }}%)\n            </p>\n            <div class=\"mt-1\">\n              <Progress :model-value=\"progressPercent\" class=\"[&_[data-slot=progress-indicator]]:bg-info h-1\" />\n            </div>\n          </div>\n\n          <div class=\"border-border bg-muted/30 rounded-lg border p-2.5\">\n            <span class=\"text-muted-foreground\">Tokens Processed</span>\n            <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">98.4M / 153.8M</p>\n            <span class=\"text-muted-foreground text-xs\">64.0% of corpus</span>\n          </div>\n\n          <div class=\"border-border bg-muted/30 rounded-lg border p-2.5\">\n            <span class=\"text-muted-foreground\">Cluster Throughput</span>\n            <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">\n              {{ tokensPerSec.toLocaleString() }} tok/s\n            </p>\n            <span class=\"text-success text-xs font-medium\">Zero pipeline bubbles</span>\n          </div>\n\n          <div class=\"border-border bg-muted/30 rounded-lg border p-2.5\">\n            <span class=\"text-muted-foreground\">Current Epoch</span>\n            <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">\n              Epoch {{ currentEpoch }} of {{ totalEpochs }}\n            </p>\n            <span class=\"text-muted-foreground text-xs\">100 steps / epoch</span>\n          </div>\n\n          <div class=\"border-border bg-muted/30 col-span-2 rounded-lg border p-2.5 sm:col-span-3 lg:col-span-1\">\n            <span class=\"text-muted-foreground\">Convergence Projection</span>\n            <p class=\"text-success text-success font-mono text-sm font-semibold tabular-nums\">0.355 at Step 500</p>\n            <span class=\"text-muted-foreground text-xs\">Expected final loss</span>\n          </div>\n        </div>\n      </CardContent>\n    </Card>\n\n    <!-- Lower Section: Checkpoint History & Hyperparameters Configuration -->\n    <div class=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n      <!-- Left Column (2 cols on lg): Checkpoint History Table -->\n      <Card class=\"border-border bg-card text-card-foreground shadow-xs lg:col-span-2\">\n        <CardHeader class=\"pb-3\">\n          <div class=\"flex flex-col gap-1 sm:flex-row sm:items-center sm:justify-between\">\n            <div class=\"space-y-0.5\">\n              <div class=\"flex items-center gap-2\">\n                <Save class=\"text-primary size-4\" />\n                <CardTitle class=\"text-base font-semibold\">Checkpoint History & Weight Exporter</CardTitle>\n              </div>\n              <CardDescription class=\"text-xs\">\n                Saved LoRA adapter snapshots. Deploy directly to test playground or download safe tensors.\n              </CardDescription>\n            </div>\n            <Badge wrap variant=\"outline\" class=\"w-fit font-mono text-xs font-normal tabular-nums\">\n              {{ activeCheckpoints.length }} Saved Snapshots\n            </Badge>\n          </div>\n        </CardHeader>\n        <CardContent class=\"p-0 sm:p-6 sm:pt-0\">\n          <div class=\"overflow-x-auto\">\n            <Table>\n              <TableHeader>\n                <TableRow>\n                  <TableHead class=\"min-w-[140px] text-xs\">Checkpoint</TableHead>\n                  <TableHead class=\"min-w-[80px] text-xs\">Step</TableHead>\n                  <TableHead class=\"min-w-[90px] text-xs\">Train Loss</TableHead>\n                  <TableHead class=\"min-w-[90px] text-xs\">Val Loss</TableHead>\n                  <TableHead class=\"min-w-[110px] text-xs\">Size & Type</TableHead>\n                  <TableHead class=\"min-w-[100px] text-xs\">Created</TableHead>\n                  <TableHead class=\"min-w-[150px] text-right text-xs\">Actions</TableHead>\n                </TableRow>\n              </TableHeader>\n              <TableBody>\n                <TableRow\n                  v-for=\"ckpt in activeCheckpoints\"\n                  :key=\"ckpt.id\"\n                  :class=\"ckpt.isBest ? 'bg-success/[0.04]' : ''\"\n                >\n                  <TableCell class=\"text-xs whitespace-nowrap\">\n                    <div class=\"space-y-0.5\">\n                      <div class=\"flex items-center gap-1.5\">\n                        <span class=\"text-foreground font-mono font-medium\">Epoch {{ ckpt.epoch }}.0</span>\n                        <Badge wrap v-if=\"ckpt.isBest\" variant=\"success\" class=\"h-4 px-1.5 text-xs font-medium\">\n                          Best Val Loss\n                        </Badge>\n                      </div>\n                      <p class=\"text-muted-foreground font-mono text-xs\">{{ ckpt.filename }}</p>\n                    </div>\n                  </TableCell>\n                  <TableCell class=\"font-mono text-xs whitespace-nowrap tabular-nums\">\n                    {{ ckpt.step }} / {{ ckpt.totalSteps }}\n                  </TableCell>\n                  <TableCell class=\"text-xs whitespace-nowrap\">\n                    <span class=\"text-info text-info font-mono font-semibold tabular-nums\">\n                      {{ ckpt.trainLoss.toFixed(3) }}\n                    </span>\n                  </TableCell>\n                  <TableCell class=\"text-xs whitespace-nowrap\">\n                    <span class=\"text-success text-success font-mono font-semibold tabular-nums\">\n                      {{ ckpt.valLoss.toFixed(3) }}\n                    </span>\n                  </TableCell>\n                  <TableCell class=\"text-muted-foreground font-mono text-xs whitespace-nowrap tabular-nums\">\n                    {{ ckpt.size }}\n                  </TableCell>\n                  <TableCell class=\"text-muted-foreground text-xs whitespace-nowrap\">\n                    {{ ckpt.createdAgo }}\n                  </TableCell>\n                  <TableCell class=\"text-right whitespace-nowrap\">\n                    <div class=\"flex items-center justify-end gap-1.5\">\n                      <Button\n                        variant=\"outline\"\n                        size=\"xs\"\n                        :disabled=\"deployingCkptId === ckpt.id\"\n                        class=\"gap-1 text-xs\"\n                        @click=\"handleDeployToPlayground(ckpt)\"\n                      >\n                        <Loader2 v-if=\"deployingCkptId === ckpt.id\" class=\"size-3 animate-spin\" />\n                        <Rocket v-else class=\"text-info size-3\" />\n                        <span>{{ deployingCkptId === ckpt.id ? 'Deploying...' : 'Deploy to Playground' }}</span>\n                      </Button>\n                      <Button\n                        variant=\"ghost\"\n                        size=\"icon-xs\"\n                        class=\"text-muted-foreground hover:text-foreground size-7\"\n                        title=\"Download LoRA .safetensors\"\n                        @click=\"handleDownloadWeights\"\n                      >\n                        <Download class=\"size-3.5\" />\n                      </Button>\n                    </div>\n                  </TableCell>\n                </TableRow>\n              </TableBody>\n            </Table>\n          </div>\n        </CardContent>\n      </Card>\n\n      <!-- Right Column (1 col on lg): Hyperparameters & Dataset Configuration Card -->\n      <Card class=\"border-border bg-card text-card-foreground shadow-xs lg:col-span-1\">\n        <CardHeader class=\"pb-3\">\n          <div class=\"flex items-center justify-between gap-x-2\">\n            <div class=\"flex items-center gap-2\">\n              <Sliders class=\"text-primary size-4\" />\n              <CardTitle class=\"text-base font-semibold\">Hyperparameters & Dataset</CardTitle>\n            </div>\n            <Badge wrap variant=\"outline\" class=\"font-mono text-xs\">LoRA PEFT</Badge>\n          </div>\n          <CardDescription class=\"text-xs\">\n            Fine-tuning recipe manifest and dataset partition metadata.\n          </CardDescription>\n        </CardHeader>\n        <CardContent class=\"space-y-4\">\n          <!-- Training Dataset Box -->\n          <div class=\"border-border/80 bg-muted/40 space-y-2 rounded-lg border p-3 text-xs\">\n            <div class=\"flex items-center justify-between gap-x-2\">\n              <div class=\"flex items-center gap-1.5\">\n                <Database class=\"text-primary size-3.5\" />\n                <span class=\"text-foreground font-semibold\">Training Dataset</span>\n              </div>\n              <button\n                type=\"button\"\n                class=\"text-muted-foreground hover:text-foreground transition-colors\"\n                title=\"Copy dataset filename\"\n                @click=\"copyDatasetName\"\n              >\n                <Check v-if=\"copiedDataset\" class=\"text-success size-3\" />\n                <Copy v-else class=\"size-3\" />\n              </button>\n            </div>\n            <p class=\"text-foreground font-mono text-xs font-medium break-all\">{{ trainingDataset }}</p>\n            <div class=\"text-muted-foreground flex flex-wrap items-center justify-between gap-1 text-xs\">\n              <span>{{ trainingExamples.toLocaleString() }} train · {{ validationExamples.toLocaleString() }} val</span>\n              <span class=\"font-mono tabular-nums\">{{ totalTokens }}</span>\n            </div>\n          </div>\n\n          <!-- Key Parameters Grid -->\n          <div class=\"space-y-2.5 text-xs\">\n            <div class=\"border-border/50 flex items-center justify-between gap-x-2 border-b pb-1.5\">\n              <span class=\"text-muted-foreground\">Effective Batch Size:</span>\n              <span class=\"text-foreground font-mono font-semibold tabular-nums\">\n                {{ batchSize }}\n                <span class=\"text-muted-foreground font-normal\"\n                  >({{ microBatchSize }} × {{ gradAccumSteps }} accum)</span\n                >\n              </span>\n            </div>\n\n            <div class=\"border-border/50 flex items-center justify-between gap-x-2 border-b pb-1.5\">\n              <span class=\"text-muted-foreground\">Context Length:</span>\n              <span class=\"text-foreground font-mono font-semibold tabular-nums\">\n                {{ contextLength.toLocaleString() }} tokens\n              </span>\n            </div>\n\n            <div class=\"border-border/50 flex items-center justify-between gap-x-2 border-b pb-1.5\">\n              <span class=\"text-muted-foreground\">Optimizer:</span>\n              <span class=\"text-foreground font-mono font-medium\">{{ optimizer }}</span>\n            </div>\n\n            <div class=\"border-border/50 flex items-center justify-between gap-x-2 border-b pb-1.5\">\n              <span class=\"text-muted-foreground\">LoRA Rank & Alpha:</span>\n              <span class=\"text-foreground font-mono font-semibold tabular-nums\">\n                r={{ loraRank }}, α={{ loraAlpha }} (dropout={{ loraDropout }})\n              </span>\n            </div>\n\n            <div class=\"border-border/50 flex items-center justify-between gap-x-2 border-b pb-1.5\">\n              <span class=\"text-muted-foreground\">Target Modules:</span>\n              <span class=\"text-foreground font-mono text-xs\">All Linear (q, k, v, o, gate, up, down)</span>\n            </div>\n\n            <div class=\"border-border/50 flex items-center justify-between gap-x-2 border-b pb-1.5\">\n              <span class=\"text-muted-foreground\">Precision & Kernel:</span>\n              <span class=\"text-foreground font-mono\">bfloat16 · FlashAttention-2</span>\n            </div>\n\n            <div class=\"flex items-center justify-between gap-x-2\">\n              <span class=\"text-muted-foreground\">Parallelism Strategy:</span>\n              <span class=\"text-foreground font-medium\">PyTorch FSDP-2 (Hybrid Sharded)</span>\n            </div>\n          </div>\n\n          <Separator />\n\n          <!-- Export & Integration Note -->\n          <div class=\"border-border bg-muted/20 space-y-1.5 rounded-lg border p-2.5 text-xs\">\n            <div class=\"text-foreground flex items-center gap-1.5 font-medium\">\n              <Sparkles class=\"text-info size-3.5\" />\n              <span>HuggingFace Hub & vLLM Ready</span>\n            </div>\n            <p class=\"text-muted-foreground leading-relaxed\">\n              Checkpoints are stored in standard SafeTensors format with tokenizer configs ready for instant serverless\n              vLLM / TensorRT-LLM deployment.\n            </p>\n          </div>\n        </CardContent>\n      </Card>\n    </div>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/FineTuningJobMonitor.vue"
    }
  ],
  "dependencies": [
    "lucide-vue-next"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "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/progress.json",
    "https://uipkge.dev/r/vue/separator.json",
    "https://uipkge.dev/r/vue/table.json"
  ],
  "description": "LLM fine-tuning job telemetry, loss curve convergence tracking, GPU cluster utilization, hyperparameter manifests, and LoRA checkpoint exporter.",
  "categories": [
    "ai",
    "dashboard",
    "app"
  ]
}