bpsai-pair 2.28.1__tar.gz → 2.28.2__tar.gz

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 (838) hide show
  1. {bpsai_pair-2.28.1/bpsai_pair.egg-info → bpsai_pair-2.28.2}/PKG-INFO +7 -1
  2. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/README.md +5 -0
  3. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/cli_startup.py +37 -13
  4. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/arch_lint_commands.py +13 -3
  5. bpsai_pair-2.28.2/bpsai_pair/commands/arch_wiring.py +161 -0
  6. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/budget.py +1 -0
  7. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage.py +14 -28
  8. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_branch.py +6 -0
  9. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_branch_multi.py +13 -6
  10. bpsai_pair-2.28.2/bpsai_pair/commands/engage_executor.py +116 -0
  11. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_pause_resume.py +17 -37
  12. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_pr.py +126 -20
  13. bpsai_pair-2.28.2/bpsai_pair/commands/engage_resume_integrity.py +140 -0
  14. bpsai_pair-2.28.2/bpsai_pair/commands/gitignore.py +138 -0
  15. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/init_commands.py +4 -1
  16. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/init_repo.py +1 -1
  17. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/preflight.py +4 -6
  18. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/support.py +43 -1
  19. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/upgrade.py +12 -5
  20. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/upgrade_helpers.py +2 -0
  21. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/upgrade_prompt.py +16 -5
  22. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/config_defaults.py +9 -0
  23. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/hook_handlers.py +0 -5
  24. bpsai_pair-2.28.2/bpsai_pair/core/hook_metrics.py +105 -0
  25. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/hooks.py +14 -7
  26. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/preset_definitions.py +4 -4
  27. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/reachability_ast.py +8 -2
  28. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/reachability_lint.py +16 -4
  29. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/subprocess_lint.py +7 -0
  30. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/settings.json +3 -0
  31. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/scripts/bootstrap-remote.sh +1 -1
  32. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/engage/constants.py +27 -1
  33. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/calibration.py +17 -36
  34. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/schema.py +4 -0
  35. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/stats.py +33 -20
  36. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/harness/claude_code.py +18 -3
  37. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/binding.py +62 -2
  38. bpsai_pair-2.28.2/bpsai_pair/licensing/cache_signing.py +127 -0
  39. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/core.py +13 -6
  40. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/online.py +62 -15
  41. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/startup.py +5 -0
  42. bpsai_pair-2.28.2/bpsai_pair/licensing/unchecked.py +39 -0
  43. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/validation_cache.py +16 -0
  44. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/backlog_parser.py +20 -0
  45. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/backlog_validation.py +62 -0
  46. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/backlog_yaml.py +4 -0
  47. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/branch_review.py +2 -2
  48. bpsai_pair-2.28.2/bpsai_pair/orchestration/checkin_diagnostic.py +143 -0
  49. bpsai_pair-2.28.2/bpsai_pair/orchestration/engage_push.py +159 -0
  50. bpsai_pair-2.28.2/bpsai_pair/orchestration/engage_push_scan.py +85 -0
  51. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/engage_review.py +2 -2
  52. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/headless.py +43 -28
  53. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/headless_runner.py +7 -1
  54. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/headless_runner_helpers.py +56 -2
  55. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/heartbeat.py +47 -15
  56. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/pr_review.py +7 -7
  57. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/review_common.py +26 -8
  58. bpsai_pair-2.28.2/bpsai_pair/orchestration/review_severity.py +93 -0
  59. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/sprint_commit.py +3 -0
  60. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/sprint_executor_baseline.py +38 -4
  61. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/sprint_executor_outcome.py +26 -9
  62. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/sprint_models.py +9 -0
  63. bpsai_pair-2.28.2/bpsai_pair/orchestration/wiring_review.py +85 -0
  64. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/task_commands.py +3 -0
  65. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/task_update_enforcement.py +62 -0
  66. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/release/commands.py +88 -10
  67. bpsai_pair-2.28.2/bpsai_pair/release/phase89_gate.py +189 -0
  68. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/release/release_checks.py +6 -0
  69. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/statusline_install.py +32 -3
  70. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/_serialization.py +2 -0
  71. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/collector.py +15 -12
  72. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/schema.py +21 -0
  73. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/tokens.py +8 -3
  74. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/budget_api.py +3 -3
  75. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/chat_api.py +1 -1
  76. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/budget.html +18 -6
  77. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2/bpsai_pair.egg-info}/PKG-INFO +7 -1
  78. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair.egg-info/SOURCES.txt +9 -0
  79. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair.egg-info/requires.txt +1 -0
  80. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/pyproject.toml +2 -1
  81. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_statusline_install.py +73 -2
  82. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_template_signal_hooks.py +18 -0
  83. bpsai_pair-2.28.1/bpsai_pair/commands/arch_wiring.py +0 -71
  84. bpsai_pair-2.28.1/bpsai_pair/commands/engage_executor.py +0 -61
  85. bpsai_pair-2.28.1/bpsai_pair/commands/gitignore.py +0 -57
  86. bpsai_pair-2.28.1/bpsai_pair/core/hook_metrics.py +0 -319
  87. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/LICENSE +0 -0
  88. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/MANIFEST.in +0 -0
  89. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/__init__.py +0 -0
  90. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/__main__.py +0 -0
  91. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/benchmarks/__init__.py +0 -0
  92. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/benchmarks/reports.py +0 -0
  93. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/benchmarks/runner.py +0 -0
  94. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/benchmarks/validation.py +0 -0
  95. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/cli.py +0 -0
  96. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/cli_registration.py +0 -0
  97. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/__init__.py +0 -0
  98. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/arch.py +0 -0
  99. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/audit.py +0 -0
  100. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/benchmark.py +0 -0
  101. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/budget_programmatic.py +0 -0
  102. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/cache.py +0 -0
  103. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/claude_md_merge.py +0 -0
  104. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/compaction_commands.py +0 -0
  105. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/config.py +0 -0
  106. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/config_cmd.py +0 -0
  107. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/containment_checkpoint.py +0 -0
  108. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/containment_commands.py +0 -0
  109. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/containment_session.py +0 -0
  110. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/context_commands.py +0 -0
  111. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/core.py +0 -0
  112. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/doctor.py +0 -0
  113. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/enforce.py +0 -0
  114. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/enforce_containment.py +0 -0
  115. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/enforce_state_edit.py +0 -0
  116. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/enforce_task_edit.py +0 -0
  117. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_base.py +0 -0
  118. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_cross_module.py +0 -0
  119. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_guards.py +0 -0
  120. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_navigator.py +0 -0
  121. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_plan_id.py +0 -0
  122. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_pr_multi.py +0 -0
  123. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_preflight.py +0 -0
  124. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_qa_multi.py +0 -0
  125. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_result.py +0 -0
  126. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_resume.py +0 -0
  127. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_security.py +0 -0
  128. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_sweep.py +0 -0
  129. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_target_repo.py +0 -0
  130. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/engage_worktree.py +0 -0
  131. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/feedback.py +0 -0
  132. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/feedback_helpers.py +0 -0
  133. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/fleet_check.py +0 -0
  134. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/init_feature.py +0 -0
  135. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/license.py +0 -0
  136. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/license_helpers.py +0 -0
  137. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/mcp.py +0 -0
  138. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/metrics/__init__.py +0 -0
  139. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/metrics/analysis_commands.py +0 -0
  140. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/metrics/burndown_command.py +0 -0
  141. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/metrics/helpers.py +0 -0
  142. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/metrics/summary_commands.py +0 -0
  143. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/orchestrate.py +0 -0
  144. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/orchestrate_evaluate.py +0 -0
  145. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/pm.py +0 -0
  146. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/pm_crud.py +0 -0
  147. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/pm_diagnostics.py +0 -0
  148. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/pm_helpers.py +0 -0
  149. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/pm_hierarchy_cmd.py +0 -0
  150. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/pm_migrate.py +0 -0
  151. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/pm_sprint.py +0 -0
  152. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/preset.py +0 -0
  153. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/prime_learn.py +0 -0
  154. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/provider_command.py +0 -0
  155. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/provider_presets.py +0 -0
  156. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/qc_commands.py +0 -0
  157. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/query.py +0 -0
  158. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/review.py +0 -0
  159. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/security.py +0 -0
  160. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/session.py +0 -0
  161. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/session_check.py +0 -0
  162. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/session_status.py +0 -0
  163. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/setup_commands.py +0 -0
  164. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/state.py +0 -0
  165. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/state_validation.py +0 -0
  166. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/status_handoff.py +0 -0
  167. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/subscription.py +0 -0
  168. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/sweep_command.py +0 -0
  169. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/sweep_helpers.py +0 -0
  170. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/system.py +0 -0
  171. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/telemetry.py +0 -0
  172. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/telemetry_aggregate_cmd.py +0 -0
  173. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/telemetry_display.py +0 -0
  174. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/telemetry_export.py +0 -0
  175. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/telemetry_helpers.py +0 -0
  176. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/telemetry_log_failure.py +0 -0
  177. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/telemetry_log_lifecycle.py +0 -0
  178. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/timer.py +0 -0
  179. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/upgrade_containment.py +0 -0
  180. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/upgrade_execute.py +0 -0
  181. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/validation_commands.py +0 -0
  182. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/version_consistency.py +0 -0
  183. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/wizard.py +0 -0
  184. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/workspace.py +0 -0
  185. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/workspace_helpers.py +0 -0
  186. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/workspace_impact.py +0 -0
  187. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/workspace_index_cmd.py +0 -0
  188. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/workspace_init_project.py +0 -0
  189. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/workspace_setup_permissions.py +0 -0
  190. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/commands/workspace_validate.py +0 -0
  191. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/compaction.py +0 -0
  192. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/compaction_events.py +0 -0
  193. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/compaction_helpers.py +0 -0
  194. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/compaction_models.py +0 -0
  195. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/compaction_recovery.py +0 -0
  196. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/context/__init__.py +0 -0
  197. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/context/cache.py +0 -0
  198. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/context/freshness.py +0 -0
  199. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/context/loader.py +0 -0
  200. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/__init__.py +0 -0
  201. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/arch_headroom.py +0 -0
  202. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/budget_heuristic.py +0 -0
  203. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/bypass_log.py +0 -0
  204. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/cache_paths.py +0 -0
  205. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/ci_gate.py +0 -0
  206. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/config.py +0 -0
  207. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/config_architecture.py +0 -0
  208. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/config_containment.py +0 -0
  209. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/config_helpers.py +0 -0
  210. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/config_loader.py +0 -0
  211. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/config_templates.py +0 -0
  212. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/config_validation.py +0 -0
  213. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/config_validator.py +0 -0
  214. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/constants.py +0 -0
  215. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/deprecation.py +0 -0
  216. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/encoding.py +0 -0
  217. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/encoding_lint.py +0 -0
  218. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/enforcement.py +0 -0
  219. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/enforcement_analyzer.py +0 -0
  220. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/enforcement_checker.py +0 -0
  221. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/enforcement_models.py +0 -0
  222. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/enforcement_utils.py +0 -0
  223. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/engage_task_start.py +0 -0
  224. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/enrichment_helpers.py +0 -0
  225. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/enrichment_hooks.py +0 -0
  226. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/file_role_detector.py +0 -0
  227. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/gate_executor.py +0 -0
  228. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/gate_hooks.py +0 -0
  229. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/hook_budget.py +0 -0
  230. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/hook_budget_programmatic.py +0 -0
  231. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/hook_pm.py +0 -0
  232. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/hook_routing.py +0 -0
  233. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/hook_state.py +0 -0
  234. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/hook_trello.py +0 -0
  235. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/hook_types.py +0 -0
  236. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/ops.py +0 -0
  237. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/ops_ci.py +0 -0
  238. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/ops_context.py +0 -0
  239. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/ops_feature.py +0 -0
  240. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/ops_git.py +0 -0
  241. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/ops_project.py +0 -0
  242. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/orchestration_hooks.py +0 -0
  243. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/preconditions.py +0 -0
  244. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/preferences.py +0 -0
  245. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/preset_config.py +0 -0
  246. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/presets.py +0 -0
  247. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/programmatic_credit_state.py +0 -0
  248. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/programmatic_credit_validator.py +0 -0
  249. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/routing.py +0 -0
  250. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/task_acceptance.py +0 -0
  251. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/task_ready.py +0 -0
  252. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/task_state.py +0 -0
  253. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/core/utils.py +0 -0
  254. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/__init__.py +0 -0
  255. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/containment_section.md +0 -0
  256. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/README.md +0 -0
  257. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/cookiecutter.json +0 -0
  258. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.agentpackignore +0 -0
  259. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/agent-memory/bellona/MEMORY.md +0 -0
  260. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/agent-memory/driver/MEMORY.md +0 -0
  261. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/agent-memory/laverna/MEMORY.md +0 -0
  262. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/agent-memory/navigator/MEMORY.md +0 -0
  263. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/agent-memory/nayru/MEMORY.md +0 -0
  264. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/agents/bellona.md +0 -0
  265. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/agents/divona.md +0 -0
  266. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/agents/driver.md +0 -0
  267. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/agents/laverna.md +0 -0
  268. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/agents/navigator.md +0 -0
  269. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/agents/nayru.md +0 -0
  270. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/agents/vaivora.md +0 -0
  271. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/commands/draft-backlog.md +0 -0
  272. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/commands/make-it-so.md +0 -0
  273. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/commands/pc-audit-sibling.md +0 -0
  274. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/commands/pc-plan.md +0 -0
  275. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/commands/run-qc.md +0 -0
  276. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/commands/start-task.md +0 -0
  277. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/commands/update-skills.md +0 -0
  278. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/rules/architecture.md +0 -0
  279. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/architecting-modules/SKILL.md +0 -0
  280. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/auditing-sibling-projects/SKILL.md +0 -0
  281. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/creating-skills/SKILL.md +0 -0
  282. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/designing-and-implementing/SKILL.md +0 -0
  283. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/finishing-branches/SKILL.md +0 -0
  284. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/implementing-with-tdd/SKILL.md +0 -0
  285. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/managing-task-lifecycle/SKILL.md +0 -0
  286. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/managing-task-lifecycle/reference/all-cli-commands.md +0 -0
  287. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/managing-task-lifecycle/reference/bps-trello-conventions.md +0 -0
  288. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/managing-task-lifecycle/scripts/check_completion.py +0 -0
  289. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/managing-task-lifecycle/scripts/validate_task_status.py +0 -0
  290. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/planning-with-pm/SKILL.md +0 -0
  291. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/planning-with-trello/SKILL.md +0 -0
  292. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/reviewing-code/SKILL.md +0 -0
  293. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.claude/skills/running-qc/SKILL.md +0 -0
  294. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.editorconfig +0 -0
  295. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.gitignore +0 -0
  296. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/.gitignore +0 -0
  297. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/capabilities.yaml +0 -0
  298. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/context/project.md +0 -0
  299. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/context/state.md +0 -0
  300. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/context/workflow.md +0 -0
  301. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/feedback/.gitkeep +0 -0
  302. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/history/.gitkeep +0 -0
  303. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/plans/.gitkeep +0 -0
  304. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/security/allowlist.yaml +0 -0
  305. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/security/sandbox.yaml +0 -0
  306. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/security/secret-allowlist.yaml +0 -0
  307. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/tasks/.gitkeep +0 -0
  308. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/.paircoder/telemetry/.gitkeep +0 -0
  309. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/CLAUDE.md +0 -0
  310. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/cookiecutter-paircoder/{{cookiecutter.project_slug}}/scripts/on_permission_denied.sh +0 -0
  311. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/hooks/on_permission_denied.sh +0 -0
  312. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/workflows/bps-full.yaml +0 -0
  313. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/data/workflows/simple.yaml +0 -0
  314. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/engage/__init__.py +0 -0
  315. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/engage/a2a_push.py +0 -0
  316. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/engage/containment_audit.py +0 -0
  317. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/__init__.py +0 -0
  318. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/anomaly.py +0 -0
  319. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/benchmark_seed.py +0 -0
  320. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/calibration_helpers.py +0 -0
  321. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/calibration_refresh.py +0 -0
  322. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/classifier.py +0 -0
  323. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/fleet.py +0 -0
  324. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/overhead.py +0 -0
  325. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/query_builder.py +0 -0
  326. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/scoring.py +0 -0
  327. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/service.py +0 -0
  328. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/stack_detect.py +0 -0
  329. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/state_query.py +0 -0
  330. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/feedback/workspace_query.py +0 -0
  331. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/github/__init__.py +0 -0
  332. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/github/client.py +0 -0
  333. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/github/commands.py +0 -0
  334. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/github/merge_strategy.py +0 -0
  335. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/github/pr.py +0 -0
  336. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/github/pr_manager.py +0 -0
  337. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/github/pr_models.py +0 -0
  338. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/github/pr_workflow.py +0 -0
  339. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/harness/__init__.py +0 -0
  340. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/harness/dispatch_adapter.py +0 -0
  341. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/harness/env_overrides.py +0 -0
  342. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/harness/provider_loader.py +0 -0
  343. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/init_bundled_cli.py +0 -0
  344. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/integrations/__init__.py +0 -0
  345. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/integrations/time_tracking.py +0 -0
  346. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/integrations/toggl.py +0 -0
  347. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/__init__.py +0 -0
  348. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/config.py +0 -0
  349. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/gap_mapper.py +0 -0
  350. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/gate_mapper.py +0 -0
  351. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/license_gate.py +0 -0
  352. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/mapper_base.py +0 -0
  353. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/pipeline.py +0 -0
  354. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/recommender.py +0 -0
  355. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/recommender_models.py +0 -0
  356. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/recommender_weights.py +0 -0
  357. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/scorer_mapper.py +0 -0
  358. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/session_mapper.py +0 -0
  359. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/signal_model.py +0 -0
  360. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/task_hook.py +0 -0
  361. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intelligence/telemetry_mapper.py +0 -0
  362. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intent_gate/__init__.py +0 -0
  363. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intent_gate/approval.py +0 -0
  364. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intent_gate/approval_gate.py +0 -0
  365. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intent_gate/capability_gate.py +0 -0
  366. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intent_gate/classifier.py +0 -0
  367. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intent_gate/dispatch_guard.py +0 -0
  368. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intent_gate/frustration.py +0 -0
  369. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intent_gate/response_injection.py +0 -0
  370. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/intent_gate/schema.py +0 -0
  371. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/json_envelope.py +0 -0
  372. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/__init__.py +0 -0
  373. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/activation.py +0 -0
  374. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/keys.py +0 -0
  375. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/machine.py +0 -0
  376. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/paths.py +0 -0
  377. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/public_key.pem +0 -0
  378. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/schema.py +0 -0
  379. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/security.py +0 -0
  380. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/snapshot_bridge.py +0 -0
  381. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/licensing/tier_change.py +0 -0
  382. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/mcp/__init__.py +0 -0
  383. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/mcp/server.py +0 -0
  384. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/mcp/tools/__init__.py +0 -0
  385. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/mcp/tools/channels.py +0 -0
  386. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/mcp/tools/context.py +0 -0
  387. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/mcp/tools/metrics.py +0 -0
  388. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/mcp/tools/orchestration.py +0 -0
  389. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/mcp/tools/planning.py +0 -0
  390. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/mcp/tools/support.py +0 -0
  391. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/mcp/tools/tasks.py +0 -0
  392. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/mcp/tools/trello.py +0 -0
  393. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/memory_retention.py +0 -0
  394. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/metrics/__init__.py +0 -0
  395. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/metrics/accuracy.py +0 -0
  396. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/metrics/budget.py +0 -0
  397. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/metrics/burndown.py +0 -0
  398. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/metrics/collector.py +0 -0
  399. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/metrics/estimation.py +0 -0
  400. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/metrics/hours_comparison.py +0 -0
  401. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/metrics/reports.py +0 -0
  402. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/metrics/token_estimator.py +0 -0
  403. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/metrics/token_feedback.py +0 -0
  404. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/metrics/velocity.py +0 -0
  405. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/migrate.py +0 -0
  406. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/__init__.py +0 -0
  407. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/agent_names.py +0 -0
  408. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/agent_selector.py +0 -0
  409. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/autonomous.py +0 -0
  410. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/autonomous_models.py +0 -0
  411. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/autonomous_steps.py +0 -0
  412. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/backlog_header.py +0 -0
  413. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/backlog_materializer.py +0 -0
  414. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/circuit_breaker_recovery.py +0 -0
  415. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/commit_verification.py +0 -0
  416. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/completion_guard.py +0 -0
  417. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/dependency_resolver.py +0 -0
  418. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/engage_run_state.py +0 -0
  419. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/findings_loop.py +0 -0
  420. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/handoff.py +0 -0
  421. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/handoff_consumer.py +0 -0
  422. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/handoff_retention.py +0 -0
  423. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/impact_dedup.py +0 -0
  424. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/invoker.py +0 -0
  425. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/manager.py +0 -0
  426. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/model_routing.py +0 -0
  427. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/nayru_deterministic.py +0 -0
  428. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/nayru_pregates.py +0 -0
  429. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/orchestrator.py +0 -0
  430. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/orchestrator_helpers.py +0 -0
  431. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/orchestrator_models.py +0 -0
  432. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/output_verifier.py +0 -0
  433. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/output_verifier_git_args.py +0 -0
  434. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/output_verifier_signals.py +0 -0
  435. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/package_builder.py +0 -0
  436. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/plan_graph.py +0 -0
  437. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/plan_graph_models.py +0 -0
  438. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/planner.py +0 -0
  439. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/pre_dispatch_check.py +0 -0
  440. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/pre_task_sha.py +0 -0
  441. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/reconciliation.py +0 -0
  442. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/review_checks.py +0 -0
  443. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/review_dispatch.py +0 -0
  444. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/review_models.py +0 -0
  445. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/review_output.py +0 -0
  446. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/reviewer.py +0 -0
  447. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/security.py +0 -0
  448. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/security_models.py +0 -0
  449. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/security_parser.py +0 -0
  450. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/serializer.py +0 -0
  451. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/sprint_executor.py +0 -0
  452. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/sprint_executor_hooks.py +0 -0
  453. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/sprint_lifecycle_args.py +0 -0
  454. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/sprint_lifecycle_hooks.py +0 -0
  455. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/sprint_review_helpers.py +0 -0
  456. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/sprint_signals.py +0 -0
  457. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/sprint_skipped_handler.py +0 -0
  458. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/sprint_summary.py +0 -0
  459. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/subagent_context.py +0 -0
  460. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/target_repo_resolution.py +0 -0
  461. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/targeted_tests.py +0 -0
  462. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/task_md_runtime.py +0 -0
  463. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/task_review.py +0 -0
  464. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/task_review_command.py +0 -0
  465. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/task_timeout.py +0 -0
  466. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/orchestration/workflow_guide.py +0 -0
  467. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/__init__.py +0 -0
  468. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/auto_assign.py +0 -0
  469. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/cli_update_cache.py +0 -0
  470. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/commands.py +0 -0
  471. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/completion_helpers.py +0 -0
  472. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/helpers.py +0 -0
  473. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/intelligence_helpers.py +0 -0
  474. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/intent_commands.py +0 -0
  475. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/intent_detection.py +0 -0
  476. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/models.py +0 -0
  477. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/parser.py +0 -0
  478. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_commands.py +0 -0
  479. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_complete_command.py +0 -0
  480. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_crud_commands.py +0 -0
  481. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_enums.py +0 -0
  482. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_estimation.py +0 -0
  483. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_intelligence.py +0 -0
  484. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_legacy_helpers.py +0 -0
  485. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_legacy_sync.py +0 -0
  486. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_model.py +0 -0
  487. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_parser.py +0 -0
  488. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_pm_enrich.py +0 -0
  489. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_pm_hierarchy.py +0 -0
  490. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_pm_sync.py +0 -0
  491. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_query_commands.py +0 -0
  492. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_status_commands.py +0 -0
  493. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_task_push.py +0 -0
  494. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_trello_sync.py +0 -0
  495. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/plan_workspace.py +0 -0
  496. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/review_intent.py +0 -0
  497. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/scope_detector.py +0 -0
  498. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/standup.py +0 -0
  499. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/standup_commands.py +0 -0
  500. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/state.py +0 -0
  501. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/status_hooks.py +0 -0
  502. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/task_archive_commands.py +0 -0
  503. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/task_check_commands.py +0 -0
  504. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/task_consistency.py +0 -0
  505. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/task_done.py +0 -0
  506. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/task_model.py +0 -0
  507. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/task_parser.py +0 -0
  508. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/task_update_completion.py +0 -0
  509. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/planning/token_estimator.py +0 -0
  510. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/__init__.py +0 -0
  511. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/actions.py +0 -0
  512. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/backlog_mixin.py +0 -0
  513. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/backlog_rollup.py +0 -0
  514. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/backlog_types.py +0 -0
  515. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/compat.py +0 -0
  516. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/completion_cascade.py +0 -0
  517. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/completion_eval.py +0 -0
  518. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/engine.py +0 -0
  519. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/errors.py +0 -0
  520. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/hierarchy.py +0 -0
  521. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/lifecycle.py +0 -0
  522. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/migration.py +0 -0
  523. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/null_provider.py +0 -0
  524. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/orchestration.py +0 -0
  525. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/presets.py +0 -0
  526. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/project_hooks.py +0 -0
  527. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/provider.py +0 -0
  528. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/registry.py +0 -0
  529. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/sprint_lifecycle.py +0 -0
  530. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/sync.py +0 -0
  531. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/types.py +0 -0
  532. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/workflow.py +0 -0
  533. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm/workflow_validation.py +0 -0
  534. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm_trello/__init__.py +0 -0
  535. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm_trello/adapter.py +0 -0
  536. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm_trello/backlog_engage.py +0 -0
  537. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm_trello/backlog_tree.py +0 -0
  538. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm_trello/config.py +0 -0
  539. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm_trello/discovery.py +0 -0
  540. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm_trello/enrichment.py +0 -0
  541. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm_trello/label_resolver.py +0 -0
  542. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm_trello/provider.py +0 -0
  543. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm_trello/relationship_ops.py +0 -0
  544. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm_trello/relationships.py +0 -0
  545. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/pm_trello/sync_ops.py +0 -0
  546. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/prime_learn/__init__.py +0 -0
  547. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/prime_learn/a2a_push.py +0 -0
  548. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/prime_learn/storage.py +0 -0
  549. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/prime_learn/synthesis.py +0 -0
  550. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/__init__.py +0 -0
  551. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/config.py +0 -0
  552. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/executor.py +0 -0
  553. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/fill_validator.py +0 -0
  554. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/gate.py +0 -0
  555. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/loader.py +0 -0
  556. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/models.py +0 -0
  557. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/reporter.py +0 -0
  558. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/results.py +0 -0
  559. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/step_handlers.py +0 -0
  560. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/telemetry_store.py +0 -0
  561. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/templates.py +0 -0
  562. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/qc/timeout_handler.py +0 -0
  563. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/query_skills/__init__.py +0 -0
  564. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/query_skills/a2a_adapter.py +0 -0
  565. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/query_skills/driver_activity.py +0 -0
  566. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/query_skills/qc_trends.py +0 -0
  567. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/query_skills/quality_metrics.py +0 -0
  568. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/query_skills/remote_query_client.py +0 -0
  569. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/query_skills/review_findings.py +0 -0
  570. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/query_skills/schema_validator.py +0 -0
  571. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/query_skills/session_outcomes.py +0 -0
  572. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/query_skills/sprint_status.py +0 -0
  573. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/query_skills/task_state.py +0 -0
  574. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/release/__init__.py +0 -0
  575. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/release/template.py +0 -0
  576. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/release/validate.py +0 -0
  577. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/Dockerfile.containment +0 -0
  578. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/__init__.py +0 -0
  579. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/allowlist.py +0 -0
  580. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/allowlist_data.py +0 -0
  581. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/allowlist_matching.py +0 -0
  582. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/checkpoint.py +0 -0
  583. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/checkpoint_base.py +0 -0
  584. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/checkpoint_containment.py +0 -0
  585. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/checkpoint_format.py +0 -0
  586. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/checkpoint_models.py +0 -0
  587. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/checkpoint_rollback.py +0 -0
  588. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/containment.py +0 -0
  589. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/containment_check.py +0 -0
  590. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/containment_config.py +0 -0
  591. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/data_classes.py +0 -0
  592. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/dep_models.py +0 -0
  593. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/dep_scanner.py +0 -0
  594. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/dependencies.py +0 -0
  595. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/image_manager.py +0 -0
  596. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/interactive_runner.py +0 -0
  597. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/network.py +0 -0
  598. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/network_control.py +0 -0
  599. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/review.py +0 -0
  600. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/review_agent.py +0 -0
  601. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/review_models.py +0 -0
  602. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/review_patterns.py +0 -0
  603. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/review_scanner.py +0 -0
  604. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/runner.py +0 -0
  605. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/sandbox.py +0 -0
  606. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/secrets.py +0 -0
  607. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/secrets_format.py +0 -0
  608. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/secrets_patterns.py +0 -0
  609. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/secrets_scanner.py +0 -0
  610. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/security/secrets_types.py +0 -0
  611. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/session.py +0 -0
  612. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/session_finalize.py +0 -0
  613. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/session_handoff.py +0 -0
  614. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/__init__.py +0 -0
  615. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/classifier.py +0 -0
  616. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/classifier_engine.py +0 -0
  617. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/classifier_models.py +0 -0
  618. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/classifier_report.py +0 -0
  619. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/cli_commands.py +0 -0
  620. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/display_helpers.py +0 -0
  621. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/export_base.py +0 -0
  622. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/exporter.py +0 -0
  623. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/gap_detector.py +0 -0
  624. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/gap_engine.py +0 -0
  625. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/gap_models.py +0 -0
  626. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/gap_persistence.py +0 -0
  627. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/gaps_commands.py +0 -0
  628. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/gate_definitions.py +0 -0
  629. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/gate_evaluator.py +0 -0
  630. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/gates.py +0 -0
  631. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/generator.py +0 -0
  632. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/generator_engine.py +0 -0
  633. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/generator_io.py +0 -0
  634. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/generator_models.py +0 -0
  635. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/installer.py +0 -0
  636. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/intent_matcher.py +0 -0
  637. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/pattern_detector.py +0 -0
  638. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/scorer.py +0 -0
  639. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/scorer_engine.py +0 -0
  640. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/scorer_format.py +0 -0
  641. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/scorer_models.py +0 -0
  642. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/scorer_telemetry.py +0 -0
  643. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/skill_commands.py +0 -0
  644. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/skill_export_cmd.py +0 -0
  645. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/skill_gap_commands.py +0 -0
  646. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/skill_install_cmd.py +0 -0
  647. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/skill_recommend_cmd.py +0 -0
  648. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/skill_score_cmds.py +0 -0
  649. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/skill_suggester.py +0 -0
  650. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/skill_validate_cmd.py +0 -0
  651. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/subagent_commands.py +0 -0
  652. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/subagent_detector.py +0 -0
  653. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/subagent_parser.py +0 -0
  654. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/subagent_patterns.py +0 -0
  655. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/suggestion.py +0 -0
  656. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/skills/validator.py +0 -0
  657. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/sprint/__init__.py +0 -0
  658. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/sprint/commands.py +0 -0
  659. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/statusline.py +0 -0
  660. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/statusline_state.py +0 -0
  661. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/support/__init__.py +0 -0
  662. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/support/auth.py +0 -0
  663. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/support/client.py +0 -0
  664. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/support/system_info.py +0 -0
  665. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/sweep/__init__.py +0 -0
  666. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/sweep/a2a_integration.py +0 -0
  667. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/sweep/classifier.py +0 -0
  668. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/sweep/diff_parser.py +0 -0
  669. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/sweep/providers/__init__.py +0 -0
  670. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/sweep/providers/_patterns.py +0 -0
  671. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/sweep/providers/generic.py +0 -0
  672. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/sweep/providers/python_provider.py +0 -0
  673. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/tasks/__init__.py +0 -0
  674. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/tasks/archiver.py +0 -0
  675. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/tasks/changelog.py +0 -0
  676. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/tasks/lifecycle.py +0 -0
  677. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/__init__.py +0 -0
  678. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/aggregate.py +0 -0
  679. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/aggregates.py +0 -0
  680. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/audit.py +0 -0
  681. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/auto_compaction.py +0 -0
  682. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/batch_submit.py +0 -0
  683. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/cache_health.py +0 -0
  684. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/collector_helpers.py +0 -0
  685. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/collectors.py +0 -0
  686. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/compaction.py +0 -0
  687. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/config.py +0 -0
  688. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/failure_pattern_detector.py +0 -0
  689. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/hook_collector.py +0 -0
  690. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/hooks_schema.py +0 -0
  691. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/migrate.py +0 -0
  692. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/parser.py +0 -0
  693. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/privacy.py +0 -0
  694. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/queries.py +0 -0
  695. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/query_helpers.py +0 -0
  696. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/recovery.py +0 -0
  697. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/recovery_helpers.py +0 -0
  698. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/session_outcomes.py +0 -0
  699. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/session_store.py +0 -0
  700. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/signal_checks.py +0 -0
  701. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/signal_emitter.py +0 -0
  702. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/signal_thresholds.py +0 -0
  703. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/snapshot.py +0 -0
  704. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/sqlite_migration.py +0 -0
  705. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/sqlite_schema.py +0 -0
  706. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/sqlite_telemetry_store.py +0 -0
  707. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/store.py +0 -0
  708. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/task_state_index.py +0 -0
  709. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/telemetry/task_state_log.py +0 -0
  710. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/__init__.py +0 -0
  711. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/activity.py +0 -0
  712. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/auth.py +0 -0
  713. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/board_commands.py +0 -0
  714. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/board_setup.py +0 -0
  715. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/checklist_ops.py +0 -0
  716. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/client.py +0 -0
  717. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/commands.py +0 -0
  718. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/connection.py +0 -0
  719. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/custom_fields.py +0 -0
  720. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/field_commands.py +0 -0
  721. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/fields.py +0 -0
  722. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/label_ops.py +0 -0
  723. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/list_resolver.py +0 -0
  724. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/progress.py +0 -0
  725. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/sync.py +0 -0
  726. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/sync_cards.py +0 -0
  727. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/sync_checklists.py +0 -0
  728. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/sync_commands.py +0 -0
  729. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/sync_fields.py +0 -0
  730. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/sync_helpers.py +0 -0
  731. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/task_card_ops.py +0 -0
  732. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/task_commands.py +0 -0
  733. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/task_completion.py +0 -0
  734. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/task_display.py +0 -0
  735. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/task_done_pipeline.py +0 -0
  736. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/task_handoff.py +0 -0
  737. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/task_helpers.py +0 -0
  738. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/task_lifecycle.py +0 -0
  739. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/task_operations.py +0 -0
  740. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/task_pm_routing.py +0 -0
  741. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/task_sync.py +0 -0
  742. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/templates.py +0 -0
  743. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/webhook.py +0 -0
  744. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/webhook_auth.py +0 -0
  745. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/webhook_commands.py +0 -0
  746. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/webhook_config.py +0 -0
  747. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/webhook_handlers.py +0 -0
  748. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/trello/webhook_server.py +0 -0
  749. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/utils/__init__.py +0 -0
  750. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/utils/sysproc.py +0 -0
  751. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/__init__.py +0 -0
  752. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/api_routes.py +0 -0
  753. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/app.py +0 -0
  754. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/config_builder.py +0 -0
  755. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/config_parser.py +0 -0
  756. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/containment_step.py +0 -0
  757. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/creator.py +0 -0
  758. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/demo.py +0 -0
  759. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/editor_api.py +0 -0
  760. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/enforcement_api.py +0 -0
  761. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/github_api.py +0 -0
  762. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/guided_api.py +0 -0
  763. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/license_installer.py +0 -0
  764. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/loader.py +0 -0
  765. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/mcp_api.py +0 -0
  766. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/page_routes.py +0 -0
  767. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/pro_page_routes.py +0 -0
  768. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/project_api.py +0 -0
  769. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/prompts/__init__.py +0 -0
  770. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/prompts/guided_setup.md +0 -0
  771. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/review_api.py +0 -0
  772. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/routes.py +0 -0
  773. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/session.py +0 -0
  774. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/state.py +0 -0
  775. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/static/chat.js +0 -0
  776. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/static/style.css +0 -0
  777. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/static/wizard.js +0 -0
  778. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/steps.py +0 -0
  779. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/base.html +0 -0
  780. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/chat.html +0 -0
  781. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/enforcement.html +0 -0
  782. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/github.html +0 -0
  783. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/index.html +0 -0
  784. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/mcp.html +0 -0
  785. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/partials/license_install.html +0 -0
  786. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/partials/locked_overlay.html +0 -0
  787. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/partials/upgrade_modal.html +0 -0
  788. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/project.html +0 -0
  789. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/review.html +0 -0
  790. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/success.html +0 -0
  791. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/trello.html +0 -0
  792. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/welcome.html +0 -0
  793. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/templates/workflow.html +0 -0
  794. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/trello_api.py +0 -0
  795. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/update_api.py +0 -0
  796. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/wizard/workflow_routes.py +0 -0
  797. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/__init__.py +0 -0
  798. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/agent_spawning.py +0 -0
  799. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/agent_teams.py +0 -0
  800. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/audit.py +0 -0
  801. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/contracts.py +0 -0
  802. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/discovery.py +0 -0
  803. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/execution_plan.py +0 -0
  804. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/git_ops.py +0 -0
  805. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/gitignore.py +0 -0
  806. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/impact.py +0 -0
  807. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/init_project.py +0 -0
  808. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/membership.py +0 -0
  809. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/orchestrator.py +0 -0
  810. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/parser.py +0 -0
  811. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/permissions.py +0 -0
  812. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/project_md.py +0 -0
  813. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/schema.py +0 -0
  814. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/sibling_conventions.py +0 -0
  815. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/stack_detect.py +0 -0
  816. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/task_push.py +0 -0
  817. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair/workspace/workspace_index.py +0 -0
  818. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair.egg-info/dependency_links.txt +0 -0
  819. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair.egg-info/entry_points.txt +0 -0
  820. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/bpsai_pair.egg-info/top_level.txt +0 -0
  821. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/setup.cfg +0 -0
  822. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_cli_registration.py +0 -0
  823. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_compaction_containment.py +0 -0
  824. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_compaction_coverage.py +0 -0
  825. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_compaction_decomp.py +0 -0
  826. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_compaction_events.py +0 -0
  827. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_feature_gating.py +0 -0
  828. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_init_bundled_cli.py +0 -0
  829. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_main_entrypoint.py +0 -0
  830. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_memory_retention.py +0 -0
  831. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_session_finalize.py +0 -0
  832. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_stale_task_lint.py +0 -0
  833. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_statusline.py +0 -0
  834. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_statusline_heartbeat.py +0 -0
  835. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_statusline_integration.py +0 -0
  836. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_statusline_mtime.py +0 -0
  837. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_t42_1_qc_rename.py +0 -0
  838. {bpsai_pair-2.28.1 → bpsai_pair-2.28.2}/tests/test_website_signal_hooks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bpsai-pair
3
- Version: 2.28.1
3
+ Version: 2.28.2
4
4
  Summary: AI-augmented pair programming framework with 220+ CLI commands for planning, orchestration, Trello/GitHub integration, and autonomous workflows
5
5
  Author-email: BPS AI Software <support@paircoder.ai>
6
6
  License-Expression: LicenseRef-Proprietary
@@ -29,6 +29,7 @@ Requires-Dist: pyyaml>=6.0
29
29
  Requires-Dist: tiktoken>=0.5.0
30
30
  Requires-Dist: pydantic>=2.0
31
31
  Requires-Dist: cryptography>=41.0
32
+ Requires-Dist: keyring>=25.0
32
33
  Requires-Dist: fastapi>=0.109.0
33
34
  Requires-Dist: jinja2>=3.1.0
34
35
  Requires-Dist: uvicorn>=0.27.0
@@ -182,6 +183,11 @@ Check your license: `bpsai-pair license status`
182
183
 
183
184
  > Full release history and detailed notes: [paircoder.ai](https://paircoder.ai).
184
185
 
186
+ **v2.28.2 — Latest-model support + engage durability (patch)**
187
+ - Claude Sonnet 5 and Fable 5 selectable in the wizard/config; current-gen context limits corrected to 1M for accurate budgets.
188
+ - Engage pushes its branch at kickoff and after every task — crash durability + mid-run visibility.
189
+ - Fixes: engage on Windows, `support create`/`list` scope, `upgrade` artifact hygiene, fail-closed `review pr`, engage auto-PR `--head`.
190
+
185
191
  **v2.28.0 — Cross-repo engage, provider-agnostic PM, plan-time arch headroom (minor)**
186
192
 
187
193
  - **Cross-repo engage.** A sprint can target sibling repos — engage commits, branches, opens PRs, and verifies in the right repo per task; backlogs declare a `Target repo:` (backlog-level or per-task), and QA/security/review fan out across every touched repo.
@@ -108,6 +108,11 @@ Check your license: `bpsai-pair license status`
108
108
 
109
109
  > Full release history and detailed notes: [paircoder.ai](https://paircoder.ai).
110
110
 
111
+ **v2.28.2 — Latest-model support + engage durability (patch)**
112
+ - Claude Sonnet 5 and Fable 5 selectable in the wizard/config; current-gen context limits corrected to 1M for accurate budgets.
113
+ - Engage pushes its branch at kickoff and after every task — crash durability + mid-run visibility.
114
+ - Fixes: engage on Windows, `support create`/`list` scope, `upgrade` artifact hygiene, fail-closed `review pr`, engage auto-PR `--head`.
115
+
111
116
  **v2.28.0 — Cross-repo engage, provider-agnostic PM, plan-time arch headroom (minor)**
112
117
 
113
118
  - **Cross-repo engage.** A sprint can target sibling repos — engage commits, branches, opens PRs, and verifies in the right repo per task; backlogs declare a `Target repo:` (backlog-level or per-task), and QA/security/review fan out across every touched repo.
@@ -25,26 +25,54 @@ def version_callback(value: bool):
25
25
  raise typer.Exit()
26
26
 
27
27
 
28
+ def _check_expired_license():
29
+ """Hard-fail if an expired subscription/trial license is installed (LA3.3).
30
+
31
+ Perpetual licenses are unaffected (is_expired returns False for them).
32
+ """
33
+ import sys
34
+
35
+ from .licensing.core import is_expired
36
+ from .licensing.unchecked import load_license_unchecked
37
+
38
+ unchecked = load_license_unchecked()
39
+ if unchecked is None or not is_expired(unchecked):
40
+ return
41
+
42
+ ltype = unchecked.payload.type
43
+ if ltype not in ("subscription", "trial"):
44
+ return
45
+
46
+ exp = unchecked.payload.expires_at
47
+ date_str = exp.strftime("%Y-%m-%d") if exp else "unknown"
48
+ err_console = Console(file=sys.stderr)
49
+ err_console.print(
50
+ f"[bold red]Your {ltype} license expired on {date_str}.[/bold red]\n"
51
+ f"Renew at [cyan]https://paircoder.ai/pricing[/cyan] "
52
+ f"or run: [cyan]bpsai-pair license renew[/cyan]"
53
+ )
54
+ sys.exit(2)
55
+
56
+
28
57
  def _run_license_validation():
29
58
  """Run license validation on startup (silent for non-critical signals).
30
59
 
31
- License validation runs in background. Errors are NOT printed here to avoid
32
- polluting JSON output and quiet mode commands. Users can check license status
33
- with `bpsai-pair license status`.
34
-
35
60
  Hard-fail conditions (exit non-zero with stderr message):
61
+ - Expired subscription/trial license — LA3.3
36
62
  - Revoked license — always
37
63
  - machine_activated=False AND past grace period — T45.22 (#157)
38
64
 
39
- Other signals (license-not-found, expired warnings, etc.) stay silent;
40
- `bpsai-pair license status` exposes the full state.
65
+ Network/import errors are caught gracefully (offline grace preserved).
41
66
  """
42
67
  try:
43
68
  import sys
44
69
 
70
+ from .licensing.online import NetworkError
45
71
  from .licensing.startup import run_startup_validation
46
72
  from .licensing.binding import is_in_grace_period
47
73
 
74
+ _check_expired_license()
75
+
48
76
  result = run_startup_validation()
49
77
  if result is None:
50
78
  return
@@ -56,10 +84,6 @@ def _run_license_validation():
56
84
  err_console.print(f"[bold red]License revoked:[/bold red] {reason}")
57
85
  sys.exit(2)
58
86
 
59
- # T45.22 #157: server says this machine isn't activated. The local
60
- # binding.is_machine_activated check uses grace period as a fallback;
61
- # mirror that here so a fresh install isn't immediately locked out.
62
- # Once the grace window passes, fail closed with the activation prompt.
63
87
  if not result.machine_activated and not is_in_grace_period():
64
88
  err_console.print(
65
89
  "[bold red]License not activated on this machine.[/bold red]\n"
@@ -68,9 +92,9 @@ def _run_license_validation():
68
92
  )
69
93
  sys.exit(2)
70
94
  except SystemExit:
71
- raise # honor sys.exit calls above
72
- except Exception:
73
- pass # Don't block CLI on validation errors (network, parse, etc.)
95
+ raise
96
+ except (NetworkError, ConnectionError, TimeoutError, OSError, ImportError):
97
+ pass # Don't block CLI on network/import errors
74
98
 
75
99
 
76
100
  def _find_project_root():
@@ -129,15 +129,25 @@ def _register_wiring(app: typer.Typer) -> None:
129
129
  False, "--strict",
130
130
  help="Exit non-zero on any finding (default: advisory, exit 0)",
131
131
  ),
132
+ gen_baseline: bool = typer.Option(
133
+ False, "--generate-baseline",
134
+ help="Write .wiring-baseline.json with current findings and exit",
135
+ ),
132
136
  ):
133
137
  """Flag public symbols/modules written but never wired in (#384).
134
138
 
135
139
  Catches the dead-on-arrival class: a public symbol/module unit-tested but
136
140
  never invoked/imported in the package. Exempts ``__all__``, CLI callbacks,
137
141
  tests, dunders/``main``, string refs, and ``[project.scripts]``. ADVISORY
138
- by default (exit 0); use --strict to gate in CI. See ``arch_wiring`` /
139
- ``core.reachability_lint`` for details and caveats.
142
+ by default (exit 0); use --strict to gate in CI.
143
+
144
+ Use --generate-baseline to snapshot current findings into
145
+ ``.wiring-baseline.json`` (committed, reviewable debt allowlist).
140
146
  """
141
- from .arch_wiring import run_check_wiring
147
+ from .arch_wiring import generate_baseline, run_check_wiring
142
148
 
149
+ if gen_baseline:
150
+ outpath = generate_baseline(path, Path.cwd())
151
+ console.print(f"[green]✓ Baseline written to {outpath}[/green]")
152
+ raise typer.Exit(code=0)
143
153
  run_check_wiring(path, strict)
@@ -0,0 +1,161 @@
1
+ """Render logic for ``bpsai-pair arch check-wiring`` (#384, #WG2.3).
2
+
3
+ Kept separate from ``arch.py`` so the Typer wrapper there stays thin and the
4
+ module stays under the architecture line limit. The command body reads
5
+ ``[project.scripts]`` entry points from the nearest ``pyproject.toml`` so
6
+ console-script symbols are not flagged as unwired.
7
+
8
+ WG2.3 additions:
9
+ - ``generate_baseline()`` writes ``.wiring-baseline.json`` for a repo.
10
+ - ``run_check_wiring_core()`` returns filtered findings (baseline-aware).
11
+ - ``run_check_wiring()`` uses baseline filtering before reporting.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import json
16
+ from pathlib import Path
17
+
18
+ import typer
19
+ from rich.console import Console
20
+
21
+ from ..core.reachability_lint import Finding, check_directory
22
+ from ..orchestration.wiring_review import filter_baseline, load_baseline
23
+
24
+ console = Console()
25
+
26
+ _BASELINE_FILE = ".wiring-baseline.json"
27
+
28
+
29
+ def _entry_point_symbols(start: Path) -> set[str]:
30
+ """Read symbol names from the nearest pyproject ``[project.scripts]``.
31
+
32
+ ``foo = "pkg.mod:func"`` contributes the symbol ``func``. Best-effort:
33
+ returns an empty set if no pyproject or tomllib is available.
34
+ """
35
+ try:
36
+ import tomllib
37
+ except ModuleNotFoundError: # pragma: no cover - py<3.11
38
+ return set()
39
+ for parent in [start, *start.resolve().parents]:
40
+ candidate = parent / "pyproject.toml"
41
+ if not candidate.is_file():
42
+ continue
43
+ try:
44
+ data = tomllib.loads(candidate.read_text(encoding="utf-8"))
45
+ except (OSError, ValueError):
46
+ return set()
47
+ scripts = data.get("project", {}).get("scripts", {})
48
+ return {str(v).rsplit(":", 1)[-1] for v in scripts.values() if ":" in str(v)}
49
+ return set()
50
+
51
+
52
+ def _relativize(finding_path: Path, scan_root: Path) -> str:
53
+ """Return the finding path relative to scan_root, as posix."""
54
+ try:
55
+ return finding_path.resolve().relative_to(scan_root.resolve()).as_posix()
56
+ except ValueError:
57
+ return finding_path.as_posix()
58
+
59
+
60
+ def _findings_to_baseline_json(
61
+ findings: list[Finding], scan_root: Path,
62
+ ) -> list[dict]:
63
+ """Convert findings to the baseline JSON format with relative paths."""
64
+ return [
65
+ {
66
+ "file": _relativize(f.file, scan_root),
67
+ "symbol": f.symbol,
68
+ "kind": f.kind,
69
+ }
70
+ for f in findings
71
+ ]
72
+
73
+
74
+ def generate_baseline(path: str, project_root: Path) -> Path:
75
+ """Produce ``.wiring-baseline.json`` from current findings.
76
+
77
+ Scans ``path`` for unwired symbols/modules and writes the full set
78
+ as the baseline allowlist at ``project_root / .wiring-baseline.json``.
79
+ Paths are stored relative to the scan root for portability.
80
+ Returns the path to the written file.
81
+ """
82
+ target = Path(path)
83
+ findings = check_directory(target, entry_points=_entry_point_symbols(target))
84
+ data = _findings_to_baseline_json(findings, target)
85
+ outpath = project_root / _BASELINE_FILE
86
+ outpath.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
87
+ return outpath
88
+
89
+
90
+ def _normalize_findings_for_baseline(
91
+ findings: list[Finding], scan_root: Path,
92
+ ) -> list[Finding]:
93
+ """Rewrite finding paths to be relative to scan_root (for baseline matching)."""
94
+ out: list[Finding] = []
95
+ for f in findings:
96
+ rel = _relativize(f.file, scan_root)
97
+ out.append(Finding(kind=f.kind, symbol=f.symbol, file=Path(rel), line=f.line))
98
+ return out
99
+
100
+
101
+ def run_check_wiring_core(
102
+ path: str, *, baseline_root: Path | None = None,
103
+ ) -> list[Finding]:
104
+ """Return non-baselined findings (no I/O side-effects).
105
+
106
+ Scans ``path`` for unwired symbols, loads the baseline from
107
+ ``baseline_root`` (if provided), and returns only NEW findings
108
+ that are not in the baseline allowlist. Baseline entries use
109
+ paths relative to ``baseline_root``, so findings are normalized
110
+ relative to ``baseline_root`` (not the scan root) when filtering.
111
+ """
112
+ target = Path(path)
113
+ findings = check_directory(target, entry_points=_entry_point_symbols(target))
114
+ if baseline_root is not None:
115
+ baseline = load_baseline(baseline_root)
116
+ if baseline:
117
+ findings = _normalize_findings_for_baseline(findings, baseline_root)
118
+ findings = filter_baseline(findings, baseline)
119
+ return findings
120
+
121
+
122
+ def run_check_wiring(path: str, strict: bool) -> None:
123
+ """Execute the wiring/reachability advisory lint and print findings.
124
+
125
+ Loads ``.wiring-baseline.json`` from the nearest project root and
126
+ excludes baselined findings. Advisory: exits 0 unless ``strict``
127
+ is set. Raises ``typer.Exit``.
128
+ """
129
+ target = Path(path)
130
+ if not target.exists():
131
+ console.print(f"[red]Error: Path not found: {target}[/red]")
132
+ raise typer.Exit(code=2)
133
+
134
+ baseline_root = _find_baseline_root(target)
135
+ findings = run_check_wiring_core(path, baseline_root=baseline_root)
136
+ if not findings:
137
+ console.print(f"[green]✓ No unwired public symbols/modules in {target}[/green]")
138
+ raise typer.Exit(code=0)
139
+
140
+ symbols = [f for f in findings if f.kind == "symbol"]
141
+ modules = [f for f in findings if f.kind == "module"]
142
+ console.print(
143
+ f"[yellow]⚠ {len(findings)} possibly-unwired item(s) in {target} "
144
+ f"({len(symbols)} symbol(s), {len(modules)} module(s)) — "
145
+ f"advisory, confirm before acting:[/yellow]\n"
146
+ )
147
+ for f in findings:
148
+ console.print(f" {f.message()}")
149
+ console.print(
150
+ "\n[dim]Static analysis cannot see dynamic dispatch; treat these as "
151
+ "candidates, not proof.[/dim]"
152
+ )
153
+ raise typer.Exit(code=1 if strict else 0)
154
+
155
+
156
+ def _find_baseline_root(start: Path) -> Path | None:
157
+ """Walk up from ``start`` to find a directory with .wiring-baseline.json."""
158
+ for parent in [start, *start.resolve().parents]:
159
+ if (parent / _BASELINE_FILE).is_file():
160
+ return parent
161
+ return None
@@ -128,6 +128,7 @@ def _find_task_file(task_id: str, root: Path) -> Optional[Path]:
128
128
 
129
129
  _MODEL_COST_PER_1K = {
130
130
  "opus": 0.005, # Opus 4.5/4.6: $5/MTok input
131
+ "fable": 0.010, # Fable 5: $10/MTok input
131
132
  "sonnet": 0.003, # Sonnet 4.0/4.5: $3/MTok input
132
133
  "haiku": 0.001, # Haiku 4.5: $1/MTok input
133
134
  }
@@ -13,6 +13,7 @@ from bpsai_pair.commands.engage_branch import ( # noqa: F401
13
13
  _cleanup_orphan_branch,
14
14
  _create_feature_branch,
15
15
  _validate_branch_name,
16
+ push_branch_at_kickoff,
16
17
  )
17
18
  from bpsai_pair.commands.engage_guards import ( # noqa: F401
18
19
  _check_protected_branch,
@@ -124,7 +125,7 @@ def engage(
124
125
  if dry_run:
125
126
  project_root = repo_root()
126
127
  _run_containment_audit_display(parsed.tasks, project_root)
127
- return _show_dry_run(parsed, json_out)
128
+ return _show_dry_run(parsed, json_out, project_root=project_root)
128
129
  env_overrides = _resolve_provider(provider) if provider else {}
129
130
  if not sprint:
130
131
  sprint = _infer_sprint(parsed)
@@ -157,7 +158,11 @@ from bpsai_pair.commands.engage_plan_id import ( # noqa: E402, F401
157
158
  _dispatch_navigator, # re-exported for tests importing it from engage
158
159
  resolve_reuse_plan_id as _resolve_reuse_plan_id,
159
160
  )
160
- from bpsai_pair.commands.engage_executor import execute_sprint as _execute_sprint # noqa: E402, F401
161
+ from bpsai_pair.commands.engage_executor import ( # noqa: E402, F401
162
+ execute_sprint as _execute_sprint,
163
+ fan_out_sibling_branches as _fan_out_sibling_branches,
164
+ preflight_parallel_same_target as _preflight_parallel_same_target,
165
+ )
161
166
  # CR.4.1 (#411): result rendering lives in ``engage_result`` (line cap);
162
167
  # re-exported so ``engage._output_result`` / ``engage._show_result`` /
163
168
  # ``engage._result_dict`` patch targets keep resolving.
@@ -296,24 +301,6 @@ def _run_preflight(
296
301
  return outcome, preflight_block
297
302
 
298
303
 
299
- def _fan_out_sibling_branches(
300
- parsed: Any, project_root: Path, active_branch: str,
301
- touched_siblings: list[tuple[Path, str | None]] | None,
302
- ) -> None:
303
- """Create the SIBLING engage branches (CR-R7) and record them (CR-R9).
304
-
305
- Runs only AFTER the preflight gate passes and BEFORE dispatch. Records each
306
- touched sibling (with its prior branch) into ``touched_siblings`` so a later
307
- sprint failure can restore those working trees (see ``_run_engage``).
308
- """
309
- if not active_branch:
310
- return
311
- touched = _branch_multi.create_cross_repo_branch(
312
- parsed, project_root, active_branch)
313
- if touched_siblings is not None:
314
- touched_siblings.extend(touched)
315
-
316
-
317
304
  def _run_sprint_pipeline(
318
305
  run_root: Path, backlog_path: Path, parsed: Any,
319
306
  sprint: str, max_parallel: int,
@@ -324,9 +311,7 @@ def _run_sprint_pipeline(
324
311
  touched_siblings: list[tuple[Path, str | None]] | None = None,
325
312
  ) -> dict[str, Any]:
326
313
  """Execute planning, sprint, and finalization in *run_root*."""
327
- if project_root is None:
328
- project_root = run_root
329
-
314
+ project_root = project_root or run_root
330
315
  reuse_plan_id = _resolve_reuse_plan_id(
331
316
  run_root, backlog_path, parsed, skip_planning, resume,
332
317
  ) # paircoder#388: reconcile onto Navigator id, not divergent engage id
@@ -336,13 +321,14 @@ def _run_sprint_pipeline(
336
321
  backlog_target, per_task_repos = _preflight.resolve_targets_or_refuse(
337
322
  parsed, project_root,
338
323
  )
339
- _, preflight_block = _run_preflight(
340
- backlog_target, per_task_repos, project_root,
341
- )
324
+ _, preflight_block = _run_preflight(backlog_target, per_task_repos, project_root)
325
+ # EH2.3: parallel-same-target guard is a preflight -> run BEFORE fan-out (below) so a refused plan branches no siblings.
326
+ _preflight_parallel_same_target(run_root, plan_id, max_parallel, backlog_target, per_task_repos)
342
327
  from bpsai_pair.pm_trello.backlog_engage import create_backlog_tree_for_engage as _create_bt # noqa: E402
343
328
  _create_bt(run_root, plan_id, parsed) # #430: after preflight → refused runs leave no orphan PM cards
344
- _fan_out_sibling_branches(
345
- parsed, project_root, active_branch, touched_siblings)
329
+ # EH1.1 (#427): push the branch to origin before dispatch (best-effort durability).
330
+ push_branch_at_kickoff(run_root, active_branch)
331
+ _fan_out_sibling_branches(parsed, project_root, active_branch, touched_siblings)
346
332
  result = _execute_sprint(
347
333
  run_root, plan_id, max_parallel, completed_tasks=completed,
348
334
  target_repo=backlog_target,
@@ -15,6 +15,12 @@ from bpsai_pair.commands.engage_guards import (
15
15
  _check_protected_branch,
16
16
  _derive_branch_slug,
17
17
  )
18
+ # EH1.1 (#427): kickoff push helper lives in ``orchestration.engage_push``
19
+ # (keeps engage.py under the arch cap); re-exported here so engage.py can call
20
+ # it via its existing ``engage_branch`` import block without a new import stmt.
21
+ from bpsai_pair.orchestration.engage_push import ( # noqa: F401
22
+ push_branch_at_kickoff,
23
+ )
18
24
 
19
25
  logger = logging.getLogger(__name__)
20
26
 
@@ -121,7 +121,10 @@ def restore_siblings_on_failure(
121
121
  for repo, prior in touched:
122
122
  if prior:
123
123
  restored = subprocess.run(
124
- ["git", "checkout", prior],
124
+ # EH2.1: ``switch --`` end-of-options guard so a flag-like prior
125
+ # branch name is never parsed as an option (defense-in-depth;
126
+ # refs are ``_validate_branch_name``-checked upstream).
127
+ ["git", "switch", "--", prior],
125
128
  cwd=repo, capture_output=True, check=False,
126
129
  encoding="utf-8", errors="replace",
127
130
  )
@@ -289,18 +292,22 @@ def _safe_checkout_engage_branch(repo: Path, branch: str) -> None:
289
292
  branch from whatever the sibling had checked out (stale feature branch /
290
293
  dirty ``main``), so the later PR diff could carry unrelated work. We now
291
294
  resolve the repo's base/default branch and cut FROM it. Idempotent: if the
292
- engage branch already exists (re-run), ``checkout -b`` fails and we fall
293
- back to a plain checkout.
295
+ engage branch already exists (re-run), ``switch -c`` fails and we fall
296
+ back to a plain ``switch``.
294
297
  """
295
298
  base = _detect_pr_base(repo)
296
299
  created = subprocess.run(
297
- ["git", "checkout", "-b", branch, base],
300
+ # EH2.1: ``switch -c -- <base>`` end-of-options guard so a flag-like
301
+ # base ref is never parsed as an option (the new branch name is safe as
302
+ # the ``-c`` argument). Mirrors the push/rev-list/gh hardening.
303
+ ["git", "switch", "-c", branch, "--", base],
298
304
  cwd=repo, capture_output=True, check=False,
299
305
  encoding="utf-8", errors="replace",
300
306
  )
301
307
  if created.returncode != 0:
302
308
  fallback = subprocess.run(
303
- ["git", "checkout", branch],
309
+ # EH2.1: ``switch --`` end-of-options guard on the fallback ref too.
310
+ ["git", "switch", "--", branch],
304
311
  cwd=repo, capture_output=True, check=False,
305
312
  encoding="utf-8", errors="replace",
306
313
  )
@@ -321,7 +328,7 @@ def create_branch_in_repos(repos: list[Path], branch: str) -> None:
321
328
  each repo is also checked for a clean tree and a non-protected branch name
322
329
  (CR-R2, Finding B), mirroring the run repo's ``_setup_branch`` rigor. The
323
330
  branch is created FROM the repo's resolved base; if it already exists
324
- (re-run) the checkout falls back to a plain checkout instead of failing.
331
+ (re-run) the create falls back to a plain ``switch`` instead of failing.
325
332
  """
326
333
  # CR-R3 (P2-1): the sibling fan-out is a funnel for the run-repo slug, an
327
334
  # explicit ``--branch`` flag, AND the derived engage name -- validate the
@@ -0,0 +1,116 @@
1
+ """Sprint execution helper extracted from engage.py to keep that file
2
+ under the 400-line architecture limit.
3
+ """
4
+ from __future__ import annotations
5
+
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ from bpsai_pair.orchestration.headless import HEADLESS_ALLOWED_TOOLS
10
+
11
+
12
+ def preflight_parallel_same_target(
13
+ project_root: Path, plan_id: str, max_parallel: int,
14
+ backlog_target: Path | None = None,
15
+ per_task_target_repos: dict[str, Path] | None = None,
16
+ ) -> None:
17
+ """Refuse a parallel-same-target plan BEFORE any sibling mutation (EH2.3).
18
+
19
+ The parallel-same-target check is logically a PREFLIGHT: it refuses a
20
+ ``ExecutionMode.PARALLEL`` phase whose tasks share one un-isolated sibling
21
+ target repo. ``_run_sprint_pipeline`` calls this BEFORE
22
+ ``_fan_out_sibling_branches`` so a refused plan branches no siblings (nothing
23
+ to restore). ``execute_sprint`` still runs the same guard as an idempotent
24
+ backstop -- that call also covers the resume path, which re-enters through
25
+ ``execute_sprint`` rather than the fresh pipeline.
26
+
27
+ A same-repo run (no per-task overrides and no sibling backlog target) has no
28
+ sibling target at all, so no parallel-same-sibling conflict is possible --
29
+ return early without building the plan graph. Only a sibling target (set via
30
+ ``per_task_target_repos`` or a cross-repo ``backlog_target``) can conflict.
31
+ """
32
+ if not per_task_target_repos and backlog_target is None:
33
+ return
34
+ from bpsai_pair.orchestration import plan_graph
35
+ from bpsai_pair.orchestration.target_repo_resolution import (
36
+ guard_parallel_same_target,
37
+ )
38
+ graph = plan_graph.PlanGraphBuilder(project_root).build(plan_id)
39
+ guard_parallel_same_target(
40
+ graph, per_task_target_repos, backlog_target, project_root,
41
+ max_parallel=max_parallel,
42
+ )
43
+
44
+
45
+ def fan_out_sibling_branches(
46
+ parsed: Any, project_root: Path, active_branch: str,
47
+ touched_siblings: list[tuple[Path, str | None]] | None,
48
+ ) -> None:
49
+ """Create the SIBLING engage branches (CR-R7) and record them (CR-R9).
50
+
51
+ Runs after the preflight gate + parallel-same-target guard pass and before
52
+ dispatch; records each touched sibling (with its prior branch) into
53
+ ``touched_siblings`` so a later sprint failure can restore those working
54
+ trees (see ``_run_engage``). EH2.3 relocated this here (from ``engage``) so
55
+ the guard can run before it while keeping ``engage`` under the arch line cap.
56
+ """
57
+ from bpsai_pair.commands import engage_branch_multi as _branch_multi
58
+
59
+ if not active_branch:
60
+ return
61
+ touched = _branch_multi.create_cross_repo_branch(
62
+ parsed, project_root, active_branch)
63
+ if touched_siblings is not None:
64
+ touched_siblings.extend(touched)
65
+
66
+
67
+ def execute_sprint(
68
+ project_root: Path, plan_id: str, max_parallel: int,
69
+ completed_tasks: list[str] | None = None,
70
+ target_repo: Path | None = None,
71
+ per_task_target_repos: dict[str, Path] | None = None,
72
+ env_overrides: dict[str, str] | None = None,
73
+ ) -> Any:
74
+ """Build plan graph and execute tasks via headless runner.
75
+
76
+ EH1.6: ``target_repo`` (from backlog ``**Target repo:**``) sets
77
+ SprintConfig.target_repo so the no-output detector reads the
78
+ sibling repo instead of the orchestrator cwd.
79
+
80
+ PD4 (2026-05-27): ``per_task_target_repos`` carries per-task
81
+ overrides for multi-repo backlogs. Each task whose
82
+ ``ParsedTask.target_repo`` resolved cleanly contributes a
83
+ ``{task_id: Path}`` entry; the executor picks the per-task value
84
+ when present, then falls back to ``target_repo``.
85
+ """
86
+ from bpsai_pair.orchestration import (
87
+ sprint_executor, plan_graph, headless_runner,
88
+ )
89
+ from bpsai_pair.orchestration.target_repo_resolution import (
90
+ guard_parallel_same_target,
91
+ )
92
+ graph = plan_graph.PlanGraphBuilder(project_root).build(plan_id)
93
+ for tid in completed_tasks or []:
94
+ graph.mark_done(tid)
95
+ # CR-R8 (P1) + R10 Fix 3 (Codex P1): refuse a PARALLEL phase sharing one
96
+ # sibling target before dispatch, but only when effective parallelism > 1
97
+ # (``--max-parallel 1`` serializes -> safe; the executor uses min(mp, n)).
98
+ guard_parallel_same_target(
99
+ graph, per_task_target_repos, target_repo, project_root,
100
+ max_parallel=max_parallel,
101
+ )
102
+ config = sprint_executor.SprintConfig(
103
+ max_parallel=max_parallel, target_repo=target_repo,
104
+ per_task_target_repos=per_task_target_repos or {},
105
+ env_overrides=env_overrides or {},
106
+ )
107
+ task_runner = headless_runner._make_headless_runner(
108
+ project_root, permission_mode="auto",
109
+ allowed_tools=HEADLESS_ALLOWED_TOOLS, approved_by="engage-cli",
110
+ sprint_config=config,
111
+ )
112
+ task_hook = sprint_executor.make_default_task_hook(project_root)
113
+ return sprint_executor.SprintExecutor(
114
+ project_root, graph, config,
115
+ task_runner=task_runner, task_complete_hook=task_hook,
116
+ ).execute()
@@ -31,6 +31,10 @@ from bpsai_pair.commands.engage_guards import (
31
31
  from bpsai_pair.commands.engage_executor import execute_sprint as _execute_sprint
32
32
  from bpsai_pair.core.utils import repo_root
33
33
  from bpsai_pair.orchestration.backlog_parser import BacklogParser
34
+ from bpsai_pair.commands.engage_resume_integrity import (
35
+ _confine_persisted_repos,
36
+ enforce_repo_set_agreement_or_exit,
37
+ )
34
38
  from bpsai_pair.orchestration.engage_run_state import (
35
39
  load_run_state, save_pause_state, verify_paused_task_done,
36
40
  )
@@ -96,36 +100,6 @@ def handle_pause(
96
100
  return _result_dict(result, paused_task=result.paused_task, run_id=run_id)
97
101
 
98
102
 
99
- def _confine_persisted_repos(
100
- raw: dict[str, str], project_root: Path,
101
- ) -> dict[str, Path]:
102
- """Re-apply the workspace-boundary check to every persisted
103
- ``per_task_target_repos`` entry on resume.
104
-
105
- P2-Laverna on PR #348 re-review: persisted paths come from a state.json an
106
- attacker with local write access could tamper with -- a planted ``"/etc"``
107
- (outside ``project_root.parent``) would become the ``cwd`` of git
108
- subprocess calls. Drop+WARN on escapes so the run continues with the fresh
109
- backlog re-resolution rather than trusting the poisoned state.
110
- """
111
- boundary = project_root.resolve().parent
112
- cleaned: dict[str, Path] = {}
113
- for tid, raw_path in raw.items():
114
- candidate = Path(raw_path).resolve()
115
- try:
116
- candidate.relative_to(boundary)
117
- except ValueError:
118
- logger.warning(
119
- "resume: persisted target_repo for %s (%s) escapes the "
120
- "workspace boundary (%s); dropping. Will re-resolve from "
121
- "backlog if the task is still listed.",
122
- tid, raw_path, boundary,
123
- )
124
- continue
125
- cleaned[tid] = candidate
126
- return cleaned
127
-
128
-
129
103
  def _rehydrate_per_task_repos(
130
104
  state, project_root: Path,
131
105
  ) -> tuple[Path | None, dict[str, Path]]:
@@ -300,13 +274,14 @@ def resume_engage(run_id: str) -> dict[str, Any]:
300
274
  so the security scan + PR + review cover EVERY touched repo on resume.
301
275
 
302
276
  CR-followup (Codex P1, drift): the ``parsed`` driving the fan-out AND
303
- finalize is now SYNTHESIZED from the rehydrated ``per_task_repos`` map (the
304
- SAME set ``_execute_sprint`` commits to), NOT a freshly re-parsed backlog. A
305
- backlog edited between pause and resume can no longer make the
306
- branched/scanned/PR'd set diverge from the committed set -- the invariant is
307
- branched == scanned == PR'd == committed. CR-R11 Fix 1: dispatch + finalize
308
- run inside a failure guard (``_execute_and_finalize_resume``) that restores
309
- stranded siblings on a raised exception.
277
+ finalize is SYNTHESIZED from the rehydrated ``per_task_repos`` map (the SAME
278
+ set ``_execute_sprint`` commits to), NOT a freshly re-parsed backlog -- the
279
+ invariant is branched == scanned == PR'd == committed. EH2.4: that set must
280
+ also agree with a fresh re-resolution of the on-disk backlog -- divergence
281
+ (an edited backlog) refuses loudly BEFORE fan-out/dispatch. CR-R11 Fix 1:
282
+ dispatch + finalize run inside a failure guard
283
+ (``_execute_and_finalize_resume``) that restores stranded siblings on a
284
+ raised exception.
310
285
  """
311
286
  project_root = repo_root()
312
287
  state = load_run_state(project_root, run_id)
@@ -325,6 +300,11 @@ def resume_engage(run_id: str) -> dict[str, Any]:
325
300
  parsed = _branch_multi.build_parsed_from_repo_map(
326
301
  per_task_repos, project_root, target_repo_path,
327
302
  )
303
+ # EH2.4: the set dispatch/fan-out act on must agree with the on-disk
304
+ # backlog -- an edited backlog fails loud here, before any fan-out.
305
+ enforce_repo_set_agreement_or_exit(
306
+ parsed, state.backlog_path or "", project_root,
307
+ )
328
308
  touched_siblings = _fan_out_resume_siblings(
329
309
  parsed, project_root, active_branch,
330
310
  )