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,1822 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from ...agent_registry import load_goal_from_registry
|
|
9
|
+
from ...boundary_authority import checkpointed_boundary_authority_summary
|
|
10
|
+
from ...control_plane.runtime.time import now_utc_iso
|
|
11
|
+
from ...domain_packs.issue_fix import (
|
|
12
|
+
default_issue_fix_candidate_preflight_ledger_path,
|
|
13
|
+
default_issue_fix_domain_state_ledger_path,
|
|
14
|
+
default_issue_fix_feasibility_ledger_path,
|
|
15
|
+
default_issue_fix_repository_snapshot_ledger_path,
|
|
16
|
+
retain_issue_fix_repository_snapshot_jsonl,
|
|
17
|
+
upsert_issue_fix_candidate_preflight_ledger_jsonl,
|
|
18
|
+
upsert_issue_fix_feasibility_ledger_jsonl,
|
|
19
|
+
upsert_issue_fix_pr_lifecycle_ledger_jsonl,
|
|
20
|
+
)
|
|
21
|
+
from ...todos import add_goal_todo
|
|
22
|
+
from .acceptance_loop import (
|
|
23
|
+
build_issue_fix_acceptance_fixture_packet,
|
|
24
|
+
build_issue_fix_caller_repo_branch_packet,
|
|
25
|
+
build_issue_fix_repo_branch_fixture_packet,
|
|
26
|
+
render_issue_fix_acceptance_loop_markdown,
|
|
27
|
+
)
|
|
28
|
+
from .candidate_evidence import collect_public_github_candidate_preflight_input
|
|
29
|
+
from .feasibility import (
|
|
30
|
+
build_issue_fix_feasibility_packet,
|
|
31
|
+
render_issue_fix_feasibility_markdown,
|
|
32
|
+
)
|
|
33
|
+
from .discovered_issue_promotion import (
|
|
34
|
+
build_discovered_issue_promotion_from_cli_args,
|
|
35
|
+
register_discovered_issue_promotion_command,
|
|
36
|
+
render_issue_fix_discovered_issue_promotion_markdown,
|
|
37
|
+
)
|
|
38
|
+
from .cli_input import (
|
|
39
|
+
_MAX_INLINE_JSON_CHARS as _MAX_INLINE_JSON_CHARS,
|
|
40
|
+
load_json_object as _load_json_object,
|
|
41
|
+
load_jsonl_row as _load_jsonl_row,
|
|
42
|
+
load_jsonl_rows as _load_jsonl_rows,
|
|
43
|
+
)
|
|
44
|
+
from .outcome_projection import (
|
|
45
|
+
build_issue_fix_outcome_projection,
|
|
46
|
+
compact_issue_fix_delivery_evidence,
|
|
47
|
+
render_issue_fix_outcome_projection_markdown,
|
|
48
|
+
)
|
|
49
|
+
from .metrics_projection import (
|
|
50
|
+
build_issue_fix_metrics_projection,
|
|
51
|
+
render_issue_fix_metrics_projection_markdown,
|
|
52
|
+
)
|
|
53
|
+
from .metrics_supplement import (
|
|
54
|
+
render_issue_fix_metrics_supplement_markdown,
|
|
55
|
+
)
|
|
56
|
+
from .metrics_supplement_cli import (
|
|
57
|
+
build_issue_fix_metrics_supplement_from_args,
|
|
58
|
+
register_issue_fix_metrics_supplement_command,
|
|
59
|
+
)
|
|
60
|
+
from .metadata_preview import normalise_github_issue_reference
|
|
61
|
+
from .pr_lifecycle import (
|
|
62
|
+
build_issue_fix_pr_lifecycle_monitor_packet,
|
|
63
|
+
render_issue_fix_pr_lifecycle_monitor_markdown,
|
|
64
|
+
validate_issue_fix_pr_lifecycle_monitor_packet,
|
|
65
|
+
)
|
|
66
|
+
from .pr_lifecycle_rollout import append_pr_merge_rollout_event
|
|
67
|
+
from .pr_monitor_materialization import (
|
|
68
|
+
DEFAULT_ISSUE_FIX_MONITOR_CADENCE,
|
|
69
|
+
materialize_issue_fix_grouped_monitors,
|
|
70
|
+
)
|
|
71
|
+
from .provider_hooks import IssueFixReviewerProviderHooksFactory
|
|
72
|
+
from . import pr_gate_reconcile_cli
|
|
73
|
+
from .reviewer_cli import (
|
|
74
|
+
REVIEWER_COMMANDS,
|
|
75
|
+
_materialize_goal_reviewer_notification_lifecycle as _materialize_goal_reviewer_notification_lifecycle,
|
|
76
|
+
handle_issue_fix_reviewer_command,
|
|
77
|
+
register_issue_fix_reviewer_commands,
|
|
78
|
+
reviewer_renderer,
|
|
79
|
+
)
|
|
80
|
+
from .repository_memory import SUPPORT_ASPECTS
|
|
81
|
+
from .repository_memory_provider import (
|
|
82
|
+
default_repository_memory_provider_config_path,
|
|
83
|
+
render_issue_fix_repository_memory_sync_markdown,
|
|
84
|
+
retrieve_issue_fix_repository_memory,
|
|
85
|
+
sync_issue_fix_repository_memory,
|
|
86
|
+
write_issue_fix_validated_outcome_memory,
|
|
87
|
+
)
|
|
88
|
+
from .repository_commit_evidence import verify_issue_fix_repository_commit_evidence
|
|
89
|
+
from .repository_snapshot import (
|
|
90
|
+
collect_public_github_repository_snapshot,
|
|
91
|
+
render_repository_snapshot_markdown,
|
|
92
|
+
repository_snapshot_record,
|
|
93
|
+
)
|
|
94
|
+
from .workflow_plan import (
|
|
95
|
+
build_issue_fix_workflow_plan_packet,
|
|
96
|
+
render_issue_fix_workflow_plan_markdown,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
PrintPayload = Callable[
|
|
101
|
+
[dict[str, object], str, Callable[[dict[str, object]], str]],
|
|
102
|
+
None,
|
|
103
|
+
]
|
|
104
|
+
FormatSelector = Callable[..., str]
|
|
105
|
+
AddFormat = Callable[[argparse.ArgumentParser], None]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _comparable_delivery_evidence(
|
|
109
|
+
value: dict[str, Any] | None,
|
|
110
|
+
) -> dict[str, Any] | None:
|
|
111
|
+
if value is None:
|
|
112
|
+
return None
|
|
113
|
+
comparable = {key: item for key, item in value.items() if key != "recorded_at"}
|
|
114
|
+
repository_evidence = comparable.get("repository_commit_evidence")
|
|
115
|
+
if isinstance(repository_evidence, dict):
|
|
116
|
+
comparable["repository_commit_evidence"] = {
|
|
117
|
+
key: item
|
|
118
|
+
for key, item in repository_evidence.items()
|
|
119
|
+
if key != "verified_at"
|
|
120
|
+
}
|
|
121
|
+
return comparable
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _configured_repository_memory_input(
|
|
125
|
+
*,
|
|
126
|
+
provider_path: str | None,
|
|
127
|
+
raw_memory_path: str | None,
|
|
128
|
+
repo_path: str | None,
|
|
129
|
+
repository_context_input: dict[str, Any] | None,
|
|
130
|
+
repo: str,
|
|
131
|
+
issue_ref: str,
|
|
132
|
+
query: str | None,
|
|
133
|
+
supports: list[str],
|
|
134
|
+
validation_label: str | None,
|
|
135
|
+
observed_at: str,
|
|
136
|
+
) -> dict[str, Any] | None:
|
|
137
|
+
if raw_memory_path and provider_path:
|
|
138
|
+
raise ValueError(
|
|
139
|
+
"--repository-memory-json cannot be combined with a configured provider"
|
|
140
|
+
)
|
|
141
|
+
if raw_memory_path:
|
|
142
|
+
return _load_json_object(raw_memory_path)
|
|
143
|
+
if not provider_path:
|
|
144
|
+
return None
|
|
145
|
+
if not repo_path or not repository_context_input:
|
|
146
|
+
return None
|
|
147
|
+
revision = str(repository_context_input.get("repository_revision") or "").strip()
|
|
148
|
+
if not revision:
|
|
149
|
+
return None
|
|
150
|
+
retrieval_query = query or " ".join(
|
|
151
|
+
value
|
|
152
|
+
for value in (
|
|
153
|
+
repo,
|
|
154
|
+
issue_ref,
|
|
155
|
+
validation_label or "repository architecture reproduction validation",
|
|
156
|
+
)
|
|
157
|
+
if value
|
|
158
|
+
)
|
|
159
|
+
query_summary = (
|
|
160
|
+
query
|
|
161
|
+
or f"Public repository context for {repo} {issue_ref} before patch planning."
|
|
162
|
+
)
|
|
163
|
+
result = retrieve_issue_fix_repository_memory(
|
|
164
|
+
config=_load_json_object(provider_path),
|
|
165
|
+
repo_path=repo_path,
|
|
166
|
+
repository_revision=revision,
|
|
167
|
+
query=retrieval_query,
|
|
168
|
+
query_summary=query_summary,
|
|
169
|
+
supports=(
|
|
170
|
+
supports or ["architecture", "change_scope", "reproduction", "validation"]
|
|
171
|
+
),
|
|
172
|
+
observed_at=observed_at,
|
|
173
|
+
)
|
|
174
|
+
return result["memory_input"]
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _add_repository_memory_provider_args(parser: argparse.ArgumentParser) -> None:
|
|
178
|
+
parser.add_argument(
|
|
179
|
+
"--repository-memory-provider-json",
|
|
180
|
+
default=None,
|
|
181
|
+
help=(
|
|
182
|
+
"Optional local-private issue_fix_repository_memory_provider_config_v0. "
|
|
183
|
+
"Defaults to LOOPX_ISSUE_FIX_REPOSITORY_MEMORY_PROVIDER_CONFIG. "
|
|
184
|
+
"The path, provider command, credentials, and raw payloads are never kept."
|
|
185
|
+
),
|
|
186
|
+
)
|
|
187
|
+
parser.add_argument(
|
|
188
|
+
"--repository-memory-query",
|
|
189
|
+
default=None,
|
|
190
|
+
help=(
|
|
191
|
+
"Optional compact public query for configured provider search/read. "
|
|
192
|
+
"A bounded issue/ref/validation query is derived when omitted."
|
|
193
|
+
),
|
|
194
|
+
)
|
|
195
|
+
parser.add_argument(
|
|
196
|
+
"--repository-memory-support",
|
|
197
|
+
action="append",
|
|
198
|
+
default=[],
|
|
199
|
+
choices=sorted(SUPPORT_ASPECTS),
|
|
200
|
+
help="Repository aspect supported by retrieved context. Repeat as needed.",
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _add_generated_at_arg(
|
|
205
|
+
parser: argparse.ArgumentParser,
|
|
206
|
+
*,
|
|
207
|
+
artifact: str,
|
|
208
|
+
) -> None:
|
|
209
|
+
parser.add_argument(
|
|
210
|
+
"--generated-at",
|
|
211
|
+
default=None,
|
|
212
|
+
help=(
|
|
213
|
+
f"Public-safe generated_at timestamp for {artifact}; "
|
|
214
|
+
"defaults to current UTC invocation time."
|
|
215
|
+
),
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _goal_boundary_authority_projection(
|
|
220
|
+
*,
|
|
221
|
+
registry_path: Path | None,
|
|
222
|
+
goal_id: str | None,
|
|
223
|
+
) -> tuple[list[str], bool]:
|
|
224
|
+
if registry_path is None or not goal_id:
|
|
225
|
+
return [], False
|
|
226
|
+
goal = load_goal_from_registry(registry_path, goal_id)
|
|
227
|
+
if not isinstance(goal, dict):
|
|
228
|
+
return [], False
|
|
229
|
+
coordination = (
|
|
230
|
+
goal.get("coordination") if isinstance(goal.get("coordination"), dict) else {}
|
|
231
|
+
)
|
|
232
|
+
summary = checkpointed_boundary_authority_summary(coordination)
|
|
233
|
+
scopes = (
|
|
234
|
+
list(summary.get("active_write_scope") or [])
|
|
235
|
+
if isinstance(summary, dict)
|
|
236
|
+
else []
|
|
237
|
+
)
|
|
238
|
+
return [str(scope) for scope in scopes], True
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def register_issue_fix_commands(
|
|
242
|
+
subparsers: argparse._SubParsersAction,
|
|
243
|
+
add_subcommand_format: AddFormat,
|
|
244
|
+
) -> None:
|
|
245
|
+
issue_fix_parser = subparsers.add_parser(
|
|
246
|
+
"issue-fix",
|
|
247
|
+
help="Run public-safe issue fix acceptance loops.",
|
|
248
|
+
)
|
|
249
|
+
issue_fix_sub = issue_fix_parser.add_subparsers(
|
|
250
|
+
dest="issue_fix_command",
|
|
251
|
+
required=True,
|
|
252
|
+
)
|
|
253
|
+
memory_sync_parser = issue_fix_sub.add_parser(
|
|
254
|
+
"repository-memory-sync",
|
|
255
|
+
help=(
|
|
256
|
+
"Plan or explicitly execute a bounded public resource sync through "
|
|
257
|
+
"the reusable context-provider module."
|
|
258
|
+
),
|
|
259
|
+
)
|
|
260
|
+
add_subcommand_format(memory_sync_parser)
|
|
261
|
+
memory_sync_parser.add_argument("--repo-path", required=True)
|
|
262
|
+
memory_sync_parser.add_argument("--repository-context-json", required=True)
|
|
263
|
+
memory_sync_parser.add_argument(
|
|
264
|
+
"--repository-memory-provider-json",
|
|
265
|
+
default=None,
|
|
266
|
+
help=(
|
|
267
|
+
"Local-private provider config; defaults to "
|
|
268
|
+
"LOOPX_ISSUE_FIX_REPOSITORY_MEMORY_PROVIDER_CONFIG."
|
|
269
|
+
),
|
|
270
|
+
)
|
|
271
|
+
memory_sync_parser.add_argument(
|
|
272
|
+
"--resource-reference",
|
|
273
|
+
action="append",
|
|
274
|
+
default=[],
|
|
275
|
+
required=True,
|
|
276
|
+
help="Repo-relative public file to index. Repeat up to the bounded cap.",
|
|
277
|
+
)
|
|
278
|
+
memory_sync_parser.add_argument(
|
|
279
|
+
"--execute",
|
|
280
|
+
action="store_true",
|
|
281
|
+
help="Perform the provider resource write. Without this flag, return a plan.",
|
|
282
|
+
)
|
|
283
|
+
_add_generated_at_arg(memory_sync_parser, artifact="the resource sync")
|
|
284
|
+
register_discovered_issue_promotion_command(
|
|
285
|
+
issue_fix_sub,
|
|
286
|
+
add_subcommand_format=add_subcommand_format,
|
|
287
|
+
add_generated_at_arg=_add_generated_at_arg,
|
|
288
|
+
)
|
|
289
|
+
workflow_parser = issue_fix_sub.add_parser(
|
|
290
|
+
"workflow-plan",
|
|
291
|
+
help=(
|
|
292
|
+
"Plan the full issue-fix workflow from public metadata to ordered "
|
|
293
|
+
"LoopX todos, validation, and PR review packet readiness without writes."
|
|
294
|
+
),
|
|
295
|
+
)
|
|
296
|
+
add_subcommand_format(workflow_parser)
|
|
297
|
+
workflow_parser.add_argument(
|
|
298
|
+
"--repo",
|
|
299
|
+
default="public_repo_fixture",
|
|
300
|
+
help="Public-safe repository label for the issue metadata.",
|
|
301
|
+
)
|
|
302
|
+
workflow_parser.add_argument(
|
|
303
|
+
"--issue-ref",
|
|
304
|
+
default="issue_123_public_metadata_fixture",
|
|
305
|
+
help="Public-safe issue or PR reference label.",
|
|
306
|
+
)
|
|
307
|
+
workflow_parser.add_argument(
|
|
308
|
+
"--url",
|
|
309
|
+
default=None,
|
|
310
|
+
help="Optional https://github.com/owner/repo/issues/123 or /pull/123 URL.",
|
|
311
|
+
)
|
|
312
|
+
workflow_parser.add_argument(
|
|
313
|
+
"--metadata-json",
|
|
314
|
+
default=None,
|
|
315
|
+
help=(
|
|
316
|
+
"Path to mocked provider JSON metadata, or '-' for stdin. "
|
|
317
|
+
"Body/comment fields stay gated and are not copied."
|
|
318
|
+
),
|
|
319
|
+
)
|
|
320
|
+
workflow_parser.add_argument(
|
|
321
|
+
"--fetch-metadata",
|
|
322
|
+
action="store_true",
|
|
323
|
+
help=(
|
|
324
|
+
"Explicitly fetch public GitHub issue/PR metadata with gh api --jq. "
|
|
325
|
+
"Only body-free metadata fields are captured."
|
|
326
|
+
),
|
|
327
|
+
)
|
|
328
|
+
workflow_parser.add_argument(
|
|
329
|
+
"--fetch-timeout-seconds",
|
|
330
|
+
type=int,
|
|
331
|
+
default=10,
|
|
332
|
+
help="Timeout for --fetch-metadata.",
|
|
333
|
+
)
|
|
334
|
+
workflow_parser.add_argument(
|
|
335
|
+
"--repo-path",
|
|
336
|
+
default=None,
|
|
337
|
+
help=(
|
|
338
|
+
"Optional caller-approved local git repository path. Planning keeps "
|
|
339
|
+
"this as a dry-run and never records the path."
|
|
340
|
+
),
|
|
341
|
+
)
|
|
342
|
+
workflow_parser.add_argument(
|
|
343
|
+
"--base-branch",
|
|
344
|
+
default="main",
|
|
345
|
+
help="Approved local base branch for the eventual issue branch.",
|
|
346
|
+
)
|
|
347
|
+
workflow_parser.add_argument(
|
|
348
|
+
"--issue-branch",
|
|
349
|
+
default=None,
|
|
350
|
+
help="Optional issue branch for the eventual caller-repo execution.",
|
|
351
|
+
)
|
|
352
|
+
workflow_parser.add_argument(
|
|
353
|
+
"--validation-label",
|
|
354
|
+
default="caller-declared validation",
|
|
355
|
+
help="Public-safe validation label stored in the workflow plan.",
|
|
356
|
+
)
|
|
357
|
+
workflow_parser.add_argument(
|
|
358
|
+
"--repository-context-json",
|
|
359
|
+
default=None,
|
|
360
|
+
help=(
|
|
361
|
+
"Optional issue_fix_repository_context_input_v0 JSON path, or '-' for "
|
|
362
|
+
"stdin. Only compact source refs, trust, freshness, and coverage are kept."
|
|
363
|
+
),
|
|
364
|
+
)
|
|
365
|
+
workflow_parser.add_argument(
|
|
366
|
+
"--candidate-preflight-json",
|
|
367
|
+
default=None,
|
|
368
|
+
help=(
|
|
369
|
+
"Optional issue_fix_candidate_preflight_input_v0 with compact prior "
|
|
370
|
+
"domain state, all-state numeric PR references, verified semantic "
|
|
371
|
+
"implementation candidates, and an existing recall receipt. The "
|
|
372
|
+
"workflow performs no provider or memory calls."
|
|
373
|
+
),
|
|
374
|
+
)
|
|
375
|
+
workflow_parser.add_argument(
|
|
376
|
+
"--fetch-candidate-evidence",
|
|
377
|
+
action="store_true",
|
|
378
|
+
help=(
|
|
379
|
+
"Collect complete issue-specific GitHub closing-PR, cross-reference, "
|
|
380
|
+
"and maintainer-disposition receipts before planning."
|
|
381
|
+
),
|
|
382
|
+
)
|
|
383
|
+
workflow_parser.add_argument(
|
|
384
|
+
"--candidate-evidence-timeout-seconds",
|
|
385
|
+
type=int,
|
|
386
|
+
default=30,
|
|
387
|
+
help="Timeout for --fetch-candidate-evidence.",
|
|
388
|
+
)
|
|
389
|
+
workflow_parser.add_argument(
|
|
390
|
+
"--candidate-resolution-json",
|
|
391
|
+
default=None,
|
|
392
|
+
help=(
|
|
393
|
+
"Optional issue_fix_candidate_resolution_v0 that resolves source-backed "
|
|
394
|
+
"PR revisions, closed PRs, or maintainer comments. Requires "
|
|
395
|
+
"--fetch-candidate-evidence so stale source bindings fail closed."
|
|
396
|
+
),
|
|
397
|
+
)
|
|
398
|
+
workflow_parser.add_argument(
|
|
399
|
+
"--goal-id",
|
|
400
|
+
default=None,
|
|
401
|
+
help=(
|
|
402
|
+
"Goal id used to persist the source-qualified candidate admission "
|
|
403
|
+
"receipt before any feasibility or implementation decision."
|
|
404
|
+
),
|
|
405
|
+
)
|
|
406
|
+
workflow_parser.add_argument(
|
|
407
|
+
"--project",
|
|
408
|
+
default=".",
|
|
409
|
+
help="Project root for the default issue_fix candidate preflight ledger.",
|
|
410
|
+
)
|
|
411
|
+
workflow_parser.add_argument(
|
|
412
|
+
"--candidate-preflight-ledger-path",
|
|
413
|
+
default=None,
|
|
414
|
+
help="Optional candidate preflight JSONL path. Overrides the default path.",
|
|
415
|
+
)
|
|
416
|
+
workflow_parser.add_argument(
|
|
417
|
+
"--no-write-domain-state",
|
|
418
|
+
action="store_true",
|
|
419
|
+
help=(
|
|
420
|
+
"Keep candidate preflight preview-only even when --goal-id or an "
|
|
421
|
+
"explicit ledger path is present."
|
|
422
|
+
),
|
|
423
|
+
)
|
|
424
|
+
workflow_parser.add_argument(
|
|
425
|
+
"--repository-memory-json",
|
|
426
|
+
default=None,
|
|
427
|
+
help=(
|
|
428
|
+
"Optional issue_fix_repository_memory_read_result_v0 JSON path, or '-' "
|
|
429
|
+
"for stdin. The host must perform explicit public-namespace search/read; "
|
|
430
|
+
"LoopX keeps only compact advisory refs and checkout verification."
|
|
431
|
+
),
|
|
432
|
+
)
|
|
433
|
+
_add_repository_memory_provider_args(workflow_parser)
|
|
434
|
+
_add_generated_at_arg(workflow_parser, artifact="the workflow plan")
|
|
435
|
+
feasibility_parser = issue_fix_sub.add_parser(
|
|
436
|
+
"feasibility",
|
|
437
|
+
help=(
|
|
438
|
+
"Select exactly one fix_pr, comment_only, or triage_only route "
|
|
439
|
+
"from compact public-safe agent observations."
|
|
440
|
+
),
|
|
441
|
+
)
|
|
442
|
+
add_subcommand_format(feasibility_parser)
|
|
443
|
+
feasibility_parser.add_argument(
|
|
444
|
+
"--repo",
|
|
445
|
+
default="public_repo_fixture",
|
|
446
|
+
help="Public-safe repository label for the issue.",
|
|
447
|
+
)
|
|
448
|
+
feasibility_parser.add_argument(
|
|
449
|
+
"--issue-ref",
|
|
450
|
+
default="issue_123_public_metadata_fixture",
|
|
451
|
+
help="Public-safe issue reference label.",
|
|
452
|
+
)
|
|
453
|
+
feasibility_parser.add_argument(
|
|
454
|
+
"--url",
|
|
455
|
+
default=None,
|
|
456
|
+
help="Optional https://github.com/owner/repo/issues/123 URL.",
|
|
457
|
+
)
|
|
458
|
+
feasibility_parser.add_argument(
|
|
459
|
+
"--reproduction-status",
|
|
460
|
+
required=True,
|
|
461
|
+
choices=("confirmed", "planned", "missing", "blocked"),
|
|
462
|
+
help="Compact agent observation of reproduction readiness.",
|
|
463
|
+
)
|
|
464
|
+
feasibility_parser.add_argument(
|
|
465
|
+
"--scope-class",
|
|
466
|
+
required=True,
|
|
467
|
+
choices=("bounded", "uncertain", "oversized"),
|
|
468
|
+
help="Compact agent observation of expected change scope.",
|
|
469
|
+
)
|
|
470
|
+
feasibility_parser.add_argument(
|
|
471
|
+
"--reproduction-label",
|
|
472
|
+
default=None,
|
|
473
|
+
help="Compact public-safe repro or repro-plan label; never raw logs.",
|
|
474
|
+
)
|
|
475
|
+
feasibility_parser.add_argument(
|
|
476
|
+
"--validation-label",
|
|
477
|
+
default=None,
|
|
478
|
+
help="Compact public-safe validation surface label.",
|
|
479
|
+
)
|
|
480
|
+
feasibility_parser.add_argument(
|
|
481
|
+
"--comment-value",
|
|
482
|
+
default="none",
|
|
483
|
+
choices=("none", "clarification", "diagnosis"),
|
|
484
|
+
help="Whether a maintainer-facing comment would add public value.",
|
|
485
|
+
)
|
|
486
|
+
feasibility_parser.add_argument(
|
|
487
|
+
"--repository-context-json",
|
|
488
|
+
default=None,
|
|
489
|
+
help=(
|
|
490
|
+
"Optional issue_fix_repository_context_input_v0 JSON path, or '-' for "
|
|
491
|
+
"stdin. The compact projection is persisted with feasibility domain state."
|
|
492
|
+
),
|
|
493
|
+
)
|
|
494
|
+
feasibility_parser.add_argument(
|
|
495
|
+
"--repository-memory-json",
|
|
496
|
+
default=None,
|
|
497
|
+
help=(
|
|
498
|
+
"Optional issue_fix_repository_memory_read_result_v0 JSON path, or '-' "
|
|
499
|
+
"for stdin. Provider failures stay fail-open and no writeback is allowed."
|
|
500
|
+
),
|
|
501
|
+
)
|
|
502
|
+
feasibility_parser.add_argument(
|
|
503
|
+
"--repo-path",
|
|
504
|
+
default=None,
|
|
505
|
+
help=(
|
|
506
|
+
"Optional caller-approved current checkout used only to verify provider "
|
|
507
|
+
"content. The path is never retained."
|
|
508
|
+
),
|
|
509
|
+
)
|
|
510
|
+
_add_repository_memory_provider_args(feasibility_parser)
|
|
511
|
+
_add_generated_at_arg(feasibility_parser, artifact="the feasibility decision")
|
|
512
|
+
feasibility_parser.add_argument(
|
|
513
|
+
"--goal-id",
|
|
514
|
+
default=None,
|
|
515
|
+
help="Goal id used for the default issue_fix feasibility ledger path.",
|
|
516
|
+
)
|
|
517
|
+
feasibility_parser.add_argument(
|
|
518
|
+
"--project",
|
|
519
|
+
default=".",
|
|
520
|
+
help="Project root for the default issue_fix feasibility ledger path.",
|
|
521
|
+
)
|
|
522
|
+
feasibility_parser.add_argument(
|
|
523
|
+
"--ledger-path",
|
|
524
|
+
default=None,
|
|
525
|
+
help="Optional local JSONL ledger path. Overrides the default path.",
|
|
526
|
+
)
|
|
527
|
+
feasibility_parser.add_argument(
|
|
528
|
+
"--no-write-domain-state",
|
|
529
|
+
action="store_true",
|
|
530
|
+
help=(
|
|
531
|
+
"Keep feasibility preview-only even when --goal-id or --ledger-path "
|
|
532
|
+
"is present."
|
|
533
|
+
),
|
|
534
|
+
)
|
|
535
|
+
pr_lifecycle_parser = issue_fix_sub.add_parser(
|
|
536
|
+
"pr-lifecycle",
|
|
537
|
+
help=(
|
|
538
|
+
"Project a public PR lifecycle observation into a successor, "
|
|
539
|
+
"monitor-continuation, user-gate, or no-follow-up transition."
|
|
540
|
+
),
|
|
541
|
+
)
|
|
542
|
+
add_subcommand_format(pr_lifecycle_parser)
|
|
543
|
+
pr_lifecycle_parser.add_argument(
|
|
544
|
+
"--repo",
|
|
545
|
+
default="public_repo_fixture",
|
|
546
|
+
help="Public-safe repository label for the PR metadata.",
|
|
547
|
+
)
|
|
548
|
+
pr_lifecycle_parser.add_argument(
|
|
549
|
+
"--pr-ref",
|
|
550
|
+
default="pull_123_public_metadata_fixture",
|
|
551
|
+
help="Public-safe PR reference label.",
|
|
552
|
+
)
|
|
553
|
+
pr_lifecycle_parser.add_argument(
|
|
554
|
+
"--issue-ref",
|
|
555
|
+
default=None,
|
|
556
|
+
help=(
|
|
557
|
+
"Optional public-safe issue reference linked to this PR. Persisting "
|
|
558
|
+
"the explicit link lets default Kanban sync compose the issue outcome "
|
|
559
|
+
"without guessing from titles or branch names. Numeric aliases such "
|
|
560
|
+
"as #123 and issue_123 are stored as issues_123."
|
|
561
|
+
),
|
|
562
|
+
)
|
|
563
|
+
pr_lifecycle_parser.add_argument(
|
|
564
|
+
"--url",
|
|
565
|
+
default=None,
|
|
566
|
+
help="Optional https://github.com/owner/repo/pull/123 URL.",
|
|
567
|
+
)
|
|
568
|
+
pr_lifecycle_parser.add_argument(
|
|
569
|
+
"--metadata-json",
|
|
570
|
+
default=None,
|
|
571
|
+
help=(
|
|
572
|
+
"Path to mocked gh pr view JSON metadata, or '-' for stdin. "
|
|
573
|
+
"Bodies, comments, raw logs, and provider responses stay out."
|
|
574
|
+
),
|
|
575
|
+
)
|
|
576
|
+
pr_lifecycle_parser.add_argument(
|
|
577
|
+
"--maintainer-correction-json",
|
|
578
|
+
default=None,
|
|
579
|
+
help=(
|
|
580
|
+
"Optional issue_fix_maintainer_correction_input_v0 JSON object. "
|
|
581
|
+
"It contains only a compact public correction, source reference, "
|
|
582
|
+
"verification plan/update path, ambiguity question, or missing scopes."
|
|
583
|
+
),
|
|
584
|
+
)
|
|
585
|
+
pr_lifecycle_parser.add_argument(
|
|
586
|
+
"--fetch-metadata",
|
|
587
|
+
action="store_true",
|
|
588
|
+
help=(
|
|
589
|
+
"Explicitly fetch public GitHub PR state with gh pr view. "
|
|
590
|
+
"Only compact lifecycle fields are captured."
|
|
591
|
+
),
|
|
592
|
+
)
|
|
593
|
+
pr_lifecycle_parser.add_argument(
|
|
594
|
+
"--fetch-timeout-seconds",
|
|
595
|
+
type=int,
|
|
596
|
+
default=10,
|
|
597
|
+
help="Timeout for --fetch-metadata.",
|
|
598
|
+
)
|
|
599
|
+
_add_generated_at_arg(pr_lifecycle_parser, artifact="the lifecycle projection")
|
|
600
|
+
pr_lifecycle_parser.add_argument(
|
|
601
|
+
"--goal-id",
|
|
602
|
+
default=None,
|
|
603
|
+
help="Goal id used for the default issue_fix domain-state ledger path.",
|
|
604
|
+
)
|
|
605
|
+
pr_lifecycle_parser.add_argument(
|
|
606
|
+
"--project",
|
|
607
|
+
default=".",
|
|
608
|
+
help="Project root for the default issue_fix domain-state ledger path.",
|
|
609
|
+
)
|
|
610
|
+
pr_lifecycle_parser.add_argument(
|
|
611
|
+
"--ledger-path",
|
|
612
|
+
default=None,
|
|
613
|
+
help="Optional local JSONL ledger path. Overrides the default domain-state path.",
|
|
614
|
+
)
|
|
615
|
+
pr_lifecycle_parser.add_argument(
|
|
616
|
+
"--no-write-domain-state",
|
|
617
|
+
action="store_true",
|
|
618
|
+
help=(
|
|
619
|
+
"Keep the PR lifecycle command preview-only even when --goal-id or "
|
|
620
|
+
"--ledger-path is present."
|
|
621
|
+
),
|
|
622
|
+
)
|
|
623
|
+
pr_lifecycle_parser.add_argument(
|
|
624
|
+
"--execute-transition",
|
|
625
|
+
action="store_true",
|
|
626
|
+
help=(
|
|
627
|
+
"Write the lifecycle transition and reconcile grouped monitors in "
|
|
628
|
+
"the existing LoopX todo state. Requires --goal-id, --claimed-by, "
|
|
629
|
+
"and a registry."
|
|
630
|
+
),
|
|
631
|
+
)
|
|
632
|
+
pr_lifecycle_parser.add_argument(
|
|
633
|
+
"--claimed-by",
|
|
634
|
+
default=None,
|
|
635
|
+
help=(
|
|
636
|
+
"Registered agent that claims an actionable patch successor or is blocked "
|
|
637
|
+
"by the generated concrete user gate."
|
|
638
|
+
),
|
|
639
|
+
)
|
|
640
|
+
pr_lifecycle_parser.add_argument(
|
|
641
|
+
"--monitor-cadence",
|
|
642
|
+
default=DEFAULT_ISSUE_FIX_MONITOR_CADENCE,
|
|
643
|
+
help=(
|
|
644
|
+
"Cadence for grouped PR lifecycle continuous monitors materialized "
|
|
645
|
+
"by --execute-transition (default: 30m)."
|
|
646
|
+
),
|
|
647
|
+
)
|
|
648
|
+
pr_gate_reconcile_cli.register_pr_gate_reconciliation_command(issue_fix_sub)
|
|
649
|
+
outcome_parser = issue_fix_sub.add_parser(
|
|
650
|
+
"outcome",
|
|
651
|
+
help=(
|
|
652
|
+
"Compose one public-safe issue-fix status/output projection from "
|
|
653
|
+
"existing feasibility and optional PR lifecycle state."
|
|
654
|
+
),
|
|
655
|
+
)
|
|
656
|
+
add_subcommand_format(outcome_parser)
|
|
657
|
+
outcome_parser.add_argument("--goal-id", required=True)
|
|
658
|
+
outcome_parser.add_argument("--project", default=".")
|
|
659
|
+
outcome_parser.add_argument("--repo", required=True)
|
|
660
|
+
outcome_parser.add_argument("--issue-ref", required=True)
|
|
661
|
+
outcome_parser.add_argument(
|
|
662
|
+
"--pr-ref",
|
|
663
|
+
help="Optional PR ref linked to this issue, such as pull_456.",
|
|
664
|
+
)
|
|
665
|
+
outcome_parser.add_argument(
|
|
666
|
+
"--feasibility-json",
|
|
667
|
+
help="Optional issue_fix_feasibility_v0 JSON object; defaults to domain state.",
|
|
668
|
+
)
|
|
669
|
+
outcome_parser.add_argument(
|
|
670
|
+
"--pr-lifecycle-json",
|
|
671
|
+
help=(
|
|
672
|
+
"Optional issue_fix_pr_lifecycle_monitor_v0 JSON object; defaults "
|
|
673
|
+
"to domain state when --pr-ref is present."
|
|
674
|
+
),
|
|
675
|
+
)
|
|
676
|
+
outcome_parser.add_argument(
|
|
677
|
+
"--delivery-evidence-json",
|
|
678
|
+
help=(
|
|
679
|
+
"Optional issue_fix_delivery_evidence_input_v0 JSON with explicit "
|
|
680
|
+
"validation status, repo-relative changed files, commit ref, outputs, and risks."
|
|
681
|
+
),
|
|
682
|
+
)
|
|
683
|
+
outcome_parser.add_argument(
|
|
684
|
+
"--write-delivery-evidence",
|
|
685
|
+
action="store_true",
|
|
686
|
+
help=(
|
|
687
|
+
"Validate and write compact delivery evidence into the selected "
|
|
688
|
+
"existing feasibility row so default outcome and Kanban sync retain it."
|
|
689
|
+
),
|
|
690
|
+
)
|
|
691
|
+
outcome_parser.add_argument(
|
|
692
|
+
"--repository-memory-provider-json",
|
|
693
|
+
default=None,
|
|
694
|
+
help=(
|
|
695
|
+
"Local-private issue_fix_repository_memory_provider_config_v0 used "
|
|
696
|
+
"only when --write-repository-memory is explicit. Defaults to "
|
|
697
|
+
"LOOPX_ISSUE_FIX_REPOSITORY_MEMORY_PROVIDER_CONFIG."
|
|
698
|
+
),
|
|
699
|
+
)
|
|
700
|
+
outcome_parser.add_argument(
|
|
701
|
+
"--write-repository-memory",
|
|
702
|
+
action="store_true",
|
|
703
|
+
help=(
|
|
704
|
+
"After passed validation and completed delivery, write one distilled "
|
|
705
|
+
"public outcome through an owner-enabled, revision-scoped provider. "
|
|
706
|
+
"No transcript or tool-result capture is performed."
|
|
707
|
+
),
|
|
708
|
+
)
|
|
709
|
+
outcome_parser.add_argument(
|
|
710
|
+
"--repo-path",
|
|
711
|
+
default=None,
|
|
712
|
+
help=(
|
|
713
|
+
"Caller-approved git checkout used to prove delivery commit identity "
|
|
714
|
+
"before evidence writeback or repository-memory publication. "
|
|
715
|
+
"The path and raw git output are never recorded."
|
|
716
|
+
),
|
|
717
|
+
)
|
|
718
|
+
outcome_parser.add_argument(
|
|
719
|
+
"--repository-ref",
|
|
720
|
+
default=None,
|
|
721
|
+
help=(
|
|
722
|
+
"Full recoverable git ref (refs/heads, refs/remotes, or refs/tags) that "
|
|
723
|
+
"must resolve exactly to the pinned repository revision when recording "
|
|
724
|
+
"passed or completed commit evidence."
|
|
725
|
+
),
|
|
726
|
+
)
|
|
727
|
+
outcome_parser.add_argument(
|
|
728
|
+
"--agent-id",
|
|
729
|
+
help="Optional registered agent id projected as the case owner.",
|
|
730
|
+
)
|
|
731
|
+
_add_generated_at_arg(outcome_parser, artifact="the read model")
|
|
732
|
+
metrics_parser = issue_fix_sub.add_parser(
|
|
733
|
+
"metrics",
|
|
734
|
+
help=(
|
|
735
|
+
"Compose a read-only baseline, attributable output inventory, repository "
|
|
736
|
+
"delta, and missing-data projection from existing issue-fix domain state."
|
|
737
|
+
),
|
|
738
|
+
)
|
|
739
|
+
add_subcommand_format(metrics_parser)
|
|
740
|
+
metrics_parser.add_argument("--goal-id", required=True)
|
|
741
|
+
metrics_parser.add_argument("--project", default=".")
|
|
742
|
+
metrics_parser.add_argument("--repo", required=True)
|
|
743
|
+
metrics_parser.add_argument(
|
|
744
|
+
"--repository-baseline-json",
|
|
745
|
+
required=True,
|
|
746
|
+
help="Public-safe issue_fix_repository_reporting_snapshot_v0 at period start.",
|
|
747
|
+
)
|
|
748
|
+
metrics_parser.add_argument(
|
|
749
|
+
"--repository-current-json",
|
|
750
|
+
required=True,
|
|
751
|
+
help=(
|
|
752
|
+
"Public-safe issue_fix_repository_reporting_snapshot_v0 at current time, "
|
|
753
|
+
"including flow_since_baseline."
|
|
754
|
+
),
|
|
755
|
+
)
|
|
756
|
+
metrics_parser.add_argument(
|
|
757
|
+
"--supplement-json",
|
|
758
|
+
default=None,
|
|
759
|
+
help=(
|
|
760
|
+
"Optional public-safe issue_fix_metrics_supplement_v0 for autonomy, "
|
|
761
|
+
"first-push CI, memory, and capability-delta counts."
|
|
762
|
+
),
|
|
763
|
+
)
|
|
764
|
+
metrics_parser.add_argument(
|
|
765
|
+
"--feasibility-ledger",
|
|
766
|
+
default=None,
|
|
767
|
+
help="Optional feasibility JSONL override; defaults to goal domain state.",
|
|
768
|
+
)
|
|
769
|
+
metrics_parser.add_argument(
|
|
770
|
+
"--pr-lifecycle-ledger",
|
|
771
|
+
default=None,
|
|
772
|
+
help="Optional PR lifecycle JSONL override; defaults to goal domain state.",
|
|
773
|
+
)
|
|
774
|
+
_add_generated_at_arg(metrics_parser, artifact="the metrics projection")
|
|
775
|
+
register_issue_fix_metrics_supplement_command(
|
|
776
|
+
issue_fix_sub,
|
|
777
|
+
add_subcommand_format=add_subcommand_format,
|
|
778
|
+
add_generated_at_arg=_add_generated_at_arg,
|
|
779
|
+
)
|
|
780
|
+
snapshot_parser = issue_fix_sub.add_parser(
|
|
781
|
+
"repository-snapshot",
|
|
782
|
+
help=(
|
|
783
|
+
"Collect a compact public GitHub repository snapshot for issue-fix "
|
|
784
|
+
"metrics and optionally retain one material snapshot per day."
|
|
785
|
+
),
|
|
786
|
+
)
|
|
787
|
+
add_subcommand_format(snapshot_parser)
|
|
788
|
+
snapshot_parser.add_argument("--goal-id", required=True)
|
|
789
|
+
snapshot_parser.add_argument("--project", default=".")
|
|
790
|
+
snapshot_parser.add_argument("--repo", required=True)
|
|
791
|
+
snapshot_parser.add_argument("--repository-baseline-json", required=True)
|
|
792
|
+
snapshot_parser.add_argument(
|
|
793
|
+
"--supplement-json",
|
|
794
|
+
default=None,
|
|
795
|
+
help=(
|
|
796
|
+
"Optional public-safe issue_fix_metrics_supplement_v0 whose "
|
|
797
|
+
"issue-close activity refs must be included in current-state collection."
|
|
798
|
+
),
|
|
799
|
+
)
|
|
800
|
+
snapshot_parser.add_argument(
|
|
801
|
+
"--fetch-public-github",
|
|
802
|
+
action="store_true",
|
|
803
|
+
help="Explicitly read bounded public repository metadata through gh.",
|
|
804
|
+
)
|
|
805
|
+
snapshot_parser.add_argument(
|
|
806
|
+
"--retain-material-snapshot",
|
|
807
|
+
action="store_true",
|
|
808
|
+
help=(
|
|
809
|
+
"Write only a material daily change into the existing issue_fix "
|
|
810
|
+
"domain-state stream."
|
|
811
|
+
),
|
|
812
|
+
)
|
|
813
|
+
snapshot_parser.add_argument("--fetch-timeout-seconds", type=int, default=30)
|
|
814
|
+
_add_generated_at_arg(snapshot_parser, artifact="the repository snapshot")
|
|
815
|
+
register_issue_fix_reviewer_commands(
|
|
816
|
+
issue_fix_sub,
|
|
817
|
+
add_subcommand_format=add_subcommand_format,
|
|
818
|
+
add_generated_at_arg=_add_generated_at_arg,
|
|
819
|
+
)
|
|
820
|
+
acceptance_parser = issue_fix_sub.add_parser(
|
|
821
|
+
"acceptance-fixture",
|
|
822
|
+
help=(
|
|
823
|
+
"Run a deterministic fix loop: failing repro, minimal patch, "
|
|
824
|
+
"focused validation, and PR-review-ready artifact."
|
|
825
|
+
),
|
|
826
|
+
)
|
|
827
|
+
add_subcommand_format(acceptance_parser)
|
|
828
|
+
acceptance_parser.add_argument(
|
|
829
|
+
"--repo",
|
|
830
|
+
default="public_repo_fixture",
|
|
831
|
+
help="Public-safe repository label for the issue metadata fixture.",
|
|
832
|
+
)
|
|
833
|
+
acceptance_parser.add_argument(
|
|
834
|
+
"--issue-ref",
|
|
835
|
+
default="issue_123_public_metadata_fixture",
|
|
836
|
+
help="Public-safe issue or PR reference label for the fixture.",
|
|
837
|
+
)
|
|
838
|
+
acceptance_parser.add_argument(
|
|
839
|
+
"--url",
|
|
840
|
+
default=None,
|
|
841
|
+
help="Optional public GitHub issue or PR URL for metadata parsing.",
|
|
842
|
+
)
|
|
843
|
+
_add_generated_at_arg(acceptance_parser, artifact="the fixture artifact")
|
|
844
|
+
branch_parser = issue_fix_sub.add_parser(
|
|
845
|
+
"repo-branch-fixture",
|
|
846
|
+
help=(
|
|
847
|
+
"Run the fix loop through a temporary git repo issue branch: "
|
|
848
|
+
"branch, repro, patch, validation, and PR evidence."
|
|
849
|
+
),
|
|
850
|
+
)
|
|
851
|
+
add_subcommand_format(branch_parser)
|
|
852
|
+
branch_parser.add_argument(
|
|
853
|
+
"--repo",
|
|
854
|
+
default="public_repo_fixture",
|
|
855
|
+
help="Public-safe repository label for the issue metadata fixture.",
|
|
856
|
+
)
|
|
857
|
+
branch_parser.add_argument(
|
|
858
|
+
"--issue-ref",
|
|
859
|
+
default="issue_123_public_metadata_fixture",
|
|
860
|
+
help="Public-safe issue or PR reference label for the fixture.",
|
|
861
|
+
)
|
|
862
|
+
branch_parser.add_argument(
|
|
863
|
+
"--url",
|
|
864
|
+
default=None,
|
|
865
|
+
help="Optional public GitHub issue or PR URL for metadata parsing.",
|
|
866
|
+
)
|
|
867
|
+
_add_generated_at_arg(branch_parser, artifact="the fixture artifact")
|
|
868
|
+
caller_branch_parser = issue_fix_sub.add_parser(
|
|
869
|
+
"caller-repo-branch",
|
|
870
|
+
help=(
|
|
871
|
+
"Prepare or execute an explicitly approved local repo issue branch "
|
|
872
|
+
"workflow without external comments, PR creation, or merge."
|
|
873
|
+
),
|
|
874
|
+
)
|
|
875
|
+
add_subcommand_format(caller_branch_parser)
|
|
876
|
+
caller_branch_parser.add_argument(
|
|
877
|
+
"--repo-path",
|
|
878
|
+
required=True,
|
|
879
|
+
help=(
|
|
880
|
+
"Caller-approved local git repository path. The public artifact records "
|
|
881
|
+
"only a repo label, never this path."
|
|
882
|
+
),
|
|
883
|
+
)
|
|
884
|
+
caller_branch_parser.add_argument(
|
|
885
|
+
"--repo",
|
|
886
|
+
default="approved_local_repo",
|
|
887
|
+
help="Public-safe repository label when no URL-derived repo is provided.",
|
|
888
|
+
)
|
|
889
|
+
caller_branch_parser.add_argument(
|
|
890
|
+
"--issue-ref",
|
|
891
|
+
default="issue_123_public_metadata",
|
|
892
|
+
help="Public-safe issue or PR reference label.",
|
|
893
|
+
)
|
|
894
|
+
caller_branch_parser.add_argument(
|
|
895
|
+
"--url",
|
|
896
|
+
default=None,
|
|
897
|
+
help="Optional public GitHub issue or PR URL used only for compact metadata.",
|
|
898
|
+
)
|
|
899
|
+
caller_branch_parser.add_argument(
|
|
900
|
+
"--base-branch",
|
|
901
|
+
default="main",
|
|
902
|
+
help="Approved local base branch used when creating a new issue branch.",
|
|
903
|
+
)
|
|
904
|
+
caller_branch_parser.add_argument(
|
|
905
|
+
"--issue-branch",
|
|
906
|
+
default=None,
|
|
907
|
+
help="Optional issue branch to create or claim. Defaults to codex/<issue>-fix.",
|
|
908
|
+
)
|
|
909
|
+
caller_branch_parser.add_argument(
|
|
910
|
+
"--validation-command",
|
|
911
|
+
default=None,
|
|
912
|
+
help="Caller-declared validation command. Required with --execute.",
|
|
913
|
+
)
|
|
914
|
+
caller_branch_parser.add_argument(
|
|
915
|
+
"--validation-label",
|
|
916
|
+
default="caller-declared validation",
|
|
917
|
+
help="Public-safe validation label stored in the artifact instead of raw command text.",
|
|
918
|
+
)
|
|
919
|
+
caller_branch_parser.add_argument(
|
|
920
|
+
"--timeout-seconds",
|
|
921
|
+
type=int,
|
|
922
|
+
default=60,
|
|
923
|
+
help="Validation timeout in seconds.",
|
|
924
|
+
)
|
|
925
|
+
caller_branch_parser.add_argument(
|
|
926
|
+
"--execute",
|
|
927
|
+
action="store_true",
|
|
928
|
+
help=(
|
|
929
|
+
"Actually inspect the approved repo, create or claim the issue branch, "
|
|
930
|
+
"and run the caller-declared validation."
|
|
931
|
+
),
|
|
932
|
+
)
|
|
933
|
+
_add_generated_at_arg(caller_branch_parser, artifact="the artifact")
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
def handle_issue_fix_command(
|
|
937
|
+
args: argparse.Namespace,
|
|
938
|
+
*,
|
|
939
|
+
registry_path: Path | None = None,
|
|
940
|
+
runtime_root_arg: str | None = None,
|
|
941
|
+
reviewer_provider_hooks_factory: (
|
|
942
|
+
IssueFixReviewerProviderHooksFactory | None
|
|
943
|
+
) = None,
|
|
944
|
+
output_format: FormatSelector,
|
|
945
|
+
print_payload: PrintPayload,
|
|
946
|
+
) -> int:
|
|
947
|
+
try:
|
|
948
|
+
invocation_at = now_utc_iso()
|
|
949
|
+
generated_at = str(args.generated_at or invocation_at).strip()
|
|
950
|
+
reviewer_result = handle_issue_fix_reviewer_command(
|
|
951
|
+
args,
|
|
952
|
+
registry_path=registry_path,
|
|
953
|
+
generated_at=generated_at,
|
|
954
|
+
delivery_observed_at=invocation_at,
|
|
955
|
+
reviewer_provider_hooks_factory=reviewer_provider_hooks_factory,
|
|
956
|
+
)
|
|
957
|
+
if reviewer_result is not None:
|
|
958
|
+
payload, renderer = reviewer_result
|
|
959
|
+
elif args.issue_fix_command == "repository-memory-sync":
|
|
960
|
+
provider_path = (
|
|
961
|
+
args.repository_memory_provider_json
|
|
962
|
+
or default_repository_memory_provider_config_path()
|
|
963
|
+
)
|
|
964
|
+
if not provider_path:
|
|
965
|
+
raise ValueError("repository memory provider config is required")
|
|
966
|
+
if provider_path == "-" and args.repository_context_json == "-":
|
|
967
|
+
raise ValueError("only one JSON input may read from stdin")
|
|
968
|
+
repository_context_input = _load_json_object(args.repository_context_json)
|
|
969
|
+
revision = str(
|
|
970
|
+
repository_context_input.get("repository_revision") or ""
|
|
971
|
+
).strip()
|
|
972
|
+
if not revision:
|
|
973
|
+
raise ValueError("repository context must pin repository_revision")
|
|
974
|
+
payload = sync_issue_fix_repository_memory(
|
|
975
|
+
config=_load_json_object(provider_path),
|
|
976
|
+
repo_path=args.repo_path,
|
|
977
|
+
repository_revision=revision,
|
|
978
|
+
references=args.resource_reference,
|
|
979
|
+
observed_at=generated_at,
|
|
980
|
+
execute=args.execute,
|
|
981
|
+
)
|
|
982
|
+
renderer = render_issue_fix_repository_memory_sync_markdown
|
|
983
|
+
elif args.issue_fix_command == "promote-discovered-issue":
|
|
984
|
+
boundary_authority_scopes, boundary_authority_resolved = (
|
|
985
|
+
_goal_boundary_authority_projection(
|
|
986
|
+
registry_path=registry_path,
|
|
987
|
+
goal_id=args.goal_id,
|
|
988
|
+
)
|
|
989
|
+
)
|
|
990
|
+
payload = build_discovered_issue_promotion_from_cli_args(
|
|
991
|
+
args,
|
|
992
|
+
load_json_object=_load_json_object,
|
|
993
|
+
boundary_authority_scopes=boundary_authority_scopes,
|
|
994
|
+
boundary_authority_resolved=boundary_authority_resolved,
|
|
995
|
+
generated_at=generated_at,
|
|
996
|
+
)
|
|
997
|
+
renderer = render_issue_fix_discovered_issue_promotion_markdown
|
|
998
|
+
elif args.issue_fix_command == "workflow-plan":
|
|
999
|
+
if args.fetch_metadata and args.metadata_json:
|
|
1000
|
+
raise ValueError(
|
|
1001
|
+
"--fetch-metadata cannot be combined with --metadata-json"
|
|
1002
|
+
)
|
|
1003
|
+
if args.fetch_candidate_evidence and args.candidate_preflight_json:
|
|
1004
|
+
raise ValueError(
|
|
1005
|
+
"--fetch-candidate-evidence cannot be combined with "
|
|
1006
|
+
"--candidate-preflight-json"
|
|
1007
|
+
)
|
|
1008
|
+
if args.candidate_resolution_json and not args.fetch_candidate_evidence:
|
|
1009
|
+
raise ValueError(
|
|
1010
|
+
"--candidate-resolution-json requires --fetch-candidate-evidence"
|
|
1011
|
+
)
|
|
1012
|
+
provider_path = args.repository_memory_provider_json or (
|
|
1013
|
+
None
|
|
1014
|
+
if args.repository_memory_json
|
|
1015
|
+
else default_repository_memory_provider_config_path()
|
|
1016
|
+
)
|
|
1017
|
+
stdin_inputs = [
|
|
1018
|
+
value
|
|
1019
|
+
for value in (
|
|
1020
|
+
args.metadata_json,
|
|
1021
|
+
args.repository_context_json,
|
|
1022
|
+
args.repository_memory_json,
|
|
1023
|
+
args.candidate_preflight_json,
|
|
1024
|
+
args.candidate_resolution_json,
|
|
1025
|
+
provider_path,
|
|
1026
|
+
)
|
|
1027
|
+
if value == "-"
|
|
1028
|
+
]
|
|
1029
|
+
if len(stdin_inputs) > 1:
|
|
1030
|
+
raise ValueError("only one JSON input may read from stdin")
|
|
1031
|
+
repository_context_input = (
|
|
1032
|
+
_load_json_object(args.repository_context_json)
|
|
1033
|
+
if args.repository_context_json
|
|
1034
|
+
else None
|
|
1035
|
+
)
|
|
1036
|
+
if args.fetch_candidate_evidence:
|
|
1037
|
+
reference = normalise_github_issue_reference(
|
|
1038
|
+
repo=args.repo,
|
|
1039
|
+
issue_ref=args.issue_ref,
|
|
1040
|
+
url=args.url,
|
|
1041
|
+
)
|
|
1042
|
+
if reference["kind"] != "issue":
|
|
1043
|
+
raise ValueError(
|
|
1044
|
+
"--fetch-candidate-evidence requires a GitHub issue"
|
|
1045
|
+
)
|
|
1046
|
+
candidate_preflight_input = (
|
|
1047
|
+
collect_public_github_candidate_preflight_input(
|
|
1048
|
+
repo=str(reference["repo"]),
|
|
1049
|
+
issue_ref=str(reference["issue_ref"]),
|
|
1050
|
+
generated_at=generated_at,
|
|
1051
|
+
timeout_seconds=args.candidate_evidence_timeout_seconds,
|
|
1052
|
+
)
|
|
1053
|
+
)
|
|
1054
|
+
if args.candidate_resolution_json:
|
|
1055
|
+
candidate_preflight_input["candidate_resolution"] = (
|
|
1056
|
+
_load_json_object(args.candidate_resolution_json)
|
|
1057
|
+
)
|
|
1058
|
+
else:
|
|
1059
|
+
candidate_preflight_input = (
|
|
1060
|
+
_load_json_object(args.candidate_preflight_json)
|
|
1061
|
+
if args.candidate_preflight_json
|
|
1062
|
+
else None
|
|
1063
|
+
)
|
|
1064
|
+
repository_memory_input = _configured_repository_memory_input(
|
|
1065
|
+
provider_path=provider_path,
|
|
1066
|
+
raw_memory_path=args.repository_memory_json,
|
|
1067
|
+
repo_path=args.repo_path,
|
|
1068
|
+
repository_context_input=repository_context_input,
|
|
1069
|
+
repo=args.repo,
|
|
1070
|
+
issue_ref=args.issue_ref,
|
|
1071
|
+
query=args.repository_memory_query,
|
|
1072
|
+
supports=args.repository_memory_support,
|
|
1073
|
+
validation_label=args.validation_label,
|
|
1074
|
+
observed_at=generated_at,
|
|
1075
|
+
)
|
|
1076
|
+
payload = build_issue_fix_workflow_plan_packet(
|
|
1077
|
+
repo=args.repo,
|
|
1078
|
+
issue_ref=args.issue_ref,
|
|
1079
|
+
url=args.url,
|
|
1080
|
+
provider_payload=_load_json_object(args.metadata_json)
|
|
1081
|
+
if args.metadata_json
|
|
1082
|
+
else None,
|
|
1083
|
+
fetch_metadata=args.fetch_metadata,
|
|
1084
|
+
fetch_timeout_seconds=args.fetch_timeout_seconds,
|
|
1085
|
+
repo_path=args.repo_path,
|
|
1086
|
+
base_branch=args.base_branch,
|
|
1087
|
+
issue_branch=args.issue_branch,
|
|
1088
|
+
validation_label=args.validation_label,
|
|
1089
|
+
repository_context_input=repository_context_input,
|
|
1090
|
+
repository_memory_input=repository_memory_input,
|
|
1091
|
+
candidate_preflight_input=candidate_preflight_input,
|
|
1092
|
+
generated_at=generated_at,
|
|
1093
|
+
)
|
|
1094
|
+
candidate_preflight = payload.get("candidate_preflight")
|
|
1095
|
+
should_write_candidate_preflight = bool(
|
|
1096
|
+
not args.no_write_domain_state
|
|
1097
|
+
and (args.goal_id or args.candidate_preflight_ledger_path)
|
|
1098
|
+
)
|
|
1099
|
+
if should_write_candidate_preflight:
|
|
1100
|
+
if not isinstance(candidate_preflight, dict):
|
|
1101
|
+
raise ValueError(
|
|
1102
|
+
"workflow plan omitted the candidate preflight receipt"
|
|
1103
|
+
)
|
|
1104
|
+
candidate_preflight_ledger_path = (
|
|
1105
|
+
Path(args.candidate_preflight_ledger_path).expanduser()
|
|
1106
|
+
if args.candidate_preflight_ledger_path
|
|
1107
|
+
else default_issue_fix_candidate_preflight_ledger_path(
|
|
1108
|
+
project=args.project,
|
|
1109
|
+
goal_id=args.goal_id,
|
|
1110
|
+
)
|
|
1111
|
+
)
|
|
1112
|
+
upsert_issue_fix_candidate_preflight_ledger_jsonl(
|
|
1113
|
+
candidate_preflight_ledger_path,
|
|
1114
|
+
candidate_preflight,
|
|
1115
|
+
)
|
|
1116
|
+
elif isinstance(candidate_preflight, dict):
|
|
1117
|
+
domain_state = candidate_preflight.get("domain_state_projection")
|
|
1118
|
+
if isinstance(domain_state, dict):
|
|
1119
|
+
domain_state["write_skipped_reason"] = (
|
|
1120
|
+
"explicitly_disabled"
|
|
1121
|
+
if args.no_write_domain_state
|
|
1122
|
+
else "goal_id_or_ledger_path_missing"
|
|
1123
|
+
)
|
|
1124
|
+
renderer = render_issue_fix_workflow_plan_markdown
|
|
1125
|
+
elif args.issue_fix_command == "feasibility":
|
|
1126
|
+
provider_path = args.repository_memory_provider_json or (
|
|
1127
|
+
None
|
|
1128
|
+
if args.repository_memory_json
|
|
1129
|
+
else default_repository_memory_provider_config_path()
|
|
1130
|
+
)
|
|
1131
|
+
if (
|
|
1132
|
+
args.repository_context_json == "-"
|
|
1133
|
+
and args.repository_memory_json == "-"
|
|
1134
|
+
):
|
|
1135
|
+
raise ValueError("only one JSON input may read from stdin")
|
|
1136
|
+
if provider_path == "-" and (
|
|
1137
|
+
args.repository_context_json == "-"
|
|
1138
|
+
or args.repository_memory_json == "-"
|
|
1139
|
+
):
|
|
1140
|
+
raise ValueError("only one JSON input may read from stdin")
|
|
1141
|
+
repository_context_input = (
|
|
1142
|
+
_load_json_object(args.repository_context_json)
|
|
1143
|
+
if args.repository_context_json
|
|
1144
|
+
else None
|
|
1145
|
+
)
|
|
1146
|
+
repository_memory_input = _configured_repository_memory_input(
|
|
1147
|
+
provider_path=provider_path,
|
|
1148
|
+
raw_memory_path=args.repository_memory_json,
|
|
1149
|
+
repo_path=args.repo_path,
|
|
1150
|
+
repository_context_input=repository_context_input,
|
|
1151
|
+
repo=args.repo,
|
|
1152
|
+
issue_ref=args.issue_ref,
|
|
1153
|
+
query=args.repository_memory_query,
|
|
1154
|
+
supports=args.repository_memory_support,
|
|
1155
|
+
validation_label=args.validation_label,
|
|
1156
|
+
observed_at=generated_at,
|
|
1157
|
+
)
|
|
1158
|
+
boundary_authority_scopes, boundary_authority_resolved = (
|
|
1159
|
+
_goal_boundary_authority_projection(
|
|
1160
|
+
registry_path=registry_path,
|
|
1161
|
+
goal_id=args.goal_id,
|
|
1162
|
+
)
|
|
1163
|
+
)
|
|
1164
|
+
payload = build_issue_fix_feasibility_packet(
|
|
1165
|
+
repo=args.repo,
|
|
1166
|
+
issue_ref=args.issue_ref,
|
|
1167
|
+
url=args.url,
|
|
1168
|
+
reproduction_status=args.reproduction_status,
|
|
1169
|
+
scope_class=args.scope_class,
|
|
1170
|
+
reproduction_label=args.reproduction_label,
|
|
1171
|
+
validation_label=args.validation_label,
|
|
1172
|
+
comment_value=args.comment_value,
|
|
1173
|
+
repository_context_input=repository_context_input,
|
|
1174
|
+
repository_memory_input=repository_memory_input,
|
|
1175
|
+
boundary_authority_scopes=boundary_authority_scopes,
|
|
1176
|
+
boundary_authority_resolved=boundary_authority_resolved,
|
|
1177
|
+
generated_at=generated_at,
|
|
1178
|
+
)
|
|
1179
|
+
should_write_domain_state = bool(
|
|
1180
|
+
not args.no_write_domain_state and (args.goal_id or args.ledger_path)
|
|
1181
|
+
)
|
|
1182
|
+
if should_write_domain_state:
|
|
1183
|
+
ledger_path = (
|
|
1184
|
+
Path(args.ledger_path).expanduser()
|
|
1185
|
+
if args.ledger_path
|
|
1186
|
+
else default_issue_fix_feasibility_ledger_path(
|
|
1187
|
+
project=args.project,
|
|
1188
|
+
goal_id=args.goal_id,
|
|
1189
|
+
)
|
|
1190
|
+
)
|
|
1191
|
+
upsert_issue_fix_feasibility_ledger_jsonl(
|
|
1192
|
+
ledger_path,
|
|
1193
|
+
payload,
|
|
1194
|
+
)
|
|
1195
|
+
else:
|
|
1196
|
+
domain_state = payload.get("domain_state_projection")
|
|
1197
|
+
if isinstance(domain_state, dict) and not args.no_write_domain_state:
|
|
1198
|
+
domain_state["write_skipped_reason"] = (
|
|
1199
|
+
"goal_id_or_ledger_path_missing"
|
|
1200
|
+
)
|
|
1201
|
+
renderer = render_issue_fix_feasibility_markdown
|
|
1202
|
+
elif args.issue_fix_command in {
|
|
1203
|
+
"pr-gate-reconcile",
|
|
1204
|
+
"pr-review-ack",
|
|
1205
|
+
"pr-review-reconcile",
|
|
1206
|
+
"pr-review-reconcile-acked",
|
|
1207
|
+
}:
|
|
1208
|
+
if args.issue_fix_command == "pr-gate-reconcile":
|
|
1209
|
+
payload = (
|
|
1210
|
+
pr_gate_reconcile_cli.build_pr_gate_reconciliation_from_args(
|
|
1211
|
+
args, registry_path, runtime_root_arg, generated_at
|
|
1212
|
+
)
|
|
1213
|
+
)
|
|
1214
|
+
renderer = (
|
|
1215
|
+
pr_gate_reconcile_cli.render_issue_fix_pr_gate_reconciliation_markdown
|
|
1216
|
+
)
|
|
1217
|
+
elif args.issue_fix_command == "pr-review-ack":
|
|
1218
|
+
payload = pr_gate_reconcile_cli.build_pr_review_ack_from_args(
|
|
1219
|
+
args, registry_path, runtime_root_arg, generated_at
|
|
1220
|
+
)
|
|
1221
|
+
renderer = (
|
|
1222
|
+
pr_gate_reconcile_cli.render_issue_fix_pr_review_ack_markdown
|
|
1223
|
+
)
|
|
1224
|
+
elif args.issue_fix_command == "pr-review-reconcile-acked":
|
|
1225
|
+
payload = (
|
|
1226
|
+
pr_gate_reconcile_cli.build_acked_pr_review_reconciliation_from_args(
|
|
1227
|
+
args, registry_path, runtime_root_arg, generated_at
|
|
1228
|
+
)
|
|
1229
|
+
)
|
|
1230
|
+
renderer = (
|
|
1231
|
+
pr_gate_reconcile_cli.render_issue_fix_acked_pr_review_reconciliation_markdown
|
|
1232
|
+
)
|
|
1233
|
+
else:
|
|
1234
|
+
payload = (
|
|
1235
|
+
pr_gate_reconcile_cli.build_pr_review_reconciliation_from_args(
|
|
1236
|
+
args, registry_path, runtime_root_arg, generated_at
|
|
1237
|
+
)
|
|
1238
|
+
)
|
|
1239
|
+
renderer = (
|
|
1240
|
+
pr_gate_reconcile_cli.render_issue_fix_pr_review_reconciliation_markdown
|
|
1241
|
+
)
|
|
1242
|
+
elif args.issue_fix_command == "pr-lifecycle":
|
|
1243
|
+
if args.fetch_metadata and args.metadata_json:
|
|
1244
|
+
raise ValueError(
|
|
1245
|
+
"--fetch-metadata cannot be combined with --metadata-json"
|
|
1246
|
+
)
|
|
1247
|
+
fetch_metadata = bool(
|
|
1248
|
+
args.fetch_metadata
|
|
1249
|
+
or (args.execute_transition and args.url and not args.metadata_json)
|
|
1250
|
+
)
|
|
1251
|
+
if args.execute_transition and args.no_write_domain_state:
|
|
1252
|
+
raise ValueError(
|
|
1253
|
+
"--execute-transition cannot be combined with --no-write-domain-state"
|
|
1254
|
+
)
|
|
1255
|
+
if args.execute_transition and registry_path is None:
|
|
1256
|
+
raise ValueError("--execute-transition requires a LoopX registry")
|
|
1257
|
+
if args.execute_transition and not args.goal_id:
|
|
1258
|
+
raise ValueError("--execute-transition requires --goal-id")
|
|
1259
|
+
if args.execute_transition and not args.claimed_by:
|
|
1260
|
+
raise ValueError("--execute-transition requires --claimed-by")
|
|
1261
|
+
payload = build_issue_fix_pr_lifecycle_monitor_packet(
|
|
1262
|
+
repo=args.repo,
|
|
1263
|
+
pr_ref=args.pr_ref,
|
|
1264
|
+
issue_ref=args.issue_ref,
|
|
1265
|
+
url=args.url,
|
|
1266
|
+
provider_payload=_load_json_object(args.metadata_json)
|
|
1267
|
+
if args.metadata_json
|
|
1268
|
+
else None,
|
|
1269
|
+
fetch_metadata=fetch_metadata,
|
|
1270
|
+
fetch_timeout_seconds=args.fetch_timeout_seconds,
|
|
1271
|
+
maintainer_correction_input=(
|
|
1272
|
+
_load_json_object(args.maintainer_correction_json)
|
|
1273
|
+
if args.maintainer_correction_json
|
|
1274
|
+
else None
|
|
1275
|
+
),
|
|
1276
|
+
generated_at=generated_at,
|
|
1277
|
+
)
|
|
1278
|
+
should_write_domain_state = bool(
|
|
1279
|
+
not args.no_write_domain_state and (args.goal_id or args.ledger_path)
|
|
1280
|
+
)
|
|
1281
|
+
if should_write_domain_state:
|
|
1282
|
+
ledger_path = (
|
|
1283
|
+
Path(args.ledger_path).expanduser()
|
|
1284
|
+
if args.ledger_path
|
|
1285
|
+
else default_issue_fix_domain_state_ledger_path(
|
|
1286
|
+
project=args.project,
|
|
1287
|
+
goal_id=args.goal_id,
|
|
1288
|
+
)
|
|
1289
|
+
)
|
|
1290
|
+
upsert_issue_fix_pr_lifecycle_ledger_jsonl(
|
|
1291
|
+
ledger_path,
|
|
1292
|
+
payload,
|
|
1293
|
+
)
|
|
1294
|
+
observation = payload.get("observation")
|
|
1295
|
+
if (
|
|
1296
|
+
args.goal_id
|
|
1297
|
+
and isinstance(observation, dict)
|
|
1298
|
+
and str(observation.get("state") or "").upper() == "MERGED"
|
|
1299
|
+
):
|
|
1300
|
+
payload["rollout_event"] = append_pr_merge_rollout_event(
|
|
1301
|
+
payload=payload,
|
|
1302
|
+
goal_id=args.goal_id,
|
|
1303
|
+
registry_path=registry_path,
|
|
1304
|
+
runtime_root_arg=runtime_root_arg,
|
|
1305
|
+
)
|
|
1306
|
+
else:
|
|
1307
|
+
domain_state = payload.get("domain_state_projection")
|
|
1308
|
+
if isinstance(domain_state, dict) and not args.no_write_domain_state:
|
|
1309
|
+
domain_state["write_skipped_reason"] = (
|
|
1310
|
+
"goal_id_or_ledger_path_missing"
|
|
1311
|
+
)
|
|
1312
|
+
transition = payload.get("transition")
|
|
1313
|
+
if args.execute_transition:
|
|
1314
|
+
if not isinstance(transition, dict):
|
|
1315
|
+
raise ValueError("PR lifecycle transition is missing")
|
|
1316
|
+
grouped_monitor_writeback = materialize_issue_fix_grouped_monitors(
|
|
1317
|
+
registry_path=registry_path,
|
|
1318
|
+
goal_id=args.goal_id,
|
|
1319
|
+
project=Path(args.project).expanduser(),
|
|
1320
|
+
ledger_path=ledger_path,
|
|
1321
|
+
claimed_by=args.claimed_by,
|
|
1322
|
+
cadence=args.monitor_cadence,
|
|
1323
|
+
generated_at=str(payload.get("generated_at") or generated_at),
|
|
1324
|
+
)
|
|
1325
|
+
payload["grouped_monitor_writeback"] = grouped_monitor_writeback
|
|
1326
|
+
grouped_monitor_projection = payload.get("grouped_monitor_projection")
|
|
1327
|
+
if isinstance(grouped_monitor_projection, dict):
|
|
1328
|
+
grouped_monitor_projection["todo_write_performed"] = bool(
|
|
1329
|
+
grouped_monitor_writeback.get("write_performed")
|
|
1330
|
+
)
|
|
1331
|
+
decision = str(transition.get("decision") or "")
|
|
1332
|
+
if decision in {"runnable_successor", "user_gate"}:
|
|
1333
|
+
role = str(transition.get("role") or "agent")
|
|
1334
|
+
todo_write = add_goal_todo(
|
|
1335
|
+
registry_path=registry_path,
|
|
1336
|
+
goal_id=args.goal_id,
|
|
1337
|
+
role=role,
|
|
1338
|
+
text=str(transition.get("text") or ""),
|
|
1339
|
+
task_class=str(
|
|
1340
|
+
transition.get("task_class") or "advancement_task"
|
|
1341
|
+
),
|
|
1342
|
+
action_kind=str(transition.get("action_kind") or ""),
|
|
1343
|
+
required_write_scopes=(
|
|
1344
|
+
list(transition.get("required_write_scopes") or [])
|
|
1345
|
+
if role == "agent"
|
|
1346
|
+
else None
|
|
1347
|
+
),
|
|
1348
|
+
claimed_by=args.claimed_by if role == "agent" else None,
|
|
1349
|
+
agent_id=args.claimed_by if role == "user" else None,
|
|
1350
|
+
project=Path(args.project).expanduser(),
|
|
1351
|
+
)
|
|
1352
|
+
todo_changed = bool(
|
|
1353
|
+
todo_write.get("added")
|
|
1354
|
+
or todo_write.get("metadata_updated")
|
|
1355
|
+
or todo_write.get("status_changed")
|
|
1356
|
+
)
|
|
1357
|
+
payload["todo_write"] = {
|
|
1358
|
+
"schema_version": "issue_fix_maintainer_correction_todo_write_v0",
|
|
1359
|
+
"write_performed": todo_changed,
|
|
1360
|
+
"already_exists": bool(todo_write.get("already_exists")),
|
|
1361
|
+
"todo_id": todo_write.get("todo_id"),
|
|
1362
|
+
"role": todo_write.get("role"),
|
|
1363
|
+
"claimed_by": todo_write.get("claimed_by"),
|
|
1364
|
+
"blocks_agent": todo_write.get("blocks_agent"),
|
|
1365
|
+
"path_recorded": False,
|
|
1366
|
+
}
|
|
1367
|
+
payload["todo_write_performed"] = todo_changed
|
|
1368
|
+
writeback_contract = payload.get("writeback_contract")
|
|
1369
|
+
if isinstance(writeback_contract, dict):
|
|
1370
|
+
writeback_contract["todo_write_performed"] = bool(todo_changed)
|
|
1371
|
+
else:
|
|
1372
|
+
payload["todo_write"] = {
|
|
1373
|
+
"schema_version": "issue_fix_maintainer_correction_todo_write_v0",
|
|
1374
|
+
"write_performed": False,
|
|
1375
|
+
"already_exists": False,
|
|
1376
|
+
"skip_reason": (
|
|
1377
|
+
"unchanged_monitor_quiet"
|
|
1378
|
+
if decision == "monitor_continuation"
|
|
1379
|
+
else "terminal_or_no_followup"
|
|
1380
|
+
),
|
|
1381
|
+
"path_recorded": False,
|
|
1382
|
+
}
|
|
1383
|
+
grouped_write_performed = bool(
|
|
1384
|
+
grouped_monitor_writeback.get("write_performed")
|
|
1385
|
+
)
|
|
1386
|
+
transition_write_performed = bool(payload.get("todo_write_performed"))
|
|
1387
|
+
payload["todo_write_performed"] = bool(
|
|
1388
|
+
grouped_write_performed or transition_write_performed
|
|
1389
|
+
)
|
|
1390
|
+
if grouped_write_performed and not transition_write_performed:
|
|
1391
|
+
payload["todo_write"] = {
|
|
1392
|
+
"schema_version": "issue_fix_pr_lifecycle_todo_write_v1",
|
|
1393
|
+
"write_performed": True,
|
|
1394
|
+
"grouped_monitor_write_performed": True,
|
|
1395
|
+
"transition_write_performed": False,
|
|
1396
|
+
"path_recorded": False,
|
|
1397
|
+
}
|
|
1398
|
+
writeback_contract = payload.get("writeback_contract")
|
|
1399
|
+
if isinstance(writeback_contract, dict):
|
|
1400
|
+
writeback_contract["todo_write_performed"] = bool(
|
|
1401
|
+
payload["todo_write_performed"]
|
|
1402
|
+
)
|
|
1403
|
+
validation = validate_issue_fix_pr_lifecycle_monitor_packet(payload)
|
|
1404
|
+
payload["validation"] = validation
|
|
1405
|
+
payload["ok"] = bool(validation["ok"])
|
|
1406
|
+
renderer = render_issue_fix_pr_lifecycle_monitor_markdown
|
|
1407
|
+
elif args.issue_fix_command == "outcome":
|
|
1408
|
+
if args.write_delivery_evidence and not args.delivery_evidence_json:
|
|
1409
|
+
raise ValueError(
|
|
1410
|
+
"--write-delivery-evidence requires --delivery-evidence-json"
|
|
1411
|
+
)
|
|
1412
|
+
if args.write_delivery_evidence and args.feasibility_json:
|
|
1413
|
+
raise ValueError(
|
|
1414
|
+
"--write-delivery-evidence uses the default feasibility domain-state row; "
|
|
1415
|
+
"do not combine it with --feasibility-json"
|
|
1416
|
+
)
|
|
1417
|
+
provider_path = args.repository_memory_provider_json or (
|
|
1418
|
+
default_repository_memory_provider_config_path()
|
|
1419
|
+
if args.write_repository_memory
|
|
1420
|
+
else None
|
|
1421
|
+
)
|
|
1422
|
+
if args.write_repository_memory and not provider_path:
|
|
1423
|
+
raise ValueError(
|
|
1424
|
+
"--write-repository-memory requires an explicit provider config "
|
|
1425
|
+
"or LOOPX_ISSUE_FIX_REPOSITORY_MEMORY_PROVIDER_CONFIG"
|
|
1426
|
+
)
|
|
1427
|
+
stdin_input_count = sum(
|
|
1428
|
+
value == "-"
|
|
1429
|
+
for value in (
|
|
1430
|
+
args.feasibility_json,
|
|
1431
|
+
args.pr_lifecycle_json,
|
|
1432
|
+
args.delivery_evidence_json,
|
|
1433
|
+
)
|
|
1434
|
+
)
|
|
1435
|
+
if stdin_input_count > 1:
|
|
1436
|
+
raise ValueError("only one outcome JSON input may read from stdin")
|
|
1437
|
+
project = Path(args.project).expanduser()
|
|
1438
|
+
feasibility_packet = (
|
|
1439
|
+
_load_json_object(args.feasibility_json)
|
|
1440
|
+
if args.feasibility_json
|
|
1441
|
+
else _load_jsonl_row(
|
|
1442
|
+
default_issue_fix_feasibility_ledger_path(
|
|
1443
|
+
project=project,
|
|
1444
|
+
goal_id=args.goal_id,
|
|
1445
|
+
),
|
|
1446
|
+
repo=args.repo,
|
|
1447
|
+
ref_field="issue_ref",
|
|
1448
|
+
ref_value=args.issue_ref,
|
|
1449
|
+
)
|
|
1450
|
+
)
|
|
1451
|
+
feasibility_observation = feasibility_packet.get("observation")
|
|
1452
|
+
if not isinstance(feasibility_observation, dict) or (
|
|
1453
|
+
str(feasibility_observation.get("repo") or "").strip() != args.repo
|
|
1454
|
+
or str(feasibility_observation.get("issue_ref") or "").strip()
|
|
1455
|
+
!= args.issue_ref
|
|
1456
|
+
):
|
|
1457
|
+
raise ValueError(
|
|
1458
|
+
"--repo/--issue-ref must match the selected feasibility packet"
|
|
1459
|
+
)
|
|
1460
|
+
pr_lifecycle_packet = None
|
|
1461
|
+
if args.pr_lifecycle_json:
|
|
1462
|
+
pr_lifecycle_packet = _load_json_object(args.pr_lifecycle_json)
|
|
1463
|
+
elif args.pr_ref:
|
|
1464
|
+
pr_lifecycle_packet = _load_jsonl_row(
|
|
1465
|
+
default_issue_fix_domain_state_ledger_path(
|
|
1466
|
+
project=project,
|
|
1467
|
+
goal_id=args.goal_id,
|
|
1468
|
+
),
|
|
1469
|
+
repo=args.repo,
|
|
1470
|
+
ref_field="pr_ref",
|
|
1471
|
+
ref_value=args.pr_ref,
|
|
1472
|
+
)
|
|
1473
|
+
if pr_lifecycle_packet is not None and args.pr_ref:
|
|
1474
|
+
lifecycle_observation = pr_lifecycle_packet.get("observation")
|
|
1475
|
+
if (
|
|
1476
|
+
not isinstance(lifecycle_observation, dict)
|
|
1477
|
+
or str(lifecycle_observation.get("pr_ref") or "").strip()
|
|
1478
|
+
!= args.pr_ref
|
|
1479
|
+
):
|
|
1480
|
+
raise ValueError(
|
|
1481
|
+
"--pr-ref must match the selected PR lifecycle packet"
|
|
1482
|
+
)
|
|
1483
|
+
explicit_delivery_evidence = (
|
|
1484
|
+
_load_json_object(args.delivery_evidence_json)
|
|
1485
|
+
if args.delivery_evidence_json
|
|
1486
|
+
else None
|
|
1487
|
+
)
|
|
1488
|
+
delivery_evidence = (
|
|
1489
|
+
compact_issue_fix_delivery_evidence(
|
|
1490
|
+
explicit_delivery_evidence,
|
|
1491
|
+
)
|
|
1492
|
+
if explicit_delivery_evidence is not None
|
|
1493
|
+
else (
|
|
1494
|
+
feasibility_packet.get("delivery_evidence")
|
|
1495
|
+
if isinstance(feasibility_packet.get("delivery_evidence"), dict)
|
|
1496
|
+
else None
|
|
1497
|
+
)
|
|
1498
|
+
)
|
|
1499
|
+
if explicit_delivery_evidence is not None:
|
|
1500
|
+
requires_commit_verification = bool(
|
|
1501
|
+
delivery_evidence.get("commit_ref")
|
|
1502
|
+
and (
|
|
1503
|
+
delivery_evidence.get("validation_status") == "passed"
|
|
1504
|
+
or delivery_evidence.get("outcome_status") == "completed"
|
|
1505
|
+
)
|
|
1506
|
+
)
|
|
1507
|
+
if requires_commit_verification and (
|
|
1508
|
+
args.repo_path
|
|
1509
|
+
or args.repository_ref
|
|
1510
|
+
or args.write_delivery_evidence
|
|
1511
|
+
):
|
|
1512
|
+
if not args.repo_path or not args.repository_ref:
|
|
1513
|
+
raise ValueError(
|
|
1514
|
+
"passed or completed commit evidence writeback requires "
|
|
1515
|
+
"--repo-path and --repository-ref"
|
|
1516
|
+
)
|
|
1517
|
+
repository_context = feasibility_observation.get(
|
|
1518
|
+
"repository_context"
|
|
1519
|
+
)
|
|
1520
|
+
revision = (
|
|
1521
|
+
str(repository_context.get("repository_revision") or "").strip()
|
|
1522
|
+
if isinstance(repository_context, dict)
|
|
1523
|
+
else ""
|
|
1524
|
+
)
|
|
1525
|
+
if not revision:
|
|
1526
|
+
raise ValueError(
|
|
1527
|
+
"passed or completed commit evidence requires a pinned "
|
|
1528
|
+
"repository_revision in feasibility context"
|
|
1529
|
+
)
|
|
1530
|
+
repository_commit_evidence = (
|
|
1531
|
+
verify_issue_fix_repository_commit_evidence(
|
|
1532
|
+
repo_path=args.repo_path,
|
|
1533
|
+
repo=args.repo,
|
|
1534
|
+
repository_revision=revision,
|
|
1535
|
+
commit_ref=str(delivery_evidence["commit_ref"]),
|
|
1536
|
+
recovery_ref=args.repository_ref,
|
|
1537
|
+
verified_at=generated_at,
|
|
1538
|
+
)
|
|
1539
|
+
)
|
|
1540
|
+
delivery_evidence = compact_issue_fix_delivery_evidence(
|
|
1541
|
+
{
|
|
1542
|
+
**delivery_evidence,
|
|
1543
|
+
"repository_commit_evidence": repository_commit_evidence,
|
|
1544
|
+
}
|
|
1545
|
+
)
|
|
1546
|
+
domain_state_write: dict[str, Any] | None = None
|
|
1547
|
+
if args.write_delivery_evidence:
|
|
1548
|
+
existing_delivery = feasibility_packet.get("delivery_evidence")
|
|
1549
|
+
existing_compact = (
|
|
1550
|
+
compact_issue_fix_delivery_evidence(existing_delivery)
|
|
1551
|
+
if isinstance(existing_delivery, dict)
|
|
1552
|
+
else None
|
|
1553
|
+
)
|
|
1554
|
+
comparable_existing = _comparable_delivery_evidence(existing_compact)
|
|
1555
|
+
comparable_delivery = _comparable_delivery_evidence(delivery_evidence)
|
|
1556
|
+
if comparable_existing == comparable_delivery:
|
|
1557
|
+
delivery_evidence = existing_delivery
|
|
1558
|
+
write_result = {
|
|
1559
|
+
"write_performed": False,
|
|
1560
|
+
"status": "unchanged",
|
|
1561
|
+
"row_count": None,
|
|
1562
|
+
}
|
|
1563
|
+
else:
|
|
1564
|
+
delivery_evidence = {
|
|
1565
|
+
**delivery_evidence,
|
|
1566
|
+
"recorded_at": generated_at,
|
|
1567
|
+
}
|
|
1568
|
+
feasibility_packet["delivery_evidence"] = delivery_evidence
|
|
1569
|
+
write_result = upsert_issue_fix_feasibility_ledger_jsonl(
|
|
1570
|
+
default_issue_fix_feasibility_ledger_path(
|
|
1571
|
+
project=project,
|
|
1572
|
+
goal_id=args.goal_id,
|
|
1573
|
+
),
|
|
1574
|
+
feasibility_packet,
|
|
1575
|
+
)
|
|
1576
|
+
domain_state_write = {
|
|
1577
|
+
"schema_version": "issue_fix_delivery_evidence_writeback_v0",
|
|
1578
|
+
"domain_pack": "issue_fix",
|
|
1579
|
+
"stream": "feasibility",
|
|
1580
|
+
"key": {"repo": args.repo, "issue_ref": args.issue_ref},
|
|
1581
|
+
"write_performed": write_result.get("write_performed") is True,
|
|
1582
|
+
"status": write_result.get("status"),
|
|
1583
|
+
"row_count": write_result.get("row_count"),
|
|
1584
|
+
"path_recorded": False,
|
|
1585
|
+
}
|
|
1586
|
+
payload = build_issue_fix_outcome_projection(
|
|
1587
|
+
goal_id=args.goal_id,
|
|
1588
|
+
feasibility_packet=feasibility_packet,
|
|
1589
|
+
pr_lifecycle_packet=pr_lifecycle_packet,
|
|
1590
|
+
delivery_evidence_input=delivery_evidence,
|
|
1591
|
+
agent_id=args.agent_id,
|
|
1592
|
+
generated_at=generated_at,
|
|
1593
|
+
)
|
|
1594
|
+
if args.write_repository_memory:
|
|
1595
|
+
if not args.repo_path:
|
|
1596
|
+
raise ValueError(
|
|
1597
|
+
"--write-repository-memory requires --repo-path for commit ancestry verification"
|
|
1598
|
+
)
|
|
1599
|
+
outcome_case = (payload.get("issue_fix_outcomes") or [{}])[0]
|
|
1600
|
+
repository_context = (
|
|
1601
|
+
outcome_case.get("repository_context")
|
|
1602
|
+
if isinstance(outcome_case, dict)
|
|
1603
|
+
else None
|
|
1604
|
+
)
|
|
1605
|
+
revision = (
|
|
1606
|
+
str(repository_context.get("revision") or "").strip()
|
|
1607
|
+
if isinstance(repository_context, dict)
|
|
1608
|
+
else ""
|
|
1609
|
+
)
|
|
1610
|
+
if not revision:
|
|
1611
|
+
raise ValueError(
|
|
1612
|
+
"--write-repository-memory requires a revision-pinned outcome"
|
|
1613
|
+
)
|
|
1614
|
+
writeback = write_issue_fix_validated_outcome_memory(
|
|
1615
|
+
config=_load_json_object(str(provider_path)),
|
|
1616
|
+
outcome_packet=payload,
|
|
1617
|
+
repository_revision=revision,
|
|
1618
|
+
repo_path=args.repo_path,
|
|
1619
|
+
observed_at=generated_at,
|
|
1620
|
+
execute=True,
|
|
1621
|
+
)
|
|
1622
|
+
payload["repository_memory_writeback"] = writeback
|
|
1623
|
+
payload["external_writes_performed"] = bool(
|
|
1624
|
+
writeback.get("external_writes_performed")
|
|
1625
|
+
)
|
|
1626
|
+
payload["ok"] = writeback.get("ok") is True
|
|
1627
|
+
payload["source_contract"]["repository_memory_writeback"] = (
|
|
1628
|
+
"issue_fix_validated_outcome_memory_writeback_v0"
|
|
1629
|
+
)
|
|
1630
|
+
payload["source_contract"]["writes_external_provider"] = bool(
|
|
1631
|
+
writeback.get("external_writes_performed")
|
|
1632
|
+
)
|
|
1633
|
+
if payload["ok"] is not True:
|
|
1634
|
+
payload["error"] = (
|
|
1635
|
+
"repository memory writeback "
|
|
1636
|
+
f"{writeback.get('status')}: "
|
|
1637
|
+
f"{writeback.get('reason_code') or 'provider write failed'}"
|
|
1638
|
+
)
|
|
1639
|
+
if domain_state_write is not None:
|
|
1640
|
+
payload["domain_state_write"] = domain_state_write
|
|
1641
|
+
payload["source_contract"]["writes_source_state"] = True
|
|
1642
|
+
renderer = render_issue_fix_outcome_projection_markdown
|
|
1643
|
+
elif args.issue_fix_command == "metrics":
|
|
1644
|
+
stdin_input_count = sum(
|
|
1645
|
+
value == "-"
|
|
1646
|
+
for value in (
|
|
1647
|
+
args.repository_baseline_json,
|
|
1648
|
+
args.repository_current_json,
|
|
1649
|
+
args.supplement_json,
|
|
1650
|
+
)
|
|
1651
|
+
)
|
|
1652
|
+
if stdin_input_count > 1:
|
|
1653
|
+
raise ValueError("only one metrics JSON input may read from stdin")
|
|
1654
|
+
project = Path(args.project).expanduser()
|
|
1655
|
+
feasibility_path = (
|
|
1656
|
+
Path(args.feasibility_ledger).expanduser()
|
|
1657
|
+
if args.feasibility_ledger
|
|
1658
|
+
else default_issue_fix_feasibility_ledger_path(
|
|
1659
|
+
project=project,
|
|
1660
|
+
goal_id=args.goal_id,
|
|
1661
|
+
)
|
|
1662
|
+
)
|
|
1663
|
+
lifecycle_path = (
|
|
1664
|
+
Path(args.pr_lifecycle_ledger).expanduser()
|
|
1665
|
+
if args.pr_lifecycle_ledger
|
|
1666
|
+
else default_issue_fix_domain_state_ledger_path(
|
|
1667
|
+
project=project,
|
|
1668
|
+
goal_id=args.goal_id,
|
|
1669
|
+
)
|
|
1670
|
+
)
|
|
1671
|
+
payload = build_issue_fix_metrics_projection(
|
|
1672
|
+
goal_id=args.goal_id,
|
|
1673
|
+
repo=args.repo,
|
|
1674
|
+
baseline_snapshot=_load_json_object(args.repository_baseline_json),
|
|
1675
|
+
current_snapshot=_load_json_object(args.repository_current_json),
|
|
1676
|
+
feasibility_rows=_load_jsonl_rows(feasibility_path),
|
|
1677
|
+
pr_lifecycle_rows=_load_jsonl_rows(lifecycle_path),
|
|
1678
|
+
supplement_input=(
|
|
1679
|
+
_load_json_object(args.supplement_json)
|
|
1680
|
+
if args.supplement_json
|
|
1681
|
+
else None
|
|
1682
|
+
),
|
|
1683
|
+
generated_at=generated_at,
|
|
1684
|
+
)
|
|
1685
|
+
renderer = render_issue_fix_metrics_projection_markdown
|
|
1686
|
+
elif args.issue_fix_command == "metrics-supplement":
|
|
1687
|
+
payload = build_issue_fix_metrics_supplement_from_args(
|
|
1688
|
+
args,
|
|
1689
|
+
registry_path=registry_path,
|
|
1690
|
+
runtime_root_arg=runtime_root_arg,
|
|
1691
|
+
generated_at=generated_at,
|
|
1692
|
+
load_json_object=_load_json_object,
|
|
1693
|
+
load_jsonl_rows=_load_jsonl_rows,
|
|
1694
|
+
)
|
|
1695
|
+
renderer = render_issue_fix_metrics_supplement_markdown
|
|
1696
|
+
elif args.issue_fix_command == "repository-snapshot":
|
|
1697
|
+
if not args.fetch_public_github:
|
|
1698
|
+
raise ValueError("repository-snapshot requires --fetch-public-github")
|
|
1699
|
+
if sum(
|
|
1700
|
+
value == "-"
|
|
1701
|
+
for value in (
|
|
1702
|
+
args.repository_baseline_json,
|
|
1703
|
+
args.supplement_json,
|
|
1704
|
+
)
|
|
1705
|
+
if value is not None
|
|
1706
|
+
) > 1:
|
|
1707
|
+
raise ValueError(
|
|
1708
|
+
"only one repository-snapshot JSON input may read from stdin"
|
|
1709
|
+
)
|
|
1710
|
+
project = Path(args.project).expanduser()
|
|
1711
|
+
payload = collect_public_github_repository_snapshot(
|
|
1712
|
+
repo=args.repo,
|
|
1713
|
+
baseline_snapshot=_load_json_object(args.repository_baseline_json),
|
|
1714
|
+
feasibility_rows=_load_jsonl_rows(
|
|
1715
|
+
default_issue_fix_feasibility_ledger_path(
|
|
1716
|
+
project=project, goal_id=args.goal_id
|
|
1717
|
+
)
|
|
1718
|
+
),
|
|
1719
|
+
pr_lifecycle_rows=_load_jsonl_rows(
|
|
1720
|
+
default_issue_fix_domain_state_ledger_path(
|
|
1721
|
+
project=project, goal_id=args.goal_id
|
|
1722
|
+
)
|
|
1723
|
+
),
|
|
1724
|
+
metrics_supplement=(
|
|
1725
|
+
_load_json_object(args.supplement_json)
|
|
1726
|
+
if args.supplement_json
|
|
1727
|
+
else None
|
|
1728
|
+
),
|
|
1729
|
+
generated_at=generated_at,
|
|
1730
|
+
timeout_seconds=args.fetch_timeout_seconds,
|
|
1731
|
+
)
|
|
1732
|
+
if args.retain_material_snapshot:
|
|
1733
|
+
write_result = retain_issue_fix_repository_snapshot_jsonl(
|
|
1734
|
+
default_issue_fix_repository_snapshot_ledger_path(
|
|
1735
|
+
project=project, goal_id=args.goal_id
|
|
1736
|
+
),
|
|
1737
|
+
repository_snapshot_record(payload["snapshot"]),
|
|
1738
|
+
)
|
|
1739
|
+
payload["retention"] = {
|
|
1740
|
+
"schema_version": "issue_fix_repository_snapshot_retention_v0",
|
|
1741
|
+
"domain_pack": "issue_fix",
|
|
1742
|
+
"stream": "repository_snapshots",
|
|
1743
|
+
"write_performed": write_result.get("write_performed") is True,
|
|
1744
|
+
"status": write_result.get("status"),
|
|
1745
|
+
"row_count": write_result.get("row_count"),
|
|
1746
|
+
"path_recorded": False,
|
|
1747
|
+
}
|
|
1748
|
+
payload["source_contract"]["writes_source_state"] = True
|
|
1749
|
+
renderer = render_repository_snapshot_markdown
|
|
1750
|
+
elif args.issue_fix_command == "acceptance-fixture":
|
|
1751
|
+
payload = build_issue_fix_acceptance_fixture_packet(
|
|
1752
|
+
repo=args.repo,
|
|
1753
|
+
issue_ref=args.issue_ref,
|
|
1754
|
+
url=args.url,
|
|
1755
|
+
generated_at=generated_at,
|
|
1756
|
+
)
|
|
1757
|
+
renderer = render_issue_fix_acceptance_loop_markdown
|
|
1758
|
+
elif args.issue_fix_command == "repo-branch-fixture":
|
|
1759
|
+
payload = build_issue_fix_repo_branch_fixture_packet(
|
|
1760
|
+
repo=args.repo,
|
|
1761
|
+
issue_ref=args.issue_ref,
|
|
1762
|
+
url=args.url,
|
|
1763
|
+
generated_at=generated_at,
|
|
1764
|
+
)
|
|
1765
|
+
renderer = render_issue_fix_acceptance_loop_markdown
|
|
1766
|
+
elif args.issue_fix_command == "caller-repo-branch":
|
|
1767
|
+
payload = build_issue_fix_caller_repo_branch_packet(
|
|
1768
|
+
repo_path=args.repo_path,
|
|
1769
|
+
repo=args.repo,
|
|
1770
|
+
issue_ref=args.issue_ref,
|
|
1771
|
+
url=args.url,
|
|
1772
|
+
base_branch=args.base_branch,
|
|
1773
|
+
issue_branch=args.issue_branch,
|
|
1774
|
+
validation_command=args.validation_command,
|
|
1775
|
+
validation_label=args.validation_label,
|
|
1776
|
+
execute=args.execute,
|
|
1777
|
+
timeout_seconds=args.timeout_seconds,
|
|
1778
|
+
generated_at=generated_at,
|
|
1779
|
+
)
|
|
1780
|
+
renderer = render_issue_fix_acceptance_loop_markdown
|
|
1781
|
+
else:
|
|
1782
|
+
raise ValueError(
|
|
1783
|
+
"issue-fix requires `repository-memory-sync`, `promote-discovered-issue`, "
|
|
1784
|
+
"`workflow-plan`, `feasibility`, "
|
|
1785
|
+
"`acceptance-fixture`, `pr-lifecycle`, `pr-gate-reconcile`, `outcome`, `metrics`, "
|
|
1786
|
+
"`metrics-supplement`, "
|
|
1787
|
+
"`repository-snapshot`, `reviewer-plan`, "
|
|
1788
|
+
"`reviewer-request`, `reviewer-notification-drain`, "
|
|
1789
|
+
"`repo-branch-fixture`, or `caller-repo-branch`"
|
|
1790
|
+
)
|
|
1791
|
+
except Exception as exc:
|
|
1792
|
+
payload = {
|
|
1793
|
+
"ok": False,
|
|
1794
|
+
"mode": "issue-fix",
|
|
1795
|
+
"error": str(exc),
|
|
1796
|
+
}
|
|
1797
|
+
renderer = (
|
|
1798
|
+
render_issue_fix_repository_memory_sync_markdown
|
|
1799
|
+
if getattr(args, "issue_fix_command", None) == "repository-memory-sync"
|
|
1800
|
+
else render_issue_fix_discovered_issue_promotion_markdown
|
|
1801
|
+
if getattr(args, "issue_fix_command", None) == "promote-discovered-issue"
|
|
1802
|
+
else render_issue_fix_workflow_plan_markdown
|
|
1803
|
+
if getattr(args, "issue_fix_command", None) == "workflow-plan"
|
|
1804
|
+
else render_issue_fix_feasibility_markdown
|
|
1805
|
+
if getattr(args, "issue_fix_command", None) == "feasibility"
|
|
1806
|
+
else render_issue_fix_pr_lifecycle_monitor_markdown
|
|
1807
|
+
if getattr(args, "issue_fix_command", None)
|
|
1808
|
+
in {"pr-lifecycle", "pr-gate-reconcile"}
|
|
1809
|
+
else render_issue_fix_outcome_projection_markdown
|
|
1810
|
+
if getattr(args, "issue_fix_command", None) == "outcome"
|
|
1811
|
+
else render_issue_fix_metrics_projection_markdown
|
|
1812
|
+
if getattr(args, "issue_fix_command", None) == "metrics"
|
|
1813
|
+
else render_issue_fix_metrics_supplement_markdown
|
|
1814
|
+
if getattr(args, "issue_fix_command", None) == "metrics-supplement"
|
|
1815
|
+
else render_repository_snapshot_markdown
|
|
1816
|
+
if getattr(args, "issue_fix_command", None) == "repository-snapshot"
|
|
1817
|
+
else reviewer_renderer(getattr(args, "issue_fix_command", None))
|
|
1818
|
+
if getattr(args, "issue_fix_command", None) in REVIEWER_COMMANDS
|
|
1819
|
+
else render_issue_fix_acceptance_loop_markdown
|
|
1820
|
+
)
|
|
1821
|
+
print_payload(payload, output_format(args), renderer)
|
|
1822
|
+
return 0 if payload.get("ok") else 1
|