tuner-testkit 4.3.0__tar.gz → 4.4.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.
Files changed (215) hide show
  1. {tuner_testkit-4.3.0/tuner_testkit.egg-info → tuner_testkit-4.4.0}/PKG-INFO +5 -1
  2. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/README.md +4 -0
  3. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/pyproject.toml +5 -1
  4. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/__init__.py +1 -1
  5. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/build.py +12 -1
  6. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/cli.py +2 -1
  7. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/agents/bdd-asset-pipeline.md +3 -1
  8. tuner_testkit-4.4.0/tuner_testkit/apps/dna/dna_payload/.cursor/agents/sut-self-learning.md +72 -0
  9. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/agents/sut-source-to-design.md +3 -1
  10. tuner_testkit-4.4.0/tuner_testkit/apps/dna/dna_payload/.cursor/rules/agent-task-log.mdc +22 -0
  11. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/commit-convention.mdc +3 -2
  12. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/index-hygiene.mdc +3 -2
  13. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/explore-sut/SKILL.md +5 -1
  14. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/AGENTS.md +8 -5
  15. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/MANIFEST.txt +1 -1
  16. tuner_testkit-4.4.0/tuner_testkit/apps/dna/dna_payload/docs/spec/agent-task-log.md +70 -0
  17. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/commit-convention.md +3 -1
  18. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/sut-self-learning.md +6 -0
  19. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/validate_commit_msg.py +12 -1
  20. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/tests/test_cli.py +3 -0
  21. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/scaffold.py +7 -7
  22. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/config/env.py +1 -0
  23. tuner_testkit-4.4.0/tuner_testkit/apps/init_repo/stubs/data/sut-accounts.example.yaml +18 -0
  24. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/tests/test_scaffold.py +5 -0
  25. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0/tuner_testkit.egg-info}/PKG-INFO +5 -1
  26. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit.egg-info/SOURCES.txt +2 -0
  27. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/LICENSE +0 -0
  28. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/setup.cfg +0 -0
  29. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/action_words/__init__.py +0 -0
  30. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/action_words/__main__.py +0 -0
  31. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/action_words/_internal/__init__.py +0 -0
  32. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/action_words/_internal/api.py +0 -0
  33. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/action_words/_internal/db.py +0 -0
  34. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/action_words/_internal/generators.py +0 -0
  35. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/action_words/_internal/ids.py +0 -0
  36. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/action_words/_internal/wait.py +0 -0
  37. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/action_words/base.py +0 -0
  38. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/action_words/context.py +0 -0
  39. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/action_words/plane.py +0 -0
  40. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/action_words/registry.py +0 -0
  41. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_mock/__init__.py +0 -0
  42. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_mock/app.py +0 -0
  43. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_mock/errors.py +0 -0
  44. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_mock/router.py +0 -0
  45. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_mock/spec.py +0 -0
  46. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_mock/store.py +0 -0
  47. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_objects/__init__.py +0 -0
  48. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_objects/auth.py +0 -0
  49. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_objects/recording/__init__.py +0 -0
  50. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_objects/recording/capture.py +0 -0
  51. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_objects/recording/codegen.py +0 -0
  52. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_objects/recording/freeze.py +0 -0
  53. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_objects/recording/mocks.py +0 -0
  54. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_objects/recording/normalize.py +0 -0
  55. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_objects/recording/pipeline.py +0 -0
  56. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_objects/recording/sanitize.py +0 -0
  57. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_test/__init__.py +0 -0
  58. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_test/client.py +0 -0
  59. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_test/errors.py +0 -0
  60. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_test/jsonpath.py +0 -0
  61. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/api_test/model.py +0 -0
  62. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/__init__.py +0 -0
  63. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/_shared/__init__.py +0 -0
  64. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/_shared/changelog.py +0 -0
  65. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/_shared/plane.py +0 -0
  66. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/_shared/plane_app.py +0 -0
  67. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/_shared/plane_asset.py +0 -0
  68. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/_shared/tests/test_plane_asset.py +0 -0
  69. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/_shared/tests/test_plane_collect.py +0 -0
  70. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/api_recorder/__init__.py +0 -0
  71. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/api_recorder/__main__.py +0 -0
  72. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/api_recorder/addon.py +0 -0
  73. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/api_recorder/cli.py +0 -0
  74. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/api_recorder/playwright_tap.py +0 -0
  75. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/api_recorder/tests/__init__.py +0 -0
  76. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/api_recorder/tests/test_addon.py +0 -0
  77. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/__init__.py +0 -0
  78. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/__main__.py +0 -0
  79. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/hooks/sync_registry.py +0 -0
  80. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/hooks.json +0 -0
  81. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/apps-authoring.mdc +0 -0
  82. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/apps-handover.mdc +0 -0
  83. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/assets-knowledge.mdc +0 -0
  84. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/bdd-asset-layering.mdc +0 -0
  85. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/bdd-pipeline-gates.mdc +0 -0
  86. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/bdd-stage-layout.mdc +0 -0
  87. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/explore-safety.mdc +0 -0
  88. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/packages-db.mdc +0 -0
  89. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/packages-fake.mdc +0 -0
  90. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/packages-logging.mdc +0 -0
  91. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/rules/packages-page-test.mdc +0 -0
  92. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/analyze-mcp-network/SKILL.md +0 -0
  93. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/create-action-word/SKILL.md +0 -0
  94. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/create-app/SKILL.md +0 -0
  95. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/derive-design-knowledge/SKILL.md +0 -0
  96. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/derive-feature-sets/SKILL.md +0 -0
  97. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/dump-ddl/SKILL.md +0 -0
  98. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/feature-authoring/SKILL.md +0 -0
  99. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/feature-review-lint/SKILL.md +0 -0
  100. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/freeze-api-objects/SKILL.md +0 -0
  101. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/maintain-behave-steps/SKILL.md +0 -0
  102. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/maintain-index/SKILL.md +0 -0
  103. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/maintain-page-objects/SKILL.md +0 -0
  104. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/release-template/SKILL.md +0 -0
  105. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/reuse-analysis/SKILL.md +0 -0
  106. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/.cursor/skills/run-feature-playwright-mcp/SKILL.md +0 -0
  107. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/action-words-syntax.md +0 -0
  108. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/api-objects-syntax.md +0 -0
  109. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/apps-authoring-syntax.md +0 -0
  110. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/assets-knowledge-syntax.md +0 -0
  111. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/bdd-run-gherkin-in-playwrightMCP.md +0 -0
  112. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/behave-gerkin-syntax.md +0 -0
  113. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/behave-step-definitions.md +0 -0
  114. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/design-knowledge-syntax.md +0 -0
  115. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/docs/spec/page-objects-syntax.md +0 -0
  116. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/README.md +0 -0
  117. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/commit-msg +0 -0
  118. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/dna_payload/tools/git-hooks/pre-push +0 -0
  119. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/paths.py +0 -0
  120. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dna/source.py +0 -0
  121. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/dump_ddl.py +0 -0
  122. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/evidence/__init__.py +0 -0
  123. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/evidence/__main__.py +0 -0
  124. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/evidence/cli.py +0 -0
  125. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/evidence/persist.py +0 -0
  126. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/evidence/tests/__init__.py +0 -0
  127. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/evidence/tests/test_cli.py +0 -0
  128. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/evidence/tests/test_persist.py +0 -0
  129. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/index_ai/__init__.py +0 -0
  130. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/index_ai/__main__.py +0 -0
  131. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/index_ai/registry.py +0 -0
  132. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/index_platform/__init__.py +0 -0
  133. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/index_platform/__main__.py +0 -0
  134. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/index_platform/build.py +0 -0
  135. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/index_platform/catalog.py +0 -0
  136. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/index_platform/plane.py +0 -0
  137. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/index_platform/tests/test_catalog.py +0 -0
  138. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/__init__.py +0 -0
  139. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/__main__.py +0 -0
  140. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/manifest.py +0 -0
  141. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/apps/__init__.py +0 -0
  142. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/behave.ini +0 -0
  143. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/__init__.py +0 -0
  144. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/action_words/__init__.py +0 -0
  145. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/action_words/_internal/__init__.py +0 -0
  146. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/action_words/_internal/params.py +0 -0
  147. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/action_words/models.py +0 -0
  148. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/__init__.py +0 -0
  149. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/auth.py +0 -0
  150. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/plane.py +0 -0
  151. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/recording/__init__.py +0 -0
  152. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/api_objects/registry.py +0 -0
  153. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/page_objects/__init__.py +0 -0
  154. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/page_objects/plane.py +0 -0
  155. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/init_repo/stubs/packages/page_objects/session.py +0 -0
  156. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/mock_server/__init__.py +0 -0
  157. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/mock_server/__main__.py +0 -0
  158. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/mock_server/cli.py +0 -0
  159. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/mock_server/plane.py +0 -0
  160. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/mock_server/seed.py +0 -0
  161. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/page_recorder/__init__.py +0 -0
  162. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/page_recorder/__main__.py +0 -0
  163. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/page_recorder/capture.py +0 -0
  164. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/page_recorder/cli.py +0 -0
  165. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/page_recorder/codegen.py +0 -0
  166. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/page_recorder/freeze.py +0 -0
  167. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/page_recorder/inject.py +0 -0
  168. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/page_recorder/session.py +0 -0
  169. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/page_recorder/tests/__init__.py +0 -0
  170. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/page_recorder/tests/test_capture.py +0 -0
  171. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/page_recorder/tests/test_cli.py +0 -0
  172. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/page_recorder/tests/test_freeze.py +0 -0
  173. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/recorder/__init__.py +0 -0
  174. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/recorder/__main__.py +0 -0
  175. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/recorder/cli.py +0 -0
  176. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/recorder/tests/__init__.py +0 -0
  177. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/apps/recorder/tests/test_cli.py +0 -0
  178. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/config.py +0 -0
  179. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/db/__init__.py +0 -0
  180. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/db/client.py +0 -0
  181. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/db/connection.py +0 -0
  182. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/excel/__init__.py +0 -0
  183. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/excel/workbook.py +0 -0
  184. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/fake/__init__.py +0 -0
  185. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/fake/__main__.py +0 -0
  186. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/fake/catalog.py +0 -0
  187. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/fake/china.py +0 -0
  188. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/fake/cli.py +0 -0
  189. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/fake/core.py +0 -0
  190. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/fake/medical.py +0 -0
  191. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/fake/wrappers.py +0 -0
  192. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/logging/__init__.py +0 -0
  193. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/logging/context.py +0 -0
  194. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/logging/core.py +0 -0
  195. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/logging/helpers.py +0 -0
  196. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/logging/hooks.py +0 -0
  197. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/logging/scenario_file.py +0 -0
  198. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/__init__.py +0 -0
  199. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/__main__.py +0 -0
  200. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/base.py +0 -0
  201. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/driver.py +0 -0
  202. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/errors.py +0 -0
  203. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/harvest.py +0 -0
  204. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/health.py +0 -0
  205. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/locator.py +0 -0
  206. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/model.py +0 -0
  207. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/registry.py +0 -0
  208. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/session.py +0 -0
  209. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/steps.py +0 -0
  210. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/page_test/testing.py +0 -0
  211. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit/project.py +0 -0
  212. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit.egg-info/dependency_links.txt +0 -0
  213. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit.egg-info/entry_points.txt +0 -0
  214. {tuner_testkit-4.3.0 → tuner_testkit-4.4.0}/tuner_testkit.egg-info/requires.txt +0 -0
  215. {tuner_testkit-4.3.0 → tuner_testkit-4.4.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: 4.3.0
3
+ Version: 4.4.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
@@ -210,4 +210,8 @@ uv sync --extra all
210
210
 
211
211
  `uv sync --extra dev` 与 `--extra all` 等价(`dev` 只是引用 `[all]`)。
212
212
 
213
+ 本仓是**平台仓**,不是 workspace。`dogfood/` 是用 `tuner-init scaffold dogfood --no-ai` 生成的 workspace 示范
214
+ (被测系统 = 平台本身,uv workspace 成员,共用 `.venv`):路线图在 `dogfood/assets/domain-notes/platform/roadmap.md`,
215
+ 验收活文档在 `dogfood/tests/features/`。见 [`dogfood/README.md`](dogfood/README.md)。
216
+
213
217
  4.3.0 发行说明见 [`docs/changelog/TEMPLATE-4.3.0.md`](docs/changelog/TEMPLATE-4.3.0.md);4.2.0 见 [`TEMPLATE-4.2.0.md`](docs/changelog/TEMPLATE-4.2.0.md);3.x → 4.x 迁移见 [`TEMPLATE-4.0.0.md`](docs/changelog/TEMPLATE-4.0.0.md)。平台能力地图见 [`INDEX.md`](INDEX.md)。
@@ -165,4 +165,8 @@ uv sync --extra all
165
165
 
166
166
  `uv sync --extra dev` 与 `--extra all` 等价(`dev` 只是引用 `[all]`)。
167
167
 
168
+ 本仓是**平台仓**,不是 workspace。`dogfood/` 是用 `tuner-init scaffold dogfood --no-ai` 生成的 workspace 示范
169
+ (被测系统 = 平台本身,uv workspace 成员,共用 `.venv`):路线图在 `dogfood/assets/domain-notes/platform/roadmap.md`,
170
+ 验收活文档在 `dogfood/tests/features/`。见 [`dogfood/README.md`](dogfood/README.md)。
171
+
168
172
  4.3.0 发行说明见 [`docs/changelog/TEMPLATE-4.3.0.md`](docs/changelog/TEMPLATE-4.3.0.md);4.2.0 见 [`TEMPLATE-4.2.0.md`](docs/changelog/TEMPLATE-4.2.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 = "4.3.0"
3
+ version = "4.4.0"
4
4
  description = "Shared test runtime, recorders, and DNA overlay for SUT test repos"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -90,6 +90,10 @@ include = ["tuner_testkit*"]
90
90
  build_py = "tuner_testkit.apps.dna.build.BuildPyWithDna"
91
91
  sdist = "tuner_testkit.apps.dna.build.SdistWithDna"
92
92
 
93
+ [tool.uv.workspace]
94
+ # dogfood/ is a workspace scaffolded by `tuner-init` from this repo (SUT = the platform itself).
95
+ members = ["dogfood"]
96
+
93
97
  [tool.tuner-testkit]
94
98
  page_objects = "packages/page_objects"
95
99
  api_objects = "packages/api_objects"
@@ -2,4 +2,4 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = "4.3.0"
5
+ __version__ = "4.4.0"
@@ -31,8 +31,19 @@ def _payload_ready(root: Path | None = None) -> bool:
31
31
 
32
32
 
33
33
  def _bundle() -> None:
34
+ """Refresh ``dna_payload`` from the template tree when building a wheel.
35
+
36
+ A leftover ``dna_payload/`` from an older build must not short-circuit:
37
+ that shipped stale DNA (4.3.0 payload inside a 4.4.0 wheel).
38
+ """
34
39
  _ensure_src_on_path()
35
- if _payload_ready():
40
+ from tuner_testkit.project import template_source_root
41
+
42
+ if template_source_root() is None:
43
+ if not _payload_ready():
44
+ raise RuntimeError(
45
+ "no DNA payload in this install and no template checkout to bundle from"
46
+ )
36
47
  return
37
48
 
38
49
  from tuner_testkit.apps.dna.cli import cmd_bundle
@@ -47,6 +47,7 @@ def cmd_sync(args: argparse.Namespace) -> int:
47
47
  continue
48
48
  if dst.is_file() and not args.overwrite:
49
49
  skipped += 1
50
+ print(f"skip {rel} (differs; pass --overwrite)")
50
51
  continue
51
52
  dst.parent.mkdir(parents=True, exist_ok=True)
52
53
  shutil.copy2(src, dst)
@@ -82,7 +83,7 @@ def cmd_check(args: argparse.Namespace) -> int:
82
83
  print(f" missing: {rel}", file=sys.stderr)
83
84
  for rel in changed:
84
85
  print(f" changed: {rel}", file=sys.stderr)
85
- print("Run `tuner-dna sync` to refresh platform DNA.", file=sys.stderr)
86
+ print("Run `tuner-dna sync --overwrite` to refresh platform DNA.", file=sys.stderr)
86
87
  return 1
87
88
 
88
89
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: bdd-asset-pipeline
3
- version: 2.0.0
3
+ version: 2.0.1
4
4
  description: Lower-half of SUT self-learning — Feature Sets + design knowledge → Reuse Analysis → Freeze API Objects → Maintain Page Objects → Maintain Steps → behave regression. Use only for behave/BDD automation assets. Do NOT use when the user explicitly requests pytest. Do NOT use this agent as the explore-first entry; start from docs/spec/sut-self-learning.md instead.
5
5
  ---
6
6
 
@@ -104,3 +104,5 @@ Before writing Then-assertions, **read `assets/design/**`**:
104
104
  - `behave --stage ui` succeeds for UI features that exist.
105
105
  - `behave --stage api` succeeds for API features that exist (or `--dry-run`
106
106
  with documented TODO).
107
+ - Task log written to `artifacts/inbox/` per `docs/spec/agent-task-log.md`
108
+ (no secrets).
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: sut-self-learning
3
+ version: 1.0.0
4
+ description: Orchestrate explore-first SUT self-learning — accounts → Playwright MCP explore → evidence → freeze API/page objects → design knowledge → index, with an artifacts/inbox task log. Hand off to bdd-asset-pipeline only when Feature Sets are in scope. Do NOT use when the user explicitly requests pytest-only work.
5
+ ---
6
+
7
+ # SUT self-learning orchestrator (upper half + optional handoff)
8
+
9
+ ## Purpose
10
+
11
+ 串起「学习被测 Web 系统并生长测试资产」的**上半程**。规格
12
+ `docs/spec/sut-self-learning.md`。本文件是可执行编排;规格不是本 agent 的替代。
13
+
14
+ **下半程**(已有 feature set → steps / behave)交给
15
+ `.cursor/agents/bdd-asset-pipeline.md`,不要在本 agent 里硬造 Gherkin,除非用户明确要验收自动化。
16
+
17
+ ## When to use
18
+
19
+ - 工程师说「探索 SUT / 学习某某模块 / 生成测试资产 / 再跑一轮自学习」。
20
+ - 下游仓已有 `tuner-init` 骨架,SUT 可访问。
21
+
22
+ ## Inputs
23
+
24
+ 1. `INDEX.md` + 若存在 `INDEX.project.md`(已有切片、勿重复冻登录接口)。
25
+ 2. **账号**(只读,禁止拷进仓库/evidence/inbox):
26
+ 1. `data/sut-accounts.local.yaml`(gitignore,首选)
27
+ 2. 否则 `config/env_local.py` 的 `TEST_ACCOUNT`
28
+ 3. 都没有则停,让工程师按 `data/sut-accounts.example.yaml` 补本机文件
29
+ 3. 垂直切片(一个模块,不是全站爬)。
30
+ 4. 可选:SUT 源码根(如 Plane `apps/api`)——有则跑 `sut-source-to-design`。
31
+
32
+ ## Skills / agents(顺序)
33
+
34
+ | 步 | 组件 | 产出 |
35
+ | --- | --- | --- |
36
+ | 0 | 读账号 + `explore-safety` | 登录参数(内存) |
37
+ | 1 | `dump-ddl`(缺表才跑,禁 `--all`) | `assets/ddl/<ds>/` |
38
+ | 2 | `explore-sut` | `artifacts/evidence/<run_id>/` + `assets/explore/` |
39
+ | 3 | `analyze-mcp-network`(`tuner-evidence routes`) | 路由表 JSON |
40
+ | 4 | `reuse-analysis` | 复用 vs 新建 |
41
+ | 5 | `freeze-api-objects` | `packages/api_objects/`(跳过 sign-in) |
42
+ | 6 | `maintain-page-objects` | `packages/page_objects/` |
43
+ | 7 | `derive-design-knowledge`;有源码则 **`sut-source-to-design`** | `assets/design/` |
44
+ | 8 | `maintain-index` | `INDEX.project.md` 或 `INDEX.md` |
45
+ | 9 | **本 agent** 写 inbox | `artifacts/inbox/<utc>-sut-self-learning-<slice>.md` |
46
+ | 10 | 仅当用户要 `.feature` | `derive-feature-sets` → **`bdd-asset-pipeline`** |
47
+
48
+ 每步先 **Read** 对应 `SKILL.md` / agent 正文再执行。不要跳过 evidence 落盘。
49
+
50
+ ## Inbox(强制)
51
+
52
+ 遵循 `docs/spec/agent-task-log.md`。SUT 自学习日志 **必须**含:
53
+
54
+ - `## Pages explored`(url pattern / title / 按钮)
55
+ - `## Assets added this run`(本任务新增或更新的 api/page/explore/design/ddl)
56
+ - `run_id`;`account_id`(无密码)
57
+ - 若这是第 N 轮 dogfood:`## Loop delta` 对比上一轮 inbox / 平台能力
58
+
59
+ ## Hard rules
60
+
61
+ - 活体 SUT:`explore-safety`(throwaway 数据;不问不准删)。
62
+ - 密钥不入库、不进 evidence、不进 inbox。
63
+ - Web cookie session 的 path 占位用 `{workspace_slug}` 等,调用走 `set_path`。
64
+ - 页面资产 app 名对齐现有 `packages/page_objects/<app>/`,勿与装饰器模块重名。
65
+ - 未走 Gate 1 证据不得写 api/page/design。
66
+
67
+ ## Done
68
+
69
+ - evidence 在磁盘且已脱敏。
70
+ - 切片的 explore +(若有写操作)design 已引用 `run_id`。
71
+ - 新路由已冻或书面说明跳过原因。
72
+ - inbox 已落盘,页面清单与资产增量齐全。
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: sut-source-to-design
3
- version: 1.0.0
3
+ version: 1.0.1
4
4
  description: Walk SUT backend source (Django models/views/serializers, or equivalent) plus assets/ddl to draft assets/design/<app>/<route-slug>.md. Use when the engineer points at a source tree. Do not invent tables. Complements derive-design-knowledge; this agent is the source-channel playbook.
5
5
  ---
6
6
 
@@ -31,3 +31,5 @@ Highest-quality `writes` / `noise` / `reads` often come from **models.save / vie
31
31
  - `confidence: inferred` for source-only; `observed` only with DB/log evidence.
32
32
  - No secrets.
33
33
  - Do not generate action words here.
34
+ - Write `artifacts/inbox/<utc>-sut-source-to-design-<slice>.md` per
35
+ `docs/spec/agent-task-log.md` (outputs = design files; no secrets).
@@ -0,0 +1,22 @@
1
+ ---
2
+ description: Every agent run must leave a task log under artifacts/inbox/ (no secrets).
3
+ alwaysApply: true
4
+ version: 1.0.0
5
+ ---
6
+
7
+ # Agent task log — `artifacts/inbox/`
8
+
9
+ 每次按 `.cursor/agents/*.md` 编排执行(含 SUT 自学习),结束前必须写一份任务记录。
10
+ 细则见 `docs/spec/agent-task-log.md`。
11
+
12
+ ## Must
13
+
14
+ - 路径:`artifacts/inbox/<UTC>-<agent>-<slice>.md`(例 `20260914T031200Z-sut-self-learning-cycles.md`)。
15
+ - 必填:`agent`、意图、输入、产出文件列表、下一步。
16
+ - **SUT 自学习**额外必填:本次探索的页面(url pattern + 标题)、本次新增/更新的测试资产路径。
17
+ - 只写 `account_id` / workspace slug,**禁止**密码、token、Cookie。
18
+
19
+ ## Must not
20
+
21
+ - 用聊天摘要代替 inbox 落盘。
22
+ - 把 inbox 当 evidence(网络 dump 仍走 `artifacts/evidence/<run_id>/`)。
@@ -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.0.0
4
+ version: 1.1.0
5
5
  ---
6
6
 
7
7
  # 提交规范(Conventional Commits + 六层 scope)
@@ -12,7 +12,8 @@ version: 1.0.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`(多层用逗号分隔,如 `feat(apps,packages): ...`)。
15
+ init_repo / index / dogfood`(多层用逗号分隔,如 `feat(apps,packages): ...`;
16
+ `dogfood/**` 一律用 `dogfood`)。
16
17
  - **scope 必须覆盖本次真实改动涉及的层**(`packages` 是三个子资产层的上位 scope)。
17
18
 
18
19
  一眼可读优先:让人从提交信息就看出"更新了 assets、新增了 apps、录制了新的 api_objects"等。
@@ -1,13 +1,14 @@
1
1
  ---
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
- globs: assets/**,packages/api_objects/**,packages/page_objects/**,apps/**,tuner_testkit/apps/**
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.1.3
5
+ version: 1.2.0
6
6
  ---
7
7
 
8
8
  # index-hygiene — 索引与留痕纪律
9
9
 
10
10
  根 `INDEX.md` 是**平台**能力地图(发现入口)。若存在 `INDEX.project.md`,那是试验田 / 下游项目仓的**业务资产**地图;两份索引都必须与各自职责范围内的仓库状态一致。
11
+ 平台仓内的 `dogfood/` 是用 scaffold 生成的 workspace,它的业务地图是 `dogfood/INDEX.project.md`。
11
12
 
12
13
  ## 留痕(changelog trail)
13
14
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: explore-sut
3
- version: 1.1.0
3
+ version: 1.2.0
4
4
  description: Explore-first Playwright MCP session against a live SUT. Produces sanitized artifacts/evidence/<run_id>/ plus assets/explore capability notes. Use when learning a web SUT, mapping pages/buttons, or gathering evidence before any .feature exists. Do NOT use when the user already has a feature to implement — use run-feature-playwright-mcp instead.
5
5
  ---
6
6
 
@@ -23,6 +23,10 @@ description: Explore-first Playwright MCP session against a live SUT. Produces s
23
23
  ## Steps
24
24
 
25
25
  1. Read `INDEX.md` and `INDEX.project.md` if present. Note base URLs from `config`.
26
+ Load login from **`data/sut-accounts.local.yaml`** if it exists; else
27
+ `config/env_local.py` `TEST_ACCOUNT`. Copy `data/sut-accounts.example.yaml`
28
+ when neither exists and **stop**. Never write the password into evidence,
29
+ explore notes, inbox, or git.
26
30
  2. Pick a **vertical slice** (e.g. workspace → project → issue), not a full-site crawl.
27
31
  3. Navigate with Playwright MCP. After each meaningful action, dump network + snapshot.
28
32
  4. Persist with **`tuner-evidence persist`** (do not leave captures only in chat):
@@ -1,4 +1,4 @@
1
- <!-- version: 1.3.0 -->
1
+ <!-- version: 1.5.0 -->
2
2
  # AGENTS — 平台总入口(轻量 DM)
3
3
 
4
4
  > 本文件是"repo as a platform"的**稳定世界观**:只写不常变的分层结构与角色。
@@ -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/`(运行产出;MCP evidence 落 `artifacts/evidence/<run_id>/`)。
24
+ 配套:`config/`(环境/数据源)、`.cursor/`(AI 组件,见下)、`artifacts/`·`logs/`(运行产出;MCP evidence 落 `artifacts/evidence/<run_id>/`;agent 任务记录落 `artifacts/inbox/`)。SUT 登录本机文件:`data/sut-accounts.local.yaml`(gitignore)。
25
25
 
26
26
  ## 2. 三角色
27
27
 
@@ -43,7 +43,7 @@
43
43
  ```mermaid
44
44
  flowchart TD
45
45
  Start[任务到达] --> Q{任务类型?}
46
- Q -->|"学习被测系统 / 探索式测试"| Learn["SUT 自学习\ndocs/spec/sut-self-learning.md"]
46
+ Q -->|"学习被测系统 / 探索式测试"| Learn["SUT 自学习编排\n.cursor/agents/sut-self-learning.md"]
47
47
  Q -->|"业务 UI/API 流自动化"| BDD["BDD 资产流水线(下半程)\n.cursor/agents/bdd-asset-pipeline.md"]
48
48
  Q -->|"明确要求 pytest / 性能 / DB 核对"| Pytest["pytest 路径\n复用 tuner_testkit + packages,不产出 .feature"]
49
49
  Q -->|"需要一个新的独立工具"| App["create-app skill\napps-authoring / apps-handover 规则"]
@@ -52,7 +52,7 @@ flowchart TD
52
52
  Q -->|"读/策展/索引知识"| Idx["查 INDEX.md + maintain-index skill"]
53
53
  ```
54
54
 
55
- - **学习被测系统** → `docs/spec/sut-self-learning.md`(explore-first:能力清单 + design 知识;证据来源开放、design 产物收敛)。
55
+ - **学习被测系统** → `.cursor/agents/sut-self-learning.md`(编排 explore → freeze → design;规格 `docs/spec/sut-self-learning.md`;任务 log 见 `docs/spec/agent-task-log.md`)。
56
56
  - **业务 UI/API 流** → `.cursor/agents/bdd-asset-pipeline.md`(自学习的**下半程**;内部含三门禁,仅在此分支生效)。
57
57
  - **明确 pytest** → 直接写 pytest,复用 `tuner_testkit` 与本仓 `packages/**` 业务资产,不要为满足分层而硬造 Gherkin。
58
58
  - **造工具** → `create-app` skill;工具做好按 `apps-handover.mdc` 补交接文档。证据通道(日志/DB 日志取数)也落 `apps/`,遵守 CLI + JSON 输出约定。
@@ -65,11 +65,14 @@ flowchart TD
65
65
  - 不得将 token / cookie / Authorization / 密码 / session 等敏感信息写入仓库(含 capture 与 api_objects)。
66
66
  - 提交遵循 Conventional Commits + 六层 scope,见 `docs/spec/commit-convention.md`(`commit-msg` hook 会校验)。
67
67
  - DB 只走 `tuner_testkit.db`,日志只走 `tuner_testkit.logging`(见对应 rule)。
68
- - 密钥只放本机 `config/env_local.py` 或环境变量,**任何分支都不得提交**。多套 prd/uat/dev 写在 `env_local.ENVIRONMENTS` 里,用 `python -m tuner_testkit.config use <name>` 切换(或 `TUNER_ENV`)。
68
+ - 密钥只放本机 `config/env_local.py`、`data/**/*.local.yaml` 或环境变量,**任何分支都不得提交**。多套 prd/uat/dev 写在 `env_local.ENVIRONMENTS` 里,用 `python -m tuner_testkit.config use <name>` 切换(或 `TUNER_ENV`)。探索账号优先 `data/sut-accounts.local.yaml`(模板 `data/sut-accounts.example.yaml`)。
69
69
 
70
70
  ## 6. 分支与下游仓
71
71
 
72
72
  本公开仓只维护**平台**:`tuner_testkit/`、`.cursor/**`、`docs/spec/**`、`INDEX.md`。
73
+ **本仓不是 workspace**:真正的个人 workspace 是 `tuner-init scaffold` 生成的下游仓。仓内 `dogfood/`
74
+ 是用同一 scaffold 生成的 workspace 示范(被测系统 = 平台本身),存放路线图、验收剧本与活文档;
75
+ 它是 uv workspace 成员,不带自己的 `.cursor/`(根 DNA 覆盖全树),提交 scope 用 `dogfood`。
73
76
 
74
77
  | 分支 | 职责 | 谁改 |
75
78
  | --- | --- | --- |
@@ -1,5 +1,5 @@
1
1
  {
2
- "files": 49,
2
+ "files": 52,
3
3
  "paths": [
4
4
  ".cursor/rules",
5
5
  ".cursor/skills",
@@ -0,0 +1,70 @@
1
+ # Agent 任务日志(`artifacts/inbox/`)
2
+
3
+ > 给 `.cursor/agents/**` 编排任务用的**运行记录**约定。
4
+ > 硬约束见 `.cursor/rules/agent-task-log.mdc`。
5
+ > Evidence(网络/DOM dump)仍落 `artifacts/evidence/<run_id>/`,本目录不替代它。
6
+
7
+ ## 1. 路径
8
+
9
+ ```text
10
+ artifacts/inbox/<YYYYMMDDTHHMMSSZ>-<agent>-<slice>.md
11
+ ```
12
+
13
+ - `<agent>`:与 agent front-matter `name` 一致(如 `sut-self-learning`)。
14
+ - `<slice>`:短横线 slug(如 `cycles`、`issue-create`)。
15
+ - 本目录默认 gitignore;本机下次会话靠读磁盘复用,不入库。
16
+
17
+ ## 2. 通用模板(所有 agent)
18
+
19
+ ```markdown
20
+ ---
21
+ agent: sut-self-learning
22
+ slice: cycles
23
+ started: 2026-09-14T03:12:00Z
24
+ ended: 2026-09-14T03:40:00Z
25
+ status: done
26
+ account_id: dogfood-admin
27
+ evidence:
28
+ - artifacts/evidence/20260914T031200Z-cycles/
29
+ ---
30
+
31
+ # <slice> — <一句话意图>
32
+
33
+ ## Intent
34
+ (用户要什么)
35
+
36
+ ## Inputs
37
+ - INDEX / INDEX.project / accounts 文件 / 源码路径
38
+
39
+ ## Outputs
40
+ | kind | path | action |
41
+ | --- | --- | --- |
42
+ | explore | assets/explore/web/….md | add |
43
+ | api_object | packages/api_objects/… | add |
44
+
45
+ ## Next
46
+ - …
47
+ ```
48
+
49
+ `kind` 建议:`explore` / `design` / `ddl` / `api_object` / `page_object` / `action_word` / `feature` / `index` / `inbox`。
50
+
51
+ ## 3. SUT 自学习额外章节(强制)
52
+
53
+ 编排 agent `.cursor/agents/sut-self-learning.md` 的 inbox **必须**再写:
54
+
55
+ ```markdown
56
+ ## Pages explored
57
+ | url pattern | title | primary actions |
58
+ | --- | --- | --- |
59
+ | `/{workspace}/projects/{id}/cycles/` | Cycles | New cycle, Save |
60
+
61
+ ## Assets added this run
62
+ (只列本任务新增或更新的路径,不要把仓库里已有资产再抄一遍)
63
+ ```
64
+
65
+ 对照两轮 dogfood 时,另写 `## Loop delta`:相对上一份 inbox,少了哪些手工步骤、多了哪些平台能力。
66
+
67
+ ## 4. 密钥
68
+
69
+ - 可用 `account_id` 指向 `data/sut-accounts.local.yaml` 的条目。
70
+ - 禁止密码、token、Cookie、Authorization 原文。
@@ -51,6 +51,7 @@
51
51
  | `hooks` | `.cursor/hooks*`、`tools/git-hooks/**` | 钩子 |
52
52
  | `init_repo` | `tuner_testkit/apps/init_repo/**` | 初始化工具与 release |
53
53
  | `index` | `INDEX.md`、`INDEX.project.md`、`.cursor/REGISTRY.md` | 索引/注册表 |
54
+ | `dogfood` | `dogfood/**` | 平台仓内用 scaffold 生成的 dogfood workspace(知识、feature、fixture) |
54
55
 
55
56
  > `packages` 视为 `api_objects` / `page_objects` / `action_words` 的**上位 scope**:
56
57
  > 声明 `packages` 可覆盖这三者的改动。
@@ -80,4 +81,5 @@ feat(apps,packages): add init_repo and release manifest surface
80
81
  git config core.hooksPath tools/git-hooks
81
82
  ```
82
83
 
83
- CI 可复用同一校验脚本(对齐 `docs/note.md` 里 Ruff+CI 规划)。合并/回滚提交(`Merge`/`Revert` 开头)跳过校验。
84
+ CI 可复用同一校验脚本。合并/回滚提交(`Merge`/`Revert` 开头)跳过校验。
85
+ 测试或活文档可用环境变量 `TUNER_COMMIT_STAGED`(换行分隔的路径列表)注入"已暂存文件",替代 `git diff --cached`。
@@ -48,6 +48,10 @@ artifacts/evidence/<run_id>/ ← 统一落盘(强制)
48
48
  steps imple → Auto UAT(behave)
49
49
  ```
50
50
 
51
+ **上半程编排**:[`.cursor/agents/sut-self-learning.md`](../../.cursor/agents/sut-self-learning.md)
52
+ (本机账号 → explore → evidence → freeze → design → `artifacts/inbox/`)。
53
+ 任务记录约定:[`agent-task-log.md`](agent-task-log.md)。
54
+
51
55
  下半程(已有 feature set + design 时写 steps)由
52
56
  [`.cursor/agents/bdd-asset-pipeline.md`](../../.cursor/agents/bdd-asset-pipeline.md) 编排。
53
57
 
@@ -87,5 +91,7 @@ artifacts/evidence/<run_id>/ ← 统一落盘(强制)
87
91
  - **阶段 2 design 闭环**:`derive-design-knowledge` + `sut-source-to-design` agent;schema 仍为 v0.1(Plane 切片缺口记在 design spec §6)。
88
92
  - **阶段 3 双路汇合**:`derive-feature-sets`;bdd-asset-pipeline 下半程。
89
93
  - **阶段 4 知识自治**:knowledge-curator;确定性 `secret-scan` hook。
94
+ - **编排与任务 log(4.4.0 DNA)**:`sut-self-learning` agent + `artifacts/inbox/`;
95
+ 探索账号本机文件 `data/sut-accounts.local.yaml`。
90
96
 
91
97
  内循环用 `uv tool install --from <platform-repo>`;阶段收口才打 tag 发 PyPI。
@@ -17,6 +17,7 @@ Exit code 0 = ok, 1 = rejected.
17
17
  """
18
18
  from __future__ import annotations
19
19
 
20
+ import os
20
21
  import re
21
22
  import subprocess
22
23
  import sys
@@ -30,10 +31,15 @@ ALLOWED_TYPES = {
30
31
  ALLOWED_SCOPES = {
31
32
  "assets", "apps", "packages", "api_objects", "page_objects", "action_words",
32
33
  "tests", "docs", "rules", "skills", "agents", "hooks", "init_repo", "index",
34
+ # in-repo dogfood workspace (scaffolded from this platform repo)
35
+ "dogfood",
33
36
  # fine-grained package aliases also accepted
34
37
  "db", "logging", "recorder", "config", "api_test", "excel",
35
38
  }
36
39
 
40
+ # Tests can inject the staged file list instead of calling git.
41
+ STAGED_ENV = "TUNER_COMMIT_STAGED"
42
+
37
43
  # packages umbrella covers these sub-layers
38
44
  PACKAGES_UMBRELLA = {"api_objects", "page_objects", "action_words", "packages",
39
45
  "db", "logging", "api_test", "excel", "config"}
@@ -44,6 +50,9 @@ HEADER_RE = re.compile(
44
50
 
45
51
 
46
52
  def _staged_files() -> list[str]:
53
+ injected = os.environ.get(STAGED_ENV)
54
+ if injected is not None:
55
+ return [line.strip() for line in injected.splitlines() if line.strip()]
47
56
  try:
48
57
  out = subprocess.run(
49
58
  ["git", "diff", "--cached", "--name-only"],
@@ -57,6 +66,8 @@ def _staged_files() -> list[str]:
57
66
  def _path_to_layer(path: str) -> str | None:
58
67
  """Map a repo path to a canonical scope layer, or None if unrecognized."""
59
68
  p = path.replace("\\", "/")
69
+ if p.startswith("dogfood/"):
70
+ return "dogfood"
60
71
  if p.startswith("packages/api_objects/"):
61
72
  return "api_objects"
62
73
  if p.startswith("packages/page_objects/"):
@@ -108,7 +119,7 @@ def main(argv: list[str]) -> int:
108
119
  return 1
109
120
 
110
121
  try:
111
- with open(argv[1], encoding="utf-8") as fh:
122
+ with open(argv[1], encoding="utf-8-sig") as fh: # tolerate a Windows editor BOM
112
123
  raw = fh.read()
113
124
  except OSError as exc:
114
125
  print(f"commit-msg: cannot read message file: {exc}", file=sys.stderr)
@@ -19,3 +19,6 @@ def test_dna_sync_and_check(tmp_path: Path):
19
19
  assert (tmp_path / "tools" / "git-hooks" / "commit-msg").is_file()
20
20
  assert (tmp_path / ".tuner-dna-version").is_file()
21
21
  assert main(["check", "--target", str(tmp_path)]) == 0
22
+ assert (tmp_path / ".cursor" / "agents" / "sut-self-learning.md").is_file()
23
+ assert (tmp_path / ".cursor" / "rules" / "agent-task-log.mdc").is_file()
24
+ assert (tmp_path / "docs" / "spec" / "agent-task-log.md").is_file()
@@ -32,6 +32,7 @@ SKELETON_DIRS: tuple[str, ...] = (
32
32
  "artifacts",
33
33
  "artifacts/evidence",
34
34
  "artifacts/catalogs",
35
+ "artifacts/inbox",
35
36
  )
36
37
 
37
38
  # Thin SUT files copied from this template (not the full kit runtime).
@@ -52,20 +53,19 @@ _STUB_FILES: tuple[str, ...] = (
52
53
  "packages/action_words/_internal/params.py",
53
54
  "apps/__init__.py",
54
55
  "behave.ini",
56
+ "data/sut-accounts.example.yaml",
55
57
  )
56
58
 
57
59
 
58
60
  def _stub_root() -> pathlib.Path | None:
59
61
  """Directory that contains thin SUT stub files (``config/env.py``, …).
60
62
 
61
- Wheel installs have no template checkout beside site-packages, and
62
- ``project_root()`` must not be used: scaffold is how a project is created.
63
+ ``init_repo/stubs/`` is the single source of truth for both editable and
64
+ wheel installs: the platform repo itself is **not** a workspace (its
65
+ workspace example lives in ``dogfood/``), so scaffold never copies from
66
+ the repo root. ``project_root()`` must not be used: scaffold is how a
67
+ project is created.
63
68
  """
64
- from tuner_testkit.project import template_source_root
65
-
66
- editable = template_source_root()
67
- if editable is not None:
68
- return editable
69
69
  bundled = pathlib.Path(__file__).resolve().parent / "stubs"
70
70
  if (bundled / "config" / "env.py").is_file():
71
71
  return bundled
@@ -5,6 +5,7 @@
5
5
  # 1. 本文件 DATABASES / TEST_* 占位
6
6
  # 2. config/env_overlay.py(可选,项目/试验田提交:额外别名与类型,仍无密钥)
7
7
  # 3. config/env_local.py(gitignore,本机真实 host/密码/账号)
8
+ # 探索登录优先读 data/sut-accounts.local.yaml(gitignore;模板 data/sut-accounts.example.yaml)
8
9
  # - 若定义了非空 ENVIRONMENTS:由 tuner_testkit.config 按激活名只套用那一套
9
10
  # (TUNER_ENV > config/.active_env > ACTIVE_ENV > 唯一 key)
10
11
  # - 否则按扁平 DATABASES / TEST_* 合并(旧写法)
@@ -0,0 +1,18 @@
1
+ # Copy to data/sut-accounts.local.yaml (gitignored) and fill real values.
2
+ # LLM explore reads the .local file; never commit passwords.
3
+
4
+ sut: example-app
5
+ ui_base_url: http://localhost:3000
6
+ api_base_url: http://localhost:8000
7
+ accounts:
8
+ - id: dogfood-admin
9
+ email: you@example.com
10
+ password: "replace-me"
11
+ notes: first-login onboarding / i18n caveats
12
+ workspace:
13
+ slug: demo
14
+ name: Demo
15
+ project:
16
+ identifier: DEMO
17
+ id: "00000000-0000-0000-0000-000000000000"
18
+ name: Demo
@@ -27,6 +27,9 @@ def test_scaffold_from_non_project_cwd(tmp_path: Path, monkeypatch):
27
27
  assert (dest / "config" / "env.py").is_file()
28
28
  assert (dest / "packages" / "action_words" / "__init__.py").is_file()
29
29
  assert (dest / ".cursor" / "rules").is_dir()
30
+ assert (dest / "artifacts" / "inbox").is_dir()
31
+ assert (dest / "data" / "sut-accounts.example.yaml").is_file()
32
+ assert "replace-me" in (dest / "data" / "sut-accounts.example.yaml").read_text(encoding="utf-8")
30
33
  assert any(line.startswith("copy config/env.py") for line in actions)
31
34
  assert any("dna sync (exit 0)" in line for line in actions)
32
35
 
@@ -43,5 +46,7 @@ def test_scaffold_uses_packaged_stubs_when_not_editable(tmp_path: Path, monkeypa
43
46
  assert (dest / "config" / "env.py").read_text(encoding="utf-8") == _STUB_ENV.read_text(
44
47
  encoding="utf-8"
45
48
  )
49
+ assert (dest / "artifacts" / "inbox").is_dir()
50
+ assert (dest / "data" / "sut-accounts.example.yaml").is_file()
46
51
  assert any(line.startswith("copy config/env.py") for line in actions)
47
52
  assert any("dna sync (exit 0)" in line for line in actions)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tuner-testkit
3
- Version: 4.3.0
3
+ Version: 4.4.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
@@ -210,4 +210,8 @@ uv sync --extra all
210
210
 
211
211
  `uv sync --extra dev` 与 `--extra all` 等价(`dev` 只是引用 `[all]`)。
212
212
 
213
+ 本仓是**平台仓**,不是 workspace。`dogfood/` 是用 `tuner-init scaffold dogfood --no-ai` 生成的 workspace 示范
214
+ (被测系统 = 平台本身,uv workspace 成员,共用 `.venv`):路线图在 `dogfood/assets/domain-notes/platform/roadmap.md`,
215
+ 验收活文档在 `dogfood/tests/features/`。见 [`dogfood/README.md`](dogfood/README.md)。
216
+
213
217
  4.3.0 发行说明见 [`docs/changelog/TEMPLATE-4.3.0.md`](docs/changelog/TEMPLATE-4.3.0.md);4.2.0 见 [`TEMPLATE-4.2.0.md`](docs/changelog/TEMPLATE-4.2.0.md);3.x → 4.x 迁移见 [`TEMPLATE-4.0.0.md`](docs/changelog/TEMPLATE-4.0.0.md)。平台能力地图见 [`INDEX.md`](INDEX.md)。
@@ -68,6 +68,7 @@ tuner_testkit/apps/dna/source.py
68
68
  tuner_testkit/apps/dna/dna_payload/AGENTS.md
69
69
  tuner_testkit/apps/dna/dna_payload/MANIFEST.txt
70
70
  tuner_testkit/apps/dna/dna_payload/docs/spec/action-words-syntax.md
71
+ tuner_testkit/apps/dna/dna_payload/docs/spec/agent-task-log.md
71
72
  tuner_testkit/apps/dna/dna_payload/docs/spec/api-objects-syntax.md
72
73
  tuner_testkit/apps/dna/dna_payload/docs/spec/apps-authoring-syntax.md
73
74
  tuner_testkit/apps/dna/dna_payload/docs/spec/assets-knowledge-syntax.md
@@ -106,6 +107,7 @@ tuner_testkit/apps/init_repo/scaffold.py
106
107
  tuner_testkit/apps/init_repo/stubs/behave.ini
107
108
  tuner_testkit/apps/init_repo/stubs/apps/__init__.py
108
109
  tuner_testkit/apps/init_repo/stubs/config/env.py
110
+ tuner_testkit/apps/init_repo/stubs/data/sut-accounts.example.yaml
109
111
  tuner_testkit/apps/init_repo/stubs/packages/__init__.py
110
112
  tuner_testkit/apps/init_repo/stubs/packages/action_words/__init__.py
111
113
  tuner_testkit/apps/init_repo/stubs/packages/action_words/models.py
File without changes
File without changes