diff --git a/codegen-examples/examples/ai_impact_analysis/README.md b/codegen-examples/examples/ai_impact_analysis/README.md
new file mode 100644
index 000000000..e34e1a8af
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/README.md
@@ -0,0 +1,124 @@
+# AI Impact Analysis
+
+This script analyzes a codebase to measure and report the impact of AI-generated code contributions. It provides detailed insights about AI vs human contributions, helping teams understand the role of AI in their development process.
+
+## Features
+
+- **Repository Analysis**: Automatically detects and analyzes git repositories:
+
+ - Uses current directory if it's a git repo
+
+ - Searches parent directories for a git repo
+
+ - Falls back to cloning a specified repository if needed
+
+ ```python
+ # Basic repository setup
+ repo_path = os.getcwd()
+ repo_config = RepoConfig.from_repo_path(repo_path)
+ repo_operator = RepoOperator(repo_config=repo_config)
+ project = ProjectConfig.from_repo_operator(repo_operator=repo_operator, programming_language=ProgrammingLanguage.PYTHON)
+ codebase = Codebase(projects=[project])
+ ```
+
+- **Comprehensive Statistics**:
+
+ - Total number of commits and AI vs human contribution percentages
+ - Files with significant AI contribution (>50%)
+ - AI-touched symbols and their impact
+ - Detailed contributor breakdown (human and AI contributors)
+
+ ```python
+ # Run the analysis
+ ai_authors = ["github-actions[bot]", "dependabot[bot]"]
+ results = analyze_ai_impact(codebase, ai_authors)
+
+ # Access statistics
+ stats = results["stats"]
+ print(f"Total commits: {stats['total_commits']}")
+ print(f"AI commits: {stats['ai_commits']} ({stats['ai_percentage']:.1f}%)")
+ print(f"Files with >50% AI: {stats['ai_file_count']} of {stats['total_file_count']}")
+
+ # View contributors
+ for author, count in results["contributors"]:
+ is_ai = any(ai_name in author for ai_name in ai_authors)
+ print(f"{'š¤' if is_ai else 'š¤'} {author}: {count} commits")
+ ```
+
+- **High-Impact Code Detection**:
+
+ - Identifies AI-written code that is heavily used by other parts of the codebase
+ - Shows dependency relationships for AI-contributed code
+
+ ```python
+ # Access high-impact AI symbols
+ for symbol in results["high_impact_symbols"]:
+ print(f"Symbol: {symbol['name']} ({symbol['filepath']})")
+ print(f"Used by {symbol['usage_count']} other symbols")
+ print(f"Last edited by: {symbol['last_editor']}")
+
+ # View top AI-contributed files
+ for file_path, percentage in stats["top_ai_files"]:
+ print(f"{file_path}: {percentage:.1f}% AI contribution")
+ ```
+
+- **Detailed Attribution**:
+
+ - Maps symbols to git history
+ - Tracks last editor and complete editor history for each symbol
+ - Flags AI-authored symbols
+
+ ```python
+ # Get attribution information for a specific symbol
+ symbol = codebase.get_symbol("path/to/file.py:MyClass.my_method")
+
+ # Access attribution data
+ print(f"Last editor: {symbol.last_editor}")
+ print(f"Editor history: {symbol.editor_history}")
+ print(f"AI authored: {symbol.is_ai_authored}")
+
+ # Find all AI-authored symbols
+ ai_symbols = [s for s in codebase.get_symbols() if s.is_ai_authored]
+ for symbol in ai_symbols:
+ print(f"AI symbol: {symbol.name}")
+ ```
+
+## Output
+
+The script generates:
+
+1. Console output with summary statistics
+1. Detailed analysis in `ai_impact_analysis.json`
+1. Attribution information added to codebase symbols
+
+## Usage
+
+```bash
+python run.py
+```
+
+The script will automatically:
+
+1. Initialize and analyze the codebase
+1. Process git history
+1. Generate attribution information
+1. Output detailed statistics
+
+You can also visualize the AI impact analysis results using a dashboard. For setup and usage instructions, please see the documentation in the `/dashboard` subdirectory.
+
+## Symbol Attribution
+
+After running the analysis, symbols in the codebase will have the following attribution information:
+
+- `symbol.last_editor`: The last person who edited the symbol
+- `symbol.editor_history`: List of all editors who have touched the symbol
+- `symbol.is_ai_authored`: Boolean indicating if the symbol was authored by AI
+
+## Learn More
+
+- [Attributions](https://docs.codegen.com/tutorials/attributions)
+- [Codegen Documentation](https://docs.codegen.com)
+
+## Contributing
+
+Feel free to submit issues and enhancement requests!
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/README.md b/codegen-examples/examples/ai_impact_analysis/dashboard/README.md
new file mode 100644
index 000000000..cde758b55
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/README.md
@@ -0,0 +1,86 @@
+# AI Impact Analysis Dashboard
+
+A web dashboard for visualizing AI-generated code contributions in your codebase. This dashboard provides detailed insights about AI vs human contributions, helping understand the role of AI in a codebase development process.
+
+## Setup
+
+### Backend
+
+1. Install dependencies:
+
+```bash
+uv venv
+source .venv/bin/activate
+uv pip install modal codegen fastapi
+```
+
+2. Deploy or serve the Modal endpoint:
+
+```bash
+modal serve backend/api.py
+```
+
+```bash
+modal deploy backend/api.py
+```
+
+### Frontend
+
+1. Install dependencies:
+
+```bash
+cd frontend
+npm install
+```
+
+2. Update the API endpoint:
+ Edit the fetch URL on line 29 in `components/repo-analysis-dashboard.tsx` to point to your Modal endpoint:
+
+```bash
+ fetch(`[your-modal-deployment-url]/analyze?repo_full_name=${repoFullName}`, {
+ method: 'POST',
+ })
+```
+
+3. Start the development server:
+
+```bash
+npm run dev
+```
+
+## Usage
+
+1. Visit the dashboard in your browser (default: http://localhost:3000)
+1. Enter a GitHub repository name (format: username/repo)
+1. Click "Analyze Repo" to generate insights
+
+The dashboard will display:
+
+- Summary statistics of AI contributions
+- Monthly contribution timeline
+- Top files with AI contributions
+- High-impact AI-authored symbols
+- Contributor breakdown visualization
+
+## Architecture
+
+- **Backend**: Modal-deployed FastAPI service that:
+
+ - Clones and analyzes repositories
+ - Processes git history
+ - Calculates AI impact metrics
+ - Returns structured analysis data
+
+- **Frontend**: Next.js application with:
+
+ - Interactive charts
+ - Visualized AI impact metrics
+
+## Learn More
+
+- [AI Impact Analysis Documentation](https://docs.codegen.com/tutorials/attributions)
+- [Codegen Documentation](https://docs.codegen.com)
+
+## Contributing
+
+Feel free to submit issues and enhancement requests!
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/backend/api.py b/codegen-examples/examples/ai_impact_analysis/dashboard/backend/api.py
new file mode 100644
index 000000000..ddb08115d
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/backend/api.py
@@ -0,0 +1,54 @@
+from codegen import Codebase
+from codegen.extensions.attribution.main import (
+ add_attribution_to_symbols,
+ analyze_ai_impact,
+)
+from fastapi import FastAPI
+from fastapi.middleware.cors import CORSMiddleware
+import modal
+
+image = modal.Image.debian_slim().apt_install("git").pip_install("codegen", "fastapi", "intervaltree", "pygit2", "requests")
+
+app = modal.App(name="ai-impact-analysis", image=image)
+
+fastapi_app = FastAPI()
+
+fastapi_app.add_middleware(
+ CORSMiddleware,
+ allow_origins=["*"],
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+)
+
+
+@fastapi_app.post("/analyze")
+async def analyze(repo_full_name: str):
+ codebase = Codebase.from_repo(repo_full_name=repo_full_name, language="python", full_history=True)
+
+ print("š¤ Analyzing AI impact on codebase...")
+
+ ai_authors = [
+ "renovate[bot]",
+ "dependabot[bot]",
+ "github-actions[bot]",
+ "devin-ai-integration[bot]",
+ ]
+
+ results = analyze_ai_impact(codebase, ai_authors)
+
+ print("\nš·ļø Adding attribution information to symbols...")
+ add_attribution_to_symbols(codebase, ai_authors)
+ print("ā
Attribution information added to symbols")
+
+ return results
+
+
+@app.function(image=image)
+@modal.asgi_app()
+def fastapi_modal_app():
+ return fastapi_app
+
+
+if __name__ == "__main__":
+ app.deploy("ai-impact-analysis")
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/app/favicon.ico b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/app/favicon.ico
new file mode 100644
index 000000000..fd8587746
Binary files /dev/null and b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/app/favicon.ico differ
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/app/globals.css b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/app/globals.css
new file mode 100644
index 000000000..1535f872d
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/app/globals.css
@@ -0,0 +1,76 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ :root {
+ --background: 0 0% 100%;
+ --foreground: 222.2 84% 4.9%;
+
+ --card: 0 0% 100%;
+ --card-foreground: 222.2 84% 4.9%;
+
+ --popover: 0 0% 100%;
+ --popover-foreground: 222.2 84% 4.9%;
+
+ --primary: 221.2 83.2% 53.3%;
+ --primary-foreground: 210 40% 98%;
+
+ --secondary: 210 40% 96.1%;
+ --secondary-foreground: 222.2 47.4% 11.2%;
+
+ --muted: 210 40% 96.1%;
+ --muted-foreground: 215.4 16.3% 46.9%;
+
+ --accent: 210 40% 96.1%;
+ --accent-foreground: 222.2 47.4% 11.2%;
+
+ --destructive: 0 84.2% 60.2%;
+ --destructive-foreground: 210 40% 98%;
+
+ --border: 214.3 31.8% 91.4%;
+ --input: 214.3 31.8% 91.4%;
+ --ring: 221.2 83.2% 53.3%;
+
+ --radius: 0.5rem;
+ }
+
+ .dark {
+ --background: 222.2 84% 4.9%;
+ --foreground: 210 40% 98%;
+
+ --card: 222.2 84% 4.9%;
+ --card-foreground: 210 40% 98%;
+
+ --popover: 222.2 84% 4.9%;
+ --popover-foreground: 210 40% 98%;
+
+ --primary: 217.2 91.2% 59.8%;
+ --primary-foreground: 222.2 47.4% 11.2%;
+
+ --secondary: 217.2 32.6% 17.5%;
+ --secondary-foreground: 210 40% 98%;
+
+ --muted: 217.2 32.6% 17.5%;
+ --muted-foreground: 215 20.2% 65.1%;
+
+ --accent: 217.2 32.6% 17.5%;
+ --accent-foreground: 210 40% 98%;
+
+ --destructive: 0 62.8% 30.6%;
+ --destructive-foreground: 210 40% 98%;
+
+ --border: 217.2 32.6% 17.5%;
+ --input: 217.2 32.6% 17.5%;
+ --ring: 224.3 76.3% 48%;
+ }
+}
+
+@layer base {
+ * {
+ @apply border-border;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/app/layout.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/app/layout.tsx
new file mode 100644
index 000000000..264632940
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/app/layout.tsx
@@ -0,0 +1,34 @@
+import type { Metadata } from "next";
+import { Inter } from "next/font/google";
+import type React from "react";
+import "./globals.css";
+import { ThemeProvider } from "@/components/theme-provider";
+
+const inter = Inter({ subsets: ["latin"] });
+
+export const metadata: Metadata = {
+ title: "AI Code Impact Analysis",
+};
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+
+
+
+ {children}
+
+
+
+ );
+}
+
+import "./globals.css";
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/app/page.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/app/page.tsx
new file mode 100644
index 000000000..5b048bbdf
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/app/page.tsx
@@ -0,0 +1,9 @@
+import { RepoAnalysisDashboard } from "@/components/repo-analysis-dashboard";
+
+export default function Home() {
+ return (
+
+
+
+ );
+}
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components.json b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components.json
new file mode 100644
index 000000000..7f48f98e8
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "default",
+ "rsc": true,
+ "tsx": true,
+ "tailwind": {
+ "config": "tailwind.config.ts",
+ "css": "app/globals.css",
+ "baseColor": "neutral",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib",
+ "hooks": "@/hooks"
+ },
+ "iconLibrary": "lucide"
+}
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/contribution-timeline.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/contribution-timeline.tsx
new file mode 100644
index 000000000..e6017ba9c
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/contribution-timeline.tsx
@@ -0,0 +1,83 @@
+"use client";
+
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+import type { Timeline } from "@/lib/types";
+import {
+ Bar,
+ BarChart,
+ ResponsiveContainer,
+ Tooltip,
+ XAxis,
+ YAxis,
+} from "recharts";
+
+interface ContributionTimelineProps {
+ timeline: Timeline[];
+}
+
+export function ContributionTimeline({ timeline }: ContributionTimelineProps) {
+ return (
+
+
+ AI Contribution Timeline
+ Monthly AI contributions over time
+
+
+
+
+
+ `${value}`}
+ />
+ {
+ if (active && payload && payload.length) {
+ return (
+
+
+
+
+ Date
+
+
+ {payload[0].payload.date}
+
+
+
+
+ Commits
+
+
+ {payload[0].value}
+
+
+
+
+ );
+ }
+ return null;
+ }}
+ />
+
+
+
+
+
+ );
+}
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/contributors-breakdown.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/contributors-breakdown.tsx
new file mode 100644
index 000000000..fb54b7fec
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/contributors-breakdown.tsx
@@ -0,0 +1,131 @@
+"use client";
+
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+import { ScrollArea } from "@/components/ui/scroll-area";
+import {
+ Cell,
+ Legend,
+ Pie,
+ PieChart,
+ ResponsiveContainer,
+ Tooltip,
+} from "recharts";
+
+interface ContributorsBreakdownProps {
+ contributors: [string, number][];
+}
+
+export function ContributorsBreakdown({
+ contributors,
+}: ContributorsBreakdownProps) {
+ // Take top 5 contributors for the chart
+ const topContributors = contributors.slice(0, 5);
+ const otherContributors = contributors.slice(5);
+ const otherCount = otherContributors.reduce(
+ (sum, [_, count]) => sum + count,
+ 0,
+ );
+
+ const chartData = [
+ ...topContributors.map(([name, count]) => ({
+ name: name.split(" ")[0], // Just use first name for chart
+ fullName: name,
+ count,
+ })),
+ otherContributors.length > 0
+ ? { name: "Others", fullName: "Other Contributors", count: otherCount }
+ : null,
+ ].filter(Boolean);
+
+ const COLORS = [
+ "#3b82f6",
+ "#10b981",
+ "#f59e0b",
+ "#ef4444",
+ "#8b5cf6",
+ "#6b7280",
+ ];
+
+ return (
+
+
+ Contributors Breakdown
+ Top contributors by commit count
+
+
+
+
+
+
+
+ {chartData.map((entry, index) => (
+ |
+ ))}
+
+ [
+ value,
+ props.payload.fullName,
+ ]}
+ contentStyle={{
+ backgroundColor: "white",
+ borderColor: "#e2e8f0",
+ borderRadius: "0.375rem",
+ }}
+ />
+
+
+
+
+
+
+
+ {contributors.slice(0, 10).map(([name, count], index) => (
+
+
+
+
+ {name.split(" ")[0]}
+
+
+
{count}
+
+ ))}
+ {contributors.length > 10 && (
+
+ +{contributors.length - 10} more contributors
+
+ )}
+
+
+
+
+
+
+ );
+}
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/dashboard-header.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/dashboard-header.tsx
new file mode 100644
index 000000000..3fa854491
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/dashboard-header.tsx
@@ -0,0 +1,18 @@
+import { Code2 } from "lucide-react";
+
+export function DashboardHeader() {
+ return (
+
+
+
+
+ AI Code Impact Analysis
+
+
+
+ Analyze AI-generated code contributions in your repository
+
+
+
+ );
+}
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/high-impact-symbols.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/high-impact-symbols.tsx
new file mode 100644
index 000000000..db1fe51aa
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/high-impact-symbols.tsx
@@ -0,0 +1,58 @@
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+import { ScrollArea } from "@/components/ui/scroll-area";
+import type { HighImpactSymbol } from "@/lib/types";
+
+interface HighImpactSymbolsProps {
+ symbols: HighImpactSymbol[];
+}
+
+export function HighImpactSymbols({ symbols }: HighImpactSymbolsProps) {
+ return (
+
+
+ High-Impact AI Symbols
+
+ AI-written code with significant usage
+
+
+
+
+
+ {symbols.length > 0 ? (
+ symbols.map((symbol) => (
+
+
+
{symbol.name}
+
+ Used by {symbol.usage_count} symbols
+
+
+
+ {symbol.filepath}
+
+
+ Last edited by:{" "}
+ {symbol.last_editor}
+
+
+ ))
+ ) : (
+
+ No high-impact AI symbols found
+
+ )}
+
+
+
+
+ );
+}
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/loading-screen.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/loading-screen.tsx
new file mode 100644
index 000000000..089cdf833
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/loading-screen.tsx
@@ -0,0 +1,15 @@
+import { Loader2 } from "lucide-react";
+
+export function LoadingScreen() {
+ return (
+
+
+
+
+ Analyzing Repository
+
+
This may take a few seconds...
+
+
+ );
+}
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/repo-analysis-dashboard.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/repo-analysis-dashboard.tsx
new file mode 100644
index 000000000..4cf6ddb71
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/repo-analysis-dashboard.tsx
@@ -0,0 +1,113 @@
+"use client";
+
+import { ContributionTimeline } from "@/components/contribution-timeline";
+import { ContributorsBreakdown } from "@/components/contributors-breakdown";
+import { DashboardHeader } from "@/components/dashboard-header";
+import { HighImpactSymbols } from "@/components/high-impact-symbols";
+import { LoadingScreen } from "@/components/loading-screen";
+import { SummaryCards } from "@/components/summary-cards";
+import { TopAIFiles } from "@/components/top-ai-files";
+import { Button } from "@/components/ui/button";
+import { Card, CardContent } from "@/components/ui/card";
+import { Input } from "@/components/ui/input";
+import type { AnalysisData } from "@/lib/types";
+import { GitBranch, Loader2 } from "lucide-react";
+import { useState } from "react";
+
+export function RepoAnalysisDashboard() {
+ const [data, setData] = useState(null);
+ const [loading, setLoading] = useState(false);
+ const [repoUrl, setRepoUrl] = useState("");
+
+ const handleSubmit = (e: React.FormEvent) => {
+ e.preventDefault();
+ if (repoUrl.trim()) {
+ setLoading(true);
+ const match = repoUrl.match(/(?:github\.com\/)?([^/\s]+\/[^/\s]+)/);
+ if (match) {
+ const repoFullName = match[1];
+ fetch(
+ `[your-modal-deployment-url]/analyze?repo_full_name=${repoFullName}`,
+ {
+ method: "POST",
+ },
+ )
+ .then((response) => {
+ if (!response.ok) {
+ throw new Error("Network response was not ok");
+ }
+ return response.json();
+ })
+ .then((analysisData: AnalysisData) => {
+ setData(analysisData);
+ setLoading(false);
+ })
+ .catch((error) => {
+ console.error("Error analyzing repository:", error);
+ setLoading(false);
+ });
+ }
+ }
+ };
+
+ return (
+
+ {loading &&
}
+
+
+
+
+
+
+
+
+
+ {data && (
+
+ )}
+
+
+
+ );
+}
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/summary-cards.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/summary-cards.tsx
new file mode 100644
index 000000000..dea866379
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/summary-cards.tsx
@@ -0,0 +1,77 @@
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import type { AnalysisData } from "@/lib/types";
+import { BarChart3, FileCode, GitCommit, Percent } from "lucide-react";
+
+interface SummaryCardsProps {
+ data: AnalysisData;
+}
+
+export function SummaryCards({ data }: SummaryCardsProps) {
+ const { stats, ai_symbol_count, total_symbol_count } = data;
+
+ return (
+
+
+
+ AI Commits
+
+
+
+
+ {stats.ai_commits} / {stats.total_commits}
+
+
+ {stats.ai_percentage.toFixed(1)}% of total commits
+
+
+
+
+
+
+ AI Files
+
+
+
+
+ {stats.ai_file_count} / {stats.total_file_count}
+
+
+ {((stats.ai_file_count / stats.total_file_count) * 100).toFixed(1)}%
+ of files have >50% AI contribution
+
+
+
+
+
+
+ AI Symbols
+
+
+
+
+ {ai_symbol_count} / {total_symbol_count}
+
+
+ {((ai_symbol_count / total_symbol_count) * 100).toFixed(1)}% of code
+ symbols
+
+
+
+
+
+
+ High Impact
+
+
+
+
+ {data.high_impact_symbols.length}
+
+
+ AI-written symbols with high usage
+
+
+
+
+ );
+}
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/theme-provider.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/theme-provider.tsx
new file mode 100644
index 000000000..020003cf9
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/theme-provider.tsx
@@ -0,0 +1,11 @@
+"use client";
+
+import {
+ ThemeProvider as NextThemesProvider,
+ type ThemeProviderProps,
+} from "next-themes";
+import * as React from "react";
+
+export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
+ return {children};
+}
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/top-ai-files.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/top-ai-files.tsx
new file mode 100644
index 000000000..67a5472a8
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/top-ai-files.tsx
@@ -0,0 +1,48 @@
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+import { Progress } from "@/components/ui/progress";
+import { ScrollArea } from "@/components/ui/scroll-area";
+
+interface TopAIFilesProps {
+ files: [string, number][];
+}
+
+export function TopAIFiles({ files }: TopAIFilesProps) {
+ return (
+
+
+ Top AI-Contributed Files
+
+ Files with highest AI contribution percentage
+
+
+
+
+
+ {files.map(([filepath, percentage]) => (
+
+
+
+ {filepath.split("/").pop()}
+
+
+ {percentage.toFixed(1)}%
+
+
+
+
+ {filepath}
+
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/button.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/button.tsx
new file mode 100644
index 000000000..91b784a28
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/button.tsx
@@ -0,0 +1,56 @@
+import { Slot } from "@radix-ui/react-slot";
+import { type VariantProps, cva } from "class-variance-authority";
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+ outline:
+ "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-10 px-4 py-2",
+ sm: "h-9 rounded-md px-3",
+ lg: "h-11 rounded-md px-8",
+ icon: "h-10 w-10",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ },
+);
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean;
+}
+
+const Button = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button";
+ return (
+
+ );
+ },
+);
+Button.displayName = "Button";
+
+export { Button, buttonVariants };
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/card.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/card.tsx
new file mode 100644
index 000000000..bb368bd00
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/card.tsx
@@ -0,0 +1,86 @@
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const Card = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+Card.displayName = "Card";
+
+const CardHeader = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardHeader.displayName = "CardHeader";
+
+const CardTitle = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardTitle.displayName = "CardTitle";
+
+const CardDescription = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardDescription.displayName = "CardDescription";
+
+const CardContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardContent.displayName = "CardContent";
+
+const CardFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardFooter.displayName = "CardFooter";
+
+export {
+ Card,
+ CardHeader,
+ CardFooter,
+ CardTitle,
+ CardDescription,
+ CardContent,
+};
diff --git a/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/chart.tsx b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/chart.tsx
new file mode 100644
index 000000000..aa3d5f99a
--- /dev/null
+++ b/codegen-examples/examples/ai_impact_analysis/dashboard/frontend/components/ui/chart.tsx
@@ -0,0 +1,365 @@
+"use client";
+
+import * as React from "react";
+import * as RechartsPrimitive from "recharts";
+
+import { cn } from "@/lib/utils";
+
+// Format: { THEME_NAME: CSS_SELECTOR }
+const THEMES = { light: "", dark: ".dark" } as const;
+
+export type ChartConfig = {
+ [k in string]: {
+ label?: React.ReactNode;
+ icon?: React.ComponentType;
+ } & (
+ | { color?: string; theme?: never }
+ | { color?: never; theme: Record }
+ );
+};
+
+type ChartContextProps = {
+ config: ChartConfig;
+};
+
+const ChartContext = React.createContext(null);
+
+function useChart() {
+ const context = React.useContext(ChartContext);
+
+ if (!context) {
+ throw new Error("useChart must be used within a ");
+ }
+
+ return context;
+}
+
+const ChartContainer = React.forwardRef<
+ HTMLDivElement,
+ React.ComponentProps<"div"> & {
+ config: ChartConfig;
+ children: React.ComponentProps<
+ typeof RechartsPrimitive.ResponsiveContainer
+ >["children"];
+ }
+>(({ id, className, children, config, ...props }, ref) => {
+ const uniqueId = React.useId();
+ const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
+
+ return (
+
+
+
+
+ {children}
+
+
+
+ );
+});
+ChartContainer.displayName = "Chart";
+
+const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
+ const colorConfig = Object.entries(config).filter(
+ ([_, config]) => config.theme || config.color,
+ );
+
+ if (!colorConfig.length) {
+ return null;
+ }
+
+ return (
+