loopx 0.4.8__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 (811) hide show
  1. loopx/__init__.py +5 -0
  2. loopx/agent_onboarding.py +654 -0
  3. loopx/agent_registry.py +112 -0
  4. loopx/ark_managed_agent_host.py +59 -0
  5. loopx/authority.py +805 -0
  6. loopx/benchmark.py +2875 -0
  7. loopx/benchmark_adapters/__init__.py +1 -0
  8. loopx/benchmark_adapters/agentissue.py +2644 -0
  9. loopx/benchmark_adapters/agents_last_exam.py +3998 -0
  10. loopx/benchmark_adapters/edgebench.py +322 -0
  11. loopx/benchmark_adapters/skillsbench.py +5978 -0
  12. loopx/benchmark_adapters/skillsbench_acp_failure_policy.py +143 -0
  13. loopx/benchmark_adapters/skillsbench_acp_process.py +31 -0
  14. loopx/benchmark_adapters/skillsbench_acp_relay.py +4832 -0
  15. loopx/benchmark_adapters/skillsbench_batch.py +124 -0
  16. loopx/benchmark_adapters/skillsbench_bridge_guard.py +209 -0
  17. loopx/benchmark_adapters/skillsbench_bridge_summary.py +203 -0
  18. loopx/benchmark_adapters/skillsbench_codex_goal_recovery.py +271 -0
  19. loopx/benchmark_adapters/skillsbench_codex_goal_trace.py +81 -0
  20. loopx/benchmark_adapters/skillsbench_codex_runtime.py +339 -0
  21. loopx/benchmark_adapters/skillsbench_dockerfile_runtime.py +467 -0
  22. loopx/benchmark_adapters/skillsbench_failure_signals.py +652 -0
  23. loopx/benchmark_adapters/skillsbench_proxy_runtime.py +327 -0
  24. loopx/benchmark_adapters/skillsbench_remote_bridge.py +402 -0
  25. loopx/benchmark_adapters/skillsbench_result_discovery.py +143 -0
  26. loopx/benchmark_adapters/skillsbench_runner_profile.py +436 -0
  27. loopx/benchmark_adapters/skillsbench_runner_source.py +99 -0
  28. loopx/benchmark_adapters/skillsbench_setup_preflight.py +771 -0
  29. loopx/benchmark_adapters/skillsbench_signals.py +15 -0
  30. loopx/benchmark_adapters/skillsbench_task_source.py +141 -0
  31. loopx/benchmark_adapters/skillsbench_turn_route.py +723 -0
  32. loopx/benchmark_adapters/skillsbench_turn_runtime.py +1069 -0
  33. loopx/benchmark_adapters/skillsbench_typed_repair.py +689 -0
  34. loopx/benchmark_adapters/skillsbench_uv_cache.py +111 -0
  35. loopx/benchmark_adapters/skillsbench_verifier_bootstrap.py +227 -0
  36. loopx/benchmark_adapters/skillsbench_verifier_cache.py +138 -0
  37. loopx/benchmark_adapters/terminal_bench.py +10078 -0
  38. loopx/benchmark_case_analysis.py +1276 -0
  39. loopx/benchmark_case_state.py +1079 -0
  40. loopx/benchmark_core/__init__.py +239 -0
  41. loopx/benchmark_core/adapter.py +84 -0
  42. loopx/benchmark_core/artifacts.py +517 -0
  43. loopx/benchmark_core/attempts.py +199 -0
  44. loopx/benchmark_core/container_exec.py +216 -0
  45. loopx/benchmark_core/io.py +68 -0
  46. loopx/benchmark_core/lifecycle.py +211 -0
  47. loopx/benchmark_core/loop_protocol.py +689 -0
  48. loopx/benchmark_core/observable_handles.py +348 -0
  49. loopx/benchmark_core/parity.py +256 -0
  50. loopx/benchmark_core/remote_closeout.py +482 -0
  51. loopx/benchmark_core/rounds.py +215 -0
  52. loopx/benchmark_core/route_profile.py +509 -0
  53. loopx/benchmark_core/run_permissions.py +206 -0
  54. loopx/benchmark_core/split_control.py +925 -0
  55. loopx/benchmark_core/turn_fidelity.py +326 -0
  56. loopx/benchmark_ledger.py +3793 -0
  57. loopx/benchmark_ledger_countability.py +372 -0
  58. loopx/benchmark_ledger_current.py +724 -0
  59. loopx/benchmark_trajectory.py +405 -0
  60. loopx/benchmarks/__init__.py +1 -0
  61. loopx/benchmarks/qualification/__init__.py +1 -0
  62. loopx/benchmarks/qualification/release_outcome_baseline.py +360 -0
  63. loopx/benchmarks/read_models/__init__.py +1 -0
  64. loopx/benchmarks/read_models/benchmark_attempt_accounting.py +53 -0
  65. loopx/benchmarks/read_models/benchmark_comparison.py +414 -0
  66. loopx/benchmarks/read_models/benchmark_event_timeline.py +113 -0
  67. loopx/benchmarks/read_models/benchmark_experiment_report.py +475 -0
  68. loopx/benchmarks/read_models/benchmark_learning_ledger.py +137 -0
  69. loopx/benchmarks/read_models/benchmark_lifecycle_contracts.py +228 -0
  70. loopx/benchmarks/read_models/benchmark_projection.py +723 -0
  71. loopx/benchmarks/read_models/benchmark_result.py +146 -0
  72. loopx/benchmarks/read_models/benchmark_run_execution_contract.py +116 -0
  73. loopx/benchmarks/read_models/benchmark_run_failure.py +157 -0
  74. loopx/benchmarks/read_models/benchmark_run_metrics.py +213 -0
  75. loopx/benchmarks/read_models/benchmark_run_post_execution.py +635 -0
  76. loopx/benchmarks/read_models/benchmark_run_pre_execution.py +541 -0
  77. loopx/benchmarks/read_models/benchmark_status_compaction.py +1255 -0
  78. loopx/benchmarks/read_models/benchmark_status_runner.py +780 -0
  79. loopx/benchmarks/read_models/goal_start_control_score.py +857 -0
  80. loopx/benchmarks/read_models/skillsbench_post_run_debug.py +746 -0
  81. loopx/benchmarks/read_models/skillsbench_verifier_attribution.py +269 -0
  82. loopx/bootstrap.py +1116 -0
  83. loopx/bootstrap_command_pack.py +2167 -0
  84. loopx/boundary_authority.py +199 -0
  85. loopx/canary/__init__.py +1 -0
  86. loopx/canary/maintainability_ratchet.py +800 -0
  87. loopx/canary/planner.py +1984 -0
  88. loopx/canary/premerge.py +1130 -0
  89. loopx/canary/qualification_profiles.py +309 -0
  90. loopx/canary/quality_surface_catalog.py +838 -0
  91. loopx/canary/release_profiles.py +51 -0
  92. loopx/canary/runner.py +1107 -0
  93. loopx/canary/smoke_health.py +581 -0
  94. loopx/canary/smoke_profiles.py +212 -0
  95. loopx/capabilities/__init__.py +0 -0
  96. loopx/capabilities/agent_turn_recall/__init__.py +17 -0
  97. loopx/capabilities/agent_turn_recall/cli.py +369 -0
  98. loopx/capabilities/agent_turn_recall/core.py +296 -0
  99. loopx/capabilities/auto_research/__init__.py +16 -0
  100. loopx/capabilities/auto_research/bootstrap_contract.py +157 -0
  101. loopx/capabilities/auto_research/cli.py +1468 -0
  102. loopx/capabilities/auto_research/core.py +11 -0
  103. loopx/capabilities/auto_research/defaults.py +79 -0
  104. loopx/capabilities/auto_research/demo_e2e.py +1848 -0
  105. loopx/capabilities/auto_research/demo_supervisor.py +186 -0
  106. loopx/capabilities/auto_research/evidence_packet.py +767 -0
  107. loopx/capabilities/auto_research/human_view.py +794 -0
  108. loopx/capabilities/auto_research/kernel.py +191 -0
  109. loopx/capabilities/auto_research/knn_demo_workspace.py +322 -0
  110. loopx/capabilities/auto_research/live_evidence.py +248 -0
  111. loopx/capabilities/auto_research/preset.py +176 -0
  112. loopx/capabilities/auto_research/research_state.py +1085 -0
  113. loopx/capabilities/auto_research/role_profiles.py +394 -0
  114. loopx/capabilities/auto_research/rollout_append.py +97 -0
  115. loopx/capabilities/auto_research/terminal_result_contract.py +422 -0
  116. loopx/capabilities/auto_research/terminal_result_projection.py +171 -0
  117. loopx/capabilities/auto_research/terminal_result_query.py +233 -0
  118. loopx/capabilities/auto_research/terminal_results.py +349 -0
  119. loopx/capabilities/auto_research/user_contract.py +190 -0
  120. loopx/capabilities/auto_research/worker_loop.py +163 -0
  121. loopx/capabilities/auto_research/worker_runtime.py +777 -0
  122. loopx/capabilities/auto_research/worker_skill/SKILL.md +343 -0
  123. loopx/capabilities/benchmark_toolkit/__init__.py +19 -0
  124. loopx/capabilities/benchmark_toolkit/integrity.py +387 -0
  125. loopx/capabilities/catalog.py +1875 -0
  126. loopx/capabilities/change_quality/__init__.py +19 -0
  127. loopx/capabilities/change_quality/cli.py +171 -0
  128. loopx/capabilities/change_quality/context.py +156 -0
  129. loopx/capabilities/change_quality/oracles.py +269 -0
  130. loopx/capabilities/change_quality/policy.py +34 -0
  131. loopx/capabilities/change_quality/receipt.py +482 -0
  132. loopx/capabilities/change_quality/result.py +493 -0
  133. loopx/capabilities/change_quality/scope.py +171 -0
  134. loopx/capabilities/change_quality/shadow.py +680 -0
  135. loopx/capabilities/content_ops/__init__.py +0 -0
  136. loopx/capabilities/content_ops/cli.py +649 -0
  137. loopx/capabilities/content_ops/connector_packets.py +164 -0
  138. loopx/capabilities/content_ops/item_lifecycle.py +1000 -0
  139. loopx/capabilities/content_ops/layout.py +451 -0
  140. loopx/capabilities/content_ops/markdown.py +456 -0
  141. loopx/capabilities/content_ops/schemas.py +51 -0
  142. loopx/capabilities/content_ops/social_browser_x.py +107 -0
  143. loopx/capabilities/content_ops/surface.py +1956 -0
  144. loopx/capabilities/content_ops/templates/layout-catalog-v0.json +72 -0
  145. loopx/capabilities/context_providers/__init__.py +36 -0
  146. loopx/capabilities/context_providers/base.py +189 -0
  147. loopx/capabilities/context_providers/factory.py +32 -0
  148. loopx/capabilities/context_providers/openviking.py +702 -0
  149. loopx/capabilities/context_providers/service_ownership.py +185 -0
  150. loopx/capabilities/decision_context/__init__.py +129 -0
  151. loopx/capabilities/decision_context/architecture.py +83 -0
  152. loopx/capabilities/decision_context/assembler.py +849 -0
  153. loopx/capabilities/decision_context/catalog_entry.py +195 -0
  154. loopx/capabilities/decision_context/cli.py +310 -0
  155. loopx/capabilities/decision_context/cursor_commit.py +535 -0
  156. loopx/capabilities/decision_context/outcome_feedback.py +352 -0
  157. loopx/capabilities/decision_context/packets.py +654 -0
  158. loopx/capabilities/decision_context/private_state.py +189 -0
  159. loopx/capabilities/decision_context/profile.py +453 -0
  160. loopx/capabilities/decision_context/providers.py +228 -0
  161. loopx/capabilities/decision_context/review_settlement.py +136 -0
  162. loopx/capabilities/decision_context/runtime.py +273 -0
  163. loopx/capabilities/decision_context/sources.py +415 -0
  164. loopx/capabilities/explore/__init__.py +1 -0
  165. loopx/capabilities/explore/activation.py +198 -0
  166. loopx/capabilities/explore/adaptive_replay_planner.py +221 -0
  167. loopx/capabilities/explore/child_replay_runtime.py +463 -0
  168. loopx/capabilities/explore/composition_frontier.py +291 -0
  169. loopx/capabilities/explore/counterfactual_runtime.py +578 -0
  170. loopx/capabilities/explore/episode_runtime.py +647 -0
  171. loopx/capabilities/explore/harness_checkpoint.py +171 -0
  172. loopx/capabilities/explore/harness_gate.py +115 -0
  173. loopx/capabilities/explore/harness_runtime.py +1124 -0
  174. loopx/capabilities/explore/replay_metrics.py +206 -0
  175. loopx/capabilities/explore/replay_runtime.py +1271 -0
  176. loopx/capabilities/explore/resource_portfolio.py +173 -0
  177. loopx/capabilities/explore/result_log.py +974 -0
  178. loopx/capabilities/explore/router_state.py +432 -0
  179. loopx/capabilities/explore/source_history_reconcile.py +255 -0
  180. loopx/capabilities/explore/speculative_scheduler.py +498 -0
  181. loopx/capabilities/explore/todo_branch_plan.py +650 -0
  182. loopx/capabilities/explore/todo_evidence.py +141 -0
  183. loopx/capabilities/explore/trace_runtime.py +284 -0
  184. loopx/capabilities/explore/worker_branch_plan.py +1257 -0
  185. loopx/capabilities/integration_branch/__init__.py +13 -0
  186. loopx/capabilities/integration_branch/cli.py +148 -0
  187. loopx/capabilities/integration_branch/core.py +916 -0
  188. loopx/capabilities/issue_fix/__init__.py +19 -0
  189. loopx/capabilities/issue_fix/acceptance_loop.py +1050 -0
  190. loopx/capabilities/issue_fix/candidate_evidence.py +503 -0
  191. loopx/capabilities/issue_fix/candidate_preflight.py +676 -0
  192. loopx/capabilities/issue_fix/cli.py +1822 -0
  193. loopx/capabilities/issue_fix/cli_input.py +87 -0
  194. loopx/capabilities/issue_fix/content_ops_cli.py +148 -0
  195. loopx/capabilities/issue_fix/discovered_issue_promotion.py +947 -0
  196. loopx/capabilities/issue_fix/explore_projection.py +710 -0
  197. loopx/capabilities/issue_fix/feasibility.py +542 -0
  198. loopx/capabilities/issue_fix/github_public.py +661 -0
  199. loopx/capabilities/issue_fix/intake_surface.py +832 -0
  200. loopx/capabilities/issue_fix/metadata_preview.py +218 -0
  201. loopx/capabilities/issue_fix/metrics_projection.py +1340 -0
  202. loopx/capabilities/issue_fix/metrics_supplement.py +634 -0
  203. loopx/capabilities/issue_fix/metrics_supplement_cli.py +127 -0
  204. loopx/capabilities/issue_fix/outcome_projection.py +1235 -0
  205. loopx/capabilities/issue_fix/periodic_report.py +189 -0
  206. loopx/capabilities/issue_fix/pr_description.py +418 -0
  207. loopx/capabilities/issue_fix/pr_gate_reconcile.py +496 -0
  208. loopx/capabilities/issue_fix/pr_gate_reconcile_cli.py +464 -0
  209. loopx/capabilities/issue_fix/pr_lifecycle.py +1327 -0
  210. loopx/capabilities/issue_fix/pr_lifecycle_rollout.py +85 -0
  211. loopx/capabilities/issue_fix/pr_monitor_materialization.py +257 -0
  212. loopx/capabilities/issue_fix/pr_review_ack.py +439 -0
  213. loopx/capabilities/issue_fix/provider_hooks.py +24 -0
  214. loopx/capabilities/issue_fix/repository_commit_evidence.py +186 -0
  215. loopx/capabilities/issue_fix/repository_context.py +457 -0
  216. loopx/capabilities/issue_fix/repository_memory.py +459 -0
  217. loopx/capabilities/issue_fix/repository_memory_provider.py +1454 -0
  218. loopx/capabilities/issue_fix/repository_snapshot.py +454 -0
  219. loopx/capabilities/issue_fix/reviewer_cli.py +917 -0
  220. loopx/capabilities/issue_fix/reviewer_notification.py +882 -0
  221. loopx/capabilities/issue_fix/reviewer_notification_drain.py +942 -0
  222. loopx/capabilities/issue_fix/reviewer_recommendation.py +1057 -0
  223. loopx/capabilities/issue_fix/reviewer_request.py +1282 -0
  224. loopx/capabilities/issue_fix/reward_memory.py +879 -0
  225. loopx/capabilities/issue_fix/workflow_plan.py +1286 -0
  226. loopx/capabilities/material_lifecycle/__init__.py +161 -0
  227. loopx/capabilities/material_lifecycle/_validation.py +183 -0
  228. loopx/capabilities/material_lifecycle/apply.py +672 -0
  229. loopx/capabilities/material_lifecycle/architecture.py +122 -0
  230. loopx/capabilities/material_lifecycle/cli.py +161 -0
  231. loopx/capabilities/material_lifecycle/decision_planning.py +470 -0
  232. loopx/capabilities/material_lifecycle/explore_execution.py +306 -0
  233. loopx/capabilities/material_lifecycle/intake.py +869 -0
  234. loopx/capabilities/material_lifecycle/inventory.py +147 -0
  235. loopx/capabilities/material_lifecycle/lifecycle.py +98 -0
  236. loopx/capabilities/material_lifecycle/preparation.py +147 -0
  237. loopx/capabilities/material_lifecycle/project_skill.py +83 -0
  238. loopx/capabilities/material_lifecycle/ranking.py +267 -0
  239. loopx/capabilities/material_lifecycle/readable_projection.py +500 -0
  240. loopx/capabilities/material_lifecycle/rebuild.py +480 -0
  241. loopx/capabilities/material_lifecycle/settlement.py +238 -0
  242. loopx/capabilities/periodic_report/__init__.py +71 -0
  243. loopx/capabilities/periodic_report/adapters.py +939 -0
  244. loopx/capabilities/periodic_report/archive.py +422 -0
  245. loopx/capabilities/periodic_report/bindings.py +705 -0
  246. loopx/capabilities/periodic_report/cli.py +277 -0
  247. loopx/capabilities/periodic_report/core.py +691 -0
  248. loopx/capabilities/periodic_report/extension_envelope.py +66 -0
  249. loopx/capabilities/periodic_report/presets.py +103 -0
  250. loopx/capabilities/periodic_report/profile.py +235 -0
  251. loopx/capabilities/periodic_report/project_progress.py +179 -0
  252. loopx/capabilities/periodic_report/triggers.py +452 -0
  253. loopx/capabilities/pr_review_queue/__init__.py +17 -0
  254. loopx/capabilities/pr_review_queue/core.py +506 -0
  255. loopx/capabilities/pr_review_queue/review_contract.py +506 -0
  256. loopx/capabilities/registry.py +192 -0
  257. loopx/capabilities/reward_memory/__init__.py +75 -0
  258. loopx/capabilities/reward_memory/application.py +819 -0
  259. loopx/capabilities/reward_memory/architecture.py +572 -0
  260. loopx/capabilities/reward_memory/candidate_review.py +511 -0
  261. loopx/capabilities/reward_memory/cli.py +469 -0
  262. loopx/capabilities/reward_memory/dogfood.py +574 -0
  263. loopx/capabilities/reward_memory/evaluation.py +296 -0
  264. loopx/capabilities/reward_memory/evaluation_fixtures.py +362 -0
  265. loopx/capabilities/reward_memory/experiment.py +567 -0
  266. loopx/capabilities/reward_memory/health.py +222 -0
  267. loopx/capabilities/reward_memory/ingestion.py +519 -0
  268. loopx/capabilities/reward_memory/registry.py +600 -0
  269. loopx/capabilities/reward_memory/runtime_hooks.py +312 -0
  270. loopx/capabilities/reward_memory/scoped_feedback.py +173 -0
  271. loopx/capabilities/semantic_preference/__init__.py +12 -0
  272. loopx/capabilities/semantic_preference/cli.py +189 -0
  273. loopx/capabilities/semantic_preference/contract.py +592 -0
  274. loopx/capabilities/semantic_preference/reward_memory.py +62 -0
  275. loopx/capabilities/value_connectors/__init__.py +1 -0
  276. loopx/capabilities/value_connectors/cli.py +401 -0
  277. loopx/capabilities/value_connectors/finance_extension_migration.py +108 -0
  278. loopx/capabilities/value_connectors/install_check.py +147 -0
  279. loopx/capabilities/value_connectors/planner.py +733 -0
  280. loopx/capabilities/value_connectors/source_map.py +446 -0
  281. loopx/claude_goal_baseline.py +138 -0
  282. loopx/claude_goal_mode/__init__.py +23 -0
  283. loopx/claude_goal_mode/hooks/goal_policy.py +212 -0
  284. loopx/claude_goal_mode/hooks/goal_state.py +139 -0
  285. loopx/claude_goal_mode/mcp/loopx_mcp.py +167 -0
  286. loopx/claude_goal_mode/scripts/connect.py +103 -0
  287. loopx/claude_goal_mode/scripts/goalmode_cmd.py +241 -0
  288. loopx/claude_goal_mode/scripts/install.py +328 -0
  289. loopx/claude_goal_mode/statusline/goal_status.py +97 -0
  290. loopx/cli.py +836 -0
  291. loopx/cli_commands/__init__.py +334 -0
  292. loopx/cli_commands/_host_thread.py +13 -0
  293. loopx/cli_commands/agentissue_runner_flow.py +447 -0
  294. loopx/cli_commands/agents_last_exam.py +160 -0
  295. loopx/cli_commands/agents_last_exam_baked_input.py +302 -0
  296. loopx/cli_commands/agents_last_exam_host_codex.py +374 -0
  297. loopx/cli_commands/agents_last_exam_launch_dry_run.py +372 -0
  298. loopx/cli_commands/agents_last_exam_local_plan.py +322 -0
  299. loopx/cli_commands/agents_last_exam_runner_source.py +352 -0
  300. loopx/cli_commands/agents_last_exam_task_material.py +335 -0
  301. loopx/cli_commands/agents_last_exam_validation_gate.py +236 -0
  302. loopx/cli_commands/benchmark_boundary.py +499 -0
  303. loopx/cli_commands/benchmark_dispatch.py +161 -0
  304. loopx/cli_commands/benchmark_release_outcome.py +123 -0
  305. loopx/cli_commands/benchmark_review_lifecycle.py +1275 -0
  306. loopx/cli_commands/benchmark_run_ledger.py +763 -0
  307. loopx/cli_commands/benchmark_run_ledger_case_analysis.py +249 -0
  308. loopx/cli_commands/benchmark_run_ledger_classification.py +45 -0
  309. loopx/cli_commands/benchmark_run_ledger_maintenance.py +486 -0
  310. loopx/cli_commands/benchmark_run_ledger_maintenance_registration.py +342 -0
  311. loopx/cli_commands/benchmark_run_ledger_maintenance_rendering.py +233 -0
  312. loopx/cli_commands/benchmark_run_ledger_parity.py +92 -0
  313. loopx/cli_commands/bootstrap_connect.py +238 -0
  314. loopx/cli_commands/canary.py +707 -0
  315. loopx/cli_commands/canary_release_qualification.py +79 -0
  316. loopx/cli_commands/capability.py +96 -0
  317. loopx/cli_commands/doctor.py +43 -0
  318. loopx/cli_commands/dreaming.py +143 -0
  319. loopx/cli_commands/edgebench.py +205 -0
  320. loopx/cli_commands/evidence_log.py +275 -0
  321. loopx/cli_commands/explore.py +989 -0
  322. loopx/cli_commands/explore_planning_commands.py +157 -0
  323. loopx/cli_commands/extension.py +271 -0
  324. loopx/cli_commands/first_run_report.py +73 -0
  325. loopx/cli_commands/goal_channel.py +656 -0
  326. loopx/cli_commands/handoff_mode.py +158 -0
  327. loopx/cli_commands/history.py +622 -0
  328. loopx/cli_commands/host_mode_plan.py +113 -0
  329. loopx/cli_commands/lark_inbox.py +431 -0
  330. loopx/cli_commands/lark_kanban.py +629 -0
  331. loopx/cli_commands/ml_experiment.py +321 -0
  332. loopx/cli_commands/multi_agent.py +211 -0
  333. loopx/cli_commands/opencode2_goal_worker.py +217 -0
  334. loopx/cli_commands/pr_review.py +167 -0
  335. loopx/cli_commands/presentation.py +218 -0
  336. loopx/cli_commands/preset.py +96 -0
  337. loopx/cli_commands/project.py +150 -0
  338. loopx/cli_commands/project_lifecycle.py +915 -0
  339. loopx/cli_commands/quota.py +859 -0
  340. loopx/cli_commands/quota_registration.py +241 -0
  341. loopx/cli_commands/quota_request.py +113 -0
  342. loopx/cli_commands/ready_score.py +110 -0
  343. loopx/cli_commands/registry_admin.py +975 -0
  344. loopx/cli_commands/registry_admin_configure.py +344 -0
  345. loopx/cli_commands/registry_admin_peer.py +84 -0
  346. loopx/cli_commands/registry_authority.py +218 -0
  347. loopx/cli_commands/review_batch.py +146 -0
  348. loopx/cli_commands/slash_commands.py +145 -0
  349. loopx/cli_commands/start_goal.py +251 -0
  350. loopx/cli_commands/starter.py +175 -0
  351. loopx/cli_commands/starter_bootstrap.py +179 -0
  352. loopx/cli_commands/starter_bootstrap_registration.py +198 -0
  353. loopx/cli_commands/starter_runtime_idle.py +107 -0
  354. loopx/cli_commands/starter_scheduler.py +207 -0
  355. loopx/cli_commands/starter_session_runtime.py +152 -0
  356. loopx/cli_commands/starter_visible_common.py +54 -0
  357. loopx/cli_commands/starter_visible_driver.py +161 -0
  358. loopx/cli_commands/starter_visible_pilot.py +278 -0
  359. loopx/cli_commands/status.py +867 -0
  360. loopx/cli_commands/status_registration.py +239 -0
  361. loopx/cli_commands/summary_all.py +222 -0
  362. loopx/cli_commands/support_control.py +809 -0
  363. loopx/cli_commands/support_control_registry.py +68 -0
  364. loopx/cli_commands/support_control_supervisor.py +289 -0
  365. loopx/cli_commands/task_lease.py +306 -0
  366. loopx/cli_commands/terminal_bench_adapter.py +717 -0
  367. loopx/cli_commands/terminal_bench_environment_result.py +1246 -0
  368. loopx/cli_commands/todo.py +940 -0
  369. loopx/cli_commands/todo_argument_validation.py +572 -0
  370. loopx/cli_commands/todo_event.py +114 -0
  371. loopx/cli_commands/turn.py +804 -0
  372. loopx/cli_commands/version.py +46 -0
  373. loopx/cli_commands/worker_bridge.py +659 -0
  374. loopx/cli_rollout.py +314 -0
  375. loopx/codex_cli_goal_tui.py +672 -0
  376. loopx/codex_cli_probe.py +1530 -0
  377. loopx/codex_cli_probe_markdown.py +935 -0
  378. loopx/codex_cli_runtime_probe.py +733 -0
  379. loopx/codex_cli_scheduler.py +564 -0
  380. loopx/codex_goal_baseline.py +620 -0
  381. loopx/configuration_catalog.py +617 -0
  382. loopx/configure_goal.py +1375 -0
  383. loopx/contract.py +996 -0
  384. loopx/control_plane/__init__.py +71 -0
  385. loopx/control_plane/agents/__init__.py +1 -0
  386. loopx/control_plane/agents/agent_lane_recommendation.py +516 -0
  387. loopx/control_plane/agents/agent_scope.py +1578 -0
  388. loopx/control_plane/agents/agent_scope_frontier.py +60 -0
  389. loopx/control_plane/agents/capability_gate.py +531 -0
  390. loopx/control_plane/agents/identity.py +140 -0
  391. loopx/control_plane/agents/legacy_migration.py +169 -0
  392. loopx/control_plane/agents/management_projection.py +658 -0
  393. loopx/control_plane/agents/material_frontier.py +608 -0
  394. loopx/control_plane/agents/material_handoff.py +156 -0
  395. loopx/control_plane/agents/multi_agent/__init__.py +1 -0
  396. loopx/control_plane/agents/multi_agent/codex_executable.py +207 -0
  397. loopx/control_plane/agents/multi_agent/collective_round_ledger.py +387 -0
  398. loopx/control_plane/agents/multi_agent/contract.py +474 -0
  399. loopx/control_plane/agents/multi_agent/recipe.py +110 -0
  400. loopx/control_plane/agents/multi_agent/role_successor.py +297 -0
  401. loopx/control_plane/agents/multi_agent/runtime_scripts.py +426 -0
  402. loopx/control_plane/agents/multi_agent/visible_launch_policy.py +149 -0
  403. loopx/control_plane/agents/multi_agent/visible_wake_scheduler.py +392 -0
  404. loopx/control_plane/agents/profile.py +216 -0
  405. loopx/control_plane/agents/runtime_model.py +73 -0
  406. loopx/control_plane/agents/subagent_activity.py +164 -0
  407. loopx/control_plane/agents/supervisor.py +544 -0
  408. loopx/control_plane/agents/supervisor_events.py +462 -0
  409. loopx/control_plane/agents/supervisor_inject.py +204 -0
  410. loopx/control_plane/agents/work_mode.py +56 -0
  411. loopx/control_plane/agents/workspace_guard.py +364 -0
  412. loopx/control_plane/effect_program.py +644 -0
  413. loopx/control_plane/goals/__init__.py +1 -0
  414. loopx/control_plane/goals/active_state_event_projection.py +103 -0
  415. loopx/control_plane/goals/active_state_metadata.py +47 -0
  416. loopx/control_plane/goals/active_state_sections.py +58 -0
  417. loopx/control_plane/goals/configure_goal_service.py +354 -0
  418. loopx/control_plane/goals/contract_health.py +132 -0
  419. loopx/control_plane/goals/dreaming.py +152 -0
  420. loopx/control_plane/goals/global_registry_health.py +199 -0
  421. loopx/control_plane/goals/global_registry_shadow.py +33 -0
  422. loopx/control_plane/goals/goal_channel.py +34 -0
  423. loopx/control_plane/goals/goal_channel_projection.py +560 -0
  424. loopx/control_plane/goals/goal_frontier/__init__.py +1917 -0
  425. loopx/control_plane/goals/goal_frontier/ack_policy.py +149 -0
  426. loopx/control_plane/goals/goal_frontier/outcome_continuity.py +437 -0
  427. loopx/control_plane/goals/goal_frontier/replan_rules.py +210 -0
  428. loopx/control_plane/goals/goal_frontier/semantic_history.py +314 -0
  429. loopx/control_plane/goals/goal_frontier/terminal.py +180 -0
  430. loopx/control_plane/goals/goal_vision.py +443 -0
  431. loopx/control_plane/goals/goal_vision_policy.py +36 -0
  432. loopx/control_plane/goals/goal_vision_state.py +62 -0
  433. loopx/control_plane/goals/goal_vision_wait.py +290 -0
  434. loopx/control_plane/goals/path_resolution.py +20 -0
  435. loopx/control_plane/goals/start_contract.py +206 -0
  436. loopx/control_plane/goals/vision_checkpoint.py +92 -0
  437. loopx/control_plane/handoff/__init__.py +1 -0
  438. loopx/control_plane/handoff/cross_runtime_impl_review.py +311 -0
  439. loopx/control_plane/handoff/delivery_contract.py +161 -0
  440. loopx/control_plane/handoff/handoff_runs.py +71 -0
  441. loopx/control_plane/handoff/project_handoff.py +155 -0
  442. loopx/control_plane/handoff/review_batch.py +463 -0
  443. loopx/control_plane/handoff/review_packet_context.py +216 -0
  444. loopx/control_plane/heartbeat/agent.py +173 -0
  445. loopx/control_plane/heartbeat/budget.py +66 -0
  446. loopx/control_plane/heartbeat/builder.py +501 -0
  447. loopx/control_plane/heartbeat/host.py +64 -0
  448. loopx/control_plane/heartbeat/rules.py +68 -0
  449. loopx/control_plane/heartbeat/task_body.py +759 -0
  450. loopx/control_plane/heartbeat/visible_goal.py +86 -0
  451. loopx/control_plane/projects/__init__.py +1 -0
  452. loopx/control_plane/projects/contract.py +25 -0
  453. loopx/control_plane/projects/registry.py +663 -0
  454. loopx/control_plane/quota/__init__.py +1 -0
  455. loopx/control_plane/quota/cli_projection.py +704 -0
  456. loopx/control_plane/quota/decision_summary.py +431 -0
  457. loopx/control_plane/quota/effect_program.py +152 -0
  458. loopx/control_plane/quota/error_codes.py +19 -0
  459. loopx/control_plane/quota/goal_boundary.py +464 -0
  460. loopx/control_plane/quota/heartbeat_receipt.py +277 -0
  461. loopx/control_plane/quota/heartbeat_recommendation.py +718 -0
  462. loopx/control_plane/quota/host_poll_receipts.py +162 -0
  463. loopx/control_plane/quota/live_decision.py +142 -0
  464. loopx/control_plane/quota/monitor_poll.py +786 -0
  465. loopx/control_plane/quota/policy_constants.py +40 -0
  466. loopx/control_plane/quota/projection_repair.py +262 -0
  467. loopx/control_plane/quota/recent_runs.py +210 -0
  468. loopx/control_plane/quota/scheduler_ack.py +490 -0
  469. loopx/control_plane/quota/selected_todo_projection.py +139 -0
  470. loopx/control_plane/quota/settlement.py +437 -0
  471. loopx/control_plane/quota/settlement_cli.py +246 -0
  472. loopx/control_plane/quota/settlement_validation.py +64 -0
  473. loopx/control_plane/quota/settlement_workspace_causality.py +180 -0
  474. loopx/control_plane/quota/should_run.py +249 -0
  475. loopx/control_plane/quota/should_run_packet.py +1165 -0
  476. loopx/control_plane/quota/should_run_prepare.py +675 -0
  477. loopx/control_plane/quota/slot_accounting.py +1123 -0
  478. loopx/control_plane/quota/spend_sources.py +11 -0
  479. loopx/control_plane/quota/stall_repair.py +397 -0
  480. loopx/control_plane/quota/states.py +29 -0
  481. loopx/control_plane/quota/task_orchestration.py +448 -0
  482. loopx/control_plane/quota/task_orchestration_admission.py +497 -0
  483. loopx/control_plane/quota/turn_envelope.py +889 -0
  484. loopx/control_plane/quota/usage_summary.py +140 -0
  485. loopx/control_plane/reward_memory.py +43 -0
  486. loopx/control_plane/runtime/__init__.py +2 -0
  487. loopx/control_plane/runtime/active_user_assisted_pilot.py +275 -0
  488. loopx/control_plane/runtime/agent_scoped_evidence_log.py +435 -0
  489. loopx/control_plane/runtime/decision_freshness.py +203 -0
  490. loopx/control_plane/runtime/event_ledger.py +197 -0
  491. loopx/control_plane/runtime/event_store_migration_bridge.py +196 -0
  492. loopx/control_plane/runtime/goal_project_route.py +70 -0
  493. loopx/control_plane/runtime/local_state_write_correctness.py +242 -0
  494. loopx/control_plane/runtime/promotion_readiness.py +152 -0
  495. loopx/control_plane/runtime/public_safety.py +120 -0
  496. loopx/control_plane/runtime/run_artifacts.py +78 -0
  497. loopx/control_plane/runtime/run_compaction.py +397 -0
  498. loopx/control_plane/runtime/run_context_retention.py +241 -0
  499. loopx/control_plane/runtime/run_history.py +132 -0
  500. loopx/control_plane/runtime/run_index_duplicates.py +205 -0
  501. loopx/control_plane/runtime/run_index_rebuild.py +263 -0
  502. loopx/control_plane/runtime/run_ingest_health.py +336 -0
  503. loopx/control_plane/runtime/runtime_projection_route.py +624 -0
  504. loopx/control_plane/runtime/runtime_projection_writer.py +98 -0
  505. loopx/control_plane/runtime/session_runtime.py +339 -0
  506. loopx/control_plane/runtime/shared_runtime_material_projection.py +332 -0
  507. loopx/control_plane/runtime/shared_runtime_refresh_projection.py +183 -0
  508. loopx/control_plane/runtime/stale_latest_run.py +90 -0
  509. loopx/control_plane/runtime/status_classifications.py +49 -0
  510. loopx/control_plane/runtime/status_projection_cache.py +235 -0
  511. loopx/control_plane/runtime/stride_observation.py +144 -0
  512. loopx/control_plane/runtime/time.py +39 -0
  513. loopx/control_plane/runtime/trajectory_hygiene.py +149 -0
  514. loopx/control_plane/runtime/validation_command.py +69 -0
  515. loopx/control_plane/scheduler/__init__.py +1 -0
  516. loopx/control_plane/scheduler/ack.py +329 -0
  517. loopx/control_plane/scheduler/arbitration.py +188 -0
  518. loopx/control_plane/scheduler/automation_liveness.py +183 -0
  519. loopx/control_plane/scheduler/execution_context.py +555 -0
  520. loopx/control_plane/scheduler/external_evidence_observation.py +428 -0
  521. loopx/control_plane/scheduler/monitor_display.py +143 -0
  522. loopx/control_plane/scheduler/monitor_poll_policy.py +161 -0
  523. loopx/control_plane/scheduler/monitor_poll_writeback.py +351 -0
  524. loopx/control_plane/scheduler/monitor_target.py +64 -0
  525. loopx/control_plane/scheduler/monitor_todo.py +146 -0
  526. loopx/control_plane/scheduler/monitor_wait.py +237 -0
  527. loopx/control_plane/scheduler/scheduler_hint.py +1284 -0
  528. loopx/control_plane/scheduler/state.py +354 -0
  529. loopx/control_plane/scheduler/state_transition_rules.py +179 -0
  530. loopx/control_plane/scheduler/time.py +10 -0
  531. loopx/control_plane/settlement_driver.py +293 -0
  532. loopx/control_plane/status/__init__.py +6 -0
  533. loopx/control_plane/status/active_state_projection.py +105 -0
  534. loopx/control_plane/status/agent_lane_projection.py +375 -0
  535. loopx/control_plane/status/attention_projection.py +74 -0
  536. loopx/control_plane/status/autonomous_replan_projection.py +103 -0
  537. loopx/control_plane/status/collection.py +140 -0
  538. loopx/control_plane/status/contract_projection.py +31 -0
  539. loopx/control_plane/status/dreaming_projection.py +52 -0
  540. loopx/control_plane/status/goal_attention_projection.py +157 -0
  541. loopx/control_plane/status/lifecycle_projection.py +110 -0
  542. loopx/control_plane/status/monitor_display_projection.py +69 -0
  543. loopx/control_plane/status/registry_health_projection.py +75 -0
  544. loopx/control_plane/status/run_projection.py +70 -0
  545. loopx/control_plane/status/runtime_summaries.py +161 -0
  546. loopx/control_plane/testing/__init__.py +1 -0
  547. loopx/control_plane/testing/actual_default_model_behavior_portfolio.py +1371 -0
  548. loopx/control_plane/testing/canary_harness.py +182 -0
  549. loopx/control_plane/testing/capability_monitor_repair_tool_behavior.py +674 -0
  550. loopx/control_plane/testing/cli_output_budget.py +807 -0
  551. loopx/control_plane/testing/cli_output_differential.py +250 -0
  552. loopx/control_plane/testing/cli_output_semantics.py +87 -0
  553. loopx/control_plane/testing/control_plane_composition_scenarios.py +225 -0
  554. loopx/control_plane/testing/decision_replay.py +268 -0
  555. loopx/control_plane/testing/doubao_model_behavior_actor.py +559 -0
  556. loopx/control_plane/testing/model_behavior_corpus.py +344 -0
  557. loopx/control_plane/testing/model_behavior_qualification.py +769 -0
  558. loopx/control_plane/testing/model_behavior_retained_cases.py +235 -0
  559. loopx/control_plane/testing/model_tool_behavior.py +536 -0
  560. loopx/control_plane/testing/onboarding_model_behavior_qualification.py +642 -0
  561. loopx/control_plane/testing/quota_fixtures.py +208 -0
  562. loopx/control_plane/testing/quota_should_run_parity.py +57 -0
  563. loopx/control_plane/testing/release_commit_qualification.py +671 -0
  564. loopx/control_plane/testing/replan_semantic_action_behavior.py +1302 -0
  565. loopx/control_plane/testing/scoped_gate_successor_tool_behavior.py +527 -0
  566. loopx/control_plane/testing/selected_todo_tool_behavior.py +1002 -0
  567. loopx/control_plane/testing/terminal_settlement_tool_behavior.py +656 -0
  568. loopx/control_plane/todos/__init__.py +1 -0
  569. loopx/control_plane/todos/active_state_editing.py +296 -0
  570. loopx/control_plane/todos/active_state_todo_parser.py +138 -0
  571. loopx/control_plane/todos/active_state_todos.py +175 -0
  572. loopx/control_plane/todos/addition.py +103 -0
  573. loopx/control_plane/todos/claim_visibility.py +253 -0
  574. loopx/control_plane/todos/completed_archive.py +139 -0
  575. loopx/control_plane/todos/completion_fence.py +49 -0
  576. loopx/control_plane/todos/completion_policy.py +153 -0
  577. loopx/control_plane/todos/completion_validation.py +248 -0
  578. loopx/control_plane/todos/completion_validation_accountability.py +27 -0
  579. loopx/control_plane/todos/completion_validation_projection.py +57 -0
  580. loopx/control_plane/todos/contract.py +1476 -0
  581. loopx/control_plane/todos/decision_scope.py +554 -0
  582. loopx/control_plane/todos/deferred_resume.py +546 -0
  583. loopx/control_plane/todos/durable_completion.py +201 -0
  584. loopx/control_plane/todos/event_writeback.py +484 -0
  585. loopx/control_plane/todos/frontier_deadline.py +132 -0
  586. loopx/control_plane/todos/handoff_gate.py +283 -0
  587. loopx/control_plane/todos/handoff_mode.py +444 -0
  588. loopx/control_plane/todos/handoff_note.py +202 -0
  589. loopx/control_plane/todos/line_update.py +361 -0
  590. loopx/control_plane/todos/list_projection.py +205 -0
  591. loopx/control_plane/todos/markdown.py +199 -0
  592. loopx/control_plane/todos/monitor_metadata.py +88 -0
  593. loopx/control_plane/todos/mutation_authority.py +299 -0
  594. loopx/control_plane/todos/projection.py +655 -0
  595. loopx/control_plane/todos/quota_summary.py +1138 -0
  596. loopx/control_plane/todos/route_continuation.py +267 -0
  597. loopx/control_plane/todos/succession_warning.py +174 -0
  598. loopx/control_plane/todos/summary_item.py +223 -0
  599. loopx/control_plane/todos/text.py +30 -0
  600. loopx/control_plane/todos/todo_index.py +226 -0
  601. loopx/control_plane/todos/todo_summary.py +1458 -0
  602. loopx/control_plane/todos/unblock_resume.py +326 -0
  603. loopx/control_plane/todos/user_gate.py +263 -0
  604. loopx/control_plane/todos/write_hint.py +63 -0
  605. loopx/control_plane/todos/write_policy.py +135 -0
  606. loopx/control_plane/turn_driver/__init__.py +85 -0
  607. loopx/control_plane/turn_driver/codex_cli.py +502 -0
  608. loopx/control_plane/turn_driver/driver.py +355 -0
  609. loopx/control_plane/turn_driver/executor.py +1468 -0
  610. loopx/control_plane/turn_driver/loop_controller.py +669 -0
  611. loopx/control_plane/turn_driver/settlement.py +318 -0
  612. loopx/control_plane/turn_driver/transaction.py +375 -0
  613. loopx/control_plane/work_items/__init__.py +1 -0
  614. loopx/control_plane/work_items/attention_fields.py +56 -0
  615. loopx/control_plane/work_items/attention_item.py +77 -0
  616. loopx/control_plane/work_items/attention_queue.py +322 -0
  617. loopx/control_plane/work_items/attention_routing.py +213 -0
  618. loopx/control_plane/work_items/autonomous_candidates.py +135 -0
  619. loopx/control_plane/work_items/autonomous_replan_ack.py +276 -0
  620. loopx/control_plane/work_items/autonomous_replan_obligation.py +786 -0
  621. loopx/control_plane/work_items/backlog_hygiene.py +59 -0
  622. loopx/control_plane/work_items/capability_monitor_fallback.py +221 -0
  623. loopx/control_plane/work_items/delivery_batch_scale.py +66 -0
  624. loopx/control_plane/work_items/delivery_outcome.py +152 -0
  625. loopx/control_plane/work_items/delivery_signals.py +113 -0
  626. loopx/control_plane/work_items/execution_obligation.py +235 -0
  627. loopx/control_plane/work_items/goal_route_hint.py +320 -0
  628. loopx/control_plane/work_items/interaction_contract.py +1540 -0
  629. loopx/control_plane/work_items/issue_meta_surface.py +159 -0
  630. loopx/control_plane/work_items/lifecycle.py +139 -0
  631. loopx/control_plane/work_items/operator_inbox.py +266 -0
  632. loopx/control_plane/work_items/outcome_followthrough.py +69 -0
  633. loopx/control_plane/work_items/primary_action.py +326 -0
  634. loopx/control_plane/work_items/progress_observation.py +630 -0
  635. loopx/control_plane/work_items/project_asset.py +675 -0
  636. loopx/control_plane/work_items/repair_delta.py +693 -0
  637. loopx/control_plane/work_items/runtime_capability_reentry.py +168 -0
  638. loopx/control_plane/work_items/semantic_replan_writeback.py +177 -0
  639. loopx/control_plane/work_items/status_contract.py +49 -0
  640. loopx/control_plane/work_items/task_graph.py +1046 -0
  641. loopx/control_plane/work_items/task_lease.py +1254 -0
  642. loopx/control_plane/work_items/task_lease_settlement.py +422 -0
  643. loopx/control_plane/work_items/work_lane.py +510 -0
  644. loopx/control_plane/work_items/work_lane_context.py +161 -0
  645. loopx/demo.py +247 -0
  646. loopx/diagnose.py +633 -0
  647. loopx/doctor.py +1251 -0
  648. loopx/domain_packs/__init__.py +1 -0
  649. loopx/domain_packs/issue_fix.py +571 -0
  650. loopx/domain_packs/ml_experiment.py +854 -0
  651. loopx/domain_state.py +137 -0
  652. loopx/dreaming.py +706 -0
  653. loopx/entrypoint.py +16 -0
  654. loopx/event_sourced_state.py +981 -0
  655. loopx/execution_profile.py +286 -0
  656. loopx/experiments/__init__.py +1 -0
  657. loopx/experiments/planner_worker/__init__.py +1 -0
  658. loopx/experiments/planner_worker/contract.py +523 -0
  659. loopx/experiments/planner_worker/runtime.py +391 -0
  660. loopx/experiments/planner_worker/traex.py +461 -0
  661. loopx/explore_graph.py +11 -0
  662. loopx/extensions/__init__.py +1 -0
  663. loopx/extensions/bundled.py +28 -0
  664. loopx/extensions/execution_envelope.py +126 -0
  665. loopx/extensions/lark/__init__.py +11 -0
  666. loopx/extensions/lark/event_collector.py +478 -0
  667. loopx/extensions/lark/event_collector_runtime.py +506 -0
  668. loopx/extensions/lark/event_inbox.py +454 -0
  669. loopx/extensions/lark/extension.toml +88 -0
  670. loopx/extensions/lark/goal_channel.py +44 -0
  671. loopx/extensions/lark/goal_channel_contracts.py +388 -0
  672. loopx/extensions/lark/goal_channel_lifecycle.py +218 -0
  673. loopx/extensions/lark/goal_channel_runtime.py +792 -0
  674. loopx/extensions/lark/goal_channel_setup.py +805 -0
  675. loopx/extensions/lark/goal_channel_targets.py +215 -0
  676. loopx/extensions/lark/goal_channel_transport.py +281 -0
  677. loopx/extensions/lark/inbox_reactions.py +650 -0
  678. loopx/extensions/lark/inbox_reply.py +430 -0
  679. loopx/extensions/lark/presentation/__init__.py +11 -0
  680. loopx/extensions/lark/presentation/explore_results.py +2276 -0
  681. loopx/extensions/lark/presentation/explore_singleflight.py +127 -0
  682. loopx/extensions/lark/presentation/explore_source_guard.py +121 -0
  683. loopx/extensions/lark/presentation/explore_stage_document.py +703 -0
  684. loopx/extensions/lark/presentation/explore_visual_integrity.py +122 -0
  685. loopx/extensions/lark/presentation/explore_visual_readback.py +452 -0
  686. loopx/extensions/lark/presentation/explore_visual_styles.py +156 -0
  687. loopx/extensions/lark/presentation/issue_fix_surface.py +612 -0
  688. loopx/extensions/lark/presentation/kanban.py +2791 -0
  689. loopx/extensions/lark/presentation/message_card.py +112 -0
  690. loopx/extensions/lark/presentation/periodic_report.py +261 -0
  691. loopx/extensions/lark/presentation/projection_rows.py +600 -0
  692. loopx/extensions/lark/presentation/record_io.py +95 -0
  693. loopx/extensions/lark/presentation/sync_receipt.py +145 -0
  694. loopx/extensions/lark/private_json.py +40 -0
  695. loopx/extensions/lark/provider.py +86 -0
  696. loopx/extensions/lark/reviewer_notification.py +604 -0
  697. loopx/extensions/manifest.py +385 -0
  698. loopx/extensions/openviking_periodic_report/__init__.py +17 -0
  699. loopx/extensions/openviking_periodic_report/activation.py +173 -0
  700. loopx/extensions/openviking_periodic_report/extension.toml +17 -0
  701. loopx/extensions/openviking_periodic_report/provider.py +355 -0
  702. loopx/extensions/openviking_periodic_report/sink.py +117 -0
  703. loopx/extensions/openviking_semantic_preference/__init__.py +5 -0
  704. loopx/extensions/openviking_semantic_preference/extension.toml +16 -0
  705. loopx/extensions/openviking_semantic_preference/history_export.py +484 -0
  706. loopx/extensions/openviking_semantic_preference/project_peer.py +68 -0
  707. loopx/extensions/openviking_semantic_preference/provider.py +312 -0
  708. loopx/extensions/presentation.py +979 -0
  709. loopx/extensions/process_runtime.py +204 -0
  710. loopx/extensions/readiness.py +168 -0
  711. loopx/extensions/runtime.py +931 -0
  712. loopx/extensions/scaffold.py +335 -0
  713. loopx/feedback.py +581 -0
  714. loopx/file_lock.py +382 -0
  715. loopx/global_registry.py +842 -0
  716. loopx/global_risks.py +970 -0
  717. loopx/global_todos.py +568 -0
  718. loopx/handoff_budget.py +28 -0
  719. loopx/heartbeat_prequota.py +80 -0
  720. loopx/heartbeat_prompt.py +159 -0
  721. loopx/help_surface.py +516 -0
  722. loopx/history.py +1507 -0
  723. loopx/host_loop_activation.py +1311 -0
  724. loopx/host_mode_planner.py +991 -0
  725. loopx/install_contract.py +1 -0
  726. loopx/interface_budget.py +196 -0
  727. loopx/long_task_cadence.py +208 -0
  728. loopx/materials.py +185 -0
  729. loopx/ml_experiment.py +3 -0
  730. loopx/onboarding.py +214 -0
  731. loopx/opencode2_goal_mode/README.md +81 -0
  732. loopx/opencode2_goal_mode/__init__.py +9 -0
  733. loopx/opencode2_goal_mode/opencode2-goal-worker.mjs +1018 -0
  734. loopx/opencode_goal_mode/README.md +99 -0
  735. loopx/opencode_goal_mode/__init__.py +13 -0
  736. loopx/opencode_goal_mode/goal-bridge-runtime.mjs +858 -0
  737. loopx/opencode_goal_mode/loopx-goal.js +8 -0
  738. loopx/operator_gate.py +420 -0
  739. loopx/orchestration.py +127 -0
  740. loopx/paths.py +59 -0
  741. loopx/pi_goal_mode/README.md +67 -0
  742. loopx/pi_goal_mode/__init__.py +13 -0
  743. loopx/pi_goal_mode/loopx-goal.ts +254 -0
  744. loopx/pi_goal_mode/pi-goal-loop-runtime.mjs +574 -0
  745. loopx/pr_review.py +1206 -0
  746. loopx/presentation/__init__.py +1 -0
  747. loopx/presentation/explore_views.py +1334 -0
  748. loopx/presentation/markdown.py +61 -0
  749. loopx/presentation/projection_source_reconcile.py +140 -0
  750. loopx/presentation/public_safety.py +42 -0
  751. loopx/presentation/renderers/__init__.py +17 -0
  752. loopx/presentation/renderers/goal_channel_html.py +269 -0
  753. loopx/presentation/renderers/periodic_report_html.py +786 -0
  754. loopx/presentation/renderers/periodic_report_markdown.py +184 -0
  755. loopx/presentation/renderers/quota_event_markdown.py +116 -0
  756. loopx/presentation/renderers/quota_markdown.py +1112 -0
  757. loopx/presentation/renderers/status_markdown.py +1570 -0
  758. loopx/presentation/renderers/trajectory_hygiene_markdown.py +39 -0
  759. loopx/presentation/renderers/turn_envelope_markdown.py +33 -0
  760. loopx/presentation/sinks/__init__.py +5 -0
  761. loopx/presentation/sinks/openviking_periodic_report.py +7 -0
  762. loopx/presentation/static_site.py +691 -0
  763. loopx/presets.py +369 -0
  764. loopx/project_alias.py +217 -0
  765. loopx/project_map.py +589 -0
  766. loopx/project_prompt.py +1153 -0
  767. loopx/project_skill_cli.py +125 -0
  768. loopx/project_skill_delivery.py +470 -0
  769. loopx/project_uninstall.py +462 -0
  770. loopx/promotion_gate.py +197 -0
  771. loopx/quota.py +1197 -0
  772. loopx/ready_score.py +413 -0
  773. loopx/registry.py +621 -0
  774. loopx/registry_writability.py +64 -0
  775. loopx/release_candidate.py +148 -0
  776. loopx/release_manifest.py +316 -0
  777. loopx/repository_identity.py +100 -0
  778. loopx/review_packet.py +1024 -0
  779. loopx/rollout_event_log.py +505 -0
  780. loopx/runtime.py +112 -0
  781. loopx/self_update.py +750 -0
  782. loopx/session_runtime.py +418 -0
  783. loopx/skill_install_readback.py +500 -0
  784. loopx/slash_command_install.py +1393 -0
  785. loopx/slash_commands.py +264 -0
  786. loopx/state_backup.py +573 -0
  787. loopx/state_migration.py +350 -0
  788. loopx/state_projection.py +809 -0
  789. loopx/state_refresh.py +1416 -0
  790. loopx/status.py +1383 -0
  791. loopx/status_server.py +935 -0
  792. loopx/summary_all.py +725 -0
  793. loopx/terminal_bench_agent.py +2056 -0
  794. loopx/thread_agent_binding.py +408 -0
  795. loopx/todo_followups.py +168 -0
  796. loopx/todo_suggestion_prompt.py +204 -0
  797. loopx/todos.py +2229 -0
  798. loopx/turn_identity.py +17 -0
  799. loopx/upgrade.py +1083 -0
  800. loopx/visible_governance.py +667 -0
  801. loopx/visible_multi_agent_launcher.py +1253 -0
  802. loopx/visible_multi_agent_tmux.py +429 -0
  803. loopx/worker_bridge.py +1574 -0
  804. loopx-0.4.8.dist-info/METADATA +708 -0
  805. loopx-0.4.8.dist-info/RECORD +811 -0
  806. loopx-0.4.8.dist-info/WHEEL +5 -0
  807. loopx-0.4.8.dist-info/entry_points.txt +5 -0
  808. loopx-0.4.8.dist-info/licenses/LICENSE +202 -0
  809. loopx-0.4.8.dist-info/licenses/LICENSE-MIT +21 -0
  810. loopx-0.4.8.dist-info/licenses/NOTICE +6 -0
  811. loopx-0.4.8.dist-info/top_level.txt +1 -0
@@ -0,0 +1,3998 @@
1
+ from __future__ import annotations
2
+
3
+ import importlib.util
4
+ import json
5
+ import os
6
+ import re
7
+ import shutil
8
+ import subprocess
9
+ import sys
10
+ import tempfile
11
+ import threading
12
+ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
13
+ from pathlib import Path
14
+ from typing import Any, Iterable
15
+
16
+ from ..benchmark_case_state import (
17
+ BENCHMARK_CASE_ACTIVE_STATE_PROOF_FIELDS,
18
+ BENCHMARK_CASE_ACTIVE_STATE_SCHEMA_VERSION,
19
+ benchmark_case_active_state_init_contract,
20
+ benchmark_case_active_state_path,
21
+ benchmark_case_goal_id,
22
+ )
23
+ from ..benchmark_core import (
24
+ BenchmarkFailureClass,
25
+ build_benchmark_attempt_accounting,
26
+ build_benchmark_launch_observable_handle,
27
+ build_run_permission_policy,
28
+ canonical_lifecycle,
29
+ compact_run_permission_policy_for_quota,
30
+ )
31
+ from ..benchmark_core.io import (
32
+ load_json_object as _load_json_object,
33
+ load_jsonl_objects as _load_jsonl_objects,
34
+ optional_float as _optional_float,
35
+ )
36
+
37
+ AGENTS_LAST_EXAM_BENCHMARK_ID = "agents-last-exam"
38
+ AGENTS_LAST_EXAM_RESULT_INGEST_POLICY_VERSION = "ale-result-ingest-contract-v0"
39
+ AGENTS_LAST_EXAM_LOCAL_PREFLIGHT_SCHEMA_VERSION = (
40
+ "agents_last_exam_local_preflight_v0"
41
+ )
42
+ AGENTS_LAST_EXAM_LOCAL_DRY_RUN_PLAN_SCHEMA_VERSION = (
43
+ "agents_last_exam_local_dry_run_plan_v0"
44
+ )
45
+ AGENTS_LAST_EXAM_LOCAL_RUNNER_READINESS_SCHEMA_VERSION = (
46
+ "agents_last_exam_local_runner_readiness_v0"
47
+ )
48
+ AGENTS_LAST_EXAM_LOCAL_SOURCE_READINESS_SCHEMA_VERSION = (
49
+ "agents_last_exam_local_source_readiness_v0"
50
+ )
51
+ AGENTS_LAST_EXAM_TASK_MATERIAL_READINESS_SCHEMA_VERSION = (
52
+ "agents_last_exam_task_material_readiness_v0"
53
+ )
54
+ AGENTS_LAST_EXAM_BAKED_TASK_INPUT_READINESS_SCHEMA_VERSION = (
55
+ "agents_last_exam_baked_task_input_readiness_v0"
56
+ )
57
+ AGENTS_LAST_EXAM_BAKED_TASK_INPUT_SCAN_SCHEMA_VERSION = (
58
+ "agents_last_exam_baked_task_input_scan_v0"
59
+ )
60
+ AGENTS_LAST_EXAM_CANDIDATE_TASK_DATA_SCAN_SCHEMA_VERSION = (
61
+ "agents_last_exam_candidate_task_data_scan_v0"
62
+ )
63
+ AGENTS_LAST_EXAM_LOCAL_LAUNCH_PACKET_SCHEMA_VERSION = (
64
+ "agents_last_exam_local_launch_packet_v0"
65
+ )
66
+ AGENTS_LAST_EXAM_LOCAL_EXACT_DRY_RUN_RESULT_SCHEMA_VERSION = (
67
+ "agents_last_exam_local_exact_dry_run_result_v0"
68
+ )
69
+ AGENTS_LAST_EXAM_HOST_CODEX_CLI_ROUTE_SCHEMA_VERSION = (
70
+ "agents_last_exam_host_codex_cli_route_v0"
71
+ )
72
+ AGENTS_LAST_EXAM_HOST_CODEX_CUA_NO_TASK_SMOKE_SCHEMA_VERSION = (
73
+ "agents_last_exam_host_codex_cua_no_task_smoke_v0"
74
+ )
75
+ AGENTS_LAST_EXAM_VALIDATION_RUN_GATE_SCHEMA_VERSION = (
76
+ "agents_last_exam_validation_run_gate_v0"
77
+ )
78
+ AGENTS_LAST_EXAM_TRACE_PUBLICNESS = (
79
+ "compact_public_safe_no_task_body_no_trajectory_no_output"
80
+ )
81
+ AGENTS_LAST_EXAM_CASE_GOAL_ID = benchmark_case_goal_id(AGENTS_LAST_EXAM_BENCHMARK_ID)
82
+ AGENTS_LAST_EXAM_CASE_STATE_PATH = benchmark_case_active_state_path(
83
+ AGENTS_LAST_EXAM_CASE_GOAL_ID
84
+ )
85
+ AGENTS_LAST_EXAM_DEFAULT_DOCKER_IMAGE = "agentslastexam/ale-kasm:latest"
86
+ AGENTS_LAST_EXAM_DEFAULT_ALT_DOCKER_IMAGE = "ale-ubuntu22-docker:latest"
87
+ AGENTS_LAST_EXAM_DEFAULT_SNAPSHOT = "cpu-free-ubuntu"
88
+ AGENTS_LAST_EXAM_DEFAULT_REPO_URL = (
89
+ "https://github.com/rdi-berkeley/agents-last-exam.git"
90
+ )
91
+ AGENTS_LAST_EXAM_RAW_SURFACES_EXCLUDED = (
92
+ "trajectory.json",
93
+ "origin_log",
94
+ "output",
95
+ )
96
+
97
+ _AGENTS_LAST_EXAM_REQUIRES_TASK_DATA_RE = re.compile(
98
+ r"^\s*(?:self\.)?REQUIRES_TASK_DATA\s*(?::[^=]+)?=\s*(True|False)\b"
99
+ )
100
+
101
+
102
+ def _agents_last_exam_public_id(value: Any, *, limit: int = 140) -> str | None:
103
+ """Return a public-safe ALE id without preserving host paths or task bodies."""
104
+
105
+ if not isinstance(value, str):
106
+ return None
107
+ text = value.strip().replace("\\", "/")
108
+ if not text or text.startswith("/") or text.startswith("~"):
109
+ return None
110
+ parts = [part for part in text.split("/") if part]
111
+ if any(part in {".", ".."} for part in parts):
112
+ return None
113
+ cleaned = []
114
+ for char in "__".join(parts):
115
+ cleaned.append(char.lower() if char.isalnum() or char in {"-", "_", "."} else "-")
116
+ label = "".join(cleaned).strip("-_.")
117
+ while "--" in label:
118
+ label = label.replace("--", "-")
119
+ return (label or None)[:limit]
120
+
121
+ def _agents_last_exam_first_public_id(*values: Any, default: str) -> str:
122
+ for value in values:
123
+ label = _agents_last_exam_public_id(value)
124
+ if label:
125
+ return label
126
+ return default
127
+
128
+ def _agents_last_exam_parse_int(value: Any) -> int | None:
129
+ try:
130
+ return int(str(value).strip())
131
+ except (TypeError, ValueError):
132
+ return None
133
+
134
+ def build_agents_last_exam_local_exact_dry_run_result(
135
+ *,
136
+ stdout_text: str | None,
137
+ exit_code: int | str | None,
138
+ expected_task_id: str | None = None,
139
+ expected_agent_id: str | None = None,
140
+ ) -> dict[str, Any]:
141
+ """Reduce ALE ``--dry-run`` stdout to a compact public-safe artifact.
142
+
143
+ The raw stdout is intentionally not returned. The reducer keeps only
144
+ public labels and matrix counts, so callers can persist the result without
145
+ copying paths, task text, trajectories, screenshots, credentials, or command
146
+ argv into LoopX state.
147
+ """
148
+
149
+ parsed_exit_code = _agents_last_exam_parse_int(exit_code)
150
+ text = stdout_text if isinstance(stdout_text, str) else ""
151
+ lines = [line.rstrip() for line in text.splitlines()]
152
+ experiment_label: str | None = None
153
+ environment_label: str | None = None
154
+ environment_route_label: str | None = None
155
+ concurrency: int | None = None
156
+ declared_unit_count: int | None = None
157
+ units: list[dict[str, Any]] = []
158
+ in_units = False
159
+
160
+ for raw_line in lines:
161
+ line = raw_line.strip()
162
+ if not line:
163
+ continue
164
+ if line.startswith("experiment:"):
165
+ experiment_label = _agents_last_exam_public_id(
166
+ line.split(":", 1)[1],
167
+ limit=160,
168
+ )
169
+ in_units = False
170
+ continue
171
+ if line.startswith("environment:"):
172
+ value = line.split(":", 1)[1].strip()
173
+ before_route, _, route = value.partition("(")
174
+ environment_label = _agents_last_exam_public_id(
175
+ before_route.strip(),
176
+ limit=80,
177
+ )
178
+ environment_route_label = _agents_last_exam_public_id(
179
+ route.rstrip(")").replace("->", "-to-") if route else value,
180
+ limit=160,
181
+ )
182
+ in_units = False
183
+ continue
184
+ if line.startswith("concurrency:"):
185
+ concurrency = _agents_last_exam_parse_int(line.split(":", 1)[1])
186
+ in_units = False
187
+ continue
188
+ if line.startswith("units (") and line.endswith("):"):
189
+ count_text = line[len("units (") : -len("):")]
190
+ declared_unit_count = _agents_last_exam_parse_int(count_text)
191
+ in_units = True
192
+ continue
193
+ if in_units:
194
+ parts = line.split()
195
+ if len(parts) >= 3:
196
+ agent_label = _agents_last_exam_public_id(parts[0], limit=80)
197
+ task_label = _agents_last_exam_public_id(parts[1], limit=180)
198
+ variant_label = _agents_last_exam_public_id(parts[2], limit=40)
199
+ units.append(
200
+ {
201
+ "agent": agent_label,
202
+ "task": task_label,
203
+ "variant": variant_label,
204
+ }
205
+ )
206
+
207
+ expected_task_label = _agents_last_exam_public_id(expected_task_id, limit=180)
208
+ expected_agent_label = _agents_last_exam_public_id(expected_agent_id, limit=80)
209
+ blockers: list[str] = []
210
+ if parsed_exit_code != 0:
211
+ blockers.append("ale_dry_run_exit_nonzero")
212
+ if declared_unit_count is None:
213
+ blockers.append("ale_dry_run_unit_count_missing")
214
+ elif declared_unit_count != len(units):
215
+ blockers.append("ale_dry_run_unit_count_mismatch")
216
+ if expected_task_label and expected_task_label not in {
217
+ str(unit.get("task") or "") for unit in units
218
+ }:
219
+ blockers.append("expected_task_not_in_dry_run_matrix")
220
+ if expected_agent_label and expected_agent_label not in {
221
+ str(unit.get("agent") or "") for unit in units
222
+ }:
223
+ blockers.append("expected_agent_not_in_dry_run_matrix")
224
+
225
+ ready = not blockers
226
+ return {
227
+ "schema_version": AGENTS_LAST_EXAM_LOCAL_EXACT_DRY_RUN_RESULT_SCHEMA_VERSION,
228
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
229
+ "ready": ready,
230
+ "first_blocker": blockers[0]
231
+ if blockers
232
+ else "ready_for_compact_ale_dry_run_result_ingest",
233
+ "blockers": blockers,
234
+ "exit_code": parsed_exit_code,
235
+ "experiment": experiment_label,
236
+ "environment": {
237
+ "kind": environment_label,
238
+ "route": environment_route_label,
239
+ },
240
+ "concurrency": concurrency,
241
+ "unit_count_declared": declared_unit_count,
242
+ "unit_count_parsed": len(units),
243
+ "units": units[:50],
244
+ "unit_list_truncated": len(units) > 50,
245
+ "expected": {
246
+ "agent": expected_agent_label,
247
+ "task": expected_task_label,
248
+ },
249
+ "boundary": {
250
+ "local_only": True,
251
+ "no_upload": True,
252
+ "submit_eligible": False,
253
+ "leaderboard_evidence": False,
254
+ "container_started": False,
255
+ "task_body_read": False,
256
+ "model_api_invoked": False,
257
+ "raw_trajectory_read": False,
258
+ "screenshot_captured": False,
259
+ "credential_values_recorded": False,
260
+ "hidden_references_allowed": False,
261
+ "production_actions_allowed": False,
262
+ "local_paths_recorded": False,
263
+ "command_argv_recorded": False,
264
+ "raw_stdout_recorded": False,
265
+ },
266
+ "decision": {
267
+ "next_allowed_action": "use_compact_ale_dry_run_result_for_run_gate"
268
+ if ready
269
+ else "repair_ale_dry_run_result_before_run_gate",
270
+ "minimum_next_evidence": (
271
+ "A compact ALE dry-run matrix with exit_code=0, matching expected "
272
+ "agent/task labels, and no raw stdout/path/task-body leakage."
273
+ ),
274
+ "must_not_claim": [
275
+ "ALE task success",
276
+ "ALE score uplift",
277
+ "LoopX treatment advantage",
278
+ "leaderboard evidence",
279
+ ],
280
+ },
281
+ "read_boundary": {
282
+ "compact_only": True,
283
+ "raw_stdout_recorded": False,
284
+ "task_text_read": False,
285
+ "raw_artifacts_read": False,
286
+ "local_paths_recorded": False,
287
+ "container_started": False,
288
+ },
289
+ }
290
+
291
+ def _agents_last_exam_event_type_counts(rows: list[dict[str, Any]]) -> dict[str, int]:
292
+ counts: dict[str, int] = {}
293
+ for row in rows:
294
+ event_type = _agents_last_exam_public_id(
295
+ row.get("type") or row.get("event_type") or row.get("event"),
296
+ limit=80,
297
+ )
298
+ if not event_type:
299
+ continue
300
+ counts[event_type] = counts.get(event_type, 0) + 1
301
+ return dict(sorted(counts.items())[:10])
302
+
303
+ def _agents_last_exam_nested(source: dict[str, Any], field: str) -> Any:
304
+ value = source.get(field)
305
+ if value is not None:
306
+ return value
307
+ unit = source.get("unit") if isinstance(source.get("unit"), dict) else {}
308
+ value = unit.get(field)
309
+ if value is not None:
310
+ return value
311
+ meta = source.get("meta") if isinstance(source.get("meta"), dict) else {}
312
+ return meta.get(field)
313
+
314
+ def _agents_last_exam_docker_image_metadata(image_ref: str) -> dict[str, Any]:
315
+ """Inspect local Docker image metadata without starting a container."""
316
+
317
+ if not shutil.which("docker"):
318
+ return {
319
+ "image_ref": image_ref,
320
+ "present": False,
321
+ "probe_available": False,
322
+ "first_blocker": "docker_cli_missing",
323
+ }
324
+ try:
325
+ result = subprocess.run(
326
+ ["docker", "image", "inspect", image_ref, "--format", "{{json .}}"],
327
+ check=False,
328
+ text=True,
329
+ capture_output=True,
330
+ timeout=20,
331
+ )
332
+ except Exception:
333
+ return {
334
+ "image_ref": image_ref,
335
+ "present": False,
336
+ "probe_available": False,
337
+ "first_blocker": "docker_image_inspect_failed",
338
+ }
339
+ if result.returncode != 0 or not result.stdout.strip():
340
+ return {
341
+ "image_ref": image_ref,
342
+ "present": False,
343
+ "probe_available": True,
344
+ "first_blocker": "docker_image_missing",
345
+ }
346
+ try:
347
+ raw = json.loads(result.stdout)
348
+ except json.JSONDecodeError:
349
+ return {
350
+ "image_ref": image_ref,
351
+ "present": False,
352
+ "probe_available": True,
353
+ "first_blocker": "docker_image_inspect_not_json",
354
+ }
355
+ repo_digests = raw.get("RepoDigests") if isinstance(raw.get("RepoDigests"), list) else []
356
+ metadata = raw.get("Metadata") if isinstance(raw.get("Metadata"), dict) else {}
357
+ return {
358
+ "image_ref": image_ref,
359
+ "present": True,
360
+ "probe_available": True,
361
+ "id": _agents_last_exam_public_id(raw.get("Id"), limit=160),
362
+ "digest": _agents_last_exam_public_id(
363
+ next((item for item in repo_digests if isinstance(item, str)), None),
364
+ limit=180,
365
+ ),
366
+ "architecture": _agents_last_exam_public_id(raw.get("Architecture"), limit=40),
367
+ "os": _agents_last_exam_public_id(raw.get("Os"), limit=40),
368
+ "size_bytes": int(raw.get("Size"))
369
+ if isinstance(raw.get("Size"), int) and not isinstance(raw.get("Size"), bool)
370
+ else None,
371
+ "created": _agents_last_exam_public_id(raw.get("Created"), limit=80),
372
+ "last_tag_time": _agents_last_exam_public_id(
373
+ metadata.get("LastTagTime"),
374
+ limit=80,
375
+ ),
376
+ "first_blocker": None,
377
+ }
378
+
379
+ def _agents_last_exam_public_image_metadata(
380
+ metadata: dict[str, Any],
381
+ *,
382
+ fallback_image_ref: str,
383
+ ) -> dict[str, Any]:
384
+ """Reduce Docker image metadata to compact public-safe fields."""
385
+
386
+ image_ref = metadata.get("image_ref") or fallback_image_ref
387
+ reduced: dict[str, Any] = {
388
+ "image_ref": _agents_last_exam_public_id(image_ref, limit=180)
389
+ or "image_ref_unavailable",
390
+ "present": metadata.get("present") is True,
391
+ "probe_available": metadata.get("probe_available") is True,
392
+ "first_blocker": _agents_last_exam_public_id(
393
+ metadata.get("first_blocker"),
394
+ limit=80,
395
+ ),
396
+ }
397
+ for field, limit in (
398
+ ("id", 160),
399
+ ("digest", 180),
400
+ ("architecture", 40),
401
+ ("os", 40),
402
+ ("created", 80),
403
+ ("last_tag_time", 80),
404
+ ):
405
+ value = _agents_last_exam_public_id(metadata.get(field), limit=limit)
406
+ if value:
407
+ reduced[field] = value
408
+ size_bytes = metadata.get("size_bytes")
409
+ if isinstance(size_bytes, int) and not isinstance(size_bytes, bool):
410
+ reduced["size_bytes"] = size_bytes
411
+ return reduced
412
+
413
+ def _agents_last_exam_disk_headroom() -> dict[str, Any]:
414
+ usage = shutil.disk_usage(Path.cwd())
415
+ free_gib = usage.free / (1024**3)
416
+ total_gib = usage.total / (1024**3)
417
+ used_pct = (usage.used / usage.total * 100.0) if usage.total else 0.0
418
+ return {
419
+ "free_gib": round(free_gib, 2),
420
+ "total_gib": round(total_gib, 2),
421
+ "used_percent": round(used_pct, 2),
422
+ "path_recorded": False,
423
+ }
424
+
425
+ def _agents_last_exam_disk_headroom_for_path(path: Path | None) -> dict[str, Any]:
426
+ try:
427
+ probe_path = path if path is not None and path.exists() else Path.cwd()
428
+ usage = shutil.disk_usage(probe_path)
429
+ except (OSError, RuntimeError):
430
+ return {
431
+ "checked": False,
432
+ "free_gib": None,
433
+ "total_gib": None,
434
+ "used_percent": None,
435
+ "path_recorded": False,
436
+ }
437
+ free_gib = usage.free / (1024**3)
438
+ total_gib = usage.total / (1024**3)
439
+ used_pct = (usage.used / usage.total * 100.0) if usage.total else 0.0
440
+ return {
441
+ "checked": True,
442
+ "free_gib": round(free_gib, 2),
443
+ "total_gib": round(total_gib, 2),
444
+ "used_percent": round(used_pct, 2),
445
+ "path_recorded": False,
446
+ }
447
+
448
+ def build_agents_last_exam_local_preflight(
449
+ *,
450
+ selected_task_id: str | None = None,
451
+ snapshot: str = AGENTS_LAST_EXAM_DEFAULT_SNAPSHOT,
452
+ provider_kind: str = "docker",
453
+ image_ref: str = AGENTS_LAST_EXAM_DEFAULT_DOCKER_IMAGE,
454
+ alternate_image_ref: str = AGENTS_LAST_EXAM_DEFAULT_ALT_DOCKER_IMAGE,
455
+ image_metadata: dict[str, Any] | None = None,
456
+ alternate_image_metadata: dict[str, Any] | None = None,
457
+ disk_headroom: dict[str, Any] | None = None,
458
+ ) -> dict[str, Any]:
459
+ """Build a local ALE adapter preflight without task/body/run execution."""
460
+
461
+ task_label = (
462
+ _agents_last_exam_public_id(selected_task_id, limit=160)
463
+ or "metadata_only_candidate"
464
+ )
465
+ primary_raw = (
466
+ image_metadata
467
+ if isinstance(image_metadata, dict)
468
+ else _agents_last_exam_docker_image_metadata(image_ref)
469
+ )
470
+ alternate_raw = (
471
+ alternate_image_metadata
472
+ if isinstance(alternate_image_metadata, dict)
473
+ else _agents_last_exam_docker_image_metadata(alternate_image_ref)
474
+ )
475
+ primary = _agents_last_exam_public_image_metadata(
476
+ primary_raw,
477
+ fallback_image_ref=image_ref,
478
+ )
479
+ alternate = _agents_last_exam_public_image_metadata(
480
+ alternate_raw,
481
+ fallback_image_ref=alternate_image_ref,
482
+ )
483
+ disk = (
484
+ disk_headroom
485
+ if isinstance(disk_headroom, dict)
486
+ else _agents_last_exam_disk_headroom()
487
+ )
488
+ no_cloud = provider_kind == "docker"
489
+ no_upload = True
490
+ required_image_present = primary.get("present") is True
491
+ ready = bool(no_cloud and no_upload and required_image_present)
492
+ if not no_cloud:
493
+ first_blocker = "provider_is_not_local_docker"
494
+ elif not primary.get("probe_available", True):
495
+ first_blocker = primary.get("first_blocker") or "docker_probe_unavailable"
496
+ elif not required_image_present:
497
+ first_blocker = primary.get("first_blocker") or "required_docker_image_missing"
498
+ else:
499
+ first_blocker = "ready_for_local_no_upload_preflight"
500
+
501
+ return {
502
+ "schema_version": AGENTS_LAST_EXAM_LOCAL_PREFLIGHT_SCHEMA_VERSION,
503
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
504
+ "task_id": task_label,
505
+ "snapshot": _agents_last_exam_public_id(snapshot, limit=80)
506
+ or AGENTS_LAST_EXAM_DEFAULT_SNAPSHOT,
507
+ "provider": {
508
+ "kind": provider_kind,
509
+ "no_cloud": no_cloud,
510
+ "required_image": primary,
511
+ "alternate_image": alternate,
512
+ },
513
+ "disk_headroom": disk,
514
+ "ready": ready,
515
+ "first_blocker": first_blocker,
516
+ "boundary": {
517
+ "local_only": True,
518
+ "no_cloud": no_cloud,
519
+ "no_upload": no_upload,
520
+ "submit_eligible": False,
521
+ "leaderboard_evidence": False,
522
+ "container_started": False,
523
+ "task_body_read": False,
524
+ "model_api_invoked": False,
525
+ "raw_trajectory_read": False,
526
+ "screenshot_captured": False,
527
+ "credential_values_recorded": False,
528
+ "local_paths_recorded": False,
529
+ },
530
+ "decision": {
531
+ "next_allowed_action": "run_no_upload_adapter_dry_run"
532
+ if ready
533
+ else "repair_preflight_blocker_before_ale_run",
534
+ "minimum_next_evidence": (
535
+ "A no-cloud/no-upload ALE adapter dry-run that confirms local "
536
+ "Docker provider selection and compact ingest boundaries."
537
+ ),
538
+ "must_not_claim": [
539
+ "ALE task success",
540
+ "ALE score uplift",
541
+ "leaderboard evidence",
542
+ "LoopX treatment advantage",
543
+ ],
544
+ },
545
+ "read_boundary": {
546
+ "compact_only": True,
547
+ "task_text_read": False,
548
+ "raw_artifacts_read": False,
549
+ "local_paths_recorded": False,
550
+ },
551
+ }
552
+
553
+ def build_agents_last_exam_local_dry_run_plan(
554
+ *,
555
+ selected_task_id: str | None = None,
556
+ snapshot: str = AGENTS_LAST_EXAM_DEFAULT_SNAPSHOT,
557
+ provider_kind: str = "docker",
558
+ image_ref: str = AGENTS_LAST_EXAM_DEFAULT_DOCKER_IMAGE,
559
+ alternate_image_ref: str = AGENTS_LAST_EXAM_DEFAULT_ALT_DOCKER_IMAGE,
560
+ image_metadata: dict[str, Any] | None = None,
561
+ alternate_image_metadata: dict[str, Any] | None = None,
562
+ disk_headroom: dict[str, Any] | None = None,
563
+ preflight: dict[str, Any] | None = None,
564
+ ) -> dict[str, Any]:
565
+ """Plan an ALE local adapter dry-run without running the adapter."""
566
+
567
+ preflight_payload = (
568
+ preflight
569
+ if isinstance(preflight, dict)
570
+ else build_agents_last_exam_local_preflight(
571
+ selected_task_id=selected_task_id,
572
+ snapshot=snapshot,
573
+ provider_kind=provider_kind,
574
+ image_ref=image_ref,
575
+ alternate_image_ref=alternate_image_ref,
576
+ image_metadata=image_metadata,
577
+ alternate_image_metadata=alternate_image_metadata,
578
+ disk_headroom=disk_headroom,
579
+ )
580
+ )
581
+ boundary = (
582
+ preflight_payload.get("boundary")
583
+ if isinstance(preflight_payload.get("boundary"), dict)
584
+ else {}
585
+ )
586
+ read_boundary = (
587
+ preflight_payload.get("read_boundary")
588
+ if isinstance(preflight_payload.get("read_boundary"), dict)
589
+ else {}
590
+ )
591
+ forbidden_side_effects = {
592
+ "container_started": False,
593
+ "task_body_read": False,
594
+ "model_api_invoked": False,
595
+ "raw_trajectory_read": False,
596
+ "screenshot_captured": False,
597
+ "credential_values_recorded": False,
598
+ "local_paths_recorded": False,
599
+ "submit_eligible": False,
600
+ "leaderboard_evidence": False,
601
+ }
602
+ boundary_preserved = (
603
+ boundary.get("local_only") is True
604
+ and boundary.get("no_cloud") is True
605
+ and boundary.get("no_upload") is True
606
+ and all(
607
+ boundary.get(field) is expected
608
+ for field, expected in forbidden_side_effects.items()
609
+ )
610
+ and read_boundary.get("compact_only") is True
611
+ and read_boundary.get("task_text_read") is False
612
+ and read_boundary.get("raw_artifacts_read") is False
613
+ and read_boundary.get("local_paths_recorded") is False
614
+ )
615
+ preflight_ready = preflight_payload.get("ready") is True
616
+ blockers: list[str] = []
617
+ if not preflight_ready:
618
+ blockers.append(
619
+ _agents_last_exam_public_id(
620
+ preflight_payload.get("first_blocker"),
621
+ limit=80,
622
+ )
623
+ or "ale_local_preflight_not_ready"
624
+ )
625
+ if not boundary_preserved:
626
+ blockers.append("ale_local_boundary_not_preserved")
627
+ ready = preflight_ready and boundary_preserved
628
+
629
+ return {
630
+ "schema_version": AGENTS_LAST_EXAM_LOCAL_DRY_RUN_PLAN_SCHEMA_VERSION,
631
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
632
+ "task_id": preflight_payload.get("task_id") or "metadata_only_candidate",
633
+ "snapshot": preflight_payload.get("snapshot")
634
+ or AGENTS_LAST_EXAM_DEFAULT_SNAPSHOT,
635
+ "preflight": preflight_payload,
636
+ "ready": ready,
637
+ "first_blocker": blockers[0] if blockers else "ready_for_contract_only_dry_run_plan",
638
+ "blockers": blockers,
639
+ "adapter_plan": {
640
+ "mode": "contract_only_no_execution",
641
+ "provider": "local_docker",
642
+ "will_start_container": False,
643
+ "will_read_task_body": False,
644
+ "will_invoke_model_api": False,
645
+ "will_upload": False,
646
+ "will_submit": False,
647
+ "will_capture_screenshot": False,
648
+ "will_record_credentials": False,
649
+ "will_record_local_paths": False,
650
+ "allowed_probes": [
651
+ "local_docker_image_inspect",
652
+ "disk_headroom_summary",
653
+ "public_task_id_label",
654
+ "compact_boundary_flags",
655
+ ],
656
+ "required_before_real_dry_run": [
657
+ "selected_public_task_id_label",
658
+ "local_docker_provider_confirmed",
659
+ "submit_eligible_false",
660
+ "compact_result_writer_boundary_declared",
661
+ "stop_before_task_body_or_raw_outputs",
662
+ ],
663
+ },
664
+ "paired_run_requirements": {
665
+ "same_task": True,
666
+ "same_model": True,
667
+ "same_sandbox_provider": True,
668
+ "same_timeout": True,
669
+ "same_attempt_count": True,
670
+ "same_grading_path": True,
671
+ "baseline_arm": "hardened-codex",
672
+ "treatment_arm": "codex-loopx",
673
+ },
674
+ "claim_boundary": {
675
+ "may_claim": [
676
+ "ALE local adapter dry-run prerequisites are represented as a compact gate",
677
+ "The gate did not start containers, read task bodies, invoke model APIs, upload, or submit",
678
+ "A future real dry-run must preserve the same no-cloud/no-upload boundary",
679
+ ],
680
+ "must_not_claim": [
681
+ "ALE task success",
682
+ "ALE score uplift",
683
+ "LoopX treatment advantage",
684
+ "leaderboard evidence",
685
+ "raw trajectory or screenshot evidence",
686
+ ],
687
+ },
688
+ "decision": {
689
+ "next_allowed_action": "run_operator_authorized_no_upload_ale_adapter_dry_run"
690
+ if ready
691
+ else "repair_ale_local_dry_run_plan_blocker",
692
+ "minimum_next_evidence": (
693
+ "A real no-cloud/no-upload adapter dry-run may only proceed if "
694
+ "it preserves the same boundary flags and produces compact "
695
+ "run/eval/events metadata without raw task or trajectory content."
696
+ ),
697
+ "stop_condition": (
698
+ "Stop before task body, hidden references, raw trajectory, "
699
+ "screenshots, credential values, local absolute paths, model "
700
+ "APIs, uploads, submissions, leaderboard claims, paid compute, "
701
+ "or production actions."
702
+ ),
703
+ },
704
+ "read_boundary": {
705
+ "compact_only": True,
706
+ "task_text_read": False,
707
+ "raw_artifacts_read": False,
708
+ "local_paths_recorded": False,
709
+ "container_started": False,
710
+ },
711
+ }
712
+
713
+ def _agents_last_exam_runner_binary_probe(runner_binary: str | None) -> dict[str, Any]:
714
+ binary = _agents_last_exam_public_id(runner_binary, limit=80)
715
+ if not runner_binary:
716
+ return {
717
+ "binary": None,
718
+ "declared": False,
719
+ "available": False,
720
+ "first_blocker": "runner_binary_missing",
721
+ "path_recorded": False,
722
+ }
723
+ if not binary:
724
+ return {
725
+ "binary": None,
726
+ "declared": True,
727
+ "available": False,
728
+ "first_blocker": "runner_binary_not_public_safe",
729
+ "path_recorded": False,
730
+ }
731
+ if "/" in runner_binary or "\\" in runner_binary:
732
+ return {
733
+ "binary": binary,
734
+ "declared": True,
735
+ "available": False,
736
+ "first_blocker": "runner_binary_must_be_name_not_path",
737
+ "path_recorded": False,
738
+ }
739
+ available = shutil.which(runner_binary) is not None
740
+ return {
741
+ "binary": binary,
742
+ "declared": True,
743
+ "available": available,
744
+ "first_blocker": None if available else "runner_binary_not_found",
745
+ "path_recorded": False,
746
+ }
747
+
748
+ def _agents_last_exam_python_module_probe(
749
+ module_name: str | None,
750
+ *,
751
+ source_root: str | None = None,
752
+ ) -> dict[str, Any]:
753
+ module = _agents_last_exam_public_id(module_name, limit=100)
754
+ source_root_declared = bool(source_root)
755
+ source_root_available = False
756
+ source_root_path: Path | None = None
757
+ if source_root:
758
+ try:
759
+ source_root_path = Path(source_root).expanduser()
760
+ except (OSError, RuntimeError):
761
+ source_root_path = None
762
+ source_root_available = bool(source_root_path and source_root_path.is_dir())
763
+ if not module_name:
764
+ return {
765
+ "module": None,
766
+ "declared": False,
767
+ "available": False,
768
+ "first_blocker": "runner_python_module_missing",
769
+ "source_root_declared": source_root_declared,
770
+ "source_root_available": source_root_available,
771
+ "source_root_path_recorded": False,
772
+ "path_recorded": False,
773
+ }
774
+ if source_root_declared and not source_root_available:
775
+ return {
776
+ "module": module,
777
+ "declared": True,
778
+ "available": False,
779
+ "first_blocker": "runner_source_root_missing",
780
+ "source_root_declared": True,
781
+ "source_root_available": False,
782
+ "source_root_path_recorded": False,
783
+ "path_recorded": False,
784
+ }
785
+ if not module or "/" in module_name or "\\" in module_name:
786
+ return {
787
+ "module": None,
788
+ "declared": True,
789
+ "available": False,
790
+ "first_blocker": "runner_python_module_not_public_safe",
791
+ "source_root_declared": source_root_declared,
792
+ "source_root_available": source_root_available,
793
+ "source_root_path_recorded": False,
794
+ "path_recorded": False,
795
+ }
796
+ parts = module_name.split(".")
797
+ if not parts or any(not part.isidentifier() for part in parts):
798
+ return {
799
+ "module": module,
800
+ "declared": True,
801
+ "available": False,
802
+ "first_blocker": "runner_python_module_not_public_safe",
803
+ "source_root_declared": source_root_declared,
804
+ "source_root_available": source_root_available,
805
+ "source_root_path_recorded": False,
806
+ "path_recorded": False,
807
+ }
808
+ if source_root_path is not None:
809
+ source_root_text = str(source_root_path)
810
+ sys.path.insert(0, source_root_text)
811
+ importlib.invalidate_caches()
812
+ try:
813
+ available = importlib.util.find_spec(module_name) is not None
814
+ finally:
815
+ try:
816
+ sys.path.remove(source_root_text)
817
+ except ValueError:
818
+ pass
819
+ importlib.invalidate_caches()
820
+ else:
821
+ available = importlib.util.find_spec(module_name) is not None
822
+ return {
823
+ "module": module,
824
+ "declared": True,
825
+ "available": available,
826
+ "first_blocker": None if available else "runner_python_module_not_found",
827
+ "source_root_declared": source_root_declared,
828
+ "source_root_available": source_root_available,
829
+ "source_root_path_recorded": False,
830
+ "path_recorded": False,
831
+ }
832
+
833
+ def _agents_last_exam_runner_binary_requires_python_module(
834
+ runner_binary: str | None,
835
+ ) -> bool:
836
+ if not isinstance(runner_binary, str):
837
+ return False
838
+ binary = Path(runner_binary).name.lower()
839
+ return binary == "python" or binary.startswith("python3")
840
+
841
+ def _agents_last_exam_codex_cli_probe(
842
+ codex_binary: str | None,
843
+ *,
844
+ binary_available: bool | None = None,
845
+ version_text: str | None = None,
846
+ ) -> dict[str, Any]:
847
+ """Probe host Codex CLI readiness without recording paths or argv."""
848
+
849
+ runner_probe = _agents_last_exam_runner_binary_probe(codex_binary)
850
+ unsafe_binary_blockers = {
851
+ "runner_binary_must_be_name_not_path",
852
+ "runner_binary_not_public_safe",
853
+ }
854
+ if (
855
+ binary_available is not None
856
+ and runner_probe.get("declared") is True
857
+ and runner_probe.get("first_blocker") not in unsafe_binary_blockers
858
+ ):
859
+ runner_probe = {
860
+ **runner_probe,
861
+ "available": bool(binary_available),
862
+ "first_blocker": None
863
+ if binary_available
864
+ else (runner_probe.get("first_blocker") or "codex_binary_not_available"),
865
+ }
866
+
867
+ version_label = _agents_last_exam_public_id(version_text, limit=120)
868
+ version_probe_available = bool(version_label)
869
+ if (
870
+ version_text is None
871
+ and runner_probe.get("available") is True
872
+ and isinstance(codex_binary, str)
873
+ and codex_binary
874
+ and "/" not in codex_binary
875
+ and "\\" not in codex_binary
876
+ ):
877
+ try:
878
+ result = subprocess.run(
879
+ [codex_binary, "--version"],
880
+ check=False,
881
+ text=True,
882
+ capture_output=True,
883
+ timeout=20,
884
+ )
885
+ except Exception:
886
+ result = None
887
+ if result is not None and result.returncode == 0:
888
+ version_label = _agents_last_exam_public_id(
889
+ result.stdout.strip() or result.stderr.strip(),
890
+ limit=120,
891
+ )
892
+ version_probe_available = bool(version_label)
893
+
894
+ first_blocker = _agents_last_exam_public_id(
895
+ runner_probe.get("first_blocker"),
896
+ limit=80,
897
+ )
898
+ if runner_probe.get("available") is True and not version_probe_available:
899
+ first_blocker = "codex_version_probe_failed"
900
+
901
+ return {
902
+ "binary": runner_probe.get("binary"),
903
+ "binary_declared": runner_probe.get("declared") is True,
904
+ "binary_available": runner_probe.get("available") is True,
905
+ "version": version_label,
906
+ "version_probe_available": version_probe_available,
907
+ "binary_path_recorded": False,
908
+ "command_argv_recorded": False,
909
+ "first_blocker": first_blocker,
910
+ }
911
+
912
+ def _agents_last_exam_cua_mcp_assets_probe(
913
+ assets_root: str | None,
914
+ ) -> dict[str, Any]:
915
+ """Check local CUA MCP server assets without recording host paths."""
916
+
917
+ if not assets_root:
918
+ return {
919
+ "declared": False,
920
+ "available": False,
921
+ "package_json_present": False,
922
+ "server_entry_present": False,
923
+ "package_lock_present": False,
924
+ "path_recorded": False,
925
+ "first_blocker": "cua_mcp_assets_root_missing",
926
+ }
927
+ try:
928
+ root = Path(assets_root).expanduser()
929
+ except (OSError, RuntimeError):
930
+ root = None
931
+ available = bool(root and root.is_dir())
932
+ package_json_present = bool(root and (root / "package.json").is_file())
933
+ package_lock_present = bool(root and (root / "package-lock.json").is_file())
934
+ server_entry_present = bool(root and (root / "src" / "index.js").is_file())
935
+ if not available:
936
+ first_blocker = "cua_mcp_assets_root_not_available"
937
+ elif not package_json_present:
938
+ first_blocker = "cua_mcp_package_json_missing"
939
+ elif not server_entry_present:
940
+ first_blocker = "cua_mcp_server_entry_missing"
941
+ else:
942
+ first_blocker = None
943
+ return {
944
+ "declared": True,
945
+ "available": available,
946
+ "package_json_present": package_json_present,
947
+ "server_entry_present": server_entry_present,
948
+ "package_lock_present": package_lock_present,
949
+ "path_recorded": False,
950
+ "first_blocker": first_blocker,
951
+ }
952
+
953
+ def build_agents_last_exam_host_codex_cli_route(
954
+ *,
955
+ codex_binary: str | None = "codex",
956
+ codex_binary_available: bool | None = None,
957
+ codex_version_text: str | None = None,
958
+ host_auth_cache_present: bool | None = None,
959
+ host_config_present: bool | None = None,
960
+ require_host_config: bool = False,
961
+ cua_mcp_assets_root: str | None = None,
962
+ ale_sandbox_cua_smoke_ready: bool = False,
963
+ operator_authorized_host_codex_auth: bool = False,
964
+ ) -> dict[str, Any]:
965
+ """Gate the ALE host-Codex route before any task-level execution.
966
+
967
+ The contract intentionally checks only host-side existence/probe facts. It
968
+ must not read, print, copy, or persist Codex auth material or task content.
969
+ """
970
+
971
+ codex_probe = _agents_last_exam_codex_cli_probe(
972
+ codex_binary,
973
+ binary_available=codex_binary_available,
974
+ version_text=codex_version_text,
975
+ )
976
+ auth_present = (
977
+ Path.home().joinpath(".codex", "auth.json").is_file()
978
+ if host_auth_cache_present is None
979
+ else bool(host_auth_cache_present)
980
+ )
981
+ config_present = (
982
+ Path.home().joinpath(".codex", "config.toml").is_file()
983
+ if host_config_present is None
984
+ else bool(host_config_present)
985
+ )
986
+ assets_probe = _agents_last_exam_cua_mcp_assets_probe(cua_mcp_assets_root)
987
+
988
+ blockers: list[str] = []
989
+ if operator_authorized_host_codex_auth is not True:
990
+ blockers.append("operator_authorization_missing")
991
+ if codex_probe.get("binary_available") is not True:
992
+ blockers.append(
993
+ _agents_last_exam_public_id(codex_probe.get("first_blocker"), limit=80)
994
+ or "host_codex_binary_not_available"
995
+ )
996
+ if codex_probe.get("version_probe_available") is not True:
997
+ blockers.append("host_codex_version_probe_missing")
998
+ if auth_present is not True:
999
+ blockers.append("host_codex_auth_cache_missing")
1000
+ if require_host_config and config_present is not True:
1001
+ blockers.append("host_codex_config_missing")
1002
+ if assets_probe.get("first_blocker"):
1003
+ blockers.append(
1004
+ _agents_last_exam_public_id(assets_probe.get("first_blocker"), limit=80)
1005
+ or "cua_mcp_assets_not_ready"
1006
+ )
1007
+ if ale_sandbox_cua_smoke_ready is not True:
1008
+ blockers.append("ale_sandbox_cua_smoke_not_ready")
1009
+
1010
+ ready = not blockers
1011
+ return {
1012
+ "schema_version": AGENTS_LAST_EXAM_HOST_CODEX_CLI_ROUTE_SCHEMA_VERSION,
1013
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
1014
+ "ready": ready,
1015
+ "first_blocker": blockers[0]
1016
+ if blockers
1017
+ else "ready_for_no_task_host_codex_cua_smoke",
1018
+ "blockers": blockers,
1019
+ "route": {
1020
+ "mode": "host_codex_cli_local_executor",
1021
+ "uses_host_codex_cli": True,
1022
+ "uses_existing_host_codex_auth": True,
1023
+ "runs_codex_inside_ale_sandbox": False,
1024
+ "drives_ale_sandbox_via_cua_mcp": True,
1025
+ "upstream_sandbox_codex_agent_bypassed": True,
1026
+ "upstream_provider_key_path_required": False,
1027
+ "next_smoke": "no_task_host_codex_cli_cua_mcp_smoke",
1028
+ },
1029
+ "host_codex_cli": codex_probe,
1030
+ "host_auth": {
1031
+ "auth_cache_present": auth_present,
1032
+ "config_present": config_present,
1033
+ "config_required": require_host_config,
1034
+ "auth_values_read": False,
1035
+ "config_content_read": False,
1036
+ "credential_values_recorded": False,
1037
+ "auth_material_copied_to_sandbox": False,
1038
+ "whole_codex_dir_copied": False,
1039
+ "paths_recorded": False,
1040
+ },
1041
+ "cua_mcp_assets": assets_probe,
1042
+ "ale_sandbox": {
1043
+ "cua_smoke_ready": ale_sandbox_cua_smoke_ready is True,
1044
+ "container_started_by_this_check": False,
1045
+ "sandbox_auth_material_present": False,
1046
+ "sandbox_auth_values_read": False,
1047
+ },
1048
+ "boundary": {
1049
+ "local_only": True,
1050
+ "no_upload": True,
1051
+ "submit_eligible": False,
1052
+ "leaderboard_evidence": False,
1053
+ "container_started": False,
1054
+ "task_body_read": False,
1055
+ "model_api_invoked": False,
1056
+ "raw_trajectory_read": False,
1057
+ "screenshot_captured": False,
1058
+ "credential_values_recorded": False,
1059
+ "hidden_references_allowed": False,
1060
+ "production_actions_allowed": False,
1061
+ "local_paths_recorded": False,
1062
+ "command_argv_recorded": False,
1063
+ },
1064
+ "decision": {
1065
+ "next_allowed_action": "run_no_task_host_codex_cli_cua_smoke"
1066
+ if ready
1067
+ else "repair_host_codex_cli_route_blocker",
1068
+ "minimum_next_evidence": (
1069
+ "A no-task host Codex CLI smoke using a project-local temporary "
1070
+ "Codex config and the ALE CUA MCP bridge, with no task prompt, "
1071
+ "no credential values, no upload, no submit, and compact result "
1072
+ "only."
1073
+ ),
1074
+ "must_not_claim": [
1075
+ "ALE task success",
1076
+ "ALE score uplift",
1077
+ "LoopX treatment advantage",
1078
+ "leaderboard evidence",
1079
+ ],
1080
+ },
1081
+ "read_boundary": {
1082
+ "compact_only": True,
1083
+ "auth_values_read": False,
1084
+ "config_content_read": False,
1085
+ "task_text_read": False,
1086
+ "raw_artifacts_read": False,
1087
+ "local_paths_recorded": False,
1088
+ "container_started": False,
1089
+ },
1090
+ }
1091
+
1092
+ def _agents_last_exam_codex_exec_surface_probe(
1093
+ codex_binary: str | None,
1094
+ ) -> dict[str, Any]:
1095
+ codex_probe = _agents_last_exam_codex_cli_probe(codex_binary)
1096
+ if codex_probe.get("binary_available") is not True:
1097
+ return {
1098
+ "available": False,
1099
+ "exit_code": None,
1100
+ "stdout_recorded": False,
1101
+ "stderr_recorded": False,
1102
+ "command_argv_recorded": False,
1103
+ "model_invoked": False,
1104
+ "first_blocker": codex_probe.get("first_blocker")
1105
+ or "host_codex_binary_not_available",
1106
+ }
1107
+ if not isinstance(codex_binary, str) or "/" in codex_binary or "\\" in codex_binary:
1108
+ return {
1109
+ "available": False,
1110
+ "exit_code": None,
1111
+ "stdout_recorded": False,
1112
+ "stderr_recorded": False,
1113
+ "command_argv_recorded": False,
1114
+ "model_invoked": False,
1115
+ "first_blocker": "host_codex_binary_not_public_safe",
1116
+ }
1117
+ try:
1118
+ result = subprocess.run(
1119
+ [codex_binary, "exec", "--help"],
1120
+ check=False,
1121
+ text=True,
1122
+ capture_output=True,
1123
+ timeout=20,
1124
+ )
1125
+ except Exception:
1126
+ return {
1127
+ "available": False,
1128
+ "exit_code": None,
1129
+ "stdout_recorded": False,
1130
+ "stderr_recorded": False,
1131
+ "command_argv_recorded": False,
1132
+ "model_invoked": False,
1133
+ "first_blocker": "codex_exec_help_probe_failed",
1134
+ }
1135
+ ok = result.returncode == 0
1136
+ return {
1137
+ "available": ok,
1138
+ "exit_code": result.returncode,
1139
+ "stdout_recorded": False,
1140
+ "stderr_recorded": False,
1141
+ "command_argv_recorded": False,
1142
+ "model_invoked": False,
1143
+ "first_blocker": None if ok else "codex_exec_help_nonzero",
1144
+ }
1145
+
1146
+ def _agents_last_exam_codex_mcp_config_probe(
1147
+ codex_binary: str | None,
1148
+ *,
1149
+ cua_mcp_assets_root: str | None,
1150
+ cua_server_url: str,
1151
+ ) -> dict[str, Any]:
1152
+ codex_probe = _agents_last_exam_codex_cli_probe(codex_binary)
1153
+ assets_probe = _agents_last_exam_cua_mcp_assets_probe(cua_mcp_assets_root)
1154
+ if codex_probe.get("binary_available") is not True:
1155
+ return {
1156
+ "available": False,
1157
+ "server_detected": False,
1158
+ "server_enabled": False,
1159
+ "transport": None,
1160
+ "raw_output_recorded": False,
1161
+ "config_path_recorded": False,
1162
+ "mcp_server_path_recorded": False,
1163
+ "command_argv_recorded": False,
1164
+ "auth_values_read": False,
1165
+ "first_blocker": codex_probe.get("first_blocker")
1166
+ or "host_codex_binary_not_available",
1167
+ }
1168
+ if assets_probe.get("first_blocker"):
1169
+ return {
1170
+ "available": False,
1171
+ "server_detected": False,
1172
+ "server_enabled": False,
1173
+ "transport": None,
1174
+ "raw_output_recorded": False,
1175
+ "config_path_recorded": False,
1176
+ "mcp_server_path_recorded": False,
1177
+ "command_argv_recorded": False,
1178
+ "auth_values_read": False,
1179
+ "first_blocker": assets_probe.get("first_blocker")
1180
+ or "cua_mcp_assets_not_ready",
1181
+ }
1182
+ if not isinstance(codex_binary, str) or "/" in codex_binary or "\\" in codex_binary:
1183
+ return {
1184
+ "available": False,
1185
+ "server_detected": False,
1186
+ "server_enabled": False,
1187
+ "transport": None,
1188
+ "raw_output_recorded": False,
1189
+ "config_path_recorded": False,
1190
+ "mcp_server_path_recorded": False,
1191
+ "command_argv_recorded": False,
1192
+ "auth_values_read": False,
1193
+ "first_blocker": "host_codex_binary_not_public_safe",
1194
+ }
1195
+
1196
+ try:
1197
+ assets_root = Path(str(cua_mcp_assets_root)).expanduser().resolve()
1198
+ with tempfile.TemporaryDirectory(prefix="loopx-codex-home-") as tmp:
1199
+ codex_home = Path(tmp)
1200
+ mcp_entry = assets_root / "src" / "index.js"
1201
+ config_text = "\n".join(
1202
+ [
1203
+ "[mcp_servers.cua]",
1204
+ 'command = "node"',
1205
+ f'args = ["{mcp_entry}"]',
1206
+ f'env = {{ CUA_SERVER_URL = "{cua_server_url}" }}',
1207
+ "",
1208
+ ]
1209
+ )
1210
+ (codex_home / "config.toml").write_text(config_text, encoding="utf-8")
1211
+ env = os.environ.copy()
1212
+ env["CODEX_HOME"] = str(codex_home)
1213
+ result = subprocess.run(
1214
+ [codex_binary, "mcp", "list", "--json"],
1215
+ check=False,
1216
+ text=True,
1217
+ capture_output=True,
1218
+ timeout=20,
1219
+ env=env,
1220
+ )
1221
+ except Exception:
1222
+ return {
1223
+ "available": False,
1224
+ "server_detected": False,
1225
+ "server_enabled": False,
1226
+ "transport": None,
1227
+ "raw_output_recorded": False,
1228
+ "config_path_recorded": False,
1229
+ "mcp_server_path_recorded": False,
1230
+ "command_argv_recorded": False,
1231
+ "auth_values_read": False,
1232
+ "first_blocker": "codex_mcp_config_probe_failed",
1233
+ }
1234
+
1235
+ server_detected = False
1236
+ server_enabled = False
1237
+ transport_type: str | None = None
1238
+ if result.returncode == 0:
1239
+ try:
1240
+ rows = json.loads(result.stdout)
1241
+ except json.JSONDecodeError:
1242
+ rows = []
1243
+ if isinstance(rows, list):
1244
+ for row in rows:
1245
+ if not isinstance(row, dict) or row.get("name") != "cua":
1246
+ continue
1247
+ server_detected = True
1248
+ server_enabled = row.get("enabled") is True
1249
+ transport = row.get("transport")
1250
+ if isinstance(transport, dict):
1251
+ transport_type = _agents_last_exam_public_id(
1252
+ transport.get("type"),
1253
+ limit=40,
1254
+ )
1255
+ break
1256
+ if result.returncode != 0:
1257
+ first_blocker = "codex_mcp_list_nonzero"
1258
+ elif not server_detected:
1259
+ first_blocker = "codex_mcp_cua_server_not_detected"
1260
+ elif not server_enabled:
1261
+ first_blocker = "codex_mcp_cua_server_not_enabled"
1262
+ elif transport_type != "stdio":
1263
+ first_blocker = "codex_mcp_cua_transport_not_stdio"
1264
+ else:
1265
+ first_blocker = None
1266
+ return {
1267
+ "available": first_blocker is None,
1268
+ "server_detected": server_detected,
1269
+ "server_enabled": server_enabled,
1270
+ "transport": transport_type,
1271
+ "raw_output_recorded": False,
1272
+ "config_path_recorded": False,
1273
+ "mcp_server_path_recorded": False,
1274
+ "command_argv_recorded": False,
1275
+ "auth_values_read": False,
1276
+ "first_blocker": first_blocker,
1277
+ }
1278
+
1279
+ def _agents_last_exam_fake_cua_server():
1280
+ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
1281
+ import threading
1282
+
1283
+ class Handler(BaseHTTPRequestHandler):
1284
+ def do_POST(self) -> None: # noqa: N802
1285
+ length = int(self.headers.get("content-length") or "0")
1286
+ body = self.rfile.read(length) if length > 0 else b"{}"
1287
+ try:
1288
+ request = json.loads(body.decode("utf-8"))
1289
+ except json.JSONDecodeError:
1290
+ request = {}
1291
+ command = request.get("command")
1292
+ if command == "get_screen_size":
1293
+ payload = {"success": True, "size": {"width": 1024, "height": 768}}
1294
+ elif command == "screenshot":
1295
+ payload = {"success": True, "image_data": "iVBORw0KGgo="}
1296
+ elif command == "get_cursor_position":
1297
+ payload = {"success": True, "position": {"x": 512, "y": 384}}
1298
+ else:
1299
+ payload = {"success": True}
1300
+ data = f"data: {json.dumps(payload)}\n\n".encode("utf-8")
1301
+ self.send_response(200)
1302
+ self.send_header("content-type", "text/event-stream")
1303
+ self.send_header("content-length", str(len(data)))
1304
+ self.end_headers()
1305
+ self.wfile.write(data)
1306
+
1307
+ def log_message(self, *_args: Any) -> None:
1308
+ return
1309
+
1310
+ server = ThreadingHTTPServer(("127.0.0.1", 0), Handler)
1311
+ thread = threading.Thread(target=server.serve_forever, daemon=True)
1312
+ thread.start()
1313
+ return server
1314
+
1315
+ def _agents_last_exam_cua_mcp_test_probe(
1316
+ *,
1317
+ cua_mcp_assets_root: str | None,
1318
+ install_node_deps: bool = False,
1319
+ ) -> dict[str, Any]:
1320
+ assets_probe = _agents_last_exam_cua_mcp_assets_probe(cua_mcp_assets_root)
1321
+ if assets_probe.get("first_blocker"):
1322
+ return {
1323
+ "available": False,
1324
+ "node_available": shutil.which("node") is not None,
1325
+ "npm_install_attempted": False,
1326
+ "fake_cua_server_used": False,
1327
+ "raw_output_recorded": False,
1328
+ "command_argv_recorded": False,
1329
+ "local_paths_recorded": False,
1330
+ "first_blocker": assets_probe.get("first_blocker")
1331
+ or "cua_mcp_assets_not_ready",
1332
+ }
1333
+ if not shutil.which("node"):
1334
+ return {
1335
+ "available": False,
1336
+ "node_available": False,
1337
+ "npm_install_attempted": False,
1338
+ "fake_cua_server_used": False,
1339
+ "raw_output_recorded": False,
1340
+ "command_argv_recorded": False,
1341
+ "local_paths_recorded": False,
1342
+ "first_blocker": "node_cli_missing",
1343
+ }
1344
+
1345
+ server = None
1346
+ try:
1347
+ with tempfile.TemporaryDirectory(prefix="loopx-cua-mcp-") as tmp:
1348
+ work_root = Path(tmp) / "cua_mcp_server"
1349
+ shutil.copytree(str(cua_mcp_assets_root), work_root)
1350
+ node_modules = work_root / "node_modules"
1351
+ npm_install_attempted = False
1352
+ if not node_modules.is_dir():
1353
+ if not install_node_deps:
1354
+ return {
1355
+ "available": False,
1356
+ "node_available": True,
1357
+ "npm_install_attempted": False,
1358
+ "fake_cua_server_used": False,
1359
+ "raw_output_recorded": False,
1360
+ "command_argv_recorded": False,
1361
+ "local_paths_recorded": False,
1362
+ "first_blocker": "cua_mcp_node_modules_missing",
1363
+ }
1364
+ if not shutil.which("npm"):
1365
+ return {
1366
+ "available": False,
1367
+ "node_available": True,
1368
+ "npm_install_attempted": False,
1369
+ "fake_cua_server_used": False,
1370
+ "raw_output_recorded": False,
1371
+ "command_argv_recorded": False,
1372
+ "local_paths_recorded": False,
1373
+ "first_blocker": "npm_cli_missing",
1374
+ }
1375
+ npm_install_attempted = True
1376
+ npm_result = subprocess.run(
1377
+ ["npm", "install", "--production", "--silent"],
1378
+ cwd=work_root,
1379
+ check=False,
1380
+ text=True,
1381
+ capture_output=True,
1382
+ timeout=120,
1383
+ )
1384
+ if npm_result.returncode != 0:
1385
+ return {
1386
+ "available": False,
1387
+ "node_available": True,
1388
+ "npm_install_attempted": True,
1389
+ "fake_cua_server_used": False,
1390
+ "raw_output_recorded": False,
1391
+ "command_argv_recorded": False,
1392
+ "local_paths_recorded": False,
1393
+ "first_blocker": "cua_mcp_npm_install_failed",
1394
+ }
1395
+ server = _agents_last_exam_fake_cua_server()
1396
+ port = server.server_address[1]
1397
+ env = os.environ.copy()
1398
+ env["CUA_SERVER_URL"] = f"http://127.0.0.1:{port}"
1399
+ test_result = subprocess.run(
1400
+ ["node", "src/index.js", "--test"],
1401
+ cwd=work_root,
1402
+ check=False,
1403
+ text=True,
1404
+ capture_output=True,
1405
+ timeout=60,
1406
+ env=env,
1407
+ )
1408
+ except Exception:
1409
+ return {
1410
+ "available": False,
1411
+ "node_available": shutil.which("node") is not None,
1412
+ "npm_install_attempted": install_node_deps,
1413
+ "fake_cua_server_used": server is not None,
1414
+ "raw_output_recorded": False,
1415
+ "command_argv_recorded": False,
1416
+ "local_paths_recorded": False,
1417
+ "first_blocker": "cua_mcp_test_probe_failed",
1418
+ }
1419
+ finally:
1420
+ if server is not None:
1421
+ server.shutdown()
1422
+ server.server_close()
1423
+
1424
+ ok = test_result.returncode == 0
1425
+ return {
1426
+ "available": ok,
1427
+ "node_available": True,
1428
+ "npm_install_attempted": npm_install_attempted,
1429
+ "fake_cua_server_used": True,
1430
+ "raw_output_recorded": False,
1431
+ "command_argv_recorded": False,
1432
+ "local_paths_recorded": False,
1433
+ "first_blocker": None if ok else "cua_mcp_test_nonzero",
1434
+ }
1435
+
1436
+ def build_agents_last_exam_host_codex_cua_no_task_smoke(
1437
+ *,
1438
+ route_gate: dict[str, Any],
1439
+ codex_exec_probe: dict[str, Any],
1440
+ mcp_config_probe: dict[str, Any],
1441
+ cua_mcp_test_probe: dict[str, Any],
1442
+ ) -> dict[str, Any]:
1443
+ blockers: list[str] = []
1444
+ if route_gate.get("ready") is not True:
1445
+ blockers.append(
1446
+ _agents_last_exam_public_id(route_gate.get("first_blocker"), limit=80)
1447
+ or "host_codex_route_gate_not_ready"
1448
+ )
1449
+ for probe_name, probe in (
1450
+ ("codex_exec_surface", codex_exec_probe),
1451
+ ("codex_mcp_config", mcp_config_probe),
1452
+ ("cua_mcp_bridge", cua_mcp_test_probe),
1453
+ ):
1454
+ if probe.get("available") is not True:
1455
+ blockers.append(
1456
+ _agents_last_exam_public_id(probe.get("first_blocker"), limit=80)
1457
+ or f"{probe_name}_not_ready"
1458
+ )
1459
+ ready = not blockers
1460
+ return {
1461
+ "schema_version": AGENTS_LAST_EXAM_HOST_CODEX_CUA_NO_TASK_SMOKE_SCHEMA_VERSION,
1462
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
1463
+ "ready": ready,
1464
+ "first_blocker": blockers[0]
1465
+ if blockers
1466
+ else "ready_for_task_level_ale_codex_dry_run_gate",
1467
+ "blockers": blockers,
1468
+ "route_gate_ready": route_gate.get("ready") is True,
1469
+ "route_gate": route_gate,
1470
+ "codex_exec_surface": codex_exec_probe,
1471
+ "codex_mcp_config": mcp_config_probe,
1472
+ "cua_mcp_bridge": cua_mcp_test_probe,
1473
+ "boundary": {
1474
+ "local_only": True,
1475
+ "no_upload": True,
1476
+ "submit_eligible": False,
1477
+ "leaderboard_evidence": False,
1478
+ "container_started": False,
1479
+ "task_body_read": False,
1480
+ "model_api_invoked": False,
1481
+ "codex_prompt_sent": False,
1482
+ "raw_trajectory_read": False,
1483
+ "screenshot_captured": False,
1484
+ "credential_values_recorded": False,
1485
+ "hidden_references_allowed": False,
1486
+ "production_actions_allowed": False,
1487
+ "local_paths_recorded": False,
1488
+ "command_argv_recorded": False,
1489
+ "raw_output_recorded": False,
1490
+ },
1491
+ "decision": {
1492
+ "next_allowed_action": "prepare_operator_authorized_task_level_ale_codex_dry_run"
1493
+ if ready
1494
+ else "repair_no_task_host_codex_cua_smoke_blocker",
1495
+ "minimum_next_evidence": (
1496
+ "An operator-authorized task-level ALE dry-run may proceed only "
1497
+ "after compact route, Codex exec surface, Codex MCP config, and "
1498
+ "CUA MCP bridge probes are ready."
1499
+ ),
1500
+ "must_not_claim": [
1501
+ "ALE task success",
1502
+ "ALE score uplift",
1503
+ "LoopX treatment advantage",
1504
+ "leaderboard evidence",
1505
+ ],
1506
+ },
1507
+ "read_boundary": {
1508
+ "compact_only": True,
1509
+ "auth_values_read": False,
1510
+ "config_content_read": False,
1511
+ "task_text_read": False,
1512
+ "raw_artifacts_read": False,
1513
+ "local_paths_recorded": False,
1514
+ "container_started": False,
1515
+ },
1516
+ }
1517
+
1518
+ def build_agents_last_exam_host_codex_cua_no_task_smoke_from_environment(
1519
+ *,
1520
+ codex_binary: str | None = "codex",
1521
+ codex_binary_available: bool | None = None,
1522
+ codex_version_text: str | None = None,
1523
+ host_auth_cache_present: bool | None = None,
1524
+ host_config_present: bool | None = None,
1525
+ require_host_config: bool = False,
1526
+ cua_mcp_assets_root: str | None = None,
1527
+ cua_server_url: str = "http://127.0.0.1:8000",
1528
+ install_node_deps: bool = False,
1529
+ ale_sandbox_cua_smoke_ready: bool = False,
1530
+ operator_authorized_host_codex_auth: bool = False,
1531
+ ) -> dict[str, Any]:
1532
+ """Build compact no-task host Codex/CUA readiness evidence.
1533
+
1534
+ This is deliberately a pre-task probe: it checks CLI/help, Codex MCP config
1535
+ loading, and the local CUA MCP bridge without sending a Codex prompt,
1536
+ reading task material, or recording auth/path/raw-output details.
1537
+ """
1538
+
1539
+ route_gate = build_agents_last_exam_host_codex_cli_route(
1540
+ codex_binary=codex_binary,
1541
+ codex_binary_available=codex_binary_available,
1542
+ codex_version_text=codex_version_text,
1543
+ host_auth_cache_present=host_auth_cache_present,
1544
+ host_config_present=host_config_present,
1545
+ require_host_config=require_host_config,
1546
+ cua_mcp_assets_root=cua_mcp_assets_root,
1547
+ ale_sandbox_cua_smoke_ready=ale_sandbox_cua_smoke_ready,
1548
+ operator_authorized_host_codex_auth=operator_authorized_host_codex_auth,
1549
+ )
1550
+ codex_exec_probe = _agents_last_exam_codex_exec_surface_probe(codex_binary)
1551
+ mcp_config_probe = _agents_last_exam_codex_mcp_config_probe(
1552
+ codex_binary,
1553
+ cua_mcp_assets_root=cua_mcp_assets_root,
1554
+ cua_server_url=cua_server_url,
1555
+ )
1556
+ cua_mcp_test_probe = _agents_last_exam_cua_mcp_test_probe(
1557
+ cua_mcp_assets_root=cua_mcp_assets_root,
1558
+ install_node_deps=install_node_deps,
1559
+ )
1560
+ return build_agents_last_exam_host_codex_cua_no_task_smoke(
1561
+ route_gate=route_gate,
1562
+ codex_exec_probe=codex_exec_probe,
1563
+ mcp_config_probe=mcp_config_probe,
1564
+ cua_mcp_test_probe=cua_mcp_test_probe,
1565
+ )
1566
+
1567
+ def _agents_last_exam_boundary_flag(
1568
+ payload: dict[str, Any],
1569
+ key: str,
1570
+ *,
1571
+ default: bool = False,
1572
+ ) -> bool:
1573
+ boundary = payload.get("boundary") if isinstance(payload.get("boundary"), dict) else {}
1574
+ return bool(boundary.get(key, default))
1575
+
1576
+ def _agents_last_exam_ready_input(
1577
+ payload: dict[str, Any],
1578
+ *,
1579
+ schema_version: str,
1580
+ blocker_prefix: str,
1581
+ ) -> tuple[bool, str | None]:
1582
+ if not isinstance(payload, dict):
1583
+ return False, f"{blocker_prefix}_missing"
1584
+ if payload.get("schema_version") != schema_version:
1585
+ return False, f"{blocker_prefix}_schema_mismatch"
1586
+ if payload.get("ready") is not True:
1587
+ first_blocker = _agents_last_exam_public_id(
1588
+ payload.get("first_blocker"),
1589
+ limit=80,
1590
+ )
1591
+ return False, first_blocker or f"{blocker_prefix}_not_ready"
1592
+ return True, None
1593
+
1594
+ def _agents_last_exam_source_freshness_input(
1595
+ launch_packet: dict[str, Any] | None,
1596
+ *,
1597
+ required: bool,
1598
+ ) -> tuple[bool | None, str | None]:
1599
+ if not required:
1600
+ return None, None
1601
+ if not isinstance(launch_packet, dict):
1602
+ return False, "fresh_source_launch_packet_missing"
1603
+ source_lock = launch_packet.get("source_lock")
1604
+ if not isinstance(source_lock, dict):
1605
+ return False, "ale_source_freshness_not_verified"
1606
+ if source_lock.get("fetch_origin_attempted") is not True:
1607
+ return False, "ale_source_fetch_origin_not_attempted"
1608
+ if source_lock.get("fetch_origin_ok") is not True:
1609
+ return False, "ale_source_fetch_origin_failed"
1610
+ if source_lock.get("require_upstream_current") is not True:
1611
+ return False, "ale_source_upstream_current_not_required"
1612
+ if source_lock.get("upstream_declared") is not True:
1613
+ return False, "ale_source_upstream_missing"
1614
+ if source_lock.get("head_matches_upstream") is not True:
1615
+ return False, "ale_source_not_at_upstream_head"
1616
+ if source_lock.get("upstream_ahead_count") != 0:
1617
+ return False, "ale_source_upstream_ahead_count_nonzero"
1618
+ if source_lock.get("upstream_behind_count") != 0:
1619
+ return False, "ale_source_upstream_behind_count_nonzero"
1620
+ return True, None
1621
+
1622
+ def _agents_last_exam_case_state_init_contract_input(
1623
+ launch_packet: dict[str, Any] | None,
1624
+ ) -> tuple[bool, str | None]:
1625
+ if not isinstance(launch_packet, dict):
1626
+ return False, "launch_packet_missing_for_case_state_init_contract"
1627
+ contract = launch_packet.get("case_state_init_contract")
1628
+ if not isinstance(contract, dict):
1629
+ return False, "case_state_init_contract_missing"
1630
+ if contract.get("schema_version") != BENCHMARK_CASE_ACTIVE_STATE_SCHEMA_VERSION:
1631
+ return False, "case_state_init_contract_schema_mismatch"
1632
+ if contract.get("benchmark_case_goal_id") != AGENTS_LAST_EXAM_CASE_GOAL_ID:
1633
+ return False, "case_state_init_contract_goal_id_mismatch"
1634
+ if contract.get("case_state_path") != AGENTS_LAST_EXAM_CASE_STATE_PATH:
1635
+ return False, "case_state_init_contract_path_mismatch"
1636
+ if contract.get("init_required_before_worker") is not True:
1637
+ return False, "case_state_init_not_required_before_worker"
1638
+ if contract.get("initialized_by_launch_packet") is not False:
1639
+ return False, "case_state_initialized_by_no_execution_packet"
1640
+ if contract.get("surrogate_state_files_allowed") is not False:
1641
+ return False, "case_state_surrogate_files_allowed"
1642
+ if contract.get("raw_task_text_required_for_init") is not False:
1643
+ return False, "case_state_init_requires_raw_task_text"
1644
+ if contract.get("local_paths_recorded") is not False:
1645
+ return False, "case_state_init_contract_local_paths_recorded"
1646
+ proof_fields = contract.get("proof_fields")
1647
+ required_fields = set(BENCHMARK_CASE_ACTIVE_STATE_PROOF_FIELDS)
1648
+ if not isinstance(proof_fields, list) or not required_fields.issubset(
1649
+ {str(field) for field in proof_fields}
1650
+ ):
1651
+ return False, "case_state_init_contract_proof_fields_incomplete"
1652
+ return True, None
1653
+
1654
+ def build_agents_last_exam_validation_run_gate(
1655
+ *,
1656
+ selected_task_id: str | None,
1657
+ validation_hypothesis: str | None,
1658
+ task_material_readiness: dict[str, Any],
1659
+ host_codex_no_task_e2e: dict[str, Any],
1660
+ exact_dry_run_result: dict[str, Any],
1661
+ launch_packet: dict[str, Any] | None = None,
1662
+ result_reducer_ready: bool = False,
1663
+ no_upload: bool = True,
1664
+ submit_enabled: bool = False,
1665
+ leaderboard_enabled: bool = False,
1666
+ formal_score_candidate: bool = False,
1667
+ require_fresh_source: bool = False,
1668
+ expected_formal_agent: str = "host_codex_gpt55_xhigh",
1669
+ ) -> dict[str, Any]:
1670
+ """Combine compact ALE readiness into a pre-run decision gate."""
1671
+
1672
+ task_label = _agents_last_exam_public_id(selected_task_id, limit=180)
1673
+ hypothesis_label = _agents_last_exam_public_id(validation_hypothesis, limit=240)
1674
+ fresh_source_required = bool(formal_score_candidate or require_fresh_source)
1675
+ blockers: list[str] = []
1676
+ for payload, schema_version, prefix in (
1677
+ (
1678
+ task_material_readiness,
1679
+ AGENTS_LAST_EXAM_TASK_MATERIAL_READINESS_SCHEMA_VERSION,
1680
+ "task_material_readiness",
1681
+ ),
1682
+ (
1683
+ host_codex_no_task_e2e,
1684
+ AGENTS_LAST_EXAM_HOST_CODEX_CUA_NO_TASK_SMOKE_SCHEMA_VERSION,
1685
+ "host_codex_no_task_e2e",
1686
+ ),
1687
+ (
1688
+ exact_dry_run_result,
1689
+ AGENTS_LAST_EXAM_LOCAL_EXACT_DRY_RUN_RESULT_SCHEMA_VERSION,
1690
+ "exact_dry_run_result",
1691
+ ),
1692
+ ):
1693
+ ready, blocker = _agents_last_exam_ready_input(
1694
+ payload,
1695
+ schema_version=schema_version,
1696
+ blocker_prefix=prefix,
1697
+ )
1698
+ if not ready and blocker:
1699
+ blockers.append(blocker)
1700
+
1701
+ launch_packet_ready = None
1702
+ if launch_packet is not None:
1703
+ ready, blocker = _agents_last_exam_ready_input(
1704
+ launch_packet,
1705
+ schema_version=AGENTS_LAST_EXAM_LOCAL_LAUNCH_PACKET_SCHEMA_VERSION,
1706
+ blocker_prefix="launch_packet",
1707
+ )
1708
+ launch_packet_ready = ready
1709
+ if not ready and blocker:
1710
+ blockers.append(blocker)
1711
+
1712
+ fresh_source_ready, fresh_source_blocker = _agents_last_exam_source_freshness_input(
1713
+ launch_packet,
1714
+ required=fresh_source_required,
1715
+ )
1716
+ if fresh_source_blocker:
1717
+ blockers.append(fresh_source_blocker)
1718
+ case_state_contract_ready, case_state_contract_blocker = (
1719
+ _agents_last_exam_case_state_init_contract_input(launch_packet)
1720
+ )
1721
+ if case_state_contract_blocker:
1722
+ blockers.append(case_state_contract_blocker)
1723
+
1724
+ if not hypothesis_label:
1725
+ blockers.append("validation_hypothesis_missing")
1726
+ if result_reducer_ready is not True:
1727
+ blockers.append("compact_result_reducer_not_ready")
1728
+ if no_upload is not True:
1729
+ blockers.append("no_upload_boundary_not_enabled")
1730
+ if submit_enabled:
1731
+ blockers.append("submit_must_remain_disabled")
1732
+ if leaderboard_enabled:
1733
+ blockers.append("leaderboard_must_remain_disabled")
1734
+
1735
+ boundary_payloads = [
1736
+ ("task_material_readiness", task_material_readiness),
1737
+ ("host_codex_no_task_e2e", host_codex_no_task_e2e),
1738
+ ("exact_dry_run_result", exact_dry_run_result),
1739
+ ]
1740
+ if launch_packet is not None:
1741
+ boundary_payloads.append(("launch_packet", launch_packet))
1742
+ for name, payload in boundary_payloads:
1743
+ if _agents_last_exam_boundary_flag(payload, "credential_values_recorded"):
1744
+ blockers.append(f"{name}_credential_values_recorded")
1745
+ if _agents_last_exam_boundary_flag(payload, "local_paths_recorded"):
1746
+ blockers.append(f"{name}_local_paths_recorded")
1747
+ if _agents_last_exam_boundary_flag(payload, "raw_trajectory_read"):
1748
+ blockers.append(f"{name}_raw_trajectory_read")
1749
+ if _agents_last_exam_boundary_flag(payload, "task_body_read"):
1750
+ blockers.append(f"{name}_task_body_read")
1751
+ if _agents_last_exam_boundary_flag(payload, "screenshot_captured"):
1752
+ blockers.append(f"{name}_screenshot_captured")
1753
+ if _agents_last_exam_boundary_flag(payload, "hidden_references_allowed"):
1754
+ blockers.append(f"{name}_hidden_refs_allowed")
1755
+ if _agents_last_exam_boundary_flag(payload, "production_actions_allowed"):
1756
+ blockers.append(f"{name}_production_actions_allowed")
1757
+
1758
+ expected = (
1759
+ exact_dry_run_result.get("expected")
1760
+ if isinstance(exact_dry_run_result.get("expected"), dict)
1761
+ else {}
1762
+ )
1763
+ expected_task = expected.get("task") if isinstance(expected, dict) else None
1764
+ if task_label and expected_task and task_label != expected_task:
1765
+ blockers.append("selected_task_mismatch_exact_dry_run")
1766
+
1767
+ ready = not blockers
1768
+ return {
1769
+ "schema_version": AGENTS_LAST_EXAM_VALIDATION_RUN_GATE_SCHEMA_VERSION,
1770
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
1771
+ "ready": ready,
1772
+ "first_blocker": blockers[0]
1773
+ if blockers
1774
+ else "ready_for_operator_authorized_local_no_upload_ale_validation_run",
1775
+ "blockers": blockers,
1776
+ "selected_task": {
1777
+ "task_id": task_label,
1778
+ "source": "compact_readiness_artifacts",
1779
+ },
1780
+ "validation_hypothesis": hypothesis_label,
1781
+ "readiness_inputs": {
1782
+ "task_material_ready": task_material_readiness.get("ready") is True,
1783
+ "host_codex_no_task_e2e_ready": host_codex_no_task_e2e.get("ready") is True,
1784
+ "exact_dry_run_ready": exact_dry_run_result.get("ready") is True,
1785
+ "launch_packet_ready": launch_packet_ready,
1786
+ "fresh_source_required": fresh_source_required,
1787
+ "fresh_source_ready": fresh_source_ready,
1788
+ "case_state_init_contract_ready": case_state_contract_ready,
1789
+ "compact_result_reducer_ready": result_reducer_ready is True,
1790
+ },
1791
+ "model_policy": {
1792
+ "connectivity_e2e_model": "gpt-5.3-codex-spark",
1793
+ "formal_score_agent": expected_formal_agent,
1794
+ "formal_score_candidate": bool(formal_score_candidate),
1795
+ },
1796
+ "run_boundary": {
1797
+ "local_only": True,
1798
+ "no_upload": no_upload is True,
1799
+ "submit_eligible": False,
1800
+ "leaderboard_evidence": False,
1801
+ "operator_authorization_required_before_task_run": True,
1802
+ "case_state_init_required_before_worker": True,
1803
+ "case_state_initialized_by_this_gate": False,
1804
+ "case_state_path": AGENTS_LAST_EXAM_CASE_STATE_PATH,
1805
+ "case_state_schema_version": BENCHMARK_CASE_ACTIVE_STATE_SCHEMA_VERSION,
1806
+ "task_run_started_by_this_gate": False,
1807
+ "container_started_by_this_gate": False,
1808
+ "model_api_invoked_by_this_gate": False,
1809
+ "codex_prompt_sent_by_this_gate": False,
1810
+ "raw_trajectory_read": False,
1811
+ "task_body_read_by_loopx": False,
1812
+ "screenshot_captured": False,
1813
+ "credential_values_recorded": False,
1814
+ "hidden_references_allowed": False,
1815
+ "production_actions_allowed": False,
1816
+ "local_paths_recorded": False,
1817
+ "raw_output_recorded": False,
1818
+ },
1819
+ "decision": {
1820
+ "next_allowed_action": "operator_authorized_local_no_upload_ale_validation_run"
1821
+ if ready
1822
+ else "repair_ale_validation_run_gate_blocker",
1823
+ "minimum_next_evidence": (
1824
+ "A task-level ALE run may proceed only as local/no-upload/no-submit "
1825
+ "work with compact result reduction through the ALE reducer, and "
1826
+ "with a concrete LoopX validation hypothesis recorded."
1827
+ ),
1828
+ "must_not_claim": [
1829
+ "ALE task success before compact result ingest",
1830
+ "ALE score uplift before paired evidence",
1831
+ "LoopX treatment advantage before paired evidence",
1832
+ "leaderboard evidence",
1833
+ ],
1834
+ },
1835
+ "read_boundary": {
1836
+ "compact_only": True,
1837
+ "task_text_read": False,
1838
+ "task_card_content_read": False,
1839
+ "script_content_read": False,
1840
+ "raw_artifacts_read": False,
1841
+ "local_paths_recorded": False,
1842
+ "container_started": False,
1843
+ "model_api_invoked": False,
1844
+ "codex_prompt_sent": False,
1845
+ },
1846
+ }
1847
+
1848
+ def _agents_last_exam_normalized_repo_label(value: Any) -> str | None:
1849
+ if not isinstance(value, str):
1850
+ return None
1851
+ text = value.strip()
1852
+ if text.endswith(".git"):
1853
+ text = text[:-4]
1854
+ text = text.replace("git@github.com:", "https://github.com/")
1855
+ text = text.replace("http://github.com/", "https://github.com/")
1856
+ return _agents_last_exam_public_id(text, limit=180)
1857
+
1858
+ def _agents_last_exam_source_git_metadata(
1859
+ source_root: str | None,
1860
+ *,
1861
+ expected_repo_url: str = AGENTS_LAST_EXAM_DEFAULT_REPO_URL,
1862
+ fetch_origin: bool = False,
1863
+ ) -> dict[str, Any]:
1864
+ expected = _agents_last_exam_normalized_repo_label(expected_repo_url)
1865
+ source_root_declared = bool(source_root)
1866
+ source_root_path: Path | None = None
1867
+ if source_root:
1868
+ try:
1869
+ source_root_path = Path(source_root).expanduser()
1870
+ except (OSError, RuntimeError):
1871
+ source_root_path = None
1872
+ source_root_available = bool(source_root_path and source_root_path.is_dir())
1873
+ base = {
1874
+ "source_root_declared": source_root_declared,
1875
+ "source_root_available": source_root_available,
1876
+ "source_root_path_recorded": False,
1877
+ "expected_repo": expected,
1878
+ "remote": None,
1879
+ "remote_matches_expected": False,
1880
+ "head": None,
1881
+ "upstream_ref": None,
1882
+ "upstream_head": None,
1883
+ "upstream_declared": False,
1884
+ "head_matches_upstream": False,
1885
+ "upstream_ahead_count": None,
1886
+ "upstream_behind_count": None,
1887
+ "fetch_origin_attempted": False,
1888
+ "fetch_origin_ok": False,
1889
+ "git_probe_available": shutil.which("git") is not None,
1890
+ "is_git_checkout": False,
1891
+ }
1892
+ if not source_root_declared:
1893
+ return {**base, "first_blocker": "source_root_missing"}
1894
+ if not source_root_available or source_root_path is None:
1895
+ return {**base, "first_blocker": "source_root_not_available"}
1896
+ if not shutil.which("git"):
1897
+ return {**base, "first_blocker": "git_cli_missing"}
1898
+
1899
+ def git_output(*args: str) -> str | None:
1900
+ try:
1901
+ result = subprocess.run(
1902
+ ["git", "-C", str(source_root_path), *args],
1903
+ check=False,
1904
+ text=True,
1905
+ capture_output=True,
1906
+ timeout=10,
1907
+ )
1908
+ except Exception:
1909
+ return None
1910
+ if result.returncode != 0:
1911
+ return None
1912
+ return result.stdout.strip() or None
1913
+
1914
+ def git_run(*args: str) -> bool:
1915
+ try:
1916
+ result = subprocess.run(
1917
+ ["git", "-C", str(source_root_path), *args],
1918
+ check=False,
1919
+ text=True,
1920
+ capture_output=True,
1921
+ timeout=30,
1922
+ )
1923
+ except Exception:
1924
+ return False
1925
+ return result.returncode == 0
1926
+
1927
+ fetch_origin_attempted = bool(fetch_origin)
1928
+ fetch_origin_ok = git_run("fetch", "--prune", "origin") if fetch_origin else False
1929
+
1930
+ top_level = git_output("rev-parse", "--show-toplevel")
1931
+ is_git_checkout = bool(top_level)
1932
+ remote = _agents_last_exam_normalized_repo_label(
1933
+ git_output("remote", "get-url", "origin")
1934
+ )
1935
+ head = _agents_last_exam_public_id(git_output("rev-parse", "HEAD"), limit=80)
1936
+ raw_upstream_ref = git_output(
1937
+ "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"
1938
+ )
1939
+ raw_upstream_head = git_output("rev-parse", "@{upstream}")
1940
+ upstream_fallback_ref = False
1941
+ if not raw_upstream_head:
1942
+ fallback_ref = "origin/main"
1943
+ fallback_head = git_output("rev-parse", fallback_ref)
1944
+ if fallback_head:
1945
+ raw_upstream_ref = fallback_ref
1946
+ raw_upstream_head = fallback_head
1947
+ upstream_fallback_ref = True
1948
+ upstream_ref = _agents_last_exam_public_id(raw_upstream_ref, limit=120)
1949
+ upstream_head = _agents_last_exam_public_id(raw_upstream_head, limit=80)
1950
+ upstream_ahead_count: int | None = None
1951
+ upstream_behind_count: int | None = None
1952
+ rev_target = raw_upstream_ref or "@{upstream}"
1953
+ rev_counts = git_output("rev-list", "--left-right", "--count", f"HEAD...{rev_target}")
1954
+ if rev_counts:
1955
+ parts = rev_counts.split()
1956
+ if len(parts) >= 2:
1957
+ try:
1958
+ upstream_ahead_count = int(parts[0])
1959
+ upstream_behind_count = int(parts[1])
1960
+ except ValueError:
1961
+ upstream_ahead_count = None
1962
+ upstream_behind_count = None
1963
+ metadata = {
1964
+ **base,
1965
+ "remote": remote,
1966
+ "remote_matches_expected": bool(remote and expected and remote == expected),
1967
+ "head": head,
1968
+ "upstream_ref": upstream_ref,
1969
+ "upstream_head": upstream_head,
1970
+ "upstream_declared": bool(upstream_ref),
1971
+ "upstream_fallback_ref": upstream_fallback_ref,
1972
+ "head_matches_upstream": bool(head and upstream_head and head == upstream_head),
1973
+ "upstream_ahead_count": upstream_ahead_count,
1974
+ "upstream_behind_count": upstream_behind_count,
1975
+ "fetch_origin_attempted": fetch_origin_attempted,
1976
+ "fetch_origin_ok": fetch_origin_ok,
1977
+ "is_git_checkout": is_git_checkout,
1978
+ }
1979
+ if not is_git_checkout:
1980
+ return {**metadata, "first_blocker": "source_root_not_git_checkout"}
1981
+ if not remote:
1982
+ return {**metadata, "first_blocker": "source_root_origin_missing"}
1983
+ if expected and remote != expected:
1984
+ return {**metadata, "first_blocker": "source_root_origin_mismatch"}
1985
+ if fetch_origin and not fetch_origin_ok:
1986
+ return {**metadata, "first_blocker": "source_root_fetch_origin_failed"}
1987
+ if not head:
1988
+ return {**metadata, "first_blocker": "source_root_head_missing"}
1989
+ return {**metadata, "first_blocker": None}
1990
+
1991
+ def build_agents_last_exam_local_source_readiness(
1992
+ *,
1993
+ source_root: str | None,
1994
+ expected_repo_url: str = AGENTS_LAST_EXAM_DEFAULT_REPO_URL,
1995
+ runner_python_module: str = "ale_run",
1996
+ fetch_origin: bool = False,
1997
+ require_upstream_current: bool = False,
1998
+ ) -> dict[str, Any]:
1999
+ """Verify a redacted public ALE source checkout contract without running ALE."""
2000
+
2001
+ git_metadata = _agents_last_exam_source_git_metadata(
2002
+ source_root,
2003
+ expected_repo_url=expected_repo_url,
2004
+ fetch_origin=fetch_origin,
2005
+ )
2006
+ module_probe = _agents_last_exam_python_module_probe(
2007
+ runner_python_module,
2008
+ source_root=source_root,
2009
+ )
2010
+ blockers: list[str] = []
2011
+ if git_metadata.get("first_blocker"):
2012
+ blockers.append(str(git_metadata["first_blocker"]))
2013
+ if require_upstream_current:
2014
+ if git_metadata.get("upstream_declared") is not True:
2015
+ blockers.append("source_root_upstream_missing")
2016
+ elif git_metadata.get("head_matches_upstream") is not True:
2017
+ behind = git_metadata.get("upstream_behind_count")
2018
+ ahead = git_metadata.get("upstream_ahead_count")
2019
+ if isinstance(behind, int) and behind > 0:
2020
+ blockers.append("source_root_behind_upstream")
2021
+ elif isinstance(ahead, int) and ahead > 0:
2022
+ blockers.append("source_root_ahead_of_upstream")
2023
+ else:
2024
+ blockers.append("source_root_not_at_upstream_head")
2025
+ if module_probe.get("available") is not True:
2026
+ blockers.append(
2027
+ _agents_last_exam_public_id(module_probe.get("first_blocker"), limit=80)
2028
+ or "runner_python_module_not_available"
2029
+ )
2030
+ ready = not blockers
2031
+ return {
2032
+ "schema_version": AGENTS_LAST_EXAM_LOCAL_SOURCE_READINESS_SCHEMA_VERSION,
2033
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
2034
+ "ready": ready,
2035
+ "first_blocker": blockers[0]
2036
+ if blockers
2037
+ else "ready_for_redacted_ale_source_lock",
2038
+ "blockers": blockers,
2039
+ "source": {
2040
+ "kind": "git_source_root",
2041
+ "expected_repo": git_metadata.get("expected_repo"),
2042
+ "remote": git_metadata.get("remote"),
2043
+ "remote_matches_expected": git_metadata.get("remote_matches_expected")
2044
+ is True,
2045
+ "head": git_metadata.get("head"),
2046
+ "upstream_ref": git_metadata.get("upstream_ref"),
2047
+ "upstream_head": git_metadata.get("upstream_head"),
2048
+ "upstream_declared": git_metadata.get("upstream_declared") is True,
2049
+ "upstream_fallback_ref": git_metadata.get("upstream_fallback_ref") is True,
2050
+ "head_matches_upstream": git_metadata.get("head_matches_upstream")
2051
+ is True,
2052
+ "upstream_ahead_count": git_metadata.get("upstream_ahead_count"),
2053
+ "upstream_behind_count": git_metadata.get("upstream_behind_count"),
2054
+ "fetch_origin_attempted": git_metadata.get("fetch_origin_attempted")
2055
+ is True,
2056
+ "fetch_origin_ok": git_metadata.get("fetch_origin_ok") is True,
2057
+ "require_upstream_current": bool(require_upstream_current),
2058
+ "git_probe_available": git_metadata.get("git_probe_available") is True,
2059
+ "is_git_checkout": git_metadata.get("is_git_checkout") is True,
2060
+ "source_root_declared": git_metadata.get("source_root_declared") is True,
2061
+ "source_root_available": git_metadata.get("source_root_available") is True,
2062
+ "source_root_path_recorded": False,
2063
+ },
2064
+ "runner_probe": {
2065
+ "python_module": module_probe.get("module"),
2066
+ "python_module_declared": module_probe.get("declared") is True,
2067
+ "python_module_available": module_probe.get("available") is True,
2068
+ "python_module_path_recorded": False,
2069
+ "source_root_path_recorded": False,
2070
+ },
2071
+ "boundary": {
2072
+ "local_only": True,
2073
+ "no_upload": True,
2074
+ "submit_eligible": False,
2075
+ "leaderboard_evidence": False,
2076
+ "container_started": False,
2077
+ "task_body_read": False,
2078
+ "model_api_invoked": False,
2079
+ "raw_trajectory_read": False,
2080
+ "screenshot_captured": False,
2081
+ "credential_values_recorded": False,
2082
+ "hidden_references_allowed": False,
2083
+ "production_actions_allowed": False,
2084
+ "local_paths_recorded": False,
2085
+ "command_argv_recorded": False,
2086
+ },
2087
+ "decision": {
2088
+ "next_allowed_action": "use_redacted_source_lock_for_runner_readiness"
2089
+ if ready
2090
+ else "repair_public_ale_source_lock_before_runner_execution",
2091
+ "minimum_next_evidence": (
2092
+ "A durable public ALE checkout with matching origin, commit, and "
2093
+ "importable runner module, followed by no-upload runner readiness."
2094
+ ),
2095
+ "must_not_claim": [
2096
+ "ALE task success",
2097
+ "ALE score uplift",
2098
+ "LoopX treatment advantage",
2099
+ "leaderboard evidence",
2100
+ ],
2101
+ },
2102
+ "read_boundary": {
2103
+ "compact_only": True,
2104
+ "task_text_read": False,
2105
+ "raw_artifacts_read": False,
2106
+ "local_paths_recorded": False,
2107
+ "container_started": False,
2108
+ },
2109
+ }
2110
+
2111
+ def _agents_last_exam_public_task_parts(task_id: str | None) -> tuple[list[str], str | None]:
2112
+ label = _agents_last_exam_public_id(task_id, limit=180)
2113
+ if not isinstance(task_id, str) or not task_id.strip():
2114
+ return [], label
2115
+ text = task_id.strip().replace("\\", "/")
2116
+ parts = [part for part in text.split("/") if part]
2117
+ safe = (
2118
+ not text.startswith("/")
2119
+ and not text.startswith("~")
2120
+ and len(parts) == 2
2121
+ and all(part not in {".", ".."} for part in parts)
2122
+ and all(_agents_last_exam_public_id(part, limit=120) == part for part in parts)
2123
+ )
2124
+ return (parts if safe else []), label
2125
+
2126
+ def _agents_last_exam_public_task_list_membership(
2127
+ source_root: str | None,
2128
+ task_id: str | None,
2129
+ selected_task_lists: Iterable[str],
2130
+ ) -> dict[str, Any]:
2131
+ safe_task_id = str(task_id or "").strip().replace("\\", "/")
2132
+ memberships: dict[str, bool] = {}
2133
+ checked = 0
2134
+ present = 0
2135
+ if not source_root:
2136
+ return {
2137
+ "checked": False,
2138
+ "selected_task_lists": [],
2139
+ "membership": memberships,
2140
+ "present_count": present,
2141
+ "path_recorded": False,
2142
+ }
2143
+ try:
2144
+ root = Path(source_root).expanduser()
2145
+ selected_root = root / "selected_tasks"
2146
+ resolved_root = root.resolve()
2147
+ except (OSError, RuntimeError):
2148
+ return {
2149
+ "checked": False,
2150
+ "selected_task_lists": [],
2151
+ "membership": memberships,
2152
+ "present_count": present,
2153
+ "path_recorded": False,
2154
+ }
2155
+ safe_lists: list[str] = []
2156
+ for raw_name in selected_task_lists:
2157
+ label = _agents_last_exam_public_id(raw_name, limit=120)
2158
+ if not label:
2159
+ continue
2160
+ parts = [part for part in str(raw_name).replace("\\", "/").split("/") if part]
2161
+ if not parts or any(part in {".", ".."} for part in parts):
2162
+ continue
2163
+ candidate = selected_root.joinpath(*parts)
2164
+ try:
2165
+ resolved_candidate = candidate.resolve()
2166
+ inside_root = resolved_candidate == resolved_root or (
2167
+ resolved_root in resolved_candidate.parents
2168
+ )
2169
+ except OSError:
2170
+ inside_root = False
2171
+ safe_lists.append(label)
2172
+ if not inside_root or not candidate.is_file():
2173
+ memberships[label] = False
2174
+ continue
2175
+ checked += 1
2176
+ try:
2177
+ lines = candidate.read_text(encoding="utf-8").splitlines()
2178
+ except OSError:
2179
+ memberships[label] = False
2180
+ continue
2181
+ matched = any(line.strip().replace("\\", "/") == safe_task_id for line in lines)
2182
+ memberships[label] = matched
2183
+ if matched:
2184
+ present += 1
2185
+ return {
2186
+ "checked": checked > 0,
2187
+ "selected_task_lists": safe_lists,
2188
+ "membership": memberships,
2189
+ "present_count": present,
2190
+ "path_recorded": False,
2191
+ }
2192
+
2193
+ def _agents_last_exam_bool_requirement(value: bool | str | None) -> bool | None:
2194
+ if isinstance(value, bool):
2195
+ return value
2196
+ if not isinstance(value, str):
2197
+ return None
2198
+ normalized = value.strip().lower()
2199
+ if normalized in {"1", "true", "yes", "required", "requires_task_data"}:
2200
+ return True
2201
+ if normalized in {"0", "false", "no", "not_required", "none"}:
2202
+ return False
2203
+ return None
2204
+
2205
+ def _agents_last_exam_local_task_data_staging_probe(
2206
+ *,
2207
+ source_root_path: Path | None,
2208
+ local_source_declared: bool,
2209
+ local_source_safe: bool,
2210
+ local_source_present: bool,
2211
+ ) -> dict[str, Any]:
2212
+ checked = bool(local_source_declared)
2213
+ fetch_script_present = False
2214
+ if source_root_path is not None and source_root_path.is_dir():
2215
+ fetch_script_present = (
2216
+ source_root_path / "scripts" / "fetch_task_data.sh"
2217
+ ).is_file()
2218
+ fetch_tool_present = shutil.which("huggingface-cli") is not None
2219
+ disk_headroom = _agents_last_exam_disk_headroom_for_path(source_root_path)
2220
+ documented_image_compressed_gib = 42
2221
+ free_gib = disk_headroom.get("free_gib")
2222
+ disk_headroom_below_documented_image = (
2223
+ isinstance(free_gib, (int, float))
2224
+ and free_gib < documented_image_compressed_gib
2225
+ )
2226
+ blockers: list[str] = []
2227
+ if checked and local_source_safe and local_source_present is not True:
2228
+ if not fetch_script_present:
2229
+ blockers.append("local_task_data_fetch_script_missing")
2230
+ if not fetch_tool_present:
2231
+ blockers.append("local_task_data_fetch_tool_missing")
2232
+ blockers.append("local_task_data_gated_huggingface_access_not_verified")
2233
+ if disk_headroom_below_documented_image:
2234
+ blockers.append(
2235
+ "local_task_data_disk_headroom_below_documented_image_pull"
2236
+ )
2237
+ return {
2238
+ "checked": checked,
2239
+ "ready": checked and not blockers if checked else None,
2240
+ "first_blocker": blockers[0] if blockers else None,
2241
+ "blockers": blockers,
2242
+ "route": "gated_huggingface_archive" if checked else None,
2243
+ "dataset_label": "agents-last-exam-data-archive" if checked else None,
2244
+ "archive_label": "ale-tasks-data.tar.gz" if checked else None,
2245
+ "fetch_script_present": fetch_script_present,
2246
+ "fetch_tool": "huggingface-cli" if checked else None,
2247
+ "fetch_tool_present": fetch_tool_present,
2248
+ "auth_status_checked": False,
2249
+ "requires_approved_huggingface_access": checked,
2250
+ "disk_headroom": disk_headroom,
2251
+ "documented_docker_image_compressed_gib": documented_image_compressed_gib,
2252
+ "disk_headroom_below_documented_image_pull": (
2253
+ disk_headroom_below_documented_image
2254
+ ),
2255
+ "local_paths_recorded": False,
2256
+ "credential_values_read": False,
2257
+ "credential_values_recorded": False,
2258
+ "task_data_content_read": False,
2259
+ "archive_content_read": False,
2260
+ }
2261
+
2262
+ def build_agents_last_exam_baked_task_input_readiness(
2263
+ *,
2264
+ selected_task_id: str | None,
2265
+ image_ref: str = AGENTS_LAST_EXAM_DEFAULT_DOCKER_IMAGE,
2266
+ image_metadata: dict[str, Any] | None = None,
2267
+ docker_binary: str = "docker",
2268
+ timeout_seconds: int = 60,
2269
+ ) -> dict[str, Any]:
2270
+ """Probe whether an ALE Docker image contains a task baked input dir.
2271
+
2272
+ This starts a tiny shell in the image to test directory existence/readability.
2273
+ It does not run the task, list files, read task data, or record the checked path.
2274
+ """
2275
+
2276
+ parts, task_label = _agents_last_exam_public_task_parts(selected_task_id)
2277
+ blockers: list[str] = []
2278
+ if not parts:
2279
+ blockers.append("selected_task_id_not_public_safe")
2280
+ docker_label = _agents_last_exam_public_id(docker_binary, limit=80)
2281
+ docker_binary_safe = bool(
2282
+ docker_label
2283
+ and docker_binary == docker_label
2284
+ and "/" not in docker_binary
2285
+ and "\\" not in docker_binary
2286
+ )
2287
+ if not docker_binary_safe:
2288
+ blockers.append("docker_binary_must_be_name_not_path")
2289
+ docker_available = bool(docker_binary_safe and shutil.which(docker_binary))
2290
+ if docker_binary_safe and not docker_available:
2291
+ blockers.append("docker_cli_missing")
2292
+
2293
+ raw_image_metadata = (
2294
+ image_metadata
2295
+ if isinstance(image_metadata, dict)
2296
+ else _agents_last_exam_docker_image_metadata(image_ref)
2297
+ )
2298
+ image = _agents_last_exam_public_image_metadata(
2299
+ raw_image_metadata,
2300
+ fallback_image_ref=image_ref,
2301
+ )
2302
+ if image.get("present") is not True:
2303
+ blockers.append(
2304
+ _agents_last_exam_public_id(image.get("first_blocker"), limit=80)
2305
+ or "docker_image_missing"
2306
+ )
2307
+
2308
+ attempted = False
2309
+ container_started = False
2310
+ baked_input_present = False
2311
+ baked_input_readable = False
2312
+ probe_return_code: int | None = None
2313
+ probe_error: str | None = None
2314
+ if not blockers and parts and docker_binary_safe:
2315
+ baked_input_path = (
2316
+ f"/media/user/data/agenthle/{parts[0]}/{parts[1]}/base/input"
2317
+ )
2318
+ attempted = True
2319
+ try:
2320
+ result = subprocess.run(
2321
+ [
2322
+ docker_binary,
2323
+ "run",
2324
+ "--rm",
2325
+ "--entrypoint",
2326
+ "/bin/sh",
2327
+ image_ref,
2328
+ "-c",
2329
+ 'test -d "$1" && test -r "$1"',
2330
+ "sh",
2331
+ baked_input_path,
2332
+ ],
2333
+ check=False,
2334
+ text=True,
2335
+ capture_output=True,
2336
+ timeout=max(1, int(timeout_seconds)),
2337
+ )
2338
+ except subprocess.TimeoutExpired:
2339
+ probe_error = "baked_task_input_probe_timeout"
2340
+ except Exception:
2341
+ probe_error = "baked_task_input_probe_failed"
2342
+ else:
2343
+ container_started = True
2344
+ probe_return_code = result.returncode
2345
+ if result.returncode == 0:
2346
+ baked_input_present = True
2347
+ baked_input_readable = True
2348
+ else:
2349
+ probe_error = "baked_task_input_missing"
2350
+ if probe_error:
2351
+ blockers.append(probe_error)
2352
+
2353
+ ready = not blockers and baked_input_present and baked_input_readable
2354
+ return {
2355
+ "schema_version": AGENTS_LAST_EXAM_BAKED_TASK_INPUT_READINESS_SCHEMA_VERSION,
2356
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
2357
+ "ready": ready,
2358
+ "first_blocker": blockers[0]
2359
+ if blockers
2360
+ else "ready_for_baked_sandbox_task_data_source",
2361
+ "blockers": blockers,
2362
+ "task": {
2363
+ "task_id": task_label,
2364
+ "category": parts[0] if parts else None,
2365
+ "name": parts[1] if parts else None,
2366
+ },
2367
+ "image": image,
2368
+ "probe": {
2369
+ "kind": "docker_shell_test_directory_only",
2370
+ "attempted": attempted,
2371
+ "container_started": container_started,
2372
+ "baked_input_present": baked_input_present,
2373
+ "baked_input_readable": baked_input_readable,
2374
+ "return_code_zero": probe_return_code == 0
2375
+ if probe_return_code is not None
2376
+ else None,
2377
+ "expected_path_template": "ale_task_base_input",
2378
+ "expected_path_recorded": False,
2379
+ "stdout_recorded": False,
2380
+ "stderr_recorded": False,
2381
+ "command_argv_recorded": False,
2382
+ },
2383
+ "boundary": {
2384
+ "local_only": True,
2385
+ "no_upload": True,
2386
+ "submit_eligible": False,
2387
+ "leaderboard_evidence": False,
2388
+ "container_started": container_started,
2389
+ "task_run_started": False,
2390
+ "task_body_read": False,
2391
+ "task_card_content_read": False,
2392
+ "script_content_read": False,
2393
+ "task_data_content_read": False,
2394
+ "directory_listed": False,
2395
+ "model_api_invoked": False,
2396
+ "codex_prompt_sent": False,
2397
+ "raw_trajectory_read": False,
2398
+ "screenshot_captured": False,
2399
+ "credential_values_recorded": False,
2400
+ "hidden_references_allowed": False,
2401
+ "production_actions_allowed": False,
2402
+ "local_paths_recorded": False,
2403
+ "command_argv_recorded": False,
2404
+ },
2405
+ "read_boundary": {
2406
+ "compact_only": True,
2407
+ "path_existence_only": True,
2408
+ "task_text_read": False,
2409
+ "task_card_content_read": False,
2410
+ "script_content_read": False,
2411
+ "task_data_content_read": False,
2412
+ "raw_artifacts_read": False,
2413
+ "local_paths_recorded": False,
2414
+ },
2415
+ }
2416
+
2417
+ def build_agents_last_exam_baked_task_input_scan(
2418
+ *,
2419
+ source_root: str | None,
2420
+ selected_task_lists: Iterable[str] = (
2421
+ "linux_only.txt",
2422
+ "unlicensed/near-term.txt",
2423
+ ),
2424
+ image_ref: str = AGENTS_LAST_EXAM_DEFAULT_DOCKER_IMAGE,
2425
+ image_metadata: dict[str, Any] | None = None,
2426
+ docker_binary: str = "docker",
2427
+ max_tasks: int = 120,
2428
+ timeout_seconds: int = 180,
2429
+ probe_results: dict[str, bool] | None = None,
2430
+ ) -> dict[str, Any]:
2431
+ """Scan selected public ALE tasks for baked input dirs without reading them."""
2432
+
2433
+ selected = _agents_last_exam_public_selected_task_scan(
2434
+ source_root,
2435
+ selected_task_lists,
2436
+ )
2437
+ task_ids = [
2438
+ task_id
2439
+ for task_id in selected.get("task_ids", [])
2440
+ if _agents_last_exam_public_task_parts(task_id)[0]
2441
+ ]
2442
+ max_count = max(0, int(max_tasks))
2443
+ if max_count:
2444
+ task_ids = task_ids[:max_count]
2445
+ else:
2446
+ task_ids = []
2447
+ blockers: list[str] = []
2448
+ if selected.get("checked") is not True:
2449
+ blockers.append("selected_task_lists_not_checked")
2450
+ if not task_ids:
2451
+ blockers.append("no_selected_tasks_to_probe")
2452
+
2453
+ docker_label = _agents_last_exam_public_id(docker_binary, limit=80)
2454
+ docker_binary_safe = bool(
2455
+ docker_label
2456
+ and docker_binary == docker_label
2457
+ and "/" not in docker_binary
2458
+ and "\\" not in docker_binary
2459
+ )
2460
+ if not docker_binary_safe:
2461
+ blockers.append("docker_binary_must_be_name_not_path")
2462
+ docker_available = bool(docker_binary_safe and shutil.which(docker_binary))
2463
+ raw_image_metadata = (
2464
+ image_metadata
2465
+ if isinstance(image_metadata, dict)
2466
+ else _agents_last_exam_docker_image_metadata(image_ref)
2467
+ )
2468
+ image = _agents_last_exam_public_image_metadata(
2469
+ raw_image_metadata,
2470
+ fallback_image_ref=image_ref,
2471
+ )
2472
+
2473
+ fixture_probe_used = isinstance(probe_results, dict)
2474
+ if not fixture_probe_used:
2475
+ if docker_binary_safe and not docker_available:
2476
+ blockers.append("docker_cli_missing")
2477
+ if image.get("present") is not True:
2478
+ blockers.append(
2479
+ _agents_last_exam_public_id(image.get("first_blocker"), limit=80)
2480
+ or "docker_image_missing"
2481
+ )
2482
+
2483
+ attempted = False
2484
+ container_started = False
2485
+ candidates: list[str] = []
2486
+ probe_error: str | None = None
2487
+ if not blockers and task_ids:
2488
+ attempted = True
2489
+ if fixture_probe_used:
2490
+ for task_id in task_ids:
2491
+ if probe_results.get(task_id) is True:
2492
+ candidates.append(task_id)
2493
+ else:
2494
+ script = (
2495
+ 'while IFS= read -r task; do '
2496
+ 'category="${task%%/*}"; name="${task#*/}"; '
2497
+ 'path="/media/user/data/agenthle/${category}/${name}/base/input"; '
2498
+ 'if test -d "$path" && test -r "$path"; then '
2499
+ 'printf "%s\\t1\\n" "$task"; else printf "%s\\t0\\n" "$task"; fi; '
2500
+ "done"
2501
+ )
2502
+ try:
2503
+ result = subprocess.run(
2504
+ [
2505
+ docker_binary,
2506
+ "run",
2507
+ "--rm",
2508
+ "--entrypoint",
2509
+ "/bin/sh",
2510
+ image_ref,
2511
+ "-c",
2512
+ script,
2513
+ ],
2514
+ input="\n".join(task_ids) + "\n",
2515
+ check=False,
2516
+ text=True,
2517
+ capture_output=True,
2518
+ timeout=max(1, int(timeout_seconds)),
2519
+ )
2520
+ except subprocess.TimeoutExpired:
2521
+ probe_error = "baked_task_input_scan_timeout"
2522
+ except Exception:
2523
+ probe_error = "baked_task_input_scan_failed"
2524
+ else:
2525
+ container_started = True
2526
+ if result.returncode != 0:
2527
+ probe_error = "baked_task_input_scan_nonzero"
2528
+ else:
2529
+ safe_task_set = set(task_ids)
2530
+ for line in result.stdout.splitlines():
2531
+ raw_task_id, _, flag = line.partition("\t")
2532
+ if flag != "1" or raw_task_id not in safe_task_set:
2533
+ continue
2534
+ parts, safe_label = _agents_last_exam_public_task_parts(
2535
+ raw_task_id
2536
+ )
2537
+ if parts and safe_label:
2538
+ candidates.append(raw_task_id)
2539
+ if probe_error:
2540
+ blockers.append(probe_error)
2541
+ if attempted and not candidates and not blockers:
2542
+ blockers.append("no_baked_input_candidate_found")
2543
+
2544
+ ready = bool(candidates) and not blockers
2545
+ return {
2546
+ "schema_version": AGENTS_LAST_EXAM_BAKED_TASK_INPUT_SCAN_SCHEMA_VERSION,
2547
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
2548
+ "ready": ready,
2549
+ "first_blocker": blockers[0]
2550
+ if blockers
2551
+ else "ready_for_baked_input_formal_candidate_selection",
2552
+ "blockers": blockers,
2553
+ "selected_tasks": {
2554
+ "checked": selected.get("checked") is True,
2555
+ "selected_task_lists": selected.get("selected_task_lists") or [],
2556
+ "selected_task_count": selected.get("selected_task_count"),
2557
+ "probed_task_count": len(task_ids),
2558
+ "max_tasks": max_count,
2559
+ "path_recorded": False,
2560
+ },
2561
+ "image": image,
2562
+ "probe": {
2563
+ "kind": "docker_shell_batch_test_directory_only",
2564
+ "attempted": attempted,
2565
+ "container_started": container_started,
2566
+ "fixture_probe_used": fixture_probe_used,
2567
+ "baked_input_candidate_count": len(candidates),
2568
+ "expected_path_template": "ale_task_base_input",
2569
+ "expected_path_recorded": False,
2570
+ "stdout_recorded": False,
2571
+ "stderr_recorded": False,
2572
+ "command_argv_recorded": False,
2573
+ },
2574
+ "candidates": {
2575
+ "eligible_baked_input_candidates": candidates[:25],
2576
+ "candidate_count": len(candidates),
2577
+ "task_ids_public": True,
2578
+ "task_paths_recorded": False,
2579
+ },
2580
+ "boundary": {
2581
+ "local_only": True,
2582
+ "no_upload": True,
2583
+ "submit_eligible": False,
2584
+ "leaderboard_evidence": False,
2585
+ "container_started": container_started,
2586
+ "task_run_started": False,
2587
+ "task_body_read": False,
2588
+ "task_card_content_read": False,
2589
+ "script_content_read": False,
2590
+ "task_data_content_read": False,
2591
+ "directory_listed": False,
2592
+ "model_api_invoked": False,
2593
+ "codex_prompt_sent": False,
2594
+ "raw_trajectory_read": False,
2595
+ "screenshot_captured": False,
2596
+ "credential_values_recorded": False,
2597
+ "hidden_references_allowed": False,
2598
+ "production_actions_allowed": False,
2599
+ "local_paths_recorded": False,
2600
+ "command_argv_recorded": False,
2601
+ "raw_output_recorded": False,
2602
+ },
2603
+ "read_boundary": {
2604
+ "compact_only": True,
2605
+ "path_existence_only": True,
2606
+ "selected_task_lists_read": True,
2607
+ "task_text_read": False,
2608
+ "task_card_content_read": False,
2609
+ "script_content_read": False,
2610
+ "task_data_content_read": False,
2611
+ "raw_artifacts_read": False,
2612
+ "local_paths_recorded": False,
2613
+ },
2614
+ }
2615
+
2616
+ def _agents_last_exam_task_data_source_readiness(
2617
+ *,
2618
+ source_root: str | None,
2619
+ requires_task_data: bool | str | None,
2620
+ task_data_source: str | None,
2621
+ baked_task_input_present: bool | None,
2622
+ baked_task_input_readiness: dict[str, Any] | None,
2623
+ gcs_sa_key: str | None,
2624
+ gcs_sa_key_present: bool | None,
2625
+ enforce_task_data_source: bool,
2626
+ ) -> dict[str, Any]:
2627
+ requirement = _agents_last_exam_bool_requirement(requires_task_data)
2628
+ raw_source = task_data_source.strip() if isinstance(task_data_source, str) else ""
2629
+ source = _agents_last_exam_public_id(raw_source, limit=120)
2630
+ official_gcs_source = raw_source.startswith("gs://ale-data-public")
2631
+ local_source_declared = raw_source.startswith("local:")
2632
+ local_source_safe = False
2633
+ local_source_present = False
2634
+ source_root_path = None
2635
+ if local_source_declared:
2636
+ local_relative = raw_source[len("local:") :].strip().replace("\\", "/")
2637
+ parts = [part for part in local_relative.split("/") if part]
2638
+ local_source_safe = bool(
2639
+ local_relative
2640
+ and not local_relative.startswith("/")
2641
+ and not local_relative.startswith("~")
2642
+ and all(part not in {".", ".."} for part in parts)
2643
+ )
2644
+ try:
2645
+ source_root_path = Path(source_root).expanduser() if source_root else None
2646
+ except (OSError, RuntimeError):
2647
+ source_root_path = None
2648
+ if (
2649
+ local_source_safe
2650
+ and source_root_path is not None
2651
+ and source_root_path.is_dir()
2652
+ ):
2653
+ candidate = source_root_path.joinpath(*parts)
2654
+ try:
2655
+ resolved_root = source_root_path.resolve()
2656
+ resolved_candidate = candidate.resolve()
2657
+ inside_root = resolved_candidate == resolved_root or (
2658
+ resolved_root in resolved_candidate.parents
2659
+ )
2660
+ except OSError:
2661
+ inside_root = False
2662
+ local_source_present = bool(inside_root and candidate.is_dir())
2663
+ local_staging = _agents_last_exam_local_task_data_staging_probe(
2664
+ source_root_path=source_root_path,
2665
+ local_source_declared=local_source_declared,
2666
+ local_source_safe=local_source_safe,
2667
+ local_source_present=local_source_present,
2668
+ )
2669
+ gcs_key_declared = bool(gcs_sa_key)
2670
+ gcs_key_file_present = False
2671
+ if gcs_sa_key:
2672
+ try:
2673
+ gcs_key_file_present = Path(gcs_sa_key).expanduser().is_file()
2674
+ except (OSError, RuntimeError):
2675
+ gcs_key_file_present = False
2676
+ effective_gcs_key_present = (
2677
+ bool(gcs_sa_key_present)
2678
+ if gcs_sa_key_present is not None
2679
+ else gcs_key_file_present
2680
+ )
2681
+ baked_probe_declared = isinstance(baked_task_input_readiness, dict)
2682
+ baked_probe_ready = (
2683
+ baked_task_input_readiness.get("schema_version")
2684
+ == AGENTS_LAST_EXAM_BAKED_TASK_INPUT_READINESS_SCHEMA_VERSION
2685
+ and baked_task_input_readiness.get("ready") is True
2686
+ if baked_probe_declared
2687
+ else False
2688
+ )
2689
+ effective_baked_input_present = (
2690
+ bool(baked_task_input_present)
2691
+ if baked_task_input_present is not None
2692
+ else baked_probe_ready
2693
+ )
2694
+ checked = enforce_task_data_source or requirement is not None or bool(source)
2695
+ blockers: list[str] = []
2696
+ if checked and requirement is None:
2697
+ blockers.append("task_data_requirement_unknown")
2698
+ if requirement is True:
2699
+ if not source:
2700
+ blockers.append("task_data_source_missing_for_required_task")
2701
+ elif raw_source == "baked_in_sandbox":
2702
+ if baked_probe_declared and baked_probe_ready is not True:
2703
+ blockers.append(
2704
+ _agents_last_exam_public_id(
2705
+ baked_task_input_readiness.get("first_blocker"),
2706
+ limit=80,
2707
+ )
2708
+ or "baked_task_input_not_verified"
2709
+ )
2710
+ elif effective_baked_input_present is not True:
2711
+ blockers.append("baked_task_input_not_verified")
2712
+ elif official_gcs_source:
2713
+ if effective_gcs_key_present is not True:
2714
+ blockers.append("gcs_sa_key_presence_not_verified")
2715
+ elif local_source_declared:
2716
+ if not local_source_safe:
2717
+ blockers.append("local_task_data_source_not_public_safe")
2718
+ elif local_source_present is not True:
2719
+ blockers.append("local_task_data_directory_not_verified")
2720
+ blockers.extend(
2721
+ blocker
2722
+ for blocker in local_staging.get("blockers", [])
2723
+ if isinstance(blocker, str)
2724
+ )
2725
+ elif raw_source in {"none", "local"}:
2726
+ blockers.append("task_data_source_not_sufficient_for_required_task")
2727
+ else:
2728
+ blockers.append("task_data_source_unsupported_for_required_task")
2729
+ ready = checked and not blockers
2730
+ if requirement is False:
2731
+ ready = True
2732
+ return {
2733
+ "checked": checked,
2734
+ "ready": ready,
2735
+ "first_blocker": blockers[0] if blockers else None,
2736
+ "blockers": blockers,
2737
+ "requires_task_data": requirement,
2738
+ "requires_task_data_declared": requirement is not None,
2739
+ "task_data_source": source,
2740
+ "task_data_source_declared": bool(source),
2741
+ "official_gcs_source": official_gcs_source,
2742
+ "local_task_data_source": local_source_declared,
2743
+ "local_task_data_source_safe": local_source_safe,
2744
+ "local_task_data_present": local_source_present,
2745
+ "local_task_data_staging": local_staging,
2746
+ "local_task_data_path_recorded": False,
2747
+ "local_task_data_content_read": False,
2748
+ "baked_input_present": effective_baked_input_present is True,
2749
+ "baked_input_presence_declared": baked_task_input_present is not None
2750
+ or baked_probe_declared,
2751
+ "baked_input_probe_declared": baked_probe_declared,
2752
+ "baked_input_probe_ready": baked_probe_ready,
2753
+ "gcs_sa_key_declared": gcs_key_declared or gcs_sa_key_present is not None,
2754
+ "gcs_sa_key_present": effective_gcs_key_present,
2755
+ "gcs_sa_key_path_recorded": False,
2756
+ "credential_values_read": False,
2757
+ "credential_values_recorded": False,
2758
+ "local_paths_recorded": False,
2759
+ }
2760
+
2761
+ def build_agents_last_exam_task_material_readiness(
2762
+ *,
2763
+ source_root: str | None,
2764
+ selected_task_id: str | None,
2765
+ selected_task_lists: Iterable[str] = (
2766
+ "linux_only.txt",
2767
+ "unlicensed/near-term.txt",
2768
+ ),
2769
+ requires_task_data: bool | str | None = None,
2770
+ task_data_source: str | None = None,
2771
+ baked_task_input_present: bool | None = None,
2772
+ baked_task_input_readiness: dict[str, Any] | None = None,
2773
+ gcs_sa_key: str | None = None,
2774
+ gcs_sa_key_present: bool | None = None,
2775
+ enforce_task_data_source: bool = False,
2776
+ ) -> dict[str, Any]:
2777
+ """Check local ALE task material existence without reading task bodies."""
2778
+
2779
+ parts, task_label = _agents_last_exam_public_task_parts(selected_task_id)
2780
+ blockers: list[str] = []
2781
+ if not parts:
2782
+ blockers.append("selected_task_id_not_public_safe")
2783
+ try:
2784
+ root = Path(source_root).expanduser() if source_root else None
2785
+ except (OSError, RuntimeError):
2786
+ root = None
2787
+ source_root_available = bool(root and root.is_dir())
2788
+ if not source_root_available or root is None:
2789
+ blockers.append("source_root_not_available")
2790
+
2791
+ task_dir_available = False
2792
+ task_card_present = False
2793
+ scripts_dir_present = False
2794
+ scorer_script_count = 0
2795
+ task_dir_entry_count = 0
2796
+ if root is not None and source_root_available and parts:
2797
+ task_dir = root / "tasks" / parts[0] / parts[1]
2798
+ try:
2799
+ resolved_root = root.resolve()
2800
+ resolved_task_dir = task_dir.resolve()
2801
+ inside_root = resolved_task_dir == resolved_root or (
2802
+ resolved_root in resolved_task_dir.parents
2803
+ )
2804
+ except OSError:
2805
+ inside_root = False
2806
+ task_dir_available = bool(inside_root and task_dir.is_dir())
2807
+ if task_dir_available:
2808
+ task_card_present = (task_dir / "task_card.json").is_file()
2809
+ scripts_dir = task_dir / "scripts"
2810
+ scripts_dir_present = scripts_dir.is_dir()
2811
+ try:
2812
+ task_dir_entry_count = sum(1 for _ in task_dir.iterdir())
2813
+ except OSError:
2814
+ task_dir_entry_count = 0
2815
+ if scripts_dir_present:
2816
+ try:
2817
+ scorer_script_count = sum(
2818
+ 1
2819
+ for path in scripts_dir.iterdir()
2820
+ if path.is_file()
2821
+ and path.suffix == ".py"
2822
+ and "score" in path.name.lower()
2823
+ )
2824
+ except OSError:
2825
+ scorer_script_count = 0
2826
+ if not task_dir_available:
2827
+ blockers.append("task_directory_missing")
2828
+ if not task_card_present:
2829
+ blockers.append("task_card_json_missing")
2830
+ if not scripts_dir_present:
2831
+ blockers.append("task_scripts_directory_missing")
2832
+ if scorer_script_count < 1:
2833
+ blockers.append("task_scorer_script_missing")
2834
+
2835
+ membership = _agents_last_exam_public_task_list_membership(
2836
+ source_root,
2837
+ selected_task_id,
2838
+ selected_task_lists,
2839
+ )
2840
+ if membership.get("checked") is not True:
2841
+ blockers.append("selected_task_list_membership_not_checked")
2842
+ elif int(membership.get("present_count") or 0) < 1:
2843
+ blockers.append("selected_task_not_in_public_task_lists")
2844
+ task_data = _agents_last_exam_task_data_source_readiness(
2845
+ source_root=source_root,
2846
+ requires_task_data=requires_task_data,
2847
+ task_data_source=task_data_source,
2848
+ baked_task_input_present=baked_task_input_present,
2849
+ baked_task_input_readiness=baked_task_input_readiness,
2850
+ gcs_sa_key=gcs_sa_key,
2851
+ gcs_sa_key_present=gcs_sa_key_present,
2852
+ enforce_task_data_source=enforce_task_data_source,
2853
+ )
2854
+ if enforce_task_data_source and task_data.get("ready") is not True:
2855
+ blockers.append(
2856
+ _agents_last_exam_public_id(task_data.get("first_blocker"), limit=80)
2857
+ or "task_data_source_not_ready"
2858
+ )
2859
+
2860
+ ready = not blockers
2861
+ return {
2862
+ "schema_version": AGENTS_LAST_EXAM_TASK_MATERIAL_READINESS_SCHEMA_VERSION,
2863
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
2864
+ "ready": ready,
2865
+ "first_blocker": blockers[0]
2866
+ if blockers
2867
+ else "ready_for_local_no_upload_ale_task_gate",
2868
+ "blockers": blockers,
2869
+ "task": {
2870
+ "task_id": task_label,
2871
+ "category": parts[0] if parts else None,
2872
+ "name": parts[1] if parts else None,
2873
+ "task_dir_available": task_dir_available,
2874
+ "task_card_json_present": task_card_present,
2875
+ "scripts_dir_present": scripts_dir_present,
2876
+ "scorer_script_count": scorer_script_count,
2877
+ "task_dir_entry_count": task_dir_entry_count,
2878
+ "task_dir_path_recorded": False,
2879
+ "task_card_content_read": False,
2880
+ "script_content_read": False,
2881
+ },
2882
+ "task_data": task_data,
2883
+ "public_task_lists": membership,
2884
+ "boundary": {
2885
+ "local_only": True,
2886
+ "no_upload": True,
2887
+ "submit_eligible": False,
2888
+ "leaderboard_evidence": False,
2889
+ "container_started": False,
2890
+ "task_body_read": False,
2891
+ "task_card_content_read": False,
2892
+ "script_content_read": False,
2893
+ "model_api_invoked": False,
2894
+ "raw_trajectory_read": False,
2895
+ "screenshot_captured": False,
2896
+ "credential_values_recorded": False,
2897
+ "hidden_references_allowed": False,
2898
+ "production_actions_allowed": False,
2899
+ "local_paths_recorded": False,
2900
+ "command_argv_recorded": False,
2901
+ "raw_output_recorded": False,
2902
+ },
2903
+ "decision": {
2904
+ "next_allowed_action": "prepare_local_no_upload_ale_validation_run_gate"
2905
+ if ready
2906
+ else "repair_ale_task_material_readiness_blocker",
2907
+ "minimum_next_evidence": (
2908
+ "A local/no-upload ALE task gate should combine this material "
2909
+ "readiness signal with host Codex no-task E2E readiness and the "
2910
+ "compact result reducer boundary before any task-level run."
2911
+ ),
2912
+ "must_not_claim": [
2913
+ "ALE task success",
2914
+ "ALE score uplift",
2915
+ "LoopX treatment advantage",
2916
+ "leaderboard evidence",
2917
+ ],
2918
+ },
2919
+ "read_boundary": {
2920
+ "compact_only": True,
2921
+ "task_text_read": False,
2922
+ "task_card_content_read": False,
2923
+ "script_content_read": False,
2924
+ "raw_artifacts_read": False,
2925
+ "local_paths_recorded": False,
2926
+ "container_started": False,
2927
+ },
2928
+ }
2929
+
2930
+ def _agents_last_exam_public_selected_task_scan(
2931
+ source_root: str | None,
2932
+ selected_task_lists: Iterable[str],
2933
+ ) -> dict[str, Any]:
2934
+ labels: list[str] = []
2935
+ task_ids: set[str] = set()
2936
+ missing_lists = 0
2937
+ checked_lists = 0
2938
+ unsafe_lists = 0
2939
+ if not source_root:
2940
+ return {
2941
+ "checked": False,
2942
+ "selected_task_lists": labels,
2943
+ "selected_task_count": 0,
2944
+ "checked_list_count": 0,
2945
+ "missing_list_count": 0,
2946
+ "unsafe_list_count": 0,
2947
+ "path_recorded": False,
2948
+ "task_ids": [],
2949
+ }
2950
+ try:
2951
+ root = Path(source_root).expanduser()
2952
+ selected_root = root / "selected_tasks"
2953
+ resolved_root = root.resolve()
2954
+ except (OSError, RuntimeError):
2955
+ return {
2956
+ "checked": False,
2957
+ "selected_task_lists": labels,
2958
+ "selected_task_count": 0,
2959
+ "checked_list_count": 0,
2960
+ "missing_list_count": 0,
2961
+ "unsafe_list_count": 0,
2962
+ "path_recorded": False,
2963
+ "task_ids": [],
2964
+ }
2965
+ for raw_name in selected_task_lists:
2966
+ label = _agents_last_exam_public_id(raw_name, limit=120)
2967
+ if not label:
2968
+ unsafe_lists += 1
2969
+ continue
2970
+ parts = [part for part in str(raw_name).replace("\\", "/").split("/") if part]
2971
+ if not parts or any(part in {".", ".."} for part in parts):
2972
+ labels.append(label)
2973
+ unsafe_lists += 1
2974
+ continue
2975
+ candidate = selected_root.joinpath(*parts)
2976
+ try:
2977
+ resolved_candidate = candidate.resolve()
2978
+ inside_root = resolved_candidate == resolved_root or (
2979
+ resolved_root in resolved_candidate.parents
2980
+ )
2981
+ except OSError:
2982
+ inside_root = False
2983
+ labels.append(label)
2984
+ if not inside_root or not candidate.is_file():
2985
+ missing_lists += 1
2986
+ continue
2987
+ checked_lists += 1
2988
+ try:
2989
+ lines = candidate.read_text(encoding="utf-8").splitlines()
2990
+ except OSError:
2991
+ missing_lists += 1
2992
+ continue
2993
+ for line in lines:
2994
+ raw_task_id = line.strip().replace("\\", "/")
2995
+ if not raw_task_id or raw_task_id.startswith("#"):
2996
+ continue
2997
+ parts, safe_label = _agents_last_exam_public_task_parts(raw_task_id)
2998
+ if parts and safe_label:
2999
+ task_ids.add("/".join(parts))
3000
+ return {
3001
+ "checked": checked_lists > 0,
3002
+ "selected_task_lists": labels,
3003
+ "selected_task_count": len(task_ids),
3004
+ "checked_list_count": checked_lists,
3005
+ "missing_list_count": missing_lists,
3006
+ "unsafe_list_count": unsafe_lists,
3007
+ "path_recorded": False,
3008
+ "task_ids": sorted(task_ids),
3009
+ }
3010
+
3011
+ def _agents_last_exam_requires_task_data_line_scan(
3012
+ *,
3013
+ source_root: str | None,
3014
+ task_id: str,
3015
+ max_lines: int = 1200,
3016
+ ) -> dict[str, Any]:
3017
+ parts, task_label = _agents_last_exam_public_task_parts(task_id)
3018
+ if not parts:
3019
+ return {
3020
+ "task_id": task_label,
3021
+ "checked": False,
3022
+ "requires_task_data": None,
3023
+ "requires_task_data_declared": False,
3024
+ "assignment_found": False,
3025
+ "assignment_kind": None,
3026
+ "line_count_scanned": 0,
3027
+ "first_blocker": "selected_task_id_not_public_safe",
3028
+ "task_source_path_recorded": False,
3029
+ "task_source_content_recorded": False,
3030
+ }
3031
+ try:
3032
+ root = Path(source_root).expanduser() if source_root else None
3033
+ except (OSError, RuntimeError):
3034
+ root = None
3035
+ if root is None or not root.is_dir():
3036
+ return {
3037
+ "task_id": task_label,
3038
+ "checked": False,
3039
+ "requires_task_data": None,
3040
+ "requires_task_data_declared": False,
3041
+ "assignment_found": False,
3042
+ "assignment_kind": None,
3043
+ "line_count_scanned": 0,
3044
+ "first_blocker": "source_root_not_available",
3045
+ "task_source_path_recorded": False,
3046
+ "task_source_content_recorded": False,
3047
+ }
3048
+ source_file = root / "tasks" / parts[0] / parts[1] / "main.py"
3049
+ try:
3050
+ resolved_root = root.resolve()
3051
+ resolved_source_file = source_file.resolve()
3052
+ inside_root = resolved_source_file == resolved_root or (
3053
+ resolved_root in resolved_source_file.parents
3054
+ )
3055
+ except OSError:
3056
+ inside_root = False
3057
+ if not inside_root or not source_file.is_file():
3058
+ return {
3059
+ "task_id": task_label,
3060
+ "checked": False,
3061
+ "requires_task_data": None,
3062
+ "requires_task_data_declared": False,
3063
+ "assignment_found": False,
3064
+ "assignment_kind": None,
3065
+ "line_count_scanned": 0,
3066
+ "first_blocker": "task_config_main_py_missing",
3067
+ "task_source_path_recorded": False,
3068
+ "task_source_content_recorded": False,
3069
+ }
3070
+ scanned = 0
3071
+ try:
3072
+ with source_file.open(encoding="utf-8") as handle:
3073
+ for raw_line in handle:
3074
+ scanned += 1
3075
+ match = _AGENTS_LAST_EXAM_REQUIRES_TASK_DATA_RE.match(raw_line)
3076
+ if match:
3077
+ requires_task_data = match.group(1) == "True"
3078
+ return {
3079
+ "task_id": task_label,
3080
+ "checked": True,
3081
+ "requires_task_data": requires_task_data,
3082
+ "requires_task_data_declared": True,
3083
+ "assignment_found": True,
3084
+ "assignment_kind": "requires_task_data_bool_assignment",
3085
+ "line_count_scanned": scanned,
3086
+ "first_blocker": None,
3087
+ "task_source_path_recorded": False,
3088
+ "task_source_content_recorded": False,
3089
+ }
3090
+ if scanned >= max_lines:
3091
+ break
3092
+ except OSError:
3093
+ return {
3094
+ "task_id": task_label,
3095
+ "checked": False,
3096
+ "requires_task_data": None,
3097
+ "requires_task_data_declared": False,
3098
+ "assignment_found": False,
3099
+ "assignment_kind": None,
3100
+ "line_count_scanned": scanned,
3101
+ "first_blocker": "task_config_main_py_unreadable",
3102
+ "task_source_path_recorded": False,
3103
+ "task_source_content_recorded": False,
3104
+ }
3105
+ return {
3106
+ "task_id": task_label,
3107
+ "checked": True,
3108
+ "requires_task_data": True,
3109
+ "requires_task_data_declared": False,
3110
+ "assignment_found": False,
3111
+ "assignment_kind": "default_true_when_assignment_missing",
3112
+ "line_count_scanned": scanned,
3113
+ "first_blocker": None,
3114
+ "task_source_path_recorded": False,
3115
+ "task_source_content_recorded": False,
3116
+ }
3117
+
3118
+ def build_agents_last_exam_candidate_task_data_scan(
3119
+ *,
3120
+ source_root: str | None,
3121
+ selected_task_lists: Iterable[str] = (
3122
+ "linux_only.txt",
3123
+ "unlicensed/near-term.txt",
3124
+ ),
3125
+ allow_demo_candidate: bool = False,
3126
+ ) -> dict[str, Any]:
3127
+ """Scan selected ALE task configs for local no-task-data candidates.
3128
+
3129
+ This is a bounded config-line scan: it extracts only a
3130
+ ``REQUIRES_TASK_DATA`` boolean assignment signal from task ``main.py`` and
3131
+ never records source paths or source text.
3132
+ """
3133
+
3134
+ selected = _agents_last_exam_public_selected_task_scan(
3135
+ source_root,
3136
+ selected_task_lists,
3137
+ )
3138
+ blockers: list[str] = []
3139
+ if selected.get("checked") is not True:
3140
+ blockers.append("selected_task_lists_not_checked")
3141
+ task_ids = [
3142
+ task_id
3143
+ for task_id in selected.get("task_ids", [])
3144
+ if isinstance(task_id, str)
3145
+ ]
3146
+ if selected.get("checked") is True and not task_ids:
3147
+ blockers.append("selected_task_lists_empty")
3148
+
3149
+ scan_results = [
3150
+ _agents_last_exam_requires_task_data_line_scan(
3151
+ source_root=source_root,
3152
+ task_id=task_id,
3153
+ )
3154
+ for task_id in task_ids
3155
+ ]
3156
+ checked_results = [item for item in scan_results if item.get("checked") is True]
3157
+ no_data_candidates = [
3158
+ str(item.get("task_id"))
3159
+ for item in checked_results
3160
+ if item.get("requires_task_data") is False and item.get("task_id")
3161
+ ]
3162
+ demo_no_data_candidates = [
3163
+ task_id for task_id in no_data_candidates if task_id.startswith("demo__")
3164
+ ]
3165
+ formal_no_data_candidates = [
3166
+ task_id for task_id in no_data_candidates if not task_id.startswith("demo__")
3167
+ ]
3168
+ eligible_candidates = (
3169
+ no_data_candidates if allow_demo_candidate else formal_no_data_candidates
3170
+ )
3171
+ if task_ids and not no_data_candidates:
3172
+ blockers.append("no_no_task_data_candidate_found")
3173
+ elif task_ids and not eligible_candidates:
3174
+ blockers.append("no_formal_no_task_data_candidate_found")
3175
+ ready = not blockers
3176
+ explicit_false_count = sum(
3177
+ 1
3178
+ for item in checked_results
3179
+ if item.get("requires_task_data") is False
3180
+ and item.get("requires_task_data_declared") is True
3181
+ )
3182
+ explicit_true_count = sum(
3183
+ 1
3184
+ for item in checked_results
3185
+ if item.get("requires_task_data") is True
3186
+ and item.get("requires_task_data_declared") is True
3187
+ )
3188
+ default_true_count = sum(
3189
+ 1
3190
+ for item in checked_results
3191
+ if item.get("requires_task_data") is True
3192
+ and item.get("requires_task_data_declared") is False
3193
+ )
3194
+ missing_config_count = sum(
3195
+ 1 for item in scan_results if item.get("checked") is not True
3196
+ )
3197
+ return {
3198
+ "schema_version": AGENTS_LAST_EXAM_CANDIDATE_TASK_DATA_SCAN_SCHEMA_VERSION,
3199
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
3200
+ "ready": ready,
3201
+ "first_blocker": blockers[0]
3202
+ if blockers
3203
+ else "ready_for_local_no_task_data_ale_candidate_gate",
3204
+ "blockers": blockers,
3205
+ "selected_task_lists": {
3206
+ key: value
3207
+ for key, value in selected.items()
3208
+ if key != "task_ids"
3209
+ },
3210
+ "scan_summary": {
3211
+ "selected_task_count": len(task_ids),
3212
+ "task_config_checked_count": len(checked_results),
3213
+ "task_config_missing_or_unreadable_count": missing_config_count,
3214
+ "explicit_requires_task_data_false_count": explicit_false_count,
3215
+ "explicit_requires_task_data_true_count": explicit_true_count,
3216
+ "default_requires_task_data_true_count": default_true_count,
3217
+ "no_task_data_candidate_count": len(no_data_candidates),
3218
+ "formal_no_task_data_candidate_count": len(formal_no_data_candidates),
3219
+ "demo_no_task_data_candidate_count": len(demo_no_data_candidates),
3220
+ "allow_demo_candidate": bool(allow_demo_candidate),
3221
+ },
3222
+ "candidate_tasks": {
3223
+ "eligible_no_task_data_candidates": eligible_candidates[:25],
3224
+ "formal_no_task_data_candidates": formal_no_data_candidates[:25],
3225
+ "demo_no_task_data_candidates": demo_no_data_candidates[:25],
3226
+ "candidate_count_truncated": len(eligible_candidates) > 25,
3227
+ "task_ids_public_only": True,
3228
+ },
3229
+ "boundary": {
3230
+ "local_only": True,
3231
+ "no_upload": True,
3232
+ "submit_eligible": False,
3233
+ "leaderboard_evidence": False,
3234
+ "container_started": False,
3235
+ "model_api_invoked": False,
3236
+ "raw_trajectory_read": False,
3237
+ "screenshot_captured": False,
3238
+ "credential_values_recorded": False,
3239
+ "hidden_references_allowed": False,
3240
+ "production_actions_allowed": False,
3241
+ "local_paths_recorded": False,
3242
+ "selected_task_list_content_recorded": False,
3243
+ "task_config_line_scan": True,
3244
+ "task_config_source_content_recorded": False,
3245
+ "task_card_content_read": False,
3246
+ "script_content_read": False,
3247
+ "task_instruction_file_read": False,
3248
+ "raw_output_recorded": False,
3249
+ },
3250
+ "decision": {
3251
+ "next_allowed_action": "prepare_no_task_data_formal_ale_validation_gate"
3252
+ if ready
3253
+ else "do_not_launch_formal_ale_until_task_data_substrate_is_ready",
3254
+ "minimum_next_evidence": (
3255
+ "A formal local/no-upload ALE candidate should either be listed "
3256
+ "as not requiring task data or carry a separately verified "
3257
+ "task-data source readiness signal before any model task run."
3258
+ ),
3259
+ "must_not_claim": [
3260
+ "ALE task success",
3261
+ "ALE score uplift",
3262
+ "LoopX treatment advantage",
3263
+ "leaderboard evidence",
3264
+ ],
3265
+ },
3266
+ "read_boundary": {
3267
+ "compact_only": True,
3268
+ "task_config_line_scan": True,
3269
+ "task_config_source_content_recorded": False,
3270
+ "task_card_content_read": False,
3271
+ "script_content_read": False,
3272
+ "task_instruction_file_read": False,
3273
+ "raw_artifacts_read": False,
3274
+ "local_paths_recorded": False,
3275
+ "container_started": False,
3276
+ },
3277
+ }
3278
+
3279
+ def _agents_last_exam_relative_file_probe(
3280
+ source_root: str | None,
3281
+ relative_path: str | None,
3282
+ *,
3283
+ file_root: str | None = None,
3284
+ ) -> dict[str, Any]:
3285
+ label = _agents_last_exam_public_id(relative_path, limit=160)
3286
+ root_kind = "external_spec_root" if file_root else "source_root"
3287
+ if not relative_path:
3288
+ return {
3289
+ "relative_path": None,
3290
+ "declared": False,
3291
+ "exists": False,
3292
+ "first_blocker": "experiment_spec_missing",
3293
+ "root_kind": root_kind,
3294
+ "source_root_path_recorded": False,
3295
+ "external_root_path_recorded": False,
3296
+ }
3297
+ text = relative_path.replace("\\", "/").strip()
3298
+ parts = [part for part in text.split("/") if part]
3299
+ if text.startswith("/") or text.startswith("~") or any(
3300
+ part in {".", ".."} for part in parts
3301
+ ):
3302
+ return {
3303
+ "relative_path": label,
3304
+ "declared": True,
3305
+ "exists": False,
3306
+ "first_blocker": "experiment_spec_relative_path_not_public_safe",
3307
+ "root_kind": root_kind,
3308
+ "source_root_path_recorded": False,
3309
+ "external_root_path_recorded": False,
3310
+ }
3311
+ probe_root = file_root or source_root
3312
+ if not probe_root:
3313
+ return {
3314
+ "relative_path": label,
3315
+ "declared": True,
3316
+ "exists": False,
3317
+ "first_blocker": f"{root_kind}_missing",
3318
+ "root_kind": root_kind,
3319
+ "source_root_path_recorded": False,
3320
+ "external_root_path_recorded": False,
3321
+ }
3322
+ try:
3323
+ source_path = Path(probe_root).expanduser()
3324
+ except (OSError, RuntimeError):
3325
+ source_path = None
3326
+ if source_path is None or not source_path.is_dir():
3327
+ return {
3328
+ "relative_path": label,
3329
+ "declared": True,
3330
+ "exists": False,
3331
+ "first_blocker": f"{root_kind}_not_available",
3332
+ "root_kind": root_kind,
3333
+ "source_root_path_recorded": False,
3334
+ "external_root_path_recorded": False,
3335
+ }
3336
+ candidate = source_path.joinpath(*parts)
3337
+ try:
3338
+ resolved_source = source_path.resolve()
3339
+ resolved_candidate = candidate.resolve()
3340
+ inside_root = resolved_candidate == resolved_source or (
3341
+ resolved_source in resolved_candidate.parents
3342
+ )
3343
+ except OSError:
3344
+ inside_root = False
3345
+ exists = bool(inside_root and candidate.is_file())
3346
+ return {
3347
+ "relative_path": label,
3348
+ "declared": True,
3349
+ "exists": exists,
3350
+ "first_blocker": None if exists else "experiment_spec_file_missing",
3351
+ "root_kind": root_kind,
3352
+ "source_root_path_recorded": False,
3353
+ "external_root_path_recorded": False,
3354
+ }
3355
+
3356
+ def build_agents_last_exam_local_launch_packet(
3357
+ *,
3358
+ source_root: str | None,
3359
+ experiment_spec_relative_path: str | None,
3360
+ experiment_spec_root: str | None = None,
3361
+ selected_task_id: str | None = None,
3362
+ expected_repo_url: str = AGENTS_LAST_EXAM_DEFAULT_REPO_URL,
3363
+ snapshot: str = AGENTS_LAST_EXAM_DEFAULT_SNAPSHOT,
3364
+ provider_kind: str = "docker",
3365
+ image_ref: str = AGENTS_LAST_EXAM_DEFAULT_DOCKER_IMAGE,
3366
+ alternate_image_ref: str = AGENTS_LAST_EXAM_DEFAULT_ALT_DOCKER_IMAGE,
3367
+ runner_binary: str | None = "python3",
3368
+ runner_python_module: str | None = "ale_run",
3369
+ runner_command_label: str | None = "python-m-ale-run",
3370
+ operator_authorized: bool = False,
3371
+ allow_public_task_material: bool = False,
3372
+ fetch_origin: bool = False,
3373
+ require_upstream_current: bool = False,
3374
+ image_metadata: dict[str, Any] | None = None,
3375
+ alternate_image_metadata: dict[str, Any] | None = None,
3376
+ disk_headroom: dict[str, Any] | None = None,
3377
+ ) -> dict[str, Any]:
3378
+ """Build a redacted no-execution packet for a future ALE dry-run."""
3379
+
3380
+ source_readiness = build_agents_last_exam_local_source_readiness(
3381
+ source_root=source_root,
3382
+ expected_repo_url=expected_repo_url,
3383
+ runner_python_module=runner_python_module or "ale_run",
3384
+ fetch_origin=fetch_origin,
3385
+ require_upstream_current=require_upstream_current,
3386
+ )
3387
+ runner_readiness = build_agents_last_exam_local_runner_readiness(
3388
+ selected_task_id=selected_task_id,
3389
+ snapshot=snapshot,
3390
+ provider_kind=provider_kind,
3391
+ image_ref=image_ref,
3392
+ alternate_image_ref=alternate_image_ref,
3393
+ runner_binary=runner_binary,
3394
+ runner_python_module=runner_python_module,
3395
+ runner_source_root=source_root,
3396
+ runner_command_label=runner_command_label,
3397
+ operator_authorized=operator_authorized,
3398
+ allow_public_task_material=allow_public_task_material,
3399
+ image_metadata=image_metadata,
3400
+ alternate_image_metadata=alternate_image_metadata,
3401
+ disk_headroom=disk_headroom,
3402
+ )
3403
+ spec_probe = _agents_last_exam_relative_file_probe(
3404
+ source_root,
3405
+ experiment_spec_relative_path,
3406
+ file_root=experiment_spec_root,
3407
+ )
3408
+ blockers: list[str] = []
3409
+ if source_readiness.get("ready") is not True:
3410
+ blockers.append(
3411
+ _agents_last_exam_public_id(source_readiness.get("first_blocker"), limit=80)
3412
+ or "ale_source_not_ready"
3413
+ )
3414
+ if runner_readiness.get("ready") is not True:
3415
+ blockers.append(
3416
+ _agents_last_exam_public_id(runner_readiness.get("first_blocker"), limit=80)
3417
+ or "ale_runner_not_ready"
3418
+ )
3419
+ if spec_probe.get("exists") is not True:
3420
+ blockers.append(
3421
+ _agents_last_exam_public_id(spec_probe.get("first_blocker"), limit=80)
3422
+ or "experiment_spec_not_ready"
3423
+ )
3424
+ ready = not blockers
3425
+ source = (
3426
+ source_readiness.get("source")
3427
+ if isinstance(source_readiness.get("source"), dict)
3428
+ else {}
3429
+ )
3430
+ runner_probe = (
3431
+ runner_readiness.get("runner_probe")
3432
+ if isinstance(runner_readiness.get("runner_probe"), dict)
3433
+ else {}
3434
+ )
3435
+ run_permission_policy = build_run_permission_policy(
3436
+ policy_id="agents_last_exam_local_launch_no_upload_policy",
3437
+ max_wall_time_minutes=120,
3438
+ )
3439
+ run_permission_projection = compact_run_permission_policy_for_quota(
3440
+ run_permission_policy
3441
+ )
3442
+ attempt_accounting = build_benchmark_attempt_accounting(
3443
+ lifecycle=canonical_lifecycle(),
3444
+ failure_label="",
3445
+ failure_class=BenchmarkFailureClass.NONE,
3446
+ official_score_attempted=False,
3447
+ )
3448
+ task_public_id = (
3449
+ _agents_last_exam_public_id(selected_task_id, limit=160)
3450
+ or "metadata_only_candidate"
3451
+ )
3452
+ task_job_id = task_public_id.replace("/", "-")
3453
+ observable_handle_registration = build_benchmark_launch_observable_handle(
3454
+ benchmark_id=AGENTS_LAST_EXAM_BENCHMARK_ID,
3455
+ launch_mode="no_execution_launch_packet",
3456
+ run_label=f"{AGENTS_LAST_EXAM_BENCHMARK_ID}-{task_job_id}-dry-run",
3457
+ job_basename=f"{AGENTS_LAST_EXAM_BENCHMARK_ID}-{task_job_id}-dry-run",
3458
+ process_state="not_started",
3459
+ compact_artifact_refs=(
3460
+ "run.compact.json",
3461
+ "eval.compact.json",
3462
+ "events.compact.json",
3463
+ ),
3464
+ allowed_poll_command="benchmark_run_status_snapshot",
3465
+ scheduler_kind="manual_operator",
3466
+ will_execute=False,
3467
+ read_boundary={
3468
+ "compact_only": True,
3469
+ "task_text_read": False,
3470
+ "raw_artifacts_read": False,
3471
+ "local_paths_recorded": False,
3472
+ "private_handle_values_recorded": False,
3473
+ },
3474
+ )
3475
+ return {
3476
+ "schema_version": AGENTS_LAST_EXAM_LOCAL_LAUNCH_PACKET_SCHEMA_VERSION,
3477
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
3478
+ "task_id": task_public_id,
3479
+ "snapshot": _agents_last_exam_public_id(snapshot, limit=80)
3480
+ or AGENTS_LAST_EXAM_DEFAULT_SNAPSHOT,
3481
+ "ready": ready,
3482
+ "first_blocker": blockers[0]
3483
+ if blockers
3484
+ else "ready_for_operator_triggered_no_upload_ale_dry_run",
3485
+ "blockers": blockers,
3486
+ "source_lock": {
3487
+ "expected_repo": source.get("expected_repo"),
3488
+ "remote": source.get("remote"),
3489
+ "remote_matches_expected": source.get("remote_matches_expected") is True,
3490
+ "head": source.get("head"),
3491
+ "upstream_ref": source.get("upstream_ref"),
3492
+ "upstream_head": source.get("upstream_head"),
3493
+ "upstream_declared": source.get("upstream_declared") is True,
3494
+ "head_matches_upstream": source.get("head_matches_upstream") is True,
3495
+ "upstream_ahead_count": source.get("upstream_ahead_count"),
3496
+ "upstream_behind_count": source.get("upstream_behind_count"),
3497
+ "fetch_origin_attempted": source.get("fetch_origin_attempted") is True,
3498
+ "fetch_origin_ok": source.get("fetch_origin_ok") is True,
3499
+ "require_upstream_current": source.get("require_upstream_current") is True,
3500
+ "source_root_path_recorded": False,
3501
+ },
3502
+ "runner": {
3503
+ "command_label": runner_probe.get("command_label"),
3504
+ "binary": runner_probe.get("binary"),
3505
+ "python_module": runner_probe.get("python_module"),
3506
+ "binary_available": runner_probe.get("binary_available") is True,
3507
+ "python_module_available": runner_probe.get("python_module_available")
3508
+ is True,
3509
+ "source_root_path_recorded": False,
3510
+ "command_argv_recorded": False,
3511
+ },
3512
+ "experiment_spec": {
3513
+ "relative_path": spec_probe.get("relative_path"),
3514
+ "declared": spec_probe.get("declared") is True,
3515
+ "exists": spec_probe.get("exists") is True,
3516
+ "content_read": False,
3517
+ "root_kind": spec_probe.get("root_kind"),
3518
+ "external_root_declared": bool(experiment_spec_root),
3519
+ "source_root_path_recorded": False,
3520
+ "external_root_path_recorded": False,
3521
+ },
3522
+ "launch_packet": {
3523
+ "mode": "no_execution_launch_packet",
3524
+ "command_shape": "python-m-ale-run-dry-run",
3525
+ "will_execute": False,
3526
+ "will_start_container": False,
3527
+ "will_read_task_body": False,
3528
+ "will_invoke_model_api": False,
3529
+ "will_upload": False,
3530
+ "will_submit": False,
3531
+ "will_capture_screenshot": False,
3532
+ "will_record_credentials": False,
3533
+ "will_record_local_paths": False,
3534
+ },
3535
+ "observable_handle_registration": observable_handle_registration,
3536
+ "case_state_init_contract": benchmark_case_active_state_init_contract(
3537
+ benchmark_id=AGENTS_LAST_EXAM_BENCHMARK_ID,
3538
+ goal_id=AGENTS_LAST_EXAM_CASE_GOAL_ID,
3539
+ case_state_path=AGENTS_LAST_EXAM_CASE_STATE_PATH,
3540
+ initialized_by_launch_packet=False,
3541
+ ),
3542
+ "run_permission_policy": run_permission_policy,
3543
+ "run_permission_quota_projection": run_permission_projection,
3544
+ "attempt_accounting": attempt_accounting,
3545
+ "boundary": {
3546
+ "local_only": True,
3547
+ "no_upload": True,
3548
+ "submit_eligible": False,
3549
+ "leaderboard_evidence": False,
3550
+ "container_started": False,
3551
+ "task_body_read": False,
3552
+ "model_api_invoked": False,
3553
+ "raw_trajectory_read": False,
3554
+ "screenshot_captured": False,
3555
+ "credential_values_recorded": False,
3556
+ "hidden_references_allowed": False,
3557
+ "production_actions_allowed": False,
3558
+ "local_paths_recorded": False,
3559
+ "command_argv_recorded": False,
3560
+ },
3561
+ "decision": {
3562
+ "next_allowed_action": "operator_trigger_exact_no_upload_ale_dry_run"
3563
+ if ready
3564
+ else "repair_ale_launch_packet_blocker_before_execution",
3565
+ "minimum_next_evidence": (
3566
+ "A human/operator-triggered ALE dry-run using the redacted source "
3567
+ "lock, runner label, and experiment spec, followed by compact "
3568
+ "run/eval/events ingest only."
3569
+ ),
3570
+ "must_not_claim": [
3571
+ "ALE task success",
3572
+ "ALE score uplift",
3573
+ "LoopX treatment advantage",
3574
+ "leaderboard evidence",
3575
+ ],
3576
+ },
3577
+ "read_boundary": {
3578
+ "compact_only": True,
3579
+ "task_text_read": False,
3580
+ "experiment_spec_content_read": False,
3581
+ "raw_artifacts_read": False,
3582
+ "local_paths_recorded": False,
3583
+ "container_started": False,
3584
+ },
3585
+ }
3586
+
3587
+ def build_agents_last_exam_local_runner_readiness(
3588
+ *,
3589
+ selected_task_id: str | None = None,
3590
+ snapshot: str = AGENTS_LAST_EXAM_DEFAULT_SNAPSHOT,
3591
+ provider_kind: str = "docker",
3592
+ image_ref: str = AGENTS_LAST_EXAM_DEFAULT_DOCKER_IMAGE,
3593
+ alternate_image_ref: str = AGENTS_LAST_EXAM_DEFAULT_ALT_DOCKER_IMAGE,
3594
+ runner_binary: str | None = None,
3595
+ runner_python_module: str | None = None,
3596
+ runner_source_root: str | None = None,
3597
+ runner_command_label: str | None = None,
3598
+ operator_authorized: bool = False,
3599
+ allow_public_task_material: bool = False,
3600
+ fetch_origin: bool = False,
3601
+ require_upstream_current: bool = False,
3602
+ image_metadata: dict[str, Any] | None = None,
3603
+ alternate_image_metadata: dict[str, Any] | None = None,
3604
+ disk_headroom: dict[str, Any] | None = None,
3605
+ preflight: dict[str, Any] | None = None,
3606
+ dry_run_plan: dict[str, Any] | None = None,
3607
+ ) -> dict[str, Any]:
3608
+ """Check whether a real local ALE dry-run runner is configured.
3609
+
3610
+ This is still a no-execution gate: it may inspect Docker image metadata and
3611
+ the local PATH for a runner binary, but it does not start containers, read
3612
+ task bodies, invoke model APIs, upload, submit, or record command argv.
3613
+ """
3614
+
3615
+ preflight_payload = (
3616
+ preflight
3617
+ if isinstance(preflight, dict)
3618
+ else build_agents_last_exam_local_preflight(
3619
+ selected_task_id=selected_task_id,
3620
+ snapshot=snapshot,
3621
+ provider_kind=provider_kind,
3622
+ image_ref=image_ref,
3623
+ alternate_image_ref=alternate_image_ref,
3624
+ image_metadata=image_metadata,
3625
+ alternate_image_metadata=alternate_image_metadata,
3626
+ disk_headroom=disk_headroom,
3627
+ )
3628
+ )
3629
+ plan_payload = (
3630
+ dry_run_plan
3631
+ if isinstance(dry_run_plan, dict)
3632
+ else build_agents_last_exam_local_dry_run_plan(
3633
+ selected_task_id=selected_task_id,
3634
+ snapshot=snapshot,
3635
+ provider_kind=provider_kind,
3636
+ image_ref=image_ref,
3637
+ alternate_image_ref=alternate_image_ref,
3638
+ image_metadata=image_metadata,
3639
+ alternate_image_metadata=alternate_image_metadata,
3640
+ disk_headroom=disk_headroom,
3641
+ preflight=preflight_payload,
3642
+ )
3643
+ )
3644
+ runner_probe = _agents_last_exam_runner_binary_probe(runner_binary)
3645
+ module_probe = _agents_last_exam_python_module_probe(
3646
+ runner_python_module,
3647
+ source_root=runner_source_root,
3648
+ )
3649
+ source_lock = None
3650
+ if fetch_origin or require_upstream_current:
3651
+ source_lock = build_agents_last_exam_local_source_readiness(
3652
+ source_root=runner_source_root,
3653
+ runner_python_module=runner_python_module or "ale_run",
3654
+ fetch_origin=fetch_origin,
3655
+ require_upstream_current=require_upstream_current,
3656
+ )
3657
+ command_label = _agents_last_exam_public_id(
3658
+ runner_command_label
3659
+ or (
3660
+ f"{runner_probe.get('binary')}-m-{module_probe.get('module')}"
3661
+ if runner_probe.get("binary") and module_probe.get("module")
3662
+ else runner_probe.get("binary")
3663
+ ),
3664
+ limit=120,
3665
+ )
3666
+ module_required = _agents_last_exam_runner_binary_requires_python_module(
3667
+ runner_binary
3668
+ )
3669
+ blockers: list[str] = []
3670
+ if operator_authorized is not True:
3671
+ blockers.append("operator_authorization_missing")
3672
+ if allow_public_task_material is not True:
3673
+ blockers.append("public_task_material_authorization_missing")
3674
+ if plan_payload.get("ready") is not True:
3675
+ blockers.append(
3676
+ _agents_last_exam_public_id(plan_payload.get("first_blocker"), limit=80)
3677
+ or "ale_local_dry_run_plan_not_ready"
3678
+ )
3679
+ if not command_label:
3680
+ blockers.append("runner_command_missing")
3681
+ if runner_probe.get("available") is not True:
3682
+ blockers.append(
3683
+ _agents_last_exam_public_id(runner_probe.get("first_blocker"), limit=80)
3684
+ or "runner_binary_not_available"
3685
+ )
3686
+ if module_required and module_probe.get("declared") is not True:
3687
+ blockers.append("runner_python_module_missing")
3688
+ if module_probe.get("declared") is True and module_probe.get("available") is not True:
3689
+ blockers.append(
3690
+ _agents_last_exam_public_id(module_probe.get("first_blocker"), limit=80)
3691
+ or "runner_python_module_not_available"
3692
+ )
3693
+ if source_lock is not None and source_lock.get("ready") is not True:
3694
+ blockers.append(
3695
+ _agents_last_exam_public_id(source_lock.get("first_blocker"), limit=80)
3696
+ or "ale_source_lock_not_ready"
3697
+ )
3698
+ ready = not blockers
3699
+
3700
+ return {
3701
+ "schema_version": AGENTS_LAST_EXAM_LOCAL_RUNNER_READINESS_SCHEMA_VERSION,
3702
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
3703
+ "task_id": plan_payload.get("task_id") or "metadata_only_candidate",
3704
+ "snapshot": plan_payload.get("snapshot") or AGENTS_LAST_EXAM_DEFAULT_SNAPSHOT,
3705
+ "preflight_ready": preflight_payload.get("ready") is True,
3706
+ "dry_run_plan_ready": plan_payload.get("ready") is True,
3707
+ "runner_ready": ready,
3708
+ "ready": ready,
3709
+ "first_blocker": blockers[0]
3710
+ if blockers
3711
+ else "ready_for_local_ale_dry_run_runner",
3712
+ "blockers": blockers,
3713
+ "runner_probe": {
3714
+ "command_label": command_label,
3715
+ "binary": runner_probe.get("binary"),
3716
+ "binary_declared": runner_probe.get("declared") is True,
3717
+ "binary_available": runner_probe.get("available") is True,
3718
+ "python_module": module_probe.get("module"),
3719
+ "python_module_declared": module_probe.get("declared") is True,
3720
+ "python_module_available": module_probe.get("available") is True,
3721
+ "source_root_declared": module_probe.get("source_root_declared") is True,
3722
+ "source_root_available": module_probe.get("source_root_available") is True,
3723
+ "source_root_path_recorded": False,
3724
+ "python_module_path_recorded": False,
3725
+ "binary_path_recorded": False,
3726
+ "command_argv_recorded": False,
3727
+ "first_blocker": _agents_last_exam_public_id(
3728
+ runner_probe.get("first_blocker"),
3729
+ limit=80,
3730
+ ),
3731
+ },
3732
+ "source_lock": source_lock,
3733
+ "boundary": {
3734
+ "local_only": True,
3735
+ "no_cloud": provider_kind == "docker",
3736
+ "no_upload": True,
3737
+ "submit_eligible": False,
3738
+ "leaderboard_evidence": False,
3739
+ "operator_authorized_local_container_start": operator_authorized is True,
3740
+ "operator_authorized_public_task_material": (
3741
+ allow_public_task_material is True
3742
+ ),
3743
+ "container_started": False,
3744
+ "task_body_read": False,
3745
+ "model_api_invoked": False,
3746
+ "model_api_allowed": False,
3747
+ "upload_allowed": False,
3748
+ "submit_allowed": False,
3749
+ "raw_trajectory_read": False,
3750
+ "screenshot_captured": False,
3751
+ "credential_values_recorded": False,
3752
+ "hidden_references_allowed": False,
3753
+ "production_actions_allowed": False,
3754
+ "local_paths_recorded": False,
3755
+ },
3756
+ "decision": {
3757
+ "next_allowed_action": "run_configured_no_upload_ale_local_dry_run"
3758
+ if ready
3759
+ else "configure_verified_ale_local_runner_before_execution",
3760
+ "minimum_next_evidence": (
3761
+ "A configured local runner command label and PATH-visible runner "
3762
+ "binary, followed by one no-upload dry-run that produces compact "
3763
+ "run/eval/events metadata only."
3764
+ ),
3765
+ "must_not_claim": [
3766
+ "ALE task success",
3767
+ "ALE score uplift",
3768
+ "LoopX treatment advantage",
3769
+ "leaderboard evidence",
3770
+ ],
3771
+ },
3772
+ "read_boundary": {
3773
+ "compact_only": True,
3774
+ "task_text_read": False,
3775
+ "raw_artifacts_read": False,
3776
+ "local_paths_recorded": False,
3777
+ "container_started": False,
3778
+ },
3779
+ }
3780
+
3781
+ def build_agents_last_exam_result_benchmark_report(
3782
+ run_dir: str | Path,
3783
+ *,
3784
+ report_id: str | None = None,
3785
+ harness_identity: str = "loopx-meta",
3786
+ runner_source: str = "ale_run_run_writer_v2",
3787
+ harness_policy_version: str = AGENTS_LAST_EXAM_RESULT_INGEST_POLICY_VERSION,
3788
+ trace_publicness: str = AGENTS_LAST_EXAM_TRACE_PUBLICNESS,
3789
+ ) -> dict[str, Any]:
3790
+ """Compact an ALE run directory into benchmark_experiment_report_v0.
3791
+
3792
+ The compactor reads only ALE's compact top-level files: ``run.json``,
3793
+ ``eval_result.json``, and ``events.jsonl``. It deliberately does not read or
3794
+ record ``trajectory.json``, ``origin_log/``, ``output/``, task bodies,
3795
+ screenshots, credential values, or local absolute paths.
3796
+ """
3797
+
3798
+ path = Path(run_dir)
3799
+ run_json = _load_json_object(path / "run.json")
3800
+ eval_result = _load_json_object(path / "eval_result.json")
3801
+ events = _load_jsonl_objects(path / "events.jsonl")
3802
+ score = _optional_float(eval_result.get("score"))
3803
+ eval_status = _agents_last_exam_public_id(eval_result.get("eval_status"), limit=80)
3804
+ run_status = _agents_last_exam_public_id(
3805
+ _agents_last_exam_nested(run_json, "status"),
3806
+ limit=80,
3807
+ )
3808
+ task_label = _agents_last_exam_first_public_id(
3809
+ _agents_last_exam_nested(run_json, "task_path"),
3810
+ _agents_last_exam_nested(run_json, "task_id"),
3811
+ _agents_last_exam_nested(run_json, "task"),
3812
+ default="unknown_task",
3813
+ )
3814
+ agent_label = _agents_last_exam_first_public_id(
3815
+ _agents_last_exam_nested(run_json, "agent_id"),
3816
+ _agents_last_exam_nested(run_json, "agent"),
3817
+ default="unknown_agent",
3818
+ )
3819
+ model_label = _agents_last_exam_first_public_id(
3820
+ _agents_last_exam_nested(run_json, "model"),
3821
+ default="unknown_model",
3822
+ )
3823
+ run_id = _agents_last_exam_public_id(
3824
+ run_json.get("run_id") or path.name,
3825
+ limit=160,
3826
+ ) or "unknown_run"
3827
+ report_label = (
3828
+ _agents_last_exam_public_id(report_id, limit=160)
3829
+ if report_id
3830
+ else f"{AGENTS_LAST_EXAM_BENCHMARK_ID}-{run_id}"
3831
+ )
3832
+ event_counts = _agents_last_exam_event_type_counts(events)
3833
+ error = eval_result.get("error") if isinstance(eval_result.get("error"), dict) else {}
3834
+ error_type = _agents_last_exam_public_id(
3835
+ error.get("type") or error.get("exception_type") or error.get("class"),
3836
+ limit=80,
3837
+ )
3838
+ duration_s = _optional_float(
3839
+ run_json.get("duration_s")
3840
+ or run_json.get("elapsed_s")
3841
+ or _agents_last_exam_nested(run_json, "duration_s")
3842
+ )
3843
+ eval_duration_s = _optional_float(eval_result.get("eval_duration_s"))
3844
+ raw_surface_presence = {
3845
+ "trajectory_json_present": (path / "trajectory.json").exists(),
3846
+ "origin_log_dir_present": (path / "origin_log").exists(),
3847
+ "output_dir_present": (path / "output").exists(),
3848
+ }
3849
+ run_json_present = bool(run_json)
3850
+ eval_result_present = bool(eval_result)
3851
+ events_jsonl_present = (path / "events.jsonl").exists()
3852
+ completed = eval_status in {"passed", "completed", "success", "ok"} or (
3853
+ score is not None and not error_type
3854
+ )
3855
+ source_events = [
3856
+ "ale run.json parsed" if run_json_present else "ale run.json missing",
3857
+ "ale eval_result.json parsed" if eval_result_present else "ale eval_result.json missing",
3858
+ "ale events.jsonl counted" if events_jsonl_present else "ale events.jsonl missing",
3859
+ "raw ALE trajectory/origin_log/output excluded",
3860
+ ]
3861
+ negative_layers = ["single_arm_no_delta", "raw_surfaces_excluded"]
3862
+ if not run_json_present:
3863
+ negative_layers.append("run_json_missing")
3864
+ if not eval_result_present:
3865
+ negative_layers.append("eval_result_missing")
3866
+ if error_type:
3867
+ negative_layers.append("eval_error_present")
3868
+ attempt_lifecycle = canonical_lifecycle(
3869
+ process_started=run_json_present,
3870
+ runner_accepted_args=run_json_present,
3871
+ job_root_materialized=run_json_present,
3872
+ trial_started=run_json_present,
3873
+ worker_started=bool(events) or completed or score is not None or bool(error_type),
3874
+ result_written=eval_result_present,
3875
+ verifier_scored=score is not None or bool(error_type),
3876
+ )
3877
+ if not run_json_present:
3878
+ attempt_failure_class = BenchmarkFailureClass.RUNNER_STARTUP_FAILED
3879
+ attempt_failure_label = "ale_run_json_missing"
3880
+ elif error_type:
3881
+ attempt_failure_class = BenchmarkFailureClass.VERIFIER_FAILED
3882
+ attempt_failure_label = f"ale_eval_error:{error_type}"
3883
+ elif score is None:
3884
+ attempt_failure_class = BenchmarkFailureClass.OFFICIAL_SCORE_FAILED
3885
+ attempt_failure_label = "ale_eval_score_missing"
3886
+ elif score == 0:
3887
+ attempt_failure_class = BenchmarkFailureClass.SOLVER_FAILED
3888
+ attempt_failure_label = "ale_eval_score_zero"
3889
+ else:
3890
+ attempt_failure_class = BenchmarkFailureClass.NONE
3891
+ attempt_failure_label = "none"
3892
+ attempt_accounting = build_benchmark_attempt_accounting(
3893
+ lifecycle=attempt_lifecycle,
3894
+ failure_label=attempt_failure_label,
3895
+ failure_class=attempt_failure_class,
3896
+ official_score_attempted=score is not None,
3897
+ )
3898
+
3899
+ return {
3900
+ "schema_version": "benchmark_experiment_report_v0",
3901
+ "experiment_identity": {
3902
+ "report_id": report_label,
3903
+ "benchmark_id": AGENTS_LAST_EXAM_BENCHMARK_ID,
3904
+ "task_slice": task_label,
3905
+ "worker_surface": "ale_run_compact_result_ingest",
3906
+ "harness_identity": harness_identity,
3907
+ "harness_policy_version": harness_policy_version,
3908
+ "trace_publicness": trace_publicness,
3909
+ },
3910
+ "official_score": {
3911
+ "kind": "ale_eval_result" if score is not None else "ale_eval_result_missing",
3912
+ "task_id_or_split": task_label,
3913
+ "runner_source": runner_source,
3914
+ "native_score": score if score is not None else 0.0,
3915
+ "wrapped_score": score if score is not None else 0.0,
3916
+ "delta": 0.0,
3917
+ "repetitions": 1 if eval_result_present else 0,
3918
+ "submit_eligible": False,
3919
+ "leaderboard_evidence": False,
3920
+ },
3921
+ "attempt_accounting": attempt_accounting,
3922
+ "passive_control_plane_score": {
3923
+ "restartability": 1.0 if run_json_present and events_jsonl_present else 0.5,
3924
+ "stale_state_avoidance": 1.0,
3925
+ "evidence_discipline": 1.0,
3926
+ "writeback_quality": 1.0 if eval_result_present else 0.5,
3927
+ "failure_attribution": 1.0 if error_type or completed else 0.5,
3928
+ "overhead_bounded": True,
3929
+ "regression_avoidance_passed": True,
3930
+ "source_events": source_events,
3931
+ },
3932
+ "operator_simulator_ablation": {
3933
+ "enabled": False,
3934
+ "leaderboard_evidence": False,
3935
+ "intervention_count": 0,
3936
+ "reason": "ALE compact result ingest is passive; simulator evidence must be a separate treatment layer.",
3937
+ },
3938
+ "cost_latency_overhead": {
3939
+ "duration_s": duration_s,
3940
+ "eval_duration_s": eval_duration_s,
3941
+ "event_count": len(events),
3942
+ "event_type_counts": event_counts,
3943
+ "raw_trace_recorded": False,
3944
+ "raw_output_recorded": False,
3945
+ },
3946
+ "failure_taxonomy": {
3947
+ "run_status": run_status or "unknown",
3948
+ "eval_status": eval_status or "unknown",
3949
+ "error_type": error_type or "none",
3950
+ "score_missing": score is None,
3951
+ "single_arm_no_delta": True,
3952
+ },
3953
+ "reproducibility_artifacts": {
3954
+ "run_json_present": run_json_present,
3955
+ "eval_result_json_present": eval_result_present,
3956
+ "events_jsonl_present": events_jsonl_present,
3957
+ "event_count": len(events),
3958
+ "event_type_counts": event_counts,
3959
+ "agent_id": agent_label,
3960
+ "model": model_label,
3961
+ "task_id": task_label,
3962
+ "raw_surfaces_excluded": list(AGENTS_LAST_EXAM_RAW_SURFACES_EXCLUDED),
3963
+ "raw_surface_presence_checked": raw_surface_presence,
3964
+ "raw_surface_content_recorded": False,
3965
+ "local_paths_recorded": False,
3966
+ "credential_values_recorded": False,
3967
+ },
3968
+ "claim_boundary": {
3969
+ "may_claim": [
3970
+ "ALE compact run/eval/events artifacts can be reduced to benchmark_experiment_report_v0",
3971
+ "Raw trajectory, origin logs, outputs, task bodies, screenshots, credentials, and local paths are excluded",
3972
+ "The report is a single-arm compact ingest artifact, not a paired treatment comparison",
3973
+ ],
3974
+ "must_not_claim": [
3975
+ "ALE leaderboard evidence",
3976
+ "LoopX treatment advantage",
3977
+ "baseline-versus-treatment score delta",
3978
+ "task solution quality from raw trajectory or outputs",
3979
+ ],
3980
+ "source_decision_note_schema": "agents_last_exam_result_ingest_contract_v0",
3981
+ "source_evidence_layer": "compact_run_eval_events_only",
3982
+ },
3983
+ "negative_results": {
3984
+ "null_official_delta": True,
3985
+ "failed_hypothesis_count": 0,
3986
+ "negative_evidence_layers": negative_layers,
3987
+ "overhead_regression_count": 0,
3988
+ },
3989
+ "next_decision": {
3990
+ "decision": "wire_ale_report_append_or_authorize_no_upload_dry_run",
3991
+ "minimum_next_evidence": "Append a synthetic ALE compact report through history, or run an operator-approved no-upload ALE dry-run without reading task bodies.",
3992
+ "stop_condition": "Stop before GCP setup, VM launch, model API use, paid compute, output upload, leaderboard submission, hidden refs, task solutions, task body copying, raw trajectories, screenshots, local absolute paths, credential values, or production actions.",
3993
+ "source_decision_note_schema": "benchmark_experiment_report_v0",
3994
+ "readiness_decision": "compact_ingest_ready",
3995
+ "failure_decision": "do_not_infer_pairwise_uplift_from_single_arm_ingest",
3996
+ },
3997
+ "section_count": 10,
3998
+ }