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
loopx/state_refresh.py ADDED
@@ -0,0 +1,1416 @@
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ import json
5
+ import re
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ from .control_plane.runtime.time import now_local_iso
10
+ from .control_plane.work_items.delivery_batch_scale import (
11
+ DELIVERY_BATCH_SCALE_CHOICES as DELIVERY_BATCH_SCALE_CHOICES,
12
+ require_delivery_batch_scale,
13
+ )
14
+ from .control_plane.work_items.delivery_outcome import (
15
+ ACCOUNTABLE_DELIVERY_OUTCOMES,
16
+ DELIVERY_OUTCOME_CHOICES as DELIVERY_OUTCOME_CHOICES,
17
+ require_delivery_outcome,
18
+ )
19
+ from .control_plane.agents.workspace_guard import capture_delivery_workspace
20
+ from .control_plane.quota.settlement import (
21
+ SettlementIdentity,
22
+ find_settlement_writeback,
23
+ require_settlement_writeback,
24
+ resolve_heartbeat_settlement_identity,
25
+ resolve_settlement_delivery_workspace_causality,
26
+ settlement_result_payload,
27
+ )
28
+ from .control_plane.work_items.repair_delta import (
29
+ REPAIR_DELTA_CONTRACT_SCHEMA_VERSION as REPAIR_DELTA_CONTRACT_SCHEMA_VERSION,
30
+ REPAIR_DELTA_KIND_CHOICES as REPAIR_DELTA_KIND_CHOICES,
31
+ build_repair_delta_contract,
32
+ normalize_repair_delta_kinds,
33
+ repair_delta_kinds_have_accountable_progress,
34
+ )
35
+ from .control_plane.work_items.autonomous_replan_ack import (
36
+ latest_monitor_replan_frontier_identity,
37
+ watch_lane_continuation_todo_ids,
38
+ )
39
+ from .control_plane.work_items.progress_observation import (
40
+ normalize_progress_observation,
41
+ )
42
+ from .control_plane.work_items.semantic_replan_writeback import (
43
+ enforce_open_replan_writeback,
44
+ )
45
+ from .control_plane.runtime.shared_runtime_refresh_projection import (
46
+ build_shared_runtime_projection,
47
+ write_shared_runtime_projection,
48
+ )
49
+ from .control_plane.runtime.runtime_projection_route import (
50
+ compact_runtime_projection_route,
51
+ resolve_runtime_projection_route,
52
+ )
53
+ from .feedback import validate_local_control_text, validate_public_safe_text
54
+ from .file_lock import exclusive_file_lock
55
+ from .global_registry import sync_project_registry_to_global
56
+ from .history import (
57
+ load_index,
58
+ load_registry,
59
+ reserve_unique_run_paths,
60
+ unique_run_paths,
61
+ )
62
+ from .control_plane.runtime.local_state_write_correctness import build_local_state_write_correctness_dry_run_packet
63
+ from .paths import resolve_runtime_root
64
+ from .control_plane.goals.goal_vision import normalize_goal_vision_update
65
+ from .control_plane.goals.vision_checkpoint import (
66
+ build_vision_checkpoint,
67
+ normalize_vision_unchanged_reason,
68
+ )
69
+ from .control_plane.goals.goal_frontier import latest_agent_vision_from_runs
70
+ from .registry import registry_goals, resolve_state_file
71
+ from .runtime import validate_goal_id_path_segment
72
+ from .state_projection import state_projection_gap_warning
73
+ from .control_plane.todos.contract import (
74
+ TODO_TASK_CLASS_ADVANCEMENT,
75
+ TODO_TASK_CLASS_BLOCKER,
76
+ TODO_TASK_CLASS_MONITOR,
77
+ TODO_TASK_CLASS_USER_GATE,
78
+ normalize_todo_claimed_by,
79
+ )
80
+ from .control_plane.todos.active_state_todo_parser import parse_active_state_todos
81
+ from .control_plane.todos.completion_validation_accountability import (
82
+ require_accountable_completion_validation,
83
+ )
84
+
85
+ DEFAULT_REFRESH_CLASSIFICATION = "state_refreshed"
86
+ DEFAULT_REFRESH_ACTION = "inspect refreshed active goal state and continue the next bounded progress segment"
87
+ RECOMMENDED_ACTION_SOURCE_EXPLICIT = "explicit_arg"
88
+ RECOMMENDED_ACTION_SOURCE_ACTIVE_NEXT_ACTION = "active_state_next_action"
89
+ RECOMMENDED_ACTION_SOURCE_AGENT_TODO_FALLBACK = "agent_todo_fallback"
90
+ RECOMMENDED_ACTION_SOURCE_DEFAULT = "default_refresh_action"
91
+ GOAL_PROGRESS_SCOPE = "goal"
92
+ AGENT_LANE_PROGRESS_SCOPE = "agent_lane"
93
+ PROGRESS_SCOPE_CHOICES = (GOAL_PROGRESS_SCOPE, AGENT_LANE_PROGRESS_SCOPE)
94
+ RECOMMENDED_ACTION_SECTION_LINE_LIMIT = 16
95
+ BULLET_PREFIX_RE = re.compile(r"^(?:[-*]\s+|\d+[.)]\s+)")
96
+ CHECKBOX_PREFIX_RE = re.compile(r"^\[(?P<mark>[ xX])\]\s+")
97
+ ACTIVE_STATE_NEXT_ACTION_UPDATE_SCHEMA_VERSION = "active_state_next_action_update_v0"
98
+ REPAIR_NOOP_SCHEMA_VERSION = "repair_noop_v0"
99
+
100
+
101
+ def now_local() -> str:
102
+ return now_local_iso()
103
+
104
+
105
+ def run_file_stem(generated_at: str) -> str:
106
+ return re.sub(r"[^0-9A-Za-z-]+", "-", generated_at).strip("-")
107
+
108
+
109
+ def parse_frontmatter(text: str) -> dict[str, str]:
110
+ if not text.startswith("---"):
111
+ return {}
112
+ parts = text.split("---", 2)
113
+ if len(parts) < 3:
114
+ return {}
115
+ values: dict[str, str] = {}
116
+ for line in parts[1].splitlines():
117
+ if ":" not in line:
118
+ continue
119
+ key, value = line.split(":", 1)
120
+ value = value.strip().strip('"')
121
+ values[key.strip()] = value
122
+ return values
123
+
124
+
125
+ def extract_section_lines(text: str, heading: str, limit: int = 8) -> list[str]:
126
+ lines = text.splitlines()
127
+ in_section = False
128
+ collected: list[str] = []
129
+ for line in lines:
130
+ if line.startswith("## "):
131
+ if in_section:
132
+ break
133
+ in_section = line[3:].strip() == heading
134
+ continue
135
+ if in_section and line.strip():
136
+ collected.append(line.strip())
137
+ if len(collected) >= limit:
138
+ break
139
+ return collected
140
+
141
+
142
+ def replace_updated_at(text: str, updated_at: str) -> str:
143
+ if not text.startswith("---"):
144
+ return text
145
+ parts = text.split("---", 2)
146
+ if len(parts) < 3:
147
+ return text
148
+ frontmatter = parts[1]
149
+ body = parts[2]
150
+ if re.search(r"(?m)^updated_at:\s*.+$", frontmatter):
151
+ frontmatter = re.sub(
152
+ r"(?m)^updated_at:\s*.+$",
153
+ f"updated_at: {updated_at}",
154
+ frontmatter,
155
+ count=1,
156
+ )
157
+ else:
158
+ frontmatter = frontmatter.rstrip("\n") + f"\nupdated_at: {updated_at}\n"
159
+ return "---" + frontmatter + "---" + body
160
+
161
+
162
+ def normalize_next_action_text(value: str) -> str:
163
+ text = " ".join(str(value or "").strip().split())
164
+ if not text:
165
+ raise ValueError("next_action must not be empty")
166
+ validate_local_control_text("active_state_next_action", text)
167
+ return text
168
+
169
+
170
+ def registered_agents_for_goal(registry_goal: dict[str, Any] | None) -> list[str]:
171
+ coordination = (
172
+ registry_goal.get("coordination")
173
+ if registry_goal and isinstance(registry_goal.get("coordination"), dict)
174
+ else {}
175
+ )
176
+ registered_raw = coordination.get("registered_agents") if isinstance(coordination, dict) else []
177
+ registered_values = registered_raw if isinstance(registered_raw, list) else []
178
+ registered_agents: list[str] = []
179
+ for value in registered_values:
180
+ candidate = value.get("id") if isinstance(value, dict) else value
181
+ normalized = normalize_todo_claimed_by(candidate)
182
+ if normalized:
183
+ registered_agents.append(normalized)
184
+ return registered_agents
185
+
186
+
187
+ def normalize_progress_scope(value: str | None) -> str:
188
+ normalized = str(value or "").strip()
189
+ if not normalized:
190
+ return ""
191
+ validate_public_safe_text("progress_scope", normalized)
192
+ if normalized not in PROGRESS_SCOPE_CHOICES:
193
+ raise ValueError(
194
+ "--progress-scope must be one of: " + ", ".join(PROGRESS_SCOPE_CHOICES)
195
+ )
196
+ return normalized
197
+
198
+
199
+ def _noop_classification_for(classification: str) -> str:
200
+ normalized = str(classification or "").strip().lower()
201
+ if "repair" in normalized and "replan" not in normalized:
202
+ return "repair_noop"
203
+ return "replan_noop"
204
+
205
+
206
+ def next_action_section_bounds(lines: list[str]) -> tuple[int, int] | None:
207
+ for index, line in enumerate(lines):
208
+ if line.strip() != "## Next Action":
209
+ continue
210
+ end = len(lines)
211
+ for next_index in range(index + 1, len(lines)):
212
+ if lines[next_index].startswith("## "):
213
+ end = next_index
214
+ break
215
+ return index, end
216
+ return None
217
+
218
+
219
+ def next_action_insert_anchor(lines: list[str]) -> int:
220
+ preferred = {
221
+ "## Recent User Feedback",
222
+ "## Progress Ledger",
223
+ "## Operating Lessons",
224
+ "## Completed Work Archive",
225
+ }
226
+ for index, line in enumerate(lines):
227
+ if line.strip() in preferred:
228
+ return index
229
+ return len(lines)
230
+
231
+
232
+ def replace_next_action_section(
233
+ state_text: str,
234
+ *,
235
+ next_action: str,
236
+ updated_at: str,
237
+ ) -> tuple[str, bool]:
238
+ lines = state_text.splitlines()
239
+ section = ["## Next Action", "", f"- {next_action}", ""]
240
+ bounds = next_action_section_bounds(lines)
241
+ if bounds:
242
+ start, end = bounds
243
+ updated_lines = [*lines[:start], *section, *lines[end:]]
244
+ else:
245
+ anchor = next_action_insert_anchor(lines)
246
+ insert = list(section)
247
+ if anchor > 0 and lines[anchor - 1].strip():
248
+ insert.insert(0, "")
249
+ updated_lines = [*lines[:anchor], *insert, *lines[anchor:]]
250
+ section_text = "\n".join(updated_lines).rstrip() + "\n"
251
+ if section_text.rstrip("\n") == state_text.rstrip("\n"):
252
+ return state_text, False
253
+ return replace_updated_at(section_text, updated_at), True
254
+
255
+
256
+ def clean_action_line(line: str) -> str:
257
+ text = BULLET_PREFIX_RE.sub("", line.strip()).strip()
258
+ return CHECKBOX_PREFIX_RE.sub("", text).strip()
259
+
260
+
261
+ def is_bullet_line(line: str) -> bool:
262
+ return bool(BULLET_PREFIX_RE.match(line.strip()))
263
+
264
+
265
+ def first_action_item(lines: list[str], start: int) -> str:
266
+ first_line = lines[start]
267
+ parts = [clean_action_line(first_line)]
268
+ if is_bullet_line(first_line):
269
+ for line in lines[start + 1 :]:
270
+ if is_bullet_line(line):
271
+ break
272
+ if line.strip().startswith("<!--"):
273
+ continue
274
+ cleaned = clean_action_line(line)
275
+ if cleaned:
276
+ parts.append(cleaned)
277
+ return " ".join(part for part in parts if part).strip()
278
+
279
+
280
+ def checkbox_mark(line: str) -> str | None:
281
+ text = BULLET_PREFIX_RE.sub("", line.strip()).strip()
282
+ match = CHECKBOX_PREFIX_RE.match(text)
283
+ if not match:
284
+ return None
285
+ return match.group("mark")
286
+
287
+
288
+ def todo_metadata(lines: list[str], start: int) -> dict[str, str]:
289
+ metadata: dict[str, str] = {}
290
+ for line in lines[start + 1 :]:
291
+ if is_bullet_line(line):
292
+ break
293
+ text = line.strip()
294
+ if not text.startswith("<!-- loopx:todo"):
295
+ continue
296
+ for key, value in re.findall(r"([A-Za-z_][A-Za-z0-9_]*)=([^ >]+)", text):
297
+ metadata[key] = value
298
+ break
299
+ return metadata
300
+
301
+
302
+ def todo_priority_rank(action: str) -> int:
303
+ match = re.match(r"^\[P(?P<rank>\d+)\]\s+", action.strip(), flags=re.IGNORECASE)
304
+ if not match:
305
+ return 99
306
+ return int(match.group("rank"))
307
+
308
+
309
+ def first_open_agent_todo_action(state_text: str) -> str | None:
310
+ lines = extract_section_lines(state_text, "Agent Todo", limit=512)
311
+ advancement_candidates: list[tuple[int, int, str]] = []
312
+ fallback_candidates: list[tuple[int, int, str]] = []
313
+ for index, line in enumerate(lines):
314
+ mark = checkbox_mark(line)
315
+ if mark is None or mark.lower() == "x":
316
+ continue
317
+ action = first_action_item(lines, index)
318
+ if not action:
319
+ continue
320
+ try:
321
+ validate_local_control_text("derived agent_todo recommended_action", action)
322
+ except ValueError:
323
+ continue
324
+ metadata = todo_metadata(lines, index)
325
+ if metadata.get("task_class") == TODO_TASK_CLASS_ADVANCEMENT:
326
+ advancement_candidates.append((todo_priority_rank(action), index, action))
327
+ continue
328
+ if metadata.get("task_class") in {
329
+ TODO_TASK_CLASS_MONITOR,
330
+ TODO_TASK_CLASS_USER_GATE,
331
+ TODO_TASK_CLASS_BLOCKER,
332
+ }:
333
+ continue
334
+ fallback_candidates.append((todo_priority_rank(action), index, action))
335
+ if advancement_candidates:
336
+ return sorted(advancement_candidates)[0][2]
337
+ if fallback_candidates:
338
+ return sorted(fallback_candidates)[0][2]
339
+ return None
340
+
341
+
342
+ def section_list_items(lines: list[str]) -> list[str]:
343
+ items: list[str] = []
344
+ index = 0
345
+ while index < len(lines):
346
+ line = lines[index]
347
+ if is_bullet_line(line):
348
+ item = first_action_item(lines, index)
349
+ if item:
350
+ items.append(item)
351
+ index += 1
352
+ while index < len(lines) and not is_bullet_line(lines[index]):
353
+ index += 1
354
+ continue
355
+ cleaned = clean_action_line(line)
356
+ if cleaned:
357
+ items.append(cleaned)
358
+ index += 1
359
+ return items
360
+
361
+
362
+ def derive_recommended_action_with_source(state_text: str) -> tuple[str, str]:
363
+ lines = extract_section_lines(state_text, "Next Action", limit=RECOMMENDED_ACTION_SECTION_LINE_LIMIT)
364
+ for index, line in enumerate(lines):
365
+ action = first_action_item(lines, index)
366
+ if not action:
367
+ continue
368
+ try:
369
+ validate_local_control_text("derived recommended_action", action)
370
+ except ValueError:
371
+ continue
372
+ return action, RECOMMENDED_ACTION_SOURCE_ACTIVE_NEXT_ACTION
373
+ agent_todo_action = first_open_agent_todo_action(state_text)
374
+ if agent_todo_action:
375
+ return agent_todo_action, RECOMMENDED_ACTION_SOURCE_AGENT_TODO_FALLBACK
376
+ return DEFAULT_REFRESH_ACTION, RECOMMENDED_ACTION_SOURCE_DEFAULT
377
+
378
+
379
+ def derive_recommended_action(state_text: str) -> str:
380
+ return derive_recommended_action_with_source(state_text)[0]
381
+
382
+
383
+ def resolve_goal_state(
384
+ *,
385
+ registry: dict[str, Any],
386
+ goal_id: str,
387
+ project_override: Path | None,
388
+ state_file_override: Path | None,
389
+ ) -> tuple[dict[str, Any] | None, Path | None, Path]:
390
+ goal = next((item for item in registry_goals(registry) if str(item.get("id")) == goal_id), None)
391
+ project = project_override.expanduser().resolve() if project_override else None
392
+ if project is None and goal and goal.get("repo"):
393
+ project = Path(str(goal.get("repo"))).expanduser()
394
+
395
+ registered_state_file = (
396
+ resolve_state_file(project, goal.get("state_file"))
397
+ if project and goal and goal.get("state_file")
398
+ else None
399
+ )
400
+ state_file = state_file_override.expanduser() if state_file_override else None
401
+ if state_file is None and goal:
402
+ state_file = registered_state_file
403
+ if state_file is None:
404
+ raise ValueError("state file is required when the goal is not resolvable from registry")
405
+ if not state_file.is_absolute():
406
+ if project is None:
407
+ raise ValueError("relative state file requires --project or registry repo")
408
+ state_file = project / state_file
409
+ state_file = state_file.resolve()
410
+ if state_file_override is not None:
411
+ if project is None:
412
+ raise ValueError("--state-file override requires --project or a registry goal with repo")
413
+ registered_resolved = (
414
+ registered_state_file.resolve() if registered_state_file is not None else None
415
+ )
416
+ if state_file != registered_resolved and not state_file.is_relative_to(project):
417
+ raise ValueError(
418
+ f"--state-file {state_file} escapes project root {project}"
419
+ )
420
+ return goal, project, state_file
421
+
422
+
423
+ def build_state_refresh_record(
424
+ *,
425
+ goal_id: str,
426
+ state_file: Path,
427
+ state_text: str,
428
+ classification: str,
429
+ recommended_action: str,
430
+ recommended_action_source: str,
431
+ generated_at: str,
432
+ registry_goal: dict[str, Any] | None,
433
+ delivery_batch_scale: str | None = None,
434
+ delivery_outcome: str | None = None,
435
+ progress_scope: str | None = None,
436
+ agent_id: str | None = None,
437
+ agent_lane: str | None = None,
438
+ autonomous_replan_recorded: bool = False,
439
+ repair_delta_contract: dict[str, Any] | None = None,
440
+ replan_semantic_delta: dict[str, Any] | None = None,
441
+ autonomous_replan_frontier_identity: str | None = None,
442
+ agent_vision: dict[str, Any] | None = None,
443
+ vision_checkpoint: dict[str, Any] | None = None,
444
+ progress_observation: dict[str, Any] | None = None,
445
+ delivery_workspace: dict[str, Any] | None = None,
446
+ settlement_identity: SettlementIdentity | None = None,
447
+ ) -> dict[str, Any]:
448
+ frontmatter = parse_frontmatter(state_text)
449
+ next_action = extract_section_lines(state_text, "Next Action")
450
+ recent_feedback = extract_section_lines(state_text, "Recent User Feedback", limit=5)
451
+ progress = extract_section_lines(state_text, "Progress Ledger", limit=5)
452
+ digest = hashlib.sha256(state_text.encode("utf-8")).hexdigest()[:16]
453
+ authority_sources = []
454
+ if registry_goal and isinstance(registry_goal.get("authority_sources"), list):
455
+ authority_sources = registry_goal.get("authority_sources") or []
456
+ record = {
457
+ "generated_at": generated_at,
458
+ "goal_id": goal_id,
459
+ "classification": classification,
460
+ "recommended_action": recommended_action,
461
+ "recommended_action_source": recommended_action_source,
462
+ "health_check": (
463
+ f"state_file 1/1; registry_goal {1 if registry_goal else 0}/1; "
464
+ f"authority_sources {len(authority_sources)}"
465
+ ),
466
+ "state": {
467
+ "path": str(state_file),
468
+ "sha256_16": digest,
469
+ "frontmatter": frontmatter,
470
+ "next_action": next_action,
471
+ "recent_feedback": recent_feedback,
472
+ "progress": progress,
473
+ },
474
+ "registry_goal": {
475
+ "present": bool(registry_goal),
476
+ "domain": registry_goal.get("domain") if registry_goal else None,
477
+ "status": registry_goal.get("status") if registry_goal else None,
478
+ "adapter": registry_goal.get("adapter") if registry_goal else None,
479
+ "authority_source_count": len(authority_sources),
480
+ },
481
+ }
482
+ projection_gap = state_projection_gap_warning(state_text)
483
+ if projection_gap:
484
+ record["state_projection_gap"] = projection_gap
485
+ if delivery_batch_scale:
486
+ record["delivery_batch_scale"] = delivery_batch_scale
487
+ if delivery_outcome:
488
+ record["delivery_outcome"] = delivery_outcome
489
+ if delivery_workspace:
490
+ record["delivery_workspace"] = delivery_workspace
491
+ if settlement_identity:
492
+ record["settlement_identity"] = settlement_identity.as_dict()
493
+ record["turn_instance_id"] = settlement_identity.turn_instance_id
494
+ record["todo_id"] = settlement_identity.todo_id
495
+ if autonomous_replan_recorded:
496
+ record["autonomous_replan_ack"] = {
497
+ "schema_version": "autonomous_replan_ack_v0",
498
+ "recorded": True,
499
+ "source": "refresh_state",
500
+ }
501
+ if repair_delta_contract:
502
+ record["autonomous_replan_ack"]["delta_contract"] = repair_delta_contract
503
+ if replan_semantic_delta:
504
+ record["autonomous_replan_ack"]["semantic_delta"] = (
505
+ replan_semantic_delta
506
+ )
507
+ if autonomous_replan_frontier_identity:
508
+ record["autonomous_replan_ack"]["frontier_identity"] = (
509
+ autonomous_replan_frontier_identity
510
+ )
511
+ if agent_vision:
512
+ record["agent_vision"] = agent_vision
513
+ if vision_checkpoint:
514
+ record["vision_checkpoint"] = vision_checkpoint
515
+ if progress_observation:
516
+ record["progress_observation"] = progress_observation
517
+ if progress_scope:
518
+ record["progress_scope"] = progress_scope
519
+ if agent_id:
520
+ record["agent_id"] = agent_id
521
+ if progress_scope == AGENT_LANE_PROGRESS_SCOPE and agent_id:
522
+ record["agent_lane"] = agent_lane or agent_id
523
+ return record
524
+
525
+
526
+ def _build_state_refresh_output_projections(
527
+ *,
528
+ record: dict[str, Any],
529
+ registry_path: Path,
530
+ runtime_root: Path,
531
+ project: Path | None,
532
+ json_path: Path,
533
+ markdown_path: Path,
534
+ index_path: Path,
535
+ dry_run: bool,
536
+ autonomous_replan_recorded_requested: bool,
537
+ ) -> tuple[dict[str, Any], dict[str, Any]]:
538
+ """Project one refresh record into its compact index and CLI response."""
539
+
540
+ record_state = record.get("state") if isinstance(record.get("state"), dict) else {}
541
+ record_frontmatter = record_state.get("frontmatter") or {}
542
+ index_record = {
543
+ field: record[field]
544
+ for field in (
545
+ "generated_at", "goal_id", "classification", "recommended_action",
546
+ "recommended_action_source", "health_check",
547
+ )
548
+ }
549
+ index_record.update({
550
+ "json_path": str(json_path),
551
+ "markdown_path": str(markdown_path),
552
+ "state": {
553
+ "sha256_16": record_state.get("sha256_16"),
554
+ "frontmatter": {"updated_at": record_frontmatter.get("updated_at")},
555
+ },
556
+ "runtime_projection_route": record["runtime_projection_route"],
557
+ })
558
+ for field in (
559
+ "delivery_batch_scale",
560
+ "delivery_outcome",
561
+ "delivery_workspace",
562
+ "settlement_identity",
563
+ "turn_instance_id",
564
+ "todo_id",
565
+ ):
566
+ if field in record:
567
+ index_record[field] = record[field]
568
+
569
+ replan_ack = record.get("autonomous_replan_ack") or {}
570
+ if autonomous_replan_recorded_requested or replan_ack.get("recorded") is True:
571
+ index_record["autonomous_replan_ack"] = replan_ack
572
+ if replan_ack.get("requested_classification"):
573
+ index_record["requested_classification"] = replan_ack["requested_classification"]
574
+
575
+ agent_vision = record.get("agent_vision")
576
+ if isinstance(agent_vision, dict):
577
+ index_record["agent_vision"] = {
578
+ field: agent_vision.get(field)
579
+ for field in (
580
+ "schema_version", "agent_id", "state", "vision_patch",
581
+ "todo_delta", "vision_budget",
582
+ )
583
+ }
584
+ if isinstance(agent_vision.get("path_delta"), dict):
585
+ index_record["agent_vision"]["path_delta"] = agent_vision["path_delta"]
586
+
587
+ for field in (
588
+ "vision_checkpoint",
589
+ "progress_observation",
590
+ "progress_scope",
591
+ "agent_id",
592
+ "agent_lane",
593
+ ):
594
+ if field in record:
595
+ index_record[field] = record[field]
596
+
597
+ payload: dict[str, Any] = {
598
+ "ok": True,
599
+ "dry_run": dry_run,
600
+ "appended": not dry_run,
601
+ "registry": str(registry_path),
602
+ "runtime_root": str(runtime_root),
603
+ "project": str(project) if project else None,
604
+ }
605
+ payload.update({
606
+ field: record.get(field)
607
+ for field in ("goal_id", "classification", "progress_scope", "agent_id", "agent_lane")
608
+ })
609
+ payload.update({
610
+ "autonomous_replan_recorded": bool(replan_ack.get("recorded")),
611
+ "autonomous_replan_recorded_requested": autonomous_replan_recorded_requested,
612
+ "repair_delta_contract": replan_ack.get("delta_contract"),
613
+ "json_path": str(json_path),
614
+ "markdown_path": str(markdown_path),
615
+ "index_path": str(index_path),
616
+ })
617
+ payload.update({
618
+ field: record.get(field)
619
+ for field in (
620
+ "agent_vision", "vision_checkpoint", "recommended_action",
621
+ "recommended_action_source", "active_state_next_action_update",
622
+ "generated_at", "health_check",
623
+ )
624
+ })
625
+ payload.update(record)
626
+ return index_record, payload
627
+
628
+
629
+ def render_state_refresh_markdown(payload: dict[str, Any]) -> str:
630
+ state = payload.get("state") if isinstance(payload.get("state"), dict) else {}
631
+ frontmatter = state.get("frontmatter") if isinstance(state.get("frontmatter"), dict) else {}
632
+ lines = [
633
+ "# LoopX State Refresh",
634
+ "",
635
+ f"- ok: `{payload.get('ok')}`",
636
+ f"- dry_run: `{payload.get('dry_run')}`",
637
+ f"- appended: `{payload.get('appended')}`",
638
+ f"- goal_id: `{payload.get('goal_id')}`",
639
+ f"- classification: `{payload.get('classification')}`",
640
+ f"- progress_scope: `{payload.get('progress_scope')}`",
641
+ f"- agent_id: `{payload.get('agent_id')}`",
642
+ f"- agent_lane: `{payload.get('agent_lane')}`",
643
+ f"- delivery_batch_scale: `{payload.get('delivery_batch_scale')}`",
644
+ f"- delivery_outcome: `{payload.get('delivery_outcome')}`",
645
+ f"- autonomous_replan_recorded: `{payload.get('autonomous_replan_recorded')}`",
646
+ f"- autonomous_replan_recorded_requested: `{payload.get('autonomous_replan_recorded_requested')}`",
647
+ f"- generated_at: `{payload.get('generated_at')}`",
648
+ f"- state_file: `{state.get('path')}`",
649
+ f"- state_updated_at: `{frontmatter.get('updated_at')}`",
650
+ f"- health_check: `{payload.get('health_check')}`",
651
+ ]
652
+ if "external_sink_delivery_authorized" in payload:
653
+ lines.append(
654
+ "- external_sink_delivery_authorized: "
655
+ f"`{payload.get('external_sink_delivery_authorized')}`"
656
+ )
657
+ delivery_workspace = (
658
+ payload.get("delivery_workspace")
659
+ if isinstance(payload.get("delivery_workspace"), dict)
660
+ else {}
661
+ )
662
+ if delivery_workspace:
663
+ lines.append(
664
+ "- delivery_workspace: "
665
+ f"repository={delivery_workspace.get('task_repository')} "
666
+ f"kind={delivery_workspace.get('workspace_kind')}"
667
+ )
668
+ if payload.get("error"):
669
+ lines.append(f"- error: {payload.get('error')}")
670
+ return "\n".join(lines)
671
+
672
+ repair_delta = (
673
+ payload.get("repair_delta_contract")
674
+ if isinstance(payload.get("repair_delta_contract"), dict)
675
+ else {}
676
+ )
677
+ if repair_delta:
678
+ lines.append(
679
+ "- repair_delta_contract: "
680
+ f"delta_present={repair_delta.get('delta_present')} "
681
+ f"kinds={','.join(repair_delta.get('delta_kinds') or [])}"
682
+ )
683
+ agent_vision = (
684
+ payload.get("agent_vision")
685
+ if isinstance(payload.get("agent_vision"), dict)
686
+ else {}
687
+ )
688
+ if agent_vision:
689
+ budget = (
690
+ agent_vision.get("vision_budget")
691
+ if isinstance(agent_vision.get("vision_budget"), dict)
692
+ else {}
693
+ )
694
+ lines.append(
695
+ "- agent_vision: "
696
+ f"state={agent_vision.get('state')} "
697
+ f"agent_id={agent_vision.get('agent_id')} "
698
+ f"budget={budget.get('total_usage')}/{budget.get('total_limit')}"
699
+ )
700
+ vision_checkpoint = (
701
+ payload.get("vision_checkpoint")
702
+ if isinstance(payload.get("vision_checkpoint"), dict)
703
+ else {}
704
+ )
705
+ if vision_checkpoint:
706
+ lines.append(
707
+ "- vision_checkpoint: "
708
+ f"agent_id={vision_checkpoint.get('agent_id')} "
709
+ f"required={vision_checkpoint.get('required')} "
710
+ f"satisfied={vision_checkpoint.get('satisfied')} "
711
+ f"decision={vision_checkpoint.get('decision')}"
712
+ )
713
+ if vision_checkpoint.get("unchanged_reason"):
714
+ lines.append(
715
+ f"- vision_unchanged_reason: {vision_checkpoint.get('unchanged_reason')}"
716
+ )
717
+ required_resolution = vision_checkpoint.get("required_resolution")
718
+ if required_resolution:
719
+ lines.append(
720
+ "- vision_checkpoint_required_resolution: "
721
+ f"{','.join(str(item) for item in required_resolution)}"
722
+ )
723
+
724
+ projection_gap = (
725
+ payload.get("state_projection_gap")
726
+ if isinstance(payload.get("state_projection_gap"), dict)
727
+ else {}
728
+ )
729
+ if projection_gap:
730
+ lines.append(
731
+ "- state_projection_gap: "
732
+ f"requires_todo_expansion={projection_gap.get('requires_todo_expansion')} "
733
+ f"user_open={projection_gap.get('user_open_count')} "
734
+ f"agent_open={projection_gap.get('agent_open_count')} "
735
+ f"target_roles={','.join(projection_gap.get('target_roles') or [])}"
736
+ )
737
+ if projection_gap.get("recommended_action"):
738
+ lines.append(f"- state_projection_gap_action: {projection_gap.get('recommended_action')}")
739
+
740
+ next_action_update = (
741
+ payload.get("active_state_next_action_update")
742
+ if isinstance(payload.get("active_state_next_action_update"), dict)
743
+ else {}
744
+ )
745
+ if next_action_update:
746
+ lines.append(
747
+ "- active_state_next_action_update: "
748
+ f"updated={next_action_update.get('updated')} "
749
+ f"would_update={next_action_update.get('would_update')} "
750
+ f"dry_run={next_action_update.get('dry_run')}"
751
+ )
752
+ if next_action_update.get("next_action"):
753
+ lines.append(
754
+ f"- active_state_next_action: {next_action_update.get('next_action')}"
755
+ )
756
+
757
+ write_correctness = (
758
+ payload.get("local_state_write_correctness")
759
+ if isinstance(payload.get("local_state_write_correctness"), dict)
760
+ else {}
761
+ )
762
+ if write_correctness:
763
+ intent = write_correctness.get("write_intent") if isinstance(write_correctness.get("write_intent"), dict) else {}
764
+ preview = write_correctness.get("preview") if isinstance(write_correctness.get("preview"), dict) else {}
765
+ apply_result = (
766
+ write_correctness.get("apply_result")
767
+ if isinstance(write_correctness.get("apply_result"), dict)
768
+ else {}
769
+ )
770
+ lines.append(
771
+ "- local_state_write_correctness: "
772
+ f"schema={write_correctness.get('schema_version')} "
773
+ f"write_class={intent.get('write_class')} "
774
+ f"status={apply_result.get('status')} "
775
+ f"non_destructive={preview.get('non_destructive')}"
776
+ )
777
+
778
+ global_sync = payload.get("global_sync") if isinstance(payload.get("global_sync"), dict) else {}
779
+ if global_sync:
780
+ lines.extend(
781
+ [
782
+ f"- global_registry: `{global_sync.get('global_registry')}`",
783
+ f"- global_sync_wrote: `{global_sync.get('wrote')}`",
784
+ ]
785
+ )
786
+
787
+ lines.extend(
788
+ [
789
+ "",
790
+ "## Recommended Action",
791
+ f"- source: `{payload.get('recommended_action_source')}`",
792
+ str(payload.get("recommended_action") or ""),
793
+ ]
794
+ )
795
+ for heading, key in (
796
+ ("Next Action", "next_action"),
797
+ ("Recent Feedback", "recent_feedback"),
798
+ ("Progress", "progress"),
799
+ ):
800
+ values = state.get(key) if isinstance(state.get(key), list) else []
801
+ if values:
802
+ lines.extend(["", f"## {heading}"])
803
+ lines.extend(f"- {value}" for value in section_list_items(values))
804
+ return "\n".join(lines)
805
+
806
+
807
+ def refresh_state_run(
808
+ *,
809
+ registry_path: Path,
810
+ runtime_root_override: str | None,
811
+ goal_id: str,
812
+ project: Path | None,
813
+ state_file: Path | None,
814
+ classification: str,
815
+ recommended_action: str | None,
816
+ next_action: str | None = None,
817
+ delivery_batch_scale: str | None = None,
818
+ delivery_outcome: str | None = None,
819
+ delivery_workspace_path: Path | None = None,
820
+ todo_id: str | None = None,
821
+ turn_instance_id: str | None = None,
822
+ agent_id: str | None = None,
823
+ agent_lane: str | None = None,
824
+ progress_scope: str | None = None,
825
+ autonomous_replan_recorded: bool = False,
826
+ repair_delta_kinds: list[str] | None = None,
827
+ agent_vision_packet: dict[str, Any] | None = None,
828
+ merge_agent_vision_patch: bool = False,
829
+ vision_unchanged_reason: str | None = None,
830
+ progress_observation: dict[str, Any] | None = None,
831
+ completion_todo_id: str | None = None,
832
+ completion_turn_key: str | None = None,
833
+ dry_run: bool,
834
+ sync_global: bool = True,
835
+ ) -> dict[str, Any]:
836
+ safe_goal_id = validate_goal_id_path_segment(goal_id)
837
+ validate_public_safe_text("classification", classification)
838
+ normalized_agent_id = (agent_id or "").strip()
839
+ normalized_agent_lane = (agent_lane or "").strip()
840
+ if normalized_agent_id:
841
+ validate_public_safe_text("agent_id", normalized_agent_id)
842
+ if normalized_agent_lane:
843
+ validate_public_safe_text("agent_lane", normalized_agent_lane)
844
+ if normalized_agent_lane and not normalized_agent_id:
845
+ raise ValueError("--agent-lane requires --agent-id so the lane has an owner")
846
+ normalized_progress_scope = normalize_progress_scope(progress_scope)
847
+ normalized_delivery_batch_scale = (
848
+ require_delivery_batch_scale(delivery_batch_scale).value if delivery_batch_scale else None
849
+ )
850
+ normalized_delivery_outcome = (
851
+ require_delivery_outcome(delivery_outcome).value if delivery_outcome else None
852
+ )
853
+ if delivery_workspace_path is not None and (
854
+ normalized_delivery_outcome not in ACCOUNTABLE_DELIVERY_OUTCOMES
855
+ ):
856
+ raise ValueError(
857
+ "--delivery-workspace-path requires an accountable --delivery-outcome"
858
+ )
859
+ normalized_repair_delta_kinds = normalize_repair_delta_kinds(repair_delta_kinds)
860
+ normalized_progress_observation = (
861
+ normalize_progress_observation(
862
+ progress_observation,
863
+ work_item_id=todo_id,
864
+ )
865
+ if progress_observation is not None
866
+ else None
867
+ )
868
+ registry = load_registry(registry_path)
869
+ runtime_root = resolve_runtime_root(registry, runtime_root_override)
870
+ settlement_identity = None
871
+ settlement_result = None
872
+ delivery_workspace_causality = None
873
+ if todo_id or turn_instance_id:
874
+ if normalized_delivery_outcome not in ACCOUNTABLE_DELIVERY_OUTCOMES:
875
+ raise ValueError(
876
+ "turn-scoped refresh-state requires an accountable --delivery-outcome"
877
+ )
878
+ settlement_result = resolve_heartbeat_settlement_identity(
879
+ runtime_root,
880
+ goal_id=safe_goal_id,
881
+ agent_id=normalized_agent_id or None,
882
+ todo_id=todo_id,
883
+ turn_instance_id=turn_instance_id,
884
+ )
885
+ if settlement_result.failure is not None:
886
+ raise ValueError(settlement_result.failure.reason)
887
+ settlement_identity = settlement_result.value
888
+ if settlement_identity is None:
889
+ raise ValueError("turn-scoped refresh-state has no settlement identity")
890
+ delivery_workspace_causality = resolve_settlement_delivery_workspace_causality(
891
+ runtime_root, settlement_identity
892
+ )
893
+ if not dry_run:
894
+ prior_writeback = require_settlement_writeback(
895
+ runtime_root,
896
+ settlement_identity,
897
+ )
898
+ if prior_writeback.failure is None and prior_writeback.value is not None:
899
+ return {
900
+ "ok": True,
901
+ "dry_run": False,
902
+ "appended": False,
903
+ "idempotent_replay": True,
904
+ "registry": str(registry_path),
905
+ "runtime_root": str(runtime_root),
906
+ "goal_id": safe_goal_id,
907
+ "classification": prior_writeback.value.get("classification"),
908
+ "delivery_batch_scale": prior_writeback.value.get(
909
+ "delivery_batch_scale"
910
+ ),
911
+ "delivery_outcome": prior_writeback.value.get(
912
+ "delivery_outcome"
913
+ ),
914
+ "settlement_identity": settlement_identity.as_dict(),
915
+ "settlement_result": settlement_result_payload(
916
+ settlement_result.bind(
917
+ lambda _identity: prior_writeback
918
+ )
919
+ ),
920
+ }
921
+ prior_writeback_run = find_settlement_writeback(
922
+ runtime_root,
923
+ settlement_identity,
924
+ )
925
+ if prior_writeback_run is not None:
926
+ return {
927
+ "ok": True,
928
+ "dry_run": False,
929
+ "appended": False,
930
+ "receipt_repair_required": True,
931
+ "registry": str(registry_path),
932
+ "runtime_root": str(runtime_root),
933
+ "goal_id": safe_goal_id,
934
+ "classification": prior_writeback_run.get("classification"),
935
+ "delivery_batch_scale": prior_writeback_run.get(
936
+ "delivery_batch_scale"
937
+ ),
938
+ "delivery_outcome": prior_writeback_run.get(
939
+ "delivery_outcome"
940
+ ),
941
+ "settlement_identity": settlement_identity.as_dict(),
942
+ "settlement_result": settlement_result_payload(
943
+ settlement_result.bind(
944
+ lambda _identity: prior_writeback
945
+ )
946
+ ),
947
+ }
948
+ runtime_projection_route = resolve_runtime_projection_route(
949
+ registry_path=registry_path,
950
+ goal_id=safe_goal_id,
951
+ source_runtime_root=runtime_root,
952
+ )
953
+ route_status = str(runtime_projection_route.get("status") or "missing")
954
+ route_target_text = str(
955
+ runtime_projection_route.get("target_runtime_root") or ""
956
+ ).strip()
957
+ route_target_root = Path(route_target_text) if route_target_text else None
958
+ shared_runtime_root = (
959
+ route_target_root if sync_global and route_status == "resolved" else None
960
+ )
961
+ global_sync_runtime_root = (
962
+ route_target_root
963
+ if sync_global and route_status in {"resolved", "single_runtime"}
964
+ else None
965
+ )
966
+ registry_goal, resolved_project, resolved_state_file = resolve_goal_state(
967
+ registry=registry,
968
+ goal_id=safe_goal_id,
969
+ project_override=project,
970
+ state_file_override=state_file,
971
+ )
972
+ if not resolved_state_file.exists():
973
+ raise FileNotFoundError(f"state file does not exist: {resolved_state_file}")
974
+ state_text = resolved_state_file.read_text(encoding="utf-8")
975
+ expected_write_state_text = state_text
976
+ if normalized_delivery_outcome in ACCOUNTABLE_DELIVERY_OUTCOMES:
977
+ require_accountable_completion_validation(
978
+ state_text,
979
+ todo_id=(settlement_identity.todo_id if settlement_identity else None),
980
+ agent_id=normalized_agent_id or None,
981
+ )
982
+ normalized_next_action = normalize_next_action_text(next_action) if next_action else None
983
+ registered_agents = registered_agents_for_goal(registry_goal)
984
+ known_agents = {agent for agent in registered_agents if agent}
985
+ multi_agent_goal = len(known_agents) > 1
986
+ workspace_guard_policy = (
987
+ registry_goal.get("workspace_guard_policy")
988
+ if isinstance(registry_goal.get("workspace_guard_policy"), dict)
989
+ else {}
990
+ )
991
+ explicit_peer_worktree_requirement = workspace_guard_policy.get(
992
+ "peer_independent_worktree_required"
993
+ )
994
+ peer_independent_worktree_required = multi_agent_goal and (
995
+ explicit_peer_worktree_requirement is None
996
+ or explicit_peer_worktree_requirement is True
997
+ )
998
+ if normalized_agent_id and known_agents and normalized_agent_id not in known_agents:
999
+ raise ValueError(
1000
+ f"agent_id {normalized_agent_id!r} is not registered for goal {safe_goal_id!r}"
1001
+ )
1002
+ if multi_agent_goal and not normalized_agent_id:
1003
+ raise ValueError(
1004
+ "multi-agent refresh-state requires --agent-id; text inference is disabled"
1005
+ )
1006
+ if not normalized_progress_scope:
1007
+ normalized_progress_scope = (
1008
+ AGENT_LANE_PROGRESS_SCOPE if normalized_agent_id else GOAL_PROGRESS_SCOPE
1009
+ )
1010
+ if normalized_progress_scope == AGENT_LANE_PROGRESS_SCOPE:
1011
+ if not normalized_agent_id:
1012
+ raise ValueError("--progress-scope agent_lane requires --agent-id")
1013
+ if normalized_next_action:
1014
+ raise ValueError(
1015
+ "agent-lane refresh-state cannot update the durable active-state Next Action; "
1016
+ "rerun without --next-action or use --progress-scope goal from a registered peer"
1017
+ )
1018
+ if normalized_progress_scope == GOAL_PROGRESS_SCOPE:
1019
+ if normalized_agent_lane:
1020
+ raise ValueError("--agent-lane requires --progress-scope agent_lane")
1021
+ if (agent_vision_packet is not None or vision_unchanged_reason) and not normalized_agent_id:
1022
+ raise ValueError("vision writeback requires --agent-id")
1023
+ normalized_vision_unchanged_reason = normalize_vision_unchanged_reason(
1024
+ vision_unchanged_reason
1025
+ )
1026
+ agent_vision: dict[str, Any] | None = None
1027
+ existing_agent_vision: dict[str, Any] | None = None
1028
+ autonomous_replan_frontier_identity: str | None = None
1029
+ newest_first_runs: list[dict[str, Any]] = []
1030
+ if normalized_agent_id:
1031
+ existing_runs, _ = load_index(
1032
+ runtime_root / "goals" / safe_goal_id / "runs" / "index.jsonl"
1033
+ )
1034
+ newest_first_runs = [
1035
+ run
1036
+ for _, run in sorted(
1037
+ enumerate(existing_runs),
1038
+ key=lambda item: (str(item[1].get("generated_at") or ""), item[0]),
1039
+ reverse=True,
1040
+ )
1041
+ ]
1042
+ existing_agent_vision = latest_agent_vision_from_runs(
1043
+ newest_first_runs,
1044
+ goal_id=safe_goal_id,
1045
+ agent_id=normalized_agent_id,
1046
+ )
1047
+ if agent_vision_packet is not None:
1048
+ agent_vision = normalize_goal_vision_update(
1049
+ agent_vision_packet,
1050
+ goal_id=safe_goal_id,
1051
+ agent_id=normalized_agent_id or None,
1052
+ existing_agent_vision=existing_agent_vision,
1053
+ merge_patch=merge_agent_vision_patch,
1054
+ require_path_delta_for_durable_change=autonomous_replan_recorded,
1055
+ )
1056
+ generated_at = now_local()
1057
+ active_state_next_action_update: dict[str, Any] | None = None
1058
+ if normalized_next_action:
1059
+ with exclusive_file_lock(resolved_state_file):
1060
+ locked_state_text = resolved_state_file.read_text(encoding="utf-8")
1061
+ expected_write_state_text = locked_state_text
1062
+ updated_state_text, state_updated = replace_next_action_section(
1063
+ locked_state_text,
1064
+ next_action=normalized_next_action,
1065
+ updated_at=generated_at,
1066
+ )
1067
+ active_state_next_action_update = {
1068
+ "schema_version": ACTIVE_STATE_NEXT_ACTION_UPDATE_SCHEMA_VERSION,
1069
+ "source": "refresh_state",
1070
+ "next_action": normalized_next_action,
1071
+ "updated": bool(state_updated and not dry_run),
1072
+ "would_update": bool(state_updated),
1073
+ "dry_run": bool(dry_run),
1074
+ "updated_at": generated_at if state_updated else None,
1075
+ }
1076
+ state_text = updated_state_text if state_updated else locked_state_text
1077
+
1078
+ if recommended_action:
1079
+ action = recommended_action
1080
+ recommended_action_source = RECOMMENDED_ACTION_SOURCE_EXPLICIT
1081
+ else:
1082
+ action, recommended_action_source = derive_recommended_action_with_source(state_text)
1083
+ validate_local_control_text("recommended_action", action)
1084
+ repair_delta_contract: dict[str, Any] | None = None
1085
+ validated_repair_delta_kinds: list[str] = []
1086
+ requested_classification = classification
1087
+ effective_autonomous_replan_recorded = bool(autonomous_replan_recorded)
1088
+ if autonomous_replan_recorded:
1089
+ repair_delta_contract = build_repair_delta_contract(
1090
+ requested_delta_kinds=normalized_repair_delta_kinds,
1091
+ active_state_next_action_update=active_state_next_action_update,
1092
+ agent_vision=agent_vision,
1093
+ existing_agent_vision=existing_agent_vision,
1094
+ agent_todo_summary=parse_active_state_todos(
1095
+ state_text, item_limit=None
1096
+ ).get("agent_todos"),
1097
+ agent_id=normalized_agent_id or None,
1098
+ dry_run=dry_run,
1099
+ selected_todo_id=(
1100
+ settlement_identity.todo_id if settlement_identity else None
1101
+ ),
1102
+ newest_first_runs=newest_first_runs,
1103
+ )
1104
+ validated_repair_delta_kinds = list(
1105
+ repair_delta_contract.get("delta_kinds") or []
1106
+ )
1107
+ if not repair_delta_contract["delta_present"]:
1108
+ classification = _noop_classification_for(classification)
1109
+ effective_autonomous_replan_recorded = False
1110
+ if normalized_delivery_outcome in {"outcome_progress", "primary_goal_outcome"}:
1111
+ normalized_delivery_outcome = "outcome_gap"
1112
+ elif (
1113
+ normalized_delivery_outcome in {"outcome_progress", "primary_goal_outcome"}
1114
+ and not repair_delta_kinds_have_accountable_progress(
1115
+ validated_repair_delta_kinds
1116
+ )
1117
+ ):
1118
+ normalized_delivery_outcome = "outcome_gap"
1119
+ if effective_autonomous_replan_recorded and normalized_agent_id:
1120
+ autonomous_replan_frontier_identity = (
1121
+ latest_monitor_replan_frontier_identity(
1122
+ newest_first_runs,
1123
+ agent_id=normalized_agent_id,
1124
+ watch_todo_ids=watch_lane_continuation_todo_ids(
1125
+ repair_delta_contract
1126
+ ),
1127
+ )
1128
+ )
1129
+ replan_semantic_delta = enforce_open_replan_writeback(
1130
+ newest_first_runs=newest_first_runs,
1131
+ state_text=state_text,
1132
+ agent_id=normalized_agent_id,
1133
+ goal_id=safe_goal_id,
1134
+ progress_observation=normalized_progress_observation,
1135
+ registry_goal=registry_goal,
1136
+ agent_vision=agent_vision,
1137
+ completion_todo_id=completion_todo_id,
1138
+ completion_turn_key=completion_turn_key,
1139
+ )
1140
+ if replan_semantic_delta:
1141
+ effective_autonomous_replan_recorded = True
1142
+ vision_checkpoint = build_vision_checkpoint(
1143
+ agent_id=normalized_agent_id or None,
1144
+ agent_vision=agent_vision,
1145
+ existing_agent_vision=existing_agent_vision,
1146
+ vision_unchanged_reason=normalized_vision_unchanged_reason,
1147
+ delivery_outcome=normalized_delivery_outcome,
1148
+ active_state_next_action_update=active_state_next_action_update,
1149
+ )
1150
+ delivery_workspace = None
1151
+ workspace_requirement = str(
1152
+ (delivery_workspace_causality or {}).get("requirement") or "unknown"
1153
+ )
1154
+ if delivery_workspace_path is not None and workspace_requirement == "not_required":
1155
+ raise ValueError(
1156
+ "--delivery-workspace-path conflicts with the original Todo's "
1157
+ "explicit non-delivery settlement contract"
1158
+ )
1159
+ if (
1160
+ normalized_delivery_outcome in ACCOUNTABLE_DELIVERY_OUTCOMES
1161
+ and workspace_requirement != "not_required"
1162
+ ):
1163
+ delivery_workspace = capture_delivery_workspace(
1164
+ current_path=delivery_workspace_path,
1165
+ peer_independent_worktree_required=peer_independent_worktree_required,
1166
+ )
1167
+ if delivery_workspace_path is not None:
1168
+ if delivery_workspace is None:
1169
+ raise ValueError(
1170
+ "--delivery-workspace-path must identify a git checkout with "
1171
+ "a credential-free origin repository"
1172
+ )
1173
+ if (
1174
+ peer_independent_worktree_required
1175
+ and delivery_workspace.get("workspace_kind")
1176
+ != "independent_git_worktree"
1177
+ ):
1178
+ raise ValueError(
1179
+ "--delivery-workspace-path must identify the independent git "
1180
+ "worktree that produced this peer delivery"
1181
+ )
1182
+ delivery_workspace["repository_source"] = (
1183
+ "refresh_state.delivery_workspace_path"
1184
+ )
1185
+ if (
1186
+ active_state_next_action_update
1187
+ and active_state_next_action_update.get("would_update")
1188
+ and not dry_run
1189
+ ):
1190
+ with exclusive_file_lock(resolved_state_file):
1191
+ current_state_text = resolved_state_file.read_text(encoding="utf-8")
1192
+ if current_state_text != expected_write_state_text:
1193
+ raise ValueError(
1194
+ "active goal state changed while refresh-state was qualifying "
1195
+ "its semantic writeback; retry from the current state"
1196
+ )
1197
+ resolved_state_file.write_text(state_text, encoding="utf-8")
1198
+ record = build_state_refresh_record(
1199
+ goal_id=safe_goal_id,
1200
+ state_file=resolved_state_file,
1201
+ state_text=state_text,
1202
+ classification=classification,
1203
+ recommended_action=action,
1204
+ recommended_action_source=recommended_action_source,
1205
+ generated_at=generated_at,
1206
+ registry_goal=registry_goal,
1207
+ delivery_batch_scale=normalized_delivery_batch_scale,
1208
+ delivery_outcome=normalized_delivery_outcome,
1209
+ progress_scope=normalized_progress_scope,
1210
+ agent_id=normalized_agent_id or None,
1211
+ agent_lane=normalized_agent_lane or None,
1212
+ autonomous_replan_recorded=effective_autonomous_replan_recorded,
1213
+ repair_delta_contract=repair_delta_contract,
1214
+ autonomous_replan_frontier_identity=autonomous_replan_frontier_identity,
1215
+ agent_vision=agent_vision,
1216
+ vision_checkpoint=vision_checkpoint,
1217
+ progress_observation=normalized_progress_observation,
1218
+ delivery_workspace=delivery_workspace,
1219
+ settlement_identity=settlement_identity,
1220
+ )
1221
+ if delivery_workspace_causality:
1222
+ record["delivery_workspace_causality"] = delivery_workspace_causality
1223
+ if autonomous_replan_recorded:
1224
+ if "autonomous_replan_ack" not in record:
1225
+ record["autonomous_replan_ack"] = {
1226
+ "schema_version": "autonomous_replan_ack_v0",
1227
+ "recorded": False,
1228
+ "source": "refresh_state",
1229
+ "delta_contract": repair_delta_contract,
1230
+ }
1231
+ record["autonomous_replan_ack"]["requested"] = True
1232
+ if autonomous_replan_frontier_identity:
1233
+ record["autonomous_replan_ack"]["frontier_identity"] = (
1234
+ autonomous_replan_frontier_identity
1235
+ )
1236
+ if requested_classification != classification:
1237
+ record["autonomous_replan_ack"]["requested_classification"] = requested_classification
1238
+ record["autonomous_replan_noop"] = {
1239
+ "schema_version": REPAIR_NOOP_SCHEMA_VERSION,
1240
+ "classification": classification,
1241
+ "requested_classification": requested_classification,
1242
+ "reason": "autonomous replan ACK requested without a machine-visible repair delta",
1243
+ }
1244
+ if replan_semantic_delta:
1245
+ record.setdefault(
1246
+ "autonomous_replan_ack",
1247
+ {
1248
+ "schema_version": "autonomous_replan_ack_v0",
1249
+ "recorded": True,
1250
+ "source": "refresh_state_semantic_delta",
1251
+ },
1252
+ )
1253
+ record["autonomous_replan_ack"]["semantic_delta"] = (
1254
+ replan_semantic_delta
1255
+ )
1256
+ if active_state_next_action_update:
1257
+ record["active_state_next_action_update"] = active_state_next_action_update
1258
+ compact_route = compact_runtime_projection_route(runtime_projection_route)
1259
+ compact_route["projection_enabled"] = bool(sync_global)
1260
+ compact_route["projection_marker_field"] = "shared_runtime_projection"
1261
+ record["runtime_projection_route"] = compact_route
1262
+
1263
+ runs_dir = runtime_root / "goals" / safe_goal_id / "runs"
1264
+ json_path, markdown_path = unique_run_paths(runs_dir, generated_at)
1265
+ index_path = runs_dir / "index.jsonl"
1266
+ index_record, payload = _build_state_refresh_output_projections(
1267
+ record=record,
1268
+ registry_path=registry_path,
1269
+ runtime_root=runtime_root,
1270
+ project=resolved_project,
1271
+ json_path=json_path,
1272
+ markdown_path=markdown_path,
1273
+ index_path=index_path,
1274
+ dry_run=dry_run,
1275
+ autonomous_replan_recorded_requested=bool(autonomous_replan_recorded),
1276
+ )
1277
+ if dry_run:
1278
+ expected_write_scopes = ["runtime_history"]
1279
+ if active_state_next_action_update and active_state_next_action_update.get("would_update"):
1280
+ expected_write_scopes.insert(0, "active_state")
1281
+ if sync_global and route_status in {"resolved", "single_runtime"}:
1282
+ expected_write_scopes.append("global_registry")
1283
+ if shared_runtime_root:
1284
+ expected_write_scopes.append("shared_runtime_projection")
1285
+ patch_parts = [f"append refresh-state run classification={classification}"]
1286
+ if active_state_next_action_update:
1287
+ if active_state_next_action_update.get("would_update"):
1288
+ patch_parts.append("preview active-state Next Action update")
1289
+ else:
1290
+ patch_parts.append("preserve active-state Next Action")
1291
+ if sync_global and route_status in {"resolved", "single_runtime"}:
1292
+ patch_parts.append("sync public-safe registry projection")
1293
+ elif sync_global:
1294
+ patch_parts.append(f"block global sync on {route_status} runtime projection route")
1295
+ if shared_runtime_root:
1296
+ patch_parts.append("project compact refresh to registered shared runtime")
1297
+ payload["local_state_write_correctness"] = build_local_state_write_correctness_dry_run_packet(
1298
+ goal_id=safe_goal_id,
1299
+ writer_id=normalized_agent_id or "loopx.refresh-state",
1300
+ write_class="refresh_state",
1301
+ state_text=expected_write_state_text,
1302
+ target_refs={
1303
+ "state_file_ref": "registry.goal.state_file",
1304
+ "run_history_ref": "runtime.goal.runs",
1305
+ "index_ref": "runtime.goal.runs.index",
1306
+ "global_registry_ref": (
1307
+ "runtime.registry.global"
1308
+ if sync_global and route_status in {"resolved", "single_runtime"}
1309
+ else None
1310
+ ),
1311
+ "shared_runtime_projection_ref": (
1312
+ "shared_runtime.goal.runs.index" if shared_runtime_root else None
1313
+ ),
1314
+ },
1315
+ patch_summary="; ".join(patch_parts),
1316
+ expected_write_scopes=expected_write_scopes,
1317
+ lease_ref=None,
1318
+ projection_status_surface=f"refresh-state dry-run: {classification}",
1319
+ )
1320
+ if not dry_run:
1321
+ runs_dir.mkdir(parents=True, exist_ok=True)
1322
+ json_path, markdown_path = reserve_unique_run_paths(runs_dir, generated_at)
1323
+ index_record["json_path"] = str(json_path)
1324
+ index_record["markdown_path"] = str(markdown_path)
1325
+ payload["json_path"] = str(json_path)
1326
+ payload["markdown_path"] = str(markdown_path)
1327
+ json_path.write_text(
1328
+ json.dumps(record, ensure_ascii=False, indent=2) + "\n",
1329
+ encoding="utf-8",
1330
+ )
1331
+ markdown_path.write_text(render_state_refresh_markdown(payload) + "\n", encoding="utf-8")
1332
+ with index_path.open("a", encoding="utf-8") as f:
1333
+ f.write(json.dumps(index_record, ensure_ascii=False) + "\n")
1334
+ if sync_global and route_status in {"missing", "ambiguous"}:
1335
+ payload["ok"] = False
1336
+ payload["partial_write"] = not dry_run
1337
+ payload["global_sync"] = {
1338
+ "ok": False,
1339
+ "enabled": False,
1340
+ "wrote": False,
1341
+ "reason": f"runtime projection route is {route_status}",
1342
+ "route_status": route_status,
1343
+ }
1344
+ payload["shared_runtime_projection"] = {
1345
+ "ok": False,
1346
+ "status": f"route_{route_status}",
1347
+ "dry_run": dry_run,
1348
+ "raw_artifacts_copied": False,
1349
+ "recommended_action_copied": False,
1350
+ "runtime_projection_route_id": compact_route.get("route_id"),
1351
+ }
1352
+ elif sync_global:
1353
+ payload["global_sync"] = sync_project_registry_to_global(
1354
+ registry_path=registry_path,
1355
+ runtime_root_override=str(global_sync_runtime_root or runtime_root),
1356
+ goal_id=safe_goal_id,
1357
+ dry_run=dry_run,
1358
+ )
1359
+ if shared_runtime_root and payload["global_sync"].get("ok"):
1360
+ projection_record, projection_index = build_shared_runtime_projection(
1361
+ record=record,
1362
+ )
1363
+ try:
1364
+ payload["shared_runtime_projection"] = write_shared_runtime_projection(
1365
+ shared_runtime_root=shared_runtime_root,
1366
+ goal_id=safe_goal_id,
1367
+ record=projection_record,
1368
+ index_record=projection_index,
1369
+ dry_run=dry_run,
1370
+ )
1371
+ except OSError as exc:
1372
+ payload["ok"] = False
1373
+ payload["partial_write"] = not dry_run
1374
+ payload["shared_runtime_projection"] = {
1375
+ "ok": False,
1376
+ "status": "write_failed",
1377
+ "dry_run": dry_run,
1378
+ "shared_runtime_root": str(shared_runtime_root),
1379
+ "raw_artifacts_copied": False,
1380
+ "recommended_action_copied": False,
1381
+ "error": str(exc),
1382
+ }
1383
+ elif shared_runtime_root:
1384
+ payload["ok"] = False
1385
+ payload["partial_write"] = not dry_run
1386
+ payload["shared_runtime_projection"] = {
1387
+ "ok": False,
1388
+ "status": "blocked_by_global_sync",
1389
+ "dry_run": dry_run,
1390
+ "shared_runtime_root": str(shared_runtime_root),
1391
+ "raw_artifacts_copied": False,
1392
+ "recommended_action_copied": False,
1393
+ }
1394
+ else:
1395
+ payload["shared_runtime_projection"] = {
1396
+ "ok": True,
1397
+ "status": "not_required",
1398
+ "dry_run": dry_run,
1399
+ "raw_artifacts_copied": False,
1400
+ "recommended_action_copied": False,
1401
+ }
1402
+ else:
1403
+ payload["global_sync"] = {
1404
+ "enabled": False,
1405
+ "global_registry": str(runtime_root / "registry.global.json"),
1406
+ "synced_goal_ids": [],
1407
+ "wrote": False,
1408
+ }
1409
+ payload["shared_runtime_projection"] = {
1410
+ "ok": True,
1411
+ "status": "disabled",
1412
+ "dry_run": dry_run,
1413
+ "raw_artifacts_copied": False,
1414
+ "recommended_action_copied": False,
1415
+ }
1416
+ return payload