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,8 @@
1
+ // <!-- loopx-managed-slash-command:v1 command=/goal surface=opencode-plugin -->
2
+ import { tool } from "@opencode-ai/plugin"
3
+ import { GoalPlugin } from "opencode-goal-plugin"
4
+
5
+ import { createLoopxGoalPlugin } from "../loopx/goal-bridge-runtime.mjs"
6
+
7
+
8
+ export const LoopXGoalPlugin = createLoopxGoalPlugin({ GoalPlugin, tool })
loopx/operator_gate.py ADDED
@@ -0,0 +1,420 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ from .feedback import validate_local_control_text, validate_public_safe_text
8
+ from .history import collect_history, load_registry
9
+ from .paths import resolve_runtime_root
10
+ from .registry import registry_goals
11
+ from .runtime import validate_goal_id_path_segment
12
+ from .state_refresh import now_local, run_file_stem
13
+ from .control_plane.runtime.shared_runtime_material_projection import (
14
+ finalize_material_projection,
15
+ prepare_material_projection_route,
16
+ )
17
+
18
+
19
+ OPERATOR_GATE_DECISIONS = {"approve", "reject", "defer"}
20
+ DEFAULT_OPERATOR_GATE = "read_only_map_opt_in"
21
+ OPERATOR_GATE_RESUME_CONTRACT_VERSION = "operator_gate_resume_contract_v0"
22
+
23
+
24
+ def find_registry_goal(registry: dict[str, Any], goal_id: str) -> dict[str, Any] | None:
25
+ for goal in registry_goals(registry):
26
+ if str(goal.get("id") or "") == goal_id:
27
+ return goal
28
+ return None
29
+
30
+
31
+ def default_operator_question(goal_id: str, gate: str) -> str:
32
+ if gate == DEFAULT_OPERATOR_GATE:
33
+ return f"是否同意 `{goal_id}` 先执行 read-only map opt-in?"
34
+ return f"是否同意 `{goal_id}` 的 operator gate `{gate}`?"
35
+
36
+
37
+ def normalize_operator_question(question: str | None, *, goal_id: str, gate: str) -> str | None:
38
+ if not question:
39
+ return question
40
+ legacy_defaults = {
41
+ f"Approve a read-only map opt-in for `{goal_id}`?",
42
+ f"Approve operator gate `{gate}` for `{goal_id}`?",
43
+ }
44
+ if question in legacy_defaults:
45
+ return default_operator_question(goal_id, gate)
46
+ return question
47
+
48
+
49
+ def default_agent_command(goal_id: str, gate: str) -> str | None:
50
+ if gate == DEFAULT_OPERATOR_GATE:
51
+ return f"loopx read-only-map --goal-id {goal_id} --dry-run"
52
+ return None
53
+
54
+
55
+ def classification_for_decision(decision: str) -> str:
56
+ if decision == "approve":
57
+ return "operator_gate_approved"
58
+ if decision == "reject":
59
+ return "operator_gate_rejected"
60
+ if decision == "defer":
61
+ return "operator_gate_deferred"
62
+ raise ValueError(f"decision must be one of: {', '.join(sorted(OPERATOR_GATE_DECISIONS))}")
63
+
64
+
65
+ def default_recommended_action(*, decision: str, agent_command: str | None) -> str:
66
+ if decision == "approve":
67
+ if agent_command:
68
+ return "把已批准的 agent_command 发给目标项目 agent;这不是写权限授权"
69
+ return "继续执行已批准的 operator gate;这不是写权限授权"
70
+ if decision == "reject":
71
+ return "保持 goal 在 gate 状态,修改 handoff 后再请求 operator 判断"
72
+ if decision == "defer":
73
+ return "保持 goal 在 gate 状态,先补齐要求的证据后再请求判断"
74
+ raise ValueError(f"decision must be one of: {', '.join(sorted(OPERATOR_GATE_DECISIONS))}")
75
+
76
+
77
+ def _latest_state_ref(
78
+ *,
79
+ registry_path: Path,
80
+ runtime_root: Path,
81
+ goal_id: str,
82
+ ) -> str:
83
+ history = collect_history(
84
+ registry_path=registry_path,
85
+ runtime_root=runtime_root,
86
+ goal_id=goal_id,
87
+ limit=1,
88
+ include_runtime_goals=True,
89
+ )
90
+ goals = [goal for goal in history.get("goals") or [] if isinstance(goal, dict)]
91
+ if not goals:
92
+ return f"goal={goal_id}; latest_run=none"
93
+
94
+ goal = goals[0]
95
+ latest = goal.get("latest_status_run") if isinstance(goal.get("latest_status_run"), dict) else {}
96
+ latest_parts = []
97
+ if latest.get("generated_at"):
98
+ latest_parts.append(f"latest_at={latest.get('generated_at')}")
99
+ if latest.get("classification"):
100
+ latest_parts.append(f"classification={latest.get('classification')}")
101
+ latest_text = "; ".join(latest_parts) if latest_parts else "latest_run=none"
102
+ return (
103
+ f"goal={goal_id}; status={goal.get('status') or 'unknown'}; "
104
+ f"adapter={goal.get('adapter_kind') or 'none'}:{goal.get('adapter_status') or 'none'}; "
105
+ f"{latest_text}"
106
+ )
107
+
108
+
109
+ def build_operator_gate_resume_contract(
110
+ *,
111
+ goal_id: str,
112
+ run_id: str,
113
+ gate: str,
114
+ decision: str,
115
+ operator_question: str,
116
+ recommended_action: str,
117
+ agent_command: str | None,
118
+ registry_path: Path,
119
+ runtime_root: Path,
120
+ ) -> dict[str, Any]:
121
+ """Describe how an operator decision may resume work without replaying stale state."""
122
+ if decision not in OPERATOR_GATE_DECISIONS:
123
+ raise ValueError(f"decision must be one of: {', '.join(sorted(OPERATOR_GATE_DECISIONS))}")
124
+ latest_state_ref = _latest_state_ref(
125
+ registry_path=registry_path,
126
+ runtime_root=runtime_root,
127
+ goal_id=goal_id,
128
+ )
129
+ resulting_action = recommended_action
130
+ validation = (
131
+ "after resume, run the approved command in its declared mode and record validation before quota spend or follow-up side effects"
132
+ if decision == "approve" and agent_command
133
+ else "after resume, keep the gate state current and record the next local-control blocker or evidence condition"
134
+ )
135
+ contract = {
136
+ "version": OPERATOR_GATE_RESUME_CONTRACT_VERSION,
137
+ "goal_id": goal_id,
138
+ "run_id": run_id,
139
+ "gate_id": gate,
140
+ "created_state_ref": latest_state_ref,
141
+ "created_policy_version": OPERATOR_GATE_RESUME_CONTRACT_VERSION,
142
+ "interrupt_payload": {
143
+ "question": operator_question,
144
+ "choices": sorted(OPERATOR_GATE_DECISIONS),
145
+ },
146
+ "allowed_decisions": sorted(OPERATOR_GATE_DECISIONS),
147
+ "operator_decision": decision,
148
+ "latest_state_ref": latest_state_ref,
149
+ "freshness_check": "resume must re-read current decision-point authority: registry, ACTIVE_GOAL_STATE, quota, repo dirty/ref snapshot, policy, and run status",
150
+ "precondition_check": "decision is actionable only at this gate decision point if current authority still matches the gate intent and stop condition",
151
+ "migration_or_rebase_result": "decision_point_rebase_only; do not restore, rewind, or carry the whole repo/worktree back to the created checkpoint",
152
+ "resulting_action": resulting_action,
153
+ "validation_after_resume": validation,
154
+ }
155
+ for label, value in (
156
+ ("created_state_ref", contract["created_state_ref"]),
157
+ ("freshness_check", contract["freshness_check"]),
158
+ ("precondition_check", contract["precondition_check"]),
159
+ ("migration_or_rebase_result", contract["migration_or_rebase_result"]),
160
+ ("validation_after_resume", contract["validation_after_resume"]),
161
+ ):
162
+ validate_public_safe_text(label, str(value))
163
+ validate_local_control_text("resulting_action", str(contract["resulting_action"]))
164
+ validate_public_safe_text("interrupt_payload.question", operator_question)
165
+ return contract
166
+
167
+
168
+ def compact_operator_gate(
169
+ *,
170
+ recorded_at: str | None,
171
+ gate: str,
172
+ decision: str,
173
+ operator_question: str,
174
+ reason_summary: str,
175
+ follow_up: str | None,
176
+ agent_command: str | None,
177
+ ) -> dict[str, Any]:
178
+ if decision not in OPERATOR_GATE_DECISIONS:
179
+ raise ValueError(f"decision must be one of: {', '.join(sorted(OPERATOR_GATE_DECISIONS))}")
180
+ for label, value in (
181
+ ("gate", gate),
182
+ ("operator_question", operator_question),
183
+ ("reason_summary", reason_summary),
184
+ ("follow_up", follow_up),
185
+ ("agent_command", agent_command),
186
+ ):
187
+ validate_public_safe_text(label, value)
188
+ payload: dict[str, Any] = {
189
+ "recorded_at": recorded_at or now_local(),
190
+ "gate": gate,
191
+ "decision": decision,
192
+ "operator_question": operator_question,
193
+ "reason_summary": reason_summary,
194
+ }
195
+ if follow_up:
196
+ payload["follow_up"] = follow_up
197
+ if agent_command:
198
+ payload["agent_command"] = agent_command
199
+ return payload
200
+
201
+
202
+ def build_operator_gate_record(
203
+ *,
204
+ goal_id: str,
205
+ registry_goal: dict[str, Any] | None,
206
+ classification: str,
207
+ recommended_action: str,
208
+ generated_at: str,
209
+ operator_gate: dict[str, Any],
210
+ ) -> dict[str, Any]:
211
+ adapter = registry_goal.get("adapter") if isinstance(registry_goal, dict) and isinstance(registry_goal.get("adapter"), dict) else {}
212
+ health_check = (
213
+ f"operator_gate decision={operator_gate.get('decision')}; "
214
+ f"registry_goal {1 if registry_goal else 0}/1; "
215
+ f"agent_command {1 if operator_gate.get('agent_command') else 0}/1"
216
+ )
217
+ return {
218
+ "generated_at": generated_at,
219
+ "goal_id": goal_id,
220
+ "classification": classification,
221
+ "recommended_action": recommended_action,
222
+ "health_check": health_check,
223
+ "operator_gate": operator_gate,
224
+ "registry_goal": {
225
+ "present": bool(registry_goal),
226
+ "domain": registry_goal.get("domain") if registry_goal else None,
227
+ "status": registry_goal.get("status") if registry_goal else None,
228
+ "adapter": {
229
+ "kind": adapter.get("kind"),
230
+ "status": adapter.get("status"),
231
+ },
232
+ },
233
+ }
234
+
235
+
236
+ def render_operator_gate_markdown(payload: dict[str, Any]) -> str:
237
+ gate = payload.get("operator_gate") if isinstance(payload.get("operator_gate"), dict) else {}
238
+ lines = [
239
+ "# LoopX Operator Gate Decision",
240
+ "",
241
+ f"- ok: `{payload.get('ok')}`",
242
+ f"- dry_run: `{payload.get('dry_run')}`",
243
+ f"- appended: `{payload.get('appended')}`",
244
+ f"- goal_id: `{payload.get('goal_id')}`",
245
+ f"- classification: `{payload.get('classification')}`",
246
+ f"- generated_at: `{payload.get('generated_at')}`",
247
+ f"- health_check: `{payload.get('health_check')}`",
248
+ ]
249
+ if payload.get("error"):
250
+ lines.append(f"- error: {payload.get('error')}")
251
+ return "\n".join(lines)
252
+
253
+ global_sync = payload.get("global_sync") if isinstance(payload.get("global_sync"), dict) else {}
254
+ if global_sync:
255
+ lines.extend(
256
+ [
257
+ f"- global_registry: `{global_sync.get('global_registry')}`",
258
+ f"- global_sync_wrote: `{global_sync.get('wrote')}`",
259
+ ]
260
+ )
261
+
262
+ lines.extend(
263
+ [
264
+ "",
265
+ "## Gate",
266
+ f"- gate: `{gate.get('gate')}`",
267
+ f"- decision: `{gate.get('decision')}`",
268
+ f"- operator_question: {gate.get('operator_question')}",
269
+ f"- reason_summary: {gate.get('reason_summary')}",
270
+ ]
271
+ )
272
+ if gate.get("follow_up"):
273
+ lines.append(f"- follow_up: {gate.get('follow_up')}")
274
+ if gate.get("agent_command"):
275
+ lines.extend(["", "## Agent Command", f"```bash\n{gate.get('agent_command')}\n```"])
276
+ resume_contract = payload.get("operator_gate_resume_contract") if isinstance(payload.get("operator_gate_resume_contract"), dict) else {}
277
+ if resume_contract:
278
+ lines.extend(
279
+ [
280
+ "",
281
+ "## Resume Contract",
282
+ f"- version: `{resume_contract.get('version')}`",
283
+ f"- gate_id: `{resume_contract.get('gate_id')}`",
284
+ f"- operator_decision: `{resume_contract.get('operator_decision')}`",
285
+ f"- latest_state_ref: {resume_contract.get('latest_state_ref')}",
286
+ f"- freshness_check: {resume_contract.get('freshness_check')}",
287
+ f"- precondition_check: {resume_contract.get('precondition_check')}",
288
+ f"- migration_or_rebase_result: {resume_contract.get('migration_or_rebase_result')}",
289
+ f"- validation_after_resume: {resume_contract.get('validation_after_resume')}",
290
+ ]
291
+ )
292
+ lines.extend(["", "## Recommended Action", str(payload.get("recommended_action") or "")])
293
+ return "\n".join(lines)
294
+
295
+
296
+ def record_operator_gate(
297
+ *,
298
+ registry_path: Path,
299
+ runtime_root_override: str | None,
300
+ goal_id: str,
301
+ gate: str,
302
+ decision: str,
303
+ operator_question: str | None,
304
+ reason_summary: str,
305
+ follow_up: str | None,
306
+ agent_command: str | None,
307
+ recommended_action: str | None,
308
+ recorded_at: str | None,
309
+ dry_run: bool,
310
+ sync_global: bool = True,
311
+ ) -> dict[str, Any]:
312
+ safe_goal_id = validate_goal_id_path_segment(goal_id)
313
+ validate_public_safe_text("gate", gate)
314
+ validate_public_safe_text("reason_summary", reason_summary)
315
+ registry = load_registry(registry_path)
316
+ runtime_root = resolve_runtime_root(registry, runtime_root_override)
317
+ projection_route, compact_projection_route = prepare_material_projection_route(
318
+ registry_path=registry_path,
319
+ goal_id=safe_goal_id,
320
+ source_runtime_root=runtime_root,
321
+ sync_global=sync_global,
322
+ )
323
+ registry_goal = find_registry_goal(registry, safe_goal_id)
324
+ question = operator_question or default_operator_question(safe_goal_id, gate)
325
+ command = agent_command
326
+ if command is None and decision == "approve":
327
+ command = default_agent_command(safe_goal_id, gate)
328
+ operator_gate = compact_operator_gate(
329
+ recorded_at=recorded_at,
330
+ gate=gate,
331
+ decision=decision,
332
+ operator_question=question,
333
+ reason_summary=reason_summary,
334
+ follow_up=follow_up,
335
+ agent_command=command,
336
+ )
337
+ classification = classification_for_decision(decision)
338
+ action = recommended_action or default_recommended_action(decision=decision, agent_command=command)
339
+ validate_local_control_text("recommended_action", action)
340
+ generated_at = now_local()
341
+ stem = f"{run_file_stem(generated_at)}-operator-gate"
342
+ resume_contract = build_operator_gate_resume_contract(
343
+ goal_id=safe_goal_id,
344
+ run_id=stem,
345
+ gate=gate,
346
+ decision=decision,
347
+ operator_question=question,
348
+ recommended_action=action,
349
+ agent_command=command,
350
+ registry_path=registry_path,
351
+ runtime_root=runtime_root,
352
+ )
353
+ record = build_operator_gate_record(
354
+ goal_id=safe_goal_id,
355
+ registry_goal=registry_goal,
356
+ classification=classification,
357
+ recommended_action=action,
358
+ generated_at=generated_at,
359
+ operator_gate=operator_gate,
360
+ )
361
+ record["operator_gate_resume_contract"] = resume_contract
362
+ record["runtime_projection_route"] = compact_projection_route
363
+
364
+ runs_dir = runtime_root / "goals" / safe_goal_id / "runs"
365
+ json_path = runs_dir / f"{stem}.json"
366
+ markdown_path = runs_dir / f"{stem}.md"
367
+ index_path = runs_dir / "index.jsonl"
368
+ index_record = {
369
+ "generated_at": generated_at,
370
+ "goal_id": safe_goal_id,
371
+ "classification": classification,
372
+ "recommended_action": action,
373
+ "health_check": record["health_check"],
374
+ "operator_gate": operator_gate,
375
+ "operator_gate_resume_contract": resume_contract,
376
+ "runtime_projection_route": compact_projection_route,
377
+ "json_path": str(json_path),
378
+ "markdown_path": str(markdown_path),
379
+ }
380
+ payload = {
381
+ "ok": True,
382
+ "dry_run": dry_run,
383
+ "appended": not dry_run,
384
+ "registry": str(registry_path),
385
+ "runtime_root": str(runtime_root),
386
+ "goal_id": safe_goal_id,
387
+ "classification": classification,
388
+ "recommended_action": action,
389
+ "generated_at": generated_at,
390
+ "health_check": record["health_check"],
391
+ "json_path": str(json_path),
392
+ "markdown_path": str(markdown_path),
393
+ "index_path": str(index_path),
394
+ "runtime_projection_route": compact_projection_route,
395
+ **record,
396
+ }
397
+ if not dry_run:
398
+ runs_dir.mkdir(parents=True, exist_ok=True)
399
+ json_path.write_text(json.dumps(record, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
400
+ markdown_path.write_text(render_operator_gate_markdown(payload) + "\n", encoding="utf-8")
401
+ with index_path.open("a", encoding="utf-8") as f:
402
+ f.write(json.dumps(index_record, ensure_ascii=False) + "\n")
403
+ projection_result = finalize_material_projection(
404
+ registry_path=registry_path,
405
+ source_runtime_root=runtime_root,
406
+ goal_id=safe_goal_id,
407
+ source_row=index_record,
408
+ projection_kind="operator_gate_decision",
409
+ route=projection_route,
410
+ sync_global=sync_global,
411
+ dry_run=dry_run,
412
+ )
413
+ payload["global_sync"] = projection_result["global_sync"]
414
+ payload["shared_runtime_material_projection"] = projection_result[
415
+ "shared_runtime_material_projection"
416
+ ]
417
+ if not projection_result["ok"]:
418
+ payload["ok"] = False
419
+ payload["partial_write"] = projection_result["partial_write"]
420
+ return payload
loopx/orchestration.py ADDED
@@ -0,0 +1,127 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from .agent_registry import normalize_registered_agents
6
+
7
+ DEFAULT_ORCHESTRATION_MODE = "default"
8
+ MULTI_SUBAGENT_ORCHESTRATION_MODE = "multi_subagent"
9
+ VALID_ORCHESTRATION_MODES = {
10
+ DEFAULT_ORCHESTRATION_MODE,
11
+ MULTI_SUBAGENT_ORCHESTRATION_MODE,
12
+ }
13
+ EXPLORE_HARNESS_PROFILES = (
14
+ "generic",
15
+ "adaptive-resilient",
16
+ "moe-router",
17
+ )
18
+
19
+
20
+ def _int_number(value: Any, *, default: int = 0) -> int:
21
+ if isinstance(value, bool):
22
+ return default
23
+ if isinstance(value, int):
24
+ return value
25
+ if isinstance(value, float):
26
+ return int(value)
27
+ if isinstance(value, str):
28
+ try:
29
+ return int(value.strip())
30
+ except ValueError:
31
+ return default
32
+ return default
33
+
34
+
35
+ def orchestration_mode_from_spawn_policy(spawn_policy: Any) -> str:
36
+ if not isinstance(spawn_policy, dict):
37
+ return DEFAULT_ORCHESTRATION_MODE
38
+ explicit_mode = str(
39
+ spawn_policy.get("mode") or spawn_policy.get("orchestration_mode") or ""
40
+ ).strip()
41
+ if explicit_mode in VALID_ORCHESTRATION_MODES:
42
+ return explicit_mode
43
+ spawn_allowed = bool(spawn_policy.get("allowed") or spawn_policy.get("spawn_allowed"))
44
+ if spawn_allowed and _int_number(spawn_policy.get("max_children")) > 0:
45
+ return MULTI_SUBAGENT_ORCHESTRATION_MODE
46
+ return DEFAULT_ORCHESTRATION_MODE
47
+
48
+
49
+ def compact_explore_harness_policy(policy: Any) -> dict[str, Any]:
50
+ """Normalize the per-goal explore-harness opt-in gate.
51
+
52
+ Absence of the section means the gate is closed. The opt-in bit is a
53
+ deny-by-default switch, so it fails closed: only a real boolean ``true``
54
+ opens it -- truthy strings like ``"false"`` or ``"true"`` stay closed
55
+ instead of silently inverting a hand-edited deny. ``profile`` is carried
56
+ only when the goal explicitly pins one, so planners can tell a pinned
57
+ profile apart from their own default.
58
+ """
59
+
60
+ harness = policy if isinstance(policy, dict) else {}
61
+ compact: dict[str, Any] = {"enabled": harness.get("enabled") is True}
62
+ profile = str(harness.get("profile") or "").strip()
63
+ if profile:
64
+ compact["profile"] = profile
65
+ return compact
66
+
67
+
68
+ def compact_orchestration_policy(spawn_policy: Any) -> dict[str, Any]:
69
+ policy = spawn_policy if isinstance(spawn_policy, dict) else {}
70
+ max_children = max(0, _int_number(policy.get("max_children")))
71
+ allowed_domains = policy.get("allowed_domains")
72
+ if not isinstance(allowed_domains, list):
73
+ allowed_domains = []
74
+ compact: dict[str, Any] = {
75
+ "mode": orchestration_mode_from_spawn_policy(policy),
76
+ "spawn_allowed": bool(policy.get("allowed") or policy.get("spawn_allowed")),
77
+ "max_children": max_children,
78
+ }
79
+ compact_domains = [str(value) for value in allowed_domains if str(value).strip()]
80
+ if compact_domains:
81
+ compact["allowed_domains"] = compact_domains
82
+ if isinstance(policy.get("explore_harness"), dict):
83
+ compact["explore_harness"] = compact_explore_harness_policy(policy.get("explore_harness"))
84
+ return compact
85
+
86
+
87
+ def compact_peer_task_coordination_policy(coordination: Any) -> dict[str, Any] | None:
88
+ """Normalize the explicit registered-peer task coordinator selection.
89
+
90
+ Registered peer identity is not coordination authority. The policy is
91
+ therefore fail-closed: only a non-empty ``coordinator_agent_id`` opts a
92
+ goal into peer task coordination. Runtime capability admission remains a
93
+ separate, per-turn decision.
94
+ """
95
+
96
+ policy = coordination if isinstance(coordination, dict) else {}
97
+ peer_policy = (
98
+ policy.get("peer_task_coordination")
99
+ if isinstance(policy.get("peer_task_coordination"), dict)
100
+ else {}
101
+ )
102
+ coordinator_agent_ids = normalize_registered_agents(
103
+ [peer_policy.get("coordinator_agent_id")]
104
+ )
105
+ if not coordinator_agent_ids:
106
+ return None
107
+ return {
108
+ "enabled": True,
109
+ "coordinator_agent_id": coordinator_agent_ids[0],
110
+ }
111
+
112
+
113
+ def orchestration_policy_summary(policy: dict[str, Any] | None) -> str:
114
+ compact = compact_orchestration_policy(policy)
115
+ summary = (
116
+ f"mode={compact.get('mode')} "
117
+ f"spawn_allowed={compact.get('spawn_allowed')} "
118
+ f"max_children={compact.get('max_children')}"
119
+ )
120
+ harness = compact.get("explore_harness")
121
+ if isinstance(harness, dict):
122
+ state = "on" if harness.get("enabled") else "off"
123
+ profile = str(harness.get("profile") or "")
124
+ if harness.get("enabled") and profile:
125
+ state = f"on({profile})"
126
+ summary += f" explore_harness={state}"
127
+ return summary
loopx/paths.py ADDED
@@ -0,0 +1,59 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from pathlib import Path
5
+
6
+
7
+ DEFAULT_RUNTIME_ROOT = Path.home() / ".codex" / "loopx"
8
+ DEFAULT_PROJECT_REGISTRY = Path(".loopx") / "registry.json"
9
+ GLOBAL_REGISTRY_FILENAME = "registry.global.json"
10
+
11
+
12
+ def default_registry_path() -> Path:
13
+ value = os.environ.get("LOOPX_REGISTRY")
14
+ if value:
15
+ return Path(value).expanduser()
16
+ return DEFAULT_PROJECT_REGISTRY
17
+
18
+
19
+ def global_registry_path(runtime_root: Path = DEFAULT_RUNTIME_ROOT) -> Path:
20
+ return runtime_root / GLOBAL_REGISTRY_FILENAME
21
+
22
+
23
+ def registry_project_root(registry_path: Path) -> Path:
24
+ """Return the project root that owns a registry path.
25
+
26
+ Project registries conventionally live at ``<project>/.loopx/registry.json``.
27
+ Standalone fixtures and global registries live directly under their owning
28
+ root. Keeping this rule here prevents relative runtime paths from silently
29
+ depending on the caller's current working directory.
30
+ """
31
+
32
+ expanded = registry_path.expanduser().resolve()
33
+ parent = expanded.parent
34
+ return parent.parent if parent.name == ".loopx" else parent
35
+
36
+
37
+ def resolve_runtime_root(
38
+ registry: dict[str, object],
39
+ override: str | None = None,
40
+ *,
41
+ registry_path: Path | None = None,
42
+ ) -> Path:
43
+ value = override
44
+ if not value:
45
+ value = registry.get("common_runtime_root") if isinstance(registry, dict) else None
46
+ if not value:
47
+ return DEFAULT_RUNTIME_ROOT
48
+
49
+ runtime_root = Path(str(value)).expanduser()
50
+ if runtime_root.is_absolute() or registry_path is None:
51
+ return runtime_root
52
+ return registry_project_root(registry_path) / runtime_root
53
+
54
+
55
+ def rel_or_abs(path: Path, root: Path) -> str:
56
+ try:
57
+ return str(path.relative_to(root))
58
+ except ValueError:
59
+ return str(path)
@@ -0,0 +1,67 @@
1
+ # LoopX Pi goal mode
2
+
3
+ The Pi host adapter for LoopX. Pi is a terminal coding agent whose extensions
4
+ register commands, tools, and event handlers; this adapter turns a Pi session
5
+ into a LoopX-governed visible goal loop.
6
+
7
+ ## Surface
8
+
9
+ - **`/loopx`** — with no arguments, runs `loopx bootstrap-command-pack --project .`
10
+ and shows the packet as a widget plus a transcript entry. With a goal text
11
+ argument, runs `loopx start-goal --guided --project . --goal-text "<text>"
12
+ --host-surface pi` and places the returned packet in the editor for review.
13
+ `/loopx resume` re-arms auto-continuation after a user-driven pause.
14
+ - **`loopx_goal_activate`** — agent-callable tool. Binds the current session to
15
+ a LoopX goal (`goalId`, heartbeat `objective`/task_body, optional `agentId`,
16
+ `registryPath`, `availableCapabilities`), then starts the quota-gated loop.
17
+ - **Goal loop** — on every `agent_settled`, the extension probes
18
+ `loopx quota should-run --runtime-profile generic_cli` for the bound goal.
19
+ LoopX decides whether to continue (the heartbeat task_body is injected as a
20
+ follow-up), wait with scheduler-hint backoff (unchanged-poll limits apply), or
21
+ stop at a validated terminal no-follow-up. Probe failures fail closed with a
22
+ bounded retry; the extension never self-declares closure.
23
+
24
+ ## Install / uninstall
25
+
26
+ ```bash
27
+ loopx slash-commands --install --surface pi --pi-project .
28
+ loopx slash-commands --uninstall --surface pi --pi-project .
29
+ ```
30
+
31
+ Installs two LoopX-managed files into the project (loaded after project
32
+ trust):
33
+
34
+ - `.pi/extensions/loopx-goal.ts` — the extension adapter that registers
35
+ `/loopx`, `loopx_goal_activate`, and the `agent_settled` loop wiring.
36
+ - `.pi/extensions/pi-goal-loop-runtime.mjs` — the quota/wait/store loop core
37
+ (not auto-discovered as an extension; the adapter imports it directly).
38
+
39
+ Pi's extension loader aliases `typebox` and the `@earendil-works/*` packages,
40
+ so no local `node_modules` are required. The `--pi-project` flag points the
41
+ installer at the target project so the command is correct even when run from
42
+ another directory; `agent-onboard --agent-type pi --project <path>` emits the
43
+ resolved project automatically.
44
+
45
+ ## State
46
+
47
+ Bindings persist under `<project>/.loopx/pi/` (gitignored), keyed by session.
48
+ Override with `LOOPX_PI_STATE_DIR`. Invoke the CLI binary via `LOOPX_BIN`.
49
+
50
+ Sessions without a session file (`pi --no-session`) are ephemeral: the
51
+ adapter uses a unique in-memory identity per extension instance and never
52
+ persists its binding, so a later `--no-session` run cannot inherit the
53
+ previous run's goal and must activate again through `loopx_goal_activate`.
54
+
55
+ ## Boundary
56
+
57
+ The extension reads only LoopX public-safe state and never copies raw
58
+ transcripts, credentials, or local session paths. Continuation is governed by
59
+ LoopX quota; user prompts pause auto-resume; `/loopx resume` or re-activation
60
+ re-arms it. No external writes happen without the active LoopX state or owner
61
+ authorization.
62
+
63
+ On `session_shutdown` (session switch, fork, or reload) the extension instance
64
+ is atomically disposed: every timer is cancelled and an in-flight quota probe
65
+ that returns afterwards stops at the disposed guard, so the old session can
66
+ never inject a follow-up or reschedule past the reload / session-replacement
67
+ boundary.