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.
- loopx/__init__.py +5 -0
- loopx/agent_onboarding.py +654 -0
- loopx/agent_registry.py +112 -0
- loopx/ark_managed_agent_host.py +59 -0
- loopx/authority.py +805 -0
- loopx/benchmark.py +2875 -0
- loopx/benchmark_adapters/__init__.py +1 -0
- loopx/benchmark_adapters/agentissue.py +2644 -0
- loopx/benchmark_adapters/agents_last_exam.py +3998 -0
- loopx/benchmark_adapters/edgebench.py +322 -0
- loopx/benchmark_adapters/skillsbench.py +5978 -0
- loopx/benchmark_adapters/skillsbench_acp_failure_policy.py +143 -0
- loopx/benchmark_adapters/skillsbench_acp_process.py +31 -0
- loopx/benchmark_adapters/skillsbench_acp_relay.py +4832 -0
- loopx/benchmark_adapters/skillsbench_batch.py +124 -0
- loopx/benchmark_adapters/skillsbench_bridge_guard.py +209 -0
- loopx/benchmark_adapters/skillsbench_bridge_summary.py +203 -0
- loopx/benchmark_adapters/skillsbench_codex_goal_recovery.py +271 -0
- loopx/benchmark_adapters/skillsbench_codex_goal_trace.py +81 -0
- loopx/benchmark_adapters/skillsbench_codex_runtime.py +339 -0
- loopx/benchmark_adapters/skillsbench_dockerfile_runtime.py +467 -0
- loopx/benchmark_adapters/skillsbench_failure_signals.py +652 -0
- loopx/benchmark_adapters/skillsbench_proxy_runtime.py +327 -0
- loopx/benchmark_adapters/skillsbench_remote_bridge.py +402 -0
- loopx/benchmark_adapters/skillsbench_result_discovery.py +143 -0
- loopx/benchmark_adapters/skillsbench_runner_profile.py +436 -0
- loopx/benchmark_adapters/skillsbench_runner_source.py +99 -0
- loopx/benchmark_adapters/skillsbench_setup_preflight.py +771 -0
- loopx/benchmark_adapters/skillsbench_signals.py +15 -0
- loopx/benchmark_adapters/skillsbench_task_source.py +141 -0
- loopx/benchmark_adapters/skillsbench_turn_route.py +723 -0
- loopx/benchmark_adapters/skillsbench_turn_runtime.py +1069 -0
- loopx/benchmark_adapters/skillsbench_typed_repair.py +689 -0
- loopx/benchmark_adapters/skillsbench_uv_cache.py +111 -0
- loopx/benchmark_adapters/skillsbench_verifier_bootstrap.py +227 -0
- loopx/benchmark_adapters/skillsbench_verifier_cache.py +138 -0
- loopx/benchmark_adapters/terminal_bench.py +10078 -0
- loopx/benchmark_case_analysis.py +1276 -0
- loopx/benchmark_case_state.py +1079 -0
- loopx/benchmark_core/__init__.py +239 -0
- loopx/benchmark_core/adapter.py +84 -0
- loopx/benchmark_core/artifacts.py +517 -0
- loopx/benchmark_core/attempts.py +199 -0
- loopx/benchmark_core/container_exec.py +216 -0
- loopx/benchmark_core/io.py +68 -0
- loopx/benchmark_core/lifecycle.py +211 -0
- loopx/benchmark_core/loop_protocol.py +689 -0
- loopx/benchmark_core/observable_handles.py +348 -0
- loopx/benchmark_core/parity.py +256 -0
- loopx/benchmark_core/remote_closeout.py +482 -0
- loopx/benchmark_core/rounds.py +215 -0
- loopx/benchmark_core/route_profile.py +509 -0
- loopx/benchmark_core/run_permissions.py +206 -0
- loopx/benchmark_core/split_control.py +925 -0
- loopx/benchmark_core/turn_fidelity.py +326 -0
- loopx/benchmark_ledger.py +3793 -0
- loopx/benchmark_ledger_countability.py +372 -0
- loopx/benchmark_ledger_current.py +724 -0
- loopx/benchmark_trajectory.py +405 -0
- loopx/benchmarks/__init__.py +1 -0
- loopx/benchmarks/qualification/__init__.py +1 -0
- loopx/benchmarks/qualification/release_outcome_baseline.py +360 -0
- loopx/benchmarks/read_models/__init__.py +1 -0
- loopx/benchmarks/read_models/benchmark_attempt_accounting.py +53 -0
- loopx/benchmarks/read_models/benchmark_comparison.py +414 -0
- loopx/benchmarks/read_models/benchmark_event_timeline.py +113 -0
- loopx/benchmarks/read_models/benchmark_experiment_report.py +475 -0
- loopx/benchmarks/read_models/benchmark_learning_ledger.py +137 -0
- loopx/benchmarks/read_models/benchmark_lifecycle_contracts.py +228 -0
- loopx/benchmarks/read_models/benchmark_projection.py +723 -0
- loopx/benchmarks/read_models/benchmark_result.py +146 -0
- loopx/benchmarks/read_models/benchmark_run_execution_contract.py +116 -0
- loopx/benchmarks/read_models/benchmark_run_failure.py +157 -0
- loopx/benchmarks/read_models/benchmark_run_metrics.py +213 -0
- loopx/benchmarks/read_models/benchmark_run_post_execution.py +635 -0
- loopx/benchmarks/read_models/benchmark_run_pre_execution.py +541 -0
- loopx/benchmarks/read_models/benchmark_status_compaction.py +1255 -0
- loopx/benchmarks/read_models/benchmark_status_runner.py +780 -0
- loopx/benchmarks/read_models/goal_start_control_score.py +857 -0
- loopx/benchmarks/read_models/skillsbench_post_run_debug.py +746 -0
- loopx/benchmarks/read_models/skillsbench_verifier_attribution.py +269 -0
- loopx/bootstrap.py +1116 -0
- loopx/bootstrap_command_pack.py +2167 -0
- loopx/boundary_authority.py +199 -0
- loopx/canary/__init__.py +1 -0
- loopx/canary/maintainability_ratchet.py +800 -0
- loopx/canary/planner.py +1984 -0
- loopx/canary/premerge.py +1130 -0
- loopx/canary/qualification_profiles.py +309 -0
- loopx/canary/quality_surface_catalog.py +838 -0
- loopx/canary/release_profiles.py +51 -0
- loopx/canary/runner.py +1107 -0
- loopx/canary/smoke_health.py +581 -0
- loopx/canary/smoke_profiles.py +212 -0
- loopx/capabilities/__init__.py +0 -0
- loopx/capabilities/agent_turn_recall/__init__.py +17 -0
- loopx/capabilities/agent_turn_recall/cli.py +369 -0
- loopx/capabilities/agent_turn_recall/core.py +296 -0
- loopx/capabilities/auto_research/__init__.py +16 -0
- loopx/capabilities/auto_research/bootstrap_contract.py +157 -0
- loopx/capabilities/auto_research/cli.py +1468 -0
- loopx/capabilities/auto_research/core.py +11 -0
- loopx/capabilities/auto_research/defaults.py +79 -0
- loopx/capabilities/auto_research/demo_e2e.py +1848 -0
- loopx/capabilities/auto_research/demo_supervisor.py +186 -0
- loopx/capabilities/auto_research/evidence_packet.py +767 -0
- loopx/capabilities/auto_research/human_view.py +794 -0
- loopx/capabilities/auto_research/kernel.py +191 -0
- loopx/capabilities/auto_research/knn_demo_workspace.py +322 -0
- loopx/capabilities/auto_research/live_evidence.py +248 -0
- loopx/capabilities/auto_research/preset.py +176 -0
- loopx/capabilities/auto_research/research_state.py +1085 -0
- loopx/capabilities/auto_research/role_profiles.py +394 -0
- loopx/capabilities/auto_research/rollout_append.py +97 -0
- loopx/capabilities/auto_research/terminal_result_contract.py +422 -0
- loopx/capabilities/auto_research/terminal_result_projection.py +171 -0
- loopx/capabilities/auto_research/terminal_result_query.py +233 -0
- loopx/capabilities/auto_research/terminal_results.py +349 -0
- loopx/capabilities/auto_research/user_contract.py +190 -0
- loopx/capabilities/auto_research/worker_loop.py +163 -0
- loopx/capabilities/auto_research/worker_runtime.py +777 -0
- loopx/capabilities/auto_research/worker_skill/SKILL.md +343 -0
- loopx/capabilities/benchmark_toolkit/__init__.py +19 -0
- loopx/capabilities/benchmark_toolkit/integrity.py +387 -0
- loopx/capabilities/catalog.py +1875 -0
- loopx/capabilities/change_quality/__init__.py +19 -0
- loopx/capabilities/change_quality/cli.py +171 -0
- loopx/capabilities/change_quality/context.py +156 -0
- loopx/capabilities/change_quality/oracles.py +269 -0
- loopx/capabilities/change_quality/policy.py +34 -0
- loopx/capabilities/change_quality/receipt.py +482 -0
- loopx/capabilities/change_quality/result.py +493 -0
- loopx/capabilities/change_quality/scope.py +171 -0
- loopx/capabilities/change_quality/shadow.py +680 -0
- loopx/capabilities/content_ops/__init__.py +0 -0
- loopx/capabilities/content_ops/cli.py +649 -0
- loopx/capabilities/content_ops/connector_packets.py +164 -0
- loopx/capabilities/content_ops/item_lifecycle.py +1000 -0
- loopx/capabilities/content_ops/layout.py +451 -0
- loopx/capabilities/content_ops/markdown.py +456 -0
- loopx/capabilities/content_ops/schemas.py +51 -0
- loopx/capabilities/content_ops/social_browser_x.py +107 -0
- loopx/capabilities/content_ops/surface.py +1956 -0
- loopx/capabilities/content_ops/templates/layout-catalog-v0.json +72 -0
- loopx/capabilities/context_providers/__init__.py +36 -0
- loopx/capabilities/context_providers/base.py +189 -0
- loopx/capabilities/context_providers/factory.py +32 -0
- loopx/capabilities/context_providers/openviking.py +702 -0
- loopx/capabilities/context_providers/service_ownership.py +185 -0
- loopx/capabilities/decision_context/__init__.py +129 -0
- loopx/capabilities/decision_context/architecture.py +83 -0
- loopx/capabilities/decision_context/assembler.py +849 -0
- loopx/capabilities/decision_context/catalog_entry.py +195 -0
- loopx/capabilities/decision_context/cli.py +310 -0
- loopx/capabilities/decision_context/cursor_commit.py +535 -0
- loopx/capabilities/decision_context/outcome_feedback.py +352 -0
- loopx/capabilities/decision_context/packets.py +654 -0
- loopx/capabilities/decision_context/private_state.py +189 -0
- loopx/capabilities/decision_context/profile.py +453 -0
- loopx/capabilities/decision_context/providers.py +228 -0
- loopx/capabilities/decision_context/review_settlement.py +136 -0
- loopx/capabilities/decision_context/runtime.py +273 -0
- loopx/capabilities/decision_context/sources.py +415 -0
- loopx/capabilities/explore/__init__.py +1 -0
- loopx/capabilities/explore/activation.py +198 -0
- loopx/capabilities/explore/adaptive_replay_planner.py +221 -0
- loopx/capabilities/explore/child_replay_runtime.py +463 -0
- loopx/capabilities/explore/composition_frontier.py +291 -0
- loopx/capabilities/explore/counterfactual_runtime.py +578 -0
- loopx/capabilities/explore/episode_runtime.py +647 -0
- loopx/capabilities/explore/harness_checkpoint.py +171 -0
- loopx/capabilities/explore/harness_gate.py +115 -0
- loopx/capabilities/explore/harness_runtime.py +1124 -0
- loopx/capabilities/explore/replay_metrics.py +206 -0
- loopx/capabilities/explore/replay_runtime.py +1271 -0
- loopx/capabilities/explore/resource_portfolio.py +173 -0
- loopx/capabilities/explore/result_log.py +974 -0
- loopx/capabilities/explore/router_state.py +432 -0
- loopx/capabilities/explore/source_history_reconcile.py +255 -0
- loopx/capabilities/explore/speculative_scheduler.py +498 -0
- loopx/capabilities/explore/todo_branch_plan.py +650 -0
- loopx/capabilities/explore/todo_evidence.py +141 -0
- loopx/capabilities/explore/trace_runtime.py +284 -0
- loopx/capabilities/explore/worker_branch_plan.py +1257 -0
- loopx/capabilities/integration_branch/__init__.py +13 -0
- loopx/capabilities/integration_branch/cli.py +148 -0
- loopx/capabilities/integration_branch/core.py +916 -0
- loopx/capabilities/issue_fix/__init__.py +19 -0
- loopx/capabilities/issue_fix/acceptance_loop.py +1050 -0
- loopx/capabilities/issue_fix/candidate_evidence.py +503 -0
- loopx/capabilities/issue_fix/candidate_preflight.py +676 -0
- loopx/capabilities/issue_fix/cli.py +1822 -0
- loopx/capabilities/issue_fix/cli_input.py +87 -0
- loopx/capabilities/issue_fix/content_ops_cli.py +148 -0
- loopx/capabilities/issue_fix/discovered_issue_promotion.py +947 -0
- loopx/capabilities/issue_fix/explore_projection.py +710 -0
- loopx/capabilities/issue_fix/feasibility.py +542 -0
- loopx/capabilities/issue_fix/github_public.py +661 -0
- loopx/capabilities/issue_fix/intake_surface.py +832 -0
- loopx/capabilities/issue_fix/metadata_preview.py +218 -0
- loopx/capabilities/issue_fix/metrics_projection.py +1340 -0
- loopx/capabilities/issue_fix/metrics_supplement.py +634 -0
- loopx/capabilities/issue_fix/metrics_supplement_cli.py +127 -0
- loopx/capabilities/issue_fix/outcome_projection.py +1235 -0
- loopx/capabilities/issue_fix/periodic_report.py +189 -0
- loopx/capabilities/issue_fix/pr_description.py +418 -0
- loopx/capabilities/issue_fix/pr_gate_reconcile.py +496 -0
- loopx/capabilities/issue_fix/pr_gate_reconcile_cli.py +464 -0
- loopx/capabilities/issue_fix/pr_lifecycle.py +1327 -0
- loopx/capabilities/issue_fix/pr_lifecycle_rollout.py +85 -0
- loopx/capabilities/issue_fix/pr_monitor_materialization.py +257 -0
- loopx/capabilities/issue_fix/pr_review_ack.py +439 -0
- loopx/capabilities/issue_fix/provider_hooks.py +24 -0
- loopx/capabilities/issue_fix/repository_commit_evidence.py +186 -0
- loopx/capabilities/issue_fix/repository_context.py +457 -0
- loopx/capabilities/issue_fix/repository_memory.py +459 -0
- loopx/capabilities/issue_fix/repository_memory_provider.py +1454 -0
- loopx/capabilities/issue_fix/repository_snapshot.py +454 -0
- loopx/capabilities/issue_fix/reviewer_cli.py +917 -0
- loopx/capabilities/issue_fix/reviewer_notification.py +882 -0
- loopx/capabilities/issue_fix/reviewer_notification_drain.py +942 -0
- loopx/capabilities/issue_fix/reviewer_recommendation.py +1057 -0
- loopx/capabilities/issue_fix/reviewer_request.py +1282 -0
- loopx/capabilities/issue_fix/reward_memory.py +879 -0
- loopx/capabilities/issue_fix/workflow_plan.py +1286 -0
- loopx/capabilities/material_lifecycle/__init__.py +161 -0
- loopx/capabilities/material_lifecycle/_validation.py +183 -0
- loopx/capabilities/material_lifecycle/apply.py +672 -0
- loopx/capabilities/material_lifecycle/architecture.py +122 -0
- loopx/capabilities/material_lifecycle/cli.py +161 -0
- loopx/capabilities/material_lifecycle/decision_planning.py +470 -0
- loopx/capabilities/material_lifecycle/explore_execution.py +306 -0
- loopx/capabilities/material_lifecycle/intake.py +869 -0
- loopx/capabilities/material_lifecycle/inventory.py +147 -0
- loopx/capabilities/material_lifecycle/lifecycle.py +98 -0
- loopx/capabilities/material_lifecycle/preparation.py +147 -0
- loopx/capabilities/material_lifecycle/project_skill.py +83 -0
- loopx/capabilities/material_lifecycle/ranking.py +267 -0
- loopx/capabilities/material_lifecycle/readable_projection.py +500 -0
- loopx/capabilities/material_lifecycle/rebuild.py +480 -0
- loopx/capabilities/material_lifecycle/settlement.py +238 -0
- loopx/capabilities/periodic_report/__init__.py +71 -0
- loopx/capabilities/periodic_report/adapters.py +939 -0
- loopx/capabilities/periodic_report/archive.py +422 -0
- loopx/capabilities/periodic_report/bindings.py +705 -0
- loopx/capabilities/periodic_report/cli.py +277 -0
- loopx/capabilities/periodic_report/core.py +691 -0
- loopx/capabilities/periodic_report/extension_envelope.py +66 -0
- loopx/capabilities/periodic_report/presets.py +103 -0
- loopx/capabilities/periodic_report/profile.py +235 -0
- loopx/capabilities/periodic_report/project_progress.py +179 -0
- loopx/capabilities/periodic_report/triggers.py +452 -0
- loopx/capabilities/pr_review_queue/__init__.py +17 -0
- loopx/capabilities/pr_review_queue/core.py +506 -0
- loopx/capabilities/pr_review_queue/review_contract.py +506 -0
- loopx/capabilities/registry.py +192 -0
- loopx/capabilities/reward_memory/__init__.py +75 -0
- loopx/capabilities/reward_memory/application.py +819 -0
- loopx/capabilities/reward_memory/architecture.py +572 -0
- loopx/capabilities/reward_memory/candidate_review.py +511 -0
- loopx/capabilities/reward_memory/cli.py +469 -0
- loopx/capabilities/reward_memory/dogfood.py +574 -0
- loopx/capabilities/reward_memory/evaluation.py +296 -0
- loopx/capabilities/reward_memory/evaluation_fixtures.py +362 -0
- loopx/capabilities/reward_memory/experiment.py +567 -0
- loopx/capabilities/reward_memory/health.py +222 -0
- loopx/capabilities/reward_memory/ingestion.py +519 -0
- loopx/capabilities/reward_memory/registry.py +600 -0
- loopx/capabilities/reward_memory/runtime_hooks.py +312 -0
- loopx/capabilities/reward_memory/scoped_feedback.py +173 -0
- loopx/capabilities/semantic_preference/__init__.py +12 -0
- loopx/capabilities/semantic_preference/cli.py +189 -0
- loopx/capabilities/semantic_preference/contract.py +592 -0
- loopx/capabilities/semantic_preference/reward_memory.py +62 -0
- loopx/capabilities/value_connectors/__init__.py +1 -0
- loopx/capabilities/value_connectors/cli.py +401 -0
- loopx/capabilities/value_connectors/finance_extension_migration.py +108 -0
- loopx/capabilities/value_connectors/install_check.py +147 -0
- loopx/capabilities/value_connectors/planner.py +733 -0
- loopx/capabilities/value_connectors/source_map.py +446 -0
- loopx/claude_goal_baseline.py +138 -0
- loopx/claude_goal_mode/__init__.py +23 -0
- loopx/claude_goal_mode/hooks/goal_policy.py +212 -0
- loopx/claude_goal_mode/hooks/goal_state.py +139 -0
- loopx/claude_goal_mode/mcp/loopx_mcp.py +167 -0
- loopx/claude_goal_mode/scripts/connect.py +103 -0
- loopx/claude_goal_mode/scripts/goalmode_cmd.py +241 -0
- loopx/claude_goal_mode/scripts/install.py +328 -0
- loopx/claude_goal_mode/statusline/goal_status.py +97 -0
- loopx/cli.py +836 -0
- loopx/cli_commands/__init__.py +334 -0
- loopx/cli_commands/_host_thread.py +13 -0
- loopx/cli_commands/agentissue_runner_flow.py +447 -0
- loopx/cli_commands/agents_last_exam.py +160 -0
- loopx/cli_commands/agents_last_exam_baked_input.py +302 -0
- loopx/cli_commands/agents_last_exam_host_codex.py +374 -0
- loopx/cli_commands/agents_last_exam_launch_dry_run.py +372 -0
- loopx/cli_commands/agents_last_exam_local_plan.py +322 -0
- loopx/cli_commands/agents_last_exam_runner_source.py +352 -0
- loopx/cli_commands/agents_last_exam_task_material.py +335 -0
- loopx/cli_commands/agents_last_exam_validation_gate.py +236 -0
- loopx/cli_commands/benchmark_boundary.py +499 -0
- loopx/cli_commands/benchmark_dispatch.py +161 -0
- loopx/cli_commands/benchmark_release_outcome.py +123 -0
- loopx/cli_commands/benchmark_review_lifecycle.py +1275 -0
- loopx/cli_commands/benchmark_run_ledger.py +763 -0
- loopx/cli_commands/benchmark_run_ledger_case_analysis.py +249 -0
- loopx/cli_commands/benchmark_run_ledger_classification.py +45 -0
- loopx/cli_commands/benchmark_run_ledger_maintenance.py +486 -0
- loopx/cli_commands/benchmark_run_ledger_maintenance_registration.py +342 -0
- loopx/cli_commands/benchmark_run_ledger_maintenance_rendering.py +233 -0
- loopx/cli_commands/benchmark_run_ledger_parity.py +92 -0
- loopx/cli_commands/bootstrap_connect.py +238 -0
- loopx/cli_commands/canary.py +707 -0
- loopx/cli_commands/canary_release_qualification.py +79 -0
- loopx/cli_commands/capability.py +96 -0
- loopx/cli_commands/doctor.py +43 -0
- loopx/cli_commands/dreaming.py +143 -0
- loopx/cli_commands/edgebench.py +205 -0
- loopx/cli_commands/evidence_log.py +275 -0
- loopx/cli_commands/explore.py +989 -0
- loopx/cli_commands/explore_planning_commands.py +157 -0
- loopx/cli_commands/extension.py +271 -0
- loopx/cli_commands/first_run_report.py +73 -0
- loopx/cli_commands/goal_channel.py +656 -0
- loopx/cli_commands/handoff_mode.py +158 -0
- loopx/cli_commands/history.py +622 -0
- loopx/cli_commands/host_mode_plan.py +113 -0
- loopx/cli_commands/lark_inbox.py +431 -0
- loopx/cli_commands/lark_kanban.py +629 -0
- loopx/cli_commands/ml_experiment.py +321 -0
- loopx/cli_commands/multi_agent.py +211 -0
- loopx/cli_commands/opencode2_goal_worker.py +217 -0
- loopx/cli_commands/pr_review.py +167 -0
- loopx/cli_commands/presentation.py +218 -0
- loopx/cli_commands/preset.py +96 -0
- loopx/cli_commands/project.py +150 -0
- loopx/cli_commands/project_lifecycle.py +915 -0
- loopx/cli_commands/quota.py +859 -0
- loopx/cli_commands/quota_registration.py +241 -0
- loopx/cli_commands/quota_request.py +113 -0
- loopx/cli_commands/ready_score.py +110 -0
- loopx/cli_commands/registry_admin.py +975 -0
- loopx/cli_commands/registry_admin_configure.py +344 -0
- loopx/cli_commands/registry_admin_peer.py +84 -0
- loopx/cli_commands/registry_authority.py +218 -0
- loopx/cli_commands/review_batch.py +146 -0
- loopx/cli_commands/slash_commands.py +145 -0
- loopx/cli_commands/start_goal.py +251 -0
- loopx/cli_commands/starter.py +175 -0
- loopx/cli_commands/starter_bootstrap.py +179 -0
- loopx/cli_commands/starter_bootstrap_registration.py +198 -0
- loopx/cli_commands/starter_runtime_idle.py +107 -0
- loopx/cli_commands/starter_scheduler.py +207 -0
- loopx/cli_commands/starter_session_runtime.py +152 -0
- loopx/cli_commands/starter_visible_common.py +54 -0
- loopx/cli_commands/starter_visible_driver.py +161 -0
- loopx/cli_commands/starter_visible_pilot.py +278 -0
- loopx/cli_commands/status.py +867 -0
- loopx/cli_commands/status_registration.py +239 -0
- loopx/cli_commands/summary_all.py +222 -0
- loopx/cli_commands/support_control.py +809 -0
- loopx/cli_commands/support_control_registry.py +68 -0
- loopx/cli_commands/support_control_supervisor.py +289 -0
- loopx/cli_commands/task_lease.py +306 -0
- loopx/cli_commands/terminal_bench_adapter.py +717 -0
- loopx/cli_commands/terminal_bench_environment_result.py +1246 -0
- loopx/cli_commands/todo.py +940 -0
- loopx/cli_commands/todo_argument_validation.py +572 -0
- loopx/cli_commands/todo_event.py +114 -0
- loopx/cli_commands/turn.py +804 -0
- loopx/cli_commands/version.py +46 -0
- loopx/cli_commands/worker_bridge.py +659 -0
- loopx/cli_rollout.py +314 -0
- loopx/codex_cli_goal_tui.py +672 -0
- loopx/codex_cli_probe.py +1530 -0
- loopx/codex_cli_probe_markdown.py +935 -0
- loopx/codex_cli_runtime_probe.py +733 -0
- loopx/codex_cli_scheduler.py +564 -0
- loopx/codex_goal_baseline.py +620 -0
- loopx/configuration_catalog.py +617 -0
- loopx/configure_goal.py +1375 -0
- loopx/contract.py +996 -0
- loopx/control_plane/__init__.py +71 -0
- loopx/control_plane/agents/__init__.py +1 -0
- loopx/control_plane/agents/agent_lane_recommendation.py +516 -0
- loopx/control_plane/agents/agent_scope.py +1578 -0
- loopx/control_plane/agents/agent_scope_frontier.py +60 -0
- loopx/control_plane/agents/capability_gate.py +531 -0
- loopx/control_plane/agents/identity.py +140 -0
- loopx/control_plane/agents/legacy_migration.py +169 -0
- loopx/control_plane/agents/management_projection.py +658 -0
- loopx/control_plane/agents/material_frontier.py +608 -0
- loopx/control_plane/agents/material_handoff.py +156 -0
- loopx/control_plane/agents/multi_agent/__init__.py +1 -0
- loopx/control_plane/agents/multi_agent/codex_executable.py +207 -0
- loopx/control_plane/agents/multi_agent/collective_round_ledger.py +387 -0
- loopx/control_plane/agents/multi_agent/contract.py +474 -0
- loopx/control_plane/agents/multi_agent/recipe.py +110 -0
- loopx/control_plane/agents/multi_agent/role_successor.py +297 -0
- loopx/control_plane/agents/multi_agent/runtime_scripts.py +426 -0
- loopx/control_plane/agents/multi_agent/visible_launch_policy.py +149 -0
- loopx/control_plane/agents/multi_agent/visible_wake_scheduler.py +392 -0
- loopx/control_plane/agents/profile.py +216 -0
- loopx/control_plane/agents/runtime_model.py +73 -0
- loopx/control_plane/agents/subagent_activity.py +164 -0
- loopx/control_plane/agents/supervisor.py +544 -0
- loopx/control_plane/agents/supervisor_events.py +462 -0
- loopx/control_plane/agents/supervisor_inject.py +204 -0
- loopx/control_plane/agents/work_mode.py +56 -0
- loopx/control_plane/agents/workspace_guard.py +364 -0
- loopx/control_plane/effect_program.py +644 -0
- loopx/control_plane/goals/__init__.py +1 -0
- loopx/control_plane/goals/active_state_event_projection.py +103 -0
- loopx/control_plane/goals/active_state_metadata.py +47 -0
- loopx/control_plane/goals/active_state_sections.py +58 -0
- loopx/control_plane/goals/configure_goal_service.py +354 -0
- loopx/control_plane/goals/contract_health.py +132 -0
- loopx/control_plane/goals/dreaming.py +152 -0
- loopx/control_plane/goals/global_registry_health.py +199 -0
- loopx/control_plane/goals/global_registry_shadow.py +33 -0
- loopx/control_plane/goals/goal_channel.py +34 -0
- loopx/control_plane/goals/goal_channel_projection.py +560 -0
- loopx/control_plane/goals/goal_frontier/__init__.py +1917 -0
- loopx/control_plane/goals/goal_frontier/ack_policy.py +149 -0
- loopx/control_plane/goals/goal_frontier/outcome_continuity.py +437 -0
- loopx/control_plane/goals/goal_frontier/replan_rules.py +210 -0
- loopx/control_plane/goals/goal_frontier/semantic_history.py +314 -0
- loopx/control_plane/goals/goal_frontier/terminal.py +180 -0
- loopx/control_plane/goals/goal_vision.py +443 -0
- loopx/control_plane/goals/goal_vision_policy.py +36 -0
- loopx/control_plane/goals/goal_vision_state.py +62 -0
- loopx/control_plane/goals/goal_vision_wait.py +290 -0
- loopx/control_plane/goals/path_resolution.py +20 -0
- loopx/control_plane/goals/start_contract.py +206 -0
- loopx/control_plane/goals/vision_checkpoint.py +92 -0
- loopx/control_plane/handoff/__init__.py +1 -0
- loopx/control_plane/handoff/cross_runtime_impl_review.py +311 -0
- loopx/control_plane/handoff/delivery_contract.py +161 -0
- loopx/control_plane/handoff/handoff_runs.py +71 -0
- loopx/control_plane/handoff/project_handoff.py +155 -0
- loopx/control_plane/handoff/review_batch.py +463 -0
- loopx/control_plane/handoff/review_packet_context.py +216 -0
- loopx/control_plane/heartbeat/agent.py +173 -0
- loopx/control_plane/heartbeat/budget.py +66 -0
- loopx/control_plane/heartbeat/builder.py +501 -0
- loopx/control_plane/heartbeat/host.py +64 -0
- loopx/control_plane/heartbeat/rules.py +68 -0
- loopx/control_plane/heartbeat/task_body.py +759 -0
- loopx/control_plane/heartbeat/visible_goal.py +86 -0
- loopx/control_plane/projects/__init__.py +1 -0
- loopx/control_plane/projects/contract.py +25 -0
- loopx/control_plane/projects/registry.py +663 -0
- loopx/control_plane/quota/__init__.py +1 -0
- loopx/control_plane/quota/cli_projection.py +704 -0
- loopx/control_plane/quota/decision_summary.py +431 -0
- loopx/control_plane/quota/effect_program.py +152 -0
- loopx/control_plane/quota/error_codes.py +19 -0
- loopx/control_plane/quota/goal_boundary.py +464 -0
- loopx/control_plane/quota/heartbeat_receipt.py +277 -0
- loopx/control_plane/quota/heartbeat_recommendation.py +718 -0
- loopx/control_plane/quota/host_poll_receipts.py +162 -0
- loopx/control_plane/quota/live_decision.py +142 -0
- loopx/control_plane/quota/monitor_poll.py +786 -0
- loopx/control_plane/quota/policy_constants.py +40 -0
- loopx/control_plane/quota/projection_repair.py +262 -0
- loopx/control_plane/quota/recent_runs.py +210 -0
- loopx/control_plane/quota/scheduler_ack.py +490 -0
- loopx/control_plane/quota/selected_todo_projection.py +139 -0
- loopx/control_plane/quota/settlement.py +437 -0
- loopx/control_plane/quota/settlement_cli.py +246 -0
- loopx/control_plane/quota/settlement_validation.py +64 -0
- loopx/control_plane/quota/settlement_workspace_causality.py +180 -0
- loopx/control_plane/quota/should_run.py +249 -0
- loopx/control_plane/quota/should_run_packet.py +1165 -0
- loopx/control_plane/quota/should_run_prepare.py +675 -0
- loopx/control_plane/quota/slot_accounting.py +1123 -0
- loopx/control_plane/quota/spend_sources.py +11 -0
- loopx/control_plane/quota/stall_repair.py +397 -0
- loopx/control_plane/quota/states.py +29 -0
- loopx/control_plane/quota/task_orchestration.py +448 -0
- loopx/control_plane/quota/task_orchestration_admission.py +497 -0
- loopx/control_plane/quota/turn_envelope.py +889 -0
- loopx/control_plane/quota/usage_summary.py +140 -0
- loopx/control_plane/reward_memory.py +43 -0
- loopx/control_plane/runtime/__init__.py +2 -0
- loopx/control_plane/runtime/active_user_assisted_pilot.py +275 -0
- loopx/control_plane/runtime/agent_scoped_evidence_log.py +435 -0
- loopx/control_plane/runtime/decision_freshness.py +203 -0
- loopx/control_plane/runtime/event_ledger.py +197 -0
- loopx/control_plane/runtime/event_store_migration_bridge.py +196 -0
- loopx/control_plane/runtime/goal_project_route.py +70 -0
- loopx/control_plane/runtime/local_state_write_correctness.py +242 -0
- loopx/control_plane/runtime/promotion_readiness.py +152 -0
- loopx/control_plane/runtime/public_safety.py +120 -0
- loopx/control_plane/runtime/run_artifacts.py +78 -0
- loopx/control_plane/runtime/run_compaction.py +397 -0
- loopx/control_plane/runtime/run_context_retention.py +241 -0
- loopx/control_plane/runtime/run_history.py +132 -0
- loopx/control_plane/runtime/run_index_duplicates.py +205 -0
- loopx/control_plane/runtime/run_index_rebuild.py +263 -0
- loopx/control_plane/runtime/run_ingest_health.py +336 -0
- loopx/control_plane/runtime/runtime_projection_route.py +624 -0
- loopx/control_plane/runtime/runtime_projection_writer.py +98 -0
- loopx/control_plane/runtime/session_runtime.py +339 -0
- loopx/control_plane/runtime/shared_runtime_material_projection.py +332 -0
- loopx/control_plane/runtime/shared_runtime_refresh_projection.py +183 -0
- loopx/control_plane/runtime/stale_latest_run.py +90 -0
- loopx/control_plane/runtime/status_classifications.py +49 -0
- loopx/control_plane/runtime/status_projection_cache.py +235 -0
- loopx/control_plane/runtime/stride_observation.py +144 -0
- loopx/control_plane/runtime/time.py +39 -0
- loopx/control_plane/runtime/trajectory_hygiene.py +149 -0
- loopx/control_plane/runtime/validation_command.py +69 -0
- loopx/control_plane/scheduler/__init__.py +1 -0
- loopx/control_plane/scheduler/ack.py +329 -0
- loopx/control_plane/scheduler/arbitration.py +188 -0
- loopx/control_plane/scheduler/automation_liveness.py +183 -0
- loopx/control_plane/scheduler/execution_context.py +555 -0
- loopx/control_plane/scheduler/external_evidence_observation.py +428 -0
- loopx/control_plane/scheduler/monitor_display.py +143 -0
- loopx/control_plane/scheduler/monitor_poll_policy.py +161 -0
- loopx/control_plane/scheduler/monitor_poll_writeback.py +351 -0
- loopx/control_plane/scheduler/monitor_target.py +64 -0
- loopx/control_plane/scheduler/monitor_todo.py +146 -0
- loopx/control_plane/scheduler/monitor_wait.py +237 -0
- loopx/control_plane/scheduler/scheduler_hint.py +1284 -0
- loopx/control_plane/scheduler/state.py +354 -0
- loopx/control_plane/scheduler/state_transition_rules.py +179 -0
- loopx/control_plane/scheduler/time.py +10 -0
- loopx/control_plane/settlement_driver.py +293 -0
- loopx/control_plane/status/__init__.py +6 -0
- loopx/control_plane/status/active_state_projection.py +105 -0
- loopx/control_plane/status/agent_lane_projection.py +375 -0
- loopx/control_plane/status/attention_projection.py +74 -0
- loopx/control_plane/status/autonomous_replan_projection.py +103 -0
- loopx/control_plane/status/collection.py +140 -0
- loopx/control_plane/status/contract_projection.py +31 -0
- loopx/control_plane/status/dreaming_projection.py +52 -0
- loopx/control_plane/status/goal_attention_projection.py +157 -0
- loopx/control_plane/status/lifecycle_projection.py +110 -0
- loopx/control_plane/status/monitor_display_projection.py +69 -0
- loopx/control_plane/status/registry_health_projection.py +75 -0
- loopx/control_plane/status/run_projection.py +70 -0
- loopx/control_plane/status/runtime_summaries.py +161 -0
- loopx/control_plane/testing/__init__.py +1 -0
- loopx/control_plane/testing/actual_default_model_behavior_portfolio.py +1371 -0
- loopx/control_plane/testing/canary_harness.py +182 -0
- loopx/control_plane/testing/capability_monitor_repair_tool_behavior.py +674 -0
- loopx/control_plane/testing/cli_output_budget.py +807 -0
- loopx/control_plane/testing/cli_output_differential.py +250 -0
- loopx/control_plane/testing/cli_output_semantics.py +87 -0
- loopx/control_plane/testing/control_plane_composition_scenarios.py +225 -0
- loopx/control_plane/testing/decision_replay.py +268 -0
- loopx/control_plane/testing/doubao_model_behavior_actor.py +559 -0
- loopx/control_plane/testing/model_behavior_corpus.py +344 -0
- loopx/control_plane/testing/model_behavior_qualification.py +769 -0
- loopx/control_plane/testing/model_behavior_retained_cases.py +235 -0
- loopx/control_plane/testing/model_tool_behavior.py +536 -0
- loopx/control_plane/testing/onboarding_model_behavior_qualification.py +642 -0
- loopx/control_plane/testing/quota_fixtures.py +208 -0
- loopx/control_plane/testing/quota_should_run_parity.py +57 -0
- loopx/control_plane/testing/release_commit_qualification.py +671 -0
- loopx/control_plane/testing/replan_semantic_action_behavior.py +1302 -0
- loopx/control_plane/testing/scoped_gate_successor_tool_behavior.py +527 -0
- loopx/control_plane/testing/selected_todo_tool_behavior.py +1002 -0
- loopx/control_plane/testing/terminal_settlement_tool_behavior.py +656 -0
- loopx/control_plane/todos/__init__.py +1 -0
- loopx/control_plane/todos/active_state_editing.py +296 -0
- loopx/control_plane/todos/active_state_todo_parser.py +138 -0
- loopx/control_plane/todos/active_state_todos.py +175 -0
- loopx/control_plane/todos/addition.py +103 -0
- loopx/control_plane/todos/claim_visibility.py +253 -0
- loopx/control_plane/todos/completed_archive.py +139 -0
- loopx/control_plane/todos/completion_fence.py +49 -0
- loopx/control_plane/todos/completion_policy.py +153 -0
- loopx/control_plane/todos/completion_validation.py +248 -0
- loopx/control_plane/todos/completion_validation_accountability.py +27 -0
- loopx/control_plane/todos/completion_validation_projection.py +57 -0
- loopx/control_plane/todos/contract.py +1476 -0
- loopx/control_plane/todos/decision_scope.py +554 -0
- loopx/control_plane/todos/deferred_resume.py +546 -0
- loopx/control_plane/todos/durable_completion.py +201 -0
- loopx/control_plane/todos/event_writeback.py +484 -0
- loopx/control_plane/todos/frontier_deadline.py +132 -0
- loopx/control_plane/todos/handoff_gate.py +283 -0
- loopx/control_plane/todos/handoff_mode.py +444 -0
- loopx/control_plane/todos/handoff_note.py +202 -0
- loopx/control_plane/todos/line_update.py +361 -0
- loopx/control_plane/todos/list_projection.py +205 -0
- loopx/control_plane/todos/markdown.py +199 -0
- loopx/control_plane/todos/monitor_metadata.py +88 -0
- loopx/control_plane/todos/mutation_authority.py +299 -0
- loopx/control_plane/todos/projection.py +655 -0
- loopx/control_plane/todos/quota_summary.py +1138 -0
- loopx/control_plane/todos/route_continuation.py +267 -0
- loopx/control_plane/todos/succession_warning.py +174 -0
- loopx/control_plane/todos/summary_item.py +223 -0
- loopx/control_plane/todos/text.py +30 -0
- loopx/control_plane/todos/todo_index.py +226 -0
- loopx/control_plane/todos/todo_summary.py +1458 -0
- loopx/control_plane/todos/unblock_resume.py +326 -0
- loopx/control_plane/todos/user_gate.py +263 -0
- loopx/control_plane/todos/write_hint.py +63 -0
- loopx/control_plane/todos/write_policy.py +135 -0
- loopx/control_plane/turn_driver/__init__.py +85 -0
- loopx/control_plane/turn_driver/codex_cli.py +502 -0
- loopx/control_plane/turn_driver/driver.py +355 -0
- loopx/control_plane/turn_driver/executor.py +1468 -0
- loopx/control_plane/turn_driver/loop_controller.py +669 -0
- loopx/control_plane/turn_driver/settlement.py +318 -0
- loopx/control_plane/turn_driver/transaction.py +375 -0
- loopx/control_plane/work_items/__init__.py +1 -0
- loopx/control_plane/work_items/attention_fields.py +56 -0
- loopx/control_plane/work_items/attention_item.py +77 -0
- loopx/control_plane/work_items/attention_queue.py +322 -0
- loopx/control_plane/work_items/attention_routing.py +213 -0
- loopx/control_plane/work_items/autonomous_candidates.py +135 -0
- loopx/control_plane/work_items/autonomous_replan_ack.py +276 -0
- loopx/control_plane/work_items/autonomous_replan_obligation.py +786 -0
- loopx/control_plane/work_items/backlog_hygiene.py +59 -0
- loopx/control_plane/work_items/capability_monitor_fallback.py +221 -0
- loopx/control_plane/work_items/delivery_batch_scale.py +66 -0
- loopx/control_plane/work_items/delivery_outcome.py +152 -0
- loopx/control_plane/work_items/delivery_signals.py +113 -0
- loopx/control_plane/work_items/execution_obligation.py +235 -0
- loopx/control_plane/work_items/goal_route_hint.py +320 -0
- loopx/control_plane/work_items/interaction_contract.py +1540 -0
- loopx/control_plane/work_items/issue_meta_surface.py +159 -0
- loopx/control_plane/work_items/lifecycle.py +139 -0
- loopx/control_plane/work_items/operator_inbox.py +266 -0
- loopx/control_plane/work_items/outcome_followthrough.py +69 -0
- loopx/control_plane/work_items/primary_action.py +326 -0
- loopx/control_plane/work_items/progress_observation.py +630 -0
- loopx/control_plane/work_items/project_asset.py +675 -0
- loopx/control_plane/work_items/repair_delta.py +693 -0
- loopx/control_plane/work_items/runtime_capability_reentry.py +168 -0
- loopx/control_plane/work_items/semantic_replan_writeback.py +177 -0
- loopx/control_plane/work_items/status_contract.py +49 -0
- loopx/control_plane/work_items/task_graph.py +1046 -0
- loopx/control_plane/work_items/task_lease.py +1254 -0
- loopx/control_plane/work_items/task_lease_settlement.py +422 -0
- loopx/control_plane/work_items/work_lane.py +510 -0
- loopx/control_plane/work_items/work_lane_context.py +161 -0
- loopx/demo.py +247 -0
- loopx/diagnose.py +633 -0
- loopx/doctor.py +1251 -0
- loopx/domain_packs/__init__.py +1 -0
- loopx/domain_packs/issue_fix.py +571 -0
- loopx/domain_packs/ml_experiment.py +854 -0
- loopx/domain_state.py +137 -0
- loopx/dreaming.py +706 -0
- loopx/entrypoint.py +16 -0
- loopx/event_sourced_state.py +981 -0
- loopx/execution_profile.py +286 -0
- loopx/experiments/__init__.py +1 -0
- loopx/experiments/planner_worker/__init__.py +1 -0
- loopx/experiments/planner_worker/contract.py +523 -0
- loopx/experiments/planner_worker/runtime.py +391 -0
- loopx/experiments/planner_worker/traex.py +461 -0
- loopx/explore_graph.py +11 -0
- loopx/extensions/__init__.py +1 -0
- loopx/extensions/bundled.py +28 -0
- loopx/extensions/execution_envelope.py +126 -0
- loopx/extensions/lark/__init__.py +11 -0
- loopx/extensions/lark/event_collector.py +478 -0
- loopx/extensions/lark/event_collector_runtime.py +506 -0
- loopx/extensions/lark/event_inbox.py +454 -0
- loopx/extensions/lark/extension.toml +88 -0
- loopx/extensions/lark/goal_channel.py +44 -0
- loopx/extensions/lark/goal_channel_contracts.py +388 -0
- loopx/extensions/lark/goal_channel_lifecycle.py +218 -0
- loopx/extensions/lark/goal_channel_runtime.py +792 -0
- loopx/extensions/lark/goal_channel_setup.py +805 -0
- loopx/extensions/lark/goal_channel_targets.py +215 -0
- loopx/extensions/lark/goal_channel_transport.py +281 -0
- loopx/extensions/lark/inbox_reactions.py +650 -0
- loopx/extensions/lark/inbox_reply.py +430 -0
- loopx/extensions/lark/presentation/__init__.py +11 -0
- loopx/extensions/lark/presentation/explore_results.py +2276 -0
- loopx/extensions/lark/presentation/explore_singleflight.py +127 -0
- loopx/extensions/lark/presentation/explore_source_guard.py +121 -0
- loopx/extensions/lark/presentation/explore_stage_document.py +703 -0
- loopx/extensions/lark/presentation/explore_visual_integrity.py +122 -0
- loopx/extensions/lark/presentation/explore_visual_readback.py +452 -0
- loopx/extensions/lark/presentation/explore_visual_styles.py +156 -0
- loopx/extensions/lark/presentation/issue_fix_surface.py +612 -0
- loopx/extensions/lark/presentation/kanban.py +2791 -0
- loopx/extensions/lark/presentation/message_card.py +112 -0
- loopx/extensions/lark/presentation/periodic_report.py +261 -0
- loopx/extensions/lark/presentation/projection_rows.py +600 -0
- loopx/extensions/lark/presentation/record_io.py +95 -0
- loopx/extensions/lark/presentation/sync_receipt.py +145 -0
- loopx/extensions/lark/private_json.py +40 -0
- loopx/extensions/lark/provider.py +86 -0
- loopx/extensions/lark/reviewer_notification.py +604 -0
- loopx/extensions/manifest.py +385 -0
- loopx/extensions/openviking_periodic_report/__init__.py +17 -0
- loopx/extensions/openviking_periodic_report/activation.py +173 -0
- loopx/extensions/openviking_periodic_report/extension.toml +17 -0
- loopx/extensions/openviking_periodic_report/provider.py +355 -0
- loopx/extensions/openviking_periodic_report/sink.py +117 -0
- loopx/extensions/openviking_semantic_preference/__init__.py +5 -0
- loopx/extensions/openviking_semantic_preference/extension.toml +16 -0
- loopx/extensions/openviking_semantic_preference/history_export.py +484 -0
- loopx/extensions/openviking_semantic_preference/project_peer.py +68 -0
- loopx/extensions/openviking_semantic_preference/provider.py +312 -0
- loopx/extensions/presentation.py +979 -0
- loopx/extensions/process_runtime.py +204 -0
- loopx/extensions/readiness.py +168 -0
- loopx/extensions/runtime.py +931 -0
- loopx/extensions/scaffold.py +335 -0
- loopx/feedback.py +581 -0
- loopx/file_lock.py +382 -0
- loopx/global_registry.py +842 -0
- loopx/global_risks.py +970 -0
- loopx/global_todos.py +568 -0
- loopx/handoff_budget.py +28 -0
- loopx/heartbeat_prequota.py +80 -0
- loopx/heartbeat_prompt.py +159 -0
- loopx/help_surface.py +516 -0
- loopx/history.py +1507 -0
- loopx/host_loop_activation.py +1311 -0
- loopx/host_mode_planner.py +991 -0
- loopx/install_contract.py +1 -0
- loopx/interface_budget.py +196 -0
- loopx/long_task_cadence.py +208 -0
- loopx/materials.py +185 -0
- loopx/ml_experiment.py +3 -0
- loopx/onboarding.py +214 -0
- loopx/opencode2_goal_mode/README.md +81 -0
- loopx/opencode2_goal_mode/__init__.py +9 -0
- loopx/opencode2_goal_mode/opencode2-goal-worker.mjs +1018 -0
- loopx/opencode_goal_mode/README.md +99 -0
- loopx/opencode_goal_mode/__init__.py +13 -0
- loopx/opencode_goal_mode/goal-bridge-runtime.mjs +858 -0
- loopx/opencode_goal_mode/loopx-goal.js +8 -0
- loopx/operator_gate.py +420 -0
- loopx/orchestration.py +127 -0
- loopx/paths.py +59 -0
- loopx/pi_goal_mode/README.md +67 -0
- loopx/pi_goal_mode/__init__.py +13 -0
- loopx/pi_goal_mode/loopx-goal.ts +254 -0
- loopx/pi_goal_mode/pi-goal-loop-runtime.mjs +574 -0
- loopx/pr_review.py +1206 -0
- loopx/presentation/__init__.py +1 -0
- loopx/presentation/explore_views.py +1334 -0
- loopx/presentation/markdown.py +61 -0
- loopx/presentation/projection_source_reconcile.py +140 -0
- loopx/presentation/public_safety.py +42 -0
- loopx/presentation/renderers/__init__.py +17 -0
- loopx/presentation/renderers/goal_channel_html.py +269 -0
- loopx/presentation/renderers/periodic_report_html.py +786 -0
- loopx/presentation/renderers/periodic_report_markdown.py +184 -0
- loopx/presentation/renderers/quota_event_markdown.py +116 -0
- loopx/presentation/renderers/quota_markdown.py +1112 -0
- loopx/presentation/renderers/status_markdown.py +1570 -0
- loopx/presentation/renderers/trajectory_hygiene_markdown.py +39 -0
- loopx/presentation/renderers/turn_envelope_markdown.py +33 -0
- loopx/presentation/sinks/__init__.py +5 -0
- loopx/presentation/sinks/openviking_periodic_report.py +7 -0
- loopx/presentation/static_site.py +691 -0
- loopx/presets.py +369 -0
- loopx/project_alias.py +217 -0
- loopx/project_map.py +589 -0
- loopx/project_prompt.py +1153 -0
- loopx/project_skill_cli.py +125 -0
- loopx/project_skill_delivery.py +470 -0
- loopx/project_uninstall.py +462 -0
- loopx/promotion_gate.py +197 -0
- loopx/quota.py +1197 -0
- loopx/ready_score.py +413 -0
- loopx/registry.py +621 -0
- loopx/registry_writability.py +64 -0
- loopx/release_candidate.py +148 -0
- loopx/release_manifest.py +316 -0
- loopx/repository_identity.py +100 -0
- loopx/review_packet.py +1024 -0
- loopx/rollout_event_log.py +505 -0
- loopx/runtime.py +112 -0
- loopx/self_update.py +750 -0
- loopx/session_runtime.py +418 -0
- loopx/skill_install_readback.py +500 -0
- loopx/slash_command_install.py +1393 -0
- loopx/slash_commands.py +264 -0
- loopx/state_backup.py +573 -0
- loopx/state_migration.py +350 -0
- loopx/state_projection.py +809 -0
- loopx/state_refresh.py +1416 -0
- loopx/status.py +1383 -0
- loopx/status_server.py +935 -0
- loopx/summary_all.py +725 -0
- loopx/terminal_bench_agent.py +2056 -0
- loopx/thread_agent_binding.py +408 -0
- loopx/todo_followups.py +168 -0
- loopx/todo_suggestion_prompt.py +204 -0
- loopx/todos.py +2229 -0
- loopx/turn_identity.py +17 -0
- loopx/upgrade.py +1083 -0
- loopx/visible_governance.py +667 -0
- loopx/visible_multi_agent_launcher.py +1253 -0
- loopx/visible_multi_agent_tmux.py +429 -0
- loopx/worker_bridge.py +1574 -0
- loopx-0.4.8.dist-info/METADATA +708 -0
- loopx-0.4.8.dist-info/RECORD +811 -0
- loopx-0.4.8.dist-info/WHEEL +5 -0
- loopx-0.4.8.dist-info/entry_points.txt +5 -0
- loopx-0.4.8.dist-info/licenses/LICENSE +202 -0
- loopx-0.4.8.dist-info/licenses/LICENSE-MIT +21 -0
- loopx-0.4.8.dist-info/licenses/NOTICE +6 -0
- loopx-0.4.8.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,940 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from ..control_plane.todos.contract import (
|
|
8
|
+
TODO_CONTINUATION_POLICY_VALUES,
|
|
9
|
+
replan_successor_semantic_binding,
|
|
10
|
+
)
|
|
11
|
+
from ..control_plane.quota.settlement import (
|
|
12
|
+
require_settlement_spend,
|
|
13
|
+
require_settlement_terminal_closeout,
|
|
14
|
+
require_settlement_writeback,
|
|
15
|
+
resolve_heartbeat_settlement_identity,
|
|
16
|
+
settlement_result_payload,
|
|
17
|
+
)
|
|
18
|
+
from ..control_plane.todos.handoff_mode import HandoffModeError
|
|
19
|
+
from ..control_plane.todos.markdown import render_todo_markdown
|
|
20
|
+
from ..control_plane.work_items.task_lease import TaskLeaseError
|
|
21
|
+
from ..file_lock import lock_timeout_error_fields
|
|
22
|
+
from ..history import load_index, load_registry
|
|
23
|
+
from ..paths import resolve_runtime_root
|
|
24
|
+
from ..registry import registry_goals
|
|
25
|
+
from ..control_plane.work_items.semantic_replan_writeback import (
|
|
26
|
+
qualify_replan_writeback,
|
|
27
|
+
)
|
|
28
|
+
from ..todo_followups import capture_followup_todos
|
|
29
|
+
from ..todo_suggestion_prompt import (
|
|
30
|
+
ALLOWED_TODO_SUGGESTION_SOURCES,
|
|
31
|
+
ALLOWED_TODO_SUGGESTION_TRIGGERS,
|
|
32
|
+
build_todo_suggestion_prompt_packet,
|
|
33
|
+
render_todo_suggestion_prompt_markdown,
|
|
34
|
+
)
|
|
35
|
+
from ..todos import (
|
|
36
|
+
ARCHIVE_COMPLETED_DEFAULT_MAX_ACTIVE_DONE,
|
|
37
|
+
add_goal_todo,
|
|
38
|
+
archive_completed_todos,
|
|
39
|
+
complete_goal_todo,
|
|
40
|
+
list_goal_todos,
|
|
41
|
+
resolve_todo_state,
|
|
42
|
+
supersede_goal_todo,
|
|
43
|
+
update_goal_todo,
|
|
44
|
+
)
|
|
45
|
+
from .todo_argument_validation import (
|
|
46
|
+
register_todo_linkage_arguments,
|
|
47
|
+
register_todo_successor_creation_arguments,
|
|
48
|
+
validate_capability_gap_options,
|
|
49
|
+
validate_shared_todo_options,
|
|
50
|
+
validate_todo_add_options,
|
|
51
|
+
validate_todo_archive_completed_options,
|
|
52
|
+
validate_todo_capture_followups_options,
|
|
53
|
+
validate_todo_claim_options,
|
|
54
|
+
validate_todo_complete_options,
|
|
55
|
+
validate_todo_list_options,
|
|
56
|
+
validate_todo_suggest_options,
|
|
57
|
+
validate_todo_supersede_options,
|
|
58
|
+
validate_todo_update_options,
|
|
59
|
+
)
|
|
60
|
+
from .todo_event import RolloutEventAppender, append_todo_rollout_event
|
|
61
|
+
|
|
62
|
+
PrintPayload = Callable[
|
|
63
|
+
[dict[str, object], str, Callable[[dict[str, object]], str]],
|
|
64
|
+
None,
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _validated_replan_successor_obligation(
|
|
69
|
+
args: argparse.Namespace,
|
|
70
|
+
*,
|
|
71
|
+
registry_path: Path,
|
|
72
|
+
runtime_root_arg: str | None,
|
|
73
|
+
) -> str | None:
|
|
74
|
+
requested = str(getattr(args, "replan_obligation_id", None) or "").strip()
|
|
75
|
+
if not requested:
|
|
76
|
+
return None
|
|
77
|
+
if not (
|
|
78
|
+
args.role == "agent"
|
|
79
|
+
and args.task_class == "advancement_task"
|
|
80
|
+
and args.claimed_by
|
|
81
|
+
):
|
|
82
|
+
raise ValueError(
|
|
83
|
+
"--replan-obligation-id requires --role agent --task-class "
|
|
84
|
+
"advancement_task and --claimed-by"
|
|
85
|
+
)
|
|
86
|
+
if replan_successor_semantic_binding(
|
|
87
|
+
action_kind=args.action_kind,
|
|
88
|
+
target_key=args.monitor_target_key,
|
|
89
|
+
explore_result_node_refs=args.explore_result_node_refs,
|
|
90
|
+
) is None:
|
|
91
|
+
raise ValueError(
|
|
92
|
+
"--replan-obligation-id requires --action-kind and either "
|
|
93
|
+
"--target-key or --explore-result-node-ref"
|
|
94
|
+
)
|
|
95
|
+
registry = load_registry(registry_path)
|
|
96
|
+
runtime_root = resolve_runtime_root(registry, runtime_root_arg)
|
|
97
|
+
_, _, state_text, _ = resolve_todo_state(
|
|
98
|
+
registry_path=registry_path,
|
|
99
|
+
goal_id=args.goal_id,
|
|
100
|
+
**_todo_path_args(args),
|
|
101
|
+
)
|
|
102
|
+
existing_runs, _ = load_index(
|
|
103
|
+
runtime_root / "goals" / args.goal_id / "runs" / "index.jsonl"
|
|
104
|
+
)
|
|
105
|
+
newest_first_runs = [
|
|
106
|
+
run
|
|
107
|
+
for _, run in sorted(
|
|
108
|
+
enumerate(existing_runs),
|
|
109
|
+
key=lambda item: (
|
|
110
|
+
str(item[1].get("generated_at") or ""),
|
|
111
|
+
item[0],
|
|
112
|
+
),
|
|
113
|
+
reverse=True,
|
|
114
|
+
)
|
|
115
|
+
]
|
|
116
|
+
registry_goal = next(
|
|
117
|
+
(
|
|
118
|
+
item
|
|
119
|
+
for item in registry_goals(registry)
|
|
120
|
+
if str(item.get("id") or "").strip() == args.goal_id
|
|
121
|
+
),
|
|
122
|
+
None,
|
|
123
|
+
)
|
|
124
|
+
obligation, _ = qualify_replan_writeback(
|
|
125
|
+
newest_first_runs=newest_first_runs,
|
|
126
|
+
state_text=state_text,
|
|
127
|
+
agent_id=args.claimed_by,
|
|
128
|
+
goal_id=args.goal_id,
|
|
129
|
+
registry_goal=registry_goal,
|
|
130
|
+
)
|
|
131
|
+
current = str((obligation or {}).get("obligation_id") or "").strip()
|
|
132
|
+
if not current:
|
|
133
|
+
raise ValueError(
|
|
134
|
+
"--replan-obligation-id was provided but this agent has no open "
|
|
135
|
+
"replan obligation"
|
|
136
|
+
)
|
|
137
|
+
if current != requested:
|
|
138
|
+
raise ValueError(
|
|
139
|
+
"--replan-obligation-id does not match the current open obligation: "
|
|
140
|
+
f"expected {current}"
|
|
141
|
+
)
|
|
142
|
+
return current
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def register_todo_command(
|
|
146
|
+
subparsers: argparse._SubParsersAction,
|
|
147
|
+
add_subcommand_format: Callable[[argparse.ArgumentParser], None],
|
|
148
|
+
) -> None:
|
|
149
|
+
todo_parser = subparsers.add_parser(
|
|
150
|
+
"todo",
|
|
151
|
+
help="Add a user or agent todo to a goal's active state.",
|
|
152
|
+
description=(
|
|
153
|
+
"Manage goal todos. The options below are the union for every todo "
|
|
154
|
+
"command; each option's help names the commands that accept it, and "
|
|
155
|
+
"unsupported combinations fail before state is read or written."
|
|
156
|
+
),
|
|
157
|
+
)
|
|
158
|
+
add_subcommand_format(todo_parser)
|
|
159
|
+
todo_parser.add_argument(
|
|
160
|
+
"todo_command",
|
|
161
|
+
nargs="?",
|
|
162
|
+
choices=[
|
|
163
|
+
"add",
|
|
164
|
+
"list",
|
|
165
|
+
"claim",
|
|
166
|
+
"update",
|
|
167
|
+
"complete",
|
|
168
|
+
"supersede",
|
|
169
|
+
"archive-completed",
|
|
170
|
+
"suggest",
|
|
171
|
+
"capture-followups",
|
|
172
|
+
],
|
|
173
|
+
default=None,
|
|
174
|
+
help=(
|
|
175
|
+
"Use add to append a checkbox todo, claim to soft-claim by registered "
|
|
176
|
+
"agent id, list to read projected todos, update/complete/supersede to transition by todo_id, or "
|
|
177
|
+
"archive-completed to move older completed todos into Completed Work Archive. "
|
|
178
|
+
"Use suggest to generate an agent-facing candidate todo analysis prompt without writing state. "
|
|
179
|
+
"Use capture-followups to record a capped public-safe unclaimed follow-up batch."
|
|
180
|
+
),
|
|
181
|
+
)
|
|
182
|
+
todo_parser.add_argument("--goal-id", required=True, help="Goal id whose active state should receive the todo.")
|
|
183
|
+
todo_parser.add_argument("--role", choices=["user", "agent"], help="Todo owner. Required for add; optional todo_id search scope for lifecycle commands. Defaults to agent for archive-completed.")
|
|
184
|
+
todo_parser.add_argument("--text", help="Todo text. Required for add; keep it short and public-safe enough for local status.")
|
|
185
|
+
todo_parser.add_argument(
|
|
186
|
+
"--follow-up",
|
|
187
|
+
dest="followups",
|
|
188
|
+
action="append",
|
|
189
|
+
help="For capture-followups, append one public-safe agent follow-up todo. Repeat up to the requested batch.",
|
|
190
|
+
)
|
|
191
|
+
todo_parser.add_argument("--todo-id", help="Structured todo id from status/quota, such as todo_ab12cd34ef56.")
|
|
192
|
+
todo_parser.add_argument(
|
|
193
|
+
"--turn-instance-id",
|
|
194
|
+
help=(
|
|
195
|
+
"For todo complete, bind the lifecycle receipt to the original "
|
|
196
|
+
"turn-scoped quota guard and reuse it on retries."
|
|
197
|
+
),
|
|
198
|
+
)
|
|
199
|
+
todo_parser.add_argument(
|
|
200
|
+
"--replan-obligation-id",
|
|
201
|
+
help=(
|
|
202
|
+
"For todo add, bind one newly selected runnable advancement successor "
|
|
203
|
+
"to the exact open replan obligation. Requires --action-kind and a "
|
|
204
|
+
"stable --target-key or --explore-result-node-ref. The Todo write "
|
|
205
|
+
"becomes the semantic receipt; no follow-up ACK command is required."
|
|
206
|
+
),
|
|
207
|
+
)
|
|
208
|
+
todo_parser.add_argument("--status", choices=["open", "done", "blocked", "deferred"], help="For todo add/update, set the lifecycle status.")
|
|
209
|
+
todo_parser.add_argument("--note", help="Public-safe note to attach to a lifecycle transition.")
|
|
210
|
+
todo_parser.add_argument("--evidence", help="Public-safe evidence pointer or short result for complete/update.")
|
|
211
|
+
todo_parser.add_argument(
|
|
212
|
+
"--validation-command",
|
|
213
|
+
help=(
|
|
214
|
+
"Caller-approved validation command (no shell) to run before a "
|
|
215
|
+
"todo's completion commits, e.g. 'pytest -q tests/test_x.py'. Set "
|
|
216
|
+
"on `todo add`; completion runs it independently and blocks on a "
|
|
217
|
+
"non-zero exit."
|
|
218
|
+
),
|
|
219
|
+
)
|
|
220
|
+
todo_parser.add_argument(
|
|
221
|
+
"--validation-label",
|
|
222
|
+
help="Optional public-safe label for the validation receipt.",
|
|
223
|
+
)
|
|
224
|
+
todo_parser.add_argument(
|
|
225
|
+
"--validation-command-json",
|
|
226
|
+
help=(
|
|
227
|
+
"Trusted JSON string array (argv form, no shell parsing) for the "
|
|
228
|
+
"completion validation command, e.g. '[\"pytest\",\"-q\",\"tests/"
|
|
229
|
+
"test_x.py\"]'. Mutually exclusive with --validation-command; set "
|
|
230
|
+
"on `todo add`."
|
|
231
|
+
),
|
|
232
|
+
)
|
|
233
|
+
todo_parser.add_argument(
|
|
234
|
+
"--validation-timeout-seconds",
|
|
235
|
+
type=int,
|
|
236
|
+
help=(
|
|
237
|
+
"Per-todo timeout for the caller-approved validation command. "
|
|
238
|
+
"Only meaningful with --validation-command or "
|
|
239
|
+
"--validation-command-json on `todo add`; must be 1-29 so a "
|
|
240
|
+
"timed-out validation still produces a typed receipt inside the "
|
|
241
|
+
"30s outer subprocess budget. Defaults to 20."
|
|
242
|
+
),
|
|
243
|
+
)
|
|
244
|
+
todo_parser.add_argument("--reason", help="Public-safe reason for blocked/deferred/supersede transitions.")
|
|
245
|
+
todo_parser.add_argument(
|
|
246
|
+
"--authority-reason",
|
|
247
|
+
help=(
|
|
248
|
+
"For a delegated lifecycle override, record the public-safe reason. "
|
|
249
|
+
"Required when the matching coordination.todo_lifecycle_authority "
|
|
250
|
+
"grant sets requires_reason=true."
|
|
251
|
+
),
|
|
252
|
+
)
|
|
253
|
+
todo_parser.add_argument(
|
|
254
|
+
"--task-class",
|
|
255
|
+
choices=["advancement_task", "continuous_monitor", "user_gate", "user_action", "blocker"],
|
|
256
|
+
help=(
|
|
257
|
+
"For todo add/update, explicitly register the routing lane. Use "
|
|
258
|
+
"advancement_task for executable delivery work; user_gate for blocking "
|
|
259
|
+
"owner/controller decisions; user_action for non-blocking user-visible "
|
|
260
|
+
"todos; continuous_monitor and blocker are non-executable lanes."
|
|
261
|
+
),
|
|
262
|
+
)
|
|
263
|
+
todo_parser.add_argument(
|
|
264
|
+
"--action-kind",
|
|
265
|
+
help=(
|
|
266
|
+
"For todo add, optional public-safe action token such as run_eval, "
|
|
267
|
+
"rebuild_score, compact_blocker_writeback, or monitor."
|
|
268
|
+
),
|
|
269
|
+
)
|
|
270
|
+
todo_parser.add_argument(
|
|
271
|
+
"--task-domain",
|
|
272
|
+
help=(
|
|
273
|
+
"For agent todo add/update, declare the bounded responsibility domain "
|
|
274
|
+
"used by adaptive child admission, such as code, docs, or validation."
|
|
275
|
+
),
|
|
276
|
+
)
|
|
277
|
+
todo_parser.add_argument(
|
|
278
|
+
"--capability-binding-ref",
|
|
279
|
+
help=(
|
|
280
|
+
"For agent todo add, persist the opaque capability admission binding "
|
|
281
|
+
"projected by a validated capability packet."
|
|
282
|
+
),
|
|
283
|
+
)
|
|
284
|
+
todo_parser.add_argument(
|
|
285
|
+
"--task-repository",
|
|
286
|
+
help=(
|
|
287
|
+
"For agent todo add/update, declare the credential-free Git repository "
|
|
288
|
+
"identity that owns the task, such as git:github.com/owner/repo. This "
|
|
289
|
+
"selects workspace isolation; it does not grant write permission."
|
|
290
|
+
),
|
|
291
|
+
)
|
|
292
|
+
todo_parser.add_argument(
|
|
293
|
+
"--continuation-policy",
|
|
294
|
+
choices=sorted(TODO_CONTINUATION_POLICY_VALUES),
|
|
295
|
+
help=(
|
|
296
|
+
"Closed completion/handoff policy for this todo. action_kind remains "
|
|
297
|
+
"an extensible domain token; defaults to independent_handoff."
|
|
298
|
+
),
|
|
299
|
+
)
|
|
300
|
+
todo_parser.add_argument(
|
|
301
|
+
"--required-write-scope",
|
|
302
|
+
dest="required_write_scopes",
|
|
303
|
+
action="append",
|
|
304
|
+
help=(
|
|
305
|
+
"For todo add/update, declare a required relative write scope such as "
|
|
306
|
+
"src/** or runners/openviking/**. Repeat for multiple scopes."
|
|
307
|
+
),
|
|
308
|
+
)
|
|
309
|
+
todo_parser.add_argument(
|
|
310
|
+
"--required-capability",
|
|
311
|
+
dest="required_capabilities",
|
|
312
|
+
action="append",
|
|
313
|
+
help=(
|
|
314
|
+
"For todo add/update, declare an execution capability such as shell, "
|
|
315
|
+
"filesystem_write, network, benchmark_runner, or external_evidence_poll. "
|
|
316
|
+
"Repeat for multiple capabilities."
|
|
317
|
+
),
|
|
318
|
+
)
|
|
319
|
+
todo_parser.add_argument(
|
|
320
|
+
"--target-capability",
|
|
321
|
+
dest="target_capabilities",
|
|
322
|
+
action="append",
|
|
323
|
+
help=(
|
|
324
|
+
"For todo add/update, declare a capability this todo is building, "
|
|
325
|
+
"repairing, materializing, or parity-checking. On complete, pair it "
|
|
326
|
+
"with --capability-gap-status to close that lifecycle. This is not a "
|
|
327
|
+
"hard execution prerequisite."
|
|
328
|
+
),
|
|
329
|
+
)
|
|
330
|
+
todo_parser.add_argument(
|
|
331
|
+
"--capability-gap-status",
|
|
332
|
+
choices=["found", "fixed", "real_callsite_verified"],
|
|
333
|
+
help=(
|
|
334
|
+
"For agent todo add/update/complete, append an auditable capability-gap "
|
|
335
|
+
"lifecycle event. Requires --target-capability; the todo_id is the "
|
|
336
|
+
"stable gap id."
|
|
337
|
+
),
|
|
338
|
+
)
|
|
339
|
+
todo_parser.add_argument(
|
|
340
|
+
"--explore-result-node-ref",
|
|
341
|
+
dest="explore_result_node_refs",
|
|
342
|
+
action="append",
|
|
343
|
+
help=(
|
|
344
|
+
"For todo add/update, link an explicit public-safe Explore result node id. "
|
|
345
|
+
"Repeat for multiple nodes; analysis resolves only these links."
|
|
346
|
+
),
|
|
347
|
+
)
|
|
348
|
+
todo_parser.add_argument(
|
|
349
|
+
"--clear-explore-result-node-refs",
|
|
350
|
+
action="store_true",
|
|
351
|
+
help="For todo update, remove all explicit Explore result node links.",
|
|
352
|
+
)
|
|
353
|
+
todo_parser.add_argument(
|
|
354
|
+
"--decision-scope",
|
|
355
|
+
help=(
|
|
356
|
+
"For user_gate add/update, declare the concrete decision as "
|
|
357
|
+
"kind:granularity:scope_key, for example direction:action:benchmark_target."
|
|
358
|
+
),
|
|
359
|
+
)
|
|
360
|
+
todo_parser.add_argument(
|
|
361
|
+
"--required-decision-scope",
|
|
362
|
+
dest="required_decision_scopes",
|
|
363
|
+
action="append",
|
|
364
|
+
help=(
|
|
365
|
+
"For agent todo add/update, declare a required decision scope as "
|
|
366
|
+
"kind:granularity:scope_key. Repeat for multiple scopes."
|
|
367
|
+
),
|
|
368
|
+
)
|
|
369
|
+
todo_parser.add_argument(
|
|
370
|
+
"--decision-outcome",
|
|
371
|
+
choices=["approve", "reject", "cancel"],
|
|
372
|
+
help=(
|
|
373
|
+
"For todo complete on a user_gate, record the explicit owner decision. "
|
|
374
|
+
"Only approve consumes authority and resumes linked work."
|
|
375
|
+
),
|
|
376
|
+
)
|
|
377
|
+
todo_parser.add_argument(
|
|
378
|
+
"--claimed-by",
|
|
379
|
+
help=(
|
|
380
|
+
"For agent todo add/claim/update, assign the soft execution owner to a "
|
|
381
|
+
"registered public-safe agent id such as codex-main-control. This names "
|
|
382
|
+
"the assignment target, not the lifecycle actor; multi-agent lifecycle "
|
|
383
|
+
"commands still require --agent-id. User todos use --bound-agent or "
|
|
384
|
+
"--goal-bound instead."
|
|
385
|
+
),
|
|
386
|
+
)
|
|
387
|
+
todo_parser.add_argument(
|
|
388
|
+
"--task-lease-idempotency-key",
|
|
389
|
+
help=(
|
|
390
|
+
"For todo complete, prove the execution instance that owns an active "
|
|
391
|
+
"hard task lease. Required when that todo has an effective lease."
|
|
392
|
+
),
|
|
393
|
+
)
|
|
394
|
+
todo_parser.add_argument(
|
|
395
|
+
"--task-lease-expected-version",
|
|
396
|
+
type=int,
|
|
397
|
+
help=(
|
|
398
|
+
"For todo complete, optionally CAS the active hard task lease version. "
|
|
399
|
+
"Requires --task-lease-idempotency-key."
|
|
400
|
+
),
|
|
401
|
+
)
|
|
402
|
+
todo_parser.add_argument(
|
|
403
|
+
"--bound-agent",
|
|
404
|
+
help=(
|
|
405
|
+
"For user todo add/update, bind reminder delivery and post-response "
|
|
406
|
+
"continuation to one registered agent lane. This is not a gate."
|
|
407
|
+
),
|
|
408
|
+
)
|
|
409
|
+
todo_parser.add_argument(
|
|
410
|
+
"--goal-bound",
|
|
411
|
+
action="store_true",
|
|
412
|
+
help=(
|
|
413
|
+
"For user todo add/update, explicitly bind the item to the whole goal "
|
|
414
|
+
"instead of one agent lane."
|
|
415
|
+
),
|
|
416
|
+
)
|
|
417
|
+
todo_parser.add_argument(
|
|
418
|
+
"--blocks-agent",
|
|
419
|
+
help=(
|
|
420
|
+
"For user_gate add/update, scope the gate to one registered agent."
|
|
421
|
+
),
|
|
422
|
+
)
|
|
423
|
+
todo_parser.add_argument(
|
|
424
|
+
"--clear-blocks-agent",
|
|
425
|
+
action="store_true",
|
|
426
|
+
help="For todo update, remove the existing blocks_agent field.",
|
|
427
|
+
)
|
|
428
|
+
todo_parser.add_argument(
|
|
429
|
+
"--excluded-agent",
|
|
430
|
+
dest="excluded_agents",
|
|
431
|
+
action="append",
|
|
432
|
+
help=(
|
|
433
|
+
"For agent todo add/update, exclude one registered peer from claiming or "
|
|
434
|
+
"executing the todo. Repeat for multiple peers."
|
|
435
|
+
),
|
|
436
|
+
)
|
|
437
|
+
todo_parser.add_argument(
|
|
438
|
+
"--clear-excluded-agents",
|
|
439
|
+
action="store_true",
|
|
440
|
+
help="For todo update, remove all executor exclusions from the todo.",
|
|
441
|
+
)
|
|
442
|
+
todo_parser.add_argument(
|
|
443
|
+
"--global-gate",
|
|
444
|
+
action="store_true",
|
|
445
|
+
help=(
|
|
446
|
+
"For todo add/update on role=user task-class=user_gate, explicitly mark "
|
|
447
|
+
"that the gate blocks every registered agent. Prefer --blocks-agent or "
|
|
448
|
+
"--agent-id when only one lane is waiting."
|
|
449
|
+
),
|
|
450
|
+
)
|
|
451
|
+
todo_parser.add_argument(
|
|
452
|
+
"--clear-global-gate",
|
|
453
|
+
action="store_true",
|
|
454
|
+
help=(
|
|
455
|
+
"For todo update on a user_gate, remove global_gate. In a multi-agent "
|
|
456
|
+
"goal, provide --blocks-agent in the same update so the gate retains "
|
|
457
|
+
"an explicit lane scope."
|
|
458
|
+
),
|
|
459
|
+
)
|
|
460
|
+
register_todo_linkage_arguments(todo_parser)
|
|
461
|
+
todo_parser.add_argument(
|
|
462
|
+
"--target-key",
|
|
463
|
+
"--monitor-target-key",
|
|
464
|
+
dest="monitor_target_key",
|
|
465
|
+
help=(
|
|
466
|
+
"For agent todo add/update, declare a stable public-safe execution "
|
|
467
|
+
"target key. --monitor-target-key remains a compatibility alias."
|
|
468
|
+
),
|
|
469
|
+
)
|
|
470
|
+
todo_parser.add_argument(
|
|
471
|
+
"--cadence",
|
|
472
|
+
help=(
|
|
473
|
+
"For agent continuous_monitor add/update, declare the monitor cadence, "
|
|
474
|
+
"such as 30m, 2h, or 1d."
|
|
475
|
+
),
|
|
476
|
+
)
|
|
477
|
+
todo_parser.add_argument(
|
|
478
|
+
"--next-due-at",
|
|
479
|
+
dest="next_due_at",
|
|
480
|
+
help=(
|
|
481
|
+
"For agent continuous_monitor add/update, declare the next due ISO "
|
|
482
|
+
"timestamp; due monitor scheduling is based on this field."
|
|
483
|
+
),
|
|
484
|
+
)
|
|
485
|
+
todo_parser.add_argument(
|
|
486
|
+
"--expires-at",
|
|
487
|
+
dest="expires_at",
|
|
488
|
+
help=(
|
|
489
|
+
"For agent continuous_monitor add/update, declare the ISO timestamp "
|
|
490
|
+
"after which the monitor is no longer due and must not catch up."
|
|
491
|
+
),
|
|
492
|
+
)
|
|
493
|
+
todo_parser.add_argument(
|
|
494
|
+
"--watch-only",
|
|
495
|
+
action="store_true",
|
|
496
|
+
help=(
|
|
497
|
+
"For agent continuous_monitor add/update, declare an intentionally "
|
|
498
|
+
"unbounded liveness watch. Watch-only monitors remain schedulable but "
|
|
499
|
+
"do not drive autonomous replan or block goal convergence."
|
|
500
|
+
),
|
|
501
|
+
)
|
|
502
|
+
todo_parser.add_argument(
|
|
503
|
+
"--clear-claim",
|
|
504
|
+
action="store_true",
|
|
505
|
+
help="For todo update, remove the soft claimed_by owner from the todo.",
|
|
506
|
+
)
|
|
507
|
+
todo_parser.add_argument(
|
|
508
|
+
"--no-follow-up",
|
|
509
|
+
action="store_true",
|
|
510
|
+
help=(
|
|
511
|
+
"For todo update/complete, record a structured no-follow-up rationale "
|
|
512
|
+
"when a completed todo intentionally has no successor."
|
|
513
|
+
),
|
|
514
|
+
)
|
|
515
|
+
register_todo_successor_creation_arguments(todo_parser)
|
|
516
|
+
todo_parser.add_argument(
|
|
517
|
+
"--max-active-done",
|
|
518
|
+
type=int,
|
|
519
|
+
default=ARCHIVE_COMPLETED_DEFAULT_MAX_ACTIVE_DONE,
|
|
520
|
+
help=(
|
|
521
|
+
"For archive-completed, keep this many completed todos in the active section. "
|
|
522
|
+
"The default leaves a small buffer below the status warning threshold."
|
|
523
|
+
),
|
|
524
|
+
)
|
|
525
|
+
todo_parser.add_argument(
|
|
526
|
+
"--agent-id",
|
|
527
|
+
help=(
|
|
528
|
+
"For user todo add, mark the authoring registered agent and bind the "
|
|
529
|
+
"user response continuation to that lane; for user_gate, the gate also "
|
|
530
|
+
"blocks this agent when --blocks-agent is omitted. For "
|
|
531
|
+
"claim/update/complete/supersede, attribute the "
|
|
532
|
+
"lifecycle actor; registered multi-agent goals require it unless an "
|
|
533
|
+
"exact linked user_gate decision_scope supplies the typed owner/controller "
|
|
534
|
+
"override. For list/suggest, select the project agent lane. Agent todo "
|
|
535
|
+
"add intentionally does not accept this option; use --claimed-by to "
|
|
536
|
+
"assign execution, or omit both options to leave the todo unclaimed."
|
|
537
|
+
),
|
|
538
|
+
)
|
|
539
|
+
todo_parser.add_argument(
|
|
540
|
+
"--from",
|
|
541
|
+
dest="suggestion_sources",
|
|
542
|
+
choices=ALLOWED_TODO_SUGGESTION_SOURCES,
|
|
543
|
+
action="append",
|
|
544
|
+
help="For todo suggest, include a source lane for agent analysis. Repeat for multiple lanes.",
|
|
545
|
+
)
|
|
546
|
+
todo_parser.add_argument(
|
|
547
|
+
"--limit",
|
|
548
|
+
dest="suggestion_limit",
|
|
549
|
+
type=int,
|
|
550
|
+
help="For todo suggest, maximum candidate count. Values above 5 are clamped to 5.",
|
|
551
|
+
)
|
|
552
|
+
todo_parser.add_argument(
|
|
553
|
+
"--trigger",
|
|
554
|
+
dest="suggestion_trigger",
|
|
555
|
+
choices=ALLOWED_TODO_SUGGESTION_TRIGGERS,
|
|
556
|
+
help="For todo suggest, why this candidate queue is being requested.",
|
|
557
|
+
)
|
|
558
|
+
todo_parser.add_argument("--project", help="Project root. Defaults to the registry goal repo.")
|
|
559
|
+
todo_parser.add_argument("--state-file", help="Active goal state path. Defaults to the registry goal state_file.")
|
|
560
|
+
todo_parser.add_argument("--dry-run", action="store_true", help="Preview the active-state edit without writing.")
|
|
561
|
+
todo_parser.add_argument("--execute", action="store_true", help="For archive-completed, write the active-state edit.")
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
def _todo_path_args(args: argparse.Namespace) -> dict[str, Path | None]:
|
|
565
|
+
return {
|
|
566
|
+
"project": Path(args.project).expanduser() if args.project else None,
|
|
567
|
+
"state_file": Path(args.state_file).expanduser() if args.state_file else None,
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
def handle_todo_command(
|
|
572
|
+
args: argparse.Namespace,
|
|
573
|
+
*,
|
|
574
|
+
registry_path: Path,
|
|
575
|
+
runtime_root_arg: str | None,
|
|
576
|
+
print_payload: PrintPayload,
|
|
577
|
+
append_cli_rollout_event: RolloutEventAppender,
|
|
578
|
+
format_name: str | None = None,
|
|
579
|
+
) -> int:
|
|
580
|
+
renderer = (
|
|
581
|
+
render_todo_suggestion_prompt_markdown
|
|
582
|
+
if args.todo_command == "suggest"
|
|
583
|
+
else render_todo_markdown
|
|
584
|
+
)
|
|
585
|
+
try:
|
|
586
|
+
if args.todo_command is None:
|
|
587
|
+
raise ValueError(
|
|
588
|
+
"`loopx todo` requires an explicit command; use `loopx todo add`, "
|
|
589
|
+
"`loopx todo claim`, `loopx todo update`, or another command shown "
|
|
590
|
+
"by `loopx todo --help`"
|
|
591
|
+
)
|
|
592
|
+
validate_shared_todo_options(args)
|
|
593
|
+
validate_capability_gap_options(args)
|
|
594
|
+
if args.todo_command == "list":
|
|
595
|
+
validate_todo_list_options(args)
|
|
596
|
+
payload = list_goal_todos(
|
|
597
|
+
registry_path=registry_path,
|
|
598
|
+
goal_id=args.goal_id,
|
|
599
|
+
role=args.role,
|
|
600
|
+
status=args.status,
|
|
601
|
+
todo_id=args.todo_id,
|
|
602
|
+
agent_id=args.agent_id,
|
|
603
|
+
**_todo_path_args(args),
|
|
604
|
+
runtime_root_arg=runtime_root_arg,
|
|
605
|
+
)
|
|
606
|
+
elif args.todo_command == "add":
|
|
607
|
+
validate_todo_add_options(args)
|
|
608
|
+
replan_obligation_id = _validated_replan_successor_obligation(
|
|
609
|
+
args,
|
|
610
|
+
registry_path=registry_path,
|
|
611
|
+
runtime_root_arg=runtime_root_arg,
|
|
612
|
+
)
|
|
613
|
+
payload = add_goal_todo(
|
|
614
|
+
registry_path=registry_path,
|
|
615
|
+
goal_id=args.goal_id,
|
|
616
|
+
role=args.role,
|
|
617
|
+
text=args.text,
|
|
618
|
+
status=args.status,
|
|
619
|
+
task_class=args.task_class,
|
|
620
|
+
action_kind=args.action_kind,
|
|
621
|
+
task_domain=args.task_domain,
|
|
622
|
+
capability_binding_ref=args.capability_binding_ref,
|
|
623
|
+
task_repository=args.task_repository,
|
|
624
|
+
continuation_policy=args.continuation_policy,
|
|
625
|
+
required_write_scopes=args.required_write_scopes,
|
|
626
|
+
required_capabilities=args.required_capabilities,
|
|
627
|
+
target_capabilities=args.target_capabilities,
|
|
628
|
+
explore_result_node_refs=args.explore_result_node_refs,
|
|
629
|
+
decision_scope=args.decision_scope,
|
|
630
|
+
required_decision_scopes=args.required_decision_scopes,
|
|
631
|
+
claimed_by=args.claimed_by,
|
|
632
|
+
bound_agent=args.bound_agent,
|
|
633
|
+
goal_bound=bool(args.goal_bound),
|
|
634
|
+
blocks_agent=args.blocks_agent,
|
|
635
|
+
excluded_agents=args.excluded_agents,
|
|
636
|
+
global_gate=bool(args.global_gate),
|
|
637
|
+
agent_id=args.agent_id,
|
|
638
|
+
unblocks_todo_id=args.unblocks_todo_id,
|
|
639
|
+
replan_obligation_id=replan_obligation_id,
|
|
640
|
+
resume_when=args.resume_when,
|
|
641
|
+
validation_command=args.validation_command,
|
|
642
|
+
validation_command_json=args.validation_command_json,
|
|
643
|
+
validation_label=args.validation_label,
|
|
644
|
+
validation_timeout_seconds=args.validation_timeout_seconds,
|
|
645
|
+
monitor_metadata={
|
|
646
|
+
"target_key": args.monitor_target_key,
|
|
647
|
+
"cadence": args.cadence,
|
|
648
|
+
"next_due_at": args.next_due_at,
|
|
649
|
+
"expires_at": args.expires_at,
|
|
650
|
+
"watch_only": "true" if args.watch_only else None,
|
|
651
|
+
},
|
|
652
|
+
**_todo_path_args(args),
|
|
653
|
+
dry_run=bool(args.dry_run),
|
|
654
|
+
)
|
|
655
|
+
if replan_obligation_id and payload.get("ok"):
|
|
656
|
+
payload["replan_transition"] = {
|
|
657
|
+
"schema_version": "replan_successor_transition_v0",
|
|
658
|
+
"obligation_id": replan_obligation_id,
|
|
659
|
+
"outcome": "new_runnable_successor",
|
|
660
|
+
"successor_todo_id": payload.get("todo_id"),
|
|
661
|
+
"recorded": not bool(payload.get("dry_run")),
|
|
662
|
+
"turn_boundary": "end_current_heartbeat",
|
|
663
|
+
}
|
|
664
|
+
if not payload.get("dry_run"):
|
|
665
|
+
payload["host_action"] = "end_current_heartbeat"
|
|
666
|
+
elif args.todo_command == "claim":
|
|
667
|
+
validate_todo_claim_options(args)
|
|
668
|
+
payload = update_goal_todo(
|
|
669
|
+
registry_path=registry_path,
|
|
670
|
+
goal_id=args.goal_id,
|
|
671
|
+
todo_id=args.todo_id,
|
|
672
|
+
role=args.role,
|
|
673
|
+
claimed_by=args.claimed_by,
|
|
674
|
+
agent_id=args.agent_id,
|
|
675
|
+
claim_only=True,
|
|
676
|
+
**_todo_path_args(args),
|
|
677
|
+
dry_run=bool(args.dry_run),
|
|
678
|
+
)
|
|
679
|
+
elif args.todo_command == "update":
|
|
680
|
+
validate_todo_update_options(args)
|
|
681
|
+
payload = update_goal_todo(
|
|
682
|
+
registry_path=registry_path,
|
|
683
|
+
goal_id=args.goal_id,
|
|
684
|
+
todo_id=args.todo_id,
|
|
685
|
+
text=args.text,
|
|
686
|
+
status=args.status,
|
|
687
|
+
role=args.role,
|
|
688
|
+
note=args.note,
|
|
689
|
+
evidence=args.evidence,
|
|
690
|
+
reason=args.reason,
|
|
691
|
+
task_class=args.task_class,
|
|
692
|
+
action_kind=args.action_kind,
|
|
693
|
+
task_domain=args.task_domain,
|
|
694
|
+
task_repository=args.task_repository,
|
|
695
|
+
continuation_policy=args.continuation_policy,
|
|
696
|
+
required_write_scopes=args.required_write_scopes,
|
|
697
|
+
required_capabilities=args.required_capabilities,
|
|
698
|
+
target_capabilities=args.target_capabilities,
|
|
699
|
+
explore_result_node_refs=(
|
|
700
|
+
[]
|
|
701
|
+
if args.clear_explore_result_node_refs
|
|
702
|
+
else args.explore_result_node_refs
|
|
703
|
+
),
|
|
704
|
+
decision_scope=args.decision_scope,
|
|
705
|
+
required_decision_scopes=args.required_decision_scopes,
|
|
706
|
+
claimed_by=args.claimed_by,
|
|
707
|
+
bound_agent=args.bound_agent,
|
|
708
|
+
goal_bound=bool(args.goal_bound),
|
|
709
|
+
blocks_agent=args.blocks_agent,
|
|
710
|
+
clear_blocks_agent=bool(args.clear_blocks_agent),
|
|
711
|
+
excluded_agents=args.excluded_agents,
|
|
712
|
+
clear_excluded_agents=bool(args.clear_excluded_agents),
|
|
713
|
+
global_gate=bool(args.global_gate),
|
|
714
|
+
clear_global_gate=bool(args.clear_global_gate),
|
|
715
|
+
agent_id=args.agent_id,
|
|
716
|
+
authority_reason=args.authority_reason,
|
|
717
|
+
unblocks_todo_id=args.unblocks_todo_id,
|
|
718
|
+
successor_todo_ids=args.successor_todo_ids,
|
|
719
|
+
resume_when=args.resume_when,
|
|
720
|
+
clear_resume_when=bool(args.clear_resume_when),
|
|
721
|
+
no_followup=True if args.no_follow_up else None,
|
|
722
|
+
monitor_metadata={
|
|
723
|
+
"target_key": args.monitor_target_key,
|
|
724
|
+
"cadence": args.cadence,
|
|
725
|
+
"next_due_at": args.next_due_at,
|
|
726
|
+
"expires_at": args.expires_at,
|
|
727
|
+
"watch_only": "true" if args.watch_only else None,
|
|
728
|
+
},
|
|
729
|
+
clear_claim=bool(args.clear_claim),
|
|
730
|
+
**_todo_path_args(args),
|
|
731
|
+
dry_run=bool(args.dry_run),
|
|
732
|
+
)
|
|
733
|
+
elif args.todo_command == "complete":
|
|
734
|
+
validate_todo_complete_options(args)
|
|
735
|
+
settlement_result = None
|
|
736
|
+
settlement_identity = None
|
|
737
|
+
completion_turn_key = None
|
|
738
|
+
if getattr(args, "turn_instance_id", None):
|
|
739
|
+
runtime_root = resolve_runtime_root(
|
|
740
|
+
load_registry(registry_path),
|
|
741
|
+
runtime_root_arg,
|
|
742
|
+
)
|
|
743
|
+
settlement_result = resolve_heartbeat_settlement_identity(
|
|
744
|
+
runtime_root,
|
|
745
|
+
goal_id=args.goal_id,
|
|
746
|
+
agent_id=args.agent_id,
|
|
747
|
+
todo_id=args.todo_id,
|
|
748
|
+
turn_instance_id=getattr(args, "turn_instance_id", None),
|
|
749
|
+
)
|
|
750
|
+
if settlement_result.failure is not None:
|
|
751
|
+
raise ValueError(settlement_result.failure.reason)
|
|
752
|
+
if settlement_result.value is None:
|
|
753
|
+
raise ValueError("turn-scoped Todo completion has no identity")
|
|
754
|
+
identity = settlement_result.value
|
|
755
|
+
settlement_identity = identity
|
|
756
|
+
if args.no_follow_up:
|
|
757
|
+
settlement_result = settlement_result.bind(
|
|
758
|
+
lambda resolved: require_settlement_writeback(
|
|
759
|
+
runtime_root,
|
|
760
|
+
resolved,
|
|
761
|
+
)
|
|
762
|
+
).bind(
|
|
763
|
+
lambda _writeback: require_settlement_spend(
|
|
764
|
+
runtime_root,
|
|
765
|
+
identity,
|
|
766
|
+
)
|
|
767
|
+
)
|
|
768
|
+
if settlement_result.failure is not None:
|
|
769
|
+
raise ValueError(
|
|
770
|
+
"terminal no-follow-up closeout requires matching "
|
|
771
|
+
"writeback and quota spend receipts: "
|
|
772
|
+
+ settlement_result.failure.reason
|
|
773
|
+
)
|
|
774
|
+
completion_turn_key = identity.effect_id
|
|
775
|
+
payload = complete_goal_todo(
|
|
776
|
+
registry_path=registry_path,
|
|
777
|
+
goal_id=args.goal_id,
|
|
778
|
+
todo_id=args.todo_id,
|
|
779
|
+
role=args.role,
|
|
780
|
+
decision_outcome=args.decision_outcome,
|
|
781
|
+
evidence=args.evidence,
|
|
782
|
+
completion_turn_key=completion_turn_key,
|
|
783
|
+
task_lease_idempotency_key=args.task_lease_idempotency_key,
|
|
784
|
+
task_lease_expected_version=args.task_lease_expected_version,
|
|
785
|
+
note=args.note,
|
|
786
|
+
no_followup=bool(args.no_follow_up),
|
|
787
|
+
successor_todo_ids=args.successor_todo_ids,
|
|
788
|
+
claimed_by=args.claimed_by,
|
|
789
|
+
clear_claim=bool(args.clear_claim),
|
|
790
|
+
next_agent_todo=args.next_agent_todo,
|
|
791
|
+
next_user_todo=args.next_user_todo,
|
|
792
|
+
next_user_task_class=args.next_user_task_class,
|
|
793
|
+
next_claimed_by=args.next_claimed_by,
|
|
794
|
+
next_task_class=args.next_task_class,
|
|
795
|
+
next_action_kind=args.next_action_kind,
|
|
796
|
+
next_task_repository=args.next_task_repository,
|
|
797
|
+
next_required_capabilities=args.next_required_capabilities,
|
|
798
|
+
next_continuation_policy=args.next_continuation_policy,
|
|
799
|
+
next_excluded_agents=args.next_excluded_agents,
|
|
800
|
+
self_merged=bool(args.self_merged),
|
|
801
|
+
agent_id=args.agent_id,
|
|
802
|
+
authority_reason=args.authority_reason,
|
|
803
|
+
**_todo_path_args(args),
|
|
804
|
+
dry_run=bool(args.dry_run),
|
|
805
|
+
)
|
|
806
|
+
if settlement_identity is not None:
|
|
807
|
+
payload["settlement_identity"] = settlement_identity.as_dict()
|
|
808
|
+
payload["settlement_result"] = settlement_result_payload(
|
|
809
|
+
settlement_result
|
|
810
|
+
)
|
|
811
|
+
elif args.todo_command == "supersede":
|
|
812
|
+
validate_todo_supersede_options(args)
|
|
813
|
+
payload = supersede_goal_todo(
|
|
814
|
+
registry_path=registry_path,
|
|
815
|
+
goal_id=args.goal_id,
|
|
816
|
+
todo_id=args.todo_id,
|
|
817
|
+
role=args.role,
|
|
818
|
+
reason=args.reason,
|
|
819
|
+
next_agent_todo=args.next_agent_todo,
|
|
820
|
+
next_user_todo=args.next_user_todo,
|
|
821
|
+
next_user_task_class=args.next_user_task_class,
|
|
822
|
+
next_claimed_by=args.next_claimed_by,
|
|
823
|
+
next_task_class=args.next_task_class,
|
|
824
|
+
next_action_kind=args.next_action_kind,
|
|
825
|
+
next_task_repository=args.next_task_repository,
|
|
826
|
+
next_required_capabilities=args.next_required_capabilities,
|
|
827
|
+
next_continuation_policy=args.next_continuation_policy,
|
|
828
|
+
next_excluded_agents=args.next_excluded_agents,
|
|
829
|
+
agent_id=args.agent_id,
|
|
830
|
+
authority_reason=args.authority_reason,
|
|
831
|
+
**_todo_path_args(args),
|
|
832
|
+
dry_run=bool(args.dry_run),
|
|
833
|
+
)
|
|
834
|
+
elif args.todo_command == "archive-completed":
|
|
835
|
+
validate_todo_archive_completed_options(args)
|
|
836
|
+
payload = archive_completed_todos(
|
|
837
|
+
registry_path=registry_path,
|
|
838
|
+
goal_id=args.goal_id,
|
|
839
|
+
role=args.role or "agent",
|
|
840
|
+
max_active_done=args.max_active_done,
|
|
841
|
+
**_todo_path_args(args),
|
|
842
|
+
dry_run=not bool(args.execute),
|
|
843
|
+
)
|
|
844
|
+
elif args.todo_command == "suggest":
|
|
845
|
+
validate_todo_suggest_options(args)
|
|
846
|
+
payload = build_todo_suggestion_prompt_packet(
|
|
847
|
+
goal_id=args.goal_id,
|
|
848
|
+
project=Path(args.project).expanduser() if args.project else None,
|
|
849
|
+
agent_id=args.agent_id,
|
|
850
|
+
sources=args.suggestion_sources,
|
|
851
|
+
limit=args.suggestion_limit,
|
|
852
|
+
trigger=args.suggestion_trigger,
|
|
853
|
+
)
|
|
854
|
+
payload["dry_run"] = True
|
|
855
|
+
elif args.todo_command == "capture-followups":
|
|
856
|
+
validate_todo_capture_followups_options(args)
|
|
857
|
+
followups = list(args.followups or [])
|
|
858
|
+
if args.text:
|
|
859
|
+
followups.append(args.text)
|
|
860
|
+
payload = capture_followup_todos(
|
|
861
|
+
registry_path=registry_path,
|
|
862
|
+
goal_id=args.goal_id,
|
|
863
|
+
followups=followups,
|
|
864
|
+
evidence=args.evidence or "",
|
|
865
|
+
task_class=args.task_class,
|
|
866
|
+
action_kind=args.action_kind,
|
|
867
|
+
required_write_scopes=args.required_write_scopes,
|
|
868
|
+
required_capabilities=args.required_capabilities,
|
|
869
|
+
target_capabilities=args.target_capabilities,
|
|
870
|
+
required_decision_scopes=args.required_decision_scopes,
|
|
871
|
+
**_todo_path_args(args),
|
|
872
|
+
dry_run=bool(args.dry_run),
|
|
873
|
+
)
|
|
874
|
+
else:
|
|
875
|
+
raise ValueError("unsupported todo command")
|
|
876
|
+
except Exception as exc:
|
|
877
|
+
payload = {
|
|
878
|
+
"ok": False,
|
|
879
|
+
"dry_run": True
|
|
880
|
+
if args.todo_command == "suggest"
|
|
881
|
+
else not bool(args.execute)
|
|
882
|
+
if args.todo_command == "archive-completed"
|
|
883
|
+
else bool(args.dry_run),
|
|
884
|
+
"added": False,
|
|
885
|
+
"already_exists": False,
|
|
886
|
+
"goal_id": args.goal_id,
|
|
887
|
+
"role": args.role,
|
|
888
|
+
"todo": args.text or "",
|
|
889
|
+
"error": str(exc),
|
|
890
|
+
**lock_timeout_error_fields(exc),
|
|
891
|
+
}
|
|
892
|
+
if isinstance(exc, (TaskLeaseError, HandoffModeError)):
|
|
893
|
+
payload["error_code"] = exc.code
|
|
894
|
+
payload.update(exc.payload)
|
|
895
|
+
append_todo_rollout_event(
|
|
896
|
+
payload,
|
|
897
|
+
args=args,
|
|
898
|
+
registry_path=registry_path,
|
|
899
|
+
runtime_root_arg=runtime_root_arg,
|
|
900
|
+
append_cli_rollout_event=append_cli_rollout_event,
|
|
901
|
+
)
|
|
902
|
+
if (
|
|
903
|
+
args.todo_command == "complete"
|
|
904
|
+
and getattr(args, "turn_instance_id", None)
|
|
905
|
+
and payload.get("ok")
|
|
906
|
+
and not payload.get("dry_run")
|
|
907
|
+
):
|
|
908
|
+
runtime_root = resolve_runtime_root(
|
|
909
|
+
load_registry(registry_path),
|
|
910
|
+
runtime_root_arg,
|
|
911
|
+
)
|
|
912
|
+
if args.no_follow_up and settlement_identity is not None:
|
|
913
|
+
assert settlement_result is not None
|
|
914
|
+
settlement_result = settlement_result.bind(
|
|
915
|
+
lambda _spend: require_settlement_terminal_closeout(
|
|
916
|
+
runtime_root,
|
|
917
|
+
settlement_identity,
|
|
918
|
+
)
|
|
919
|
+
)
|
|
920
|
+
else:
|
|
921
|
+
settlement_result = resolve_heartbeat_settlement_identity(
|
|
922
|
+
runtime_root,
|
|
923
|
+
goal_id=args.goal_id,
|
|
924
|
+
agent_id=args.agent_id,
|
|
925
|
+
todo_id=args.todo_id,
|
|
926
|
+
turn_instance_id=getattr(args, "turn_instance_id", None),
|
|
927
|
+
)
|
|
928
|
+
payload["settlement_result"] = settlement_result_payload(
|
|
929
|
+
settlement_result
|
|
930
|
+
)
|
|
931
|
+
if settlement_result.failure is not None:
|
|
932
|
+
payload["ok"] = False
|
|
933
|
+
payload["receipt_repair_required"] = True
|
|
934
|
+
payload["error"] = settlement_result.failure.reason
|
|
935
|
+
print_payload(
|
|
936
|
+
payload,
|
|
937
|
+
format_name or str(getattr(args, "format", None) or "markdown"),
|
|
938
|
+
renderer,
|
|
939
|
+
)
|
|
940
|
+
return 0 if payload.get("ok") else 1
|