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,572 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from collections.abc import Iterable
|
|
5
|
+
|
|
6
|
+
from ..control_plane.todos.contract import TODO_CONTINUATION_POLICY_VALUES
|
|
7
|
+
|
|
8
|
+
TODO_OPTION_FIELDS = (
|
|
9
|
+
("--role", "role"),
|
|
10
|
+
("--text", "text"),
|
|
11
|
+
("--follow-up", "followups"),
|
|
12
|
+
("--todo-id", "todo_id"),
|
|
13
|
+
("--turn-instance-id", "turn_instance_id"),
|
|
14
|
+
("--replan-obligation-id", "replan_obligation_id"),
|
|
15
|
+
("--status", "status"),
|
|
16
|
+
("--note", "note"),
|
|
17
|
+
("--evidence", "evidence"),
|
|
18
|
+
("--reason", "reason"),
|
|
19
|
+
("--authority-reason", "authority_reason"),
|
|
20
|
+
("--task-class", "task_class"),
|
|
21
|
+
("--action-kind", "action_kind"),
|
|
22
|
+
("--task-domain", "task_domain"),
|
|
23
|
+
("--capability-binding-ref", "capability_binding_ref"),
|
|
24
|
+
("--task-repository", "task_repository"),
|
|
25
|
+
("--continuation-policy", "continuation_policy"),
|
|
26
|
+
("--required-write-scope", "required_write_scopes"),
|
|
27
|
+
("--required-capability", "required_capabilities"),
|
|
28
|
+
("--target-capability", "target_capabilities"),
|
|
29
|
+
("--capability-gap-status", "capability_gap_status"),
|
|
30
|
+
("--explore-result-node-ref", "explore_result_node_refs"),
|
|
31
|
+
("--clear-explore-result-node-refs", "clear_explore_result_node_refs"),
|
|
32
|
+
("--decision-scope", "decision_scope"),
|
|
33
|
+
("--required-decision-scope", "required_decision_scopes"),
|
|
34
|
+
("--decision-outcome", "decision_outcome"),
|
|
35
|
+
("--claimed-by", "claimed_by"),
|
|
36
|
+
("--task-lease-idempotency-key", "task_lease_idempotency_key"),
|
|
37
|
+
("--task-lease-expected-version", "task_lease_expected_version"),
|
|
38
|
+
("--bound-agent", "bound_agent"),
|
|
39
|
+
("--goal-bound", "goal_bound"),
|
|
40
|
+
("--blocks-agent", "blocks_agent"),
|
|
41
|
+
("--clear-blocks-agent", "clear_blocks_agent"),
|
|
42
|
+
("--excluded-agent", "excluded_agents"),
|
|
43
|
+
("--clear-excluded-agents", "clear_excluded_agents"),
|
|
44
|
+
("--global-gate", "global_gate"),
|
|
45
|
+
("--clear-global-gate", "clear_global_gate"),
|
|
46
|
+
("--unblocks-todo-id", "unblocks_todo_id"),
|
|
47
|
+
("--successor-todo-id", "successor_todo_ids"),
|
|
48
|
+
("--resume-when", "resume_when"),
|
|
49
|
+
("--validation-command", "validation_command"),
|
|
50
|
+
("--validation-command-json", "validation_command_json"),
|
|
51
|
+
("--validation-label", "validation_label"),
|
|
52
|
+
("--validation-timeout-seconds", "validation_timeout_seconds"),
|
|
53
|
+
("--clear-resume-when", "clear_resume_when"),
|
|
54
|
+
("--target-key", "monitor_target_key"),
|
|
55
|
+
("--cadence", "cadence"),
|
|
56
|
+
("--next-due-at", "next_due_at"),
|
|
57
|
+
("--expires-at", "expires_at"),
|
|
58
|
+
("--watch-only", "watch_only"),
|
|
59
|
+
("--clear-claim", "clear_claim"),
|
|
60
|
+
("--no-follow-up", "no_follow_up"),
|
|
61
|
+
("--next-agent-todo", "next_agent_todo"),
|
|
62
|
+
("--next-user-todo", "next_user_todo"),
|
|
63
|
+
("--next-user-task-class", "next_user_task_class"),
|
|
64
|
+
("--next-claimed-by", "next_claimed_by"),
|
|
65
|
+
("--next-task-class", "next_task_class"),
|
|
66
|
+
("--next-action-kind", "next_action_kind"),
|
|
67
|
+
("--next-task-repository", "next_task_repository"),
|
|
68
|
+
("--next-required-capability", "next_required_capabilities"),
|
|
69
|
+
("--next-continuation-policy", "next_continuation_policy"),
|
|
70
|
+
("--next-excluded-agent", "next_excluded_agents"),
|
|
71
|
+
("--self-merged", "self_merged"),
|
|
72
|
+
("--agent-id", "agent_id"),
|
|
73
|
+
("--from", "suggestion_sources"),
|
|
74
|
+
("--limit", "suggestion_limit"),
|
|
75
|
+
("--trigger", "suggestion_trigger"),
|
|
76
|
+
("--state-file", "state_file"),
|
|
77
|
+
("--execute", "execute"),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
_TODO_UPDATE_MUTABLE_FIELDS = (
|
|
81
|
+
"text", "followups", "status", "note", "evidence", "reason", "task_class",
|
|
82
|
+
"action_kind", "task_domain", "task_repository", "continuation_policy", "required_write_scopes",
|
|
83
|
+
"required_capabilities", "target_capabilities", "capability_gap_status",
|
|
84
|
+
"explore_result_node_refs", "clear_explore_result_node_refs", "decision_scope",
|
|
85
|
+
"required_decision_scopes", "claimed_by", "bound_agent", "goal_bound",
|
|
86
|
+
"blocks_agent", "clear_blocks_agent", "excluded_agents", "clear_excluded_agents",
|
|
87
|
+
"global_gate", "clear_global_gate", "unblocks_todo_id", "successor_todo_ids",
|
|
88
|
+
"resume_when", "clear_resume_when", "no_follow_up", "monitor_target_key",
|
|
89
|
+
"cadence", "next_due_at", "expires_at", "watch_only", "clear_claim",
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
_TODO_UPDATE_UNSUPPORTED_FIELDS = (
|
|
93
|
+
(
|
|
94
|
+
"decision_outcome",
|
|
95
|
+
"todo update does not accept --decision-outcome; use todo complete",
|
|
96
|
+
),
|
|
97
|
+
(
|
|
98
|
+
"followups",
|
|
99
|
+
"todo update does not support --follow-up; use `todo capture-followups`",
|
|
100
|
+
),
|
|
101
|
+
("next_claimed_by", "todo update does not support --next-claimed-by"),
|
|
102
|
+
(
|
|
103
|
+
"next_task_repository",
|
|
104
|
+
"todo update does not support --next-task-repository",
|
|
105
|
+
),
|
|
106
|
+
(
|
|
107
|
+
"next_required_capabilities",
|
|
108
|
+
"todo update does not support --next-required-capability",
|
|
109
|
+
),
|
|
110
|
+
(
|
|
111
|
+
"next_continuation_policy",
|
|
112
|
+
"todo update does not support --next-continuation-policy",
|
|
113
|
+
),
|
|
114
|
+
("next_excluded_agents", "todo update does not support --next-excluded-agent"),
|
|
115
|
+
("self_merged", "todo update does not support --self-merged"),
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
_TODO_ADD_INITIAL_RULES = (
|
|
119
|
+
("decision_outcome", True, "does not accept --decision-outcome; record it on completion"),
|
|
120
|
+
("followups", True, "does not support --follow-up; use `todo capture-followups`"),
|
|
121
|
+
("role", False, "requires --role"),
|
|
122
|
+
("text", False, "requires --text"),
|
|
123
|
+
("clear_claim", True, "accepts --claimed-by but not --clear-claim"),
|
|
124
|
+
(
|
|
125
|
+
"clear_explore_result_node_refs",
|
|
126
|
+
True,
|
|
127
|
+
"accepts --explore-result-node-ref but not --clear-explore-result-node-refs",
|
|
128
|
+
),
|
|
129
|
+
)
|
|
130
|
+
_TODO_ADD_UNSUPPORTED_FIELDS = (
|
|
131
|
+
"next_claimed_by", "next_task_repository", "next_required_capabilities",
|
|
132
|
+
"next_continuation_policy", "next_excluded_agents", "clear_excluded_agents",
|
|
133
|
+
"clear_blocks_agent", "self_merged", "no_follow_up",
|
|
134
|
+
)
|
|
135
|
+
_TODO_OPTION_FLAGS = {field: flag for flag, field in TODO_OPTION_FIELDS}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def register_todo_linkage_arguments(
|
|
139
|
+
todo_parser: argparse.ArgumentParser,
|
|
140
|
+
) -> None:
|
|
141
|
+
todo_parser.add_argument(
|
|
142
|
+
"--unblocks-todo-id",
|
|
143
|
+
help=(
|
|
144
|
+
"For todo add/update, link this todo to the blocked todo it unblocks, "
|
|
145
|
+
"for example todo_ab12cd34ef56. Completing an exactly linked user_gate "
|
|
146
|
+
"also consumes the target required decision scopes covered by that gate."
|
|
147
|
+
),
|
|
148
|
+
)
|
|
149
|
+
todo_parser.add_argument(
|
|
150
|
+
"--successor-todo-id",
|
|
151
|
+
dest="successor_todo_ids",
|
|
152
|
+
action="append",
|
|
153
|
+
help=(
|
|
154
|
+
"For todo update/complete, link an existing successor todo to the "
|
|
155
|
+
"current todo. Repeat for multiple successors."
|
|
156
|
+
),
|
|
157
|
+
)
|
|
158
|
+
todo_parser.add_argument(
|
|
159
|
+
"--resume-when",
|
|
160
|
+
help=(
|
|
161
|
+
"For deferred todo add/update, declare a machine-readable resume condition "
|
|
162
|
+
"such as todo_done:todo_ab12cd34ef56, pr_merged:#532, or "
|
|
163
|
+
"capacity_available:short_pool. Capacity keys are resolved from quota "
|
|
164
|
+
"--available-capability declarations."
|
|
165
|
+
),
|
|
166
|
+
)
|
|
167
|
+
todo_parser.add_argument(
|
|
168
|
+
"--clear-resume-when",
|
|
169
|
+
action="store_true",
|
|
170
|
+
help=(
|
|
171
|
+
"For todo update, remove the existing resume condition after its "
|
|
172
|
+
"successor replan has made the todo runnable."
|
|
173
|
+
),
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def register_todo_successor_creation_arguments(
|
|
178
|
+
todo_parser: argparse.ArgumentParser,
|
|
179
|
+
) -> None:
|
|
180
|
+
todo_parser.add_argument(
|
|
181
|
+
"--next-agent-todo",
|
|
182
|
+
help="For complete/supersede, atomically add or update the next agent todo.",
|
|
183
|
+
)
|
|
184
|
+
todo_parser.add_argument(
|
|
185
|
+
"--next-user-todo",
|
|
186
|
+
help="For complete/supersede, atomically add or update the next user todo.",
|
|
187
|
+
)
|
|
188
|
+
todo_parser.add_argument(
|
|
189
|
+
"--next-user-task-class",
|
|
190
|
+
choices=["user_gate", "user_action"],
|
|
191
|
+
help=(
|
|
192
|
+
"Required with --next-user-todo: user_gate for a blocking owner "
|
|
193
|
+
"decision or user_action for a visible reminder that must not block "
|
|
194
|
+
"the bound agent lane."
|
|
195
|
+
),
|
|
196
|
+
)
|
|
197
|
+
todo_parser.add_argument(
|
|
198
|
+
"--next-claimed-by",
|
|
199
|
+
help=(
|
|
200
|
+
"For complete/supersede with --next-agent-todo, soft-claim the successor "
|
|
201
|
+
"todo for a registered agent. Independent handoffs remain unclaimed unless "
|
|
202
|
+
"explicitly assigned, while same-agent non-delivery continuations keep the "
|
|
203
|
+
"current owner. Use --self-merged with --evidence for an eligible same-agent "
|
|
204
|
+
"delivery."
|
|
205
|
+
),
|
|
206
|
+
)
|
|
207
|
+
todo_parser.add_argument(
|
|
208
|
+
"--self-merged",
|
|
209
|
+
action="store_true",
|
|
210
|
+
help=(
|
|
211
|
+
"For todo complete, record that a small validated change was self-merged; "
|
|
212
|
+
"requires --evidence."
|
|
213
|
+
),
|
|
214
|
+
)
|
|
215
|
+
todo_parser.add_argument(
|
|
216
|
+
"--next-task-class",
|
|
217
|
+
choices=["advancement_task", "continuous_monitor", "blocker"],
|
|
218
|
+
help="Task class for --next-agent-todo. Defaults to advancement_task.",
|
|
219
|
+
)
|
|
220
|
+
todo_parser.add_argument(
|
|
221
|
+
"--next-action-kind",
|
|
222
|
+
help="Action kind for --next-agent-todo.",
|
|
223
|
+
)
|
|
224
|
+
todo_parser.add_argument(
|
|
225
|
+
"--next-task-repository",
|
|
226
|
+
help=(
|
|
227
|
+
"Credential-free Git repository identity for --next-agent-todo, such as "
|
|
228
|
+
"git:github.com/owner/repo."
|
|
229
|
+
),
|
|
230
|
+
)
|
|
231
|
+
todo_parser.add_argument(
|
|
232
|
+
"--next-required-capability",
|
|
233
|
+
dest="next_required_capabilities",
|
|
234
|
+
action="append",
|
|
235
|
+
help=(
|
|
236
|
+
"Execution capability required by --next-agent-todo. Repeat for multiple "
|
|
237
|
+
"capabilities."
|
|
238
|
+
),
|
|
239
|
+
)
|
|
240
|
+
todo_parser.add_argument(
|
|
241
|
+
"--next-continuation-policy",
|
|
242
|
+
choices=sorted(TODO_CONTINUATION_POLICY_VALUES),
|
|
243
|
+
help="Continuation policy for --next-agent-todo.",
|
|
244
|
+
)
|
|
245
|
+
todo_parser.add_argument(
|
|
246
|
+
"--next-excluded-agent",
|
|
247
|
+
dest="next_excluded_agents",
|
|
248
|
+
action="append",
|
|
249
|
+
help=(
|
|
250
|
+
"For complete/supersede with --next-agent-todo, exclude one registered "
|
|
251
|
+
"peer from claiming or executing the successor. Repeat for multiple peers."
|
|
252
|
+
),
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def unsupported_todo_options(
|
|
257
|
+
args: argparse.Namespace,
|
|
258
|
+
*,
|
|
259
|
+
allowed_fields: Iterable[str],
|
|
260
|
+
) -> list[str]:
|
|
261
|
+
allowed = set(allowed_fields)
|
|
262
|
+
return [
|
|
263
|
+
flag
|
|
264
|
+
for flag, field in TODO_OPTION_FIELDS
|
|
265
|
+
if field not in allowed and getattr(args, field, None)
|
|
266
|
+
]
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _validate_todo_option_subset(args: argparse.Namespace, allowed_fields: Iterable[str], error_prefix: str) -> None:
|
|
270
|
+
unsupported = unsupported_todo_options(args, allowed_fields=allowed_fields)
|
|
271
|
+
if unsupported:
|
|
272
|
+
raise ValueError(error_prefix + ", ".join(unsupported))
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def validate_todo_list_options(args: argparse.Namespace) -> None:
|
|
276
|
+
_validate_todo_option_subset(
|
|
277
|
+
args,
|
|
278
|
+
{"role", "todo_id", "status", "agent_id", "state_file"},
|
|
279
|
+
"todo list only accepts --goal-id, optional --role, --status, --todo-id, "
|
|
280
|
+
"--agent-id, --project, --state-file, --dry-run, and --format; unsupported: ",
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def validate_todo_add_options(args: argparse.Namespace) -> None:
|
|
285
|
+
for field, reject_when_present, message in _TODO_ADD_INITIAL_RULES:
|
|
286
|
+
if bool(getattr(args, field)) is reject_when_present:
|
|
287
|
+
raise ValueError(f"todo add {message}")
|
|
288
|
+
for field in _TODO_ADD_UNSUPPORTED_FIELDS:
|
|
289
|
+
if getattr(args, field):
|
|
290
|
+
raise ValueError(f"todo add does not support {_TODO_OPTION_FLAGS[field]}")
|
|
291
|
+
if args.successor_todo_ids:
|
|
292
|
+
raise ValueError("todo add does not support --successor-todo-id; use todo update/complete to link existing successor work")
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def validate_todo_claim_options(args: argparse.Namespace) -> None:
|
|
296
|
+
if not args.todo_id:
|
|
297
|
+
raise ValueError("todo claim requires --todo-id")
|
|
298
|
+
if not args.claimed_by:
|
|
299
|
+
raise ValueError("todo claim requires --claimed-by")
|
|
300
|
+
if args.clear_claim:
|
|
301
|
+
raise ValueError(
|
|
302
|
+
"todo claim requires --claimed-by and does not support --clear-claim"
|
|
303
|
+
)
|
|
304
|
+
_validate_todo_option_subset(
|
|
305
|
+
args,
|
|
306
|
+
{"role", "todo_id", "claimed_by", "agent_id", "state_file"},
|
|
307
|
+
"todo claim only accepts --todo-id, --claimed-by, --agent-id, optional --role, "
|
|
308
|
+
"--project, --state-file, and --dry-run; unsupported: ",
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def validate_todo_update_options(args: argparse.Namespace) -> None:
|
|
313
|
+
if not args.todo_id:
|
|
314
|
+
raise ValueError("todo update requires --todo-id")
|
|
315
|
+
if args.claimed_by and args.clear_claim:
|
|
316
|
+
raise ValueError(
|
|
317
|
+
"todo update accepts either --claimed-by or --clear-claim, not both"
|
|
318
|
+
)
|
|
319
|
+
if args.explore_result_node_refs and args.clear_explore_result_node_refs:
|
|
320
|
+
raise ValueError(
|
|
321
|
+
"todo update accepts either --explore-result-node-ref or "
|
|
322
|
+
"--clear-explore-result-node-refs, not both"
|
|
323
|
+
)
|
|
324
|
+
if not any(getattr(args, field) for field in _TODO_UPDATE_MUTABLE_FIELDS):
|
|
325
|
+
raise ValueError("todo update requires at least one mutable todo field")
|
|
326
|
+
if args.no_follow_up and not (args.note or args.reason or args.evidence):
|
|
327
|
+
raise ValueError("--no-follow-up requires --note, --reason, or --evidence")
|
|
328
|
+
for field, message in _TODO_UPDATE_UNSUPPORTED_FIELDS:
|
|
329
|
+
if getattr(args, field):
|
|
330
|
+
raise ValueError(message)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def validate_todo_complete_options(args: argparse.Namespace) -> None:
|
|
334
|
+
if not args.todo_id:
|
|
335
|
+
raise ValueError("todo complete requires --todo-id")
|
|
336
|
+
if args.explore_result_node_refs or args.clear_explore_result_node_refs:
|
|
337
|
+
raise ValueError("todo complete does not update --explore-result-node-ref; use todo update first")
|
|
338
|
+
if args.claimed_by and args.clear_claim:
|
|
339
|
+
raise ValueError("todo complete accepts either --claimed-by or --clear-claim, not both")
|
|
340
|
+
if args.task_lease_expected_version is not None and not args.task_lease_idempotency_key:
|
|
341
|
+
raise ValueError(
|
|
342
|
+
"--task-lease-expected-version requires --task-lease-idempotency-key"
|
|
343
|
+
)
|
|
344
|
+
if any(getattr(args, field) for field in ("task_repository", "bound_agent", "goal_bound", "blocks_agent", "clear_blocks_agent", "excluded_agents", "clear_excluded_agents", "global_gate", "clear_global_gate", "unblocks_todo_id", "resume_when")):
|
|
345
|
+
raise ValueError("todo complete does not update current todo routing metadata; use todo update first")
|
|
346
|
+
if any(getattr(args, field) for field in ("monitor_target_key", "cadence", "next_due_at", "expires_at")):
|
|
347
|
+
raise ValueError("todo complete does not update target or monitor schedule metadata; use todo update before completion")
|
|
348
|
+
if args.no_follow_up and (args.next_agent_todo or args.next_user_todo):
|
|
349
|
+
raise ValueError("--no-follow-up cannot be combined with successor todos")
|
|
350
|
+
if args.no_follow_up and args.successor_todo_ids:
|
|
351
|
+
raise ValueError("--no-follow-up cannot be combined with successor todos")
|
|
352
|
+
if args.successor_todo_ids and (args.next_agent_todo or args.next_user_todo):
|
|
353
|
+
raise ValueError("--successor-todo-id links existing work and cannot be combined with --next-agent-todo or --next-user-todo")
|
|
354
|
+
if args.no_follow_up and not (args.note or args.evidence):
|
|
355
|
+
raise ValueError("--no-follow-up requires --note or --evidence")
|
|
356
|
+
if args.followups:
|
|
357
|
+
raise ValueError("todo complete does not support --follow-up; use `todo capture-followups`")
|
|
358
|
+
if args.continuation_policy:
|
|
359
|
+
raise ValueError("todo complete does not update --continuation-policy; use todo update first")
|
|
360
|
+
validate_successor_routing_options(args)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def validate_todo_supersede_options(args: argparse.Namespace) -> None:
|
|
364
|
+
if not args.todo_id:
|
|
365
|
+
raise ValueError("todo supersede requires --todo-id")
|
|
366
|
+
if args.explore_result_node_refs or args.clear_explore_result_node_refs:
|
|
367
|
+
raise ValueError("todo supersede does not update --explore-result-node-ref; use todo update first")
|
|
368
|
+
if args.decision_outcome:
|
|
369
|
+
raise ValueError("todo supersede does not accept --decision-outcome; use todo complete")
|
|
370
|
+
if args.claimed_by:
|
|
371
|
+
raise ValueError("todo supersede does not support --claimed-by; use --next-claimed-by to assign the successor, or omit it to inherit the superseded todo owner when present")
|
|
372
|
+
if args.clear_claim:
|
|
373
|
+
raise ValueError("todo supersede does not support --clear-claim")
|
|
374
|
+
if args.self_merged:
|
|
375
|
+
raise ValueError("todo supersede does not support --self-merged")
|
|
376
|
+
if args.no_follow_up:
|
|
377
|
+
raise ValueError("todo supersede does not support --no-follow-up")
|
|
378
|
+
if args.followups:
|
|
379
|
+
raise ValueError("todo supersede does not support --follow-up; use `todo capture-followups`")
|
|
380
|
+
if args.continuation_policy:
|
|
381
|
+
raise ValueError("todo supersede does not update --continuation-policy; use todo update first")
|
|
382
|
+
validate_successor_routing_options(args)
|
|
383
|
+
if any(getattr(args, field) for field in ("blocks_agent", "clear_blocks_agent", "excluded_agents", "clear_excluded_agents", "global_gate", "clear_global_gate", "unblocks_todo_id", "resume_when")):
|
|
384
|
+
raise ValueError("todo supersede does not update current todo routing metadata; use todo update first")
|
|
385
|
+
if args.successor_todo_ids:
|
|
386
|
+
raise ValueError("todo supersede does not support --successor-todo-id; use --next-agent-todo or update the source todo before supersede")
|
|
387
|
+
if any(getattr(args, field) for field in ("monitor_target_key", "cadence", "next_due_at", "expires_at")):
|
|
388
|
+
raise ValueError("todo supersede does not update target or monitor schedule metadata; use todo update before supersede")
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
def validate_todo_archive_completed_options(args: argparse.Namespace) -> None:
|
|
392
|
+
checks = (
|
|
393
|
+
(args.decision_outcome, "todo archive-completed does not support --decision-outcome"),
|
|
394
|
+
(args.claimed_by or args.clear_claim, "todo archive-completed does not support --claimed-by or --clear-claim"),
|
|
395
|
+
(any(getattr(args, field) for field in ("clear_blocks_agent", "excluded_agents", "clear_excluded_agents", "next_excluded_agents")), "todo archive-completed does not support executor exclusions"),
|
|
396
|
+
(args.next_claimed_by, "todo archive-completed does not support --next-claimed-by"),
|
|
397
|
+
(args.next_task_repository or args.next_required_capabilities, "todo archive-completed does not support successor routing metadata"),
|
|
398
|
+
(args.self_merged, "todo archive-completed does not support --self-merged"),
|
|
399
|
+
(args.no_follow_up, "todo archive-completed does not support --no-follow-up"),
|
|
400
|
+
(args.followups, "todo archive-completed does not support --follow-up; use `todo capture-followups`"),
|
|
401
|
+
(args.successor_todo_ids, "todo archive-completed does not support --successor-todo-id"),
|
|
402
|
+
)
|
|
403
|
+
for triggered, message in checks:
|
|
404
|
+
if triggered:
|
|
405
|
+
raise ValueError(message)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def validate_todo_suggest_options(args: argparse.Namespace) -> None:
|
|
409
|
+
_validate_todo_option_subset(
|
|
410
|
+
args,
|
|
411
|
+
{"agent_id", "suggestion_sources", "suggestion_limit", "suggestion_trigger"},
|
|
412
|
+
"todo suggest only accepts --goal-id, optional --project, --agent-id, "
|
|
413
|
+
"--from, --limit, --trigger, --dry-run, and --format; unsupported: ",
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def validate_todo_capture_followups_options(args: argparse.Namespace) -> None:
|
|
418
|
+
checks = (
|
|
419
|
+
(args.role, "todo capture-followups always records agent todos; do not pass --role"),
|
|
420
|
+
(args.claimed_by, "todo capture-followups writes unclaimed todos; do not pass --claimed-by"),
|
|
421
|
+
)
|
|
422
|
+
for triggered, message in checks:
|
|
423
|
+
if triggered:
|
|
424
|
+
raise ValueError(message)
|
|
425
|
+
_validate_todo_option_subset(
|
|
426
|
+
args,
|
|
427
|
+
{
|
|
428
|
+
"text", "followups", "evidence", "task_class", "action_kind",
|
|
429
|
+
"continuation_policy", "required_write_scopes", "required_capabilities",
|
|
430
|
+
"target_capabilities", "required_decision_scopes", "state_file",
|
|
431
|
+
},
|
|
432
|
+
"todo capture-followups only accepts --goal-id, --follow-up, optional "
|
|
433
|
+
"--text shorthand, --evidence, routing metadata, --project, --state-file, "
|
|
434
|
+
"and --dry-run; unsupported: ",
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def validate_shared_todo_options(args: argparse.Namespace) -> None:
|
|
439
|
+
agent_id_allowed_for_user_authoring = (
|
|
440
|
+
args.todo_command == "add"
|
|
441
|
+
and args.role == "user"
|
|
442
|
+
and args.task_class in {"user_gate", "user_action"}
|
|
443
|
+
)
|
|
444
|
+
agent_id_allowed_for_read = args.todo_command == "list"
|
|
445
|
+
agent_id_allowed_for_lifecycle = args.todo_command in {
|
|
446
|
+
"claim",
|
|
447
|
+
"update",
|
|
448
|
+
"complete",
|
|
449
|
+
"supersede",
|
|
450
|
+
}
|
|
451
|
+
global_gate_allowed = args.todo_command in {"add", "update"}
|
|
452
|
+
clear_global_gate_allowed = args.todo_command == "update"
|
|
453
|
+
authority_reason_allowed = args.todo_command in {
|
|
454
|
+
"update",
|
|
455
|
+
"complete",
|
|
456
|
+
"supersede",
|
|
457
|
+
}
|
|
458
|
+
if getattr(args, "turn_instance_id", None) and args.todo_command != "complete":
|
|
459
|
+
raise ValueError(
|
|
460
|
+
"--turn-instance-id is supported only by todo complete settlement"
|
|
461
|
+
)
|
|
462
|
+
if (
|
|
463
|
+
getattr(args, "replan_obligation_id", None)
|
|
464
|
+
and args.todo_command != "add"
|
|
465
|
+
):
|
|
466
|
+
raise ValueError(
|
|
467
|
+
"--replan-obligation-id is supported only by todo add"
|
|
468
|
+
)
|
|
469
|
+
if (
|
|
470
|
+
args.todo_command != "complete"
|
|
471
|
+
and (
|
|
472
|
+
args.task_lease_idempotency_key
|
|
473
|
+
or args.task_lease_expected_version is not None
|
|
474
|
+
)
|
|
475
|
+
):
|
|
476
|
+
raise ValueError(
|
|
477
|
+
"--task-lease-idempotency-key and --task-lease-expected-version "
|
|
478
|
+
"are supported only by todo complete"
|
|
479
|
+
)
|
|
480
|
+
if args.capability_binding_ref and args.todo_command != "add":
|
|
481
|
+
raise ValueError(
|
|
482
|
+
"--capability-binding-ref is immutable and supported only by todo add"
|
|
483
|
+
)
|
|
484
|
+
if args.authority_reason and not authority_reason_allowed:
|
|
485
|
+
raise ValueError(
|
|
486
|
+
"--authority-reason is supported only by todo update/complete/supersede"
|
|
487
|
+
)
|
|
488
|
+
if (
|
|
489
|
+
args.todo_command not in {"suggest", "capture-followups"}
|
|
490
|
+
and args.agent_id
|
|
491
|
+
and not agent_id_allowed_for_user_authoring
|
|
492
|
+
and not agent_id_allowed_for_read
|
|
493
|
+
and not agent_id_allowed_for_lifecycle
|
|
494
|
+
):
|
|
495
|
+
if args.todo_command == "add" and args.role == "agent":
|
|
496
|
+
raise ValueError(
|
|
497
|
+
"todo add does not support --agent-id for agent todos; omit "
|
|
498
|
+
"--agent-id and use --claimed-by <registered-agent> only when "
|
|
499
|
+
"assigning execution, or omit both options to leave the todo "
|
|
500
|
+
"unclaimed."
|
|
501
|
+
)
|
|
502
|
+
raise ValueError(
|
|
503
|
+
f"todo {args.todo_command} does not support --agent-id; --agent-id "
|
|
504
|
+
"scopes todo list/suggest, user-todo authoring, and lifecycle actor "
|
|
505
|
+
"attribution only."
|
|
506
|
+
)
|
|
507
|
+
if args.global_gate and not global_gate_allowed:
|
|
508
|
+
raise ValueError(
|
|
509
|
+
"--global-gate is supported only by todo add/update for user_gate items"
|
|
510
|
+
)
|
|
511
|
+
if args.clear_global_gate and not clear_global_gate_allowed:
|
|
512
|
+
raise ValueError(
|
|
513
|
+
"--clear-global-gate is supported only by todo update for user_gate items"
|
|
514
|
+
)
|
|
515
|
+
if args.clear_resume_when and args.todo_command != "update":
|
|
516
|
+
raise ValueError("--clear-resume-when is supported only by todo update")
|
|
517
|
+
if args.clear_resume_when and args.resume_when:
|
|
518
|
+
raise ValueError(
|
|
519
|
+
"todo update accepts either --resume-when or --clear-resume-when, not both"
|
|
520
|
+
)
|
|
521
|
+
if (
|
|
522
|
+
args.todo_command not in {"suggest", "capture-followups"}
|
|
523
|
+
and (
|
|
524
|
+
args.suggestion_sources
|
|
525
|
+
or args.suggestion_limit is not None
|
|
526
|
+
or args.suggestion_trigger
|
|
527
|
+
)
|
|
528
|
+
):
|
|
529
|
+
raise ValueError(
|
|
530
|
+
"--from, --limit, and --trigger are supported only by todo suggest"
|
|
531
|
+
)
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
def validate_capability_gap_options(args: argparse.Namespace) -> None:
|
|
535
|
+
if not args.capability_gap_status:
|
|
536
|
+
return
|
|
537
|
+
if args.todo_command not in {"add", "update", "complete"}:
|
|
538
|
+
raise ValueError(
|
|
539
|
+
"--capability-gap-status is supported only by todo add/update/complete"
|
|
540
|
+
)
|
|
541
|
+
if args.role != "agent":
|
|
542
|
+
raise ValueError("--capability-gap-status requires --role agent")
|
|
543
|
+
if not args.target_capabilities:
|
|
544
|
+
raise ValueError(
|
|
545
|
+
"--capability-gap-status requires at least one --target-capability"
|
|
546
|
+
)
|
|
547
|
+
if (
|
|
548
|
+
args.capability_gap_status in {"fixed", "real_callsite_verified"}
|
|
549
|
+
and not args.evidence
|
|
550
|
+
):
|
|
551
|
+
raise ValueError(
|
|
552
|
+
"fixed and real_callsite_verified capability gaps require "
|
|
553
|
+
"public-safe --evidence"
|
|
554
|
+
)
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
def validate_successor_routing_options(args: argparse.Namespace) -> None:
|
|
558
|
+
if args.next_user_task_class and not args.next_user_todo:
|
|
559
|
+
raise ValueError("--next-user-task-class requires --next-user-todo")
|
|
560
|
+
if args.next_user_todo and not args.next_user_task_class:
|
|
561
|
+
raise ValueError(
|
|
562
|
+
"--next-user-todo requires explicit --next-user-task-class "
|
|
563
|
+
"user_action|user_gate"
|
|
564
|
+
)
|
|
565
|
+
if args.next_continuation_policy and not args.next_agent_todo:
|
|
566
|
+
raise ValueError("--next-continuation-policy requires --next-agent-todo")
|
|
567
|
+
if args.next_task_repository and not args.next_agent_todo:
|
|
568
|
+
raise ValueError("--next-task-repository requires --next-agent-todo")
|
|
569
|
+
if args.next_required_capabilities and not args.next_agent_todo:
|
|
570
|
+
raise ValueError("--next-required-capability requires --next-agent-todo")
|
|
571
|
+
if args.next_excluded_agents and not args.next_agent_todo:
|
|
572
|
+
raise ValueError("--next-excluded-agent requires --next-agent-todo")
|
|
@@ -0,0 +1,114 @@
|
|
|
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 decision_scope_metadata_value
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
RolloutEventAppender = Callable[..., dict[str, object]]
|
|
11
|
+
|
|
12
|
+
TODO_EVENT_KINDS = {
|
|
13
|
+
"add": "todo_add",
|
|
14
|
+
"claim": "todo_claim",
|
|
15
|
+
"update": "todo_update",
|
|
16
|
+
"complete": "todo_complete",
|
|
17
|
+
"supersede": "todo_supersede",
|
|
18
|
+
"archive-completed": "todo_archive_completed",
|
|
19
|
+
"capture-followups": "todo_capture_followups",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
def append_todo_rollout_event(
|
|
23
|
+
payload: dict[str, object],
|
|
24
|
+
*,
|
|
25
|
+
args: argparse.Namespace,
|
|
26
|
+
registry_path: Path,
|
|
27
|
+
runtime_root_arg: str | None,
|
|
28
|
+
append_cli_rollout_event: RolloutEventAppender,
|
|
29
|
+
) -> None:
|
|
30
|
+
turn_instance_id = getattr(args, "turn_instance_id", None)
|
|
31
|
+
if (
|
|
32
|
+
not payload.get("ok")
|
|
33
|
+
or payload.get("dry_run")
|
|
34
|
+
or (payload.get("idempotent_replay") and not turn_instance_id)
|
|
35
|
+
):
|
|
36
|
+
return
|
|
37
|
+
append_cli_rollout_event(
|
|
38
|
+
payload,
|
|
39
|
+
registry_path=registry_path,
|
|
40
|
+
runtime_root_arg=runtime_root_arg,
|
|
41
|
+
event_kind=TODO_EVENT_KINDS.get(args.todo_command, "todo_update"),
|
|
42
|
+
agent_id=args.agent_id or args.claimed_by,
|
|
43
|
+
todo_id=args.todo_id or str(payload.get("todo_id") or "").strip() or None,
|
|
44
|
+
run_id=turn_instance_id,
|
|
45
|
+
status=str(payload.get("status") or args.todo_command or "").strip(),
|
|
46
|
+
summary=(
|
|
47
|
+
f"todo {args.todo_command} recorded for "
|
|
48
|
+
f"{payload.get('todo_id') or args.todo_id or 'unstructured todo'}"
|
|
49
|
+
),
|
|
50
|
+
details={
|
|
51
|
+
"command": "todo",
|
|
52
|
+
"todo_command": args.todo_command,
|
|
53
|
+
"role": payload.get("role") or args.role or "",
|
|
54
|
+
"task_class": (
|
|
55
|
+
payload.get("task_class")
|
|
56
|
+
or getattr(args, "task_class", None)
|
|
57
|
+
or ""
|
|
58
|
+
),
|
|
59
|
+
"decision_scope": decision_scope_metadata_value(
|
|
60
|
+
payload.get("decision_scope")
|
|
61
|
+
),
|
|
62
|
+
"decision_outcome": payload.get("decision_outcome"),
|
|
63
|
+
"changed": bool(payload.get("changed")),
|
|
64
|
+
"added": bool(payload.get("added")),
|
|
65
|
+
"already_exists": bool(payload.get("already_exists")),
|
|
66
|
+
"no_followup": bool(getattr(args, "no_follow_up", False)),
|
|
67
|
+
"mutation_authority": payload.get("mutation_authority"),
|
|
68
|
+
"replan_transition": payload.get("replan_transition"),
|
|
69
|
+
"settlement_effect_id": (
|
|
70
|
+
payload.get("settlement_identity", {}).get("effect_id")
|
|
71
|
+
if isinstance(payload.get("settlement_identity"), dict)
|
|
72
|
+
else None
|
|
73
|
+
),
|
|
74
|
+
},
|
|
75
|
+
idempotency_fields=(
|
|
76
|
+
["goal_id", "event_kind", "agent_id", "todo_id", "run_id"]
|
|
77
|
+
if turn_instance_id
|
|
78
|
+
else None
|
|
79
|
+
),
|
|
80
|
+
)
|
|
81
|
+
capability_gap_status = str(
|
|
82
|
+
getattr(args, "capability_gap_status", None) or ""
|
|
83
|
+
).strip()
|
|
84
|
+
if not capability_gap_status:
|
|
85
|
+
return
|
|
86
|
+
gap_payload: dict[str, object] = {
|
|
87
|
+
"ok": True,
|
|
88
|
+
"goal_id": payload.get("goal_id"),
|
|
89
|
+
}
|
|
90
|
+
append_cli_rollout_event(
|
|
91
|
+
gap_payload,
|
|
92
|
+
registry_path=registry_path,
|
|
93
|
+
runtime_root_arg=runtime_root_arg,
|
|
94
|
+
event_kind="capability_gap",
|
|
95
|
+
agent_id=args.agent_id or args.claimed_by,
|
|
96
|
+
todo_id=args.todo_id or str(payload.get("todo_id") or "").strip() or None,
|
|
97
|
+
status=capability_gap_status,
|
|
98
|
+
summary=(
|
|
99
|
+
f"capability gap {capability_gap_status} for "
|
|
100
|
+
f"{payload.get('todo_id') or args.todo_id}"
|
|
101
|
+
),
|
|
102
|
+
details={
|
|
103
|
+
"command": "todo",
|
|
104
|
+
"todo_command": args.todo_command,
|
|
105
|
+
"target_capabilities": ",".join(args.target_capabilities or []),
|
|
106
|
+
"evidence": args.evidence or "not_required_for_found",
|
|
107
|
+
},
|
|
108
|
+
)
|
|
109
|
+
if gap_payload.get("rollout_event"):
|
|
110
|
+
payload["capability_gap_event"] = gap_payload["rollout_event"]
|
|
111
|
+
elif gap_payload.get("rollout_event_log_error"):
|
|
112
|
+
payload["capability_gap_event_error"] = gap_payload[
|
|
113
|
+
"rollout_event_log_error"
|
|
114
|
+
]
|