"""Real-World Developer AI Adoption and Code Quality Chart""" import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent)) import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt from src.data.agent_adoption import ( developer_ai_adoption, code_acceptance_rates, code_quality_in_production, failure_modes ) from src.utils.styling import ( get_theme, EXPORT_DPI, AGENT_GROWTH, BUBBLE_ZONE, WARNING_ZONE, NORMAL_ZONE, GRAY_DARK, GRAY_LIGHT ) def plot_developer_reality() -> str: plt.rcParams.update(get_theme()) fig = plt.figure(figsize=(16, 12)) fig.set_facecolor("#ffffff") # --- Layout: 3 panels via GridSpec --- from matplotlib.gridspec import GridSpec gs = GridSpec(2, 2, figure=fig, height_ratios=[1, 1.5], hspace=0.45, wspace=0.30, left=0.07, right=0.93, top=0.88, bottom=0.06) ax1 = fig.add_subplot(gs[0, 0]) # Panel A — Adoption ax2 = fig.add_subplot(gs[0, 1]) # Panel B — Acceptance ax3 = fig.add_subplot(gs[1, :]) # Panel C — Code Quality (full width) # ========================================================= # Panel A: AI Coding Tool Adoption Rates # ========================================================= adoption_labels = [ "84% use or plan AI tools\n(Stack Overflow 2025)", "51% professional devs\nuse AI daily (Stack Overflow)", "85% regular AI usage\n(JetBrains 2025)", "62% rely on coding\nassistant (JetBrains)", "91% AI adoption in active\nrepos (DX DevCycle)", ] adoption_values = [84, 51, 85, 62, 91] adoption_colors = [ AGENT_GROWTH, AGENT_GROWTH, "#5b2d8e", "#3c1d6e", AGENT_GROWTH, ] bars_a = ax1.barh( range(len(adoption_labels)), adoption_values, color=adoption_colors, edgecolor="white", height=0.55, ) ax1.set_yticks(range(len(adoption_labels))) ax1.set_yticklabels(adoption_labels, fontsize=9.5) ax1.set_xlim(0, 105) ax1.set_xticks(range(0, 110, 10)) ax1.tick_params(axis="x", labelsize=8) ax1.invert_yaxis() for bar, val in zip(bars_a, adoption_values): ax1.text(val + 1.5, bar.get_y() + bar.get_height() / 2, f"{val}%", va="center", fontsize=10, fontweight="bold", color=GRAY_DARK) ax1.set_title("AI Coding Tool Adoption Rates", fontsize=14, fontweight="bold", pad=10) ax1.grid(True, alpha=0.3, axis="x") ax1.spines["top"].set_visible(False) ax1.spines["right"].set_visible(False) # ========================================================= # Panel B: Code Acceptance Rates # ========================================================= acceptance_labels = [ "~30% acceptance rate\n(GitHub Copilot)", "88% code retention rate\n(GitHub Copilot)", "22% of merged code is\nAI-authored (DX DevCycle)", "71% do NOT merge AI code\nwithout manual review", ] acceptance_values = [30, 88, 22, 71] acceptance_colors = [ WARNING_ZONE, # 30% acceptance — warning NORMAL_ZONE, # 88% retention — good AGENT_GROWTH, # 22% AI-authored — neutral GRAY_DARK, # 71% manual review — caution signal ] bars_b = ax2.barh( range(len(acceptance_labels)), acceptance_values, color=acceptance_colors, edgecolor="white", height=0.55, ) ax2.set_yticks(range(len(acceptance_labels))) ax2.set_yticklabels(acceptance_labels, fontsize=9.5) ax2.set_xlim(0, 105) ax2.set_xticks(range(0, 110, 10)) ax2.tick_params(axis="x", labelsize=8) ax2.invert_yaxis() for bar, val in zip(bars_b, acceptance_values): ax2.text(val + 1.5, bar.get_y() + bar.get_height() / 2, f"{val}%", va="center", fontsize=10, fontweight="bold", color=GRAY_DARK) ax2.set_title("Code Acceptance Rates", fontsize=14, fontweight="bold", pad=10) ax2.grid(True, alpha=0.3, axis="x") ax2.spines["top"].set_visible(False) ax2.spines["right"].set_visible(False) # Annotation: adoption vs acceptance gap ax2.annotate( "HUGE GAP:\nHigh adoption,\nlow acceptance", xy=(30, 1.8), xytext=(58, 0.8), arrowprops=dict(arrowstyle="->", color=BUBBLE_ZONE, lw=2), fontsize=10, fontweight="bold", color=BUBBLE_ZONE, ha="center", bbox=dict(boxstyle="round,pad=0.3", facecolor=GRAY_LIGHT, edgecolor=BUBBLE_ZONE, linewidth=1.2), ) # ========================================================= # Panel C: Code Quality in Production # ========================================================= quality_labels = [ "29.1% Python AI code has\nsecurity weaknesses", "24.2% JavaScript AI code has\nsecurity weaknesses", "48% AI-generated code has\npotential vulnerabilities", "1.7x more issues in\nAI-coauthored PRs (CodeRabbit)", "7.2% drop in delivery\nstability (Google DORA)", ] quality_values = [29.1, 24.2, 48, 1.7, 7.2] # All bars use BUBBLE_ZONE to signal danger quality_colors = [BUBBLE_ZONE] * len(quality_labels) bars_c = ax3.barh( range(len(quality_labels)), quality_values, color=quality_colors, edgecolor="white", height=0.45, ) ax3.set_yticks(range(len(quality_labels))) ax3.set_yticklabels(quality_labels, fontsize=10) # X-axis scaled to the max value ax3.set_xlim(0, max(quality_values) * 1.25) ax3.set_xticks([0, 10, 20, 30, 40, 50]) ax3.tick_params(axis="x", labelsize=9) ax3.invert_yaxis() for bar, val in zip(bars_c, quality_values): label = f"{val}x" if val < 5 and val != int(val) else f"{val}" ax3.text(val + 1, bar.get_y() + bar.get_height() / 2, label, va="center", fontsize=11, fontweight="bold", color="#c0392b") ax3.set_title("Code Quality Concerns in Production", fontsize=14, fontweight="bold", pad=10, color=BUBBLE_ZONE) ax3.grid(True, alpha=0.3, axis="x") ax3.spines["top"].set_visible(False) ax3.spines["right"].set_visible(False) # ========================================================= # Figure-level title and disclaimer # ========================================================= fig.suptitle( "Real-World Developer AI: Adoption vs. Code Quality", fontsize=18, fontweight="bold", y=0.96, color=GRAY_DARK, ) fig.text( 0.5, 0.925, "Benchmarks measure lab tasks, not production shipping", ha="center", fontsize=13, style="italic", color=GRAY_DARK, alpha=0.8, ) # Prominent disclaimer banner fig.text( 0.5, 0.015, "⚠ Benchmarks measure controlled lab tasks, NOT production shipping", ha="center", fontsize=12, fontweight="bold", color=BUBBLE_ZONE, bbox=dict( boxstyle="round,pad=0.5", facecolor=GRAY_LIGHT, edgecolor=BUBBLE_ZONE, linewidth=2, ), ) # ========================================================= # Save # ========================================================= out_path = "output/charts/12_developer_ai_reality.png" fig.savefig( out_path, dpi=EXPORT_DPI, facecolor=fig.get_facecolor(), edgecolor="none", ) plt.close(fig) return out_path def main(): path = plot_developer_reality() print(f"Chart saved: {path}") if __name__ == "__main__": main()