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,1468 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ import re
6
+ from collections.abc import Callable
7
+ from datetime import datetime, timezone
8
+ from pathlib import Path
9
+
10
+ from .human_view import render_auto_research_markdown
11
+ from .research_state import (
12
+ build_auto_research_projection,
13
+ build_live_auto_research_projection,
14
+ load_auto_research_fixture,
15
+ )
16
+ from .demo_supervisor import build_auto_research_demo_supervisor_plan
17
+ from .evidence_packet import load_auto_research_evidence_packet_inputs
18
+ from .defaults import (
19
+ AUTO_RESEARCH_DEFAULT_GOAL_ID,
20
+ AUTO_RESEARCH_DEFAULT_OBJECTIVE,
21
+ AUTO_RESEARCH_KNN_DEMO_PRESET_ID,
22
+ AUTO_RESEARCH_SUPPORTED_PRESET_IDS,
23
+ )
24
+ from .demo_e2e import run_auto_research_demo_e2e
25
+ from .knn_demo_workspace import materialize_knn_demo_workspace
26
+ from .live_evidence import (
27
+ LIVE_CODEX_E2E_DEFAULT_OUTPUT,
28
+ capture_live_codex_e2e_evidence,
29
+ )
30
+ from .worker_loop import run_auto_research_worker_loop
31
+ from .worker_runtime import run_auto_research_worker_turn
32
+ from .rollout_append import (
33
+ append_auto_research_rollout_events as _append_auto_research_rollout_events,
34
+ )
35
+ from .terminal_results import (
36
+ decide_terminal_result,
37
+ project_terminal_results,
38
+ query_terminal_results,
39
+ review_terminal_result,
40
+ )
41
+ from .user_contract import (
42
+ build_auto_research_user_contract,
43
+ infer_auto_research_output_language,
44
+ normalize_auto_research_preset_id,
45
+ )
46
+ from ...control_plane.agents.multi_agent.visible_launch_policy import (
47
+ make_visible_launcher_callback,
48
+ make_visible_wake_callback,
49
+ resolve_codex_trust_workspace,
50
+ resolve_visible_launch_policy,
51
+ )
52
+ from ...control_plane.runtime.public_safety import public_safe_compact_text
53
+ from ...history import load_registry
54
+ from ...paths import resolve_runtime_root
55
+ from ...quota import build_quota_should_run
56
+ from ...rollout_event_log import load_rollout_events, rollout_event_log_path
57
+ from ...status import collect_status
58
+ from ...visible_multi_agent_launcher import (
59
+ execute_visible_multi_agent_launcher,
60
+ )
61
+
62
+
63
+ PrintPayload = Callable[
64
+ [dict[str, object], str, Callable[[dict[str, object]], str]],
65
+ None,
66
+ ]
67
+ FormatSelector = Callable[..., str]
68
+ AddFormat = Callable[[argparse.ArgumentParser], None]
69
+
70
+ AUTO_RESEARCH_DEMO_GOAL_PREFIX = "loopx-auto-research-demo"
71
+ AUTO_RESEARCH_START_AGENT_ID = "auto-research-operator"
72
+ AUTO_RESEARCH_COMMAND_FAILED_ERROR_CODE = "auto_research_command_failed"
73
+ AUTO_RESEARCH_INVALID_INPUT_ERROR_CODE = "auto_research_invalid_input"
74
+ AUTO_RESEARCH_IO_FAILED_ERROR_CODE = "auto_research_io_failed"
75
+ AUTO_RESEARCH_SUBCOMMANDS = frozenset(
76
+ {
77
+ "append-evidence",
78
+ "capture-live-evidence",
79
+ "contract",
80
+ "decide",
81
+ "demo-e2e",
82
+ "demo-supervisor",
83
+ "evidence",
84
+ "frontier",
85
+ "project-results",
86
+ "results",
87
+ "review",
88
+ "start",
89
+ "worker-loop",
90
+ "worker-turn",
91
+ }
92
+ )
93
+
94
+
95
+ def _public_auto_research_error(exc: Exception) -> tuple[str, str]:
96
+ """Project an internal exception into a stable, public-safe CLI error."""
97
+
98
+ if isinstance(exc, json.JSONDecodeError):
99
+ return (
100
+ AUTO_RESEARCH_INVALID_INPUT_ERROR_CODE,
101
+ "Auto Research input must be valid JSON.",
102
+ )
103
+ if isinstance(exc, OSError):
104
+ return (
105
+ AUTO_RESEARCH_IO_FAILED_ERROR_CODE,
106
+ "Auto Research could not access a required resource.",
107
+ )
108
+ if isinstance(exc, ValueError):
109
+ public_message = public_safe_compact_text(str(exc), limit=220)
110
+ return (
111
+ AUTO_RESEARCH_INVALID_INPUT_ERROR_CODE,
112
+ public_message or "Auto Research input is invalid.",
113
+ )
114
+ return (
115
+ AUTO_RESEARCH_COMMAND_FAILED_ERROR_CODE,
116
+ "Auto Research command failed unexpectedly.",
117
+ )
118
+
119
+
120
+ def rewrite_auto_research_question_argv(argv: list[str]) -> list[str]:
121
+ """Map `loopx auto-research "<question>"` to the explicit contract command."""
122
+
123
+ values = list(argv)
124
+ try:
125
+ command_index = values.index("auto-research")
126
+ except ValueError:
127
+ return values
128
+
129
+ cursor = command_index + 1
130
+ while cursor < len(values):
131
+ token = values[cursor]
132
+ if token == "--format" and cursor + 1 < len(values):
133
+ cursor += 2
134
+ continue
135
+ if token.startswith("--format="):
136
+ cursor += 1
137
+ continue
138
+ break
139
+ if cursor >= len(values):
140
+ return values
141
+
142
+ token = values[cursor]
143
+ if token.startswith("-") or token in AUTO_RESEARCH_SUBCOMMANDS:
144
+ return values
145
+ return values[:cursor] + ["contract"] + values[cursor:]
146
+
147
+
148
+ def _demo_goal_suffix(value: object, *, fallback: str = "run") -> str:
149
+ text = re.sub(r"[^A-Za-z0-9._-]+", "-", str(value or "").strip()).strip("-._")
150
+ return text[:40] or fallback
151
+
152
+
153
+ def _default_auto_research_start_workspace(goal_id: str) -> str:
154
+ return str(
155
+ Path.home()
156
+ / "loopx-auto-research"
157
+ / _demo_goal_suffix(goal_id, fallback="run")
158
+ / "visible-workspace"
159
+ )
160
+
161
+
162
+ def _resolve_demo_goal_surface(
163
+ *,
164
+ goal_id: str | None,
165
+ demo_run_id: str | None,
166
+ inherit_default_goal: bool,
167
+ ) -> tuple[str, str]:
168
+ if inherit_default_goal and goal_id:
169
+ raise ValueError("--inherit-default-goal cannot be combined with --goal-id")
170
+ if inherit_default_goal and demo_run_id:
171
+ raise ValueError("--inherit-default-goal cannot be combined with --demo-run-id")
172
+ if goal_id and demo_run_id:
173
+ raise ValueError("--demo-run-id is only used when --goal-id is omitted")
174
+ if inherit_default_goal:
175
+ return AUTO_RESEARCH_DEFAULT_GOAL_ID, "inherited_default_goal"
176
+ if goal_id:
177
+ return goal_id, "explicit_goal"
178
+ run_id = demo_run_id or datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
179
+ return f"{AUTO_RESEARCH_DEMO_GOAL_PREFIX}-{_demo_goal_suffix(run_id)}", "fresh_demo_goal"
180
+
181
+
182
+ def register_auto_research_commands(
183
+ subparsers: argparse._SubParsersAction,
184
+ add_subcommand_format: AddFormat,
185
+ ) -> None:
186
+ auto_research_parser = subparsers.add_parser(
187
+ "auto-research",
188
+ help="Project public-safe decentralized auto-research frontiers.",
189
+ )
190
+ auto_research_parser.add_argument(
191
+ "--format",
192
+ dest="auto_research_format",
193
+ choices=["markdown", "json"],
194
+ help="Output format for the auto-research command group.",
195
+ )
196
+ auto_research_sub = auto_research_parser.add_subparsers(
197
+ dest="auto_research_command",
198
+ required=True,
199
+ )
200
+ contract_parser = auto_research_sub.add_parser(
201
+ "contract",
202
+ help="Render the fixed user-facing auto-research contract for one open question.",
203
+ )
204
+ add_subcommand_format(contract_parser)
205
+ contract_parser.add_argument("open_question", help="Quoted open research question.")
206
+ contract_parser.add_argument(
207
+ "--max-todos",
208
+ type=int,
209
+ default=5,
210
+ help="Maximum action-plan todos, capped at 5.",
211
+ )
212
+ contract_parser.add_argument(
213
+ "--language",
214
+ choices=["auto", "zh", "en"],
215
+ default="auto",
216
+ help="Human-readable output language for the research process.",
217
+ )
218
+ contract_parser.add_argument(
219
+ "--preset",
220
+ choices=AUTO_RESEARCH_SUPPORTED_PRESET_IDS,
221
+ help="Explicit domain demo context, e.g. knn-demo materializes a KNN benchmark workspace.",
222
+ )
223
+
224
+ start_parser = auto_research_sub.add_parser(
225
+ "start",
226
+ help="Start visible multi-agent auto-research from one open question.",
227
+ )
228
+ add_subcommand_format(start_parser)
229
+ start_parser.add_argument("open_question", help="Quoted open research question.")
230
+ start_parser.add_argument(
231
+ "--language",
232
+ choices=["auto", "zh", "en"],
233
+ default="auto",
234
+ help="Human-readable output language for visible role panes.",
235
+ )
236
+ start_parser.add_argument(
237
+ "--preset",
238
+ choices=AUTO_RESEARCH_SUPPORTED_PRESET_IDS,
239
+ help=(
240
+ "Explicit domain demo context. Use knn-demo when the baseline/metric "
241
+ "come from a generated KNN benchmark workspace rather than the question text."
242
+ ),
243
+ )
244
+ start_parser.add_argument(
245
+ "--execute",
246
+ action="store_true",
247
+ help=(
248
+ "Create an isolated research goal and launch visible Codex TUI lanes. "
249
+ "Omit to preview the exact contract, commands, and runner packet."
250
+ ),
251
+ )
252
+ start_parser.add_argument(
253
+ "--headless",
254
+ action="store_true",
255
+ help="With --execute, run the non-interactive worker-loop proof instead of visible panes.",
256
+ )
257
+ start_parser.add_argument(
258
+ "--wake-visible-after-launch",
259
+ action="store_true",
260
+ default=None,
261
+ help=(
262
+ "After launching visible panes, broadcast the fixed decentralized A2A wake prompt. "
263
+ "Omit for the default operator-visible launch where each Codex TUI runs its own first tick."
264
+ ),
265
+ )
266
+ start_parser.add_argument(
267
+ "--no-wake-visible-after-launch",
268
+ dest="wake_visible_after_launch",
269
+ action="store_false",
270
+ help=(
271
+ "Keep the post-launch wake disabled while preserving the normal visible launch."
272
+ ),
273
+ )
274
+ start_parser.add_argument(
275
+ "--auto-wake",
276
+ action=argparse.BooleanOptionalAction,
277
+ default=True,
278
+ help=(
279
+ "Run a session-scoped background wake loop so successor todos can be picked up "
280
+ "without a human sending `loopx multi-agent wake`. Use --no-auto-wake for full "
281
+ "manual takeover."
282
+ ),
283
+ )
284
+ start_parser.add_argument(
285
+ "--auto-wake-interval-seconds",
286
+ type=float,
287
+ default=45.0,
288
+ help=argparse.SUPPRESS,
289
+ )
290
+ start_parser.add_argument(
291
+ "--no-attach",
292
+ action="store_true",
293
+ help="With visible --execute, start tmux in the background instead of attaching.",
294
+ )
295
+ start_parser.add_argument(
296
+ "--attach",
297
+ action="store_true",
298
+ help=(
299
+ "With visible --execute, attach to tmux after launch and skip the default wake so "
300
+ "operator takeover happens first."
301
+ ),
302
+ )
303
+ start_parser.add_argument(
304
+ "--demo-run-id",
305
+ help="Optional public-safe suffix for the isolated goal id.",
306
+ )
307
+ start_parser.add_argument(
308
+ "--goal-id",
309
+ help=argparse.SUPPRESS,
310
+ )
311
+ start_parser.add_argument(
312
+ "--tracking-goal-id",
313
+ help=argparse.SUPPRESS,
314
+ )
315
+ start_parser.add_argument(
316
+ "--worker-loop-rounds",
317
+ type=int,
318
+ default=4,
319
+ help=argparse.SUPPRESS,
320
+ )
321
+ start_parser.add_argument(
322
+ "--configure-visible-worker-turn",
323
+ action="store_true",
324
+ help=argparse.SUPPRESS,
325
+ )
326
+ start_parser.add_argument(
327
+ "--session-name",
328
+ default="loopx-auto-research",
329
+ help="Public-safe tmux session name for visible lanes.",
330
+ )
331
+ start_parser.add_argument(
332
+ "--workspace",
333
+ help=(
334
+ "Directory where visible Codex lanes should start. "
335
+ "Omit to use ~/loopx-auto-research/<run>/visible-workspace."
336
+ ),
337
+ )
338
+ start_parser.add_argument(
339
+ "--create-workspace",
340
+ action="store_true",
341
+ help="Create --workspace when it does not already exist.",
342
+ )
343
+ start_parser.add_argument(
344
+ "--keep-workspace",
345
+ action="store_true",
346
+ help=argparse.SUPPRESS,
347
+ )
348
+ start_parser.add_argument("--cli-bin", default="loopx", help=argparse.SUPPRESS)
349
+ start_parser.add_argument("--codex-bin", default="codex", help=argparse.SUPPRESS)
350
+ start_parser.add_argument("--tmux-bin", default="tmux", help=argparse.SUPPRESS)
351
+ start_parser.add_argument(
352
+ "--reasoning-effort",
353
+ default="high",
354
+ help=argparse.SUPPRESS,
355
+ )
356
+ start_parser.add_argument(
357
+ "--launcher",
358
+ choices=["auto", "tmux"],
359
+ default="auto",
360
+ help=argparse.SUPPRESS,
361
+ )
362
+ start_parser.add_argument(
363
+ "--replace-existing",
364
+ action="store_true",
365
+ help=argparse.SUPPRESS,
366
+ )
367
+ start_parser.add_argument(
368
+ "--codex-trust-workspace",
369
+ action=argparse.BooleanOptionalAction,
370
+ default=None,
371
+ help=argparse.SUPPRESS,
372
+ )
373
+
374
+ frontier_parser = auto_research_sub.add_parser(
375
+ "frontier",
376
+ help="Render a per-agent decentralized research frontier from a public fixture or live LoopX state.",
377
+ )
378
+ add_subcommand_format(frontier_parser)
379
+ frontier_parser.add_argument(
380
+ "--fixture",
381
+ help="Path to a decentralized_auto_research_fixture_v0 JSON file.",
382
+ )
383
+ frontier_parser.add_argument(
384
+ "--goal-id",
385
+ help="Goal id for live LoopX quota/status input. Mutually exclusive with --fixture.",
386
+ )
387
+ frontier_parser.add_argument(
388
+ "--agent-id",
389
+ required=True,
390
+ help="Agent id whose runnable frontier should be projected.",
391
+ )
392
+
393
+ evidence_parser = auto_research_sub.add_parser(
394
+ "evidence",
395
+ help="Build public-safe research hypothesis/evidence records from metric evaluator outputs.",
396
+ )
397
+ add_subcommand_format(evidence_parser)
398
+ evidence_parser.add_argument("--contract", required=True, help="Path to research_contract_v0 JSON.")
399
+ evidence_parser.add_argument(
400
+ "--eval-result",
401
+ action="append",
402
+ required=True,
403
+ help="Path to a public-safe evaluator JSON result. Repeat for dev/holdout or retry evidence.",
404
+ )
405
+ evidence_parser.add_argument("--hypothesis-id", required=True)
406
+ evidence_parser.add_argument("--todo-id", required=True)
407
+ evidence_parser.add_argument("--agent-id", required=True)
408
+ evidence_parser.add_argument("--claimed-by", required=True)
409
+ evidence_parser.add_argument("--mechanism-family", required=True)
410
+ evidence_parser.add_argument("--hypothesis", required=True)
411
+ evidence_parser.add_argument("--parent-hypothesis-id")
412
+ evidence_parser.add_argument("--grounding-ref", action="append", default=[])
413
+ evidence_parser.add_argument("--novelty-audit-ref")
414
+ evidence_parser.add_argument("--branch-ref")
415
+ evidence_parser.add_argument("--attempt-start", type=int, default=1)
416
+
417
+ append_parser = auto_research_sub.add_parser(
418
+ "append-evidence",
419
+ help="Append an auto_research_evidence_packet_v0 into the LoopX rollout event log.",
420
+ )
421
+ add_subcommand_format(append_parser)
422
+ append_parser.add_argument("--packet", required=True, help="Path to auto_research_evidence_packet_v0 JSON.")
423
+ append_parser.add_argument(
424
+ "--dry-run",
425
+ action="store_true",
426
+ help="Preview rollout events without appending them.",
427
+ )
428
+ append_parser.add_argument(
429
+ "--output",
430
+ help="Write the append result JSON to this path without recording the path in LoopX state.",
431
+ )
432
+
433
+ decide_parser = auto_research_sub.add_parser(
434
+ "decide",
435
+ help="Record an evidence-bound terminal decision for one Auto Research hypothesis.",
436
+ )
437
+ add_subcommand_format(decide_parser)
438
+ decide_parser.add_argument("--goal-id", required=True)
439
+ decide_parser.add_argument("--hypothesis-id", required=True)
440
+ decide_parser.add_argument("--outcome", choices=["promoted", "retired"], required=True)
441
+ decide_parser.add_argument(
442
+ "--reason",
443
+ choices=[
444
+ "contradicted",
445
+ "duplicate",
446
+ "holdout_validated",
447
+ "operator_rejected",
448
+ "retry_exhausted",
449
+ "superseded",
450
+ ],
451
+ required=True,
452
+ )
453
+ decide_parser.add_argument("--agent-id", required=True)
454
+ decide_parser.add_argument("--evidence-ref", action="append", default=[])
455
+ decide_parser.add_argument(
456
+ "--execute",
457
+ action="store_true",
458
+ help="Append the terminal decision. Omit to preview the validated decision.",
459
+ )
460
+
461
+ review_parser = auto_research_sub.add_parser(
462
+ "review",
463
+ help="Record a review receipt bound to the current terminal decision and evidence graph revision.",
464
+ )
465
+ add_subcommand_format(review_parser)
466
+ review_parser.add_argument("--goal-id", required=True)
467
+ review_parser.add_argument("--hypothesis-id", required=True)
468
+ review_parser.add_argument("--reviewer-agent-id", required=True)
469
+ review_parser.add_argument(
470
+ "--verdict",
471
+ choices=["approve", "needs_more_evidence", "reject"],
472
+ required=True,
473
+ )
474
+ review_parser.add_argument("--evidence-ref", action="append", default=[])
475
+ review_parser.add_argument(
476
+ "--require-independent",
477
+ action="store_true",
478
+ help="Reject a reviewer who produced the hypothesis or terminal decision.",
479
+ )
480
+ review_parser.add_argument(
481
+ "--execute",
482
+ action="store_true",
483
+ help="Append the review receipt. Omit to preview the validated receipt.",
484
+ )
485
+
486
+ results_parser = auto_research_sub.add_parser(
487
+ "results",
488
+ help="Query current terminal decisions and review state by exact hypothesis id.",
489
+ )
490
+ add_subcommand_format(results_parser)
491
+ results_parser.add_argument("--goal-id", required=True)
492
+ results_parser.add_argument("--hypothesis-id")
493
+ results_parser.add_argument("--include-history", action="store_true")
494
+
495
+ project_results_parser = auto_research_sub.add_parser(
496
+ "project-results",
497
+ help="Project terminal Auto Research decisions into the existing Explore result log.",
498
+ )
499
+ add_subcommand_format(project_results_parser)
500
+ project_results_parser.add_argument("--goal-id", required=True)
501
+ project_results_parser.add_argument(
502
+ "--execute",
503
+ action="store_true",
504
+ help="Append the deterministic Explore events. Omit to preview.",
505
+ )
506
+
507
+ live_evidence_parser = auto_research_sub.add_parser(
508
+ "capture-live-evidence",
509
+ help="Build compact public-safe live Codex E2E evidence after lane-authored evidence is appended.",
510
+ )
511
+ add_subcommand_format(live_evidence_parser)
512
+ live_evidence_parser.add_argument(
513
+ "--packet",
514
+ required=True,
515
+ help="Path to the public auto_research_evidence_packet_v0 JSON produced by a visible lane.",
516
+ )
517
+ live_evidence_parser.add_argument(
518
+ "--append-result",
519
+ required=True,
520
+ help="Path to the JSON output from a real auto-research append-evidence run.",
521
+ )
522
+ live_evidence_parser.add_argument("--agent-id", required=True)
523
+ live_evidence_parser.add_argument(
524
+ "--lane-count",
525
+ type=int,
526
+ default=4,
527
+ help="Accepted visible lane count to record in the compact live evidence.",
528
+ )
529
+ live_evidence_parser.add_argument(
530
+ "--visible-lanes-accepted",
531
+ action="store_true",
532
+ help="Required acknowledgement that the visible lanes were launched and accepted.",
533
+ )
534
+ live_evidence_parser.add_argument(
535
+ "--output",
536
+ default=LIVE_CODEX_E2E_DEFAULT_OUTPUT,
537
+ help="Output path for --execute. The path is not recorded in the evidence payload.",
538
+ )
539
+ live_evidence_parser.add_argument(
540
+ "--execute",
541
+ action="store_true",
542
+ help="Write the compact evidence JSON to --output. Omit to preview the payload.",
543
+ )
544
+
545
+ worker_turn_parser = auto_research_sub.add_parser(
546
+ "worker-turn",
547
+ help="Run one LoopX-selected auto-research worker turn from quota/frontier.",
548
+ )
549
+ add_subcommand_format(worker_turn_parser)
550
+ worker_turn_parser.add_argument("--agent-id", required=True)
551
+ worker_turn_parser.add_argument(
552
+ "--goal-id",
553
+ default=AUTO_RESEARCH_DEFAULT_GOAL_ID,
554
+ help="Research goal id whose quota/frontier this worker should obey.",
555
+ )
556
+ worker_turn_parser.add_argument(
557
+ "--objective",
558
+ default=AUTO_RESEARCH_DEFAULT_OBJECTIVE,
559
+ help="Public-safe objective used by the built-in lightweight metric kernel.",
560
+ )
561
+ worker_turn_parser.add_argument(
562
+ "--output-dir",
563
+ default="auto_research_lightweight_kernel",
564
+ help=argparse.SUPPRESS,
565
+ )
566
+ worker_turn_parser.add_argument(
567
+ "--evidence-dir",
568
+ default=".local/auto-research-worker",
569
+ help="Local-only evidence output directory inside the worker workspace.",
570
+ )
571
+ worker_turn_parser.add_argument(
572
+ "--lane-count",
573
+ type=int,
574
+ default=1,
575
+ help="Visible lane count recorded when live evidence is captured.",
576
+ )
577
+ worker_turn_parser.add_argument(
578
+ "--visible-lanes-accepted",
579
+ action="store_true",
580
+ help="Acknowledge that the visible lanes were launched and accepted.",
581
+ )
582
+ worker_turn_parser.add_argument(
583
+ "--live-evidence-output",
584
+ default=LIVE_CODEX_E2E_DEFAULT_OUTPUT,
585
+ help="Local filename for compact public-safe live evidence.",
586
+ )
587
+ worker_turn_parser.add_argument(
588
+ "--complete-selected-todo",
589
+ action="store_true",
590
+ help="After a successful --execute turn, mark the selected LoopX todo done.",
591
+ )
592
+ worker_turn_parser.add_argument(
593
+ "--execute",
594
+ action="store_true",
595
+ help="Run the selected worker action. Omit to show the plan from quota/frontier.",
596
+ )
597
+
598
+ worker_loop_parser = auto_research_sub.add_parser(
599
+ "worker-loop",
600
+ help="Run repeated LoopX-selected auto-research worker turns for a visible lane set.",
601
+ )
602
+ add_subcommand_format(worker_loop_parser)
603
+ worker_loop_parser.add_argument(
604
+ "--agent-id",
605
+ action="append",
606
+ required=True,
607
+ help="Agent id to poll in loop order. Repeat for each visible worker lane.",
608
+ )
609
+ worker_loop_parser.add_argument(
610
+ "--goal-id",
611
+ default=AUTO_RESEARCH_DEFAULT_GOAL_ID,
612
+ help="Research goal id whose quota/frontier each worker should obey.",
613
+ )
614
+ worker_loop_parser.add_argument(
615
+ "--objective",
616
+ default=AUTO_RESEARCH_DEFAULT_OBJECTIVE,
617
+ help="Public-safe objective used by the built-in lightweight metric kernel.",
618
+ )
619
+ worker_loop_parser.add_argument(
620
+ "--output-dir",
621
+ default="auto_research_lightweight_kernel",
622
+ help=argparse.SUPPRESS,
623
+ )
624
+ worker_loop_parser.add_argument(
625
+ "--evidence-dir",
626
+ default=".local/auto-research-worker",
627
+ help="Local-only evidence output directory inside the worker workspace.",
628
+ )
629
+ worker_loop_parser.add_argument(
630
+ "--lane-count",
631
+ type=int,
632
+ help="Visible lane count recorded when live evidence is captured.",
633
+ )
634
+ worker_loop_parser.add_argument(
635
+ "--visible-lanes-accepted",
636
+ action="store_true",
637
+ help="Acknowledge that the visible lanes were launched and accepted.",
638
+ )
639
+ worker_loop_parser.add_argument(
640
+ "--live-evidence-output",
641
+ default=LIVE_CODEX_E2E_DEFAULT_OUTPUT,
642
+ help="Local filename for compact public-safe live evidence.",
643
+ )
644
+ worker_loop_parser.add_argument(
645
+ "--complete-selected-todo",
646
+ action="store_true",
647
+ help="After successful --execute turns, mark selected LoopX todos done.",
648
+ )
649
+ worker_loop_parser.add_argument(
650
+ "--max-rounds",
651
+ type=int,
652
+ default=4,
653
+ help="Maximum polling rounds across the agent list.",
654
+ )
655
+ worker_loop_parser.add_argument(
656
+ "--execute",
657
+ action="store_true",
658
+ help="Run each selected worker action. Omit to preview loop selection.",
659
+ )
660
+
661
+ demo_supervisor_parser = auto_research_sub.add_parser(
662
+ "demo-supervisor",
663
+ help="Plan a dry-run tmux/Codex-CLI supervisor for decentralized auto-research lanes.",
664
+ )
665
+ add_subcommand_format(demo_supervisor_parser)
666
+ demo_supervisor_parser.add_argument(
667
+ "--goal-id",
668
+ help=(
669
+ "Research goal id whose frontier each lane should inspect. "
670
+ "Omit to use a fresh demo-local goal surface."
671
+ ),
672
+ )
673
+ demo_supervisor_parser.add_argument(
674
+ "--demo-run-id",
675
+ help="Public-safe suffix for the generated demo goal id when --goal-id is omitted.",
676
+ )
677
+ demo_supervisor_parser.add_argument(
678
+ "--inherit-default-goal",
679
+ action="store_true",
680
+ help=f"Opt into the shared internal demo goal {AUTO_RESEARCH_DEFAULT_GOAL_ID}.",
681
+ )
682
+ demo_supervisor_parser.add_argument(
683
+ "--agent",
684
+ action="append",
685
+ default=[],
686
+ help=(
687
+ "Agent/lane pair as agent_id:lane_id. Repeat for each visible lane. "
688
+ "Omit to use the default LoopX auto-research demo lane set."
689
+ ),
690
+ )
691
+ demo_supervisor_parser.add_argument(
692
+ "--session-name",
693
+ default="loopx-auto-research",
694
+ help="Public-safe tmux session name for the generated dry-run script.",
695
+ )
696
+ demo_supervisor_parser.add_argument("--cli-bin", default="loopx", help="LoopX CLI executable name.")
697
+ demo_supervisor_parser.add_argument("--codex-bin", default="codex", help="Codex CLI executable name.")
698
+ demo_supervisor_parser.add_argument("--tmux-bin", default="tmux", help="tmux executable name.")
699
+ demo_supervisor_parser.add_argument(
700
+ "--reasoning-effort",
701
+ default="high",
702
+ help="Reasoning effort passed to visible Codex lanes through model_reasoning_effort.",
703
+ )
704
+ demo_supervisor_parser.add_argument(
705
+ "--language",
706
+ choices=["auto", "zh", "en"],
707
+ default="auto",
708
+ help="Human-readable output language for visible role panes.",
709
+ )
710
+ demo_supervisor_parser.add_argument(
711
+ "--execute",
712
+ action="store_true",
713
+ help=(
714
+ "Launch visible Codex CLI lanes in tmux. Omit for the default dry-run packet. "
715
+ "This only starts local visible terminals; LoopX writeback still happens through normal lane commands."
716
+ ),
717
+ )
718
+ demo_supervisor_parser.add_argument(
719
+ "--launcher",
720
+ choices=["auto", "tmux"],
721
+ default="auto",
722
+ help="Visible process launcher for --execute. auto currently resolves to tmux.",
723
+ )
724
+ demo_supervisor_parser.add_argument(
725
+ "--attach",
726
+ action="store_true",
727
+ help="After --execute with tmux, attach to the session. Terminal launcher opens visible windows directly.",
728
+ )
729
+ demo_supervisor_parser.add_argument(
730
+ "--replace-existing",
731
+ action="store_true",
732
+ help="With tmux launcher, kill an existing session with the same name before launching.",
733
+ )
734
+ demo_supervisor_parser.add_argument(
735
+ "--workspace",
736
+ help=(
737
+ "Directory where visible Codex lanes should start. Defaults to the current directory. "
738
+ "For demos, prefer an empty user-owned research workspace that shares LoopX state through "
739
+ "--registry/--runtime-root."
740
+ ),
741
+ )
742
+ demo_supervisor_parser.add_argument(
743
+ "--create-workspace",
744
+ action="store_true",
745
+ help="Create --workspace when it does not already exist.",
746
+ )
747
+ demo_supervisor_parser.add_argument(
748
+ "--codex-trust-workspace",
749
+ action=argparse.BooleanOptionalAction,
750
+ default=False,
751
+ help=(
752
+ "Pass a per-invocation Codex trust config for the selected visible workspace. "
753
+ "Default is off for generic supervisor launches."
754
+ ),
755
+ )
756
+
757
+ demo_e2e_parser = auto_research_sub.add_parser(
758
+ "demo-e2e",
759
+ help=(
760
+ "Run or preview the one-command multi-round lightweight research path and "
761
+ "launch visible Codex TUI lanes or a headless worker-loop proof."
762
+ ),
763
+ )
764
+ add_subcommand_format(demo_e2e_parser)
765
+ demo_e2e_parser.add_argument("--agent-id", required=True)
766
+ demo_e2e_parser.add_argument(
767
+ "--agent",
768
+ action="append",
769
+ default=[],
770
+ help=(
771
+ "Optional visible worker lane as agent_id:lane_id:role_id. "
772
+ "Omit to use the default four-role worker loop."
773
+ ),
774
+ )
775
+ demo_e2e_parser.add_argument(
776
+ "--goal-id",
777
+ help=(
778
+ "Research goal id for the demo evidence. "
779
+ "Omit to create a fresh isolated demo goal surface."
780
+ ),
781
+ )
782
+ demo_e2e_parser.add_argument(
783
+ "--demo-run-id",
784
+ help="Public-safe suffix for the generated demo goal id when --goal-id is omitted.",
785
+ )
786
+ demo_e2e_parser.add_argument(
787
+ "--inherit-default-goal",
788
+ action="store_true",
789
+ help=f"Opt into reusing the shared internal demo goal {AUTO_RESEARCH_DEFAULT_GOAL_ID}.",
790
+ )
791
+ demo_e2e_parser.add_argument(
792
+ "--tracking-goal-id",
793
+ help=(
794
+ "Optional parent/productization goal id for status writeback context. "
795
+ "Visible lanes still inspect --goal-id as the research frontier."
796
+ ),
797
+ )
798
+ demo_e2e_parser.add_argument(
799
+ "--objective",
800
+ default=AUTO_RESEARCH_DEFAULT_OBJECTIVE,
801
+ help="Compact public-safe research objective for the generated contract.",
802
+ )
803
+ demo_e2e_parser.add_argument(
804
+ "--language",
805
+ choices=["auto", "zh", "en"],
806
+ default="auto",
807
+ help="Human-readable output language for visible role panes.",
808
+ )
809
+ demo_e2e_parser.add_argument(
810
+ "--output-dir",
811
+ default="auto_research_lightweight_kernel",
812
+ help=argparse.SUPPRESS,
813
+ )
814
+ demo_e2e_parser.add_argument(
815
+ "--execute",
816
+ action="store_true",
817
+ help=(
818
+ "Seed a demo-local LoopX goal queue and, by default, launch visible Codex TUI lanes "
819
+ "that work the frontier from zero. Use --headless or --run-worker-loop for the "
820
+ "non-interactive worker-loop proof path."
821
+ ),
822
+ )
823
+ demo_e2e_parser.add_argument(
824
+ "--run-worker-loop",
825
+ action="store_true",
826
+ help=argparse.SUPPRESS,
827
+ )
828
+ demo_e2e_parser.add_argument(
829
+ "--worker-loop-rounds",
830
+ type=int,
831
+ default=4,
832
+ help="Maximum worker-loop rounds for --execute.",
833
+ )
834
+ demo_e2e_parser.add_argument(
835
+ "--launch-visible",
836
+ action="store_true",
837
+ help=(
838
+ "With --execute, explicitly launch the visible multi-lane supervisor. "
839
+ "This is the default unless --headless is set. "
840
+ "Visible panes alone do not make the multi-round kernel a live Codex E2E result."
841
+ ),
842
+ )
843
+ demo_e2e_parser.add_argument(
844
+ "--headless",
845
+ action="store_true",
846
+ help="With --execute, skip visible tmux/Codex panes and return JSON only.",
847
+ )
848
+ demo_e2e_parser.add_argument(
849
+ "--live-evidence",
850
+ help=(
851
+ "Path to compact public-safe live Codex lane evidence. "
852
+ "Raw transcripts are not read."
853
+ ),
854
+ )
855
+ demo_e2e_parser.add_argument(
856
+ "--visible-live-evidence-wait-seconds",
857
+ type=float,
858
+ default=30.0,
859
+ help=argparse.SUPPRESS,
860
+ )
861
+ demo_e2e_parser.add_argument(
862
+ "--configure-visible-worker-turn",
863
+ action="store_true",
864
+ help=argparse.SUPPRESS,
865
+ )
866
+ demo_e2e_parser.add_argument(
867
+ "--wake-visible-after-launch",
868
+ action="store_true",
869
+ help=(
870
+ "After starting visible tmux panes, broadcast the fixed pane-local A2A "
871
+ "wake prompt. Each pane still runs its own LoopX tick from state."
872
+ ),
873
+ )
874
+ demo_e2e_parser.add_argument(
875
+ "--auto-wake",
876
+ action=argparse.BooleanOptionalAction,
877
+ default=True,
878
+ help=(
879
+ "Run a session-scoped background wake loop for visible auto-research lanes. "
880
+ "Use --no-auto-wake for full manual takeover."
881
+ ),
882
+ )
883
+ demo_e2e_parser.add_argument(
884
+ "--auto-wake-interval-seconds",
885
+ type=float,
886
+ default=45.0,
887
+ help=argparse.SUPPRESS,
888
+ )
889
+ demo_e2e_parser.add_argument(
890
+ "--keep-workspace",
891
+ action="store_true",
892
+ help="Keep the temporary demo workspace after execution. The output payload still redacts its absolute path.",
893
+ )
894
+ demo_e2e_parser.add_argument(
895
+ "--session-name",
896
+ default="loopx-auto-research",
897
+ help="Public-safe tmux session name when --launch-visible is set.",
898
+ )
899
+ demo_e2e_parser.add_argument("--cli-bin", default="loopx", help="LoopX CLI executable name.")
900
+ demo_e2e_parser.add_argument("--codex-bin", default="codex", help="Codex CLI executable name.")
901
+ demo_e2e_parser.add_argument("--tmux-bin", default="tmux", help="tmux executable name.")
902
+ demo_e2e_parser.add_argument(
903
+ "--reasoning-effort",
904
+ default="high",
905
+ help="Reasoning effort passed to visible Codex lanes through model_reasoning_effort.",
906
+ )
907
+ demo_e2e_parser.add_argument(
908
+ "--launcher",
909
+ choices=["auto", "tmux"],
910
+ default="auto",
911
+ help="Visible process launcher for --launch-visible. auto currently resolves to tmux.",
912
+ )
913
+ demo_e2e_parser.add_argument(
914
+ "--attach",
915
+ action="store_true",
916
+ help="After visible launch with tmux, attach to the session. This is the default for --execute unless --no-attach is set.",
917
+ )
918
+ demo_e2e_parser.add_argument(
919
+ "--no-attach",
920
+ action="store_true",
921
+ help="With the default visible --execute launch, start tmux in the background instead of attaching.",
922
+ )
923
+ demo_e2e_parser.add_argument(
924
+ "--replace-existing",
925
+ action="store_true",
926
+ help="With tmux launcher, kill an existing session with the same name before launching.",
927
+ )
928
+ demo_e2e_parser.add_argument(
929
+ "--workspace",
930
+ help=(
931
+ "Directory where visible Codex lanes should start when --launch-visible is set. "
932
+ "Omit to use a demo-owned clean workspace."
933
+ ),
934
+ )
935
+ demo_e2e_parser.add_argument(
936
+ "--create-workspace",
937
+ action="store_true",
938
+ help="Create --workspace when it does not already exist.",
939
+ )
940
+ demo_e2e_parser.add_argument(
941
+ "--codex-trust-workspace",
942
+ action=argparse.BooleanOptionalAction,
943
+ default=None,
944
+ help=(
945
+ "Pass a per-invocation Codex trust config for the visible workspace. "
946
+ "Defaults on only for the demo-owned clean workspace."
947
+ ),
948
+ )
949
+
950
+
951
+ def _execute_auto_research_demo_supervisor(
952
+ payload: dict[str, object],
953
+ *,
954
+ registry_path: Path,
955
+ runtime_root_arg: str | None,
956
+ launcher: str,
957
+ tmux_bin: str,
958
+ cli_bin: str,
959
+ codex_bin: str,
960
+ attach: bool,
961
+ replace_existing: bool,
962
+ workspace: str | None,
963
+ create_workspace: bool,
964
+ codex_trust_workspace: bool,
965
+ auto_wake: bool = False,
966
+ auto_wake_interval_seconds: float = 45.0,
967
+ ) -> dict[str, object]:
968
+ registry = load_registry(registry_path)
969
+ runtime_root = resolve_runtime_root(registry, runtime_root_arg)
970
+ result, chosen, workspace_mode = execute_visible_multi_agent_launcher(
971
+ payload=payload,
972
+ registry=registry_path,
973
+ runtime_root=runtime_root,
974
+ requested_launcher=launcher,
975
+ tmux_bin=tmux_bin,
976
+ cli_bin=cli_bin,
977
+ codex_bin=codex_bin,
978
+ attach=attach,
979
+ replace_existing=replace_existing,
980
+ workspace=workspace,
981
+ create_workspace=create_workspace,
982
+ cwd=Path.cwd(),
983
+ codex_trust_workspace=codex_trust_workspace,
984
+ auto_wake=auto_wake,
985
+ auto_wake_interval_seconds=auto_wake_interval_seconds,
986
+ launch_result_schema="auto_research_demo_launch_result_v0",
987
+ lane_default="research-lane",
988
+ )
989
+ payload["mode"] = "executed_visible_launch"
990
+ payload["launch_result"] = result
991
+ boundary = payload.get("boundary")
992
+ if isinstance(boundary, dict):
993
+ boundary.update(
994
+ {
995
+ "dry_run_plan_only": False,
996
+ "starts_tmux": chosen == "tmux",
997
+ "opens_terminal": False,
998
+ "runs_codex": True,
999
+ "writes_loopx_state": False,
1000
+ "spends_loopx_quota": False,
1001
+ "external_service_call": False,
1002
+ "workspace_mode": workspace_mode,
1003
+ "workspace_write_scope": "selected_visible_workspace_only",
1004
+ "codex_trust_workspace": codex_trust_workspace,
1005
+ "codex_trust_scope": (
1006
+ "persisted_selected_workspace_and_git_root"
1007
+ if codex_trust_workspace
1008
+ else "native_codex_trust_prompt"
1009
+ ),
1010
+ "shared_state_route": "LOOPX_REGISTRY_and_LOOPX_RUNTIME_ROOT",
1011
+ "shared_goal_surface": True,
1012
+ "all_lane_workspace_isolation": False,
1013
+ "mutation_isolation_policy": (
1014
+ "only mutating research-executor attempts require a claimed git worktree "
1015
+ "or equivalent execution boundary"
1016
+ ),
1017
+ }
1018
+ )
1019
+ return payload
1020
+
1021
+
1022
+ def handle_auto_research_command(
1023
+ args: argparse.Namespace,
1024
+ *,
1025
+ registry_path: Path,
1026
+ runtime_root_arg: str | None,
1027
+ output_format: FormatSelector,
1028
+ print_payload: PrintPayload,
1029
+ ) -> int:
1030
+ try:
1031
+ if args.auto_research_command == "contract":
1032
+ payload = build_auto_research_user_contract(
1033
+ args.open_question,
1034
+ max_todos=args.max_todos,
1035
+ output_language=args.language,
1036
+ preset_id=args.preset,
1037
+ )
1038
+ elif args.auto_research_command == "start":
1039
+ preset_id = normalize_auto_research_preset_id(args.preset)
1040
+ launch_visible = bool(args.execute and not args.headless)
1041
+ visible_policy = resolve_visible_launch_policy(
1042
+ args,
1043
+ launch_visible=launch_visible,
1044
+ default_wake_allowed=False,
1045
+ default_attach_allowed=launch_visible,
1046
+ attach_wake_conflict_message=(
1047
+ "--attach cannot be combined with --wake-visible-after-launch; "
1048
+ "choose operator takeover (--attach) or visible role wake (--no-attach)"
1049
+ ),
1050
+ )
1051
+ goal_id, goal_surface_mode = _resolve_demo_goal_surface(
1052
+ goal_id=args.goal_id,
1053
+ demo_run_id=args.demo_run_id,
1054
+ inherit_default_goal=False,
1055
+ )
1056
+ output_language = infer_auto_research_output_language(
1057
+ args.open_question,
1058
+ output_language=args.language,
1059
+ )
1060
+
1061
+ def append_start_evidence(packet_path: str) -> dict[str, object]:
1062
+ return _append_auto_research_rollout_events(
1063
+ packet_path=packet_path,
1064
+ registry_path=registry_path,
1065
+ runtime_root_arg=runtime_root_arg,
1066
+ dry_run=False,
1067
+ )
1068
+
1069
+ visible_launcher: Callable[[dict[str, object], Path, str | None, Path], dict[str, object]] | None = None
1070
+ visible_wake: Callable[[str, list[str]], dict[str, object]] | None = None
1071
+ codex_trust_visible_workspace = resolve_codex_trust_workspace(
1072
+ args,
1073
+ launch_visible=visible_policy.launch_visible,
1074
+ default=True,
1075
+ )
1076
+ prepared_preset_workspace: dict[str, object] | None = None
1077
+
1078
+ def start_workspace_policy(_default_workspace: Path) -> tuple[str | None, bool, bool]:
1079
+ nonlocal prepared_preset_workspace
1080
+ default_start_workspace = args.workspace is None
1081
+ workspace = (
1082
+ _default_auto_research_start_workspace(goal_id)
1083
+ if default_start_workspace
1084
+ else args.workspace
1085
+ )
1086
+ create_workspace = True if default_start_workspace else args.create_workspace
1087
+ if preset_id == AUTO_RESEARCH_KNN_DEMO_PRESET_ID and workspace:
1088
+ prepared_preset_workspace = materialize_knn_demo_workspace(
1089
+ workspace,
1090
+ goal_id=goal_id,
1091
+ )
1092
+ create_workspace = True
1093
+ return (
1094
+ workspace,
1095
+ create_workspace,
1096
+ codex_trust_visible_workspace,
1097
+ )
1098
+
1099
+ visible_launcher = make_visible_launcher_callback(
1100
+ launch_visible=visible_policy.launch_visible,
1101
+ launch_executor=_execute_auto_research_demo_supervisor,
1102
+ launcher=args.launcher,
1103
+ tmux_bin=args.tmux_bin,
1104
+ cli_bin=args.cli_bin,
1105
+ codex_bin=args.codex_bin,
1106
+ attach=visible_policy.attach,
1107
+ replace_existing=args.replace_existing,
1108
+ workspace_policy=start_workspace_policy,
1109
+ auto_wake=bool(visible_policy.launch_visible and args.auto_wake),
1110
+ auto_wake_interval_seconds=args.auto_wake_interval_seconds,
1111
+ )
1112
+
1113
+ if visible_policy.launch_visible:
1114
+ visible_wake = make_visible_wake_callback(tmux_bin=args.tmux_bin)
1115
+
1116
+ payload = run_auto_research_demo_e2e(
1117
+ agent_id=AUTO_RESEARCH_START_AGENT_ID,
1118
+ goal_id=goal_id,
1119
+ goal_surface_mode=goal_surface_mode,
1120
+ tracking_goal_id=args.tracking_goal_id,
1121
+ preset_id=preset_id,
1122
+ objective=args.open_question,
1123
+ output_dir="auto_research_lightweight_kernel",
1124
+ execute=args.execute,
1125
+ run_worker_loop=bool(args.execute and args.headless),
1126
+ worker_loop_rounds=args.worker_loop_rounds,
1127
+ configure_visible_worker_turn=args.configure_visible_worker_turn,
1128
+ launch_visible=visible_policy.launch_visible,
1129
+ keep_workspace=args.keep_workspace,
1130
+ registry_path=registry_path,
1131
+ runtime_root_arg=runtime_root_arg,
1132
+ session_name=args.session_name,
1133
+ cli_bin=args.cli_bin,
1134
+ codex_bin=args.codex_bin,
1135
+ tmux_bin=args.tmux_bin,
1136
+ reasoning_effort=args.reasoning_effort,
1137
+ output_language=output_language,
1138
+ live_evidence_path=None,
1139
+ append_evidence=append_start_evidence,
1140
+ visible_launcher=visible_launcher,
1141
+ visible_wake=visible_wake,
1142
+ wake_visible_after_launch=visible_policy.wake_visible_after_launch,
1143
+ )
1144
+ if prepared_preset_workspace:
1145
+ payload["preset_workspace"] = prepared_preset_workspace
1146
+ elif args.auto_research_command == "frontier":
1147
+ if bool(args.fixture) == bool(args.goal_id):
1148
+ raise ValueError(f"auto-research {args.auto_research_command} requires exactly one of --fixture or --goal-id")
1149
+ if args.fixture:
1150
+ fixture = load_auto_research_fixture(args.fixture)
1151
+ payload = build_auto_research_projection(
1152
+ fixture,
1153
+ agent_id=args.agent_id,
1154
+ )
1155
+ else:
1156
+ status_payload = collect_status(
1157
+ registry_path=registry_path,
1158
+ runtime_root_override=runtime_root_arg,
1159
+ scan_roots=[Path.cwd()],
1160
+ limit=5,
1161
+ goal_id=args.goal_id,
1162
+ )
1163
+ quota_payload = build_quota_should_run(
1164
+ status_payload,
1165
+ goal_id=args.goal_id,
1166
+ agent_id=args.agent_id,
1167
+ )
1168
+ registry = load_registry(registry_path)
1169
+ runtime_root = resolve_runtime_root(registry, runtime_root_arg)
1170
+ rollout_events = load_rollout_events(
1171
+ rollout_event_log_path(runtime_root, args.goal_id)
1172
+ )
1173
+ payload = build_live_auto_research_projection(
1174
+ goal_id=args.goal_id,
1175
+ agent_id=args.agent_id,
1176
+ quota_payload=quota_payload,
1177
+ rollout_events=rollout_events,
1178
+ )
1179
+ elif args.auto_research_command == "evidence":
1180
+ payload = load_auto_research_evidence_packet_inputs(
1181
+ contract_path=args.contract,
1182
+ eval_result_paths=args.eval_result,
1183
+ hypothesis_id=args.hypothesis_id,
1184
+ todo_id=args.todo_id,
1185
+ agent_id=args.agent_id,
1186
+ claimed_by=args.claimed_by,
1187
+ mechanism_family=args.mechanism_family,
1188
+ hypothesis=args.hypothesis,
1189
+ parent_hypothesis_id=args.parent_hypothesis_id,
1190
+ grounding_refs=args.grounding_ref,
1191
+ novelty_audit_ref=args.novelty_audit_ref,
1192
+ branch_ref=args.branch_ref,
1193
+ attempt_start=args.attempt_start,
1194
+ )
1195
+ elif args.auto_research_command == "append-evidence":
1196
+ payload = _append_auto_research_rollout_events(
1197
+ packet_path=args.packet,
1198
+ registry_path=registry_path,
1199
+ runtime_root_arg=runtime_root_arg,
1200
+ dry_run=args.dry_run,
1201
+ )
1202
+ if args.output:
1203
+ output_path = Path(args.output).expanduser()
1204
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1205
+ output_path.write_text(
1206
+ json.dumps(payload, indent=2, sort_keys=True) + "\n",
1207
+ encoding="utf-8",
1208
+ )
1209
+ elif args.auto_research_command == "decide":
1210
+ payload = decide_terminal_result(
1211
+ registry_path=registry_path,
1212
+ runtime_root_arg=runtime_root_arg,
1213
+ goal_id=args.goal_id,
1214
+ hypothesis_id=args.hypothesis_id,
1215
+ outcome=args.outcome,
1216
+ reason=args.reason,
1217
+ decided_by=args.agent_id,
1218
+ evidence_refs=args.evidence_ref,
1219
+ dry_run=not args.execute,
1220
+ )
1221
+ elif args.auto_research_command == "review":
1222
+ payload = review_terminal_result(
1223
+ registry_path=registry_path,
1224
+ runtime_root_arg=runtime_root_arg,
1225
+ goal_id=args.goal_id,
1226
+ hypothesis_id=args.hypothesis_id,
1227
+ reviewer_agent_id=args.reviewer_agent_id,
1228
+ verdict=args.verdict,
1229
+ evidence_refs=args.evidence_ref,
1230
+ require_independent=args.require_independent,
1231
+ dry_run=not args.execute,
1232
+ )
1233
+ elif args.auto_research_command == "results":
1234
+ payload = query_terminal_results(
1235
+ registry_path=registry_path,
1236
+ runtime_root_arg=runtime_root_arg,
1237
+ goal_id=args.goal_id,
1238
+ hypothesis_id=args.hypothesis_id,
1239
+ include_history=args.include_history,
1240
+ )
1241
+ elif args.auto_research_command == "project-results":
1242
+ payload = project_terminal_results(
1243
+ registry_path=registry_path,
1244
+ runtime_root_arg=runtime_root_arg,
1245
+ goal_id=args.goal_id,
1246
+ dry_run=not args.execute,
1247
+ )
1248
+ elif args.auto_research_command == "capture-live-evidence":
1249
+ payload = capture_live_codex_e2e_evidence(
1250
+ packet_path=args.packet,
1251
+ append_result_path=args.append_result,
1252
+ agent_id=args.agent_id,
1253
+ lane_count=args.lane_count,
1254
+ visible_lanes_accepted=args.visible_lanes_accepted,
1255
+ )
1256
+ if args.execute:
1257
+ output_path = Path(args.output).expanduser()
1258
+ output_path.parent.mkdir(parents=True, exist_ok=True)
1259
+ output_path.write_text(
1260
+ json.dumps(payload, indent=2, sort_keys=True) + "\n",
1261
+ encoding="utf-8",
1262
+ )
1263
+ elif args.auto_research_command == "worker-turn":
1264
+ def append_worker_evidence(packet_path: str) -> dict[str, object]:
1265
+ return _append_auto_research_rollout_events(
1266
+ packet_path=packet_path,
1267
+ registry_path=registry_path,
1268
+ runtime_root_arg=runtime_root_arg,
1269
+ dry_run=False,
1270
+ )
1271
+
1272
+ payload = run_auto_research_worker_turn(
1273
+ registry_path=registry_path,
1274
+ runtime_root_arg=runtime_root_arg,
1275
+ goal_id=args.goal_id,
1276
+ agent_id=args.agent_id,
1277
+ objective=args.objective,
1278
+ workspace=Path.cwd(),
1279
+ output_dir=args.output_dir,
1280
+ evidence_dir=args.evidence_dir,
1281
+ execute=args.execute,
1282
+ append_evidence=append_worker_evidence if args.execute else None,
1283
+ lane_count=args.lane_count,
1284
+ visible_lanes_accepted=args.visible_lanes_accepted,
1285
+ live_evidence_output=args.live_evidence_output,
1286
+ complete_selected_todo=args.complete_selected_todo,
1287
+ )
1288
+ elif args.auto_research_command == "worker-loop":
1289
+ def append_loop_evidence(packet_path: str) -> dict[str, object]:
1290
+ return _append_auto_research_rollout_events(
1291
+ packet_path=packet_path,
1292
+ registry_path=registry_path,
1293
+ runtime_root_arg=runtime_root_arg,
1294
+ dry_run=False,
1295
+ )
1296
+
1297
+ payload = run_auto_research_worker_loop(
1298
+ registry_path=registry_path,
1299
+ runtime_root_arg=runtime_root_arg,
1300
+ goal_id=args.goal_id,
1301
+ agent_ids=args.agent_id,
1302
+ objective=args.objective,
1303
+ workspace=Path.cwd(),
1304
+ output_dir=args.output_dir,
1305
+ evidence_dir=args.evidence_dir,
1306
+ execute=args.execute,
1307
+ append_evidence=append_loop_evidence if args.execute else None,
1308
+ lane_count=args.lane_count,
1309
+ visible_lanes_accepted=args.visible_lanes_accepted,
1310
+ live_evidence_output=args.live_evidence_output,
1311
+ complete_selected_todo=args.complete_selected_todo,
1312
+ max_rounds=args.max_rounds,
1313
+ )
1314
+ elif args.auto_research_command == "demo-supervisor":
1315
+ goal_id, goal_surface_mode = _resolve_demo_goal_surface(
1316
+ goal_id=args.goal_id,
1317
+ demo_run_id=args.demo_run_id,
1318
+ inherit_default_goal=args.inherit_default_goal,
1319
+ )
1320
+ payload = build_auto_research_demo_supervisor_plan(
1321
+ goal_id=goal_id,
1322
+ agent_specs=args.agent,
1323
+ session_name=args.session_name,
1324
+ cli_bin=args.cli_bin,
1325
+ codex_bin=args.codex_bin,
1326
+ tmux_bin=args.tmux_bin,
1327
+ reasoning_effort=args.reasoning_effort,
1328
+ output_language=infer_auto_research_output_language(
1329
+ "",
1330
+ output_language=args.language,
1331
+ ),
1332
+ )
1333
+ payload["goal_surface_route"] = {
1334
+ "schema_version": "auto_research_demo_goal_surface_v0",
1335
+ "mode": goal_surface_mode,
1336
+ "goal_id": goal_id,
1337
+ "fresh_by_default": goal_surface_mode == "fresh_demo_goal",
1338
+ "reuses_default_internal_goal": goal_id == AUTO_RESEARCH_DEFAULT_GOAL_ID,
1339
+ "default_internal_goal_id": AUTO_RESEARCH_DEFAULT_GOAL_ID,
1340
+ }
1341
+ if args.execute:
1342
+ payload = _execute_auto_research_demo_supervisor(
1343
+ payload,
1344
+ registry_path=registry_path,
1345
+ runtime_root_arg=runtime_root_arg,
1346
+ launcher=args.launcher,
1347
+ tmux_bin=args.tmux_bin,
1348
+ cli_bin=args.cli_bin,
1349
+ codex_bin=args.codex_bin,
1350
+ attach=args.attach,
1351
+ replace_existing=args.replace_existing,
1352
+ workspace=args.workspace,
1353
+ create_workspace=args.create_workspace,
1354
+ codex_trust_workspace=args.codex_trust_workspace,
1355
+ )
1356
+ elif args.auto_research_command == "demo-e2e":
1357
+ if args.headless and args.launch_visible:
1358
+ raise ValueError("--headless cannot be combined with --launch-visible")
1359
+ goal_id, goal_surface_mode = _resolve_demo_goal_surface(
1360
+ goal_id=args.goal_id,
1361
+ demo_run_id=args.demo_run_id,
1362
+ inherit_default_goal=args.inherit_default_goal,
1363
+ )
1364
+
1365
+ def append_demo_e2e_evidence(packet_path: str) -> dict[str, object]:
1366
+ return _append_auto_research_rollout_events(
1367
+ packet_path=packet_path,
1368
+ registry_path=registry_path,
1369
+ runtime_root_arg=runtime_root_arg,
1370
+ dry_run=False,
1371
+ )
1372
+
1373
+ visible_launcher: Callable[[dict[str, object], Path, str | None, Path], dict[str, object]] | None = None
1374
+ visible_wake: Callable[[str, list[str]], dict[str, object]] | None = None
1375
+ auto_visible_launch = bool(args.execute and not args.headless)
1376
+ launch_visible = bool(args.launch_visible or auto_visible_launch)
1377
+ visible_policy = resolve_visible_launch_policy(
1378
+ args,
1379
+ launch_visible=launch_visible,
1380
+ default_wake_allowed=auto_visible_launch,
1381
+ default_attach_allowed=auto_visible_launch,
1382
+ attach_wake_conflict_message=(
1383
+ "--wake-visible-after-launch cannot be combined with --attach; "
1384
+ "wake evidence must be recorded before operator takeover"
1385
+ ),
1386
+ )
1387
+ def demo_workspace_policy(default_workspace: Path) -> tuple[str | None, bool, bool]:
1388
+ demo_owned_workspace = args.workspace is None
1389
+ return (
1390
+ str(default_workspace / "visible-user-workspace")
1391
+ if demo_owned_workspace
1392
+ else args.workspace,
1393
+ True if demo_owned_workspace else args.create_workspace,
1394
+ resolve_codex_trust_workspace(
1395
+ args,
1396
+ launch_visible=visible_policy.launch_visible,
1397
+ default=demo_owned_workspace,
1398
+ ),
1399
+ )
1400
+
1401
+ visible_launcher = make_visible_launcher_callback(
1402
+ launch_visible=visible_policy.launch_visible,
1403
+ launch_executor=_execute_auto_research_demo_supervisor,
1404
+ launcher=args.launcher,
1405
+ tmux_bin=args.tmux_bin,
1406
+ cli_bin=args.cli_bin,
1407
+ codex_bin=args.codex_bin,
1408
+ attach=visible_policy.attach,
1409
+ replace_existing=args.replace_existing,
1410
+ workspace_policy=demo_workspace_policy,
1411
+ auto_wake=bool(visible_policy.launch_visible and args.auto_wake),
1412
+ auto_wake_interval_seconds=args.auto_wake_interval_seconds,
1413
+ )
1414
+
1415
+ if visible_policy.launch_visible:
1416
+ visible_wake = make_visible_wake_callback(tmux_bin=args.tmux_bin)
1417
+
1418
+ run_hidden_worker_loop = bool(args.execute and (args.headless or args.run_worker_loop))
1419
+ payload = run_auto_research_demo_e2e(
1420
+ agent_id=args.agent_id,
1421
+ goal_id=goal_id,
1422
+ goal_surface_mode=goal_surface_mode,
1423
+ agent_specs=args.agent,
1424
+ tracking_goal_id=args.tracking_goal_id,
1425
+ objective=args.objective,
1426
+ output_dir=args.output_dir,
1427
+ execute=args.execute,
1428
+ run_worker_loop=run_hidden_worker_loop,
1429
+ worker_loop_rounds=args.worker_loop_rounds,
1430
+ configure_visible_worker_turn=args.configure_visible_worker_turn,
1431
+ launch_visible=visible_policy.launch_visible,
1432
+ keep_workspace=args.keep_workspace,
1433
+ registry_path=registry_path,
1434
+ runtime_root_arg=runtime_root_arg,
1435
+ session_name=args.session_name,
1436
+ cli_bin=args.cli_bin,
1437
+ codex_bin=args.codex_bin,
1438
+ tmux_bin=args.tmux_bin,
1439
+ reasoning_effort=args.reasoning_effort,
1440
+ output_language=infer_auto_research_output_language(
1441
+ args.objective,
1442
+ output_language=args.language,
1443
+ ),
1444
+ live_evidence_path=args.live_evidence,
1445
+ append_evidence=append_demo_e2e_evidence,
1446
+ visible_launcher=visible_launcher,
1447
+ visible_wake=visible_wake,
1448
+ wake_visible_after_launch=visible_policy.wake_visible_after_launch,
1449
+ visible_live_evidence_wait_seconds=args.visible_live_evidence_wait_seconds,
1450
+ )
1451
+ else:
1452
+ raise ValueError(
1453
+ "auto-research requires the `contract`, `frontier`, `evidence`, "
1454
+ "`append-evidence`, `decide`, `review`, `results`, "
1455
+ "`project-results`, `capture-live-evidence`, "
1456
+ "`worker-turn`, `worker-loop`, `demo-supervisor`, `demo-e2e`, "
1457
+ "or `start` subcommand"
1458
+ )
1459
+ except Exception as exc:
1460
+ error_code, public_error = _public_auto_research_error(exc)
1461
+ payload = {
1462
+ "ok": False,
1463
+ "mode": "auto-research",
1464
+ "error_code": error_code,
1465
+ "error": public_error,
1466
+ }
1467
+ print_payload(payload, output_format(args, "auto_research_format"), render_auto_research_markdown)
1468
+ return 0 if payload.get("ok") else 1