minitest-cli 0.40.0__tar.gz → 0.41.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 (267) hide show
  1. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/.env.example +1 -1
  2. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/PKG-INFO +80 -6
  3. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/README.md +78 -5
  4. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/pyproject.toml +2 -1
  5. minitest_cli-0.41.0/src/minitest_cli/commands/glossary.py +140 -0
  6. minitest_cli-0.41.0/src/minitest_cli/commands/knowledge.py +105 -0
  7. minitest_cli-0.41.0/src/minitest_cli/commands/knowledge_documents.py +86 -0
  8. minitest_cli-0.41.0/src/minitest_cli/commands/knowledge_helpers.py +97 -0
  9. minitest_cli-0.41.0/src/minitest_cli/commands/schedules.py +156 -0
  10. minitest_cli-0.41.0/src/minitest_cli/commands/schedules_body.py +139 -0
  11. minitest_cli-0.41.0/src/minitest_cli/commands/schedules_create.py +145 -0
  12. minitest_cli-0.41.0/src/minitest_cli/commands/schedules_display.py +106 -0
  13. minitest_cli-0.41.0/src/minitest_cli/commands/schedules_helpers.py +83 -0
  14. minitest_cli-0.41.0/src/minitest_cli/commands/schedules_history.py +109 -0
  15. minitest_cli-0.41.0/src/minitest_cli/commands/schedules_options.py +195 -0
  16. minitest_cli-0.41.0/src/minitest_cli/commands/schedules_scope.py +60 -0
  17. minitest_cli-0.41.0/src/minitest_cli/commands/schedules_spec.py +113 -0
  18. minitest_cli-0.41.0/src/minitest_cli/commands/schedules_update.py +92 -0
  19. minitest_cli-0.41.0/src/minitest_cli/commands/schedules_where.py +127 -0
  20. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/secret.py +43 -50
  21. minitest_cli-0.41.0/src/minitest_cli/commands/secret_create.py +185 -0
  22. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/secret_helpers.py +4 -3
  23. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/secret_lint.py +6 -1
  24. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/secret_manage.py +2 -29
  25. minitest_cli-0.41.0/src/minitest_cli/commands/secret_state.py +42 -0
  26. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/test_profile_secret_refs.py +4 -1
  27. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/core/config.py +2 -2
  28. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/main.py +9 -0
  29. minitest_cli-0.41.0/tests/test_config_defaults.py +32 -0
  30. minitest_cli-0.41.0/tests/test_knowledge_v2_commands.py +289 -0
  31. minitest_cli-0.41.0/tests/test_schedules_commands.py +329 -0
  32. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_secret_commands.py +51 -32
  33. minitest_cli-0.41.0/tests/test_secret_create.py +181 -0
  34. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_secret_lint_extract.py +14 -0
  35. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/uv.lock +49 -1
  36. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/.github/workflows/ci.yml +0 -0
  37. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/.github/workflows/install-scripts.yml +0 -0
  38. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/.github/workflows/release.yml +0 -0
  39. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/.gitignore +0 -0
  40. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/.opencode/skill/release/SKILL.md +0 -0
  41. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/AGENTS.md +0 -0
  42. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/RELEASE.md +0 -0
  43. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/install.ps1 +0 -0
  44. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/install.sh +0 -0
  45. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/pyrightconfig.json +0 -0
  46. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/renovate.json +0 -0
  47. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/__init__.py +0 -0
  48. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/api/__init__.py +0 -0
  49. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/api/apps_manager_client.py +0 -0
  50. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/api/client.py +0 -0
  51. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/api/errors.py +0 -0
  52. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/assets/__init__.py +0 -0
  53. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/assets/callback.html +0 -0
  54. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/__init__.py +0 -0
  55. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/_abi_mismatch.py +0 -0
  56. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/_response_errors.py +0 -0
  57. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/app_knowledge.py +0 -0
  58. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/app_knowledge_helpers.py +0 -0
  59. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/app_network_helpers.py +0 -0
  60. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/app_skill.py +0 -0
  61. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/app_skill_helpers.py +0 -0
  62. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/app_skill_secret.py +0 -0
  63. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/app_skill_write.py +0 -0
  64. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/apps.py +0 -0
  65. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/apps_dependencies.py +0 -0
  66. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/apps_get.py +0 -0
  67. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/apps_helpers.py +0 -0
  68. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/apps_table.py +0 -0
  69. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/auth.py +0 -0
  70. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/auth_api_key.py +0 -0
  71. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/batch.py +0 -0
  72. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/batch_helpers.py +0 -0
  73. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/batch_warnings.py +0 -0
  74. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/build.py +0 -0
  75. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/build_bundle.py +0 -0
  76. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/build_commit.py +0 -0
  77. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/build_conversion.py +0 -0
  78. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/build_fix_prompts.py +0 -0
  79. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/build_get.py +0 -0
  80. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/build_helpers.py +0 -0
  81. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/build_signing.py +0 -0
  82. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/capabilities.py +0 -0
  83. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/commit_helpers.py +0 -0
  84. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/deprecated_alias.py +0 -0
  85. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft.py +0 -0
  86. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_asks.py +0 -0
  87. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_conversation.py +0 -0
  88. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_create.py +0 -0
  89. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_feature.py +0 -0
  90. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_feature_apply.py +0 -0
  91. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_feature_conflicts.py +0 -0
  92. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_feature_helpers.py +0 -0
  93. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_feature_show.py +0 -0
  94. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_helpers.py +0 -0
  95. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_legacy.py +0 -0
  96. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_lifecycle.py +0 -0
  97. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_pr.py +0 -0
  98. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_render.py +0 -0
  99. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_update.py +0 -0
  100. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/draft_watch.py +0 -0
  101. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/env.py +0 -0
  102. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/env_helpers.py +0 -0
  103. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/flow_types.py +0 -0
  104. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/flow_types_helpers.py +0 -0
  105. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/flow_types_write.py +0 -0
  106. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/init.py +0 -0
  107. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/init_helpers.py +0 -0
  108. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/init_playbook.py +0 -0
  109. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/issues.py +0 -0
  110. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/issues_fix.py +0 -0
  111. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/issues_get.py +0 -0
  112. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/issues_helpers.py +0 -0
  113. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/issues_projection.py +0 -0
  114. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/issues_service.py +0 -0
  115. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/private_network.py +0 -0
  116. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/private_network_helpers.py +0 -0
  117. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/recording_timeline.py +0 -0
  118. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/residential_proxy.py +0 -0
  119. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run.py +0 -0
  120. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run_cancel.py +0 -0
  121. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run_commit.py +0 -0
  122. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run_commit_helpers.py +0 -0
  123. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run_display.py +0 -0
  124. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run_feedback.py +0 -0
  125. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run_helpers.py +0 -0
  126. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run_list.py +0 -0
  127. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run_logs.py +0 -0
  128. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run_recording.py +0 -0
  129. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run_recording_helpers.py +0 -0
  130. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run_tagged.py +0 -0
  131. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/run_targets.py +0 -0
  132. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/screens.py +0 -0
  133. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/screens_detail.py +0 -0
  134. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/screens_format.py +0 -0
  135. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/screens_helpers.py +0 -0
  136. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/screens_tree.py +0 -0
  137. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/secret_extract.py +0 -0
  138. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/secret_value.py +0 -0
  139. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/skill.py +0 -0
  140. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/tags.py +0 -0
  141. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/tags_helpers.py +0 -0
  142. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/test_file.py +0 -0
  143. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/test_file_helpers.py +0 -0
  144. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/test_file_list.py +0 -0
  145. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/test_profile.py +0 -0
  146. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/test_profile_card.py +0 -0
  147. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/test_profile_default.py +0 -0
  148. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/test_profile_helpers.py +0 -0
  149. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/test_profile_list.py +0 -0
  150. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/test_profile_update.py +0 -0
  151. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/upgrade.py +0 -0
  152. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story.py +0 -0
  153. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_app_skills.py +0 -0
  154. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_bindings.py +0 -0
  155. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_camera.py +0 -0
  156. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_create.py +0 -0
  157. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_criteria.py +0 -0
  158. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_criterion_edits.py +0 -0
  159. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_delete.py +0 -0
  160. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_device_count.py +0 -0
  161. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_helpers.py +0 -0
  162. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_iap.py +0 -0
  163. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_modify.py +0 -0
  164. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_overrides.py +0 -0
  165. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_profiles.py +0 -0
  166. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_setup_commit.py +0 -0
  167. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/user_story_update.py +0 -0
  168. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/verdicts.py +0 -0
  169. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/verdicts_helpers.py +0 -0
  170. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/commands/verdicts_projection.py +0 -0
  171. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/core/__init__.py +0 -0
  172. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/core/app_context.py +0 -0
  173. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/core/auth.py +0 -0
  174. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/core/credentials.py +0 -0
  175. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/core/oauth.py +0 -0
  176. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/core/tenants.py +0 -0
  177. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/core/token_exchange.py +0 -0
  178. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/__init__.py +0 -0
  179. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/app.py +0 -0
  180. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/app_env_vars.py +0 -0
  181. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/app_failure.py +0 -0
  182. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/app_screen.py +0 -0
  183. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/base.py +0 -0
  184. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/batch.py +0 -0
  185. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/build.py +0 -0
  186. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/commit_build.py +0 -0
  187. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/draft_feature.py +0 -0
  188. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/flow_type.py +0 -0
  189. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/issues.py +0 -0
  190. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/lane_logs.py +0 -0
  191. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/recording.py +0 -0
  192. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/story_run.py +0 -0
  193. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/tag.py +0 -0
  194. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/targets.py +0 -0
  195. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/models/user_story.py +0 -0
  196. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/utils/__init__.py +0 -0
  197. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/utils/confirm.py +0 -0
  198. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/utils/dependency_sim.py +0 -0
  199. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/utils/mermaid.py +0 -0
  200. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/utils/output.py +0 -0
  201. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/utils/skill_refresh.py +0 -0
  202. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/utils/update_check.py +0 -0
  203. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/src/minitest_cli/utils/video_frames.py +0 -0
  204. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/__init__.py +0 -0
  205. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/_commit_transport.py +0 -0
  206. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/_network_settings_server.py +0 -0
  207. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/_secret_router.py +0 -0
  208. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/conftest.py +0 -0
  209. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/draft_backend.py +0 -0
  210. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_api_client_auth.py +0 -0
  211. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_app_context.py +0 -0
  212. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_app_knowledge_commands.py +0 -0
  213. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_app_skill_commands.py +0 -0
  214. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_apps_commands.py +0 -0
  215. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_apps_dependencies.py +0 -0
  216. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_auth.py +0 -0
  217. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_auth_api_key.py +0 -0
  218. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_auth_commands.py +0 -0
  219. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_batch_commands.py +0 -0
  220. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_build_bundle.py +0 -0
  221. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_build_commands.py +0 -0
  222. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_build_fix_prompts.py +0 -0
  223. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_build_get_command.py +0 -0
  224. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_capabilities_command.py +0 -0
  225. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_channel_header.py +0 -0
  226. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_code_quality.py +0 -0
  227. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_commit_commands.py +0 -0
  228. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_deprecated_commands.py +0 -0
  229. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_deprecated_flags.py +0 -0
  230. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_draft_ask_commands.py +0 -0
  231. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_draft_commands.py +0 -0
  232. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_draft_conversation_commands.py +0 -0
  233. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_draft_feature_commands.py +0 -0
  234. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_draft_pr_commands.py +0 -0
  235. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_env.py +0 -0
  236. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_flow_types_commands.py +0 -0
  237. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_init_command.py +0 -0
  238. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_issues.py +0 -0
  239. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_issues_commands.py +0 -0
  240. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_issues_get_command.py +0 -0
  241. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_mermaid.py +0 -0
  242. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_native_device_types.py +0 -0
  243. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_network_errors.py +0 -0
  244. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_physical_devices.py +0 -0
  245. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_private_network_commands.py +0 -0
  246. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_recording_timeline.py +0 -0
  247. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_residential_proxy_commands.py +0 -0
  248. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_response_errors.py +0 -0
  249. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_run_cancel.py +0 -0
  250. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_run_commands.py +0 -0
  251. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_run_frames_command.py +0 -0
  252. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_run_logs_command.py +0 -0
  253. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_screens_commands.py +0 -0
  254. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_skill_command.py +0 -0
  255. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_suite_change_provenance.py +0 -0
  256. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_tags_commands.py +0 -0
  257. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_test_file_commands.py +0 -0
  258. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_test_profile_commands.py +0 -0
  259. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_test_profile_secret_refs.py +0 -0
  260. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_upgrade_command.py +0 -0
  261. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_user_story_bindings_commands.py +0 -0
  262. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_user_story_commands.py +0 -0
  263. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_user_story_in_app_purchases.py +0 -0
  264. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_user_story_setup_commit.py +0 -0
  265. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_verdicts.py +0 -0
  266. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_verdicts_actionable.py +0 -0
  267. {minitest_cli-0.40.0 → minitest_cli-0.41.0}/tests/test_version.py +0 -0
@@ -24,7 +24,7 @@ MINITEST_CONDUCTOR_URL=https://conductor.dev.minitap.ai
24
24
 
25
25
  # —— Integrations ——
26
26
  # Production
27
- # MINITEST_INTEGRATIONS_URL=https://integrations.minitap.ai
27
+ # MINITEST_INTEGRATIONS_URL=https://integrations.app.minitap.ai
28
28
  # Development
29
29
  MINITEST_INTEGRATIONS_URL=https://integrations.dev.minitap.ai
30
30
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: minitest-cli
3
- Version: 0.40.0
3
+ Version: 0.41.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
@@ -23,6 +23,7 @@ Requires-Python: >=3.12
23
23
  Requires-Dist: httpx>=0.28.1
24
24
  Requires-Dist: pydantic-settings>=2.13.1
25
25
  Requires-Dist: pydantic>=2.12.5
26
+ Requires-Dist: pyyaml>=6.0.3
26
27
  Requires-Dist: rich>=14.3.3
27
28
  Requires-Dist: typer>=0.24.1
28
29
  Provides-Extra: dev
@@ -214,12 +215,18 @@ app defaults.
214
215
  | `minitest df` | Low-level suite branches Mini writes (draft features) |
215
216
  | `minitest test-profile` | Test profiles (Test accounts in the webapp) |
216
217
  | `minitest tags` | List, create, update and delete scenario tags |
218
+ | `minitest brief` | Product brief: what the app is, who uses it, its core flows (Knowledge v2) |
219
+ | `minitest app-guide` | App guide: how to use the app when testing it (Knowledge v2) |
220
+ | `minitest glossary` | Glossary: product terms, their meaning and aliases (Knowledge v2) |
221
+ | `minitest knowledge` | Change history of the brief, app guide and glossary, and reverts |
222
+ | `minitest app-knowledge` | The single Memory document of workspaces without Knowledge v2 |
217
223
  | `minitest app-skill` | App skills (Skills in the webapp): procedures Mini loads to arrange test state |
218
224
  | `minitest secret` | App secrets vault: passwords, OTP seeds, cards, API tokens referenced as `{{secret:NAME}}` (write-only values) |
219
225
  | `minitest screens` | Inspect the screens exploration mapped for an app |
220
226
  | `minitest build` | Native iOS/Android build management |
221
227
  | `minitest run` | Start runs and inspect their scenario runs |
222
228
  | `minitest batch` | List, inspect and cancel runs (a batch is a Run in the webapp) |
229
+ | `minitest schedules` | Scheduled runs: run scenarios at a set time and post a Slack summary |
223
230
  | `minitest issues` | Read app issues and their fix prompts, mark them fixed |
224
231
  | `minitest skill` | Print the CLI skill for your AI coding agent (not app skills) |
225
232
 
@@ -240,6 +247,65 @@ stderr and leave `--json` stdout unchanged. Switch to the new names.
240
247
  | `run cancel --srp`, `run recording --srp` | `--target-id` |
241
248
  | `--type` on `scenario create/update/list` | `--tag` |
242
249
 
250
+ ## Scheduled runs
251
+
252
+ A schedule starts an ordinary run on its own at a wall-clock time on chosen
253
+ weekdays, then posts one summary to a Slack channel. What runs (the whole suite,
254
+ tags minus exclusions, or picked scenarios) is re-resolved at every start, so
255
+ scenarios tagged later join on their own.
256
+
257
+ ```bash
258
+ # Weekdays at 03:00 (this machine's timezone), tagged scenarios on desktop and Android Chrome
259
+ minitest schedules create --name "Nightly sanity check" --at 03:00 \
260
+ --tag Navigation --exclude "Deals page opens" \
261
+ --url https://www.example.com --browser chrome --browser chrome:android \
262
+ --slack-channel C0123ABCD --slack-channel-name minitap
263
+
264
+ # Native: newest installable build on Android, a fixed iOS build, every day in Oslo
265
+ minitest schedules create --name "Monitoring" --at 05:00 --days every-day --timezone Europe/Oslo \
266
+ --android --ios-build <build-id> --slack-channel C0123ABCD
267
+
268
+ minitest schedules preview "Nightly sanity check" # duration, builds tonight would pick, next starts
269
+ minitest schedules list # cadence, next run, scenario count
270
+ minitest --json schedules get "Nightly sanity check" > nightly.json
271
+ minitest schedules create --from-file nightly.json --name "Nightly copy" # JSON or YAML
272
+ minitest schedules update "Nightly sanity check" --at 04:00 --android-branch main
273
+ minitest schedules pause|resume "Nightly sanity check"
274
+ minitest schedules run "Nightly sanity check" # start one now (posts to Slack too)
275
+ minitest schedules fires "Nightly sanity check" # last runs: verdict, new / still open / fixed, or why it didn't run
276
+ minitest schedules delete "Nightly sanity check" --yes # `schedules restore <id>` undoes it
277
+ ```
278
+
279
+ Platforms: `--browser BROWSER[:SURFACE]` (`chrome`, `chrome:mobile`,
280
+ `chrome:tablet`, `chrome:android`, `safari:ios`…) tests `--url` or builds
281
+ `--web-branch` first. `--ios` / `--android` run the newest build that installs;
282
+ `--<platform>-build <id>` pins one build, `--<platform>-branch <branch>` builds
283
+ the branch before each run. On `update`, any `--<platform>-*` flag redefines that
284
+ platform, `--browser` replaces the browsers, `--drop web|ios|android` removes one.
285
+
286
+ A night that can't run is still a fire, with a reason (out of credits, no
287
+ installable build, branch build failed, previous run still going, no phone
288
+ free…); `fires` shows it and Slack gets a message. On a server without
289
+ scheduled runs, every command exits 4 with `Scheduled runs are not available
290
+ on this workspace yet.`
291
+
292
+ ## Knowledge
293
+
294
+ On workspaces with Knowledge v2, what Mini knows about an app is split by job:
295
+
296
+ | Element | Holds | Commands |
297
+ | ------- | ----- | -------- |
298
+ | Product brief | What the app is, who uses it, its core flows. Short (max 2000 chars). | `brief get`, `brief update --content/--content-file` |
299
+ | App guide | How to use the app when testing: navigation, quirks, test data. | `app-guide get`, `app-guide update --content/--content-file` |
300
+ | Glossary | Product terms and what they mean, with aliases. | `glossary list`, `glossary add --term --meaning [--alias]`, `glossary update <id-or-term>`, `glossary remove <id-or-term> --yes` |
301
+
302
+ Every change is versioned with its author and channel (`cli` for these
303
+ commands): `minitest knowledge history [--element product_brief|app_guide|glossary]`
304
+ lists each change with its version ID, and `minitest knowledge revert <version-id>`
305
+ restores that version as a new `reverted` change.
306
+ On a workspace without Knowledge v2, writes fail with a message pointing to
307
+ `minitest app-knowledge`.
308
+
243
309
  ## Secrets
244
310
 
245
311
  Credentials live in the app's vault, never in scenario text. Write
@@ -250,18 +316,26 @@ Workspaces without the feature get `Secrets are not enabled for this workspace y
250
316
 
251
317
  ```bash
252
318
  printf '%s' "$ADMIN_PW" | minitest secret set ADMIN_PASSWORD --kind password --note "Admin login"
253
- echo '{"number":"4242424242424242","expiry":"12/34","cvc":"123"}' \
319
+ echo '{"number":"<number>","expiry":"<MM/YY>","cvc":"<cvc>"}' \
254
320
  | minitest secret set STRIPE_CARD --kind card # optional holder_name, postal_code
255
- minitest secret list [--missing] # names, kinds, usages, requests
321
+ minitest secret create QA_PASSWORD --kind password --generate [--length 24] [--charset default|alnum]
322
+ minitest secret create SANDBOX_KEY --kind token --empty --reason "Checkout calls the sandbox" [--scenario <id>]
323
+ minitest secret list [--missing] # names, kinds, state (set / missing + reason), usages
256
324
  minitest secret describe ADMIN_PASSWORD # usages + reference to copy
257
- minitest secret lint --scenario <id> # exit 1 on leaks or missing secrets
325
+ minitest secret lint --scenario <id> # exit 1 on leaks or missing; warns on pending
258
326
  minitest secret extract <id> --as ADMIN_PASSWORD --kind password [--dry-run]
259
327
  minitest test-profile update <id> --password-secret ADMIN_PASSWORD
260
328
  ```
261
329
 
262
330
  `set` reads stdin only and refuses a terminal (`--interactive` opens a hidden
263
- prompt). Inside a test run (`MINITAP_SECRETS_SOCKET` or `STORY_RUN_ID` set) it
264
- refuses: use `minitest secret request NAME --kind <kind> --reason "…"` instead.
331
+ prompt) and also fills a secret that is waiting for a value. Inside a test run
332
+ (`MINITAP_SECRETS_SOCKET` or `STORY_RUN_ID` set) it refuses: use `secret create`
333
+ instead, which never handles a value. `--generate` (password, token, text) lets
334
+ the server pick a random value (default 24 chars, 12–64); `--empty --reason`
335
+ creates the secret without a value for a human to fill, and runs that need it
336
+ wait until then. Personas can point at either (`--password-secret` etc.).
337
+ `secret request` is a deprecated alias of `create --empty`; on servers that
338
+ predate `create`, `--empty` falls back to the old request endpoint.
265
339
  `extract` reads the leaked literal from the scenario on your machine, creates
266
340
  the secret with it, then rewrites every occurrence to `{{secret:NAME}}`. Older
267
341
  scenario versions and past run logs may still hold the literal: rotate it.
@@ -181,12 +181,18 @@ app defaults.
181
181
  | `minitest df` | Low-level suite branches Mini writes (draft features) |
182
182
  | `minitest test-profile` | Test profiles (Test accounts in the webapp) |
183
183
  | `minitest tags` | List, create, update and delete scenario tags |
184
+ | `minitest brief` | Product brief: what the app is, who uses it, its core flows (Knowledge v2) |
185
+ | `minitest app-guide` | App guide: how to use the app when testing it (Knowledge v2) |
186
+ | `minitest glossary` | Glossary: product terms, their meaning and aliases (Knowledge v2) |
187
+ | `minitest knowledge` | Change history of the brief, app guide and glossary, and reverts |
188
+ | `minitest app-knowledge` | The single Memory document of workspaces without Knowledge v2 |
184
189
  | `minitest app-skill` | App skills (Skills in the webapp): procedures Mini loads to arrange test state |
185
190
  | `minitest secret` | App secrets vault: passwords, OTP seeds, cards, API tokens referenced as `{{secret:NAME}}` (write-only values) |
186
191
  | `minitest screens` | Inspect the screens exploration mapped for an app |
187
192
  | `minitest build` | Native iOS/Android build management |
188
193
  | `minitest run` | Start runs and inspect their scenario runs |
189
194
  | `minitest batch` | List, inspect and cancel runs (a batch is a Run in the webapp) |
195
+ | `minitest schedules` | Scheduled runs: run scenarios at a set time and post a Slack summary |
190
196
  | `minitest issues` | Read app issues and their fix prompts, mark them fixed |
191
197
  | `minitest skill` | Print the CLI skill for your AI coding agent (not app skills) |
192
198
 
@@ -207,6 +213,65 @@ stderr and leave `--json` stdout unchanged. Switch to the new names.
207
213
  | `run cancel --srp`, `run recording --srp` | `--target-id` |
208
214
  | `--type` on `scenario create/update/list` | `--tag` |
209
215
 
216
+ ## Scheduled runs
217
+
218
+ A schedule starts an ordinary run on its own at a wall-clock time on chosen
219
+ weekdays, then posts one summary to a Slack channel. What runs (the whole suite,
220
+ tags minus exclusions, or picked scenarios) is re-resolved at every start, so
221
+ scenarios tagged later join on their own.
222
+
223
+ ```bash
224
+ # Weekdays at 03:00 (this machine's timezone), tagged scenarios on desktop and Android Chrome
225
+ minitest schedules create --name "Nightly sanity check" --at 03:00 \
226
+ --tag Navigation --exclude "Deals page opens" \
227
+ --url https://www.example.com --browser chrome --browser chrome:android \
228
+ --slack-channel C0123ABCD --slack-channel-name minitap
229
+
230
+ # Native: newest installable build on Android, a fixed iOS build, every day in Oslo
231
+ minitest schedules create --name "Monitoring" --at 05:00 --days every-day --timezone Europe/Oslo \
232
+ --android --ios-build <build-id> --slack-channel C0123ABCD
233
+
234
+ minitest schedules preview "Nightly sanity check" # duration, builds tonight would pick, next starts
235
+ minitest schedules list # cadence, next run, scenario count
236
+ minitest --json schedules get "Nightly sanity check" > nightly.json
237
+ minitest schedules create --from-file nightly.json --name "Nightly copy" # JSON or YAML
238
+ minitest schedules update "Nightly sanity check" --at 04:00 --android-branch main
239
+ minitest schedules pause|resume "Nightly sanity check"
240
+ minitest schedules run "Nightly sanity check" # start one now (posts to Slack too)
241
+ minitest schedules fires "Nightly sanity check" # last runs: verdict, new / still open / fixed, or why it didn't run
242
+ minitest schedules delete "Nightly sanity check" --yes # `schedules restore <id>` undoes it
243
+ ```
244
+
245
+ Platforms: `--browser BROWSER[:SURFACE]` (`chrome`, `chrome:mobile`,
246
+ `chrome:tablet`, `chrome:android`, `safari:ios`…) tests `--url` or builds
247
+ `--web-branch` first. `--ios` / `--android` run the newest build that installs;
248
+ `--<platform>-build <id>` pins one build, `--<platform>-branch <branch>` builds
249
+ the branch before each run. On `update`, any `--<platform>-*` flag redefines that
250
+ platform, `--browser` replaces the browsers, `--drop web|ios|android` removes one.
251
+
252
+ A night that can't run is still a fire, with a reason (out of credits, no
253
+ installable build, branch build failed, previous run still going, no phone
254
+ free…); `fires` shows it and Slack gets a message. On a server without
255
+ scheduled runs, every command exits 4 with `Scheduled runs are not available
256
+ on this workspace yet.`
257
+
258
+ ## Knowledge
259
+
260
+ On workspaces with Knowledge v2, what Mini knows about an app is split by job:
261
+
262
+ | Element | Holds | Commands |
263
+ | ------- | ----- | -------- |
264
+ | Product brief | What the app is, who uses it, its core flows. Short (max 2000 chars). | `brief get`, `brief update --content/--content-file` |
265
+ | App guide | How to use the app when testing: navigation, quirks, test data. | `app-guide get`, `app-guide update --content/--content-file` |
266
+ | Glossary | Product terms and what they mean, with aliases. | `glossary list`, `glossary add --term --meaning [--alias]`, `glossary update <id-or-term>`, `glossary remove <id-or-term> --yes` |
267
+
268
+ Every change is versioned with its author and channel (`cli` for these
269
+ commands): `minitest knowledge history [--element product_brief|app_guide|glossary]`
270
+ lists each change with its version ID, and `minitest knowledge revert <version-id>`
271
+ restores that version as a new `reverted` change.
272
+ On a workspace without Knowledge v2, writes fail with a message pointing to
273
+ `minitest app-knowledge`.
274
+
210
275
  ## Secrets
211
276
 
212
277
  Credentials live in the app's vault, never in scenario text. Write
@@ -217,18 +282,26 @@ Workspaces without the feature get `Secrets are not enabled for this workspace y
217
282
 
218
283
  ```bash
219
284
  printf '%s' "$ADMIN_PW" | minitest secret set ADMIN_PASSWORD --kind password --note "Admin login"
220
- echo '{"number":"4242424242424242","expiry":"12/34","cvc":"123"}' \
285
+ echo '{"number":"<number>","expiry":"<MM/YY>","cvc":"<cvc>"}' \
221
286
  | minitest secret set STRIPE_CARD --kind card # optional holder_name, postal_code
222
- minitest secret list [--missing] # names, kinds, usages, requests
287
+ minitest secret create QA_PASSWORD --kind password --generate [--length 24] [--charset default|alnum]
288
+ minitest secret create SANDBOX_KEY --kind token --empty --reason "Checkout calls the sandbox" [--scenario <id>]
289
+ minitest secret list [--missing] # names, kinds, state (set / missing + reason), usages
223
290
  minitest secret describe ADMIN_PASSWORD # usages + reference to copy
224
- minitest secret lint --scenario <id> # exit 1 on leaks or missing secrets
291
+ minitest secret lint --scenario <id> # exit 1 on leaks or missing; warns on pending
225
292
  minitest secret extract <id> --as ADMIN_PASSWORD --kind password [--dry-run]
226
293
  minitest test-profile update <id> --password-secret ADMIN_PASSWORD
227
294
  ```
228
295
 
229
296
  `set` reads stdin only and refuses a terminal (`--interactive` opens a hidden
230
- prompt). Inside a test run (`MINITAP_SECRETS_SOCKET` or `STORY_RUN_ID` set) it
231
- refuses: use `minitest secret request NAME --kind <kind> --reason "…"` instead.
297
+ prompt) and also fills a secret that is waiting for a value. Inside a test run
298
+ (`MINITAP_SECRETS_SOCKET` or `STORY_RUN_ID` set) it refuses: use `secret create`
299
+ instead, which never handles a value. `--generate` (password, token, text) lets
300
+ the server pick a random value (default 24 chars, 12–64); `--empty --reason`
301
+ creates the secret without a value for a human to fill, and runs that need it
302
+ wait until then. Personas can point at either (`--password-secret` etc.).
303
+ `secret request` is a deprecated alias of `create --empty`; on servers that
304
+ predate `create`, `--empty` falls back to the old request endpoint.
232
305
  `extract` reads the leaked literal from the scenario on your machine, creates
233
306
  the secret with it, then rewrites every occurrence to `{{secret:NAME}}`. Older
234
307
  scenario versions and past run logs may still hold the literal: rotate it.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "minitest-cli"
3
- version = "0.40.0"
3
+ version = "0.41.0"
4
4
  description = "Minitest CLI – command-line interface for the Minitest testing platform"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -32,6 +32,7 @@ dependencies = [
32
32
  "pydantic>=2.12.5",
33
33
  "pydantic-settings>=2.13.1",
34
34
  "rich>=14.3.3",
35
+ "pyyaml>=6.0.3",
35
36
  ]
36
37
 
37
38
  [project.optional-dependencies]
@@ -0,0 +1,140 @@
1
+ """`minitest glossary`: the app's product terms, their meaning and aliases."""
2
+
3
+ from typing import Annotated, Any
4
+
5
+ import typer
6
+
7
+ from minitest_cli.api.client import ApiClient
8
+ from minitest_cli.commands.knowledge_helpers import (
9
+ app_path,
10
+ call_for_app,
11
+ check_response,
12
+ describe_actor,
13
+ )
14
+ from minitest_cli.commands.user_story_helpers import EXIT_NOT_FOUND, is_json_mode
15
+ from minitest_cli.utils.confirm import confirm_or_exit
16
+ from minitest_cli.utils.output import output, print_error, print_info, print_success, print_table
17
+
18
+ app = typer.Typer(
19
+ name="glossary",
20
+ help="Glossary: product terms Mini must understand, with their meaning and aliases.",
21
+ no_args_is_help=True,
22
+ )
23
+
24
+ TermRef = Annotated[str, typer.Argument(help="Term ID, or the term itself (case-insensitive).")]
25
+ AliasOption = Annotated[
26
+ list[str] | None,
27
+ typer.Option("--alias", help="Other name for the term (repeatable; replaces the aliases)."),
28
+ ]
29
+
30
+
31
+ async def _fetch_terms(client: ApiClient, app_id: str) -> list[dict[str, Any]]:
32
+ resp = await client.get(app_path(app_id, "glossary"))
33
+ check_response(resp, resource="Glossary")
34
+ return resp.json().get("terms", [])
35
+
36
+
37
+ def _find_term(terms: list[dict[str, Any]], ref: str) -> dict[str, Any]:
38
+ wanted = ref.strip().casefold()
39
+ for term in terms:
40
+ if term.get("id") == ref or str(term.get("term", "")).casefold() == wanted:
41
+ return term
42
+ print_error(f"Glossary term not found: {ref}. Run `minitest glossary list` to see the terms.")
43
+ raise typer.Exit(code=EXIT_NOT_FOUND)
44
+
45
+
46
+ @app.command(name="list")
47
+ def list_terms() -> None:
48
+ """List every term with its meaning, aliases and last author."""
49
+ terms = call_for_app(_fetch_terms)
50
+ if is_json_mode():
51
+ output({"terms": terms}, json_mode=True)
52
+ return
53
+ if not terms:
54
+ print_info("No glossary terms yet. Add one with `minitest glossary add`.")
55
+ return
56
+ rows = [
57
+ [
58
+ t.get("term", ""),
59
+ t.get("meaning", ""),
60
+ ", ".join(t.get("aliases") or []),
61
+ describe_actor(t.get("actor")),
62
+ t.get("id", ""),
63
+ ]
64
+ for t in terms
65
+ ]
66
+ print_table(["Term", "Meaning", "Aliases", "Last edited by", "ID"], rows, title="Glossary")
67
+
68
+
69
+ @app.command(name="add")
70
+ def add_term(
71
+ term: Annotated[str, typer.Option("--term", help="The product term, as users say it.")],
72
+ meaning: Annotated[str, typer.Option("--meaning", help="What the term means in this app.")],
73
+ alias: AliasOption = None,
74
+ ) -> None:
75
+ """Add a term to the glossary."""
76
+ body = {"term": term, "meaning": meaning, "aliases": alias or []}
77
+
78
+ async def _add(client: ApiClient, app_id: str) -> dict[str, Any]:
79
+ resp = await client.post(app_path(app_id, "glossary"), json=body)
80
+ check_response(resp, resource="Glossary")
81
+ return resp.json()
82
+
83
+ created = call_for_app(_add)
84
+ if not is_json_mode():
85
+ print_success(f"Glossary term added: {created.get('term')} ({created.get('id')})")
86
+ output(created, json_mode=is_json_mode())
87
+
88
+
89
+ @app.command(name="update")
90
+ def update_term(
91
+ term_ref: TermRef,
92
+ term: Annotated[str | None, typer.Option("--term", help="Rename the term.")] = None,
93
+ meaning: Annotated[str | None, typer.Option("--meaning", help="New meaning.")] = None,
94
+ alias: AliasOption = None,
95
+ clear_aliases: Annotated[
96
+ bool, typer.Option("--clear-aliases", help="Remove every alias. Excludes --alias.")
97
+ ] = False,
98
+ ) -> None:
99
+ """Change a term's name, meaning or aliases."""
100
+ if clear_aliases and alias:
101
+ print_error("Use either --alias or --clear-aliases, not both.")
102
+ raise typer.Exit(code=1)
103
+ fields: dict[str, Any] = {"term": term, "meaning": meaning}
104
+ fields["aliases"] = [] if clear_aliases else alias or None
105
+ payload = {key: value for key, value in fields.items() if value is not None}
106
+ if not payload:
107
+ print_error("Provide at least one of --term, --meaning, --alias or --clear-aliases.")
108
+ raise typer.Exit(code=1)
109
+
110
+ async def _update(client: ApiClient, app_id: str) -> dict[str, Any]:
111
+ found = _find_term(await _fetch_terms(client, app_id), term_ref)
112
+ resp = await client.patch(app_path(app_id, f"glossary/{found['id']}"), json=payload)
113
+ check_response(resp, resource="Glossary term")
114
+ return resp.json()
115
+
116
+ updated = call_for_app(_update)
117
+ if not is_json_mode():
118
+ print_success(f"Glossary term updated: {updated.get('term')}")
119
+ output(updated, json_mode=is_json_mode())
120
+
121
+
122
+ @app.command(name="remove")
123
+ def remove_term(
124
+ term_ref: TermRef,
125
+ yes: Annotated[bool, typer.Option("--yes", help="Confirm the removal.")] = False,
126
+ ) -> None:
127
+ """Remove a term from the glossary (kept in its history)."""
128
+ confirm_or_exit(yes, f"Removing glossary term {term_ref!r}")
129
+
130
+ async def _remove(client: ApiClient, app_id: str) -> dict[str, Any]:
131
+ found = _find_term(await _fetch_terms(client, app_id), term_ref)
132
+ resp = await client.delete(app_path(app_id, f"glossary/{found['id']}"))
133
+ check_response(resp, resource="Glossary term")
134
+ return found
135
+
136
+ removed = call_for_app(_remove)
137
+ if is_json_mode():
138
+ output({"removed": True, "id": removed["id"], "term": removed["term"]}, json_mode=True)
139
+ else:
140
+ print_success(f"Glossary term removed: {removed['term']}")
@@ -0,0 +1,105 @@
1
+ """`minitest knowledge history|revert`: who changed the Product brief, App guide or Glossary."""
2
+
3
+ from enum import StrEnum
4
+ from typing import Annotated, Any
5
+
6
+ import typer
7
+
8
+ from minitest_cli.api.client import ApiClient
9
+ from minitest_cli.commands.knowledge_helpers import (
10
+ app_path,
11
+ call_for_app,
12
+ check_response,
13
+ describe_actor,
14
+ )
15
+ from minitest_cli.commands.user_story_helpers import is_json_mode
16
+ from minitest_cli.utils.output import output, print_info, print_success, print_table
17
+
18
+ app = typer.Typer(
19
+ name="knowledge",
20
+ help="Change history of the Product brief, App guide and Glossary, and reverts.",
21
+ no_args_is_help=True,
22
+ )
23
+
24
+
25
+ class KnowledgeElement(StrEnum):
26
+ product_brief = "product_brief"
27
+ app_guide = "app_guide"
28
+ glossary = "glossary"
29
+
30
+
31
+ @app.callback()
32
+ def _callback() -> None:
33
+ """Knowledge operations."""
34
+
35
+
36
+ @app.command(name="history")
37
+ def history(
38
+ element: Annotated[
39
+ KnowledgeElement | None,
40
+ typer.Option("--element", help="Only this element (default: all three, merged)."),
41
+ ] = None,
42
+ limit: Annotated[int, typer.Option("--limit", min=1, max=200, help="Max changes.")] = 20,
43
+ ) -> None:
44
+ """List recent changes, newest first, with author, channel and version."""
45
+ elements = [element] if element else list(KnowledgeElement)
46
+
47
+ async def _history(client: ApiClient, app_id: str) -> list[dict[str, Any]]:
48
+ changes: list[dict[str, Any]] = []
49
+ for wanted in elements:
50
+ resp = await client.get(
51
+ app_path(app_id, "knowledge/history"),
52
+ params={"element": wanted.value, "limit": limit},
53
+ )
54
+ check_response(resp, resource="Knowledge history")
55
+ changes.extend(resp.json())
56
+ changes.sort(key=lambda change: change.get("createdAt") or "", reverse=True)
57
+ return changes[:limit]
58
+
59
+ changes = call_for_app(_history)
60
+ if is_json_mode():
61
+ output(changes, json_mode=True)
62
+ return
63
+ if not changes:
64
+ print_info("No knowledge changes yet.")
65
+ return
66
+ rows = [
67
+ [
68
+ c.get("createdAt", ""),
69
+ c.get("element", ""),
70
+ c.get("change", ""),
71
+ _subject(c),
72
+ describe_actor(c.get("actor")),
73
+ c.get("versionId", ""),
74
+ ]
75
+ for c in changes
76
+ ]
77
+ print_table(["When", "Element", "Change", "Version / term", "By", "Version ID"], rows)
78
+
79
+
80
+ def _subject(change: dict[str, Any]) -> str:
81
+ if change.get("versionNumber") is not None:
82
+ return f"v{change['versionNumber']}"
83
+ after = change.get("after") if isinstance(change.get("after"), dict) else None
84
+ before = change.get("before") if isinstance(change.get("before"), dict) else None
85
+ snapshot = after or before or {}
86
+ return str(snapshot.get("term") or change.get("termId") or "")
87
+
88
+
89
+ @app.command(name="revert")
90
+ def revert(
91
+ version_id: Annotated[
92
+ str, typer.Argument(help="Version ID from `minitest knowledge history`.")
93
+ ],
94
+ ) -> None:
95
+ """Restore an element to that version, recorded as a new 'reverted' change."""
96
+
97
+ async def _revert(client: ApiClient, app_id: str) -> None:
98
+ resp = await client.post(app_path(app_id, f"knowledge/history/{version_id}/revert"))
99
+ check_response(resp, resource="Knowledge version")
100
+
101
+ call_for_app(_revert)
102
+ if is_json_mode():
103
+ output({"versionId": version_id, "reverted": True}, json_mode=True)
104
+ return
105
+ print_success(f"Reverted to version {version_id}.")
@@ -0,0 +1,86 @@
1
+ """`minitest brief` and `minitest app-guide`: the two versioned Knowledge v2 documents."""
2
+
3
+ from typing import Any
4
+
5
+ import typer
6
+
7
+ from minitest_cli.api.client import ApiClient
8
+ from minitest_cli.commands.knowledge_helpers import (
9
+ ContentFileOption,
10
+ ContentOption,
11
+ app_path,
12
+ call_for_app,
13
+ check_response,
14
+ describe_actor,
15
+ resolve_content,
16
+ )
17
+ from minitest_cli.commands.user_story_helpers import is_json_mode
18
+ from minitest_cli.utils.output import output, print_info, print_success
19
+
20
+
21
+ def _document_app(name: str, route: str, label: str, help_text: str) -> typer.Typer:
22
+ group = typer.Typer(name=name, help=help_text, no_args_is_help=True)
23
+
24
+ @group.command(name="get")
25
+ def get_document() -> None:
26
+ """Print the current content (with --json: content, version and author)."""
27
+
28
+ async def _get(client: ApiClient, app_id: str) -> dict[str, Any]:
29
+ resp = await client.get(app_path(app_id, route))
30
+ check_response(resp, resource=label)
31
+ return resp.json()
32
+
33
+ record = call_for_app(_get)
34
+ if is_json_mode():
35
+ output(record, json_mode=True)
36
+ return
37
+ if not record.get("content"):
38
+ print_info(f"No {label} written yet.")
39
+ return
40
+ print_info(_version_line(record))
41
+ print(record["content"]) # noqa: T201
42
+
43
+ @group.command(name="update")
44
+ def update_document(
45
+ content: ContentOption = None, content_file: ContentFileOption = None
46
+ ) -> None:
47
+ """Replace the content, creating a new version authored by you via the CLI."""
48
+ body = {"content": resolve_content(content, content_file)}
49
+
50
+ async def _put(client: ApiClient, app_id: str) -> dict[str, Any]:
51
+ resp = await client.put(app_path(app_id, route), json=body)
52
+ check_response(resp, resource=label)
53
+ return resp.json()
54
+
55
+ record = call_for_app(_put)
56
+ if is_json_mode():
57
+ output(record, json_mode=True)
58
+ return
59
+ print_success(f"{label} updated (version {record.get('versionNumber')}).")
60
+ print(record.get("versionNumber")) # noqa: T201
61
+
62
+ return group
63
+
64
+
65
+ def _version_line(record: dict[str, Any]) -> str:
66
+ author = describe_actor(record.get("actor"))
67
+ line = f"Version {record.get('versionNumber')}"
68
+ if author:
69
+ line += f" by {author}"
70
+ if record.get("createdAt"):
71
+ line += f", {record['createdAt']}"
72
+ return line
73
+
74
+
75
+ brief_app = _document_app(
76
+ "brief",
77
+ "product-brief",
78
+ "Product brief",
79
+ "Product brief: what the app is, who uses it and its core flows (max 2000 chars).",
80
+ )
81
+ app_guide_app = _document_app(
82
+ "app-guide",
83
+ "app-guide",
84
+ "App guide",
85
+ "App guide: how to use the app when testing it (navigation, quirks, test data).",
86
+ )