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,462 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .capability_registry import (
|
|
4
|
+
CLAUDE_HEAVY_MODEL,
|
|
5
|
+
DEFAULT_EXECUTOR,
|
|
6
|
+
default_model_profile_for_executor,
|
|
7
|
+
provider_policy_capabilities,
|
|
8
|
+
)
|
|
9
|
+
from .models import (
|
|
10
|
+
ExecutionPolicyRule,
|
|
11
|
+
ModelSelection,
|
|
12
|
+
ResolvedExecutionPolicy,
|
|
13
|
+
WorkUnitPolicy,
|
|
14
|
+
require_literal,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
OPENAI_HEAVY_MODEL = "gpt-5.5"
|
|
19
|
+
OPENCODE_OPENAI_HEAVY_MODEL = "openai/gpt-5.5"
|
|
20
|
+
GEMINI_PRO_ROUTED_MODEL = "pro"
|
|
21
|
+
GEMINI_AUTO_ROUTED_MODEL = "auto"
|
|
22
|
+
GEMINI_FLASH_MODEL = "Gemini 3.5 Flash (High)"
|
|
23
|
+
PI_AUTO_ROUTED_MODEL = "auto"
|
|
24
|
+
|
|
25
|
+
DEFAULT_PROFILES = {
|
|
26
|
+
"roadmap": (OPENAI_HEAVY_MODEL, "high"),
|
|
27
|
+
"plan": (OPENAI_HEAVY_MODEL, "high"),
|
|
28
|
+
"execute": (OPENAI_HEAVY_MODEL, "medium"),
|
|
29
|
+
"repair": (OPENAI_HEAVY_MODEL, "medium"),
|
|
30
|
+
"review": (OPENAI_HEAVY_MODEL, "high"),
|
|
31
|
+
"skill-maintenance": (OPENAI_HEAVY_MODEL, "high"),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
ACTION_WORK_UNITS = {
|
|
35
|
+
"roadmap": "roadmap_build",
|
|
36
|
+
"plan": "phase_plan",
|
|
37
|
+
"execute": "lane_execute",
|
|
38
|
+
"repair": "repair",
|
|
39
|
+
"review": "lane_review",
|
|
40
|
+
"maintain-skills": "phase_verify",
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
EXECUTOR_MODEL_OVERRIDES = {
|
|
44
|
+
"claude": {
|
|
45
|
+
"roadmap": CLAUDE_HEAVY_MODEL,
|
|
46
|
+
"plan": CLAUDE_HEAVY_MODEL,
|
|
47
|
+
"execute": CLAUDE_HEAVY_MODEL,
|
|
48
|
+
"repair": CLAUDE_HEAVY_MODEL,
|
|
49
|
+
"review": CLAUDE_HEAVY_MODEL,
|
|
50
|
+
},
|
|
51
|
+
"opencode": {
|
|
52
|
+
"roadmap": OPENCODE_OPENAI_HEAVY_MODEL,
|
|
53
|
+
"plan": OPENCODE_OPENAI_HEAVY_MODEL,
|
|
54
|
+
"execute": OPENCODE_OPENAI_HEAVY_MODEL,
|
|
55
|
+
"repair": OPENCODE_OPENAI_HEAVY_MODEL,
|
|
56
|
+
"review": OPENCODE_OPENAI_HEAVY_MODEL,
|
|
57
|
+
},
|
|
58
|
+
"gemini": {
|
|
59
|
+
"roadmap": GEMINI_PRO_ROUTED_MODEL,
|
|
60
|
+
"plan": GEMINI_PRO_ROUTED_MODEL,
|
|
61
|
+
"execute": GEMINI_AUTO_ROUTED_MODEL,
|
|
62
|
+
"repair": GEMINI_AUTO_ROUTED_MODEL,
|
|
63
|
+
"review": GEMINI_PRO_ROUTED_MODEL,
|
|
64
|
+
},
|
|
65
|
+
"pi": {
|
|
66
|
+
"roadmap": PI_AUTO_ROUTED_MODEL,
|
|
67
|
+
"plan": PI_AUTO_ROUTED_MODEL,
|
|
68
|
+
"execute": PI_AUTO_ROUTED_MODEL,
|
|
69
|
+
"repair": PI_AUTO_ROUTED_MODEL,
|
|
70
|
+
"review": PI_AUTO_ROUTED_MODEL,
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
EXECUTOR_EFFORT_OVERRIDES = {
|
|
75
|
+
"claude": {
|
|
76
|
+
"roadmap": "high",
|
|
77
|
+
"plan": "high",
|
|
78
|
+
"execute": "high",
|
|
79
|
+
"repair": "high",
|
|
80
|
+
"review": "high",
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# --- model-routing-v1: vendor-agnostic model_class -> concrete model ----------
|
|
85
|
+
# Where a provider exposes no separate implementer/worker tier, all classes map
|
|
86
|
+
# to its single model (pi). Non-`phase-loop-` model strings pass through
|
|
87
|
+
# `_resolve_policy_model` unchanged for every executor (claude/codex have no
|
|
88
|
+
# model_aliases; gemini/pi pass through non-alias strings), so these resolve.
|
|
89
|
+
CLAUDE_IMPLEMENTER_MODEL = "claude-sonnet-5"
|
|
90
|
+
CLAUDE_WORKER_MODEL = "claude-haiku-4-5"
|
|
91
|
+
OPENAI_IMPLEMENTER_MODEL = "gpt-5.4"
|
|
92
|
+
OPENAI_WORKER_MODEL = "gpt-5.4-mini"
|
|
93
|
+
OPENCODE_OPENAI_IMPLEMENTER_MODEL = "openai/gpt-5.4"
|
|
94
|
+
OPENCODE_OPENAI_WORKER_MODEL = "openai/gpt-5.4-mini"
|
|
95
|
+
# Gemini planner stays on the CLI `pro` alias; bounded implementer/worker lanes
|
|
96
|
+
# use the validated agy model name directly rather than the broad `auto` alias.
|
|
97
|
+
GEMINI_IMPLEMENTER_MODEL = GEMINI_FLASH_MODEL
|
|
98
|
+
GEMINI_WORKER_MODEL = GEMINI_FLASH_MODEL
|
|
99
|
+
|
|
100
|
+
CLASS_MODEL_OVERRIDES = {
|
|
101
|
+
"claude": {
|
|
102
|
+
"planner": CLAUDE_HEAVY_MODEL,
|
|
103
|
+
"implementer": CLAUDE_IMPLEMENTER_MODEL,
|
|
104
|
+
"worker": CLAUDE_WORKER_MODEL,
|
|
105
|
+
},
|
|
106
|
+
"codex": {
|
|
107
|
+
"planner": OPENAI_HEAVY_MODEL,
|
|
108
|
+
"implementer": OPENAI_IMPLEMENTER_MODEL,
|
|
109
|
+
"worker": OPENAI_WORKER_MODEL,
|
|
110
|
+
},
|
|
111
|
+
"opencode": {
|
|
112
|
+
"planner": OPENCODE_OPENAI_HEAVY_MODEL,
|
|
113
|
+
"implementer": OPENCODE_OPENAI_IMPLEMENTER_MODEL,
|
|
114
|
+
"worker": OPENCODE_OPENAI_WORKER_MODEL,
|
|
115
|
+
},
|
|
116
|
+
"gemini": {
|
|
117
|
+
"planner": GEMINI_PRO_ROUTED_MODEL,
|
|
118
|
+
"implementer": GEMINI_IMPLEMENTER_MODEL,
|
|
119
|
+
"worker": GEMINI_WORKER_MODEL,
|
|
120
|
+
},
|
|
121
|
+
"pi": {
|
|
122
|
+
"planner": PI_AUTO_ROUTED_MODEL,
|
|
123
|
+
"implementer": PI_AUTO_ROUTED_MODEL,
|
|
124
|
+
"worker": PI_AUTO_ROUTED_MODEL,
|
|
125
|
+
},
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def resolve_model_class(executor: str, model_class: str) -> str | None:
|
|
130
|
+
"""Map (model_class, executor) -> concrete model, or None if unmapped."""
|
|
131
|
+
return CLASS_MODEL_OVERRIDES.get(executor, {}).get(model_class)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# Actions that author a final patch. The `worker` class (bounded, high-volume
|
|
135
|
+
# subtasks) must never own these — enforced as a routing invariant (P5).
|
|
136
|
+
PATCH_AUTHORING_ACTIONS: tuple[str, ...] = ("execute", "repair")
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def max_effort_planner_eligible(executor: str) -> bool:
|
|
140
|
+
"""True iff `executor`'s planner-class model can actually run at `max` effort.
|
|
141
|
+
|
|
142
|
+
The "planner of record" for a max-effort planning action must deliver max
|
|
143
|
+
reasoning. Gemini ceilings at `high` (its `effort_map` clamps `max -> high`),
|
|
144
|
+
so it is NOT eligible as the max-effort planner of record — it serves as a
|
|
145
|
+
panel member instead, never the authoritative planner. This is the
|
|
146
|
+
dispatch-selection guard the effort clamp alone does not provide: the clamp
|
|
147
|
+
keeps gemini from *running* at max, but only this guard keeps it from being
|
|
148
|
+
*selected* as the max-effort planner.
|
|
149
|
+
"""
|
|
150
|
+
capability = provider_policy_capabilities().get(executor)
|
|
151
|
+
return bool(capability and "max" in capability.supported_efforts)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
# The repo's SHIPPED model_policy. THIS repo's default: planning at max,
|
|
155
|
+
# implementation at the implementer model. `clamp=True` resolves a sub-max
|
|
156
|
+
# provider's `max` request to its ceiling via the provider effort_map fallback
|
|
157
|
+
# (otherwise normalize_provider_effort RAISES). A downstream repo that ships no
|
|
158
|
+
# policy keeps the registry defaults — that empty-policy path is the back-compat
|
|
159
|
+
# contract (callers pass model_policy_rule=None to get it).
|
|
160
|
+
SHIPPED_MODEL_POLICY = {
|
|
161
|
+
"roadmap": {"model_class": "planner", "effort": "max", "clamp": True},
|
|
162
|
+
"plan": {"model_class": "planner", "effort": "max", "clamp": True},
|
|
163
|
+
"execute": {"model_class": "implementer", "effort": "medium"},
|
|
164
|
+
"repair": {"model_class": "implementer", "effort": "medium"},
|
|
165
|
+
"review": {"model_class": "planner", "effort": "high", "clamp": True},
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def shipped_model_policy_rule(action: str) -> ExecutionPolicyRule | None:
|
|
170
|
+
"""The shipped model_policy rule for an action, or None if unmapped."""
|
|
171
|
+
spec = SHIPPED_MODEL_POLICY.get(action)
|
|
172
|
+
if spec is None:
|
|
173
|
+
return None
|
|
174
|
+
clamp = bool(spec.get("clamp", False))
|
|
175
|
+
return ExecutionPolicyRule(
|
|
176
|
+
selector=action,
|
|
177
|
+
action=action,
|
|
178
|
+
model_class=spec.get("model_class"),
|
|
179
|
+
effort=spec.get("effort"),
|
|
180
|
+
unsupported_policy_behavior="fallback" if clamp else "block",
|
|
181
|
+
fallback="high" if clamp else None,
|
|
182
|
+
source="model_policy",
|
|
183
|
+
override_reason="shipped model_policy (model-routing-v1)",
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def normalize_provider_effort(
|
|
188
|
+
*,
|
|
189
|
+
provider_key: str,
|
|
190
|
+
work_unit_policy: WorkUnitPolicy,
|
|
191
|
+
default_effort: str | None = None,
|
|
192
|
+
) -> str:
|
|
193
|
+
capabilities = provider_policy_capabilities()
|
|
194
|
+
if provider_key not in capabilities:
|
|
195
|
+
raise ValueError(f"unknown provider policy capability: {provider_key}")
|
|
196
|
+
|
|
197
|
+
capability = capabilities[provider_key]
|
|
198
|
+
require_literal(work_unit_policy.work_unit_kind, capability.supported_work_units, "provider work-unit kind")
|
|
199
|
+
requested_effort = work_unit_policy.effort or default_effort or capability.default_effort
|
|
200
|
+
if requested_effort is None:
|
|
201
|
+
if work_unit_policy.unsupported_policy_behavior == "inherit_default" and work_unit_policy.inherit_default:
|
|
202
|
+
requested_effort = capability.default_effort
|
|
203
|
+
if requested_effort is None:
|
|
204
|
+
raise ValueError(f"no default effort for provider policy capability: {provider_key}")
|
|
205
|
+
|
|
206
|
+
if requested_effort in capability.supported_efforts:
|
|
207
|
+
return requested_effort
|
|
208
|
+
|
|
209
|
+
if work_unit_policy.unsupported_policy_behavior == "inherit_default" and capability.default_effort:
|
|
210
|
+
return capability.default_effort
|
|
211
|
+
if work_unit_policy.unsupported_policy_behavior == "fallback" and work_unit_policy.fallback:
|
|
212
|
+
fallback_effort = capability.effort_map.get(work_unit_policy.fallback, work_unit_policy.fallback)
|
|
213
|
+
if fallback_effort in capability.supported_efforts:
|
|
214
|
+
return fallback_effort
|
|
215
|
+
raise ValueError(f"unsupported effort `{requested_effort}` for provider `{provider_key}`")
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def resolve_profile(profile: str, model: str | None = None, effort: str | None = None) -> ModelSelection:
|
|
219
|
+
default_model, default_effort = DEFAULT_PROFILES[profile]
|
|
220
|
+
selected_model = model or default_model
|
|
221
|
+
selected_effort = effort or default_effort
|
|
222
|
+
if model or effort:
|
|
223
|
+
return ModelSelection(
|
|
224
|
+
profile=profile,
|
|
225
|
+
model=selected_model,
|
|
226
|
+
effort=selected_effort,
|
|
227
|
+
source="user_override",
|
|
228
|
+
override_reason="user supplied --model or --effort",
|
|
229
|
+
)
|
|
230
|
+
return ModelSelection(profile=profile, model=selected_model, effort=selected_effort)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def resolve_profile_for_executor(
|
|
234
|
+
*,
|
|
235
|
+
action: str,
|
|
236
|
+
executor: str,
|
|
237
|
+
profile: str | None = None,
|
|
238
|
+
model: str | None = None,
|
|
239
|
+
effort: str | None = None,
|
|
240
|
+
) -> ModelSelection:
|
|
241
|
+
selected_profile = profile or default_model_profile_for_executor(action, executor)
|
|
242
|
+
selection = resolve_profile(selected_profile, model=model, effort=effort)
|
|
243
|
+
if model is not None:
|
|
244
|
+
return selection
|
|
245
|
+
executor_default = EXECUTOR_MODEL_OVERRIDES.get(executor, {}).get(action)
|
|
246
|
+
effort_default = EXECUTOR_EFFORT_OVERRIDES.get(executor, {}).get(action)
|
|
247
|
+
if not executor_default and not effort_default:
|
|
248
|
+
return selection
|
|
249
|
+
return ModelSelection(
|
|
250
|
+
profile=selection.profile,
|
|
251
|
+
model=executor_default or selection.model,
|
|
252
|
+
effort=effort or effort_default or selection.effort,
|
|
253
|
+
source=f"{executor}_default",
|
|
254
|
+
override_reason=f"{executor} live adapter default model alias",
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def resolve_execution_policy(
|
|
259
|
+
*,
|
|
260
|
+
action: str,
|
|
261
|
+
executor: str,
|
|
262
|
+
model_selection: ModelSelection,
|
|
263
|
+
operator_model: str | None = None,
|
|
264
|
+
operator_effort: str | None = None,
|
|
265
|
+
plan_policy: ExecutionPolicyRule | None = None,
|
|
266
|
+
roadmap_policy: ExecutionPolicyRule | None = None,
|
|
267
|
+
model_policy_rule: ExecutionPolicyRule | None = None,
|
|
268
|
+
lane: str | None = None,
|
|
269
|
+
) -> ResolvedExecutionPolicy:
|
|
270
|
+
require_literal(action, tuple(ACTION_WORK_UNITS.keys()), "execution policy action")
|
|
271
|
+
policy, source = _merge_policies(plan_policy, roadmap_policy, model_policy_rule)
|
|
272
|
+
if _claude_model_needs_claude_executor(executor, model_selection.model, policy):
|
|
273
|
+
executor = "claude"
|
|
274
|
+
work_unit_kind = (
|
|
275
|
+
(policy.work_unit_kind if policy else None)
|
|
276
|
+
or ACTION_WORK_UNITS[action]
|
|
277
|
+
)
|
|
278
|
+
policy_executor = executor
|
|
279
|
+
executor_source = "dispatch decision"
|
|
280
|
+
policy_model = model_selection.model
|
|
281
|
+
model_source = model_selection.source
|
|
282
|
+
policy_effort = model_selection.effort
|
|
283
|
+
effort_source = model_selection.source
|
|
284
|
+
fallback = policy.fallback if policy else None
|
|
285
|
+
fallback_source = source or "registry defaults"
|
|
286
|
+
unsupported_behavior = policy.unsupported_policy_behavior if policy else "block"
|
|
287
|
+
override_reason = policy.override_reason if policy else model_selection.override_reason
|
|
288
|
+
|
|
289
|
+
if policy is not None:
|
|
290
|
+
if policy.executor is not None:
|
|
291
|
+
policy_executor = policy.executor
|
|
292
|
+
executor_source = source or policy.source
|
|
293
|
+
if policy.model is not None:
|
|
294
|
+
policy_model = policy.model
|
|
295
|
+
model_source = source or policy.source
|
|
296
|
+
elif policy.model_class is not None:
|
|
297
|
+
# model_class -> concrete model for the resolved executor. An
|
|
298
|
+
# explicit `model` always wins; a class only fills in when no model
|
|
299
|
+
# is given (model-routing-v1).
|
|
300
|
+
class_model = resolve_model_class(policy_executor, policy.model_class)
|
|
301
|
+
if class_model is not None:
|
|
302
|
+
policy_model = class_model
|
|
303
|
+
model_source = source or policy.source
|
|
304
|
+
if policy.effort is not None:
|
|
305
|
+
policy_effort = policy.effort
|
|
306
|
+
effort_source = source or policy.source
|
|
307
|
+
|
|
308
|
+
if operator_model is not None:
|
|
309
|
+
policy_model = operator_model
|
|
310
|
+
model_source = "CLI/operator override"
|
|
311
|
+
override_reason = "operator supplied --model"
|
|
312
|
+
if operator_effort is not None:
|
|
313
|
+
policy_effort = operator_effort
|
|
314
|
+
effort_source = "CLI/operator override"
|
|
315
|
+
override_reason = "operator supplied --effort"
|
|
316
|
+
|
|
317
|
+
# model-routing-v1 guard (wired, not just asserted): an executor whose
|
|
318
|
+
# planner-class model cannot actually run at `max` (gemini/pi) must never be
|
|
319
|
+
# the max-effort planner of record. Force the clamp so its `max` request
|
|
320
|
+
# resolves to the provider ceiling instead of raising, regardless of whether
|
|
321
|
+
# the policy opted into a fallback. This makes the effort clamp + this guard
|
|
322
|
+
# jointly enforce the invariant at the dispatch-resolution boundary.
|
|
323
|
+
policy_model_class = policy.model_class if policy else None
|
|
324
|
+
if (
|
|
325
|
+
policy_model_class == "planner"
|
|
326
|
+
and policy_effort == "max"
|
|
327
|
+
and not max_effort_planner_eligible(policy_executor)
|
|
328
|
+
):
|
|
329
|
+
unsupported_behavior = "fallback"
|
|
330
|
+
if not fallback:
|
|
331
|
+
fallback = "high"
|
|
332
|
+
|
|
333
|
+
work_unit_policy = WorkUnitPolicy(
|
|
334
|
+
work_unit_kind=work_unit_kind,
|
|
335
|
+
effort=policy_effort,
|
|
336
|
+
unsupported_policy_behavior=unsupported_behavior,
|
|
337
|
+
fallback=fallback,
|
|
338
|
+
inherit_default=bool(policy.inherit_default) if policy else False,
|
|
339
|
+
)
|
|
340
|
+
normalized_effort = normalize_provider_effort(
|
|
341
|
+
provider_key=policy_executor,
|
|
342
|
+
work_unit_policy=work_unit_policy,
|
|
343
|
+
default_effort=model_selection.effort,
|
|
344
|
+
)
|
|
345
|
+
fallback_applied = normalized_effort != policy_effort
|
|
346
|
+
resolved_model = _resolve_policy_model(policy_executor, work_unit_kind, policy_model, fallback, unsupported_behavior)
|
|
347
|
+
return ResolvedExecutionPolicy(
|
|
348
|
+
action=action,
|
|
349
|
+
lane=lane,
|
|
350
|
+
executor=policy_executor,
|
|
351
|
+
model=resolved_model,
|
|
352
|
+
effort=normalized_effort,
|
|
353
|
+
work_unit_kind=work_unit_kind,
|
|
354
|
+
fallback=fallback,
|
|
355
|
+
unsupported_policy_behavior=unsupported_behavior,
|
|
356
|
+
execution_policy_source=source or "registry defaults",
|
|
357
|
+
execution_policy_override_reason=override_reason,
|
|
358
|
+
executor_source=executor_source,
|
|
359
|
+
model_source=model_source,
|
|
360
|
+
effort_source=effort_source,
|
|
361
|
+
fallback_source=fallback_source,
|
|
362
|
+
fallback_applied=fallback_applied,
|
|
363
|
+
model_class=policy.model_class if policy else None,
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def _claude_model_needs_claude_executor(
|
|
368
|
+
executor: str,
|
|
369
|
+
model: str,
|
|
370
|
+
policy: ExecutionPolicyRule | None,
|
|
371
|
+
) -> bool:
|
|
372
|
+
if executor != "pi":
|
|
373
|
+
return False
|
|
374
|
+
if policy is not None and policy.executor == "pi" and policy.override_reason:
|
|
375
|
+
return False
|
|
376
|
+
return model.lower().startswith(("claude", "anthropic/claude"))
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def resolve_model_selection_from_policy(
|
|
380
|
+
*,
|
|
381
|
+
profile: str,
|
|
382
|
+
resolved_policy: ResolvedExecutionPolicy,
|
|
383
|
+
) -> ModelSelection:
|
|
384
|
+
return ModelSelection(
|
|
385
|
+
profile=profile,
|
|
386
|
+
model=resolved_policy.model,
|
|
387
|
+
effort=resolved_policy.effort,
|
|
388
|
+
source=resolved_policy.execution_policy_source,
|
|
389
|
+
override_reason=resolved_policy.execution_policy_override_reason,
|
|
390
|
+
model_class=resolved_policy.model_class,
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def _merge_policies(
|
|
395
|
+
plan_policy: ExecutionPolicyRule | None,
|
|
396
|
+
roadmap_policy: ExecutionPolicyRule | None,
|
|
397
|
+
model_policy_rule: ExecutionPolicyRule | None = None,
|
|
398
|
+
) -> tuple[ExecutionPolicyRule | None, str | None]:
|
|
399
|
+
# Precedence: plan > roadmap > model_policy > registry defaults — but LAYERED,
|
|
400
|
+
# not winner-take-all. A higher-precedence policy overrides only the fields it
|
|
401
|
+
# specifies; the rest fall through to the lower layer. This is the fix for the
|
|
402
|
+
# tiering-bypass bug: a plan policy that pins only `executor=`/`effort=` (no
|
|
403
|
+
# model/model_class) still inherits the shipped model_policy's `model_class`
|
|
404
|
+
# and its clamp, instead of silently reverting to the registry heavy model.
|
|
405
|
+
layers = [
|
|
406
|
+
(model_policy_rule, "model_policy"),
|
|
407
|
+
(roadmap_policy, "roadmap policy"),
|
|
408
|
+
(plan_policy, "phase-plan policy"),
|
|
409
|
+
]
|
|
410
|
+
present = [(rule, src) for rule, src in layers if rule is not None]
|
|
411
|
+
if not present:
|
|
412
|
+
return None, None
|
|
413
|
+
top_rule, top_source = present[-1]
|
|
414
|
+
merged: dict[str, object] = {
|
|
415
|
+
"selector": top_rule.selector,
|
|
416
|
+
"action": top_rule.action,
|
|
417
|
+
"lane": top_rule.lane,
|
|
418
|
+
"executor": None,
|
|
419
|
+
"model": None,
|
|
420
|
+
"model_class": None,
|
|
421
|
+
"effort": None,
|
|
422
|
+
"work_unit_kind": None,
|
|
423
|
+
"unsupported_policy_behavior": "block",
|
|
424
|
+
"fallback": None,
|
|
425
|
+
"inherit_default": False,
|
|
426
|
+
"source": top_source,
|
|
427
|
+
"override_reason": None,
|
|
428
|
+
}
|
|
429
|
+
for rule, _src in present: # low → high overlay
|
|
430
|
+
for field_name in ("executor", "model", "model_class", "effort",
|
|
431
|
+
"work_unit_kind", "fallback", "override_reason", "action", "lane"):
|
|
432
|
+
value = getattr(rule, field_name)
|
|
433
|
+
if value is not None:
|
|
434
|
+
merged[field_name] = value
|
|
435
|
+
if rule.unsupported_policy_behavior and rule.unsupported_policy_behavior != "block":
|
|
436
|
+
merged["unsupported_policy_behavior"] = rule.unsupported_policy_behavior
|
|
437
|
+
if rule.inherit_default:
|
|
438
|
+
merged["inherit_default"] = True
|
|
439
|
+
return ExecutionPolicyRule(**merged), top_source
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def _resolve_policy_model(
|
|
443
|
+
executor: str,
|
|
444
|
+
work_unit_kind: str,
|
|
445
|
+
model: str,
|
|
446
|
+
fallback: str | None,
|
|
447
|
+
unsupported_behavior: str,
|
|
448
|
+
) -> str:
|
|
449
|
+
capability = provider_policy_capabilities()[executor]
|
|
450
|
+
if not capability.model_aliases:
|
|
451
|
+
return model
|
|
452
|
+
allowed = set(capability.model_aliases.values())
|
|
453
|
+
default_alias = capability.model_aliases.get(work_unit_kind)
|
|
454
|
+
if model in allowed:
|
|
455
|
+
return model
|
|
456
|
+
if unsupported_behavior == "inherit_default" and default_alias:
|
|
457
|
+
return default_alias
|
|
458
|
+
if unsupported_behavior == "fallback" and fallback in allowed:
|
|
459
|
+
return fallback
|
|
460
|
+
if model.startswith("phase-loop-"):
|
|
461
|
+
raise ValueError(f"unsupported model `{model}` for provider `{executor}`")
|
|
462
|
+
return model
|