'use client' import { useMemo, useEffect, useState } from 'react' import type { UsageData } from '@/lib/parse-logs' import { generateCoachInsights, type CoachInsight, type InsightCategory, type InsightSeverity, type CraftDimension, type CraftScores } from '@/lib/coach' import type { CommandInsight } from '@/lib/command-insights' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { formatCost, formatDuration, formatNumber } from '@/lib/format' import { Trophy, AlertTriangle, Lightbulb, DollarSign, Zap, Wrench, Monitor, Cpu, Flame, Calendar, Search, Clock, Brain, Radar, Bot, Activity, Gauge, } from 'lucide-react' const CATEGORY_ICONS: Record = { cost: DollarSign, efficiency: Zap, tools: Wrench, context: Monitor, model: Cpu, habits: Calendar, discovery: Search, streak: Flame, } const SEVERITY_STYLES: Record = { achievement: { border: 'border-l-chart-2', icon: Trophy, iconClass: 'text-chart-2' }, warning: { border: 'border-l-chart-5', icon: AlertTriangle, iconClass: 'text-chart-5' }, tip: { border: 'border-l-chart-1', icon: Lightbulb, iconClass: 'text-chart-1' }, } const CRAFT_DIMENSIONS: { key: CraftDimension letter: string label: string color: string icon: typeof Brain description: string metrics: string[] }[] = [ { key: 'context', letter: 'C', label: 'Context', color: 'var(--chart-1)', icon: Brain, description: 'How well you engineer the context available to the AI — not just window size, but the holistic curation of tokens: system prompts (CLAUDE.md), just-in-time retrieval, structured notes, sub-agent isolation, and cache efficiency.', metrics: ['System prompt maintenance (15%)', 'Cache reuse (15%)', 'Overflow avoidance (15%)', 'Just-in-time retrieval (20%)', 'Session length (10%)', 'Note-taking (10%)', 'Output density (10%)', 'Sub-agent isolation (5%)'], }, { key: 'reach', letter: 'R', label: 'Reach', color: 'var(--chart-2)', icon: Radar, description: 'How broadly you leverage available capabilities. Using diverse tools, subagents, and custom skills means you\'re getting more out of the AI assistant.', metrics: ['Tool diversity (35%)', 'Subagent parallelization (35%)', 'Skill/command adoption (30%)'], }, { key: 'autonomy', letter: 'A', label: 'Autonomy', color: 'var(--chart-3)', icon: Bot, description: 'How independently the agent works for you. High autonomy means clear prompts, fewer interruptions, the agent reading before editing, and trusting it with permissions.', metrics: ['Assistant/user message ratio (25%)', 'Low interruption rate (25%)', 'Read-before-edit ratio (25%)', 'Permission trust level (25%)'], }, { key: 'flow', letter: 'F', label: 'Flow', color: 'var(--chart-4)', icon: Activity, description: 'How consistently you maintain a coding rhythm. Regular usage builds mastery faster than sporadic intense sessions.', metrics: ['Current streak length (35%)', 'Daily consistency (35%)', 'Active days coverage (30%)'], }, { key: 'throughput', letter: 'T', label: 'Throughput', color: 'var(--chart-6)', icon: Gauge, description: 'How much output you get for your investment. Efficient sessions produce more output per dollar with fewer errors, and parallel sessions multiply your throughput.', metrics: ['Cost efficiency (25%)', 'Output volume (25%)', 'Parallel sessions (25%)', 'Low error rate (25%)'], }, ] function FitnessRing({ score, label }: { score: number; label: string }) { const radius = 70 const circumference = 2 * Math.PI * radius const offset = circumference - (score / 100) * circumference const getColor = (s: number) => { if (s >= 85) return 'var(--chart-2)' if (s >= 70) return 'var(--chart-1)' if (s >= 55) return 'var(--chart-3)' return 'var(--chart-5)' } return (
{score} {label}
) } function DimensionBar({ value, color }: { value: number; color: string }) { return (
) } function InsightCard({ insight }: { insight: CoachInsight }) { const style = SEVERITY_STYLES[insight.severity] const SeverityIcon = style.icon return (

{insight.title}

{insight.metric && ( {insight.metric} )}

{insight.description}

{insight.recommendation && (
Recommendation: {insight.recommendation}
)}
) } export function AgentCoach({ data }: { data: UsageData }) { const coach = useMemo(() => generateCoachInsights(data), [data]) const [cmdInsights, setCmdInsights] = useState([]) useEffect(() => { fetch('/api/command-insights') .then(r => r.json()) .then(setCmdInsights) .catch(() => {}) }, []) const allInsights: CoachInsight[] = [ ...coach.insights, ...cmdInsights.map(i => ({ ...i, category: 'discovery' as InsightCategory, craft: 'reach' as CraftDimension })), ] // Group insights by CRAFT dimension const insightsByDimension = (dim: CraftDimension) => allInsights.filter(i => i.craft === dim) // Ungrouped insights (no craft tag) const ungroupedWarnings = allInsights.filter(i => !i.craft && i.severity === 'warning') const ungroupedTips = allInsights.filter(i => !i.craft && i.severity === 'tip') const ungroupedAchievements = allInsights.filter(i => !i.craft && i.severity === 'achievement') return (
{/* Hero: CRAFT Score + Framework Overview */}
CRAFT Score Your overall AI coding proficiency, measured across 5 dimensions
{coach.stats.currentStreak > 0 ? `${coach.stats.currentStreak}d streak` : 'No streak'} {coach.stats.longestStreak > 0 && ( (best: {coach.stats.longestStreak}d) )}
{CRAFT_DIMENSIONS.map(({ key, letter, label, color }) => (
{letter} {label} {coach.craft[key]}
))}
Weights: A 25% · C/R/T 20% each · F 15%
{/* What is CRAFT */} What is CRAFT? A framework for measuring Human-AI coding proficiency

Every CRAFT metric is derived directly from your local conversation logs. No external integrations or surveys needed.

{CRAFT_DIMENSIONS.map(({ letter, label, color, icon: Icon }) => (
{letter}
{label}
))}

Each dimension is scored 0-100 based on your actual usage patterns. The overall score is a weighted average prioritizing behavioral quality (Autonomy) over volume (Throughput).

{/* Per-dimension breakdown with insights */} {CRAFT_DIMENSIONS.map(({ key, letter, label, color, icon: Icon, description, metrics }) => { const dimInsights = insightsByDimension(key) const dimScore = coach.craft[key] return (
{letter} {label} {description}
{dimScore}
/ 100
{/* How this score is calculated */}
How this score is calculated:
{metrics.map((m) => (
{m}
))}
{/* Score bar */}
{dimScore}/100
{/* Insights for this dimension */} {dimInsights.length > 0 ? (
{dimInsights.map(i => )}
) : (

No specific insights for this dimension yet.

)} ) })} {/* Ungrouped insights (if any) */} {(ungroupedWarnings.length > 0 || ungroupedTips.length > 0 || ungroupedAchievements.length > 0) && ( Other Insights General recommendations not tied to a specific CRAFT dimension {[...ungroupedWarnings, ...ungroupedTips, ...ungroupedAchievements].map(i => ( ))} )} {/* Session Averages */} Session Averages
Cost / Session
{formatCost(coach.stats.avgCostPerSession)}
Duration
{formatDuration(coach.stats.avgDurationMinutes)}
Messages
{formatNumber(Math.round(coach.stats.avgMessagesPerSession))}
Peak Hour
{coach.stats.peakHour}:00
) }