wade-cli 1.2.4__tar.gz → 1.2.6__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 (440) hide show
  1. {wade_cli-1.2.4 → wade_cli-1.2.6}/AGENTS.md +4 -2
  2. {wade_cli-1.2.4 → wade_cli-1.2.6}/CHANGELOG.md +12 -0
  3. {wade_cli-1.2.4 → wade_cli-1.2.6}/PKG-INFO +20 -15
  4. {wade_cli-1.2.4 → wade_cli-1.2.6}/README.md +18 -13
  5. {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/architecture.md +10 -6
  6. {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/native-cli-plan-verification.md +33 -2
  7. {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/testing.md +8 -2
  8. {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/workflows-and-skills.md +2 -2
  9. {wade_cli-1.2.4 → wade_cli-1.2.6}/pyproject.toml +2 -2
  10. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/probe_native_plan_handoff.py +4 -3
  11. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/__init__.py +1 -1
  12. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/plan_service.py +25 -1
  13. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/plan.md +1 -1
  14. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_plan_contract.py +18 -0
  15. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_plan_service.py +13 -0
  16. wade_cli-1.2.6/tests/unit/test_services/test_plan_startup_events.py +82 -0
  17. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_crossby_contract.py +17 -1
  18. {wade_cli-1.2.4 → wade_cli-1.2.6}/uv.lock +214 -5
  19. {wade_cli-1.2.4 → wade_cli-1.2.6}/.gitattributes +0 -0
  20. {wade_cli-1.2.4 → wade_cli-1.2.6}/.github/workflows/auto-version.yml +0 -0
  21. {wade_cli-1.2.4 → wade_cli-1.2.6}/.github/workflows/ci.yml +0 -0
  22. {wade_cli-1.2.4 → wade_cli-1.2.6}/.github/workflows/pr-title-lint.yml +0 -0
  23. {wade_cli-1.2.4 → wade_cli-1.2.6}/.github/workflows/publish.yml +0 -0
  24. {wade_cli-1.2.4 → wade_cli-1.2.6}/.github/workflows/release.yml +0 -0
  25. {wade_cli-1.2.4 → wade_cli-1.2.6}/.gitignore +0 -0
  26. {wade_cli-1.2.4 → wade_cli-1.2.6}/.pre-commit-config.yaml +0 -0
  27. {wade_cli-1.2.4 → wade_cli-1.2.6}/.wade.yml +0 -0
  28. {wade_cli-1.2.4 → wade_cli-1.2.6}/CONTRIBUTING.md +0 -0
  29. {wade_cli-1.2.4 → wade_cli-1.2.6}/KNOWLEDGE.md +0 -0
  30. {wade_cli-1.2.4 → wade_cli-1.2.6}/KNOWLEDGE.ratings.jsonl +0 -0
  31. {wade_cli-1.2.4 → wade_cli-1.2.6}/assets/wade.png +0 -0
  32. {wade_cli-1.2.4 → wade_cli-1.2.6}/docker-compose.e2e.yml +0 -0
  33. {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/crossby-native-planning-checkpoint.md +0 -0
  34. {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/documentation-policies.md +0 -0
  35. {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/extending.md +0 -0
  36. {wade_cli-1.2.4 → wade_cli-1.2.6}/docs/dev/skills-system.md +0 -0
  37. {wade_cli-1.2.4 → wade_cli-1.2.6}/install.sh +0 -0
  38. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/auto_version.py +0 -0
  39. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/changelog.py +0 -0
  40. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/check-all.sh +0 -0
  41. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/check.sh +0 -0
  42. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/fmt.sh +0 -0
  43. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/hooks/pre-push +0 -0
  44. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/install-hooks.sh +0 -0
  45. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/release.sh +0 -0
  46. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/setup-worktree.sh +0 -0
  47. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test-concurrency.sh +0 -0
  48. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test-e2e-docker.sh +0 -0
  49. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test-e2e.sh +0 -0
  50. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test-live-ai-taskr.sh +0 -0
  51. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test-live-ai.sh +0 -0
  52. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test-live-gh.sh +0 -0
  53. {wade_cli-1.2.4 → wade_cli-1.2.6}/scripts/test.sh +0 -0
  54. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/__main__.py +0 -0
  55. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/__init__.py +0 -0
  56. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/admin.py +0 -0
  57. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/autocomplete.py +0 -0
  58. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/deps_session.py +0 -0
  59. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/hook.py +0 -0
  60. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/implementation_session.py +0 -0
  61. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/knowledge.py +0 -0
  62. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/main.py +0 -0
  63. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/plan_session.py +0 -0
  64. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/review.py +0 -0
  65. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/review_pr_comments_session.py +0 -0
  66. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/session.py +0 -0
  67. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/session_shared.py +0 -0
  68. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/skills.py +0 -0
  69. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/task.py +0 -0
  70. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/cli/worktree.py +0 -0
  71. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/config/__init__.py +0 -0
  72. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/config/loader.py +0 -0
  73. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/config/migrations.py +0 -0
  74. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/config/schema.py +0 -0
  75. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/__init__.py +0 -0
  76. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/branch.py +0 -0
  77. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/hooks.py +0 -0
  78. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/pr.py +0 -0
  79. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/repo.py +0 -0
  80. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/stash.py +0 -0
  81. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/sync.py +0 -0
  82. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/git/worktree.py +0 -0
  83. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/hooks/__init__.py +0 -0
  84. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/hooks/cli.py +0 -0
  85. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/hooks/policies.py +0 -0
  86. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/logging/__init__.py +0 -0
  87. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/logging/context.py +0 -0
  88. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/logging/setup.py +0 -0
  89. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/__init__.py +0 -0
  90. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/batch.py +0 -0
  91. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/config.py +0 -0
  92. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/delegation.py +0 -0
  93. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/deps.py +0 -0
  94. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/events.py +0 -0
  95. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/hooks.py +0 -0
  96. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/interactive_plan.py +0 -0
  97. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/permission.py +0 -0
  98. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/plan_bundle.py +0 -0
  99. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/readiness.py +0 -0
  100. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/review.py +0 -0
  101. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/review_cycle.py +0 -0
  102. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/session.py +0 -0
  103. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/session_manifest.py +0 -0
  104. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/skill.py +0 -0
  105. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/task.py +0 -0
  106. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/workflow.py +0 -0
  107. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/models/worktree.py +0 -0
  108. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/__init__.py +0 -0
  109. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/_pr_delegate.py +0 -0
  110. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/base.py +0 -0
  111. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/clickup.py +0 -0
  112. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/github.py +0 -0
  113. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/markdown.py +0 -0
  114. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/providers/registry.py +0 -0
  115. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/__init__.py +0 -0
  116. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/ai_resolution.py +0 -0
  117. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/batch_review_service.py +0 -0
  118. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/bot_trigger.py +0 -0
  119. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/check_service.py +0 -0
  120. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/delegation_service.py +0 -0
  121. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/deps_service.py +0 -0
  122. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/documentation_receipt_service.py +0 -0
  123. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/__init__.py +0 -0
  124. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/_shared.py +0 -0
  125. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/batch.py +0 -0
  126. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/bootstrap.py +0 -0
  127. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/cleanup.py +0 -0
  128. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/core.py +0 -0
  129. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/done.py +0 -0
  130. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/draft_pr.py +0 -0
  131. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/lifecycle.py +0 -0
  132. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/sync.py +0 -0
  133. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/implementation_service/usage_tracking.py +0 -0
  134. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/__init__.py +0 -0
  135. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/auth.py +0 -0
  136. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/commands.py +0 -0
  137. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/config_io.py +0 -0
  138. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/manifest.py +0 -0
  139. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/migrations.py +0 -0
  140. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/prompts_ai.py +0 -0
  141. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/prompts_setup.py +0 -0
  142. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/init_service/shell.py +0 -0
  143. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/interactive_plan_service.py +0 -0
  144. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/knowledge_recovery.py +0 -0
  145. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/knowledge_search.py +0 -0
  146. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/knowledge_service.py +0 -0
  147. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/native_plan_service.py +0 -0
  148. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/prompt_delivery.py +0 -0
  149. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/review_cycle_service.py +0 -0
  150. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/review_delegation_service.py +0 -0
  151. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/review_record_service.py +0 -0
  152. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/review_service.py +0 -0
  153. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/review_settle.py +0 -0
  154. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/session_composition_service.py +0 -0
  155. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/skill_diagnostics_service.py +0 -0
  156. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/skill_invocation_service.py +0 -0
  157. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/smart_start.py +0 -0
  158. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/services/task_service.py +0 -0
  159. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/__init__.py +0 -0
  160. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/catalog.py +0 -0
  161. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/discovery.py +0 -0
  162. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/doc_targets.py +0 -0
  163. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/installer.py +0 -0
  164. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/materializer.py +0 -0
  165. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/pointer.py +0 -0
  166. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/resolver.py +0 -0
  167. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/skills/validation.py +0 -0
  168. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/ui/__init__.py +0 -0
  169. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/ui/console.py +0 -0
  170. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/ui/prompts.py +0 -0
  171. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/__init__.py +0 -0
  172. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/body_markers.py +0 -0
  173. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/clipboard.py +0 -0
  174. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/conventional.py +0 -0
  175. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/filelock.py +0 -0
  176. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/gitref.py +0 -0
  177. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/http.py +0 -0
  178. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/install.py +0 -0
  179. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/knowledge_file.py +0 -0
  180. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/markdown.py +0 -0
  181. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/markers.py +0 -0
  182. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/paths.py +0 -0
  183. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/plan_validation.py +0 -0
  184. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/process.py +0 -0
  185. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/runtime_env.py +0 -0
  186. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/safe_state.py +0 -0
  187. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/slug.py +0 -0
  188. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/stale_base.py +0 -0
  189. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/templates.py +0 -0
  190. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/terminal.py +0 -0
  191. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/token_usage_markdown.py +0 -0
  192. {wade_cli-1.2.4 → wade_cli-1.2.6}/src/wade/utils/update_check.py +0 -0
  193. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/agents-pointer.md +0 -0
  194. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/hooks/commit-msg +0 -0
  195. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/hooks/pre-commit +0 -0
  196. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/hooks/pre-push +0 -0
  197. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/deps-analysis.md +0 -0
  198. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/implement-context.md +0 -0
  199. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/plan-session.md +0 -0
  200. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-batch.md +0 -0
  201. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-code.md +0 -0
  202. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-finding-admission.md +0 -0
  203. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-plan.md +0 -0
  204. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-pr-comments.md +0 -0
  205. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-batch.md +0 -0
  206. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-code.md +0 -0
  207. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-deps.md +0 -0
  208. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-full-branch.md +0 -0
  209. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-implementation.md +0 -0
  210. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-plan.md +0 -0
  211. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/review-result-pr-comments.md +0 -0
  212. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/session-start-implement.md +0 -0
  213. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/session-start-plan.md +0 -0
  214. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/prompts/session-start-review.md +0 -0
  215. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/setup-worktree.sh.example +0 -0
  216. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/batch-review/SKILL.md +0 -0
  217. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/code-review/SKILL.md +0 -0
  218. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/dependency-analysis/SKILL.md +0 -0
  219. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/feedback-fix-review/SKILL.md +0 -0
  220. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/implementation/SKILL.md +0 -0
  221. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/knowledge/SKILL.md +0 -0
  222. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/plan-review/SKILL.md +0 -0
  223. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/planning/SKILL.md +0 -0
  224. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/review-comments/SKILL.md +0 -0
  225. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/task/SKILL.md +0 -0
  226. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/task/examples.md +0 -0
  227. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/task/plan-format.md +0 -0
  228. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/skills/task/reference/session-summary-format.md +0 -0
  229. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/statusline-command.sh +0 -0
  230. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/_partials/completion.md +0 -0
  231. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/_partials/documentation-step.md +0 -0
  232. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/_partials/interaction-policy.md +0 -0
  233. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/_partials/knowledge-step.md +0 -0
  234. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/_partials/review-budget.md +0 -0
  235. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/implementation.md +0 -0
  236. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/documentation.md +0 -0
  237. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/new-plan.md +0 -0
  238. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/plan-output-contract.md +0 -0
  239. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/pr-summary-format.md +0 -0
  240. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/recovery.md +0 -0
  241. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/session-summary-format.md +0 -0
  242. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/reference/tracking-issues.md +0 -0
  243. {wade_cli-1.2.4 → wade_cli-1.2.6}/templates/workflows/review-pr-comments.md +0 -0
  244. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/__init__.py +0 -0
  245. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/concurrency/__init__.py +0 -0
  246. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/concurrency/test_batch_multi_pr.py +0 -0
  247. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/concurrency/test_knowledge_merge.py +0 -0
  248. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/concurrency/test_lock_retry.py +0 -0
  249. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/concurrency/test_stash_race.py +0 -0
  250. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/conftest.py +0 -0
  251. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/__init__.py +0 -0
  252. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/_support.py +0 -0
  253. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/conftest.py +0 -0
  254. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/mock_gh_script.py +0 -0
  255. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_admin_contract.py +0 -0
  256. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_check_contract.py +0 -0
  257. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_implement_work_done_contract.py +0 -0
  258. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_knowledge_contract.py +0 -0
  259. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_mock_gh_contract.py +0 -0
  260. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_review_contract.py +0 -0
  261. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_smart_start_contract.py +0 -0
  262. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_task_contract.py +0 -0
  263. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/e2e/test_work_sync_list_contract.py +0 -0
  264. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/fixtures/live/taskr_header_hi_body.md +0 -0
  265. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/fixtures/live/taskr_header_howdy_body.md +0 -0
  266. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/fixtures/transcripts/claude_session.txt +0 -0
  267. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/fixtures/transcripts/codex_session.txt +0 -0
  268. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/fixtures/transcripts/copilot_session.txt +0 -0
  269. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/fixtures/transcripts/generic_session.txt +0 -0
  270. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/__init__.py +0 -0
  271. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_autostash.py +0 -0
  272. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_check.py +0 -0
  273. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_dynamic_skill_sessions.py +0 -0
  274. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_git.py +0 -0
  275. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_implementation_lifecycle.py +0 -0
  276. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_init.py +0 -0
  277. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_knowledge.py +0 -0
  278. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_markdown_provider.py +0 -0
  279. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_skill_context_budget.py +0 -0
  280. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/integration/test_skill_install.py +0 -0
  281. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/live/__init__.py +0 -0
  282. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/live/test_wade_live_ai.py +0 -0
  283. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/live/test_wade_live_ai_taskr.py +0 -0
  284. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/live/test_wade_live_gh.py +0 -0
  285. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/test_cli_basics.py +0 -0
  286. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/__init__.py +0 -0
  287. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/conftest.py +0 -0
  288. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/__init__.py +0 -0
  289. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_autocomplete.py +0 -0
  290. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_done_doc_pass_advisory.py +0 -0
  291. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_done_review_hint.py +0 -0
  292. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_knowledge_cli.py +0 -0
  293. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_review_cli.py +0 -0
  294. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_session_subapps.py +0 -0
  295. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_shell_init.py +0 -0
  296. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_skills_session_cli.py +0 -0
  297. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_task_cli.py +0 -0
  298. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_work_ai_flags.py +0 -0
  299. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_cli/test_work_cli.py +0 -0
  300. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/__init__.py +0 -0
  301. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/test_bot_review_config.py +0 -0
  302. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/test_dynamic_skill_config.py +0 -0
  303. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/test_loader.py +0 -0
  304. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/test_merge_strategy_migration.py +0 -0
  305. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/test_migrations.py +0 -0
  306. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_config/test_migrations_atomic.py +0 -0
  307. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_console.py +0 -0
  308. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_effort.py +0 -0
  309. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/__init__.py +0 -0
  310. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_all_patches_present.py +0 -0
  311. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_branch_list.py +0 -0
  312. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_branch_slugify.py +0 -0
  313. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_detached_worktree.py +0 -0
  314. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_is_merged_into.py +0 -0
  315. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_main_checkout_root.py +0 -0
  316. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_merge_count.py +0 -0
  317. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_pr_base.py +0 -0
  318. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_pr_lookup.py +0 -0
  319. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_pr_retry.py +0 -0
  320. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_pr_title.py +0 -0
  321. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_repo.py +0 -0
  322. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_reset_branch.py +0 -0
  323. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_scaffold_commit.py +0 -0
  324. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_stash_drop.py +0 -0
  325. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_sync_conflicted_files.py +0 -0
  326. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_tip_commit_is_empty.py +0 -0
  327. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_git/test_worktree_remove.py +0 -0
  328. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_hooks/__init__.py +0 -0
  329. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_hooks/test_hook_cli.py +0 -0
  330. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_hooks/test_policies.py +0 -0
  331. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_hooks/test_post_tool_use.py +0 -0
  332. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_hooks/test_session_start.py +0 -0
  333. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/__init__.py +0 -0
  334. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_batch.py +0 -0
  335. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_config_models.py +0 -0
  336. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_delegation.py +0 -0
  337. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_deps_models.py +0 -0
  338. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_deps_partition.py +0 -0
  339. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_review.py +0 -0
  340. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_review_expectation.py +0 -0
  341. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_task_models.py +0 -0
  342. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_models/test_workflow_models.py +0 -0
  343. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_permission_mode.py +0 -0
  344. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_providers/__init__.py +0 -0
  345. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_providers/test_clickup.py +0 -0
  346. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_providers/test_github.py +0 -0
  347. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_providers/test_github_pr.py +0 -0
  348. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_providers/test_markdown.py +0 -0
  349. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_scripts/__init__.py +0 -0
  350. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_scripts/test_changelog.py +0 -0
  351. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/__init__.py +0 -0
  352. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_ai_resolution.py +0 -0
  353. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_batch_build_cmd.py +0 -0
  354. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_batch_pr_index.py +0 -0
  355. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_batch_review_service.py +0 -0
  356. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bootstrap_allowlist.py +0 -0
  357. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bootstrap_guard_matcher.py +0 -0
  358. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bootstrap_hook_timeout.py +0 -0
  359. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bootstrap_post_tool_use.py +0 -0
  360. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bootstrap_pre_push.py +0 -0
  361. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bootstrap_session_start.py +0 -0
  362. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_bot_trigger.py +0 -0
  363. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_catchup.py +0 -0
  364. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_catchup_reconcile.py +0 -0
  365. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_check.py +0 -0
  366. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_cleanup_loss_guard.py +0 -0
  367. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_codex_worktree_launch_context.py +0 -0
  368. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_delegation_service.py +0 -0
  369. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_deps_service.py +0 -0
  370. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_documentation_receipt.py +0 -0
  371. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_done_gates.py +0 -0
  372. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_done_idempotent.py +0 -0
  373. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_done_plan_flag.py +0 -0
  374. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_done_pr_title_sync.py +0 -0
  375. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_draft_pr_base_fetch.py +0 -0
  376. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_draft_pr_retarget.py +0 -0
  377. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_implementation_done_sync.py +0 -0
  378. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_implementation_launch_context.py +0 -0
  379. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_implementation_service.py +0 -0
  380. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_implementation_service_resume.py +0 -0
  381. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_init.py +0 -0
  382. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_init_shell_integration.py +0 -0
  383. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_interactive_plan_service.py +0 -0
  384. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_knowledge_recovery.py +0 -0
  385. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_knowledge_search.py +0 -0
  386. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_knowledge_service.py +0 -0
  387. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_managed_git_hooks.py +0 -0
  388. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_native_plan_service.py +0 -0
  389. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_no_direct_git.py +0 -0
  390. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_poll_for_reviews.py +0 -0
  391. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_post_implementation_lifecycle.py +0 -0
  392. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_pr_lookup_guards.py +0 -0
  393. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_pr_summary_path.py +0 -0
  394. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_pre_push_backstop.py +0 -0
  395. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_preserve_session_data.py +0 -0
  396. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_prompt_delivery.py +0 -0
  397. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_push_recovery.py +0 -0
  398. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_resolve_task_branch.py +0 -0
  399. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_resume_autonomy.py +0 -0
  400. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_review_cycle_service.py +0 -0
  401. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_review_delegation_service.py +0 -0
  402. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_review_receipts.py +0 -0
  403. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_review_records.py +0 -0
  404. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_review_service.py +0 -0
  405. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_review_status_block.py +0 -0
  406. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_skill_diagnostics_service.py +0 -0
  407. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_skill_invocation_service.py +0 -0
  408. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_smart_start.py +0 -0
  409. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_smart_start_resume.py +0 -0
  410. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_stale_base_surface.py +0 -0
  411. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_sync_base_branch.py +0 -0
  412. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_task_service.py +0 -0
  413. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_tracked_managed_files.py +0 -0
  414. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_services/test_worktree_gitignore.py +0 -0
  415. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_doc_targets.py +0 -0
  416. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_dynamic_skills.py +0 -0
  417. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_generic_builtin_boundaries.py +0 -0
  418. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_knowledge_attributes.py +0 -0
  419. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_managed_gitignore.py +0 -0
  420. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_pointer.py +0 -0
  421. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_skills/test_review_budget_partial.py +0 -0
  422. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/__init__.py +0 -0
  423. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_body_markers.py +0 -0
  424. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_conventional.py +0 -0
  425. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_filelock.py +0 -0
  426. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_gitref.py +0 -0
  427. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_http.py +0 -0
  428. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_install.py +0 -0
  429. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_markdown.py +0 -0
  430. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_markers.py +0 -0
  431. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_plan_validation.py +0 -0
  432. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_process.py +0 -0
  433. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_prompts.py +0 -0
  434. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_runtime_env.py +0 -0
  435. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_slug.py +0 -0
  436. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_stale_base.py +0 -0
  437. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_terminal.py +0 -0
  438. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_terminal_launch.py +0 -0
  439. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_utils/test_update_check.py +0 -0
  440. {wade_cli-1.2.4 → wade_cli-1.2.6}/tests/unit/test_yolo.py +0 -0
@@ -93,8 +93,10 @@ No circular dependencies. Models are pure data. Services orchestrate. **Never im
93
93
  AI tool adapters are not part of this repo — they live in the external [`crossby`](https://github.com/ivanviragine/crossby) package (`pyproject.toml`). See `docs/dev/architecture.md` for what moved there.
94
94
 
95
95
  Native planning prefers Crossby's ordinary interactive launch with native Plan
96
- mode and supported approval flags. Tools without terminal Plan support (Codex)
97
- retain the public collected-session/preflight API. WADE owns explicit file/stdin
96
+ mode and supported approval flags. For deferred startup (currently Codex), WADE
97
+ handles Crossby's typed ready/submitted events and sends the task exactly once;
98
+ Crossby owns `/plan` and terminal mechanics. The public collected-session API
99
+ remains the fallback for adapters without terminal Plan support. WADE owns explicit file/stdin
98
100
  handoff, review receipts bound to current content and frozen skills, validation,
99
101
  knowledge handoff, and task persistence; native flags/protocols stay upstream.
100
102
  Update the tracked `uv.lock` and Crossby contract tripwire with dependency
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Conventional Commits](https://conventionalcommits.org/).
6
6
 
7
+ ## [v1.2.6] — 2026-09-23
8
+
9
+ ### Chores
10
+
11
+ - adopt Crossby 0.36 model catalogs and defaults (#517) (cc9ae47)
12
+
13
+ ## [v1.2.5] — 2026-09-16
14
+
15
+ ### Bug Fixes
16
+
17
+ - launch Codex native UI with deferred prompt delivery (#514) (8424a77)
18
+
7
19
  ## [v1.2.4] — 2026-09-16
8
20
 
9
21
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: wade-cli
3
- Version: 1.2.4
3
+ Version: 1.2.6
4
4
  Summary: WADE — Workflow for AI-Driven Engineering
5
5
  Project-URL: Homepage, https://github.com/ivanviragine/wade
6
6
  Project-URL: Repository, https://github.com/ivanviragine/wade
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.12
16
16
  Classifier: Programming Language :: Python :: 3.13
17
17
  Classifier: Topic :: Software Development :: Version Control :: Git
18
18
  Requires-Python: >=3.11
19
- Requires-Dist: crossby<0.33.0,>=0.32.1
19
+ Requires-Dist: crossby<0.37.0,>=0.36.0
20
20
  Requires-Dist: httpx<1.0,>=0.27
21
21
  Requires-Dist: pydantic-settings>=2.0
22
22
  Requires-Dist: pydantic>=2.0
@@ -280,11 +280,12 @@ Most workflow commands accept `--ai <tool>`, `--model <model>`, `--effort <level
280
280
 
281
281
  ## Planning & base branches
282
282
 
283
- `wade plan` launches **Claude, Cursor, Copilot, OpenCode, and Antigravity CLI**
283
+ `wade plan` launches **Claude, Cursor, Copilot, OpenCode, Antigravity CLI, and Codex**
284
284
  in their own interactive terminal, with **native Plan mode active before the
285
285
  first task turn**. You keep the tool's UI, questions, and conversation. Crossby
286
- validates native support and translates approval flags; WADE does not type
287
- `/plan`, switch to an editing session, or replace the tool's questions.
286
+ validates native support and translates approval flags. For Codex, Crossby
287
+ submits `/plan` first and WADE sends the task on its ready event. Native questions
288
+ and subsequent interaction stay in the tool.
288
289
 
289
290
  Use `--permission-mode` (or `--yolo`) for the native approval policy:
290
291
 
@@ -295,6 +296,7 @@ Use `--permission-mode` (or `--yolo`) for the native approval policy:
295
296
  | Copilot | `default`, `accept-edits`, `yolo` |
296
297
  | OpenCode | `default`, `yolo` |
297
298
  | Antigravity CLI | `default`, `yolo` |
299
+ | Codex CLI | `default`, `accept-edits`, `auto`, `yolo` |
298
300
 
299
301
  Unsupported combinations fail before creating a planning worktree. These are
300
302
  native approval settings, not permission to implement the plan. The later
@@ -319,20 +321,23 @@ including an explicit empty list when appropriate. The parent revalidates the
319
321
  completed handoff after exit, then creates tasks and draft PRs. Failed or missing
320
322
  handoffs retain output and create no tasks.
321
323
 
322
- **Codex keeps the collected-session path** for now: Crossby collects its native
323
- plan artifact and questions, then WADE runs review and validation in the parent.
324
- Its `--yolo` affects parent confirmations only; `auto` and `accept-edits` remain
325
- unsupported. Codex's native session provenance is retained separately from the
326
- plan; no transcript or token totals are invented from plan text.
327
-
328
- Interactive terminals use the ordinary sandbox default (off); the Codex collector
329
- keeps its safe default (on). Explicit `--sandbox`, `--network-access` /
324
+ **Codex requires CLI 0.154.x and a POSIX terminal (macOS/Linux).** Crossby's
325
+ current startup adapter waits for the rendered Plan indicator before WADE sends
326
+ the initial task; unknown versions or an unrecognized startup screen fail
327
+ without retrying the task. This temporary terminal adapter can be replaced by a
328
+ native launch flag when Codex provides one. WADE requires the task-submitted
329
+ event before collecting the explicit reviewed handoff. Codex can submit plan
330
+ Markdown through `--from-stdin`; no native file destination is assumed.
331
+
332
+ All native terminals now use the ordinary sandbox default (off), including Codex;
333
+ use `--sandbox` or `ai.plan.sandbox: true` to retain confinement. The retained
334
+ collector fallback has its own safe default (on). Explicit `--sandbox`, `--network-access` /
330
335
  `--no-network-access`, and `--trusted-dir` require support from the selected tool.
331
336
  No network flag adds no network grant and does not promise isolation.
332
337
  `--approval-policy on-request|untrusted|never` and `--timeout` are collector
333
338
  settings; interactive terminals use `--permission-mode` and have no time limit.
334
- Set `ai.plan.mode` to `interactive` or leave it unset for native terminals; leave
335
- it unset for Codex. GUI launchers remain unsupported for planning.
339
+ Set `ai.plan.mode` to `interactive` or leave it unset for native terminals.
340
+ GUI launchers remain unsupported for planning.
336
341
 
337
342
  Authentication, model availability, and successful handoff are runtime checks.
338
343
  Native terminal output is retained for recovery; usage is reported only when
@@ -244,11 +244,12 @@ Most workflow commands accept `--ai <tool>`, `--model <model>`, `--effort <level
244
244
 
245
245
  ## Planning & base branches
246
246
 
247
- `wade plan` launches **Claude, Cursor, Copilot, OpenCode, and Antigravity CLI**
247
+ `wade plan` launches **Claude, Cursor, Copilot, OpenCode, Antigravity CLI, and Codex**
248
248
  in their own interactive terminal, with **native Plan mode active before the
249
249
  first task turn**. You keep the tool's UI, questions, and conversation. Crossby
250
- validates native support and translates approval flags; WADE does not type
251
- `/plan`, switch to an editing session, or replace the tool's questions.
250
+ validates native support and translates approval flags. For Codex, Crossby
251
+ submits `/plan` first and WADE sends the task on its ready event. Native questions
252
+ and subsequent interaction stay in the tool.
252
253
 
253
254
  Use `--permission-mode` (or `--yolo`) for the native approval policy:
254
255
 
@@ -259,6 +260,7 @@ Use `--permission-mode` (or `--yolo`) for the native approval policy:
259
260
  | Copilot | `default`, `accept-edits`, `yolo` |
260
261
  | OpenCode | `default`, `yolo` |
261
262
  | Antigravity CLI | `default`, `yolo` |
263
+ | Codex CLI | `default`, `accept-edits`, `auto`, `yolo` |
262
264
 
263
265
  Unsupported combinations fail before creating a planning worktree. These are
264
266
  native approval settings, not permission to implement the plan. The later
@@ -283,20 +285,23 @@ including an explicit empty list when appropriate. The parent revalidates the
283
285
  completed handoff after exit, then creates tasks and draft PRs. Failed or missing
284
286
  handoffs retain output and create no tasks.
285
287
 
286
- **Codex keeps the collected-session path** for now: Crossby collects its native
287
- plan artifact and questions, then WADE runs review and validation in the parent.
288
- Its `--yolo` affects parent confirmations only; `auto` and `accept-edits` remain
289
- unsupported. Codex's native session provenance is retained separately from the
290
- plan; no transcript or token totals are invented from plan text.
291
-
292
- Interactive terminals use the ordinary sandbox default (off); the Codex collector
293
- keeps its safe default (on). Explicit `--sandbox`, `--network-access` /
288
+ **Codex requires CLI 0.154.x and a POSIX terminal (macOS/Linux).** Crossby's
289
+ current startup adapter waits for the rendered Plan indicator before WADE sends
290
+ the initial task; unknown versions or an unrecognized startup screen fail
291
+ without retrying the task. This temporary terminal adapter can be replaced by a
292
+ native launch flag when Codex provides one. WADE requires the task-submitted
293
+ event before collecting the explicit reviewed handoff. Codex can submit plan
294
+ Markdown through `--from-stdin`; no native file destination is assumed.
295
+
296
+ All native terminals now use the ordinary sandbox default (off), including Codex;
297
+ use `--sandbox` or `ai.plan.sandbox: true` to retain confinement. The retained
298
+ collector fallback has its own safe default (on). Explicit `--sandbox`, `--network-access` /
294
299
  `--no-network-access`, and `--trusted-dir` require support from the selected tool.
295
300
  No network flag adds no network grant and does not promise isolation.
296
301
  `--approval-policy on-request|untrusted|never` and `--timeout` are collector
297
302
  settings; interactive terminals use `--permission-mode` and have no time limit.
298
- Set `ai.plan.mode` to `interactive` or leave it unset for native terminals; leave
299
- it unset for Codex. GUI launchers remain unsupported for planning.
303
+ Set `ai.plan.mode` to `interactive` or leave it unset for native terminals.
304
+ GUI launchers remain unsupported for planning.
300
305
 
301
306
  Authentication, model availability, and successful handoff are runtime checks.
302
307
  Native terminal output is retained for recovery; usage is reported only when
@@ -197,9 +197,13 @@ Adding support for a new AI tool means contributing an adapter to crossby, not t
197
197
  `plan_service.plan()` resolves the final confirmed selection before worktree or
198
198
  provider mutations. An adapter advertising `supports_plan_mode` uses ordinary
199
199
  `launch(plan_mode=True)` after `validate_plan_mode_request()`. Crossby owns
200
- native flags, version gates, and approval compatibility. WADE forwards the
200
+ native flags, version gates, and approval compatibility. For adapters declaring
201
+ `supports_ready_event`, WADE uses the public `on_event` callback: `PLAN_READY`
202
+ submits the task through `session.send_message()` exactly once and
203
+ `MESSAGE_SUBMITTED` confirms delivery before handoff collection. Crossby owns
204
+ Codex's `/plan` activation and PTY; WADE never reads screen text. WADE forwards the
201
205
  requested autonomy tier without downgrading unsupported Plan combinations.
202
- Claude, Cursor, Copilot, OpenCode, and Antigravity CLI currently use this path.
206
+ Claude, Cursor, Copilot, OpenCode, Antigravity CLI, and Codex use this path.
203
207
  Questions and the full terminal UI remain native. Explicit unsupported sandbox,
204
208
  network, trusted-directory, timeout, or transport settings fail before launch.
205
209
  The default sandbox is off, as for ordinary interactive launches.
@@ -223,7 +227,7 @@ Nonzero exits and absent/stale handoffs retain output without creating tasks.
223
227
  Native terminal output can supply adapter-parsed usage; the WADE handoff ID is
224
228
  never presented as a native CLI session ID.
225
229
 
226
- Tools without terminal Plan support, currently Codex, retain the public
230
+ Tools without terminal Plan support retain the public
227
231
  `PlanSessionRequest` → `preflight_plan_session()` → `run_plan_session()` flow.
228
232
  `native_plan_service` consumes Crossby's complete-session metadata, required
229
233
  `PlanCommandPolicy` (`wade *` plus configured patterns), and supported path policy.
@@ -1086,7 +1090,7 @@ models: # values below are crossby's claude defaults, not w
1086
1090
  easy: claude-haiku-4.5
1087
1091
  medium: claude-sonnet-5
1088
1092
  complex: claude-sonnet-5
1089
- very_complex: claude-opus-5
1093
+ very_complex: claude-opus-5.5
1090
1094
  provider:
1091
1095
  name: github
1092
1096
  hooks:
@@ -1273,9 +1277,9 @@ exactly as before #448. See knowledge `cc91cd11` for the generalized principle.
1273
1277
 
1274
1278
  The tier values `wade init` writes are **not wade constants** — `init_service/config_io.py::_resolve_models()` seeds them from `crossby.config.defaults.get_defaults(tool)`, so **bumping the crossby pin changes what newly initialized projects get**. The example above shows crossby's `claude` defaults at the currently pinned version; run `get_defaults()` for the authoritative set rather than trusting a doc snapshot, and re-check this block on every crossby bump. A bump does **not** rewrite tiers an existing `.wade.yml` already sets: `wade update` re-resolves the defaults and calls `_patch_config` without `force`, which backfills only *absent* tiers. So a fresh `wade init` picks up the new defaults wholesale, while an existing project changes only where it left a tier unset.
1275
1279
 
1276
- **Per-command AI tool and model overrides**: The `ai` section supports `plan`, `deps`, `implement`, `review_plan`, `review_implementation`, `review_batch`, and `review_pr_comments` sub-sections (`AI_COMMAND_NAMES` in `models/config.py`), with optional `tool`, `model`, `mode`, `effort`, `enabled`, `yolo`, `permission_mode`, `sandbox`, and `timeout` keys as applicable. `sandbox` (global `ai.sandbox` or per-command) is the cross-tool AI-runtime sandbox profile resolved by `resolve_sandbox()`: CLI `--sandbox`/`--no-sandbox` > per-command > global > **`False` (unrestricted)** for ordinary launches. Native terminal planning uses that same default; Codex collection keeps its safe posture. Both preserve explicit sandbox requirements. Network access is unconditionally on for ordinary non-plan launches; planning exposes an independent default-off request — see the "AI runtime sandbox profile" section above. `timeout` bounds a headless subprocess (seconds). When **unset**, the review/deps services compute the budget with `effective_timeout` (`delegation_service.py`, #366): it scales from **payload bytes + reasoning effort** — `scaled_timeout` starts at a **600s floor** (`TIMEOUT_FLOOR`, covers CLI cold-start + a small high-effort run), adds ~0.0075 s/byte of prompt, multiplies high/xhigh/max effort by 1.5–1.75×, and clamps to a **1500s ceiling** (`TIMEOUT_CEILING`). A headless timeout is **not** discarded: `run` (`utils/process.py`) decodes and reattaches the partial stdout (bytes even under `text=True`), `_delegate_headless` returns it as `feedback` with `DelegationResult.timed_out=True`, and wade **retries once** at a longer budget (`extended_timeout`, 1.5×) — bounding the *sum* of both legs to `TOTAL_TIMEOUT_CAP` (`TIMEOUT_CEILING + TIMEOUT_CEILING * TIMEOUT_RETRY_MULTIPLIER`, ~3750s / 62.5 min) so the worst case is predictable while the retry always gets the full multiplier, never a shorter budget than the attempt that just timed out (#366 review). The pre-launch advisory — now also printed by `deps_service.analyze_deps` before a headless run, not just the review commands (#366 review) — announces that worst-case total. A crash (`CommandError` / non-zero exit) is never retried and never flagged `timed_out`. Setting `ai.<cmd>.timeout` **explicitly** is a deliberate override: it is honored verbatim and **bypasses scaling and the retry math** — the escape hatch for orchestrators with a hard tool-timeout (set it below the harness limit). The fallback chain (tool/model) is: CLI `--ai`/`--model` flag -> command-specific config -> global `default_tool`. This is implemented in `ProjectConfig.get_ai_tool(command)` and `ProjectConfig.get_model(command)`. When `mode` is omitted, `review_plan` and `review_implementation` default to `prompt`, while `review_batch` defaults to `interactive`. `review_pr_comments` (#389) governs the **auto-launched review session** (post-`done` "Wait for reviews" → comments land → `review_service.start`): it resolves that session's tool, model, effort, and autonomy tier under its own key rather than inheriting `ai.implement.*`. The inherited implementation-session `tool` / `model` / `permission_mode` are honored only when the user set them *explicitly* (`--ai` / `--model` / `--permission-mode` / `--yolo`); the implementation flow forwards its already-*resolved* concrete values (never `None`), which would otherwise short-circuit the resolvers and shadow `ai.review_pr_comments` — so a merely config/default-derived value is dropped and the review config (then global `ai.*`) governs.
1280
+ **Per-command AI tool and model overrides**: The `ai` section supports `plan`, `deps`, `implement`, `review_plan`, `review_implementation`, `review_batch`, and `review_pr_comments` sub-sections (`AI_COMMAND_NAMES` in `models/config.py`), with optional `tool`, `model`, `mode`, `effort`, `enabled`, `yolo`, `permission_mode`, `sandbox`, and `timeout` keys as applicable. `sandbox` (global `ai.sandbox` or per-command) is the cross-tool AI-runtime sandbox profile resolved by `resolve_sandbox()`: CLI `--sandbox`/`--no-sandbox` > per-command > global > **`False` (unrestricted)** for ordinary launches. Native terminal planning uses that same default; the collector fallback keeps its safe posture. Both preserve explicit sandbox requirements. Network access is unconditionally on for ordinary non-plan launches; planning exposes an independent default-off request — see the "AI runtime sandbox profile" section above. `timeout` bounds a headless subprocess (seconds). When **unset**, the review/deps services compute the budget with `effective_timeout` (`delegation_service.py`, #366): it scales from **payload bytes + reasoning effort** — `scaled_timeout` starts at a **600s floor** (`TIMEOUT_FLOOR`, covers CLI cold-start + a small high-effort run), adds ~0.0075 s/byte of prompt, multiplies high/xhigh/max effort by 1.5–1.75×, and clamps to a **1500s ceiling** (`TIMEOUT_CEILING`). A headless timeout is **not** discarded: `run` (`utils/process.py`) decodes and reattaches the partial stdout (bytes even under `text=True`), `_delegate_headless` returns it as `feedback` with `DelegationResult.timed_out=True`, and wade **retries once** at a longer budget (`extended_timeout`, 1.5×) — bounding the *sum* of both legs to `TOTAL_TIMEOUT_CAP` (`TIMEOUT_CEILING + TIMEOUT_CEILING * TIMEOUT_RETRY_MULTIPLIER`, ~3750s / 62.5 min) so the worst case is predictable while the retry always gets the full multiplier, never a shorter budget than the attempt that just timed out (#366 review). The pre-launch advisory — now also printed by `deps_service.analyze_deps` before a headless run, not just the review commands (#366 review) — announces that worst-case total. A crash (`CommandError` / non-zero exit) is never retried and never flagged `timed_out`. Setting `ai.<cmd>.timeout` **explicitly** is a deliberate override: it is honored verbatim and **bypasses scaling and the retry math** — the escape hatch for orchestrators with a hard tool-timeout (set it below the harness limit). The fallback chain (tool/model) is: CLI `--ai`/`--model` flag -> command-specific config -> global `default_tool`. This is implemented in `ProjectConfig.get_ai_tool(command)` and `ProjectConfig.get_model(command)`. When `mode` is omitted, `review_plan` and `review_implementation` default to `prompt`, while `review_batch` defaults to `interactive`. `review_pr_comments` (#389) governs the **auto-launched review session** (post-`done` "Wait for reviews" → comments land → `review_service.start`): it resolves that session's tool, model, effort, and autonomy tier under its own key rather than inheriting `ai.implement.*`. The inherited implementation-session `tool` / `model` / `permission_mode` are honored only when the user set them *explicitly* (`--ai` / `--model` / `--permission-mode` / `--yolo`); the implementation flow forwards its already-*resolved* concrete values (never `None`), which would otherwise short-circuit the resolvers and shadow `ai.review_pr_comments` — so a merely config/default-derived value is dropped and the review config (then global `ai.*`) governs.
1277
1281
 
1278
- **Permission (autonomy) mode vs. delegation `mode` — two orthogonal axes**: The `mode` key (`DelegationMode`: `prompt`/`interactive`/`headless`, `models/delegation.py`) governs *how* a tool is dispatched. `permission_mode` (`PermissionMode`: `default`/`accept-edits`/`auto`/`yolo`, `models/permission.py`) governs *how much* the tool may do without prompting — the autonomy axis crossby exposes via the `yolo`/`auto`/`accept_edits` launch booleans. Do **not** conflate them: they live in separate modules on purpose. Resolution (`resolve_permission_mode()` in `ai_resolution.py`) follows CLI `--permission-mode` > `--yolo` alias > command config > global config > `default`; `permission_mode` wins over the legacy `yolo` alias at any level, and `get_yolo()`/`resolve_yolo()` are thin shims that derive from the resolved mode so the alias has a single source of truth. WADE forwards only the *requested* tier and does **not** gate on per-tool capability — crossby owns capability-aware downgrades and warnings (`_autonomy_launch_args`), so `auto` on a tool without native auto support can downgrade to `accept-edits` instead of WADE silently disabling it. The headless delegation path always forces `default` (no autonomy grant) regardless of config, since `deps`/`review_plan`/`review_implementation`/`review_batch` are read/analytical; `review_pr_comments` is the exception — it launches an *interactive* session and honors its configured `ai.review_pr_comments.permission_mode`. Native terminal planning forwards the requested tier through Crossby's Plan-mode validator and ordinary launch; unsupported combinations fail instead of downgrading. Codex retains `run_plan_session`, with parent-only `default`/`yolo` and separate native approval policy. Ordinary invalid autonomy configuration warns and falls back to `default`. Every ordinary launch command (`implement`, `implement-batch`, `review pr-comments`, `review plan`/`implementation`/`batch`, `task deps`, and the delegation paths) exposes `--yolo`/`--permission-mode` and resolves + forwards the tier; `confirm_ai_selection()` (`ai_resolution.py`) **always displays** the resolved tool/model/effort/permission mode with a per-tier descriptor (`permission.describe_permission_mode`) before its skip guard, so the mode surfaces on every path (TTY, non-TTY, headless, all-flags-explicit) and what is shown always equals what is applied. For the read-only headless paths (`deps`/`review_*` in headless mode), the service computes the *effective* mode as `default` and uses that single value for both display and the `DelegationRequest`, mirroring the `delegation_service` headless force-default rule. In addition, a completed non-zero headless exit preserves trimmed stdout and appends a clearly labeled stderr tail (the final 20 non-empty lines, capped at 4,000 characters, with truncation labeled); only failures with neither stream retain the generic no-output fallback.
1282
+ **Permission (autonomy) mode vs. delegation `mode` — two orthogonal axes**: The `mode` key (`DelegationMode`: `prompt`/`interactive`/`headless`, `models/delegation.py`) governs *how* a tool is dispatched. `permission_mode` (`PermissionMode`: `default`/`accept-edits`/`auto`/`yolo`, `models/permission.py`) governs *how much* the tool may do without prompting — the autonomy axis crossby exposes via the `yolo`/`auto`/`accept_edits` launch booleans. Do **not** conflate them: they live in separate modules on purpose. Resolution (`resolve_permission_mode()` in `ai_resolution.py`) follows CLI `--permission-mode` > `--yolo` alias > command config > global config > `default`; `permission_mode` wins over the legacy `yolo` alias at any level, and `get_yolo()`/`resolve_yolo()` are thin shims that derive from the resolved mode so the alias has a single source of truth. WADE forwards only the *requested* tier and does **not** gate on per-tool capability — crossby owns capability-aware downgrades and warnings (`_autonomy_launch_args`), so `auto` on a tool without native auto support can downgrade to `accept-edits` instead of WADE silently disabling it. The headless delegation path always forces `default` (no autonomy grant) regardless of config, since `deps`/`review_plan`/`review_implementation`/`review_batch` are read/analytical; `review_pr_comments` is the exception — it launches an *interactive* session and honors its configured `ai.review_pr_comments.permission_mode`. Native terminal planning forwards the requested tier through Crossby's Plan-mode validator and ordinary launch; unsupported combinations fail instead of downgrading. Codex uses native terminal startup events and supports all four approval tiers. The retained collector fallback uses parent-only `default`/`yolo` and a separate native approval policy. Ordinary invalid autonomy configuration warns and falls back to `default`. Every ordinary launch command (`implement`, `implement-batch`, `review pr-comments`, `review plan`/`implementation`/`batch`, `task deps`, and the delegation paths) exposes `--yolo`/`--permission-mode` and resolves + forwards the tier; `confirm_ai_selection()` (`ai_resolution.py`) **always displays** the resolved tool/model/effort/permission mode with a per-tier descriptor (`permission.describe_permission_mode`) before its skip guard, so the mode surfaces on every path (TTY, non-TTY, headless, all-flags-explicit) and what is shown always equals what is applied. For the read-only headless paths (`deps`/`review_*` in headless mode), the service computes the *effective* mode as `default` and uses that single value for both display and the `DelegationRequest`, mirroring the `delegation_service` headless force-default rule. In addition, a completed non-zero headless exit preserves trimmed stdout and appends a clearly labeled stderr tail (the final 20 non-empty lines, capped at 4,000 characters, with truncation labeled); only failures with neither stream retain the generic no-output fallback.
1279
1283
 
1280
1284
  **Worktree hooks**: The `hooks` section lets projects run setup automatically when a worktree is created. `post_worktree_create` points to a script that runs in the new worktree (e.g., installing dependencies). `copy_to_worktree` lists files to copy from the project root into the worktree before the hook runs (e.g., `.env`). Hook failures are non-fatal — a warning is logged and the session continues.
1281
1285
 
@@ -2,7 +2,9 @@
2
2
 
3
3
  Verified on 2026-09-16 with the published Crossby 0.32.1 wheel. Upstream approval
4
4
  support shipped in [Crossby PR #181](https://github.com/ivanviragine/crossby/pull/181).
5
- Codex remains on its existing collected-session path.
5
+ Codex terminal support subsequently shipped in Crossby 0.33.0 via
6
+ [PR #183](https://github.com/ivanviragine/crossby/pull/183); its WADE verification
7
+ is described below.
6
8
 
7
9
  ## Live WADE handoff
8
10
 
@@ -19,6 +21,7 @@ or PRs. Every successful run retained the original greeting source unchanged.
19
21
  | Cursor 2026.09.10-fd3934a | Passed | Native plan file, import, self-review/ack, completion in fallback workspace |
20
22
  | OpenCode 1.18.29 | Passed | Native Plan session, explicit handoff, self-review/ack, completion in fallback workspace |
21
23
  | Antigravity CLI 1.2.3 | Passed | Native artifact file, import, self-review/ack, completion; fallback and real detached worktree with bootstrap/guards |
24
+ | Codex CLI 0.154.0 | Reviewed handoff verified | Published Crossby 0.33.0; ready-event prompt delivery; sandboxed detached worktree; native questions; stdin import, self-review/ack, completion |
22
25
  | Copilot | Authenticated run omitted | Explicit user request after earlier credential failure; published adapter and WADE launch contracts remain tested |
23
26
 
24
27
  Claude's native `plansDirectory` setting selects `.wade/plans/native/`. Cursor
@@ -46,7 +49,7 @@ used ordinary approvals, not unrestricted YOLO.
46
49
  later focused regressions cover native policy rejection and incomplete-output
47
50
  preservation as well.
48
51
  - Explicit host deterministic E2E lane: 109 passed, including the real completion
49
- command invoked by a fake native CLI and the unchanged Codex app-server lane.
52
+ command invoked by a fake native CLI and the explicit collector-compatibility lane.
50
53
  - Fresh review fixed stale receipts after failed reviews, unsafe managed review
51
54
  sources, missing knowledge handoff at completion, native artifact containment,
52
55
  selected-tool bootstrap, and preservation before the first successful import.
@@ -54,3 +57,31 @@ used ordinary approvals, not unrestricted YOLO.
54
57
  Use `--worktree` on the probe for real bootstrap/guards. Keep CLI authentication
55
58
  local and distinguish native startup, completed authenticated handoff, and
56
59
  provider persistence; the live probe intentionally does not exercise the last.
60
+
61
+
62
+ ## Codex deferred startup and stdin handoff
63
+
64
+ The Codex probe uses `--sandbox --worktree --model gpt-5.6-sol` and ordinary
65
+ native approvals. Crossby alone submits `/plan`; WADE receives `PLAN_READY`,
66
+ sends the rendered workflow prompt once, and requires `MESSAGE_SUBMITTED` before
67
+ accepting the handoff. User questions appear in the native Codex UI.
68
+
69
+ Codex ran readiness, inspected `greeting.py`, obtained native confirmation,
70
+ and piped its plan to `wade plan-session done --from-stdin`. WADE wrote `PLAN.md`
71
+ and rejected completion until review. Codex then ran `wade review plan`, read
72
+ and performed the frozen review method, acknowledged it with
73
+ `--ack-self-review`, and completed `done` while remaining in native Plan mode.
74
+ The parent returned `PASS: received 1 completed, reviewed plan(s)` after normal
75
+ Codex exit. Native session `01a0a7fa-90e6-7450-9a87-c0f12145da32` recorded Plan
76
+ mode throughout and one task message (Codex trims its final newline). The
77
+ completed receipt and exact plan content are checked again by the parent.
78
+ No issues or PRs are created by this probe; the greeting remains unchanged.
79
+
80
+ Published Crossby 0.33.0 wheel contracts: 374 passed, including the terminal PTY
81
+ suite, approval combinations, and collector regressions. WADE startup tests
82
+ reject absent, duplicate, mismatched, and out-of-order events. The older fake
83
+ app-server E2E lane now explicitly selects its collector capability, so it does
84
+ not claim to represent production Codex's new terminal path.
85
+
86
+ WADE adoption checklist: 4,408 tests passed, with lint, formatting, and strict
87
+ types passing. The live probe returned one completed reviewed plan after exit.
@@ -121,7 +121,9 @@ credentials, or binaries are missing.
121
121
  Use real public Crossby request/result models in consumer tests, not mocks that
122
122
  invent fields. `tests/e2e/test_plan_contract.py` uses a deterministic fake Codex
123
123
  app-server with the **published collector** and real WADE CLI/provider handoff;
124
- this is protocol-contract evidence, not genuine model inference.
124
+ the fixture explicitly selects its collector capability now that production
125
+ Codex prefers the terminal. This is protocol-contract evidence, not genuine
126
+ model inference.
125
127
 
126
128
  For dependency adoption, also run the release's own focused native suites from
127
129
  a disposable checkout of its release tag. Install the published wheel in an
@@ -159,8 +161,11 @@ versions, completed live runs, and their limits.
159
161
 
160
162
  `test_interactive_plan_service.py` exercises explicit import, review receipts,
161
163
  self-review acknowledgement, revisions, safe file handling, and completion.
162
- `test_plan_service.py` runs the published adapter builders for all five native
164
+ `test_plan_service.py` runs the published adapter builders for the five flag-based native
163
165
  terminals and asserts the Plan selector reaches the real launch boundary.
166
+ `test_plan_startup_events.py` verifies Codex deferred prompt delivery and rejects
167
+ missing, duplicate, mismatched, or out-of-order startup events. Crossby's nested
168
+ PTY suite covers the terminal mechanics against the published wheel.
164
169
  The E2E plan contract also launches a fake OpenCode executable that invokes the
165
170
  real `wade plan-session done` command and persists through the fake provider.
166
171
 
@@ -171,6 +176,7 @@ uv run python scripts/probe_native_plan_handoff.py --tool claude
171
176
  uv run python scripts/probe_native_plan_handoff.py --tool cursor --model auto
172
177
  uv run python scripts/probe_native_plan_handoff.py --tool opencode
173
178
  uv run python scripts/probe_native_plan_handoff.py --tool antigravity-cli
179
+ uv run python scripts/probe_native_plan_handoff.py --tool codex --sandbox --worktree --model gpt-5.6-sol
174
180
  ```
175
181
 
176
182
  The probe uses ordinary native approvals, real workflow/review commands, and no
@@ -73,7 +73,7 @@ WADE's canonical copies with `review plan`, and finishes the validated handoff
73
73
  before exit. Review receipts bind to exact content, the frozen bundle, and the
74
74
  current run. Prompt review requires actual self-review and `--ack-self-review`.
75
75
  Revisions require current receipts. The command loads the REVIEW method; WORK
76
- does not activate it directly. Tools without terminal Plan support (Codex) retain
76
+ does not activate it directly. Tools without terminal Plan support retain
77
77
  native artifact collection and parent review, including explicit prompt-review
78
78
  acknowledgement. Both paths leave task persistence and implementation decisions
79
79
  to the parent. The legacy file-presence Stop hook remains uninstalled.
@@ -327,7 +327,7 @@ plans, including salvage paths. Managed native terminal sessions additionally
327
327
  require a completed `plan-session done` handoff and current content/binding review
328
328
  receipts. `review plan --ack-self-review` confirms a performed prompt-mode review;
329
329
  it cannot acknowledge changed content. Standalone plan review retains its ordinary
330
- behavior, and Codex collection retains parent-side review.
330
+ behavior; the collector fallback retains parent-side review.
331
331
 
332
332
  ## Extension rules
333
333
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "wade-cli"
7
- version = "1.2.4"
7
+ version = "1.2.6"
8
8
  description = "WADE — Workflow for AI-Driven Engineering"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -24,7 +24,7 @@ classifiers = [
24
24
  "Topic :: Software Development :: Version Control :: Git",
25
25
  ]
26
26
  dependencies = [
27
- "crossby>=0.32.1,<0.33.0",
27
+ "crossby>=0.36.0,<0.37.0",
28
28
  "typer>=0.12,<0.26",
29
29
  "pydantic>=2.0",
30
30
  "pydantic-settings>=2.0",
@@ -30,9 +30,10 @@ def main() -> int:
30
30
  parser.add_argument(
31
31
  "--tool",
32
32
  required=True,
33
- choices=["claude", "cursor", "opencode", "antigravity-cli", "copilot"],
33
+ choices=["claude", "cursor", "opencode", "antigravity-cli", "copilot", "codex"],
34
34
  )
35
35
  parser.add_argument("--model")
36
+ parser.add_argument("--sandbox", action="store_true", help="Enable the native runtime sandbox")
36
37
  parser.add_argument(
37
38
  "--worktree", action="store_true", help="Also exercise actual worktree bootstrap and hooks"
38
39
  )
@@ -76,7 +77,7 @@ def main() -> int:
76
77
  selected_ai_tool=args.tool,
77
78
  session_phase=SessionPhase.PLAN,
78
79
  session_kind=SessionKind.PLAN,
79
- sandbox=False,
80
+ sandbox=args.sandbox,
80
81
  )
81
82
  else:
82
83
  compose_session(root, root, config, kind=SessionKind.PLAN, task_id=None)
@@ -93,7 +94,7 @@ def main() -> int:
93
94
  prompt="Plan handoff probe",
94
95
  working_dir=root,
95
96
  model=args.model,
96
- sandbox=False,
97
+ sandbox=args.sandbox,
97
98
  ),
98
99
  permission_mode=PermissionMode.DEFAULT,
99
100
  config=config,
@@ -1,3 +1,3 @@
1
1
  """WADE (Workflow for AI-Driven Engineering) — AI-agent-driven git workflow management CLI."""
2
2
 
3
- __version__ = "1.2.4"
3
+ __version__ = "1.2.6"
@@ -19,6 +19,9 @@ from pathlib import Path
19
19
  import structlog
20
20
  from crossby.ai_tools import (
21
21
  AbstractAITool,
22
+ InteractiveLaunchEvent,
23
+ InteractiveLaunchEventKind,
24
+ InteractiveSession,
22
25
  PlanSessionError,
23
26
  preflight_plan_session,
24
27
  terminal_interaction_handler,
@@ -399,11 +402,30 @@ def run_interactive_planning_session(
399
402
  request.working_dir, ("plans", "native"), ".wade-owned", ""
400
403
  ):
401
404
  raise ValueError("Cannot safely create the native plan directory")
405
+ deferred_input = adapter.capabilities().plan_mode.supports_ready_event
406
+ ready = False
407
+ submitted = False
408
+
409
+ def on_event(event: InteractiveLaunchEvent, session: InteractiveSession) -> None:
410
+ nonlocal ready, submitted
411
+ if event.tool_id != adapter.TOOL_ID:
412
+ raise ValueError("Planning startup event belongs to another AI tool")
413
+ if event.kind is InteractiveLaunchEventKind.PLAN_READY:
414
+ if ready:
415
+ raise ValueError("Planning CLI reported Plan readiness more than once")
416
+ ready = True
417
+ session.send_message(prompt)
418
+ elif event.kind is InteractiveLaunchEventKind.MESSAGE_SUBMITTED:
419
+ if not ready or submitted:
420
+ raise ValueError("Planning CLI reported task submission out of order")
421
+ submitted = True
422
+
402
423
  exit_code = adapter.launch(
403
424
  request.working_dir,
404
425
  model=request.model,
405
426
  effort=request.effort,
406
- prompt=prompt,
427
+ prompt=None if deferred_input else prompt,
428
+ on_event=on_event if deferred_input else None,
407
429
  plan_mode=True,
408
430
  plan_output_dir=native_dir,
409
431
  transcript_path=transcript,
@@ -415,6 +437,8 @@ def run_interactive_planning_session(
415
437
  )
416
438
  if exit_code != 0:
417
439
  raise ValueError(f"Native planning CLI exited with code {exit_code}; output was retained")
440
+ if deferred_input and not submitted:
441
+ raise ValueError("Native Plan task submission was not confirmed; output was retained")
418
442
  bundle = interactive_plan.collect(request.working_dir)
419
443
  usage = adapter.parse_transcript(transcript) if transcript.is_file() else None
420
444
  return bundle, usage
@@ -16,7 +16,7 @@ Review methodology (loaded only by the bounded review step):
16
16
 
17
17
  An interactive terminal session has `.wade/plans/interactive-session.json`.
18
18
  It keeps questions, review feedback, and revisions inside the native CLI.
19
- A session without that file uses native collection and parent review (Codex).
19
+ A session without that file uses native collection and parent review.
20
20
 
21
21
  ## Required steps
22
22
 
@@ -79,6 +79,24 @@ for line in sys.stdin:
79
79
  encoding="utf-8",
80
80
  )
81
81
  codex_script.chmod(0o755)
82
+ # Keep the collector lane explicit now that production Codex prefers its TUI.
83
+ # Only capability selection is overridden; real CLI, collector, and provider run.
84
+ collector_wade = mock_bin / "wade"
85
+ collector_wade.write_text(
86
+ """#!/usr/bin/env python3
87
+ from crossby.ai_tools.codex import CodexAdapter
88
+ from crossby.models.ai import PlanModeActivation
89
+ from wade.cli.main import cli_main
90
+ original = CodexAdapter.capabilities
91
+ def collected_capabilities(self):
92
+ caps = original(self)
93
+ return caps.model_copy(update={"plan_mode": caps.plan_mode.model_copy(
94
+ update={"activation": PlanModeActivation.UNSUPPORTED})})
95
+ CodexAdapter.capabilities = collected_capabilities
96
+ cli_main()
97
+ """
98
+ )
99
+ collector_wade.chmod(0o755)
82
100
 
83
101
 
84
102
  def _disable_plan_review(repo: Path) -> None:
@@ -368,7 +368,20 @@ def collected_harness(
368
368
  Task(id=str(number), title="feat: native test plan") for number in range(1, 10)
369
369
  ]
370
370
  provider.read_task.return_value = Task(id="330", title="feat: existing", body="Original body")
371
+ # Exercise the retained collector path independently of Codex's new TUI capability.
372
+ from crossby.ai_tools.codex import CodexAdapter
373
+ from crossby.models.ai import PlanModeActivation
374
+
375
+ collected_caps = CodexAdapter().capabilities()
376
+ collected_caps = collected_caps.model_copy(
377
+ update={
378
+ "plan_mode": collected_caps.plan_mode.model_copy(
379
+ update={"activation": PlanModeActivation.UNSUPPORTED}
380
+ )
381
+ }
382
+ )
371
383
  with (
384
+ patch.object(CodexAdapter, "capabilities", return_value=collected_caps),
372
385
  patch("wade.services.plan_service.load_config", return_value=config),
373
386
  patch("wade.services.review_delegation_service.load_config", return_value=config),
374
387
  patch("wade.services.plan_service.get_provider", return_value=provider),
@@ -0,0 +1,82 @@
1
+ """WADE owns task delivery through Crossby's public terminal startup events."""
2
+
3
+ from pathlib import Path
4
+ from unittest.mock import MagicMock, patch
5
+
6
+ import pytest
7
+ from crossby.ai_tools import InteractiveLaunchEvent, InteractiveLaunchEventKind, InteractiveSession
8
+ from crossby.models.ai import AIToolID, PlanSessionRequest
9
+
10
+ from wade.models.config import AICommandConfig, AIConfig, ProjectConfig
11
+ from wade.models.permission import PermissionMode
12
+ from wade.models.workflow import SessionKind
13
+ from wade.services import interactive_plan_service as handoff
14
+ from wade.services.plan_service import run_interactive_planning_session
15
+ from wade.services.session_composition_service import compose_session
16
+
17
+
18
+ @pytest.mark.parametrize(
19
+ "events",
20
+ [
21
+ ["plan_ready", "message_submitted"],
22
+ [],
23
+ ["plan_ready"],
24
+ ["message_submitted"],
25
+ ["plan_ready", "plan_ready"],
26
+ ["plan_ready", "message_submitted", "message_submitted"],
27
+ ["wrong_tool"],
28
+ ],
29
+ )
30
+ def test_codex_deferred_delivery_and_completion_gate(tmp_path: Path, events: list[str]) -> None:
31
+ config = ProjectConfig(ai=AIConfig(review_plan=AICommandConfig(enabled=False)))
32
+ compose_session(tmp_path, tmp_path, config, kind=SessionKind.PLAN, task_id=None)
33
+ port = MagicMock(spec=InteractiveSession)
34
+
35
+ def native_run(command, working_dir, **kwargs):
36
+ assert working_dir == tmp_path
37
+ assert command[0] == "codex"
38
+ assert "app-server" not in command
39
+ assert "/plan" not in command
40
+ assert kwargs["prompt"] is None
41
+ assert callable(kwargs["on_event"])
42
+ for kind in events:
43
+ kwargs["on_event"](
44
+ InteractiveLaunchEvent(
45
+ kind=InteractiveLaunchEventKind.PLAN_READY
46
+ if kind == "wrong_tool"
47
+ else InteractiveLaunchEventKind(kind),
48
+ tool_id=AIToolID.CLAUDE if kind == "wrong_tool" else AIToolID.CODEX,
49
+ ),
50
+ port,
51
+ )
52
+ handoff.import_artifact(tmp_path, "# fix: native Codex plan\n\n## Complexity\neasy\n")
53
+ handoff.complete(tmp_path)
54
+ return 0
55
+
56
+ with (
57
+ patch("crossby.utils.versioning.detect_binary_version", return_value=(0, 154, 0)),
58
+ patch("crossby.ai_tools.codex_terminal.run_terminal_plan", side_effect=native_run),
59
+ ):
60
+ arguments = dict(
61
+ request=PlanSessionRequest(prompt="preflight", working_dir=tmp_path),
62
+ permission_mode=PermissionMode.DEFAULT,
63
+ config=config,
64
+ issue_context="# Task\nPlan the greeting change.",
65
+ session_bundle=str(tmp_path / ".wade/session"),
66
+ source_root=str(tmp_path),
67
+ )
68
+ if events == ["plan_ready", "message_submitted"]:
69
+ bundle, _ = run_interactive_planning_session(
70
+ "codex", str(tmp_path / ".wade/plans"), **arguments
71
+ )
72
+ assert len(bundle.plans) == 1
73
+ port.send_message.assert_called_once()
74
+ prompt = port.send_message.call_args.args[0]
75
+ assert prompt == (tmp_path / ".wade/plans/prompt.txt").read_text()
76
+ assert "WORKFLOW.md" in prompt and not prompt.startswith("/plan")
77
+ else:
78
+ with pytest.raises(ValueError):
79
+ run_interactive_planning_session(
80
+ "codex", str(tmp_path / ".wade/plans"), **arguments
81
+ )
82
+ assert port.send_message.call_count <= 1
@@ -30,7 +30,7 @@ def _skill(root: Path, relative: str, name: str) -> Path:
30
30
 
31
31
 
32
32
  def test_crossby_version_and_skill_root_mapping_contract() -> None:
33
- assert version("crossby") == "0.32.1"
33
+ assert version("crossby") == "0.36.0"
34
34
  assert SKILLS_DIR == {
35
35
  AIToolID.CLAUDE: ".claude/skills",
36
36
  AIToolID.CURSOR: ".cursor/skills",
@@ -115,3 +115,19 @@ def test_crossby_list_skills_is_sorted_and_requires_skill_markdown(
115
115
  (tmp_path / ".claude/skills/not-a-skill").mkdir()
116
116
 
117
117
  assert list_skills(tmp_path / ".claude/skills") == ["alpha", "zeta"]
118
+
119
+
120
+ def test_interactive_plan_startup_events_contract() -> None:
121
+ from crossby.ai_tools import InteractiveLaunchEvent, InteractiveLaunchEventKind
122
+ from crossby.models.ai import PlanModeActivation
123
+
124
+ caps = AbstractAITool.get("codex").capabilities()
125
+ assert caps.supports_plan_mode
126
+ assert caps.plan_mode.activation is PlanModeActivation.TERMINAL_INPUT
127
+ assert caps.plan_mode.supports_ready_event
128
+ assert caps.plan_mode.collector_verified_version == "0.153.4"
129
+ assert set(InteractiveLaunchEvent.model_fields) == {"kind", "tool_id"}
130
+ assert {kind.value for kind in InteractiveLaunchEventKind} == {
131
+ "plan_ready",
132
+ "message_submitted",
133
+ }