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.
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/CHANGELOG.md +20 -0
- {pyplaykit-1.37.1/pyplaykit.egg-info → pyplaykit-1.37.2}/PKG-INFO +2 -1
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/README.md +1 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/config.yaml +8 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_AGENTS_DESIGN.md +2 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_AGENTS_GUIDE.md +39 -2
- pyplaykit-1.37.2/docs/TEST_CREATION_PLAYGROUND.md +269 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0019-test-creation-from-test-cases-on-sandbox-branches.md +32 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/agent.py +5 -3
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/cli.py +64 -5
- pyplaykit-1.37.2/pyplaykit/agents/sandbox.py +445 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/settings.py +9 -2
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/stacks/environment.py +1 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/cli.py +57 -16
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/config/config.yaml +8 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/QE_AGENTS_GUIDE.md +39 -2
- pyplaykit-1.37.2/pyplaykit/docs/TEST_CREATION_PLAYGROUND.md +269 -0
- pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/api_posts.csv +8 -0
- pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/custom_columns.csv +7 -0
- pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/db_employees.csv +11 -0
- pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/device_thermostat.csv +12 -0
- pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/mixed_checkout.csv +13 -0
- pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/steps_per_row.csv +7 -0
- pyplaykit-1.37.2/pyplaykit/docs/examples/testcases/ui_login.csv +21 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2/pyplaykit.egg-info}/PKG-INFO +2 -1
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit.egg-info/SOURCES.txt +10 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyproject.toml +2 -2
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/.github/copilot-instructions.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/.github/prompts/review-execution-plan-and-implement-next-task.prompt.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/.github/prompts/run-unit-tests-and-coverage.prompt.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/.github/prompts/security-audit-and-consolidated-report.prompt.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/CHOOSE_YOUR_STRUCTURE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/CLAUDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/COLUMN_MAPPING_AND_IGNORE_FIELDS_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/COMMANDS_FOR_YOUR_PROJECTS.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/COMMIT_SUMMARY.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/CONTRIBUTING.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/CORRECTED_PROJECT_NAMES.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/DATABASE_IMPLEMENTATION_SUMMARY.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/DELIVERABLES_SUMMARY.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/ENTERPRISE_TEST_STRUCTURE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/FINAL_PROJECT_SETUP.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/GAP_TRACKER.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/HOW_TO_ACCESS_DOCS.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/INIT_COMMAND_EXAMPLES.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/KEY_BASED_MATCHING_SOLUTION.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/MANIFEST.in +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/MIGRATION_COMPLETE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/MIGRATION_PLAN.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/PIP_INSTALL_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/PYPLAYKIT_CLIENT_OVERVIEW.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/QUICK_DB_REFERENCE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/QUICK_REFERENCE_COMPARISON_FEATURES.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/QUICK_START_QE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/STRUCTURE_COMPARISON.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/TEST_LOCATION_CHEATSHEET.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/VISUAL_COMPARISON.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/WINDOWS_INSTALL_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/YOUR_PROJECTS_IMPLEMENTATION_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/YOUR_SETUP_SUMMARY.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/bin/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/components/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/components/base_component.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/components/data_table.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/components/form_field.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/components/modal.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/data_comparison_profiles.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/devices.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/environments.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/projects/customs_modernization.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/projects/device_lab.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/projects/dispatcho.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/config/projects/timelyquote.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/core/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/core/base_page.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/core/base_test.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/core/browser_factory.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/core/playwright_manager.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/core/quality_gate.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/data_validation_dashboard.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/docker-compose.yml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/engineering_dashboard.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/executive_qe_dashboard.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/grafana-provisioning/dashboards/pyplaykit.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/prometheus.yml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/release_quality_dashboard.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dashboards/test_health_dashboard.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/demo/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/demo/device_lab/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/demo/functional/database/file_comparison/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/demo/functional/database/postgres_src_tgt/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dist_pkg/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/dist_pkg/distribution.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/API_TESTING_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/ARCHITECTURE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/CI_INTEGRATION.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/CLI_REFERENCE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/COMPETITIVE_ANALYSIS.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/COVERAGE_IMPROVEMENTS.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/CUSTOMER_SCENARIOS.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/DATABASE_SUPPORT.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/DATA_VALIDATION_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/DELIVERABLES_INDEX.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/DEVICE_AUTOMATION_WBS.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/EXAMPLE_TESTS_SUMMARY.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/Enterprise-Framework-Assessment-REVISED.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/Enterprise-Readiness-Assessment.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/Example-Tests-Guide.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/Execution-Plan-Backlog-and-Closure-Tracker.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/FRAMEWORK_CONTRIBUTION_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/01_ARCHITECTURE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/02_DEPLOYMENT_RUNBOOK.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/03_ACCESS_MATRIX.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/04_CLIENT_CONTACT_MATRIX.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/05_OPEN_RISKS_REGISTER.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/06_PENDING_ENHANCEMENTS.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/07_PRODUCT_ROADMAP.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/08_ENVIRONMENT_DETAILS.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/09_OPERATIONAL_SOPS.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/10_ESCALATION_MATRIX.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/11_KT_RECORDINGS_INDEX.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/12_REVERSE_KT_SIGNOFF.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/13_LEADERSHIP_SIGNOFF.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/KT/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/MCP_SERVER_DESIGN.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/MULTI_DB_VALIDATION_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/MULTI_PROJECT_STRUCTURE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/OBSERVABILITY.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/PIP_INSTALL_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/PLUGIN_AUTHORING_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/PyPlayKit-Framework-Overview.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/PyPlayKit-Usage-Scenarios.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_AGENTS_CAPABILITY_INVENTORY.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_AGENTS_SPIKES.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_AGENTS_THREAT_MODEL.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_AGENT_PLATFORM_EXPANSION.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QE_VISUAL_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/QUALITY_GATE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/RESILIENCE_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/RUN_TESTS_QUICK_REFERENCE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/SECRETS_AND_GOVERNANCE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/TEST_ORGANIZATION.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/Usage-Scenarios-Feasibility-Analysis.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0001-sync-device-api-with-background-io.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0002-devices-subpackage-and-layering.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0003-dut-naming-for-cli-config-and-fixtures.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0004-optional-dependencies-and-import-guards.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0005-single-source-device-pytest-plugin.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0006-agent-runtime-transport.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0007-agent-autonomy-and-scm-boundaries.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0008-agent-contract-and-versioning.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0009-host-mediation-and-enforcement-model.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0010-target-stack-adapters-and-result-normalization.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0011-generation-capability-registry.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0012-regression-test-selection-safety.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0013-agent-telemetry-and-data-handling.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0014-agents-adopt-vs-build.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0015-agent-release-lifecycle-and-registry.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0016-review-driven-amendments.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0017-agent-evaluation-baseline-then-threshold.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/0018-change-intelligence-without-product-source.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/adr/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/device_automation/DESIGN.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/device_automation/GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/docs/device_automation/SPIKES.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/integrations/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/integrations/adapters.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/_ast_utils.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/_config_utils.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/cli.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/server.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/tools/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/tools/agent_tools.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/tools/device_tools.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/tools/package_discovery.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/tools/project_introspection.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/mcp_server/tools/project_state.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/orchestration/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/orchestration/enforcer.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/orchestration/planner.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/orchestration/selection.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pages/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pages/dashboard_page.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pages/login_page.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pages/orangehrm_login_page.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pages/saucedemo_inventory_page.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pages/saucedemo_login_page.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/_observer.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/_reference.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/api_plugin.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/base.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/data_plugin.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/manifest.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/registry.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/plugins/security_plugin.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/PIP_INSTALL_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/__main__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/audit.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/budgets.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/_common.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/agent.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/agent.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/impact.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/prompts/change_semantics.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/prompts/regression_additions.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/risk.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/schemas/input.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/schemas/output.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/change_intelligence/selection.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/agent.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/assemble.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/layout.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/prompts/generate_tests.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/prompts/guide_api.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/prompts/guide_db.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/prompts/guide_device.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/prompts/guide_ui.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/schemas/input.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/schemas/output.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_creation/testcases.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/agent.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/agent.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/prompts/test_intent.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/rules.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/schemas/input.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/builtin/test_review/schemas/output.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/contract.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/enforcement.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/errors.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/host_tools.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/impact_map.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/anthropic.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/base.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/cache.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/fake.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/ollama.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/openai_compat.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/pricing.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/recording.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/llm/routing.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/output.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/policy.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/read_tools.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/redaction.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/registry.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/reports.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/runner.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/schemas/1/agent-manifest.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/schemas/1/change-proposal.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/schemas/1/run-result.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/schemas/1/task-envelope.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/session.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/stacks/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/stacks/base.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/stacks/junit.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/stacks/python_pytest.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/telemetry.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/agents/tools.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/config/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/config/devices.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/config/environments.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/_extras.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/assertions.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/buffer.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/candb.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/channel.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/clock.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/commands.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/components.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/config.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/console.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/device.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/editor.html +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/editor.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/errors.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/events.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/factory.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/fault_proxy.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/faults.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/fidelity.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/gatt.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/introspect.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/inventory.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/leasing.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/matching.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/messages.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/parsers.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/pool.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/power.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/provider.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/pytest_plugin.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/recording.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/recovery.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/registers.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/ble.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/components.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/base.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/ble.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/can.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/http.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/modbus.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/mqtt.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/serial.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/endpoints/ssh.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/host.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/modbus.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/replay.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/scheduler.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/seed.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/sensor_faults.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/serve.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/signals.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/subprocess_twin.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/templating.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twin.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/energy_meter.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/engine.dbc +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/engine_ecu.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/environment_sensor.yaml +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/heart_rate.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/smart_plug.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/twins/thermostat.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/sim/yaml_twin.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/snmp.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/terminal.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/testing.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transcript.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transport.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/_async_bridge.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/adb.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/ble.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/can.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/coap.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/http.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/modbus.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/mqtt.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/serial.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/ssh.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/transports/telnet.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/waiting.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/devices/yamlutil.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/API_TESTING_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/ARCHITECTURE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/CI_INTEGRATION.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/CLI_REFERENCE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/DATABASE_SUPPORT.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/DATA_VALIDATION_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/MCP_SERVER_DESIGN.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/MULTI_PROJECT_STRUCTURE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/OBSERVABILITY.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/PLUGIN_AUTHORING_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/QE_VISUAL_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/QUICK_START_QE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/RESILIENCE_GUIDE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/RUN_TESTS_QUICK_REFERENCE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/SECRETS_AND_GOVERNANCE.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/docs/TEST_ORGANIZATION.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/extras.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/plugin.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit/show_docs.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit.egg-info/dependency_links.txt +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit.egg-info/entry_points.txt +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit.egg-info/requires.txt +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/pyplaykit.egg-info/top_level.txt +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/resilience/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/resilience/locator_recovery.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/setup.cfg +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/spikes/device_automation/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/spikes/qe_agents/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/api/ecom/auth_payloads.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/api/ecom/product_payloads.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/api_test_data.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/data_validation_test_data.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/login_test_data.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/orangehrm_login_data.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/pacts/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/test_data/ui_test_data.json +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/customs_modernization/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/demo/functional/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/demo/functional/api/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/demo/functional/database/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/demo/functional/ui/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/demo/integration/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/dispatcho/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/tests/projects/timelyquote/README.md +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/api_client.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/api_test_helper.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/assertion_helper.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/auth_manager.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/comparison_config_loader.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/contract/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/contract/pact_consumer.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/dashboard.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/data_comparison_report.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/data_comparison_utils.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/data_loader.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/data_source.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/data_validator.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/database_clients.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_client.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/db2.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/informix.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/mongodb.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/mysql.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/oracle.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/snowflake.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/sqlite.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_drivers/sqlserver.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_factory.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_fixtures.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_pool.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/db_validation_helper.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/environment_validator.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/file_reader.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/governance.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/graphql_client.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/logger.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/observability.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/observability_report.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/org_governance.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/project_config.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/response_validator.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/screenshot_helper.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secret_redaction.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secrets/__init__.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secrets/aws_provider.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secrets/azure_provider.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secrets/base.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secrets/env_provider.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/secrets/vault_provider.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/soap_client.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/tdm.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/telemetry.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/telemetry_schema.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/transformation_validator.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/ui_db_validator.py +0 -0
- {pyplaykit-1.37.1 → pyplaykit-1.37.2}/utils/version_checker.py +0 -0
- {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.
|
|
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.
|
|
146
|
-
|
|
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``.
|
|
14
|
-
|
|
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` (
|
|
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
|
|
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,
|
|
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
|
-
|
|
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())
|