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,678 @@
1
+ """Deterministic, outcome-free measurement for paper inputs and trajectories.
2
+
3
+ The paper protocol uses these rules as the executable measurement path. Human
4
+ annotation is deliberately an audit of the rules, not a dependency of model
5
+ execution. Rules may inspect the visible pre-action state and public benchmark
6
+ metadata, but never evaluator gold, another arm's outcome, or post-treatment
7
+ success.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import hashlib
13
+ import re
14
+ from collections import Counter, defaultdict
15
+ from collections.abc import Mapping, Sequence
16
+ from typing import Any
17
+
18
+ from agentinputlab.contracts.errors import ValidationError
19
+ from agentinputlab.contracts.serialization import content_hash
20
+ from agentinputlab.contracts.state import ContextBlock, ExecutionBudget, FrozenAgentState, Message
21
+ from agentinputlab.selectors.features import VisibleStateFeatureExtractor
22
+
23
+ AUTOMATIC_INPUT_LABEL_PROTOCOL = "agentinputlab.automatic-input-label.v1"
24
+ AUTOMATIC_TRAJECTORY_PROTOCOL = "agentinputlab.automatic-trajectory-validity.v1"
25
+ AUTOMATIC_REPAIR_QUALITY_PROTOCOL = "agentinputlab.automatic-proximal-repair-quality.v1"
26
+ AUTOMATIC_MEASUREMENT_RULE_REVISION = "deterministic-visible-contract-v2"
27
+
28
+ _FAMILIES = ("reformulate", "decompose", "acquire", "clarify", "curate")
29
+ _DEFECT_FIELDS = (
30
+ "unclear_or_misaligned_request",
31
+ "decomposition_need",
32
+ "missing_external_evidence",
33
+ "clarification_need",
34
+ "context_overload_or_noise",
35
+ )
36
+ _KNOWN_MAIN_ARENAS = frozenset(
37
+ {
38
+ "tau3.banking_knowledge",
39
+ "state_bench.common_support",
40
+ "toolsandbox.common_support",
41
+ }
42
+ )
43
+ _THRESHOLDS = {
44
+ "unclear_or_misaligned_request": 0.35,
45
+ "decomposition_need": 0.30,
46
+ "missing_external_evidence": 0.30,
47
+ "clarification_need": 0.30,
48
+ "context_overload_or_noise": 0.35,
49
+ }
50
+ _FAMILY_TARGET_DEFECT = {
51
+ "reformulate": "unclear_or_misaligned_request",
52
+ "decompose": "decomposition_need",
53
+ "acquire": "missing_external_evidence",
54
+ "clarify": "clarification_need",
55
+ "curate": "context_overload_or_noise",
56
+ }
57
+ _NUMBER = re.compile(
58
+ r"(?<![\w.])(?:[$£€¥][\u0020\u00a0]*)?[+-]?(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?%?"
59
+ )
60
+ _EMAIL = re.compile(r"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b", re.IGNORECASE)
61
+ _IDENTIFIER = re.compile(
62
+ r"\b(?=[A-Z0-9_-]{4,}\b)(?=[A-Z0-9_-]*[A-Z])(?=[A-Z0-9_-]*\d)[A-Z0-9_-]+\b"
63
+ )
64
+ _QUOTED = re.compile(
65
+ r"[\"'\u201c\u201d\u2018\u2019\u300c\u300d]"
66
+ r"([^\"'\u201c\u201d\u2018\u2019\u300c\u300d]{2,80})"
67
+ r"[\"'\u201c\u201d\u2018\u2019\u300c\u300d]"
68
+ )
69
+ _CONSTRAINT_TERMS = re.compile(
70
+ r"\b(?:must|mustn't|must not|should|shouldn't|should not|only|without|before|after|"
71
+ r"at least|at most|no more than|do not|don't|cannot|can't|required|unless)\b|"
72
+ r"(?:必须|不得|不要|只能|仅限|至少|至多|之前|之后|除非)",
73
+ re.IGNORECASE,
74
+ )
75
+ _CLAUSE_SPLIT = re.compile(r"[\n.!?\u3002\uff01\uff1f;\uff1b]+")
76
+
77
+
78
+ def frozen_state_from_visible(value: Mapping[str, Any]) -> FrozenAgentState:
79
+ """Parse the dataset-neutral visible checkpoint schema into a frozen state."""
80
+
81
+ if not isinstance(value, Mapping):
82
+ raise ValidationError("visible state must be an object")
83
+ context: list[ContextBlock] = []
84
+ for raw in _sequence(value.get("context", ()), label="visible state context"):
85
+ if not isinstance(raw, Mapping) or not isinstance(raw.get("text"), str):
86
+ raise ValidationError("visible state context block is invalid")
87
+ context.append(
88
+ ContextBlock(
89
+ text=raw["text"],
90
+ block_id=str(raw.get("block_id", "")),
91
+ source=str(raw.get("source", "")),
92
+ score=raw.get("score"),
93
+ metadata=_mapping(raw.get("metadata", {}), label="context metadata"),
94
+ )
95
+ )
96
+ messages: list[Message] = []
97
+ for raw in _sequence(value.get("messages", ()), label="visible state messages"):
98
+ if not isinstance(raw, Mapping):
99
+ raise ValidationError("visible state message is invalid")
100
+ messages.append(
101
+ Message(
102
+ role=str(raw.get("role", "")),
103
+ content=str(raw.get("content", "")),
104
+ name=(str(raw["name"]) if raw.get("name") is not None else None),
105
+ )
106
+ )
107
+ raw_budget = _mapping(value.get("budget", {}), label="visible state budget")
108
+ budget_fields = {
109
+ name: raw_budget[name]
110
+ for name in (
111
+ "max_model_calls",
112
+ "max_retrieval_calls",
113
+ "max_tool_calls",
114
+ "max_output_tokens",
115
+ "max_context_tokens",
116
+ "max_cost_usd",
117
+ )
118
+ if name in raw_budget
119
+ }
120
+ tools = _sequence(value.get("tool_names", ()), label="visible state tool_names")
121
+ if any(not isinstance(item, str) or not item for item in tools):
122
+ raise ValidationError("visible state tool_names are invalid")
123
+ return FrozenAgentState(
124
+ query=str(value.get("query", "")),
125
+ task_id=str(value.get("task_id", "")),
126
+ instruction=str(value.get("instruction", "")),
127
+ context=tuple(context),
128
+ messages=tuple(messages),
129
+ tool_names=tuple(tools),
130
+ metadata=_mapping(value.get("metadata", {}), label="visible state metadata"),
131
+ budget=ExecutionBudget(**budget_fields),
132
+ )
133
+
134
+
135
+ def automatic_input_label(checkpoint: Mapping[str, Any]) -> dict[str, Any]:
136
+ """Assign deterministic defect and family-eligibility labels to one input."""
137
+
138
+ visible = checkpoint.get("visible_state")
139
+ if not isinstance(visible, Mapping):
140
+ raise ValidationError("checkpoint requires visible_state")
141
+ benchmark_id = _text(checkpoint.get("benchmark_id"), label="benchmark_id")
142
+ group_id = _text(checkpoint.get("group_id"), label="group_id")
143
+ checkpoint_id = _text(checkpoint.get("checkpoint_id"), label="checkpoint_id")
144
+ state = frozen_state_from_visible(visible)
145
+ observation, scores = _visible_observation_and_scores(state)
146
+ defects = {name: scores[name] >= _THRESHOLDS[name] for name in _DEFECT_FIELDS}
147
+ defects["low_defect_state"] = not any(defects.values())
148
+
149
+ metadata = _mapping(visible.get("metadata", {}), label="visible state metadata")
150
+ declared = metadata.get("eligible_families")
151
+ if declared is None:
152
+ declared = checkpoint.get("eligible_families")
153
+ declared_set = (
154
+ frozenset(str(value) for value in _sequence(declared, label="eligible_families"))
155
+ if declared is not None
156
+ else None
157
+ )
158
+ if declared_set is not None and not declared_set <= set(_FAMILIES):
159
+ raise ValidationError("checkpoint eligible_families contains an unknown family")
160
+ arena_common_support = benchmark_id in _KNOWN_MAIN_ARENAS or benchmark_id.startswith(
161
+ ("tau3.", "state_bench.", "toolsandbox.")
162
+ )
163
+ eligibility = {
164
+ f"{family}_eligible": (
165
+ family in declared_set if declared_set is not None else arena_common_support
166
+ )
167
+ for family in _FAMILIES
168
+ }
169
+ if not arena_common_support and declared_set is None:
170
+ # Conservative dataset-neutral fallback. It never reads gold or outcomes.
171
+ eligibility.update(
172
+ {
173
+ "reformulate_eligible": bool(state.query or state.instruction),
174
+ "decompose_eligible": bool(state.query or state.instruction),
175
+ "acquire_eligible": bool(state.tool_names or state.context),
176
+ "clarify_eligible": bool(state.messages or metadata.get("interactive", False)),
177
+ "curate_eligible": bool(state.context or state.messages),
178
+ }
179
+ )
180
+ primary = "low_defect_state"
181
+ if not defects["low_defect_state"]:
182
+ primary = max(_DEFECT_FIELDS, key=lambda name: (scores[name], name))
183
+ record = {
184
+ "schema_version": 1,
185
+ "protocol": AUTOMATIC_INPUT_LABEL_PROTOCOL,
186
+ "rule_revision": AUTOMATIC_MEASUREMENT_RULE_REVISION,
187
+ "benchmark_id": benchmark_id,
188
+ "checkpoint_id": checkpoint_id,
189
+ "group_id": group_id,
190
+ "visible_state_hash": state.state_hash,
191
+ "feature_schema_id": observation.provenance["schema_id"],
192
+ "feature_schema_hash": observation.provenance["schema_hash"],
193
+ "feature_hash": observation.feature_hash,
194
+ "defect_scores": {name: round(float(value), 8) for name, value in scores.items()},
195
+ "defect_labels": defects,
196
+ "primary_stratum": primary,
197
+ "eligibility_labels": eligibility,
198
+ "evidence": {
199
+ "benchmark_common_support": arena_common_support,
200
+ "declared_eligible_families_used": declared_set is not None,
201
+ "visible_signal_counts": observation.provenance["signals"],
202
+ "outcome_fields_accessed": False,
203
+ "gold_fields_accessed": False,
204
+ },
205
+ "human_audit_required_for_execution": False,
206
+ }
207
+ record["label_hash"] = content_hash(record)
208
+ return record
209
+
210
+
211
+ def visible_defect_scores(visible_state: Mapping[str, Any]) -> dict[str, float]:
212
+ """Return the frozen outcome-free defect scores for one visible state.
213
+
214
+ This is the public bridge used by runtime intervention measurement. It is
215
+ deliberately the same implementation used by :func:`automatic_input_label`
216
+ so a paper exporter cannot silently redefine a proximal target.
217
+ """
218
+
219
+ _observation, scores = _visible_observation_and_scores(frozen_state_from_visible(visible_state))
220
+ return {name: round(float(value), 8) for name, value in scores.items()}
221
+
222
+
223
+ def automatic_proximal_repair_quality(
224
+ *,
225
+ pre_state: Mapping[str, Any],
226
+ post_state: Mapping[str, Any],
227
+ candidate_family: str,
228
+ contract_retention: Mapping[str, float | bool],
229
+ action_evidence: float,
230
+ ) -> dict[str, Any]:
231
+ """Measure target-defect repair without reading an arena outcome.
232
+
233
+ The score is not an activation flag. It combines (i) reduction of the
234
+ family-matched visible defect, (ii) an explicit artifact signal only for
235
+ decomposition/clarification, whose artifacts are not represented by the
236
+ generic feature extractor, and (iii) the worst protected-contract
237
+ retention component. Contract loss is subtracted, so an aggressive edit
238
+ cannot receive positive repair quality merely because it activated.
239
+
240
+ The returned value lies in ``[-1, 1]`` and is a *proximal*, visible-state
241
+ construct. It never claims official task success or semantic correctness.
242
+ """
243
+
244
+ if candidate_family not in _FAMILY_TARGET_DEFECT:
245
+ raise ValidationError("repair quality candidate_family is invalid")
246
+ if isinstance(action_evidence, bool) or not isinstance(action_evidence, (int, float)):
247
+ raise ValidationError("repair quality action_evidence must be numeric")
248
+ evidence = float(action_evidence)
249
+ if not 0.0 <= evidence <= 1.0:
250
+ raise ValidationError("repair quality action_evidence must lie in [0, 1]")
251
+ required = {
252
+ "instruction_exactly_preserved",
253
+ "entity_retention",
254
+ "numeric_retention",
255
+ "constraint_retention",
256
+ }
257
+ if set(contract_retention) != required:
258
+ raise ValidationError("repair quality contract_retention fields are invalid")
259
+ instruction = contract_retention["instruction_exactly_preserved"]
260
+ if not isinstance(instruction, bool):
261
+ raise ValidationError("instruction_exactly_preserved must be boolean")
262
+ components = [float(instruction)]
263
+ for name in ("entity_retention", "numeric_retention", "constraint_retention"):
264
+ value = contract_retention[name]
265
+ if isinstance(value, bool) or not isinstance(value, (int, float)):
266
+ raise ValidationError(f"repair quality {name} must be numeric")
267
+ number = float(value)
268
+ if not 0.0 <= number <= 1.0:
269
+ raise ValidationError(f"repair quality {name} must lie in [0, 1]")
270
+ components.append(number)
271
+
272
+ before_scores = visible_defect_scores(pre_state)
273
+ after_scores = visible_defect_scores(post_state)
274
+ target = _FAMILY_TARGET_DEFECT[candidate_family]
275
+ raw_reduction = before_scores[target] - after_scores[target]
276
+ # A decomposition plan and a clarification request are intermediate
277
+ # artifacts rather than a state in which the underlying need disappears.
278
+ # For those two families only, credit the artifact in proportion to the
279
+ # pre-action target need. Merely editing/adding context in the other
280
+ # families receives no such fallback credit.
281
+ artifact_credit = (
282
+ before_scores[target] * evidence if candidate_family in {"decompose", "clarify"} else 0.0
283
+ )
284
+ target_repair = min(1.0, max(0.0, raw_reduction, artifact_credit))
285
+ retention_floor = min(components)
286
+ contract_loss = 1.0 - retention_floor
287
+ score = max(-1.0, min(1.0, target_repair * retention_floor - contract_loss))
288
+ result = {
289
+ "schema_version": 1,
290
+ "protocol": AUTOMATIC_REPAIR_QUALITY_PROTOCOL,
291
+ "rule_revision": AUTOMATIC_MEASUREMENT_RULE_REVISION,
292
+ "claim_scope": "outcome_blind_visible_state_proximal",
293
+ "candidate_family": candidate_family,
294
+ "target_defect": target,
295
+ "target_need_before": round(before_scores[target], 8),
296
+ "target_need_after": round(after_scores[target], 8),
297
+ "raw_target_defect_reduction": round(raw_reduction, 8),
298
+ "artifact_credit": round(artifact_credit, 8),
299
+ "action_evidence": round(evidence, 8),
300
+ "contract_retention_floor": round(retention_floor, 8),
301
+ "contract_loss": round(contract_loss, 8),
302
+ "repair_quality": round(score, 8),
303
+ "repair_success": score > 0.0,
304
+ "outcome_fields_accessed": False,
305
+ "gold_fields_accessed": False,
306
+ }
307
+ result["measurement_hash"] = content_hash(result)
308
+ return result
309
+
310
+
311
+ def _visible_observation_and_scores(
312
+ state: FrozenAgentState,
313
+ ) -> tuple[Any, dict[str, float]]:
314
+ observation = VisibleStateFeatureExtractor().extract(state)
315
+ feature = observation.features
316
+ return observation, {
317
+ "unclear_or_misaligned_request": max(
318
+ feature.reformulation_need_score,
319
+ 0.5 * feature.ambiguity_score,
320
+ ),
321
+ "decomposition_need": feature.multi_step_score,
322
+ "missing_external_evidence": feature.retrieval_need_score,
323
+ "clarification_need": feature.ambiguity_score,
324
+ "context_overload_or_noise": feature.context_pressure,
325
+ }
326
+
327
+
328
+ def infer_visible_contract(visible_state: Mapping[str, Any]) -> dict[str, Any]:
329
+ """Extract auditable entity, numeric, and constraint anchors from visible input."""
330
+
331
+ state = frozen_state_from_visible(visible_state)
332
+ # API catalogs describe tools, not the user's task. Treating JSON schema
333
+ # strings such as ``required`` or example IDs as intent anchors would make
334
+ # legal context curation look like task drift.
335
+ text = _contract_text(visible_state)
336
+ metadata = _mapping(visible_state.get("metadata", {}), label="visible state metadata")
337
+ explicit = metadata.get("intent_contract", {})
338
+ if explicit is None:
339
+ explicit = {}
340
+ explicit = _mapping(explicit, label="visible intent_contract")
341
+ entities = set(_strings(explicit.get("required_entities", ()), label="required_entities"))
342
+ entities.update(_EMAIL.findall(text))
343
+ entities.update(_IDENTIFIER.findall(text))
344
+ entities.update(match.group(1).strip() for match in _QUOTED.finditer(text))
345
+ constraints = set(
346
+ _strings(explicit.get("required_constraints", ()), label="required_constraints")
347
+ )
348
+ constraints.update(
349
+ clause.strip()
350
+ for clause in _CLAUSE_SPLIT.split(text)
351
+ if clause.strip() and _CONSTRAINT_TERMS.search(clause)
352
+ )
353
+ forbidden = set(
354
+ _strings(explicit.get("forbidden_assumptions", ()), label="forbidden_assumptions")
355
+ )
356
+ numbers = {_normalize_number(value) for value in _NUMBER.findall(text)}
357
+ contract = {
358
+ "required_entities": sorted(entities, key=str.casefold),
359
+ "required_numbers": sorted(numbers),
360
+ "required_constraints": sorted(constraints, key=str.casefold),
361
+ "forbidden_assumptions": sorted(forbidden, key=str.casefold),
362
+ "may_request_clarification": bool(explicit.get("may_request_clarification", True)),
363
+ "source_state_hash": state.state_hash,
364
+ "extraction_revision": AUTOMATIC_MEASUREMENT_RULE_REVISION,
365
+ }
366
+ contract["contract_hash"] = content_hash(contract)
367
+ return contract
368
+
369
+
370
+ def visible_contract_retention(
371
+ *,
372
+ pre_state: Mapping[str, Any],
373
+ post_state: Mapping[str, Any],
374
+ ) -> dict[str, float | bool | int | str]:
375
+ """Measure protected task-anchor retention without reading gold or outcomes."""
376
+
377
+ contract = infer_visible_contract(pre_state)
378
+ output_text = _visible_text(post_state)
379
+ output_numbers = {_normalize_number(value) for value in _NUMBER.findall(output_text)}
380
+
381
+ def phrase_retention(values: Sequence[str]) -> float:
382
+ if not values:
383
+ return 1.0
384
+ return sum(_contains_phrase(output_text, value) for value in values) / len(values)
385
+
386
+ entities = tuple(contract["required_entities"])
387
+ numbers = tuple(contract["required_numbers"])
388
+ constraints = tuple(contract["required_constraints"])
389
+ forbidden = tuple(contract["forbidden_assumptions"])
390
+ introduced_forbidden = sum(_contains_phrase(output_text, value) for value in forbidden)
391
+ constraint_retention = phrase_retention(constraints)
392
+ if introduced_forbidden:
393
+ constraint_retention = 0.0
394
+ return {
395
+ "instruction_exactly_preserved": str(pre_state.get("instruction", ""))
396
+ == str(post_state.get("instruction", "")),
397
+ "entity_retention": phrase_retention(entities),
398
+ "numeric_retention": (
399
+ 1.0 if not numbers else sum(value in output_numbers for value in numbers) / len(numbers)
400
+ ),
401
+ "constraint_retention": constraint_retention,
402
+ "required_entity_count": len(entities),
403
+ "required_number_count": len(numbers),
404
+ "required_constraint_count": len(constraints),
405
+ "introduced_forbidden_assumption_count": introduced_forbidden,
406
+ "protected_contract_hash": str(contract["contract_hash"]),
407
+ "extraction_revision": AUTOMATIC_MEASUREMENT_RULE_REVISION,
408
+ }
409
+
410
+
411
+ def automatic_trajectory_validity(record: Mapping[str, Any]) -> dict[str, Any]:
412
+ """Judge one observed trajectory with four deterministic contract checks."""
413
+
414
+ for name in (
415
+ "slot_id",
416
+ "group_id",
417
+ "benchmark_id",
418
+ "checkpoint_id",
419
+ "candidate_family",
420
+ ):
421
+ _text(record.get(name), label=f"trajectory {name}")
422
+ if record["candidate_family"] not in _FAMILIES:
423
+ raise ValidationError("trajectory candidate_family is invalid")
424
+ pre = record.get("pre_state")
425
+ if not isinstance(pre, Mapping):
426
+ raise ValidationError("trajectory requires pre_state")
427
+ raw_checkpoints = record.get("trajectory_checkpoints")
428
+ if raw_checkpoints is None and isinstance(record.get("post_state"), Mapping):
429
+ raw_checkpoints = [{"checkpoint_id": "final_state", "state": record["post_state"]}]
430
+ checkpoints = _sequence(raw_checkpoints, label="trajectory_checkpoints")
431
+ if not checkpoints:
432
+ raise ValidationError("trajectory requires at least one observed checkpoint")
433
+ contract = record.get("protected_contract")
434
+ if contract is None:
435
+ contract = infer_visible_contract(pre)
436
+ contract = _validated_contract(contract)
437
+ results = []
438
+ for raw in checkpoints:
439
+ if not isinstance(raw, Mapping) or not isinstance(raw.get("state"), Mapping):
440
+ raise ValidationError("trajectory checkpoint is invalid")
441
+ checkpoint_name = _text(raw.get("checkpoint_id"), label="trajectory checkpoint_id")
442
+ output_text = _visible_text(raw["state"])
443
+ missing_entities = [
444
+ value
445
+ for value in contract["required_entities"]
446
+ if not _contains_phrase(output_text, value)
447
+ ]
448
+ output_numbers = {_normalize_number(value) for value in _NUMBER.findall(output_text)}
449
+ missing_numbers = [
450
+ value for value in contract["required_numbers"] if value not in output_numbers
451
+ ]
452
+ missing_constraints = [
453
+ value
454
+ for value in contract["required_constraints"]
455
+ if not _contains_phrase(output_text, value)
456
+ ]
457
+ introduced = [
458
+ value
459
+ for value in contract["forbidden_assumptions"]
460
+ if _contains_phrase(output_text, value)
461
+ ]
462
+ contract_diff = {
463
+ "missing_entities": missing_entities,
464
+ "missing_numbers": missing_numbers,
465
+ "missing_constraints": missing_constraints,
466
+ "introduced_forbidden_assumptions": introduced,
467
+ }
468
+ checks = {
469
+ "contract_diff": not any(contract_diff.values()),
470
+ "entity_preservation": not missing_entities,
471
+ "numeric_preservation": not missing_numbers,
472
+ "constraint_preservation": not missing_constraints and not introduced,
473
+ }
474
+ results.append(
475
+ {
476
+ "checkpoint_id": checkpoint_name,
477
+ "checks": checks,
478
+ "diff": contract_diff,
479
+ "valid": all(checks.values()),
480
+ }
481
+ )
482
+ result = {
483
+ "schema_version": 1,
484
+ "protocol": AUTOMATIC_TRAJECTORY_PROTOCOL,
485
+ "rule_revision": AUTOMATIC_MEASUREMENT_RULE_REVISION,
486
+ "slot_id": record["slot_id"],
487
+ "group_id": record["group_id"],
488
+ "benchmark_id": record["benchmark_id"],
489
+ "checkpoint_id": record["checkpoint_id"],
490
+ "candidate_family": record["candidate_family"],
491
+ "protected_contract": contract,
492
+ "checkpoint_results": results,
493
+ "auto_contract_valid": all(row["valid"] for row in results),
494
+ "validity_stratum": (
495
+ "valid" if all(row["valid"] for row in results) else "contract_violation"
496
+ ),
497
+ "contract_anchor_count": sum(
498
+ len(contract[name])
499
+ for name in (
500
+ "required_entities",
501
+ "required_numbers",
502
+ "required_constraints",
503
+ "forbidden_assumptions",
504
+ )
505
+ ),
506
+ "human_audit_required_for_execution": False,
507
+ }
508
+ result["measurement_hash"] = content_hash(result)
509
+ return result
510
+
511
+
512
+ def deterministic_stratified_sample(
513
+ records: Sequence[Mapping[str, Any]],
514
+ *,
515
+ count: int,
516
+ seed: int,
517
+ strata: Sequence[str],
518
+ ) -> list[Mapping[str, Any]]:
519
+ """Select an exact, reproducible, proportionally stratified audit sample."""
520
+
521
+ if isinstance(count, bool) or not isinstance(count, int) or count < 1:
522
+ raise ValidationError("audit sample count must be a positive integer")
523
+ if isinstance(seed, bool) or not isinstance(seed, int) or seed < 0:
524
+ raise ValidationError("audit sample seed must be a non-negative integer")
525
+ if not strata:
526
+ raise ValidationError("audit sample requires strata fields")
527
+ values = list(records)
528
+ if count > len(values):
529
+ raise ValidationError("audit sample count exceeds the record census")
530
+ groups: dict[tuple[str, ...], list[Mapping[str, Any]]] = defaultdict(list)
531
+ for row in values:
532
+ key = tuple(_text(row.get(field), label=f"audit stratum {field}") for field in strata)
533
+ groups[key].append(row)
534
+ for key, rows in groups.items():
535
+ rows.sort(key=lambda row: _stable_order(seed, key, row))
536
+ allocations = {key: 0 for key in groups}
537
+ if count >= len(groups):
538
+ for key in groups:
539
+ allocations[key] = 1
540
+ remaining = count - sum(allocations.values())
541
+ population = len(values)
542
+ while remaining:
543
+ candidates = [key for key, rows in groups.items() if allocations[key] < len(rows)]
544
+ if not candidates: # pragma: no cover - count/census invariant
545
+ raise AssertionError("audit allocation exhausted before reaching target")
546
+ key = max(
547
+ candidates,
548
+ key=lambda item: (
549
+ len(groups[item]) * count / population - allocations[item],
550
+ -int(hashlib.sha256(f"{seed}:{item}".encode()).hexdigest(), 16),
551
+ ),
552
+ )
553
+ allocations[key] += 1
554
+ remaining -= 1
555
+ selected = [row for key, rows in groups.items() for row in rows[: allocations[key]]]
556
+ return sorted(selected, key=lambda row: _stable_order(seed, ("final",), row))
557
+
558
+
559
+ def audit_summary(records: Sequence[Mapping[str, Any]], *, strata: Sequence[str]) -> dict[str, Any]:
560
+ counts = Counter(tuple(str(row[field]) for field in strata) for row in records)
561
+ return {"|".join(key): value for key, value in sorted(counts.items())}
562
+
563
+
564
+ def _validated_contract(value: Any) -> dict[str, Any]:
565
+ raw = _mapping(value, label="protected_contract")
566
+ required = {
567
+ "required_entities",
568
+ "required_numbers",
569
+ "required_constraints",
570
+ "forbidden_assumptions",
571
+ }
572
+ contract = {name: list(_strings(raw.get(name, ()), label=name)) for name in required}
573
+ contract.update(
574
+ {
575
+ "may_request_clarification": bool(raw.get("may_request_clarification", True)),
576
+ "source_state_hash": str(raw.get("source_state_hash", "")),
577
+ "extraction_revision": str(
578
+ raw.get("extraction_revision", AUTOMATIC_MEASUREMENT_RULE_REVISION)
579
+ ),
580
+ }
581
+ )
582
+ expected_hash = raw.get("contract_hash")
583
+ contract["contract_hash"] = content_hash(contract)
584
+ if expected_hash is not None and expected_hash != contract["contract_hash"]:
585
+ raise ValidationError("protected_contract hash mismatch")
586
+ return contract
587
+
588
+
589
+ def _visible_text(value: Mapping[str, Any]) -> str:
590
+ parts = [str(value.get("instruction", "")), str(value.get("query", ""))]
591
+ for block in _sequence(value.get("context", ()), label="state context"):
592
+ if isinstance(block, Mapping):
593
+ parts.append(str(block.get("text", "")))
594
+ for message in _sequence(value.get("messages", ()), label="state messages"):
595
+ if isinstance(message, Mapping):
596
+ parts.append(str(message.get("content", "")))
597
+ return "\n".join(part for part in parts if part)
598
+
599
+
600
+ def _contract_text(value: Mapping[str, Any]) -> str:
601
+ """Return task-bearing visible text while excluding structural tool catalogs."""
602
+
603
+ parts = [str(value.get("instruction", "")), str(value.get("query", ""))]
604
+ for block in _sequence(value.get("context", ()), label="state context"):
605
+ if not isinstance(block, Mapping):
606
+ continue
607
+ block_id = str(block.get("block_id", "")).casefold()
608
+ source = str(block.get("source", "")).casefold()
609
+ if block_id == "official_tool_catalog" or any(
610
+ marker in source
611
+ for marker in ("tool_schema", "tool_catalog", ".tools", "starting_context")
612
+ ):
613
+ continue
614
+ parts.append(str(block.get("text", "")))
615
+ for message in _sequence(value.get("messages", ()), label="state messages"):
616
+ if isinstance(message, Mapping):
617
+ parts.append(str(message.get("content", "")))
618
+ return "\n".join(part for part in parts if part)
619
+
620
+
621
+ def _normalize_number(value: str) -> str:
622
+ return value.replace(",", "").replace("\u00a0", "").strip().casefold()
623
+
624
+
625
+ def _contains_phrase(text: str, phrase: str) -> bool:
626
+ tokens = tuple(re.findall(r"\w+", text.casefold(), flags=re.UNICODE))
627
+ phrase_tokens = tuple(re.findall(r"\w+", phrase.casefold(), flags=re.UNICODE))
628
+ width = len(phrase_tokens)
629
+ return bool(width) and any(
630
+ tokens[index : index + width] == phrase_tokens for index in range(len(tokens) - width + 1)
631
+ )
632
+
633
+
634
+ def _stable_order(seed: int, stratum: tuple[str, ...], row: Mapping[str, Any]) -> str:
635
+ identity = row.get("label_hash", row.get("measurement_hash", row.get("group_id")))
636
+ return hashlib.sha256(f"{seed}:{stratum}:{identity}".encode()).hexdigest()
637
+
638
+
639
+ def _mapping(value: Any, *, label: str) -> Mapping[str, Any]:
640
+ if not isinstance(value, Mapping):
641
+ raise ValidationError(f"{label} must be an object")
642
+ return value
643
+
644
+
645
+ def _sequence(value: Any, *, label: str) -> Sequence[Any]:
646
+ if isinstance(value, (str, bytes)) or not isinstance(value, Sequence):
647
+ raise ValidationError(f"{label} must be an array")
648
+ return value
649
+
650
+
651
+ def _strings(value: Any, *, label: str) -> tuple[str, ...]:
652
+ values = _sequence(value, label=label)
653
+ if any(not isinstance(item, str) or not item.strip() for item in values):
654
+ raise ValidationError(f"{label} must contain non-empty strings")
655
+ return tuple(item.strip() for item in values)
656
+
657
+
658
+ def _text(value: Any, *, label: str) -> str:
659
+ if not isinstance(value, str) or not value.strip():
660
+ raise ValidationError(f"{label} must be a non-empty string")
661
+ return value.strip()
662
+
663
+
664
+ __all__ = [
665
+ "AUTOMATIC_INPUT_LABEL_PROTOCOL",
666
+ "AUTOMATIC_MEASUREMENT_RULE_REVISION",
667
+ "AUTOMATIC_REPAIR_QUALITY_PROTOCOL",
668
+ "AUTOMATIC_TRAJECTORY_PROTOCOL",
669
+ "audit_summary",
670
+ "automatic_input_label",
671
+ "automatic_proximal_repair_quality",
672
+ "automatic_trajectory_validity",
673
+ "deterministic_stratified_sample",
674
+ "frozen_state_from_visible",
675
+ "infer_visible_contract",
676
+ "visible_contract_retention",
677
+ "visible_defect_scores",
678
+ ]