pyplaykit 1.37.1__tar.gz → 1.37.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (457) hide show
  1. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/CHANGELOG.md +20 -0
  2. {pyplaykit-1.37.1/pyplaykit.egg-info → pyplaykit-1.37.2}/PKG-INFO +2 -1
  3. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/README.md +1 -0
  4. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/config.yaml +8 -0
  5. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_AGENTS_DESIGN.md +2 -0
  6. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_AGENTS_GUIDE.md +39 -2
  7. pyplaykit-1.37.2/docs/TEST_CREATION_PLAYGROUND.md +269 -0
  8. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0019-test-creation-from-test-cases-on-sandbox-branches.md +32 -0
  9. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/agent.py +5 -3
  10. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/cli.py +64 -5
  11. pyplaykit-1.37.2/pyplaykit/agents/sandbox.py +445 -0
  12. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/settings.py +9 -2
  13. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/stacks/environment.py +1 -0
  14. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/cli.py +57 -16
  15. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/config/config.yaml +8 -0
  16. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/QE_AGENTS_GUIDE.md +39 -2
  17. pyplaykit-1.37.2/pyplaykit/docs/TEST_CREATION_PLAYGROUND.md +269 -0
  18. pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/api_posts.csv +8 -0
  19. pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/custom_columns.csv +7 -0
  20. pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/db_employees.csv +11 -0
  21. pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/device_thermostat.csv +12 -0
  22. pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/mixed_checkout.csv +13 -0
  23. pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/steps_per_row.csv +7 -0
  24. pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/ui_login.csv +21 -0
  25. {pyplaykit-1.37.1 → pyplaykit-1.37.2/pyplaykit.egg-info}/PKG-INFO +2 -1
  26. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit.egg-info/SOURCES.txt +10 -0
  27. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyproject.toml +2 -2
  28. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/.github/copilot-instructions.md +0 -0
  29. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/.github/prompts/review-execution-plan-and-implement-next-task.prompt.md +0 -0
  30. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/.github/prompts/run-unit-tests-and-coverage.prompt.md +0 -0
  31. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/.github/prompts/security-audit-and-consolidated-report.prompt.md +0 -0
  32. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/CHOOSE_YOUR_STRUCTURE.md +0 -0
  33. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/CLAUDE.md +0 -0
  34. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/COLUMN_MAPPING_AND_IGNORE_FIELDS_GUIDE.md +0 -0
  35. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/COMMANDS_FOR_YOUR_PROJECTS.md +0 -0
  36. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/COMMIT_SUMMARY.md +0 -0
  37. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/CONTRIBUTING.md +0 -0
  38. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/CORRECTED_PROJECT_NAMES.md +0 -0
  39. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/DATABASE_IMPLEMENTATION_SUMMARY.md +0 -0
  40. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/DELIVERABLES_SUMMARY.md +0 -0
  41. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/ENTERPRISE_TEST_STRUCTURE.md +0 -0
  42. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/FINAL_PROJECT_SETUP.md +0 -0
  43. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/GAP_TRACKER.md +0 -0
  44. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/HOW_TO_ACCESS_DOCS.md +0 -0
  45. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/INIT_COMMAND_EXAMPLES.md +0 -0
  46. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/KEY_BASED_MATCHING_SOLUTION.md +0 -0
  47. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/MANIFEST.in +0 -0
  48. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/MIGRATION_COMPLETE.md +0 -0
  49. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/MIGRATION_PLAN.md +0 -0
  50. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/PIP_INSTALL_GUIDE.md +0 -0
  51. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/PYPLAYKIT_CLIENT_OVERVIEW.md +0 -0
  52. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/QUICK_DB_REFERENCE.md +0 -0
  53. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/QUICK_REFERENCE_COMPARISON_FEATURES.md +0 -0
  54. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/QUICK_START_QE.md +0 -0
  55. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/STRUCTURE_COMPARISON.md +0 -0
  56. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/TEST_LOCATION_CHEATSHEET.md +0 -0
  57. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/VISUAL_COMPARISON.md +0 -0
  58. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/WINDOWS_INSTALL_GUIDE.md +0 -0
  59. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/YOUR_PROJECTS_IMPLEMENTATION_GUIDE.md +0 -0
  60. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/YOUR_SETUP_SUMMARY.md +0 -0
  61. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/bin/README.md +0 -0
  62. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/components/__init__.py +0 -0
  63. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/components/base_component.py +0 -0
  64. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/components/data_table.py +0 -0
  65. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/components/form_field.py +0 -0
  66. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/components/modal.py +0 -0
  67. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/data_comparison_profiles.yaml +0 -0
  68. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/devices.yaml +0 -0
  69. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/environments.yaml +0 -0
  70. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/projects/customs_modernization.yaml +0 -0
  71. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/projects/device_lab.yaml +0 -0
  72. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/projects/dispatcho.yaml +0 -0
  73. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/projects/timelyquote.yaml +0 -0
  74. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/core/__init__.py +0 -0
  75. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/core/base_page.py +0 -0
  76. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/core/base_test.py +0 -0
  77. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/core/browser_factory.py +0 -0
  78. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/core/playwright_manager.py +0 -0
  79. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/core/quality_gate.py +0 -0
  80. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/README.md +0 -0
  81. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/data_validation_dashboard.json +0 -0
  82. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/docker-compose.yml +0 -0
  83. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/engineering_dashboard.json +0 -0
  84. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/executive_qe_dashboard.json +0 -0
  85. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/grafana-provisioning/dashboards/pyplaykit.yaml +0 -0
  86. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/prometheus.yml +0 -0
  87. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/release_quality_dashboard.json +0 -0
  88. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/test_health_dashboard.json +0 -0
  89. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/demo/README.md +0 -0
  90. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/demo/device_lab/README.md +0 -0
  91. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/demo/functional/database/file_comparison/README.md +0 -0
  92. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/demo/functional/database/postgres_src_tgt/README.md +0 -0
  93. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dist_pkg/__init__.py +0 -0
  94. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dist_pkg/distribution.py +0 -0
  95. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/API_TESTING_GUIDE.md +0 -0
  96. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/ARCHITECTURE.md +0 -0
  97. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/CI_INTEGRATION.md +0 -0
  98. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/CLI_REFERENCE.md +0 -0
  99. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/COMPETITIVE_ANALYSIS.md +0 -0
  100. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/COVERAGE_IMPROVEMENTS.md +0 -0
  101. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/CUSTOMER_SCENARIOS.md +0 -0
  102. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/DATABASE_SUPPORT.md +0 -0
  103. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/DATA_VALIDATION_GUIDE.md +0 -0
  104. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/DELIVERABLES_INDEX.md +0 -0
  105. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/DEVICE_AUTOMATION_WBS.md +0 -0
  106. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/EXAMPLE_TESTS_SUMMARY.md +0 -0
  107. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/Enterprise-Framework-Assessment-REVISED.md +0 -0
  108. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/Enterprise-Readiness-Assessment.md +0 -0
  109. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/Example-Tests-Guide.md +0 -0
  110. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/Execution-Plan-Backlog-and-Closure-Tracker.md +0 -0
  111. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/FRAMEWORK_CONTRIBUTION_GUIDE.md +0 -0
  112. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/01_ARCHITECTURE.md +0 -0
  113. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/02_DEPLOYMENT_RUNBOOK.md +0 -0
  114. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/03_ACCESS_MATRIX.md +0 -0
  115. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/04_CLIENT_CONTACT_MATRIX.md +0 -0
  116. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/05_OPEN_RISKS_REGISTER.md +0 -0
  117. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/06_PENDING_ENHANCEMENTS.md +0 -0
  118. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/07_PRODUCT_ROADMAP.md +0 -0
  119. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/08_ENVIRONMENT_DETAILS.md +0 -0
  120. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/09_OPERATIONAL_SOPS.md +0 -0
  121. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/10_ESCALATION_MATRIX.md +0 -0
  122. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/11_KT_RECORDINGS_INDEX.md +0 -0
  123. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/12_REVERSE_KT_SIGNOFF.md +0 -0
  124. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/13_LEADERSHIP_SIGNOFF.md +0 -0
  125. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/README.md +0 -0
  126. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/MCP_SERVER_DESIGN.md +0 -0
  127. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/MULTI_DB_VALIDATION_GUIDE.md +0 -0
  128. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/MULTI_PROJECT_STRUCTURE.md +0 -0
  129. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/OBSERVABILITY.md +0 -0
  130. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/PIP_INSTALL_GUIDE.md +0 -0
  131. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/PLUGIN_AUTHORING_GUIDE.md +0 -0
  132. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/PyPlayKit-Framework-Overview.md +0 -0
  133. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/PyPlayKit-Usage-Scenarios.md +0 -0
  134. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_AGENTS_CAPABILITY_INVENTORY.md +0 -0
  135. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_AGENTS_SPIKES.md +0 -0
  136. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_AGENTS_THREAT_MODEL.md +0 -0
  137. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_AGENT_PLATFORM_EXPANSION.md +0 -0
  138. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_VISUAL_GUIDE.md +0 -0
  139. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QUALITY_GATE.md +0 -0
  140. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/RESILIENCE_GUIDE.md +0 -0
  141. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/RUN_TESTS_QUICK_REFERENCE.md +0 -0
  142. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/SECRETS_AND_GOVERNANCE.md +0 -0
  143. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/TEST_ORGANIZATION.md +0 -0
  144. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/Usage-Scenarios-Feasibility-Analysis.md +0 -0
  145. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0001-sync-device-api-with-background-io.md +0 -0
  146. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0002-devices-subpackage-and-layering.md +0 -0
  147. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0003-dut-naming-for-cli-config-and-fixtures.md +0 -0
  148. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0004-optional-dependencies-and-import-guards.md +0 -0
  149. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0005-single-source-device-pytest-plugin.md +0 -0
  150. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0006-agent-runtime-transport.md +0 -0
  151. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0007-agent-autonomy-and-scm-boundaries.md +0 -0
  152. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0008-agent-contract-and-versioning.md +0 -0
  153. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0009-host-mediation-and-enforcement-model.md +0 -0
  154. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0010-target-stack-adapters-and-result-normalization.md +0 -0
  155. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0011-generation-capability-registry.md +0 -0
  156. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0012-regression-test-selection-safety.md +0 -0
  157. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0013-agent-telemetry-and-data-handling.md +0 -0
  158. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0014-agents-adopt-vs-build.md +0 -0
  159. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0015-agent-release-lifecycle-and-registry.md +0 -0
  160. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0016-review-driven-amendments.md +0 -0
  161. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0017-agent-evaluation-baseline-then-threshold.md +0 -0
  162. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0018-change-intelligence-without-product-source.md +0 -0
  163. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/README.md +0 -0
  164. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/device_automation/DESIGN.md +0 -0
  165. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/device_automation/GUIDE.md +0 -0
  166. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/device_automation/SPIKES.md +0 -0
  167. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/integrations/__init__.py +0 -0
  168. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/integrations/adapters.py +0 -0
  169. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/__init__.py +0 -0
  170. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/_ast_utils.py +0 -0
  171. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/_config_utils.py +0 -0
  172. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/cli.py +0 -0
  173. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/server.py +0 -0
  174. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/tools/__init__.py +0 -0
  175. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/tools/agent_tools.py +0 -0
  176. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/tools/device_tools.py +0 -0
  177. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/tools/package_discovery.py +0 -0
  178. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/tools/project_introspection.py +0 -0
  179. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/tools/project_state.py +0 -0
  180. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/orchestration/__init__.py +0 -0
  181. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/orchestration/enforcer.py +0 -0
  182. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/orchestration/planner.py +0 -0
  183. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/orchestration/selection.py +0 -0
  184. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pages/__init__.py +0 -0
  185. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pages/dashboard_page.py +0 -0
  186. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pages/login_page.py +0 -0
  187. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pages/orangehrm_login_page.py +0 -0
  188. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pages/saucedemo_inventory_page.py +0 -0
  189. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pages/saucedemo_login_page.py +0 -0
  190. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/__init__.py +0 -0
  191. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/_observer.py +0 -0
  192. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/_reference.py +0 -0
  193. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/api_plugin.py +0 -0
  194. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/base.py +0 -0
  195. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/data_plugin.py +0 -0
  196. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/manifest.py +0 -0
  197. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/registry.py +0 -0
  198. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/security_plugin.py +0 -0
  199. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/PIP_INSTALL_GUIDE.md +0 -0
  200. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/README.md +0 -0
  201. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/__init__.py +0 -0
  202. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/__init__.py +0 -0
  203. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/__main__.py +0 -0
  204. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/audit.py +0 -0
  205. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/budgets.py +0 -0
  206. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/__init__.py +0 -0
  207. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/_common.py +0 -0
  208. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/__init__.py +0 -0
  209. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/agent.py +0 -0
  210. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/agent.yaml +0 -0
  211. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/impact.py +0 -0
  212. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/prompts/change_semantics.md +0 -0
  213. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/prompts/regression_additions.md +0 -0
  214. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/risk.py +0 -0
  215. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/schemas/input.json +0 -0
  216. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/schemas/output.json +0 -0
  217. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/selection.py +0 -0
  218. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/__init__.py +0 -0
  219. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/agent.yaml +0 -0
  220. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/assemble.py +0 -0
  221. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/layout.py +0 -0
  222. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/prompts/generate_tests.md +0 -0
  223. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/prompts/guide_api.md +0 -0
  224. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/prompts/guide_db.md +0 -0
  225. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/prompts/guide_device.md +0 -0
  226. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/prompts/guide_ui.md +0 -0
  227. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/schemas/input.json +0 -0
  228. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/schemas/output.json +0 -0
  229. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/testcases.py +0 -0
  230. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/__init__.py +0 -0
  231. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/agent.py +0 -0
  232. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/agent.yaml +0 -0
  233. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/prompts/test_intent.md +0 -0
  234. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/rules.py +0 -0
  235. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/schemas/input.json +0 -0
  236. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/schemas/output.json +0 -0
  237. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/contract.py +0 -0
  238. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/enforcement.py +0 -0
  239. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/errors.py +0 -0
  240. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/host_tools.py +0 -0
  241. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/impact_map.py +0 -0
  242. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/__init__.py +0 -0
  243. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/anthropic.py +0 -0
  244. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/base.py +0 -0
  245. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/cache.py +0 -0
  246. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/fake.py +0 -0
  247. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/ollama.py +0 -0
  248. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/openai_compat.py +0 -0
  249. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/pricing.py +0 -0
  250. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/recording.py +0 -0
  251. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/routing.py +0 -0
  252. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/output.py +0 -0
  253. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/policy.py +0 -0
  254. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/read_tools.py +0 -0
  255. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/redaction.py +0 -0
  256. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/registry.py +0 -0
  257. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/reports.py +0 -0
  258. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/runner.py +0 -0
  259. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/schemas/1/agent-manifest.json +0 -0
  260. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/schemas/1/change-proposal.json +0 -0
  261. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/schemas/1/run-result.json +0 -0
  262. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/schemas/1/task-envelope.json +0 -0
  263. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/session.py +0 -0
  264. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/stacks/__init__.py +0 -0
  265. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/stacks/base.py +0 -0
  266. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/stacks/junit.py +0 -0
  267. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/stacks/python_pytest.py +0 -0
  268. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/telemetry.py +0 -0
  269. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/tools.py +0 -0
  270. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/config/__init__.py +0 -0
  271. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/config/devices.yaml +0 -0
  272. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/config/environments.yaml +0 -0
  273. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/__init__.py +0 -0
  274. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/_extras.py +0 -0
  275. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/assertions.py +0 -0
  276. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/buffer.py +0 -0
  277. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/candb.py +0 -0
  278. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/channel.py +0 -0
  279. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/clock.py +0 -0
  280. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/commands.py +0 -0
  281. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/components.py +0 -0
  282. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/config.py +0 -0
  283. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/console.py +0 -0
  284. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/device.py +0 -0
  285. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/editor.html +0 -0
  286. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/editor.py +0 -0
  287. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/errors.py +0 -0
  288. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/events.py +0 -0
  289. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/factory.py +0 -0
  290. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/fault_proxy.py +0 -0
  291. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/faults.py +0 -0
  292. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/fidelity.py +0 -0
  293. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/gatt.py +0 -0
  294. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/introspect.py +0 -0
  295. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/inventory.py +0 -0
  296. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/leasing.py +0 -0
  297. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/matching.py +0 -0
  298. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/messages.py +0 -0
  299. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/parsers.py +0 -0
  300. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/pool.py +0 -0
  301. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/power.py +0 -0
  302. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/provider.py +0 -0
  303. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/pytest_plugin.py +0 -0
  304. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/recording.py +0 -0
  305. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/recovery.py +0 -0
  306. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/registers.py +0 -0
  307. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/__init__.py +0 -0
  308. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/ble.py +0 -0
  309. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/components.py +0 -0
  310. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/__init__.py +0 -0
  311. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/base.py +0 -0
  312. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/ble.py +0 -0
  313. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/can.py +0 -0
  314. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/http.py +0 -0
  315. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/modbus.py +0 -0
  316. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/mqtt.py +0 -0
  317. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/serial.py +0 -0
  318. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/ssh.py +0 -0
  319. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/host.py +0 -0
  320. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/modbus.py +0 -0
  321. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/replay.py +0 -0
  322. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/scheduler.py +0 -0
  323. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/seed.py +0 -0
  324. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/sensor_faults.py +0 -0
  325. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/serve.py +0 -0
  326. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/signals.py +0 -0
  327. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/subprocess_twin.py +0 -0
  328. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/templating.py +0 -0
  329. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twin.py +0 -0
  330. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/__init__.py +0 -0
  331. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/energy_meter.py +0 -0
  332. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/engine.dbc +0 -0
  333. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/engine_ecu.py +0 -0
  334. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/environment_sensor.yaml +0 -0
  335. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/heart_rate.py +0 -0
  336. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/smart_plug.py +0 -0
  337. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/thermostat.py +0 -0
  338. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/yaml_twin.py +0 -0
  339. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/snmp.py +0 -0
  340. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/terminal.py +0 -0
  341. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/testing.py +0 -0
  342. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transcript.py +0 -0
  343. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transport.py +0 -0
  344. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/__init__.py +0 -0
  345. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/_async_bridge.py +0 -0
  346. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/adb.py +0 -0
  347. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/ble.py +0 -0
  348. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/can.py +0 -0
  349. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/coap.py +0 -0
  350. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/http.py +0 -0
  351. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/modbus.py +0 -0
  352. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/mqtt.py +0 -0
  353. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/serial.py +0 -0
  354. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/ssh.py +0 -0
  355. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/telnet.py +0 -0
  356. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/waiting.py +0 -0
  357. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/yamlutil.py +0 -0
  358. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/API_TESTING_GUIDE.md +0 -0
  359. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/ARCHITECTURE.md +0 -0
  360. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/CI_INTEGRATION.md +0 -0
  361. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/CLI_REFERENCE.md +0 -0
  362. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/DATABASE_SUPPORT.md +0 -0
  363. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/DATA_VALIDATION_GUIDE.md +0 -0
  364. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/MCP_SERVER_DESIGN.md +0 -0
  365. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/MULTI_PROJECT_STRUCTURE.md +0 -0
  366. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/OBSERVABILITY.md +0 -0
  367. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/PLUGIN_AUTHORING_GUIDE.md +0 -0
  368. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/QE_VISUAL_GUIDE.md +0 -0
  369. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/QUICK_START_QE.md +0 -0
  370. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/RESILIENCE_GUIDE.md +0 -0
  371. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/RUN_TESTS_QUICK_REFERENCE.md +0 -0
  372. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/SECRETS_AND_GOVERNANCE.md +0 -0
  373. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/TEST_ORGANIZATION.md +0 -0
  374. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/extras.py +0 -0
  375. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/plugin.py +0 -0
  376. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/show_docs.py +0 -0
  377. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit.egg-info/dependency_links.txt +0 -0
  378. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit.egg-info/entry_points.txt +0 -0
  379. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit.egg-info/requires.txt +0 -0
  380. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit.egg-info/top_level.txt +0 -0
  381. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/resilience/__init__.py +0 -0
  382. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/resilience/locator_recovery.py +0 -0
  383. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/setup.cfg +0 -0
  384. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/spikes/device_automation/README.md +0 -0
  385. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/spikes/qe_agents/README.md +0 -0
  386. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/api/ecom/auth_payloads.json +0 -0
  387. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/api/ecom/product_payloads.json +0 -0
  388. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/api_test_data.json +0 -0
  389. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/data_validation_test_data.json +0 -0
  390. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/login_test_data.json +0 -0
  391. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/orangehrm_login_data.json +0 -0
  392. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/pacts/README.md +0 -0
  393. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/ui_test_data.json +0 -0
  394. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/README.md +0 -0
  395. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/customs_modernization/README.md +0 -0
  396. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/demo/functional/README.md +0 -0
  397. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/demo/functional/api/README.md +0 -0
  398. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/demo/functional/database/README.md +0 -0
  399. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/demo/functional/ui/README.md +0 -0
  400. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/demo/integration/README.md +0 -0
  401. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/dispatcho/README.md +0 -0
  402. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/timelyquote/README.md +0 -0
  403. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/__init__.py +0 -0
  404. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/api_client.py +0 -0
  405. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/api_test_helper.py +0 -0
  406. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/assertion_helper.py +0 -0
  407. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/auth_manager.py +0 -0
  408. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/comparison_config_loader.py +0 -0
  409. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/contract/__init__.py +0 -0
  410. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/contract/pact_consumer.py +0 -0
  411. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/dashboard.py +0 -0
  412. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/data_comparison_report.py +0 -0
  413. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/data_comparison_utils.py +0 -0
  414. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/data_loader.py +0 -0
  415. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/data_source.py +0 -0
  416. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/data_validator.py +0 -0
  417. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/database_clients.py +0 -0
  418. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_client.py +0 -0
  419. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/__init__.py +0 -0
  420. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/db2.py +0 -0
  421. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/informix.py +0 -0
  422. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/mongodb.py +0 -0
  423. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/mysql.py +0 -0
  424. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/oracle.py +0 -0
  425. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/snowflake.py +0 -0
  426. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/sqlite.py +0 -0
  427. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/sqlserver.py +0 -0
  428. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_factory.py +0 -0
  429. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_fixtures.py +0 -0
  430. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_pool.py +0 -0
  431. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_validation_helper.py +0 -0
  432. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/environment_validator.py +0 -0
  433. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/file_reader.py +0 -0
  434. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/governance.py +0 -0
  435. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/graphql_client.py +0 -0
  436. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/logger.py +0 -0
  437. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/observability.py +0 -0
  438. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/observability_report.py +0 -0
  439. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/org_governance.py +0 -0
  440. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/project_config.py +0 -0
  441. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/response_validator.py +0 -0
  442. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/screenshot_helper.py +0 -0
  443. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secret_redaction.py +0 -0
  444. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secrets/__init__.py +0 -0
  445. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secrets/aws_provider.py +0 -0
  446. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secrets/azure_provider.py +0 -0
  447. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secrets/base.py +0 -0
  448. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secrets/env_provider.py +0 -0
  449. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secrets/vault_provider.py +0 -0
  450. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/soap_client.py +0 -0
  451. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/tdm.py +0 -0
  452. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/telemetry.py +0 -0
  453. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/telemetry_schema.py +0 -0
  454. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/transformation_validator.py +0 -0
  455. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/ui_db_validator.py +0 -0
  456. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/version_checker.py +0 -0
  457. {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/yaml_config_reader.py +0 -0
@@ -11,6 +11,26 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
11
11
 
12
12
  ---
13
13
 
14
+ ## [1.37.2] — 2026-10-11
15
+
16
+ `test-creation` can now commit generated tests to a feature branch of your sandbox repository and push that branch for you to validate and raise as a pull request; a hands-on playground with sample CSVs ships with the package (`pyplaykit docs test-creation`); scaffolded projects no longer break without pandas. Agents stay **disabled by default**, and branch mode needs `agents.autonomy.max: branch` plus `--autonomy branch`.
17
+
18
+ ### Behaviour changes — check before upgrading
19
+
20
+ - **Test runs started by agents no longer receive `PYPLAYKIT_SANDBOX_*` variables** (they hold the sandbox push token). *What to do:* nothing, unless a test reads such a variable; rename it.
21
+ - **`agents.scm.sandbox` is a new config block** (empty `repo` by default). Projects that copy `config/config.yaml` by hand can add it from a fresh `pyplaykit init`; without it the defaults apply.
22
+
23
+ ### Added
24
+
25
+ - **Test creation playground (`pyplaykit docs test-creation`).** A hands-on guide from a fresh `pip install` + `pyplaykit init` project: skeletons without a model, real tests with a model, sandbox feature branches, CSV format, settings and troubleshooting. Seven sample CSVs ship with the package (UI, API with inferred types, database, device, mixed, one row per step, custom column names); `pyplaykit docs <topic> --save-examples [DIR]` copies them (default `test_data/testcases/`, never overwrites).
26
+ - **Sandbox feature branches for `test-creation` (ADR-0019 amendment 1, US-AG12.3.3).** With `--autonomy branch` and `agents.scm.sandbox.repo` set, `pyplaykit agents run test-creation` clones the sandbox repository, creates `feature/test-creation/<csv>-<UTC time>` from `origin/main`, generates the tests against that repository's layout, validates them (`pytest --collect-only`; device tests in sim mode), commits them with the test-case CSV as the engineer, and pushes only the feature branch. It never opens a pull request or touches `main`: the engineer validates and edits the tests and opens the pull request. The push token comes from `PYPLAYKIT_SANDBOX_GIT_TOKEN` (environment or `.env`) and reaches git only as an HTTP header; test runs never receive it. New `agents.scm.sandbox` settings; one `sandbox_branch` audit record per run.
27
+
28
+ ### Fixed
29
+
30
+ - **Scaffolded data-comparison demos without pandas.** In a project created by `pyplaykit init` on a plain `pip install pyplaykit`, `test_demo_excel.py` broke test collection (`No module named 'pandas'`) and the file-comparison demos failed. They now skip with `pip install "pyplaykit[data-comparison]"`; `init` names the same extra when it skips the demo workbooks. Existing projects: re-run `pyplaykit init` does not replace existing files; copy the new guard from a fresh scaffold or install the extra.
31
+
32
+ ---
33
+
14
34
  ## [1.37.1] — 2026-10-11
15
35
 
16
36
  First release on PyPI of the QE agents Phase 1 work: the v1.37.0 tag was not published because its CI gate failed on three agent unit tests under `CI=true`. 1.37.1 contains everything in [1.37.0] below, plus two new built-in agents, `test-review` and `test-creation`. Agents stay **disabled by default**.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyplaykit
3
- Version: 1.37.1
3
+ Version: 1.37.2
4
4
  Summary: Enterprise Python + Playwright automation framework
5
5
  Author-email: Shan Konduru <shankonduru@gmail.com>
6
6
  License: MIT
@@ -1021,6 +1021,7 @@ Each project config includes:
1021
1021
  - GenAI spans for agent runs, LLM and tool calls (OpenTelemetry GenAI conventions), content capture off by default; `agent.*` events and `pyplaykit_agent_*` Prometheus metrics (tokens, cost, latency, tool calls, budget breaches, proposals); `reports/agents/runs.jsonl` and `usage_summary.json`, agent sections in the persona reports, a dashboard panel, `pyplaykit agents usage` and the MCP `list_agents` / `get_agent_usage` tools
1022
1022
  - v1.37.0: Phase 1 complete — tool layer and Python stack adapter, the test-impact map, and the first built-in agent `change-intelligence` (impact, risk score, regression plan applied with `--pyplaykit-select-from` in PR pipelines); user guide: `pyplaykit docs agents`
1023
1023
  - v1.37.1: first PyPI release of Phase 1 (v1.37.0 was not published), plus built-in agents `test-review` (test code quality) and `test-creation` (UI, API, database and device tests from test-case CSVs)
1024
+ - v1.37.2: `test-creation` commits to a feature branch of your sandbox repository and pushes it (never a pull request); hands-on playground with sample CSVs (`pyplaykit docs test-creation --save-examples`); scaffold demos skip without pandas
1024
1025
  - v1.36.0: agent governance and safety — policy through org governance, redaction, audit log, tool tiers, enforcement model
1025
1026
  - v1.35.0: agent observability — GenAI traces, `agent.*` events and `pyplaykit_agent_*` metrics, run log and reports
1026
1027
  - v1.34.0: LLM layer — provider-neutral requests, Anthropic / OpenAI-compatible / Ollama adapters, fake and record/replay clients, model tiers with fallback and retries, budgets, cost and a response cache. No built-in agents ship yet.
@@ -846,6 +846,7 @@ Each project config includes:
846
846
  - GenAI spans for agent runs, LLM and tool calls (OpenTelemetry GenAI conventions), content capture off by default; `agent.*` events and `pyplaykit_agent_*` Prometheus metrics (tokens, cost, latency, tool calls, budget breaches, proposals); `reports/agents/runs.jsonl` and `usage_summary.json`, agent sections in the persona reports, a dashboard panel, `pyplaykit agents usage` and the MCP `list_agents` / `get_agent_usage` tools
847
847
  - v1.37.0: Phase 1 complete — tool layer and Python stack adapter, the test-impact map, and the first built-in agent `change-intelligence` (impact, risk score, regression plan applied with `--pyplaykit-select-from` in PR pipelines); user guide: `pyplaykit docs agents`
848
848
  - v1.37.1: first PyPI release of Phase 1 (v1.37.0 was not published), plus built-in agents `test-review` (test code quality) and `test-creation` (UI, API, database and device tests from test-case CSVs)
849
+ - v1.37.2: `test-creation` commits to a feature branch of your sandbox repository and pushes it (never a pull request); hands-on playground with sample CSVs (`pyplaykit docs test-creation --save-examples`); scaffold demos skip without pandas
849
850
  - v1.36.0: agent governance and safety — policy through org governance, redaction, audit log, tool tiers, enforcement model
850
851
  - v1.35.0: agent observability — GenAI traces, `agent.*` events and `pyplaykit_agent_*` metrics, run log and reports
851
852
  - v1.34.0: LLM layer — provider-neutral requests, Anthropic / OpenAI-compatible / Ollama adapters, fake and record/replay clients, model tiers with fallback and retries, budgets, cost and a response cache. No built-in agents ship yet.
@@ -311,6 +311,14 @@ agents:
311
311
  scm:
312
312
  protected_branches: [main, master, "release/*"]
313
313
  allow_pr: false
314
+ sandbox: # test-creation with --autonomy branch (and autonomy.max: branch)
315
+ repo: "" # repository for feature branches (URL or path); "" = this repository
316
+ base: main # branches start from origin/<base>; never pushed to
317
+ branch_prefix: feature/test-creation
318
+ push: true # push the feature branch only; never a pull request
319
+ token_env: PYPLAYKIT_SANDBOX_GIT_TOKEN # token variable (environment, else .env); sent as a header only
320
+ writable: [tests, pages, test_data]
321
+ workspace: reports/agents/sandbox # clone and worktrees
314
322
  telemetry: # GenAI spans need telemetry.enabled (and otlp_endpoint for OTLP)
315
323
  capture_content: false # prompts, completions, tool arguments/results; redacted
316
324
  otlp_classes: [metadata] # data classes the OTLP endpoint may receive; captured content
@@ -953,6 +953,8 @@ Implemented in US-AG17.3.3 (`pyplaykit/agents/builtin/test_review/`): `test-revi
953
953
 
954
954
  Implemented in US-AG12.3.1 and US-AG12.3.2 ([ADR-0019](adr/0019-test-creation-from-test-cases-on-sandbox-branches.md), `pyplaykit/agents/builtin/test_creation/`): `test-creation` reads a test-case CSV (columns by name and synonyms; one row per case or per step), detects the `pyplaykit init` layout (multi- or single-project) with the new `list_files` read tool, gathers page objects, `BasePage`, utilities, fixtures, registered markers, DUTs and an example test per type, and asks the model per type and batch for test bodies and page-object members. The host assembles every file (imports, traceable docstrings, registered markers, unique module basenames, page-object edits that never overwrite existing code), checks it with the test-review rules and resends problems up to `fix_attempts`, and delivers a patch, report and skeletons when no model is available. `read_source` now reports each file's newline style so patches apply to CRLF and LF checkouts.
955
955
 
956
+ Implemented in US-AG12.3.3 ([ADR-0019](adr/0019-test-creation-from-test-cases-on-sandbox-branches.md) amendment 1, `pyplaykit/agents/sandbox.py`): with effective autonomy `branch`, `pyplaykit agents run` clones `agents.scm.sandbox.repo` (or uses the project's repository), adds a worktree on `<branch_prefix>/<name>-<UTC time>` from `origin/<base>`, stages local input files, points the run's read tools at the worktree, applies the agent's patch (only `writable` paths), validates with `pytest --collect-only` and device tests in sim mode, commits as the engineer and pushes the feature branch only (token as an HTTP header in git's environment, masked everywhere). No pull request is opened; one `sandbox_branch` audit record per run.
957
+
956
958
  **Order.** Read-only STLC agents (requirements review, test planning, test data design, test review, environment intelligence, execution optimizer, defect triage, test closure) can follow Phase 2 once their dependencies ship; agents that change files (service virtualization, defect reproduction, baseline and retirement proposals, feature files) need the Phase 4 proposal pipeline. Which STLC agents to build first is decided per client from the same value-and-risk view used for the core agents; each is released only through the agent release gates (§7).
957
959
 
958
960
  ### Shared capability: knowledge index
@@ -113,6 +113,9 @@ agents:
113
113
 
114
114
  ## 3c. test-creation
115
115
 
116
+ **Hands-on:** `pyplaykit docs test-creation` walks through it with sample CSVs
117
+ (`pyplaykit docs test-creation --save-examples`).
118
+
116
119
  Turns your test cases (a CSV in the repository) into PyPlayKit tests, in your project's own layout, reusing your
117
120
  page objects and the framework's libraries:
118
121
 
@@ -142,8 +145,42 @@ credentials only from environment variables. Without `Type` the agent infers it
142
145
  **Output:** `test_creation.patch` (apply with `git apply`), `test_creation.md` (each test case to its test, page
143
146
  objects changed, locators to verify) and `test_creation.json`. Without a model every test case becomes a skeleton
144
147
  with its steps as comments. Generated code is checked with the test-review rules and problems are sent back to
145
- the model up to `fix_attempts` times. A sandbox branch (`agents/test-creation/<run id>`) follows in the next
146
- release (ADR-0019).
148
+ the model up to `fix_attempts` times.
149
+
150
+ **Feature branches in your sandbox repository** (ADR-0019 amendment 1). With `--autonomy branch` (and
151
+ `agents.autonomy.max: branch`) the agent works on a fresh checkout of `agents.scm.sandbox.repo` instead of the
152
+ current project:
153
+
154
+ ```bash
155
+ export PYPLAYKIT_SANDBOX_GIT_TOKEN=... # or put it in .env (gitignored); Contents read/write on that repo only
156
+ pyplaykit agents run test-creation --autonomy branch \
157
+ --input '{"test_cases": "cases/checkout.csv", "project": "demo"}'
158
+ ```
159
+
160
+ 1. The host clones the repository (kept under `reports/agents/sandbox/`) and creates
161
+ `feature/test-creation/<csv name>-<UTC time>` from `origin/main`.
162
+ 2. Your CSV is copied to `test_data/testcases/` on that branch; the agent reads the sandbox repository's layout,
163
+ page objects, fixtures and markers and writes tests there (only `tests/`, `pages/`, `test_data/`).
164
+ 3. The new tests are collected with `pytest --collect-only` and device tests run in sim mode.
165
+ 4. The host commits as you (your git identity) and pushes **only the feature branch**. It never opens a pull
166
+ request and never touches `main`.
167
+ 5. You pull the branch, validate and edit the tests, and open the pull request to `main` when they work; the
168
+ output prints the GitHub page that opens it.
169
+
170
+ ```yaml
171
+ agents:
172
+ autonomy: {max: branch}
173
+ scm:
174
+ sandbox:
175
+ repo: https://github.com/ShanKonduru/pyplaykit-sandbox.git
176
+ base: main
177
+ branch_prefix: feature/test-creation
178
+ push: true # false: commit in the local worktree only
179
+ token_env: PYPLAYKIT_SANDBOX_GIT_TOKEN
180
+ ```
181
+
182
+ The exit code is 0 only when every test was generated, the branch was committed (and pushed) and validation
183
+ passed. Every run is recorded in the audit log (`sandbox_branch`), without credentials.
147
184
 
148
185
  ```yaml
149
186
  agents:
@@ -0,0 +1,269 @@
1
+ # Test creation playground: from test-case CSVs to PyPlayKit tests
2
+
3
+ A hands-on walkthrough of the `test-creation` agent. You start with no model and no git, then add a model, then
4
+ let the agent commit to a feature branch in your sandbox repository. Every command here works on a fresh
5
+ `pip install pyplaykit` + `pyplaykit init` project, using the sample CSVs that ship with the package.
6
+
7
+ Background and every setting: `pyplaykit docs agents` (section 3c). Design decisions: ADR-0019.
8
+
9
+ ---
10
+
11
+ ## 1. Set up a playground project (2 minutes)
12
+
13
+ ```bash
14
+ python -m venv .venv
15
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
16
+ pip install "pyplaykit[agents]" # the agents extra validates agent input and output
17
+ playwright install chromium
18
+
19
+ mkdir tc-playground && cd tc-playground
20
+ pyplaykit init # multi-project layout; the project is "demo"
21
+ git init -q && git add -A && git commit -qm "scaffold" # optional: lets you apply the patch with git
22
+ ```
23
+
24
+ Turn the agent on in `config/config.yaml` (the `agents:` block is already there, switched off):
25
+
26
+ ```yaml
27
+ agents:
28
+ enabled: true
29
+ enabled_agents: [test-creation]
30
+ ```
31
+
32
+ Check: `pyplaykit agents list` shows `test-creation`.
33
+
34
+ ## 2. Get the sample CSVs
35
+
36
+ ```bash
37
+ pyplaykit docs test-creation --save-examples # into test_data/testcases/ (never overwrites)
38
+ pyplaykit docs test-creation --save-examples cases # or any folder you like
39
+ ```
40
+
41
+ | File | What it shows |
42
+ |---|---|
43
+ | `ui_login.csv` | UI only: login and cart against the scaffolded `LoginPage` (SauceDemo) |
44
+ | `api_posts.csv` | API only, **no Type column**: the type is inferred from the steps (`GET /posts`, status codes) |
45
+ | `db_employees.csv` | Database: row counts and migrated values in the scaffolded `test_data/demo.db` |
46
+ | `device_thermostat.csv` | Device: the simulated `demo-thermostat` from `config/devices.yaml` |
47
+ | `mixed_checkout.csv` | One file with UI, API, DB and device test cases |
48
+ | `steps_per_row.csv` | One row per step: the test case id is filled only on its first row |
49
+ | `custom_columns.csv` | Your own column names, mapped in config (see section 6) |
50
+
51
+ ## 3. First run: skeletons, no model, no git
52
+
53
+ ```bash
54
+ pyplaykit agents run test-creation \
55
+ --input '{"test_cases": "test_data/testcases/ui_login.csv", "project": "demo", "summarise": false}'
56
+ ```
57
+
58
+ `"summarise": false` means "do not call a model": every test case becomes a **skeleton**, a test whose docstring
59
+ carries the test case id, objective and steps, with the steps as comments and `pytest.skip(...)` in the body. The
60
+ run reports `partial` and exits 1 because the tests still need bodies. That is expected here.
61
+
62
+ Windows PowerShell: put the JSON in a file and pass the path, e.g. `--input run.json`.
63
+
64
+ **Where the output is:** `reports/agents/runs/<run id>/artifacts/`
65
+
66
+ | File | Read it for |
67
+ |---|---|
68
+ | `test_creation.md` | Each test case → test function and file; page objects changed; locators to verify; notes |
69
+ | `test_creation.patch` | The change itself; apply it with `git apply` |
70
+ | `test_creation.json` | The same report for tools and pipelines (also the full new file contents) |
71
+
72
+ Find the newest run and apply it:
73
+
74
+ ```bash
75
+ ls -t reports/agents/runs | head -1 # the run id
76
+ git apply reports/agents/runs/<run id>/artifacts/test_creation.patch
77
+ pytest tests/demo/functional/ui --collect-only -q # the generated tests are collected
78
+ ```
79
+
80
+ Without git: copy the files from `test_creation.json` (`content`), or use the branch mode in section 5.
81
+
82
+ ## 4. With a model: real test bodies
83
+
84
+ Add a model to `config/config.yaml`. Any of the three adapters works; a local Ollama keeps everything on your
85
+ machine:
86
+
87
+ ```yaml
88
+ agents:
89
+ enabled: true
90
+ enabled_agents: [test-creation]
91
+ llm:
92
+ adapter: openai_compat # anthropic | openai_compat | ollama
93
+ endpoint: http://localhost:11434/v1 # Ollama's OpenAI-compatible endpoint
94
+ tiers:
95
+ strong: { model: "qwen3:14b" } # test-creation asks for the "strong" tier
96
+ providers:
97
+ default: { hosting: self_hosted }
98
+ ```
99
+
100
+ For a hosted model set `api_key: ${SECRET:PYPLAYKIT_LLM_API_KEY}` and allow what may be sent with
101
+ `agents.llm.egress` (see `pyplaykit docs agents`, section 2, and `pyplaykit docs secrets-governance`).
102
+
103
+ Then drop `"summarise": false`:
104
+
105
+ ```bash
106
+ # UI: reuses LoginPage; members it needs but cannot find are added, new locators are marked UNVERIFIED
107
+ pyplaykit agents run test-creation --input '{"test_cases": "test_data/testcases/ui_login.csv", "project": "demo"}'
108
+
109
+ # API: ApiClient + ResponseValidator; types inferred (the report says so)
110
+ pyplaykit agents run test-creation --input '{"test_cases": "test_data/testcases/api_posts.csv", "project": "demo"}'
111
+
112
+ # Database: db_client / DbValidationHelper against the demo database
113
+ pyplaykit agents run test-creation --input '{"test_cases": "test_data/testcases/db_employees.csv", "project": "demo"}'
114
+
115
+ # Device: dut, requires_dut("demo-thermostat"), sim_clock
116
+ pyplaykit agents run test-creation --input '{"test_cases": "test_data/testcases/device_thermostat.csv", "project": "demo"}'
117
+
118
+ # Everything at once: one module per type and feature
119
+ pyplaykit agents run test-creation --input '{"test_cases": "test_data/testcases/mixed_checkout.csv", "project": "demo"}'
120
+ ```
121
+
122
+ Narrow a run:
123
+
124
+ ```bash
125
+ # only some test cases
126
+ pyplaykit agents run test-creation --input '{"test_cases": "test_data/testcases/ui_login.csv", "ids": ["TC-UI-001", "TC-UI-004"]}'
127
+
128
+ # force a type for every selected test case (overrides the Type column and inference)
129
+ pyplaykit agents run test-creation --input '{"test_cases": "test_data/testcases/api_posts.csv", "type": "api"}'
130
+
131
+ # put every test in one feature folder
132
+ pyplaykit agents run test-creation --input '{"test_cases": "test_data/testcases/mixed_checkout.csv", "feature": "smoke_pack"}'
133
+ ```
134
+
135
+ Generated code is checked with the test-review rules (assertions, no sleeps, no raw selectors in tests, no
136
+ hardcoded URLs or credentials, no print). Problems go back to the model up to `fix_attempts` times; a test case
137
+ that still fails is written as a skeleton and listed in the report.
138
+
139
+ Run what was generated:
140
+
141
+ ```bash
142
+ git apply reports/agents/runs/<run id>/artifacts/test_creation.patch
143
+ pytest tests/demo/functional/api -v
144
+ pytest tests/demo/functional/device -v # simulated thermostat, no hardware
145
+ pytest tests/demo/functional/ui -v --pyplaykit-headed # export PYPLAYKIT_TEST_USERNAME / _PASSWORD first
146
+ ```
147
+
148
+ ## 5. Feature branches in your sandbox repository
149
+
150
+ Instead of a patch, the agent can commit the tests to a new feature branch of a repository you choose and push
151
+ that branch. It never opens a pull request and never touches `main`: you validate, edit, and open the PR.
152
+
153
+ ```yaml
154
+ agents:
155
+ enabled: true
156
+ enabled_agents: [test-creation]
157
+ autonomy:
158
+ max: branch # allow the branch level
159
+ scm:
160
+ protected_branches: [main, master, "release/*"]
161
+ sandbox:
162
+ repo: https://github.com/<you>/<your-sandbox>.git # a pyplaykit init project
163
+ base: main
164
+ branch_prefix: feature/test-creation
165
+ push: true # false: commit in a local worktree only
166
+ token_env: PYPLAYKIT_SANDBOX_GIT_TOKEN
167
+ ```
168
+
169
+ The token: a GitHub fine-grained token with **Contents: read and write** on that repository only. Put it in the
170
+ environment or in `.env` (gitignored) as `PYPLAYKIT_SANDBOX_GIT_TOKEN=...`. Git receives it only as an HTTP
171
+ header; it never appears in URLs, logs, the audit record or test runs.
172
+
173
+ ```bash
174
+ pyplaykit agents run test-creation --autonomy branch --project demo \
175
+ --input '{"test_cases": "test_data/testcases/ui_login.csv", "project": "demo"}'
176
+ ```
177
+
178
+ ```text
179
+ succeeded: 4 test case(s) -> 4 generated test(s), 0 skeleton(s) in 2 file(s); 1 page object(s) changed, ...
180
+ sandbox: pushed (https://github.com/<you>/<your-sandbox>.git, base main)
181
+ branch feature/test-creation/ui-login-20261011-155901 @ f2a9a7fead59
182
+ validation passed
183
+ next validate and edit the tests, then open the pull request: https://github.com/<you>/<your-sandbox>/compare/main...feature/test-creation/ui-login-20261011-155901?expand=1
184
+ ```
185
+
186
+ What happened:
187
+
188
+ 1. The repository was cloned to `reports/agents/sandbox/` and `feature/test-creation/<csv>-<UTC time>` created
189
+ from `origin/main`.
190
+ 2. Your CSV was copied to `test_data/testcases/` on the branch, so the test cases travel with the tests.
191
+ 3. The agent read **that** repository's layout, page objects, fixtures and markers, and wrote only under
192
+ `tests/`, `pages/` and `test_data/`.
193
+ 4. The new tests were collected (`pytest --collect-only`), device tests ran in sim mode.
194
+ 5. The commit is yours (your git name and email); only the feature branch was pushed.
195
+
196
+ Then, on your machine:
197
+
198
+ ```bash
199
+ git fetch origin
200
+ git switch feature/test-creation/ui-login-20261011-155901
201
+ pytest tests/demo/functional/ui -v # validate; edit tests and verify UNVERIFIED locators
202
+ git commit -am "Verify locators" && git push
203
+ # open the pull request to main (the link printed above)
204
+ ```
205
+
206
+ The CSV can also be outside the project: an absolute path or a path relative to the project is copied in.
207
+
208
+ ## 6. Your own CSVs
209
+
210
+ Columns are found by name; case, spaces, `-` and `_` are ignored.
211
+
212
+ | Field | Required | Column names it recognises |
213
+ |---|---|---|
214
+ | id | yes | Test Case ID, TC ID, TC No, ID, Test ID, Case ID |
215
+ | name | yes | Test Case Name, Name, Title, Summary, Scenario |
216
+ | steps | yes | Test Steps - Actions, Steps, Actions, Step, Procedure |
217
+ | expected | | Expected Steps, Expected Result(s), Expected, Expected Outcome |
218
+ | description | | Test Case Description, Description, Details |
219
+ | objective | | Test Objective, Objective, Purpose, Goal |
220
+ | type | | Type, Test Type, Category, Layer: `UI`/`Web`, `API`/`REST`, `DB`/`Database`/`SQL`, `Device`/`Embedded`/`IoT` |
221
+ | feature | | Feature, Module, Component, Area (the folder under `functional/<type>/`) |
222
+ | tags | | Tags, Labels, Markers, Suite: offered as markers; only markers registered in `pytest.ini` are kept |
223
+ | preconditions, test data, priority | | Preconditions, Test Data, Priority / Severity: given to the model |
224
+
225
+ **Steps:** numbered lines in one cell (`1. Open ...` newline `2. Enter ...`) pair with numbered expected
226
+ results; or one row per step with the id only on the first row (`steps_per_row.csv`).
227
+
228
+ **Other column names:** map them in config. `custom_columns.csv` uses `Why` and `Outcome`:
229
+
230
+ ```yaml
231
+ agents:
232
+ test_creation:
233
+ columns: {objective: "Why", expected: "Outcome"}
234
+ ```
235
+
236
+ **Excel:** save the sheet as CSV (UTF-8). Cells with line breaks are fine; Excel quotes them.
237
+
238
+ **Type inference** (no Type column): `GET /path`, status codes, payloads → API; `SELECT`, tables, row counts →
239
+ DB; device, firmware, console, sensor → device; click, page, button, login → UI. The report marks inferred types;
240
+ set the column or `"type"` when it guesses wrong.
241
+
242
+ ## 7. Settings worth knowing
243
+
244
+ ```yaml
245
+ agents:
246
+ test_creation:
247
+ max_test_cases: 25 # per run; a warning says how many were left out
248
+ batch_size: 5 # test cases per model request
249
+ fix_attempts: 2 # rounds of review findings sent back to the model
250
+ columns: {} # field -> your column name
251
+ ```
252
+
253
+ ## 8. Troubleshooting
254
+
255
+ | You see | Do this |
256
+ |---|---|
257
+ | `agents are disabled` / `not in enabled_agents` | `agents.enabled: true` and `enabled_agents: [test-creation]` |
258
+ | `validating agent input needs 'jsonschema'` | `pip install "pyplaykit[agents]"` |
259
+ | `cannot read '...csv' through read_source` | The path is relative to the project root (patch mode); in branch mode local files are copied in |
260
+ | `The test-case file cannot be used` | A required column (id, name, steps) is missing; rename it or map it in `columns` |
261
+ | Every test is a skeleton, `provider_failure` | No model reachable: check `agents.llm`; or use `"summarise": false` on purpose |
262
+ | `The target project is unclear` | Multi-project layout with several projects: pass `"project": "<name>"` |
263
+ | `sandbox: git clone failed` | Check `scm.sandbox.repo` and the token (`Contents: read and write` on that repository) |
264
+ | `branch ... is protected` | `branch_prefix` matches `protected_branches`; use e.g. `feature/test-creation` |
265
+ | `validation failed` (collect) | The branch is still pushed; fix the import or fixture on the branch and push |
266
+ | Branch mode not used | Needs `--autonomy branch` **and** `agents.autonomy.max: branch` |
267
+
268
+ Exit codes: `0` every test generated (and, in branch mode, committed, pushed and validated); `1` partial results
269
+ (skeletons, validation or push failed: see the output); `2` the run could not start (config, input, sandbox).
@@ -87,3 +87,35 @@
87
87
  `recommend` (patch only).
88
88
  - 🔧 Plan: EP-AG12 gains "Test creation from test cases (Python)"; EP-AG10's worktree and agent-branch stories are
89
89
  delivered with it for `test-creation`; recipes (EP-AG12 F1) later absorb the per-type rules.
90
+
91
+ ## Amendment 1 (2026-10-11): feature branches in a separate sandbox repository
92
+
93
+ Decided with the team after the first release of the agent. Decision 5 changes as follows; the rest stands.
94
+
95
+ - **Where.** The branch is created in the repository named by `agents.scm.sandbox.repo` (a URL or a local path;
96
+ e.g. `https://github.com/ShanKonduru/pyplaykit-sandbox.git`), from `origin/<base>` (`base`, default `main`). The
97
+ host keeps a clone under `reports/agents/sandbox/` and adds a worktree per run. Without `repo`, the project's own
98
+ repository is used as before (from `base`, else `HEAD`).
99
+ - **What the agent reads.** The run's read tools point at the sandbox worktree, so the agent learns *that*
100
+ repository's layout, page objects, fixtures and markers. A local test-case file named in the input is copied to
101
+ `test_data/testcases/` on the branch and committed with the tests (traceability).
102
+ - **Branch name.** `<branch_prefix>/<test-case file>-<UTC time>` (default prefix `feature/test-creation`); a name
103
+ matching `agents.scm.protected_branches` or `base` is refused.
104
+ - **Push.** With `push: true` (default) the host pushes the feature branch only: never the base branch, never
105
+ forced, and never a pull request (`agents.scm.allow_pr` stays false). The engineer pulls the branch, validates
106
+ and edits the tests offline, and opens the pull request to `base` when they work. With `push: false` the commit
107
+ stays in the local worktree.
108
+ - **Credentials.** A token in the variable named by `token_env` (default `PYPLAYKIT_SANDBOX_GIT_TOKEN`; from the
109
+ environment, else the project's `.env`) reaches git only as an HTTP header in git's environment, scoped to the
110
+ remote's host: never in a URL, argument, file, log or the audit record, and masked in every message. Test runs
111
+ never receive it (the scrubbed environment refuses `PYPLAYKIT_SANDBOX_*`). Without it git uses its own
112
+ credential helpers.
113
+ - **Validation.** `pytest --collect-only` on the new test modules, and device tests in `sim` mode (judged by their
114
+ JUnit results, so a repository's session gates do not mask passing tests). A failed check does not block the
115
+ commit: the branch is for the engineer to fix, and the result, the commit message and the CLI exit code (1) say
116
+ so. Collection errors are not sent back to the model in v1 (decision 6's fix loop covers syntax and the
117
+ test-review rules).
118
+ - **Audit.** One `sandbox_branch` record per run: repository (without credentials), base, branch, commit, pushed,
119
+ files, validation status.
120
+ - **Writes.** Only the patch's paths under `writable` (default `tests/`, `pages/`, `test_data/`) and the staged
121
+ input file are committed; a patch with any other path is refused and the branch is discarded.
@@ -10,8 +10,9 @@
10
10
  objects in the page directory. Only ``tests/``, the page directory and ``test_data/`` may be written (F5b).
11
11
  4. Validate statically (syntax, the test-review rules) and send problems back to the model up to
12
12
  ``fix_attempts``; a test case that still fails becomes a traceable skeleton.
13
- 5. Deliver ``test_creation.patch``, ``test_creation.md`` and ``test_creation.json``. The sandbox branch
14
- (US-AG12.3.3) applies the same files on ``agents/test-creation/<run id>``.
13
+ 5. Deliver ``test_creation.patch``, ``test_creation.md`` and ``test_creation.json``. With autonomy ``branch``
14
+ the host runs the agent on a sandbox worktree and commits the patch to a feature branch
15
+ (:mod:`pyplaykit.agents.sandbox`, US-AG12.3.3).
15
16
 
16
17
  Without a model every test case becomes a skeleton (docstring with the steps, ``pytest.skip``) and the run is
17
18
  ``partial``.
@@ -449,7 +450,8 @@ class TestCreationAgent:
449
450
  tests = report["tests"]
450
451
  lines = [f"# Generated tests from `{report['source']}`", "",
451
452
  f"Layout: {report['layout']}-project" + (f", project `{report['project']}`" if report["project"] else ""),
452
- "", "Apply with `git apply test_creation.patch` (or use the sandbox branch), then review.", "",
453
+ "", "Apply with `git apply test_creation.patch` (with `--autonomy branch` it is committed to a sandbox "
454
+ "feature branch), then review.", "",
453
455
  "| Test case | Type | Test | Notes |", "|---|---|---|---|"]
454
456
  for test in tests:
455
457
  notes = []
@@ -33,7 +33,9 @@ from pyplaykit.agents.output import encode
33
33
  from pyplaykit.agents.policy import agent_policy_report, resolve_agent_policy
34
34
  from pyplaykit.agents.registry import BUILTIN_DIR, DiscoveredAgent, DiscoveryReport
35
35
  from pyplaykit.agents.reports import aggregate
36
- from pyplaykit.agents.runner import RunRequest, effective_autonomy, mcp_status
36
+ from pyplaykit.agents import sandbox
37
+ from pyplaykit.agents.runner import RunRequest, autonomy_allows, effective_autonomy, mcp_status
38
+ from pyplaykit.agents.stacks.environment import execution_environment
37
39
  from pyplaykit.agents.audit import DEFAULT_RETENTION_DAYS as AUDIT_RETENTION_DAYS
38
40
  from pyplaykit.agents.audit import chain_head, verify
39
41
  from pyplaykit.agents.enforcement import controls_by_class, scan_path
@@ -428,29 +430,86 @@ def _run(report: DiscoveryReport, section: dict[str, Any], args: argparse.Namesp
428
430
  except (OSError, ValueError) as exc:
429
431
  print(f"error: invalid --input: {exc}", file=out)
430
432
  return 2
433
+ project_root = config_dir.resolve().parent
434
+ policy = run_policy(section, base_dir=project_root, project=args.project)
435
+ box = None
436
+ try:
437
+ level = effective_autonomy(agent.manifest.autonomy_max, policy.autonomy_max, args.autonomy)
438
+ except ValueError:
439
+ level = "analyze" # the runner reports the invalid level
440
+ if autonomy_allows(level, "branch"):
441
+ try: # US-AG12.3.3: the agent works on a feature branch of the sandbox repository
442
+ box = sandbox.Sandbox(sandbox.SandboxConfig.from_section(section), project_root)
443
+ hint = Path(str(payload.get("test_cases") or args.agent)).stem
444
+ box.prepare(hint)
445
+ payload = box.stage_inputs(payload, project_root)
446
+ except (sandbox.SandboxError, OSError) as exc:
447
+ message = box.mask(str(exc)) if box else str(exc)
448
+ if box:
449
+ box.discard(message)
450
+ print(f"error: sandbox: {encode(message, 'terminal')}", file=out)
451
+ return 2
431
452
  request = RunRequest(agent=agent, project=args.project, input=payload, requested_autonomy=args.autonomy,
432
453
  stack=args.stack, trace_context=trace_links(), trigger="cli", environment=args.env)
433
454
  try:
434
- runner = agent_runner(section, config_dir, project=args.project)
455
+ runner = agent_runner(section, config_dir, project=args.project, tools_root=box.worktree if box else None)
435
456
  except ValueError as exc: # agents.llm, agents.telemetry or the agents policy is invalid
457
+ if box:
458
+ box.discard(str(exc))
436
459
  print(f"error: {exc}", file=out)
437
460
  return 2
438
461
  try:
439
- outcome = runner.run(request, run_policy(section, base_dir=config_dir.resolve().parent, project=args.project))
462
+ outcome = runner.run(request, policy)
440
463
  finally:
441
464
  runner.close()
442
465
  result = outcome.result
466
+ branch = None
467
+ if box:
468
+ env = execution_environment(section, config_dir=box.worktree / "config", environment=args.env).env
469
+ timeout = int((section.get("execution") or {}).get("timeout_s") or 900)
470
+ branch = sandbox.complete(box, result, runner.artifacts_dir or project_root / "reports/agents/runs",
471
+ agent=args.agent, env=env, timeout=timeout)
472
+ audit_log(config_dir).append("sandbox_branch", agent=args.agent, run_id=result.run_id,
473
+ **{k: v for k, v in branch.to_dict().items() if k not in ("validation",)},
474
+ validation=branch.validation.get("status"))
443
475
  if args.json:
444
- print(json.dumps({"mcp_status": mcp_status(result), "result": to_dict(result), "events": outcome.events},
445
- indent=2, default=str), file=out)
476
+ print(json.dumps({"mcp_status": mcp_status(result), "result": to_dict(result), "events": outcome.events,
477
+ **({"sandbox": branch.to_dict()} if branch else {})}, indent=2, default=str), file=out)
446
478
  else:
447
479
  print(f"{result.status}: {encode(result.summary, 'terminal')}", file=out)
448
480
  if result.error:
449
481
  print(f" {result.error.category}: {encode(result.error.message, 'terminal')}", file=out)
450
482
  for warning in result.warnings:
451
483
  print(f" warning: {encode(warning, 'terminal')}", file=out)
484
+ if branch:
485
+ _print_sandbox(branch, out)
486
+ if branch and (branch.status not in ("committed", "pushed") or branch.error
487
+ or branch.validation.get("status") == "failed"):
488
+ return 1
452
489
  return 0 if result.status == "succeeded" else 1
453
490
 
454
491
 
492
+ def _print_sandbox(branch: sandbox.SandboxOutcome, out: TextIO) -> None:
493
+ print(f"sandbox: {branch.status} ({branch.repo}, base {branch.base})", file=out)
494
+ if branch.branch:
495
+ print(f" branch {branch.branch}" + (f" @ {branch.commit[:12]}" if branch.commit else ""), file=out)
496
+ if branch.validation:
497
+ print(f" validation {branch.validation['status']}", file=out)
498
+ for name, check in branch.validation.items():
499
+ if isinstance(check, dict) and not check["passed"]:
500
+ print(f" {name} failed (exit {check['exit_code']}):", file=out)
501
+ for line in check["output"].splitlines()[-10:]:
502
+ print(f" {encode(line, 'terminal')}", file=out)
503
+ if branch.pull_request_url:
504
+ print(f" next validate and edit the tests, then open the pull request: {branch.pull_request_url}",
505
+ file=out)
506
+ elif branch.worktree:
507
+ print(f" worktree {branch.worktree}", file=out)
508
+ if branch.error:
509
+ print(f" error: {encode(branch.error, 'terminal')}", file=out)
510
+ for warning in branch.warnings:
511
+ print(f" warning: {encode(warning, 'terminal')}", file=out)
512
+
513
+
455
514
  if __name__ == "__main__": # pragma: no cover - python -m pyplaykit.agents.cli (CI templates)
456
515
  sys.exit(main())