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,339 @@
|
|
|
1
|
+
"""Runtime publishing primitive — IF-0-P1-1 (#29 P1).
|
|
2
|
+
|
|
3
|
+
Factors the #28 worktree→branch→verify→commit→push→PR flow out of the
|
|
4
|
+
execute-skill prose into a runtime module the coordinator (P3+) and the
|
|
5
|
+
execute skills both call, so the safety controls are code, not interpretation.
|
|
6
|
+
|
|
7
|
+
Contract (IF-0-P1-1): ``publish_from_worktree(repo, owned_paths, ...)``
|
|
8
|
+
returns ``{branch, head_sha, pr_url, status}`` on success, or
|
|
9
|
+
``{status: "publication_blocked", reason: str, detail: str}`` on any invariant
|
|
10
|
+
violation. The ``branch`` and ``head_sha`` fields are load-bearing: the
|
|
11
|
+
coordinator (P3) injects them into downstream nodes via IF-0-P2-2.
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import subprocess
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Any, Sequence
|
|
18
|
+
|
|
19
|
+
from .git_topology import (
|
|
20
|
+
_gh_pr_metadata,
|
|
21
|
+
collect_git_topology,
|
|
22
|
+
resolve_closeout_push_target,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Branches that are never valid publication targets.
|
|
26
|
+
PROTECTED_BRANCHES: frozenset[str] = frozenset({"main", "master", "develop", "release"})
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _is_secret_path(path: str) -> bool:
|
|
30
|
+
"""Return True if the path looks like a secret, credential, or .env file.
|
|
31
|
+
|
|
32
|
+
Used during the staged-diff audit to reject any file whose name matches
|
|
33
|
+
common credential/env patterns, even if the caller listed it in owned_paths.
|
|
34
|
+
"""
|
|
35
|
+
name = Path(path).name.lower()
|
|
36
|
+
# .env, .env.local, .env.production, .env.test, etc.
|
|
37
|
+
if name.startswith(".env"):
|
|
38
|
+
return True
|
|
39
|
+
# Common credential / secret file names.
|
|
40
|
+
for fragment in ("credential", "secret", ".key", "private"):
|
|
41
|
+
if fragment in name:
|
|
42
|
+
return True
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _blocked(reason: str, detail: str = "") -> dict[str, Any]:
|
|
47
|
+
"""Return a structured publication_blocked result."""
|
|
48
|
+
result: dict[str, Any] = {"status": "publication_blocked", "reason": reason}
|
|
49
|
+
if detail:
|
|
50
|
+
result["detail"] = detail
|
|
51
|
+
return result
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# ---------------------------------------------------------------------------
|
|
55
|
+
# Seam functions — wrapping subprocess calls for git push and gh pr create so
|
|
56
|
+
# tests can patch them without live network access.
|
|
57
|
+
# ---------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _run_git_push(repo: Path, remote: str, push_ref: str) -> int:
|
|
61
|
+
"""Push to remote without force. Returns the process returncode."""
|
|
62
|
+
# push_ref from resolve_closeout_push_target is ``refs/heads/<branch>``.
|
|
63
|
+
completed = subprocess.run(
|
|
64
|
+
["git", "-C", str(repo), "push", remote, push_ref],
|
|
65
|
+
capture_output=True,
|
|
66
|
+
text=True,
|
|
67
|
+
timeout=60,
|
|
68
|
+
)
|
|
69
|
+
return completed.returncode
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _run_gh_pr_create(
|
|
73
|
+
repo: Path,
|
|
74
|
+
*,
|
|
75
|
+
draft: bool,
|
|
76
|
+
title: str | None,
|
|
77
|
+
body: str | None,
|
|
78
|
+
) -> int:
|
|
79
|
+
"""Create a PR via the ``gh`` CLI. Returns the process returncode.
|
|
80
|
+
|
|
81
|
+
Uses ``--draft`` when ``draft=True``, ``--fill`` (populate from commits)
|
|
82
|
+
when ``draft=False``. ``title`` and ``body`` override the ``--fill``
|
|
83
|
+
defaults when supplied.
|
|
84
|
+
|
|
85
|
+
The PR URL is NOT parsed from stdout — ``gh`` may emit warnings or notices
|
|
86
|
+
before the URL, making stdout parsing brittle. Call ``_gh_pr_metadata``
|
|
87
|
+
after a successful create to retrieve the URL via ``gh pr list --json``.
|
|
88
|
+
"""
|
|
89
|
+
args: list[str] = ["pr", "create"]
|
|
90
|
+
if draft:
|
|
91
|
+
args.append("--draft")
|
|
92
|
+
else:
|
|
93
|
+
args.append("--fill")
|
|
94
|
+
if title:
|
|
95
|
+
args.extend(["--title", title])
|
|
96
|
+
if body:
|
|
97
|
+
args.extend(["--body", body])
|
|
98
|
+
|
|
99
|
+
completed = subprocess.run(
|
|
100
|
+
["gh", *args],
|
|
101
|
+
cwd=repo,
|
|
102
|
+
capture_output=True,
|
|
103
|
+
text=True,
|
|
104
|
+
timeout=30,
|
|
105
|
+
)
|
|
106
|
+
return completed.returncode
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _git_run(repo: Path, *args: str) -> int:
|
|
110
|
+
"""Run a git command; return returncode."""
|
|
111
|
+
completed = subprocess.run(
|
|
112
|
+
["git", "-C", str(repo), *args],
|
|
113
|
+
capture_output=True,
|
|
114
|
+
text=True,
|
|
115
|
+
timeout=30,
|
|
116
|
+
)
|
|
117
|
+
return completed.returncode
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _git_output(repo: Path, *args: str) -> str | None:
|
|
121
|
+
"""Run a git command; return stripped stdout or None on failure."""
|
|
122
|
+
completed = subprocess.run(
|
|
123
|
+
["git", "-C", str(repo), *args],
|
|
124
|
+
capture_output=True,
|
|
125
|
+
text=True,
|
|
126
|
+
timeout=30,
|
|
127
|
+
)
|
|
128
|
+
if completed.returncode != 0:
|
|
129
|
+
return None
|
|
130
|
+
return completed.stdout.strip() or None
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# ---------------------------------------------------------------------------
|
|
134
|
+
# Public API — IF-0-P1-1
|
|
135
|
+
# ---------------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def publish_from_worktree(
|
|
139
|
+
repo: Path,
|
|
140
|
+
owned_paths: Sequence[str],
|
|
141
|
+
*,
|
|
142
|
+
draft: bool = True,
|
|
143
|
+
pr_title: str | None = None,
|
|
144
|
+
pr_body: str | None = None,
|
|
145
|
+
commit_message: str | None = None,
|
|
146
|
+
topology: dict[str, Any] | None = None,
|
|
147
|
+
protected_branches: frozenset[str] = PROTECTED_BRANCHES,
|
|
148
|
+
) -> dict[str, Any]:
|
|
149
|
+
"""Perform the #28 publish flow for one repo/worktree (IF-0-P1-1).
|
|
150
|
+
|
|
151
|
+
Parameters
|
|
152
|
+
----------
|
|
153
|
+
repo:
|
|
154
|
+
Repository (or worktree) root. All git operations run here.
|
|
155
|
+
owned_paths:
|
|
156
|
+
File paths (relative to *repo*) this run owns and intends to publish.
|
|
157
|
+
Only these paths are staged; no ``git add -A`` is ever used.
|
|
158
|
+
draft:
|
|
159
|
+
Open the PR as a draft when True (dependencies remain or verification
|
|
160
|
+
partial). Open as ready (``--fill``) when False.
|
|
161
|
+
pr_title:
|
|
162
|
+
Optional PR title override (passed to ``gh pr create --title``).
|
|
163
|
+
pr_body:
|
|
164
|
+
Optional PR body override (passed to ``gh pr create --body``).
|
|
165
|
+
commit_message:
|
|
166
|
+
Commit message override. Defaults to ``"chore: publish plan changes"``.
|
|
167
|
+
topology:
|
|
168
|
+
Pre-collected git topology dict. When None, topology is collected via
|
|
169
|
+
``collect_git_topology(repo)``. Useful in tests or when the caller
|
|
170
|
+
already has topology.
|
|
171
|
+
protected_branches:
|
|
172
|
+
Branch names that are never valid publication targets. Defaults to
|
|
173
|
+
``PROTECTED_BRANCHES``.
|
|
174
|
+
|
|
175
|
+
Returns
|
|
176
|
+
-------
|
|
177
|
+
dict
|
|
178
|
+
On success: ``{status: "published", branch, head_sha, pr_url}``.
|
|
179
|
+
On any invariant violation: ``{status: "publication_blocked",
|
|
180
|
+
reason: <reason-slug>, detail: <human-readable explanation>}``.
|
|
181
|
+
|
|
182
|
+
Safety invariants enforced (fail-closed):
|
|
183
|
+
- Never publish from ``main`` or a protected branch.
|
|
184
|
+
- Never ``git add -A``; stage only *owned_paths* by explicit path.
|
|
185
|
+
- Staged-diff audit: staged set must be a subset of *owned_paths*; no
|
|
186
|
+
secret/credential/``.env`` paths; ``git diff --cached --check`` clean.
|
|
187
|
+
- Commit, then ``resolve_closeout_push_target`` re-checks the post-commit
|
|
188
|
+
state (dirty worktree → stop; behind upstream → stop / unowned branch).
|
|
189
|
+
- Push without ``--force``; a rejected push returns publication_blocked.
|
|
190
|
+
- ``gh pr create`` opens a draft or ready PR per intent.
|
|
191
|
+
"""
|
|
192
|
+
topo = dict(topology or collect_git_topology(repo))
|
|
193
|
+
|
|
194
|
+
if not topo.get("available"):
|
|
195
|
+
return _blocked("not_a_git_worktree", "Repo is not a git worktree")
|
|
196
|
+
|
|
197
|
+
branch = topo.get("branch", "")
|
|
198
|
+
|
|
199
|
+
# Invariant: never publish from main or a protected branch.
|
|
200
|
+
if not branch or branch.startswith("detached@"):
|
|
201
|
+
return _blocked("detached_head", "Cannot publish from detached HEAD state")
|
|
202
|
+
if branch in protected_branches:
|
|
203
|
+
return _blocked(
|
|
204
|
+
"branch_protected",
|
|
205
|
+
f"Cannot publish from protected branch {branch!r}; "
|
|
206
|
+
"establish a worktree/branch first (Workflow step 6)",
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
if not owned_paths:
|
|
210
|
+
return _blocked("no_owned_paths", "No owned paths to stage; nothing to publish")
|
|
211
|
+
|
|
212
|
+
# Stage owned paths by explicit name — never git add -A.
|
|
213
|
+
stage_rc = _git_run(repo, "add", "--", *owned_paths)
|
|
214
|
+
if stage_rc != 0:
|
|
215
|
+
return _blocked(
|
|
216
|
+
"stage_failed",
|
|
217
|
+
f"git add -- <owned_paths> failed (rc={stage_rc}); "
|
|
218
|
+
"check that owned paths exist in the worktree",
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
# Staged-diff audit ---------------------------------------------------
|
|
222
|
+
audit_result = _audit_staged_diff(repo, owned_paths)
|
|
223
|
+
if audit_result is not None:
|
|
224
|
+
return audit_result
|
|
225
|
+
|
|
226
|
+
# Commit --------------------------------------------------------------
|
|
227
|
+
msg = commit_message or "chore: publish plan changes"
|
|
228
|
+
commit_rc = _git_run(repo, "commit", "-m", msg)
|
|
229
|
+
if commit_rc != 0:
|
|
230
|
+
return _blocked(
|
|
231
|
+
"commit_failed",
|
|
232
|
+
f"git commit failed (rc={commit_rc}); "
|
|
233
|
+
"possibly nothing was staged or a pre-commit hook rejected the commit",
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# Capture head_sha immediately after commit (load-bearing for IF-0-P1-1).
|
|
237
|
+
head_sha = _git_output(repo, "rev-parse", "HEAD")
|
|
238
|
+
if not head_sha:
|
|
239
|
+
return _blocked("head_sha_missing", "Could not resolve HEAD after commit")
|
|
240
|
+
|
|
241
|
+
# Post-commit push target check (dirty / unowned / behind upstream) ----
|
|
242
|
+
push_check = resolve_closeout_push_target(repo)
|
|
243
|
+
if not push_check.get("allowed"):
|
|
244
|
+
refusal = push_check.get("refusal_reason", "unknown")
|
|
245
|
+
return _blocked(refusal, f"Push target refused: {refusal}")
|
|
246
|
+
|
|
247
|
+
remote = push_check["remote"]
|
|
248
|
+
push_ref = push_check["push_ref"]
|
|
249
|
+
|
|
250
|
+
# Push — no force -----------------------------------------------------
|
|
251
|
+
push_rc = _run_git_push(repo, remote, push_ref)
|
|
252
|
+
if push_rc != 0:
|
|
253
|
+
return _blocked(
|
|
254
|
+
"push_rejected",
|
|
255
|
+
f"Push to {remote} {push_ref} was rejected "
|
|
256
|
+
"(divergent / non-fast-forward / branch protection); "
|
|
257
|
+
"never force-push — stop and report publication blocked",
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# Open PR (draft or ready) --------------------------------------------
|
|
261
|
+
create_rc = _run_gh_pr_create(repo, draft=draft, title=pr_title, body=pr_body)
|
|
262
|
+
if create_rc != 0:
|
|
263
|
+
return _blocked(
|
|
264
|
+
"gh_pr_create_failed",
|
|
265
|
+
"gh pr create failed; check gh auth status and that the branch was pushed",
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
# Fetch URL via _gh_pr_metadata (reused from git_topology per IF-0-P1-1):
|
|
269
|
+
# avoids brittle stdout parsing when gh prints notices before the URL.
|
|
270
|
+
pr_meta = _gh_pr_metadata(repo, branch)
|
|
271
|
+
pr_url = pr_meta.get("pr_url")
|
|
272
|
+
if not pr_url:
|
|
273
|
+
return _blocked(
|
|
274
|
+
"gh_pr_url_missing",
|
|
275
|
+
"gh pr create succeeded but could not retrieve PR URL via gh pr list --json; "
|
|
276
|
+
"check gh auth status",
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
"status": "published",
|
|
281
|
+
"branch": branch,
|
|
282
|
+
"head_sha": head_sha,
|
|
283
|
+
"pr_url": pr_url,
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
# ---------------------------------------------------------------------------
|
|
288
|
+
# Internal helpers
|
|
289
|
+
# ---------------------------------------------------------------------------
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def _audit_staged_diff(repo: Path, owned_paths: Sequence[str]) -> dict[str, Any] | None:
|
|
293
|
+
"""Audit the staged diff against the safety invariants.
|
|
294
|
+
|
|
295
|
+
Returns a ``publication_blocked`` dict on the first violation, or ``None``
|
|
296
|
+
when the staged set is clean. Checks (in order):
|
|
297
|
+
|
|
298
|
+
1. Something must be staged (nothing staged → blocked).
|
|
299
|
+
2. Every staged path must be in *owned_paths* (no out-of-scope files).
|
|
300
|
+
3. No staged path may look like a secret/credential/``.env`` file.
|
|
301
|
+
4. ``git diff --cached --check`` must pass (no trailing whitespace etc.).
|
|
302
|
+
"""
|
|
303
|
+
owned_set = {Path(p).as_posix() for p in owned_paths}
|
|
304
|
+
|
|
305
|
+
staged_raw = _git_output(repo, "diff", "--cached", "--name-only")
|
|
306
|
+
staged_paths = [p.strip() for p in (staged_raw or "").splitlines() if p.strip()]
|
|
307
|
+
|
|
308
|
+
if not staged_paths:
|
|
309
|
+
return _blocked(
|
|
310
|
+
"nothing_staged",
|
|
311
|
+
"No changes were staged after git add; "
|
|
312
|
+
"owned paths may already be clean or not modified",
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
for path in staged_paths:
|
|
316
|
+
norm = Path(path).as_posix()
|
|
317
|
+
if norm not in owned_set:
|
|
318
|
+
return _blocked(
|
|
319
|
+
"out_of_scope_staged_path",
|
|
320
|
+
f"Staged path {path!r} is not in the owned-paths set; "
|
|
321
|
+
"unstage it or add it to owned_paths explicitly",
|
|
322
|
+
)
|
|
323
|
+
if _is_secret_path(path):
|
|
324
|
+
return _blocked(
|
|
325
|
+
"secret_staged_path",
|
|
326
|
+
f"Staged path {path!r} matches a secret/credential/.env pattern; "
|
|
327
|
+
"remove it from owned_paths and unstage it",
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
# Trailing-whitespace / mixed-indent check.
|
|
331
|
+
check_rc = _git_run(repo, "diff", "--cached", "--check")
|
|
332
|
+
if check_rc != 0:
|
|
333
|
+
return _blocked(
|
|
334
|
+
"staged_check_failed",
|
|
335
|
+
"git diff --cached --check found trailing whitespace or mixed indent; "
|
|
336
|
+
"fix and restage before publishing",
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
return None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|