evalrx 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. evalrx/__init__.py +139 -0
  2. evalrx/agent_assets/__init__.py +2 -0
  3. evalrx/agent_assets/skills/README.md +28 -0
  4. evalrx/agent_assets/skills/eval-chart-style/SKILL.md +172 -0
  5. evalrx/agent_assets/skills/evalrx-report-ui/SKILL.md +116 -0
  6. evalrx/agent_assets/skills/nature-figure/LICENSE +201 -0
  7. evalrx/agent_assets/skills/nature-figure/README.md +412 -0
  8. evalrx/agent_assets/skills/nature-figure/SKILL.md +60 -0
  9. evalrx/agent_assets/skills/nature-figure/manifest.yaml +59 -0
  10. evalrx/agent_assets/skills/nature-figure/references/api.md +436 -0
  11. evalrx/agent_assets/skills/nature-figure/references/backend-selection.md +100 -0
  12. evalrx/agent_assets/skills/nature-figure/references/chart-types.md +281 -0
  13. evalrx/agent_assets/skills/nature-figure/references/common-patterns.md +350 -0
  14. evalrx/agent_assets/skills/nature-figure/references/demos.md +65 -0
  15. evalrx/agent_assets/skills/nature-figure/references/design-theory.md +439 -0
  16. evalrx/agent_assets/skills/nature-figure/references/figure-contract.md +93 -0
  17. evalrx/agent_assets/skills/nature-figure/references/figure-legend-conventions.md +71 -0
  18. evalrx/agent_assets/skills/nature-figure/references/nature-2026-observations.md +112 -0
  19. evalrx/agent_assets/skills/nature-figure/references/qa-contract.md +119 -0
  20. evalrx/agent_assets/skills/nature-figure/references/r-template-index.md +66 -0
  21. evalrx/agent_assets/skills/nature-figure/references/r-workflow.md +161 -0
  22. evalrx/agent_assets/skills/nature-figure/references/tutorials.md +251 -0
  23. evalrx/agent_assets/skills/nature-figure/static/core/contract.md +29 -0
  24. evalrx/agent_assets/skills/nature-figure/static/core/stance.md +37 -0
  25. evalrx/agent_assets/skills/nature-figure/static/fragments/backend/python.md +37 -0
  26. evalrx/agent_assets/skills/nature-figure/static/fragments/backend/r.md +44 -0
  27. evalrx/agent_assets/skills/outcome-driver-analysis/SKILL.md +213 -0
  28. evalrx/agent_assets/skills/outcome-driver-analysis/assets/analysis_report_template.md +53 -0
  29. evalrx/agent_assets/skills/outcome-driver-analysis/references/model_selection.md +72 -0
  30. evalrx/agent_assets/skills/outcome-driver-analysis/scripts/explanatory_var_eda.R +130 -0
  31. evalrx/agent_assets/skills/outcome-driver-analysis/scripts/explanatory_var_eda.py +150 -0
  32. evalrx/agent_assets/skills/outcome-driver-analysis/scripts/fit_outcome_model.R +181 -0
  33. evalrx/agent_assets/skills/outcome-driver-analysis/scripts/fit_outcome_model.py +186 -0
  34. evalrx/agent_assets/skills/outcome-driver-analysis/scripts/univariate_eda.R +149 -0
  35. evalrx/agent_assets/skills/outcome-driver-analysis/scripts/univariate_eda.py +177 -0
  36. evalrx/agent_assets/skills.py +27 -0
  37. evalrx/agent_runtime/__init__.py +78 -0
  38. evalrx/agent_runtime/_docker_runner.py +89 -0
  39. evalrx/agent_runtime/cli_runtime.py +103 -0
  40. evalrx/agent_runtime/cli_transcript.py +138 -0
  41. evalrx/agent_runtime/cli_types.py +68 -0
  42. evalrx/agent_runtime/codegen/__init__.py +5 -0
  43. evalrx/agent_runtime/codegen/runner.py +94 -0
  44. evalrx/agent_runtime/experiment_harness.py +117 -0
  45. evalrx/agent_runtime/factory.py +102 -0
  46. evalrx/agent_runtime/json_shape.py +44 -0
  47. evalrx/agent_runtime/judges/__init__.py +28 -0
  48. evalrx/agent_runtime/judges/agy.py +179 -0
  49. evalrx/agent_runtime/judges/autodetect.py +135 -0
  50. evalrx/agent_runtime/judges/claude.py +159 -0
  51. evalrx/agent_runtime/judges/codex.py +120 -0
  52. evalrx/agent_runtime/providers/__init__.py +21 -0
  53. evalrx/agent_runtime/providers/antigravity.py +31 -0
  54. evalrx/agent_runtime/providers/base.py +145 -0
  55. evalrx/agent_runtime/providers/claude_code.py +49 -0
  56. evalrx/agent_runtime/providers/codex.py +37 -0
  57. evalrx/agent_runtime/providers/gemini_cli.py +26 -0
  58. evalrx/agent_runtime/providers/kimi_cli.py +27 -0
  59. evalrx/agent_runtime/providers/opencode.py +27 -0
  60. evalrx/agent_runtime/providers/registry.py +58 -0
  61. evalrx/agent_runtime/sandbox.py +517 -0
  62. evalrx/agent_runtime/skill_audit.py +143 -0
  63. evalrx/agent_runtime/skills/__init__.py +19 -0
  64. evalrx/agent_runtime/skills/installer.py +68 -0
  65. evalrx/agent_runtime/skills/prompt_policy.py +86 -0
  66. evalrx/agent_runtime/skills/resolver.py +19 -0
  67. evalrx/analysis/__init__.py +132 -0
  68. evalrx/analysis/adjudicate.py +154 -0
  69. evalrx/analysis/analysis_module.py +361 -0
  70. evalrx/analysis/api.py +171 -0
  71. evalrx/analysis/case_studio.py +651 -0
  72. evalrx/analysis/cli.py +114 -0
  73. evalrx/analysis/dashboard.py +350 -0
  74. evalrx/analysis/eval_case_matrix.py +118 -0
  75. evalrx/analysis/eval_viz_theme.py +833 -0
  76. evalrx/analysis/explore_run.py +333 -0
  77. evalrx/analysis/explorer.py +1276 -0
  78. evalrx/analysis/failure_modes.py +607 -0
  79. evalrx/analysis/fused_pipeline.py +489 -0
  80. evalrx/analysis/holdout.py +300 -0
  81. evalrx/analysis/hypothesis_agent.py +230 -0
  82. evalrx/analysis/narration.py +177 -0
  83. evalrx/analysis/operationalize.py +442 -0
  84. evalrx/analysis/plain_language.py +42 -0
  85. evalrx/analysis/planner.py +283 -0
  86. evalrx/analysis/probe_search.py +203 -0
  87. evalrx/analysis/profile.py +268 -0
  88. evalrx/analysis/prompts/__init__.py +0 -0
  89. evalrx/analysis/prompts/explorer.py +417 -0
  90. evalrx/analysis/prompts/failure_modes.py +33 -0
  91. evalrx/analysis/prompts/holdout.py +27 -0
  92. evalrx/analysis/prompts/hypothesis_agent.py +78 -0
  93. evalrx/analysis/prompts/run_codebase.py +47 -0
  94. evalrx/analysis/prompts/stats_agent.py +72 -0
  95. evalrx/analysis/prompts/stats_tool_generator.py +43 -0
  96. evalrx/analysis/result_marker.py +47 -0
  97. evalrx/analysis/run_codebase.py +242 -0
  98. evalrx/analysis/run_view.py +205 -0
  99. evalrx/analysis/stage_views.py +93 -0
  100. evalrx/analysis/stats_agent.py +944 -0
  101. evalrx/analysis/stats_tool_agent.py +261 -0
  102. evalrx/analysis/stats_tool_generator.py +415 -0
  103. evalrx/analysis/stats_tools.py +1153 -0
  104. evalrx/analysis/trajectory_records.py +193 -0
  105. evalrx/analysis/workbench.py +431 -0
  106. evalrx/analyzers/__init__.py +42 -0
  107. evalrx/analyzers/agent/__init__.py +25 -0
  108. evalrx/analyzers/agent/counterfactual.py +84 -0
  109. evalrx/analyzers/agent/first_error_judge.py +96 -0
  110. evalrx/analyzers/agent/ignored_obs.py +81 -0
  111. evalrx/analyzers/agent/loop_detect.py +79 -0
  112. evalrx/analyzers/agent/reliability.py +165 -0
  113. evalrx/analyzers/agent/tool_shap.py +225 -0
  114. evalrx/analyzers/agent/trajectory_rubric.py +168 -0
  115. evalrx/analyzers/attention/__init__.py +19 -0
  116. evalrx/analyzers/attention/relative_attn.py +610 -0
  117. evalrx/analyzers/attention/rollout.py +73 -0
  118. evalrx/analyzers/attention/sink.py +56 -0
  119. evalrx/analyzers/attention/summary.py +190 -0
  120. evalrx/analyzers/attribution/__init__.py +6 -0
  121. evalrx/analyzers/attribution/generic_attn.py +31 -0
  122. evalrx/analyzers/attribution/gradcam.py +30 -0
  123. evalrx/analyzers/base.py +12 -0
  124. evalrx/analyzers/geometry/__init__.py +6 -0
  125. evalrx/analyzers/geometry/cka.py +70 -0
  126. evalrx/analyzers/geometry/linear_probe.py +157 -0
  127. evalrx/analyzers/hallucination/__init__.py +9 -0
  128. evalrx/analyzers/hallucination/chair.py +78 -0
  129. evalrx/analyzers/hallucination/opera.py +29 -0
  130. evalrx/analyzers/hallucination/pope.py +119 -0
  131. evalrx/analyzers/hallucination/selfcheck.py +155 -0
  132. evalrx/analyzers/hallucination/vcd.py +29 -0
  133. evalrx/analyzers/lens/__init__.py +7 -0
  134. evalrx/analyzers/lens/layer_contrast.py +133 -0
  135. evalrx/analyzers/lens/logit_lens.py +138 -0
  136. evalrx/analyzers/lens/tuned_lens.py +30 -0
  137. evalrx/analyzers/patching/__init__.py +5 -0
  138. evalrx/analyzers/patching/causal_trace.py +30 -0
  139. evalrx/analyzers/perturbation/__init__.py +23 -0
  140. evalrx/analyzers/perturbation/_shapley.py +54 -0
  141. evalrx/analyzers/perturbation/context_shap.py +174 -0
  142. evalrx/analyzers/perturbation/cot_faithfulness.py +239 -0
  143. evalrx/analyzers/perturbation/format_sensitivity.py +237 -0
  144. evalrx/analyzers/perturbation/mm_shap.py +146 -0
  145. evalrx/analyzers/perturbation/modality_ablation.py +196 -0
  146. evalrx/analyzers/perturbation/perturbation_battery.py +274 -0
  147. evalrx/analyzers/perturbation/prompt_contrast.py +265 -0
  148. evalrx/analyzers/perturbation/rise.py +94 -0
  149. evalrx/analyzers/perturbation/vl_shap.py +102 -0
  150. evalrx/analyzers/reasoning/__init__.py +33 -0
  151. evalrx/analyzers/reasoning/_text.py +328 -0
  152. evalrx/analyzers/reasoning/answer_extraction_audit.py +327 -0
  153. evalrx/analyzers/reasoning/arith_audit.py +226 -0
  154. evalrx/analyzers/reasoning/contamination.py +214 -0
  155. evalrx/analyzers/reasoning/knowledge_split.py +253 -0
  156. evalrx/analyzers/reasoning/self_repair.py +246 -0
  157. evalrx/analyzers/reasoning/step_rollout_value.py +216 -0
  158. evalrx/analyzers/reasoning/termination_audit.py +258 -0
  159. evalrx/analyzers/uncertainty/__init__.py +18 -0
  160. evalrx/analyzers/uncertainty/calibration.py +174 -0
  161. evalrx/analyzers/uncertainty/coverage_gap.py +199 -0
  162. evalrx/analyzers/uncertainty/entropy.py +90 -0
  163. evalrx/analyzers/uncertainty/logprob_entropy.py +69 -0
  164. evalrx/analyzers/uncertainty/self_consistency.py +204 -0
  165. evalrx/analyzers/uncertainty/verbalized_conf.py +64 -0
  166. evalrx/cli.py +411 -0
  167. evalrx/config.py +77 -0
  168. evalrx/contract/__init__.py +179 -0
  169. evalrx/contract/common.py +452 -0
  170. evalrx/contract/emit.py +948 -0
  171. evalrx/contract/export.py +237 -0
  172. evalrx/contract/m1.py +325 -0
  173. evalrx/contract/m2.py +317 -0
  174. evalrx/contract/m3.py +165 -0
  175. evalrx/contract/m4.py +130 -0
  176. evalrx/contract/m5.py +292 -0
  177. evalrx/contract/methodology.py +76 -0
  178. evalrx/contract/pre_m1.py +58 -0
  179. evalrx/contract/typescript.py +140 -0
  180. evalrx/core/__init__.py +85 -0
  181. evalrx/core/analyzer.py +174 -0
  182. evalrx/core/capability.py +54 -0
  183. evalrx/core/case.py +443 -0
  184. evalrx/core/experiment.py +106 -0
  185. evalrx/core/model.py +198 -0
  186. evalrx/core/pipeline.py +42 -0
  187. evalrx/core/registry.py +142 -0
  188. evalrx/core/result.py +64 -0
  189. evalrx/core/spec.py +173 -0
  190. evalrx/core/tokentype.py +165 -0
  191. evalrx/core/tool.py +92 -0
  192. evalrx/datasets/__init__.py +41 -0
  193. evalrx/datasets/base.py +68 -0
  194. evalrx/datasets/gui_os.py +52 -0
  195. evalrx/datasets/llm_qa.py +57 -0
  196. evalrx/datasets/pure_qa.py +12 -0
  197. evalrx/datasets/vlm_qa.py +695 -0
  198. evalrx/datasets/web_search_qa.py +52 -0
  199. evalrx/eval_agent/__init__.py +341 -0
  200. evalrx/eval_agent/_tools.py +81 -0
  201. evalrx/eval_agent/ab_runner.py +50 -0
  202. evalrx/eval_agent/agentic/__init__.py +43 -0
  203. evalrx/eval_agent/agentic/actions.py +216 -0
  204. evalrx/eval_agent/agentic/board.py +107 -0
  205. evalrx/eval_agent/agentic/loop.py +190 -0
  206. evalrx/eval_agent/agentic/tools.py +538 -0
  207. evalrx/eval_agent/checkpoint.py +57 -0
  208. evalrx/eval_agent/cli_agent.py +59 -0
  209. evalrx/eval_agent/cli_skills.py +5 -0
  210. evalrx/eval_agent/evolution.py +396 -0
  211. evalrx/eval_agent/git_manager.py +215 -0
  212. evalrx/eval_agent/hypothesis.py +172 -0
  213. evalrx/eval_agent/label_quarantine.py +209 -0
  214. evalrx/eval_agent/legacy.py +530 -0
  215. evalrx/eval_agent/log_schema.py +497 -0
  216. evalrx/eval_agent/loop.py +2159 -0
  217. evalrx/eval_agent/loop_reports.py +116 -0
  218. evalrx/eval_agent/model_instrumentation.py +282 -0
  219. evalrx/eval_agent/narration.py +193 -0
  220. evalrx/eval_agent/nl_runner.py +460 -0
  221. evalrx/eval_agent/orchestrator.py +61 -0
  222. evalrx/eval_agent/preregister.py +93 -0
  223. evalrx/eval_agent/prompts/__init__.py +1 -0
  224. evalrx/eval_agent/prompts/agentic.py +46 -0
  225. evalrx/eval_agent/prompts/case_discovery.py +25 -0
  226. evalrx/eval_agent/prompts/diagnosis.py +125 -0
  227. evalrx/eval_agent/prompts/experiment_writer.py +265 -0
  228. evalrx/eval_agent/prompts/explore_step.py +37 -0
  229. evalrx/eval_agent/prompts/fix_agent.py +257 -0
  230. evalrx/eval_agent/prompts/hypothesis_tester.py +15 -0
  231. evalrx/eval_agent/prompts/nl_runner.py +38 -0
  232. evalrx/eval_agent/prompts/probe_agent.py +25 -0
  233. evalrx/eval_agent/prompts/probe_candidate_generator.py +14 -0
  234. evalrx/eval_agent/prompts/probe_generator.py +35 -0
  235. evalrx/eval_agent/prompts/whitebox_probe_generator.py +38 -0
  236. evalrx/eval_agent/report.py +58 -0
  237. evalrx/eval_agent/run_context.py +354 -0
  238. evalrx/eval_agent/run_log.schema.json +1215 -0
  239. evalrx/eval_agent/run_logger_v2.py +1764 -0
  240. evalrx/eval_agent/run_metadata.py +208 -0
  241. evalrx/eval_agent/stages/__init__.py +56 -0
  242. evalrx/eval_agent/stages/case_discovery.py +293 -0
  243. evalrx/eval_agent/stages/diagnosis.py +1017 -0
  244. evalrx/eval_agent/stages/experiment_writer.py +1634 -0
  245. evalrx/eval_agent/stages/fix_agent.py +3916 -0
  246. evalrx/eval_agent/stages/fix_internals.py +499 -0
  247. evalrx/eval_agent/stages/fix_pipeline.py +725 -0
  248. evalrx/eval_agent/stages/fix_tiers.py +187 -0
  249. evalrx/eval_agent/stages/fix_tools.py +1034 -0
  250. evalrx/eval_agent/stages/hypothesis_tester.py +1014 -0
  251. evalrx/eval_agent/stages/probe.py +439 -0
  252. evalrx/eval_agent/stages/probe_agent.py +1079 -0
  253. evalrx/eval_agent/stages/probe_candidate_generator.py +128 -0
  254. evalrx/eval_agent/stages/probe_generator.py +326 -0
  255. evalrx/eval_agent/stages/probe_search_agent.py +106 -0
  256. evalrx/eval_agent/stages/protocol.py +112 -0
  257. evalrx/eval_agent/stages/repair_catalog.py +273 -0
  258. evalrx/eval_agent/stages/surgery.py +524 -0
  259. evalrx/eval_agent/stages/whitebox_probe_generator.py +351 -0
  260. evalrx/eval_agent/store.py +231 -0
  261. evalrx/logging_utils.py +112 -0
  262. evalrx/models/__init__.py +161 -0
  263. evalrx/models/_discover.py +101 -0
  264. evalrx/models/agent.py +380 -0
  265. evalrx/models/backends/__init__.py +58 -0
  266. evalrx/models/backends/api.py +169 -0
  267. evalrx/models/backends/base.py +57 -0
  268. evalrx/models/backends/gemini_compat.py +579 -0
  269. evalrx/models/backends/hf_local.py +2074 -0
  270. evalrx/models/backends/openai_compat.py +301 -0
  271. evalrx/models/backends/vllm_offline.py +116 -0
  272. evalrx/models/base.py +24 -0
  273. evalrx/models/blackbox/__init__.py +4 -0
  274. evalrx/models/blackbox/agent.py +31 -0
  275. evalrx/models/blackbox/base.py +29 -0
  276. evalrx/models/blackbox/gemini.py +279 -0
  277. evalrx/models/blackbox/llm_api.py +17 -0
  278. evalrx/models/blackbox/vlm_api.py +17 -0
  279. evalrx/models/compose.py +66 -0
  280. evalrx/models/inference.py +88 -0
  281. evalrx/models/paper_methods/__init__.py +8 -0
  282. evalrx/models/paper_methods/aad.py +53 -0
  283. evalrx/models/paper_methods/ifcd.py +204 -0
  284. evalrx/models/paper_methods/pai.py +164 -0
  285. evalrx/models/paper_methods/tcd.py +202 -0
  286. evalrx/models/paper_methods/vcd.py +45 -0
  287. evalrx/models/paper_methods/vicrop.py +137 -0
  288. evalrx/models/toolcodec.py +143 -0
  289. evalrx/models/tools/__init__.py +20 -0
  290. evalrx/models/tools/perception.py +300 -0
  291. evalrx/models/tools/visual.py +174 -0
  292. evalrx/models/whitebox/__init__.py +26 -0
  293. evalrx/models/whitebox/agent.py +31 -0
  294. evalrx/models/whitebox/base.py +24 -0
  295. evalrx/models/whitebox/qwen.py +61 -0
  296. evalrx/models/whitebox/qwen2_5_omni.py +29 -0
  297. evalrx/models/whitebox/qwen2_audio.py +25 -0
  298. evalrx/models/whitebox/qwen_omni.py +53 -0
  299. evalrx/models/whitebox/qwen_vl.py +62 -0
  300. evalrx/observability/__init__.py +21 -0
  301. evalrx/observability/envelope.py +122 -0
  302. evalrx/observability/outbox.py +111 -0
  303. evalrx/observability/tracer.py +882 -0
  304. evalrx/reporting/__init__.py +28 -0
  305. evalrx/reporting/case_study.py +947 -0
  306. evalrx/reporting/compiler.py +587 -0
  307. evalrx/reporting/dynamic.py +1882 -0
  308. evalrx/reporting/html_report.py +2225 -0
  309. evalrx/reporting/langfuse_exporter.py +38 -0
  310. evalrx/reporting/langfuse_source.py +155 -0
  311. evalrx/reporting/model.py +151 -0
  312. evalrx/reporting/run_events.py +184 -0
  313. evalrx/reporting/server.py +557 -0
  314. evalrx/reporting/stages.py +58 -0
  315. evalrx/reporting/static_export.py +142 -0
  316. evalrx/reporting/web_dist/index.html +146 -0
  317. evalrx/specs.py +727 -0
  318. evalrx/stats/__init__.py +47 -0
  319. evalrx/stats/api.py +192 -0
  320. evalrx/stats/bootstrap.py +86 -0
  321. evalrx/stats/ebh.py +27 -0
  322. evalrx/stats/evalue.py +98 -0
  323. evalrx/stats/friedman.py +138 -0
  324. evalrx/stats/mcnemar.py +40 -0
  325. evalrx/stats/multiplicity.py +159 -0
  326. evalrx/stats/subset_sampling.py +55 -0
  327. evalrx/term_links.py +43 -0
  328. evalrx/viz/__init__.py +7 -0
  329. evalrx/viz/labels.py +77 -0
  330. evalrx/viz/prompts.py +39 -0
  331. evalrx/viz/renderer.py +590 -0
  332. evalrx/viz/schema.py +36 -0
  333. evalrx/viz/style.py +134 -0
  334. evalrx-0.1.2.dist-info/METADATA +532 -0
  335. evalrx-0.1.2.dist-info/RECORD +339 -0
  336. evalrx-0.1.2.dist-info/WHEEL +5 -0
  337. evalrx-0.1.2.dist-info/entry_points.txt +3 -0
  338. evalrx-0.1.2.dist-info/licenses/LICENSE +121 -0
  339. evalrx-0.1.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,417 @@
1
+ """Prompt templates and prompt policies for exploratory analysis."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from evalrx.agent_runtime.skills.prompt_policy import fences_hint, skills_hint
6
+
7
+ RECORDS_FILENAME = "records.json" # also read by explore_run.py / HTML report compiler
8
+ _RESULT_MARKER = "EXPLORATORY_RESULT_JSON="
9
+
10
+ _INTRO_AND_QUESTION = """\
11
+ You are an exploratory data-analysis agent (Lambda-style): given ANY tabular
12
+ dataset — with a binary outcome, a multi-class outcome, a continuous outcome,
13
+ or no outcome at all — you write Python that discovers and charts the
14
+ structure that actually matters, adapting the story to what the data is.
15
+
16
+ Question:
17
+ {question}
18
+
19
+ """
20
+
21
+ _DATA_ACCESS_RECORDS = """\
22
+ A JSON file named "{input_filename}" is in the current working directory.
23
+ It contains a list of row dictionaries. Data profile (the host already
24
+ inferred column roles/dtypes and classified the outcome below — trust this
25
+ over re-guessing from raw values):
26
+ {data_profile}
27
+
28
+ Write a self-contained Python script that performs a THOROUGH, Lambda-style
29
+ exploratory analysis and PRODUCES A RICH SET OF CHARTS BY DEFAULT.
30
+
31
+ Setup:
32
+ - reads "{input_filename}" from the current working directory
33
+ - may use only local Python packages (pandas / numpy / matplotlib are fine); no
34
+ network and no repo mutation
35
+ - the profile's "columns" block gives each column's role (id / outcome / group
36
+ / time / predictor) and dtype; its "outcome" block ({{"present","column","kind"}})
37
+ tells you whether there is one and what kind it is. Do not invent an outcome
38
+ or a FAIL/PASS split when "outcome.present" is false.
39
+
40
+ {framing}
41
+
42
+ """
43
+
44
+ _DATA_ACCESS_RAW_FOLDER = """\
45
+ The RAW M1-style output is at "{raw_input_dir}/" in the current working
46
+ directory — nothing has been parsed, reshaped, or profiled for you. A
47
+ filesystem-level scan of what's on disk (file/dir counts, extensions, a
48
+ sample of entries — NOT parsed rows):
49
+ {folder_scan}
50
+
51
+ Write a self-contained Python script that performs a THOROUGH, Lambda-style
52
+ exploratory analysis and PRODUCES A RICH SET OF CHARTS BY DEFAULT.
53
+
54
+ Setup:
55
+ - FIRST, load and organize the raw data into ONE tidy table YOURSELF — this is
56
+ part of your job, not a solved input. The files under "{raw_input_dir}/" may
57
+ be a single file or many, and each file's JSON shape is not guaranteed: it
58
+ could already be a flat list of row dicts, JSONL (one JSON object per line),
59
+ or a dict holding scalar run/file metadata (e.g. "model", "seed") alongside
60
+ a list of per-case records under a conventional key such as "cases" /
61
+ "results" / "rows" / "items" / "data" / "examples" / "samples" — or
62
+ something else entirely. Inspect what is actually there before assuming a
63
+ shape. If a file wraps a list of per-case dicts alongside scalar metadata,
64
+ merge that metadata into every row it produces (e.g. a per-model file's
65
+ "model" field becomes a "model" column on each of that file's rows).
66
+ - a browser workbench bundle may also contain ``records.json`` (normalized
67
+ tabular rows), ``media_units.jsonl`` (file/page/time-segment metadata), and
68
+ a ``media/`` tree holding original images, PDFs, audio, or video. Start from
69
+ the normalized rows when present, join media units by source path when useful,
70
+ and inspect representative media only when your CLI can actually read it.
71
+ Do not invent semantic content for audio/video/PDF pages you could not open;
72
+ state the capability limitation in a caveat instead.
73
+ {outcome_hint}- after building the tidy table, determine whether it has a recognizable
74
+ outcome column (binary / categorical / continuous) or none at all — do NOT
75
+ invent a FAIL/PASS split when there is no such column.
76
+ - also write the tidy table you built to "{input_filename}" (a JSON list of
77
+ row dicts) in the current working directory, so it is available to whoever
78
+ reviews this analysis afterward.
79
+ - may use only local Python packages (pandas / numpy / matplotlib are fine); no
80
+ network and no repo mutation
81
+
82
+ {framing}
83
+
84
+ """
85
+
86
+ _GENERIC_FRAMING = """\
87
+ OUTCOME FRAMING — apply whichever case matches what you find after loading:
88
+ - BINARY outcome (2 distinct values in some column): call the two groups
89
+ FAIL and PASS and tell the FAIL-vs-PASS story — class balance; per numeric
90
+ signal vs FAIL/PASS (distribution view PNG + binned fail-rate curve spec);
91
+ a ranked bar of each signal's FAIL-vs-PASS separation; fail rate by
92
+ categorical group columns (group -> fail_rate, n, n_fail); signal
93
+ correlations; 1-2 scatter plots of the most discriminative pairs coloured
94
+ by outcome.
95
+ - CATEGORICAL outcome (3+ classes): tell the per-class story — do NOT
96
+ collapse it into a binary split. Class balance per class; per numeric
97
+ signal's distribution across classes (box/violin) plus a ranked
98
+ cross-class separation bar; class composition by categorical group
99
+ columns; signal correlations; 1-2 scatter plots coloured by class.
100
+ - CONTINUOUS outcome: a correlation/regression-style story — do not
101
+ binarize it unless the question explicitly asks for that. Outcome
102
+ distribution; per numeric signal vs outcome (scatter + trend line, plus a
103
+ binned mean-outcome curve); a ranked bar of correlation magnitude with the
104
+ outcome; outcome distribution by categorical group columns; predictor
105
+ correlation heatmap; 1-2 scatter plots of the most associated pairs.
106
+ - NO recognizable outcome/target column: unsupervised exploration — describe
107
+ structure, do NOT invent a label that isn't in the data. Missingness
108
+ overview; per-numeric-column distributions; per-categorical-column value
109
+ counts (skip columns with very high cardinality as a bar chart, note it in
110
+ caveats); correlation table/heatmap; 1-2 scatter plots of the most
111
+ correlated numeric pairs; if a group/time column exists, contrast numeric
112
+ distributions across it."""
113
+
114
+ _ANALYSIS_CONTRACT = """\
115
+ VISUAL ANALYSIS — before writing plotting code, make an explicit intermediate
116
+ visualization plan. The plan is part of the machine-readable output and should
117
+ show that YOU selected plot types from the data semantics, not from a fixed
118
+ template. Aim for 6-12 charts/plots that together tell the dataset's story.
119
+
120
+ First build a "visual_plan" list. Each item should be a dict:
121
+ {{
122
+ "name": "<stable artifact/chart name>",
123
+ "display_name": "<short human title, no raw generated/probe id>",
124
+ "question": "<what this visual answers>",
125
+ "data_shape": "<numeric-vs-binary | numeric-vs-categorical | numeric-vs-numeric | many-numeric | paired | unsupervised | ...>",
126
+ "plot_kind": "<chosen plot type, e.g. violin, box, strip, scatter, line, forest, heatmap, paired_slope, ECDF>",
127
+ "fallback_kind": "<bar|line|scatter|forest when a deterministic host chart is useful>",
128
+ "required_columns": ["..."],
129
+ "rationale": "<why this plot type fits the data and avoids misleading summaries>",
130
+ "disposition": "<primary|supporting|skipped>",
131
+ "not_promoted_reason": "<required when supporting; why this is context/diagnostic material rather than a ranked takeaway>"
132
+ }}
133
+
134
+ Use these decision principles (chart-type policy: a bar's filled area means
135
+ "amount accumulated from zero" — BARS ARE FOR COUNTS ONLY; never a rate, a
136
+ mean, a proportion, or an effect size — the host demotes such a bar to a line
137
+ or a forest plot):
138
+ - class balance (count per outcome class): a count table; the host draws it
139
+ as ONE composition strip, never two tall bars.
140
+ - a rate or a mean compared across a few groups (FAIL vs PASS, present vs
141
+ absent, ...): a group->value table WITH an "n" column — and for a RATE also
142
+ the numerator column (e.g. "n_fail") or explicit "ci_low"/"ci_high"; the
143
+ host draws <= 3 groups as a dot + 95% CI (a lollipop when no interval can
144
+ be formed), never as bars. A "mean_*" of per-case values gets no invented
145
+ interval — give ci_low/ci_high yourself if you have them.
146
+ - a rate/mean/effect over MORE than 3 groups or over bins: a line (binned
147
+ rates) or a ranked forest/dot plot (effect sizes), never bars.
148
+ - numeric predictor vs categorical/binary outcome: the deterministic spec is
149
+ the BINNED fail-rate LINE (bin -> fail_rate, with n per bin) — do NOT also
150
+ emit a two-group "mean of the signal by outcome" spec for it; the
151
+ distribution view (violin/box/strip by outcome) is a rich PNG you draw.
152
+ - binned numeric trend (event rate, or mean of a continuous outcome): line
153
+ over ordered bins/percentiles.
154
+ - numeric vs numeric: scatter, optionally colored/stratified by outcome or group.
155
+ - many numeric signals: ranked effect/association DOT plot (forest) plus
156
+ correlation heatmap — never green/grey effect bars.
157
+ - paired/intervention data: paired slope or discordant-count visual.
158
+ - no outcome column: prioritize distributions, missingness, correlation
159
+ structure, and group contrasts over any label-vs-label story.
160
+ - skip a planned visual when required columns are absent or sample size makes it
161
+ misleading; say so in caveats.
162
+ - A ``primary`` visual MUST be cited by at least one takeaway's ``chart_names``.
163
+ Use ``supporting`` only for context/diagnostic material and give a concrete
164
+ ``not_promoted_reason``. Do not emit an artifact for a ``skipped`` visual.
165
+
166
+ For EVERY chart you report in "charts":
167
+ - write its plotted data as a CSV under "tables/<name>.csv"
168
+ - add a spec {{"name","display_name","kind","data","x","y","title"}} with data="tables/<name>.csv"
169
+ and kind in {{"bar","line","scatter","forest"}}. The HOST renders these deterministically,
170
+ so PRE-AGGREGATE distributions into the CSV (histogram = bin->count; outcome
171
+ rate or mean-outcome curve = bin->value plus n; group comparison =
172
+ group->value plus n, and for a rate its numerator or ci_low/ci_high) —
173
+ never rely on a raw dump. The host picks the chart FORM from the table
174
+ (composition strip for class counts, dot + CI for <= 3 groups, line for
175
+ bins, forest plot for ranked effects, bars only for raw counts — a
176
+ kind="bar" whose y is a rate/mean/effect is demoted automatically) and
177
+ colours FAIL/PASS with the house hues, so name outcome groups exactly
178
+ "FAIL" / "PASS".
179
+ ADDITIONALLY you MAY draw richer figures (box / violin / heatmap / scatter-matrix)
180
+ directly as PNG under "figures/" and list them in "plots"; a figure-styling skill
181
+ (when available) will make these publication-quality.
182
+
183
+ This is PURE EXPLORATORY DATA ANALYSIS. Describe what the data shows. Do NOT
184
+ propose causal explanations, do NOT claim anything is "confirmed" or
185
+ "validated", and do NOT frame findings as hypotheses to be tested — hypothesis
186
+ generation and validation are a different, separate step that this tool does
187
+ not perform. Stick to descriptive, evidence-grounded statements.
188
+
189
+ Plain-language framing of the question (the dashboard's page headline, so it
190
+ renders BEFORE any takeaway):
191
+ - "plain_question": restate the Question above in ONE everyday sentence — what
192
+ is actually being investigated, in plain words a non-technical reader would
193
+ understand, not a compressed research-question shorthand. The caller's own
194
+ question may itself be dense/technical (column names, stats jargon, a
195
+ numbered list of sub-asks); your job is to say in plain terms what it's
196
+ really asking, not to copy it. Same jargon/acronym/symbol ban as
197
+ "plain_title" below, and it is checked the same way.
198
+
199
+ Reader-friendly writing contract:
200
+ - Write for a user who may understand the evaluation problem but may NOT know
201
+ machine-learning or statistics terms. Prefer concrete, plain language over
202
+ terms like "rank-biserial", "AUC", "VIF", "collinearity", "effect size",
203
+ "bootstrap", or "regression" in reader-facing titles and summaries. If one of
204
+ those terms is unavoidable, define it immediately in the same sentence.
205
+ - Separate three ideas in every reader-facing explanation: what was observed,
206
+ why it matters for the user's question, and what remains uncertain.
207
+ - Use raw counts alongside percentages whenever you can, e.g. "24 of 30 cases
208
+ (80%)" rather than only "80%". For group comparisons, name both groups and
209
+ their sample sizes.
210
+ - Never imply that an observed relationship proves a cause. Use wording like
211
+ "is linked with", "appears more often with", or "is a candidate signal", not
212
+ "drives", "causes", or "explains", unless an intervention actually tested it.
213
+ - Clearly flag weak evidence in ordinary language: small samples, missing data,
214
+ uneven group sizes, repeated cases, class imbalance, wide uncertainty, or
215
+ thresholds chosen on the same exploration rows.
216
+
217
+
218
+ Takeaways (THE PRIMARY OUTPUT — this is what a reader sees first):
219
+ - "takeaways": a ranked list of 4-8 dicts, most important/surprising finding
220
+ first, each shaped exactly like:
221
+ {{"plain_title": "<the SAME finding as 'title' below, restated in ONE
222
+ everyday sentence a non-technical reader (a PM, not a
223
+ statistician) can understand at a glance. NO acronyms
224
+ (AUC, ROC, CI, ECDF...), NO statistics jargon
225
+ (collinear, logistic, coefficient, p-value, quantile,
226
+ monotonic, confound, variance, latent, mediator...),
227
+ NO symbols (→, ρ, σ). Numbers/percentages ARE
228
+ encouraged — plain language does not mean vague; keep
229
+ the evidence, drop the notation. This is the headline
230
+ a reader sees first; it is checked automatically and a
231
+ jargon-y or copy-pasted one is sent back for a
232
+ rewrite.>",
233
+ "title": "<one concise companion sentence with the precise technical
234
+ detail and real counts/percentages; statistics terms are fine
235
+ here when they add useful precision>",
236
+
237
+ "chart_names": ["<name(s) from 'charts' or 'plots' that support it>"],
238
+ "table_names": ["<key(s) from 'tables' that support it, if any>"],
239
+ "analysis": "<2-4 plain-language sentences: (1) what was observed, (2)
240
+ why it matters for the user's question, and (3) what
241
+ remains uncertain. Cite actual counts, percentages,
242
+ columns, and groups behind the chart(s).>",
243
+ "caveat": "<short plain-language note on what this does NOT show, or '' if nothing notable>"}}
244
+ EVERY important chart/plot you produce should be referenced by at least one
245
+ takeaway's "chart_names" — never leave a chart orphaned with no explanation,
246
+ and never write a takeaway with no supporting chart/table unless the data
247
+ genuinely has none to offer (rare).
248
+
249
+ Report/dashboard contract:
250
+ - Emit ONE "dashboard_storyboard" panel dict (a list with one entry) orienting
251
+ the reader on the data/question before the takeaways:
252
+ {{"id": "problem_setting", "title": "Problem Setting", "summary": "...",
253
+ "items": ["..."], "artifact_refs": ["data_profile"]}}
254
+ The problem-setting summary/items must state, in plain language:
255
+ * what is being studied;
256
+ * the user's question;
257
+ * the unit of analysis (one row = one case/batch/request/etc.);
258
+ * how many records were loaded and which groups/splits are relevant;
259
+ * what the outcome column means in practical terms (e.g. what FAIL/PASS
260
+ mean, or what a continuous outcome measures).
261
+ Do not add "analysis" or "hypotheses" panels — "takeaways" already covers
262
+ that ground, and this tool does not generate hypotheses.
263
+
264
+ Secondary fields (for programmatic consumers such as a downstream confirmatory
265
+ pipeline — NOT the primary reader-facing narrative; keep these terse):
266
+ - add "chart_readings": one short dict for EVERY emitted chart or plot, keyed
267
+ by its exact chart name or PNG stem, with
268
+ {{"chart": "<name/title>", "reading": "<what a human should see>",
269
+ "do_not_infer": "<what this chart cannot prove>"}}. This is the explanation
270
+ displayed immediately below that visual; never leave it generic or omit it.
271
+ The reading should explain the visible pattern in one or two simple
272
+ sentences, name the comparison groups and sample sizes when available, and
273
+ avoid merely restating the axes. The do_not_infer field should name the main
274
+ boundary, such as "does not prove causation", "small group", "chosen on
275
+ exploration rows", or "missing data may affect this comparison".
276
+ - add "claims" only for carefully worded descriptive/confirmable statements. Each
277
+ claim must cite chart/signal identifiers in "evidence_ids"; set status to
278
+ "descriptive" (never "supported" — this tool does not confirm anything).
279
+ - add "critique": agent self-audit notes about leakage, small n, double-dipping,
280
+ missingness, misleading plot choices, or alternative explanations.
281
+ - Never use raw internal IDs like "generated_probe1_false_detection" as user-facing
282
+ chart titles or claim text. Use display names such as "Sanity check: probe
283
+ false-detection flag", and demote probe-derived fields to sanity-check
284
+ evidence rather than explanatory findings.
285
+ - PREFERRED: for any composite / threshold / interaction signal that is a
286
+ DETERMINISTIC FUNCTION of the numeric columns, attach a "recipe" so a
287
+ downstream confirmatory pipeline can compute it on a HELD-OUT split later
288
+ (this tool itself does not run that confirmation):
289
+ "recipe": {{"name": "<new signal key>", "kind": "expr",
290
+ "expr": "<boolean/numeric expression over the numeric columns above>"}}
291
+ The expr may use the columns BY NAME, comparisons (< <= > >= == !=), and/or/not,
292
+ arithmetic (+ - * / %), and abs/min/max/float/int/len. It must NOT reference the
293
+ label/outcome column (a recipe is a PREDICTOR, never the answer). Example:
294
+ "recipe": {{"name": "small_and_peripheral", "kind": "expr", "expr": "(obj_size < 40) and (focus_share < 0.3)"}}
295
+ Emit a recipe rather than prose whenever the candidate is computable from the columns.
296
+ - ALTERNATIVELY, you MAY attach host-adjudicable "sufficient" statistics computed
297
+ from the rows, as ONE of these shapes:
298
+ {{"kind": "two_group", "a": [0/1, ...], "b": [0/1, ...]}} # is_fail indicators among signal-ABSENT (a) vs signal-PRESENT (b) cases
299
+ {{"kind": "paired_binary", "b": <int>, "c": <int>}} # discordant counts of a paired intervention (b = flips the good way, c = the bad way)
300
+ Do NOT emit "reject"/"e_value"/"p_value" anywhere — this tool never adjudicates
301
+ a verdict itself; a self-declared verdict is ignored. Omit both for
302
+ descriptive-only signals.
303
+ - prints the final result as the LAST stdout line exactly like (note "charts" is a
304
+ RICH list here, one entry per CSV you wrote). The example below illustrates the
305
+ JSON SHAPE using a binary-outcome dataset; KEEP THE SAME KEYS but replace the
306
+ FAIL/PASS/fail_rate wording with language that matches the ACTUAL outcome kind
307
+ from the profile above (categorical classes, a continuous outcome's mean/curve,
308
+ or plain unsupervised structure when there is no outcome):
309
+ {marker}{{
310
+ "plain_question": "Whether small objects are harder for the model to get right.",
311
+ "observations": ["..."],
312
+ "visual_plan": [
313
+ {{"name": "failrate_by_objsize",
314
+ "display_name": "Failure rate by object size",
315
+ "question": "Does object size change failure risk?",
316
+ "data_shape": "numeric-vs-binary",
317
+ "plot_kind": "line",
318
+ "fallback_kind": "line",
319
+ "required_columns": ["obj_size", "label"],
320
+ "rationale": "Ordered bins show risk trend without assuming linearity.",
321
+ "disposition": "primary",
322
+ "not_promoted_reason": ""}}
323
+ ],
324
+ "takeaways": [
325
+ {{"plain_title": "Small objects trip up the model much more often than big ones.",
326
+ "title": "Small-object cases failed in 18 of 100 rows (18%), compared with 4 of 100 larger-object rows (4%).",
327
+
328
+ "chart_names": ["failrate_by_objsize"],
329
+ "table_names": [],
330
+ "analysis": "The chart compares small-object cases with larger-object cases. Small-object cases failed in 18 of 100 rows (18%), compared with 4 of 100 larger-object rows (4%). This matters because it points to a concrete group of cases to inspect next, but the chart does not show whether object size itself is the reason for the failures.",
331
+ "caveat": "Descriptive only — other differences between the two groups may be responsible, and this is not a causal finding."}}
332
+ ],
333
+ "chart_readings": [
334
+ {{"chart": "failrate_by_objsize",
335
+ "reading": "The smallest object-size bins have visibly higher failure rates than the larger-object bins. Include the number of cases in each bin so the reader can see whether the comparison is based on enough data.",
336
+ "do_not_infer": "This chart does not prove object size causes the error; it only shows where failures are more common in these rows."}}
337
+ ],
338
+ "claims": [
339
+ {{"id": "C1",
340
+ "text": "Small object size is a descriptive failure correlate.",
341
+ "status": "descriptive",
342
+ "evidence_ids": ["chart:failrate_by_objsize"],
343
+ "interpretation": "A candidate signal for downstream confirmatory analysis.",
344
+ "do_not_infer": "Not causal; not yet confirmed by any statistical test."}}
345
+ ],
346
+ "dashboard_storyboard": [
347
+ {{"id": "problem_setting", "title": "Problem Setting",
348
+ "summary": "This run studies labeled model-evaluation cases to find which recorded signals are linked with failures.",
349
+ "items": ["User question: which case features are linked with FAIL outcomes?", "Unit of analysis: one row is one evaluated case.", "Outcome: FAIL means the model gave the wrong answer; PASS means it answered correctly.", "Report the number of loaded rows and the FAIL/PASS counts here."],
350
+ "artifact_refs": ["data_profile"]}}
351
+ ],
352
+ "candidate_signals": [
353
+ {{"name": "...", "display_name": "<human-readable signal label>",
354
+ "rationale": "...", "suggested_test": "...",
355
+ "recipe": {{"name": "...", "kind": "expr",
356
+ "expr": "(col_a < 40) and (col_b < 0.3)"}}}}
357
+ ],
358
+ "plots": ["figures/corr_heatmap.png"],
359
+ "tables": {{}},
360
+ "charts": [
361
+ {{"name": "class_balance", "kind": "bar",
362
+ "display_name": "FAIL/PASS case balance",
363
+ "data": "tables/class_balance.csv", "x": "outcome", "y": "count",
364
+ "title": "FAIL vs PASS"}},
365
+ {{"name": "failrate_by_objsize", "kind": "line",
366
+ "display_name": "Failure rate by object size",
367
+ "data": "tables/failrate_by_objsize.csv", "x": "obj_size_bin",
368
+ "y": "fail_rate", "title": "Fail rate by object size"}},
369
+ {{"name": "top_discriminators", "kind": "bar",
370
+ "data": "tables/top_discriminators.csv", "x": "signal",
371
+ "y": "separation", "title": "Top FAIL/PASS discriminators"}}
372
+ ],
373
+ "caveats": ["..."],
374
+ "critique": ["..."],
375
+ "recommended_confirmatory_tests": ["..."]
376
+ }}
377
+ {skills_hint}
378
+ Return ONLY the Python code{fences_hint}."""
379
+
380
+ _GENERATE_PROMPT_RECORDS = _INTRO_AND_QUESTION + _DATA_ACCESS_RECORDS + _ANALYSIS_CONTRACT
381
+ _GENERATE_PROMPT_RAW_FOLDER = _INTRO_AND_QUESTION + _DATA_ACCESS_RAW_FOLDER + _ANALYSIS_CONTRACT
382
+
383
+ _REPAIR_PROMPT = """\
384
+ The exploratory analysis script failed or produced an invalid result.
385
+
386
+ Question:
387
+ {question}
388
+
389
+ Data profile:
390
+ {data_profile}
391
+
392
+ Previous code:
393
+ ```python
394
+ {code}
395
+ ```
396
+
397
+ Sandbox stdout:
398
+ {stdout}
399
+
400
+ Sandbox stderr:
401
+ {stderr}
402
+
403
+ Parser/execution error:
404
+ {error}
405
+
406
+ Rewrite the script so it succeeds end-to-end and still prints a final
407
+ {marker} JSON line with the required keys, in the same format as before.
408
+ Return ONLY Python code{fences_hint}."""
409
+
410
+ RESULT_MARKER = _RESULT_MARKER
411
+ GENERIC_FRAMING = _GENERIC_FRAMING
412
+ GENERATE_PROMPT_RECORDS = _GENERATE_PROMPT_RECORDS
413
+ GENERATE_PROMPT_RAW_FOLDER = _GENERATE_PROMPT_RAW_FOLDER
414
+ REPAIR_PROMPT = _REPAIR_PROMPT
415
+
416
+ _fences_hint = fences_hint
417
+ _skills_hint = skills_hint
@@ -0,0 +1,33 @@
1
+ """Prompt template for naming failure-mode clusters."""
2
+
3
+ from __future__ import annotations
4
+
5
+ NAME_CLUSTERS_PROMPT = """\
6
+ You are an ML failure-analysis expert. Below are groups of failing cases that
7
+ were clustered by similarity. For each cluster, propose a short, specific
8
+ failure-mode name and a one-sentence description of what these cases have in
9
+ common. Some clusters include a "boundary contrast" section: a failing case
10
+ paired with its nearest successful (non-failing) counterpart. When present,
11
+ use these pairs to pinpoint exactly where the model's behavior crosses from
12
+ correct to incorrect, rather than just describing the failing topic.
13
+
14
+ {clusters_block}
15
+
16
+ Reply with EXACTLY ONE JSON array, one object per cluster listed above:
17
+ [{{"cluster_id": <int>, "name": "<short_snake_case_tag>", "description": "<one sentence>"}}, ...]
18
+
19
+ Return ONLY the JSON array — no prose outside it."""
20
+
21
+ ERROR_SIGNAL_PROMPT = """\
22
+ You are an ML failure-analysis expert. Below are (expected, observed) pairs
23
+ from cases where a model's output was judged incorrect. For each pair, write
24
+ a short phrase (5-10 words) describing the *mechanism* of the mismatch (e.g.
25
+ "off-by-one count", "wrong entity substituted", "missing negation"), not just
26
+ that it is wrong.
27
+
28
+ {pairs_block}
29
+
30
+ Reply with EXACTLY ONE JSON array, one object per pair listed above:
31
+ [{{"index": <int>, "error": "<short phrase>"}}, ...]
32
+
33
+ Return ONLY the JSON array — no prose outside it."""
@@ -0,0 +1,27 @@
1
+ """Prompt template for the held-out hypothesis judge (`analysis.holdout`)."""
2
+
3
+ JUDGE_PROMPT = """You are adjudicating a proposed hypothesis about failure patterns
4
+ in a dataset, using HELD-OUT rows the proposer never saw.
5
+
6
+ HYPOTHESIS: {statement}
7
+ BASIS (from the exploration phase): {basis}
8
+ PROPOSED TEST DESIGN: {test_design}
9
+
10
+ HELD-OUT EVIDENCE (validate split, n={n_rows}; recipe thresholds frozen from the
11
+ exploration phase; REJECT H0 means the signal separated the outcome groups on
12
+ held-out data):
13
+ {evidence}
14
+
15
+ Grade the hypothesis STRICTLY against this held-out evidence:
16
+ - "supported": the held-out statistics directly back the hypothesis's claim.
17
+ - "partial": the correlational part holds up but the hypothesis claims more
18
+ (e.g. a mechanism or causal direction) than these statistics can establish.
19
+ - "refuted": the held-out statistics contradict the claim.
20
+ - "not_testable": these observational statistics cannot decide the claim at
21
+ all (e.g. causal direction); it needs an intervention/surgery experiment.
22
+
23
+ Reply with ONLY a JSON object:
24
+ {{"verdict": "supported|partial|refuted|not_testable",
25
+ "reasoning": "<2-3 sentences citing the held-out numbers>",
26
+ "needs_surgery": true/false}}
27
+ """
@@ -0,0 +1,78 @@
1
+ """Prompt template for the standalone M3 HypothesisAgent."""
2
+
3
+ from __future__ import annotations
4
+
5
+ # Column-name markers that identify agent-trajectory records (produced by
6
+ # evalrx.analysis.trajectory_records / the agent M1 probes). When any of
7
+ # these appear in the report, AGENT_TRAJECTORY_HINT is appended to the propose
8
+ # prompt.
9
+ AGENT_COLUMN_MARKERS: tuple[str, ...] = (
10
+ "n_tool_calls", "n_calls_", "max_consecutive_repeat", "repeated_call_frac",
11
+ "tool_error_rate", "tool_seq_diversity", "n_images_returned",
12
+ "failure_mode", "shap_outcome_", "shap_answer_",
13
+ "success_rate", "pass_at_k", "pass_all_k", "trajectory",
14
+ )
15
+
16
+ AGENT_TRAJECTORY_HINT = """\
17
+ These records describe AGENT TRAJECTORIES (a model calling tools in a loop).
18
+ Extra guidance for this data:
19
+ - Prefer hypotheses that name an INTERVENABLE cause — something a prompt or
20
+ scaffold change could alter: the system-prompt wording, a tool's description
21
+ or argument conventions, which tools are available, or the loop/stop policy.
22
+ Fixes for agents are black-box only, so "this part of the agent's setup
23
+ causes failures" is repairable, while "failures correlate with X" alone is
24
+ not a mechanism.
25
+ - Column-family semantics, where present: shap_outcome_<tool> is the causal
26
+ contribution of that tool to passing (measured by re-running with tool
27
+ subsets); success_rate / flaky / pass_at_k come from repeated runs and
28
+ measure stability, not capability; failure_mode is a judge-assigned label —
29
+ itself a hypothesis to verify, never ground truth; total_*_tokens and
30
+ *_latency_ms are cost.
31
+ - A TEST line may propose re-running the agent with a changed prompt, tool
32
+ description, or tool subset on held-out cases — interventions are directly
33
+ testable here, not just observational splits."""
34
+
35
+ PROPOSE_PROMPT = """\
36
+ You are a data analyst explaining candidate explanations to a general
37
+ audience — mostly non-technical stakeholders, not statisticians. Based on
38
+ the exploratory analysis below, propose specific, falsifiable hypotheses
39
+ that could explain the patterns found. A hypothesis is a candidate
40
+ explanation or mechanism — not a restatement of a finding, and not a claim
41
+ you are asked to prove here.
42
+
43
+ Question investigated: {question}
44
+
45
+ Key takeaways from the exploratory analysis (title: analysis):
46
+ {takeaways_text}
47
+
48
+ Observations:
49
+ {observations_text}
50
+
51
+ Candidate signals already noted:
52
+ {signals_text}
53
+
54
+ Propose 1-3 hypotheses. For each write exactly four lines:
55
+ HYPOTHESIS: <one-sentence falsifiable claim explaining a pattern above; precise language and technical terms are fine here>
56
+ PLAIN: <the SAME claim restated in ONE everyday sentence a non-technical reader can understand at a glance — NO acronyms (AUC, CI...), NO statistics jargon (collinear, logistic, coefficient, p-value, latent, mediator...), NO symbols. Numbers/percentages are fine and encouraged>
57
+ BASIS: <which takeaway(s)/signal(s) above this is grounded in>
58
+ TEST: <what evidence/analysis would confirm or refute this claim>
59
+
60
+ Do not repeat a takeaway verbatim — propose a CAUSE or MECHANISM behind what
61
+ was observed. If the findings are too thin to support any falsifiable
62
+ hypothesis, respond with exactly: NO_HYPOTHESIS"""
63
+
64
+ PLAIN_REPAIR_PROMPT = """\
65
+ Your previous answer below proposed hypotheses correctly, but some PLAIN
66
+ lines fail a plain-language check: PLAIN must be a jargon-free, one-sentence,
67
+ everyday paraphrase of the matching HYPOTHESIS line — no statistics terms,
68
+ acronyms, or symbols. Numbers/percentages are fine.
69
+
70
+ Previous answer:
71
+ {raw}
72
+
73
+ Problems found:
74
+ {violations}
75
+
76
+ Rewrite the FULL set of hypotheses in the exact same
77
+ HYPOTHESIS/PLAIN/BASIS/TEST format, fixing only the flagged PLAIN lines. Do
78
+ not change the HYPOTHESIS, BASIS, or TEST lines."""
@@ -0,0 +1,47 @@
1
+ """Prompt templates for the ``run_codebase`` entry: a CLI coding agent runs a
2
+ user's existing evaluation/inference codebase and harvests its per-case
3
+ results into the records-file output contract that
4
+ :func:`evalrx.analysis.run_codebase.run_codebase` reads.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ RUN_PROMPT_TEMPLATE = """\
10
+ You are working inside a copy of a user's evaluation/inference codebase, at
11
+ the current working directory. Your job:
12
+
13
+ 1. Understand the codebase: find its evaluation or inference entry point
14
+ (a script, notebook-derived script, or main/run/eval module) and whatever
15
+ dependencies or config it needs.
16
+ 2. Run it so it actually executes the evaluation over its dataset. Install
17
+ missing lightweight dependencies if needed. If it requires resources you
18
+ do not have (GPU, network, missing API keys), do the best you can and
19
+ report what happened in your final message.
20
+ 3. Produce a file named "{records_name}" in this directory: a JSON array or
21
+ JSON-Lines file with ONE ROW PER EVALUATION CASE. Each row MUST include:
22
+ - a "label" field: "PASS"/"FAIL" (or another clear correctness verdict
23
+ for the task) for that case
24
+ - the case's input, prediction/output, and target/expected fields, using
25
+ whatever field names make sense for this task
26
+ If the codebase already writes per-case outputs (predictions, logs, a
27
+ results table), read them and CONVERT them into "{records_name}" in this
28
+ format rather than re-running everything from scratch when that is
29
+ faster and equally faithful.
30
+
31
+ Do not fabricate results. If the run genuinely fails, still write
32
+ "{records_name}" with whatever real per-case rows you were able to produce
33
+ (even from a partial run), and explain the failure in your final message.
34
+
35
+ Task context supplied by the user:
36
+ {question}
37
+ """
38
+
39
+ REPAIR_PROMPT_TEMPLATE = """\
40
+ Your previous attempt did not leave a usable "{records_name}" in this
41
+ directory ({reason}). Look at what actually happened (error output, partial
42
+ results, logs) and try again: get the evaluation to run and write
43
+ "{records_name}" as a JSON array or JSON-Lines file, one row per case, each
44
+ with a "label" field plus the case's input/prediction/target fields. If a
45
+ full run is not possible, write whatever real partial results you have
46
+ rather than nothing.
47
+ """