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,1257 @@
1
+ from __future__ import annotations
2
+
3
+ from copy import deepcopy
4
+ import re
5
+ from typing import Any, Mapping, Sequence
6
+
7
+ from ...control_plane.todos.contract import (
8
+ TODO_TASK_CLASS_MONITOR,
9
+ normalize_todo_claimed_by,
10
+ normalize_todo_id,
11
+ )
12
+ from .harness_gate import (
13
+ GATE_STATE_ANALYSIS_ONLY,
14
+ GATE_STATE_DISABLED,
15
+ explore_harness_required_contract,
16
+ resolve_explore_harness_gate as _resolve_explore_harness_gate,
17
+ )
18
+ from .router_state import family_routing_terms, is_router_state
19
+ from .resource_portfolio import (
20
+ resource_assignment,
21
+ resource_lane_from_capabilities,
22
+ resource_portfolio_with_selection,
23
+ resolve_resource_portfolio,
24
+ )
25
+ from .speculative_scheduler import (
26
+ build_accept_reject_event,
27
+ calibrate_load_factor,
28
+ confident_bundle_prefix_length,
29
+ partition_invalidated_successors,
30
+ schedule_confidence_prefix,
31
+ schedule_independent_lanes,
32
+ )
33
+ from .todo_branch_plan import (
34
+ DEFAULT_BRANCH_WIDTH,
35
+ MAX_BRANCH_WIDTH,
36
+ _branch_confidence,
37
+ _branch_expected_evidence_units,
38
+ _branch_score,
39
+ _claim_command,
40
+ _compact_text,
41
+ _frontier_tokens,
42
+ _lease_command,
43
+ _monitor_lane_exclusion,
44
+ _required_capabilities,
45
+ _required_write_scopes,
46
+ _shared_dependency_capabilities,
47
+ _scopes_overlap,
48
+ )
49
+ from ...control_plane.todos.projection import todo_item_task_class, todo_projection_sort_key
50
+
51
+
52
+ WORKER_BRANCH_PLAN_SCHEMA_VERSION = "loopx_explore_worker_branch_plan_v0"
53
+ WORKER_HARNESS_PROFILE_SCHEMA_VERSION = "loopx_explore_worker_harness_profile_v0"
54
+ DEFAULT_TODOS_PER_WORKER_BRANCH = 3
55
+ MAX_TODOS_PER_WORKER_BRANCH = 8
56
+ # Worker lanes are independent parallel worker processes; their width ceiling
57
+ # must not inherit MAX_BRANCH_WIDTH=8 from the serial todo-branch planner
58
+ # (that clamp silently capped a requested width of 10 at 8 in an early
59
+ # long-horizon calibration run).
60
+ MAX_WORKER_LANES = 16
61
+ DEFAULT_WORKER_HARNESS_PROFILE = "generic"
62
+ BRANCH_FILL_POLICIES = {"bundle-by-affinity", "value-first", "confident-prefix"}
63
+
64
+ WORKER_HARNESS_PROFILES: dict[str, dict[str, Any]] = {
65
+ "generic": {
66
+ "schema_version": WORKER_HARNESS_PROFILE_SCHEMA_VERSION,
67
+ "profile": "generic",
68
+ "source": "loopx_explore_worker_branch_plan_default",
69
+ "design_intent": "Generic dry-run worker-lane planning without runtime policy assumptions.",
70
+ "branch_fill_policy": "bundle-by-affinity",
71
+ "concurrency_policy": {
72
+ "mode": "bounded_confidence_prefix",
73
+ "fixed_worker_count": False,
74
+ "does_not_force_requested_width": True,
75
+ },
76
+ "duration_guard": {
77
+ "enabled": False,
78
+ "controlled_by_planner": False,
79
+ },
80
+ "retry_policy": {
81
+ "enabled": False,
82
+ "controlled_by_planner": False,
83
+ },
84
+ "infra_cooldown": {
85
+ "enabled": False,
86
+ "controlled_by_planner": False,
87
+ },
88
+ "todo_batching_policy": {
89
+ "mode": "fixed_safety_ceiling",
90
+ "default_ceiling": DEFAULT_TODOS_PER_WORKER_BRANCH,
91
+ "external_ceiling_role": "planner_batch_ceiling",
92
+ },
93
+ },
94
+ "adaptive-resilient": {
95
+ "schema_version": WORKER_HARNESS_PROFILE_SCHEMA_VERSION,
96
+ "profile": "adaptive-resilient",
97
+ "source": "generalized_from_long_horizon_calibration_evidence",
98
+ "design_intent": (
99
+ "Generalize the best observed harness traits without copying an experimental "
100
+ "N value, duration limit, or saturated-fill policy. Lane width uses "
101
+ "independent-lane admission -- the serial survival-product prefix was a "
102
+ "structural mismatch for parallel lanes and under-filled requested width "
103
+ "in early calibration."
104
+ ),
105
+ "branch_fill_policy": "value-first",
106
+ "marginal_score_floor": 0.72,
107
+ "todo_batching_policy": {
108
+ "mode": "adaptive_value_scheduled",
109
+ "default_ceiling": MAX_TODOS_PER_WORKER_BRANCH,
110
+ "external_ceiling_required": False,
111
+ "external_ceiling_role": "optional_safety_cap_only",
112
+ "intent": (
113
+ "Let the planner decide whether to bundle extra todos into a worker lane "
114
+ "from marginal value, rather than forcing a per-worker todo count."
115
+ ),
116
+ },
117
+ "concurrency_policy": {
118
+ "mode": "independent_lane_admission",
119
+ "fixed_worker_count": False,
120
+ "does_not_force_requested_width": True,
121
+ "worker_width_is_ceiling": True,
122
+ "branch_count_is_value_scheduled": True,
123
+ },
124
+ "lane_start_stagger_seconds": 1.25,
125
+ "retry_policy": {
126
+ "enabled": True,
127
+ "uses_backoff": True,
128
+ "retryable_error_families": [
129
+ "provider_service_unreachable",
130
+ "transient_infra_failure",
131
+ ],
132
+ },
133
+ "infra_cooldown": {
134
+ "enabled": True,
135
+ "failure_threshold": 2,
136
+ "cooldown_epochs": 2,
137
+ "strict_skip_when_healthy_width_available": True,
138
+ },
139
+ "duration_guard": {
140
+ "enabled": False,
141
+ "controlled_by_planner": False,
142
+ "reason": "Duration limits are runner policy, not part of the generalized harness design.",
143
+ },
144
+ "coverage_floor": {
145
+ "enabled": False,
146
+ "reason": "An earlier coverage-floor calibration arm did not show enough value to become the default design.",
147
+ },
148
+ },
149
+ "moe-router": {
150
+ "schema_version": WORKER_HARNESS_PROFILE_SCHEMA_VERSION,
151
+ "profile": "moe-router",
152
+ "source": "moe_style_router_redesign",
153
+ "design_intent": (
154
+ "MoE-style value-first routing under a fixed worker ceiling: task families "
155
+ "are the experts, todos are routed tokens. Width via independent-lane "
156
+ "admission (interference-priced, never a fill rule); coverage via an "
157
+ "aux-loss-free per-family bias that only reorders routing (DeepSeek-V3 "
158
+ "invariant: bias never touches value bookkeeping); bundle length via the "
159
+ "DSpark confident-prefix cutoff (arXiv:2607.05147) with per-family "
160
+ "accept-rate calibration plus a wall-clock straggler guard."
161
+ ),
162
+ "branch_fill_policy": "confident-prefix",
163
+ "marginal_score_floor": 0.72,
164
+ "bundle_confidence_threshold": 0.6,
165
+ # 2.5 x median permits a 2-deep bundle at uniform measured durations
166
+ # while still fencing slow families; 1.25 would cap everything at 1
167
+ # and make the confident-prefix rule unreachable.
168
+ "bundle_straggler_factor": 2.5,
169
+ "todo_batching_policy": {
170
+ "mode": "confident_prefix_scheduled",
171
+ "default_ceiling": MAX_TODOS_PER_WORKER_BRANCH,
172
+ "external_ceiling_required": False,
173
+ "external_ceiling_role": "optional_safety_cap_only",
174
+ "intent": (
175
+ "DSpark-faithful bundle sizing: append todos while calibrated per-todo "
176
+ "acceptance confidence clears the threshold; truncate at the first "
177
+ "below-threshold todo; cap the serial tail by predicted wall-clock."
178
+ ),
179
+ },
180
+ "concurrency_policy": {
181
+ "mode": "independent_lane_admission",
182
+ "fixed_worker_count": False,
183
+ "does_not_force_requested_width": True,
184
+ "worker_width_is_ceiling": True,
185
+ "branch_count_is_value_scheduled": True,
186
+ },
187
+ "opportunistic_lane_policy": {
188
+ "enabled": True,
189
+ "target_utilization_floor": 0.65,
190
+ "min_lane_value_floor": 0.01,
191
+ "min_lane_value_ratio": 0.2,
192
+ "intent": (
193
+ "Keep the high-confidence core from the theta peak, "
194
+ "then admit additional positive-yield lanes up to a utilization floor "
195
+ "so B does not waste worker capacity after proving active-lane quality."
196
+ ),
197
+ },
198
+ "router_policy": {
199
+ "enabled": True,
200
+ "state_schema": "loopx_explore_router_state_v0",
201
+ "bias_affects_routing_order_only": True,
202
+ "admission_uses_unbiased_value": True,
203
+ "experts": "affinity families (scope:artifacts/<family>) declared via work-item write scopes",
204
+ },
205
+ "lane_start_stagger_seconds": 1.25,
206
+ "retry_policy": {
207
+ "enabled": True,
208
+ "uses_backoff": True,
209
+ "retryable_error_families": [
210
+ "provider_service_unreachable",
211
+ "transient_infra_failure",
212
+ ],
213
+ },
214
+ "infra_cooldown": {
215
+ "enabled": True,
216
+ "failure_threshold": 2,
217
+ "cooldown_epochs": 2,
218
+ "strict_skip_when_healthy_width_available": True,
219
+ },
220
+ "duration_guard": {
221
+ "enabled": False,
222
+ "controlled_by_planner": False,
223
+ "reason": "Duration limits are runner policy, not part of the harness design.",
224
+ },
225
+ "coverage_floor": {
226
+ "enabled": False,
227
+ "reason": "Replaced by the aux-loss-free routing bias plus coverage recency bonus.",
228
+ },
229
+ },
230
+ }
231
+
232
+ COMMON_TOPIC_TOKENS = {
233
+ "add",
234
+ "after",
235
+ "agent",
236
+ "against",
237
+ "and",
238
+ "audit",
239
+ "before",
240
+ "between",
241
+ "branch",
242
+ "build",
243
+ "check",
244
+ "codex",
245
+ "continue",
246
+ "current",
247
+ "deliver",
248
+ "existing",
249
+ "explore",
250
+ "fix",
251
+ "from",
252
+ "goal",
253
+ "inspect",
254
+ "into",
255
+ "latest",
256
+ "loopx",
257
+ "new",
258
+ "next",
259
+ "one",
260
+ "p0",
261
+ "p1",
262
+ "p2",
263
+ "recent",
264
+ "review",
265
+ "run",
266
+ "test",
267
+ "the",
268
+ "then",
269
+ "this",
270
+ "through",
271
+ "todo",
272
+ "update",
273
+ "validate",
274
+ "when",
275
+ "while",
276
+ "with",
277
+ "without",
278
+ }
279
+ TOKEN_PATTERN = re.compile(r"[A-Za-z0-9_:\-]{3,}")
280
+
281
+
282
+ def worker_harness_profile_names() -> tuple[str, ...]:
283
+ return tuple(sorted(WORKER_HARNESS_PROFILES))
284
+
285
+
286
+ def _worker_harness_profile(profile: str | None) -> dict[str, Any]:
287
+ normalized = str(profile or DEFAULT_WORKER_HARNESS_PROFILE).strip().lower().replace("_", "-")
288
+ if normalized not in WORKER_HARNESS_PROFILES:
289
+ choices = ", ".join(worker_harness_profile_names())
290
+ raise ValueError(f"unknown worker harness profile {profile!r}; expected one of: {choices}")
291
+ return deepcopy(WORKER_HARNESS_PROFILES[normalized])
292
+
293
+
294
+ def _normalize_branch_fill_policy(value: str | None, *, profile: Mapping[str, Any]) -> str:
295
+ policy = str(value or profile.get("branch_fill_policy") or "bundle-by-affinity").strip().lower()
296
+ policy = policy.replace("_", "-")
297
+ if policy not in BRANCH_FILL_POLICIES:
298
+ choices = ", ".join(sorted(BRANCH_FILL_POLICIES))
299
+ raise ValueError(f"unknown branch fill policy {value!r}; expected one of: {choices}")
300
+ return policy
301
+
302
+
303
+ def _resolve_todo_bundle_ceiling(
304
+ value: int | None,
305
+ *,
306
+ profile: Mapping[str, Any],
307
+ ) -> tuple[int, bool, str]:
308
+ """Return the worker-lane bundle ceiling and whether it was explicitly set."""
309
+
310
+ explicit = value is not None and int(value or 0) > 0
311
+ if explicit:
312
+ return max(1, min(MAX_TODOS_PER_WORKER_BRANCH, int(value or 1))), True, "explicit_safety_cap"
313
+ batching_policy = profile.get("todo_batching_policy") or {}
314
+ if str(batching_policy.get("mode") or "") == "adaptive_value_scheduled":
315
+ default_ceiling = int(batching_policy.get("default_ceiling") or MAX_TODOS_PER_WORKER_BRANCH)
316
+ return max(1, min(MAX_TODOS_PER_WORKER_BRANCH, default_ceiling)), False, "adaptive_planner_default"
317
+ if str(batching_policy.get("mode") or "") == "confident_prefix_scheduled":
318
+ default_ceiling = int(batching_policy.get("default_ceiling") or MAX_TODOS_PER_WORKER_BRANCH)
319
+ return (
320
+ max(1, min(MAX_TODOS_PER_WORKER_BRANCH, default_ceiling)),
321
+ False,
322
+ "confident_prefix_scheduler_safety_cap",
323
+ )
324
+ default_ceiling = int(batching_policy.get("default_ceiling") or DEFAULT_TODOS_PER_WORKER_BRANCH)
325
+ return max(1, min(MAX_TODOS_PER_WORKER_BRANCH, default_ceiling)), False, "profile_default"
326
+
327
+
328
+ def _ordered_topic_tokens(value: Any) -> list[str]:
329
+ """Return meaningful topic tokens in their original textual order."""
330
+
331
+ tokens: list[str] = []
332
+ seen: set[str] = set()
333
+ for match in TOKEN_PATTERN.finditer(str(value or "")):
334
+ token = match.group(0).lower()
335
+ if token in COMMON_TOPIC_TOKENS or token in seen:
336
+ continue
337
+ seen.add(token)
338
+ tokens.append(token)
339
+ return tokens
340
+
341
+
342
+ def _scope_family(scope: str) -> str:
343
+ clean = str(scope or "").replace("\\", "/").strip()
344
+ for marker in ("/**", "/*"):
345
+ if marker in clean:
346
+ clean = clean.split(marker, 1)[0]
347
+ parts = [part for part in clean.split("/") if part and part not in {".", "**", "*"}]
348
+ if len(parts) >= 2:
349
+ return "/".join(parts[:2])
350
+ if parts:
351
+ return parts[0]
352
+ return ""
353
+
354
+
355
+ def _affinity_key(candidate: Mapping[str, Any]) -> str:
356
+ scopes = [scope for scope in candidate.get("required_write_scopes") or [] if str(scope).strip()]
357
+ if scopes:
358
+ family = _scope_family(str(scopes[0]))
359
+ if family:
360
+ return f"scope:{family}"
361
+ capabilities = [
362
+ capability for capability in candidate.get("required_capabilities") or [] if str(capability).strip()
363
+ ]
364
+ if capabilities:
365
+ return f"capability:{str(capabilities[0]).strip()}"
366
+ tokens = _ordered_topic_tokens(candidate.get("text"))
367
+ if tokens:
368
+ return f"topic:{tokens[0]}"
369
+ return "topic:general"
370
+
371
+
372
+ def _claim_bucket(candidate: Mapping[str, Any], *, agent_id: str | None) -> int:
373
+ normalized_agent = normalize_todo_claimed_by(agent_id)
374
+ claimed_by = normalize_todo_claimed_by(candidate.get("claimed_by"))
375
+ if normalized_agent and claimed_by == normalized_agent:
376
+ return 0
377
+ if not claimed_by:
378
+ return 1
379
+ return 2
380
+
381
+
382
+ def _todo_candidate(
383
+ item: Mapping[str, Any],
384
+ *,
385
+ agent_id: str | None,
386
+ frontier: set[str],
387
+ ) -> dict[str, Any] | None:
388
+ todo_id = normalize_todo_id(item.get("todo_id"))
389
+ if not todo_id:
390
+ return None
391
+ score, reason_codes, hazards = _branch_score(
392
+ item,
393
+ agent_id=agent_id,
394
+ frontier=frontier,
395
+ )
396
+ task_class = todo_item_task_class(dict(item))
397
+ required_capabilities = _required_capabilities(item)
398
+ candidate = {
399
+ "todo_id": todo_id,
400
+ "text": _compact_text(item.get("text") or item.get("title")),
401
+ "priority": item.get("priority"),
402
+ "task_class": task_class,
403
+ "claimed_by": normalize_todo_claimed_by(item.get("claimed_by")) or "",
404
+ "required_write_scopes": _required_write_scopes(item),
405
+ "required_capabilities": required_capabilities,
406
+ "shared_dependency_capabilities": _shared_dependency_capabilities(item),
407
+ "resource_lane": resource_lane_from_capabilities(required_capabilities),
408
+ "depends_on": item.get("depends_on") or item.get("dependency_todo_ids") or item.get("blocked_by_todo_ids") or [],
409
+ "score": round(score, 2),
410
+ "confidence": _branch_confidence(score, hazards=hazards),
411
+ "expected_evidence_units": _branch_expected_evidence_units(
412
+ task_class=task_class,
413
+ reason_codes=reason_codes,
414
+ hazards=hazards,
415
+ ),
416
+ "reason_codes": reason_codes,
417
+ "hazards": hazards,
418
+ "claim_bucket": _claim_bucket(item, agent_id=agent_id),
419
+ "source_index": item.get("index"),
420
+ }
421
+ candidate["affinity_key"] = _affinity_key(candidate)
422
+ return candidate
423
+
424
+
425
+ def _dedupe_preserve_order(values: Sequence[Any]) -> list[str]:
426
+ seen: set[str] = set()
427
+ result: list[str] = []
428
+ for value in values:
429
+ text = str(value or "").strip()
430
+ if not text or text in seen:
431
+ continue
432
+ seen.add(text)
433
+ result.append(text)
434
+ return result
435
+
436
+
437
+ def _branch_id(affinity_key: str, *, index: int) -> str:
438
+ slug = re.sub(r"[^A-Za-z0-9_]+", "_", affinity_key).strip("_").lower() or "general"
439
+ return f"worker_branch_{index}_{slug}"
440
+
441
+
442
+ def _aggregate_confidence(bundle: Sequence[Mapping[str, Any]]) -> float:
443
+ if not bundle:
444
+ return 0.0
445
+ confidence = 1.0
446
+ for item in bundle:
447
+ confidence *= max(0.05, min(0.95, float(item.get("confidence") or 0.05)))
448
+ return round(confidence ** (1.0 / len(bundle)), 3)
449
+
450
+
451
+ def _branch_candidate(
452
+ *,
453
+ goal_id: str,
454
+ agent_id: str | None,
455
+ affinity_key: str,
456
+ bundle: Sequence[Mapping[str, Any]],
457
+ index: int,
458
+ router_terms: Mapping[str, Any] | None = None,
459
+ ) -> dict[str, Any]:
460
+ todo_bundle = [dict(item) for item in bundle]
461
+ todo_ids = [str(item["todo_id"]) for item in todo_bundle]
462
+ write_scopes = _dedupe_preserve_order(
463
+ scope for item in todo_bundle for scope in item.get("required_write_scopes") or []
464
+ )
465
+ capabilities = _dedupe_preserve_order(
466
+ capability for item in todo_bundle for capability in item.get("required_capabilities") or []
467
+ )
468
+ shared_dependency_capabilities = _dedupe_preserve_order(
469
+ capability
470
+ for item in todo_bundle
471
+ for capability in item.get("shared_dependency_capabilities") or []
472
+ )
473
+ dependencies = _dedupe_preserve_order(
474
+ dep for item in todo_bundle for dep in item.get("depends_on") or []
475
+ )
476
+ hazards = _dedupe_preserve_order(
477
+ hazard for item in todo_bundle for hazard in item.get("hazards") or []
478
+ )
479
+ branch_id = _branch_id(affinity_key, index=index)
480
+ resource_lanes = _dedupe_preserve_order(
481
+ item.get("resource_lane") for item in todo_bundle if item.get("resource_lane")
482
+ )
483
+ if len(resource_lanes) > 1:
484
+ raise ValueError("a worker branch cannot bundle todos from multiple resource lanes")
485
+ expected_evidence = round(
486
+ sum(float(item.get("expected_evidence_units") or 0.0) for item in todo_bundle),
487
+ 3,
488
+ )
489
+ score = round(sum(float(item.get("score") or 0.0) for item in todo_bundle), 2)
490
+ commands: list[str] = []
491
+ for item in todo_bundle:
492
+ todo_id = str(item["todo_id"])
493
+ commands.extend(
494
+ command
495
+ for command in (
496
+ _claim_command(goal_id=goal_id, todo_id=todo_id, agent_id=agent_id),
497
+ _lease_command(
498
+ goal_id=goal_id,
499
+ todo_id=todo_id,
500
+ agent_id=agent_id,
501
+ write_scopes=item.get("required_write_scopes") or [],
502
+ ),
503
+ )
504
+ if command
505
+ )
506
+ aggregate_confidence = _aggregate_confidence(todo_bundle)
507
+ candidate = {
508
+ "branch_id": branch_id,
509
+ "todo_id": branch_id,
510
+ "affinity_key": affinity_key,
511
+ "objective_slice": affinity_key.removeprefix("scope:").removeprefix("capability:").removeprefix("topic:"),
512
+ "todo_ids": todo_ids,
513
+ "todo_bundle": todo_bundle,
514
+ "required_write_scopes": write_scopes,
515
+ "required_capabilities": capabilities,
516
+ "shared_dependency_capabilities": shared_dependency_capabilities,
517
+ "resource_lane": resource_lanes[0] if resource_lanes else "",
518
+ "depends_on": dependencies,
519
+ "score": score,
520
+ "confidence": aggregate_confidence,
521
+ "expected_evidence_units": expected_evidence,
522
+ "hazards": hazards,
523
+ "suggested_commands": commands,
524
+ "merge_policy": "merge only verified node/edge/finding evidence through LoopX explore result_log",
525
+ "rollback_policy": "record rejected/dead-end evidence; do not mutate active state from the plan packet",
526
+ }
527
+ if router_terms:
528
+ # Bias enters ONLY routing_score (ordering); calibrated confidence and
529
+ # novelty-adjusted evidence stay bias-free so admission and all
530
+ # reported value bookkeeping remain unbiased (aux-loss-free invariant).
531
+ # Zero is a meaningful value for these terms, so guard on None -- an
532
+ # `or`-default would silently turn a fully-depleted/rejected family
533
+ # back into a fresh one.
534
+ multiplier = router_terms.get("routing_multiplier")
535
+ accept_rate = router_terms.get("accept_rate")
536
+ novelty = router_terms.get("novelty")
537
+ candidate["router"] = dict(router_terms)
538
+ candidate["routing_score"] = round(
539
+ score * (float(multiplier) if multiplier is not None else 1.0), 2
540
+ )
541
+ candidate["calibrated_confidence"] = round(
542
+ max(
543
+ 0.05,
544
+ min(
545
+ 0.95,
546
+ aggregate_confidence
547
+ * (float(accept_rate) if accept_rate is not None else 1.0),
548
+ ),
549
+ ),
550
+ 3,
551
+ )
552
+ candidate["novelty_adjusted_evidence_units"] = round(
553
+ expected_evidence * (float(novelty) if novelty is not None else 1.0),
554
+ 3,
555
+ )
556
+ return candidate
557
+
558
+
559
+ def _confident_prefix_bundles(
560
+ bucket: Sequence[Mapping[str, Any]],
561
+ *,
562
+ chunk_size: int,
563
+ confidence_threshold: float,
564
+ straggler_factor: float,
565
+ router_terms: Mapping[str, Any] | None,
566
+ median_duration_minutes: float | None,
567
+ ) -> list[list[dict[str, Any]]]:
568
+ """DSpark-faithful bundle sizing (arXiv:2607.05147).
569
+
570
+ A lane's serial todo bundle is the draft block: append todos while the
571
+ calibrated per-todo acceptance confidence (plan confidence x learned
572
+ family accept rate) clears the threshold, truncating at the first
573
+ below-threshold todo. Unlike DSpark -- where drafting is nearly free -- a
574
+ serial todo costs real wall-clock, so a straggler guard caps the bundle
575
+ so its predicted wall stays within ``straggler_factor`` x the median
576
+ single-probe duration. A lane always carries at least its seed todo.
577
+ """
578
+
579
+ raw_accept_rate = (router_terms or {}).get("accept_rate")
580
+ accept_rate = float(raw_accept_rate) if raw_accept_rate is not None else 1.0
581
+ family_duration = float((router_terms or {}).get("duration_minutes") or 0.0)
582
+ max_by_wall = chunk_size
583
+ if (
584
+ straggler_factor > 0
585
+ and median_duration_minutes
586
+ and family_duration > 0
587
+ # Only bind the wall cap on MEASURED durations: cold-start defaults are
588
+ # uniform by construction and would silently cap every bundle at the
589
+ # floor, turning the confident-prefix rule into dead code.
590
+ and bool((router_terms or {}).get("duration_observed"))
591
+ ):
592
+ max_by_wall = max(
593
+ 1, int((straggler_factor * median_duration_minutes) // max(family_duration, 0.05))
594
+ )
595
+ bundles: list[list[dict[str, Any]]] = []
596
+ remaining = list(bucket)
597
+ while remaining:
598
+ window = remaining[: max(1, chunk_size)]
599
+ confidences = [
600
+ max(0.0, min(1.0, float(item.get("confidence") or 0.0) * accept_rate))
601
+ for item in window
602
+ ]
603
+ prefix = confident_bundle_prefix_length(
604
+ confidences,
605
+ threshold=confidence_threshold,
606
+ max_length=chunk_size,
607
+ )
608
+ length = min(max(1, prefix), max_by_wall)
609
+ bundles.append(remaining[:length])
610
+ remaining = remaining[length:]
611
+ return bundles
612
+
613
+
614
+ def _build_worker_branch_candidates(
615
+ *,
616
+ goal_id: str,
617
+ todos: Sequence[Mapping[str, Any]],
618
+ projection: Mapping[str, Any] | None,
619
+ agent_id: str | None,
620
+ max_todos_per_branch: int,
621
+ branch_fill_policy: str,
622
+ marginal_score_floor: float,
623
+ bundle_confidence_threshold: float = 0.0,
624
+ bundle_straggler_factor: float = 0.0,
625
+ router_state: Mapping[str, Any] | None = None,
626
+ ) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
627
+ normalized_agent = normalize_todo_claimed_by(agent_id)
628
+ frontier = _frontier_tokens(projection)
629
+ todo_candidates = [
630
+ candidate
631
+ for item in todos
632
+ if (candidate := _todo_candidate(item, agent_id=normalized_agent, frontier=frontier))
633
+ ]
634
+ todo_candidates.sort(
635
+ key=lambda item: (
636
+ -float(item.get("score") or 0.0),
637
+ int(item.get("claim_bucket") or 9),
638
+ *todo_projection_sort_key(item),
639
+ str(item.get("todo_id") or ""),
640
+ )
641
+ )
642
+
643
+ monitor_lanes = [
644
+ exclusion
645
+ for candidate in todo_candidates
646
+ if (exclusion := _monitor_lane_exclusion(candidate)) is not None
647
+ ]
648
+ blocked = [
649
+ {**candidate, "selection_status": "blocked_claimed_by_other"}
650
+ for candidate in todo_candidates
651
+ if candidate.get("task_class") != TODO_TASK_CLASS_MONITOR
652
+ if candidate.get("claimed_by") and candidate.get("claimed_by") != normalized_agent
653
+ ]
654
+ eligible = [
655
+ candidate
656
+ for candidate in todo_candidates
657
+ if candidate.get("task_class") != TODO_TASK_CLASS_MONITOR
658
+ if not (candidate.get("claimed_by") and candidate.get("claimed_by") != normalized_agent)
659
+ ]
660
+
661
+ buckets: dict[tuple[str, str], list[dict[str, Any]]] = {}
662
+ for candidate in eligible:
663
+ bucket_key = (
664
+ str(candidate.get("resource_lane") or ""),
665
+ str(candidate.get("affinity_key") or "topic:general"),
666
+ )
667
+ buckets.setdefault(bucket_key, []).append(candidate)
668
+
669
+ router_enabled = is_router_state(router_state)
670
+ terms_by_family: dict[tuple[str, str], dict[str, Any]] = {}
671
+ if router_enabled:
672
+ terms_by_family = {
673
+ bucket_key: family_routing_terms(router_state, bucket_key[1])
674
+ for bucket_key in buckets
675
+ }
676
+ known_durations = sorted(
677
+ terms.get("duration_minutes")
678
+ for terms in terms_by_family.values()
679
+ if terms.get("duration_minutes") and terms.get("duration_observed")
680
+ )
681
+ median_duration = (
682
+ float(known_durations[len(known_durations) // 2]) if known_durations else None
683
+ )
684
+
685
+ def _bucket_sort_key(item: tuple[tuple[str, str], list[dict[str, Any]]]) -> tuple:
686
+ bucket_key, bucket = item
687
+ resource_lane, affinity_key = bucket_key
688
+ total_score = sum(float(todo.get("score") or 0.0) for todo in bucket)
689
+ if router_enabled:
690
+ routing_value = float(
691
+ (terms_by_family.get(bucket_key) or {}).get("routing_value") or 0.0
692
+ )
693
+ return (-routing_value, -total_score, resource_lane, affinity_key)
694
+ return (-total_score, resource_lane, affinity_key)
695
+
696
+ branch_candidates: list[dict[str, Any]] = []
697
+ branch_index = 0
698
+ chunk_size = max(1, min(MAX_TODOS_PER_WORKER_BRANCH, int(max_todos_per_branch or 1)))
699
+ score_floor = max(0.0, min(1.0, float(marginal_score_floor)))
700
+ for bucket_key, bucket in sorted(buckets.items(), key=_bucket_sort_key):
701
+ _, affinity_key = bucket_key
702
+ router_terms = terms_by_family.get(bucket_key)
703
+ bundles: list[list[dict[str, Any]]] = []
704
+ if branch_fill_policy == "confident-prefix":
705
+ bundles = _confident_prefix_bundles(
706
+ bucket,
707
+ chunk_size=chunk_size,
708
+ confidence_threshold=max(0.0, min(1.0, float(bundle_confidence_threshold))),
709
+ straggler_factor=max(0.0, float(bundle_straggler_factor)),
710
+ router_terms=router_terms,
711
+ median_duration_minutes=median_duration,
712
+ )
713
+ elif branch_fill_policy == "value-first":
714
+ remaining = list(bucket)
715
+ while remaining:
716
+ seed = remaining.pop(0)
717
+ bundle = [seed]
718
+ seed_score = max(0.001, float(seed.get("score") or 0.001))
719
+ while remaining and len(bundle) < chunk_size:
720
+ next_score = float(remaining[0].get("score") or 0.0)
721
+ if next_score < seed_score * score_floor:
722
+ break
723
+ bundle.append(remaining.pop(0))
724
+ bundles.append(bundle)
725
+ else:
726
+ bundles = [bucket[offset : offset + chunk_size] for offset in range(0, len(bucket), chunk_size)]
727
+ for bundle in bundles:
728
+ branch_index += 1
729
+ branch_candidates.append(
730
+ _branch_candidate(
731
+ goal_id=goal_id,
732
+ agent_id=normalized_agent,
733
+ affinity_key=affinity_key,
734
+ bundle=bundle,
735
+ index=branch_index,
736
+ router_terms=router_terms,
737
+ )
738
+ )
739
+
740
+ def _branch_sort_key(item: Mapping[str, Any]) -> tuple:
741
+ if router_enabled:
742
+ primary = -float(item.get("routing_score") or item.get("score") or 0.0)
743
+ else:
744
+ primary = -float(item.get("score") or 0.0)
745
+ return (
746
+ primary,
747
+ -float(item.get("expected_evidence_units") or 0.0),
748
+ str(item.get("branch_id") or ""),
749
+ )
750
+
751
+ branch_candidates.sort(key=_branch_sort_key)
752
+ return branch_candidates, [*monitor_lanes, *blocked]
753
+
754
+
755
+ def _baseline_worker_lanes(branch_candidates: Sequence[Mapping[str, Any]], *, width: int) -> dict[str, Any]:
756
+ selected = list(branch_candidates[: max(1, int(width or 1))])
757
+ return {
758
+ "strategy": "loopx_priority_order_worker_lanes",
759
+ "selected_branch_ids": [item.get("branch_id") for item in selected],
760
+ "expected_evidence_units": round(
761
+ sum(float(item.get("expected_evidence_units") or 0.0) for item in selected),
762
+ 3,
763
+ ),
764
+ "confidence_mean": round(
765
+ sum(float(item.get("confidence") or 0.0) for item in selected) / max(1, len(selected)),
766
+ 3,
767
+ ),
768
+ }
769
+
770
+
771
+ def resolve_explore_harness_gate(
772
+ orchestration: Mapping[str, Any] | None,
773
+ *,
774
+ requested_width: int,
775
+ ) -> dict[str, Any]:
776
+ """Resolve the shared explore-harness gate with this planner's lane ceiling."""
777
+
778
+ return _resolve_explore_harness_gate(
779
+ orchestration,
780
+ requested_width=requested_width,
781
+ max_lanes=MAX_WORKER_LANES,
782
+ max_lanes_label="max_worker_lanes",
783
+ )
784
+
785
+
786
+ def _disabled_worker_branch_plan(
787
+ *,
788
+ goal_id: str,
789
+ agent_id: str | None,
790
+ gate: Mapping[str, Any],
791
+ ) -> dict[str, Any]:
792
+ return {
793
+ "ok": True,
794
+ "schema_version": WORKER_BRANCH_PLAN_SCHEMA_VERSION,
795
+ "goal_id": goal_id,
796
+ "agent_id": normalize_todo_claimed_by(agent_id) or "",
797
+ "experimental": True,
798
+ "dry_run": True,
799
+ "enabled": False,
800
+ "strategy": "explore_harness_disabled",
801
+ "orchestration_gate": dict(gate),
802
+ "required_contract": explore_harness_required_contract(
803
+ default_profile=DEFAULT_WORKER_HARNESS_PROFILE
804
+ ),
805
+ "worker_width": 0,
806
+ "max_worker_lanes": MAX_WORKER_LANES,
807
+ "branch_candidate_count": 0,
808
+ "excluded_monitor_todo_count": 0,
809
+ "selected_worker_branch_count": 0,
810
+ "selected_worker_branches": [],
811
+ "rejected_worker_branches": [],
812
+ "accept_reject_trace": [],
813
+ "boundary": {
814
+ "writes_state": False,
815
+ "claims_todos": False,
816
+ "acquires_leases": False,
817
+ "starts_agents": False,
818
+ "changes_quota": False,
819
+ },
820
+ "next_action": (
821
+ "Worker-lane planning is not enabled for this goal. Opt in by setting "
822
+ "explore_harness.enabled=true on the registered goal's spawn_policy "
823
+ "(projected into quota should-run as goal_boundary.orchestration), then "
824
+ "rerun worker-branch-plan; execution always stays in the normal LoopX "
825
+ "quota/claim/lease lifecycle."
826
+ ),
827
+ }
828
+
829
+
830
+ def build_explore_worker_branch_plan(
831
+ *,
832
+ goal_id: str,
833
+ todos: Sequence[Mapping[str, Any]],
834
+ projection: Mapping[str, Any] | None = None,
835
+ agent_id: str | None = None,
836
+ orchestration: Mapping[str, Any] | None = None,
837
+ worker_width: int = DEFAULT_BRANCH_WIDTH,
838
+ max_todos_per_branch: int | None = None,
839
+ scheduler_load: float = 0.2,
840
+ allow_unscoped_parallel: bool = True,
841
+ harness_profile: str = DEFAULT_WORKER_HARNESS_PROFILE,
842
+ branch_fill_policy: str | None = None,
843
+ marginal_score_floor: float | None = None,
844
+ router_state: Mapping[str, Any] | None = None,
845
+ load_profile: Mapping[str, Any] | None = None,
846
+ resource_capacities: Mapping[str, int] | None = None,
847
+ resource_usage: Mapping[str, int] | None = None,
848
+ ) -> dict[str, Any]:
849
+ """Plan worker-lane branches on top of the existing LoopX harness.
850
+
851
+ The packet is deliberately read-only: it consumes LoopX todo/projection
852
+ state and emits worker-lane bundles plus suggested claim/lease commands,
853
+ but it does not launch workers or mutate quota, leases, todos, or state.
854
+
855
+ ``orchestration`` is the registered goal's ``spawn_policy`` -- the single
856
+ source projected into ``goal_boundary.orchestration``. Planning is gated on
857
+ ``explore_harness.enabled`` (default deny, including when no boundary is
858
+ provided), suggested commands require ``spawn_allowed``, and worker width
859
+ is capped by ``max_children`` in addition to ``MAX_WORKER_LANES``.
860
+
861
+ ``router_state`` (see ``router_state.py``) carries cross-epoch learned
862
+ per-family statistics maintained by the runner; it is consumed only by
863
+ profiles whose ``router_policy`` enables it. ``load_profile`` carries the
864
+ runner's observed parallel timings for ``calibrate_load_factor`` so lane
865
+ admission prices measured interference instead of a hardcoded prior.
866
+ """
867
+
868
+ normalized_agent = normalize_todo_claimed_by(agent_id)
869
+ resource_portfolio = resolve_resource_portfolio(resource_capacities, resource_usage)
870
+ requested_width = max(1, int(worker_width or DEFAULT_BRANCH_WIDTH))
871
+ gate = resolve_explore_harness_gate(orchestration, requested_width=requested_width)
872
+ if gate["state"] == GATE_STATE_DISABLED:
873
+ return _disabled_worker_branch_plan(goal_id=goal_id, agent_id=normalized_agent, gate=gate)
874
+ pinned_profile = gate.get("goal_pinned_profile")
875
+ profile = _worker_harness_profile(str(pinned_profile) if pinned_profile else harness_profile)
876
+ gate["requested_profile"] = str(harness_profile or DEFAULT_WORKER_HARNESS_PROFILE)
877
+ gate["effective_profile"] = profile.get("profile")
878
+ gate["profile_source"] = "goal_boundary" if pinned_profile else "planner_request"
879
+ normalized_fill_policy = _normalize_branch_fill_policy(branch_fill_policy, profile=profile)
880
+ normalized_marginal_floor = (
881
+ float(marginal_score_floor)
882
+ if marginal_score_floor is not None
883
+ else float(profile.get("marginal_score_floor") or 0.0)
884
+ )
885
+ normalized_width = int(gate["effective_width"])
886
+
887
+ router_policy = profile.get("router_policy") or {}
888
+ router_supported = bool(router_policy.get("enabled"))
889
+ router_provided = is_router_state(router_state)
890
+ router_used = router_supported and router_provided
891
+
892
+ load_calibration: dict[str, Any] | None = None
893
+ effective_load = max(0.0, min(1.0, float(scheduler_load)))
894
+ if load_profile:
895
+ load_calibration = calibrate_load_factor(
896
+ load_profile,
897
+ fallback_load_factor=effective_load,
898
+ )
899
+ effective_load = float(load_calibration.get("load_factor") or effective_load)
900
+
901
+ normalized_max_todos, max_todos_explicit, max_todos_source = _resolve_todo_bundle_ceiling(
902
+ max_todos_per_branch,
903
+ profile=profile,
904
+ )
905
+ branch_candidates, blocked_todos = _build_worker_branch_candidates(
906
+ goal_id=goal_id,
907
+ todos=todos,
908
+ projection=projection,
909
+ agent_id=normalized_agent,
910
+ max_todos_per_branch=normalized_max_todos,
911
+ branch_fill_policy=normalized_fill_policy,
912
+ marginal_score_floor=normalized_marginal_floor,
913
+ bundle_confidence_threshold=float(profile.get("bundle_confidence_threshold") or 0.0),
914
+ bundle_straggler_factor=float(profile.get("bundle_straggler_factor") or 0.0),
915
+ router_state=router_state if router_used else None,
916
+ )
917
+ excluded_monitor_todo_count = sum(
918
+ item.get("selection_status") == "excluded_non_exploration_lane"
919
+ for item in blocked_todos
920
+ )
921
+ if gate["state"] == GATE_STATE_ANALYSIS_ONLY:
922
+ # Analysis stays available (ranking, bundles, A/B estimate), but the
923
+ # boundary forbids spawning workers, so no claim/lease commands leave
924
+ # the planner in any branch list.
925
+ for branch in branch_candidates:
926
+ branch["suggested_commands"] = []
927
+ branch["commands_suppressed_reason"] = str(gate.get("reason") or "")
928
+ concurrency_mode = str((profile.get("concurrency_policy") or {}).get("mode") or "")
929
+ if concurrency_mode == "independent_lane_admission":
930
+ opportunistic_policy = profile.get("opportunistic_lane_policy") or {}
931
+ # Admission consumes UNBIASED value terms (calibrated confidence and
932
+ # novelty-adjusted evidence carry no routing bias); the bias already
933
+ # did its only job upstream by reordering branch_candidates.
934
+ scheduler_view = [
935
+ {
936
+ "todo_id": branch.get("branch_id"),
937
+ "confidence": branch.get("calibrated_confidence", branch.get("confidence")),
938
+ "expected_evidence_units": branch.get(
939
+ "novelty_adjusted_evidence_units", branch.get("expected_evidence_units")
940
+ ),
941
+ }
942
+ for branch in branch_candidates
943
+ ]
944
+ scheduler = schedule_independent_lanes(
945
+ scheduler_view,
946
+ max_width=normalized_width,
947
+ load_factor=effective_load,
948
+ opportunistic_utilization_floor=(
949
+ float(opportunistic_policy.get("target_utilization_floor") or 0.0)
950
+ if opportunistic_policy.get("enabled")
951
+ else 0.0
952
+ ),
953
+ opportunistic_lane_value_floor=(
954
+ float(opportunistic_policy.get("min_lane_value_floor") or 0.0)
955
+ if opportunistic_policy.get("enabled")
956
+ else 0.0
957
+ ),
958
+ opportunistic_lane_value_ratio=(
959
+ float(opportunistic_policy.get("min_lane_value_ratio") or 0.0)
960
+ if opportunistic_policy.get("enabled")
961
+ else 0.0
962
+ ),
963
+ )
964
+ else:
965
+ scheduler = schedule_confidence_prefix(
966
+ branch_candidates,
967
+ max_width=normalized_width,
968
+ max_branch_width=MAX_BRANCH_WIDTH,
969
+ load_factor=effective_load,
970
+ )
971
+ verification_budget = max(1, int(scheduler.get("selected_prefix_length") or 1))
972
+ profile["branch_fill_policy"] = normalized_fill_policy
973
+ profile["marginal_score_floor"] = round(max(0.0, min(1.0, normalized_marginal_floor)), 3)
974
+ profile["worker_width_ceiling"] = normalized_width
975
+ profile["max_todos_per_branch_ceiling"] = normalized_max_todos
976
+ profile["max_todos_per_branch_ceiling_explicit"] = max_todos_explicit
977
+ profile["max_todos_per_branch_ceiling_source"] = max_todos_source
978
+ profile["scheduler_load"] = scheduler.get("load_factor")
979
+ profile["scheduler_model"] = scheduler.get("strategy")
980
+
981
+ selection_budget = normalized_width if resource_portfolio["enabled"] else verification_budget
982
+ ordered_branches = list(branch_candidates)
983
+ if resource_portfolio["enabled"]:
984
+ ordered_branches.sort(key=lambda item: 0 if item.get("resource_lane") else 1)
985
+
986
+ invalidated_branch_ids: set[str] = set()
987
+ dependency_rejections: list[dict[str, Any]] = []
988
+ invalidation_events: list[dict[str, Any]] = []
989
+ while True:
990
+ selected = []
991
+ selection_rejections: list[dict[str, Any]] = []
992
+ selected_scopes: list[tuple[str, list[str]]] = []
993
+ selected_by_resource_lane: dict[str, int] = {}
994
+ for branch in ordered_branches:
995
+ branch_id = str(branch.get("branch_id") or "")
996
+ if branch_id in invalidated_branch_ids:
997
+ continue
998
+ branch_scopes = list(branch.get("required_write_scopes") or [])
999
+ resource_lane = str(branch.get("resource_lane") or "")
1000
+ conflict_with = ""
1001
+ if branch_scopes:
1002
+ for selected_branch_id, selected_branch_scopes in selected_scopes:
1003
+ if _scopes_overlap(branch_scopes, selected_branch_scopes):
1004
+ conflict_with = selected_branch_id
1005
+ break
1006
+ elif not allow_unscoped_parallel and selected:
1007
+ conflict_with = str(selected[0].get("branch_id") or "")
1008
+
1009
+ if conflict_with:
1010
+ selection_rejections.append(
1011
+ {
1012
+ **branch,
1013
+ "selection_status": "rejected_hazard",
1014
+ "conflict_with": conflict_with,
1015
+ "hazards": [
1016
+ *list(branch.get("hazards") or []),
1017
+ f"worker_branch_conflict:{conflict_with}",
1018
+ ],
1019
+ }
1020
+ )
1021
+ continue
1022
+ if resource_portfolio["enabled"] and resource_lane:
1023
+ lane = resource_portfolio["lanes"].get(resource_lane)
1024
+ if lane is None:
1025
+ selection_rejections.append(
1026
+ {
1027
+ **branch,
1028
+ "selection_status": "rejected_resource_lane",
1029
+ "hazards": [
1030
+ *list(branch.get("hazards") or []),
1031
+ f"resource_capacity_undeclared:{resource_lane}",
1032
+ ],
1033
+ }
1034
+ )
1035
+ continue
1036
+ if selected_by_resource_lane.get(resource_lane, 0) >= int(
1037
+ lane.get("available_slots") or 0
1038
+ ):
1039
+ selection_rejections.append(
1040
+ {
1041
+ **branch,
1042
+ "selection_status": "resource_lane_capacity_exhausted",
1043
+ "hazards": [
1044
+ *list(branch.get("hazards") or []),
1045
+ f"resource_capacity_exhausted:{resource_lane}",
1046
+ ],
1047
+ }
1048
+ )
1049
+ continue
1050
+ if len(selected) >= selection_budget:
1051
+ selection_rejections.append(
1052
+ {**branch, "selection_status": "outside_verification_budget"}
1053
+ )
1054
+ continue
1055
+
1056
+ role = "primary" if not selected else "speculative_worker"
1057
+ selected_in_lane = selected_by_resource_lane.get(resource_lane, 0) + 1
1058
+ selected_branch = {
1059
+ **branch,
1060
+ "selection_status": "selected",
1061
+ "branch_role": role,
1062
+ "branch_index": len(selected),
1063
+ "worker_hint": f"worker-{len(selected) + 1}",
1064
+ "execution_contract": {
1065
+ "must_enter_loopx_harness": True,
1066
+ "requires_quota_should_run": True,
1067
+ "requires_todo_claim": True,
1068
+ "requires_task_lease_for_write_scopes": bool(branch_scopes),
1069
+ "writeback_surfaces": ["explore_result_log", "refresh_state", "quota_spend_slot"],
1070
+ },
1071
+ }
1072
+ assignment = resource_assignment(
1073
+ resource_portfolio,
1074
+ resource_lane=resource_lane,
1075
+ selected_count=selected_in_lane,
1076
+ )
1077
+ if assignment is not None:
1078
+ selected_branch["resource_assignment"] = assignment
1079
+ selected.append(selected_branch)
1080
+ selected_scopes.append((branch_id, branch_scopes))
1081
+ if resource_lane:
1082
+ selected_by_resource_lane[resource_lane] = selected_in_lane
1083
+
1084
+ valid_selected, invalidated, events = partition_invalidated_successors(
1085
+ selected,
1086
+ selected_ids=[
1087
+ todo_id
1088
+ for selected_branch in selected
1089
+ for todo_id in selected_branch.get("todo_ids") or []
1090
+ ],
1091
+ lane="worker_branch_plan",
1092
+ )
1093
+ if not invalidated:
1094
+ rejected = [*blocked_todos, *dependency_rejections, *selection_rejections]
1095
+ selected = valid_selected
1096
+ break
1097
+ new_invalidated_ids = {
1098
+ str(item.get("branch_id") or "") for item in invalidated
1099
+ } - invalidated_branch_ids
1100
+ dependency_rejections.extend(invalidated)
1101
+ invalidation_events.extend(events)
1102
+ invalidated_branch_ids.update(new_invalidated_ids)
1103
+ if not new_invalidated_ids:
1104
+ rejected = [*blocked_todos, *dependency_rejections, *selection_rejections]
1105
+ selected = valid_selected
1106
+ break
1107
+
1108
+ baseline = _baseline_worker_lanes(branch_candidates, width=normalized_width)
1109
+ treatment_expected = round(
1110
+ sum(float(branch.get("expected_evidence_units") or 0.0) for branch in selected),
1111
+ 3,
1112
+ )
1113
+ baseline_expected = max(0.001, float(baseline.get("expected_evidence_units") or 0.0))
1114
+ predicted_events = [
1115
+ build_accept_reject_event(
1116
+ lane="worker_branch_plan",
1117
+ event_type="predicted",
1118
+ todo_id=str(branch.get("branch_id") or ""),
1119
+ reason="worker_lane_selected_for_harness_execution",
1120
+ payload={
1121
+ "todo_ids": branch.get("todo_ids") or [],
1122
+ "worker_hint": branch.get("worker_hint"),
1123
+ "confidence": branch.get("confidence"),
1124
+ "expected_evidence_units": branch.get("expected_evidence_units"),
1125
+ },
1126
+ )
1127
+ for branch in selected
1128
+ ]
1129
+ return {
1130
+ "ok": True,
1131
+ "schema_version": WORKER_BRANCH_PLAN_SCHEMA_VERSION,
1132
+ "goal_id": goal_id,
1133
+ "agent_id": normalized_agent or "",
1134
+ "experimental": True,
1135
+ "dry_run": True,
1136
+ "enabled": True,
1137
+ "orchestration_gate": gate,
1138
+ "strategy": (
1139
+ "moe_router_worker_lane_prediction"
1140
+ if router_used
1141
+ else "independent_lane_worker_prediction"
1142
+ if concurrency_mode == "independent_lane_admission"
1143
+ else "dspark_worker_lane_prediction"
1144
+ ),
1145
+ "harness_profile": profile.get("profile"),
1146
+ "worker_harness_profile": profile,
1147
+ "worker_width": normalized_width,
1148
+ "requested_worker_width": requested_width,
1149
+ "max_worker_lanes": MAX_WORKER_LANES,
1150
+ "scheduler_model": scheduler.get("strategy"),
1151
+ "load_calibration": load_calibration,
1152
+ "router": {
1153
+ "enabled": router_used,
1154
+ "supported_by_profile": router_supported,
1155
+ "state_provided": router_provided,
1156
+ "state_schema_version": (router_state or {}).get("schema_version") if router_provided else None,
1157
+ "state_updated_epoch": (router_state or {}).get("updated_epoch") if router_provided else None,
1158
+ "known_family_count": len((router_state or {}).get("families") or {}) if router_provided else 0,
1159
+ "bias_affects_routing_order_only": True,
1160
+ },
1161
+ "admission_audit": scheduler.get("admission_audit"),
1162
+ "max_todos_per_branch": normalized_max_todos,
1163
+ "max_todos_per_branch_explicit": max_todos_explicit,
1164
+ "max_todos_per_branch_source": max_todos_source,
1165
+ "branch_fill_policy": normalized_fill_policy,
1166
+ "verification_budget": verification_budget,
1167
+ "selection_budget": selection_budget,
1168
+ "scheduler": scheduler,
1169
+ "harness_compatibility": {
1170
+ "uses_loopx_todo_projection": True,
1171
+ "uses_explore_projection": True,
1172
+ "gated_by_goal_boundary_orchestration": True,
1173
+ "replaces_loopx_runtime": False,
1174
+ "launches_workers": False,
1175
+ "mutates_quota_or_state": False,
1176
+ "claim_and_lease_are_suggested_only": True,
1177
+ "duration_guard_controlled_by_planner": False,
1178
+ "fixed_worker_count_controlled_by_planner": False,
1179
+ "forces_full_branch_fill": False,
1180
+ "todo_bundle_ceiling_is_safety_cap": max_todos_source in {
1181
+ "explicit_safety_cap",
1182
+ "adaptive_planner_default",
1183
+ "confident_prefix_scheduler_safety_cap",
1184
+ },
1185
+ "adaptive_todo_batching": max_todos_source in {
1186
+ "adaptive_planner_default",
1187
+ "confident_prefix_scheduler_safety_cap",
1188
+ },
1189
+ "confidence_prefix_todo_batching": (
1190
+ max_todos_source == "confident_prefix_scheduler_safety_cap"
1191
+ ),
1192
+ },
1193
+ "ab_result": {
1194
+ "schema_version": "loopx_explore_worker_branch_plan_ab_result_v0",
1195
+ "metric": "estimated_worker_lane_evidence_units",
1196
+ "baseline_strategy": baseline["strategy"],
1197
+ "treatment_strategy": "adaptive_worker_branch_plan_concurrent",
1198
+ "harness_profile": profile.get("profile"),
1199
+ "baseline_selected_branch_ids": baseline["selected_branch_ids"],
1200
+ "baseline_expected_evidence_units": baseline["expected_evidence_units"],
1201
+ "dspark_selected_branch_ids": [branch.get("branch_id") for branch in selected],
1202
+ "dspark_expected_evidence_units": treatment_expected,
1203
+ "estimated_speedup_vs_baseline": round(treatment_expected / baseline_expected, 3),
1204
+ "interpretation": (
1205
+ "Dry-run only: compares LoopX priority-order worker lanes with "
1206
+ "DSpark-style worker-lane bundles before any worker is launched."
1207
+ ),
1208
+ },
1209
+ "branch_candidate_count": len(branch_candidates),
1210
+ "excluded_monitor_todo_count": excluded_monitor_todo_count,
1211
+ "selected_worker_branch_count": len(selected),
1212
+ "selected_worker_branches": selected,
1213
+ "rejected_worker_branches": rejected[: max(0, normalized_width * 3)],
1214
+ "resource_portfolio": resource_portfolio_with_selection(resource_portfolio, selected),
1215
+ "accept_reject_trace": [*predicted_events, *invalidation_events],
1216
+ "execution_model": {
1217
+ "planner_layer": "experimental worker-branch planner",
1218
+ "execution_layer": "existing LoopX harness",
1219
+ "worker_branch_semantics": "one branch is a worker lane containing a bundle of LoopX todos",
1220
+ "monitor_lane_semantics": (
1221
+ "continuous_monitor todos remain visible as excluded diagnostics and do not "
1222
+ "consume worker width or enter todo bundles"
1223
+ ),
1224
+ "scope_conflict_semantics": (
1225
+ "only required_write_scopes create lane mutexes; shared_artifact:* and "
1226
+ "shared_implementation:* capabilities describe immutable shared inputs, while "
1227
+ "mutable shared builds remain required write scopes"
1228
+ ),
1229
+ "resource_lane_semantics": (
1230
+ "resource_lane:<key> capabilities consume only explicitly declared empty slots; "
1231
+ "continuous monitors consume none, and rejected lanes are backfilled in the same call"
1232
+ ),
1233
+ "branch_fill_semantics": (
1234
+ "max_todos_per_branch is a safety ceiling; adaptive profiles decide "
1235
+ "bundle size from marginal value and do not pad lanes to fill requested width"
1236
+ ),
1237
+ "commit_stage": "verified findings merge through explore node/edge/finding events",
1238
+ "next_cycle": "merged findings and blocked frontier feed the next planning call",
1239
+ },
1240
+ "boundary": {
1241
+ "writes_state": False,
1242
+ "claims_todos": False,
1243
+ "acquires_leases": False,
1244
+ "starts_agents": False,
1245
+ "changes_quota": False,
1246
+ },
1247
+ "next_action": (
1248
+ "Read-only analysis: this goal's orchestration boundary does not permit "
1249
+ "spawning workers, so no claim/lease commands are suggested. Update the "
1250
+ "registered goal's spawn_policy (spawn_allowed, max_children) to receive "
1251
+ "suggested commands; execution stays in the normal LoopX lifecycle."
1252
+ if gate["state"] == GATE_STATE_ANALYSIS_ONLY
1253
+ else "Use quota should-run, then execute each selected worker branch through "
1254
+ "normal LoopX claim, lease, todo execution, explore writeback, refresh-state, "
1255
+ "and quota spend-slot."
1256
+ ),
1257
+ }