tuner-testkit 5.0.0__tar.gz → 5.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tuner_testkit-5.0.0/tuner_testkit.egg-info → tuner_testkit-5.2.0}/PKG-INFO +6 -3
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/README.md +1 -1
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/pyproject.toml +9 -2
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/__init__.py +1 -1
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/action_words/base.py +4 -1
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/action_words/registry.py +19 -3
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/apps-authoring.mdc +2 -1
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/commit-convention.mdc +3 -3
- tuner_testkit-5.2.0/tuner_testkit/apps/dna/dna_payload/.cursor/rules/work-task.mdc +24 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/create-action-word/SKILL.md +8 -2
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/create-app/SKILL.md +12 -6
- tuner_testkit-5.2.0/tuner_testkit/apps/dna/dna_payload/.cursor/skills/derive-test-design/SKILL.md +73 -0
- tuner_testkit-5.2.0/tuner_testkit/apps/dna/dna_payload/.cursor/skills/generate-test-report/SKILL.md +74 -0
- tuner_testkit-5.2.0/tuner_testkit/apps/dna/dna_payload/.cursor/skills/run-test-execution/SKILL.md +42 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/AGENTS.md +5 -3
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/MANIFEST.txt +1 -1
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/action-words-syntax.md +17 -5
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/agent-task-log.md +11 -1
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/apps-authoring-syntax.md +33 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/artifacts-layout.md +4 -2
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/assets-knowledge-syntax.md +2 -1
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/commit-convention.md +1 -0
- tuner_testkit-5.2.0/tuner_testkit/apps/dna/dna_payload/docs/spec/metadata-conventions.md +70 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/sut-self-learning.md +1 -1
- tuner_testkit-5.2.0/tuner_testkit/apps/dna/dna_payload/docs/spec/test-design-syntax.md +66 -0
- tuner_testkit-5.2.0/tuner_testkit/apps/dna/dna_payload/docs/spec/work-task.md +93 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/validate_commit_msg.py +3 -1
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/evidence/cli.py +31 -1
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/evidence/persist.py +143 -2
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/evidence/tests/test_persist.py +32 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/index_ai/registry.py +99 -4
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/scaffold.py +2 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/registry.py +1 -1
- tuner_testkit-5.2.0/tuner_testkit/apps/init_repo/stubs/workbench.cmd +3 -0
- tuner_testkit-5.2.0/tuner_testkit/apps/init_repo/stubs/workbench.sh +3 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/tests/test_git_hooks.py +3 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/tests/test_scaffold.py +2 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/mock_server/cli.py +2 -2
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/page_recorder/freeze.py +1 -1
- tuner_testkit-5.2.0/tuner_testkit/apps/task/__init__.py +5 -0
- tuner_testkit-5.2.0/tuner_testkit/apps/task/__main__.py +3 -0
- tuner_testkit-5.2.0/tuner_testkit/apps/task/cli.py +192 -0
- tuner_testkit-5.2.0/tuner_testkit/apps/task/store.py +460 -0
- tuner_testkit-5.2.0/tuner_testkit/apps/task/tests/test_store.py +108 -0
- tuner_testkit-5.2.0/tuner_testkit/apps/task/validate.py +47 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/catalog/__init__.py +6 -2
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/catalog/build.py +12 -0
- tuner_testkit-5.2.0/tuner_testkit/catalog/directory.py +91 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/catalog/scan.py +29 -7
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/catalog/tests/test_build.py +2 -0
- tuner_testkit-5.2.0/tuner_testkit/catalog/tests/test_directory.py +172 -0
- tuner_testkit-5.2.0/tuner_testkit/tools/runner.py +213 -0
- tuner_testkit-5.2.0/tuner_testkit/tools/tests/test_runner.py +45 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/__init__.py +14 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/__main__.py +4 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/app.py +475 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/cli.py +49 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/kinds/__init__.py +97 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/kinds/app_generic.py +13 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/kinds/word_db_seed.py +13 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/kinds/word_generic.py +22 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/static/app.css +24 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/_params_form.html +64 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/ai.html +47 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/ai_detail.html +27 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/base.html +26 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/env.html +24 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/history.html +20 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/home.html +24 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/knowledge.html +21 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/run.html +27 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/tool.html +17 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/tools.html +26 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/word.html +15 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/word_db_seed.html +23 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/templates/words.html +25 -0
- tuner_testkit-5.2.0/tuner_testkit/workbench/tests/test_app.py +120 -0
- tuner_testkit-5.2.0/tuner_testkit/workspace/meta.py +70 -0
- tuner_testkit-5.2.0/tuner_testkit/workspace/tests/test_meta.py +21 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0/tuner_testkit.egg-info}/PKG-INFO +6 -3
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit.egg-info/SOURCES.txt +42 -1
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit.egg-info/entry_points.txt +2 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit.egg-info/requires.txt +5 -1
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/LICENSE +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/setup.cfg +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/action_words/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/action_words/__main__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/action_words/_internal/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/action_words/_internal/api.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/action_words/_internal/db.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/action_words/_internal/generators.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/action_words/_internal/ids.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/action_words/_internal/wait.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/action_words/context.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_mock/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_mock/app.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_mock/errors.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_mock/router.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_mock/spec.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_mock/store.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_objects/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_objects/auth.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_objects/recording/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_objects/recording/capture.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_objects/recording/codegen.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_objects/recording/freeze.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_objects/recording/mocks.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_objects/recording/normalize.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_objects/recording/pipeline.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_objects/recording/sanitize.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_test/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_test/client.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_test/errors.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_test/jsonpath.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/api_test/model.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/_shared/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/_shared/changelog.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/api_recorder/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/api_recorder/__main__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/api_recorder/addon.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/api_recorder/cli.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/api_recorder/playwright_tap.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/api_recorder/tests/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/api_recorder/tests/test_addon.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/__main__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/build.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/cli.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/agents/bdd-asset-pipeline.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/agents/sut-self-learning.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/agents/sut-source-to-design.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/hooks/sync_registry.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/hooks.json +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/agent-task-log.mdc +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/apps-handover.mdc +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/assets-knowledge.mdc +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/bdd-asset-layering.mdc +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/bdd-pipeline-gates.mdc +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/bdd-stage-layout.mdc +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/explore-safety.mdc +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/index-hygiene.mdc +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/packages-db.mdc +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/packages-fake.mdc +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/packages-logging.mdc +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/packages-page-test.mdc +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/analyze-mcp-network/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/derive-design-knowledge/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/derive-feature-sets/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/dump-ddl/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/explore-sut/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/feature-authoring/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/feature-review-lint/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/freeze-api-objects/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/maintain-behave-steps/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/maintain-index/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/maintain-page-objects/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/release-template/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/reuse-analysis/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/run-feature-playwright-mcp/SKILL.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/api-objects-syntax.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/bdd-run-gherkin-in-playwrightMCP.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/behave-gerkin-syntax.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/behave-step-definitions.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/design-knowledge-syntax.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/page-objects-syntax.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/README.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/commit-msg +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/pre-commit +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/pre-push +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/secret_scan.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/paths.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/source.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/targets.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/tests/test_cli.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dna/tests/test_targets.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/dump_ddl.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/evidence/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/evidence/__main__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/evidence/tests/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/evidence/tests/test_cli.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/index_ai/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/index_ai/__main__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/__main__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/manifest.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/INDEX.project.md +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/apps/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/behave.ini +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/config/env.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/data/sut-accounts.example.yaml +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/gitignore +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/packages/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/packages/action_words/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/packages/action_words/_internal/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/packages/action_words/_internal/params.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/packages/action_words/models.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/auth.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/recording/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/packages/page_objects/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/packages/page_objects/session.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/tests/features/api_environment.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/tests/features/api_steps/given.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/tests/features/api_steps/then.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/tests/features/api_steps/when.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/tests/features/ui_environment.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/tests/features/ui_steps/given.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/tests/features/ui_steps/then.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/tests/features/ui_steps/when.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/init_repo/stubs/tests/pytest/conftest.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/mock_server/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/mock_server/__main__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/mock_server/seed.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/mock_server/tool.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/page_recorder/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/page_recorder/__main__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/page_recorder/capture.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/page_recorder/cli.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/page_recorder/codegen.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/page_recorder/inject.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/page_recorder/session.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/page_recorder/tests/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/page_recorder/tests/test_capture.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/page_recorder/tests/test_cli.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/page_recorder/tests/test_freeze.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/recorder/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/recorder/__main__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/recorder/cli.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/recorder/tests/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/apps/recorder/tests/test_cli.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/artifacts.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/catalog/front_matter.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/catalog/tests/test_front_matter.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/config.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/db/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/db/client.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/db/connection.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/excel/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/excel/workbook.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/fake/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/fake/__main__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/fake/catalog.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/fake/china.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/fake/cli.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/fake/core.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/fake/medical.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/fake/wrappers.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/logging/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/logging/context.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/logging/core.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/logging/helpers.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/logging/hooks.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/logging/scenario_file.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/__main__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/base.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/driver.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/errors.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/harvest.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/health.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/locator.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/model.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/registry.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/session.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/steps.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/page_test/testing.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/project.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/tools/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/tools/manifest.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/tools/tests/test_manifest.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/workspace/__init__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/workspace/__main__.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/workspace/cli.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/workspace/index_render.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit/workspace/tests/test_index_render.py +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit.egg-info/dependency_links.txt +0 -0
- {tuner_testkit-5.0.0 → tuner_testkit-5.2.0}/tuner_testkit.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tuner-testkit
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.2.0
|
|
4
4
|
Summary: Shared test runtime, recorders, and DNA overlay for SUT test repos
|
|
5
5
|
Author: tuner-testkit contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,6 +26,9 @@ Provides-Extra: mock
|
|
|
26
26
|
Requires-Dist: fastapi>=0.115.0; extra == "mock"
|
|
27
27
|
Requires-Dist: uvicorn[standard]>=0.32.0; extra == "mock"
|
|
28
28
|
Requires-Dist: httpx>=0.28.0; extra == "mock"
|
|
29
|
+
Provides-Extra: workbench
|
|
30
|
+
Requires-Dist: tuner-testkit[mock]; extra == "workbench"
|
|
31
|
+
Requires-Dist: jinja2>=3.1.0; extra == "workbench"
|
|
29
32
|
Provides-Extra: recorder
|
|
30
33
|
Requires-Dist: playwright>=1.54.0; extra == "recorder"
|
|
31
34
|
Requires-Dist: mitmproxy>=11.1.3; extra == "recorder"
|
|
@@ -38,7 +41,7 @@ Requires-Dist: behave>=1.2.6; extra == "bdd"
|
|
|
38
41
|
Requires-Dist: playwright>=1.54.0; extra == "bdd"
|
|
39
42
|
Requires-Dist: behave-html-pretty-formatter>=1.16.1; extra == "bdd"
|
|
40
43
|
Provides-Extra: all
|
|
41
|
-
Requires-Dist: tuner-testkit[api,bdd,db,excel,fake,mock,phone-ui,recorder,test,web-ui]; extra == "all"
|
|
44
|
+
Requires-Dist: tuner-testkit[api,bdd,db,excel,fake,mock,phone-ui,recorder,test,web-ui,workbench]; extra == "all"
|
|
42
45
|
Provides-Extra: dev
|
|
43
46
|
Requires-Dist: tuner-testkit[all]; extra == "dev"
|
|
44
47
|
Dynamic: license-file
|
|
@@ -218,4 +221,4 @@ uv sync --extra all
|
|
|
218
221
|
(被测系统 = 平台本身,uv workspace 成员,共用 `.venv`):路线图在 `dogfood/assets/domain-notes/platform/roadmap.md`,
|
|
219
222
|
验收活文档在 `dogfood/tests/features/`。见 [`dogfood/README.md`](dogfood/README.md)。
|
|
220
223
|
|
|
221
|
-
5.0.0
|
|
224
|
+
5.2.0 发行说明(work task / 测试设计 / 证据附件)见 [`docs/changelog/TEMPLATE-5.2.0.md`](docs/changelog/TEMPLATE-5.2.0.md);5.1.0 发行说明(工作台 / meta stamp / `--json`)见 [`docs/changelog/TEMPLATE-5.1.0.md`](docs/changelog/TEMPLATE-5.1.0.md);5.0.0(Plane Job 协议退场、`tuner-workspace`)见 [`TEMPLATE-5.0.0.md`](docs/changelog/TEMPLATE-5.0.0.md);4.3.0 见 [`TEMPLATE-4.3.0.md`](docs/changelog/TEMPLATE-4.3.0.md);3.x → 4.x 迁移见 [`TEMPLATE-4.0.0.md`](docs/changelog/TEMPLATE-4.0.0.md)。平台能力地图见 [`INDEX.md`](INDEX.md)。
|
|
@@ -173,4 +173,4 @@ uv sync --extra all
|
|
|
173
173
|
(被测系统 = 平台本身,uv workspace 成员,共用 `.venv`):路线图在 `dogfood/assets/domain-notes/platform/roadmap.md`,
|
|
174
174
|
验收活文档在 `dogfood/tests/features/`。见 [`dogfood/README.md`](dogfood/README.md)。
|
|
175
175
|
|
|
176
|
-
5.0.0
|
|
176
|
+
5.2.0 发行说明(work task / 测试设计 / 证据附件)见 [`docs/changelog/TEMPLATE-5.2.0.md`](docs/changelog/TEMPLATE-5.2.0.md);5.1.0 发行说明(工作台 / meta stamp / `--json`)见 [`docs/changelog/TEMPLATE-5.1.0.md`](docs/changelog/TEMPLATE-5.1.0.md);5.0.0(Plane Job 协议退场、`tuner-workspace`)见 [`TEMPLATE-5.0.0.md`](docs/changelog/TEMPLATE-5.0.0.md);4.3.0 见 [`TEMPLATE-4.3.0.md`](docs/changelog/TEMPLATE-4.3.0.md);3.x → 4.x 迁移见 [`TEMPLATE-4.0.0.md`](docs/changelog/TEMPLATE-4.0.0.md)。平台能力地图见 [`INDEX.md`](INDEX.md)。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tuner-testkit"
|
|
3
|
-
version = "5.
|
|
3
|
+
version = "5.2.0"
|
|
4
4
|
description = "Shared test runtime, recorders, and DNA overlay for SUT test repos"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -37,6 +37,10 @@ mock = [
|
|
|
37
37
|
"uvicorn[standard]>=0.32.0",
|
|
38
38
|
"httpx>=0.28.0",
|
|
39
39
|
]
|
|
40
|
+
workbench = [
|
|
41
|
+
"tuner-testkit[mock]",
|
|
42
|
+
"jinja2>=3.1.0",
|
|
43
|
+
]
|
|
40
44
|
recorder = [
|
|
41
45
|
"playwright>=1.54.0",
|
|
42
46
|
"mitmproxy>=11.1.3",
|
|
@@ -53,7 +57,7 @@ bdd = [
|
|
|
53
57
|
]
|
|
54
58
|
# Union of capability extras (excludes `dev` to avoid a cycle).
|
|
55
59
|
all = [
|
|
56
|
-
"tuner-testkit[db,api,web-ui,phone-ui,excel,fake,mock,recorder,test,bdd]",
|
|
60
|
+
"tuner-testkit[db,api,web-ui,phone-ui,excel,fake,mock,recorder,test,bdd,workbench]",
|
|
57
61
|
]
|
|
58
62
|
dev = [
|
|
59
63
|
"tuner-testkit[all]",
|
|
@@ -74,6 +78,8 @@ tuner-fake = "tuner_testkit.fake.cli:main"
|
|
|
74
78
|
tuner-page-test = "tuner_testkit.page_test.__main__:main"
|
|
75
79
|
tuner-action-words = "tuner_testkit.action_words.__main__:main"
|
|
76
80
|
tuner-evidence = "tuner_testkit.apps.evidence.cli:main"
|
|
81
|
+
tuner-task = "tuner_testkit.apps.task.cli:main"
|
|
82
|
+
tuner-workbench = "tuner_testkit.workbench.cli:main"
|
|
77
83
|
|
|
78
84
|
[build-system]
|
|
79
85
|
requires = ["setuptools>=77", "wheel"]
|
|
@@ -85,6 +91,7 @@ include = ["tuner_testkit*"]
|
|
|
85
91
|
[tool.setuptools.package-data]
|
|
86
92
|
"tuner_testkit.apps.dna" = ["dna_payload/**/*"]
|
|
87
93
|
"tuner_testkit.apps.init_repo" = ["stubs/**/*"]
|
|
94
|
+
"tuner_testkit.workbench" = ["templates/**/*", "static/**/*"]
|
|
88
95
|
|
|
89
96
|
[tool.setuptools.cmdclass]
|
|
90
97
|
build_py = "tuner_testkit.apps.dna.build.BuildPyWithDna"
|
|
@@ -79,6 +79,8 @@ class ActionWord(ABC):
|
|
|
79
79
|
datasource: ClassVar[str] = DEFAULT_ALIAS
|
|
80
80
|
#: 可直接运行的入参样例(必须能通过 Params 校验)
|
|
81
81
|
example_params: ClassVar[dict[str, Any]] = {}
|
|
82
|
+
#: 工作台 / catalog 目录可见性。``local`` 不进工作台列表。
|
|
83
|
+
visibility: ClassVar[str] = "workbench"
|
|
82
84
|
|
|
83
85
|
class Params(BaseModel):
|
|
84
86
|
"""入参契约;子类内嵌覆盖。未知键一律拒绝,避免拼写错误静默生效。"""
|
|
@@ -127,5 +129,6 @@ class ActionWord(ABC):
|
|
|
127
129
|
"datasource": cls.datasource,
|
|
128
130
|
"doc": (cls.__doc__ or "").strip(),
|
|
129
131
|
"params_schema": cls.params_schema(),
|
|
130
|
-
"example_params": cls.example_params,
|
|
132
|
+
"example_params": dict(cls.example_params or {}),
|
|
133
|
+
"visibility": getattr(cls, "visibility", "workbench") or "workbench",
|
|
131
134
|
}
|
|
@@ -36,6 +36,9 @@ def register(cls: type[ActionWord]) -> type[ActionWord]:
|
|
|
36
36
|
raise ValueError(f"{word_id}: 必须有业务 docstring")
|
|
37
37
|
if not word_id.startswith(f"{cls.category}."):
|
|
38
38
|
raise ValueError(f"{word_id}: word_id 须以类别前缀开头,如 '{cls.category}.xxx'")
|
|
39
|
+
visibility = getattr(cls, "visibility", "workbench") or "workbench"
|
|
40
|
+
if visibility not in {"workbench", "local"}:
|
|
41
|
+
raise ValueError(f"{word_id}: visibility 须是 'workbench' 或 'local'")
|
|
39
42
|
existing = _REGISTRY.get(word_id)
|
|
40
43
|
if existing is not None and existing is not cls:
|
|
41
44
|
raise ValueError(f"word_id 重复注册: {word_id} ({existing.__name__} vs {cls.__name__})")
|
|
@@ -64,8 +67,22 @@ def iter_ids() -> Iterable[str]:
|
|
|
64
67
|
_discovered = False
|
|
65
68
|
|
|
66
69
|
|
|
70
|
+
def _import_word_package(pkg: Any) -> None:
|
|
71
|
+
"""递归导入类别子包(含 ``db_seed/audit`` 这类业务子目录)。跳过 ``_`` 前缀。"""
|
|
72
|
+
paths = getattr(pkg, "__path__", None)
|
|
73
|
+
if not paths:
|
|
74
|
+
return
|
|
75
|
+
for mod_info in pkgutil.iter_modules(paths, prefix=f"{pkg.__name__}."):
|
|
76
|
+
short = mod_info.name.rsplit(".", 1)[-1]
|
|
77
|
+
if short.startswith("_"):
|
|
78
|
+
continue
|
|
79
|
+
module = importlib.import_module(mod_info.name)
|
|
80
|
+
if mod_info.ispkg:
|
|
81
|
+
_import_word_package(module)
|
|
82
|
+
|
|
83
|
+
|
|
67
84
|
def discover() -> None:
|
|
68
|
-
"""
|
|
85
|
+
"""导入全部类别子包下的模块(含子目录),触发 ``@register`` 副作用。幂等。"""
|
|
69
86
|
global _discovered
|
|
70
87
|
if _discovered:
|
|
71
88
|
return
|
|
@@ -80,8 +97,7 @@ def discover() -> None:
|
|
|
80
97
|
pkg = importlib.import_module(f"{root_pkg.__name__}.{sub}")
|
|
81
98
|
except ModuleNotFoundError:
|
|
82
99
|
continue # 预留类别(如 ui_action)尚未建目录
|
|
83
|
-
|
|
84
|
-
importlib.import_module(f"{pkg.__name__}.{mod_info.name}")
|
|
100
|
+
_import_word_package(pkg)
|
|
85
101
|
|
|
86
102
|
|
|
87
103
|
def export_catalog() -> list[dict[str, Any]]:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
description: SUT apps/ and kit tuner_testkit.apps tools must be standalone-runnable and reuse tuner_testkit plus this repo's packages business assets; no reinventing wheels, no secrets, not imported by tests
|
|
3
3
|
globs: apps/**,tuner_testkit/apps/**
|
|
4
4
|
alwaysApply: false
|
|
5
|
-
version: 2.0.
|
|
5
|
+
version: 2.0.1
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# apps — 创建期约束
|
|
@@ -43,6 +43,7 @@ version: 2.0.0
|
|
|
43
43
|
不写 `tool.py`,或写了但 `visibility="local"`。
|
|
44
44
|
- 发现器只 import `apps/*/tool.py` 与 kit 的 `tuner_testkit/apps/*/tool.py`;`cli.py` 可以较重,
|
|
45
45
|
但 `tool.py` 及其 import 的模块禁止顶层 import DB 驱动 / Playwright / mitmproxy。
|
|
46
|
+
没有 `apps/<name>/tool.py` = 工作台当它不存在。
|
|
46
47
|
- 需要机器可读输出时用 `--json` envelope(`status / outputs[] / artifacts[] / log_path`),见规范 §7。
|
|
47
48
|
|
|
48
49
|
## 相关
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Commits must follow Conventional Commits with a layer-aligned scope; the declared scope must cover the layers actually changed. Single source of truth is docs/spec/commit-convention.md.
|
|
3
3
|
alwaysApply: true
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# 提交规范(Conventional Commits + 六层 scope)
|
|
@@ -12,8 +12,8 @@ version: 1.1.0
|
|
|
12
12
|
- `type` ∈ `feat|fix|refactor|docs|test|perf|chore|build|ci|style|revert`。
|
|
13
13
|
- `scope` 用**对齐六层/资产类别**的值:`assets / apps / packages / api_objects /
|
|
14
14
|
page_objects / action_words / tests / docs / rules / skills / agents / hooks /
|
|
15
|
-
init_repo / index / dogfood`(多层用逗号分隔,如 `feat(apps,packages): ...`;
|
|
16
|
-
`dogfood/**` 一律用 `dogfood`)。
|
|
15
|
+
init_repo / index / dogfood / work`(多层用逗号分隔,如 `feat(apps,packages): ...`;
|
|
16
|
+
`dogfood/**` 一律用 `dogfood`;`work/tasks` 用 `work`)。
|
|
17
17
|
- **scope 必须覆盖本次真实改动涉及的层**(`packages` 是三个子资产层的上位 scope)。
|
|
18
18
|
|
|
19
19
|
一眼可读优先:让人从提交信息就看出"更新了 assets、新增了 apps、录制了新的 api_objects"等。
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Work tasks live in work/tasks. When a human must choose a missing evidence channel, write an inbox question and block the task instead of inventing the channel.
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 工作任务与人类提问
|
|
8
|
+
|
|
9
|
+
细则见 `docs/spec/work-task.md`、`docs/spec/test-design-syntax.md`。
|
|
10
|
+
|
|
11
|
+
## Must
|
|
12
|
+
|
|
13
|
+
- 人发布的任务用 `tuner-task create` 写入 `work/tasks/TASK-*.md`,不要只留在聊天里。
|
|
14
|
+
- 测试设计写入 `assets/testdesign/`,并用 `tuner-task validate` 检查八个章节。
|
|
15
|
+
- 端到端点击用 `type: test-execution`,`design` 指向已有测试设计;报告写入 `assets/testreport/`,证据用 `tuner-evidence persist` 或 `attach` 挂上 `task_id`、截图、脱敏日志、接口 JSON。
|
|
16
|
+
- 执行结束后把结果写入该测试设计的「执行反馈」,只引用证据路径。
|
|
17
|
+
- 仓库没有写明的证据通道(典型是后端日志:SSH 目录、日志接口、Rancher API)立刻 `tuner-task ask`。日志主题用 `sut-log-source`。
|
|
18
|
+
- 提问写入 `artifacts/inbox/questions/` 后停止这一支,把任务保持在 `blocked`,直到 `tuner-task answer`。
|
|
19
|
+
|
|
20
|
+
## Must not
|
|
21
|
+
|
|
22
|
+
- 在人回答前选定日志通道,或编写对应的 SSH / HTTP / Rancher 取数实现。
|
|
23
|
+
- 把密码、token、Cookie 写进任务、问题、`--note` 或 domain-notes。用 `account_id`、环境变量名或 `config/env_local.py` 指向。
|
|
24
|
+
- 用 `artifacts/inbox/` 的会话流水代替 `work/tasks`。会话流水仍然要写,见 `agent-task-log`。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: create-action-word
|
|
3
|
-
version: 1.1.
|
|
3
|
+
version: 1.1.4
|
|
4
4
|
description: Creates or updates action words under packages/action_words/ following action-words-syntax.md. Use when adding DB seed/assert, API request/assert, or UI action/assert business actions, or when migrating ad-hoc test logic (SQL scripts, step bodies) into reusable action words.
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -39,7 +39,7 @@ description: Creates or updates action words under packages/action_words/ follow
|
|
|
39
39
|
|
|
40
40
|
- 类与模块 docstring 描述业务/前置条件/副作用(非一行占位);
|
|
41
41
|
- `word_id` / `name`(中文业务名)/ `category` 必填,word_id 前缀与 category 一致;
|
|
42
|
-
- `Params`:pydantic v2,`extra="forbid"`,**每个字段**带类型 + `Field(description=中文)
|
|
42
|
+
- `Params`:pydantic v2,`extra="forbid"`,**每个字段**带类型 + `Field(description=中文)`(工作台表单 label);
|
|
43
43
|
- `Result` 继承 `ActionResult`,业务字段同样带 description;
|
|
44
44
|
- `example_params` 非空且能通过 `Params.model_validate`;
|
|
45
45
|
- `run(params)` 带完整类型标注;
|
|
@@ -48,6 +48,12 @@ description: Creates or updates action words under packages/action_words/ follow
|
|
|
48
48
|
- 资源一律经 `self.ctx`(DB 用 `self.db`,即
|
|
49
49
|
`ctx.get_db(cls.datasource)`;API 用 `ctx.api_token`),不自建连接;
|
|
50
50
|
- 源码 / example / 日志中不得出现真实 token、密码、Cookie。
|
|
51
|
+
- 工作台只扫 `packages/action_words/{db_seed,db_assert,api_request,api_assert,ui_action,ui_assert}/`
|
|
52
|
+
(含子目录 `*.py`)上的 `@register`;没有入口文件 = 工作台当它不存在。
|
|
53
|
+
**必须用 kit 的 register**:`from packages.action_words import register`,且
|
|
54
|
+
`__init__.py` re-export `tuner_testkit.action_words.register`(或本仓 register 双写 kit)。
|
|
55
|
+
本仓自建 registry、不接到 kit 的 `@register` **不会**进工作台。
|
|
56
|
+
默认 `visibility = "workbench"`,`local` 不进目录。模块顶层不得连库 / 读 `env_local`。
|
|
51
57
|
|
|
52
58
|
## Recommended structure (db_seed)
|
|
53
59
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: create-app
|
|
3
3
|
description: Scaffolds a new standalone SUT-private tool under apps/ that reuses tuner_testkit plus this repo's packages business assets, following apps-authoring-syntax.md. Use when the engineer needs an on-demand test tool (data generator, checker, exporter, capture/enrichment). Do not scaffold into tuner_testkit/apps/.
|
|
4
|
-
version: 1.1
|
|
4
|
+
version: 1.2.1
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Create App — 按需开发一个独立工具
|
|
@@ -28,9 +28,10 @@ version: 1.1.0
|
|
|
28
28
|
apps/<name>/
|
|
29
29
|
├── __init__.py
|
|
30
30
|
├── __main__.py # from .cli import main; raise SystemExit(main())
|
|
31
|
-
├── cli.py # argparse
|
|
31
|
+
├── cli.py # argparse:build_parser() + main();每个参数有 help;带 --json
|
|
32
|
+
├── tool.py # import-safe:用 @tool 装饰 build_parser(工作台 / catalog)
|
|
32
33
|
├── <core>.py # 纯逻辑,尽量可离线单测
|
|
33
|
-
├── README.md # 交接文档
|
|
34
|
+
├── README.md # 交接文档 + metadata-conventions front-matter
|
|
34
35
|
└── tests/ # 离线单测
|
|
35
36
|
```
|
|
36
37
|
|
|
@@ -43,7 +44,11 @@ apps/<name>/
|
|
|
43
44
|
+ 环境变量取;**禁止** `print`、直连驱动、硬编码 DSN、SQL 拼接、自建日志文件。
|
|
44
45
|
- 覆盖式生成 `assets/**` / `packages/api_objects/**` / `packages/page_objects/**` 的工具,运行结束必须
|
|
45
46
|
`tuner_testkit.apps._shared.changelog.append_entry(...)` 追加对应区 `CHANGELOG.md`。
|
|
46
|
-
- 不得被 `tests/` import;不得写入 token/cookie/密码等敏感值;破坏性操作默认 dry-run
|
|
47
|
+
- 不得被 `tests/` import;不得写入 token/cookie/密码等敏感值;破坏性操作默认 dry-run/只读,`@tool(..., destructive=True)`。
|
|
48
|
+
- `tool.py` 及其 import **禁止**顶层 import DB / Playwright / mitmproxy。
|
|
49
|
+
没有 `apps/<name>/tool.py` + `@tool` = 工作台当它不存在。
|
|
50
|
+
- `--json` 时 stdout 打印 envelope:`status / outputs[] / artifacts[] / log_path`(见 apps-authoring-syntax §7)。
|
|
51
|
+
- README 写完后立刻 `uv run tuner-workspace meta stamp apps/<name>/README.md --kind app`(不要手填邮箱)。
|
|
47
52
|
|
|
48
53
|
## 交接文档(完成期必产出)
|
|
49
54
|
|
|
@@ -53,8 +58,9 @@ apps/<name>/
|
|
|
53
58
|
## Verify
|
|
54
59
|
|
|
55
60
|
1. `python -m apps.<name> --help` 正常输出用法。
|
|
56
|
-
2.
|
|
57
|
-
3.
|
|
61
|
+
2. `tuner-workspace catalog` 的 `tools[]` 出现该 `tool_id`,且 `params_schema.properties` 每项有 `description`。
|
|
62
|
+
3. 离线单测 `uv run pytest apps/<name>/tests -q`(若有)。
|
|
63
|
+
4. 有环境时跑一条示例命令,确认产出位置与 `CHANGELOG` 追加正确。
|
|
58
64
|
|
|
59
65
|
## Output checklist
|
|
60
66
|
|
tuner_testkit-5.2.0/tuner_testkit/apps/dna/dna_payload/.cursor/skills/derive-test-design/SKILL.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: derive-test-design
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: Write assets/testdesign/<sut>/<slug>.md from a work task plus usecases, domain-notes, explore, or design notes. Use when the task type is test-design or the user asks for a test design. Do not invent click paths that are not in evidence or a cited source.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Derive test design
|
|
8
|
+
|
|
9
|
+
## Scope
|
|
10
|
+
|
|
11
|
+
- **Write**: `assets/testdesign/<sut>/<slug>.md`,并让任务的 `outputs` 指向它。
|
|
12
|
+
- **Read**: `work/tasks/<id>.md`、`assets/usecases`、`assets/domain-notes`、`assets/explore`、`assets/design`、`INDEX.md`(及 `INDEX.project.md`)。
|
|
13
|
+
- **Must follow**: `docs/spec/test-design-syntax.md`、`docs/spec/work-task.md`。
|
|
14
|
+
|
|
15
|
+
## Steps
|
|
16
|
+
|
|
17
|
+
1. 若还没有任务:`tuner-task create --type test-design --title … --input <已有知识路径>`。
|
|
18
|
+
2. 只根据 inputs 里点名的知识写范围、不测、风险、策略、点击路径、用例大纲。没有页面流或证据支撑的点击行不要编。
|
|
19
|
+
3. 「执行反馈」写「无」。
|
|
20
|
+
4. front-matter:`kind: testdesign`,`task_id` 指向任务,`source` 或 `evidence` 至少一项。
|
|
21
|
+
5. 校验并署名:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
uv run tuner-task validate assets/testdesign/<sut>/<slug>.md
|
|
25
|
+
uv run tuner-workspace meta stamp assets/testdesign/<sut>/<slug>.md --kind testdesign
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
6. 把该路径挂到任务上:`uv run tuner-task bind <TASK> --output assets/testdesign/<sut>/<slug>.md`。
|
|
29
|
+
|
|
30
|
+
## Template
|
|
31
|
+
|
|
32
|
+
```markdown
|
|
33
|
+
---
|
|
34
|
+
kind: testdesign
|
|
35
|
+
id: <slug>
|
|
36
|
+
title: <一句话>
|
|
37
|
+
sut: <sut>
|
|
38
|
+
task_id: TASK-YYYYMMDD-nnn
|
|
39
|
+
source: <assets/...>
|
|
40
|
+
version: 1.0.0
|
|
41
|
+
confidence: high
|
|
42
|
+
evidence: []
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
# <title>
|
|
46
|
+
|
|
47
|
+
## 范围
|
|
48
|
+
|
|
49
|
+
## 不测
|
|
50
|
+
|
|
51
|
+
## 风险
|
|
52
|
+
|
|
53
|
+
## 策略
|
|
54
|
+
|
|
55
|
+
## 点击路径
|
|
56
|
+
|
|
57
|
+
| id | 页面流 | 操作 | 期望 |
|
|
58
|
+
| --- | --- | --- | --- |
|
|
59
|
+
|
|
60
|
+
## 用例大纲
|
|
61
|
+
|
|
62
|
+
## 执行反馈
|
|
63
|
+
|
|
64
|
+
| run_id | task_id | 结果 | 要回写的结论 |
|
|
65
|
+
| --- | --- | --- | --- |
|
|
66
|
+
|
|
67
|
+
## 证据与来源
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Hard rules
|
|
71
|
+
|
|
72
|
+
- 缺日志来源时 `tuner-task ask --topic sut-log-source`,不要写死 SSH、日志接口或 Rancher。
|
|
73
|
+
- 不把响应体、截图、密钥抄进设计。
|
tuner_testkit-5.2.0/tuner_testkit/apps/dna/dna_payload/.cursor/skills/generate-test-report/SKILL.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: generate-test-report
|
|
3
|
+
description: Turn a regression run under artifacts/reports/<run_id>/ (plus inbox and optional design notes) into a curated Markdown test report at assets/testreport/<sut>/<yyyy-mm>/<slug>.md with metadata-conventions front-matter. Use when the user asks to 生成测试报告 / write a test report / 汇总回归结果.
|
|
4
|
+
version: 1.1.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Generate Test Report
|
|
8
|
+
|
|
9
|
+
## Scope
|
|
10
|
+
|
|
11
|
+
- **Write**: `assets/testreport/<sut>/<yyyy-mm>/<slug>.md` only(策展知识,不是原始报告)。
|
|
12
|
+
- **Read**: `artifacts/reports/<run_id>/manifest.json` + `summary.json`;可选 `artifacts/inbox/`、`assets/design/**`、`INDEX.project.md`。
|
|
13
|
+
- **Must follow**: `docs/spec/metadata-conventions.md`、`docs/spec/artifacts-layout.md`、`docs/spec/assets-knowledge-syntax.md`。
|
|
14
|
+
|
|
15
|
+
## Steps
|
|
16
|
+
|
|
17
|
+
1. 选定 `run_id`(用户给出,或取 `artifacts/reports/` 最新一份 `manifest.json`)。
|
|
18
|
+
2. 读 manifest / summary,**不要编造**未出现的失败数或缺陷。
|
|
19
|
+
3. 定 `<sut>`(`INDEX.project.md` 或用户指定,默认 `platform`)与 `<slug>`(短横线,如 `qa-daily-offline`)。
|
|
20
|
+
4. 写文件,front-matter:
|
|
21
|
+
|
|
22
|
+
```markdown
|
|
23
|
+
---
|
|
24
|
+
kind: testreport
|
|
25
|
+
id: <slug>
|
|
26
|
+
title: <一句话>
|
|
27
|
+
author: ""
|
|
28
|
+
created:
|
|
29
|
+
updated:
|
|
30
|
+
version: 1.0.0
|
|
31
|
+
sut: <sut>
|
|
32
|
+
env: <命名环境或 unknown>
|
|
33
|
+
run_id: <run_id>
|
|
34
|
+
period: <YYYY-MM>
|
|
35
|
+
result: {total: 0, passed: 0, failed: 0}
|
|
36
|
+
evidence: []
|
|
37
|
+
features: []
|
|
38
|
+
task_id: # 有 work task 时填写
|
|
39
|
+
design: # test-execution 指向 assets/testdesign/...
|
|
40
|
+
confidence: high
|
|
41
|
+
source: artifacts/reports/<run_id>
|
|
42
|
+
---
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
5. 正文固定六个二级标题,缺信息写「无」而不是省略:
|
|
46
|
+
|
|
47
|
+
```markdown
|
|
48
|
+
## 范围
|
|
49
|
+
## 环境
|
|
50
|
+
## 结果
|
|
51
|
+
## 缺陷
|
|
52
|
+
## 风险
|
|
53
|
+
## 证据链接
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
6. 立刻运行(不要手填邮箱):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
uv run tuner-workspace meta stamp assets/testreport/<sut>/<yyyy-mm>/<slug>.md --kind testreport
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
7. 如有 `INDEX.project.md` 的 testreport 自动区,跑 `tuner-workspace index render`;否则用 `maintain-index` 在人工区加一行。
|
|
63
|
+
|
|
64
|
+
## Hard rules
|
|
65
|
+
|
|
66
|
+
- 不得把 token / cookie / 密码写进报告。
|
|
67
|
+
- 不得把 `artifacts/evidence/` 原文贴进仓库;只写相对路径链接。
|
|
68
|
+
- `assets/testreport` 是策展知识;原始 html/junit 留在 `artifacts/reports/`。
|
|
69
|
+
|
|
70
|
+
## Verify
|
|
71
|
+
|
|
72
|
+
1. front-matter 含 `kind: testreport`、`run_id`、`result`。
|
|
73
|
+
2. `tuner-workspace meta stamp` 后 `author` 非空(本机有 git email)。
|
|
74
|
+
3. 六个章节都在。
|
tuner_testkit-5.2.0/tuner_testkit/apps/dna/dna_payload/.cursor/skills/run-test-execution/SKILL.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: run-test-execution
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: Run the click paths in a test design, attach screenshots and sanitized API or log evidence, and write a curated test report that links back to the design. Use when the task type is test-execution or the user asks for an end-to-end click report.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Run test execution
|
|
8
|
+
|
|
9
|
+
## Scope
|
|
10
|
+
|
|
11
|
+
- **Read**: 任务的 `design`(`assets/testdesign/**`)及其「点击路径」。
|
|
12
|
+
- **Write**: `assets/testreport/<sut>/<yyyy-mm>/<slug>.md`,回写设计的「执行反馈」,必要时 `tuner-evidence attach`。
|
|
13
|
+
- **Must follow**: `docs/spec/work-task.md`、`docs/spec/test-design-syntax.md`、`generate-test-report` skill。
|
|
14
|
+
|
|
15
|
+
## Steps
|
|
16
|
+
|
|
17
|
+
1. `tuner-task create --type test-execution --title … --design assets/testdesign/<sut>/<slug>.md`,或继续已有任务。然后 `tuner-task start <id>`。
|
|
18
|
+
2. 按「点击路径」每一行执行 `python -m tuner_testkit.page_test run <page_id> --flow <flow>`,或对应的 behave UI 场景。失败步使用 page_test 已有的整页截图路径。
|
|
19
|
+
3. 把当次网络、截图、接口 JSON、日志片段放进同一次 evidence run,并带上任务号:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv run tuner-evidence persist --run-id <run_id> --scenario explore:<slug> --network captures.jsonl --task-id <TASK> --screenshot <png> --api <response.json>
|
|
23
|
+
uv run tuner-evidence attach --run-id <run_id> --task-id <TASK> --log <excerpt.log> --screenshot <png>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
4. 设计要求日志证据,但仓库没有 log provider(domain-notes 或 `apps/` 里没有)时,立刻:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
uv run tuner-task ask --task <TASK> --topic sut-log-source --prompt "仓库没有写明后端日志从哪取"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
然后停止依赖日志的回写。不要选择 SSH、日志接口或 Rancher,也不要开始写 fetcher。人回答后再按 `create-app` 做对应工具。人选择 `skip` 时,报告里日志写「无」。
|
|
33
|
+
|
|
34
|
+
5. 用 `generate-test-report` 写报告。front-matter 额外加上 `task_id` 与 `design`。结果表每一行带证据相对路径(截图、`api/*.json`、`logs/*.log`)。
|
|
35
|
+
6. 在测试设计「执行反馈」追加一行:`run_id`、`task_id`、通过或失败、要回写的结论。不改「范围」,除非人确认。
|
|
36
|
+
7. `uv run tuner-task bind <id> --output assets/testreport/<sut>/<yyyy-mm>/<slug>.md --evidence artifacts/evidence/<run_id>/`,然后 `tuner-task finish <id>`。仍有未答问题时 CLI 会失败。
|
|
37
|
+
|
|
38
|
+
## Hard rules
|
|
39
|
+
|
|
40
|
+
- 报告和设计只链到 `artifacts/evidence/<run_id>/`,不入库截图或响应原文。
|
|
41
|
+
- 不编造未出现在 summary 或证据里的失败数。
|
|
42
|
+
- 点出的新副作用策展到 `assets/design/`,并在设计的风险里加一行指向同一 `run_id`。
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- version: 1.
|
|
1
|
+
<!-- version: 1.6.0 -->
|
|
2
2
|
# AGENTS — 平台总入口(轻量 DM)
|
|
3
3
|
|
|
4
4
|
> 本文件是"repo as a platform"的**稳定世界观**:只写不常变的分层结构与角色。
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
| 层 | 目录 | 职责 | 谁运行 |
|
|
15
15
|
| --- | --- | --- | --- |
|
|
16
|
-
| 知识层 | `assets/` | 给人和 LLM 阅读、生成测试代码的基础知识(ddl / sql / usecases / domain-notes / explore / design / testreport)。见 `docs/spec/assets-knowledge-syntax.md`。 | 只读引用 |
|
|
16
|
+
| 知识层 | `assets/` | 给人和 LLM 阅读、生成测试代码的基础知识(ddl / sql / usecases / domain-notes / explore / design / testdesign / testreport)。见 `docs/spec/assets-knowledge-syntax.md`。 | 只读引用 |
|
|
17
17
|
| 运行库 | `tuner_testkit/`(PyPI:`tuner-testkit`) | 公共运行时与 CLI(db / logging / api_test / page_test / fake / recorders / dna)。SUT 用 `uv` 锁版本。 | `import tuner_testkit`;`tuner-recorder` 等 scripts |
|
|
18
18
|
| 组件层 | `packages/` | **本仓业务资产**(api_objects / page_objects / action_words),不是 kit 运行库。 | 被 import |
|
|
19
19
|
| 工具层 | `apps/` | **本仓私有**工具。公共工具在 `tuner_testkit.apps`。见 `docs/spec/apps-authoring-syntax.md`。 | `python -m apps.<name>`(仅项目工具) |
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
| 测试层 | `tests/` | 自动化测试代码(behave `features/` + `pytest/`)。 | behave / pytest |
|
|
22
22
|
| 文档层 | `docs/` | 仓库使用说明与规范(`docs/spec/**`)。 | 只读 |
|
|
23
23
|
|
|
24
|
-
配套:`config/`(环境/数据源)、`.cursor/`(AI 组件,见下)、`artifacts/`·`logs/`(运行产出,规范 `docs/spec/artifacts-layout.md`:MCP evidence 落 `artifacts/evidence/<run_id>/`;agent 任务记录落 `artifacts/inbox/`;工具运行落 `artifacts/runs/<run_id>/`;回归报告落 `artifacts/reports/<run_id>/`,每个 run 目录带 `manifest.json`)。SUT 登录本机文件:`data/sut-accounts.local.yaml`(gitignore)。
|
|
24
|
+
配套:`config/`(环境/数据源)、`.cursor/`(AI 组件,见下)、`work/tasks/`(入库的任务上下文,规范 `docs/spec/work-task.md`)、`artifacts/`·`logs/`(运行产出,规范 `docs/spec/artifacts-layout.md`:MCP evidence 落 `artifacts/evidence/<run_id>/`;agent 任务记录落 `artifacts/inbox/`;阻塞式人类提问落 `artifacts/inbox/questions/`;工具运行落 `artifacts/runs/<run_id>/`;回归报告落 `artifacts/reports/<run_id>/`,每个 run 目录带 `manifest.json`)。SUT 登录本机文件:`data/sut-accounts.local.yaml`(gitignore)。
|
|
25
25
|
|
|
26
26
|
## 2. 三角色
|
|
27
27
|
|
|
@@ -50,6 +50,7 @@ flowchart TD
|
|
|
50
50
|
Q -->|"缺少知识(ddl/api/用例)"| Know["先跑 kit CLI 回填 assets\n再走生成"]
|
|
51
51
|
Q -->|"新建/更新项目仓"| Init["tuner-init / tuner-dna / release-template"]
|
|
52
52
|
Q -->|"读/策展/索引知识"| Idx["查 INDEX.md + maintain-index skill"]
|
|
53
|
+
Q -->|"发布任务 / 测试设计 / 端到端执行"| Task["work/tasks + tuner-task\ndocs/spec/work-task.md"]
|
|
53
54
|
```
|
|
54
55
|
|
|
55
56
|
- **学习被测系统** → `.cursor/agents/sut-self-learning.md`(编排 explore → freeze → design;规格 `docs/spec/sut-self-learning.md`;任务 log 见 `docs/spec/agent-task-log.md`)。
|
|
@@ -59,6 +60,7 @@ flowchart TD
|
|
|
59
60
|
- **补知识** → 用 `tuner-dump-ddl`、Playwright MCP 探索(落盘 `artifacts/evidence/`)、`tuner-recorder` / `tuner-api-recorder` / `tuner-page-recorder` 等回填,再进入生成。
|
|
60
61
|
- **仓库初始化/发布** → `tuner-init scaffold`(骨架 + 依赖 `tuner-testkit` + 一次 `tuner-dna sync`)+ `release-template` skill。下游升 kit:`uv add tuner-testkit==x.y.z` 然后 `tuner-dna sync`,再提交。
|
|
61
62
|
- **读/索引知识** → 先查 `INDEX.md`;若存在 `INDEX.project.md` 则一并查。索引维护用 `maintain-index` skill。
|
|
63
|
+
- **发布任务** → `tuner-task create` 写入 `work/tasks/`。测试设计走 `derive-test-design`;端到端点击报告走 `run-test-execution`。缺人才能决定的通道(如后端日志)用 `tuner-task ask`,不要猜。
|
|
62
64
|
|
|
63
65
|
## 5. 全程硬约束(跨分支)
|
|
64
66
|
|
|
@@ -45,6 +45,12 @@ packages/action_words/
|
|
|
45
45
|
(如 `create_invoice_relation` 与 `link_invoice_to_uninvoiced`)可同模块。
|
|
46
46
|
- 新增类别子包后无需注册:`registry.discover()` 会自动扫描
|
|
47
47
|
`_WORD_SUBPACKAGES` 中列出的子包。
|
|
48
|
+
- **工作台入口**:发现器只扫
|
|
49
|
+
`packages/action_words/{db_seed,db_assert,api_request,api_assert,ui_action,ui_assert}/`
|
|
50
|
+
下的模块(允许业务子目录,如 `db_seed/audit/*.py`)。
|
|
51
|
+
`_internal/`、`models.py`、类别目录之外的路径不会出现在工作台。没有入口文件 = 工作台当它不存在。
|
|
52
|
+
`@register` 必须落到 **kit** registry(`packages.action_words` re-export
|
|
53
|
+
`tuner_testkit.action_words.register`,或本仓装饰器双写 kit)。本仓自建表不算登记。
|
|
48
54
|
|
|
49
55
|
## 类模板(强制)
|
|
50
56
|
|
|
@@ -65,7 +71,8 @@ class CreateInOut(ActionWord):
|
|
|
65
71
|
tags = ("发票审计", "出入库") # 业务域标签,便于目录过滤
|
|
66
72
|
requires = frozenset({"db"}) # 依赖资源:"db" / "api"
|
|
67
73
|
datasource = "main" # 目标数据源别名(config/env.py DATABASES 键)
|
|
68
|
-
example_params = {...} # 必须能通过 Params
|
|
74
|
+
example_params = {...} # 必须能通过 Params 校验;特化表单预填
|
|
75
|
+
visibility = "workbench" # 可选;"local" 不进工作台目录
|
|
69
76
|
|
|
70
77
|
Params = InOutParams # pydantic BaseModel,见下
|
|
71
78
|
|
|
@@ -130,7 +137,8 @@ uv run python -m tuner_testkit.action_words catalog [-o out.json] # 全量目录
|
|
|
130
137
|
- `run` 输出 `Result` 的 JSON(含 cleanup 登记),退出码 0/1 对应成功/失败;
|
|
131
138
|
- 手工造数后需要清理时,按输出的 cleanup 逐表 `DELETE ... WHERE id IN (...)`。
|
|
132
139
|
- `catalog` 供本机调用 `export_catalog()`;`tuner-workspace catalog` 把**全部** `@register` 的词条(含 `params_schema`、
|
|
133
|
-
`destructive`
|
|
140
|
+
`destructive` 推断、`visibility`)写入 `artifacts/catalogs/workspace.json` 的 `action_words[]`。
|
|
141
|
+
工作台列表/搜索**不**读这份全量 JSON,只扫本节登记的入口(见下)。
|
|
134
142
|
|
|
135
143
|
## 与 BDD / pytest 的集成
|
|
136
144
|
|
|
@@ -144,12 +152,15 @@ uv run python -m tuner_testkit.action_words catalog [-o out.json] # 全量目录
|
|
|
144
152
|
|
|
145
153
|
## 与本地工作台(workbench)
|
|
146
154
|
|
|
147
|
-
- `@register`
|
|
155
|
+
- `@register` 即工作台登记,不需要第二套装饰器。类属性 `visibility` 默认 `"workbench"`;`"local"` 的词不进目录切片,仍可 CLI 运行。
|
|
156
|
+
- 扫描只认类别目录下的模块:`packages/action_words/<category>/*.py`。模块必须 **import-safe**:顶层不得连库、不得读 `env_local`、不得启动浏览器。
|
|
157
|
+
- `Params` 每字段 `Field(description=...)`、`example_params` 非空——特化表单依赖这两项。
|
|
148
158
|
- 运行:工作台经 `tuner-workspace run <word_id> --params JSON` 调用
|
|
149
159
|
`python -m tuner_testkit.action_words run <word_id> --params JSON`;只暴露 `word_id` 与 `--params`,
|
|
150
160
|
不暴露 `--username` / `--password` / `--params-file`(凭据来自本机 `config/env_local.py`)。
|
|
151
161
|
- `db_seed` / `api_request` / `ui_action` 三类按类别推断为 **destructive**:工作台要求勾选确认,未确认拒绝运行。
|
|
152
|
-
-
|
|
162
|
+
- `db_seed` 有特化页(`/words/db_seed/<word_id>`):预填 `example_params`、`dry_run` 缺省 True、结果强调 `cleanup[]`。
|
|
163
|
+
其它类别先走通用词页,kit 加类别时在 `tuner_testkit/workbench/kinds/` 加模块即可。
|
|
153
164
|
|
|
154
165
|
|
|
155
166
|
## 敏感信息
|
|
@@ -169,4 +180,5 @@ uv run python -m tuner_testkit.action_words catalog [-o out.json] # 全量目录
|
|
|
169
180
|
5. `uv run pytest packages/tests/test_action_word_template.py` 通过;
|
|
170
181
|
6. `python -m tuner_testkit.action_words run <word_id> --example` 冒烟(需要环境时);
|
|
171
182
|
7. 若供 behave 使用,在步骤层接线并跑 `behave --stage api --dry-run`。
|
|
172
|
-
8. `tuner-workspace catalog` 后确认词条出现在 `action_words[]
|
|
183
|
+
8. `tuner-workspace catalog` 后确认词条出现在 `action_words[]`;工作台热路径读目录切片,
|
|
184
|
+
没有类别目录下的入口文件 = 工作台当它不存在。
|
|
@@ -64,7 +64,17 @@ evidence:
|
|
|
64
64
|
|
|
65
65
|
对照两轮 dogfood 时,另写 `## Loop delta`:相对上一份 inbox,少了哪些手工步骤、多了哪些平台能力。
|
|
66
66
|
|
|
67
|
-
## 4.
|
|
67
|
+
## 4. 人类提问(阻塞)
|
|
68
|
+
|
|
69
|
+
必须由人选择的缺口(仓库没写明的后端日志来源等)不写进会话流水,立刻另存:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
artifacts/inbox/questions/Q-<YYYYMMDD>-<nnn>.md
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
字段与命令见 `docs/spec/work-task.md`。提问后把对应 `work/tasks` 标为 `blocked`。回答写入任务的 `## Decisions`;可复用的通道说明策展到 `assets/domain-notes/`。
|
|
76
|
+
|
|
77
|
+
## 5. 密钥
|
|
68
78
|
|
|
69
79
|
- 可用 `account_id` 指向 `data/sut-accounts.local.yaml` 的条目。
|
|
70
80
|
- 禁止密码、token、Cookie、Authorization 原文。
|