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,433 @@
|
|
|
1
|
+
"""v45 SCHED — per-phase git worktree lifecycle (IF-0-SCHED-1 support).
|
|
2
|
+
|
|
3
|
+
Concurrent cross-phase dispatch is only safe when each phase's child executor
|
|
4
|
+
runs in its *own* git worktree: the children run ``git add``/``commit``/``status``
|
|
5
|
+
and would otherwise race on ``index.lock``/HEAD in a shared tree even when their
|
|
6
|
+
owned files are disjoint. ``validate_concurrent_phase_ownership`` guarantees the
|
|
7
|
+
file-disjointness; this module provides the isolation that makes concurrent git
|
|
8
|
+
operations safe and the merge-back conflict-free.
|
|
9
|
+
|
|
10
|
+
Lifecycle per phase in a ready wave:
|
|
11
|
+
|
|
12
|
+
1. ``create_phase_worktree`` — ``git worktree add -b <temp-branch> <path> <base>``.
|
|
13
|
+
Each phase gets its OWN temporary branch off the pipeline-branch tip, because
|
|
14
|
+
git refuses to check out one branch in two worktrees simultaneously.
|
|
15
|
+
2. The caller launches the child with ``repo=<worktree_path>`` so the executor's
|
|
16
|
+
``wrapped_cwd`` points the child into the isolated tree.
|
|
17
|
+
3. ``integrate_phase_worktree`` — fast-forward/merge the phase's temp branch back
|
|
18
|
+
onto the pipeline branch in the *main* worktree. Because waved siblings own
|
|
19
|
+
disjoint files (enforced upstream), sequential merges never conflict.
|
|
20
|
+
4. ``teardown_phase_worktree`` — remove the worktree and delete the temp branch.
|
|
21
|
+
|
|
22
|
+
Only repo-tracked content crosses the worktree boundary via the temp branch.
|
|
23
|
+
Runner-owned ledger/state (``events.jsonl``/``state.json`` under ``.phase-loop``)
|
|
24
|
+
is written by the parent against the main repo and is not committed, so it never
|
|
25
|
+
participates in merge-back.
|
|
26
|
+
"""
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
import subprocess
|
|
30
|
+
from dataclasses import dataclass, field
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
from .runtime_paths import lane_worktree_path
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass(frozen=True)
|
|
37
|
+
class PhaseWorktreeHandle:
|
|
38
|
+
"""Identifies one phase's isolated worktree and its temporary branch."""
|
|
39
|
+
|
|
40
|
+
phase: str
|
|
41
|
+
worktree_path: Path
|
|
42
|
+
temp_branch: str
|
|
43
|
+
target_branch: str
|
|
44
|
+
base_sha: str
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
class WorktreeIntegrationResult:
|
|
49
|
+
"""Outcome of merging a phase's temp branch back onto the pipeline branch."""
|
|
50
|
+
|
|
51
|
+
phase: str
|
|
52
|
+
temp_branch: str
|
|
53
|
+
integrated: bool
|
|
54
|
+
conflict: bool = False
|
|
55
|
+
merged_sha: str | None = None
|
|
56
|
+
had_commits: bool = True
|
|
57
|
+
reason: str | None = None
|
|
58
|
+
conflicted_paths: tuple[str, ...] = field(default_factory=tuple)
|
|
59
|
+
|
|
60
|
+
def to_json(self) -> dict[str, object]:
|
|
61
|
+
return {
|
|
62
|
+
"phase": self.phase,
|
|
63
|
+
"temp_branch": self.temp_branch,
|
|
64
|
+
"integrated": self.integrated,
|
|
65
|
+
"conflict": self.conflict,
|
|
66
|
+
"merged_sha": self.merged_sha,
|
|
67
|
+
"had_commits": self.had_commits,
|
|
68
|
+
"reason": self.reason,
|
|
69
|
+
"conflicted_paths": list(self.conflicted_paths),
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass(frozen=True)
|
|
74
|
+
class WorktreeTransferResult:
|
|
75
|
+
"""Outcome of transporting a phase child's worktree changes onto main.
|
|
76
|
+
|
|
77
|
+
``had_changes`` is True when the child produced any delta since base (dirty
|
|
78
|
+
and/or committed). ``applied`` is True when main's working tree now carries
|
|
79
|
+
that delta (or there was nothing to transfer). A failed apply leaves
|
|
80
|
+
``applied=False`` with ``conflict=True``; ``git apply`` is atomic, so main is
|
|
81
|
+
left untouched and the work is preserved on ``temp_branch`` for diagnosis.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
phase: str
|
|
85
|
+
temp_branch: str
|
|
86
|
+
had_changes: bool
|
|
87
|
+
applied: bool
|
|
88
|
+
conflict: bool = False
|
|
89
|
+
reason: str | None = None
|
|
90
|
+
|
|
91
|
+
def to_json(self) -> dict[str, object]:
|
|
92
|
+
return {
|
|
93
|
+
"phase": self.phase,
|
|
94
|
+
"temp_branch": self.temp_branch,
|
|
95
|
+
"had_changes": self.had_changes,
|
|
96
|
+
"applied": self.applied,
|
|
97
|
+
"conflict": self.conflict,
|
|
98
|
+
"reason": self.reason,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class PhaseWorktreeError(RuntimeError):
|
|
103
|
+
"""Raised when a worktree lifecycle git operation fails unexpectedly."""
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _git(
|
|
107
|
+
repo: Path,
|
|
108
|
+
*args: str,
|
|
109
|
+
check: bool = True,
|
|
110
|
+
) -> subprocess.CompletedProcess[str]:
|
|
111
|
+
return subprocess.run(
|
|
112
|
+
["git", "-C", str(repo), *args],
|
|
113
|
+
check=check,
|
|
114
|
+
capture_output=True,
|
|
115
|
+
text=True,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _git_bytes(
|
|
120
|
+
repo: Path,
|
|
121
|
+
*args: str,
|
|
122
|
+
input_bytes: bytes | None = None,
|
|
123
|
+
) -> subprocess.CompletedProcess[bytes]:
|
|
124
|
+
"""Run git capturing stdout/stderr as raw BYTES (never text-decoded).
|
|
125
|
+
|
|
126
|
+
A git patch is a byte stream that must survive verbatim: routing it through
|
|
127
|
+
``text=True`` strips ``\\r`` (corrupting CRLF files into spurious apply
|
|
128
|
+
conflicts or silent LF rewrites) and raises ``UnicodeDecodeError`` on any
|
|
129
|
+
non-UTF-8 "text" blob git inlines raw (high bytes without a NUL, so git does
|
|
130
|
+
not base85-encode it). The diff capture and ``git apply`` stdin in
|
|
131
|
+
:func:`transfer_phase_worktree_dirty` therefore use bytes I/O.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
return subprocess.run(
|
|
135
|
+
["git", "-C", str(repo), *args],
|
|
136
|
+
check=False,
|
|
137
|
+
capture_output=True,
|
|
138
|
+
input=input_bytes,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def resolve_base_sha(repo: Path, ref: str = "HEAD") -> str:
|
|
143
|
+
"""Resolve ``ref`` (default the current tip) to a concrete commit SHA."""
|
|
144
|
+
|
|
145
|
+
result = _git(repo, "rev-parse", ref)
|
|
146
|
+
return result.stdout.strip()
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def current_branch(repo: Path) -> str:
|
|
150
|
+
"""Name of the branch currently checked out in ``repo``'s main worktree.
|
|
151
|
+
|
|
152
|
+
This is the pipeline branch concurrent phases branch from and integrate back
|
|
153
|
+
onto. Detached HEAD returns ``"HEAD"``.
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
return _git(repo, "rev-parse", "--abbrev-ref", "HEAD").stdout.strip()
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def phase_temp_branch(target_branch: str, phase: str) -> str:
|
|
160
|
+
"""Deterministic temp-branch name for a phase's isolated worktree.
|
|
161
|
+
|
|
162
|
+
Slashes in the pipeline branch are preserved (git refs allow them); the
|
|
163
|
+
``phase-loop/sched/`` prefix namespaces these throwaway branches so cleanup
|
|
164
|
+
sweeps can recognize them.
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
return f"phase-loop/sched/{target_branch}/{phase.upper()}"
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _branch_exists(repo: Path, branch: str) -> bool:
|
|
171
|
+
return _git(repo, "rev-parse", "--verify", "--quiet", f"refs/heads/{branch}", check=False).returncode == 0
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _remove_worktree(repo: Path, path: Path) -> None:
|
|
175
|
+
_git(repo, "worktree", "remove", "--force", str(path), check=False)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def create_phase_worktree(
|
|
179
|
+
repo: Path,
|
|
180
|
+
*,
|
|
181
|
+
phase: str,
|
|
182
|
+
target_branch: str,
|
|
183
|
+
base_sha: str,
|
|
184
|
+
workspace_mount: Path | None = None,
|
|
185
|
+
) -> PhaseWorktreeHandle:
|
|
186
|
+
"""Create an isolated worktree for ``phase`` on its own temp branch.
|
|
187
|
+
|
|
188
|
+
Idempotent: a stale worktree at the computed path or a stale temp branch
|
|
189
|
+
(from a crashed prior run) is pruned/deleted before recreation. The new
|
|
190
|
+
worktree is checked out at ``base_sha`` so every concurrent sibling starts
|
|
191
|
+
from the same pipeline-branch tip.
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
phase = phase.upper()
|
|
195
|
+
worktree_path = lane_worktree_path(
|
|
196
|
+
repo,
|
|
197
|
+
branch=target_branch,
|
|
198
|
+
lane_id=phase,
|
|
199
|
+
workspace_mount=workspace_mount,
|
|
200
|
+
)
|
|
201
|
+
temp_branch = phase_temp_branch(target_branch, phase)
|
|
202
|
+
|
|
203
|
+
# Clear stale state from an interrupted prior run before recreating.
|
|
204
|
+
if worktree_path.exists():
|
|
205
|
+
_remove_worktree(repo, worktree_path)
|
|
206
|
+
_git(repo, "worktree", "prune", check=False)
|
|
207
|
+
if _branch_exists(repo, temp_branch):
|
|
208
|
+
_git(repo, "branch", "-D", temp_branch, check=False)
|
|
209
|
+
|
|
210
|
+
worktree_path.parent.mkdir(parents=True, exist_ok=True)
|
|
211
|
+
created = _git(
|
|
212
|
+
repo,
|
|
213
|
+
"worktree",
|
|
214
|
+
"add",
|
|
215
|
+
"-b",
|
|
216
|
+
temp_branch,
|
|
217
|
+
str(worktree_path),
|
|
218
|
+
base_sha,
|
|
219
|
+
check=False,
|
|
220
|
+
)
|
|
221
|
+
if created.returncode != 0:
|
|
222
|
+
raise PhaseWorktreeError(
|
|
223
|
+
f"failed to create worktree for phase {phase} at {worktree_path}: "
|
|
224
|
+
f"{created.stderr.strip() or created.stdout.strip()}"
|
|
225
|
+
)
|
|
226
|
+
return PhaseWorktreeHandle(
|
|
227
|
+
phase=phase,
|
|
228
|
+
worktree_path=worktree_path,
|
|
229
|
+
temp_branch=temp_branch,
|
|
230
|
+
target_branch=target_branch,
|
|
231
|
+
base_sha=base_sha,
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def integrate_phase_worktree(
|
|
236
|
+
repo: Path,
|
|
237
|
+
handle: PhaseWorktreeHandle,
|
|
238
|
+
*,
|
|
239
|
+
message: str | None = None,
|
|
240
|
+
) -> WorktreeIntegrationResult:
|
|
241
|
+
"""Merge a phase's temp branch back onto the pipeline branch.
|
|
242
|
+
|
|
243
|
+
Precondition: the main worktree (``repo``) is checked out on
|
|
244
|
+
``handle.target_branch`` with a clean index for the merged files (the caller
|
|
245
|
+
integrates sequentially after all children finish). Disjoint owned files make
|
|
246
|
+
the merge conflict-free by construction; a conflict is surfaced (and aborted)
|
|
247
|
+
rather than resolved silently, because it signals the ownership gate was
|
|
248
|
+
bypassed.
|
|
249
|
+
"""
|
|
250
|
+
|
|
251
|
+
commits = _git(repo, "rev-list", f"{handle.base_sha}..{handle.temp_branch}", check=False)
|
|
252
|
+
if commits.returncode != 0:
|
|
253
|
+
return WorktreeIntegrationResult(
|
|
254
|
+
phase=handle.phase,
|
|
255
|
+
temp_branch=handle.temp_branch,
|
|
256
|
+
integrated=False,
|
|
257
|
+
had_commits=False,
|
|
258
|
+
reason=f"could not inspect commits: {commits.stderr.strip()}",
|
|
259
|
+
)
|
|
260
|
+
if not commits.stdout.strip():
|
|
261
|
+
# Child produced no commits (e.g. plan-only, blocked, or dry run).
|
|
262
|
+
return WorktreeIntegrationResult(
|
|
263
|
+
phase=handle.phase,
|
|
264
|
+
temp_branch=handle.temp_branch,
|
|
265
|
+
integrated=True,
|
|
266
|
+
had_commits=False,
|
|
267
|
+
merged_sha=resolve_base_sha(repo),
|
|
268
|
+
reason="no commits to integrate",
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
merge_message = message or f"phase-loop sched: integrate {handle.phase}"
|
|
272
|
+
merged = _git(
|
|
273
|
+
repo,
|
|
274
|
+
"merge",
|
|
275
|
+
"--no-ff",
|
|
276
|
+
"-m",
|
|
277
|
+
merge_message,
|
|
278
|
+
handle.temp_branch,
|
|
279
|
+
check=False,
|
|
280
|
+
)
|
|
281
|
+
if merged.returncode != 0:
|
|
282
|
+
conflicted = _git(repo, "diff", "--name-only", "--diff-filter=U", check=False)
|
|
283
|
+
conflicted_paths = tuple(
|
|
284
|
+
line.strip() for line in conflicted.stdout.splitlines() if line.strip()
|
|
285
|
+
)
|
|
286
|
+
_git(repo, "merge", "--abort", check=False)
|
|
287
|
+
return WorktreeIntegrationResult(
|
|
288
|
+
phase=handle.phase,
|
|
289
|
+
temp_branch=handle.temp_branch,
|
|
290
|
+
integrated=False,
|
|
291
|
+
conflict=True,
|
|
292
|
+
conflicted_paths=conflicted_paths,
|
|
293
|
+
reason=(
|
|
294
|
+
"merge conflict integrating phase worktree — the concurrent "
|
|
295
|
+
"ownership-disjointness gate should have prevented this"
|
|
296
|
+
),
|
|
297
|
+
)
|
|
298
|
+
return WorktreeIntegrationResult(
|
|
299
|
+
phase=handle.phase,
|
|
300
|
+
temp_branch=handle.temp_branch,
|
|
301
|
+
integrated=True,
|
|
302
|
+
merged_sha=resolve_base_sha(repo),
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def transfer_phase_worktree_dirty(
|
|
307
|
+
repo: Path,
|
|
308
|
+
handle: PhaseWorktreeHandle,
|
|
309
|
+
*,
|
|
310
|
+
commit_message: str | None = None,
|
|
311
|
+
) -> WorktreeTransferResult:
|
|
312
|
+
"""Transport a phase child's worktree work onto main as UNSTAGED changes.
|
|
313
|
+
|
|
314
|
+
Unlike :func:`integrate_phase_worktree` (which merges only *committed* work),
|
|
315
|
+
a real phase executor leaves its verified work DIRTY in the worktree and
|
|
316
|
+
emits ``awaiting_phase_closeout`` — the parent runner's closeout is what
|
|
317
|
+
stages+commits the dirty phase-owned files. So the committed-only merge is a
|
|
318
|
+
no-op against a real child and the work is lost. This brings the child's full
|
|
319
|
+
delta (uncommitted + any self-commits) onto the *main* working tree without
|
|
320
|
+
committing it, so the parent's existing closeout — whose selective
|
|
321
|
+
``git add -- <owned>`` is what enforces the ownership gate — commits it on the
|
|
322
|
+
pipeline branch exactly as in serial mode.
|
|
323
|
+
|
|
324
|
+
The work is first committed onto ``temp_branch`` (preserving it on a ref), then
|
|
325
|
+
transported via ``git diff base..temp | git apply`` rather than a
|
|
326
|
+
cherry-pick: cherry-pick would pre-stage every changed path into main's index
|
|
327
|
+
and defeat the closeout's selective, ownership-gated staging. ``git apply`` is
|
|
328
|
+
atomic, so a failed apply (which the disjointness gate should make impossible)
|
|
329
|
+
leaves main untouched and the work recoverable on ``temp_branch``.
|
|
330
|
+
"""
|
|
331
|
+
|
|
332
|
+
worktree = handle.worktree_path
|
|
333
|
+
# Stage everything dirty (captures untracked new files too) and commit it onto
|
|
334
|
+
# the temp branch so the work survives on a ref even if the apply to main fails.
|
|
335
|
+
_git(worktree, "add", "-A", check=False)
|
|
336
|
+
has_staged = _git(worktree, "diff", "--cached", "--quiet", check=False).returncode != 0
|
|
337
|
+
if has_staged:
|
|
338
|
+
message = commit_message or f"phase-loop sched transport: {handle.phase}"
|
|
339
|
+
committed = _git(worktree, "commit", "-q", "-m", message, check=False)
|
|
340
|
+
if committed.returncode != 0:
|
|
341
|
+
return WorktreeTransferResult(
|
|
342
|
+
phase=handle.phase,
|
|
343
|
+
temp_branch=handle.temp_branch,
|
|
344
|
+
had_changes=True,
|
|
345
|
+
applied=False,
|
|
346
|
+
reason=(
|
|
347
|
+
"failed to commit worktree changes for transport: "
|
|
348
|
+
f"{committed.stderr.strip() or committed.stdout.strip()}"
|
|
349
|
+
),
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
revs = _git(worktree, "rev-list", f"{handle.base_sha}..{handle.temp_branch}", check=False)
|
|
353
|
+
if revs.returncode != 0:
|
|
354
|
+
# The transport commit above already succeeded (when there was dirt), so
|
|
355
|
+
# the work is on temp_branch — mark had_changes=True so the caller PRESERVES
|
|
356
|
+
# the branch (its preserve guard keys on had_changes) instead of deleting it.
|
|
357
|
+
return WorktreeTransferResult(
|
|
358
|
+
phase=handle.phase,
|
|
359
|
+
temp_branch=handle.temp_branch,
|
|
360
|
+
had_changes=has_staged,
|
|
361
|
+
applied=False,
|
|
362
|
+
conflict=has_staged,
|
|
363
|
+
reason=f"could not inspect commits: {revs.stderr.strip()}",
|
|
364
|
+
)
|
|
365
|
+
if not revs.stdout.strip():
|
|
366
|
+
# Child produced no work (blocked, plan-only, dry run, or a clean
|
|
367
|
+
# self-reported terminal). Nothing to transport; main is untouched.
|
|
368
|
+
return WorktreeTransferResult(
|
|
369
|
+
phase=handle.phase,
|
|
370
|
+
temp_branch=handle.temp_branch,
|
|
371
|
+
had_changes=False,
|
|
372
|
+
applied=True,
|
|
373
|
+
reason="no changes to transfer",
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
# Bytes I/O: the patch must survive verbatim (CRLF, binary, non-UTF-8 blobs).
|
|
377
|
+
diff = _git_bytes(worktree, "diff", "--binary", handle.base_sha, handle.temp_branch)
|
|
378
|
+
if diff.returncode != 0:
|
|
379
|
+
return WorktreeTransferResult(
|
|
380
|
+
phase=handle.phase,
|
|
381
|
+
temp_branch=handle.temp_branch,
|
|
382
|
+
had_changes=True,
|
|
383
|
+
applied=False,
|
|
384
|
+
conflict=True,
|
|
385
|
+
reason=f"could not compute transfer diff: {diff.stderr.decode('utf-8', 'replace').strip()}",
|
|
386
|
+
)
|
|
387
|
+
if not diff.stdout.strip():
|
|
388
|
+
return WorktreeTransferResult(
|
|
389
|
+
phase=handle.phase,
|
|
390
|
+
temp_branch=handle.temp_branch,
|
|
391
|
+
had_changes=False,
|
|
392
|
+
applied=True,
|
|
393
|
+
reason="empty net diff",
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
applied = _git_bytes(repo, "apply", "--whitespace=nowarn", "-", input_bytes=diff.stdout)
|
|
397
|
+
if applied.returncode != 0:
|
|
398
|
+
return WorktreeTransferResult(
|
|
399
|
+
phase=handle.phase,
|
|
400
|
+
temp_branch=handle.temp_branch,
|
|
401
|
+
had_changes=True,
|
|
402
|
+
applied=False,
|
|
403
|
+
conflict=True,
|
|
404
|
+
reason=(
|
|
405
|
+
"git apply failed transporting worktree changes onto main — the "
|
|
406
|
+
"concurrent ownership-disjointness gate should have prevented this: "
|
|
407
|
+
f"{applied.stderr.decode('utf-8', 'replace').strip() or applied.stdout.decode('utf-8', 'replace').strip()}"
|
|
408
|
+
),
|
|
409
|
+
)
|
|
410
|
+
return WorktreeTransferResult(
|
|
411
|
+
phase=handle.phase,
|
|
412
|
+
temp_branch=handle.temp_branch,
|
|
413
|
+
had_changes=True,
|
|
414
|
+
applied=True,
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def teardown_phase_worktree(
|
|
419
|
+
repo: Path,
|
|
420
|
+
handle: PhaseWorktreeHandle,
|
|
421
|
+
*,
|
|
422
|
+
delete_branch: bool = True,
|
|
423
|
+
) -> None:
|
|
424
|
+
"""Remove the phase's worktree and (by default) delete its temp branch.
|
|
425
|
+
|
|
426
|
+
Best-effort: missing worktree/branch is not an error so this is safe to call
|
|
427
|
+
in a ``finally`` even if creation partially failed.
|
|
428
|
+
"""
|
|
429
|
+
|
|
430
|
+
_remove_worktree(repo, handle.worktree_path)
|
|
431
|
+
_git(repo, "worktree", "prune", check=False)
|
|
432
|
+
if delete_branch and _branch_exists(repo, handle.temp_branch):
|
|
433
|
+
_git(repo, "branch", "-D", handle.temp_branch, check=False)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Pipeline adapter helpers.
|
|
4
|
+
|
|
5
|
+
The hard-coded v32 governed-pipeline ratification trigger contract is
|
|
6
|
+
`.pipeline/ratification-trigger.json`.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .flag import branchgov_enabled
|
|
10
|
+
from .markers import detect_pipeline_mode
|
|
11
|
+
|
|
12
|
+
__all__ = ("branchgov_enabled", "detect_pipeline_mode")
|