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,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: codex-execute-phase
|
|
3
|
+
description: "Harness-optimized executor for a `<harness>-plan-phase` lane plan. Use when the user wants Harness to implement a planned phase. Executes lanes with clean git preflight, owned-file boundaries, verification, and optional explicit worker-subagent fanout for disjoint lanes."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Harness Execute Phase
|
|
7
|
+
|
|
8
|
+
Executes a phase plan produced by `<harness>-plan-phase`. The default executor is the main Harness thread. Worker subagents are optional and only used when the user explicitly asks for subagents, delegation, or parallel execution. Write-capable parallel execution also requires machine-verified disjoint lanes and scheduler-owned worktree assignments; prose lane labels are not sufficient.
|
|
9
|
+
|
|
10
|
+
## Core Rules
|
|
11
|
+
|
|
12
|
+
Use `phase_loop_runtime.skill_paths` resolver helpers for harness skill roots, handoff roots, helper roots, and reflection roots.
|
|
13
|
+
|
|
14
|
+
- Read the full phase plan before editing.
|
|
15
|
+
- Preserve user work. Never revert changes you did not make.
|
|
16
|
+
- Use `apply_patch` for manual edits.
|
|
17
|
+
- When implementation depends on current external documentation, use PMCP first. Context7 is the preferred path for library docs; Bright Data or other search/scrape tools may be used only when `gateway_catalog_search` shows they are available.
|
|
18
|
+
- Before asking the user for credentials, account setup, infrastructure state, admin action, or another access blocker, inspect repo-local docs/config and safe read-only or metadata-only state from available CLIs: `op`, `gh`, `vercel`/`npx vercel`, `supabase`/`npx supabase`, `gcloud`, `wrangler`, `cloudflared`, and `gam`. Never record secret values.
|
|
19
|
+
- Keep lane ownership boundaries. If implementation requires touching another lane's files, stop and revise the plan or ask the user.
|
|
20
|
+
- Treat ignored, private, raw-data, credential, and evidence-source files as read-protected unless the phase plan or source bundle explicitly allowlists the exact path or glob for read access. Do not infer permission from nearby owned output paths, old memory, or prior phases.
|
|
21
|
+
- Before final closeout, compare `git status --short` dirty paths against the active plan's owned files and control artifacts. If any generated path is unowned, ignored without explicit allowlist/staging policy, or derived from unauthorized raw/private inputs, stop with `dirty_worktree_conflict` instead of calling the phase complete.
|
|
22
|
+
- For Pipeline-aware plans, recompute `source_bundle_sha256` from source bundle bytes before implementation or child work; treat `freshness.source_bundle_hash` as Pipeline-owned metadata unless it is a sha256 digest. For pipeline_required execution, validate protected-source hashes and stop before child launch on missing, stale, malformed, or mismatched source bundles.
|
|
23
|
+
- Refuse protected Pipeline writes, including `.pipeline/**`, `pipeline.definition.json`, governed-pipeline specs, Portal contracts, Greenfield authority files, private evidence, raw data, raw evidence, credentials, provider-supplied payloads, or legacy `.codex/phase-loop/` state unless the source-bundle write policy and phase-plan owned files both explicitly authorize the output path. The active plan and source bundle explicitly own the exact path or glob before these inputs or outputs may be read or written.
|
|
24
|
+
- Preserve standalone execution behavior for local phase plans without Pipeline metadata; governed-pipeline, Portal, Greenfield, `.pipeline/**`, and source bundles are not mandatory for manual dotfiles use.
|
|
25
|
+
- Use `## Execution Policy` only for model, effort, work-unit defaults, lane-specific policy, fallback, policy source, or override reason. `Dispatch Hints` remain executor fallback metadata. Supported selectors are `work-unit defaults`, `roadmap`, `plan`, `execute`, `repair`, `review`, `maintain-skills`, and lane selectors such as `SL-2`; reducer and verification work use lane selectors with `work-unit=phase_reducer` or `work-unit=phase_verify`. Policy precedence is CLI/operator override, phase-plan policy, roadmap policy, `Dispatch Hints`, then registry defaults; policy precedence must not allow silent downgrade without explicit fallback or default inheritance.
|
|
26
|
+
- Do not run destructive git commands such as `git reset --hard` or `git checkout -- <path>` unless the user explicitly requested that operation.
|
|
27
|
+
- Do not commit, push, or merge unless the user asked for those git actions.
|
|
28
|
+
- Claude Code CLI exception wording means local Claude Code CLI execution through the phase-loop launcher, not Anthropic API-key execution or PI provider fallback. Harness and Gemini fallback wording must stay CLI-based and reason-coded.
|
|
29
|
+
|
|
30
|
+
## Runner-Owned Lane Work Units
|
|
31
|
+
|
|
32
|
+
Injected HARNESSLANE runs may include a `HarnessLaneAssignment` from
|
|
33
|
+
`shared/phase-loop/protocol.md`. Treat that assignment as the work-unit
|
|
34
|
+
contract: execute only the selected `lane_id`, write only the listed
|
|
35
|
+
`owned_files`, treat `consumed_interfaces` as read-only, and emit one shared
|
|
36
|
+
`automation:` closeout for that work unit. Installed-skill drift is
|
|
37
|
+
warning-only when the repo-injected context is present.
|
|
38
|
+
|
|
39
|
+
Review, reducer, verify, and closeout prompts are distinct from implementation
|
|
40
|
+
prompts. If the selected policy is unsupported by the active harness, stop with
|
|
41
|
+
a typed non-human blocker instead of silently downgrading. Do not spawn peer
|
|
42
|
+
harnesses directly; cross-harness execute, repair, or review work must be
|
|
43
|
+
externalized as a typed `DelegationRequest`.
|
|
44
|
+
|
|
45
|
+
## Inputs
|
|
46
|
+
|
|
47
|
+
- Plan path: default latest `plans/phase-plan-*.md`.
|
|
48
|
+
- `--dry-run`: parse and print the lane schedule without editing.
|
|
49
|
+
- `--parallel`: allowed only when the user explicitly requests parallel worker execution.
|
|
50
|
+
|
|
51
|
+
If no plan path is explicit, first check the current repo and branch handoff from `<harness>-plan-phase` using `<harness>-config/shared/runtime-state.md`: read the repo-local handoff resolver target `.dev-skills/handoffs/<harness>-plan-phase/latest.md`, validate `from`, `repo`, `repo_root`, `branch`, `branch_slug`, `commit`, and `artifact`, then use the artifact only if it exists under the current repo root. Ignore missing or mismatched handoffs unless the user explicitly asks to reuse cross-branch state.
|
|
52
|
+
|
|
53
|
+
## Preflight
|
|
54
|
+
|
|
55
|
+
1. Resolve repo root and plan path.
|
|
56
|
+
2. Run `git status --short`.
|
|
57
|
+
3. Run `git status --short -- <plan_path>` and classify the plan as tracked, modified, or untracked. If untracked, warn before editing or executing: `This execution input is untracked and can be deleted by git clean -fd.`
|
|
58
|
+
4. If the tree has unrelated dirty files, leave them alone and scope edits around them.
|
|
59
|
+
5. Parse:
|
|
60
|
+
- interface gates;
|
|
61
|
+
- lane DAG;
|
|
62
|
+
- owned files;
|
|
63
|
+
- any explicit read allowlists for ignored, private, raw-data, credential, or evidence-source paths;
|
|
64
|
+
- task lists;
|
|
65
|
+
- verification commands.
|
|
66
|
+
- optional dispatch hints from the roadmap or plan `## Dispatch Hints` section, using only:
|
|
67
|
+
`preferred executors`, `allowed executors`, `fallback executors`, `disabled executors`, and `required capabilities`
|
|
68
|
+
with optional action selectors `roadmap`, `plan`, `execute`, `repair`, `review`, and `maintain-skills`.
|
|
69
|
+
Treat lane `**Owned files**` entries as the execution ownership contract:
|
|
70
|
+
repo-relative literals and globs inside backticks are owned paths, `none`
|
|
71
|
+
owns nothing, and the active roadmap plus active plan artifact are always
|
|
72
|
+
control paths. Treat `Interfaces consumed` as read-only contract inputs
|
|
73
|
+
unless the same path is also listed under `Owned files`. If a test or docs
|
|
74
|
+
update pressures execution to rewrite a consumed upstream artifact, first
|
|
75
|
+
adjust the current phase's owned tests/docs to consume the existing
|
|
76
|
+
contract; if that is impossible, stop and route back to `<harness>-plan-phase`
|
|
77
|
+
for an ownership or downstream-roadmap amendment.
|
|
78
|
+
Owned files authorize writes, not unrestricted reads of ignored/private/raw
|
|
79
|
+
inputs. Read ignored data, private evidence, raw corpora, local-only
|
|
80
|
+
exports, credentials, or user data only when the plan/source bundle names
|
|
81
|
+
the path or glob as an allowed read input; otherwise use metadata-only
|
|
82
|
+
fixtures, committed docs, or stop with a non-human plan/contract blocker.
|
|
83
|
+
6. Validate producer dependencies:
|
|
84
|
+
- any lane that consumes another lane's findings, interfaces, or artifacts must list that producer lane in `Depends on`;
|
|
85
|
+
- any lane that writes a synthesized artifact must be downstream of every producer lane it summarizes;
|
|
86
|
+
- if dependencies are missing, stop and require a plan correction before execution.
|
|
87
|
+
7. For Pipeline-aware plans, run `pipeline_execution_plan_diagnostic`: parse `phase-source-bundle.v1`, recompute `source_bundle_sha256` from source bundle bytes, re-check protected sources, and compare `freshness.source_bundle_hash` only when it is sha256-shaped. Stale source bundles, changed protected sources, missing Pipeline phase artifacts, and unknown Pipeline phase ids are repairable non-human blockers routed to planning or repair with `human_required=false` and `blocker_class=contract_bug`.
|
|
88
|
+
8. For `--dry-run`, report the topological lane order and stop.
|
|
89
|
+
|
|
90
|
+
## Execution Workflow
|
|
91
|
+
|
|
92
|
+
1. Execute lanes in topological order.
|
|
93
|
+
2. For each lane:
|
|
94
|
+
- resolve executor policy in this order: CLI/operator override, then phase-plan hints, then roadmap hints, then registry defaults;
|
|
95
|
+
- reject disabled or capability-mismatched preferred executors with a typed non-human blocker instead of silently falling through;
|
|
96
|
+
- read the owned files and related tests;
|
|
97
|
+
- write or update tests first when practical;
|
|
98
|
+
- implement only lane-scoped changes;
|
|
99
|
+
- for Pipeline-aware lanes, keep writes inside both the phase-plan owned files and source-bundle-authorized Pipeline outputs;
|
|
100
|
+
- do not edit consumed-interface artifacts unless they are also owned by
|
|
101
|
+
the active lane;
|
|
102
|
+
- run lane verification (normalize any phase-plan pytest `-k` selector whose prose terms contain spaces — e.g. `remote connect` becomes `'remote and connect'` — or quote it; a bare spaced `-k` term is an executor-side normalization, not a plan blocker);
|
|
103
|
+
- run any phase-level checks that cover touched files.
|
|
104
|
+
3. After each lane:
|
|
105
|
+
- inspect `git diff -- <owned files>`;
|
|
106
|
+
- confirm no peer-owned files were modified;
|
|
107
|
+
- run `git status --short` and confirm every new or modified path is either lane-owned or a planning/control artifact;
|
|
108
|
+
- for any phase-owned generated path under an ignored parent, confirm the plan/source bundle explicitly allows it to be preserved or force-staged;
|
|
109
|
+
- run `pipeline_write_boundary_diagnostic` when the plan has Pipeline metadata, and fail closed on unauthorized `.pipeline/**`, protected Pipeline, `pipeline.definition.json`, or portal contract writes;
|
|
110
|
+
- record completed gates.
|
|
111
|
+
4. After all lanes:
|
|
112
|
+
- run the full phase verification commands;
|
|
113
|
+
- if execution discoveries change downstream work, amend the phase roadmap at the nearest downstream phase in the amended roadmap that is not already executing;
|
|
114
|
+
- treat any older downstream phase plan or handoff as stale after a roadmap amendment and route the next step back through `<harness>-plan-phase` for the newly selected downstream phase;
|
|
115
|
+
- summarize changed files, tests run, and any residual risks.
|
|
116
|
+
|
|
117
|
+
## Optional Worker Fanout
|
|
118
|
+
|
|
119
|
+
Use worker subagents only when the user explicitly authorizes parallel agent work and the DAG-ready lanes are disjoint.
|
|
120
|
+
|
|
121
|
+
For every worker brief:
|
|
122
|
+
|
|
123
|
+
- State that they are not alone in the codebase.
|
|
124
|
+
- Assign exact owned files or globs.
|
|
125
|
+
- List files they may read but not edit.
|
|
126
|
+
- Tell them not to revert unrelated changes.
|
|
127
|
+
- Require a final response with changed paths, tests run, failures, and blockers.
|
|
128
|
+
- Do not give two workers overlapping write ownership.
|
|
129
|
+
|
|
130
|
+
The main thread remains responsible for integrating results, reviewing diffs, running final verification, and resolving conflicts.
|
|
131
|
+
|
|
132
|
+
## Failure Policy
|
|
133
|
+
|
|
134
|
+
- Test failure in a lane: diagnose once, fix within the lane if the cause is local, otherwise stop and report.
|
|
135
|
+
- Ownership violation: stop and revise the plan before continuing.
|
|
136
|
+
- Missing dependency, malformed lane dependency, or unclear interface: stop and route back to `<harness>-plan-phase` with `human_required=false` unless a true product or human decision is missing.
|
|
137
|
+
- Verification command unavailable: report the missing tool and run the closest available static check only if it is meaningful.
|
|
138
|
+
- True human-required blockers must use the frozen blocker taxonomy from `<harness>-config/shared/runtime-state.md`: `missing_secret`, `account_or_billing_setup`, `admin_approval`, `destructive_operation`, `ambiguous_roadmap_selection`, `product_decision_missing`, `dirty_worktree_conflict`, `branch_sync_conflict`, `stalled_child_observation`, `repeated_verification_failure`, or `unretryable_external_outage`.
|
|
139
|
+
- If the same verification remains failing after one local diagnosis and repair attempt, set `blocker_class=repeated_verification_failure`. If unrelated user work overlaps required lane files, set `blocker_class=dirty_worktree_conflict`.
|
|
140
|
+
- If a release plan with `phase_loop_mutation: release_dispatch` discovers that release-affecting files must be edited before dispatch, do not call the external release command. Stop with `automation.status=blocked`, `human_required=true`, `blocker_class=dirty_worktree_conflict`, and a summary telling the operator to complete/commit the prepare work first.
|
|
141
|
+
- If a phase is ready to report `complete`, verify that `git status --short` is clean for the target repo. If the repo is dirty only because of phase-owned output and required verification passed, do not report it as a human blocker; report `blocked`, `human_required=false`, `blocker_class=dirty_worktree_conflict`, and state that a loop repair turn can commit, isolate, or convert the state to a true human blocker. Use `human_required=true` only when pre-existing unrelated dirty paths overlap the required work, the repo is on the wrong branch/ref, or a true human/product/access decision is needed.
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
## Runner Verification Evidence
|
|
145
|
+
|
|
146
|
+
Before reporting a successful closeout, require the runner-owned verification artifact. The closeout must name `verification_artifact_path`, quote the artifact summary line, and must not report `verification_status=passed` unless that artifact exists and supports the executed work. Treat dependency-manifest install refresh and the full suite before closeout as runner-enforced expectations, not optional narrative checks. A blocked gate may be re-verdicted only by rerunning the originally specified runner check; proxy evidence requires a roadmap or plan amendment before the verdict changes. A prior run's terminal-summary is authoritative for reconcile-or-skip only when that closeout was accepted; a rejected or blocked prior closeout — regardless of any self-reported `complete`/`passed` — must not be reconciled against. On a re-run, re-do and re-verify the phase work from scratch rather than skipping on a stale summary.
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
## Spec Delta Closeout
|
|
150
|
+
|
|
151
|
+
When reporting `verification_status=passed` for a generic phase, attach the runner verification artifact (the closeout's `artifact_paths.verification`, or a top-level `verification_artifact_path`). If the phase legitimately has no executable verification (docs-only, config-only), record a `verification_evidence_opt_out` reason instead — one of `no_executable_verification`, `verification_deferred_to_later_phase`, or `operator_attested_manual`. This is the input the autonomy-first verification-evidence review gate checks (warn by default); recording the artifact or a typed opt-out keeps the closeout clean with no human.
|
|
152
|
+
|
|
153
|
+
Before final closeout, when the diff touches a user-visible public surface (CLI flags, exported symbols, config/openapi schema, contract docs, `README.md`, or `CHANGELOG.md`), record a `doc_delta_decision`: `docs_updated` (you updated the matching doc surface in this phase), `docs_follow_up_filed` (tracked for a later phase), or `no_doc_delta` (the change needs no doc update — state why). This is the input the autonomy-first doc-delta review gate checks; the gate defaults to `PHASE_LOOP_REVIEW=warn` (records the finding and the loop continues), so recording the decision keeps the closeout clean and is satisfiable by the agent with no human. Prefer updating the doc surface within the phase's docs lane over deferring.
|
|
154
|
+
|
|
155
|
+
Before final closeout, when the diff changes a UI/visual surface (`*.tsx`, `*.jsx`, `*.vue`, `*.svelte`, `*.css`/`*.scss`, or `components/**`), capture a screenshot of the rendered result (claude-in-chrome or Playwright-via-PMCP) and record its path as `visual_evidence_path` (with a brief `visual_evidence_observed` note). This is the input the autonomy-first visual-evidence review gate checks; it defaults to warn (recorded, non-blocking) and is satisfiable by the agent capturing the screenshot — no human eyeball needed to pass. The screenshot is the artifact a human spot-checks after a bounded run.
|
|
156
|
+
|
|
157
|
+
Before final closeout, choose exactly one `spec_delta_closeout.v1` decision: `no_spec_delta`, `roadmap_amendment`, `canonical_spec_update`, `governed_pipeline_refresh`, `mirror_cutover_required`, `dotfiles_skill_source_update`, or `human_source_judgment_required`. Cite metadata-only evidence paths such as the active plan, lane closeouts, targeted pytest output, and `git diff --check` output. Preserve the phase plan's target surfaces and `redaction_posture=metadata_only`; do not include raw specification bodies, raw patch bodies, credentials, provider-supplied payloads, local environment values, or evidence-source contents. Missing or malformed spec-closeout evidence is a repairable automation blocker with `blocker_class=contract_bug` unless the decision is `human_source_judgment_required`.
|
|
158
|
+
|
|
159
|
+
## Closeout
|
|
160
|
+
|
|
161
|
+
### Manifest lifecycle
|
|
162
|
+
|
|
163
|
+
After plan validation and before lane execution, perform a best-effort `plan-manifest append` lifecycle update through `phase_loop_runtime.plan_manifest.update_lifecycle` to mark the matching `type=phase` entry `executing` with run metadata. During closeout, update the same entry to `completed` or `failed` with verification metadata, reflection metadata, produced-gate metadata, `if_gates_produced`, and dirty-worktree summary fields as available. `if_gates_produced` must list only the IF gates the active phase produces per its own plan; never carry a prior phase's gate forward into this phase's closeout. Manifest lifecycle failures are non-fatal during the dual-mode window: emit a ledger warning, mention the warning in the mandatory reflection, and preserve the existing phase closeout JSON, verification, and dirty-worktree behavior.
|
|
164
|
+
|
|
165
|
+
Before final closeout, run `git status --short -- <plan_path> <roadmap_path>` for every consumed or updated planning artifact. If any planning artifact is untracked or modified and the user did not explicitly forbid staging, run `git add <path>` for each artifact. Rerun status and report `Artifact state: staged|tracked|modified|unstaged|blocked` for each artifact. Do not commit unless requested. Repo-local handoff files are operational state: do not `git add` an ignored handoff alongside the plan artifact unless the plan's owned-files/allowlist explicitly includes the handoff directory; leave ignored handoffs ignored and exclude them from artifact-state reporting.
|
|
166
|
+
|
|
167
|
+
Also run a whole-tree `git status --short` closeout audit. Classify every dirty path as phase-owned, planning/control, pre-existing unrelated, or unowned. For ignored phase-owned outputs that must be preserved, verify an explicit plan/source-bundle allowlist or staging policy before using `git add -f`; otherwise report a repairable `dirty_worktree_conflict`. Precedence for a verified phase: when required verification passed and the ONLY uncommitted paths are phase-owned outputs this run was not authorized to commit, report `terminal_status=awaiting_phase_closeout` and let the runner's graduated closeout gate commit them — do NOT report `dirty_worktree_conflict`; reserve that conflict for unowned, unauthorized-ignored, or overlapping-unrelated dirty paths. Never report `complete` while unowned generated files, unauthorized ignored outputs, or outputs derived from unauthorized raw/private reads remain in the worktree.
|
|
168
|
+
|
|
169
|
+
Determine the next step before final response and handoff:
|
|
170
|
+
|
|
171
|
+
- If the current phase is incomplete or verification failed, report `Next phase: <current alias> - blocked: <blocker>` and `Next command: none - <blocker>`.
|
|
172
|
+
- If another generated phase plan is ready, report `Next phase: <next alias> - execution ready` and `Next command: <harness>-execute-phase <next_plan_path>`.
|
|
173
|
+
- If the roadmap has an unplanned ready phase, report `Next phase: <next alias> - planning ready` and `Next command: <harness>-plan-phase <roadmap_path> <next_alias>`.
|
|
174
|
+
- If the roadmap needs extension, report `Next phase: none - roadmap extension needed` and `Next command: <harness>-phase-roadmap-builder <roadmap_path>`.
|
|
175
|
+
- If all phases are complete, report `Next phase: none - roadmap complete` and `Next command: none - roadmap complete`.
|
|
176
|
+
|
|
177
|
+
Add a machine-readable automation handoff that agrees with the human-readable next step fields. Closeout payload shape is defined by `EmitPhaseCloseout` in `phase_loop_runtime/baml_src/emit_phase_closeout.baml` (if that path is absent in the checkout, use the operator/prompt-supplied field contract or the installed `phase_loop_runtime` package — the missing vendored BAML source is not a blocker); keep skill text focused on value selection and handoff routing, not duplicated field ceremony.
|
|
178
|
+
|
|
179
|
+
Before final response, write a reflection for every non-trivial run. Write it to `resolve_skill_bundle_root("codex")/<harness>-execute-phase/reflections/<repo_hash>/<branch_slug>/<run_id>.md`. The reflection must include `## Run context` with skill name, ISO timestamp, repo, branch, commit, and artifact path if any, followed by `## What worked`, `## What didn't`, and `## Improvements to SKILL.md`. skip only when no artifact was produced AND no decision was made AND the run was pure inspection.
|
|
180
|
+
|
|
181
|
+
Set `automation.status=complete`, `verification_status=passed`, and `human_required=false` only when acceptance criteria and required verification are satisfied. Set `automation.status=executed` when implementation ran but acceptance reduction, artifact tracking, or a required verification remains unresolved. Use the consumed phase plan as the handoff `artifact`; the autonomous phase loop trusts phase status handoffs only when that plan's phase-loop frontmatter still matches the selected roadmap. For repairable plan gaps such as malformed dependencies or missing lane interfaces, set `automation.status=blocked`, `next_skill=<harness>-plan-phase`, `next_command=<harness>-plan-phase <roadmap_path> <current_alias>`, `next_model_hint=plan`, `next_effort_hint=high`, and `human_required=false`. For true human blockers, set `human_required=true`, a frozen `blocker_class`, a redacted `blocker_summary`, non-secret `required_human_inputs`, and redacted `access_attempts` when access was involved. Never include secret values.
|
|
182
|
+
|
|
183
|
+
Manual TUI runs remain valid without the outer phase loop. When `.phase-loop/` exists, treat it as the authoritative runner state; legacy `.codex/phase-loop/` files are compatibility artifacts only and must not block or supersede canonical `.phase-loop/` state. When canonical `.phase-loop/state.json` or `tui-handoff.md` lags behind the newer `.phase-loop/events.jsonl` plus live git topology, reconcile current phase state from the ledger and `git status --short`/HEAD and cite that reconciliation; stale handoff text is not blocking. Only append a legacy `manual` source event to `.codex/phase-loop/events.jsonl` for standalone manual compatibility when no canonical `.phase-loop/` runtime exists, using the same `automation.status`, `next_skill`, `next_command`, `next_model_hint`, `next_effort_hint`, `human_required`, `blocker_class`, `blocker_summary`, `required_human_inputs`, `verification_status`, `artifact`, and `artifact_state` values. This manual event import must preserve the same machine-readable closeout contract. If execution amended the roadmap downstream, compute `roadmap_sha256` and `phase_sha256` from the amended roadmap for the completed current phase before appending the event; do not reuse stale plan frontmatter, next-phase hashes, or pre-amendment roadmap hashes.
|
|
184
|
+
|
|
185
|
+
Report:
|
|
186
|
+
|
|
187
|
+
- lanes completed;
|
|
188
|
+
- files changed;
|
|
189
|
+
- planning artifact tracking state;
|
|
190
|
+
- next phase and next command;
|
|
191
|
+
- verification commands and results;
|
|
192
|
+
- commands not run and why;
|
|
193
|
+
- follow-up risks or manual checks.
|
|
194
|
+
|
|
195
|
+
Resolve closeout writes through `shared/phase-loop/handoff_path.py` and the repo-local handoff resolver; legacy harness handoff roots are read only for migration. Follow `<harness>-config/shared/runtime-state.md` and use Harness paths only:
|
|
196
|
+
|
|
197
|
+
- Reflection: `resolve_skill_bundle_root("codex")/<harness>-execute-phase/reflections/<repo_hash>/<branch_slug>/<run_id>.md`
|
|
198
|
+
- Handoff: `<repo>/.dev-skills/handoffs/<harness>-execute-phase/<run_id>.md`
|
|
199
|
+
- Latest handoff pointer: `<repo>/.dev-skills/handoffs/<harness>-execute-phase/latest.md`
|
|
200
|
+
|
|
201
|
+
Handoff frontmatter must include `from: <harness>-execute-phase`, `timestamp:`, `repo:`, `repo_root:`, `branch:`, `branch_slug:`, `commit:`, `run_id:`, `artifact:`, `artifact_state:`, `next_skill:`, `next_command:`, and `next_phase:`. Put open follow-up items in the body, and update `latest.md` with the same handoff content.
|
|
202
|
+
|
|
203
|
+
If execution is blocked by credentials, account setup, infrastructure state, admin action, or other access prerequisites, write a handoff with `human_required=true` and redacted `access_attempts` entries before asking the user to act. Each `access_attempts` entry must include `source`, `probe`, `result`, `details`, and `timestamp`, and `details` may report only metadata such as command availability, account or project identity, vault/item/field names, environment variable names, presence, and validation status.
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
## Publication mode
|
|
207
|
+
|
|
208
|
+
After verified phase work, select exactly one of three modes. **Default to (a) unless a
|
|
209
|
+
clear interactive signal is present** — a run missing BOTH the adapter prompt prefix AND
|
|
210
|
+
`PHASE_LOOP_RUN_MODE` is AMBIGUOUS and MUST be treated as (a) (fail safe toward the runner).
|
|
211
|
+
|
|
212
|
+
- (a) Runner-managed closeout (incl. governed mode), OR ambiguous mode. If this is the
|
|
213
|
+
phase-loop adapter (the prompt begins with `<harness>-execute-phase <plan>` from a
|
|
214
|
+
pipeline run dir), or `PHASE_LOOP_RUN_MODE` is set (autonomous/governed), OR neither
|
|
215
|
+
interactive signal is clearly present, the RUNNER owns closeout and commit. Do NOT
|
|
216
|
+
independently publish — defer entirely to runner closeout (`awaiting_phase_closeout` /
|
|
217
|
+
runner commit). Publishing here would bypass the governed pre-merge review panel.
|
|
218
|
+
- (b) Interactive orchestrator on a clean, non-protected feature branch (a clear
|
|
219
|
+
interactive signal, and the merge target passed the merge-target safety gate). After the
|
|
220
|
+
Step-9 clean-tree state, push the merge-target branch and open a PR (`gh pr create`,
|
|
221
|
+
`--draft` if dependencies remain or verification was partial/skipped, else ready) instead
|
|
222
|
+
of leaving the lane merge only local.
|
|
223
|
+
- (c) Merge target is `main` or a protected branch. Already STOPPED at the merge-target
|
|
224
|
+
safety gate before any lane merge — never merge lanes onto `main`/protected. Re-target a
|
|
225
|
+
feature branch or take explicit instruction.
|
|
226
|
+
|
|
227
|
+
This applies only to interactive (non-runner) completion; it never overrides
|
|
228
|
+
`awaiting_phase_closeout`, the runner's deliberate non-complete terminal. Allowed runner
|
|
229
|
+
hygiene (forced lane-worktree removal, `branch -D`, `sweep_stale_worktrees.sh`) is
|
|
230
|
+
unchanged — the destructive-op ban targets publication branches/worktrees holding
|
|
231
|
+
unmerged work.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# allocate_worktree_name.sh — emit a collision-impossible worktree name
|
|
3
|
+
# for a swim-lane teammate.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# allocate_worktree_name.sh <sl-id>
|
|
7
|
+
#
|
|
8
|
+
# <sl-id> Lane identifier, e.g. "sl-1" or "sl-2b".
|
|
9
|
+
#
|
|
10
|
+
# Emits exactly one line to stdout:
|
|
11
|
+
# lane-<sl-id>-<UTC-YYYYMMDDHHMMSS>-<4char-random>
|
|
12
|
+
#
|
|
13
|
+
# Rationale: the default `lane-<sl-id>` naming is not unique across rapid
|
|
14
|
+
# consecutive dispatch of in-process teammates — two teammates spawned in
|
|
15
|
+
# the same message can race on the same EnterWorktree slot. The 4-char
|
|
16
|
+
# random suffix + UTC timestamp eliminates the race by construction.
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
if [[ $# -ne 1 ]]; then
|
|
21
|
+
echo "usage: allocate_worktree_name.sh <sl-id>" >&2
|
|
22
|
+
exit 2
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
sl_id="$1"
|
|
26
|
+
ts="$(date -u +%Y%m%dT%H%M%S)"
|
|
27
|
+
rand="$(tr -dc 'a-z0-9' </dev/urandom | head -c 4 || true)"
|
|
28
|
+
if [[ -z "$rand" ]]; then
|
|
29
|
+
# Extremely unlikely; fall back to $RANDOM-derived 4 chars.
|
|
30
|
+
rand="$(printf "%04x" "$((RANDOM & 0xFFFF))")"
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
echo "lane-${sl_id}-${ts}-${rand}"
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
audit_lane_file_touches.py — audit a lane's commit against the plan's
|
|
4
|
+
disjoint-owned-files contract.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
audit_lane_file_touches.py <lane-sha> <plan-doc-path> <this-lane-id>
|
|
8
|
+
|
|
9
|
+
Emits EXACTLY one token on stdout, exit 0 always (verdict is on stdout
|
|
10
|
+
for the orchestrator to act on):
|
|
11
|
+
|
|
12
|
+
CLEAN
|
|
13
|
+
- Every file touched by <lane-sha> (vs its first-parent ancestor)
|
|
14
|
+
falls within <this-lane-id>'s `Owned files` globs from the plan
|
|
15
|
+
doc.
|
|
16
|
+
|
|
17
|
+
PEER_INTRUSION
|
|
18
|
+
- One or more files touched match some OTHER lane's `Owned files`
|
|
19
|
+
globs. The lane wandered into a peer's territory. Orchestrator
|
|
20
|
+
surfaces to user for merge/no-merge decision — defensive cross-
|
|
21
|
+
lane test-mock edits happen and are usually benign, but should be
|
|
22
|
+
reviewed rather than surfacing as a later merge conflict.
|
|
23
|
+
|
|
24
|
+
ORPHAN_FILES
|
|
25
|
+
- One or more files touched fall OUTSIDE every lane's globs. The
|
|
26
|
+
teammate worked outside any declared lane scope — probable bug.
|
|
27
|
+
|
|
28
|
+
Any combination of intrusion + orphan is reported with intrusion winning.
|
|
29
|
+
Details (which peer, which files) are written to stderr.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from __future__ import annotations
|
|
33
|
+
|
|
34
|
+
import re
|
|
35
|
+
import subprocess
|
|
36
|
+
import sys
|
|
37
|
+
from pathlib import Path
|
|
38
|
+
from typing import Dict, List, Optional, Set
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
_SL_SECTION_RE = re.compile(r"^###\s+(SL-\d+)\b.*$", re.MULTILINE)
|
|
42
|
+
_OWNED_BULLET_RE = re.compile(
|
|
43
|
+
r"^\s*-\s*\*\*Owned files\*\*\s*:\s*(.*?)\s*$",
|
|
44
|
+
re.IGNORECASE,
|
|
45
|
+
)
|
|
46
|
+
_CODE_TOKEN_RE = re.compile(r"`([^`]+)`")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _fail(msg: str) -> None:
|
|
50
|
+
print(f"audit_lane_file_touches: {msg}", file=sys.stderr)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _read(path: Path) -> str:
|
|
54
|
+
try:
|
|
55
|
+
return path.read_text(encoding="utf-8")
|
|
56
|
+
except Exception as exc:
|
|
57
|
+
_fail(f"cannot read {path}: {exc}")
|
|
58
|
+
sys.exit(2)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _extract_lanes_body(src: str) -> str:
|
|
62
|
+
"""Return the body between '## Lanes' and the next '## '."""
|
|
63
|
+
lines = src.splitlines()
|
|
64
|
+
out: List[str] = []
|
|
65
|
+
in_section = False
|
|
66
|
+
for line in lines:
|
|
67
|
+
if line.startswith("## ") and line.strip() == "## Lanes":
|
|
68
|
+
in_section = True
|
|
69
|
+
continue
|
|
70
|
+
if in_section and line.startswith("## "):
|
|
71
|
+
break
|
|
72
|
+
if in_section:
|
|
73
|
+
out.append(line)
|
|
74
|
+
return "\n".join(out)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _parse_owned_globs(lanes_body: str) -> Dict[str, List[str]]:
|
|
78
|
+
"""Map SL-N -> list of owned globs as declared in the plan."""
|
|
79
|
+
matches = list(_SL_SECTION_RE.finditer(lanes_body))
|
|
80
|
+
result: Dict[str, List[str]] = {}
|
|
81
|
+
for idx, m in enumerate(matches):
|
|
82
|
+
sl_id = m.group(1)
|
|
83
|
+
start = m.end()
|
|
84
|
+
end = matches[idx + 1].start() if idx + 1 < len(matches) else len(lanes_body)
|
|
85
|
+
body = lanes_body[start:end]
|
|
86
|
+
globs: List[str] = []
|
|
87
|
+
for line in body.splitlines():
|
|
88
|
+
mb = _OWNED_BULLET_RE.match(line)
|
|
89
|
+
if not mb:
|
|
90
|
+
continue
|
|
91
|
+
raw = mb.group(1)
|
|
92
|
+
tokens = _CODE_TOKEN_RE.findall(raw)
|
|
93
|
+
globs.extend(t.strip() for t in tokens if t.strip())
|
|
94
|
+
# Drop annotation-only items like "(NEW)" / "(DELETE)".
|
|
95
|
+
globs = [
|
|
96
|
+
g.split()[0].strip() for g in globs
|
|
97
|
+
if g and not g.startswith("(")
|
|
98
|
+
]
|
|
99
|
+
result[sl_id] = globs
|
|
100
|
+
return result
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _glob_to_regex(pattern: str) -> re.Pattern:
|
|
104
|
+
"""Minimal glob → regex. ** → any depth; * → any non-/; ? → one non-/."""
|
|
105
|
+
s = pattern.strip("`").strip()
|
|
106
|
+
esc = re.escape(s)
|
|
107
|
+
esc = esc.replace(r"\*\*", ".*").replace(r"\*", "[^/]*").replace(r"\?", "[^/]")
|
|
108
|
+
return re.compile("^" + esc + "$")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _touched_files(sha: str) -> List[str]:
|
|
112
|
+
"""Files changed by <sha> relative to its first parent."""
|
|
113
|
+
try:
|
|
114
|
+
r = subprocess.run(
|
|
115
|
+
["git", "diff", "--name-only", f"{sha}^..{sha}"],
|
|
116
|
+
capture_output=True, text=True, check=True,
|
|
117
|
+
)
|
|
118
|
+
except subprocess.CalledProcessError:
|
|
119
|
+
# Commit has no parent (e.g., root) — fall back to diff against empty tree.
|
|
120
|
+
r = subprocess.run(
|
|
121
|
+
["git", "show", "--name-only", "--pretty=", sha],
|
|
122
|
+
capture_output=True, text=True, check=True,
|
|
123
|
+
)
|
|
124
|
+
return [line for line in r.stdout.splitlines() if line.strip()]
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def main(argv: List[str]) -> int:
|
|
128
|
+
if len(argv) != 4:
|
|
129
|
+
_fail("usage: audit_lane_file_touches.py <lane-sha> <plan-doc-path> <this-lane-id>")
|
|
130
|
+
return 2
|
|
131
|
+
|
|
132
|
+
lane_sha = argv[1]
|
|
133
|
+
plan_path = Path(argv[2])
|
|
134
|
+
this_lane = argv[3]
|
|
135
|
+
|
|
136
|
+
if not plan_path.exists():
|
|
137
|
+
_fail(f"plan doc not found: {plan_path}")
|
|
138
|
+
return 2
|
|
139
|
+
|
|
140
|
+
src = _read(plan_path)
|
|
141
|
+
lanes_body = _extract_lanes_body(src)
|
|
142
|
+
owned_map = _parse_owned_globs(lanes_body)
|
|
143
|
+
|
|
144
|
+
if this_lane not in owned_map:
|
|
145
|
+
_fail(f"lane {this_lane} not found in plan doc's `## Lanes` section")
|
|
146
|
+
return 2
|
|
147
|
+
|
|
148
|
+
# Compile regexes per lane.
|
|
149
|
+
compiled: Dict[str, List[re.Pattern]] = {
|
|
150
|
+
sl: [_glob_to_regex(g) for g in globs]
|
|
151
|
+
for sl, globs in owned_map.items()
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
touched = _touched_files(lane_sha)
|
|
155
|
+
|
|
156
|
+
def match_any(path: str, pats: List[re.Pattern]) -> bool:
|
|
157
|
+
return any(p.match(path) for p in pats)
|
|
158
|
+
|
|
159
|
+
intrusions: Dict[str, List[str]] = {}
|
|
160
|
+
orphans: List[str] = []
|
|
161
|
+
clean: List[str] = []
|
|
162
|
+
for path in touched:
|
|
163
|
+
if match_any(path, compiled[this_lane]):
|
|
164
|
+
clean.append(path)
|
|
165
|
+
continue
|
|
166
|
+
peer_hit: Optional[str] = None
|
|
167
|
+
for sl, pats in compiled.items():
|
|
168
|
+
if sl == this_lane:
|
|
169
|
+
continue
|
|
170
|
+
if match_any(path, pats):
|
|
171
|
+
peer_hit = sl
|
|
172
|
+
break
|
|
173
|
+
if peer_hit is not None:
|
|
174
|
+
intrusions.setdefault(peer_hit, []).append(path)
|
|
175
|
+
else:
|
|
176
|
+
orphans.append(path)
|
|
177
|
+
|
|
178
|
+
# Emit verdict. Intrusion takes precedence over orphan (intrusion is more actionable).
|
|
179
|
+
if intrusions:
|
|
180
|
+
for peer, paths in sorted(intrusions.items()):
|
|
181
|
+
_fail(f"{this_lane} touched files owned by {peer}: {paths}")
|
|
182
|
+
if orphans:
|
|
183
|
+
_fail(f"{this_lane} also touched orphan files (no lane owns): {orphans}")
|
|
184
|
+
print("PEER_INTRUSION")
|
|
185
|
+
return 0
|
|
186
|
+
|
|
187
|
+
if orphans:
|
|
188
|
+
_fail(f"{this_lane} touched files outside any lane's Owned files: {orphans}")
|
|
189
|
+
print("ORPHAN_FILES")
|
|
190
|
+
return 0
|
|
191
|
+
|
|
192
|
+
print("CLEAN")
|
|
193
|
+
return 0
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
if __name__ == "__main__":
|
|
197
|
+
sys.exit(main(sys.argv))
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# cleanup_lane_worktrees.sh — remove lane worktrees and their auto-named
|
|
3
|
+
# branches after a phase merges.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# cleanup_lane_worktrees.sh <branch-pattern>
|
|
7
|
+
#
|
|
8
|
+
# <branch-pattern> Glob applied to each worktree's branch name (the
|
|
9
|
+
# short name, not refs/heads/…). Defaults to
|
|
10
|
+
# 'worktree-*' so the common case works with no arg.
|
|
11
|
+
#
|
|
12
|
+
# Behavior:
|
|
13
|
+
# - Enumerates every worktree via `git worktree list --porcelain`.
|
|
14
|
+
# - Skips the orchestrator's own worktree (identified by matching the
|
|
15
|
+
# `git rev-parse --show-toplevel` of the current cwd).
|
|
16
|
+
# - For each remaining worktree whose branch matches <branch-pattern>:
|
|
17
|
+
# * `git worktree remove --force <path>`
|
|
18
|
+
# * If the branch also matches 'worktree-*' or 'phase/*/sl-*',
|
|
19
|
+
# `git branch -D <branch>` (salvage footgun: -D, not -d).
|
|
20
|
+
# - Never blocks the phase: exit 0 even on individual cleanup failures;
|
|
21
|
+
# each failure is logged to stderr.
|
|
22
|
+
#
|
|
23
|
+
# Rationale: Step 7 post-merge cleanup. Keeps human-named branches intact
|
|
24
|
+
# (skills/*, feature/*, fix/*) even when accidentally matched by glob.
|
|
25
|
+
|
|
26
|
+
set -uo pipefail
|
|
27
|
+
|
|
28
|
+
pattern="${1:-worktree-*}"
|
|
29
|
+
|
|
30
|
+
# Resolve orchestrator's anchored worktree so we don't try to delete it.
|
|
31
|
+
orch_root=""
|
|
32
|
+
if orch_root="$(git rev-parse --show-toplevel 2>/dev/null)"; then
|
|
33
|
+
:
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
removed=0
|
|
37
|
+
skipped=0
|
|
38
|
+
|
|
39
|
+
# Parse `git worktree list --porcelain`. Each record is separated by a blank line:
|
|
40
|
+
# worktree <path>
|
|
41
|
+
# HEAD <sha>
|
|
42
|
+
# branch refs/heads/<name>
|
|
43
|
+
while IFS= read -r block; do
|
|
44
|
+
# `git worktree list --porcelain` actually yields one line per key; we
|
|
45
|
+
# collapse them back into records here.
|
|
46
|
+
[[ -z "$block" ]] && continue
|
|
47
|
+
key="${block%% *}"
|
|
48
|
+
value="${block#* }"
|
|
49
|
+
case "$key" in
|
|
50
|
+
worktree)
|
|
51
|
+
wt_path="$value"
|
|
52
|
+
wt_branch=""
|
|
53
|
+
;;
|
|
54
|
+
branch)
|
|
55
|
+
# value looks like 'refs/heads/worktree-sl-1'
|
|
56
|
+
wt_branch="${value#refs/heads/}"
|
|
57
|
+
;;
|
|
58
|
+
HEAD) ;; # ignore
|
|
59
|
+
detached) wt_branch="" ;;
|
|
60
|
+
esac
|
|
61
|
+
# When we hit a new `worktree` line, the previous record is complete —
|
|
62
|
+
# but the block-mode loop above feeds us line-by-line. We process each
|
|
63
|
+
# line and finalize when we hit a record boundary below.
|
|
64
|
+
done < <(git worktree list --porcelain)
|
|
65
|
+
|
|
66
|
+
# Process each worktree block (re-read cleanly; the above was an artifact).
|
|
67
|
+
while IFS= read -r path; do
|
|
68
|
+
[[ -z "$path" ]] && continue
|
|
69
|
+
# Skip orchestrator's anchor.
|
|
70
|
+
if [[ "$path" == "$orch_root" ]]; then
|
|
71
|
+
skipped=$((skipped + 1))
|
|
72
|
+
continue
|
|
73
|
+
fi
|
|
74
|
+
# Resolve this worktree's branch.
|
|
75
|
+
branch="$(git -C "$path" rev-parse --abbrev-ref HEAD 2>/dev/null || echo '')"
|
|
76
|
+
if [[ -z "$branch" || "$branch" == "HEAD" ]]; then
|
|
77
|
+
# Detached HEAD worktree — skip.
|
|
78
|
+
skipped=$((skipped + 1))
|
|
79
|
+
continue
|
|
80
|
+
fi
|
|
81
|
+
# Apply the branch pattern.
|
|
82
|
+
# shellcheck disable=SC2053
|
|
83
|
+
if [[ "$branch" != $pattern ]]; then
|
|
84
|
+
skipped=$((skipped + 1))
|
|
85
|
+
continue
|
|
86
|
+
fi
|
|
87
|
+
# Remove the worktree.
|
|
88
|
+
if git worktree remove --force "$path" 2>/dev/null; then
|
|
89
|
+
removed=$((removed + 1))
|
|
90
|
+
else
|
|
91
|
+
echo "cleanup_lane_worktrees: failed to remove worktree $path (branch=$branch)" >&2
|
|
92
|
+
continue
|
|
93
|
+
fi
|
|
94
|
+
# Delete the branch only if it's an auto-named pattern.
|
|
95
|
+
if [[ "$branch" == worktree-* || "$branch" == phase/*/sl-* ]]; then
|
|
96
|
+
if ! git branch -D "$branch" 2>/dev/null; then
|
|
97
|
+
echo "cleanup_lane_worktrees: failed to delete branch $branch" >&2
|
|
98
|
+
fi
|
|
99
|
+
fi
|
|
100
|
+
done < <(git worktree list --porcelain | awk '$1 == "worktree" { print $2 }')
|
|
101
|
+
|
|
102
|
+
echo "cleanup_lane_worktrees: removed $removed, skipped $skipped"
|
|
103
|
+
exit 0
|