phase-loop-runtime 0.2.0__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.
- phase_loop_runtime/__init__.py +20 -0
- phase_loop_runtime/_contract_docs/phase-loop/extraction-readiness.md +90 -0
- phase_loop_runtime/_contract_docs/phase-loop/granular-execution-policy.md +137 -0
- phase_loop_runtime/_contract_docs/phase-loop/harness-capability-matrix.md +510 -0
- phase_loop_runtime/_contract_docs/phase-loop/harness-skill-matrix.md +125 -0
- phase_loop_runtime/_contract_docs/phase-loop/harness-substrate-manifest.md +232 -0
- phase_loop_runtime/_contract_docs/phase-loop/pi-loop-control.md +247 -0
- phase_loop_runtime/_contract_docs/phase-loop/protocol.md +2759 -0
- phase_loop_runtime/_contract_docs/phase-loop/runtime-boundary.md +289 -0
- phase_loop_runtime/_contract_docs/phase-loop/spec-discovery-roots.md +47 -0
- phase_loop_runtime/_contract_docs/phase-loop/substrate-soak-governed-pipeline.md +42 -0
- phase_loop_runtime/_contract_docs/phase-loop/substrate-soak-portal-projection.md +34 -0
- phase_loop_runtime/_contract_docs/phase-loop/substrate-soak-regenesis.md +29 -0
- phase_loop_runtime/_contract_docs/phase-loop/substrate-soak-report.md +32 -0
- phase_loop_runtime/_contract_docs/runtime/verification-evidence-contract.md +52 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-mixed-signals/commands.txt +2 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-mixed-signals/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-mixed-signals/mixed.json +5 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-provider-timeout/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-provider-timeout/timeout-note.txt +2 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-redacted-summary/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-redacted-summary/redacted-summary.json +6 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-small-sample/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-small-sample/sample.json +7 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-threshold-edge/edge.txt +2 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-threshold-edge/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-duplicate-png/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-duplicate-png/shot-a.txt +1 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-duplicate-png/shot-b.txt +1 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-duplicate-png/shot-c.txt +1 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-missing-references/claimed-results.json +5 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-missing-references/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-subtle-low-variance/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-subtle-low-variance/metrics.json +9 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-templated-prose/findings.md +10 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-templated-prose/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-uniform-scores/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-uniform-scores/scores.json +4 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-uniform-scores/summary.txt +1 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-adoption-bundle/bundle-check.json +8 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-adoption-bundle/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-adoption-bundle/operator-note.txt +2 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-handoff-ledger/events-sample.jsonl +3 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-handoff-ledger/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-handoff-ledger/receipt.txt +1 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-runner-diff/evidence.json +13 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-runner-diff/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-runner-diff/summary.txt +2 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-test-matrix/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-test-matrix/matrix.json +9 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-test-matrix/notes.md +4 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-ui-screenshot-standin/console-summary.txt +2 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-ui-screenshot-standin/manifest.json +16 -0
- phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-ui-screenshot-standin/screenshot-standin.ppm +5 -0
- phase_loop_runtime/adoption_bundle.py +273 -0
- phase_loop_runtime/advisor_board/CONTRACTS.md +257 -0
- phase_loop_runtime/advisor_board/__init__.py +288 -0
- phase_loop_runtime/advisor_board/backing.py +137 -0
- phase_loop_runtime/advisor_board/backing_omnigent.py +498 -0
- phase_loop_runtime/advisor_board/config.py +225 -0
- phase_loop_runtime/advisor_board/events.py +115 -0
- phase_loop_runtime/advisor_board/fixtures/advisor-boards.example.toml +59 -0
- phase_loop_runtime/advisor_board/fixtures.py +91 -0
- phase_loop_runtime/advisor_board/harness_mapping.py +125 -0
- phase_loop_runtime/advisor_board/matrix.py +146 -0
- phase_loop_runtime/advisor_board/observability.py +481 -0
- phase_loop_runtime/advisor_board/presets.py +188 -0
- phase_loop_runtime/advisor_board/registries.py +309 -0
- phase_loop_runtime/advisor_board/resolver.py +253 -0
- phase_loop_runtime/advisor_board/schema.py +269 -0
- phase_loop_runtime/advisor_board/standin.py +166 -0
- phase_loop_runtime/advisor_board/validation.py +159 -0
- phase_loop_runtime/agent_runtime_provider.py +676 -0
- phase_loop_runtime/baml_modular.py +656 -0
- phase_loop_runtime/baml_src/dotfiles_adoption_manifest.baml +37 -0
- phase_loop_runtime/baml_src/dotfiles_c4_document.baml +14 -0
- phase_loop_runtime/baml_src/dotfiles_plan_manifest.baml +50 -0
- phase_loop_runtime/baml_src/dotfiles_runtime_projection.baml +16 -0
- phase_loop_runtime/baml_src/dotfiles_task_catalog.baml +20 -0
- phase_loop_runtime/baml_src/emit_phase_closeout.baml +86 -0
- phase_loop_runtime/baml_src/evaluate_suspected_fake_evidence.baml +36 -0
- phase_loop_runtime/baml_src/verification_evidence.baml +40 -0
- phase_loop_runtime/broker.py +181 -0
- phase_loop_runtime/build_bundle.py +294 -0
- phase_loop_runtime/capability_registry.py +835 -0
- phase_loop_runtime/classifier.py +87 -0
- phase_loop_runtime/claude_agent_view.py +625 -0
- phase_loop_runtime/claude_channel_sidecar.py +1086 -0
- phase_loop_runtime/cli.py +2599 -0
- phase_loop_runtime/closeout.py +865 -0
- phase_loop_runtime/closeout_classifier.py +120 -0
- phase_loop_runtime/closeout_evidence_audit.py +112 -0
- phase_loop_runtime/closeout_validation.py +144 -0
- phase_loop_runtime/closeout_validators.py +203 -0
- phase_loop_runtime/consiliency_gates.py +374 -0
- phase_loop_runtime/consiliency_ingest.py +399 -0
- phase_loop_runtime/consiliency_layout.py +176 -0
- phase_loop_runtime/consiliency_scaffold.py +305 -0
- phase_loop_runtime/cross_repo_channel.py +331 -0
- phase_loop_runtime/discovery.py +2368 -0
- phase_loop_runtime/dispatch_lock.py +167 -0
- phase_loop_runtime/doc_delta_validator.py +98 -0
- phase_loop_runtime/docs_audit.py +285 -0
- phase_loop_runtime/docs_freshness.py +468 -0
- phase_loop_runtime/docs_surfaces.py +150 -0
- phase_loop_runtime/dotfiles_profile_plugin.py +96 -0
- phase_loop_runtime/events.py +154 -0
- phase_loop_runtime/events_migration.py +96 -0
- phase_loop_runtime/evidence_audit.py +1082 -0
- phase_loop_runtime/evidence_audit_config.py +172 -0
- phase_loop_runtime/fleet_map.py +426 -0
- phase_loop_runtime/fleet_metrics.py +298 -0
- phase_loop_runtime/fleet_metrics_export.py +196 -0
- phase_loop_runtime/git_discipline.py +479 -0
- phase_loop_runtime/git_ops.py +122 -0
- phase_loop_runtime/git_topology.py +252 -0
- phase_loop_runtime/governed_bundle.py +137 -0
- phase_loop_runtime/governed_premerge.py +219 -0
- phase_loop_runtime/governed_review.py +264 -0
- phase_loop_runtime/handoff.py +932 -0
- phase_loop_runtime/handoff_path.py +14 -0
- phase_loop_runtime/injection.py +740 -0
- phase_loop_runtime/install_status.py +88 -0
- phase_loop_runtime/lane_scheduler.py +317 -0
- phase_loop_runtime/launcher.py +2760 -0
- phase_loop_runtime/lease_store.py +553 -0
- phase_loop_runtime/maintenance.py +401 -0
- phase_loop_runtime/migrate_handoffs.py +201 -0
- phase_loop_runtime/models.py +2144 -0
- phase_loop_runtime/observability.py +1290 -0
- phase_loop_runtime/panel_invoker.py +1638 -0
- phase_loop_runtime/phase_loop_drift_audit.py +388 -0
- phase_loop_runtime/phase_worktree_executor.py +433 -0
- phase_loop_runtime/pipeline_adapter/__init__.py +12 -0
- phase_loop_runtime/pipeline_adapter/branch_ops.py +274 -0
- phase_loop_runtime/pipeline_adapter/flag.py +55 -0
- phase_loop_runtime/pipeline_adapter/markers.py +13 -0
- phase_loop_runtime/pipeline_adapter/merge_policy.py +72 -0
- phase_loop_runtime/pipeline_adapter/ratification.py +100 -0
- phase_loop_runtime/pipeline_adapter/sibling_matcher.py +123 -0
- phase_loop_runtime/plan_ir.py +523 -0
- phase_loop_runtime/plan_manifest.py +415 -0
- phase_loop_runtime/planner_validation.py +176 -0
- phase_loop_runtime/profiles.py +462 -0
- phase_loop_runtime/prompts.py +365 -0
- phase_loop_runtime/provenance.py +165 -0
- phase_loop_runtime/publishing.py +339 -0
- phase_loop_runtime/py.typed +1 -0
- phase_loop_runtime/reconcile.py +1550 -0
- phase_loop_runtime/redaction.py +184 -0
- phase_loop_runtime/reflection_sync.py +293 -0
- phase_loop_runtime/release_guard.py +186 -0
- phase_loop_runtime/render.py +432 -0
- phase_loop_runtime/repo_validation.py +427 -0
- phase_loop_runtime/review_summary.py +150 -0
- phase_loop_runtime/roadmap_lint.py +425 -0
- phase_loop_runtime/route_log.py +59 -0
- phase_loop_runtime/route_policy/__init__.py +11 -0
- phase_loop_runtime/route_policy/fixtures/route_selection.golden.json +263 -0
- phase_loop_runtime/runner.py +8400 -0
- phase_loop_runtime/runtime_paths.py +225 -0
- phase_loop_runtime/runtime_projection.py +113 -0
- phase_loop_runtime/runtime_resources.py +36 -0
- phase_loop_runtime/schema_export.py +292 -0
- phase_loop_runtime/schemas/phase_loop_closeout.schema.json +366 -0
- phase_loop_runtime/skill_install.py +176 -0
- phase_loop_runtime/skill_inventory.py +662 -0
- phase_loop_runtime/skill_paths.py +42 -0
- phase_loop_runtime/skill_sources_plugin.py +37 -0
- phase_loop_runtime/skills_bundle/claude-advisor-board/README.md +1 -0
- phase_loop_runtime/skills_bundle/claude-advisor-board/SKILL.md +38 -0
- phase_loop_runtime/skills_bundle/claude-advisor-panel/README.md +1 -0
- phase_loop_runtime/skills_bundle/claude-advisor-panel/SKILL.md +38 -0
- phase_loop_runtime/skills_bundle/claude-execute-detailed/README.md +1 -0
- phase_loop_runtime/skills_bundle/claude-execute-detailed/SKILL.md +152 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/README.md +1 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/SKILL.md +745 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/allocate_worktree_name.sh +33 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/audit_lane_file_touches.py +197 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/cleanup_lane_worktrees.sh +103 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/parent_tree_leakage_check.sh +125 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/post_merge_import_smoke.sh +62 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/pre_merge_destructiveness_check.sh +127 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/resolve_branch_from_sha.sh +51 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/state.py +274 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/sweep_stale_worktrees.sh +62 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/team_teardown.sh +32 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/validate_plan_doc.py +642 -0
- phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/verify_harness.sh +96 -0
- phase_loop_runtime/skills_bundle/claude-phase-loop/README.md +1 -0
- phase_loop_runtime/skills_bundle/claude-phase-loop/SKILL.md +115 -0
- phase_loop_runtime/skills_bundle/claude-phase-roadmap-builder/README.md +1 -0
- phase_loop_runtime/skills_bundle/claude-phase-roadmap-builder/SKILL.md +439 -0
- phase_loop_runtime/skills_bundle/claude-phase-roadmap-builder/assets/review_prompt.md +19 -0
- phase_loop_runtime/skills_bundle/claude-phase-roadmap-builder/references/parallelization-heuristics.md +111 -0
- phase_loop_runtime/skills_bundle/claude-phase-roadmap-builder/references/roadmap-template.md +193 -0
- phase_loop_runtime/skills_bundle/claude-phase-roadmap-builder/scripts/validate_roadmap.py +32 -0
- phase_loop_runtime/skills_bundle/claude-plan-detailed/README.md +1 -0
- phase_loop_runtime/skills_bundle/claude-plan-detailed/SKILL.md +334 -0
- phase_loop_runtime/skills_bundle/claude-plan-detailed/assets/review_prompt.md +25 -0
- phase_loop_runtime/skills_bundle/claude-plan-phase/README.md +1 -0
- phase_loop_runtime/skills_bundle/claude-plan-phase/SKILL.md +776 -0
- phase_loop_runtime/skills_bundle/claude-plan-phase/assets/review_prompt.md +17 -0
- phase_loop_runtime/skills_bundle/claude-plan-phase/scripts/validate_plan_doc.py +1092 -0
- phase_loop_runtime/skills_bundle/claude-run-train/README.md +1 -0
- phase_loop_runtime/skills_bundle/claude-run-train/SKILL.md +75 -0
- phase_loop_runtime/skills_bundle/claude-skill-editor/README.md +1 -0
- phase_loop_runtime/skills_bundle/claude-skill-editor/SKILL.md +243 -0
- phase_loop_runtime/skills_bundle/claude-skill-editor/assets/editor_prompt.md +72 -0
- phase_loop_runtime/skills_bundle/claude-skill-improvement-planner/README.md +1 -0
- phase_loop_runtime/skills_bundle/claude-skill-improvement-planner/SKILL.md +249 -0
- phase_loop_runtime/skills_bundle/claude-skill-improvement-planner/assets/aggregator_prompt.md +79 -0
- phase_loop_runtime/skills_bundle/claude-task-contextualizer/README.md +1 -0
- phase_loop_runtime/skills_bundle/claude-task-contextualizer/SKILL.md +74 -0
- phase_loop_runtime/skills_bundle/claude-task-contextualizer/references/task-templates.md +103 -0
- phase_loop_runtime/skills_bundle/codex-advisor-board/README.md +1 -0
- phase_loop_runtime/skills_bundle/codex-advisor-board/SKILL.md +38 -0
- phase_loop_runtime/skills_bundle/codex-advisor-panel/README.md +1 -0
- phase_loop_runtime/skills_bundle/codex-advisor-panel/SKILL.md +38 -0
- phase_loop_runtime/skills_bundle/codex-execute-detailed/README.md +1 -0
- phase_loop_runtime/skills_bundle/codex-execute-detailed/SKILL.md +154 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/README.md +1 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/SKILL.md +231 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/allocate_worktree_name.sh +33 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/audit_lane_file_touches.py +197 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/cleanup_lane_worktrees.sh +103 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/parent_tree_leakage_check.sh +125 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/post_merge_import_smoke.sh +62 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/pre_merge_destructiveness_check.sh +127 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/resolve_branch_from_sha.sh +51 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/state.py +274 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/sweep_stale_worktrees.sh +62 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/team_teardown.sh +32 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/validate_plan_doc.py +642 -0
- phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/verify_harness.sh +96 -0
- phase_loop_runtime/skills_bundle/codex-phase-loop/README.md +1 -0
- phase_loop_runtime/skills_bundle/codex-phase-loop/SKILL.md +248 -0
- phase_loop_runtime/skills_bundle/codex-phase-roadmap-builder/README.md +1 -0
- phase_loop_runtime/skills_bundle/codex-phase-roadmap-builder/SKILL.md +150 -0
- phase_loop_runtime/skills_bundle/codex-phase-roadmap-builder/assets/review_prompt.md +19 -0
- phase_loop_runtime/skills_bundle/codex-phase-roadmap-builder/references/parallelization-heuristics.md +111 -0
- phase_loop_runtime/skills_bundle/codex-phase-roadmap-builder/references/roadmap-template.md +193 -0
- phase_loop_runtime/skills_bundle/codex-phase-roadmap-builder/scripts/validate_roadmap.py +32 -0
- phase_loop_runtime/skills_bundle/codex-plan-detailed/README.md +1 -0
- phase_loop_runtime/skills_bundle/codex-plan-detailed/SKILL.md +119 -0
- phase_loop_runtime/skills_bundle/codex-plan-detailed/assets/review_prompt.md +25 -0
- phase_loop_runtime/skills_bundle/codex-plan-phase/README.md +1 -0
- phase_loop_runtime/skills_bundle/codex-plan-phase/SKILL.md +307 -0
- phase_loop_runtime/skills_bundle/codex-plan-phase/assets/review_prompt.md +17 -0
- phase_loop_runtime/skills_bundle/codex-plan-phase/scripts/validate_plan_doc.py +1092 -0
- phase_loop_runtime/skills_bundle/codex-run-train/README.md +1 -0
- phase_loop_runtime/skills_bundle/codex-run-train/SKILL.md +75 -0
- phase_loop_runtime/skills_bundle/codex-skill-editor/README.md +1 -0
- phase_loop_runtime/skills_bundle/codex-skill-editor/SKILL.md +94 -0
- phase_loop_runtime/skills_bundle/codex-skill-editor/assets/editor_prompt.md +72 -0
- phase_loop_runtime/skills_bundle/codex-skill-improvement-planner/README.md +1 -0
- phase_loop_runtime/skills_bundle/codex-skill-improvement-planner/SKILL.md +114 -0
- phase_loop_runtime/skills_bundle/codex-skill-improvement-planner/assets/aggregator_prompt.md +79 -0
- phase_loop_runtime/skills_bundle/codex-task-contextualizer/README.md +1 -0
- phase_loop_runtime/skills_bundle/codex-task-contextualizer/SKILL.md +102 -0
- phase_loop_runtime/skills_bundle/codex-task-contextualizer/references/task-templates.md +103 -0
- phase_loop_runtime/skills_bundle/gemini-advisor-board/README.md +1 -0
- phase_loop_runtime/skills_bundle/gemini-advisor-board/SKILL.md +38 -0
- phase_loop_runtime/skills_bundle/gemini-advisor-panel/README.md +1 -0
- phase_loop_runtime/skills_bundle/gemini-advisor-panel/SKILL.md +38 -0
- phase_loop_runtime/skills_bundle/gemini-execute-detailed/README.md +1 -0
- phase_loop_runtime/skills_bundle/gemini-execute-detailed/SKILL.md +144 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/README.md +1 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/SKILL.md +198 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/allocate_worktree_name.sh +33 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/audit_lane_file_touches.py +197 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/cleanup_lane_worktrees.sh +103 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/parent_tree_leakage_check.sh +125 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/post_merge_import_smoke.sh +62 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/pre_merge_destructiveness_check.sh +127 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/resolve_branch_from_sha.sh +51 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/state.py +274 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/sweep_stale_worktrees.sh +62 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/team_teardown.sh +32 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/validate_plan_doc.py +642 -0
- phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/verify_harness.sh +96 -0
- phase_loop_runtime/skills_bundle/gemini-phase-loop/README.md +1 -0
- phase_loop_runtime/skills_bundle/gemini-phase-loop/SKILL.md +111 -0
- phase_loop_runtime/skills_bundle/gemini-phase-roadmap-builder/README.md +1 -0
- phase_loop_runtime/skills_bundle/gemini-phase-roadmap-builder/SKILL.md +147 -0
- phase_loop_runtime/skills_bundle/gemini-phase-roadmap-builder/assets/review_prompt.md +19 -0
- phase_loop_runtime/skills_bundle/gemini-phase-roadmap-builder/references/parallelization-heuristics.md +111 -0
- phase_loop_runtime/skills_bundle/gemini-phase-roadmap-builder/references/roadmap-template.md +193 -0
- phase_loop_runtime/skills_bundle/gemini-phase-roadmap-builder/scripts/validate_roadmap.py +32 -0
- phase_loop_runtime/skills_bundle/gemini-plan-detailed/README.md +1 -0
- phase_loop_runtime/skills_bundle/gemini-plan-detailed/SKILL.md +119 -0
- phase_loop_runtime/skills_bundle/gemini-plan-detailed/assets/review_prompt.md +25 -0
- phase_loop_runtime/skills_bundle/gemini-plan-phase/README.md +1 -0
- phase_loop_runtime/skills_bundle/gemini-plan-phase/SKILL.md +217 -0
- phase_loop_runtime/skills_bundle/gemini-plan-phase/assets/review_prompt.md +17 -0
- phase_loop_runtime/skills_bundle/gemini-plan-phase/scripts/validate_plan_doc.py +1092 -0
- phase_loop_runtime/skills_bundle/gemini-run-train/README.md +1 -0
- phase_loop_runtime/skills_bundle/gemini-run-train/SKILL.md +75 -0
- phase_loop_runtime/skills_bundle/gemini-skill-editor/README.md +1 -0
- phase_loop_runtime/skills_bundle/gemini-skill-editor/SKILL.md +87 -0
- phase_loop_runtime/skills_bundle/gemini-skill-editor/assets/editor_prompt.md +72 -0
- phase_loop_runtime/skills_bundle/gemini-skill-improvement-planner/README.md +1 -0
- phase_loop_runtime/skills_bundle/gemini-skill-improvement-planner/SKILL.md +109 -0
- phase_loop_runtime/skills_bundle/gemini-skill-improvement-planner/assets/aggregator_prompt.md +79 -0
- phase_loop_runtime/skills_bundle/gemini-task-contextualizer/README.md +1 -0
- phase_loop_runtime/skills_bundle/gemini-task-contextualizer/SKILL.md +98 -0
- phase_loop_runtime/skills_bundle/gemini-task-contextualizer/references/task-templates.md +103 -0
- phase_loop_runtime/skills_bundle/opencode-advisor-board/README.md +1 -0
- phase_loop_runtime/skills_bundle/opencode-advisor-board/SKILL.md +38 -0
- phase_loop_runtime/skills_bundle/opencode-advisor-panel/README.md +1 -0
- phase_loop_runtime/skills_bundle/opencode-advisor-panel/SKILL.md +38 -0
- phase_loop_runtime/skills_bundle/opencode-execute-detailed/README.md +1 -0
- phase_loop_runtime/skills_bundle/opencode-execute-detailed/SKILL.md +144 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/README.md +1 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/SKILL.md +196 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/allocate_worktree_name.sh +33 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/audit_lane_file_touches.py +197 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/cleanup_lane_worktrees.sh +103 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/parent_tree_leakage_check.sh +125 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/post_merge_import_smoke.sh +62 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/pre_merge_destructiveness_check.sh +127 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/resolve_branch_from_sha.sh +51 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/state.py +274 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/sweep_stale_worktrees.sh +62 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/team_teardown.sh +32 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/validate_plan_doc.py +642 -0
- phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/verify_harness.sh +96 -0
- phase_loop_runtime/skills_bundle/opencode-phase-loop/README.md +1 -0
- phase_loop_runtime/skills_bundle/opencode-phase-loop/SKILL.md +113 -0
- phase_loop_runtime/skills_bundle/opencode-phase-roadmap-builder/README.md +1 -0
- phase_loop_runtime/skills_bundle/opencode-phase-roadmap-builder/SKILL.md +147 -0
- phase_loop_runtime/skills_bundle/opencode-phase-roadmap-builder/assets/review_prompt.md +19 -0
- phase_loop_runtime/skills_bundle/opencode-phase-roadmap-builder/references/parallelization-heuristics.md +111 -0
- phase_loop_runtime/skills_bundle/opencode-phase-roadmap-builder/references/roadmap-template.md +193 -0
- phase_loop_runtime/skills_bundle/opencode-phase-roadmap-builder/scripts/validate_roadmap.py +32 -0
- phase_loop_runtime/skills_bundle/opencode-plan-detailed/README.md +1 -0
- phase_loop_runtime/skills_bundle/opencode-plan-detailed/SKILL.md +119 -0
- phase_loop_runtime/skills_bundle/opencode-plan-detailed/assets/review_prompt.md +25 -0
- phase_loop_runtime/skills_bundle/opencode-plan-phase/README.md +1 -0
- phase_loop_runtime/skills_bundle/opencode-plan-phase/SKILL.md +211 -0
- phase_loop_runtime/skills_bundle/opencode-plan-phase/assets/review_prompt.md +17 -0
- phase_loop_runtime/skills_bundle/opencode-plan-phase/scripts/validate_plan_doc.py +1092 -0
- phase_loop_runtime/skills_bundle/opencode-run-train/README.md +1 -0
- phase_loop_runtime/skills_bundle/opencode-run-train/SKILL.md +75 -0
- phase_loop_runtime/skills_bundle/opencode-skill-editor/README.md +1 -0
- phase_loop_runtime/skills_bundle/opencode-skill-editor/SKILL.md +87 -0
- phase_loop_runtime/skills_bundle/opencode-skill-editor/assets/editor_prompt.md +72 -0
- phase_loop_runtime/skills_bundle/opencode-skill-improvement-planner/README.md +1 -0
- phase_loop_runtime/skills_bundle/opencode-skill-improvement-planner/SKILL.md +109 -0
- phase_loop_runtime/skills_bundle/opencode-skill-improvement-planner/assets/aggregator_prompt.md +79 -0
- phase_loop_runtime/skills_bundle/opencode-task-contextualizer/README.md +1 -0
- phase_loop_runtime/skills_bundle/opencode-task-contextualizer/SKILL.md +98 -0
- phase_loop_runtime/skills_bundle/opencode-task-contextualizer/references/task-templates.md +103 -0
- phase_loop_runtime/state.py +156 -0
- phase_loop_runtime/state_degradation.py +136 -0
- phase_loop_runtime/state_ops.py +676 -0
- phase_loop_runtime/train_ledger.py +215 -0
- phase_loop_runtime/train_roadmap.py +339 -0
- phase_loop_runtime/train_runner.py +1197 -0
- phase_loop_runtime/verification_evidence.py +650 -0
- phase_loop_runtime/verification_evidence_validator.py +75 -0
- phase_loop_runtime/visual_evidence_validator.py +36 -0
- phase_loop_runtime/worker_pool.py +123 -0
- phase_loop_runtime/worktree_index.py +270 -0
- phase_loop_runtime-0.2.0.data/data/share/phase-loop-runtime/protocol/protocol.md +2475 -0
- phase_loop_runtime-0.2.0.dist-info/METADATA +106 -0
- phase_loop_runtime-0.2.0.dist-info/RECORD +370 -0
- phase_loop_runtime-0.2.0.dist-info/WHEEL +5 -0
- phase_loop_runtime-0.2.0.dist-info/entry_points.txt +9 -0
- phase_loop_runtime-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,835 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from .models import (
|
|
6
|
+
ClaudeTeamPolicy,
|
|
7
|
+
DispatchDecision,
|
|
8
|
+
DispatchHints,
|
|
9
|
+
ExecutorCapabilityRecord,
|
|
10
|
+
NORMALIZED_EFFORT_LEVELS,
|
|
11
|
+
PRODUCT_LOOP_ACTIONS,
|
|
12
|
+
ProviderPolicyCapability,
|
|
13
|
+
UNSUPPORTED_POLICY_BEHAVIORS,
|
|
14
|
+
WORK_UNIT_KINDS,
|
|
15
|
+
)
|
|
16
|
+
from .state_degradation import active_degraded_executors
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
DEFAULT_EXECUTOR = "codex"
|
|
20
|
+
DEFAULT_LANE_EXECUTOR = "pi"
|
|
21
|
+
CLAUDE_HEAVY_MODEL = "claude-opus-4-8"
|
|
22
|
+
_CLAUDE_BASE_ALLOWED_TOOLS = ("Bash", "Read", "Edit", "MultiEdit", "Write", "Glob", "Grep", "LS")
|
|
23
|
+
_CLAUDE_COLLABORATION_TOOLS = (
|
|
24
|
+
"Agent",
|
|
25
|
+
"TaskCreate",
|
|
26
|
+
"TaskUpdate",
|
|
27
|
+
"TaskList",
|
|
28
|
+
"TeamCreate",
|
|
29
|
+
"TeamDelete",
|
|
30
|
+
"SendMessage",
|
|
31
|
+
"EnterWorktree",
|
|
32
|
+
"ExitWorktree",
|
|
33
|
+
"ToolSearch",
|
|
34
|
+
)
|
|
35
|
+
_CLAUDE_BASE_DISALLOWED_TOOLS = (
|
|
36
|
+
"Agent",
|
|
37
|
+
"TaskCreate",
|
|
38
|
+
"TaskUpdate",
|
|
39
|
+
"TaskList",
|
|
40
|
+
"TeamCreate",
|
|
41
|
+
"TeamDelete",
|
|
42
|
+
"SendMessage",
|
|
43
|
+
"EnterWorktree",
|
|
44
|
+
"ExitWorktree",
|
|
45
|
+
"AskUserQuestion",
|
|
46
|
+
"ExitPlanMode",
|
|
47
|
+
"ToolSearch",
|
|
48
|
+
"advisor",
|
|
49
|
+
)
|
|
50
|
+
_CLAUDE_SUBAGENT_ALLOWED_TOOLS = _CLAUDE_BASE_ALLOWED_TOOLS + (
|
|
51
|
+
"Agent",
|
|
52
|
+
"TaskCreate",
|
|
53
|
+
"TaskUpdate",
|
|
54
|
+
"TaskList",
|
|
55
|
+
"SendMessage",
|
|
56
|
+
"ToolSearch",
|
|
57
|
+
)
|
|
58
|
+
_CLAUDE_TEAM_ALLOWED_TOOLS = _CLAUDE_BASE_ALLOWED_TOOLS + _CLAUDE_COLLABORATION_TOOLS
|
|
59
|
+
_CLAUDE_TEAM_DISALLOWED_TOOLS = (
|
|
60
|
+
"AskUserQuestion",
|
|
61
|
+
"ExitPlanMode",
|
|
62
|
+
"advisor",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
_ACTION_DEFAULT_PROFILES = {
|
|
66
|
+
"roadmap": "roadmap",
|
|
67
|
+
"plan": "plan",
|
|
68
|
+
"execute": "execute",
|
|
69
|
+
"repair": "repair",
|
|
70
|
+
"review": "review",
|
|
71
|
+
"maintain-skills": "skill-maintenance",
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
DEFAULT_CAPABILITY_REGISTRY = {
|
|
75
|
+
"codex": ExecutorCapabilityRecord(
|
|
76
|
+
executor="codex",
|
|
77
|
+
supported_actions=PRODUCT_LOOP_ACTIONS,
|
|
78
|
+
capabilities=(
|
|
79
|
+
"live_launch",
|
|
80
|
+
"dry_run",
|
|
81
|
+
"skill_bundle_injection",
|
|
82
|
+
"subagents",
|
|
83
|
+
"explicit_approval_controls",
|
|
84
|
+
"structured_output",
|
|
85
|
+
),
|
|
86
|
+
strengths=("repo-native execution", "stable automation contract", "shared phase-loop ownership"),
|
|
87
|
+
limits=("requires local Codex subscription auth",),
|
|
88
|
+
injection_mode="prompt_only",
|
|
89
|
+
permission_posture="explicit",
|
|
90
|
+
subagent_posture="native",
|
|
91
|
+
live_available=True,
|
|
92
|
+
dry_run_available=True,
|
|
93
|
+
live_proof_gate="none",
|
|
94
|
+
promotion_status="live",
|
|
95
|
+
promotion_requirements=("shared launch contract", "shared terminal summary contract"),
|
|
96
|
+
auth_preflight_mode="metadata_only",
|
|
97
|
+
auth_preflight_probes=("codex --version", "codex --help", "codex login status"),
|
|
98
|
+
timeout_posture="runner_managed",
|
|
99
|
+
output_capture_format="json_stream",
|
|
100
|
+
default_model_profiles=dict(_ACTION_DEFAULT_PROFILES),
|
|
101
|
+
),
|
|
102
|
+
"claude": ExecutorCapabilityRecord(
|
|
103
|
+
executor="claude",
|
|
104
|
+
supported_actions=("roadmap", "plan", "execute", "repair", "review"),
|
|
105
|
+
capabilities=(
|
|
106
|
+
"live_launch",
|
|
107
|
+
"dry_run",
|
|
108
|
+
"skill_bundle_injection",
|
|
109
|
+
"inline_instructions",
|
|
110
|
+
"context_file_instructions",
|
|
111
|
+
"subagents",
|
|
112
|
+
"explicit_approval_controls",
|
|
113
|
+
"structured_output",
|
|
114
|
+
),
|
|
115
|
+
strengths=("native prompt injection", "documented effort controls", "authenticated local CLI"),
|
|
116
|
+
limits=(
|
|
117
|
+
"requires local Claude subscription auth",
|
|
118
|
+
"current autonomous live proof is blocked on non-interactive closeout parity",
|
|
119
|
+
),
|
|
120
|
+
injection_mode="inline",
|
|
121
|
+
permission_posture="explicit",
|
|
122
|
+
subagent_posture="native",
|
|
123
|
+
live_available=True,
|
|
124
|
+
dry_run_available=True,
|
|
125
|
+
live_proof_gate="disposable_proof_required",
|
|
126
|
+
promotion_status="proof_gated",
|
|
127
|
+
promotion_requirements=(
|
|
128
|
+
"fake harness parity regression proof",
|
|
129
|
+
"disposable live roadmap proof",
|
|
130
|
+
"launch.json",
|
|
131
|
+
"terminal-summary.json",
|
|
132
|
+
),
|
|
133
|
+
auth_preflight_mode="metadata_only",
|
|
134
|
+
auth_preflight_probes=("claude --version", "claude --help", "claude auth status"),
|
|
135
|
+
timeout_posture="runner_managed",
|
|
136
|
+
output_capture_format="terminal_summary",
|
|
137
|
+
known_failure_cases=(
|
|
138
|
+
"non_interactive_timeout",
|
|
139
|
+
"empty_or_unusable_output_capture",
|
|
140
|
+
"missing_automation_block",
|
|
141
|
+
"missing_terminal_summary",
|
|
142
|
+
"stale_handoff_after_repair",
|
|
143
|
+
),
|
|
144
|
+
default_model_profiles={action: _ACTION_DEFAULT_PROFILES[action] for action in ("roadmap", "plan", "execute", "repair", "review")},
|
|
145
|
+
default_claude_execution_mode="solo",
|
|
146
|
+
claude_execution_policies=(
|
|
147
|
+
ClaudeTeamPolicy(
|
|
148
|
+
execution_mode="solo",
|
|
149
|
+
maturity_label="proof_blocked",
|
|
150
|
+
live_proof_gate="disposable_proof_required",
|
|
151
|
+
promotion_status="proof_gated",
|
|
152
|
+
launch_default=True,
|
|
153
|
+
default_model=CLAUDE_HEAVY_MODEL,
|
|
154
|
+
default_effort="high",
|
|
155
|
+
budget_guidance={"mode": "metadata_only", "notes": "Native solo launch keeps team fanout at zero."},
|
|
156
|
+
allowed_actions=("roadmap", "plan", "execute", "repair", "review"),
|
|
157
|
+
allowed_tools=_CLAUDE_BASE_ALLOWED_TOOLS,
|
|
158
|
+
disallowed_tools=_CLAUDE_BASE_DISALLOWED_TOOLS,
|
|
159
|
+
task_lifecycle_supported=False,
|
|
160
|
+
),
|
|
161
|
+
ClaudeTeamPolicy(
|
|
162
|
+
execution_mode="subagent",
|
|
163
|
+
maturity_label="experimental",
|
|
164
|
+
live_proof_gate="disposable_proof_required",
|
|
165
|
+
promotion_status="proof_gated",
|
|
166
|
+
max_native_tasks=2,
|
|
167
|
+
max_delegation_depth=1,
|
|
168
|
+
max_fanout=2,
|
|
169
|
+
default_model=CLAUDE_HEAVY_MODEL,
|
|
170
|
+
default_effort="high",
|
|
171
|
+
budget_guidance={"mode": "metadata_only", "max_cost_usd": 3.0, "notes": "Bounded native subagent fanout only."},
|
|
172
|
+
allowed_actions=("execute", "repair", "review"),
|
|
173
|
+
disallowed_actions=("roadmap", "plan", "maintain-skills"),
|
|
174
|
+
allowed_tools=_CLAUDE_SUBAGENT_ALLOWED_TOOLS,
|
|
175
|
+
disallowed_tools=_CLAUDE_TEAM_DISALLOWED_TOOLS + ("TeamCreate", "TeamDelete", "EnterWorktree", "ExitWorktree"),
|
|
176
|
+
requires_disjoint_owned_files=True,
|
|
177
|
+
task_lifecycle_supported=True,
|
|
178
|
+
),
|
|
179
|
+
ClaudeTeamPolicy(
|
|
180
|
+
execution_mode="agent_team",
|
|
181
|
+
maturity_label="experimental",
|
|
182
|
+
live_proof_gate="disposable_proof_required",
|
|
183
|
+
promotion_status="proof_gated",
|
|
184
|
+
max_teammates=3,
|
|
185
|
+
max_native_tasks=4,
|
|
186
|
+
max_delegation_depth=1,
|
|
187
|
+
max_fanout=2,
|
|
188
|
+
default_model=CLAUDE_HEAVY_MODEL,
|
|
189
|
+
default_effort="high",
|
|
190
|
+
budget_guidance={"mode": "metadata_only", "max_cost_usd": 5.0, "notes": "Task-list or teammate activity stays gated behind TEAMGOV and TASKLEDGER evidence."},
|
|
191
|
+
allowed_actions=("execute", "repair", "review"),
|
|
192
|
+
disallowed_actions=("roadmap", "plan", "maintain-skills"),
|
|
193
|
+
allowed_tools=_CLAUDE_TEAM_ALLOWED_TOOLS,
|
|
194
|
+
disallowed_tools=_CLAUDE_TEAM_DISALLOWED_TOOLS,
|
|
195
|
+
requires_disjoint_owned_files=True,
|
|
196
|
+
direct_teammate_messaging_allowed=True,
|
|
197
|
+
task_lifecycle_supported=True,
|
|
198
|
+
),
|
|
199
|
+
),
|
|
200
|
+
),
|
|
201
|
+
"gemini": ExecutorCapabilityRecord(
|
|
202
|
+
executor="gemini",
|
|
203
|
+
supported_actions=("roadmap", "plan", "execute", "repair", "review"),
|
|
204
|
+
# v46 EXEC: agy (the gemini executor's CLI) has NO --output-format (the
|
|
205
|
+
# closeout is prompt-injected + text-parsed) and NO granular approval mode, so
|
|
206
|
+
# `structured_output` and `explicit_approval_controls` are dropped here.
|
|
207
|
+
capabilities=(
|
|
208
|
+
"live_launch",
|
|
209
|
+
"dry_run",
|
|
210
|
+
"skill_bundle_injection",
|
|
211
|
+
"inline_instructions",
|
|
212
|
+
"context_file_instructions",
|
|
213
|
+
),
|
|
214
|
+
strengths=("native skill ecosystem", "context-file friendly", "authenticated local CLI"),
|
|
215
|
+
# v46 EXEC: the gemini executor now drives the Antigravity CLI (`agy`); the
|
|
216
|
+
# standalone gemini CLI was sunset. agy auth is a subscription OAuth token.
|
|
217
|
+
# NOTE: write actions auto-approve via --dangerously-skip-permissions
|
|
218
|
+
# (permissive-in-effect); `review` stays read-only. Flipping permission_posture
|
|
219
|
+
# to `permissive` (forcing explicit opt-in) is a follow-up product decision.
|
|
220
|
+
limits=(
|
|
221
|
+
"requires local Antigravity (agy) subscription auth",
|
|
222
|
+
"agy has no granular approval mode: write actions auto-approve, review is read-only",
|
|
223
|
+
"agy emits no structured JSON; closeout is prompt-injected and text-parsed",
|
|
224
|
+
),
|
|
225
|
+
injection_mode="context_file",
|
|
226
|
+
permission_posture="explicit",
|
|
227
|
+
subagent_posture="limited",
|
|
228
|
+
live_available=True,
|
|
229
|
+
dry_run_available=True,
|
|
230
|
+
live_proof_gate="disposable_proof_recorded",
|
|
231
|
+
promotion_status="live",
|
|
232
|
+
promotion_requirements=(
|
|
233
|
+
"fake harness parity regression proof",
|
|
234
|
+
"disposable live roadmap proof",
|
|
235
|
+
"launch.json",
|
|
236
|
+
"terminal-summary.json",
|
|
237
|
+
),
|
|
238
|
+
auth_preflight_mode="metadata_only",
|
|
239
|
+
auth_preflight_probes=("agy --version", "agy --help"),
|
|
240
|
+
timeout_posture="runner_managed",
|
|
241
|
+
output_capture_format="terminal_summary",
|
|
242
|
+
default_model_profiles={action: _ACTION_DEFAULT_PROFILES[action] for action in ("roadmap", "plan", "execute", "repair", "review")},
|
|
243
|
+
),
|
|
244
|
+
"opencode": ExecutorCapabilityRecord(
|
|
245
|
+
executor="opencode",
|
|
246
|
+
supported_actions=("roadmap", "plan", "execute", "repair", "review"),
|
|
247
|
+
capabilities=(
|
|
248
|
+
"live_launch",
|
|
249
|
+
"dry_run",
|
|
250
|
+
"skill_bundle_injection",
|
|
251
|
+
"inline_instructions",
|
|
252
|
+
"context_file_instructions",
|
|
253
|
+
"explicit_approval_controls",
|
|
254
|
+
"structured_output",
|
|
255
|
+
),
|
|
256
|
+
strengths=("agent-oriented CLI", "context-file delivery"),
|
|
257
|
+
limits=("requires local OpenCode subscription auth", "live launch requires explicit opt-in when the selected agent posture is permissive"),
|
|
258
|
+
injection_mode="context_file",
|
|
259
|
+
permission_posture="explicit",
|
|
260
|
+
subagent_posture="limited",
|
|
261
|
+
live_available=True,
|
|
262
|
+
dry_run_available=True,
|
|
263
|
+
live_proof_gate="disposable_proof_recorded",
|
|
264
|
+
promotion_status="live",
|
|
265
|
+
promotion_requirements=(
|
|
266
|
+
"fake harness parity regression proof",
|
|
267
|
+
"disposable live roadmap proof",
|
|
268
|
+
"launch.json",
|
|
269
|
+
"terminal-summary.json",
|
|
270
|
+
),
|
|
271
|
+
auth_preflight_mode="metadata_only",
|
|
272
|
+
auth_preflight_probes=("opencode --version", "opencode run --help", "opencode agent list"),
|
|
273
|
+
timeout_posture="runner_managed",
|
|
274
|
+
output_capture_format="terminal_summary",
|
|
275
|
+
default_model_profiles={action: _ACTION_DEFAULT_PROFILES[action] for action in ("roadmap", "plan", "execute", "repair", "review")},
|
|
276
|
+
),
|
|
277
|
+
"pi": ExecutorCapabilityRecord(
|
|
278
|
+
executor="pi",
|
|
279
|
+
supported_actions=("roadmap", "plan", "execute", "repair", "review"),
|
|
280
|
+
capabilities=(
|
|
281
|
+
"live_launch",
|
|
282
|
+
"dry_run",
|
|
283
|
+
"skill_bundle_injection",
|
|
284
|
+
"context_file_instructions",
|
|
285
|
+
"explicit_approval_controls",
|
|
286
|
+
"structured_output",
|
|
287
|
+
),
|
|
288
|
+
strengths=(
|
|
289
|
+
"repo-local phase-loop-pi package",
|
|
290
|
+
"bounded simple-lane child runner",
|
|
291
|
+
"shared automation closeout contract",
|
|
292
|
+
),
|
|
293
|
+
limits=(
|
|
294
|
+
"requires local Pi Agent CLI and provider auth outside phase-loop",
|
|
295
|
+
"not a global scheduler, runtime ledger owner, worktree allocator, or merge reducer",
|
|
296
|
+
),
|
|
297
|
+
injection_mode="context_file",
|
|
298
|
+
permission_posture="explicit",
|
|
299
|
+
subagent_posture="none",
|
|
300
|
+
live_available=True,
|
|
301
|
+
dry_run_available=True,
|
|
302
|
+
live_proof_gate="disposable_proof_recorded",
|
|
303
|
+
promotion_status="live",
|
|
304
|
+
promotion_requirements=(
|
|
305
|
+
"fake harness parity regression proof",
|
|
306
|
+
"fake Pi adapter matrix",
|
|
307
|
+
"launch.json",
|
|
308
|
+
"terminal-summary.json",
|
|
309
|
+
),
|
|
310
|
+
auth_preflight_mode="metadata_only",
|
|
311
|
+
auth_preflight_probes=("pi --version", "pi --help"),
|
|
312
|
+
timeout_posture="runner_managed",
|
|
313
|
+
output_capture_format="terminal_summary",
|
|
314
|
+
default_model_profiles={action: _ACTION_DEFAULT_PROFILES[action] for action in ("roadmap", "plan", "execute", "repair", "review")},
|
|
315
|
+
),
|
|
316
|
+
"command": ExecutorCapabilityRecord(
|
|
317
|
+
executor="command",
|
|
318
|
+
supported_actions=("roadmap", "plan", "execute", "repair", "review"),
|
|
319
|
+
capabilities=("live_launch", "dry_run", "context_file_instructions", "structured_output"),
|
|
320
|
+
strengths=("explicit command wrapper", "runner-owned launch artifacts"),
|
|
321
|
+
limits=("requires explicit adapter template", "non-default executor", "unsupported command shapes fail closed"),
|
|
322
|
+
injection_mode="context_file",
|
|
323
|
+
permission_posture="manual",
|
|
324
|
+
subagent_posture="none",
|
|
325
|
+
live_available=True,
|
|
326
|
+
dry_run_available=True,
|
|
327
|
+
live_proof_gate="none",
|
|
328
|
+
promotion_status="manual_only",
|
|
329
|
+
promotion_requirements=(
|
|
330
|
+
"fake harness parity regression proof",
|
|
331
|
+
"typed adapter contract",
|
|
332
|
+
"explicit operator selection",
|
|
333
|
+
"launch.json",
|
|
334
|
+
"terminal-summary.json",
|
|
335
|
+
),
|
|
336
|
+
timeout_posture="runner_managed",
|
|
337
|
+
output_capture_format="terminal_summary",
|
|
338
|
+
default_model_profiles={
|
|
339
|
+
"roadmap": _ACTION_DEFAULT_PROFILES["roadmap"],
|
|
340
|
+
"plan": _ACTION_DEFAULT_PROFILES["plan"],
|
|
341
|
+
"execute": _ACTION_DEFAULT_PROFILES["execute"],
|
|
342
|
+
"repair": _ACTION_DEFAULT_PROFILES["repair"],
|
|
343
|
+
"review": _ACTION_DEFAULT_PROFILES["review"],
|
|
344
|
+
},
|
|
345
|
+
),
|
|
346
|
+
"manual": ExecutorCapabilityRecord(
|
|
347
|
+
executor="manual",
|
|
348
|
+
supported_actions=("repair", "review"),
|
|
349
|
+
capabilities=("dry_run", "manual_handoff"),
|
|
350
|
+
strengths=("operator handoff"),
|
|
351
|
+
limits=("metadata-only until manual import completes",),
|
|
352
|
+
injection_mode="manual",
|
|
353
|
+
permission_posture="manual",
|
|
354
|
+
subagent_posture="none",
|
|
355
|
+
live_available=False,
|
|
356
|
+
dry_run_available=True,
|
|
357
|
+
promotion_status="manual_only",
|
|
358
|
+
promotion_requirements=("manual import", "shared automation handoff"),
|
|
359
|
+
timeout_posture="unknown",
|
|
360
|
+
default_model_profiles={"repair": "repair", "review": "review"},
|
|
361
|
+
),
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
DEFAULT_EXECUTOR_POLICY = {
|
|
365
|
+
"roadmap": "codex",
|
|
366
|
+
"plan": "codex",
|
|
367
|
+
"execute": "codex",
|
|
368
|
+
"repair": "codex",
|
|
369
|
+
"review": "codex",
|
|
370
|
+
"maintain-skills": "codex",
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
_ALL_WORK_UNITS = WORK_UNIT_KINDS
|
|
374
|
+
_ALL_EFFORTS = NORMALIZED_EFFORT_LEVELS
|
|
375
|
+
_FAIL_CLOSED = UNSUPPORTED_POLICY_BEHAVIORS[0]
|
|
376
|
+
|
|
377
|
+
DEFAULT_PROVIDER_POLICY_CAPABILITIES = {
|
|
378
|
+
"codex": ProviderPolicyCapability(
|
|
379
|
+
provider="openai",
|
|
380
|
+
executor="codex",
|
|
381
|
+
supported_work_units=_ALL_WORK_UNITS,
|
|
382
|
+
supported_efforts=_ALL_EFFORTS,
|
|
383
|
+
unsupported_policy_behavior=_FAIL_CLOSED,
|
|
384
|
+
default_effort="medium",
|
|
385
|
+
effort_map={effort: effort for effort in _ALL_EFFORTS},
|
|
386
|
+
notes=("Codex/OpenAI accepts normalized reasoning effort metadata directly.",),
|
|
387
|
+
),
|
|
388
|
+
"claude": ProviderPolicyCapability(
|
|
389
|
+
provider="claude-code",
|
|
390
|
+
executor="claude",
|
|
391
|
+
supported_work_units=_ALL_WORK_UNITS,
|
|
392
|
+
supported_efforts=("low", "medium", "high", "max"),
|
|
393
|
+
unsupported_policy_behavior=_FAIL_CLOSED,
|
|
394
|
+
default_effort="high",
|
|
395
|
+
effort_map={
|
|
396
|
+
"minimal": "low",
|
|
397
|
+
"low": "low",
|
|
398
|
+
"medium": "medium",
|
|
399
|
+
"high": "high",
|
|
400
|
+
"xhigh": "max",
|
|
401
|
+
"max": "max",
|
|
402
|
+
},
|
|
403
|
+
notes=("Claude Code has documented effort controls but no separate xhigh literal.",),
|
|
404
|
+
),
|
|
405
|
+
"gemini": ProviderPolicyCapability(
|
|
406
|
+
provider="gemini-cli",
|
|
407
|
+
executor="gemini",
|
|
408
|
+
supported_work_units=_ALL_WORK_UNITS,
|
|
409
|
+
supported_efforts=("medium", "high"),
|
|
410
|
+
unsupported_policy_behavior=_FAIL_CLOSED,
|
|
411
|
+
default_effort="medium",
|
|
412
|
+
effort_map={
|
|
413
|
+
"minimal": "medium",
|
|
414
|
+
"low": "medium",
|
|
415
|
+
"medium": "medium",
|
|
416
|
+
"high": "high",
|
|
417
|
+
"xhigh": "high",
|
|
418
|
+
"max": "high",
|
|
419
|
+
},
|
|
420
|
+
model_aliases={
|
|
421
|
+
"roadmap_build": "phase-loop-plan-high",
|
|
422
|
+
"phase_plan": "phase-loop-plan-high",
|
|
423
|
+
"lane_execute": "phase-loop-execute-medium",
|
|
424
|
+
"lane_review": "phase-loop-review-high",
|
|
425
|
+
"phase_reducer": "phase-loop-review-high",
|
|
426
|
+
"phase_verify": "phase-loop-review-high",
|
|
427
|
+
"repair": "phase-loop-execute-medium",
|
|
428
|
+
"closeout": "phase-loop-review-high",
|
|
429
|
+
},
|
|
430
|
+
requires_run_local_user_scope=True,
|
|
431
|
+
notes=(
|
|
432
|
+
"Gemini CLI fallback stays CLI-based and reason-coded; API-key execution requires an explicit command adapter.",
|
|
433
|
+
"Gemini CLI defaults use built-in routing aliases (`pro` for planning/review and `auto` for execution/repair) to preserve CLI fallback behavior.",
|
|
434
|
+
"Model-routing-v3 uses explicit `Gemini 3.5 Flash (High)` for implementer/worker model_class routing, but Gemini remains capped at high effort and is not max-effort planner-of-record eligible.",
|
|
435
|
+
"Run-local user-scope modelConfigs.customAliases remain available only for explicit phase-loop thinking-level proof runs.",
|
|
436
|
+
"thinkingConfig.thinkingLevel is carried by custom aliases and is not exposed as a CLI flag.",
|
|
437
|
+
),
|
|
438
|
+
),
|
|
439
|
+
"gemini-api": ProviderPolicyCapability(
|
|
440
|
+
provider="gemini-api-openai-compatible",
|
|
441
|
+
executor="command",
|
|
442
|
+
supported_work_units=_ALL_WORK_UNITS,
|
|
443
|
+
supported_efforts=("medium", "high"),
|
|
444
|
+
unsupported_policy_behavior=_FAIL_CLOSED,
|
|
445
|
+
default_effort="medium",
|
|
446
|
+
effort_map={
|
|
447
|
+
"minimal": "medium",
|
|
448
|
+
"low": "medium",
|
|
449
|
+
"medium": "medium",
|
|
450
|
+
"high": "high",
|
|
451
|
+
"xhigh": "high",
|
|
452
|
+
"max": "high",
|
|
453
|
+
},
|
|
454
|
+
notes=("Gemini API/OpenAI-compatible policy is command-adapter metadata only in v8.",),
|
|
455
|
+
),
|
|
456
|
+
"opencode": ProviderPolicyCapability(
|
|
457
|
+
provider="opencode",
|
|
458
|
+
executor="opencode",
|
|
459
|
+
supported_work_units=_ALL_WORK_UNITS,
|
|
460
|
+
supported_efforts=_ALL_EFFORTS,
|
|
461
|
+
unsupported_policy_behavior=_FAIL_CLOSED,
|
|
462
|
+
default_effort="medium",
|
|
463
|
+
effort_map={effort: effort for effort in _ALL_EFFORTS},
|
|
464
|
+
notes=("OpenCode policy is normalized for future adapter selection without changing dispatch.",),
|
|
465
|
+
),
|
|
466
|
+
"pi": ProviderPolicyCapability(
|
|
467
|
+
provider="pi-agent",
|
|
468
|
+
executor="pi",
|
|
469
|
+
supported_work_units=_ALL_WORK_UNITS,
|
|
470
|
+
supported_efforts=("low", "medium", "high"),
|
|
471
|
+
unsupported_policy_behavior=_FAIL_CLOSED,
|
|
472
|
+
default_effort="medium",
|
|
473
|
+
effort_map={
|
|
474
|
+
"minimal": "low",
|
|
475
|
+
"low": "low",
|
|
476
|
+
"medium": "medium",
|
|
477
|
+
"high": "high",
|
|
478
|
+
"xhigh": "high",
|
|
479
|
+
"max": "high",
|
|
480
|
+
},
|
|
481
|
+
notes=(
|
|
482
|
+
"Pi Agent is the default executor for simple bounded scheduler-assigned lane execution.",
|
|
483
|
+
"Pi Agent runner path is repo-local and bounded to one scheduler-assigned lane.",
|
|
484
|
+
"Claude/Anthropic model work defaults to Claude Code CLI unless policy explicitly selects a Pi-wrapped Claude route with an override reason.",
|
|
485
|
+
"Unsupported effort or tool-policy requests fail closed unless the phase policy explicitly falls back.",
|
|
486
|
+
),
|
|
487
|
+
),
|
|
488
|
+
"command": ProviderPolicyCapability(
|
|
489
|
+
provider="generic-command-adapter",
|
|
490
|
+
executor="command",
|
|
491
|
+
supported_work_units=_ALL_WORK_UNITS,
|
|
492
|
+
supported_efforts=_ALL_EFFORTS,
|
|
493
|
+
unsupported_policy_behavior=_FAIL_CLOSED,
|
|
494
|
+
default_effort="medium",
|
|
495
|
+
effort_map={effort: effort for effort in _ALL_EFFORTS},
|
|
496
|
+
notes=("Generic command adapters must fail closed when unsupported policy cannot be mapped.",),
|
|
497
|
+
),
|
|
498
|
+
"manual": ProviderPolicyCapability(
|
|
499
|
+
provider="manual-handoff",
|
|
500
|
+
executor="manual",
|
|
501
|
+
supported_work_units=_ALL_WORK_UNITS,
|
|
502
|
+
supported_efforts=_ALL_EFFORTS,
|
|
503
|
+
unsupported_policy_behavior=_FAIL_CLOSED,
|
|
504
|
+
default_effort="medium",
|
|
505
|
+
effort_map={effort: effort for effort in _ALL_EFFORTS},
|
|
506
|
+
notes=("Manual handoff is non-default and must be selected explicitly.",),
|
|
507
|
+
),
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def capability_registry() -> dict[str, ExecutorCapabilityRecord]:
|
|
512
|
+
return DEFAULT_CAPABILITY_REGISTRY
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
def provider_policy_capabilities() -> dict[str, ProviderPolicyCapability]:
|
|
516
|
+
return DEFAULT_PROVIDER_POLICY_CAPABILITIES
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
def claude_support_slice_posture() -> dict[str, dict[str, object]]:
|
|
520
|
+
record = DEFAULT_CAPABILITY_REGISTRY["claude"]
|
|
521
|
+
policy_by_mode = {
|
|
522
|
+
policy.execution_mode: policy for policy in record.claude_execution_policies
|
|
523
|
+
}
|
|
524
|
+
solo = policy_by_mode["solo"]
|
|
525
|
+
subagent = policy_by_mode["subagent"]
|
|
526
|
+
agent_team = policy_by_mode["agent_team"]
|
|
527
|
+
return {
|
|
528
|
+
"claude_solo": {
|
|
529
|
+
"execution_mode": "solo",
|
|
530
|
+
"maturity_label": solo.maturity_label,
|
|
531
|
+
"live_proof_gate": solo.live_proof_gate,
|
|
532
|
+
"promotion_status": solo.promotion_status,
|
|
533
|
+
"launch_default": solo.launch_default,
|
|
534
|
+
"requires_disjoint_owned_files": solo.requires_disjoint_owned_files,
|
|
535
|
+
"allows_read_only_lanes": solo.allows_read_only_lanes,
|
|
536
|
+
"max_delegation_depth": 0,
|
|
537
|
+
"max_fanout": 0,
|
|
538
|
+
"budget_guidance": solo.budget_guidance,
|
|
539
|
+
},
|
|
540
|
+
"claude_delegated_worker": {
|
|
541
|
+
"execution_mode": "delegated_worker",
|
|
542
|
+
"maturity_label": "proof_blocked",
|
|
543
|
+
"live_proof_gate": record.live_proof_gate,
|
|
544
|
+
"promotion_status": record.promotion_status,
|
|
545
|
+
"launch_default": False,
|
|
546
|
+
"requires_disjoint_owned_files": True,
|
|
547
|
+
"allows_read_only_lanes": True,
|
|
548
|
+
"max_delegation_depth": 1,
|
|
549
|
+
"max_fanout": 1,
|
|
550
|
+
"budget_guidance": {
|
|
551
|
+
"mode": "metadata_only",
|
|
552
|
+
"notes": "Runner-brokered Claude child work stays bounded by typed delegation budget metadata.",
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
"claude_subagent": {
|
|
556
|
+
"execution_mode": "subagent",
|
|
557
|
+
"maturity_label": subagent.maturity_label,
|
|
558
|
+
"live_proof_gate": subagent.live_proof_gate,
|
|
559
|
+
"promotion_status": subagent.promotion_status,
|
|
560
|
+
"launch_default": subagent.launch_default,
|
|
561
|
+
"requires_disjoint_owned_files": subagent.requires_disjoint_owned_files,
|
|
562
|
+
"allows_read_only_lanes": subagent.allows_read_only_lanes,
|
|
563
|
+
"max_delegation_depth": subagent.max_delegation_depth,
|
|
564
|
+
"max_fanout": subagent.max_fanout,
|
|
565
|
+
"budget_guidance": subagent.budget_guidance,
|
|
566
|
+
},
|
|
567
|
+
"claude_agent_team": {
|
|
568
|
+
"execution_mode": "agent_team",
|
|
569
|
+
"maturity_label": agent_team.maturity_label,
|
|
570
|
+
"live_proof_gate": agent_team.live_proof_gate,
|
|
571
|
+
"promotion_status": agent_team.promotion_status,
|
|
572
|
+
"launch_default": agent_team.launch_default,
|
|
573
|
+
"requires_disjoint_owned_files": agent_team.requires_disjoint_owned_files,
|
|
574
|
+
"allows_read_only_lanes": agent_team.allows_read_only_lanes,
|
|
575
|
+
"max_delegation_depth": agent_team.max_delegation_depth,
|
|
576
|
+
"max_fanout": agent_team.max_fanout,
|
|
577
|
+
"budget_guidance": agent_team.budget_guidance,
|
|
578
|
+
},
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
def claude_team_capability_posture() -> dict[str, dict[str, object]]:
|
|
583
|
+
slice_posture = claude_support_slice_posture()
|
|
584
|
+
return {
|
|
585
|
+
"solo": slice_posture["claude_solo"],
|
|
586
|
+
"subagent": slice_posture["claude_subagent"],
|
|
587
|
+
"agent_team": slice_posture["claude_agent_team"],
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
def default_executor_for_action(action: str) -> str:
|
|
592
|
+
if action == "maintain-skills":
|
|
593
|
+
return "codex"
|
|
594
|
+
return DEFAULT_EXECUTOR_POLICY.get(action, DEFAULT_EXECUTOR)
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
def default_executor_for_work_unit(work_unit_kind: str, *, scheduler_assigned: bool = False) -> str:
|
|
598
|
+
if scheduler_assigned and work_unit_kind == "lane_execute":
|
|
599
|
+
return DEFAULT_LANE_EXECUTOR
|
|
600
|
+
return default_executor_for_action("execute" if work_unit_kind == "lane_execute" else "review")
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
def merge_dispatch_hints(
|
|
604
|
+
*,
|
|
605
|
+
action: str,
|
|
606
|
+
operator: DispatchHints | None = None,
|
|
607
|
+
plan: DispatchHints | None = None,
|
|
608
|
+
roadmap: DispatchHints | None = None,
|
|
609
|
+
) -> DispatchHints:
|
|
610
|
+
preferred = _first_nonempty(operator, plan, roadmap, field="preferred_executors")
|
|
611
|
+
allowed = _first_nonempty(operator, plan, roadmap, field="allowed_executors")
|
|
612
|
+
fallback = _first_nonempty(operator, plan, roadmap, field="fallback_executors")
|
|
613
|
+
disabled = _union(operator, plan, roadmap, field="disabled_executors")
|
|
614
|
+
required = _union(operator, plan, roadmap, field="required_capabilities")
|
|
615
|
+
source = _source_name(operator, plan, roadmap, preferred, allowed, fallback)
|
|
616
|
+
return DispatchHints(
|
|
617
|
+
preferred_executors=preferred,
|
|
618
|
+
allowed_executors=allowed,
|
|
619
|
+
fallback_executors=fallback,
|
|
620
|
+
disabled_executors=disabled,
|
|
621
|
+
required_capabilities=required,
|
|
622
|
+
source=source,
|
|
623
|
+
action=action,
|
|
624
|
+
)
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
def resolve_dispatch_decision(
|
|
628
|
+
*,
|
|
629
|
+
action: str,
|
|
630
|
+
dry_run: bool,
|
|
631
|
+
repo: Path | None = None,
|
|
632
|
+
registry: dict[str, ExecutorCapabilityRecord] | None = None,
|
|
633
|
+
operator: DispatchHints | None = None,
|
|
634
|
+
plan: DispatchHints | None = None,
|
|
635
|
+
roadmap: DispatchHints | None = None,
|
|
636
|
+
) -> DispatchDecision:
|
|
637
|
+
registry = registry or capability_registry()
|
|
638
|
+
if action == "maintain-skills":
|
|
639
|
+
return DispatchDecision(
|
|
640
|
+
action=action,
|
|
641
|
+
selected_executor="codex",
|
|
642
|
+
source="maintain-skills-fixed",
|
|
643
|
+
considered_executors=("codex",),
|
|
644
|
+
selected_via="fixed_action_policy",
|
|
645
|
+
)
|
|
646
|
+
|
|
647
|
+
merged = merge_dispatch_hints(action=action, operator=operator, plan=plan, roadmap=roadmap)
|
|
648
|
+
allowed = merged.allowed_executors or tuple(
|
|
649
|
+
executor for executor, record in registry.items() if action in record.supported_actions
|
|
650
|
+
)
|
|
651
|
+
preferred = merged.preferred_executors or (default_executor_for_action(action),)
|
|
652
|
+
fallback = tuple(executor for executor in merged.fallback_executors if executor not in preferred)
|
|
653
|
+
candidate_order = _dedupe((*preferred, *fallback, *allowed, default_executor_for_action(action)))
|
|
654
|
+
considered: list[str] = []
|
|
655
|
+
degraded = active_degraded_executors(repo) if repo is not None and not dry_run else set()
|
|
656
|
+
degraded_viable: list[str] = []
|
|
657
|
+
|
|
658
|
+
for executor in candidate_order:
|
|
659
|
+
considered.append(executor)
|
|
660
|
+
if executor in merged.disabled_executors:
|
|
661
|
+
if executor in preferred:
|
|
662
|
+
return _blocked_decision(
|
|
663
|
+
action,
|
|
664
|
+
merged,
|
|
665
|
+
tuple(considered),
|
|
666
|
+
"disabled_executor",
|
|
667
|
+
f"Dispatch policy rejected `{executor}` for `{action}` because it is disabled by hints.",
|
|
668
|
+
)
|
|
669
|
+
continue
|
|
670
|
+
if executor not in allowed:
|
|
671
|
+
if executor in preferred:
|
|
672
|
+
return _blocked_decision(
|
|
673
|
+
action,
|
|
674
|
+
merged,
|
|
675
|
+
tuple(considered),
|
|
676
|
+
"executor_not_allowed",
|
|
677
|
+
f"Dispatch policy rejected `{executor}` for `{action}` because it is outside the allowed executor set.",
|
|
678
|
+
)
|
|
679
|
+
continue
|
|
680
|
+
record = registry.get(executor)
|
|
681
|
+
if record is None or action not in record.supported_actions:
|
|
682
|
+
if executor in preferred:
|
|
683
|
+
return _blocked_decision(
|
|
684
|
+
action,
|
|
685
|
+
merged,
|
|
686
|
+
tuple(considered),
|
|
687
|
+
"unsupported_action",
|
|
688
|
+
f"Dispatch policy rejected `{executor}` for `{action}` because the registry does not support that action.",
|
|
689
|
+
)
|
|
690
|
+
continue
|
|
691
|
+
missing = tuple(capability for capability in merged.required_capabilities if capability not in record.capabilities)
|
|
692
|
+
if missing:
|
|
693
|
+
if executor in preferred:
|
|
694
|
+
return _blocked_decision(
|
|
695
|
+
action,
|
|
696
|
+
merged,
|
|
697
|
+
tuple(considered),
|
|
698
|
+
"missing_required_capabilities",
|
|
699
|
+
f"Dispatch policy rejected `{executor}` for `{action}` because it lacks required capabilities: {', '.join(missing)}.",
|
|
700
|
+
)
|
|
701
|
+
continue
|
|
702
|
+
if dry_run:
|
|
703
|
+
if not record.dry_run_available:
|
|
704
|
+
continue
|
|
705
|
+
elif not record.live_available:
|
|
706
|
+
if executor in preferred and not fallback:
|
|
707
|
+
return _blocked_decision(
|
|
708
|
+
action,
|
|
709
|
+
merged,
|
|
710
|
+
tuple(considered),
|
|
711
|
+
"live_launch_unavailable",
|
|
712
|
+
f"Dispatch policy selected `{executor}` for `{action}`, but that executor is currently dry-run-only.",
|
|
713
|
+
)
|
|
714
|
+
if executor in preferred and fallback:
|
|
715
|
+
continue
|
|
716
|
+
continue
|
|
717
|
+
if executor in degraded:
|
|
718
|
+
degraded_viable.append(executor)
|
|
719
|
+
continue
|
|
720
|
+
return DispatchDecision(
|
|
721
|
+
action=action,
|
|
722
|
+
selected_executor=executor,
|
|
723
|
+
source=merged.source,
|
|
724
|
+
preferred_executors=preferred,
|
|
725
|
+
allowed_executors=allowed,
|
|
726
|
+
fallback_executors=fallback,
|
|
727
|
+
disabled_executors=merged.disabled_executors,
|
|
728
|
+
required_capabilities=merged.required_capabilities,
|
|
729
|
+
considered_executors=tuple(considered),
|
|
730
|
+
fallback_applied=executor not in preferred,
|
|
731
|
+
selected_via="fallback" if executor not in preferred else "preferred",
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
if degraded_viable:
|
|
735
|
+
return _blocked_decision(
|
|
736
|
+
action,
|
|
737
|
+
merged,
|
|
738
|
+
tuple(considered or candidate_order),
|
|
739
|
+
"all_candidates_session_degraded",
|
|
740
|
+
f"Dispatch policy could not resolve a live executor for `{action}` because all otherwise viable candidates are session-degraded.",
|
|
741
|
+
)
|
|
742
|
+
|
|
743
|
+
return _blocked_decision(
|
|
744
|
+
action,
|
|
745
|
+
merged,
|
|
746
|
+
tuple(considered or candidate_order),
|
|
747
|
+
"no_allowed_executor",
|
|
748
|
+
f"Dispatch policy could not resolve an executor for `{action}` with the current hints and registry.",
|
|
749
|
+
)
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
def describe_dispatch_decision(decision: DispatchDecision) -> str:
|
|
753
|
+
if decision.blocked:
|
|
754
|
+
return decision.blocked_summary or "dispatch blocked"
|
|
755
|
+
parts = [f"selected `{decision.selected_executor}` via {decision.source}"]
|
|
756
|
+
if decision.fallback_applied:
|
|
757
|
+
parts.append("fallback applied")
|
|
758
|
+
if decision.required_capabilities:
|
|
759
|
+
parts.append(f"required capabilities: {', '.join(decision.required_capabilities)}")
|
|
760
|
+
return "; ".join(parts)
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
def default_model_profile_for_executor(action: str, executor: str) -> str:
|
|
764
|
+
record = capability_registry()[executor]
|
|
765
|
+
return record.default_model_profiles.get(action, _ACTION_DEFAULT_PROFILES[action])
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
def _first_nonempty(*hints: DispatchHints | None, field: str) -> tuple[str, ...]:
|
|
769
|
+
for hint in hints:
|
|
770
|
+
if hint is None:
|
|
771
|
+
continue
|
|
772
|
+
values = getattr(hint, field)
|
|
773
|
+
if values:
|
|
774
|
+
return tuple(values)
|
|
775
|
+
return ()
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
def _union(*hints: DispatchHints | None, field: str) -> tuple[str, ...]:
|
|
779
|
+
values: list[str] = []
|
|
780
|
+
for hint in reversed(hints):
|
|
781
|
+
if hint is None:
|
|
782
|
+
continue
|
|
783
|
+
values.extend(getattr(hint, field))
|
|
784
|
+
return _dedupe(values)
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
def _dedupe(values: tuple[str, ...] | list[str] | tuple[str, ...]) -> tuple[str, ...]:
|
|
788
|
+
seen: list[str] = []
|
|
789
|
+
for value in values:
|
|
790
|
+
if value not in seen:
|
|
791
|
+
seen.append(value)
|
|
792
|
+
return tuple(seen)
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
def _source_name(
|
|
796
|
+
operator: DispatchHints | None,
|
|
797
|
+
plan: DispatchHints | None,
|
|
798
|
+
roadmap: DispatchHints | None,
|
|
799
|
+
preferred: tuple[str, ...],
|
|
800
|
+
allowed: tuple[str, ...],
|
|
801
|
+
fallback: tuple[str, ...],
|
|
802
|
+
) -> str:
|
|
803
|
+
for source_name, hint in (("operator", operator), ("plan", plan), ("roadmap", roadmap)):
|
|
804
|
+
if hint is None:
|
|
805
|
+
continue
|
|
806
|
+
if preferred and hint.preferred_executors == preferred:
|
|
807
|
+
return source_name
|
|
808
|
+
if allowed and hint.allowed_executors == allowed:
|
|
809
|
+
return source_name
|
|
810
|
+
if fallback and hint.fallback_executors == fallback:
|
|
811
|
+
return source_name
|
|
812
|
+
return "registry_default"
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
def _blocked_decision(
|
|
816
|
+
action: str,
|
|
817
|
+
merged: DispatchHints,
|
|
818
|
+
considered: tuple[str, ...],
|
|
819
|
+
blocked_reason: str,
|
|
820
|
+
blocked_summary: str,
|
|
821
|
+
) -> DispatchDecision:
|
|
822
|
+
return DispatchDecision(
|
|
823
|
+
action=action,
|
|
824
|
+
selected_executor=None,
|
|
825
|
+
source=merged.source,
|
|
826
|
+
preferred_executors=merged.preferred_executors or (default_executor_for_action(action),),
|
|
827
|
+
allowed_executors=merged.allowed_executors,
|
|
828
|
+
fallback_executors=merged.fallback_executors,
|
|
829
|
+
disabled_executors=merged.disabled_executors,
|
|
830
|
+
required_capabilities=merged.required_capabilities,
|
|
831
|
+
considered_executors=considered,
|
|
832
|
+
blocked_reason=blocked_reason,
|
|
833
|
+
blocked_summary=blocked_summary,
|
|
834
|
+
selected_via=None,
|
|
835
|
+
)
|