From e44721a422ce78a98ff1fbc80dc994f22d94f810 Mon Sep 17 00:00:00 2001 From: Orchestrator Date: Thu, 4 Jun 2026 17:55:08 -0500 Subject: [PATCH] feat(chart): real-world developer AI adoption and code quality --- src/charts/developer_reality.py | 222 ++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 src/charts/developer_reality.py diff --git a/src/charts/developer_reality.py b/src/charts/developer_reality.py new file mode 100644 index 0000000..0e2c663 --- /dev/null +++ b/src/charts/developer_reality.py @@ -0,0 +1,222 @@ +"""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()