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.
Files changed (370) hide show
  1. phase_loop_runtime/__init__.py +20 -0
  2. phase_loop_runtime/_contract_docs/phase-loop/extraction-readiness.md +90 -0
  3. phase_loop_runtime/_contract_docs/phase-loop/granular-execution-policy.md +137 -0
  4. phase_loop_runtime/_contract_docs/phase-loop/harness-capability-matrix.md +510 -0
  5. phase_loop_runtime/_contract_docs/phase-loop/harness-skill-matrix.md +125 -0
  6. phase_loop_runtime/_contract_docs/phase-loop/harness-substrate-manifest.md +232 -0
  7. phase_loop_runtime/_contract_docs/phase-loop/pi-loop-control.md +247 -0
  8. phase_loop_runtime/_contract_docs/phase-loop/protocol.md +2759 -0
  9. phase_loop_runtime/_contract_docs/phase-loop/runtime-boundary.md +289 -0
  10. phase_loop_runtime/_contract_docs/phase-loop/spec-discovery-roots.md +47 -0
  11. phase_loop_runtime/_contract_docs/phase-loop/substrate-soak-governed-pipeline.md +42 -0
  12. phase_loop_runtime/_contract_docs/phase-loop/substrate-soak-portal-projection.md +34 -0
  13. phase_loop_runtime/_contract_docs/phase-loop/substrate-soak-regenesis.md +29 -0
  14. phase_loop_runtime/_contract_docs/phase-loop/substrate-soak-report.md +32 -0
  15. phase_loop_runtime/_contract_docs/runtime/verification-evidence-contract.md +52 -0
  16. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-mixed-signals/commands.txt +2 -0
  17. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-mixed-signals/manifest.json +16 -0
  18. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-mixed-signals/mixed.json +5 -0
  19. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-provider-timeout/manifest.json +16 -0
  20. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-provider-timeout/timeout-note.txt +2 -0
  21. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-redacted-summary/manifest.json +16 -0
  22. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-redacted-summary/redacted-summary.json +6 -0
  23. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-small-sample/manifest.json +16 -0
  24. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-small-sample/sample.json +7 -0
  25. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-threshold-edge/edge.txt +2 -0
  26. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/borderline/borderline-threshold-edge/manifest.json +16 -0
  27. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-duplicate-png/manifest.json +16 -0
  28. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-duplicate-png/shot-a.txt +1 -0
  29. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-duplicate-png/shot-b.txt +1 -0
  30. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-duplicate-png/shot-c.txt +1 -0
  31. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-missing-references/claimed-results.json +5 -0
  32. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-missing-references/manifest.json +16 -0
  33. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-subtle-low-variance/manifest.json +16 -0
  34. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-subtle-low-variance/metrics.json +9 -0
  35. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-templated-prose/findings.md +10 -0
  36. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-templated-prose/manifest.json +16 -0
  37. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-uniform-scores/manifest.json +16 -0
  38. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-uniform-scores/scores.json +4 -0
  39. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-fake/fake-uniform-scores/summary.txt +1 -0
  40. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-adoption-bundle/bundle-check.json +8 -0
  41. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-adoption-bundle/manifest.json +16 -0
  42. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-adoption-bundle/operator-note.txt +2 -0
  43. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-handoff-ledger/events-sample.jsonl +3 -0
  44. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-handoff-ledger/manifest.json +16 -0
  45. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-handoff-ledger/receipt.txt +1 -0
  46. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-runner-diff/evidence.json +13 -0
  47. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-runner-diff/manifest.json +16 -0
  48. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-runner-diff/summary.txt +2 -0
  49. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-test-matrix/manifest.json +16 -0
  50. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-test-matrix/matrix.json +9 -0
  51. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-test-matrix/notes.md +4 -0
  52. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-ui-screenshot-standin/console-summary.txt +2 -0
  53. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-ui-screenshot-standin/manifest.json +16 -0
  54. phase_loop_runtime/_test_fixtures/evidence-audit-calibration/known-real/real-ui-screenshot-standin/screenshot-standin.ppm +5 -0
  55. phase_loop_runtime/adoption_bundle.py +273 -0
  56. phase_loop_runtime/advisor_board/CONTRACTS.md +257 -0
  57. phase_loop_runtime/advisor_board/__init__.py +288 -0
  58. phase_loop_runtime/advisor_board/backing.py +137 -0
  59. phase_loop_runtime/advisor_board/backing_omnigent.py +498 -0
  60. phase_loop_runtime/advisor_board/config.py +225 -0
  61. phase_loop_runtime/advisor_board/events.py +115 -0
  62. phase_loop_runtime/advisor_board/fixtures/advisor-boards.example.toml +59 -0
  63. phase_loop_runtime/advisor_board/fixtures.py +91 -0
  64. phase_loop_runtime/advisor_board/harness_mapping.py +125 -0
  65. phase_loop_runtime/advisor_board/matrix.py +146 -0
  66. phase_loop_runtime/advisor_board/observability.py +481 -0
  67. phase_loop_runtime/advisor_board/presets.py +188 -0
  68. phase_loop_runtime/advisor_board/registries.py +309 -0
  69. phase_loop_runtime/advisor_board/resolver.py +253 -0
  70. phase_loop_runtime/advisor_board/schema.py +269 -0
  71. phase_loop_runtime/advisor_board/standin.py +166 -0
  72. phase_loop_runtime/advisor_board/validation.py +159 -0
  73. phase_loop_runtime/agent_runtime_provider.py +676 -0
  74. phase_loop_runtime/baml_modular.py +656 -0
  75. phase_loop_runtime/baml_src/dotfiles_adoption_manifest.baml +37 -0
  76. phase_loop_runtime/baml_src/dotfiles_c4_document.baml +14 -0
  77. phase_loop_runtime/baml_src/dotfiles_plan_manifest.baml +50 -0
  78. phase_loop_runtime/baml_src/dotfiles_runtime_projection.baml +16 -0
  79. phase_loop_runtime/baml_src/dotfiles_task_catalog.baml +20 -0
  80. phase_loop_runtime/baml_src/emit_phase_closeout.baml +86 -0
  81. phase_loop_runtime/baml_src/evaluate_suspected_fake_evidence.baml +36 -0
  82. phase_loop_runtime/baml_src/verification_evidence.baml +40 -0
  83. phase_loop_runtime/broker.py +181 -0
  84. phase_loop_runtime/build_bundle.py +294 -0
  85. phase_loop_runtime/capability_registry.py +835 -0
  86. phase_loop_runtime/classifier.py +87 -0
  87. phase_loop_runtime/claude_agent_view.py +625 -0
  88. phase_loop_runtime/claude_channel_sidecar.py +1086 -0
  89. phase_loop_runtime/cli.py +2599 -0
  90. phase_loop_runtime/closeout.py +865 -0
  91. phase_loop_runtime/closeout_classifier.py +120 -0
  92. phase_loop_runtime/closeout_evidence_audit.py +112 -0
  93. phase_loop_runtime/closeout_validation.py +144 -0
  94. phase_loop_runtime/closeout_validators.py +203 -0
  95. phase_loop_runtime/consiliency_gates.py +374 -0
  96. phase_loop_runtime/consiliency_ingest.py +399 -0
  97. phase_loop_runtime/consiliency_layout.py +176 -0
  98. phase_loop_runtime/consiliency_scaffold.py +305 -0
  99. phase_loop_runtime/cross_repo_channel.py +331 -0
  100. phase_loop_runtime/discovery.py +2368 -0
  101. phase_loop_runtime/dispatch_lock.py +167 -0
  102. phase_loop_runtime/doc_delta_validator.py +98 -0
  103. phase_loop_runtime/docs_audit.py +285 -0
  104. phase_loop_runtime/docs_freshness.py +468 -0
  105. phase_loop_runtime/docs_surfaces.py +150 -0
  106. phase_loop_runtime/dotfiles_profile_plugin.py +96 -0
  107. phase_loop_runtime/events.py +154 -0
  108. phase_loop_runtime/events_migration.py +96 -0
  109. phase_loop_runtime/evidence_audit.py +1082 -0
  110. phase_loop_runtime/evidence_audit_config.py +172 -0
  111. phase_loop_runtime/fleet_map.py +426 -0
  112. phase_loop_runtime/fleet_metrics.py +298 -0
  113. phase_loop_runtime/fleet_metrics_export.py +196 -0
  114. phase_loop_runtime/git_discipline.py +479 -0
  115. phase_loop_runtime/git_ops.py +122 -0
  116. phase_loop_runtime/git_topology.py +252 -0
  117. phase_loop_runtime/governed_bundle.py +137 -0
  118. phase_loop_runtime/governed_premerge.py +219 -0
  119. phase_loop_runtime/governed_review.py +264 -0
  120. phase_loop_runtime/handoff.py +932 -0
  121. phase_loop_runtime/handoff_path.py +14 -0
  122. phase_loop_runtime/injection.py +740 -0
  123. phase_loop_runtime/install_status.py +88 -0
  124. phase_loop_runtime/lane_scheduler.py +317 -0
  125. phase_loop_runtime/launcher.py +2760 -0
  126. phase_loop_runtime/lease_store.py +553 -0
  127. phase_loop_runtime/maintenance.py +401 -0
  128. phase_loop_runtime/migrate_handoffs.py +201 -0
  129. phase_loop_runtime/models.py +2144 -0
  130. phase_loop_runtime/observability.py +1290 -0
  131. phase_loop_runtime/panel_invoker.py +1638 -0
  132. phase_loop_runtime/phase_loop_drift_audit.py +388 -0
  133. phase_loop_runtime/phase_worktree_executor.py +433 -0
  134. phase_loop_runtime/pipeline_adapter/__init__.py +12 -0
  135. phase_loop_runtime/pipeline_adapter/branch_ops.py +274 -0
  136. phase_loop_runtime/pipeline_adapter/flag.py +55 -0
  137. phase_loop_runtime/pipeline_adapter/markers.py +13 -0
  138. phase_loop_runtime/pipeline_adapter/merge_policy.py +72 -0
  139. phase_loop_runtime/pipeline_adapter/ratification.py +100 -0
  140. phase_loop_runtime/pipeline_adapter/sibling_matcher.py +123 -0
  141. phase_loop_runtime/plan_ir.py +523 -0
  142. phase_loop_runtime/plan_manifest.py +415 -0
  143. phase_loop_runtime/planner_validation.py +176 -0
  144. phase_loop_runtime/profiles.py +462 -0
  145. phase_loop_runtime/prompts.py +365 -0
  146. phase_loop_runtime/provenance.py +165 -0
  147. phase_loop_runtime/publishing.py +339 -0
  148. phase_loop_runtime/py.typed +1 -0
  149. phase_loop_runtime/reconcile.py +1550 -0
  150. phase_loop_runtime/redaction.py +184 -0
  151. phase_loop_runtime/reflection_sync.py +293 -0
  152. phase_loop_runtime/release_guard.py +186 -0
  153. phase_loop_runtime/render.py +432 -0
  154. phase_loop_runtime/repo_validation.py +427 -0
  155. phase_loop_runtime/review_summary.py +150 -0
  156. phase_loop_runtime/roadmap_lint.py +425 -0
  157. phase_loop_runtime/route_log.py +59 -0
  158. phase_loop_runtime/route_policy/__init__.py +11 -0
  159. phase_loop_runtime/route_policy/fixtures/route_selection.golden.json +263 -0
  160. phase_loop_runtime/runner.py +8400 -0
  161. phase_loop_runtime/runtime_paths.py +225 -0
  162. phase_loop_runtime/runtime_projection.py +113 -0
  163. phase_loop_runtime/runtime_resources.py +36 -0
  164. phase_loop_runtime/schema_export.py +292 -0
  165. phase_loop_runtime/schemas/phase_loop_closeout.schema.json +366 -0
  166. phase_loop_runtime/skill_install.py +176 -0
  167. phase_loop_runtime/skill_inventory.py +662 -0
  168. phase_loop_runtime/skill_paths.py +42 -0
  169. phase_loop_runtime/skill_sources_plugin.py +37 -0
  170. phase_loop_runtime/skills_bundle/claude-advisor-board/README.md +1 -0
  171. phase_loop_runtime/skills_bundle/claude-advisor-board/SKILL.md +38 -0
  172. phase_loop_runtime/skills_bundle/claude-advisor-panel/README.md +1 -0
  173. phase_loop_runtime/skills_bundle/claude-advisor-panel/SKILL.md +38 -0
  174. phase_loop_runtime/skills_bundle/claude-execute-detailed/README.md +1 -0
  175. phase_loop_runtime/skills_bundle/claude-execute-detailed/SKILL.md +152 -0
  176. phase_loop_runtime/skills_bundle/claude-execute-phase/README.md +1 -0
  177. phase_loop_runtime/skills_bundle/claude-execute-phase/SKILL.md +745 -0
  178. phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/allocate_worktree_name.sh +33 -0
  179. phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/audit_lane_file_touches.py +197 -0
  180. phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/cleanup_lane_worktrees.sh +103 -0
  181. phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/parent_tree_leakage_check.sh +125 -0
  182. phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/post_merge_import_smoke.sh +62 -0
  183. phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/pre_merge_destructiveness_check.sh +127 -0
  184. phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/resolve_branch_from_sha.sh +51 -0
  185. phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/state.py +274 -0
  186. phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/sweep_stale_worktrees.sh +62 -0
  187. phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/team_teardown.sh +32 -0
  188. phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/validate_plan_doc.py +642 -0
  189. phase_loop_runtime/skills_bundle/claude-execute-phase/scripts/verify_harness.sh +96 -0
  190. phase_loop_runtime/skills_bundle/claude-phase-loop/README.md +1 -0
  191. phase_loop_runtime/skills_bundle/claude-phase-loop/SKILL.md +115 -0
  192. phase_loop_runtime/skills_bundle/claude-phase-roadmap-builder/README.md +1 -0
  193. phase_loop_runtime/skills_bundle/claude-phase-roadmap-builder/SKILL.md +439 -0
  194. phase_loop_runtime/skills_bundle/claude-phase-roadmap-builder/assets/review_prompt.md +19 -0
  195. phase_loop_runtime/skills_bundle/claude-phase-roadmap-builder/references/parallelization-heuristics.md +111 -0
  196. phase_loop_runtime/skills_bundle/claude-phase-roadmap-builder/references/roadmap-template.md +193 -0
  197. phase_loop_runtime/skills_bundle/claude-phase-roadmap-builder/scripts/validate_roadmap.py +32 -0
  198. phase_loop_runtime/skills_bundle/claude-plan-detailed/README.md +1 -0
  199. phase_loop_runtime/skills_bundle/claude-plan-detailed/SKILL.md +334 -0
  200. phase_loop_runtime/skills_bundle/claude-plan-detailed/assets/review_prompt.md +25 -0
  201. phase_loop_runtime/skills_bundle/claude-plan-phase/README.md +1 -0
  202. phase_loop_runtime/skills_bundle/claude-plan-phase/SKILL.md +776 -0
  203. phase_loop_runtime/skills_bundle/claude-plan-phase/assets/review_prompt.md +17 -0
  204. phase_loop_runtime/skills_bundle/claude-plan-phase/scripts/validate_plan_doc.py +1092 -0
  205. phase_loop_runtime/skills_bundle/claude-run-train/README.md +1 -0
  206. phase_loop_runtime/skills_bundle/claude-run-train/SKILL.md +75 -0
  207. phase_loop_runtime/skills_bundle/claude-skill-editor/README.md +1 -0
  208. phase_loop_runtime/skills_bundle/claude-skill-editor/SKILL.md +243 -0
  209. phase_loop_runtime/skills_bundle/claude-skill-editor/assets/editor_prompt.md +72 -0
  210. phase_loop_runtime/skills_bundle/claude-skill-improvement-planner/README.md +1 -0
  211. phase_loop_runtime/skills_bundle/claude-skill-improvement-planner/SKILL.md +249 -0
  212. phase_loop_runtime/skills_bundle/claude-skill-improvement-planner/assets/aggregator_prompt.md +79 -0
  213. phase_loop_runtime/skills_bundle/claude-task-contextualizer/README.md +1 -0
  214. phase_loop_runtime/skills_bundle/claude-task-contextualizer/SKILL.md +74 -0
  215. phase_loop_runtime/skills_bundle/claude-task-contextualizer/references/task-templates.md +103 -0
  216. phase_loop_runtime/skills_bundle/codex-advisor-board/README.md +1 -0
  217. phase_loop_runtime/skills_bundle/codex-advisor-board/SKILL.md +38 -0
  218. phase_loop_runtime/skills_bundle/codex-advisor-panel/README.md +1 -0
  219. phase_loop_runtime/skills_bundle/codex-advisor-panel/SKILL.md +38 -0
  220. phase_loop_runtime/skills_bundle/codex-execute-detailed/README.md +1 -0
  221. phase_loop_runtime/skills_bundle/codex-execute-detailed/SKILL.md +154 -0
  222. phase_loop_runtime/skills_bundle/codex-execute-phase/README.md +1 -0
  223. phase_loop_runtime/skills_bundle/codex-execute-phase/SKILL.md +231 -0
  224. phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/allocate_worktree_name.sh +33 -0
  225. phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/audit_lane_file_touches.py +197 -0
  226. phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/cleanup_lane_worktrees.sh +103 -0
  227. phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/parent_tree_leakage_check.sh +125 -0
  228. phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/post_merge_import_smoke.sh +62 -0
  229. phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/pre_merge_destructiveness_check.sh +127 -0
  230. phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/resolve_branch_from_sha.sh +51 -0
  231. phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/state.py +274 -0
  232. phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/sweep_stale_worktrees.sh +62 -0
  233. phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/team_teardown.sh +32 -0
  234. phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/validate_plan_doc.py +642 -0
  235. phase_loop_runtime/skills_bundle/codex-execute-phase/scripts/verify_harness.sh +96 -0
  236. phase_loop_runtime/skills_bundle/codex-phase-loop/README.md +1 -0
  237. phase_loop_runtime/skills_bundle/codex-phase-loop/SKILL.md +248 -0
  238. phase_loop_runtime/skills_bundle/codex-phase-roadmap-builder/README.md +1 -0
  239. phase_loop_runtime/skills_bundle/codex-phase-roadmap-builder/SKILL.md +150 -0
  240. phase_loop_runtime/skills_bundle/codex-phase-roadmap-builder/assets/review_prompt.md +19 -0
  241. phase_loop_runtime/skills_bundle/codex-phase-roadmap-builder/references/parallelization-heuristics.md +111 -0
  242. phase_loop_runtime/skills_bundle/codex-phase-roadmap-builder/references/roadmap-template.md +193 -0
  243. phase_loop_runtime/skills_bundle/codex-phase-roadmap-builder/scripts/validate_roadmap.py +32 -0
  244. phase_loop_runtime/skills_bundle/codex-plan-detailed/README.md +1 -0
  245. phase_loop_runtime/skills_bundle/codex-plan-detailed/SKILL.md +119 -0
  246. phase_loop_runtime/skills_bundle/codex-plan-detailed/assets/review_prompt.md +25 -0
  247. phase_loop_runtime/skills_bundle/codex-plan-phase/README.md +1 -0
  248. phase_loop_runtime/skills_bundle/codex-plan-phase/SKILL.md +307 -0
  249. phase_loop_runtime/skills_bundle/codex-plan-phase/assets/review_prompt.md +17 -0
  250. phase_loop_runtime/skills_bundle/codex-plan-phase/scripts/validate_plan_doc.py +1092 -0
  251. phase_loop_runtime/skills_bundle/codex-run-train/README.md +1 -0
  252. phase_loop_runtime/skills_bundle/codex-run-train/SKILL.md +75 -0
  253. phase_loop_runtime/skills_bundle/codex-skill-editor/README.md +1 -0
  254. phase_loop_runtime/skills_bundle/codex-skill-editor/SKILL.md +94 -0
  255. phase_loop_runtime/skills_bundle/codex-skill-editor/assets/editor_prompt.md +72 -0
  256. phase_loop_runtime/skills_bundle/codex-skill-improvement-planner/README.md +1 -0
  257. phase_loop_runtime/skills_bundle/codex-skill-improvement-planner/SKILL.md +114 -0
  258. phase_loop_runtime/skills_bundle/codex-skill-improvement-planner/assets/aggregator_prompt.md +79 -0
  259. phase_loop_runtime/skills_bundle/codex-task-contextualizer/README.md +1 -0
  260. phase_loop_runtime/skills_bundle/codex-task-contextualizer/SKILL.md +102 -0
  261. phase_loop_runtime/skills_bundle/codex-task-contextualizer/references/task-templates.md +103 -0
  262. phase_loop_runtime/skills_bundle/gemini-advisor-board/README.md +1 -0
  263. phase_loop_runtime/skills_bundle/gemini-advisor-board/SKILL.md +38 -0
  264. phase_loop_runtime/skills_bundle/gemini-advisor-panel/README.md +1 -0
  265. phase_loop_runtime/skills_bundle/gemini-advisor-panel/SKILL.md +38 -0
  266. phase_loop_runtime/skills_bundle/gemini-execute-detailed/README.md +1 -0
  267. phase_loop_runtime/skills_bundle/gemini-execute-detailed/SKILL.md +144 -0
  268. phase_loop_runtime/skills_bundle/gemini-execute-phase/README.md +1 -0
  269. phase_loop_runtime/skills_bundle/gemini-execute-phase/SKILL.md +198 -0
  270. phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/allocate_worktree_name.sh +33 -0
  271. phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/audit_lane_file_touches.py +197 -0
  272. phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/cleanup_lane_worktrees.sh +103 -0
  273. phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/parent_tree_leakage_check.sh +125 -0
  274. phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/post_merge_import_smoke.sh +62 -0
  275. phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/pre_merge_destructiveness_check.sh +127 -0
  276. phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/resolve_branch_from_sha.sh +51 -0
  277. phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/state.py +274 -0
  278. phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/sweep_stale_worktrees.sh +62 -0
  279. phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/team_teardown.sh +32 -0
  280. phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/validate_plan_doc.py +642 -0
  281. phase_loop_runtime/skills_bundle/gemini-execute-phase/scripts/verify_harness.sh +96 -0
  282. phase_loop_runtime/skills_bundle/gemini-phase-loop/README.md +1 -0
  283. phase_loop_runtime/skills_bundle/gemini-phase-loop/SKILL.md +111 -0
  284. phase_loop_runtime/skills_bundle/gemini-phase-roadmap-builder/README.md +1 -0
  285. phase_loop_runtime/skills_bundle/gemini-phase-roadmap-builder/SKILL.md +147 -0
  286. phase_loop_runtime/skills_bundle/gemini-phase-roadmap-builder/assets/review_prompt.md +19 -0
  287. phase_loop_runtime/skills_bundle/gemini-phase-roadmap-builder/references/parallelization-heuristics.md +111 -0
  288. phase_loop_runtime/skills_bundle/gemini-phase-roadmap-builder/references/roadmap-template.md +193 -0
  289. phase_loop_runtime/skills_bundle/gemini-phase-roadmap-builder/scripts/validate_roadmap.py +32 -0
  290. phase_loop_runtime/skills_bundle/gemini-plan-detailed/README.md +1 -0
  291. phase_loop_runtime/skills_bundle/gemini-plan-detailed/SKILL.md +119 -0
  292. phase_loop_runtime/skills_bundle/gemini-plan-detailed/assets/review_prompt.md +25 -0
  293. phase_loop_runtime/skills_bundle/gemini-plan-phase/README.md +1 -0
  294. phase_loop_runtime/skills_bundle/gemini-plan-phase/SKILL.md +217 -0
  295. phase_loop_runtime/skills_bundle/gemini-plan-phase/assets/review_prompt.md +17 -0
  296. phase_loop_runtime/skills_bundle/gemini-plan-phase/scripts/validate_plan_doc.py +1092 -0
  297. phase_loop_runtime/skills_bundle/gemini-run-train/README.md +1 -0
  298. phase_loop_runtime/skills_bundle/gemini-run-train/SKILL.md +75 -0
  299. phase_loop_runtime/skills_bundle/gemini-skill-editor/README.md +1 -0
  300. phase_loop_runtime/skills_bundle/gemini-skill-editor/SKILL.md +87 -0
  301. phase_loop_runtime/skills_bundle/gemini-skill-editor/assets/editor_prompt.md +72 -0
  302. phase_loop_runtime/skills_bundle/gemini-skill-improvement-planner/README.md +1 -0
  303. phase_loop_runtime/skills_bundle/gemini-skill-improvement-planner/SKILL.md +109 -0
  304. phase_loop_runtime/skills_bundle/gemini-skill-improvement-planner/assets/aggregator_prompt.md +79 -0
  305. phase_loop_runtime/skills_bundle/gemini-task-contextualizer/README.md +1 -0
  306. phase_loop_runtime/skills_bundle/gemini-task-contextualizer/SKILL.md +98 -0
  307. phase_loop_runtime/skills_bundle/gemini-task-contextualizer/references/task-templates.md +103 -0
  308. phase_loop_runtime/skills_bundle/opencode-advisor-board/README.md +1 -0
  309. phase_loop_runtime/skills_bundle/opencode-advisor-board/SKILL.md +38 -0
  310. phase_loop_runtime/skills_bundle/opencode-advisor-panel/README.md +1 -0
  311. phase_loop_runtime/skills_bundle/opencode-advisor-panel/SKILL.md +38 -0
  312. phase_loop_runtime/skills_bundle/opencode-execute-detailed/README.md +1 -0
  313. phase_loop_runtime/skills_bundle/opencode-execute-detailed/SKILL.md +144 -0
  314. phase_loop_runtime/skills_bundle/opencode-execute-phase/README.md +1 -0
  315. phase_loop_runtime/skills_bundle/opencode-execute-phase/SKILL.md +196 -0
  316. phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/allocate_worktree_name.sh +33 -0
  317. phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/audit_lane_file_touches.py +197 -0
  318. phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/cleanup_lane_worktrees.sh +103 -0
  319. phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/parent_tree_leakage_check.sh +125 -0
  320. phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/post_merge_import_smoke.sh +62 -0
  321. phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/pre_merge_destructiveness_check.sh +127 -0
  322. phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/resolve_branch_from_sha.sh +51 -0
  323. phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/state.py +274 -0
  324. phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/sweep_stale_worktrees.sh +62 -0
  325. phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/team_teardown.sh +32 -0
  326. phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/validate_plan_doc.py +642 -0
  327. phase_loop_runtime/skills_bundle/opencode-execute-phase/scripts/verify_harness.sh +96 -0
  328. phase_loop_runtime/skills_bundle/opencode-phase-loop/README.md +1 -0
  329. phase_loop_runtime/skills_bundle/opencode-phase-loop/SKILL.md +113 -0
  330. phase_loop_runtime/skills_bundle/opencode-phase-roadmap-builder/README.md +1 -0
  331. phase_loop_runtime/skills_bundle/opencode-phase-roadmap-builder/SKILL.md +147 -0
  332. phase_loop_runtime/skills_bundle/opencode-phase-roadmap-builder/assets/review_prompt.md +19 -0
  333. phase_loop_runtime/skills_bundle/opencode-phase-roadmap-builder/references/parallelization-heuristics.md +111 -0
  334. phase_loop_runtime/skills_bundle/opencode-phase-roadmap-builder/references/roadmap-template.md +193 -0
  335. phase_loop_runtime/skills_bundle/opencode-phase-roadmap-builder/scripts/validate_roadmap.py +32 -0
  336. phase_loop_runtime/skills_bundle/opencode-plan-detailed/README.md +1 -0
  337. phase_loop_runtime/skills_bundle/opencode-plan-detailed/SKILL.md +119 -0
  338. phase_loop_runtime/skills_bundle/opencode-plan-detailed/assets/review_prompt.md +25 -0
  339. phase_loop_runtime/skills_bundle/opencode-plan-phase/README.md +1 -0
  340. phase_loop_runtime/skills_bundle/opencode-plan-phase/SKILL.md +211 -0
  341. phase_loop_runtime/skills_bundle/opencode-plan-phase/assets/review_prompt.md +17 -0
  342. phase_loop_runtime/skills_bundle/opencode-plan-phase/scripts/validate_plan_doc.py +1092 -0
  343. phase_loop_runtime/skills_bundle/opencode-run-train/README.md +1 -0
  344. phase_loop_runtime/skills_bundle/opencode-run-train/SKILL.md +75 -0
  345. phase_loop_runtime/skills_bundle/opencode-skill-editor/README.md +1 -0
  346. phase_loop_runtime/skills_bundle/opencode-skill-editor/SKILL.md +87 -0
  347. phase_loop_runtime/skills_bundle/opencode-skill-editor/assets/editor_prompt.md +72 -0
  348. phase_loop_runtime/skills_bundle/opencode-skill-improvement-planner/README.md +1 -0
  349. phase_loop_runtime/skills_bundle/opencode-skill-improvement-planner/SKILL.md +109 -0
  350. phase_loop_runtime/skills_bundle/opencode-skill-improvement-planner/assets/aggregator_prompt.md +79 -0
  351. phase_loop_runtime/skills_bundle/opencode-task-contextualizer/README.md +1 -0
  352. phase_loop_runtime/skills_bundle/opencode-task-contextualizer/SKILL.md +98 -0
  353. phase_loop_runtime/skills_bundle/opencode-task-contextualizer/references/task-templates.md +103 -0
  354. phase_loop_runtime/state.py +156 -0
  355. phase_loop_runtime/state_degradation.py +136 -0
  356. phase_loop_runtime/state_ops.py +676 -0
  357. phase_loop_runtime/train_ledger.py +215 -0
  358. phase_loop_runtime/train_roadmap.py +339 -0
  359. phase_loop_runtime/train_runner.py +1197 -0
  360. phase_loop_runtime/verification_evidence.py +650 -0
  361. phase_loop_runtime/verification_evidence_validator.py +75 -0
  362. phase_loop_runtime/visual_evidence_validator.py +36 -0
  363. phase_loop_runtime/worker_pool.py +123 -0
  364. phase_loop_runtime/worktree_index.py +270 -0
  365. phase_loop_runtime-0.2.0.data/data/share/phase-loop-runtime/protocol/protocol.md +2475 -0
  366. phase_loop_runtime-0.2.0.dist-info/METADATA +106 -0
  367. phase_loop_runtime-0.2.0.dist-info/RECORD +370 -0
  368. phase_loop_runtime-0.2.0.dist-info/WHEEL +5 -0
  369. phase_loop_runtime-0.2.0.dist-info/entry_points.txt +9 -0
  370. phase_loop_runtime-0.2.0.dist-info/top_level.txt +1 -0
@@ -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
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env bash
2
+ # parent_tree_leakage_check.sh — detect when a teammate's filesystem edits
3
+ # escaped its worktree into the parent checkout, or when EnterWorktree
4
+ # silently fell back to in-place branch creation in the parent.
5
+ #
6
+ # Usage:
7
+ # parent_tree_leakage_check.sh <lane-id> <owned-globs-file> [<merge-target>]
8
+ #
9
+ # <lane-id> Informational only; echoed into stdout for
10
+ # orchestrator logging.
11
+ # <owned-globs-file> File with one glob pattern per line; these are
12
+ # the lane's `Owned files` from the plan doc.
13
+ # Passing /dev/null is valid (treat empty globs
14
+ # as "nothing is owned" → any dirty file counts
15
+ # as unrelated).
16
+ # <merge-target> Optional. Branch the phase merges into (default
17
+ # "main"). Used by the new PARENT_ON_WRONG_BRANCH
18
+ # probe.
19
+ #
20
+ # Behavior: emits EXACTLY one token on stdout, exit 0 always.
21
+ #
22
+ # CLEAN
23
+ # - Working tree has no uncommitted changes AND the parent is on the
24
+ # merge-target branch. No leakage.
25
+ #
26
+ # LEAKAGE_DETECTED
27
+ # - Working tree has dirty files AND at least one matches the lane's
28
+ # owned globs. The teammate wrote into the parent checkout rather
29
+ # than the worktree; orchestrator should stash or abort before merge.
30
+ #
31
+ # UNRELATED_DIRTY_TREE
32
+ # - Working tree has dirty files but NONE match the lane's owned
33
+ # globs. Probably other orchestrator-level changes; caller decides.
34
+ #
35
+ # PARENT_ON_WRONG_BRANCH
36
+ # - Working tree is CLEAN but the parent checkout is on a branch
37
+ # OTHER than <merge-target>. Symptom of EnterWorktree silently
38
+ # falling back to in-place branch creation (a name collision is
39
+ # the typical cause). The lane's commit is usually fine — merge
40
+ # by SHA, then `git checkout <merge-target>` in the parent before
41
+ # post-merge worktree cleanup.
42
+ #
43
+ # Implementation notes:
44
+ # - Runs from the parent checkout (the cwd of the orchestrator's git
45
+ # context, not the lane's worktree).
46
+ # - `git status --porcelain` output: `XY <path>` where X/Y are status
47
+ # codes; we parse the path by stripping the first 3 chars.
48
+
49
+ set -uo pipefail
50
+
51
+ if [[ $# -lt 2 || $# -gt 3 ]]; then
52
+ echo "usage: parent_tree_leakage_check.sh <lane-id> <owned-globs-file> [<merge-target>]" >&2
53
+ exit 2
54
+ fi
55
+
56
+ lane_id="$1"
57
+ globs_path="$2"
58
+ merge_target="${3:-main}"
59
+
60
+ # Load owned globs.
61
+ globs=()
62
+ if [[ -r "$globs_path" && "$globs_path" != "/dev/null" ]]; then
63
+ while IFS= read -r line; do
64
+ line="${line%%#*}"
65
+ line="$(echo -n "$line" | xargs || true)"
66
+ [[ -z "$line" ]] && continue
67
+ globs+=("$line")
68
+ done < "$globs_path"
69
+ fi
70
+
71
+ # Enumerate dirty paths from the parent checkout.
72
+ dirty_paths=()
73
+ while IFS= read -r line; do
74
+ [[ -z "$line" ]] && continue
75
+ # Status code (first 2 chars) + a space, then the path. Renames use
76
+ # "R old -> new"; we take the NEW path.
77
+ path="${line:3}"
78
+ if [[ "$path" == *" -> "* ]]; then
79
+ path="${path#* -> }"
80
+ fi
81
+ # Strip surrounding quotes git adds for paths with spaces.
82
+ path="${path#\"}"
83
+ path="${path%\"}"
84
+ dirty_paths+=("$path")
85
+ done < <(git status --porcelain 2>/dev/null)
86
+
87
+ if [[ ${#dirty_paths[@]} -eq 0 ]]; then
88
+ # Parent is clean — but is it on the right branch?
89
+ current_branch="$(git branch --show-current 2>/dev/null || true)"
90
+ if [[ -n "$current_branch" && "$current_branch" != "$merge_target" ]]; then
91
+ echo "parent_tree_leakage_check: $lane_id — parent checkout is on branch '$current_branch' (expected '$merge_target')" >&2
92
+ echo "PARENT_ON_WRONG_BRANCH"
93
+ exit 0
94
+ fi
95
+ echo "CLEAN"
96
+ exit 0
97
+ fi
98
+
99
+ # Test each dirty path against the lane's globs.
100
+ is_owned() {
101
+ local path="$1"
102
+ local pat
103
+ for pat in "${globs[@]+"${globs[@]}"}"; do
104
+ # shellcheck disable=SC2053
105
+ if [[ "$path" == $pat ]]; then
106
+ return 0
107
+ fi
108
+ done
109
+ return 1
110
+ }
111
+
112
+ leakage=false
113
+ for p in "${dirty_paths[@]}"; do
114
+ if is_owned "$p"; then
115
+ leakage=true
116
+ echo "parent_tree_leakage_check: $lane_id — dirty path $p matches owned globs" >&2
117
+ fi
118
+ done
119
+
120
+ if [[ "$leakage" == "true" ]]; then
121
+ echo "LEAKAGE_DETECTED"
122
+ exit 0
123
+ fi
124
+ echo "UNRELATED_DIRTY_TREE"
125
+ exit 0
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env bash
2
+ # post_merge_import_smoke.sh — verify post-merge Python-package imports.
3
+ #
4
+ # Usage:
5
+ # post_merge_import_smoke.sh <pkg.dotted.path> [<pkg.another> ...]
6
+ #
7
+ # For each package argument, runs `python -c "import <pkg>"` using the
8
+ # repo-local .venv (falls back to plain `python` if .venv is missing).
9
+ # Emits one line per package:
10
+ #
11
+ # IMPORT_OK: <pkg>
12
+ # IMPORT_FAIL: <pkg> — <first-line-of-error>
13
+ #
14
+ # Exit code:
15
+ # 0 — every package imports cleanly
16
+ # 1 — at least one package failed to import
17
+ # 2 — usage error
18
+ #
19
+ # Rationale: a lane that drops or renames a symbol re-exported by an
20
+ # `__init__.py` breaks package load silently — the ImportError only
21
+ # surfaces when some downstream code happens to trigger the import. A
22
+ # post-merge import smoke on every `__init__.py` the lane touched catches
23
+ # this in seconds, before the next wave builds on a broken base.
24
+ #
25
+ # Invocation pattern for the orchestrator (Step 7):
26
+ # packages="$(git diff --name-only HEAD~..HEAD \
27
+ # | grep '__init__\.py$' \
28
+ # | sed 's|/__init__\.py$||; s|/|.|g' \
29
+ # | sort -u)"
30
+ # [[ -n "$packages" ]] && bash <script> $packages
31
+
32
+ set -uo pipefail
33
+
34
+ if [[ $# -lt 1 ]]; then
35
+ echo "usage: post_merge_import_smoke.sh <pkg.dotted.path> [<pkg.another> ...]" >&2
36
+ exit 2
37
+ fi
38
+
39
+ # Prefer repo-local venv if present.
40
+ python_bin="python"
41
+ if [[ -x ".venv/bin/python" ]]; then
42
+ python_bin=".venv/bin/python"
43
+ elif [[ -x "venv/bin/python" ]]; then
44
+ python_bin="venv/bin/python"
45
+ fi
46
+
47
+ any_fail=0
48
+ for pkg in "$@"; do
49
+ # Run the import in a subshell; capture stderr.
50
+ err="$("$python_bin" -c "import ${pkg}" 2>&1 >/dev/null)"
51
+ rc=$?
52
+ if [[ $rc -eq 0 ]]; then
53
+ echo "IMPORT_OK: ${pkg}"
54
+ else
55
+ # First line of the error only.
56
+ first_line="$(echo "$err" | tail -n 1)"
57
+ echo "IMPORT_FAIL: ${pkg} — ${first_line}"
58
+ any_fail=1
59
+ fi
60
+ done
61
+
62
+ exit $any_fail
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env bash
2
+ # pre_merge_destructiveness_check.sh — classify a lane's merge before
3
+ # performing it, to prevent stale-base destruction of peer-lane work.
4
+ #
5
+ # Usage:
6
+ # pre_merge_destructiveness_check.sh <lane-sha> <merge-target> <whitelist-path>
7
+ #
8
+ # <lane-sha> Commit SHA produced by the lane.
9
+ # <merge-target> Branch the lane will be merged into (typically main).
10
+ # <whitelist-path> File with one path per line listing destructive
11
+ # changes the plan EXPECTS for this lane. Supports
12
+ # shell-glob patterns. Use /dev/null if the lane
13
+ # is purely additive.
14
+ #
15
+ # Behavior: emits EXACTLY one token on stdout, exit 0 always (verdict is
16
+ # on stdout for the orchestrator to act on).
17
+ #
18
+ # SAFE
19
+ # - The ancestor-diff deletion list is empty OR every deletion is
20
+ # explicitly whitelisted. Proceed with `git merge --no-ff`.
21
+ #
22
+ # STALE_BASE_DETECTED
23
+ # - The lane's diff-against-target shows deletions of files that
24
+ # WEREN'T in the lane's ancestor; i.e. peer lanes merged additions
25
+ # between the lane's base and target, and `git merge --no-ff` would
26
+ # revert them. Orchestrator should salvage (cherry-pick the lane's
27
+ # owned paths) rather than retry.
28
+ #
29
+ # CONFLICT
30
+ # - Some other destructive signature that doesn't match either of the
31
+ # above. Orchestrator should surface to the teammate for manual
32
+ # resolution.
33
+ #
34
+ # Rationale: Step 7's MANDATORY pre-merge check. A lane that committed
35
+ # against a stale base can wipe peer-lane work on `--no-ff` merge; the
36
+ # naive `git diff main..lane` can't distinguish that from a parallel-
37
+ # branch false positive. Extracting the 3-part diff (naive + ancestor +
38
+ # whitelist) into a script makes the verdict deterministic.
39
+
40
+ set -uo pipefail
41
+
42
+ if [[ $# -ne 3 ]]; then
43
+ echo "usage: pre_merge_destructiveness_check.sh <lane-sha> <merge-target> <whitelist-path>" >&2
44
+ exit 2
45
+ fi
46
+
47
+ sha="$1"
48
+ target="$2"
49
+ whitelist_path="$3"
50
+
51
+ # Load whitelist patterns (one per line; '#' comments OK; blank lines skipped).
52
+ whitelist=()
53
+ if [[ -r "$whitelist_path" && "$whitelist_path" != "/dev/null" ]]; then
54
+ while IFS= read -r line; do
55
+ line="${line%%#*}"
56
+ line="${line//[[:space:]]/}"
57
+ [[ -z "$line" ]] && continue
58
+ whitelist+=("$line")
59
+ done < "$whitelist_path"
60
+ fi
61
+
62
+ # Primary: deletions in target..lane-sha (naïve diff).
63
+ mapfile -t naive_deletions < <(
64
+ git diff --diff-filter=D --name-only "$target..$sha" 2>/dev/null
65
+ )
66
+
67
+ # Disambiguator: deletions in ancestor..lane-sha (what the lane actually
68
+ # did, ignoring what target gained since).
69
+ ancestor="$(git merge-base "$target" "$sha" 2>/dev/null)"
70
+ mapfile -t ancestor_deletions < <(
71
+ [[ -n "$ancestor" ]] \
72
+ && git diff --diff-filter=D --name-only "$ancestor..$sha" 2>/dev/null \
73
+ || true
74
+ )
75
+
76
+ # Helper: test whether a path matches any whitelist glob.
77
+ is_whitelisted() {
78
+ local path="$1"
79
+ local pat
80
+ for pat in "${whitelist[@]+"${whitelist[@]}"}"; do
81
+ # shellcheck disable=SC2053
82
+ if [[ "$path" == $pat ]]; then
83
+ return 0
84
+ fi
85
+ done
86
+ return 1
87
+ }
88
+
89
+ # Case 1: the lane itself did zero deletions (ancestor..lane is additive-only
90
+ # OR all lane-side deletions are whitelisted). The naive deletion list may
91
+ # still show peer-lane additions — which is the stale-base signature.
92
+ lane_did_unwhitelisted_delete=false
93
+ for d in "${ancestor_deletions[@]+"${ancestor_deletions[@]}"}"; do
94
+ [[ -z "$d" ]] && continue
95
+ if ! is_whitelisted "$d"; then
96
+ lane_did_unwhitelisted_delete=true
97
+ break
98
+ fi
99
+ done
100
+
101
+ # Compute naive-but-not-ancestor deletions (files target has that lane
102
+ # never had -> peer lanes added them after lane branched off).
103
+ declare -A ancestor_set=()
104
+ for d in "${ancestor_deletions[@]+"${ancestor_deletions[@]}"}"; do
105
+ [[ -z "$d" ]] && continue
106
+ ancestor_set["$d"]=1
107
+ done
108
+ stale_base_deletions=()
109
+ for d in "${naive_deletions[@]+"${naive_deletions[@]}"}"; do
110
+ [[ -z "$d" ]] && continue
111
+ if [[ -z "${ancestor_set[$d]+set}" ]]; then
112
+ stale_base_deletions+=("$d")
113
+ fi
114
+ done
115
+
116
+ if [[ "$lane_did_unwhitelisted_delete" == "false" && ${#stale_base_deletions[@]} -eq 0 ]]; then
117
+ echo "SAFE"
118
+ exit 0
119
+ fi
120
+ if [[ "$lane_did_unwhitelisted_delete" == "false" && ${#stale_base_deletions[@]} -gt 0 ]]; then
121
+ # Lane is additive but diff-against-target shows deletions from peer-lane
122
+ # additions — classic stale base.
123
+ echo "STALE_BASE_DETECTED"
124
+ exit 0
125
+ fi
126
+ echo "CONFLICT"
127
+ exit 0