tuner-testkit 4.4.0__tar.gz → 5.0.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-4.4.0/tuner_testkit.egg-info → tuner_testkit-5.0.0}/PKG-INFO +6 -2
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/README.md +5 -1
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/pyproject.toml +2 -2
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_mock/store.py +2 -3
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/cli.py +48 -43
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/apps-authoring.mdc +15 -13
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/bdd-asset-layering.mdc +3 -3
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/index-hygiene.mdc +4 -2
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/maintain-index/SKILL.md +14 -1
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/maintain-page-objects/SKILL.md +2 -2
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/AGENTS.md +5 -1
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/MANIFEST.txt +1 -1
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/action-words-syntax.md +13 -13
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/api-objects-syntax.md +3 -3
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/apps-authoring-syntax.md +9 -7
- tuner_testkit-5.0.0/tuner_testkit/apps/dna/dna_payload/docs/spec/artifacts-layout.md +94 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/page-objects-syntax.md +2 -1
- tuner_testkit-5.0.0/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/README.md +32 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/pre-commit +19 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/secret_scan.py +145 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/dna/targets.py +182 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/dna/tests/test_targets.py +62 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/evidence/persist.py +25 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/index_ai/registry.py +30 -10
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/scaffold.py +38 -2
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/stubs/INDEX.project.md +82 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/stubs/behave.ini +23 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/stubs/gitignore +36 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/registry.py +3 -4
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/stubs/tests/features/api_environment.py +49 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/stubs/tests/features/api_steps/given.py +1 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/stubs/tests/features/api_steps/then.py +1 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/stubs/tests/features/api_steps/when.py +1 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/stubs/tests/features/ui_environment.py +70 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/stubs/tests/features/ui_steps/given.py +1 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/stubs/tests/features/ui_steps/then.py +1 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/stubs/tests/features/ui_steps/when.py +1 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/stubs/tests/pytest/conftest.py +53 -0
- tuner_testkit-5.0.0/tuner_testkit/apps/init_repo/tests/test_git_hooks.py +70 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/tests/test_scaffold.py +11 -0
- tuner_testkit-4.4.0/tuner_testkit/apps/mock_server/plane.py → tuner_testkit-5.0.0/tuner_testkit/apps/mock_server/tool.py +13 -20
- tuner_testkit-5.0.0/tuner_testkit/artifacts.py +274 -0
- tuner_testkit-5.0.0/tuner_testkit/catalog/__init__.py +20 -0
- tuner_testkit-5.0.0/tuner_testkit/catalog/build.py +109 -0
- tuner_testkit-5.0.0/tuner_testkit/catalog/front_matter.py +259 -0
- tuner_testkit-5.0.0/tuner_testkit/catalog/scan.py +499 -0
- tuner_testkit-5.0.0/tuner_testkit/catalog/tests/test_build.py +95 -0
- tuner_testkit-5.0.0/tuner_testkit/catalog/tests/test_front_matter.py +60 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/registry.py +2 -2
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/project.py +17 -1
- tuner_testkit-5.0.0/tuner_testkit/tools/__init__.py +44 -0
- tuner_testkit-5.0.0/tuner_testkit/tools/manifest.py +482 -0
- tuner_testkit-5.0.0/tuner_testkit/tools/tests/test_manifest.py +102 -0
- tuner_testkit-5.0.0/tuner_testkit/workspace/__init__.py +1 -0
- tuner_testkit-5.0.0/tuner_testkit/workspace/__main__.py +3 -0
- tuner_testkit-5.0.0/tuner_testkit/workspace/cli.py +145 -0
- tuner_testkit-5.0.0/tuner_testkit/workspace/index_render.py +175 -0
- tuner_testkit-5.0.0/tuner_testkit/workspace/tests/test_index_render.py +63 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0/tuner_testkit.egg-info}/PKG-INFO +6 -2
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit.egg-info/SOURCES.txt +34 -16
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit.egg-info/entry_points.txt +1 -1
- tuner_testkit-4.4.0/tuner_testkit/action_words/plane.py +0 -83
- tuner_testkit-4.4.0/tuner_testkit/apps/_shared/plane.py +0 -25
- tuner_testkit-4.4.0/tuner_testkit/apps/_shared/plane_app.py +0 -296
- tuner_testkit-4.4.0/tuner_testkit/apps/_shared/plane_asset.py +0 -147
- tuner_testkit-4.4.0/tuner_testkit/apps/_shared/tests/test_plane_asset.py +0 -124
- tuner_testkit-4.4.0/tuner_testkit/apps/_shared/tests/test_plane_collect.py +0 -45
- tuner_testkit-4.4.0/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/README.md +0 -28
- tuner_testkit-4.4.0/tuner_testkit/apps/index_platform/__init__.py +0 -9
- tuner_testkit-4.4.0/tuner_testkit/apps/index_platform/__main__.py +0 -29
- tuner_testkit-4.4.0/tuner_testkit/apps/index_platform/build.py +0 -63
- tuner_testkit-4.4.0/tuner_testkit/apps/index_platform/catalog.py +0 -228
- tuner_testkit-4.4.0/tuner_testkit/apps/index_platform/plane.py +0 -29
- tuner_testkit-4.4.0/tuner_testkit/apps/index_platform/tests/test_catalog.py +0 -29
- tuner_testkit-4.4.0/tuner_testkit/apps/init_repo/stubs/behave.ini +0 -18
- tuner_testkit-4.4.0/tuner_testkit/apps/init_repo/stubs/packages/api_objects/plane.py +0 -14
- tuner_testkit-4.4.0/tuner_testkit/apps/init_repo/stubs/packages/page_objects/plane.py +0 -14
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/LICENSE +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/setup.cfg +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/action_words/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/action_words/__main__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/action_words/_internal/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/action_words/_internal/api.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/action_words/_internal/db.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/action_words/_internal/generators.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/action_words/_internal/ids.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/action_words/_internal/wait.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/action_words/base.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/action_words/context.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/action_words/registry.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_mock/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_mock/app.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_mock/errors.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_mock/router.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_mock/spec.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_objects/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_objects/auth.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_objects/recording/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_objects/recording/capture.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_objects/recording/codegen.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_objects/recording/freeze.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_objects/recording/mocks.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_objects/recording/normalize.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_objects/recording/pipeline.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_objects/recording/sanitize.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_test/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_test/client.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_test/errors.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_test/jsonpath.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/api_test/model.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/_shared/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/_shared/changelog.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/api_recorder/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/api_recorder/__main__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/api_recorder/addon.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/api_recorder/cli.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/api_recorder/playwright_tap.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/api_recorder/tests/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/api_recorder/tests/test_addon.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/__main__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/build.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/agents/bdd-asset-pipeline.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/agents/sut-self-learning.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/agents/sut-source-to-design.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/hooks/sync_registry.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/hooks.json +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/agent-task-log.mdc +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/apps-handover.mdc +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/assets-knowledge.mdc +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/bdd-pipeline-gates.mdc +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/bdd-stage-layout.mdc +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/commit-convention.mdc +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/explore-safety.mdc +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/packages-db.mdc +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/packages-fake.mdc +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/packages-logging.mdc +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/packages-page-test.mdc +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/analyze-mcp-network/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/create-action-word/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/create-app/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/derive-design-knowledge/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/derive-feature-sets/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/dump-ddl/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/explore-sut/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/feature-authoring/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/feature-review-lint/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/freeze-api-objects/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/maintain-behave-steps/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/release-template/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/reuse-analysis/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/run-feature-playwright-mcp/SKILL.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/agent-task-log.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/assets-knowledge-syntax.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/bdd-run-gherkin-in-playwrightMCP.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/behave-gerkin-syntax.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/behave-step-definitions.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/commit-convention.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/design-knowledge-syntax.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/sut-self-learning.md +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/commit-msg +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/pre-push +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/validate_commit_msg.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/paths.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/source.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dna/tests/test_cli.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/dump_ddl.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/evidence/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/evidence/__main__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/evidence/cli.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/evidence/tests/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/evidence/tests/test_cli.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/evidence/tests/test_persist.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/index_ai/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/index_ai/__main__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/__main__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/manifest.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/apps/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/config/env.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/data/sut-accounts.example.yaml +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/packages/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/packages/action_words/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/packages/action_words/_internal/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/packages/action_words/_internal/params.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/packages/action_words/models.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/auth.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/recording/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/packages/page_objects/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/init_repo/stubs/packages/page_objects/session.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/mock_server/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/mock_server/__main__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/mock_server/cli.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/mock_server/seed.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/page_recorder/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/page_recorder/__main__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/page_recorder/capture.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/page_recorder/cli.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/page_recorder/codegen.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/page_recorder/freeze.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/page_recorder/inject.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/page_recorder/session.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/page_recorder/tests/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/page_recorder/tests/test_capture.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/page_recorder/tests/test_cli.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/page_recorder/tests/test_freeze.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/recorder/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/recorder/__main__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/recorder/cli.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/recorder/tests/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/apps/recorder/tests/test_cli.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/config.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/db/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/db/client.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/db/connection.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/excel/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/excel/workbook.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/fake/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/fake/__main__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/fake/catalog.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/fake/china.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/fake/cli.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/fake/core.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/fake/medical.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/fake/wrappers.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/logging/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/logging/context.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/logging/core.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/logging/helpers.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/logging/hooks.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/logging/scenario_file.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/__init__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/__main__.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/base.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/driver.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/errors.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/harvest.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/health.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/locator.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/model.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/session.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/steps.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit/page_test/testing.py +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit.egg-info/dependency_links.txt +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.0}/tuner_testkit.egg-info/requires.txt +0 -0
- {tuner_testkit-4.4.0 → tuner_testkit-5.0.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:
|
|
3
|
+
Version: 5.0.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
|
|
@@ -167,6 +167,10 @@ git add -A && git commit
|
|
|
167
167
|
|
|
168
168
|
`tuner-dna check` 核对项目树 DNA 是否与**当前 PATH 上那份** kit 一致。建议先 `uv tool upgrade`,再 `sync`,避免 CLI 还是旧包、`.venv` 已是新包。
|
|
169
169
|
|
|
170
|
+
**其他 AI IDE**:DNA 以 Cursor 布局为源,`tuner-dna sync --ide claude,agents`(或 `all`)把 skills 渲染到
|
|
171
|
+
`.claude/skills/` / `.agents/skills/`、subagents 到 `.claude/agents/`,并生成 `CLAUDE.md`(`@AGENTS.md` + always-on 规则内联 + 路径规则清单)。
|
|
172
|
+
`tuner-dna targets` 列出各目标落点;hooks.json 不跨工具翻译。目录约定随各工具文档变动,用前核对。
|
|
173
|
+
|
|
170
174
|
新仓第一次仍用第 2 节的 `tuner-init scaffold`(会写依赖并做一次 `tuner-dna sync`),不是每次发版都重新 scaffold。
|
|
171
175
|
|
|
172
176
|
`[phone-ui]` 为预留空 extra,4.0 未实现。
|
|
@@ -214,4 +218,4 @@ uv sync --extra all
|
|
|
214
218
|
(被测系统 = 平台本身,uv workspace 成员,共用 `.venv`):路线图在 `dogfood/assets/domain-notes/platform/roadmap.md`,
|
|
215
219
|
验收活文档在 `dogfood/tests/features/`。见 [`dogfood/README.md`](dogfood/README.md)。
|
|
216
220
|
|
|
217
|
-
|
|
221
|
+
5.0.0 发行说明(Plane Job 协议退场、`tuner-workspace`)见 [`docs/changelog/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)。
|
|
@@ -122,6 +122,10 @@ git add -A && git commit
|
|
|
122
122
|
|
|
123
123
|
`tuner-dna check` 核对项目树 DNA 是否与**当前 PATH 上那份** kit 一致。建议先 `uv tool upgrade`,再 `sync`,避免 CLI 还是旧包、`.venv` 已是新包。
|
|
124
124
|
|
|
125
|
+
**其他 AI IDE**:DNA 以 Cursor 布局为源,`tuner-dna sync --ide claude,agents`(或 `all`)把 skills 渲染到
|
|
126
|
+
`.claude/skills/` / `.agents/skills/`、subagents 到 `.claude/agents/`,并生成 `CLAUDE.md`(`@AGENTS.md` + always-on 规则内联 + 路径规则清单)。
|
|
127
|
+
`tuner-dna targets` 列出各目标落点;hooks.json 不跨工具翻译。目录约定随各工具文档变动,用前核对。
|
|
128
|
+
|
|
125
129
|
新仓第一次仍用第 2 节的 `tuner-init scaffold`(会写依赖并做一次 `tuner-dna sync`),不是每次发版都重新 scaffold。
|
|
126
130
|
|
|
127
131
|
`[phone-ui]` 为预留空 extra,4.0 未实现。
|
|
@@ -169,4 +173,4 @@ uv sync --extra all
|
|
|
169
173
|
(被测系统 = 平台本身,uv workspace 成员,共用 `.venv`):路线图在 `dogfood/assets/domain-notes/platform/roadmap.md`,
|
|
170
174
|
验收活文档在 `dogfood/tests/features/`。见 [`dogfood/README.md`](dogfood/README.md)。
|
|
171
175
|
|
|
172
|
-
|
|
176
|
+
5.0.0 发行说明(Plane Job 协议退场、`tuner-workspace`)见 [`docs/changelog/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 = "
|
|
3
|
+
version = "5.0.0"
|
|
4
4
|
description = "Shared test runtime, recorders, and DNA overlay for SUT test repos"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -69,7 +69,7 @@ tuner-mock-server = "tuner_testkit.apps.mock_server.cli:main"
|
|
|
69
69
|
tuner-dna = "tuner_testkit.apps.dna.cli:main"
|
|
70
70
|
tuner-init = "tuner_testkit.apps.init_repo.__main__:main"
|
|
71
71
|
tuner-index-ai = "tuner_testkit.apps.index_ai.__main__:main"
|
|
72
|
-
tuner-
|
|
72
|
+
tuner-workspace = "tuner_testkit.workspace.cli:main"
|
|
73
73
|
tuner-fake = "tuner_testkit.fake.cli:main"
|
|
74
74
|
tuner-page-test = "tuner_testkit.page_test.__main__:main"
|
|
75
75
|
tuner-action-words = "tuner_testkit.action_words.__main__:main"
|
|
@@ -6,9 +6,8 @@ Two layers:
|
|
|
6
6
|
* **overrides** — whatever the admin API changed since startup.
|
|
7
7
|
|
|
8
8
|
Overrides win on read and stay in memory until :meth:`MockStore.persist` writes
|
|
9
|
-
them out. That split is deliberate: the
|
|
10
|
-
response without the server writing into the checked-out repo
|
|
11
|
-
``tuner_testkit/apps/index_platform/README.md`` — catalog jobs do not write git).
|
|
9
|
+
them out. That split is deliberate: a test platform or the workbench must be able
|
|
10
|
+
to redefine a response without the server writing into the checked-out repo.
|
|
12
11
|
"""
|
|
13
12
|
from __future__ import annotations
|
|
14
13
|
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import argparse
|
|
6
|
-
import hashlib
|
|
7
6
|
import json
|
|
8
7
|
import shutil
|
|
9
8
|
import sys
|
|
@@ -16,44 +15,39 @@ from tuner_testkit.apps.dna.source import (
|
|
|
16
15
|
iter_dna_files,
|
|
17
16
|
payload_package_dir,
|
|
18
17
|
)
|
|
18
|
+
from tuner_testkit.apps.dna.targets import (
|
|
19
|
+
TARGET_LAYOUTS,
|
|
20
|
+
diff_file_map,
|
|
21
|
+
parse_targets,
|
|
22
|
+
render_target,
|
|
23
|
+
write_file_map,
|
|
24
|
+
)
|
|
19
25
|
from tuner_testkit.project import ProjectRootError, project_root
|
|
20
26
|
|
|
21
27
|
|
|
22
|
-
def _hash_bytes(data: bytes) -> str:
|
|
23
|
-
return hashlib.sha256(data).hexdigest()
|
|
24
|
-
|
|
25
|
-
|
|
26
28
|
def _target_root(explicit: str | None) -> Path:
|
|
27
29
|
if explicit:
|
|
28
30
|
return Path(explicit).expanduser().resolve()
|
|
29
31
|
return project_root()
|
|
30
32
|
|
|
31
33
|
|
|
34
|
+
def _targets(args: argparse.Namespace) -> list[str]:
|
|
35
|
+
return parse_targets(getattr(args, "ide", None))
|
|
36
|
+
|
|
37
|
+
|
|
32
38
|
def cmd_sync(args: argparse.Namespace) -> int:
|
|
33
39
|
try:
|
|
34
40
|
source = dna_source_root()
|
|
35
41
|
dest = _target_root(args.target)
|
|
36
|
-
|
|
42
|
+
targets = _targets(args)
|
|
43
|
+
except (DnaSourceError, ProjectRootError, ValueError) as exc:
|
|
37
44
|
print(str(exc), file=sys.stderr)
|
|
38
45
|
return 2
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if dst.exists() and not args.overwrite:
|
|
45
|
-
if dst.is_file() and src.read_bytes() == dst.read_bytes():
|
|
46
|
-
skipped += 1
|
|
47
|
-
continue
|
|
48
|
-
if dst.is_file() and not args.overwrite:
|
|
49
|
-
skipped += 1
|
|
50
|
-
print(f"skip {rel} (differs; pass --overwrite)")
|
|
51
|
-
continue
|
|
52
|
-
dst.parent.mkdir(parents=True, exist_ok=True)
|
|
53
|
-
shutil.copy2(src, dst)
|
|
54
|
-
copied += 1
|
|
55
|
-
print(f"copy {rel}")
|
|
56
|
-
print(f"dna sync: copied={copied} skipped={skipped} dest={dest}")
|
|
47
|
+
for target in targets:
|
|
48
|
+
files = render_target(source, target)
|
|
49
|
+
copied, skipped = write_file_map(dest, files, overwrite=args.overwrite)
|
|
50
|
+
print(f"dna sync[{target}]: copied={copied} skipped={skipped} dest={dest}")
|
|
57
51
|
marker = dest / ".tuner-dna-version"
|
|
58
52
|
marker.write_text(_kit_version() + "\n", encoding="utf-8")
|
|
59
53
|
return 0
|
|
@@ -63,28 +57,33 @@ def cmd_check(args: argparse.Namespace) -> int:
|
|
|
63
57
|
try:
|
|
64
58
|
source = dna_source_root()
|
|
65
59
|
dest = _target_root(args.target)
|
|
66
|
-
|
|
60
|
+
targets = _targets(args)
|
|
61
|
+
except (DnaSourceError, ProjectRootError, ValueError) as exc:
|
|
67
62
|
print(str(exc), file=sys.stderr)
|
|
68
63
|
return 2
|
|
69
64
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
missing.append(rel)
|
|
65
|
+
drifted = False
|
|
66
|
+
for target in targets:
|
|
67
|
+
missing, changed = diff_file_map(dest, render_target(source, target))
|
|
68
|
+
if not missing and not changed:
|
|
69
|
+
print(f"DNA[{target}] matches installed kit payload.")
|
|
76
70
|
continue
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
print(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
71
|
+
drifted = True
|
|
72
|
+
for rel in missing:
|
|
73
|
+
print(f" [{target}] missing: {rel}", file=sys.stderr)
|
|
74
|
+
for rel in changed:
|
|
75
|
+
print(f" [{target}] changed: {rel}", file=sys.stderr)
|
|
76
|
+
if drifted:
|
|
77
|
+
print("Run `tuner-dna sync --overwrite [--ide <targets>]` to refresh platform DNA.", file=sys.stderr)
|
|
78
|
+
return 1
|
|
79
|
+
return 0
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def cmd_targets(_args: argparse.Namespace) -> int:
|
|
83
|
+
for name, layout in TARGET_LAYOUTS.items():
|
|
84
|
+
print(f"{name:8s} skills={layout.skills_dir or '-':16s} agents={layout.agents_dir or '-':16s} "
|
|
85
|
+
f"instructions={layout.instructions_file or '-':10s} {layout.note}")
|
|
86
|
+
return 0
|
|
88
87
|
|
|
89
88
|
|
|
90
89
|
def cmd_bundle(_args: argparse.Namespace) -> int:
|
|
@@ -124,19 +123,25 @@ def _kit_version() -> str:
|
|
|
124
123
|
def main(argv: list[str] | None = None) -> int:
|
|
125
124
|
parser = argparse.ArgumentParser(
|
|
126
125
|
prog="tuner-dna",
|
|
127
|
-
description="Sync
|
|
126
|
+
description="Sync AI-IDE / git DNA from tuner-testkit into a project repo (Cursor by default; --ide for others).",
|
|
128
127
|
)
|
|
129
128
|
sub = parser.add_subparsers(dest="cmd", required=True)
|
|
129
|
+
ide_help = "comma-separated IDE targets: cursor (default), claude, agents, codex, all"
|
|
130
130
|
|
|
131
|
-
p_sync = sub.add_parser("sync", help="copy DNA files into the project")
|
|
131
|
+
p_sync = sub.add_parser("sync", help="copy / render DNA files into the project")
|
|
132
132
|
p_sync.add_argument("--target", default=None, help="project root (default: cwd project)")
|
|
133
133
|
p_sync.add_argument("--overwrite", action="store_true", help="overwrite differing files")
|
|
134
|
+
p_sync.add_argument("--ide", default=None, help=ide_help)
|
|
134
135
|
p_sync.set_defaults(func=cmd_sync)
|
|
135
136
|
|
|
136
137
|
p_check = sub.add_parser("check", help="report DNA drift vs the kit payload")
|
|
137
138
|
p_check.add_argument("--target", default=None)
|
|
139
|
+
p_check.add_argument("--ide", default=None, help=ide_help)
|
|
138
140
|
p_check.set_defaults(func=cmd_check)
|
|
139
141
|
|
|
142
|
+
p_targets = sub.add_parser("targets", help="list IDE targets and where each renders")
|
|
143
|
+
p_targets.set_defaults(func=cmd_targets)
|
|
144
|
+
|
|
140
145
|
p_bundle = sub.add_parser("bundle", help="copy DNA into the wheel payload directory")
|
|
141
146
|
p_bundle.set_defaults(func=cmd_bundle)
|
|
142
147
|
|
|
@@ -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:
|
|
5
|
+
version: 2.0.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# apps — 创建期约束
|
|
@@ -30,18 +30,20 @@ version: 1.4.0
|
|
|
30
30
|
- 不得被 `tests/` import(复用逻辑下沉到 `packages/` 业务资产或 `tuner_testkit`)。
|
|
31
31
|
- 不得写入 token / cookie / 密码 / Authorization / session 等敏感值。
|
|
32
32
|
- 破坏性操作无开关、默认非 dry-run/只读 → 禁止。
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
`
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
33
|
+
- 造数 / API / UI 动作不得做成伪 app:写成 action word(`@register` 后自动进目录与工作台)。
|
|
34
|
+
|
|
35
|
+
## 工作台可见 vs 本地维护
|
|
36
|
+
|
|
37
|
+
- **工作台可见**(团队成员要在 `tuner-workbench` 里填参运行):提供 import-safe 的
|
|
38
|
+
`apps/<name>/tool.py`,用 `tuner_testkit.tools.tool(tool_id=..., name=..., module="apps.<name>", group=...,
|
|
39
|
+
destructive=..., timeout=...)` 装饰 `build_parser`;`tuner-workspace catalog` 据此导出
|
|
40
|
+
`params_schema` / `argv_plan`。每个参数必须有 `help`(即表单 label);破坏性工具声明 `destructive=True`
|
|
41
|
+
且 CLI 默认 dry-run。
|
|
42
|
+
- **本地维护**(工程师跑完再 commit,产物进 git;如 dump_ddl / recorder / init_repo / index_ai):
|
|
43
|
+
不写 `tool.py`,或写了但 `visibility="local"`。
|
|
44
|
+
- 发现器只 import `apps/*/tool.py` 与 kit 的 `tuner_testkit/apps/*/tool.py`;`cli.py` 可以较重,
|
|
45
|
+
但 `tool.py` 及其 import 的模块禁止顶层 import DB 驱动 / Playwright / mitmproxy。
|
|
46
|
+
- 需要机器可读输出时用 `--json` envelope(`status / outputs[] / artifacts[] / log_path`),见规范 §7。
|
|
45
47
|
|
|
46
48
|
## 相关
|
|
47
49
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
description: Enforce layered boundaries between feature/steps/action_words/page_objects/api_objects and tuner_testkit runtime; no selector or request leakage across layers
|
|
3
3
|
globs: **/*.py
|
|
4
4
|
alwaysApply: false
|
|
5
|
-
version: 1.
|
|
5
|
+
version: 1.4.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Asset Layering — boundary rules per layer
|
|
@@ -43,8 +43,8 @@ Each layer owns one responsibility. Leakage across layers (e.g. selectors in ste
|
|
|
43
43
|
- **No secrets in repo**, ever: `Authorization`, `Cookie`, `Set-Cookie`, `*token*`, `*secret*`, `*password*`, `*session*`. Also applies to captures under `artifacts/evidence/`.
|
|
44
44
|
- **Evidence-driven edits**: Page/API object changes must be backed by Playwright MCP snapshots, `tuner-recorder` / `tuner-api-recorder` captures (`python -m tuner_testkit.apps.recorder` / `api_recorder`), or run_summary findings; avoid locator/path guesses.
|
|
45
45
|
- **`tests/**` must not import `apps.*`**. Action words for BDD/pytest stay in
|
|
46
|
-
`tuner_testkit.action_words
|
|
47
|
-
`
|
|
46
|
+
`tuner_testkit.action_words`; every `@register`ed word is already listed by
|
|
47
|
+
`tuner-workspace catalog` and runnable from the workbench — do not wrap them as `apps.*`.
|
|
48
48
|
|
|
49
49
|
## Examples
|
|
50
50
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
description: Keep the repo-level INDEX.md current and require managed assets to leave a changelog trail; index is the discovery entry for humans and the LLM
|
|
3
3
|
globs: assets/**,packages/api_objects/**,packages/page_objects/**,apps/**,tuner_testkit/apps/**,dogfood/assets/**,dogfood/packages/**,dogfood/apps/**,dogfood/INDEX.project.md
|
|
4
4
|
alwaysApply: false
|
|
5
|
-
version: 1.
|
|
5
|
+
version: 1.3.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# index-hygiene — 索引与留痕纪律
|
|
@@ -22,7 +22,9 @@ version: 1.2.0
|
|
|
22
22
|
|
|
23
23
|
## 增量维护(省 token)
|
|
24
24
|
|
|
25
|
-
-
|
|
25
|
+
- 索引里 `<!-- auto:begin:<zone> -->` 围栏内的区块由 `tuner-workspace index render` 从
|
|
26
|
+
`artifacts/catalogs/workspace.json` 确定性渲染,**禁止手写**;CI 跑 `tuner-workspace index check`。
|
|
27
|
+
- 围栏外的人工区更新 `INDEX.md` 时**优先读各区 `CHANGELOG` 的 delta**,据此补条目;
|
|
26
28
|
**不要为维护索引而全量读取 `assets/ddl/*.sql` 正文**。
|
|
27
29
|
- AI 组件区(`.cursor/**`)不手写进 `INDEX.md`:由 `python -m tuner_testkit.apps.index_ai`
|
|
28
30
|
确定性生成 `.cursor/REGISTRY.md`,`INDEX.md` 只链接过去。
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: maintain-index
|
|
3
3
|
description: Updates the repo-level INDEX.md (knowledge/capability map) incrementally by reading changelog deltas, not full asset bodies. Use after new assets/tools/objects are added, or when INDEX.md drifts from reality.
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Maintain INDEX.md(增量、省 token)
|
|
@@ -13,6 +13,19 @@ version: 1.1.2
|
|
|
13
13
|
- **写范围**:`INDEX.md`;若 `INDEX.project.md` 存在则也可改它。AI 组件区不手写(见下)。
|
|
14
14
|
- **分流**:平台工具 / 公共 `packages` / AI 组件链接 → `INDEX.md`。业务 DDL / SQL / 用例 / explore / design / api_objects / page_objects / features → 有 `INDEX.project.md` 就写那里,不要把 SUT 明细填进 `INDEX.md`。
|
|
15
15
|
|
|
16
|
+
## 先跑确定性渲染,再做人工区
|
|
17
|
+
|
|
18
|
+
索引文件里被 `<!-- auto:begin:<zone> -->` … `<!-- auto:end:<zone> -->` 围起来的区块**不要手写**:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
uv run tuner-workspace catalog # 刷新 artifacts/catalogs/workspace.json
|
|
22
|
+
uv run tuner-workspace index render # 渲染 INDEX.project.md(无则 INDEX.md)的 auto 围栏
|
|
23
|
+
uv run tuner-workspace index check # CI:自动区过期则 exit 1
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
zone:`ddl` / `sql` / `assets` / `api_objects` / `page_objects` / `action_words` / `apps` / `features`。
|
|
27
|
+
本 skill 只负责围栏**之外**的人工区(用途一句话、confidence 采信说明、平台工具的交接文档链接等)。
|
|
28
|
+
|
|
16
29
|
## 核心原则:读 delta,不全量读
|
|
17
30
|
|
|
18
31
|
- **自动区**(`assets/ddl/`、`packages/api_objects/`、`packages/page_objects/` 等):**只读各区 `CHANGELOG` 的尾部增量**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: maintain-page-objects
|
|
3
|
-
version: 2.0
|
|
3
|
+
version: 2.1.0
|
|
4
4
|
description: Creates or updates page assets under packages/page_objects/ on the tuner_testkit.page_test runtime (PageModel element table + declarative flows, or BasePage escape hatch) following page-objects-syntax.md. Use when UI steps fail due to locators, new UI flows are needed, selector leakage must be removed from steps, or doctor reports locator rot.
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -50,7 +50,7 @@ description: Creates or updates page assets under packages/page_objects/ on the
|
|
|
50
50
|
- 每个 flow 带 `description` 与 `example_params`(让 `run --example` 可一键跑)。
|
|
51
51
|
- 页面级 `asserts` / `extracts` 只放**页面自身的稳定契约**(`open()` 时执行);
|
|
52
52
|
flow 级断言写在该 flow 的 steps 里。
|
|
53
|
-
-
|
|
53
|
+
- 不需要任何装饰器就会出现在 `tuner-workspace catalog` 与工作台的只读页面清单里(静态扫描 `page_id`)。
|
|
54
54
|
|
|
55
55
|
## Quick validation(必须跑)
|
|
56
56
|
|
|
@@ -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
|
|
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)。
|
|
25
25
|
|
|
26
26
|
## 2. 三角色
|
|
27
27
|
|
|
@@ -81,3 +81,7 @@ flowchart TD
|
|
|
81
81
|
- **下游 SUT 测试仓**用 `tuner-init scaffold` 从空白目录新建,用 `uv add tuner-testkit==x.y.z` + `tuner-dna sync` 取平台能力。业务资产(`assets/`、objects、features、`INDEX.project.md`)只活在下游仓。
|
|
82
82
|
- 试用中发现框架要改:在 `public-main` 改并提交(内循环可用 `uv tool install --from <this-repo>`);阶段收口打 tag 发 PyPI,下游再升级。
|
|
83
83
|
- 历史分支 `plane-dogfood` **退役**:分支式 dogfood 验不了 `tuner-init` + PyPI 全链。Plane 的业务测试仓是外部仓(如 `tuner-test-platform-testrepo`)。
|
|
84
|
+
- **「Plane」在本仓只指 dogfood 的被测系统**(plane.so 类项目管理产品)。曾经的 Plane Job / Sync 协议
|
|
85
|
+
(`@plane_app`、`@plane_*`、`index_platform`)已在 5.0.0 退场,对应能力中立化为 `tuner_testkit.tools`
|
|
86
|
+
(tool manifest)与 `tuner_testkit.catalog`(`tuner-workspace catalog`);云端拉取 workspace 属于 D 阶段,
|
|
87
|
+
见 `dogfood/assets/domain-notes/platform/roadmap.md`。
|
|
@@ -11,8 +11,8 @@ description: Action Words spec for unified test-asset management. Covers the bas
|
|
|
11
11
|
- **目标**:把测试资产收敛为**最小可复用业务动作单元**(action word),统一管理
|
|
12
12
|
DB 造数 / DB 断言 / 接口请求 / 接口断言 / 页面操作 / 页面断言六类工作,做到:
|
|
13
13
|
- 每个 word **独立可运行**(CLI 一键执行),也可被 behave 步骤或 pytest 直接调用;
|
|
14
|
-
- 入参/出参有**统一数据契约**(pydantic v2),可导出 JSON Schema
|
|
15
|
-
|
|
14
|
+
- 入参/出参有**统一数据契约**(pydantic v2),可导出 JSON Schema 供本地工作台
|
|
15
|
+
(`tuner-workbench`)做可视化表单与一键执行;
|
|
16
16
|
- 造数产生的行**按表登记 cleanup**,测试夹具场景后精确删除。
|
|
17
17
|
- **边界**:
|
|
18
18
|
- action word 是**业务动作**,不是技术封装——`tuner_testkit/db`、`tuner_testkit/api_test`、
|
|
@@ -26,7 +26,7 @@ description: Action Words spec for unified test-asset management. Covers the bas
|
|
|
26
26
|
框架(基类 / registry / CLI)在 **`tuner_testkit.action_words`**。SUT 仓的 `packages/action_words/` 只做 re-export 并放本仓 word:
|
|
27
27
|
|
|
28
28
|
```
|
|
29
|
-
tuner_testkit/action_words/ # kit:base / context / registry /
|
|
29
|
+
tuner_testkit/action_words/ # kit:base / context / registry / CLI
|
|
30
30
|
packages/action_words/
|
|
31
31
|
├── __init__.py # re-export ActionWord / ActionResult / register 等
|
|
32
32
|
├── __main__.py # 转到 tuner_testkit.action_words CLI
|
|
@@ -129,7 +129,8 @@ uv run python -m tuner_testkit.action_words catalog [-o out.json] # 全量目录
|
|
|
129
129
|
|
|
130
130
|
- `run` 输出 `Result` 的 JSON(含 cleanup 登记),退出码 0/1 对应成功/失败;
|
|
131
131
|
- 手工造数后需要清理时,按输出的 cleanup 逐表 `DELETE ... WHERE id IN (...)`。
|
|
132
|
-
- `catalog` 供本机调用 `export_catalog()
|
|
132
|
+
- `catalog` 供本机调用 `export_catalog()`;`tuner-workspace catalog` 把**全部** `@register` 的词条(含 `params_schema`、
|
|
133
|
+
`destructive` 推断)写入 `artifacts/catalogs/workspace.json` 的 `action_words[]`,工作台据此渲染表单。
|
|
133
134
|
|
|
134
135
|
## 与 BDD / pytest 的集成
|
|
135
136
|
|
|
@@ -141,15 +142,14 @@ uv run python -m tuner_testkit.action_words catalog [-o out.json] # 全量目录
|
|
|
141
142
|
纯构建函数(`build_*_rows` / `build_links`)可离线断言列集与关联键。
|
|
142
143
|
- **禁止**:`tests/**` import `apps.*`。组合层永远是本包。
|
|
143
144
|
|
|
144
|
-
##
|
|
145
|
+
## 与本地工作台(workbench)
|
|
145
146
|
|
|
146
|
-
-
|
|
147
|
-
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
-
|
|
151
|
-
|
|
152
|
-
- 词条 `params_schema` 仍给 Formulation 业务表单;Job 校验用 `job_params_schema`。
|
|
147
|
+
- `@register` 即可见:工作台从 `tuner-workspace catalog` 的 `action_words[]` 读取词条,不需要额外装饰器。
|
|
148
|
+
- 运行:工作台经 `tuner-workspace run <word_id> --params JSON` 调用
|
|
149
|
+
`python -m tuner_testkit.action_words run <word_id> --params JSON`;只暴露 `word_id` 与 `--params`,
|
|
150
|
+
不暴露 `--username` / `--password` / `--params-file`(凭据来自本机 `config/env_local.py`)。
|
|
151
|
+
- `db_seed` / `api_request` / `ui_action` 三类按类别推断为 **destructive**:工作台要求勾选确认,未确认拒绝运行。
|
|
152
|
+
- 每个 `Params` 字段的 `Field(description=...)` 就是表单 label;缺 description 会被模板测试拦截。
|
|
153
153
|
|
|
154
154
|
|
|
155
155
|
## 敏感信息
|
|
@@ -169,4 +169,4 @@ uv run python -m tuner_testkit.action_words catalog [-o out.json] # 全量目录
|
|
|
169
169
|
5. `uv run pytest packages/tests/test_action_word_template.py` 通过;
|
|
170
170
|
6. `python -m tuner_testkit.action_words run <word_id> --example` 冒烟(需要环境时);
|
|
171
171
|
7. 若供 behave 使用,在步骤层接线并跑 `behave --stage api --dry-run`。
|
|
172
|
-
8.
|
|
172
|
+
8. `tuner-workspace catalog` 后确认词条出现在 `action_words[]`(工作台随即可见)。
|
|
@@ -26,10 +26,10 @@ description: API Objects (APIModel) spec for an AI-assisted automation repo. Foc
|
|
|
26
26
|
- **唯一对齐**:`method + normalized_path` 决定“落到哪个资产”。
|
|
27
27
|
- **禁止**:同一路由为不同场景重复创建多个 API Object(除非重大变更需要升级版本)。
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## 目录可见性(workspace catalog)
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
`auth.py`
|
|
31
|
+
`tuner-workspace catalog` 用静态扫描(`method = ...` / `path = ...`)列出全部冻结资产,不需要任何装饰器;
|
|
32
|
+
`auth.py` / `registry.py` / `recording/` 等辅助模块会被跳过。API Object 在工作台只做只读展示,不从工作台发请求。
|
|
33
33
|
|
|
34
34
|
## 目录结构与命名规范
|
|
35
35
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> `apps/` 存放 **SUT 私有**、可独立运行的测试工具(`python -m apps.<name>`)。
|
|
4
4
|
> **平台**工具在 `tuner_testkit.apps`(`tuner-recorder`、`tuner-dump-ddl` 等),不要再拷进下游 `apps/`。
|
|
5
|
-
> 领域动作(造数 / API / UI)留在 `packages
|
|
5
|
+
> 领域动作(造数 / API / UI)留在 `packages/`(action words 经 `@register` 自动进入目录与工作台),不经 apps 冒充。
|
|
6
6
|
> 供 `apps-authoring.mdc`(创建期)与 `apps-handover.mdc`(完成期)引用。
|
|
7
7
|
|
|
8
8
|
## 1. 目录与入口
|
|
@@ -14,8 +14,9 @@ apps/ # 仅 SUT 私有工具
|
|
|
14
14
|
├── __init__.py
|
|
15
15
|
└── <your_tool>/
|
|
16
16
|
├── __init__.py __main__.py
|
|
17
|
-
├── cli.py
|
|
18
|
-
├──
|
|
17
|
+
├── cli.py # argparse build_parser() + main()
|
|
18
|
+
├── tool.py # import-safe @tool 清单(工作台 / catalog 读取)
|
|
19
|
+
├── README.md # 交接文档(front-matter 见 metadata-conventions)
|
|
19
20
|
└── tests/
|
|
20
21
|
|
|
21
22
|
# 平台工具(已安装的 tuner-testkit,不要写进本仓 apps/)
|
|
@@ -63,10 +64,11 @@ apps/ # 仅 SUT 私有工具
|
|
|
63
64
|
- 不得写入 token / cookie / 密码 / Authorization / session 等敏感值(含产出文件与日志)。
|
|
64
65
|
- apps 是**独立运行**的工具,**不得被 `tests/` import**(测试复用逻辑应下沉到 `packages/`)。
|
|
65
66
|
- 破坏性操作(写生产库、删除文件)必须显式开关 + 默认 dry-run/只读。
|
|
66
|
-
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
- **工作台可见 vs 本地维护**:要出现在 `tuner-workspace catalog` / 工作台的工具,提供 import-safe 的
|
|
68
|
+
`apps/<name>/tool.py`,用 `tuner_testkit.tools.tool` 装饰 `build_parser`(argparse → `params_schema` + `argv_plan`)。
|
|
69
|
+
纯本地维护、产物直接进 git 的工具可以不写 `tool.py`,或写了但声明 `visibility="local"`。
|
|
70
|
+
`tool.py` 及其 import 的模块**不得**在顶层 import DB 驱动 / 浏览器 / 代理。领域动作留在 `packages/`
|
|
71
|
+
(action words 经 `@register` 自动进目录)。
|
|
70
72
|
|
|
71
73
|
## 6. 测试
|
|
72
74
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: artifacts-layout
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: 交付物目录 artifacts/ 的子目录职责、run 级 manifest.json 契约、与 assets/testreport 的边界。
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# artifacts 交付物规范(artifacts-layout)
|
|
8
|
+
|
|
9
|
+
> `artifacts/` 是 workspace 的**运行产出与交付物**目录:工具运行、回归报告、探索证据、agent 任务记录、catalog。
|
|
10
|
+
> 它是唯一的同步边界——本地工作台读它,将来 `tuner-publish` 从它往企业平台送。
|
|
11
|
+
> 知识层 `assets/`(含 `assets/testreport/`)放**人工策展后**的内容;`artifacts/` 放**原始产出**。
|
|
12
|
+
|
|
13
|
+
## 1. 目录
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
artifacts/
|
|
17
|
+
├── evidence/<run_id>/ # Playwright MCP / 网络 dump(tuner-evidence persist);脱敏;gitignore
|
|
18
|
+
├── inbox/<utc>-<agent>-<slice>.md # agent 任务记录(agent-task-log.md);gitignore
|
|
19
|
+
├── runs/<run_id>/ # 工具 / 动作词的一次运行(tuner-workspace run、工作台);gitignore
|
|
20
|
+
├── reports/<run_id>/ # 一次回归(behave / pytest)的报告与摘要;gitignore
|
|
21
|
+
├── catalogs/workspace.json # tuner-workspace catalog 产物;gitignore
|
|
22
|
+
├── exports/ # 待发布到企业平台的暂存区(C 阶段 tuner-publish);gitignore
|
|
23
|
+
├── playwright/ # 失败截图等浏览器产物;gitignore
|
|
24
|
+
└── page_test/ # page_test doctor / run 的产物(历史路径,保留)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- `run_id`:`<YYYYMMDDTHHMMSSZ>-<slug>`(UTC,slug 为短横线小写),全 workspace 唯一;`tuner_testkit.artifacts.new_run_id(slug)` 生成。
|
|
28
|
+
- 路径解析统一走 `tuner_testkit.project.asset_path("artifacts_<kind>")`(见 §4),禁止在代码里硬编码 `artifacts/...`。
|
|
29
|
+
- 除 `artifacts/.gitkeep` 外全部 gitignore;要入库的知识请策展到 `assets/`。
|
|
30
|
+
|
|
31
|
+
## 2. run 级 `manifest.json`(强制)
|
|
32
|
+
|
|
33
|
+
`runs/`、`reports/`、`evidence/` 下每个 run 目录必须带 `manifest.json`,由 `tuner_testkit.artifacts.RunManifest` 写入:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"manifest_version": 1,
|
|
38
|
+
"kind": "run", // run | report | evidence
|
|
39
|
+
"run_id": "20260922T081200Z-sample-tool",
|
|
40
|
+
"producer": {
|
|
41
|
+
"tool_id": "sample_tool", // 或 suite: "behave --stage api"
|
|
42
|
+
"argv": ["python", "-m", "apps.sample_tool", "--count", "3"],
|
|
43
|
+
"user_email": "qa@example.com", // git config user.email;无则 null
|
|
44
|
+
"host": "DESKTOP-1",
|
|
45
|
+
"kit_version": "5.0.0"
|
|
46
|
+
},
|
|
47
|
+
"params": {"count": 3, "label": "demo"},
|
|
48
|
+
"started": "2026-09-22T08:12:00Z",
|
|
49
|
+
"ended": "2026-09-22T08:12:03Z",
|
|
50
|
+
"status": "succeeded", // running | succeeded | failed | cancelled
|
|
51
|
+
"exit_code": 0,
|
|
52
|
+
"files": [{"path": "stdout.log", "kind": "log", "bytes": 1024}],
|
|
53
|
+
"summary": {"total": 12, "passed": 12, "failed": 0}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- `status=running` 在开始时写入,结束时改写为终态;工作台与 catalog 靠它区分「还在跑」与「跑完」。
|
|
58
|
+
- `files[]` 只列 run 目录内的相对路径;`kind` 建议:`log` / `report` / `envelope` / `screenshot` / `json` / `other`。
|
|
59
|
+
- `summary` 自由结构但必须是 JSON 对象;报告类建议 `total / passed / failed / skipped`。
|
|
60
|
+
- **禁止**写入 token / cookie / 密码;`params` 中命中敏感键名(`*password*` / `*token*` / `*secret*` / `*cookie*` / `authorization`)的值写入前必须掩码为 `***`(`RunManifest` 自动处理)。
|
|
61
|
+
|
|
62
|
+
## 3. 谁写什么
|
|
63
|
+
|
|
64
|
+
| 产出者 | 目录 | 写法 |
|
|
65
|
+
| --- | --- | --- |
|
|
66
|
+
| `tuner-workspace run` / 工作台 | `runs/<run_id>/` | `stdout.log`、`stderr.log`、`envelope.json`(工具 `--json` 输出)、`manifest.json` |
|
|
67
|
+
| behave(`*_environment.py` 钩子) | `reports/<run_id>/` | `summary.json`(feature/scenario 状态)、`manifest.json`;`-f html-pretty -o $TUNER_REPORT_DIR/report.html` 时 html 同目录 |
|
|
68
|
+
| pytest | `reports/<run_id>/` | `pytest --junitxml artifacts/reports/<run_id>/junit.xml`,再 `tuner_testkit.artifacts.finish_run` 写 manifest |
|
|
69
|
+
| `tuner-evidence persist` | `evidence/<run_id>/` | `network.jsonl` / `actions.jsonl` / `run_summary.md`(4.3.0 起);5.x 起补 `manifest.json` |
|
|
70
|
+
| agent(编排) | `inbox/` | 见 `agent-task-log.md` |
|
|
71
|
+
| `tuner-workspace catalog` | `catalogs/workspace.json` | 见 `tuner_testkit/workspace/README.md` |
|
|
72
|
+
|
|
73
|
+
环境变量 `TUNER_REPORT_DIR` 指定本次回归的 run 目录(不设则钩子自动生成 `reports/<run_id>/`);
|
|
74
|
+
`TUNER_RUN_ID` 指定 run_id(不设则自动生成)。
|
|
75
|
+
|
|
76
|
+
## 4. 路径键(`tuner_testkit.project`)
|
|
77
|
+
|
|
78
|
+
| key | 默认 | 覆盖环境变量 |
|
|
79
|
+
| --- | --- | --- |
|
|
80
|
+
| `artifacts` | `artifacts` | `TUNER_ARTIFACTS_DIR` |
|
|
81
|
+
| `artifacts_evidence` | `artifacts/evidence` | — |
|
|
82
|
+
| `artifacts_inbox` | `artifacts/inbox` | — |
|
|
83
|
+
| `artifacts_runs` | `artifacts/runs` | — |
|
|
84
|
+
| `artifacts_reports` | `artifacts/reports` | — |
|
|
85
|
+
| `artifacts_catalogs` | `artifacts/catalogs` | — |
|
|
86
|
+
| `artifacts_exports` | `artifacts/exports` | — |
|
|
87
|
+
| `artifacts_playwright` | `artifacts/playwright` | — |
|
|
88
|
+
| `artifacts_page_test` | `artifacts/page_test` | `PAGE_TEST_ARTIFACTS_DIR` |
|
|
89
|
+
|
|
90
|
+
## 5. 与知识层的边界
|
|
91
|
+
|
|
92
|
+
- `artifacts/reports/<run_id>/` 是**原始交付物**;人工或 `generate-test-report` skill 整理后的报告落
|
|
93
|
+
`assets/testreport/<sut>/<yyyy-mm>/<slug>.md`,front-matter 用 `evidence: [artifacts/reports/<run_id>]` 指回来源。
|
|
94
|
+
- `artifacts/inbox/` 不是 evidence;evidence 只认 `artifacts/evidence/<run_id>/`。
|
|
@@ -40,7 +40,8 @@ allowed-tools: [Read, Write, Edit, Bash, Glob, Grep]
|
|
|
40
40
|
- **无 host**:`url_path` 与 `Goto(path=...)` 只写路径;host 由
|
|
41
41
|
`tuner_testkit.config.get_ui_base_url()` 运行时注入。
|
|
42
42
|
- **无凭据**:敏感值写 `{{password}}` 占位符,运行时从入参或环境变量代入,**永不落盘**。
|
|
43
|
-
-
|
|
43
|
+
- **目录可见**:`tuner-workspace catalog` 静态扫描 `packages/page_objects/**` 中带 `page_id` 的 `PageModel` /
|
|
44
|
+
`BasePage` 文件,不需要装饰器;`session.py` / `pages.py` 等辅助模块会被跳过。
|
|
44
45
|
- **可审计**:脆弱 locator 必须声明 `confidence="fragile"` 并在 `note` 写清风险与替代建议。
|
|
45
46
|
|
|
46
47
|
## Locator 策略
|