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,1153 @@
1
+ from __future__ import annotations
2
+
3
+ import shlex
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ from .bootstrap import default_goal_id
8
+ from .control_plane.scheduler.execution_context import (
9
+ GENERIC_CLI_OUTER_CONTROLLER_SCHEDULER_CONTEXT,
10
+ render_scheduler_execution_args,
11
+ )
12
+ from .control_plane.todos.contract import normalize_required_capabilities
13
+ from .install_contract import NO_CLONE_INSTALL_URL
14
+
15
+ DEFAULT_HANDOFF_OBJECTIVE = "<OBJECTIVE_FROM_GOAL_DOC>"
16
+ DEFAULT_HANDOFF_DOMAIN = "<DOMAIN>"
17
+ DEFAULT_HANDOFF_ADAPTER_KIND = "read_only_project_map_v0"
18
+ DEFAULT_HANDOFF_ADAPTER_STATUS = "connected-read-only"
19
+ DEFAULT_HANDOFF_NEXT_PROBE = "(omit --next-probe until a read-only pre-tick command exists)"
20
+ SHARED_GLOBAL_REGISTRY = '"$HOME/.codex/loopx/registry.global.json"'
21
+ CODEX_CLI_VISIBLE_SCHEDULER_CONTEXT = {
22
+ "host_surface": "codex_cli",
23
+ "scheduler_owner": "agent_cli_loop",
24
+ "execution_mode": "interactive",
25
+ }
26
+
27
+
28
+ def shell_arg(value: str) -> str:
29
+ return shlex.quote(value)
30
+
31
+
32
+ def shell_arg_or_placeholder(value: str) -> str:
33
+ text = str(value)
34
+ if text.startswith("<") and text.endswith(">"):
35
+ return text
36
+ return shell_arg(text)
37
+
38
+
39
+ def render_available_capability_args(values: Any) -> str:
40
+ return "".join(
41
+ f" --available-capability {shell_arg(capability)}"
42
+ for capability in normalize_required_capabilities(values)
43
+ )
44
+
45
+
46
+ def render_cli_preflight(*, cli_bin: str = "loopx") -> str:
47
+ cli_bin_arg = shell_arg(cli_bin)
48
+ return f"""export PATH="$HOME/.local/bin:$PATH"
49
+ install_script="$HOME/loopx/scripts/install-local.sh"
50
+ if ! command -v {cli_bin_arg} >/dev/null 2>&1; then
51
+ if [ -x "$install_script" ]; then
52
+ "$install_script"
53
+ export PATH="$HOME/.local/bin:$PATH"
54
+ else
55
+ echo "loopx is not on PATH; clone the LoopX repo and run scripts/install-local.sh" >&2
56
+ exit 1
57
+ fi
58
+ fi
59
+ {cli_bin_arg} doctor >/dev/null"""
60
+
61
+
62
+ def render_codex_cli_no_clone_preflight(
63
+ *,
64
+ cli_bin: str = "loopx",
65
+ doctor_agent_type: str | None = None,
66
+ ) -> str:
67
+ cli_bin_arg = shell_arg(cli_bin)
68
+ doctor_agent_arg = (
69
+ f" --agent-type {shell_arg(doctor_agent_type)}"
70
+ if doctor_agent_type
71
+ else ""
72
+ )
73
+ return f"""export PATH="$HOME/.local/bin:$PATH"
74
+ if ! command -v {cli_bin_arg} >/dev/null 2>&1; then
75
+ if command -v curl >/dev/null 2>&1; then
76
+ curl -fsSL {NO_CLONE_INSTALL_URL} | bash
77
+ export PATH="$HOME/.local/bin:$PATH"
78
+ else
79
+ echo "loopx is not on PATH and curl is unavailable; install curl or use a contributor clone with scripts/install-local.sh" >&2
80
+ exit 1
81
+ fi
82
+ fi
83
+ {cli_bin_arg} doctor{doctor_agent_arg} >/dev/null"""
84
+
85
+
86
+ def render_quota_guard_command(
87
+ goal_id: str,
88
+ *,
89
+ cli_bin: str = "loopx",
90
+ agent_id: str | None = None,
91
+ available_capabilities: Any = None,
92
+ runtime_profile: str | None = None,
93
+ scheduler_execution_context: dict[str, Any] | None = None,
94
+ heartbeat_turn_receipt: bool = False,
95
+ ) -> str:
96
+ agent_arg = f" --agent-id {shell_arg(agent_id)}" if agent_id else ""
97
+ capability_args = render_available_capability_args(available_capabilities)
98
+ scheduler_args = render_scheduler_execution_args(
99
+ runtime_profile=runtime_profile,
100
+ scheduler_execution_context=scheduler_execution_context,
101
+ )
102
+ turn_arg = (
103
+ ' --turn-instance-id "${LOOPX_TURN:?}"'
104
+ if heartbeat_turn_receipt
105
+ else ""
106
+ )
107
+ return (
108
+ f"{shell_arg(cli_bin)} --format json "
109
+ f"--registry {SHARED_GLOBAL_REGISTRY} "
110
+ f"quota should-run --goal-id {shell_arg(goal_id)}{agent_arg}"
111
+ f"{capability_args}{scheduler_args}{turn_arg}"
112
+ )
113
+
114
+
115
+ def render_quota_spend_command(
116
+ goal_id: str,
117
+ *,
118
+ source: str = "adapter",
119
+ cli_bin: str = "loopx",
120
+ agent_id: str | None = None,
121
+ available_capabilities: Any = None,
122
+ ) -> str:
123
+ agent_arg = f" --agent-id {shell_arg(agent_id)}" if agent_id else ""
124
+ capability_args = render_available_capability_args(available_capabilities)
125
+ return (
126
+ f"{shell_arg(cli_bin)} "
127
+ f"--registry {SHARED_GLOBAL_REGISTRY} "
128
+ "quota spend-slot "
129
+ f"--goal-id {shell_arg(goal_id)} "
130
+ f"--slots 1 --source {shell_arg(source)} --execute{agent_arg}{capability_args}"
131
+ )
132
+
133
+
134
+ def render_refresh_state_command(
135
+ goal_id: str,
136
+ *,
137
+ cli_bin: str = "loopx",
138
+ project: str | None = None,
139
+ agent_id: str | None = None,
140
+ progress_scope: str | None = None,
141
+ classification: str | None = None,
142
+ delivery_batch_scale: str | None = None,
143
+ delivery_outcome: str | None = None,
144
+ ) -> str:
145
+ project_arg = f" --project {shell_arg(project)}" if project else ""
146
+ agent_arg = f" --agent-id {shell_arg(agent_id)}" if agent_id else ""
147
+ scope_arg = f" --progress-scope {shell_arg(progress_scope)}" if progress_scope else ""
148
+ classification_arg = (
149
+ f" --classification {shell_arg_or_placeholder(classification)}"
150
+ if classification
151
+ else ""
152
+ )
153
+ scale_arg = (
154
+ f" --delivery-batch-scale {shell_arg_or_placeholder(delivery_batch_scale)}"
155
+ if delivery_batch_scale
156
+ else ""
157
+ )
158
+ outcome_arg = (
159
+ f" --delivery-outcome {shell_arg_or_placeholder(delivery_outcome)}"
160
+ if delivery_outcome
161
+ else ""
162
+ )
163
+ return (
164
+ f"{shell_arg(cli_bin)} refresh-state --goal-id {shell_arg(goal_id)}"
165
+ f"{project_arg}{classification_arg}{scale_arg}{outcome_arg}{agent_arg}{scope_arg}"
166
+ )
167
+
168
+
169
+ def render_accountable_progress_refresh_command(
170
+ goal_id: str,
171
+ *,
172
+ cli_bin: str = "loopx",
173
+ agent_id: str | None = None,
174
+ progress_scope: str | None = None,
175
+ classification: str = "<PUBLIC_SAFE_PROGRESS_CLASSIFICATION>",
176
+ delivery_batch_scale: str = "<ACTUAL_DELIVERY_BATCH_SCALE>",
177
+ delivery_outcome: str = "<ACTUAL_DELIVERY_OUTCOME>",
178
+ ) -> str:
179
+ return render_refresh_state_command(
180
+ goal_id,
181
+ cli_bin=cli_bin,
182
+ agent_id=agent_id,
183
+ progress_scope=progress_scope,
184
+ classification=classification,
185
+ delivery_batch_scale=delivery_batch_scale,
186
+ delivery_outcome=delivery_outcome,
187
+ )
188
+
189
+
190
+ def render_heartbeat_prompt_command(
191
+ goal_id: str,
192
+ *,
193
+ cli_bin: str = "loopx",
194
+ agent_id: str | None = None,
195
+ agent_scope: str = "Codex CLI /goal visible TUI loop",
196
+ body: str = "thin",
197
+ available_capabilities: Any = None,
198
+ runtime_profile: str | None = None,
199
+ scheduler_execution_context: dict[str, Any] | None = None,
200
+ visible_goal_host: str | None = None,
201
+ ) -> str:
202
+ agent_arg = f" --agent-id {shell_arg(agent_id)}" if agent_id else ""
203
+ scope_arg = f" --agent-scope {shell_arg(agent_scope)}" if agent_id else ""
204
+ capability_args = render_available_capability_args(available_capabilities)
205
+ scheduler_args = render_scheduler_execution_args(
206
+ runtime_profile=runtime_profile,
207
+ scheduler_execution_context=scheduler_execution_context,
208
+ )
209
+ visible_goal_arg = (
210
+ f" --visible-goal-host {shell_arg(visible_goal_host)}"
211
+ if visible_goal_host
212
+ else ""
213
+ )
214
+ return (
215
+ f"{shell_arg(cli_bin)} heartbeat-prompt --{shell_arg(body)} "
216
+ f"--goal-id {shell_arg(goal_id)}{agent_arg}{scope_arg}{capability_args}"
217
+ f"{scheduler_args}{visible_goal_arg}"
218
+ )
219
+
220
+
221
+ def render_heartbeat_prompt_json_command(
222
+ goal_id: str,
223
+ *,
224
+ cli_bin: str = "loopx",
225
+ agent_id: str | None = None,
226
+ agent_scope: str = "Codex CLI /goal visible TUI loop",
227
+ body: str = "thin",
228
+ available_capabilities: Any = None,
229
+ runtime_profile: str | None = None,
230
+ scheduler_execution_context: dict[str, Any] | None = None,
231
+ visible_goal_host: str | None = None,
232
+ ) -> str:
233
+ agent_arg = f" --agent-id {shell_arg(agent_id)}" if agent_id else ""
234
+ scope_arg = f" --agent-scope {shell_arg(agent_scope)}" if agent_id else ""
235
+ capability_args = render_available_capability_args(available_capabilities)
236
+ scheduler_args = render_scheduler_execution_args(
237
+ runtime_profile=runtime_profile,
238
+ scheduler_execution_context=scheduler_execution_context,
239
+ )
240
+ visible_goal_arg = (
241
+ f" --visible-goal-host {shell_arg(visible_goal_host)}"
242
+ if visible_goal_host
243
+ else ""
244
+ )
245
+ return (
246
+ f"{shell_arg(cli_bin)} --format json heartbeat-prompt --{shell_arg(body)} "
247
+ f"--goal-id {shell_arg(goal_id)}{agent_arg}{scope_arg}{capability_args}"
248
+ f"{scheduler_args}{visible_goal_arg}"
249
+ )
250
+
251
+
252
+ def render_connect_command(
253
+ *,
254
+ project: str,
255
+ goal_doc: str,
256
+ goal_id: str,
257
+ objective: str,
258
+ domain: str,
259
+ adapter_kind: str,
260
+ adapter_status: str,
261
+ next_probe: str | None,
262
+ spawn_allowed: bool,
263
+ allowed_domains: list[str],
264
+ write_scope: list[str],
265
+ cli_bin: str = "loopx",
266
+ ) -> str:
267
+ lines = [
268
+ f"cd {shell_arg(project)}",
269
+ f"{shell_arg(cli_bin)} connect \\",
270
+ f" --goal-id {shell_arg(goal_id)} \\",
271
+ f" --objective {shell_arg(objective)} \\",
272
+ f" --domain {shell_arg(domain)} \\",
273
+ f" --goal-doc {shell_arg(goal_doc)} \\",
274
+ f" --adapter-kind {shell_arg(adapter_kind)} \\",
275
+ f" --adapter-status {shell_arg(adapter_status)}",
276
+ ]
277
+ if next_probe:
278
+ lines[-1] += " \\"
279
+ lines.append(f" --next-probe {shell_arg(next_probe)}")
280
+ if spawn_allowed:
281
+ lines[-1] += " \\"
282
+ lines.append(" --spawn-allowed")
283
+ for allowed_domain in allowed_domains:
284
+ lines[-1] += " \\"
285
+ lines.append(f" --allowed-domain {shell_arg(allowed_domain)}")
286
+ for scope in write_scope:
287
+ lines[-1] += " \\"
288
+ lines.append(f" --write-scope {shell_arg(scope)}")
289
+ return "\n".join(lines)
290
+
291
+
292
+ def build_new_project_prompt(
293
+ *,
294
+ project: Path,
295
+ goal_doc: Path,
296
+ goal_id: str | None,
297
+ objective: str | None,
298
+ domain: str | None,
299
+ adapter_kind: str,
300
+ adapter_status: str,
301
+ next_probe: str | None,
302
+ spawn_allowed: bool,
303
+ allowed_domains: list[str] | None,
304
+ write_scope: list[str] | None,
305
+ ) -> dict[str, Any]:
306
+ project_text = str(project.expanduser())
307
+ goal_doc_text = str(goal_doc.expanduser())
308
+ resolved_goal_id = goal_id or default_goal_id(project)
309
+ resolved_objective = objective or DEFAULT_HANDOFF_OBJECTIVE
310
+ resolved_domain = domain or DEFAULT_HANDOFF_DOMAIN
311
+ resolved_next_probe = next_probe or DEFAULT_HANDOFF_NEXT_PROBE
312
+ allowed_domains = allowed_domains or []
313
+ write_scope = write_scope or []
314
+ connect_command = render_connect_command(
315
+ project=project_text,
316
+ goal_doc=goal_doc_text,
317
+ goal_id=resolved_goal_id,
318
+ objective=resolved_objective,
319
+ domain=resolved_domain,
320
+ adapter_kind=adapter_kind,
321
+ adapter_status=adapter_status,
322
+ next_probe=next_probe,
323
+ spawn_allowed=spawn_allowed,
324
+ allowed_domains=allowed_domains,
325
+ write_scope=write_scope,
326
+ cli_bin="loopx",
327
+ )
328
+ quota_guard_command = render_quota_guard_command(
329
+ resolved_goal_id,
330
+ scheduler_execution_context=(
331
+ GENERIC_CLI_OUTER_CONTROLLER_SCHEDULER_CONTEXT
332
+ ),
333
+ )
334
+ quota_spend_command = render_quota_spend_command(resolved_goal_id)
335
+ refresh_command = render_refresh_state_command(resolved_goal_id)
336
+ progress_refresh_command = render_accountable_progress_refresh_command(
337
+ resolved_goal_id
338
+ )
339
+ prompt = render_prompt_text(
340
+ project=project_text,
341
+ goal_doc=goal_doc_text,
342
+ goal_id=resolved_goal_id,
343
+ objective=resolved_objective,
344
+ domain=resolved_domain,
345
+ adapter_kind=adapter_kind,
346
+ adapter_status=adapter_status,
347
+ next_probe=resolved_next_probe,
348
+ cli_preflight=render_cli_preflight(),
349
+ connect_command=connect_command,
350
+ quota_guard_command=quota_guard_command,
351
+ quota_spend_command=quota_spend_command,
352
+ refresh_command=refresh_command,
353
+ progress_refresh_command=progress_refresh_command,
354
+ cli_bin="loopx",
355
+ spawn_allowed=spawn_allowed,
356
+ allowed_domains=allowed_domains,
357
+ write_scope=write_scope,
358
+ )
359
+ return {
360
+ "ok": True,
361
+ "project": project_text,
362
+ "goal_doc": goal_doc_text,
363
+ "goal_id": resolved_goal_id,
364
+ "objective": resolved_objective,
365
+ "domain": resolved_domain,
366
+ "adapter_kind": adapter_kind,
367
+ "adapter_status": adapter_status,
368
+ "next_probe": resolved_next_probe,
369
+ "spawn_allowed": spawn_allowed,
370
+ "allowed_domains": allowed_domains,
371
+ "write_scope": write_scope,
372
+ "connect_command": connect_command,
373
+ "quota_guard_command": quota_guard_command,
374
+ "quota_spend_command": quota_spend_command,
375
+ "refresh_command": refresh_command,
376
+ "progress_refresh_command": progress_refresh_command,
377
+ "cli_preflight": render_cli_preflight(),
378
+ "prompt": prompt,
379
+ }
380
+
381
+
382
+ def render_codex_cli_bootstrap_connect_command(
383
+ *,
384
+ project: str,
385
+ goal_id: str,
386
+ cli_bin: str,
387
+ ) -> str:
388
+ return "\n".join(
389
+ [
390
+ f"cd {shell_arg(project)}",
391
+ f"{shell_arg(cli_bin)} bootstrap \\",
392
+ " --project . \\",
393
+ f" --goal-id {shell_arg(goal_id)} \\",
394
+ f" --adapter-kind {shell_arg(DEFAULT_HANDOFF_ADAPTER_KIND)} \\",
395
+ f" --adapter-status {shell_arg(DEFAULT_HANDOFF_ADAPTER_STATUS)}",
396
+ ]
397
+ )
398
+
399
+
400
+ def build_codex_cli_bootstrap_message(
401
+ *,
402
+ project: Path,
403
+ goal_id: str | None,
404
+ agent_id: str | None,
405
+ cli_bin: str,
406
+ ) -> dict[str, Any]:
407
+ resolved_project = str(project.expanduser())
408
+ resolved_goal_id = goal_id or default_goal_id(project)
409
+ connect_command = render_codex_cli_bootstrap_connect_command(
410
+ project=resolved_project,
411
+ goal_id=resolved_goal_id,
412
+ cli_bin=cli_bin,
413
+ )
414
+ quota_guard_command = render_quota_guard_command(
415
+ resolved_goal_id,
416
+ cli_bin=cli_bin,
417
+ agent_id=agent_id,
418
+ scheduler_execution_context=CODEX_CLI_VISIBLE_SCHEDULER_CONTEXT,
419
+ )
420
+ quota_spend_command = render_quota_spend_command(
421
+ resolved_goal_id,
422
+ source="heartbeat",
423
+ cli_bin=cli_bin,
424
+ agent_id=agent_id,
425
+ )
426
+ heartbeat_prompt_command = render_heartbeat_prompt_command(
427
+ resolved_goal_id,
428
+ cli_bin=cli_bin,
429
+ agent_id=agent_id,
430
+ scheduler_execution_context=CODEX_CLI_VISIBLE_SCHEDULER_CONTEXT,
431
+ )
432
+ heartbeat_prompt_json_command = render_heartbeat_prompt_json_command(
433
+ resolved_goal_id,
434
+ cli_bin=cli_bin,
435
+ agent_id=agent_id,
436
+ scheduler_execution_context=CODEX_CLI_VISIBLE_SCHEDULER_CONTEXT,
437
+ )
438
+ install_repair_command = render_codex_cli_no_clone_preflight(cli_bin=cli_bin)
439
+ refresh_command = render_refresh_state_command(
440
+ resolved_goal_id,
441
+ cli_bin=cli_bin,
442
+ agent_id=agent_id,
443
+ progress_scope="agent_lane" if agent_id else None,
444
+ )
445
+ progress_refresh_command = render_accountable_progress_refresh_command(
446
+ resolved_goal_id,
447
+ cli_bin=cli_bin,
448
+ agent_id=agent_id,
449
+ progress_scope="agent_lane" if agent_id else None,
450
+ )
451
+ first_run_validation_checklist = [
452
+ f"{cli_bin} doctor passed after no-clone install repair or existing install",
453
+ "repo bootstrap/connect completed conservatively or a concrete install/connect blocker was shown",
454
+ f"thin heartbeat task_body generated from {cli_bin} heartbeat-prompt --thin, not hand-written",
455
+ "host loop surface activated from the thin task_body: Codex CLI /goal or Codex App heartbeat automation initially every 3 minutes, then following quota scheduler_hint",
456
+ "setup was not reported complete from registry/quota identity alone; missing host-loop mutation was reported as a concrete gate",
457
+ "quota/status guard checked with the registered agent id when available after bootstrap/connect",
458
+ "current goal, concrete user gate or none, top todos, and next safe action shown in the TUI",
459
+ "no raw Codex transcripts, session files, credentials, private paths, stdout, or stderr persisted",
460
+ ]
461
+ message = render_codex_cli_bootstrap_message_text(
462
+ project=resolved_project,
463
+ goal_id=resolved_goal_id,
464
+ agent_id=agent_id,
465
+ cli_preflight=install_repair_command,
466
+ existing_goal_probe_command=quota_guard_command,
467
+ connect_command=connect_command,
468
+ heartbeat_prompt_json_command=heartbeat_prompt_json_command,
469
+ heartbeat_prompt_command=heartbeat_prompt_command,
470
+ quota_guard_command=quota_guard_command,
471
+ refresh_command=refresh_command,
472
+ progress_refresh_command=progress_refresh_command,
473
+ quota_spend_command=quota_spend_command,
474
+ first_run_validation_checklist=first_run_validation_checklist,
475
+ )
476
+ return {
477
+ "ok": True,
478
+ "schema_version": "codex_cli_bootstrap_message_v1",
479
+ "invocation_mode": "codex_cli_setup_then_goal_mode",
480
+ "project": resolved_project,
481
+ "goal_id": resolved_goal_id,
482
+ "agent_id": agent_id,
483
+ "cli_bin": cli_bin,
484
+ "install_repair_command": install_repair_command,
485
+ "existing_goal_probe_command": quota_guard_command,
486
+ "connect_command": connect_command,
487
+ "heartbeat_prompt_command": heartbeat_prompt_command,
488
+ "heartbeat_prompt_json_command": heartbeat_prompt_json_command,
489
+ "codex_cli_goal_prefix": "/goal ",
490
+ "codex_app_loop_surface": "heartbeat automation task_body",
491
+ "codex_app_default_heartbeat_cadence": "initially 3 minutes, then follow quota scheduler_hint",
492
+ "quota_guard_command": quota_guard_command,
493
+ "refresh_command": refresh_command,
494
+ "progress_refresh_command": progress_refresh_command,
495
+ "quota_spend_command": quota_spend_command,
496
+ "first_run_validation_checklist": first_run_validation_checklist,
497
+ "message": message,
498
+ }
499
+
500
+
501
+ def build_codex_cli_tui_bootstrap_smoke_bundle(
502
+ *,
503
+ project: Path,
504
+ goal_id: str | None,
505
+ agent_id: str | None,
506
+ cli_bin: str,
507
+ ) -> dict[str, Any]:
508
+ bootstrap = build_codex_cli_bootstrap_message(
509
+ project=project,
510
+ goal_id=goal_id,
511
+ agent_id=agent_id,
512
+ cli_bin=cli_bin,
513
+ )
514
+ resolved_project = str(bootstrap["project"])
515
+ resolved_goal_id = str(bootstrap["goal_id"])
516
+ agent_arg = f" --agent-id {shell_arg(agent_id)}" if agent_id else ""
517
+ message_only_command = (
518
+ f"{shell_arg(cli_bin)} codex-cli-bootstrap-message "
519
+ f"--project {shell_arg(resolved_project)} "
520
+ f"--goal-id {shell_arg(resolved_goal_id)}{agent_arg} --message-only"
521
+ )
522
+ review_packet_command = (
523
+ f"{shell_arg(cli_bin)} codex-cli-bootstrap-message "
524
+ f"--project {shell_arg(resolved_project)} "
525
+ f"--goal-id {shell_arg(resolved_goal_id)}{agent_arg}"
526
+ )
527
+ boundary = {
528
+ "runs_codex": False,
529
+ "reads_raw_transcripts": False,
530
+ "reads_session_files": False,
531
+ "reads_credentials": False,
532
+ "mutates_codex_session": False,
533
+ "spends_loopx_quota": False,
534
+ "requires_loopx_repo_clone": False,
535
+ }
536
+ validation_checklist = [
537
+ "archive installer works from a temporary GitHub-style tarball or existing install",
538
+ "message-only command prints only the setup paste block, not the Markdown review packet",
539
+ "paste block includes no-clone install repair, project bootstrap/connect, thin heartbeat generation, loop activation, and quota guard",
540
+ "accountable progress refresh then quota spend remain later post-delivery commands inside the paste block, not setup or smoke side effects",
541
+ "no raw Codex transcripts, session files, credentials, stdout, stderr, or private paths are read",
542
+ ]
543
+ return {
544
+ "ok": True,
545
+ "schema_version": "codex_cli_tui_bootstrap_smoke_bundle_v0",
546
+ "project": resolved_project,
547
+ "goal_id": resolved_goal_id,
548
+ "agent_id": agent_id,
549
+ "cli_bin": cli_bin,
550
+ "install_repair_command": bootstrap["install_repair_command"],
551
+ "review_packet_command": review_packet_command,
552
+ "message_only_command": message_only_command,
553
+ "heartbeat_prompt_command": bootstrap["heartbeat_prompt_command"],
554
+ "heartbeat_prompt_json_command": bootstrap["heartbeat_prompt_json_command"],
555
+ "quota_guard_command": bootstrap["quota_guard_command"],
556
+ "refresh_command": bootstrap["refresh_command"],
557
+ "progress_refresh_command": bootstrap["progress_refresh_command"],
558
+ "quota_spend_command": bootstrap["quota_spend_command"],
559
+ "validation_checklist": validation_checklist,
560
+ "boundary": boundary,
561
+ }
562
+
563
+
564
+ def build_codex_cli_exec_handoff(
565
+ *,
566
+ project: Path,
567
+ goal_id: str | None,
568
+ agent_id: str | None,
569
+ cli_bin: str,
570
+ codex_bin: str,
571
+ ) -> dict[str, Any]:
572
+ bootstrap = build_codex_cli_bootstrap_message(
573
+ project=project,
574
+ goal_id=goal_id,
575
+ agent_id=agent_id,
576
+ cli_bin=cli_bin,
577
+ )
578
+ resolved_project = str(project.expanduser())
579
+ resolved_goal_id = str(bootstrap["goal_id"])
580
+ agent_arg = f" --agent-id {shell_arg(agent_id)}" if agent_id else ""
581
+ message_only_command = (
582
+ f"{shell_arg(cli_bin)} codex-cli-bootstrap-message "
583
+ f"--project {shell_arg(resolved_project)} "
584
+ f"--goal-id {shell_arg(resolved_goal_id)}{agent_arg} --message-only"
585
+ )
586
+ return {
587
+ "ok": True,
588
+ "schema_version": "codex_cli_exec_handoff_v0",
589
+ "mode": "headless_fallback_disabled_for_goal_mode_bootstrap",
590
+ "primary_experience": "codex_cli_tui_goal_bootstrap",
591
+ "project": resolved_project,
592
+ "goal_id": resolved_goal_id,
593
+ "agent_id": agent_id,
594
+ "cli_bin": cli_bin,
595
+ "codex_bin": codex_bin,
596
+ "disabled_reason": (
597
+ "Default Codex CLI LoopX bootstrap must stay visible in the TUI; "
598
+ "headless codex exec handoff is disabled to avoid accidental hidden execution."
599
+ ),
600
+ "session_probe_command": f"{shell_arg(cli_bin)} codex-cli-session-probe --codex-bin {shell_arg(codex_bin)}",
601
+ "quota_guard_command": bootstrap["quota_guard_command"],
602
+ "progress_refresh_command": bootstrap["progress_refresh_command"],
603
+ "refresh_command": bootstrap["refresh_command"],
604
+ "quota_spend_command": bootstrap["quota_spend_command"],
605
+ "heartbeat_prompt_json_command": bootstrap["heartbeat_prompt_json_command"],
606
+ "message_only_command": message_only_command,
607
+ "handoff_command": "",
608
+ "boundary": {
609
+ "runs_codex": False,
610
+ "reads_raw_transcripts": False,
611
+ "reads_credentials": False,
612
+ "reads_session_files": False,
613
+ "mutates_codex_session": False,
614
+ "spends_loopx_quota": False,
615
+ "headless_execution_disabled": True,
616
+ "provides_executable_headless_command": False,
617
+ },
618
+ }
619
+
620
+
621
+ def render_codex_cli_bootstrap_message_text(
622
+ *,
623
+ project: str,
624
+ goal_id: str,
625
+ agent_id: str | None,
626
+ cli_preflight: str,
627
+ existing_goal_probe_command: str,
628
+ connect_command: str,
629
+ heartbeat_prompt_json_command: str,
630
+ heartbeat_prompt_command: str,
631
+ quota_guard_command: str,
632
+ refresh_command: str,
633
+ progress_refresh_command: str,
634
+ quota_spend_command: str,
635
+ first_run_validation_checklist: list[str],
636
+ ) -> str:
637
+ agent_line = f"Use registered LoopX agent id `{agent_id}` when claiming or spending." if agent_id else (
638
+ "If this project has registered agents, inspect the registry and use the correct registered agent id before claiming todos."
639
+ )
640
+ checklist = "\n".join(f"- {item}" for item in first_run_validation_checklist)
641
+ return f"""Install and connect LoopX for this repo from this same Codex CLI TUI session.
642
+
643
+ Goal: one-message setup, then loop activation. Keep this TUI as the visible
644
+ place where I can watch, steer, review, and take over. Do not use hidden
645
+ headless `codex exec` for this bootstrap path.
646
+
647
+ This first message is the setup/bootstrap instruction, not the reusable
648
+ heartbeat prompt. Complete the setup in order: install or repair LoopX
649
+ if needed; probe whether this goal already exists in the shared global
650
+ registry; only bootstrap/connect this project when the goal is absent; then
651
+ configure the current loop surface from the generated thin heartbeat prompt.
652
+ For Codex CLI, set the current TUI goal to `/goal ` plus the thin `task_body`.
653
+ For Codex App, set or refresh the heartbeat automation to start at 3 minutes
654
+ with that same thin `task_body`, then follow quota `scheduler_hint` for
655
+ backoff. If the current surface cannot be mutated from this session, show the
656
+ exact pasteable `/goal` or automation body and report that as a concrete user
657
+ gate; do not claim setup success.
658
+
659
+ Project: `{project}`
660
+ Goal id: `{goal_id}`
661
+ {agent_line}
662
+
663
+ Success criteria for this first setup turn:
664
+ - I should not need to inspect registry paths, runtime roots, JSON payloads, or
665
+ hidden session files.
666
+ - If LoopX is already installed and this goal is already present in the shared
667
+ global registry, reuse the existing `source_registry` route and do not
668
+ duplicate bootstrap from this worktree.
669
+ - Configure the loop target after bootstrap: Codex CLI `/goal <thin task_body>`
670
+ or Codex App heartbeat automation starting at 3 minutes with
671
+ `<thin task_body>`, then follow quota `scheduler_hint`.
672
+ - Do not claim setup success from registry/quota identity alone. Setup is
673
+ complete only when the host loop surface is active, or when you report the
674
+ exact host-tool gate that prevented setting Codex CLI `/goal` or creating the
675
+ Codex App heartbeat automation.
676
+ - Show me the current goal id, concrete user gate if any, top user todo if any,
677
+ top agent todo, and next safe action.
678
+ - Do not do longer delivery work in the setup turn unless I explicitly ask; the
679
+ configured thin loop owns later quota/spend delivery turns.
680
+
681
+ 1. Ensure the LoopX CLI works. Prefer the no-clone GitHub archive
682
+ installer; do not ask me to clone the LoopX repo just to try the first
683
+ run:
684
+
685
+ ```bash
686
+ {cli_preflight}
687
+ ```
688
+
689
+ 2. Before bootstrap/connect, probe the shared global registry for this goal:
690
+
691
+ ```bash
692
+ {existing_goal_probe_command}
693
+ ```
694
+
695
+ If this command returns a known goal, even with a normal delivery gate or
696
+ workspace guard, treat the goal as already connected and reuse the existing
697
+ global route/source_registry. In an independent peer-agent worktree, do not
698
+ run `loopx bootstrap` for the same `goal_id`; that can create a route collision
699
+ between the primary checkout and the worktree. Only run bootstrap when the
700
+ probe clearly says the goal is absent from the registered quota plan.
701
+
702
+ 3. If the goal is absent and this repo is not connected to LoopX yet, connect
703
+ it conservatively:
704
+
705
+ ```bash
706
+ {connect_command}
707
+ ```
708
+
709
+ If the connect output includes onboarding candidate todos, summarize them in
710
+ this TUI and ask me which ones to accept before starting autonomous delivery.
711
+
712
+ 4. Generate the thin loop prompt after route reuse or bootstrap/connect, not before. Do not
713
+ hand-write or copy an old heartbeat body:
714
+
715
+ ```bash
716
+ {heartbeat_prompt_json_command}
717
+ ```
718
+
719
+ Read `task_body` from the JSON result. Then configure the current surface:
720
+ - Codex CLI TUI: set the current goal to `/goal ` followed by that `task_body`.
721
+ - Codex App: create or update the heartbeat automation to start at 3 minutes
722
+ with that `task_body`, then follow quota `scheduler_hint`. If this session
723
+ cannot mutate Codex App automations, report that exact gate and do not say
724
+ LoopX automation is enabled.
725
+
726
+ For review, the Markdown form is:
727
+
728
+ ```bash
729
+ {heartbeat_prompt_command}
730
+ ```
731
+
732
+ 5. After install/connect and loop activation, run the quota/status guard for
733
+ the first control-plane snapshot:
734
+
735
+ ```bash
736
+ {quota_guard_command}
737
+ ```
738
+
739
+ Follow `interaction_contract` exactly:
740
+ - If `user_channel.action_required=true` or open user todos exist, ask only the
741
+ concrete user gate or todo payload.
742
+ - If `workspace_guard` blocks delivery, move to an independent worktree and
743
+ rerun the same guard before editing.
744
+ - If delivery is allowed, choose one runnable agent todo after a short steering
745
+ audit, preferably a current-agent claimed advancement todo.
746
+
747
+ 6. Report the current goal/gate/todo/next-action snapshot in this TUI. Stop
748
+ after setup unless I explicitly asked for delivery in this same turn. Do not
749
+ store raw Codex transcripts, credentials, private paths, raw logs, or
750
+ production artifacts in public docs or LoopX state.
751
+
752
+ 7. Before writeback, use this transcript-free validation checklist:
753
+
754
+ {checklist}
755
+
756
+ 8. After setup writeback, refresh state if needed. Do not spend quota for a
757
+ setup-only turn. The configured thin loop spends only after a later validated
758
+ delivery writeback. If I explicitly asked you to do delivery in this same turn
759
+ and you completed a validated delivery segment, replace all three placeholders
760
+ with this turn's actual validated classification, batch scale, and outcome.
761
+ Never default or upgrade them to `multi_surface` / `outcome_progress`. Then write
762
+ one accountable progress refresh and spend exactly once against that record:
763
+
764
+ ```bash
765
+ {progress_refresh_command}
766
+ {quota_spend_command}
767
+ ```
768
+
769
+ If the dashboard or controller needs another update after spend, run the plain
770
+ state-only refresh below. It is quota-neutral and must not carry a delivery
771
+ outcome:
772
+
773
+ ```bash
774
+ {refresh_command}
775
+ ```
776
+
777
+ Do not append another accountable progress refresh after spend; it would become
778
+ a new unspent delivery record.
779
+
780
+ End with changed files, validation result, current gate/todo state, and next
781
+ safe action. Later automation may add visible steering turns to this session
782
+ only after public-safe visible proof, runtime idle evidence, a fresh guard, and
783
+ explicit execution bounds. Keep optional automation checks such as
784
+ local-driver-plan or visible-session-proof as follow-up diagnostics, not
785
+ first-run prerequisites.
786
+ """
787
+
788
+ def render_prompt_text(
789
+ *,
790
+ project: str,
791
+ goal_doc: str,
792
+ goal_id: str,
793
+ objective: str,
794
+ domain: str,
795
+ adapter_kind: str,
796
+ adapter_status: str,
797
+ next_probe: str,
798
+ cli_preflight: str,
799
+ connect_command: str,
800
+ quota_guard_command: str,
801
+ quota_spend_command: str,
802
+ refresh_command: str,
803
+ progress_refresh_command: str,
804
+ cli_bin: str,
805
+ spawn_allowed: bool,
806
+ allowed_domains: list[str],
807
+ write_scope: list[str],
808
+ ) -> str:
809
+ spawn_note = "本项目初始不需要主控拆 sub-agent;除非目标文档另有授权,先保持单 controller read-only 接入。"
810
+ if spawn_allowed:
811
+ spawn_note = (
812
+ "本项目允许主控拆 sub-agent;子 agent 只能进入已声明 allowed-domain,"
813
+ "写入范围只能落在已声明 write-scope。"
814
+ )
815
+ allowed_domains_text = ", ".join(allowed_domains) if allowed_domains else "(none)"
816
+ write_scope_text = ", ".join(write_scope) if write_scope else "(none)"
817
+ return f"""我有一个新项目要接入 LoopX。
818
+
819
+ 项目文件夹:
820
+ {project}
821
+
822
+ 项目目标文档:
823
+ {goal_doc}
824
+
825
+ 请你按下面步骤推进,不要停在方案讨论;如果信息缺失,先从目标文档和项目结构中做保守抽取,并在最后说明假设。
826
+ 重要:`{cli_bin} connect` 默认会做一次快速 onboarding scan,基于 git status、最近 commit、顶层项目信号生成候选 agent todo。
827
+ 接入后不要直接开始 delivery;先把候选 todo 展示给我,并问我两件事:
828
+ 1. 接受、编辑或拒绝哪些候选 agent todo;
829
+ 2. 是否允许你从接受的 todo 开始自主推进。
830
+
831
+ 0. 先确认当前 shell 能调用 LoopX CLI;如果提示 `loopx` 不在 PATH,运行本机安装脚本再继续:
832
+
833
+ ```bash
834
+ {cli_preflight}
835
+ ```
836
+
837
+ 1. 再只读检查项目文件夹和目标文档,抽取:
838
+ - stable goal id;
839
+ - 一句话 objective;
840
+ - domain;
841
+ - authority sources;
842
+ - work clusters;
843
+ - validation surfaces;
844
+ - private/public boundary;
845
+ - 第一个 recommended_action。
846
+ 2. 用这些初始参数作为默认值;如果目标文档给出更好的命名或边界,可以修正:
847
+ - stable goal id: `{goal_id}`
848
+ - objective: `{objective}`
849
+ - domain: `{domain}`
850
+ - adapter_kind: `{adapter_kind}`
851
+ - adapter_status: `{adapter_status}`
852
+ - goal_doc: `{goal_doc}`
853
+ - next_probe: `{next_probe}`
854
+ - spawn_allowed: `{spawn_allowed}`
855
+ - allowed_domains: `{allowed_domains_text}`
856
+ - write_scope: `{write_scope_text}`
857
+ 3. 运行 LoopX 接入命令:
858
+
859
+ ```bash
860
+ {connect_command}
861
+ ```
862
+
863
+ 4. 确认 `.loopx/registry.json` 和 `.codex/goals/{goal_id}/ACTIVE_GOAL_STATE.md` 已创建或更新。
864
+ 阅读输出里的 `Onboarding Scan`、`Proposed Onboarding Candidates`、`Accept Candidate Commands`
865
+ 和 `Autonomy Choice`。不要让用户手动执行这些命令;你应当用中文简要解释候选 todo,
866
+ 然后询问用户:
867
+ - 接受哪些编号,是否需要改写;
868
+ - 是否 `autonomous=yes`,允许你在 quota guard 通过后开始执行第一个接受的 agent todo。
869
+ 如果用户接受候选 todo,用输出里的 `{cli_bin} todo add ...` 命令写入 agent todo;
870
+ 如果用户允许自主推进,先运行 quota guard,再执行第一个已接受 agent todo。
871
+ 如果用户不允许自主推进,只写入接受的 todo 并运行 `{refresh_command}`,
872
+ 然后停下来汇报。
873
+ 如果目标状态包含私有证据,把 `.loopx/` 和 `.codex/goals/` 加入该项目 `.gitignore`。
874
+ `{cli_bin} connect` 默认会同步到共享全局 registry;不要手动编辑其他项目的 registry。
875
+ 接入后检查 registry 里的 `execution_profile`:它是本项目后续 heartbeat / adapter 的执行画像。
876
+ 默认 cadence 是 `bounded_progress_segment`,连续小步达到阈值后,下一轮必须扩展到
877
+ `minimum_scale` 并包含 `must_include` 里的真实 artifact、targeted validation、state writeback;
878
+ 如果做不到,先报 blocker,不 append quota spend。
879
+ 5. 在任何 heartbeat、scheduled tick、long-running adapter 或自主 delivery 前,先问 compute guard:
880
+
881
+ ```bash
882
+ {quota_guard_command}
883
+ ```
884
+
885
+ 如果返回 `state=operator_gate`,把它当成人/控制器交互,而不是安静 skip:优先读取 payload 里的
886
+ `gate_prompt`、`operator_question`、`recommended_action`、`next_handoff_condition`、`missing_gates`、
887
+ `user_todo_summary` 和 `agent_todo_summary`,用中文主动告诉用户当前卡在哪个 gate、期望怎样回复;
888
+ 同时把 `agent_todo_summary` 当作项目 agent 自己的安全后续清单。不要执行任何
889
+ `agent_command`、adapter work、write-control、生产动作或该 gated action。
890
+ 如果同一个未决 gate 最近已经问过,且返回 `safe_bypass_allowed=true`,该 gate 只阻塞被 gate 覆盖的
891
+ delivery path;可以从 active state / Priority Stack 里选择一个不依赖该 gate 的 bounded 只读分析、
892
+ steering、文档或 P0/P1 工作。若实际完成 safe-bypass 工作,仍需验证、写回进展,并 append 一次
893
+ quota spend。
894
+ 如果 payload 返回 `notify_user_on_open_todo=true`,把开放 user todo 当作 blocker-push,而不是
895
+ 静默 skip:用中文最多列 3 个开放项和期望回复格式,并且本轮不做 delivery、不 append quota spend,
896
+ 除非同一个 blocker 最近已经问过。
897
+ 无论 `should_run` 是 true 还是 false,都先看 `execution_obligation`、
898
+ `effective_action`、`recovery_delivery_allowed`、`safe_bypass_kind` 和
899
+ `heartbeat_recommendation`。`heartbeat_recommendation.notify` 只是用户通知策略,
900
+ 不是执行 gate;如果 `execution_obligation.must_attempt_work=true`,即使
901
+ `notify=DONT_NOTIFY` 也要尝试一个 bounded segment,只有
902
+ `must_attempt_work=false` 才能 quiet no-op。
903
+ 如果是 `outcome_floor_recovery`,这是 Codex 可执行 recovery turn:只允许做一次所需
904
+ ranker/cross-domain evidence recovery,或写回阻止该 evidence 的具体 blocker;
905
+ 不做 surface-only / synthetic-only 循环,验证并写回后才能 append 一次 quota spend。
906
+ 如果不是 operator gate / blocker-push / outcome-floor recovery / 明确 safe-bypass,本轮不要做实现或 adapter 工作,
907
+ 只记录 public-safe reason;不要执行任何 `agent_command`,即使 status 或 review packet 里提到过命令。
908
+ 只有当返回 `should_run=true` 且 payload 里包含 `agent_command` 时,才执行该命令。
909
+ 如果 `should_run=true` 但没有 `agent_command`,按
910
+ `execution_obligation` / `recommended_action` / `goal_boundary` 选择下一个
911
+ 安全 bounded 动作;只读目标保持只读,delivery 目标按已授权 write scope 执行。
912
+ 如果命令非零,fail closed,先修 `{cli_bin} doctor` / `{cli_bin} status`。
913
+ 这个 guard 不等于写权限、不绕过 operator gate、也不替代 human reward。
914
+ 任何时候,如果你通过 read-only 分析、review doc、gate checklist 或 P0/P1 steering 发现新的
915
+ 用户/owner 待办,不要只写在 `Next Action`、外部 review 文档或聊天里。立刻把它写进 active state
916
+ 的 user todo 权威区:
917
+
918
+ ```bash
919
+ {cli_bin} todo add --goal-id {goal_id} --role user --task-class user_gate --blocks-agent <agent-id> --text "<public-safe blocking user/owner decision>"
920
+ {cli_bin} todo add --goal-id {goal_id} --role user --task-class user_action --text "<public-safe non-blocking user/owner todo>"
921
+ ```
922
+
923
+ agent 自己的后续动作写成 `--role agent`。写入后如果 dashboard 需要看到最新状态,运行
924
+ `{refresh_command}`。
925
+ 完整契约见 LoopX 仓库里的 `docs/project-agent-todo-contract.md`。
926
+ 6. 如果需要把当前 packet 或已批准命令交给项目 agent,优先生成最小 handoff,不要从旧聊天、
927
+ 旧 review packet 或 `run_history.latest_runs` 拼当前状态。当前权威状态来自
928
+ `attention_queue.items` / `project_asset`;如果缺少 `project_asset` 或标记为
929
+ `legacy/raw fallback`,不要把 raw queue 字段当作 owner/gate/stop authority:
930
+
931
+ ```bash
932
+ {cli_bin} review-packet --goal-id {goal_id} --handoff-only
933
+ ```
934
+
935
+ 只把输出的 handoff 交给目标项目 agent;完整 review packet 留给 operator view / evidence drill-down。
936
+ 7. 如果要给这个项目设置 recurring Codex App heartbeat,默认每 3 分钟一次,后续跟随 `quota should-run.scheduler_hint` 降频;不要手抄 guard 和 spend 协议;先生成 task body,再把输出复制进 automation:
937
+
938
+ ```bash
939
+ {cli_bin} heartbeat-prompt --goal-id {goal_id} --active-state .codex/goals/{goal_id}/ACTIVE_GOAL_STATE.md
940
+ ```
941
+
942
+ 8. 生成一个 read-only project map 或 first pre-tick run。不要启动线上任务、不同步外部系统、不要写生产状态,除非目标文档明确授权。通用接入优先跑:
943
+
944
+ ```bash
945
+ {cli_bin} read-only-map --goal-id {goal_id}
946
+ ```
947
+
948
+ 9. 如果本轮只更新了 active state、ledger 或外部规划文档,没有产生新的
949
+ adapter run,追加一个 state-only refresh run,然后停止且不记 quota spend。
950
+ 如果本轮实际消耗了 automatic delivery compute,先不要运行这个 state-only
951
+ refresh;把它留到第 11 步记账之后:
952
+
953
+ ```bash
954
+ {refresh_command}
955
+ ```
956
+
957
+ 这个命令也会自动同步全局 registry。
958
+
959
+ 10. 跑验证:
960
+ - `{cli_bin} registry`
961
+ - `{cli_bin} status`(在没有项目局部 registry 的目录里也应自动读共享全局 registry)
962
+ - `{cli_bin} check --scan-path <PUBLIC_SAFE_FILE_OR_DIR>`
963
+ 11. 如果本轮实际花了 automatic delivery compute(例如 read-only map、adapter
964
+ tick、实现推进或验证推进),在 validation / writeback 完成后,把命令中的
965
+ 三个 placeholder 替换为本轮实际验证过的 classification、batch scale 和
966
+ outcome;不要默认或拔高成 `multi_surface` / `outcome_progress`。然后记录本轮
967
+ accountable delivery:
968
+
969
+ ```bash
970
+ {progress_refresh_command}
971
+ ```
972
+
973
+ 这是 `spend-slot` 将消费的因果记录;普通 state-only refresh 不能替代它。
974
+ 然后只 append 一次 quota spend:
975
+
976
+ ```bash
977
+ {quota_spend_command}
978
+ ```
979
+
980
+ 如果 dashboard 或 controller 在 spend 后仍需状态更新,再运行第 9 步的
981
+ `{refresh_command}`。不要在 spend 后追加另一个 accountable progress
982
+ refresh,否则它会成为新的未记账 delivery。
983
+
984
+ 不要为 quiet `should_run=false` skip、preflight 失败、或纯 dry-run preview 记账;如果
985
+ `should_run=false` 但实际完成了 `safe_bypass_allowed=true` 的 bounded safe-bypass 工作,要记一次账。
986
+ accountable `refresh-state` 应从实际交付 worktree 运行;若 registry/state 投影只能从另一个
987
+ checkout 执行,显式加 `--delivery-workspace-path <delivery-worktree>`,不要让 canonical checkout
988
+ 覆盖交付归因。
989
+ 不要重复执行。
990
+ 12. 最后用中文汇报:
991
+ - changed files;
992
+ - validation output;
993
+ - 当前 goal 在 dashboard / attention queue 里会怎么显示;
994
+ - next safe action;
995
+ - 如果还不能接入 decision-advisor,明确缺哪些 gates。
996
+
997
+ 并行/权限边界:
998
+ {spawn_note}
999
+ """
1000
+
1001
+
1002
+ def render_new_project_prompt_markdown(payload: dict[str, Any]) -> str:
1003
+ return f"""# New Project Codex Handoff Prompt
1004
+
1005
+ Copy the block below into the Codex session that can access the target project.
1006
+
1007
+ ````text
1008
+ {payload.get("prompt", "")}
1009
+ ````
1010
+
1011
+ ## Generator Inputs
1012
+
1013
+ - project: `{payload.get("project")}`
1014
+ - goal_doc: `{payload.get("goal_doc")}`
1015
+ - goal_id: `{payload.get("goal_id")}`
1016
+ - domain: `{payload.get("domain")}`
1017
+ - adapter: `{payload.get("adapter_kind")}:{payload.get("adapter_status")}`
1018
+ """
1019
+
1020
+
1021
+ def render_codex_cli_bootstrap_message_markdown(payload: dict[str, Any]) -> str:
1022
+ checklist = "\n".join(
1023
+ f"- {item}" for item in payload.get("first_run_validation_checklist", [])
1024
+ )
1025
+ goal_mode_note = ""
1026
+ if payload.get("invocation_mode") == "codex_cli_setup_then_goal_mode":
1027
+ goal_mode_note = (
1028
+ "\nThe generated block is a setup message, not the reusable heartbeat body. "
1029
+ "After install/bootstrap, it tells the agent to set Codex CLI goal mode "
1030
+ "to `/goal <thin task_body>` or Codex App automation starting at 3 minutes "
1031
+ "with `<thin task_body>`.\n"
1032
+ )
1033
+ return f"""# Codex CLI LoopX Bootstrap Message
1034
+
1035
+ Copy the block below into Codex CLI TUI from the project repo.
1036
+ {goal_mode_note}
1037
+
1038
+ ````text
1039
+ {payload.get("message", "")}
1040
+ ````
1041
+
1042
+ ## Fresh Repo Install Repair
1043
+
1044
+ The generated message uses the no-clone GitHub archive installer before asking
1045
+ for a contributor clone:
1046
+
1047
+ ```bash
1048
+ {payload.get("install_repair_command", "")}
1049
+ ```
1050
+
1051
+ ## Post-Bootstrap Thin Loop Prompt
1052
+
1053
+ Generate the thin task body after the project is connected:
1054
+
1055
+ ```bash
1056
+ {payload.get("heartbeat_prompt_json_command", "")}
1057
+ ```
1058
+
1059
+ - Codex CLI TUI loop: set `/goal <task_body>`.
1060
+ - Codex App loop: set heartbeat automation initially every 3 minutes with
1061
+ `<task_body>`, then follow quota `scheduler_hint`.
1062
+
1063
+ ## Transcript-Free Validation Checklist
1064
+
1065
+ {checklist}
1066
+
1067
+ ## Generator Inputs
1068
+
1069
+ - project: `{payload.get("project")}`
1070
+ - goal_id: `{payload.get("goal_id")}`
1071
+ - agent_id: `{payload.get("agent_id") or "(not provided)"}`
1072
+ - cli_bin: `{payload.get("cli_bin")}`
1073
+ - heartbeat_prompt_drift_check: `{payload.get("heartbeat_prompt_command")}`
1074
+ """
1075
+
1076
+
1077
+ def render_codex_cli_tui_bootstrap_smoke_bundle_markdown(payload: dict[str, Any]) -> str:
1078
+ boundary = payload.get("boundary") or {}
1079
+ checklist = "\n".join(f"- {item}" for item in payload.get("validation_checklist", []))
1080
+ return f"""# Codex CLI TUI Bootstrap Smoke Bundle
1081
+
1082
+ This packet is for validating the first-run Codex CLI path without launching or
1083
+ mutating a real Codex session.
1084
+
1085
+ ## Commands
1086
+
1087
+ ```bash
1088
+ {payload.get("message_only_command", "")}
1089
+ ```
1090
+
1091
+ - review_packet: `{payload.get("review_packet_command")}`
1092
+ - heartbeat_prompt: `{payload.get("heartbeat_prompt_command")}`
1093
+ - heartbeat_prompt_json: `{payload.get("heartbeat_prompt_json_command")}`
1094
+ - quota_guard: `{payload.get("quota_guard_command")}`
1095
+ - accountable_progress_refresh: `{payload.get("progress_refresh_command")}`
1096
+ - quota_spend_after_validation: `{payload.get("quota_spend_command")}`
1097
+ - optional_state_only_refresh_after_spend: `{payload.get("refresh_command")}`
1098
+
1099
+ ## Fresh Repo Install Repair
1100
+
1101
+ ```bash
1102
+ {payload.get("install_repair_command", "")}
1103
+ ```
1104
+
1105
+ ## Transcript-Free Boundary
1106
+
1107
+ - runs_codex: `{boundary.get("runs_codex")}`
1108
+ - reads_raw_transcripts: `{boundary.get("reads_raw_transcripts")}`
1109
+ - reads_session_files: `{boundary.get("reads_session_files")}`
1110
+ - reads_credentials: `{boundary.get("reads_credentials")}`
1111
+ - mutates_codex_session: `{boundary.get("mutates_codex_session")}`
1112
+ - spends_loopx_quota: `{boundary.get("spends_loopx_quota")}`
1113
+ - requires_loopx_repo_clone: `{boundary.get("requires_loopx_repo_clone")}`
1114
+
1115
+ ## Validation Checklist
1116
+
1117
+ {checklist}
1118
+ """
1119
+
1120
+
1121
+ def render_codex_cli_exec_handoff_markdown(payload: dict[str, Any]) -> str:
1122
+ boundary = payload.get("boundary") or {}
1123
+ return f"""# Codex CLI Exec Handoff Disabled
1124
+
1125
+ The default Codex CLI LoopX bootstrap is visible setup, then thin
1126
+ `/goal <task_body>` activation. Headless `codex exec` handoff is disabled here
1127
+ to avoid accidental hidden execution. Use the message-only command below inside
1128
+ the visible Codex CLI TUI.
1129
+
1130
+ ````bash
1131
+ {payload.get("message_only_command", "")}
1132
+ ````
1133
+
1134
+ ## Guard Commands
1135
+
1136
+ - session_probe: `{payload.get("session_probe_command")}`
1137
+ - quota_guard: `{payload.get("quota_guard_command")}`
1138
+ - accountable_progress_refresh: `{payload.get("progress_refresh_command")}`
1139
+ - quota_spend: `{payload.get("quota_spend_command")}`
1140
+ - optional_state_only_refresh_after_spend: `{payload.get("refresh_command")}`
1141
+ - disabled_reason: {payload.get("disabled_reason")}
1142
+
1143
+ ## Boundary
1144
+
1145
+ - runs_codex: `{boundary.get("runs_codex")}`
1146
+ - reads_raw_transcripts: `{boundary.get("reads_raw_transcripts")}`
1147
+ - reads_credentials: `{boundary.get("reads_credentials")}`
1148
+ - reads_session_files: `{boundary.get("reads_session_files")}`
1149
+ - mutates_codex_session: `{boundary.get("mutates_codex_session")}`
1150
+ - spends_loopx_quota: `{boundary.get("spends_loopx_quota")}`
1151
+ - headless_execution_disabled: `{boundary.get("headless_execution_disabled")}`
1152
+ - provides_executable_headless_command: `{boundary.get("provides_executable_headless_command")}`
1153
+ """