testo-core 1.1.1__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 (289) hide show
  1. testo_core-1.1.1/.gitignore +76 -0
  2. testo_core-1.1.1/CHANGELOG.md +252 -0
  3. testo_core-1.1.1/LICENSE +21 -0
  4. testo_core-1.1.1/PKG-INFO +310 -0
  5. testo_core-1.1.1/README.md +238 -0
  6. testo_core-1.1.1/pyproject.toml +166 -0
  7. testo_core-1.1.1/pytest.ini +29 -0
  8. testo_core-1.1.1/testo_api/__init__.py +3 -0
  9. testo_core-1.1.1/testo_api/cycle_execution_manager.py +539 -0
  10. testo_core-1.1.1/testo_api/dependencies.py +21 -0
  11. testo_core-1.1.1/testo_api/main.py +162 -0
  12. testo_core-1.1.1/testo_api/models.py +408 -0
  13. testo_core-1.1.1/testo_api/routes/__init__.py +1 -0
  14. testo_core-1.1.1/testo_api/routes/ai.py +100 -0
  15. testo_core-1.1.1/testo_api/routes/analytics.py +141 -0
  16. testo_core-1.1.1/testo_api/routes/cycles.py +214 -0
  17. testo_core-1.1.1/testo_api/routes/dashboard.py +121 -0
  18. testo_core-1.1.1/testo_api/routes/health.py +46 -0
  19. testo_core-1.1.1/testo_api/routes/history.py +149 -0
  20. testo_core-1.1.1/testo_api/security.py +77 -0
  21. testo_core-1.1.1/testo_core/__init__.py +65 -0
  22. testo_core-1.1.1/testo_core/cli/__init__.py +5 -0
  23. testo_core-1.1.1/testo_core/cli/app.py +161 -0
  24. testo_core-1.1.1/testo_core/cli/cleanup.py +42 -0
  25. testo_core-1.1.1/testo_core/cli/commands/__init__.py +6 -0
  26. testo_core-1.1.1/testo_core/cli/commands/clean.py +75 -0
  27. testo_core-1.1.1/testo_core/cli/commands/config.py +127 -0
  28. testo_core-1.1.1/testo_core/cli/commands/config_db.py +140 -0
  29. testo_core-1.1.1/testo_core/cli/commands/diff_cli.py +112 -0
  30. testo_core-1.1.1/testo_core/cli/commands/doctor.py +161 -0
  31. testo_core-1.1.1/testo_core/cli/commands/init_cmd.py +65 -0
  32. testo_core-1.1.1/testo_core/cli/commands/plans.py +92 -0
  33. testo_core-1.1.1/testo_core/cli/commands/report.py +424 -0
  34. testo_core-1.1.1/testo_core/cli/commands/run.py +100 -0
  35. testo_core-1.1.1/testo_core/cli/commands/version.py +18 -0
  36. testo_core-1.1.1/testo_core/cli/commands/watch.py +135 -0
  37. testo_core-1.1.1/testo_core/cli/runner.py +211 -0
  38. testo_core-1.1.1/testo_core/cli/ui/__init__.py +5 -0
  39. testo_core-1.1.1/testo_core/cli/ui/ci_renderer.py +19 -0
  40. testo_core-1.1.1/testo_core/cli/ui/console.py +65 -0
  41. testo_core-1.1.1/testo_core/cli/ui/panels.py +128 -0
  42. testo_core-1.1.1/testo_core/cli/ui/progress.py +29 -0
  43. testo_core-1.1.1/testo_core/cli/ui/renderers.py +178 -0
  44. testo_core-1.1.1/testo_core/cli/ui/summary_dashboard.py +345 -0
  45. testo_core-1.1.1/testo_core/config/__init__.py +28 -0
  46. testo_core-1.1.1/testo_core/config/database_section.py +165 -0
  47. testo_core-1.1.1/testo_core/config/errors.py +29 -0
  48. testo_core-1.1.1/testo_core/config/loader.py +458 -0
  49. testo_core-1.1.1/testo_core/config/resolver.py +95 -0
  50. testo_core-1.1.1/testo_core/config/schema.py +117 -0
  51. testo_core-1.1.1/testo_core/config/triggers.py +294 -0
  52. testo_core-1.1.1/testo_core/engine/__init__.py +30 -0
  53. testo_core-1.1.1/testo_core/engine/events.py +46 -0
  54. testo_core-1.1.1/testo_core/engine/executor.py +256 -0
  55. testo_core-1.1.1/testo_core/engine/exit_codes.py +45 -0
  56. testo_core-1.1.1/testo_core/engine/log_buffer.py +144 -0
  57. testo_core-1.1.1/testo_core/engine/orchestrator.py +246 -0
  58. testo_core-1.1.1/testo_core/engine/result.py +51 -0
  59. testo_core-1.1.1/testo_core/frameworks/__init__.py +21 -0
  60. testo_core-1.1.1/testo_core/frameworks/base.py +73 -0
  61. testo_core-1.1.1/testo_core/frameworks/behave_adapter.py +49 -0
  62. testo_core-1.1.1/testo_core/frameworks/behavex_adapter.py +82 -0
  63. testo_core-1.1.1/testo_core/frameworks/command_adapter.py +41 -0
  64. testo_core-1.1.1/testo_core/frameworks/pytest_adapter.py +121 -0
  65. testo_core-1.1.1/testo_core/history/__init__.py +16 -0
  66. testo_core-1.1.1/testo_core/history/maintenance.py +46 -0
  67. testo_core-1.1.1/testo_core/history/read_model.py +52 -0
  68. testo_core-1.1.1/testo_core/history/report_links.py +45 -0
  69. testo_core-1.1.1/testo_core/history/snapshots.py +21 -0
  70. testo_core-1.1.1/testo_core/history/views.py +122 -0
  71. testo_core-1.1.1/testo_core/mascot/__init__.py +422 -0
  72. testo_core-1.1.1/testo_core/mascot/__main__.py +30 -0
  73. testo_core-1.1.1/testo_core/mascot/export_ts.py +51 -0
  74. testo_core-1.1.1/testo_core/mascot/render.py +114 -0
  75. testo_core-1.1.1/testo_core/paths.py +102 -0
  76. testo_core-1.1.1/testo_core/persistence/__init__.py +23 -0
  77. testo_core-1.1.1/testo_core/persistence/backend.py +21 -0
  78. testo_core-1.1.1/testo_core/persistence/composite.py +50 -0
  79. testo_core-1.1.1/testo_core/persistence/db_backend.py +128 -0
  80. testo_core-1.1.1/testo_core/persistence/failure_context.py +112 -0
  81. testo_core-1.1.1/testo_core/persistence/health.py +109 -0
  82. testo_core-1.1.1/testo_core/persistence/json_backend.py +63 -0
  83. testo_core-1.1.1/testo_core/reporting/__init__.py +11 -0
  84. testo_core-1.1.1/testo_core/reporting/allure.py +84 -0
  85. testo_core-1.1.1/testo_core/reporting/allure_cli.py +212 -0
  86. testo_core-1.1.1/testo_core/reporting/allure_results.py +232 -0
  87. testo_core-1.1.1/testo_core/reporting/collector.py +144 -0
  88. testo_core-1.1.1/testo_core/reporting/entry.py +129 -0
  89. testo_core-1.1.1/testo_core/reporting/exporter.py +151 -0
  90. testo_core-1.1.1/testo_core/reporting/history_inject.py +76 -0
  91. testo_core-1.1.1/testo_core/reporting/integrations.py +232 -0
  92. testo_core-1.1.1/testo_core/reporting/junit_import.py +161 -0
  93. testo_core-1.1.1/testo_core/reporting/metrics.py +191 -0
  94. testo_core-1.1.1/testo_core/reporting/metrics_extractor.py +187 -0
  95. testo_core-1.1.1/testo_core/reporting/native_reports.py +277 -0
  96. testo_core-1.1.1/testo_core/reporting/paths.py +81 -0
  97. testo_core-1.1.1/testo_core/reporting/pyramid_data.py +33 -0
  98. testo_core-1.1.1/testo_core/reporting/pyramid_viz.py +120 -0
  99. testo_core-1.1.1/testo_core/reporting/report_generator.py +537 -0
  100. testo_core-1.1.1/testo_core/reporting/reporters/__init__.py +14 -0
  101. testo_core-1.1.1/testo_core/reporting/reporters/allure_reporter.py +137 -0
  102. testo_core-1.1.1/testo_core/reporting/reporters/base.py +63 -0
  103. testo_core-1.1.1/testo_core/reporting/reporters/extent_builder.py +106 -0
  104. testo_core-1.1.1/testo_core/reporting/reporters/extent_reporter.py +61 -0
  105. testo_core-1.1.1/testo_core/reporting/reporters/factory.py +122 -0
  106. testo_core-1.1.1/testo_core/reporting/reporters/orchestrate.py +93 -0
  107. testo_core-1.1.1/testo_core/reporting/reporters/reportportal_client.py +367 -0
  108. testo_core-1.1.1/testo_core/reporting/reporters/reportportal_reporter.py +97 -0
  109. testo_core-1.1.1/testo_core/reporting/reporters/templates/extent_dashboard.html.j2 +244 -0
  110. testo_core-1.1.1/testo_core/reporting/reporters/testbeats_payloads.py +197 -0
  111. testo_core-1.1.1/testo_core/reporting/reporters/testbeats_reporter.py +115 -0
  112. testo_core-1.1.1/testo_core/reporting/server.py +140 -0
  113. testo_core-1.1.1/testo_core/repository/__init__.py +15 -0
  114. testo_core-1.1.1/testo_core/repository/adapters.py +137 -0
  115. testo_core-1.1.1/testo_core/repository/base.py +62 -0
  116. testo_core-1.1.1/testo_core/repository/db.py +31 -0
  117. testo_core-1.1.1/testo_core/repository/db_config.py +117 -0
  118. testo_core-1.1.1/testo_core/repository/factory.py +115 -0
  119. testo_core-1.1.1/testo_core/repository/models.py +87 -0
  120. testo_core-1.1.1/testo_core/repository/report_archive_repository.py +90 -0
  121. testo_core-1.1.1/testo_core/security/__init__.py +15 -0
  122. testo_core-1.1.1/testo_core/security/redaction.py +53 -0
  123. testo_core-1.1.1/testo_core/services/__init__.py +86 -0
  124. testo_core-1.1.1/testo_core/services/ai/__init__.py +33 -0
  125. testo_core-1.1.1/testo_core/services/ai/config.py +54 -0
  126. testo_core-1.1.1/testo_core/services/ai/factory.py +18 -0
  127. testo_core-1.1.1/testo_core/services/ai/integration_settings.py +66 -0
  128. testo_core-1.1.1/testo_core/services/ai/provider_base.py +54 -0
  129. testo_core-1.1.1/testo_core/services/ai/providers/__init__.py +4 -0
  130. testo_core-1.1.1/testo_core/services/ai/providers/anthropic_provider.py +76 -0
  131. testo_core-1.1.1/testo_core/services/ai/providers/openai_provider.py +78 -0
  132. testo_core-1.1.1/testo_core/services/ci_provenance.py +84 -0
  133. testo_core-1.1.1/testo_core/services/cycle_run.py +355 -0
  134. testo_core-1.1.1/testo_core/services/dashboard_service.py +341 -0
  135. testo_core-1.1.1/testo_core/services/delta_models.py +61 -0
  136. testo_core-1.1.1/testo_core/services/delta_service.py +284 -0
  137. testo_core-1.1.1/testo_core/services/failure_analysis_service.py +192 -0
  138. testo_core-1.1.1/testo_core/services/failure_context_builder.py +105 -0
  139. testo_core-1.1.1/testo_core/services/metrics_service.py +41 -0
  140. testo_core-1.1.1/testo_core/services/report_archive.py +160 -0
  141. testo_core-1.1.1/testo_core/services/report_archive_diff.py +191 -0
  142. testo_core-1.1.1/testo_core/services/report_service.py +121 -0
  143. testo_core-1.1.1/testo_core/services/run_snapshot_diff.py +37 -0
  144. testo_core-1.1.1/tests/README.md +11 -0
  145. testo_core-1.1.1/tests/TEST_LAYOUT.md +58 -0
  146. testo_core-1.1.1/tests/__init__.py +1 -0
  147. testo_core-1.1.1/tests/_allure_utils.py +41 -0
  148. testo_core-1.1.1/tests/conftest.py +412 -0
  149. testo_core-1.1.1/tests/contract/api/test_adhoc_executions_contract.py +98 -0
  150. testo_core-1.1.1/tests/contract/api/test_ai_contract.py +118 -0
  151. testo_core-1.1.1/tests/contract/api/test_analytics_contract.py +333 -0
  152. testo_core-1.1.1/tests/contract/api/test_cycle_executions_contract.py +97 -0
  153. testo_core-1.1.1/tests/contract/api/test_cycles_contract.py +93 -0
  154. testo_core-1.1.1/tests/contract/api/test_dashboard_contract.py +136 -0
  155. testo_core-1.1.1/tests/contract/api/test_history_contract.py +197 -0
  156. testo_core-1.1.1/tests/contract/api/test_security_contract.py +136 -0
  157. testo_core-1.1.1/tests/contract/ci/test_tiered_ci_contract.py +48 -0
  158. testo_core-1.1.1/tests/contract/ci/test_wrapper_contract.py +41 -0
  159. testo_core-1.1.1/tests/contract/testo_core/test_cli_docs_drift.py +61 -0
  160. testo_core-1.1.1/tests/contract/testo_core/test_docs_vault.py +78 -0
  161. testo_core-1.1.1/tests/contract/testo_core/test_exit_code_contract.py +82 -0
  162. testo_core-1.1.1/tests/contract/testo_core/test_packaging_contract.py +67 -0
  163. testo_core-1.1.1/tests/contract/testo_core/test_repository_contract.py +42 -0
  164. testo_core-1.1.1/tests/contract/testo_core/test_run_metadata_contract.py +145 -0
  165. testo_core-1.1.1/tests/contracts/models.py +76 -0
  166. testo_core-1.1.1/tests/contracts/test_mock_api_contracts.py +142 -0
  167. testo_core-1.1.1/tests/e2e/__init__.py +1 -0
  168. testo_core-1.1.1/tests/e2e/flows/__init__.py +1 -0
  169. testo_core-1.1.1/tests/e2e/flows/flow_runner.py +39 -0
  170. testo_core-1.1.1/tests/e2e/flows/flow_scenario.py +42 -0
  171. testo_core-1.1.1/tests/e2e/flows/test_external_provider_lifecycle.py +78 -0
  172. testo_core-1.1.1/tests/e2e/flows/test_plugin_mocked_paths.py +78 -0
  173. testo_core-1.1.1/tests/e2e/provisioners/__init__.py +1 -0
  174. testo_core-1.1.1/tests/e2e/provisioners/github.py +68 -0
  175. testo_core-1.1.1/tests/e2e/provisioners/gitlab.py +70 -0
  176. testo_core-1.1.1/tests/e2e/provisioners/local.py +11 -0
  177. testo_core-1.1.1/tests/e2e/provisioners/mock_github.py +12 -0
  178. testo_core-1.1.1/tests/e2e/provisioners/mock_gitlab.py +12 -0
  179. testo_core-1.1.1/tests/e2e/sandbox_api/test_user_journeys.py +87 -0
  180. testo_core-1.1.1/tests/e2e/verifiers/__init__.py +1 -0
  181. testo_core-1.1.1/tests/e2e/verifiers/artifact_bundle.py +32 -0
  182. testo_core-1.1.1/tests/e2e/verifiers/cleanup_audit.py +10 -0
  183. testo_core-1.1.1/tests/e2e/verifiers/provider_status.py +10 -0
  184. testo_core-1.1.1/tests/fixtures/__init__.py +1 -0
  185. testo_core-1.1.1/tests/fixtures/ci/github_workflow_minimal.yml +13 -0
  186. testo_core-1.1.1/tests/fixtures/e2e/github_workflow_e2e.yml +9 -0
  187. testo_core-1.1.1/tests/fixtures/e2e/gitlab_pipeline_e2e.yml +9 -0
  188. testo_core-1.1.1/tests/fixtures/e2e/local.external.env.sample +10 -0
  189. testo_core-1.1.1/tests/fixtures/e2e/local.fast.env.sample +5 -0
  190. testo_core-1.1.1/tests/fixtures/e2e/local.heavy.env.sample +5 -0
  191. testo_core-1.1.1/tests/fixtures/e2e/sample_plugin.py +5 -0
  192. testo_core-1.1.1/tests/fixtures/e2e/sample_repo_config.yaml +6 -0
  193. testo_core-1.1.1/tests/fixtures/engine/__init__.py +233 -0
  194. testo_core-1.1.1/tests/fixtures/engine/scripts/echo.py +37 -0
  195. testo_core-1.1.1/tests/fixtures/engine/scripts/hang.py +9 -0
  196. testo_core-1.1.1/tests/integration/api/test_history_endpoints.py +35 -0
  197. testo_core-1.1.1/tests/integration/sandbox_api/conftest.py +36 -0
  198. testo_core-1.1.1/tests/integration/sandbox_api/test_auth_flow.py +32 -0
  199. testo_core-1.1.1/tests/integration/sandbox_api/test_chaos_flow.py +48 -0
  200. testo_core-1.1.1/tests/integration/sandbox_api/test_items_flow.py +41 -0
  201. testo_core-1.1.1/tests/integration/sandbox_api/test_upload_flow.py +46 -0
  202. testo_core-1.1.1/tests/integration/testo_core/engine/test_subprocess_smoke.py +119 -0
  203. testo_core-1.1.1/tests/unit/cases/json_payloads.py +22 -0
  204. testo_core-1.1.1/tests/unit/cases/paths.py +22 -0
  205. testo_core-1.1.1/tests/unit/cases/strings.py +26 -0
  206. testo_core-1.1.1/tests/unit/ci/test_e2e_artifact_redaction.py +16 -0
  207. testo_core-1.1.1/tests/unit/ci/test_export_static_site.py +125 -0
  208. testo_core-1.1.1/tests/unit/ci/test_github_action_wrapper.py +97 -0
  209. testo_core-1.1.1/tests/unit/ci/test_gitlab_pages_demo_contract.py +125 -0
  210. testo_core-1.1.1/tests/unit/ci/test_gitlab_template_contract.py +22 -0
  211. testo_core-1.1.1/tests/unit/ci/test_marker_tiering_contract.py +26 -0
  212. testo_core-1.1.1/tests/unit/test_cycle_execution_manager.py +310 -0
  213. testo_core-1.1.1/tests/unit/test_defaults_and_placeholders.py +21 -0
  214. testo_core-1.1.1/tests/unit/testo_core/cli/conftest.py +23 -0
  215. testo_core-1.1.1/tests/unit/testo_core/cli/test_cli_commands_smoke.py +61 -0
  216. testo_core-1.1.1/tests/unit/testo_core/cli/test_config_discovery.py +127 -0
  217. testo_core-1.1.1/tests/unit/testo_core/cli/test_run_archive.py +152 -0
  218. testo_core-1.1.1/tests/unit/testo_core/cli/test_run_ci_ndjson.py +205 -0
  219. testo_core-1.1.1/tests/unit/testo_core/cli/test_run_exit_codes.py +196 -0
  220. testo_core-1.1.1/tests/unit/testo_core/cli/test_run_flags.py +226 -0
  221. testo_core-1.1.1/tests/unit/testo_core/engine/test_executor.py +236 -0
  222. testo_core-1.1.1/tests/unit/testo_core/engine/test_exit_codes.py +72 -0
  223. testo_core-1.1.1/tests/unit/testo_core/engine/test_log_buffer.py +115 -0
  224. testo_core-1.1.1/tests/unit/testo_core/engine/test_orchestrator.py +176 -0
  225. testo_core-1.1.1/tests/unit/testo_core/engine/test_orchestrator_lifecycle.py +345 -0
  226. testo_core-1.1.1/tests/unit/testo_core/test_ai_config_model.py +14 -0
  227. testo_core-1.1.1/tests/unit/testo_core/test_ai_provider_abstraction.py +30 -0
  228. testo_core-1.1.1/tests/unit/testo_core/test_allure_cli.py +60 -0
  229. testo_core-1.1.1/tests/unit/testo_core/test_allure_reporter.py +82 -0
  230. testo_core-1.1.1/tests/unit/testo_core/test_behave_adapter.py +11 -0
  231. testo_core-1.1.1/tests/unit/testo_core/test_behavex_adapter.py +52 -0
  232. testo_core-1.1.1/tests/unit/testo_core/test_ci_provenance.py +81 -0
  233. testo_core-1.1.1/tests/unit/testo_core/test_cli_app.py +23 -0
  234. testo_core-1.1.1/tests/unit/testo_core/test_cli_clean.py +96 -0
  235. testo_core-1.1.1/tests/unit/testo_core/test_cli_config_db.py +94 -0
  236. testo_core-1.1.1/tests/unit/testo_core/test_cli_diff.py +163 -0
  237. testo_core-1.1.1/tests/unit/testo_core/test_cli_doctor.py +76 -0
  238. testo_core-1.1.1/tests/unit/testo_core/test_cli_help_panels.py +22 -0
  239. testo_core-1.1.1/tests/unit/testo_core/test_cli_init.py +79 -0
  240. testo_core-1.1.1/tests/unit/testo_core/test_cli_report_archive.py +94 -0
  241. testo_core-1.1.1/tests/unit/testo_core/test_cli_version_flag.py +37 -0
  242. testo_core-1.1.1/tests/unit/testo_core/test_cli_watch.py +79 -0
  243. testo_core-1.1.1/tests/unit/testo_core/test_command_adapter.py +265 -0
  244. testo_core-1.1.1/tests/unit/testo_core/test_config_resolver.py +74 -0
  245. testo_core-1.1.1/tests/unit/testo_core/test_cycle_config_triggers.py +124 -0
  246. testo_core-1.1.1/tests/unit/testo_core/test_cycle_run_service.py +253 -0
  247. testo_core-1.1.1/tests/unit/testo_core/test_dashboard_service.py +202 -0
  248. testo_core-1.1.1/tests/unit/testo_core/test_database_url_resolution.py +107 -0
  249. testo_core-1.1.1/tests/unit/testo_core/test_delta_service.py +217 -0
  250. testo_core-1.1.1/tests/unit/testo_core/test_failure_analysis_service.py +423 -0
  251. testo_core-1.1.1/tests/unit/testo_core/test_failure_context_builder.py +112 -0
  252. testo_core-1.1.1/tests/unit/testo_core/test_flow_runner_harness.py +64 -0
  253. testo_core-1.1.1/tests/unit/testo_core/test_history.py +175 -0
  254. testo_core-1.1.1/tests/unit/testo_core/test_integrations_branch_matrix.py +116 -0
  255. testo_core-1.1.1/tests/unit/testo_core/test_integrations_more.py +124 -0
  256. testo_core-1.1.1/tests/unit/testo_core/test_integrations_unit.py +19 -0
  257. testo_core-1.1.1/tests/unit/testo_core/test_metrics.py +52 -0
  258. testo_core-1.1.1/tests/unit/testo_core/test_metrics_advanced.py +26 -0
  259. testo_core-1.1.1/tests/unit/testo_core/test_metrics_extractor_more.py +47 -0
  260. testo_core-1.1.1/tests/unit/testo_core/test_metrics_extractor_unit.py +25 -0
  261. testo_core-1.1.1/tests/unit/testo_core/test_native_report_snapshot.py +73 -0
  262. testo_core-1.1.1/tests/unit/testo_core/test_native_reports.py +131 -0
  263. testo_core-1.1.1/tests/unit/testo_core/test_paths.py +43 -0
  264. testo_core-1.1.1/tests/unit/testo_core/test_paths_behave_native.py +15 -0
  265. testo_core-1.1.1/tests/unit/testo_core/test_persistence_backends.py +421 -0
  266. testo_core-1.1.1/tests/unit/testo_core/test_persistence_failure_context.py +126 -0
  267. testo_core-1.1.1/tests/unit/testo_core/test_pyramid_data.py +97 -0
  268. testo_core-1.1.1/tests/unit/testo_core/test_pyramid_viz.py +46 -0
  269. testo_core-1.1.1/tests/unit/testo_core/test_pytest_adapter.py +173 -0
  270. testo_core-1.1.1/tests/unit/testo_core/test_redaction.py +34 -0
  271. testo_core-1.1.1/tests/unit/testo_core/test_report_archive.py +124 -0
  272. testo_core-1.1.1/tests/unit/testo_core/test_report_archive_diff.py +219 -0
  273. testo_core-1.1.1/tests/unit/testo_core/test_report_generator.py +138 -0
  274. testo_core-1.1.1/tests/unit/testo_core/test_report_generator_branch_matrix.py +41 -0
  275. testo_core-1.1.1/tests/unit/testo_core/test_report_generator_helpers.py +28 -0
  276. testo_core-1.1.1/tests/unit/testo_core/test_report_generator_http.py +28 -0
  277. testo_core-1.1.1/tests/unit/testo_core/test_report_generator_static_sync.py +53 -0
  278. testo_core-1.1.1/tests/unit/testo_core/test_report_history_inject.py +117 -0
  279. testo_core-1.1.1/tests/unit/testo_core/test_report_service_more.py +44 -0
  280. testo_core-1.1.1/tests/unit/testo_core/test_reporters_config.py +83 -0
  281. testo_core-1.1.1/tests/unit/testo_core/test_reporting_paths.py +128 -0
  282. testo_core-1.1.1/tests/unit/testo_core/test_reporting_server.py +32 -0
  283. testo_core-1.1.1/tests/unit/testo_core/test_repository_factory.py +62 -0
  284. testo_core-1.1.1/tests/unit/testo_core/test_repository_sqlite.py +115 -0
  285. testo_core-1.1.1/tests/unit/testo_core/test_run_snapshot_diff.py +84 -0
  286. testo_core-1.1.1/tests/unit/testo_core/test_services.py +27 -0
  287. testo_core-1.1.1/tests/unit/testo_core/test_stage_tier_config.py +101 -0
  288. testo_core-1.1.1/tests/unit/testo_core/test_summary_dashboard.py +55 -0
  289. testo_core-1.1.1/tests/unit/testo_core/test_triggers.py +235 -0
@@ -0,0 +1,76 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .DS_Store
4
+ .venv/
5
+ venv/
6
+
7
+ # Local secrets (copy from .env.example)
8
+ .env
9
+
10
+ # Default local SQLite DB when DATABASE_URL is unset (testo_core/repository/db_config.py)
11
+ uqo_history.db
12
+ testo_history.db
13
+
14
+ # Generated sandbox DB from the test suite (tests/artifacts/)
15
+ tests/artifacts/*.db
16
+
17
+ # Cursor IDE local state (debug logs, plans, rules, etc.)
18
+ .cursor/
19
+
20
+ # Local e2e test scratch (cleanup ledgers, etc.)
21
+ .artifacts/
22
+
23
+ # Built Python distribution artifacts
24
+ dist/
25
+ build/
26
+ *.egg-info/
27
+
28
+ # Local release-gate run logs
29
+ artifacts/release-gate-*/
30
+
31
+ # Generated report HTML (static/history/ is served by the API for each run's Report Links)
32
+ static/
33
+
34
+ # Persisted run history (SQLite + per-run HTML snapshots)
35
+ artifacts/uqo_run_history.sqlite
36
+ artifacts/testo_sandbox.db
37
+ artifacts/history/
38
+
39
+ # Local/generated artifacts
40
+ .coverage
41
+ coverage.xml
42
+ artifacts/allure-report/
43
+ artifacts/allure-results/
44
+ artifacts/allure-results-archive/
45
+ artifacts/allure-report.zip
46
+ artifacts/metrics.json
47
+
48
+ # Runtime logs
49
+ logs/
50
+
51
+ # Frontend workspace artifacts
52
+ frontend/node_modules/
53
+ frontend/dist/
54
+
55
+ # Root Node tooling (Allure CLI, commitlint)
56
+ node_modules/
57
+
58
+ # Local sample-cycle run output (testo run --cycle sample-*)
59
+ artifacts/sample-behave/
60
+ artifacts/sample-pytests/
61
+ artifacts/sample-all-frameworks/
62
+ artifacts/self-test/
63
+ artifacts/fake-api/
64
+ .testo/
65
+
66
+ # Local test-suite scratch DBs
67
+ tests/artifacts/
68
+
69
+ # Local ReportPortal Postgres data volume
70
+ data/
71
+
72
+
73
+ # GitLab Pages demo output (scripts/export_static_site.py + the Pages job)
74
+ /public/
75
+ /.ci-history/
76
+ /.demo/
@@ -0,0 +1,252 @@
1
+ # Changelog
2
+
3
+ All notable changes to `testo-core` will be documented in this file.
4
+
5
+ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ---
8
+
9
+ ## [Unreleased]
10
+
11
+ ## [1.1.1] - 2026-10-19
12
+
13
+ First release meant for PyPI (`pip install testo-core`).
14
+
15
+ ### Added
16
+ - Open-source community files: `SECURITY.md` (private vulnerability reporting), `CODE_OF_CONDUCT.md` (Contributor Covenant 2.1), `CITATION.cff`, issue forms (`.github/ISSUE_TEMPLATE/*.yml`, blank issues off, links to Discussions and the security form) and `.github/dependabot.yml` (weekly grouped updates for pip, npm and GitHub Actions, `chore(deps)` commits with the `no-changelog` label; `commitlint.config.js` skips Dependabot's long commit bodies). `CONTRIBUTING.md` gains "Finding something to work on" and a note on the AI-agent files, and its Quickstart link is fixed
17
+ - README: animated walkthroughs of the web UI and of the CLI (`docs/assets/demo/`)
18
+ - `docs/Prompts & Snippets/Setup Prompts.md`: copy-paste prompts for an AI coding assistant to install Testosterone in another project, write its `testosterone.yaml`, run it in GitHub Actions or GitLab CI, open the web UI and troubleshoot. They install from GitHub until `testo-core` is on PyPI. Command Reference no longer calls `doctor`, `clean`, `watch` and `init` unimplemented
19
+
20
+ ### Fixed
21
+ - `pip install testo-core` followed by `testo run` crashed with `ModuleNotFoundError: No module named 'sqlalchemy'`: run history is always saved (SQLite by default) but `sqlmodel` was only in the `[db]` extra. It is now a core dependency; `[db]` keeps the Postgres driver and `tomli-w`. A new `package` CI job (`scripts/package_smoke.sh`) installs the built wheel with no extras and runs a cycle, and the publish workflow runs the same check before uploading
22
+ - Compare showed "n/a" / "Unknown" for "Test time (sum)" and "Avg per test" on every run because nothing stored them. Both persistence backends now write `metrics_duration_ms` (sum of per-test Allure durations) and `avg_case_ms` (that sum over the test count, `null` with no tests), plus `test_time_ms` per stage. Runs saved earlier still show "n/a". A new contract test fails when `history/views.py` reads a run metadata key that persistence never writes
23
+
24
+ ### Changed
25
+ - Package metadata for PyPI: description, MIT license expression, author, keywords, classifiers and project links (homepage, docs, demo, issues, changelog). The README shown on PyPI has its relative images and links rewritten to GitHub URLs at build time (`hatch-fancy-pypi-readme`), and the sdist now carries only the Python package, its tests and the top-level docs (about 260 KB instead of 3.5 MB)
26
+ - `publish.yml` fails before uploading when the release tag does not match `pyproject.toml`'s version, and runs `twine check --strict`
27
+ - README: PyPI badge and a `pip install testo-core` quickstart
28
+ - Pages demo: the read-only notice is now a dismissible alert with a × button, remembered across reloads, and a "Read-only demo" badge in the header reopens it
29
+ - Detailed architecture diagram (`docs/assets/testosterone-architecture-detailed-{dark,light}.png`, drawn by `scripts/render_architecture_diagram.js`) showing `CycleRunService`, the `history/` read side and the repository; it replaces the six-box picture in the README and leads `docs/Architecture/System Diagram.md`
30
+ - Docs vault: the architecture diagram now has its own note (`docs/Architecture/System Diagram.md`) so it shows in Obsidian and the GitHub wiki, not only the README; Architecture Overview's text sketch is a Mermaid flowchart. New decision note for the vault and wiki sync, the second wave of the 2026-10-07 interview fixes, and this repo's workflows in CI-CD Pipeline Setup. `scripts/docs_vault.py lint --base` accepts a second edit to a note already dated today
31
+
32
+ ## [1.1.0] - 2026-10-07
33
+
34
+ One engine behind every surface. The Docker-based second execution stack, the Streamlit UI, MinIO and the `uqo` command are gone; the CLI, the API and CI all run cycles through `CycleRunService`. The release also adds an API security model, a type-checked API, same-cycle run comparison and a read-only demo on GitHub Pages. Upgrading from 1.0: see "Migrating from v1.0" in the README.
35
+
36
+ ### Added
37
+ - Docs vault rules: `docs/CLAUDE.md` (schema), `docs/log.md`, frontmatter on every note, and `scripts/docs_vault.py lint` (frontmatter, broken links, wikilinks, orphans, `updated` date on edited notes) as a `docs_vault` CI job and a contract test. `.github/workflows/wiki-sync.yml` regenerates the GitHub wiki from `docs/` on every push to `main` that touches the vault. The root `CLAUDE.md` gains the six second-brain rules, and `docs/Specs & ADRs/` gains decision notes for the 2026-10-06 architecture consolidation and the 2026-10-07 interview fixes
38
+ - Pages demo on GitHub and GitLab: `.github/workflows/pages-demo.yml` (GitHub Pages, `https://<owner>.github.io/<repo>/`) and `.gitlab-ci.yml` (GitLab Pages) each run testosterone's own suite (`self-test` cycle) and the deliberately broken [fake-api](https://github.com/taltal-beep/fake-api) app (`fake-api` cycle), then publishes the React UI as a read-only snapshot of those runs (`scripts/export_static_site.py` freezes the API's own responses; `frontend/src/lib/static-backend.ts` serves them to the unchanged pages). Run history is cached between pipelines. `.github/workflows/mirror-to-gitlab.yml` mirrors `main` to GitLab, inert until configured
39
+ - `frontend` CI job in `ci.yml`: runs the React dashboard's typecheck, vitest suite and production build on every PR (the frontend had no CI coverage)
40
+ - `POST /api/v1/adhoc-executions`: run one framework (`pytest`, `behave`, `behavex`, `command`) against a repo without defining a cycle. It runs as a one-stage `adhoc` cycle through `CycleRunService`, with status and SSE events under `/api/v1/cycle-executions/{id}`
41
+ - Quick Run page in the React frontend (`/quick-run`, under Advanced) built on that endpoint; it replaces the Legacy Execution page
42
+ - Engine run records now store failure evidence for failed runs (failing cases, first traceback, log tail, timeout flag; all redacted) for the AI failure summary, and CI provenance (`ci_provider`, `ci_pipeline_id`, `ci_job_id`, `ci_commit_sha`, `ci_ref_name`) when run in CI
43
+ - After every cycle run, test KPIs are pushed to InfluxDB and/or a Prometheus Pushgateway when `INFLUXDB_*` / `PROMETHEUS_PUSHGATEWAY_URL` are set
44
+
45
+ ### Changed
46
+ - Loose `testo_core` root modules moved into their subpackages (no compatibility shims): `db.py` → `repository/db.py`, `db_config.py` → `repository/db_config.py`, `report_generator.py` / `metrics.py` / `metrics_extractor.py` / `integrations.py` → `reporting/`, `triggers.py` → `config/triggers.py`. Only the cross-cutting `paths.py` stays at the root
47
+ - CI type-checks `testo_api` as well as `testo_core` (`mypy testo_core testo_api`, blocking). The AI config routes validate their status payload through Pydantic, and report diffs type the change kind as a `Literal`
48
+ - Pages demo explains itself: the banner says it shows testosterone's self-test and fake-api (whose red is deliberate), only cycles that ran are exported and their Run buttons are disabled with the local `testo run` command, the read-only message no longer names GitLab, and with an optional `ANTHROPIC_API_KEY` the export freezes an AI failure summary per failed run (otherwise the card says summaries are generated live)
49
+ - API access control: CORS now allows only the Vite dev/preview servers by default (`TESTO_CORS_ORIGINS`; credentials only for an explicit origin list, never with `*`) and mutating requests from other browser origins get `403`, optional `TESTO_API_TOKEN` requires a bearer token on mutating requests (the frontend sends `VITE_TESTO_API_TOKEN`), and `testo-api` warns when bound beyond loopback without a token. `ARCHITECTURE.md` gains "Security model" and "Trade-offs and known limits" sections
50
+ - Running a cycle (trigger gate, engine, reporters, native report snapshot, report archive, trigger snapshot) now lives in one application service, `testo_core/services/cycle_run.py` (`CycleRunService`). `testo run` and `POST /api/v1/cycles/{cycle}/executions` both call it, so the API no longer imports private helpers from `testo_core/cli/runner.py`
51
+ - API cycle executions now save the trigger snapshot after a successful triggered run, as `testo run` already did; before, a cycle with `trigger:` started from the dashboard never advanced its snapshot
52
+ - Frontend API types are now generated from FastAPI's OpenAPI schema (`frontend/openapi.json` → `frontend/src/lib/api-schema.ts`) instead of being hand-written; CI's `frontend` job runs `tsc` and fails on a stale schema or generated file
53
+ - `ARCHITECTURE.md` and `README.md` now describe the single execution engine (config → `CycleRunService` → engine → framework adapters → reporting/persistence) with a system diagram, layer table and the typed Pydantic-to-React contract
54
+ - `testo_core/run_history.py` is replaced by the `testo_core/history/` package: `views` (typed run views), `read_model` (queries), `report_links`, `snapshots` and `maintenance`. All of it goes through the run repository, which gains `merge_run_metadata()`; `STATIC_HISTORY_ROOT` moves to `testo_core.paths`
55
+ - GitHub Action and GitLab template now run `testo run --ci` (they called `uqo run --config … --ghost`, which v1.0's `uqo` alias no longer accepted). Action inputs are `config-path`, `cycle`, `ci-mode`, `persist`, `python-version`; `ghost-mode`, `stream-json`, `runner-image`, `runner-prebuilt` and the `run_id` output are gone. GitLab variables are now `TESTO_CONFIG_PATH`, `TESTO_CYCLE`, `TESTO_PERSIST`
56
+ - The React UI names runs by cycle and start time (`fake-api · Oct 7 03:21`) with the short run id as secondary text, on the Dashboard, Runs, Run detail and Compare pages; `GET /api/v1/dashboard/runs/recent` items now include `cycle`. Compare shows Reliability/Performance as tables with coloured deltas and state badges instead of raw `key=value` strings, and its run pickers are grouped and filterable by cycle
57
+ - CI's `format` job now blocks on `mypy testo_core` and `ruff format --check` (both were advisory); the codebase was reformatted once with `ruff format`, and a `ruff-format` pre-commit hook was added
58
+ - A stage's `workers` now does what it says, or says it doesn't: pytest stages get `-n <workers>` when pytest-xdist is installed for the `pytest` on PATH (otherwise one warning and a serial run), `workers:` on a behave or command stage logs a warning, and the API/UI only show workers for frameworks that use them
59
+ - CI's `test` job now enforces coverage (it ran `--no-cov`): `pytest.ini` measures `testo_core` and `testo_api` with branch coverage and fails below 65% (was 50%, `testo_core` only), and `coverage.xml` is uploaded as an artifact. `nightly-external`, `release-gate` and `pr-heavy` pass `--no-cov`: their few marker-selected tests could never meet that project-wide gate, which is why `nightly-external` failed every night. `nightly-external` also reads `TESTO_E2E_*` secrets instead of `UQO_E2E_*` and skips with a notice when none are set
60
+ - Renamed the remaining UQO names in code and UI to Testosterone: tab title, OpenAPI title (`Testosterone API`), and env vars `UQO_*` → `TESTO_*` (`TESTO_SHARED_ALLURE_RESULTS_DIR`, `TESTO_ARTIFACTS_ROOT`, `TESTO_LAST_TEST_TYPE`, `TESTO_RUN_ID`, `TESTO_E2E_*`, runner image build args) with no aliases for the old names. Defaults changed too: `PROMETHEUS_JOB_NAME` is `testo`, metrics are `testo_*` / `testo_test_run`, the default SQLite history file is `testo_history.db`, and the compose Postgres is `testo-postgres` / `testo_admin` / `testo_history`
61
+
62
+ ### Removed
63
+ - MinIO support: the `s3` readiness check (`/api/v1/health/ready` reported "degraded" without MinIO credentials), `testo_core/s3_client.py`, `history/s3_snapshots.py` (pre-v1.1 snapshot reads), the pre-v1.1 record shape in `history/views.py`, the `boto3` dependency, and the `minio`, `minio-init`, `allure-sync` and `allure` compose services. `docker-compose.yml` now only provides Postgres
64
+ - The second, Docker-based execution stack: `HeadlessEngineService`, `testo_core/runners.py`, `command_builders.py`, `multi_run.py`, `event_drain.py`, `config_loader.py`, `audit_service.py`, `ghost_policy.py`, `result_management.py`, and the pluggy `orchestrator.py` / `specs.py` / `plugins_builtin.py`. Every run now goes through the cycle engine
65
+ - The v1.0 `uqo run --config <runs.yaml>` contract (`--ghost`, `--no-ghost`, `--json`, `--stream-json`, summary JSON); use `testo run --cycle <name> --ci`
66
+ - The `uqo` console script (`testo_core/cli/deprecated.py`) and the frontend's legacy route redirects (`/history`, `/runner`, `/execution`, `/advanced/execution`); use `testo` and the current routes. Unknown frontend paths now show a not-found page
67
+ - `POST /api/v1/executions`, `GET /api/v1/executions/{id}` and `GET /api/v1/executions/{id}/events`; use `POST /api/v1/adhoc-executions` or `POST /api/v1/cycles/{cycle}/executions`
68
+ - The Streamlit UI (`testo_ui/`, `testo-ui` script, `ui` extra), as scheduled in 1.0.0
69
+ - The `docker` extra and the `pluggy` runtime dependency
70
+ - Run-history writer functions in `run_history.py` (`create_run`, `record_completed_run`, MinIO uploads), the unused `compare_latest_two()` and the `db_path` arguments on history queries
71
+ - Generated run output that was committed by mistake (`artifacts/allure-report*`, `artifacts/allure-results-archive/`, `artifacts/metrics.json`); these paths are now ignored
72
+ - `testo_core/reporting/allure_delta_transform.py`, `allure_history_serve.py` and `allure_summary_widgets.py`: unreferenced modules that could not be imported (they depended on functions no longer in `services/report_archive_diff.py`)
73
+ - Dead code and test-failure injection: `.streamlit/`, `drop_in_hooks/`, `requirements.txt`, `deploy/nginx/`, `examples/gitlab/`, the unused GitLab tier templates, `sample_target_repo/random_fail.py` and the `sample-all-frameworks-stochastic` cycle, and the `UQO_FLAKY_DEMO` / `SANDBOX_API_FLAKY_P` switches in testosterone's own suite. `testo_core/sandbox_api.py` (a uvicorn launcher for the sample mock API, used only by one black-box test on a fixed port) is gone with that test, so it no longer ships in the wheel
74
+
75
+ ### Fixed
76
+ - Dashboard and Compare badges say "1 improvement" / "1 regression" instead of "1 improvements"
77
+ - `release-gate.yml` reads the `TESTO_E2E_*` repository secrets, matching the nightly job, instead of the old `UQO_E2E_*` names
78
+ - Errors in I/O and reporting paths are no longer swallowed silently: `except Exception: pass` sites in `testo_core/` and `testo_api/` now catch the specific exceptions they expect and log with the module logger, and the deliberate catch-alls (orchestrator, reporter factory, API routes) log with a traceback. A failed BehaveX HTML report now sets the stage's `error` and is written to `run.log`, and a failed Git trigger evaluation logs a warning and says so in the trigger `reason` (exit codes unchanged)
79
+ - The frontend's top nav overflowed the page at phone width. Below 640px the nav links and the Advanced menu now collapse into a menu button (`aria-expanded`, closes on navigation and Escape), and page gutters shrink to 16px; no page of the demo scrolls sideways at 390px any more
80
+ - Dashboard trends and "Compare latest two" (dashboard and Runs page) compared the latest run with whatever ran before it, even another cycle; the baseline is now the previous run of the same cycle, and the dashboard names it. A cycle whose stage crashed without producing results no longer reports the other stages' pass rate (often 100%) as its health
81
+ - The API's execution registry kept every execution in memory forever and each SSE viewer held a worker thread while polling `events.ndjson` every 0.2 s. Finished executions beyond `TESTO_MAX_FINISHED_EXECUTIONS` (default 200) are now evicted (their status/events endpoints return 404 pointing to `/api/v1/runs`); the SSE tail is an async generator with poll backoff (0.1 s to 2 s) that closes right after the run's own last event (not the next run's, which shares `events.ndjson`) or when the client disconnects, and no longer drops a line caught mid-write
82
+ - The test pyramid (`testo report pyramid`, `/api/v1/runs/{id}/pyramid`) bucketed a run by the tiers in the *current* `testosterone.yaml`, so renaming a stage re-counted old runs as "unit". Run records now store each stage's `tier`; only older records without one fall back to the YAML
83
+ - A `command` stage's `junit_xml:` reports were never imported by `testo run` or the API, so the stage showed 0 tests and PASS. Cycle resolution and the `--workers` override rebuilt each stage without its `junit_xml` and `tier`; they now copy the stage with `dataclasses.replace`
84
+ - Pytest stages ignored the target repo's own pytest config (`pythonpath`, markers) when the target sat inside another pytest project, such as a repo cloned into the testosterone checkout in CI, so tests failed to import the target's code. The adapter passed `--alluredir <path>` as two tokens, and pytest counted the results path when choosing its rootdir; it now passes `--alluredir=<path>`
85
+ - Compare's test-level changes were always empty for two runs of the same cycle, and a run's artifact download returned whichever run of that cycle came last. Run records pointed `snapshot_dir` at the shared `artifacts/<cycle>/` tree, which every run overwrites; each run now keeps its own copy at `static/history/<run_id>/artifacts/`
86
+ - Frontend typecheck errors surfaced by the generated types: `/health/ready` is typed `"ready" | "degraded"` as the API returns, and `StatusPill` handles a `null` status
87
+ - `mypy testo_core` reports 0 errors, down from 59: reporters take a typed Rich `Console`, `testo report` narrows its optional open path before use, and the persistence, repository and CLI UI code is fully annotated
88
+ - `equipment: behavex`: every BehaveX stage failed at startup with `OSError: AF_UNIX path too long`, because BehaveX points `TEMP` at its output folder and the multiprocessing socket landed there; the adapter now pins `TMPDIR` to the system temp dir
89
+ - API errors surfaced in the UI as `API error <status>`; the client now shows the message the API returned, and the Run detail page reports a failed AI-summary request instead of swallowing it
90
+ - Run detail, dashboard and compare showed a wall duration of 0 ms for every cycle run; engine-sourced records store `duration_s`, which the history view now falls back to
91
+
92
+ ---
93
+
94
+ ## [1.0.0] - 2026-09-27
95
+
96
+ First public release. Published to PyPI (`testo-core`), GHCR (`testo-runner`), and JFrog Artifactory.
97
+
98
+ ### Deprecated
99
+ - `testo-ui` / Streamlit interface: prints a deprecation notice on stderr and is scheduled for removal in v1.1. The React frontend (`frontend/`) is the official UI.
100
+ - `uqo` CLI alias: continues to forward to `testo`; removal in a future release.
101
+
102
+ ### Added
103
+ - `.pre-commit-config.yaml`: local `ruff`, changelog-format, and whitespace/YAML/TOML hooks (`pre-commit install` to enable)
104
+ - `mypy` type-check tooling: `[tool.mypy]` config in `pyproject.toml`, advisory step in `ci.yml`'s `format` job
105
+ - Extended `[tool.ruff.lint]` selection (added `UP`, `B`) and made `ruff check` blocking in `ci.yml` now that the tree is clean
106
+ - `changelog_required` CI gate in `ci.yml`: fails PRs with non-doc changes that don't touch `CHANGELOG.md` (escape hatch: `no-changelog` label)
107
+ - `commitlint` CI check (`.github/workflows/commitlint.yml`, `commitlint.config.js`) enforcing Conventional Commits on PR commit messages
108
+ - `changelog-on-main.yml`: AI-drafted `CHANGELOG.md [Unreleased]` entries on push to `main`, gated by `scripts/check_changelog_format.py` — see `docs/changelog_automation_policy.md` for the review-step tradeoff and required secrets/branch-protection setup
109
+ - `CONTRIBUTING.md`, `.github/PULL_REQUEST_TEMPLATE.md`, `.github/ISSUE_TEMPLATE/` (bug report, feature request), and `CODEOWNERS`
110
+ - Root-level `CLAUDE.md` pointing any directly-invoked AI agent at `docs/Index.md` and the Agent Context Guide
111
+ - Persistence module with `PersistenceBackend` protocol, JSON and DB backends
112
+ - Single-sourced `EngineExitCode` across modern and legacy execution stacks
113
+ - Contract tests asserting exit code consistency between stacks
114
+ - Execution stack boundary documentation in Architecture Overview
115
+ - `_SENSITIVE_KEY_PATTERN` in `redaction.py` to detect sensitive mapping keys (#35)
116
+ - `_redacted_context_text()` in `failure_context_builder.py` for structured metadata redaction (#35)
117
+ - Allure failure context wiring in `record_completed_run()` for run recording (#35)
118
+ - `equipment: command`: run any test runner (Jest, Playwright, Maestro, `go test`, ...) as a stage. `args` is the full argv
119
+ - Stage key `junit_xml` (glob or list, relative to `target_repo`): JUnit XML written by the stage is converted into Allure results after it exits, so non-Allure runners count in summaries, health % and every reporter (`testo_core/reporting/junit_import.py`)
120
+ - `artifactory-publish.yml`: mirrors the release to JFrog Artifactory (PyPI + Docker repos), inert until `ARTIFACTORY_URL` is set — see `docs/Processes & Guides/Publishing to Artifactory.md`
121
+
122
+ ### Changed
123
+ - `--no-persist` / `--persist` CLI flags with clarified semantics
124
+ - `classify_exit_code` consolidated into `engine/exit_codes.py`
125
+ - Literal exit code constants in CLI replaced with `EngineExitCode` enum
126
+
127
+ ### Fixed
128
+ - Sprint 2 release gate execution across all 4 phases
129
+ - Contract test assertion mismatch (`--plan` vs `--cycle`)
130
+ - Allure CLI unit test mock for `resolve_allure_command`
131
+ - `publish.yml`: post-publish verification installed `testo-core==v1.0.0` from the raw git tag, which is not a valid version specifier; the leading `v` is now stripped
132
+ - `docker-publish.yml`: Trivy scan and verify steps referenced an image tag that never existed (`docker/metadata-action` strips the `v`); both now use the resolved metadata version
133
+ - `docker-publish.yml`: the `latest` tag was gated on `is_default_branch`, which is never true for a release event, so `latest` would never have been published
134
+ - `.gitattributes`: GitHub reported the repository as HTML because the generated 3.2 MB `artifacts/allure-report/index.html` outweighed all authored Python and TypeScript; generated and vendored paths are now excluded from language statistics
135
+ - `Dockerfile.testo-runner`: the image ran as root, which fails the release workflow's blocking Trivy config scan (DS002, HIGH); it now runs as an unprivileged `testo` user, and the entrypoint is `testo` instead of the deprecated `uqo` alias
136
+
137
+ ---
138
+
139
+ ## [0.1.0] — Phase 1–4 Feature Complete
140
+
141
+ ### Phase 4: BYOK AI Failure Summaries
142
+
143
+ *AI-powered test failure analysis with bring-your-own-key provider support.*
144
+
145
+ #### Added
146
+ - `testo_core/services/failure_analysis_service.py` — context-aware AI failure summary generation
147
+ - `PUT /api/v1/ai/config` — runtime AI provider/model configuration (memory-only key storage)
148
+ - `GET /api/v1/runs/{run_id}/ai-summary` — cached AI summary retrieval
149
+ - `POST /api/v1/runs/{run_id}/ai-summary:generate` — on-demand summary generation for failed runs
150
+ - `GET /api/v1/ai/config/status` — non-secret AI configuration status endpoint
151
+ - React AI Settings page (`/settings/ai`) — provider config, key management, model selection
152
+ - AI summary display on Run Detail page (`/runs/:runId`)
153
+ - AI summary caching — generate once, retrieve cached on refresh
154
+ - AI failure context capture tests
155
+ - Passing-run AI summary skip regression test
156
+
157
+ #### Security
158
+ - Raw API keys never returned by backend responses
159
+ - Runtime key input memory-only by default (not persisted to DB/files)
160
+ - Token-like values redacted from internal error surfaces before transport
161
+ - AI integration explicit opt-in (`enabled=false` by default)
162
+
163
+ #### Fixed
164
+ - AI summary refresh data loss on forced refresh failure (#32)
165
+ - AI failure summary and context builder regression coverage (#33, #34)
166
+
167
+ ---
168
+
169
+ ### Phase 3: Unified Dashboard, Delta Engine, Frontend Migration
170
+
171
+ *React frontend, run comparison analytics, and unified dashboard.*
172
+
173
+ #### Added
174
+ - FastAPI backend (`testo_api/`) — thin adapter over `HeadlessEngineService`
175
+ - React frontend (`frontend/`) — Vite + React + Tailwind dashboard
176
+ - Dashboard overview page (`/`) — KPI cards, trend badges, drill-down links
177
+ - Delta comparison engine (`testo_core/services/delta_service.py`) — regression/improvement classification
178
+ - Compare page (`/compare`) — run selection and delta visualization
179
+ - SSE client (`frontend/src/lib/sse-client.ts`) — real-time execution log streaming
180
+ - `GET /api/v1/dashboard/overview` — unified dashboard payload endpoint
181
+ - `GET /api/v1/analytics/delta` — core-owned run delta comparison endpoint
182
+ - `POST /api/v1/executions` — create run execution job endpoint
183
+ - `GET /api/v1/executions/{id}/events` — SSE stream for log/result/summary events
184
+ - Health probes: `GET /api/v1/health/live`, `GET /api/v1/health/ready`
185
+ - Degraded-data behavior (n/a display, degraded banner, missing report links)
186
+ - Report DB archives, diff CLI, Allure history, hybrid cycles
187
+ - Report archive extraction path hardening (#28, #30)
188
+ - Report archive diff regression tests (#27, #29)
189
+ - Execution accepted-status regression test (#26)
190
+ - Frontend unit tests (Vitest) and E2E test harness
191
+
192
+ #### Fixed
193
+ - Race condition in 202 Accepted response status for `/executions`
194
+
195
+ ---
196
+
197
+ ### Phase 2: CI Integrations, Ghost Mode, Runner Image
198
+
199
+ *CI wrappers, headless ghost execution, and prebuilt Docker runner.*
200
+
201
+ #### Added
202
+ - GitHub Action wrapper (`ariel-evn/uqo-action@v1`) with typed inputs/outputs
203
+ - GitLab CI template (`ci/gitlab/testo.gitlab-ci.yml`)
204
+ - Ghost mode — CI auto-detection for GitHub, GitLab, Buildkite, CircleCI, Jenkins, Azure Pipelines
205
+ - `--ghost` / `--no-ghost` / `--ci` CLI flags with precedence rules
206
+ - `Dockerfile.testo-runner` — prebuilt runner image for CI execution
207
+ - Configurable runner image path (`UQO_RUNNER_IMAGE`)
208
+ - NDJSON event streaming (`--stream-json`) for CI log consumption
209
+ - Ghost summary and NDJSON contract tests
210
+ - CI provenance unit tests
211
+ - GitHub Action and GitLab wrapper contract tests
212
+
213
+ #### Changed
214
+ - Renamed `uqo`-prefixed CI files to `testo`-prefixed
215
+
216
+ ---
217
+
218
+ ### Phase 1: Foundation
219
+
220
+ *Core engine, CLI, packaging, database adapters, Allure reporting.*
221
+
222
+ #### Added
223
+ - `testo_core/` — config-driven orchestration engine reading `testosterone.yaml`
224
+ - `testo` CLI entrypoint (via Typer) with `run`, `report`, `cycles`, `config` subcommands
225
+ - `uqo` legacy CLI alias (deprecated)
226
+ - Framework adapters: `PytestAdapter`, `BehaveAdapter`, `BehaveXAdapter`
227
+ - Repository pattern (`testo_core/repository/`) — SQLite default, Postgres/MySQL optional
228
+ - Allure reporting pipeline with per-framework isolation and unified reports
229
+ - MinIO S3 artifact storage (`testo_core/s3_client.py`)
230
+ - Docker-based ephemeral test execution (`testo_core/runners.py`)
231
+ - Dockerless local fallback when Docker is unavailable
232
+ - Streamlit UI (`testo_ui/`) for interactive execution and history
233
+ - Pluggy-based plugin system for drop-in runner extensions
234
+ - Shared headless engine service (`testo_core/services/headless_engine.py`)
235
+ - Hatchling-based packaging (`pyproject.toml`) with extras: `ui`, `api`, `db`, `docker`, `metrics`, `dev`
236
+ - Stable exit codes: 0 (success), 1 (test failure), 2 (invalid input), 3 (infra failure), 4 (internal error)
237
+ - Crash recovery: orphaned `RUNNING` rows auto-marked `FAILED` on startup
238
+ - Container timeout safety net (`UQO_CONTAINER_TIMEOUT_S`)
239
+ - Docker Compose infrastructure: Postgres, MinIO, Allure static host, Allure sync
240
+
241
+ #### Fixed
242
+ - Docker runner path mapping
243
+ - Mock API and built-in Pluggy hooks restoration
244
+ - Multi-run batch locking until complete
245
+ - Multi-run polling active until batch ends
246
+
247
+ ---
248
+
249
+ [Unreleased]: https://github.com/taltal-beep/testosterone/compare/v1.1.0...HEAD
250
+ [1.1.0]: https://github.com/taltal-beep/testosterone/compare/v1.0.0...v1.1.0
251
+ [1.0.0]: https://github.com/taltal-beep/testosterone/compare/v0.1.0...v1.0.0
252
+ [0.1.0]: https://github.com/taltal-beep/testosterone/releases/tag/v0.1.0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Testosterone contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.