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,188 @@
1
+ """Named board presets (ABDREG, Phase 2 — lane 4).
2
+
3
+ Nine built-in presets, each a named, purpose-tagged, open-ended seat list:
4
+
5
+ * ``default`` — IS ``fixtures.DEFAULT_BOARD`` (imported, not re-declared), so
6
+ the back-compat keystone holds by construction: the default
7
+ board reconstructs today's exact three seats (the claude seat
8
+ on Fable, ``claude-fable-5``).
9
+ * ``code-review`` — three frontier vendors, each adversarial: codex ``gpt-5.5``,
10
+ ``Gemini 3.1 Pro``, and ``claude-fable-5``.
11
+ * ``brainstorm`` — multi-vendor divergent thinking, lens-differentiated.
12
+ * ``doc-edit`` — a lighter documentation-editing board.
13
+ * ``legal-review`` / ``legal-strategy-review`` / ``legal-brainstorm`` — the legal
14
+ boards (see below).
15
+
16
+ **Review-class boards run on frontier models, never the implementer.** Pre-merge
17
+ and legal review are mid-tier decisions where being wrong is expensive, so the
18
+ review-class boards (``default``, ``code-review``, ``legal-review``,
19
+ ``legal-strategy-review``) seat Fable (``claude-fable-5``) on the claude lane, not
20
+ the implementer ``claude-sonnet-5``. The divergent-thinking boards (``brainstorm``,
21
+ ``doc-edit``, ``legal-brainstorm``) deliberately KEEP Sonnet — a diverse voice / a
22
+ low-stakes copyedit / an aggressive-but-cheap ideation seat — where it is the right
23
+ tool.
24
+
25
+ Every preset seat uses only REGISTERED, VALID ``(model, harness)`` pairs on the
26
+ built-3 + ``opencode`` lanes (no ``pi`` / ``cursor`` / unregistered-model seats),
27
+ so the presets pass their OWN config-time validation — ``config.load_boards()``
28
+ self-validates every preset (``tests/test_advisor_board_config.py``). Adding a
29
+ preset seat on an unregistered model or an incompatible lane would turn the suite
30
+ red, which is the intended guardrail. ``lens`` and ``purpose`` are free-form
31
+ strings (``schema.py``): the legal lenses/purposes below need no enum extension.
32
+ """
33
+ from __future__ import annotations
34
+
35
+ from .fixtures import DEFAULT_BOARD
36
+ from .schema import Board, Seat
37
+
38
+ # code-review: review-class = three frontier vendors, always. Each seat carries the
39
+ # adversarial lens (find-the-bug framing); the claude seat is Fable, not the
40
+ # implementer. This supersedes the old two-seat (codex + sonnet) composition.
41
+ CODE_REVIEW_BOARD: Board = Board(
42
+ name="code-review",
43
+ purpose="code-review",
44
+ seats=(
45
+ Seat(model="gpt-5.5", effort="max", harness="codex", lens="adversarial"),
46
+ Seat(model="Gemini 3.1 Pro", effort="high", harness="gemini", lens="adversarial"),
47
+ Seat(model="claude-fable-5", effort="max", harness="claude", lens="adversarial"),
48
+ ),
49
+ )
50
+
51
+ # brainstorm: divergent, multi-vendor, each seat a different thinking lens.
52
+ BRAINSTORM_BOARD: Board = Board(
53
+ name="brainstorm",
54
+ purpose="brainstorm",
55
+ seats=(
56
+ Seat(model="claude-sonnet-5", effort="high", harness="claude", lens="adversarial"),
57
+ Seat(model="gpt-5.5", effort="high", harness="codex", lens="supportive"),
58
+ Seat(model="Gemini 3.1 Pro", effort="high", harness="gemini", lens="lateral"),
59
+ ),
60
+ )
61
+
62
+ # doc-edit: a lighter documentation-editing board (structure + copyedit).
63
+ DOC_EDIT_BOARD: Board = Board(
64
+ name="doc-edit",
65
+ purpose="doc-edit",
66
+ seats=(
67
+ Seat(model="claude-sonnet-5", effort="medium", harness="claude", lens="copyedit"),
68
+ Seat(model="gpt-5.5", effort="medium", harness="codex", lens="structure"),
69
+ ),
70
+ )
71
+
72
+ # --- legal boards ----------------------------------------------------------
73
+ #
74
+ # Each seat below encodes the PRIMARY review lens per vendor. The richer treatment
75
+ # — four lenses per seat, an apex-Opus seat, a verify-round, and retrieval-grounded
76
+ # citation-verification — is a documented deep-seat FOLLOW-ON (see CONTRACTS.md),
77
+ # intentionally NOT built here. Review-class legal boards seat Fable on claude;
78
+ # legal-brainstorm keeps Sonnet as a cheap aggressive ideation voice.
79
+
80
+ # legal-review: document/contract review. Opposing-counsel adversary, risk/liability
81
+ # scan, and authority (citation/precedent) verification.
82
+ LEGAL_REVIEW_BOARD: Board = Board(
83
+ name="legal-review",
84
+ purpose="legal-review",
85
+ seats=(
86
+ Seat(model="gpt-5.5", effort="max", harness="codex", lens="opposing-counsel"),
87
+ Seat(model="Gemini 3.1 Pro", effort="high", harness="gemini", lens="risk-liability"),
88
+ Seat(model="claude-fable-5", effort="max", harness="claude", lens="authority-verification"),
89
+ ),
90
+ )
91
+
92
+ # legal-strategy-review: red-team a legal strategy — attack it, surface alternatives,
93
+ # and stress the downside / ethical exposure.
94
+ LEGAL_STRATEGY_REVIEW_BOARD: Board = Board(
95
+ name="legal-strategy-review",
96
+ purpose="legal-strategy-review",
97
+ seats=(
98
+ Seat(model="gpt-5.5", effort="max", harness="codex", lens="red-team"),
99
+ Seat(model="Gemini 3.1 Pro", effort="high", harness="gemini", lens="alternatives"),
100
+ Seat(model="claude-fable-5", effort="max", harness="claude", lens="downside-ethics"),
101
+ ),
102
+ )
103
+
104
+ # legal-brainstorm: divergent legal ideation. KEEPS Sonnet (aggressive, cheap voice)
105
+ # alongside a conservative and a creative seat.
106
+ LEGAL_BRAINSTORM_BOARD: Board = Board(
107
+ name="legal-brainstorm",
108
+ purpose="legal-brainstorm",
109
+ seats=(
110
+ Seat(model="claude-sonnet-5", effort="high", harness="claude", lens="aggressive"),
111
+ Seat(model="gpt-5.5", effort="high", harness="codex", lens="conservative"),
112
+ Seat(model="Gemini 3.1 Pro", effort="high", harness="gemini", lens="creative"),
113
+ ),
114
+ )
115
+
116
+ # --- general-purpose catch-alls -------------------------------------------
117
+ #
118
+ # For use cases we have NOT pre-modeled, so the board library is open-ended rather
119
+ # than limited to the named domains. Both default to TOP-END models: an unanticipated
120
+ # task cannot be assumed low-stakes, so the safe default is frontier — dial down
121
+ # explicitly (a cheaper board or max_concurrency aside) when a task is known-cheap.
122
+
123
+ # general: the domain-agnostic top-tier PANEL. Three frontier vendors with generic
124
+ # critical lenses (adversarial / alternative-angle / completeness) — hand it any
125
+ # task + brief and it convenes a cross-vendor frontier review.
126
+ GENERAL_BOARD: Board = Board(
127
+ name="general",
128
+ purpose="general",
129
+ seats=(
130
+ Seat(model="gpt-5.5", effort="max", harness="codex", lens="adversarial"),
131
+ Seat(model="Gemini 3.1 Pro", effort="high", harness="gemini", lens="alternative"),
132
+ Seat(model="claude-fable-5", effort="max", harness="claude", lens="completeness"),
133
+ ),
134
+ )
135
+
136
+ # solo: the general-purpose single MEMBER — one quick top-end opinion when a full
137
+ # panel is overkill. A one-seat board resolves + validates like any other.
138
+ SOLO_BOARD: Board = Board(
139
+ name="solo",
140
+ purpose="general",
141
+ seats=(
142
+ Seat(model="claude-fable-5", effort="max", harness="claude", lens="completeness"),
143
+ ),
144
+ )
145
+
146
+ # The built-in presets, keyed by name. ``default`` IS the shared fixture board.
147
+ PRESETS: dict[str, Board] = {
148
+ DEFAULT_BOARD.name: DEFAULT_BOARD,
149
+ CODE_REVIEW_BOARD.name: CODE_REVIEW_BOARD,
150
+ BRAINSTORM_BOARD.name: BRAINSTORM_BOARD,
151
+ DOC_EDIT_BOARD.name: DOC_EDIT_BOARD,
152
+ LEGAL_REVIEW_BOARD.name: LEGAL_REVIEW_BOARD,
153
+ LEGAL_STRATEGY_REVIEW_BOARD.name: LEGAL_STRATEGY_REVIEW_BOARD,
154
+ LEGAL_BRAINSTORM_BOARD.name: LEGAL_BRAINSTORM_BOARD,
155
+ GENERAL_BOARD.name: GENERAL_BOARD,
156
+ SOLO_BOARD.name: SOLO_BOARD,
157
+ }
158
+
159
+ PRESET_NAMES: tuple[str, ...] = tuple(PRESETS)
160
+
161
+ # The board a bare ``advisor-board`` invocation resolves to absent a user override.
162
+ DEFAULT_BOARD_NAME: str = DEFAULT_BOARD.name
163
+
164
+
165
+ def get_preset(name: str) -> Board:
166
+ """Return a built-in preset by name, or raise ``KeyError`` naming the known
167
+ presets."""
168
+ try:
169
+ return PRESETS[name]
170
+ except KeyError as exc:
171
+ known = ", ".join(PRESET_NAMES)
172
+ raise KeyError(f"unknown board preset {name!r}; known presets: {known}") from exc
173
+
174
+
175
+ __all__ = [
176
+ "PRESETS",
177
+ "PRESET_NAMES",
178
+ "DEFAULT_BOARD_NAME",
179
+ "CODE_REVIEW_BOARD",
180
+ "BRAINSTORM_BOARD",
181
+ "DOC_EDIT_BOARD",
182
+ "LEGAL_REVIEW_BOARD",
183
+ "LEGAL_STRATEGY_REVIEW_BOARD",
184
+ "LEGAL_BRAINSTORM_BOARD",
185
+ "GENERAL_BOARD",
186
+ "SOLO_BOARD",
187
+ "get_preset",
188
+ ]
@@ -0,0 +1,309 @@
1
+ """Registry interfaces + (model x harness) matrix API — INTERFACES ONLY
2
+ (IF-0-ABDFREEZE-2).
3
+
4
+ This freezes the *return types* and the *method surface* that ABDREG populates
5
+ and that ABDRESOLVE / ABDHOME import. It ships importable Protocols, the frozen
6
+ record + result types, and ``NotImplemented``-raising stubs — **no six-harness
7
+ data** (that is ABDREG). Keeping the return types concrete here (rather than bare
8
+ tuples) is what lets ABDREG's matrix and ABDRESOLVE's validation compile against
9
+ the same shapes without divergence.
10
+ """
11
+ from __future__ import annotations
12
+
13
+ from dataclasses import dataclass
14
+ from typing import Protocol, runtime_checkable
15
+
16
+ from .schema import AUTH_SUBSCRIPTION, BACKING_HOMEBREW
17
+
18
+
19
+ # --- frozen record + result types (imported by ABDREG and ABDRESOLVE) -------
20
+
21
+
22
+ @dataclass(frozen=True)
23
+ class HarnessSpec:
24
+ """A registered harness (execution lane). Populated by ABDREG.
25
+
26
+ ``cli`` is the availability-probe binary (e.g. ``codex`` / ``agy`` / ``claude``
27
+ / ``cursor-agent``); ``auth_lanes`` the credential lanes it supports; ``backing``
28
+ its default provider transport. ``available`` is a *probe result*, not frozen
29
+ data — the stub registry leaves it ``None`` (unknown)."""
30
+
31
+ name: str
32
+ cli: str
33
+ auth_lanes: tuple[str, ...] = (AUTH_SUBSCRIPTION,)
34
+ backing: str = BACKING_HOMEBREW
35
+ available: bool | None = None
36
+
37
+
38
+ @dataclass(frozen=True)
39
+ class ModelSpec:
40
+ """A registered model. Populated by ABDREG.
41
+
42
+ ``default_lane`` the harness a bare seat resolves to; ``runnable_by`` the
43
+ harness lanes that can run it; ``effort_ceiling`` the max canonical effort the
44
+ model honors (a seat above it is clamped/rejected at validation)."""
45
+
46
+ model: str
47
+ vendor_family: str
48
+ default_lane: str
49
+ runnable_by: tuple[str, ...] = ()
50
+ effort_ceiling: str = "max"
51
+
52
+
53
+ @dataclass(frozen=True)
54
+ class AuthAvailability:
55
+ """Which credential lanes are usable for a ``(model, harness)`` pair.
56
+
57
+ Returned as the second element of ``CompatibilityMatrix.is_valid``. Concrete
58
+ (not a bare bool) so no-silent-key is *testable* for a seat: a seat may be a
59
+ valid pairing yet have neither lane available (skip-with-warning), or only the
60
+ subscription lane (the default), or the api-key lane behind an explicit
61
+ board opt-in."""
62
+
63
+ subscription: bool = False
64
+ api_key: bool = False
65
+ detail: str = ""
66
+
67
+ @property
68
+ def any_available(self) -> bool:
69
+ return self.subscription or self.api_key
70
+
71
+
72
+ # ``is_valid`` return alias — frozen so both the matrix impl and validation import it.
73
+ MatrixVerdict = tuple[bool, AuthAvailability]
74
+
75
+
76
+ # --- interfaces (Protocols) -------------------------------------------------
77
+
78
+
79
+ @runtime_checkable
80
+ class HarnessRegistry(Protocol):
81
+ """The six-harness registry (claude, codex, gemini, opencode, pi, cursor)."""
82
+
83
+ def list_harnesses(self) -> tuple[HarnessSpec, ...]: ...
84
+
85
+ def get(self, name: str) -> HarnessSpec: ...
86
+
87
+ def is_available(self, name: str) -> bool: ...
88
+
89
+
90
+ @runtime_checkable
91
+ class ModelRegistry(Protocol):
92
+ """Model -> default lane / runnable_by / effort ceiling."""
93
+
94
+ def list_models(self) -> tuple[ModelSpec, ...]: ...
95
+
96
+ def get(self, model: str) -> ModelSpec: ...
97
+
98
+ def default_lane(self, model: str) -> str: ...
99
+
100
+
101
+ @runtime_checkable
102
+ class CompatibilityMatrix(Protocol):
103
+ """The ``(model x harness)`` compatibility + per-lane auth-availability API.
104
+
105
+ ``is_valid(model, harness)`` -> ``(ok, AuthAvailability)``: ``ok`` is whether
106
+ the pairing is *expressible at all* (an invalid pairing such as
107
+ ``claude:gpt-5.5`` is rejected at config time with a clear message); the
108
+ ``AuthAvailability`` reports which lanes are actually usable so a valid-but-
109
+ unauthed seat degrades rather than blocks. ``default_lane`` is the harness a
110
+ bare ``model`` seat resolves onto.
111
+ """
112
+
113
+ def is_valid(self, model: str, harness: str) -> MatrixVerdict: ...
114
+
115
+ def default_lane(self, model: str) -> str: ...
116
+
117
+
118
+ # --- stubs (ABDREG replaces these with populated data) ----------------------
119
+
120
+ _STUB_MSG = "advisor-board registry is populated in ABDREG (Phase 2); this is the frozen stub"
121
+
122
+
123
+ @dataclass
124
+ class StubHarnessRegistry:
125
+ """Importable placeholder satisfying ``HarnessRegistry``. Every accessor raises
126
+ so a phase that accidentally depends on real data before ABDREG fails loudly."""
127
+
128
+ def list_harnesses(self) -> tuple[HarnessSpec, ...]:
129
+ raise NotImplementedError(_STUB_MSG)
130
+
131
+ def get(self, name: str) -> HarnessSpec:
132
+ raise NotImplementedError(_STUB_MSG)
133
+
134
+ def is_available(self, name: str) -> bool:
135
+ raise NotImplementedError(_STUB_MSG)
136
+
137
+
138
+ @dataclass
139
+ class StubModelRegistry:
140
+ def list_models(self) -> tuple[ModelSpec, ...]:
141
+ raise NotImplementedError(_STUB_MSG)
142
+
143
+ def get(self, model: str) -> ModelSpec:
144
+ raise NotImplementedError(_STUB_MSG)
145
+
146
+ def default_lane(self, model: str) -> str:
147
+ raise NotImplementedError(_STUB_MSG)
148
+
149
+
150
+ @dataclass
151
+ class StubCompatibilityMatrix:
152
+ def is_valid(self, model: str, harness: str) -> MatrixVerdict:
153
+ raise NotImplementedError(_STUB_MSG)
154
+
155
+ def default_lane(self, model: str) -> str:
156
+ raise NotImplementedError(_STUB_MSG)
157
+
158
+
159
+ # ===========================================================================
160
+ # ABDREG (Phase 2) — populated registries.
161
+ #
162
+ # Everything above is the ABDFREEZE interface freeze and is byte-frozen (the
163
+ # stubs still raise; ``tests/test_advisor_board_registries.py`` asserts it).
164
+ # Below is the real six-harness / model data ABDREG owns. It is additive: no
165
+ # frozen type, protocol, or stub changes. The compatibility + auth matrix that
166
+ # consumes these lives in ``matrix.py``; the presets + config loader in
167
+ # ``presets.py`` / ``config.py``.
168
+ # ===========================================================================
169
+
170
+ import shutil
171
+ from collections.abc import Callable
172
+
173
+ from .schema import AUTH_API_KEY, BACKING_OMNIGENT, vendor_family, vendor_of_harness
174
+
175
+
176
+ class UnknownModelError(KeyError):
177
+ """A seat references a model the registry does not know. Raised with the
178
+ known-model list so a config-time rejection is actionable."""
179
+
180
+
181
+ class UnknownHarnessError(KeyError):
182
+ """A seat references a harness the registry does not know."""
183
+
184
+
185
+ # --- harness registry data --------------------------------------------------
186
+
187
+ # The six harnesses. claude / codex / gemini are the built-3 (homebrew, native +
188
+ # TUI legs, ABDHOME); opencode / pi / cursor are breadth — registered here
189
+ # regardless, but their default transport is ``omnigent`` (routed via
190
+ # omniagent-plus -> Omnigent per ABDOMNI; NOT hand-written homebrew adapters).
191
+ # ``cli`` is the availability-probe binary: codex -> ``codex``, gemini -> ``agy``
192
+ # (panel_invoker._LEG_CLI), cursor -> ``cursor-agent`` (so cursor is gated on the
193
+ # cursor-agent binary being present). All six support both credential lanes; the
194
+ # subscription lane is the default and the api-key lane is reachable only behind a
195
+ # board opt-in (never-silent-key).
196
+ _BOTH_LANES: tuple[str, ...] = (AUTH_SUBSCRIPTION, AUTH_API_KEY)
197
+
198
+ _HARNESS_SPECS: tuple[HarnessSpec, ...] = (
199
+ HarnessSpec(name="claude", cli="claude", auth_lanes=_BOTH_LANES, backing=BACKING_HOMEBREW),
200
+ HarnessSpec(name="codex", cli="codex", auth_lanes=_BOTH_LANES, backing=BACKING_HOMEBREW),
201
+ HarnessSpec(name="gemini", cli="agy", auth_lanes=_BOTH_LANES, backing=BACKING_HOMEBREW),
202
+ HarnessSpec(name="opencode", cli="opencode", auth_lanes=_BOTH_LANES, backing=BACKING_OMNIGENT),
203
+ HarnessSpec(name="pi", cli="pi", auth_lanes=_BOTH_LANES, backing=BACKING_OMNIGENT),
204
+ HarnessSpec(name="cursor", cli="cursor-agent", auth_lanes=_BOTH_LANES, backing=BACKING_OMNIGENT),
205
+ )
206
+
207
+
208
+ @dataclass
209
+ class DefaultHarnessRegistry:
210
+ """Populated ``HarnessRegistry`` over the six harnesses.
211
+
212
+ ``is_available`` is a PATH probe only (``shutil.which``) — metadata-only, it
213
+ never authenticates or spends tokens, mirroring
214
+ ``panel_invoker.available_panel_legs``. The probe is injectable so tests are
215
+ deterministic (cursor's gate is just ``which("cursor-agent")``).
216
+ """
217
+
218
+ probe: Callable[[str], bool] | None = None
219
+
220
+ def _probe(self) -> Callable[[str], bool]:
221
+ return self.probe if self.probe is not None else (lambda cli: shutil.which(cli) is not None)
222
+
223
+ def list_harnesses(self) -> tuple[HarnessSpec, ...]:
224
+ return _HARNESS_SPECS
225
+
226
+ def get(self, name: str) -> HarnessSpec:
227
+ key = (name or "").lower()
228
+ for spec in _HARNESS_SPECS:
229
+ if spec.name == key:
230
+ return spec
231
+ known = ", ".join(s.name for s in _HARNESS_SPECS)
232
+ raise UnknownHarnessError(f"unknown harness {name!r}; known harnesses: {known}")
233
+
234
+ def is_available(self, name: str) -> bool:
235
+ spec = self.get(name)
236
+ return self._probe()(spec.cli)
237
+
238
+
239
+ # --- model registry data ----------------------------------------------------
240
+
241
+ # (model, default_lane, effort_ceiling). ``vendor_family`` is derived from the
242
+ # FROZEN ``schema.vendor_family`` projection (not retyped, so it can never drift
243
+ # from the governed-gate mapping). ``runnable_by`` is derived from that family
244
+ # across the six harnesses (a harness runs a model iff its lane vendor-family
245
+ # matches). ``default_lane`` is PINNED to a built-3 leg so a bare seat resolves
246
+ # onto the native lane — e.g. ``gpt-5.5`` is runnable by both ``codex`` and
247
+ # ``opencode`` but a bare ``gpt-5.5`` seat MUST resolve to ``codex`` or the
248
+ # default board's back-compat breaks. ``effort_ceiling`` defaults to the ladder
249
+ # max; lower it only where there is concrete evidence a model caps out below max
250
+ # (none of the built-3 do — codex's ``xhigh`` IS canonical ``max``).
251
+ _MODEL_DEFS: tuple[tuple[str, str, str], ...] = (
252
+ ("gpt-5.5", "codex", "max"),
253
+ ("claude-sonnet-5", "claude", "max"),
254
+ ("claude-opus-4-8", "claude", "max"),
255
+ ("claude-haiku-4-5", "claude", "max"),
256
+ ("claude-fable-5", "claude", "max"),
257
+ ("Gemini 3.1 Pro", "gemini", "max"),
258
+ )
259
+
260
+
261
+ def _runnable_by(model_vendor: str) -> tuple[str, ...]:
262
+ """Harness lanes that can run a model of ``model_vendor``: those whose lane
263
+ vendor-family matches. Derived from the six registered harnesses so a new
264
+ harness automatically joins its family's runnable set."""
265
+ return tuple(s.name for s in _HARNESS_SPECS if vendor_of_harness(s.name) == model_vendor)
266
+
267
+
268
+ def _build_model_specs() -> tuple[ModelSpec, ...]:
269
+ specs: list[ModelSpec] = []
270
+ for model, default_lane, ceiling in _MODEL_DEFS:
271
+ family = vendor_family(model, default_lane)
272
+ specs.append(
273
+ ModelSpec(
274
+ model=model,
275
+ vendor_family=family,
276
+ default_lane=default_lane,
277
+ runnable_by=_runnable_by(family),
278
+ effort_ceiling=ceiling,
279
+ )
280
+ )
281
+ return tuple(specs)
282
+
283
+
284
+ _MODEL_SPECS: tuple[ModelSpec, ...] = _build_model_specs()
285
+
286
+
287
+ @dataclass
288
+ class DefaultModelRegistry:
289
+ """Populated ``ModelRegistry``. ``get`` / ``default_lane`` raise
290
+ ``UnknownModelError`` (with the known-model list) for an unregistered model —
291
+ this IS the unknown-model config-time rejection."""
292
+
293
+ def list_models(self) -> tuple[ModelSpec, ...]:
294
+ return _MODEL_SPECS
295
+
296
+ def get(self, model: str) -> ModelSpec:
297
+ for spec in _MODEL_SPECS:
298
+ if spec.model == model:
299
+ return spec
300
+ known = ", ".join(s.model for s in _MODEL_SPECS)
301
+ raise UnknownModelError(f"unknown model {model!r}; known models: {known}")
302
+
303
+ def default_lane(self, model: str) -> str:
304
+ return self.get(model).default_lane
305
+
306
+
307
+ # Module-level singletons the matrix / config loader default to.
308
+ DEFAULT_HARNESS_REGISTRY = DefaultHarnessRegistry()
309
+ DEFAULT_MODEL_REGISTRY = DefaultModelRegistry()