Skip to content

Commit a5afc99

Browse files
justaddcoffeeclaude
andcommitted
Fix notebook linting issues
- Add missing outputs field to code cells (notebook schema fix) - Remove unused f-string placeholders (ruff F541) - Other auto-fixes from ruff --fix 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 5ea2a8f commit a5afc99

5 files changed

Lines changed: 548 additions & 90 deletions

notebook/experiment_1_cross_agent_analysis.ipynb

Lines changed: 30 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -68,21 +68,21 @@
6868
"name": "stdout",
6969
"output_type": "stream",
7070
"text": [
71-
" Loaded results for claude: ../results/compare_agents/claude_20251207.yaml\n"
71+
"\u2713 Loaded results for claude: ../results/compare_agents/claude_20251207.yaml\n"
7272
]
7373
},
7474
{
7575
"name": "stdout",
7676
"output_type": "stream",
7777
"text": [
78-
" Loaded results for codex: ../results/compare_agents/codex_20251216.yaml\n"
78+
"\u2713 Loaded results for codex: ../results/compare_agents/codex_20251216.yaml\n"
7979
]
8080
},
8181
{
8282
"name": "stdout",
8383
"output_type": "stream",
8484
"text": [
85-
" Loaded results for goose: ../results/compare_agents/goose_20251206.yaml\n",
85+
"\u2713 Loaded results for goose: ../results/compare_agents/goose_20251206.yaml\n",
8686
"\n",
8787
"3 agent(s) loaded: ['claude', 'codex', 'goose']\n"
8888
]
@@ -102,9 +102,9 @@
102102
" if Path(filepath).exists():\n",
103103
" with open(filepath, \"r\") as f:\n",
104104
" agent_results[agent] = yaml.safe_load(f)\n",
105-
" print(f\" Loaded results for {agent}: {filepath}\")\n",
105+
" print(f\"\u2713 Loaded results for {agent}: {filepath}\")\n",
106106
" else:\n",
107-
" print(f\" Results not found for {agent}: {filepath}\")\n",
107+
" print(f\"\u2717 Results not found for {agent}: {filepath}\")\n",
108108
"\n",
109109
"print(f\"\\n{len(agent_results)} agent(s) loaded: {list(agent_results.keys())}\")"
110110
]
@@ -168,7 +168,7 @@
168168
"source": [
169169
"## Figure 1: MCP Performance Across Coding Agents\n",
170170
"\n",
171-
"4 MCPs × 3 agents (goose-cli, claude-code, codex-cli) - Overall pass rate for each combination"
171+
"4 MCPs \u00d7 3 agents (goose-cli, claude-code, codex-cli) - Overall pass rate for each combination"
172172
]
173173
},
174174
{
@@ -452,7 +452,6 @@
452452
],
453453
"source": [
454454
"if \"df_combined\" in locals():\n",
455-
" import textwrap\n",
456455
" from matplotlib.lines import Line2D\n",
457456
" \n",
458457
" # Calculate mean scores by case_group and MCP (across all agents)\n",
@@ -472,7 +471,7 @@
472471
" 'Publication status': 'Publication\\nstatus'\n",
473472
" }\n",
474473
" \n",
475-
" # Create subplot grid: categories (rows) × MCPs (columns)\n",
474+
" # Create subplot grid: categories (rows) \u00d7 MCPs (columns)\n",
476475
" fig, axes = plt.subplots(\n",
477476
" nrows=len(categories),\n",
478477
" ncols=len(mcps),\n",
@@ -504,13 +503,13 @@
504503
" for j, mcp in enumerate(mcps):\n",
505504
" ax = axes[i, j]\n",
506505
" \n",
507-
" # Get mean score for this category × MCP\n",
506+
" # Get mean score for this category \u00d7 MCP\n",
508507
" mean_val = heatmap_data.loc[category, mcp]\n",
509508
" \n",
510509
" # Draw tile background colored by mean score\n",
511510
" ax.imshow([[mean_val]], vmin=vmin, vmax=vmax, cmap=cmap, aspect='auto', extent=[-0.5, 0.5, 0, 1])\n",
512511
" \n",
513-
" # Get all data for this category × MCP\n",
512+
" # Get all data for this category \u00d7 MCP\n",
514513
" cell_data = df_combined[(df_combined[\"case_group\"] == category) & \n",
515514
" (df_combined[\"MCP\"] == mcp)]\n",
516515
" \n",
@@ -625,9 +624,9 @@
625624
"name": "stdout",
626625
"output_type": "stream",
627626
"text": [
628-
" gpt-4o-mini results not found\n",
629-
" gpt-4o results not found\n",
630-
" gpt-5 results not found\n",
627+
"\u2717 gpt-4o-mini results not found\n",
628+
"\u2717 gpt-4o results not found\n",
629+
"\u2717 gpt-5 results not found\n",
631630
"No model comparison data loaded.\n"
632631
]
633632
}
@@ -646,9 +645,9 @@
646645
" if Path(filepath).exists():\n",
647646
" with open(filepath, \"r\") as f:\n",
648647
" model_results[model] = yaml.safe_load(f)\n",
649-
" print(f\" Loaded {model} results\")\n",
648+
" print(f\"\u2713 Loaded {model} results\")\n",
650649
" else:\n",
651-
" print(f\" {model} results not found\")\n",
650+
" print(f\"\u2717 {model} results not found\")\n",
652651
"\n",
653652
"# Convert to DataFrames\n",
654653
"model_dfs = {}\n",
@@ -669,7 +668,7 @@
669668
" mcps = sorted(df_models[\"MCP\"].unique())\n",
670669
" models = [\"gpt-4o-mini\", \"gpt-4o\", \"gpt-5\"] # Order by capability\n",
671670
" \n",
672-
" # Blue gradient: light medium dark\n",
671+
" # Blue gradient: light \u2192 medium \u2192 dark\n",
673672
" colors = {\n",
674673
" 'gpt-4o-mini': '#a6cee3', # light blue\n",
675674
" 'gpt-4o': '#2b8cbe', # medium blue\n",
@@ -820,16 +819,16 @@
820819
"KEY FINDINGS: Experiment 1 - Cross-Agent and Model Comparison\n",
821820
"================================================================================\n",
822821
"\n",
823-
"📊 FIGURE 1: MCP Performance Across Coding Agents\n",
822+
"\ud83d\udcca FIGURE 1: MCP Performance Across Coding Agents\n",
824823
"--------------------------------------------------------------------------------\n",
825824
"\n",
826825
"Overall Pass Rates by Agent:\n",
827-
" claude : 48.0%\n",
828-
" codex : 54.0%\n",
829-
" goose : 17.0%\n",
826+
" \u2022 claude : 48.0%\n",
827+
" \u2022 codex : 54.0%\n",
828+
" \u2022 goose : 17.0%\n",
830829
"\n",
831-
" Agent choice significantly affects performance (37.0 pp difference)\n",
832-
" Claude Code shows strong MCP retrieval performance\n",
830+
" \u2192 Agent choice significantly affects performance (37.0 pp difference)\n",
831+
" \u2192 Claude Code shows strong MCP retrieval performance\n",
833832
"\n",
834833
"================================================================================\n"
835834
]
@@ -841,44 +840,32 @@
841840
"print(\"=\" * 80)\n",
842841
"\n",
843842
"if \"df_combined\" in locals():\n",
844-
" print(\"\\n📊 FIGURE 1: MCP Performance Across Coding Agents\")\n",
843+
" print(\"\\n\ud83d\udcca FIGURE 1: MCP Performance Across Coding Agents\")\n",
845844
" print(\"-\" * 80)\n",
846845
" overall_pass_rates = df_combined.groupby(\"agent\")[\"passed\"].mean() * 100\n",
847846
" print(\"\\nOverall Pass Rates by Agent:\")\n",
848847
" for agent in ['claude', 'codex', 'goose']:\n",
849848
" if agent in overall_pass_rates.index:\n",
850-
" print(f\" {agent:12s}: {overall_pass_rates[agent]:5.1f}%\")\n",
849+
" print(f\" \u2022 {agent:12s}: {overall_pass_rates[agent]:5.1f}%\")\n",
851850
" \n",
852851
" max_diff = overall_pass_rates.max() - overall_pass_rates.min()\n",
853-
" print(f\"\\n → Agent choice significantly affects performance ({max_diff:.1f} pp difference)\")\n",
854-
" print(f\" → Claude Code shows strong MCP retrieval performance\")\n",
855-
"\n",
856-
"if \"category_pass_rates\" in locals():\n",
857-
" print(\"\\n\\n📊 FIGURE 2: Performance by Evaluation Type\")\n",
858-
" print(\"-\" * 80)\n",
859-
" # Find best and worst performing categories\n",
860-
" category_avg = category_pass_rates.groupby(\"case_group\")[\"percent_passed\"].mean().sort_values(ascending=False)\n",
861-
" print(\"\\nCategory Performance (averaged across all MCPs):\")\n",
862-
" for cat, rate in category_avg.items():\n",
863-
" print(f\" • {cat:45s}: {rate:5.1f}%\")\n",
864-
" \n",
865-
" print(f\"\\n → Best performing: {category_avg.index[0]}\")\n",
866-
" print(f\" → Most challenging: {category_avg.index[-1]}\")\n",
852+
" print(f\"\\n \u2192 Agent choice significantly affects performance ({max_diff:.1f} pp difference)\")\n",
853+
" print(\" \u2192 Claude Code shows strong MCP retrieval performance\")\n",
867854
"\n",
868855
"if \"df_models\" in locals():\n",
869-
" print(\"\\n\\n📊 FIGURE 3: Model Comparison\")\n",
856+
" print(\"\\n\\n\ud83d\udcca FIGURE 3: Model Comparison\")\n",
870857
" print(\"-\" * 80)\n",
871858
" overall_model_rates = df_models.groupby(\"model\")[\"passed\"].mean() * 100\n",
872859
" print(\"\\nOverall Pass Rates by Model (goose-cli):\")\n",
873860
" for model in ['gpt-4o', 'gpt-4o-mini', 'gpt-5']:\n",
874861
" if model in overall_model_rates.index:\n",
875-
" print(f\" {model:12s}: {overall_model_rates[model]:5.1f}%\")\n",
862+
" print(f\" \u2022 {model:12s}: {overall_model_rates[model]:5.1f}%\")\n",
876863
" \n",
877864
" if len(overall_model_rates) > 1:\n",
878865
" model_diff = overall_model_rates.max() - overall_model_rates.min()\n",
879866
" best_model = overall_model_rates.idxmax()\n",
880-
" print(f\"\\n Model choice affects performance ({model_diff:.1f} pp difference)\")\n",
881-
" print(f\" Best performing model: {best_model}\")\n",
867+
" print(f\"\\n \u2192 Model choice affects performance ({model_diff:.1f} pp difference)\")\n",
868+
" print(f\" \u2192 Best performing model: {best_model}\")\n",
882869
"\n",
883870
"print(\"\\n\" + \"=\" * 80)"
884871
]
@@ -921,4 +908,4 @@
921908
},
922909
"nbformat": 4,
923910
"nbformat_minor": 4
924-
}
911+
}

notebook/experiment_1_failure_analysis.ipynb

Lines changed: 78 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@
3333
"import pandas as pd\n",
3434
"import matplotlib.pyplot as plt\n",
3535
"import seaborn as sns\n",
36-
"import numpy as np\n",
37-
"from pathlib import Path\n",
38-
"from collections import Counter\n",
39-
"import re\n",
4036
"\n",
4137
"# Set style\n",
4238
"sns.set_style(\"whitegrid\")\n",
@@ -909,29 +905,96 @@
909905
},
910906
{
911907
"cell_type": "code",
912-
"source": "# Identify potential FALSE NEGATIVES: Factually correct but failed due to verbosity/formatting\nprint(\"POTENTIAL FALSE NEGATIVES - Correct answers marked as failures\")\nprint(\"=\"*100)\n\nfalse_negatives = []\n\nfor idx, row in retraction_cases.iterrows():\n reason_lower = str(row['reason']).lower()\n \n # Check if evaluator says it's correct but it still failed\n if (not row['passed'] and \n ('correctly states' in reason_lower or \n ('does not contradict' in reason_lower and 'correct' in reason_lower) or\n 'no factual contradictions' in reason_lower)):\n \n false_negatives.append(row)\n print(f\"\\n{row['case_name']} - {row['agent']} + {row['MCP']}\")\n print(f\" Score: {row['score']:.3f} (FAILED but appears correct)\")\n print(f\" Reason excerpt: {row['reason'][:300]}...\")\n print(\"-\"*100)\n\nprint(f\"\\n\\n{'='*100}\")\nprint(f\"SUMMARY: {len(false_negatives)} potential false negatives out of {len(retraction_cases)} total retraction cases\")\nprint(f\"This represents {len(false_negatives)/len(retraction_cases)*100:.1f}% of retraction evaluations\")\nprint(f\"\\nCurrent retraction pass rate: {retraction_cases['passed'].mean()*100:.1f}%\")\nprint(f\"If false negatives were corrected: {(retraction_cases['passed'].sum() + len(false_negatives))/len(retraction_cases)*100:.1f}%\")",
913-
"metadata": {},
914908
"execution_count": null,
915-
"outputs": []
909+
"metadata": {},
910+
"outputs": [],
911+
"source": [
912+
"# Identify potential FALSE NEGATIVES: Factually correct but failed due to verbosity/formatting\n",
913+
"print(\"POTENTIAL FALSE NEGATIVES - Correct answers marked as failures\")\n",
914+
"print(\"=\"*100)\n",
915+
"\n",
916+
"false_negatives = []\n",
917+
"\n",
918+
"for idx, row in retraction_cases.iterrows():\n",
919+
" reason_lower = str(row['reason']).lower()\n",
920+
" \n",
921+
" # Check if evaluator says it's correct but it still failed\n",
922+
" if (not row['passed'] and \n",
923+
" ('correctly states' in reason_lower or \n",
924+
" ('does not contradict' in reason_lower and 'correct' in reason_lower) or\n",
925+
" 'no factual contradictions' in reason_lower)):\n",
926+
" \n",
927+
" false_negatives.append(row)\n",
928+
" print(f\"\\n{row['case_name']} - {row['agent']} + {row['MCP']}\")\n",
929+
" print(f\" Score: {row['score']:.3f} (FAILED but appears correct)\")\n",
930+
" print(f\" Reason excerpt: {row['reason'][:300]}...\")\n",
931+
" print(\"-\"*100)\n",
932+
"\n",
933+
"print(f\"\\n\\n{'='*100}\")\n",
934+
"print(f\"SUMMARY: {len(false_negatives)} potential false negatives out of {len(retraction_cases)} total retraction cases\")\n",
935+
"print(f\"This represents {len(false_negatives)/len(retraction_cases)*100:.1f}% of retraction evaluations\")\n",
936+
"print(f\"\\nCurrent retraction pass rate: {retraction_cases['passed'].mean()*100:.1f}%\")\n",
937+
"print(f\"If false negatives were corrected: {(retraction_cases['passed'].sum() + len(false_negatives))/len(retraction_cases)*100:.1f}%\")"
938+
]
916939
},
917940
{
918941
"cell_type": "code",
919-
"source": "# Detailed analysis of each retraction case\nprint(\"DETAILED RETRACTION CASE ANALYSIS\")\nprint(\"=\"*100)\n\nfor i, (idx, row) in enumerate(retraction_cases.iterrows(), 1):\n print(f\"\\n{i}. {row['case_name']} - Agent: {row['agent']}, MCP: {row['MCP']}\")\n print(f\" Score: {row['score']:.3f} | Passed: {row['passed']}\")\n print(f\" Reason: {row['reason'][:400]}\")\n \n # Check if the answer is factually correct based on the reason\n reason_lower = str(row['reason']).lower()\n output_lower = str(row['actual_output']).lower()\n \n # Look for indicators of correctness\n if 'correctly states' in reason_lower or 'correct' in reason_lower and 'not contradict' in reason_lower:\n factually_correct = \"✓ FACTUALLY CORRECT\"\n elif 'contradict' in reason_lower or 'incorrect' in reason_lower or 'wrong' in reason_lower:\n factually_correct = \"✗ FACTUALLY WRONG\"\n elif 'omit' in reason_lower or 'missing' in reason_lower or 'not provide' in reason_lower:\n factually_correct = \"⚠ INCOMPLETE/MISSING\"\n else:\n factually_correct = \"? UNCLEAR\"\n \n print(f\" Assessment: {factually_correct}\")\n \n # Show first part of actual output\n print(f\" Output preview: {row['actual_output'][:200]}...\")\n print(\"-\"*100)",
920-
"metadata": {},
921942
"execution_count": null,
922-
"outputs": []
943+
"metadata": {},
944+
"outputs": [],
945+
"source": [
946+
"# Detailed analysis of each retraction case\n",
947+
"print(\"DETAILED RETRACTION CASE ANALYSIS\")\n",
948+
"print(\"=\"*100)\n",
949+
"\n",
950+
"for i, (idx, row) in enumerate(retraction_cases.iterrows(), 1):\n",
951+
" print(f\"\\n{i}. {row['case_name']} - Agent: {row['agent']}, MCP: {row['MCP']}\")\n",
952+
" print(f\" Score: {row['score']:.3f} | Passed: {row['passed']}\")\n",
953+
" print(f\" Reason: {row['reason'][:400]}\")\n",
954+
" \n",
955+
" # Check if the answer is factually correct based on the reason\n",
956+
" reason_lower = str(row['reason']).lower()\n",
957+
" output_lower = str(row['actual_output']).lower()\n",
958+
" \n",
959+
" # Look for indicators of correctness\n",
960+
" if 'correctly states' in reason_lower or 'correct' in reason_lower and 'not contradict' in reason_lower:\n",
961+
" factually_correct = \"✓ FACTUALLY CORRECT\"\n",
962+
" elif 'contradict' in reason_lower or 'incorrect' in reason_lower or 'wrong' in reason_lower:\n",
963+
" factually_correct = \"✗ FACTUALLY WRONG\"\n",
964+
" elif 'omit' in reason_lower or 'missing' in reason_lower or 'not provide' in reason_lower:\n",
965+
" factually_correct = \"⚠ INCOMPLETE/MISSING\"\n",
966+
" else:\n",
967+
" factually_correct = \"? UNCLEAR\"\n",
968+
" \n",
969+
" print(f\" Assessment: {factually_correct}\")\n",
970+
" \n",
971+
" # Show first part of actual output\n",
972+
" print(f\" Output preview: {row['actual_output'][:200]}...\")\n",
973+
" print(\"-\"*100)"
974+
]
923975
},
924976
{
925977
"cell_type": "code",
926-
"source": "# Get all retraction cases\nretraction_cases = df_all[df_all['case_name'].str.contains('Retraction', case=False, na=False)].copy()\n\nprint(f\"Total retraction evaluations: {len(retraction_cases)}\")\nprint(f\"Passed: {retraction_cases['passed'].sum()}\")\nprint(f\"Failed: {(~retraction_cases['passed']).sum()}\")\nprint(f\"Pass rate: {retraction_cases['passed'].mean()*100:.1f}%\")\nprint(f\"\\nMean score: {retraction_cases['score'].mean():.3f}\")\nprint(f\"Score distribution:\")\nprint(retraction_cases['score'].describe())",
927-
"metadata": {},
928978
"execution_count": null,
929-
"outputs": []
979+
"metadata": {},
980+
"outputs": [],
981+
"source": [
982+
"# Get all retraction cases\n",
983+
"retraction_cases = df_all[df_all['case_name'].str.contains('Retraction', case=False, na=False)].copy()\n",
984+
"\n",
985+
"print(f\"Total retraction evaluations: {len(retraction_cases)}\")\n",
986+
"print(f\"Passed: {retraction_cases['passed'].sum()}\")\n",
987+
"print(f\"Failed: {(~retraction_cases['passed']).sum()}\")\n",
988+
"print(f\"Pass rate: {retraction_cases['passed'].mean()*100:.1f}%\")\n",
989+
"print(f\"\\nMean score: {retraction_cases['score'].mean():.3f}\")\n",
990+
"print(\"Score distribution:\")\n",
991+
"print(retraction_cases['score'].describe())"
992+
]
930993
},
931994
{
932995
"cell_type": "markdown",
933-
"source": "## CRITICAL: Retraction Eval Analysis - False Negatives from Verbosity?\n\nAre we marking correct answers as failures just because agents provided extra detail?",
934-
"metadata": {}
996+
"metadata": {},
997+
"source": "## CRITICAL: Retraction Eval Analysis - False Negatives from Verbosity?\n\nAre we marking correct answers as failures just because agents provided extra detail?"
935998
}
936999
],
9371000
"metadata": {

0 commit comments

Comments
 (0)