minitest-cli 0.33.0__tar.gz → 0.35.0__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 (207) hide show
  1. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/PKG-INFO +59 -9
  2. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/README.md +58 -8
  3. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/pyproject.toml +1 -1
  4. minitest_cli-0.35.0/src/minitest_cli/commands/app_network_helpers.py +114 -0
  5. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/app_skill.py +1 -1
  6. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/apps.py +11 -20
  7. minitest_cli-0.35.0/src/minitest_cli/commands/apps_table.py +28 -0
  8. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/batch.py +24 -17
  9. minitest_cli-0.35.0/src/minitest_cli/commands/deprecated_alias.py +57 -0
  10. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/draft_feature.py +10 -6
  11. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/draft_feature_apply.py +1 -1
  12. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/draft_feature_conflicts.py +1 -1
  13. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/draft_feature_helpers.py +3 -1
  14. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/draft_feature_show.py +1 -1
  15. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/issues.py +9 -7
  16. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/issues_fix.py +1 -1
  17. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/maintenance.py +2 -2
  18. minitest_cli-0.35.0/src/minitest_cli/commands/private_network.py +143 -0
  19. minitest_cli-0.35.0/src/minitest_cli/commands/private_network_helpers.py +93 -0
  20. minitest_cli-0.35.0/src/minitest_cli/commands/residential_proxy.py +121 -0
  21. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run.py +7 -5
  22. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_cancel.py +12 -5
  23. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_commit.py +15 -7
  24. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_recording.py +6 -1
  25. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_recording_helpers.py +5 -3
  26. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/skill.py +4 -1
  27. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_profile.py +3 -1
  28. minitest_cli-0.35.0/src/minitest_cli/commands/user_story_app_skills.py +51 -0
  29. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_bindings.py +7 -38
  30. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/verdicts.py +2 -2
  31. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/main.py +1 -0
  32. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/app.py +7 -0
  33. minitest_cli-0.35.0/tests/_network_settings_server.py +106 -0
  34. minitest_cli-0.35.0/tests/conftest.py +11 -0
  35. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_app_skill_commands.py +6 -3
  36. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_apps_commands.py +15 -1
  37. minitest_cli-0.33.0/tests/test_scenario_command.py → minitest_cli-0.35.0/tests/test_deprecated_commands.py +22 -10
  38. minitest_cli-0.35.0/tests/test_deprecated_flags.py +102 -0
  39. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_draft_feature_commands.py +4 -4
  40. minitest_cli-0.35.0/tests/test_private_network_commands.py +118 -0
  41. minitest_cli-0.35.0/tests/test_residential_proxy_commands.py +89 -0
  42. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_run_cancel.py +1 -1
  43. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/uv.lock +1 -1
  44. minitest_cli-0.33.0/src/minitest_cli/commands/deprecated_alias.py +0 -16
  45. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/.env.example +0 -0
  46. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/.github/workflows/ci.yml +0 -0
  47. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/.github/workflows/install-scripts.yml +0 -0
  48. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/.github/workflows/release.yml +0 -0
  49. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/.gitignore +0 -0
  50. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/.opencode/skill/release/SKILL.md +0 -0
  51. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/AGENTS.md +0 -0
  52. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/RELEASE.md +0 -0
  53. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/install.ps1 +0 -0
  54. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/install.sh +0 -0
  55. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/pyrightconfig.json +0 -0
  56. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/renovate.json +0 -0
  57. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/__init__.py +0 -0
  58. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/api/__init__.py +0 -0
  59. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/api/apps_manager_client.py +0 -0
  60. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/api/client.py +0 -0
  61. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/api/errors.py +0 -0
  62. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/assets/__init__.py +0 -0
  63. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/assets/callback.html +0 -0
  64. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/__init__.py +0 -0
  65. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/_response_errors.py +0 -0
  66. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/app_knowledge.py +0 -0
  67. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/app_knowledge_helpers.py +0 -0
  68. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/app_skill_helpers.py +0 -0
  69. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/app_skill_secret.py +0 -0
  70. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/app_skill_write.py +0 -0
  71. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/apps_dependencies.py +0 -0
  72. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/apps_get.py +0 -0
  73. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/apps_helpers.py +0 -0
  74. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/auth.py +0 -0
  75. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/auth_api_key.py +0 -0
  76. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/batch_helpers.py +0 -0
  77. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/batch_warnings.py +0 -0
  78. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/build.py +0 -0
  79. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/build_commit.py +0 -0
  80. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/build_fix_prompts.py +0 -0
  81. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/build_helpers.py +0 -0
  82. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/capabilities.py +0 -0
  83. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/commit_helpers.py +0 -0
  84. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/env.py +0 -0
  85. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/env_helpers.py +0 -0
  86. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/flow_types.py +0 -0
  87. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/flow_types_helpers.py +0 -0
  88. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/flow_types_write.py +0 -0
  89. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/init.py +0 -0
  90. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/init_helpers.py +0 -0
  91. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/init_playbook.py +0 -0
  92. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/issues_helpers.py +0 -0
  93. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/issues_projection.py +0 -0
  94. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/issues_service.py +0 -0
  95. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/maintenance_callbacks.py +0 -0
  96. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/maintenance_helpers.py +0 -0
  97. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/maintenance_state.py +0 -0
  98. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/recording_timeline.py +0 -0
  99. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_commit_helpers.py +0 -0
  100. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_display.py +0 -0
  101. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_feedback.py +0 -0
  102. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_helpers.py +0 -0
  103. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_tagged.py +0 -0
  104. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/run_targets.py +0 -0
  105. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/screens.py +0 -0
  106. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/screens_detail.py +0 -0
  107. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/screens_format.py +0 -0
  108. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/screens_helpers.py +0 -0
  109. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/screens_tree.py +0 -0
  110. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/tags.py +0 -0
  111. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/tags_helpers.py +0 -0
  112. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_file.py +0 -0
  113. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_file_helpers.py +0 -0
  114. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_file_list.py +0 -0
  115. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_profile_card.py +0 -0
  116. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_profile_default.py +0 -0
  117. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_profile_helpers.py +0 -0
  118. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_profile_list.py +0 -0
  119. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/test_profile_update.py +0 -0
  120. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/upgrade.py +0 -0
  121. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story.py +0 -0
  122. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_camera.py +0 -0
  123. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_create.py +0 -0
  124. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_criteria.py +0 -0
  125. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_criterion_edits.py +0 -0
  126. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_delete.py +0 -0
  127. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_device_count.py +0 -0
  128. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_helpers.py +0 -0
  129. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_modify.py +0 -0
  130. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_overrides.py +0 -0
  131. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_profiles.py +0 -0
  132. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_setup_commit.py +0 -0
  133. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/user_story_update.py +0 -0
  134. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/verdicts_helpers.py +0 -0
  135. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/commands/verdicts_projection.py +0 -0
  136. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/__init__.py +0 -0
  137. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/app_context.py +0 -0
  138. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/auth.py +0 -0
  139. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/config.py +0 -0
  140. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/credentials.py +0 -0
  141. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/oauth.py +0 -0
  142. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/tenants.py +0 -0
  143. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/core/token_exchange.py +0 -0
  144. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/__init__.py +0 -0
  145. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/app_env_vars.py +0 -0
  146. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/app_failure.py +0 -0
  147. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/app_screen.py +0 -0
  148. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/base.py +0 -0
  149. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/batch.py +0 -0
  150. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/build.py +0 -0
  151. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/commit_build.py +0 -0
  152. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/draft_feature.py +0 -0
  153. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/flow_type.py +0 -0
  154. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/issues.py +0 -0
  155. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/recording.py +0 -0
  156. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/story_run.py +0 -0
  157. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/tag.py +0 -0
  158. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/targets.py +0 -0
  159. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/models/user_story.py +0 -0
  160. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/__init__.py +0 -0
  161. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/confirm.py +0 -0
  162. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/dependency_sim.py +0 -0
  163. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/mermaid.py +0 -0
  164. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/output.py +0 -0
  165. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/skill_refresh.py +0 -0
  166. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/update_check.py +0 -0
  167. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/src/minitest_cli/utils/video_frames.py +0 -0
  168. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/__init__.py +0 -0
  169. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/_commit_transport.py +0 -0
  170. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_api_client_auth.py +0 -0
  171. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_app_knowledge_commands.py +0 -0
  172. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_apps_dependencies.py +0 -0
  173. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_auth.py +0 -0
  174. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_auth_api_key.py +0 -0
  175. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_auth_commands.py +0 -0
  176. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_batch_commands.py +0 -0
  177. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_build_commands.py +0 -0
  178. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_build_fix_prompts.py +0 -0
  179. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_capabilities_command.py +0 -0
  180. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_channel_header.py +0 -0
  181. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_code_quality.py +0 -0
  182. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_commit_commands.py +0 -0
  183. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_env.py +0 -0
  184. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_flow_types_commands.py +0 -0
  185. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_init_command.py +0 -0
  186. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_issues.py +0 -0
  187. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_issues_commands.py +0 -0
  188. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_mermaid.py +0 -0
  189. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_native_device_types.py +0 -0
  190. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_network_errors.py +0 -0
  191. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_recording_timeline.py +0 -0
  192. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_response_errors.py +0 -0
  193. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_run_commands.py +0 -0
  194. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_run_frames_command.py +0 -0
  195. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_screens_commands.py +0 -0
  196. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_skill_command.py +0 -0
  197. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_suite_change_provenance.py +0 -0
  198. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_tags_commands.py +0 -0
  199. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_test_file_commands.py +0 -0
  200. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_test_profile_commands.py +0 -0
  201. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_upgrade_command.py +0 -0
  202. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_user_story_bindings_commands.py +0 -0
  203. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_user_story_commands.py +0 -0
  204. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_user_story_setup_commit.py +0 -0
  205. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_verdicts.py +0 -0
  206. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_verdicts_actionable.py +0 -0
  207. {minitest_cli-0.33.0 → minitest_cli-0.35.0}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: minitest-cli
3
- Version: 0.33.0
3
+ Version: 0.35.0
4
4
  Summary: Minitest CLI – command-line interface for the Minitest testing platform
5
5
  Project-URL: Homepage, https://minitap.ai/
6
6
  Project-URL: Source, https://github.com/minitap-ai/minitest-cli
@@ -166,21 +166,71 @@ app defaults.
166
166
  | Command | Description |
167
167
  | ---------------- | ------------------------- |
168
168
  | `minitest auth` | Authentication management |
169
- | `minitest apps` | List, inspect, and create apps |
170
- | `minitest scenario` | Create, update, list and delete scenarios (`user-story` is a deprecated alias) |
171
- | `minitest scenario-binding` | Bind test profiles, files or skills to scenarios (`user-story-binding` is a deprecated alias) |
172
- | `minitest df` | Draft features — branches of the test suite |
173
- | `minitest flow-types` | List flow types, create/rename/delete custom ones |
169
+ | `minitest apps` | List, inspect, and create apps; residential proxy and private network settings |
170
+ | `minitest scenario` | Create, update, list and delete scenarios |
171
+ | `minitest scenario-binding` | Bind test accounts, test files or app skills to scenarios |
172
+ | `minitest draft` | Drafts — branches of the test suite |
173
+ | `minitest test-profile` | Test profiles (Test accounts in the webapp) |
174
+ | `minitest tags` | List, create, update and delete scenario tags |
175
+ | `minitest app-skill` | App skills (Skills in the webapp): procedures Mini loads to arrange test state |
174
176
  | `minitest screens` | Inspect the screens exploration mapped for an app |
175
177
  | `minitest build` | Native iOS/Android build management |
176
- | `minitest run` | Test execution for mobile and web lanes |
177
- | `minitest maintenance` | CLI-only test-flow maintenance against local code |
178
+ | `minitest run` | Start runs and inspect their scenario runs |
179
+ | `minitest batch` | List, inspect and cancel runs (a batch is a Run in the webapp) |
180
+ | `minitest issues` | Read app issues and their fix prompts, mark them fixed |
181
+ | `minitest maintenance` | CLI-only scenario maintenance against local code |
182
+ | `minitest skill` | Print the CLI skill for your AI coding agent (not app skills) |
183
+
184
+ ### Deprecated names
185
+
186
+ Old names keep working as hidden aliases: they print a deprecation warning on
187
+ stderr and leave `--json` stdout unchanged. Switch to the new names.
188
+
189
+ | Deprecated | Use instead |
190
+ | ---------- | ----------- |
191
+ | `minitest user-story` | `minitest scenario` |
192
+ | `minitest user-story-binding` | `minitest scenario-binding` |
193
+ | `minitest scenario-binding set-skills` | `minitest scenario-binding set-app-skills` |
194
+ | `minitest df` | `minitest draft` |
195
+ | `minitest flow-types` | `minitest tags` |
196
+ | `run from-commit --user-story` / `-u` | `run from-commit --scenario` / `-s` |
197
+ | `batch list --user-story-id` | `batch list --scenario` |
198
+ | `run cancel --srp`, `run recording --srp` | `--target-id` |
199
+ | `--type` on `scenario create/update/list` | `--tag` |
200
+
201
+ ## App network settings
202
+
203
+ Two per-app settings decide how test devices reach the network. Anyone on the
204
+ app can read them; only workspace **owners and admins** can change them (other
205
+ roles get `Only workspace owners and admins can change this setting`, exit 2).
206
+ `set` reads the current settings first and changes only what you pass.
207
+ Domains are an exact host (`api.stg.example.com`) or `*.example.com`, which
208
+ matches subdomains only, not `example.com` itself.
209
+
210
+ ```bash
211
+ # Residential proxy: reach the listed domains from a residential IP in one country
212
+ minitest --app <app-id> apps residential-proxy show
213
+ minitest --app <app-id> apps residential-proxy set [--enable|--disable] [--country tr] \
214
+ [--domain ipinfo.io ...] [--remove-domain <d> ...] [--clear-domains]
215
+
216
+ # Private network: reach internal domains through a connector running in your network
217
+ minitest --app <app-id> apps private-network show
218
+ minitest --app <app-id> apps private-network connectors
219
+ minitest --app <app-id> apps private-network set [--enable|--disable] [--connector <name-or-id>] \
220
+ [--domain api.stg.corp.internal ...] [--remove-domain <d> ...] [--clear-domains] [--port 443 ...]
221
+ ```
222
+
223
+ `--clear-domains --domain a --domain b` replaces the list; `--port` replaces the
224
+ ports (default 443). Turning the private network on needs a connector and at
225
+ least one domain. Connectors cannot be created from the CLI: a workspace owner
226
+ or admin creates them in the webapp, under **Workspace settings → Private
227
+ network**.
178
228
 
179
229
  ## CLI-only maintenance
180
230
 
181
231
  `minitest maintenance` lets a coding agent keep Minitest scenarios in sync
182
232
  without connecting GitHub. Run it from the app repository: the code stays on the
183
- machine, while the CLI sends only proposed test-flow edits and the local HEAD SHA.
233
+ machine, while the CLI sends only proposed scenario edits and the local HEAD SHA.
184
234
 
185
235
  ```bash
186
236
  # Print the server-composed maintenance instructions for your coding agent
@@ -133,21 +133,71 @@ app defaults.
133
133
  | Command | Description |
134
134
  | ---------------- | ------------------------- |
135
135
  | `minitest auth` | Authentication management |
136
- | `minitest apps` | List, inspect, and create apps |
137
- | `minitest scenario` | Create, update, list and delete scenarios (`user-story` is a deprecated alias) |
138
- | `minitest scenario-binding` | Bind test profiles, files or skills to scenarios (`user-story-binding` is a deprecated alias) |
139
- | `minitest df` | Draft features — branches of the test suite |
140
- | `minitest flow-types` | List flow types, create/rename/delete custom ones |
136
+ | `minitest apps` | List, inspect, and create apps; residential proxy and private network settings |
137
+ | `minitest scenario` | Create, update, list and delete scenarios |
138
+ | `minitest scenario-binding` | Bind test accounts, test files or app skills to scenarios |
139
+ | `minitest draft` | Drafts — branches of the test suite |
140
+ | `minitest test-profile` | Test profiles (Test accounts in the webapp) |
141
+ | `minitest tags` | List, create, update and delete scenario tags |
142
+ | `minitest app-skill` | App skills (Skills in the webapp): procedures Mini loads to arrange test state |
141
143
  | `minitest screens` | Inspect the screens exploration mapped for an app |
142
144
  | `minitest build` | Native iOS/Android build management |
143
- | `minitest run` | Test execution for mobile and web lanes |
144
- | `minitest maintenance` | CLI-only test-flow maintenance against local code |
145
+ | `minitest run` | Start runs and inspect their scenario runs |
146
+ | `minitest batch` | List, inspect and cancel runs (a batch is a Run in the webapp) |
147
+ | `minitest issues` | Read app issues and their fix prompts, mark them fixed |
148
+ | `minitest maintenance` | CLI-only scenario maintenance against local code |
149
+ | `minitest skill` | Print the CLI skill for your AI coding agent (not app skills) |
150
+
151
+ ### Deprecated names
152
+
153
+ Old names keep working as hidden aliases: they print a deprecation warning on
154
+ stderr and leave `--json` stdout unchanged. Switch to the new names.
155
+
156
+ | Deprecated | Use instead |
157
+ | ---------- | ----------- |
158
+ | `minitest user-story` | `minitest scenario` |
159
+ | `minitest user-story-binding` | `minitest scenario-binding` |
160
+ | `minitest scenario-binding set-skills` | `minitest scenario-binding set-app-skills` |
161
+ | `minitest df` | `minitest draft` |
162
+ | `minitest flow-types` | `minitest tags` |
163
+ | `run from-commit --user-story` / `-u` | `run from-commit --scenario` / `-s` |
164
+ | `batch list --user-story-id` | `batch list --scenario` |
165
+ | `run cancel --srp`, `run recording --srp` | `--target-id` |
166
+ | `--type` on `scenario create/update/list` | `--tag` |
167
+
168
+ ## App network settings
169
+
170
+ Two per-app settings decide how test devices reach the network. Anyone on the
171
+ app can read them; only workspace **owners and admins** can change them (other
172
+ roles get `Only workspace owners and admins can change this setting`, exit 2).
173
+ `set` reads the current settings first and changes only what you pass.
174
+ Domains are an exact host (`api.stg.example.com`) or `*.example.com`, which
175
+ matches subdomains only, not `example.com` itself.
176
+
177
+ ```bash
178
+ # Residential proxy: reach the listed domains from a residential IP in one country
179
+ minitest --app <app-id> apps residential-proxy show
180
+ minitest --app <app-id> apps residential-proxy set [--enable|--disable] [--country tr] \
181
+ [--domain ipinfo.io ...] [--remove-domain <d> ...] [--clear-domains]
182
+
183
+ # Private network: reach internal domains through a connector running in your network
184
+ minitest --app <app-id> apps private-network show
185
+ minitest --app <app-id> apps private-network connectors
186
+ minitest --app <app-id> apps private-network set [--enable|--disable] [--connector <name-or-id>] \
187
+ [--domain api.stg.corp.internal ...] [--remove-domain <d> ...] [--clear-domains] [--port 443 ...]
188
+ ```
189
+
190
+ `--clear-domains --domain a --domain b` replaces the list; `--port` replaces the
191
+ ports (default 443). Turning the private network on needs a connector and at
192
+ least one domain. Connectors cannot be created from the CLI: a workspace owner
193
+ or admin creates them in the webapp, under **Workspace settings → Private
194
+ network**.
145
195
 
146
196
  ## CLI-only maintenance
147
197
 
148
198
  `minitest maintenance` lets a coding agent keep Minitest scenarios in sync
149
199
  without connecting GitHub. Run it from the app repository: the code stays on the
150
- machine, while the CLI sends only proposed test-flow edits and the local HEAD SHA.
200
+ machine, while the CLI sends only proposed scenario edits and the local HEAD SHA.
151
201
 
152
202
  ```bash
153
203
  # Print the server-composed maintenance instructions for your coding agent
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "minitest-cli"
3
- version = "0.33.0"
3
+ version = "0.35.0"
4
4
  description = "Minitest CLI – command-line interface for the Minitest testing platform"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -0,0 +1,114 @@
1
+ """Shared plumbing for the per-app network settings (residential proxy, private network)."""
2
+
3
+ import asyncio
4
+ import re
5
+ from typing import Any
6
+
7
+ import httpx
8
+ import typer
9
+
10
+ from minitest_cli.api.client import ApiClient
11
+ from minitest_cli.api.errors import format_network_error
12
+ from minitest_cli.commands._response_errors import extract_detail
13
+ from minitest_cli.core.app_context import resolve_app_id
14
+ from minitest_cli.core.auth import require_auth
15
+ from minitest_cli.core.config import Settings
16
+ from minitest_cli.utils.output import print_error
17
+
18
+ EXIT_GENERAL_ERROR = 1
19
+ EXIT_AUTH_ERROR = 2
20
+ EXIT_NETWORK_ERROR = 3
21
+ EXIT_NOT_FOUND = 4
22
+
23
+ ADMIN_ONLY_MESSAGE = "Only workspace owners and admins can change this setting."
24
+
25
+
26
+ def is_json_mode() -> bool:
27
+ return typer.Context.json_mode # type: ignore[attr-defined]
28
+
29
+
30
+ def resolve_target() -> tuple[Settings, str]:
31
+ settings: Settings = typer.Context.settings # type: ignore[attr-defined]
32
+ require_auth(settings)
33
+ return settings, resolve_app_id(settings, typer.Context.app_flag) # type: ignore[attr-defined]
34
+
35
+
36
+ def fail(message: str, code: int = EXIT_GENERAL_ERROR) -> typer.Exit:
37
+ print_error(message)
38
+ return typer.Exit(code=code)
39
+
40
+
41
+ def _raise_for_status(resp: httpx.Response) -> None:
42
+ if resp.status_code < 400:
43
+ return
44
+ detail = extract_detail(resp)
45
+ if resp.status_code == 403:
46
+ raise fail(f"{ADMIN_ONLY_MESSAGE} ({detail})", EXIT_AUTH_ERROR)
47
+ if resp.status_code == 401:
48
+ raise fail(f"Authentication failed: {detail}", EXIT_AUTH_ERROR)
49
+ if resp.status_code == 404:
50
+ raise fail(f"Not found: {detail}", EXIT_NOT_FOUND)
51
+ if resp.status_code in (400, 409, 422):
52
+ raise fail(f"Rejected by the server ({resp.status_code}): {detail}")
53
+ raise fail(f"API error ({resp.status_code}): {detail}", EXIT_NETWORK_ERROR)
54
+
55
+
56
+ def call_api(
57
+ settings: Settings, method: str, path: str, body: dict[str, Any] | None = None
58
+ ) -> dict[str, Any]:
59
+ async def _run() -> dict[str, Any]:
60
+ async with ApiClient(settings) as client:
61
+ resp = await client.request(method, path, json=body)
62
+ _raise_for_status(resp)
63
+ try:
64
+ return resp.json()
65
+ except ValueError as exc:
66
+ raise fail(
67
+ f"Unexpected non-JSON response ({resp.status_code}): {resp.text[:200]}",
68
+ EXIT_NETWORK_ERROR,
69
+ ) from exc
70
+
71
+ try:
72
+ return asyncio.run(_run())
73
+ except httpx.HTTPError as exc:
74
+ raise fail(format_network_error(exc), EXIT_NETWORK_ERROR) from exc
75
+
76
+
77
+ def merge_domains(
78
+ current: list[str],
79
+ *,
80
+ add: list[str] | None,
81
+ remove: list[str] | None,
82
+ clear: bool,
83
+ pattern: str,
84
+ max_domains: int,
85
+ ) -> list[str]:
86
+ """Apply ``--clear-domains``, ``--remove-domain`` then ``--domain`` and validate the result."""
87
+ added = [_normalize(d) for d in add or []]
88
+ invalid = [d for d in added if not re.fullmatch(pattern, d)]
89
+ if invalid:
90
+ raise fail(
91
+ f"Invalid domain(s): {', '.join(invalid)}. Use a lowercase host like api.example.com, "
92
+ "or *.example.com to match its subdomains (not example.com itself)."
93
+ )
94
+ removed = {_normalize(d) for d in remove or []}
95
+ unknown = sorted(removed - set(current))
96
+ if unknown:
97
+ raise fail(f"Not in the current domain list: {', '.join(unknown)}.")
98
+ base = [] if clear else [d for d in current if d not in removed]
99
+ merged = list(dict.fromkeys([*base, *added]))
100
+ if len(merged) > max_domains:
101
+ raise fail(f"Too many domains: {len(merged)} (max {max_domains}).")
102
+ return merged
103
+
104
+
105
+ def _normalize(domain: str) -> str:
106
+ return domain.strip().lower().rstrip(".")
107
+
108
+
109
+ def on_off(value: bool) -> str:
110
+ return "on" if value else "off"
111
+
112
+
113
+ def domain_list(domains: list[str]) -> str:
114
+ return ", ".join(domains) if domains else "-"
@@ -21,7 +21,7 @@ from minitest_cli.utils.output import print_info, print_json, print_success, pri
21
21
 
22
22
  app = typer.Typer(
23
23
  name="app-skill",
24
- help="Manage app skills: procedures Mini loads to arrange test state.",
24
+ help="Manage app skills (Skills in the webapp): procedures Mini loads to arrange test state.",
25
25
  no_args_is_help=True,
26
26
  )
27
27
  app.add_typer(app_skill_secret.app)
@@ -1,4 +1,4 @@
1
- """App management commands: list, get, create, dependencies."""
1
+ """App management commands: list, get, create, dependencies, network settings."""
2
2
 
3
3
  import asyncio
4
4
  from pathlib import Path
@@ -10,8 +10,14 @@ import typer
10
10
  from minitest_cli.api.apps_manager_client import AppsManagerClient # noqa: F401 re-exported for tests
11
11
  from minitest_cli.api.client import ApiClient
12
12
  from minitest_cli.api.errors import format_network_error
13
- from minitest_cli.commands import apps_dependencies, apps_get
13
+ from minitest_cli.commands import (
14
+ apps_dependencies,
15
+ apps_get,
16
+ private_network,
17
+ residential_proxy,
18
+ )
14
19
  from minitest_cli.commands.apps_helpers import create_app_request
20
+ from minitest_cli.commands.apps_table import APP_TABLE_HEADERS, app_row
15
21
  from minitest_cli.core.auth import require_auth
16
22
  from minitest_cli.core.config import Settings
17
23
  from minitest_cli.core.tenants import fetch_user_tenants, resolve_tenant_id
@@ -29,6 +35,8 @@ EXIT_NETWORK_ERROR = 3
29
35
  app = typer.Typer(name="apps", help="App management.")
30
36
  app.command(name="dependencies")(apps_dependencies.dependencies)
31
37
  app.command(name="get")(apps_get.get_app)
38
+ app.add_typer(residential_proxy.app)
39
+ app.add_typer(private_network.app)
32
40
 
33
41
 
34
42
  @app.callback()
@@ -36,22 +44,6 @@ def _callback() -> None:
36
44
  """App management."""
37
45
 
38
46
 
39
- APP_TABLE_HEADERS = ["ID", "Name", "Platform"]
40
-
41
- _PLATFORM_LABELS: dict[str, str] = {
42
- "android": "Android",
43
- "ios": "iOS",
44
- "web": "Web",
45
- }
46
-
47
-
48
- def _format_platforms(values: list[str]) -> str:
49
- """Render an app's platform lanes for the table."""
50
- if not values:
51
- return "—"
52
- return ", ".join(_PLATFORM_LABELS.get(v, v) for v in values)
53
-
54
-
55
47
  def _get_settings() -> Settings:
56
48
  return typer.Context.settings # type: ignore[attr-defined]
57
49
 
@@ -92,8 +84,7 @@ def list_apps() -> None:
92
84
  print_json([a.model_dump(mode="json", by_alias=True) for a in data.apps])
93
85
  return
94
86
 
95
- rows = [[a.id, a.name, _format_platforms(a.platforms)] for a in data.apps]
96
- print_table(APP_TABLE_HEADERS, rows, title="Apps")
87
+ print_table(APP_TABLE_HEADERS, [app_row(a) for a in data.apps], title="Apps")
97
88
 
98
89
 
99
90
  @app.command(name="create")
@@ -0,0 +1,28 @@
1
+ """Rows of the `apps list` table."""
2
+
3
+ from minitest_cli.models.app import AppResponse
4
+
5
+ APP_TABLE_HEADERS = ["ID", "Name", "Platform", "Repository", "Folder"]
6
+
7
+ _PLATFORM_LABELS: dict[str, str] = {
8
+ "android": "Android",
9
+ "ios": "iOS",
10
+ "web": "Web",
11
+ }
12
+
13
+
14
+ def _format_platforms(values: list[str]) -> str:
15
+ if not values:
16
+ return "—"
17
+ return ", ".join(_PLATFORM_LABELS.get(v, v) for v in values)
18
+
19
+
20
+ def app_row(app: AppResponse) -> list[str]:
21
+ repo = app.repository
22
+ return [
23
+ app.id,
24
+ app.name,
25
+ _format_platforms(app.platforms),
26
+ repo.full_name if repo else "—",
27
+ (repo.folder or "/") if repo else "—",
28
+ ]
@@ -7,6 +7,7 @@ import typer
7
7
 
8
8
  from minitest_cli.api.client import ApiClient
9
9
  from minitest_cli.commands.batch_helpers import batches_base_path
10
+ from minitest_cli.commands.deprecated_alias import deprecated_option, merge_deprecated_option
10
11
  from minitest_cli.commands.run_display import _derive_run_status
11
12
  from minitest_cli.commands.run_helpers import (
12
13
  ensure_uuid,
@@ -26,7 +27,7 @@ from minitest_cli.utils.output import (
26
27
  print_table,
27
28
  )
28
29
 
29
- app = typer.Typer(name="batch", help="Manage batch runs (multi-scenario executions).")
30
+ app = typer.Typer(name="batch", help="List, inspect and cancel runs (Runs in the webapp).")
30
31
 
31
32
  BATCH_TABLE_HEADERS = ["ID", "Status", "Source", "Commit", "Tag", "Targets", "Created"]
32
33
 
@@ -57,26 +58,32 @@ def list_batches(
57
58
  typer.Option("--result", help="Filter by derived result (repeatable)."),
58
59
  ] = None,
59
60
  commit_sha: Annotated[str | None, typer.Option("--commit-sha")] = None,
60
- user_story_id: Annotated[str | None, typer.Option("--user-story-id")] = None,
61
+ scenario_id: Annotated[
62
+ str | None, typer.Option("--scenario", help="Only runs that include this scenario ID.")
63
+ ] = None,
64
+ legacy_user_story_id: Annotated[
65
+ str | None, deprecated_option("--user-story-id", new_flag="--scenario")
66
+ ] = None,
61
67
  search: Annotated[str | None, typer.Option("--search")] = None,
62
68
  all_pages: Annotated[bool, typer.Option("--all", help="Fetch all pages.")] = False,
63
69
  ) -> None:
64
- """List batches for the current app."""
70
+ """List the runs (batches) of the current app."""
65
71
  settings, app_id, json_mode = resolve_app()
66
72
  if all_pages:
67
73
  page, page_size = 1, 100
68
74
 
75
+ scenario_id = merge_deprecated_option(
76
+ scenario_id, legacy_user_story_id, old_flag="--user-story-id", new_flag="--scenario"
77
+ )
78
+ filters = {
79
+ "status": status_filter,
80
+ "result": result_filter,
81
+ "commit_sha": commit_sha,
82
+ "user_story_id": scenario_id,
83
+ "search": search,
84
+ }
69
85
  params: dict[str, object] = {"page": page, "page_size": page_size}
70
- if status_filter:
71
- params["status"] = status_filter
72
- if result_filter:
73
- params["result"] = result_filter
74
- if commit_sha:
75
- params["commit_sha"] = commit_sha
76
- if user_story_id:
77
- params["user_story_id"] = user_story_id
78
- if search:
79
- params["search"] = search
86
+ params.update({key: value for key, value in filters.items() if value})
80
87
 
81
88
  async def _list() -> BatchListResponse:
82
89
  async with ApiClient(settings) as client:
@@ -108,9 +115,9 @@ def list_batches(
108
115
 
109
116
  @app.command(name="get")
110
117
  def get_batch(
111
- batch_id: Annotated[str, typer.Argument(help="Batch ID.")],
118
+ batch_id: Annotated[str, typer.Argument(help="Run (batch) ID.")],
112
119
  ) -> None:
113
- """Get a single batch with its scenario runs."""
120
+ """Get one run (batch) with its scenario runs."""
114
121
  settings, app_id, json_mode = resolve_app()
115
122
  ensure_uuid(batch_id, kind="batch id")
116
123
 
@@ -173,9 +180,9 @@ def get_batch(
173
180
 
174
181
  @app.command()
175
182
  def cancel(
176
- batch_id: Annotated[str, typer.Argument(help="Batch ID to cancel.")],
183
+ batch_id: Annotated[str, typer.Argument(help="Run (batch) ID to cancel.")],
177
184
  ) -> None:
178
- """Cancel a batch and all its pending/running scenario runs."""
185
+ """Cancel a run (batch) and all its pending/running scenario runs."""
179
186
  settings, app_id, json_mode = resolve_app()
180
187
  ensure_uuid(batch_id, kind="batch id")
181
188
 
@@ -0,0 +1,57 @@
1
+ import functools
2
+ from collections.abc import Callable
3
+ from typing import Any
4
+
5
+ import typer
6
+
7
+ from minitest_cli.utils.output import print_error, print_warning
8
+
9
+
10
+ def deprecated_alias(source: typer.Typer, *, old_name: str) -> typer.Typer:
11
+ """Expose ``source``'s commands under a hidden legacy name that warns on stderr."""
12
+ new_name = source.info.name
13
+ alias = typer.Typer(name=old_name, help=f"Deprecated: use `minitest {new_name}`.", hidden=True)
14
+
15
+ @alias.callback()
16
+ def _warn() -> None:
17
+ print_warning(f"`minitest {old_name}` is deprecated; use `minitest {new_name}` instead.")
18
+
19
+ alias.registered_commands = source.registered_commands
20
+ return alias
21
+
22
+
23
+ def deprecated_command(
24
+ group: typer.Typer, command: Callable[..., Any], *, old_name: str, new_name: str
25
+ ) -> None:
26
+ """Register ``command`` again under a hidden legacy subcommand name that warns on stderr."""
27
+ group_name = group.info.name
28
+
29
+ @functools.wraps(command)
30
+ def _legacy(*args: Any, **kwargs: Any) -> Any:
31
+ print_warning(
32
+ f"`minitest {group_name} {old_name}` is deprecated; "
33
+ f"use `minitest {group_name} {new_name}` instead."
34
+ )
35
+ return command(*args, **kwargs)
36
+
37
+ group.command(name=old_name, hidden=True, help=f"Deprecated: use `{new_name}`.")(_legacy)
38
+
39
+
40
+ def deprecated_option(*param_decls: str, new_flag: str) -> Any:
41
+ """A hidden option kept for a renamed flag; pair it with ``merge_deprecated_option``."""
42
+ return typer.Option(*param_decls, hidden=True, help=f"Deprecated alias for {new_flag}.")
43
+
44
+
45
+ def merge_deprecated_option[T](
46
+ new: T | None, old: T | None, *, old_flag: str, new_flag: str
47
+ ) -> T | None:
48
+ """Return the renamed flag's value, falling back to its deprecated alias with a warning."""
49
+ if old is None:
50
+ return new
51
+ print_warning(f"{old_flag} is deprecated; use {new_flag} instead.")
52
+ if new is None:
53
+ return old
54
+ if isinstance(new, list) and isinstance(old, list):
55
+ return [*new, *old] # type: ignore[return-value]
56
+ print_error(f"Use either {new_flag} or {old_flag}, not both.")
57
+ raise typer.Exit(code=1)
@@ -11,6 +11,7 @@ import typer
11
11
 
12
12
  from minitest_cli.api.client import ApiClient
13
13
  from minitest_cli.commands import draft_feature_apply, draft_feature_show
14
+ from minitest_cli.commands.deprecated_alias import deprecated_alias
14
15
  from minitest_cli.commands.draft_feature_helpers import (
15
16
  DRAFT_FEATURE_TABLE_HEADERS,
16
17
  base_path,
@@ -21,7 +22,7 @@ from minitest_cli.commands.run_helpers import ensure_uuid, resolve_app, run_api_
21
22
  from minitest_cli.models.draft_feature import DraftFeatureResponse, DraftFeatureStatus
22
23
  from minitest_cli.utils.output import output, print_error, print_info, print_success, print_table
23
24
 
24
- app = typer.Typer(name="df", help="Draft features — branches of the app's test suite.")
25
+ app = typer.Typer(name="draft", help="Drafts — branches of the app's test suite.")
25
26
  draft_feature_show.register(app)
26
27
  draft_feature_apply.register(app)
27
28
 
@@ -42,7 +43,7 @@ def list_draft_features(
42
43
  async def _list() -> list[DraftFeatureResponse]:
43
44
  async with ApiClient(settings) as client:
44
45
  resp = await client.get(base_path(app_id), params=params)
45
- handle_response_error(resp, resource="Draft features")
46
+ handle_response_error(resp, resource="Drafts")
46
47
  return [DraftFeatureResponse.model_validate(item) for item in resp.json()]
47
48
 
48
49
  features = run_api_call(_list())
@@ -51,12 +52,12 @@ def list_draft_features(
51
52
  output([f.model_dump(mode="json", by_alias=True) for f in features], json_mode=True)
52
53
  return
53
54
  if not features:
54
- print_info("No draft features found.")
55
+ print_info("No drafts found.")
55
56
  return
56
57
  print_table(
57
58
  DRAFT_FEATURE_TABLE_HEADERS,
58
59
  [format_draft_feature_row(f) for f in features],
59
- title=f"Draft features ({len(features)})",
60
+ title=f"Drafts ({len(features)})",
60
61
  )
61
62
 
62
63
 
@@ -88,7 +89,7 @@ def create_draft_feature(
88
89
 
89
90
  feature = run_api_call(_create())
90
91
  if not json_mode:
91
- print_success(f"Draft feature created: {feature.id}")
92
+ print_success(f"Draft created: {feature.id}")
92
93
  output(feature.model_dump(mode="json", by_alias=True), json_mode=json_mode)
93
94
 
94
95
 
@@ -114,4 +115,7 @@ def delete_draft_feature(
114
115
  if json_mode:
115
116
  output(feature.model_dump(mode="json", by_alias=True), json_mode=True)
116
117
  else:
117
- print_success(f"Draft feature abandoned: {feature.id} (status: {feature.status.value})")
118
+ print_success(f"Draft abandoned: {feature.id} (status: {feature.status.value})")
119
+
120
+
121
+ legacy_app = deprecated_alias(app, old_name="df")
@@ -1,4 +1,4 @@
1
- """`minitest df apply` — post a changeset file to a branch."""
1
+ """`minitest draft apply` — post a changeset file to a branch."""
2
2
 
3
3
  from pathlib import Path
4
4
  from typing import Annotated
@@ -1,4 +1,4 @@
1
- """Rendering for `minitest df show --view conflicts`.
1
+ """Rendering for `minitest draft show --view conflicts`.
2
2
 
3
3
  The three sides of a conflict are whole story tuples, so printing them as three
4
4
  JSON blobs in a table makes the one thing a resolver needs — which key is in
@@ -59,7 +59,9 @@ def handle_response_error(resp: httpx.Response, *, resource: str = "Draft featur
59
59
  if resp.status_code == 409:
60
60
  detail = extract_detail(resp)
61
61
  print_error(detail or f"{resource} changed since it was read.")
62
- print_info("Re-run `df show --view diff`, rebuild against the mainRev it returns, retry.")
62
+ print_info(
63
+ "Re-run `draft show --view diff`, rebuild against the mainRev it returns, retry."
64
+ )
63
65
  raise typer.Exit(code=EXIT_CONFLICT)
64
66
  if resp.status_code >= 400:
65
67
  detail = extract_detail(resp)
@@ -1,4 +1,4 @@
1
- """`minitest df show` — read a branch as a diff, as the suite it would run, or as its conflicts."""
1
+ """`minitest draft show` — read a branch as a diff, as the suite it runs, or as its conflicts."""
2
2
 
3
3
  from enum import StrEnum
4
4
  from typing import Annotated