agentinputlab 0.1.0a1__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 (469) hide show
  1. agentinputlab/__init__.py +28 -0
  2. agentinputlab/algorithms/__init__.py +6 -0
  3. agentinputlab/algorithms/acquire/__init__.py +145 -0
  4. agentinputlab/algorithms/acquire/adaptive_rag/__init__.py +43 -0
  5. agentinputlab/algorithms/acquire/adaptive_rag/replay.py +367 -0
  6. agentinputlab/algorithms/acquire/adaptive_rag/runtime.py +1202 -0
  7. agentinputlab/algorithms/acquire/adaptive_rag_common_support.py +542 -0
  8. agentinputlab/algorithms/acquire/hyde.py +296 -0
  9. agentinputlab/algorithms/acquire/hyde_controlled.py +200 -0
  10. agentinputlab/algorithms/acquire/hyde_external.py +148 -0
  11. agentinputlab/algorithms/acquire/ircot.py +28 -0
  12. agentinputlab/algorithms/acquire/ircot_common_support.py +478 -0
  13. agentinputlab/algorithms/acquire/ircot_native.py +355 -0
  14. agentinputlab/algorithms/acquire/ircot_replay.py +327 -0
  15. agentinputlab/algorithms/acquire/qrag/__init__.py +79 -0
  16. agentinputlab/algorithms/acquire/qrag/bridge.py +828 -0
  17. agentinputlab/algorithms/acquire/qrag/common_support.py +891 -0
  18. agentinputlab/algorithms/acquire/qrag/native_axis.py +71 -0
  19. agentinputlab/algorithms/acquire/qrag/reader_adapter.py +139 -0
  20. agentinputlab/algorithms/acquire/r2ag/__init__.py +57 -0
  21. agentinputlab/algorithms/acquire/r2ag/bridge.py +1312 -0
  22. agentinputlab/algorithms/acquire/r2ag/common_support.py +1029 -0
  23. agentinputlab/algorithms/acquire/r2ag/socket_runtime.py +255 -0
  24. agentinputlab/algorithms/clarify/__init__.py +61 -0
  25. agentinputlab/algorithms/clarify/_structured.py +64 -0
  26. agentinputlab/algorithms/clarify/active_task_disambiguation.py +371 -0
  27. agentinputlab/algorithms/clarify/ask_or_assume/__init__.py +17 -0
  28. agentinputlab/algorithms/clarify/ask_or_assume/monitor.py +410 -0
  29. agentinputlab/algorithms/clarify/future_turns.py +379 -0
  30. agentinputlab/algorithms/clarify/udcs.py +255 -0
  31. agentinputlab/algorithms/clarify/udcs_deterministic.py +196 -0
  32. agentinputlab/algorithms/curate/__init__.py +65 -0
  33. agentinputlab/algorithms/curate/acon/__init__.py +27 -0
  34. agentinputlab/algorithms/curate/acon/common.py +284 -0
  35. agentinputlab/algorithms/curate/acon/common_support.py +136 -0
  36. agentinputlab/algorithms/curate/acon/history_bridge.py +309 -0
  37. agentinputlab/algorithms/curate/acon/observation_bridge.py +290 -0
  38. agentinputlab/algorithms/curate/llmlingua/__init__.py +30 -0
  39. agentinputlab/algorithms/curate/llmlingua/adapters.py +537 -0
  40. agentinputlab/algorithms/curate/llmlingua/budget.py +48 -0
  41. agentinputlab/algorithms/curate/llmlingua/controlled.py +175 -0
  42. agentinputlab/algorithms/curate/llmlingua/multilingual.py +105 -0
  43. agentinputlab/algorithms/curate/llmlingua/span_map.py +167 -0
  44. agentinputlab/algorithms/curate/recomp/__init__.py +47 -0
  45. agentinputlab/algorithms/curate/recomp/external.py +1129 -0
  46. agentinputlab/algorithms/curate/recomp/selective.py +304 -0
  47. agentinputlab/algorithms/decompose/__init__.py +107 -0
  48. agentinputlab/algorithms/decompose/decomp/__init__.py +53 -0
  49. agentinputlab/algorithms/decompose/decomp/common_support.py +478 -0
  50. agentinputlab/algorithms/decompose/decomp/planner_component.py +199 -0
  51. agentinputlab/algorithms/decompose/decomp/worker_bridge.py +416 -0
  52. agentinputlab/algorithms/decompose/llm_compiler/__init__.py +35 -0
  53. agentinputlab/algorithms/decompose/llm_compiler/bridge.py +520 -0
  54. agentinputlab/algorithms/decompose/llm_compiler/common_support.py +504 -0
  55. agentinputlab/algorithms/decompose/plan_and_budget/__init__.py +43 -0
  56. agentinputlab/algorithms/decompose/plan_and_budget/cached_soft_budget.py +362 -0
  57. agentinputlab/algorithms/decompose/plan_and_budget/decomposer_component.py +107 -0
  58. agentinputlab/algorithms/decompose/plan_and_budget/full.py +205 -0
  59. agentinputlab/algorithms/decompose/plan_and_budget/hard_cap.py +246 -0
  60. agentinputlab/algorithms/decompose/plan_and_budget/regenerated_soft_budget.py +448 -0
  61. agentinputlab/algorithms/decompose/plan_and_solve/__init__.py +33 -0
  62. agentinputlab/algorithms/decompose/plan_and_solve/plan_component.py +192 -0
  63. agentinputlab/algorithms/decompose/plan_and_solve/ps_prompt.py +127 -0
  64. agentinputlab/algorithms/decompose/self_ask/__init__.py +27 -0
  65. agentinputlab/algorithms/decompose/self_ask/loop.py +362 -0
  66. agentinputlab/algorithms/decompose/self_ask/planner_component.py +117 -0
  67. agentinputlab/algorithms/reformulate/__init__.py +85 -0
  68. agentinputlab/algorithms/reformulate/infocqr/__init__.py +40 -0
  69. agentinputlab/algorithms/reformulate/infocqr/cache_replay.py +362 -0
  70. agentinputlab/algorithms/reformulate/infocqr/external.py +675 -0
  71. agentinputlab/algorithms/reformulate/infocqr/student.py +189 -0
  72. agentinputlab/algorithms/reformulate/query2doc/__init__.py +42 -0
  73. agentinputlab/algorithms/reformulate/query2doc/controlled_live.py +190 -0
  74. agentinputlab/algorithms/reformulate/query2doc/models.py +95 -0
  75. agentinputlab/algorithms/reformulate/query2doc/official_cached.py +335 -0
  76. agentinputlab/algorithms/reformulate/query2doc/querygym_bridge.py +223 -0
  77. agentinputlab/algorithms/reformulate/query2doc/querygym_runtime.py +326 -0
  78. agentinputlab/algorithms/reformulate/reformer/__init__.py +23 -0
  79. agentinputlab/algorithms/reformulate/reformer/external.py +417 -0
  80. agentinputlab/algorithms/reformulate/rrr.py +696 -0
  81. agentinputlab/annotation/__init__.py +5 -0
  82. agentinputlab/annotation/independent.py +428 -0
  83. agentinputlab/annotation/server.py +233 -0
  84. agentinputlab/annotation/static/app.js +121 -0
  85. agentinputlab/annotation/static/index.html +60 -0
  86. agentinputlab/annotation/static/review.css +2 -0
  87. agentinputlab/annotation/static/review.html +10 -0
  88. agentinputlab/annotation/static/review.js +11 -0
  89. agentinputlab/annotation/static/styles.css +55 -0
  90. agentinputlab/annotation/store.py +444 -0
  91. agentinputlab/api.py +368 -0
  92. agentinputlab/artifacts/__init__.py +15 -0
  93. agentinputlab/artifacts/json_file.py +104 -0
  94. agentinputlab/artifacts/manifest.py +98 -0
  95. agentinputlab/artifacts/store.py +157 -0
  96. agentinputlab/backends/__init__.py +98 -0
  97. agentinputlab/backends/embedding/__init__.py +25 -0
  98. agentinputlab/backends/embedding/base.py +145 -0
  99. agentinputlab/backends/embedding/callable.py +75 -0
  100. agentinputlab/backends/embedding/replay.py +129 -0
  101. agentinputlab/backends/llm/__init__.py +31 -0
  102. agentinputlab/backends/llm/base.py +149 -0
  103. agentinputlab/backends/llm/callable.py +108 -0
  104. agentinputlab/backends/llm/decomp_completion.py +88 -0
  105. agentinputlab/backends/llm/final_content_stop.py +72 -0
  106. agentinputlab/backends/llm/gpt_oss_final_channel.py +84 -0
  107. agentinputlab/backends/llm/openai_compatible.py +332 -0
  108. agentinputlab/backends/llm/transformers.py +171 -0
  109. agentinputlab/backends/retrieval/__init__.py +35 -0
  110. agentinputlab/backends/retrieval/base.py +50 -0
  111. agentinputlab/backends/retrieval/dense.py +777 -0
  112. agentinputlab/backends/retrieval/memory.py +119 -0
  113. agentinputlab/backends/retrieval/sqlite_fts.py +155 -0
  114. agentinputlab/backends/user/__init__.py +15 -0
  115. agentinputlab/backends/user/base.py +66 -0
  116. agentinputlab/backends/user/callable.py +54 -0
  117. agentinputlab/backends/user/replay.py +89 -0
  118. agentinputlab/backends/vector.py +38 -0
  119. agentinputlab/benchmarks/__init__.py +246 -0
  120. agentinputlab/benchmarks/acquisition.py +106 -0
  121. agentinputlab/benchmarks/ale.py +540 -0
  122. agentinputlab/benchmarks/appworld_ul.py +669 -0
  123. agentinputlab/benchmarks/assets.py +226 -0
  124. agentinputlab/benchmarks/base.py +68 -0
  125. agentinputlab/benchmarks/beir_archive.py +235 -0
  126. agentinputlab/benchmarks/beir_sample.py +269 -0
  127. agentinputlab/benchmarks/bfcl_native.py +245 -0
  128. agentinputlab/benchmarks/bfcl_v3.py +607 -0
  129. agentinputlab/benchmarks/cache.py +218 -0
  130. agentinputlab/benchmarks/clariq.py +203 -0
  131. agentinputlab/benchmarks/data/registry.json +321 -0
  132. agentinputlab/benchmarks/data/smoke_assets.json +511 -0
  133. agentinputlab/benchmarks/data/statebench_v0_8_1_task_ids.json +475 -0
  134. agentinputlab/benchmarks/data/toolsandbox_165848b_scenario_names.json +1 -0
  135. agentinputlab/benchmarks/execution.py +1111 -0
  136. agentinputlab/benchmarks/interactive.py +257 -0
  137. agentinputlab/benchmarks/ir_query.py +204 -0
  138. agentinputlab/benchmarks/longbench.py +203 -0
  139. agentinputlab/benchmarks/paired_replay.py +479 -0
  140. agentinputlab/benchmarks/preprocess.py +2313 -0
  141. agentinputlab/benchmarks/production.py +236 -0
  142. agentinputlab/benchmarks/qa.py +963 -0
  143. agentinputlab/benchmarks/registry.py +110 -0
  144. agentinputlab/benchmarks/retrieval.py +459 -0
  145. agentinputlab/benchmarks/runtime.py +509 -0
  146. agentinputlab/benchmarks/statebench.py +938 -0
  147. agentinputlab/benchmarks/tau3.py +725 -0
  148. agentinputlab/benchmarks/toolsandbox.py +626 -0
  149. agentinputlab/benchmarks/trec_dl_sample.py +263 -0
  150. agentinputlab/campaign.py +654 -0
  151. agentinputlab/campaign_runner.py +953 -0
  152. agentinputlab/cli/__init__.py +6 -0
  153. agentinputlab/cli/main.py +933 -0
  154. agentinputlab/connectors/__init__.py +46 -0
  155. agentinputlab/connectors/knowledge/__init__.py +4 -0
  156. agentinputlab/connectors/tools/__init__.py +30 -0
  157. agentinputlab/connectors/tools/base.py +57 -0
  158. agentinputlab/connectors/tools/mcp.py +222 -0
  159. agentinputlab/connectors/tools/memory.py +41 -0
  160. agentinputlab/connectors/tools/openapi.py +695 -0
  161. agentinputlab/connectors/tools/schema.py +102 -0
  162. agentinputlab/contracts/__init__.py +91 -0
  163. agentinputlab/contracts/availability.py +24 -0
  164. agentinputlab/contracts/dependency.py +58 -0
  165. agentinputlab/contracts/enums.py +82 -0
  166. agentinputlab/contracts/errors.py +63 -0
  167. agentinputlab/contracts/evidence.py +43 -0
  168. agentinputlab/contracts/intent.py +110 -0
  169. agentinputlab/contracts/lifecycle.py +164 -0
  170. agentinputlab/contracts/patch.py +167 -0
  171. agentinputlab/contracts/serialization.py +93 -0
  172. agentinputlab/contracts/state.py +127 -0
  173. agentinputlab/contracts/trace.py +59 -0
  174. agentinputlab/contracts/worker.py +42 -0
  175. agentinputlab/core/__init__.py +7 -0
  176. agentinputlab/data/__init__.py +32 -0
  177. agentinputlab/data/checksums.py +9 -0
  178. agentinputlab/data/downloader.py +235 -0
  179. agentinputlab/data/http.py +171 -0
  180. agentinputlab/data/index.py +21 -0
  181. agentinputlab/data/overlap.py +28 -0
  182. agentinputlab/data/preprocess.py +32 -0
  183. agentinputlab/data/storage.py +57 -0
  184. agentinputlab/data/trec_sample.py +427 -0
  185. agentinputlab/evaluation/__init__.py +5 -0
  186. agentinputlab/evaluation/outcomes.py +32 -0
  187. agentinputlab/experiments/__init__.py +278 -0
  188. agentinputlab/experiments/analysis.py +981 -0
  189. agentinputlab/experiments/artifacts.py +687 -0
  190. agentinputlab/experiments/automatic_measurement.py +678 -0
  191. agentinputlab/experiments/auxiliary_matrix.py +203 -0
  192. agentinputlab/experiments/bindings.py +430 -0
  193. agentinputlab/experiments/blueprints.py +147 -0
  194. agentinputlab/experiments/builders/__init__.py +45 -0
  195. agentinputlab/experiments/builders/executable_external_payload.py +423 -0
  196. agentinputlab/experiments/builders/external_process_arena.py +1018 -0
  197. agentinputlab/experiments/builders/registry_intervention.py +463 -0
  198. agentinputlab/experiments/cli.py +158 -0
  199. agentinputlab/experiments/controls.py +340 -0
  200. agentinputlab/experiments/driver_guard.py +205 -0
  201. agentinputlab/experiments/drivers/__init__.py +89 -0
  202. agentinputlab/experiments/drivers/external_arena.py +2908 -0
  203. agentinputlab/experiments/drivers/method_process.py +662 -0
  204. agentinputlab/experiments/drivers/parity_process.py +1484 -0
  205. agentinputlab/experiments/drivers/static_production.py +1574 -0
  206. agentinputlab/experiments/executor.py +448 -0
  207. agentinputlab/experiments/loader.py +605 -0
  208. agentinputlab/experiments/measurement.py +675 -0
  209. agentinputlab/experiments/paper_analysis.py +1818 -0
  210. agentinputlab/experiments/parity_identity.py +605 -0
  211. agentinputlab/experiments/plan.py +277 -0
  212. agentinputlab/experiments/production_builders.py +3739 -0
  213. agentinputlab/experiments/readiness.py +432 -0
  214. agentinputlab/experiments/schema.py +514 -0
  215. agentinputlab/experiments/secrets.py +177 -0
  216. agentinputlab/experiments/stateful_analysis.py +1738 -0
  217. agentinputlab/experiments/transfer_analysis.py +1316 -0
  218. agentinputlab/experiments/unseen_analysis.py +1025 -0
  219. agentinputlab/integrations/__init__.py +1 -0
  220. agentinputlab/integrations/action_space/__init__.py +1 -0
  221. agentinputlab/integrations/external_workers/__init__.py +76 -0
  222. agentinputlab/integrations/external_workers/ace.py +431 -0
  223. agentinputlab/integrations/external_workers/base.py +181 -0
  224. agentinputlab/integrations/external_workers/decomp_live.py +249 -0
  225. agentinputlab/integrations/external_workers/decomp_planner.py +30 -0
  226. agentinputlab/integrations/external_workers/infocqr_student.py +280 -0
  227. agentinputlab/integrations/external_workers/ircot.py +576 -0
  228. agentinputlab/integrations/external_workers/llmcompiler_live.py +360 -0
  229. agentinputlab/integrations/external_workers/longllmlingua.py +162 -0
  230. agentinputlab/integrations/external_workers/method.py +314 -0
  231. agentinputlab/integrations/external_workers/process.py +678 -0
  232. agentinputlab/integrations/external_workers/supervisor.py +1071 -0
  233. agentinputlab/integrations/full_architecture/__init__.py +1 -0
  234. agentinputlab/integrations/full_architecture/hyde.py +212 -0
  235. agentinputlab/integrations/full_architecture/plan_and_budget.py +188 -0
  236. agentinputlab/integrations/live_history.py +222 -0
  237. agentinputlab/integrations/prompt_optimization/__init__.py +1 -0
  238. agentinputlab/integrations/training/__init__.py +1 -0
  239. agentinputlab/metrics/__init__.py +50 -0
  240. agentinputlab/metrics/catalog.py +313 -0
  241. agentinputlab/metrics/harm.py +95 -0
  242. agentinputlab/metrics/paired.py +40 -0
  243. agentinputlab/metrics/qa.py +76 -0
  244. agentinputlab/metrics/text.py +33 -0
  245. agentinputlab/metrics/third_party.py +161 -0
  246. agentinputlab/models/__init__.py +4 -0
  247. agentinputlab/observability/__init__.py +56 -0
  248. agentinputlab/observability/budget.py +316 -0
  249. agentinputlab/observability/instrumentation.py +754 -0
  250. agentinputlab/observability/models.py +403 -0
  251. agentinputlab/observability/monitor.py +380 -0
  252. agentinputlab/optimizers/__init__.py +1 -0
  253. agentinputlab/optimizers/clarify/__init__.py +12 -0
  254. agentinputlab/optimizers/context/__init__.py +22 -0
  255. agentinputlab/optimizers/decompose/__init__.py +64 -0
  256. agentinputlab/optimizers/evidence/__init__.py +22 -0
  257. agentinputlab/optimizers/rewrite/__init__.py +30 -0
  258. agentinputlab/parity/__init__.py +5 -0
  259. agentinputlab/parity/base.py +206 -0
  260. agentinputlab/production_campaign.py +763 -0
  261. agentinputlab/py.typed +1 -0
  262. agentinputlab/recipes/__init__.py +333 -0
  263. agentinputlab/recipes/ace.py +418 -0
  264. agentinputlab/recipes/ace_bfcl.py +273 -0
  265. agentinputlab/recipes/ace_common_support.py +169 -0
  266. agentinputlab/recipes/ace_native_plan.py +322 -0
  267. agentinputlab/recipes/ace_online.py +711 -0
  268. agentinputlab/recipes/ace_retrieval.py +330 -0
  269. agentinputlab/recipes/ace_statebench.py +382 -0
  270. agentinputlab/recipes/ace_tau.py +463 -0
  271. agentinputlab/recipes/ace_toolsandbox.py +432 -0
  272. agentinputlab/recipes/acon_guideline.py +22 -0
  273. agentinputlab/recipes/adaptive_rag.py +822 -0
  274. agentinputlab/recipes/llmlingua2_inference.py +146 -0
  275. agentinputlab/recipes/llmlingua2_training.py +796 -0
  276. agentinputlab/recipes/mce.py +1486 -0
  277. agentinputlab/recipes/mce_final.py +335 -0
  278. agentinputlab/recipes/mce_text_fit.py +499 -0
  279. agentinputlab/recipes/mce_text_only.py +298 -0
  280. agentinputlab/recipes/qrag.py +729 -0
  281. agentinputlab/recipes/qrag_inference.py +364 -0
  282. agentinputlab/recipes/r2ag_features.py +236 -0
  283. agentinputlab/recipes/r2ag_inference.py +503 -0
  284. agentinputlab/recipes/r2ag_training.py +948 -0
  285. agentinputlab/recipes/recomp_abstractive.py +592 -0
  286. agentinputlab/recipes/recomp_extractive.py +525 -0
  287. agentinputlab/recipes/reformer.py +17 -0
  288. agentinputlab/recipes/rqrag.py +1516 -0
  289. agentinputlab/recipes/rqrag_common_support.py +193 -0
  290. agentinputlab/recipes/rqrag_completion.py +147 -0
  291. agentinputlab/recipes/skillopt.py +462 -0
  292. agentinputlab/recipes/skillopt_common_support.py +154 -0
  293. agentinputlab/recipes/skillopt_environment.py +165 -0
  294. agentinputlab/recipes/skillopt_environment_cli.py +5 -0
  295. agentinputlab/recipes/skillopt_retrieval.py +188 -0
  296. agentinputlab/recipes/smartsearch.py +897 -0
  297. agentinputlab/recipes/smartsearch_curriculum.py +283 -0
  298. agentinputlab/recipes/smartsearch_grpo_contracts.py +58 -0
  299. agentinputlab/recipes/smartsearch_grpo_data.py +314 -0
  300. agentinputlab/recipes/smartsearch_grpo_meter.py +324 -0
  301. agentinputlab/recipes/smartsearch_grpo_prefix.py +144 -0
  302. agentinputlab/recipes/smartsearch_grpo_rollout.py +119 -0
  303. agentinputlab/recipes/smartsearch_grpo_tools.py +364 -0
  304. agentinputlab/recipes/smartsearch_grpo_training.py +305 -0
  305. agentinputlab/recipes/smartsearch_grpo_transport.py +248 -0
  306. agentinputlab/recipes/smartsearch_grpo_worker.py +364 -0
  307. agentinputlab/recipes/smartsearch_inference.py +524 -0
  308. agentinputlab/recipes/smartsearch_native_data.py +172 -0
  309. agentinputlab/recipes/smartsearch_policy.py +616 -0
  310. agentinputlab/recipes/smartsearch_policy_worker.py +9 -0
  311. agentinputlab/recipes/smartsearch_sampling.py +232 -0
  312. agentinputlab/recipes/smartsearch_teacher.py +203 -0
  313. agentinputlab/recipes/smartsearch_training.py +265 -0
  314. agentinputlab/registry/__init__.py +46 -0
  315. agentinputlab/registry/beta.py +727 -0
  316. agentinputlab/registry/data/algorithms.json +1959 -0
  317. agentinputlab/registry/data/auxiliary_method_profiles.json +34 -0
  318. agentinputlab/registry/loader.py +100 -0
  319. agentinputlab/registry/result_manifest.py +184 -0
  320. agentinputlab/registry/runtime.py +195 -0
  321. agentinputlab/registry/schema.py +449 -0
  322. agentinputlab/runner/__init__.py +30 -0
  323. agentinputlab/runner/balance.py +248 -0
  324. agentinputlab/runner/cache.py +135 -0
  325. agentinputlab/runner/composite.py +130 -0
  326. agentinputlab/runner/engine.py +285 -0
  327. agentinputlab/runner/runtime_guard.py +268 -0
  328. agentinputlab/runner/worker.py +80 -0
  329. agentinputlab/runtime_bootstrap.py +288 -0
  330. agentinputlab/selectors/__init__.py +196 -0
  331. agentinputlab/selectors/advanced.py +1514 -0
  332. agentinputlab/selectors/artifacts.py +1087 -0
  333. agentinputlab/selectors/base.py +112 -0
  334. agentinputlab/selectors/campaigns.py +1893 -0
  335. agentinputlab/selectors/catalog.py +86 -0
  336. agentinputlab/selectors/discovery.py +1860 -0
  337. agentinputlab/selectors/evaluation.py +1348 -0
  338. agentinputlab/selectors/features.py +383 -0
  339. agentinputlab/selectors/learned.py +502 -0
  340. agentinputlab/selectors/no_op.py +28 -0
  341. agentinputlab/selectors/outcome_table.py +475 -0
  342. agentinputlab/selectors/producer.py +853 -0
  343. agentinputlab/selectors/rules.py +109 -0
  344. agentinputlab/selectors/runtime.py +420 -0
  345. agentinputlab/studies/__init__.py +16 -0
  346. agentinputlab/studies/design.py +165 -0
  347. agentinputlab/studies/paired.py +322 -0
  348. agentinputlab/studio/__init__.py +6 -0
  349. agentinputlab/studio/campaigns.py +819 -0
  350. agentinputlab/studio/engine.py +1408 -0
  351. agentinputlab/studio/model_backends.py +425 -0
  352. agentinputlab/studio/prepared.py +410 -0
  353. agentinputlab/studio/server.py +613 -0
  354. agentinputlab/studio/static/app.js +397 -0
  355. agentinputlab/studio/static/campaigns.html +175 -0
  356. agentinputlab/studio/static/campaigns.js +426 -0
  357. agentinputlab/studio/static/index.html +192 -0
  358. agentinputlab/studio/static/result.html +103 -0
  359. agentinputlab/studio/static/result.js +273 -0
  360. agentinputlab/studio/static/styles.css +467 -0
  361. agentinputlab-0.1.0a1.data/data/share/agentinputlab/CITATION.cff +22 -0
  362. agentinputlab-0.1.0a1.dist-info/METADATA +392 -0
  363. agentinputlab-0.1.0a1.dist-info/RECORD +469 -0
  364. agentinputlab-0.1.0a1.dist-info/WHEEL +5 -0
  365. agentinputlab-0.1.0a1.dist-info/entry_points.txt +6 -0
  366. agentinputlab-0.1.0a1.dist-info/licenses/LICENSE +21 -0
  367. agentinputlab-0.1.0a1.dist-info/licenses/NOTICE +31 -0
  368. agentinputlab-0.1.0a1.dist-info/licenses/THIRD_PARTY_NOTICES.md +94 -0
  369. agentinputlab-0.1.0a1.dist-info/top_level.txt +2 -0
  370. workers/README.md +94 -0
  371. workers/ace/README.md +261 -0
  372. workers/ace/__init__.py +1 -0
  373. workers/ace/compatibility_manifest.json +39 -0
  374. workers/ace/driver.py +1682 -0
  375. workers/acon/README.md +215 -0
  376. workers/acon/__init__.py +5 -0
  377. workers/acon/compatibility_manifest.json +93 -0
  378. workers/acon/driver.py +1859 -0
  379. workers/acon/fitted.py +395 -0
  380. workers/acon/guideline.py +470 -0
  381. workers/acon/guideline_source_manifest.json +20 -0
  382. workers/adaptive_rag/README.md +96 -0
  383. workers/adaptive_rag/__init__.py +15 -0
  384. workers/adaptive_rag/compatibility_manifest.json +61 -0
  385. workers/adaptive_rag/driver.py +1470 -0
  386. workers/adaptive_rag/fixture_runtime.py +163 -0
  387. workers/adaptive_rag/runtime.py +252 -0
  388. workers/ask_or_assume/README.md +124 -0
  389. workers/ask_or_assume/__init__.py +1 -0
  390. workers/ask_or_assume/compatibility_manifest.json +36 -0
  391. workers/ask_or_assume/driver.py +1227 -0
  392. workers/decomp/README.md +133 -0
  393. workers/decomp/UPSTREAM_LICENSE.Apache-2.0.txt +201 -0
  394. workers/decomp/__init__.py +5 -0
  395. workers/decomp/compatibility_manifest.json +205 -0
  396. workers/decomp/driver.py +1015 -0
  397. workers/decomp/live.py +137 -0
  398. workers/decomp/runtime.py +231 -0
  399. workers/infocqr/README.md +106 -0
  400. workers/infocqr/__init__.py +1 -0
  401. workers/infocqr/compatibility_manifest.json +84 -0
  402. workers/infocqr/driver.py +1766 -0
  403. workers/ircot/README.md +167 -0
  404. workers/ircot/__init__.py +7 -0
  405. workers/ircot/compatibility_manifest.json +121 -0
  406. workers/ircot/controlled.py +457 -0
  407. workers/ircot/driver.py +1373 -0
  408. workers/ircot/fixture_bindings.json +39 -0
  409. workers/ircot/fixture_config.json +48 -0
  410. workers/ircot/fixture_prompt.txt +2 -0
  411. workers/ircot/native_qa.py +398 -0
  412. workers/ircot/qa_compatibility_manifest.json +57 -0
  413. workers/ircot/runtime.py +97 -0
  414. workers/llmcompiler/README.md +160 -0
  415. workers/llmcompiler/__init__.py +1 -0
  416. workers/llmcompiler/compatibility_manifest.json +45 -0
  417. workers/llmcompiler/driver.py +1514 -0
  418. workers/llmcompiler/export_prompts.py +74 -0
  419. workers/llmcompiler/live.py +174 -0
  420. workers/llmcompiler/patch_manifest.json +147 -0
  421. workers/mce/README.md +198 -0
  422. workers/mce/__init__.py +29 -0
  423. workers/mce/compatibility_manifest.json +115 -0
  424. workers/mce/driver.py +2585 -0
  425. workers/mce/final_eval.py +173 -0
  426. workers/official_arenas/README.md +25 -0
  427. workers/official_arenas/__init__.py +1 -0
  428. workers/official_arenas/capture_records.py +110 -0
  429. workers/official_arenas/driver.py +619 -0
  430. workers/official_arenas/protocol.py +334 -0
  431. workers/official_arenas/providers/__init__.py +1 -0
  432. workers/official_arenas/providers/_live_history.py +228 -0
  433. workers/official_arenas/providers/_message_compat.py +77 -0
  434. workers/official_arenas/providers/appworld_ul.py +196 -0
  435. workers/official_arenas/providers/fixture.py +112 -0
  436. workers/official_arenas/providers/statebench.py +960 -0
  437. workers/official_arenas/providers/tau3.py +1672 -0
  438. workers/official_arenas/providers/tau_retail.py +586 -0
  439. workers/official_arenas/providers/toolsandbox.py +1321 -0
  440. workers/official_arenas/providers/tooltalk.py +699 -0
  441. workers/official_arenas/retail_capture.py +188 -0
  442. workers/official_arenas/retail_driver.py +275 -0
  443. workers/qrag/README.md +172 -0
  444. workers/qrag/__init__.py +1 -0
  445. workers/qrag/compatibility_manifest.json +64 -0
  446. workers/qrag/driver.py +673 -0
  447. workers/r2ag/README.md +154 -0
  448. workers/r2ag/__init__.py +5 -0
  449. workers/r2ag/compatibility_manifest.json +55 -0
  450. workers/r2ag/driver.py +1287 -0
  451. workers/r2ag/feature_schema.json +8 -0
  452. workers/r2ag/runtime.py +589 -0
  453. workers/recomp/README.md +120 -0
  454. workers/recomp/__init__.py +1 -0
  455. workers/recomp/compatibility_manifest.json +43 -0
  456. workers/recomp/driver.py +1653 -0
  457. workers/reformer/README.md +125 -0
  458. workers/reformer/__init__.py +1 -0
  459. workers/reformer/compatibility_manifest.json +68 -0
  460. workers/reformer/driver.py +1459 -0
  461. workers/reformer/induction.py +457 -0
  462. workers/rrr/README.md +126 -0
  463. workers/rrr/__init__.py +1 -0
  464. workers/rrr/compatibility_manifest.json +57 -0
  465. workers/rrr/driver.py +1133 -0
  466. workers/smartsearch/README.md +331 -0
  467. workers/smartsearch/__init__.py +1 -0
  468. workers/smartsearch/compatibility_manifest.json +41 -0
  469. workers/smartsearch/driver.py +1643 -0
@@ -0,0 +1,1893 @@
1
+ """Frozen selector-study manifests and full-information policy analysis.
2
+
3
+ The campaign layer is deliberately execution neutral. It binds preregistered
4
+ selection rules, frozen policy artifacts, evaluation support, and diagnostic
5
+ roles without calling a model or benchmark. Real outcomes enter only through
6
+ an explicitly verified, non-synthetic result artifact.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import json
13
+ import math
14
+ import random
15
+ import re
16
+ from collections import defaultdict
17
+ from collections.abc import Mapping, Sequence
18
+ from pathlib import Path
19
+ from statistics import fmean
20
+ from typing import Any
21
+
22
+ from agentinputlab.contracts.enums import SemanticFamily
23
+ from agentinputlab.contracts.errors import ArtifactError, ValidationError
24
+ from agentinputlab.contracts.serialization import content_hash, freeze_mapping
25
+
26
+ _SHA256 = re.compile(r"^[0-9a-f]{64}$")
27
+ _IDENTIFIER = re.compile(r"^[a-z0-9][a-z0-9_.:-]*$")
28
+ _GROUP_ID = re.compile(r"^group_[0-9a-f]{64}$")
29
+ _CORE_FAMILIES = (
30
+ SemanticFamily.REFORMULATE,
31
+ SemanticFamily.DECOMPOSE,
32
+ SemanticFamily.ACQUIRE,
33
+ SemanticFamily.CLARIFY,
34
+ SemanticFamily.CURATE,
35
+ )
36
+ _REPRESENTATIVE_ARTIFACT = "agentinputlab.selector_representative_manifest"
37
+ _CAMPAIGN_ARTIFACT = "agentinputlab.selector_campaign_manifest"
38
+ _RESULT_ARTIFACT = "agentinputlab.selector_campaign_results"
39
+ _LOSO_ARTIFACT = "agentinputlab.selector_loso_manifest"
40
+ _DISCOVERY_SUMMARY_ARTIFACT = "agentinputlab.selector_discovery_summary"
41
+ _RULE_ARTIFACT = "agentinputlab.selector_pareto_rule"
42
+ _DESIGN_ARTIFACT = "agentinputlab.selector_campaign_design"
43
+ _BINDINGS_ARTIFACT = "agentinputlab.selector_campaign_bindings"
44
+ _ABLATION_BINDINGS_ARTIFACT = "agentinputlab.selector_ablation_bindings"
45
+ _ABLATION_MATRIX_ARTIFACT = "agentinputlab.selector_ablation_matrix"
46
+ _LOSO_DESIGN_ARTIFACT = "agentinputlab.selector_loso_design"
47
+
48
+
49
+ def freeze_pareto_representatives(
50
+ summary: Mapping[str, Any],
51
+ rule: Mapping[str, Any],
52
+ *,
53
+ source_file_sha256: str | None = None,
54
+ ) -> Mapping[str, Any]:
55
+ """Select two deterministic representatives per family from verified discovery.
56
+
57
+ Candidates are first filtered by the frozen support/safety rule, then
58
+ ordered by successive Pareto fronts over benefit (higher), hard harm
59
+ (lower), and normalized cost (lower). The preregistered utility score and
60
+ a stable release-ID tie break order candidates within a front.
61
+ """
62
+
63
+ parsed_summary = _validated_discovery_summary(summary)
64
+ parsed_rule = _validated_pareto_rule(rule)
65
+ if source_file_sha256 is not None:
66
+ _require_sha256(source_file_sha256, label="discovery summary file SHA-256")
67
+ candidates = parsed_summary["candidates"]
68
+ by_family: dict[SemanticFamily, list[dict[str, Any]]] = defaultdict(list)
69
+ for candidate in candidates:
70
+ by_family[candidate["family"]].append(candidate)
71
+
72
+ selected_rows: list[dict[str, Any]] = []
73
+ rejected_rows: list[dict[str, Any]] = []
74
+ count = parsed_rule["representatives_per_family"]
75
+ for family in _CORE_FAMILIES:
76
+ family_rows = by_family.get(family, [])
77
+ if not family_rows:
78
+ raise ValidationError(f"discovery summary has no candidates for {family.value}")
79
+ eligible: list[dict[str, Any]] = []
80
+ for candidate in family_rows:
81
+ reasons: list[str] = []
82
+ if candidate["independent_groups"] < parsed_rule["minimum_independent_groups"]:
83
+ reasons.append("insufficient_independent_groups")
84
+ if candidate["support_fraction"] < parsed_rule["minimum_support_fraction"]:
85
+ reasons.append("insufficient_support")
86
+ if candidate["hard_harm_rate"] > parsed_rule["maximum_hard_harm_rate"]:
87
+ reasons.append("hard_harm_gate")
88
+ if candidate["mean_valid_success_gain"] < parsed_rule["minimum_valid_success_gain"]:
89
+ reasons.append("minimum_gain_gate")
90
+ if reasons:
91
+ rejected_rows.append(
92
+ {
93
+ "family": family.value,
94
+ "release_id": candidate["release_id"],
95
+ "reason_codes": sorted(reasons),
96
+ }
97
+ )
98
+ else:
99
+ eligible.append(candidate)
100
+ if len(eligible) < count:
101
+ raise ValidationError(
102
+ f"Pareto freeze requires at least {count} eligible candidates for "
103
+ f"{family.value}; found {len(eligible)}"
104
+ )
105
+ ranked = _pareto_ranked(eligible, parsed_rule)
106
+ for rank, row in enumerate(ranked[:count], start=1):
107
+ selected_rows.append(
108
+ {
109
+ "family": family.value,
110
+ "rank": rank,
111
+ "release_id": row["release_id"],
112
+ "pareto_layer": row["pareto_layer"],
113
+ "utility_score": row["utility_score"],
114
+ "mean_valid_success_gain": row["mean_valid_success_gain"],
115
+ "hard_harm_rate": row["hard_harm_rate"],
116
+ "normalized_cost": row["normalized_cost"],
117
+ "independent_groups": row["independent_groups"],
118
+ "support_fraction": row["support_fraction"],
119
+ "source_run_identity_hash": row["source_run_identity_hash"],
120
+ }
121
+ )
122
+
123
+ semantic_summary_hash = content_hash(_summary_for_hash(parsed_summary))
124
+ base = {
125
+ "schema_version": 1,
126
+ "artifact": _REPRESENTATIVE_ARTIFACT,
127
+ "stage": "frozen",
128
+ "selection_scope": "two_per_core_family",
129
+ "source_summary": {
130
+ "revision": parsed_summary["revision"],
131
+ "semantic_sha256": semantic_summary_hash,
132
+ "file_sha256": source_file_sha256,
133
+ "profile_kind": "controlled_adapter",
134
+ "source_run_identity_hashes": sorted(
135
+ item["run_identity_hash"] for item in parsed_summary["source_runs"]
136
+ ),
137
+ },
138
+ "rule": {
139
+ **{key: value for key, value in parsed_rule.items() if key != "rule_hash"},
140
+ "rule_hash": parsed_rule["rule_hash"],
141
+ },
142
+ "selections": selected_rows,
143
+ "rejections": sorted(
144
+ rejected_rows,
145
+ key=lambda item: (item["family"], item["release_id"]),
146
+ ),
147
+ "experiments_executed": False,
148
+ }
149
+ return freeze_mapping({**base, "manifest_hash": content_hash(base)})
150
+
151
+
152
+ def validate_representative_manifest(value: Mapping[str, Any]) -> Mapping[str, Any]:
153
+ """Validate and freeze one representative-selection artifact."""
154
+
155
+ data = _strict_mapping(
156
+ value,
157
+ label="representative manifest",
158
+ keys={
159
+ "schema_version",
160
+ "artifact",
161
+ "stage",
162
+ "selection_scope",
163
+ "source_summary",
164
+ "rule",
165
+ "selections",
166
+ "rejections",
167
+ "experiments_executed",
168
+ "manifest_hash",
169
+ },
170
+ )
171
+ if (
172
+ data["schema_version"] != 1
173
+ or data["artifact"] != _REPRESENTATIVE_ARTIFACT
174
+ or data["stage"] != "frozen"
175
+ or data["selection_scope"] != "two_per_core_family"
176
+ or data["experiments_executed"] is not False
177
+ ):
178
+ raise ValidationError("representative manifest identity or stage is invalid")
179
+ expected_hash = data["manifest_hash"]
180
+ _require_sha256(expected_hash, label="representative manifest hash")
181
+ if content_hash({key: item for key, item in data.items() if key != "manifest_hash"}) != (
182
+ expected_hash
183
+ ):
184
+ raise ValidationError("representative manifest hash differs from its content")
185
+ source = _strict_mapping(
186
+ data["source_summary"],
187
+ label="representative source summary",
188
+ keys={
189
+ "revision",
190
+ "semantic_sha256",
191
+ "file_sha256",
192
+ "profile_kind",
193
+ "source_run_identity_hashes",
194
+ },
195
+ )
196
+ _require_text(source["revision"], label="representative source revision")
197
+ _require_sha256(source["semantic_sha256"], label="representative source semantic hash")
198
+ if source["file_sha256"] is not None:
199
+ _require_sha256(source["file_sha256"], label="representative source file hash")
200
+ if source["profile_kind"] != "controlled_adapter":
201
+ raise ValidationError("selector representatives require controlled discovery outcomes")
202
+ identities = _string_sequence(
203
+ source["source_run_identity_hashes"],
204
+ label="representative source run identities",
205
+ )
206
+ if not identities or identities != tuple(sorted(set(identities))):
207
+ raise ValidationError("representative source run identities must be sorted unique")
208
+ for identity in identities:
209
+ _require_sha256(identity, label="representative source run identity")
210
+ rule = _strict_mapping(
211
+ data["rule"],
212
+ label="representative rule",
213
+ keys={
214
+ "schema_version",
215
+ "artifact",
216
+ "stage",
217
+ "representatives_per_family",
218
+ "minimum_independent_groups",
219
+ "minimum_support_fraction",
220
+ "maximum_hard_harm_rate",
221
+ "minimum_valid_success_gain",
222
+ "benefit_weight",
223
+ "harm_penalty",
224
+ "cost_penalty",
225
+ "tie_break",
226
+ "rule_hash",
227
+ },
228
+ )
229
+ _validated_pareto_rule({key: item for key, item in rule.items() if key != "rule_hash"})
230
+ _require_sha256(rule["rule_hash"], label="representative rule hash")
231
+ if (
232
+ content_hash({key: item for key, item in rule.items() if key != "rule_hash"})
233
+ != rule["rule_hash"]
234
+ ):
235
+ raise ValidationError("representative rule hash differs from its content")
236
+ selections = _sequence(data["selections"], label="representative selections")
237
+ expected_pairs = {(family.value, rank) for family in _CORE_FAMILIES for rank in (1, 2)}
238
+ observed_pairs: set[tuple[str, int]] = set()
239
+ releases: set[str] = set()
240
+ for index, raw in enumerate(selections):
241
+ row = _strict_mapping(
242
+ raw,
243
+ label=f"representative selection {index}",
244
+ keys={
245
+ "family",
246
+ "rank",
247
+ "release_id",
248
+ "pareto_layer",
249
+ "utility_score",
250
+ "mean_valid_success_gain",
251
+ "hard_harm_rate",
252
+ "normalized_cost",
253
+ "independent_groups",
254
+ "support_fraction",
255
+ "source_run_identity_hash",
256
+ },
257
+ )
258
+ family = _core_family(row["family"], label=f"selection {index} family")
259
+ rank = _positive_integer(row["rank"], label=f"selection {index} rank")
260
+ observed_pairs.add((family.value, rank))
261
+ release_id = _identifier(row["release_id"], label=f"selection {index} release")
262
+ if release_id in releases:
263
+ raise ValidationError("representative releases must be unique across families")
264
+ releases.add(release_id)
265
+ _nonnegative_integer(row["pareto_layer"], label=f"selection {index} Pareto layer")
266
+ _finite(row["utility_score"], label=f"selection {index} utility score")
267
+ _bounded(row["mean_valid_success_gain"], -1.0, 1.0, label="selection gain")
268
+ _bounded(row["hard_harm_rate"], 0.0, 1.0, label="selection hard harm")
269
+ _bounded(row["normalized_cost"], 0.0, 1.0, label="selection normalized cost")
270
+ _positive_integer(row["independent_groups"], label="selection independent groups")
271
+ _bounded(row["support_fraction"], 0.0, 1.0, label="selection support")
272
+ _require_sha256(
273
+ row["source_run_identity_hash"],
274
+ label="selection source run identity",
275
+ )
276
+ if row["source_run_identity_hash"] not in identities:
277
+ raise ValidationError(
278
+ "representative selection source is absent from the source summary"
279
+ )
280
+ if observed_pairs != expected_pairs or len(selections) != 10:
281
+ raise ValidationError("representative manifest requires exact ranks 1 and 2 per family")
282
+ _sequence(data["rejections"], label="representative rejections")
283
+ return freeze_mapping(data)
284
+
285
+
286
+ def build_selector_baseline_campaign(
287
+ representatives: Mapping[str, Any],
288
+ bindings: Mapping[str, Any],
289
+ design: Mapping[str, Any],
290
+ ) -> Mapping[str, Any]:
291
+ """Build the frozen multi-policy baseline campaign."""
292
+
293
+ reps = validate_representative_manifest(representatives)
294
+ parsed_bindings = _validated_campaign_bindings(bindings)
295
+ parsed_design = _validated_campaign_design(design)
296
+ if parsed_bindings["representative_manifest_hash"] != reps["manifest_hash"]:
297
+ raise ValidationError("selector campaign bindings differ from the representative manifest")
298
+ selected = _selected_releases(reps)
299
+ best = parsed_bindings["best_fixed_global"]
300
+ if best["selected_release_id"] != selected[best["selected_family"]][0]:
301
+ raise ValidationError("best-fixed release is not the rank-1 selector representative")
302
+
303
+ policies: list[dict[str, Any]] = [
304
+ _policy(
305
+ "no_op",
306
+ kind="no_op",
307
+ role="fixed_baseline",
308
+ formal_inference=True,
309
+ diagnostic_only=False,
310
+ parameters={"release_id": "baseline.no_op"},
311
+ ),
312
+ _policy(
313
+ "random_eligible",
314
+ kind="random_eligible",
315
+ role="frequency_control",
316
+ formal_inference=True,
317
+ diagnostic_only=False,
318
+ parameters={"random_seed": parsed_design["random_seed"]},
319
+ ),
320
+ ]
321
+ for family in _CORE_FAMILIES:
322
+ policies.append(
323
+ _policy(
324
+ f"fixed_{family.value}",
325
+ kind="fixed_family",
326
+ role="family_fixed_baseline",
327
+ formal_inference=True,
328
+ diagnostic_only=False,
329
+ parameters={
330
+ "family": family.value,
331
+ "release_id": selected[family][0],
332
+ "representative_rank": 1,
333
+ },
334
+ )
335
+ )
336
+ policies.extend(
337
+ (
338
+ _policy(
339
+ "best_fixed_global",
340
+ kind="best_fixed_global",
341
+ role="calibration_frozen_baseline",
342
+ formal_inference=True,
343
+ diagnostic_only=False,
344
+ parameters={
345
+ "selected_family": best["selected_family"].value,
346
+ "selected_release_id": best["selected_release_id"],
347
+ "policy_manifest_sha256": best["policy_manifest_sha256"],
348
+ },
349
+ ),
350
+ _artifact_policy(
351
+ "defect_rule",
352
+ parsed_bindings["selectors"]["defect_rule"],
353
+ role="interpretable_baseline",
354
+ formal_inference=True,
355
+ ),
356
+ _artifact_policy(
357
+ "zero_shot_router",
358
+ parsed_bindings["selectors"]["zero_shot_router"],
359
+ role="generic_router_comparator",
360
+ formal_inference=True,
361
+ ),
362
+ _artifact_policy(
363
+ "penalized_t_learner",
364
+ parsed_bindings["selectors"]["penalized_t_learner"],
365
+ role="confirmatory_learned_policy",
366
+ formal_inference=True,
367
+ ),
368
+ _artifact_policy(
369
+ "gbdt_t_learner",
370
+ parsed_bindings["selectors"]["gbdt_t_learner"],
371
+ role="exploratory_nonlinear_policy",
372
+ formal_inference=False,
373
+ ),
374
+ _artifact_policy(
375
+ "eligibility_aware_selector",
376
+ parsed_bindings["selectors"]["eligibility_aware_selector"],
377
+ role="locked_primary_selector",
378
+ formal_inference=True,
379
+ ),
380
+ _policy(
381
+ "observed_action_oracle",
382
+ kind="observed_action_oracle",
383
+ role="descriptive_upper_bound",
384
+ formal_inference=False,
385
+ diagnostic_only=True,
386
+ parameters={
387
+ "outcome_access": "post_outcome_only",
388
+ "may_select_or_train": False,
389
+ },
390
+ ),
391
+ )
392
+ )
393
+ metadata = {
394
+ "suite_ids": list(parsed_design["suite_ids"]),
395
+ "required_independent_groups": parsed_design["required_independent_groups"],
396
+ "minimum_common_support_groups": parsed_design["minimum_common_support_groups"],
397
+ "random_seed": parsed_design["random_seed"],
398
+ "selector_representative_rank": parsed_bindings["representative_rank"],
399
+ "oracle_policy_id": "observed_action_oracle",
400
+ "oracle_diagnostic_only": True,
401
+ "fit_or_calibrate_allowed": False,
402
+ "preflight_first": True,
403
+ }
404
+ return _campaign(
405
+ campaign_id=parsed_design["campaign_id"],
406
+ campaign_kind="baseline",
407
+ primary_metric=parsed_design["primary_metric"],
408
+ evaluation_split=parsed_design["evaluation_split"],
409
+ representative_manifest_hash=reps["manifest_hash"],
410
+ policies=policies,
411
+ metadata=metadata,
412
+ )
413
+
414
+
415
+ def build_selector_ablation_campaign(
416
+ baseline_campaign: Mapping[str, Any],
417
+ bindings: Mapping[str, Any],
418
+ matrix: Mapping[str, Any],
419
+ *,
420
+ campaign_id: str,
421
+ ) -> Mapping[str, Any]:
422
+ """Build refit-required feature and guardrail ablations."""
423
+
424
+ baseline = validate_selector_campaign_manifest(baseline_campaign)
425
+ if baseline["campaign_kind"] != "baseline":
426
+ raise ValidationError("selector ablations require a baseline campaign")
427
+ _identifier(campaign_id, label="selector ablation campaign ID")
428
+ parsed = _validated_ablation_bindings(bindings)
429
+ if parsed["baseline_campaign_hash"] != baseline["campaign_hash"]:
430
+ raise ValidationError("selector ablation bindings differ from the baseline campaign")
431
+ entries = _validated_ablation_matrix(matrix)
432
+ policies: list[dict[str, Any]] = []
433
+ no_op = next(item for item in baseline["policies"] if item["policy_id"] == "no_op")
434
+ policies.append(dict(no_op))
435
+ primary = next(
436
+ item for item in baseline["policies"] if item["policy_id"] == "eligibility_aware_selector"
437
+ )
438
+ policies.append(
439
+ {
440
+ **dict(primary),
441
+ "policy_id": "full_selector",
442
+ "role": "ablation_reference",
443
+ "formal_inference": False,
444
+ }
445
+ )
446
+ unsafe = {entry["policy_id"] for entry in entries if entry["diagnostic_only"]}
447
+ for entry in entries:
448
+ policy_id = entry["policy_id"]
449
+ artifact = parsed["artifacts"][policy_id]
450
+ policies.append(
451
+ _policy(
452
+ policy_id,
453
+ kind="frozen_ablation",
454
+ role="prespecified_ablation",
455
+ formal_inference=False,
456
+ diagnostic_only=entry["diagnostic_only"],
457
+ parameters={
458
+ "changed_component": entry["changed_component"],
459
+ "requires_independent_refit": entry["requires_independent_refit"],
460
+ "artifact_binding": artifact,
461
+ },
462
+ )
463
+ )
464
+ metadata = {
465
+ **dict(baseline["metadata"]),
466
+ "baseline_campaign_hash": baseline["campaign_hash"],
467
+ "unsafe_ablation_policy_ids": sorted(unsafe),
468
+ "ablation_results_are_secondary": True,
469
+ "fit_or_calibrate_allowed_during_evaluation": False,
470
+ }
471
+ return _campaign(
472
+ campaign_id=campaign_id,
473
+ campaign_kind="ablation",
474
+ primary_metric=baseline["primary_metric"],
475
+ evaluation_split=baseline["evaluation_split"],
476
+ representative_manifest_hash=baseline["representative_manifest_hash"],
477
+ policies=policies,
478
+ metadata=metadata,
479
+ )
480
+
481
+
482
+ def build_selector_loso_manifest(design: Mapping[str, Any]) -> Mapping[str, Any]:
483
+ """Generate leave-one-suite-out refit/freeze instructions."""
484
+
485
+ data = _strict_mapping(
486
+ design,
487
+ label="selector LOSO design",
488
+ keys={
489
+ "schema_version",
490
+ "artifact",
491
+ "stage",
492
+ "campaign_id",
493
+ "suite_ids",
494
+ "selector_kind",
495
+ "fit_config_sha256",
496
+ "calibration_config_sha256",
497
+ "representative_manifest_hash",
498
+ "revision_prefix",
499
+ "minimum_train_suites",
500
+ },
501
+ )
502
+ if (
503
+ data["schema_version"] != 1
504
+ or data["artifact"] != _LOSO_DESIGN_ARTIFACT
505
+ or data["stage"] != "frozen"
506
+ ):
507
+ raise ValidationError("selector LOSO design identity or stage is invalid")
508
+ campaign_id = _identifier(data["campaign_id"], label="selector LOSO campaign ID")
509
+ suites = _identifier_sequence(data["suite_ids"], label="selector LOSO suites")
510
+ minimum = _positive_integer(
511
+ data["minimum_train_suites"],
512
+ label="selector LOSO minimum train suites",
513
+ )
514
+ if len(suites) < minimum + 1:
515
+ raise ValidationError("selector LOSO design has too few suites for its training floor")
516
+ selector_kind = _identifier(data["selector_kind"], label="selector LOSO kind")
517
+ for label in (
518
+ "fit_config_sha256",
519
+ "calibration_config_sha256",
520
+ "representative_manifest_hash",
521
+ ):
522
+ _require_sha256(data[label], label=f"selector LOSO {label}")
523
+ prefix = _identifier(data["revision_prefix"], label="selector LOSO revision prefix")
524
+ folds = []
525
+ for held_out in suites:
526
+ training = tuple(item for item in suites if item != held_out)
527
+ folds.append(
528
+ {
529
+ "fold_id": f"holdout.{held_out}",
530
+ "held_out_suite": held_out,
531
+ "training_suites": list(training),
532
+ "calibration_source": "training_suites_group_disjoint",
533
+ "evaluation_split": "untouched_held_out_suite",
534
+ "selector_kind": selector_kind,
535
+ "fit_config_sha256": data["fit_config_sha256"],
536
+ "calibration_config_sha256": data["calibration_config_sha256"],
537
+ "output_revision": f"{prefix}.{held_out}",
538
+ "requires_fresh_fit": True,
539
+ "test_outcomes_visible_during_fit": False,
540
+ "test_outcomes_visible_during_calibration": False,
541
+ }
542
+ )
543
+ base = {
544
+ "schema_version": 1,
545
+ "artifact": _LOSO_ARTIFACT,
546
+ "stage": "frozen",
547
+ "campaign_id": campaign_id,
548
+ "representative_manifest_hash": data["representative_manifest_hash"],
549
+ "minimum_train_suites": minimum,
550
+ "folds": folds,
551
+ "preflight_first": True,
552
+ "experiments_executed": False,
553
+ }
554
+ return freeze_mapping({**base, "manifest_hash": content_hash(base)})
555
+
556
+
557
+ def validate_selector_loso_manifest(value: Mapping[str, Any]) -> Mapping[str, Any]:
558
+ """Validate a generated LOSO artifact and its disjoint folds."""
559
+
560
+ data = _strict_mapping(
561
+ value,
562
+ label="selector LOSO manifest",
563
+ keys={
564
+ "schema_version",
565
+ "artifact",
566
+ "stage",
567
+ "campaign_id",
568
+ "representative_manifest_hash",
569
+ "minimum_train_suites",
570
+ "folds",
571
+ "preflight_first",
572
+ "experiments_executed",
573
+ "manifest_hash",
574
+ },
575
+ )
576
+ if (
577
+ data["schema_version"] != 1
578
+ or data["artifact"] != _LOSO_ARTIFACT
579
+ or data["stage"] != "frozen"
580
+ or data["preflight_first"] is not True
581
+ or data["experiments_executed"] is not False
582
+ ):
583
+ raise ValidationError("selector LOSO manifest identity or stage is invalid")
584
+ _identifier(data["campaign_id"], label="selector LOSO campaign ID")
585
+ _require_sha256(
586
+ data["representative_manifest_hash"],
587
+ label="selector LOSO representative hash",
588
+ )
589
+ minimum = _positive_integer(
590
+ data["minimum_train_suites"],
591
+ label="selector LOSO minimum train suites",
592
+ )
593
+ folds = _sequence(data["folds"], label="selector LOSO folds")
594
+ if len(folds) < minimum + 1:
595
+ raise ValidationError("selector LOSO manifest has too few folds")
596
+ held_out: set[str] = set()
597
+ all_suites: set[str] = set()
598
+ for index, raw in enumerate(folds):
599
+ fold = _strict_mapping(
600
+ raw,
601
+ label=f"selector LOSO fold {index}",
602
+ keys={
603
+ "fold_id",
604
+ "held_out_suite",
605
+ "training_suites",
606
+ "calibration_source",
607
+ "evaluation_split",
608
+ "selector_kind",
609
+ "fit_config_sha256",
610
+ "calibration_config_sha256",
611
+ "output_revision",
612
+ "requires_fresh_fit",
613
+ "test_outcomes_visible_during_fit",
614
+ "test_outcomes_visible_during_calibration",
615
+ },
616
+ )
617
+ _identifier(fold["fold_id"], label=f"selector LOSO fold {index} ID")
618
+ held = _identifier(fold["held_out_suite"], label=f"selector LOSO fold {index} holdout")
619
+ training = set(
620
+ _identifier_sequence(
621
+ fold["training_suites"],
622
+ label=f"selector LOSO fold {index} training suites",
623
+ )
624
+ )
625
+ if held in training or len(training) < minimum:
626
+ raise ValidationError("selector LOSO fold violates its suite separation")
627
+ if held in held_out:
628
+ raise ValidationError("selector LOSO holdout suites must be unique")
629
+ held_out.add(held)
630
+ all_suites.update(training)
631
+ all_suites.add(held)
632
+ if (
633
+ fold["calibration_source"] != "training_suites_group_disjoint"
634
+ or fold["evaluation_split"] != "untouched_held_out_suite"
635
+ or fold["requires_fresh_fit"] is not True
636
+ or fold["test_outcomes_visible_during_fit"] is not False
637
+ or fold["test_outcomes_visible_during_calibration"] is not False
638
+ ):
639
+ raise ValidationError("selector LOSO fold permits held-out leakage")
640
+ _identifier(fold["selector_kind"], label="selector LOSO selector kind")
641
+ _identifier(fold["output_revision"], label="selector LOSO output revision")
642
+ _require_sha256(fold["fit_config_sha256"], label="selector LOSO fit config hash")
643
+ _require_sha256(
644
+ fold["calibration_config_sha256"],
645
+ label="selector LOSO calibration config hash",
646
+ )
647
+ if held_out != all_suites:
648
+ raise ValidationError("selector LOSO folds do not hold out every declared suite")
649
+ _require_sha256(data["manifest_hash"], label="selector LOSO manifest hash")
650
+ if (
651
+ content_hash({key: item for key, item in data.items() if key != "manifest_hash"})
652
+ != data["manifest_hash"]
653
+ ):
654
+ raise ValidationError("selector LOSO manifest hash differs from its content")
655
+ return freeze_mapping(data)
656
+
657
+
658
+ def validate_selector_campaign_manifest(value: Mapping[str, Any]) -> Mapping[str, Any]:
659
+ """Validate a frozen baseline or ablation campaign."""
660
+
661
+ data = _strict_mapping(
662
+ value,
663
+ label="selector campaign manifest",
664
+ keys={
665
+ "schema_version",
666
+ "artifact",
667
+ "stage",
668
+ "campaign_id",
669
+ "campaign_kind",
670
+ "primary_metric",
671
+ "evaluation_split",
672
+ "representative_manifest_hash",
673
+ "policies",
674
+ "metadata",
675
+ "experiments_executed",
676
+ "campaign_hash",
677
+ },
678
+ )
679
+ if (
680
+ data["schema_version"] != 1
681
+ or data["artifact"] != _CAMPAIGN_ARTIFACT
682
+ or data["stage"] != "frozen"
683
+ or data["campaign_kind"] not in {"baseline", "ablation"}
684
+ or data["experiments_executed"] is not False
685
+ ):
686
+ raise ValidationError("selector campaign identity or stage is invalid")
687
+ _identifier(data["campaign_id"], label="selector campaign ID")
688
+ _identifier(data["primary_metric"], label="selector campaign primary metric")
689
+ _identifier(data["evaluation_split"], label="selector campaign evaluation split")
690
+ _require_sha256(
691
+ data["representative_manifest_hash"],
692
+ label="selector campaign representative hash",
693
+ )
694
+ policies = _sequence(data["policies"], label="selector campaign policies")
695
+ if len(policies) < 3:
696
+ raise ValidationError("selector campaign requires at least three policies")
697
+ policy_ids: set[str] = set()
698
+ oracle_count = 0
699
+ no_op_count = 0
700
+ for index, raw in enumerate(policies):
701
+ policy = _validated_policy(raw, label=f"selector campaign policy {index}")
702
+ if policy["policy_id"] in policy_ids:
703
+ raise ValidationError("selector campaign policy IDs must be unique")
704
+ policy_ids.add(policy["policy_id"])
705
+ no_op_count += policy["policy_id"] == "no_op"
706
+ if policy["kind"] == "observed_action_oracle":
707
+ oracle_count += 1
708
+ if (
709
+ policy["diagnostic_only"] is not True
710
+ or policy["formal_inference"] is not False
711
+ or policy["parameters"].get("outcome_access") != "post_outcome_only"
712
+ ):
713
+ raise ValidationError("observed-action oracle must remain diagnostic-only")
714
+ if no_op_count != 1:
715
+ raise ValidationError("selector campaign requires exactly one NO_OP policy")
716
+ if data["campaign_kind"] == "baseline" and oracle_count != 1:
717
+ raise ValidationError("baseline campaign requires one diagnostic observed-action oracle")
718
+ if data["campaign_kind"] == "ablation" and oracle_count:
719
+ raise ValidationError("ablation campaign must not introduce an outcome oracle")
720
+ metadata = _mapping(data["metadata"], label="selector campaign metadata")
721
+ _positive_integer(
722
+ metadata.get("required_independent_groups"),
723
+ label="selector campaign required independent groups",
724
+ )
725
+ minimum = _positive_integer(
726
+ metadata.get("minimum_common_support_groups"),
727
+ label="selector campaign minimum common-support groups",
728
+ )
729
+ if minimum > metadata["required_independent_groups"]:
730
+ raise ValidationError("selector campaign common-support floor exceeds total groups")
731
+ suites = _identifier_sequence(metadata.get("suite_ids"), label="selector campaign suites")
732
+ if not suites:
733
+ raise ValidationError("selector campaign requires suite IDs")
734
+ if metadata.get("preflight_first") is not True:
735
+ raise ValidationError("selector campaign must remain preflight-first")
736
+ _require_sha256(data["campaign_hash"], label="selector campaign hash")
737
+ if (
738
+ content_hash({key: item for key, item in data.items() if key != "campaign_hash"})
739
+ != data["campaign_hash"]
740
+ ):
741
+ raise ValidationError("selector campaign hash differs from its content")
742
+ return freeze_mapping(data)
743
+
744
+
745
+ def validate_selector_campaign_design(value: Mapping[str, Any]) -> Mapping[str, Any]:
746
+ """Validate the outcome-blind design used before policy artifacts exist."""
747
+
748
+ return freeze_mapping(_validated_campaign_design(value))
749
+
750
+
751
+ def validate_selector_campaign_results(
752
+ campaign: Mapping[str, Any],
753
+ results: Mapping[str, Any],
754
+ ) -> Mapping[str, Any]:
755
+ """Validate complete, verified, non-synthetic multi-policy outcomes."""
756
+
757
+ manifest = validate_selector_campaign_manifest(campaign)
758
+ data = _strict_mapping(
759
+ results,
760
+ label="selector campaign results",
761
+ keys={
762
+ "schema_version",
763
+ "artifact",
764
+ "stage",
765
+ "data_status",
766
+ "is_synthetic",
767
+ "campaign_manifest_hash",
768
+ "source_runs",
769
+ "records",
770
+ },
771
+ )
772
+ if (
773
+ data["schema_version"] != 1
774
+ or data["artifact"] != _RESULT_ARTIFACT
775
+ or data["stage"] != "verified"
776
+ or data["data_status"] != "VERIFIED_REAL_RESULTS"
777
+ or data["is_synthetic"] is not False
778
+ ):
779
+ raise ValidationError("selector results are not verified real outcomes")
780
+ if data["campaign_manifest_hash"] != manifest["campaign_hash"]:
781
+ raise ValidationError("selector result campaign hash differs from the manifest")
782
+ source_runs = _validated_source_runs(data["source_runs"])
783
+ if not source_runs:
784
+ raise ValidationError("selector campaign results require verified source runs")
785
+ policies = {
786
+ item["policy_id"]: item
787
+ for item in (
788
+ _validated_policy(raw, label="selector result policy") for raw in manifest["policies"]
789
+ )
790
+ }
791
+ records = _sequence(data["records"], label="selector campaign records")
792
+ by_group: dict[str, dict[str, dict[str, Any]]] = defaultdict(dict)
793
+ suites = set(manifest["metadata"]["suite_ids"])
794
+ common_groups: set[str] = set()
795
+ for index, raw in enumerate(records):
796
+ record = _validated_result_record(
797
+ raw,
798
+ label=f"selector result record {index}",
799
+ )
800
+ if record["suite_id"] not in suites:
801
+ raise ValidationError("selector result references an undeclared suite")
802
+ try:
803
+ policy = policies[record["policy_id"]]
804
+ except KeyError as exc:
805
+ raise ValidationError("selector result references an undeclared policy") from exc
806
+ if record["diagnostic_only"] is not policy["diagnostic_only"]:
807
+ raise ValidationError("selector result diagnostic role differs from its policy")
808
+ if record["policy_id"] in by_group[record["group_id"]]:
809
+ raise ValidationError("selector results contain duplicate group-policy rows")
810
+ if (
811
+ not record["selection_eligible"]
812
+ and record["intervened"]
813
+ and not policy["diagnostic_only"]
814
+ ):
815
+ raise ValidationError("release policy selected a structurally ineligible action")
816
+ by_group[record["group_id"]][record["policy_id"]] = record
817
+ if record["common_support"]:
818
+ common_groups.add(record["group_id"])
819
+
820
+ required_groups = manifest["metadata"]["required_independent_groups"]
821
+ if len(by_group) != required_groups:
822
+ raise ValidationError(
823
+ f"selector result group count is {len(by_group)}, expected {required_groups}"
824
+ )
825
+ if len(common_groups) < manifest["metadata"]["minimum_common_support_groups"]:
826
+ raise ValidationError("selector results miss the frozen common-support floor")
827
+ expected_policies = set(policies)
828
+ fixed_policy_ids = {"no_op", *(f"fixed_{family.value}" for family in _CORE_FAMILIES)}
829
+ for group_id, group_rows in by_group.items():
830
+ if set(group_rows) != expected_policies:
831
+ raise ValidationError(f"selector group {group_id} lacks the complete policy set")
832
+ support_values = {row["common_support"] for row in group_rows.values()}
833
+ suite_values = {row["suite_id"] for row in group_rows.values()}
834
+ baseline_values = {row["no_op_value"] for row in group_rows.values()}
835
+ if len(support_values) != 1 or len(suite_values) != 1 or len(baseline_values) != 1:
836
+ raise ValidationError("selector group has inconsistent support, suite, or baseline")
837
+ no_op = group_rows["no_op"]
838
+ if (
839
+ no_op["selected_family"] != SemanticFamily.NO_OP.value
840
+ or no_op["selected_release_id"] != "baseline.no_op"
841
+ or no_op["intervened"]
842
+ or not no_op["selection_eligible"]
843
+ or no_op["value"] != no_op["no_op_value"]
844
+ or no_op["hard_harm"]
845
+ ):
846
+ raise ValidationError("selector NO_OP result violates the identity policy")
847
+ if "observed_action_oracle" in group_rows:
848
+ if not fixed_policy_ids.issubset(group_rows):
849
+ raise ValidationError("oracle validation requires NO_OP and five fixed policies")
850
+ fixed_values = [group_rows[policy_id]["value"] for policy_id in fixed_policy_ids]
851
+ oracle = group_rows["observed_action_oracle"]
852
+ maximum = max(fixed_values)
853
+ if not math.isclose(oracle["value"], maximum, abs_tol=1e-12):
854
+ raise ValidationError("observed-action oracle differs from fixed-action headroom")
855
+ maximizing_actions = {
856
+ (
857
+ group_rows[policy_id]["selected_family"],
858
+ group_rows[policy_id]["selected_release_id"],
859
+ )
860
+ for policy_id in fixed_policy_ids
861
+ if math.isclose(group_rows[policy_id]["value"], maximum, abs_tol=1e-12)
862
+ }
863
+ if (
864
+ oracle["selected_family"],
865
+ oracle["selected_release_id"],
866
+ ) not in maximizing_actions:
867
+ raise ValidationError(
868
+ "observed-action oracle action differs from the maximizing fixed action"
869
+ )
870
+ return freeze_mapping(
871
+ {
872
+ **data,
873
+ "source_runs": source_runs,
874
+ "records": tuple(
875
+ row
876
+ for group_id in sorted(by_group)
877
+ for _policy_id, row in sorted(by_group[group_id].items())
878
+ ),
879
+ }
880
+ )
881
+
882
+
883
+ def analyze_selector_campaign_results(
884
+ campaign: Mapping[str, Any],
885
+ results: Mapping[str, Any],
886
+ *,
887
+ bootstrap_samples: int = 2_000,
888
+ random_seed: int = 2027,
889
+ ) -> Mapping[str, Any]:
890
+ """Summarize multi-policy value, harm, cost, eligibility, and coverage."""
891
+
892
+ if (
893
+ isinstance(bootstrap_samples, bool)
894
+ or not isinstance(bootstrap_samples, int)
895
+ or bootstrap_samples < 100
896
+ ):
897
+ raise ValidationError("selector campaign bootstrap_samples must be an integer >= 100")
898
+ if isinstance(random_seed, bool) or not isinstance(random_seed, int) or random_seed < 0:
899
+ raise ValidationError("selector campaign random_seed must be non-negative")
900
+ manifest = validate_selector_campaign_manifest(campaign)
901
+ verified = validate_selector_campaign_results(manifest, results)
902
+ policy_specs = {item["policy_id"]: item for item in manifest["policies"]}
903
+ rows_by_policy: dict[str, list[Mapping[str, Any]]] = defaultdict(list)
904
+ for record in verified["records"]:
905
+ rows_by_policy[record["policy_id"]].append(record)
906
+ rng = random.Random(random_seed)
907
+ summaries: dict[str, Any] = {}
908
+ for policy_id in sorted(rows_by_policy):
909
+ rows = rows_by_policy[policy_id]
910
+ effects = [row["value"] - row["no_op_value"] for row in rows]
911
+ summaries[policy_id] = {
912
+ "independent_groups": len(rows),
913
+ "mean_value": fmean(row["value"] for row in rows),
914
+ "mean_no_op_value": fmean(row["no_op_value"] for row in rows),
915
+ "mean_gain_vs_no_op": fmean(effects),
916
+ "gain_interval": _bootstrap_mean_interval(
917
+ effects,
918
+ samples=bootstrap_samples,
919
+ rng=rng,
920
+ ),
921
+ "intervention_coverage": fmean(1.0 if row["intervened"] else 0.0 for row in rows),
922
+ "hard_harm_rate": fmean(1.0 if row["hard_harm"] else 0.0 for row in rows),
923
+ "ineligible_selection_rate": fmean(
924
+ 1.0 if row["intervened"] and not row["selection_eligible"] else 0.0 for row in rows
925
+ ),
926
+ "mean_cost": fmean(row["cost"] for row in rows),
927
+ "diagnostic_only": policy_specs[policy_id]["diagnostic_only"],
928
+ "formal_inference": policy_specs[policy_id]["formal_inference"],
929
+ }
930
+ formal = sorted(
931
+ policy_id
932
+ for policy_id, policy in policy_specs.items()
933
+ if policy["formal_inference"] and not policy["diagnostic_only"]
934
+ )
935
+ diagnostic = sorted(
936
+ policy_id for policy_id, policy in policy_specs.items() if policy["diagnostic_only"]
937
+ )
938
+ return freeze_mapping(
939
+ {
940
+ "schema_version": 1,
941
+ "analysis": "selector_multi_policy_campaign",
942
+ "campaign_id": manifest["campaign_id"],
943
+ "campaign_hash": manifest["campaign_hash"],
944
+ "primary_metric": manifest["primary_metric"],
945
+ "evaluation_split": manifest["evaluation_split"],
946
+ "independent_groups": manifest["metadata"]["required_independent_groups"],
947
+ "common_support_groups": len(
948
+ {row["group_id"] for row in verified["records"] if row["common_support"]}
949
+ ),
950
+ "policy_summaries": summaries,
951
+ "formal_inference_policy_ids": formal,
952
+ "diagnostic_policy_ids": diagnostic,
953
+ "observed_action_oracle_used_for_training": False,
954
+ "observed_action_oracle_used_for_inference": False,
955
+ "bootstrap_samples": bootstrap_samples,
956
+ "random_seed": random_seed,
957
+ "paper_claim_authorized": False,
958
+ }
959
+ )
960
+
961
+
962
+ def load_json_mapping(path: str | Path, *, label: str) -> tuple[Mapping[str, Any], str]:
963
+ """Read one bounded JSON object and return its exact file digest."""
964
+
965
+ source = Path(path).expanduser().resolve()
966
+ try:
967
+ content = source.read_bytes()
968
+ except OSError as exc:
969
+ raise ArtifactError(f"cannot read {label}: {source}") from exc
970
+ if len(content) > 16 * 1024 * 1024:
971
+ raise ArtifactError(f"{label} exceeds the 16 MiB JSON limit")
972
+ try:
973
+ value = json.loads(content.decode("utf-8"))
974
+ except (UnicodeError, json.JSONDecodeError) as exc:
975
+ raise ArtifactError(f"{label} is not valid UTF-8 JSON") from exc
976
+ if not isinstance(value, Mapping):
977
+ raise ValidationError(f"{label} must be a JSON object")
978
+ return value, hashlib.sha256(content).hexdigest()
979
+
980
+
981
+ def _validated_discovery_summary(value: Mapping[str, Any]) -> dict[str, Any]:
982
+ data = _strict_mapping(
983
+ value,
984
+ label="selector discovery summary",
985
+ keys={
986
+ "schema_version",
987
+ "artifact",
988
+ "stage",
989
+ "revision",
990
+ "data_status",
991
+ "observed",
992
+ "is_synthetic",
993
+ "profile_kind",
994
+ "source_runs",
995
+ "candidates",
996
+ },
997
+ )
998
+ if (
999
+ data["schema_version"] != 1
1000
+ or data["artifact"] != _DISCOVERY_SUMMARY_ARTIFACT
1001
+ or data["stage"] != "verified"
1002
+ or data["data_status"] != "VERIFIED_REAL_RESULTS"
1003
+ or data["observed"] is not True
1004
+ or data["is_synthetic"] is not False
1005
+ or data["profile_kind"] != "controlled_adapter"
1006
+ ):
1007
+ raise ValidationError("representative selection requires verified real controlled results")
1008
+ revision = _identifier(data["revision"], label="selector discovery summary revision")
1009
+ source_runs = _validated_source_runs(data["source_runs"])
1010
+ source_identities = {item["run_identity_hash"] for item in source_runs}
1011
+ candidates: list[dict[str, Any]] = []
1012
+ seen: set[tuple[SemanticFamily, str]] = set()
1013
+ for index, raw in enumerate(_sequence(data["candidates"], label="discovery candidates")):
1014
+ row = _strict_mapping(
1015
+ raw,
1016
+ label=f"discovery candidate {index}",
1017
+ keys={
1018
+ "family",
1019
+ "release_id",
1020
+ "mean_valid_success_gain",
1021
+ "hard_harm_rate",
1022
+ "normalized_cost",
1023
+ "independent_groups",
1024
+ "support_fraction",
1025
+ "source_run_identity_hash",
1026
+ },
1027
+ )
1028
+ family = _core_family(row["family"], label=f"discovery candidate {index} family")
1029
+ release = _identifier(
1030
+ row["release_id"],
1031
+ label=f"discovery candidate {index} release",
1032
+ )
1033
+ key = (family, release)
1034
+ if key in seen:
1035
+ raise ValidationError("selector discovery candidates must be unique by family/release")
1036
+ seen.add(key)
1037
+ source_identity = row["source_run_identity_hash"]
1038
+ _require_sha256(source_identity, label="candidate source run identity")
1039
+ if source_identity not in source_identities:
1040
+ raise ValidationError("candidate source identity is absent from verified source runs")
1041
+ candidates.append(
1042
+ {
1043
+ "family": family,
1044
+ "release_id": release,
1045
+ "mean_valid_success_gain": _bounded(
1046
+ row["mean_valid_success_gain"],
1047
+ -1.0,
1048
+ 1.0,
1049
+ label="candidate mean valid-success gain",
1050
+ ),
1051
+ "hard_harm_rate": _bounded(
1052
+ row["hard_harm_rate"],
1053
+ 0.0,
1054
+ 1.0,
1055
+ label="candidate hard-harm rate",
1056
+ ),
1057
+ "normalized_cost": _bounded(
1058
+ row["normalized_cost"],
1059
+ 0.0,
1060
+ 1.0,
1061
+ label="candidate normalized cost",
1062
+ ),
1063
+ "independent_groups": _positive_integer(
1064
+ row["independent_groups"],
1065
+ label="candidate independent groups",
1066
+ ),
1067
+ "support_fraction": _bounded(
1068
+ row["support_fraction"],
1069
+ 0.0,
1070
+ 1.0,
1071
+ label="candidate support fraction",
1072
+ ),
1073
+ "source_run_identity_hash": source_identity,
1074
+ }
1075
+ )
1076
+ if not candidates:
1077
+ raise ValidationError("selector discovery summary has no candidates")
1078
+ return {
1079
+ **data,
1080
+ "revision": revision,
1081
+ "source_runs": source_runs,
1082
+ "candidates": candidates,
1083
+ }
1084
+
1085
+
1086
+ def _validated_pareto_rule(value: Mapping[str, Any]) -> dict[str, Any]:
1087
+ data = _strict_mapping(
1088
+ value,
1089
+ label="selector Pareto rule",
1090
+ keys={
1091
+ "schema_version",
1092
+ "artifact",
1093
+ "stage",
1094
+ "representatives_per_family",
1095
+ "minimum_independent_groups",
1096
+ "minimum_support_fraction",
1097
+ "maximum_hard_harm_rate",
1098
+ "minimum_valid_success_gain",
1099
+ "benefit_weight",
1100
+ "harm_penalty",
1101
+ "cost_penalty",
1102
+ "tie_break",
1103
+ },
1104
+ )
1105
+ if (
1106
+ data["schema_version"] != 1
1107
+ or data["artifact"] != _RULE_ARTIFACT
1108
+ or data["stage"] != "frozen"
1109
+ ):
1110
+ raise ValidationError("selector Pareto rule must use frozen schema v1")
1111
+ count = _positive_integer(
1112
+ data["representatives_per_family"],
1113
+ label="representatives per family",
1114
+ )
1115
+ if count != 2:
1116
+ raise ValidationError("current selector protocol requires exactly two per family")
1117
+ parsed = {
1118
+ **data,
1119
+ "representatives_per_family": count,
1120
+ "minimum_independent_groups": _positive_integer(
1121
+ data["minimum_independent_groups"],
1122
+ label="Pareto minimum independent groups",
1123
+ ),
1124
+ "minimum_support_fraction": _bounded(
1125
+ data["minimum_support_fraction"],
1126
+ 0.0,
1127
+ 1.0,
1128
+ label="Pareto minimum support",
1129
+ ),
1130
+ "maximum_hard_harm_rate": _bounded(
1131
+ data["maximum_hard_harm_rate"],
1132
+ 0.0,
1133
+ 1.0,
1134
+ label="Pareto maximum hard harm",
1135
+ ),
1136
+ "minimum_valid_success_gain": _bounded(
1137
+ data["minimum_valid_success_gain"],
1138
+ -1.0,
1139
+ 1.0,
1140
+ label="Pareto minimum gain",
1141
+ ),
1142
+ "benefit_weight": _positive_number(
1143
+ data["benefit_weight"],
1144
+ label="Pareto benefit weight",
1145
+ ),
1146
+ "harm_penalty": _nonnegative_number(
1147
+ data["harm_penalty"],
1148
+ label="Pareto harm penalty",
1149
+ ),
1150
+ "cost_penalty": _nonnegative_number(
1151
+ data["cost_penalty"],
1152
+ label="Pareto cost penalty",
1153
+ ),
1154
+ }
1155
+ if data["tie_break"] != "pareto_layer,-utility,-benefit,harm,cost,-support,release_id":
1156
+ raise ValidationError("unsupported selector Pareto tie-break")
1157
+ parsed["rule_hash"] = content_hash(parsed)
1158
+ return parsed
1159
+
1160
+
1161
+ def _pareto_ranked(
1162
+ candidates: Sequence[Mapping[str, Any]],
1163
+ rule: Mapping[str, Any],
1164
+ ) -> list[dict[str, Any]]:
1165
+ remaining = [dict(item) for item in candidates]
1166
+ ranked: list[dict[str, Any]] = []
1167
+ layer = 0
1168
+ while remaining:
1169
+ front = [
1170
+ candidate
1171
+ for candidate in remaining
1172
+ if not any(
1173
+ _dominates(other, candidate) for other in remaining if other is not candidate
1174
+ )
1175
+ ]
1176
+ if not front: # pragma: no cover - finite partial order always has a front
1177
+ raise AssertionError("Pareto ordering produced no front")
1178
+ for candidate in front:
1179
+ candidate["pareto_layer"] = layer
1180
+ candidate["utility_score"] = (
1181
+ rule["benefit_weight"] * candidate["mean_valid_success_gain"]
1182
+ - rule["harm_penalty"] * candidate["hard_harm_rate"]
1183
+ - rule["cost_penalty"] * candidate["normalized_cost"]
1184
+ )
1185
+ front.sort(
1186
+ key=lambda item: (
1187
+ -item["utility_score"],
1188
+ -item["mean_valid_success_gain"],
1189
+ item["hard_harm_rate"],
1190
+ item["normalized_cost"],
1191
+ -item["support_fraction"],
1192
+ item["release_id"],
1193
+ )
1194
+ )
1195
+ ranked.extend(front)
1196
+ front_ids = {id(item) for item in front}
1197
+ remaining = [item for item in remaining if id(item) not in front_ids]
1198
+ layer += 1
1199
+ return ranked
1200
+
1201
+
1202
+ def _dominates(left: Mapping[str, Any], right: Mapping[str, Any]) -> bool:
1203
+ no_worse = (
1204
+ left["mean_valid_success_gain"] >= right["mean_valid_success_gain"]
1205
+ and left["hard_harm_rate"] <= right["hard_harm_rate"]
1206
+ and left["normalized_cost"] <= right["normalized_cost"]
1207
+ )
1208
+ strict = (
1209
+ left["mean_valid_success_gain"] > right["mean_valid_success_gain"]
1210
+ or left["hard_harm_rate"] < right["hard_harm_rate"]
1211
+ or left["normalized_cost"] < right["normalized_cost"]
1212
+ )
1213
+ return no_worse and strict
1214
+
1215
+
1216
+ def _summary_for_hash(summary: Mapping[str, Any]) -> Mapping[str, Any]:
1217
+ return {
1218
+ **{key: item for key, item in summary.items() if key != "candidates"},
1219
+ "candidates": [
1220
+ {
1221
+ **candidate,
1222
+ "family": candidate["family"].value,
1223
+ }
1224
+ for candidate in summary["candidates"]
1225
+ ],
1226
+ }
1227
+
1228
+
1229
+ def _validated_campaign_design(value: Mapping[str, Any]) -> dict[str, Any]:
1230
+ data = _strict_mapping(
1231
+ value,
1232
+ label="selector campaign design",
1233
+ keys={
1234
+ "schema_version",
1235
+ "artifact",
1236
+ "stage",
1237
+ "campaign_id",
1238
+ "primary_metric",
1239
+ "evaluation_split",
1240
+ "suite_ids",
1241
+ "required_independent_groups",
1242
+ "minimum_common_support_groups",
1243
+ "random_seed",
1244
+ },
1245
+ )
1246
+ if (
1247
+ data["schema_version"] != 1
1248
+ or data["artifact"] != _DESIGN_ARTIFACT
1249
+ or data["stage"] != "frozen"
1250
+ ):
1251
+ raise ValidationError("selector campaign design must use frozen schema v1")
1252
+ parsed = {
1253
+ **data,
1254
+ "campaign_id": _identifier(data["campaign_id"], label="selector campaign ID"),
1255
+ "primary_metric": _identifier(
1256
+ data["primary_metric"],
1257
+ label="selector campaign primary metric",
1258
+ ),
1259
+ "evaluation_split": _identifier(
1260
+ data["evaluation_split"],
1261
+ label="selector campaign evaluation split",
1262
+ ),
1263
+ "suite_ids": _identifier_sequence(
1264
+ data["suite_ids"],
1265
+ label="selector campaign suites",
1266
+ ),
1267
+ "required_independent_groups": _positive_integer(
1268
+ data["required_independent_groups"],
1269
+ label="selector campaign required independent groups",
1270
+ ),
1271
+ "minimum_common_support_groups": _positive_integer(
1272
+ data["minimum_common_support_groups"],
1273
+ label="selector campaign minimum common-support groups",
1274
+ ),
1275
+ "random_seed": _nonnegative_integer(
1276
+ data["random_seed"],
1277
+ label="selector campaign random seed",
1278
+ ),
1279
+ }
1280
+ if (
1281
+ not parsed["suite_ids"]
1282
+ or parsed["minimum_common_support_groups"] > parsed["required_independent_groups"]
1283
+ ):
1284
+ raise ValidationError("selector campaign support design is invalid")
1285
+ return parsed
1286
+
1287
+
1288
+ def _validated_campaign_bindings(value: Mapping[str, Any]) -> dict[str, Any]:
1289
+ data = _strict_mapping(
1290
+ value,
1291
+ label="selector campaign bindings",
1292
+ keys={
1293
+ "schema_version",
1294
+ "artifact",
1295
+ "stage",
1296
+ "representative_manifest_hash",
1297
+ "representative_rank",
1298
+ "best_fixed_global",
1299
+ "selectors",
1300
+ },
1301
+ )
1302
+ if (
1303
+ data["schema_version"] != 1
1304
+ or data["artifact"] != _BINDINGS_ARTIFACT
1305
+ or data["stage"] != "frozen"
1306
+ ):
1307
+ raise ValidationError("selector campaign bindings must use frozen schema v1")
1308
+ representative_manifest_hash = _sha256_value(
1309
+ data["representative_manifest_hash"],
1310
+ label="selector campaign representative manifest",
1311
+ )
1312
+ representative_rank = _positive_integer(
1313
+ data["representative_rank"],
1314
+ label="selector campaign representative rank",
1315
+ )
1316
+ if representative_rank != 1:
1317
+ raise ValidationError("selector campaign currently requires rank-1 family policies")
1318
+ best = _strict_mapping(
1319
+ data["best_fixed_global"],
1320
+ label="selector best-fixed binding",
1321
+ keys={
1322
+ "selected_family",
1323
+ "selected_release_id",
1324
+ "policy_manifest_sha256",
1325
+ },
1326
+ )
1327
+ parsed_best = {
1328
+ "selected_family": _core_family(
1329
+ best["selected_family"],
1330
+ label="selector best-fixed family",
1331
+ ),
1332
+ "selected_release_id": _identifier(
1333
+ best["selected_release_id"],
1334
+ label="selector best-fixed release",
1335
+ ),
1336
+ "policy_manifest_sha256": _sha256_value(
1337
+ best["policy_manifest_sha256"],
1338
+ label="selector best-fixed policy manifest",
1339
+ ),
1340
+ }
1341
+ raw_selectors = _strict_mapping(
1342
+ data["selectors"],
1343
+ label="selector artifact bindings",
1344
+ keys={
1345
+ "defect_rule",
1346
+ "zero_shot_router",
1347
+ "penalized_t_learner",
1348
+ "gbdt_t_learner",
1349
+ "eligibility_aware_selector",
1350
+ },
1351
+ )
1352
+ selectors = {
1353
+ policy_id: _validated_artifact_binding(
1354
+ raw,
1355
+ label=f"selector artifact binding {policy_id}",
1356
+ )
1357
+ for policy_id, raw in raw_selectors.items()
1358
+ }
1359
+ expected_kinds = {
1360
+ "defect_rule": {"rule"},
1361
+ "zero_shot_router": {"zero_shot_router"},
1362
+ "penalized_t_learner": {"ridge_t_learner", "logistic_t_learner"},
1363
+ "gbdt_t_learner": {"gbdt_t_learner"},
1364
+ "eligibility_aware_selector": {
1365
+ "ridge_utility",
1366
+ "ridge_t_learner",
1367
+ "logistic_t_learner",
1368
+ "gbdt_t_learner",
1369
+ "knn_utility",
1370
+ "cost_risk_guardrail",
1371
+ },
1372
+ }
1373
+ for policy_id, allowed in expected_kinds.items():
1374
+ if selectors[policy_id]["selector_kind"] not in allowed:
1375
+ raise ValidationError(f"{policy_id} binding has an incompatible selector kind")
1376
+ return {
1377
+ **data,
1378
+ "representative_manifest_hash": representative_manifest_hash,
1379
+ "representative_rank": representative_rank,
1380
+ "best_fixed_global": parsed_best,
1381
+ "selectors": selectors,
1382
+ }
1383
+
1384
+
1385
+ def _validated_ablation_bindings(value: Mapping[str, Any]) -> dict[str, Any]:
1386
+ data = _strict_mapping(
1387
+ value,
1388
+ label="selector ablation bindings",
1389
+ keys={
1390
+ "schema_version",
1391
+ "artifact",
1392
+ "stage",
1393
+ "baseline_campaign_hash",
1394
+ "artifacts",
1395
+ },
1396
+ )
1397
+ if (
1398
+ data["schema_version"] != 1
1399
+ or data["artifact"] != _ABLATION_BINDINGS_ARTIFACT
1400
+ or data["stage"] != "frozen"
1401
+ ):
1402
+ raise ValidationError("selector ablation bindings must use frozen schema v1")
1403
+ baseline_campaign_hash = _sha256_value(
1404
+ data["baseline_campaign_hash"],
1405
+ label="selector ablation baseline campaign",
1406
+ )
1407
+ artifacts = _strict_mapping(
1408
+ data["artifacts"],
1409
+ label="selector ablation artifacts",
1410
+ keys={
1411
+ "drop_ambiguity_features",
1412
+ "drop_multistep_features",
1413
+ "drop_retrieval_features",
1414
+ "drop_context_features",
1415
+ "drop_reformulation_features",
1416
+ "without_eligibility_mask",
1417
+ "without_cost_gate",
1418
+ "without_harm_calibration",
1419
+ },
1420
+ )
1421
+ return {
1422
+ **data,
1423
+ "baseline_campaign_hash": baseline_campaign_hash,
1424
+ "artifacts": {
1425
+ policy_id: _validated_artifact_binding(
1426
+ raw,
1427
+ label=f"selector ablation artifact {policy_id}",
1428
+ )
1429
+ for policy_id, raw in artifacts.items()
1430
+ },
1431
+ }
1432
+
1433
+
1434
+ def _validated_ablation_matrix(value: Mapping[str, Any]) -> tuple[dict[str, Any], ...]:
1435
+ data = _strict_mapping(
1436
+ value,
1437
+ label="selector ablation matrix",
1438
+ keys={"schema_version", "artifact", "stage", "entries"},
1439
+ )
1440
+ if (
1441
+ data["schema_version"] != 1
1442
+ or data["artifact"] != _ABLATION_MATRIX_ARTIFACT
1443
+ or data["stage"] != "frozen"
1444
+ ):
1445
+ raise ValidationError("selector ablation matrix must use frozen schema v1")
1446
+ expected = {
1447
+ "drop_ambiguity_features": ("feature_group.ambiguity", True, False),
1448
+ "drop_multistep_features": ("feature_group.multi_step", True, False),
1449
+ "drop_retrieval_features": ("feature_group.retrieval_need", True, False),
1450
+ "drop_context_features": ("feature_group.context_pressure", True, False),
1451
+ "drop_reformulation_features": (
1452
+ "feature_group.reformulation_need",
1453
+ True,
1454
+ False,
1455
+ ),
1456
+ "without_eligibility_mask": ("eligibility_mask", False, True),
1457
+ "without_cost_gate": ("cost_gate", False, False),
1458
+ "without_harm_calibration": ("harm_calibration", False, True),
1459
+ }
1460
+ parsed: dict[str, dict[str, Any]] = {}
1461
+ for index, raw in enumerate(_sequence(data["entries"], label="selector ablation entries")):
1462
+ row = _strict_mapping(
1463
+ raw,
1464
+ label=f"selector ablation entry {index}",
1465
+ keys={
1466
+ "policy_id",
1467
+ "changed_component",
1468
+ "requires_independent_refit",
1469
+ "diagnostic_only",
1470
+ },
1471
+ )
1472
+ policy_id = _identifier(row["policy_id"], label="selector ablation policy ID")
1473
+ if policy_id in parsed:
1474
+ raise ValidationError("selector ablation policy IDs must be unique")
1475
+ parsed[policy_id] = {
1476
+ "policy_id": policy_id,
1477
+ "changed_component": _identifier(
1478
+ row["changed_component"],
1479
+ label="selector ablation changed component",
1480
+ ),
1481
+ "requires_independent_refit": _boolean(
1482
+ row["requires_independent_refit"],
1483
+ label="selector ablation refit flag",
1484
+ ),
1485
+ "diagnostic_only": _boolean(
1486
+ row["diagnostic_only"],
1487
+ label="selector ablation diagnostic flag",
1488
+ ),
1489
+ }
1490
+ if set(parsed) != set(expected):
1491
+ raise ValidationError("selector ablation matrix differs from the frozen protocol")
1492
+ for policy_id, values in expected.items():
1493
+ row = parsed[policy_id]
1494
+ if (
1495
+ row["changed_component"],
1496
+ row["requires_independent_refit"],
1497
+ row["diagnostic_only"],
1498
+ ) != values:
1499
+ raise ValidationError(f"selector ablation entry {policy_id} differs from protocol")
1500
+ return tuple(parsed[policy_id] for policy_id in expected)
1501
+
1502
+
1503
+ def _validated_artifact_binding(value: Any, *, label: str) -> dict[str, Any]:
1504
+ data = _strict_mapping(
1505
+ value,
1506
+ label=label,
1507
+ keys={"stage", "selector_kind", "selector_id", "revision", "sha256"},
1508
+ )
1509
+ if data["stage"] != "frozen":
1510
+ raise ValidationError(f"{label} must bind a frozen artifact")
1511
+ return {
1512
+ "stage": "frozen",
1513
+ "selector_kind": _identifier(data["selector_kind"], label=f"{label} kind"),
1514
+ "selector_id": _identifier(data["selector_id"], label=f"{label} ID"),
1515
+ "revision": _identifier(data["revision"], label=f"{label} revision"),
1516
+ "sha256": _sha256_value(data["sha256"], label=f"{label} SHA-256"),
1517
+ }
1518
+
1519
+
1520
+ def _selected_releases(
1521
+ representatives: Mapping[str, Any],
1522
+ ) -> dict[SemanticFamily, tuple[str, str]]:
1523
+ selected: dict[SemanticFamily, list[tuple[int, str]]] = defaultdict(list)
1524
+ for row in representatives["selections"]:
1525
+ selected[SemanticFamily(row["family"])].append((row["rank"], row["release_id"]))
1526
+ return {
1527
+ family: tuple(release for _rank, release in sorted(rows))
1528
+ for family, rows in selected.items()
1529
+ }
1530
+
1531
+
1532
+ def _campaign(
1533
+ *,
1534
+ campaign_id: str,
1535
+ campaign_kind: str,
1536
+ primary_metric: str,
1537
+ evaluation_split: str,
1538
+ representative_manifest_hash: str,
1539
+ policies: Sequence[Mapping[str, Any]],
1540
+ metadata: Mapping[str, Any],
1541
+ ) -> Mapping[str, Any]:
1542
+ base = {
1543
+ "schema_version": 1,
1544
+ "artifact": _CAMPAIGN_ARTIFACT,
1545
+ "stage": "frozen",
1546
+ "campaign_id": campaign_id,
1547
+ "campaign_kind": campaign_kind,
1548
+ "primary_metric": primary_metric,
1549
+ "evaluation_split": evaluation_split,
1550
+ "representative_manifest_hash": representative_manifest_hash,
1551
+ "policies": list(policies),
1552
+ "metadata": dict(metadata),
1553
+ "experiments_executed": False,
1554
+ }
1555
+ result = freeze_mapping({**base, "campaign_hash": content_hash(base)})
1556
+ return validate_selector_campaign_manifest(result)
1557
+
1558
+
1559
+ def _policy(
1560
+ policy_id: str,
1561
+ *,
1562
+ kind: str,
1563
+ role: str,
1564
+ formal_inference: bool,
1565
+ diagnostic_only: bool,
1566
+ parameters: Mapping[str, Any],
1567
+ ) -> dict[str, Any]:
1568
+ return {
1569
+ "policy_id": policy_id,
1570
+ "kind": kind,
1571
+ "role": role,
1572
+ "formal_inference": formal_inference,
1573
+ "diagnostic_only": diagnostic_only,
1574
+ "parameters": dict(parameters),
1575
+ }
1576
+
1577
+
1578
+ def _artifact_policy(
1579
+ policy_id: str,
1580
+ binding: Mapping[str, Any],
1581
+ *,
1582
+ role: str,
1583
+ formal_inference: bool,
1584
+ ) -> dict[str, Any]:
1585
+ return _policy(
1586
+ policy_id,
1587
+ kind="frozen_artifact_policy",
1588
+ role=role,
1589
+ formal_inference=formal_inference,
1590
+ diagnostic_only=False,
1591
+ parameters={"artifact_binding": dict(binding)},
1592
+ )
1593
+
1594
+
1595
+ def _validated_policy(value: Any, *, label: str) -> dict[str, Any]:
1596
+ data = _strict_mapping(
1597
+ value,
1598
+ label=label,
1599
+ keys={
1600
+ "policy_id",
1601
+ "kind",
1602
+ "role",
1603
+ "formal_inference",
1604
+ "diagnostic_only",
1605
+ "parameters",
1606
+ },
1607
+ )
1608
+ policy_id = _identifier(data["policy_id"], label=f"{label} ID")
1609
+ kind = _identifier(data["kind"], label=f"{label} kind")
1610
+ role = _identifier(data["role"], label=f"{label} role")
1611
+ formal = _boolean(data["formal_inference"], label=f"{label} formal inference")
1612
+ diagnostic = _boolean(data["diagnostic_only"], label=f"{label} diagnostic flag")
1613
+ if formal and diagnostic:
1614
+ raise ValidationError(f"{label} cannot be both formal and diagnostic-only")
1615
+ return {
1616
+ "policy_id": policy_id,
1617
+ "kind": kind,
1618
+ "role": role,
1619
+ "formal_inference": formal,
1620
+ "diagnostic_only": diagnostic,
1621
+ "parameters": freeze_mapping(_mapping(data["parameters"], label=f"{label} parameters")),
1622
+ }
1623
+
1624
+
1625
+ def _validated_result_record(value: Any, *, label: str) -> dict[str, Any]:
1626
+ data = _strict_mapping(
1627
+ value,
1628
+ label=label,
1629
+ keys={
1630
+ "group_id",
1631
+ "suite_id",
1632
+ "policy_id",
1633
+ "selected_family",
1634
+ "selected_release_id",
1635
+ "value",
1636
+ "no_op_value",
1637
+ "hard_harm",
1638
+ "cost",
1639
+ "intervened",
1640
+ "selection_eligible",
1641
+ "common_support",
1642
+ "diagnostic_only",
1643
+ },
1644
+ )
1645
+ group_id = _require_text(data["group_id"], label=f"{label} group ID")
1646
+ if _GROUP_ID.fullmatch(group_id) is None:
1647
+ raise ValidationError(f"{label} group ID must be a privacy-safe hash")
1648
+ family = _family(data["selected_family"], label=f"{label} selected family")
1649
+ release = _require_text(data["selected_release_id"], label=f"{label} selected release")
1650
+ if family is SemanticFamily.NO_OP and release != "baseline.no_op":
1651
+ raise ValidationError(f"{label} NO_OP selection requires baseline.no_op")
1652
+ if family is not SemanticFamily.NO_OP and release == "baseline.no_op":
1653
+ raise ValidationError(f"{label} intervention selection cannot use baseline.no_op")
1654
+ intervened = _boolean(data["intervened"], label=f"{label} intervened")
1655
+ if intervened is (family is SemanticFamily.NO_OP):
1656
+ raise ValidationError(f"{label} intervention flag differs from its selected family")
1657
+ return {
1658
+ "group_id": group_id,
1659
+ "suite_id": _identifier(data["suite_id"], label=f"{label} suite"),
1660
+ "policy_id": _identifier(data["policy_id"], label=f"{label} policy"),
1661
+ "selected_family": family.value,
1662
+ "selected_release_id": release,
1663
+ "value": _bounded(data["value"], 0.0, 1.0, label=f"{label} value"),
1664
+ "no_op_value": _bounded(
1665
+ data["no_op_value"],
1666
+ 0.0,
1667
+ 1.0,
1668
+ label=f"{label} NO_OP value",
1669
+ ),
1670
+ "hard_harm": _boolean(data["hard_harm"], label=f"{label} hard harm"),
1671
+ "cost": _nonnegative_number(data["cost"], label=f"{label} cost"),
1672
+ "intervened": intervened,
1673
+ "selection_eligible": _boolean(
1674
+ data["selection_eligible"],
1675
+ label=f"{label} selection eligibility",
1676
+ ),
1677
+ "common_support": _boolean(
1678
+ data["common_support"],
1679
+ label=f"{label} common support",
1680
+ ),
1681
+ "diagnostic_only": _boolean(
1682
+ data["diagnostic_only"],
1683
+ label=f"{label} diagnostic flag",
1684
+ ),
1685
+ }
1686
+
1687
+
1688
+ def _validated_source_runs(value: Any) -> tuple[dict[str, str], ...]:
1689
+ rows = _sequence(value, label="selector verified source runs")
1690
+ parsed: list[dict[str, str]] = []
1691
+ identities: set[str] = set()
1692
+ for index, raw in enumerate(rows):
1693
+ row = _strict_mapping(
1694
+ raw,
1695
+ label=f"selector source run {index}",
1696
+ keys={
1697
+ "study_id",
1698
+ "run_identity_hash",
1699
+ "manifest_hash",
1700
+ "plan_hash",
1701
+ "result_set_hash",
1702
+ },
1703
+ )
1704
+ parsed_row = {
1705
+ "study_id": _identifier(row["study_id"], label="selector source study ID"),
1706
+ "run_identity_hash": _sha256_value(
1707
+ row["run_identity_hash"],
1708
+ label="selector run identity",
1709
+ ),
1710
+ "manifest_hash": _sha256_value(
1711
+ row["manifest_hash"],
1712
+ label="selector source manifest",
1713
+ ),
1714
+ "plan_hash": _sha256_value(row["plan_hash"], label="selector source plan"),
1715
+ "result_set_hash": _sha256_value(
1716
+ row["result_set_hash"],
1717
+ label="selector result set",
1718
+ ),
1719
+ }
1720
+ if parsed_row["run_identity_hash"] in identities:
1721
+ raise ValidationError("selector source run identities must be unique")
1722
+ identities.add(parsed_row["run_identity_hash"])
1723
+ parsed.append(parsed_row)
1724
+ return tuple(sorted(parsed, key=lambda item: item["run_identity_hash"]))
1725
+
1726
+
1727
+ def _bootstrap_mean_interval(
1728
+ values: Sequence[float],
1729
+ *,
1730
+ samples: int,
1731
+ rng: random.Random,
1732
+ ) -> Mapping[str, float]:
1733
+ if not values:
1734
+ raise ValidationError("selector bootstrap requires values")
1735
+ estimates = sorted(
1736
+ fmean(values[rng.randrange(len(values))] for _ in values) for _ in range(samples)
1737
+ )
1738
+ return {
1739
+ "estimate": fmean(values),
1740
+ "low": _quantile(estimates, 0.025),
1741
+ "high": _quantile(estimates, 0.975),
1742
+ "method": "independent_group_bootstrap",
1743
+ }
1744
+
1745
+
1746
+ def _quantile(values: Sequence[float], probability: float) -> float:
1747
+ index = (len(values) - 1) * probability
1748
+ lower = math.floor(index)
1749
+ upper = math.ceil(index)
1750
+ if lower == upper:
1751
+ return values[lower]
1752
+ weight = index - lower
1753
+ return values[lower] * (1.0 - weight) + values[upper] * weight
1754
+
1755
+
1756
+ def _strict_mapping(
1757
+ value: Any,
1758
+ *,
1759
+ label: str,
1760
+ keys: set[str],
1761
+ ) -> dict[str, Any]:
1762
+ if not isinstance(value, Mapping) or any(not isinstance(key, str) for key in value):
1763
+ raise ValidationError(f"{label} must be an object")
1764
+ data = dict(value)
1765
+ if set(data) != keys:
1766
+ raise ValidationError(
1767
+ f"{label} fields differ: expected {sorted(keys)!r}, got {sorted(data)!r}"
1768
+ )
1769
+ return data
1770
+
1771
+
1772
+ def _mapping(value: Any, *, label: str) -> dict[str, Any]:
1773
+ if not isinstance(value, Mapping) or any(not isinstance(key, str) for key in value):
1774
+ raise ValidationError(f"{label} must be an object")
1775
+ return dict(value)
1776
+
1777
+
1778
+ def _sequence(value: Any, *, label: str) -> tuple[Any, ...]:
1779
+ if isinstance(value, (str, bytes)) or not isinstance(value, Sequence):
1780
+ raise ValidationError(f"{label} must be an array")
1781
+ return tuple(value)
1782
+
1783
+
1784
+ def _string_sequence(value: Any, *, label: str) -> tuple[str, ...]:
1785
+ rows = _sequence(value, label=label)
1786
+ if any(not isinstance(item, str) or not item.strip() for item in rows):
1787
+ raise ValidationError(f"{label} must contain non-empty strings")
1788
+ return tuple(rows)
1789
+
1790
+
1791
+ def _identifier_sequence(value: Any, *, label: str) -> tuple[str, ...]:
1792
+ rows = tuple(_identifier(item, label=f"{label} item") for item in _sequence(value, label=label))
1793
+ if len(rows) != len(set(rows)):
1794
+ raise ValidationError(f"{label} must be unique")
1795
+ return rows
1796
+
1797
+
1798
+ def _identifier(value: Any, *, label: str) -> str:
1799
+ text = _require_text(value, label=label)
1800
+ if _IDENTIFIER.fullmatch(text) is None:
1801
+ raise ValidationError(f"{label} must be a lowercase stable identifier")
1802
+ return text
1803
+
1804
+
1805
+ def _require_text(value: Any, *, label: str) -> str:
1806
+ if not isinstance(value, str) or not value.strip() or value != value.strip():
1807
+ raise ValidationError(f"{label} must be a trimmed non-empty string")
1808
+ return value
1809
+
1810
+
1811
+ def _sha256_value(value: Any, *, label: str) -> str:
1812
+ _require_sha256(value, label=label)
1813
+ return value
1814
+
1815
+
1816
+ def _require_sha256(value: Any, *, label: str) -> None:
1817
+ if not isinstance(value, str) or _SHA256.fullmatch(value) is None:
1818
+ raise ValidationError(f"{label} must be a lowercase SHA-256")
1819
+
1820
+
1821
+ def _core_family(value: Any, *, label: str) -> SemanticFamily:
1822
+ family = _family(value, label=label)
1823
+ if family not in _CORE_FAMILIES:
1824
+ raise ValidationError(f"{label} must be a core intervention family")
1825
+ return family
1826
+
1827
+
1828
+ def _family(value: Any, *, label: str) -> SemanticFamily:
1829
+ try:
1830
+ return SemanticFamily(value)
1831
+ except (TypeError, ValueError) as exc:
1832
+ raise ValidationError(f"{label} must be a semantic family") from exc
1833
+
1834
+
1835
+ def _boolean(value: Any, *, label: str) -> bool:
1836
+ if not isinstance(value, bool):
1837
+ raise ValidationError(f"{label} must be boolean")
1838
+ return value
1839
+
1840
+
1841
+ def _positive_integer(value: Any, *, label: str) -> int:
1842
+ result = _nonnegative_integer(value, label=label)
1843
+ if result < 1:
1844
+ raise ValidationError(f"{label} must be positive")
1845
+ return result
1846
+
1847
+
1848
+ def _nonnegative_integer(value: Any, *, label: str) -> int:
1849
+ if isinstance(value, bool) or not isinstance(value, int) or value < 0:
1850
+ raise ValidationError(f"{label} must be a non-negative integer")
1851
+ return value
1852
+
1853
+
1854
+ def _finite(value: Any, *, label: str) -> float:
1855
+ if isinstance(value, bool) or not isinstance(value, (int, float)) or not math.isfinite(value):
1856
+ raise ValidationError(f"{label} must be finite")
1857
+ return float(value)
1858
+
1859
+
1860
+ def _bounded(value: Any, lower: float, upper: float, *, label: str) -> float:
1861
+ result = _finite(value, label=label)
1862
+ if not lower <= result <= upper:
1863
+ raise ValidationError(f"{label} must be in [{lower:g}, {upper:g}]")
1864
+ return result
1865
+
1866
+
1867
+ def _positive_number(value: Any, *, label: str) -> float:
1868
+ result = _finite(value, label=label)
1869
+ if result <= 0:
1870
+ raise ValidationError(f"{label} must be positive")
1871
+ return result
1872
+
1873
+
1874
+ def _nonnegative_number(value: Any, *, label: str) -> float:
1875
+ result = _finite(value, label=label)
1876
+ if result < 0:
1877
+ raise ValidationError(f"{label} must be non-negative")
1878
+ return result
1879
+
1880
+
1881
+ __all__ = [
1882
+ "analyze_selector_campaign_results",
1883
+ "build_selector_ablation_campaign",
1884
+ "build_selector_baseline_campaign",
1885
+ "build_selector_loso_manifest",
1886
+ "freeze_pareto_representatives",
1887
+ "load_json_mapping",
1888
+ "validate_representative_manifest",
1889
+ "validate_selector_campaign_design",
1890
+ "validate_selector_campaign_manifest",
1891
+ "validate_selector_campaign_results",
1892
+ "validate_selector_loso_manifest",
1893
+ ]