atdd 0.7.2__tar.gz → 0.7.3__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 (216) hide show
  1. {atdd-0.7.2/src/atdd.egg-info → atdd-0.7.3}/PKG-INFO +1 -1
  2. {atdd-0.7.2 → atdd-0.7.3}/pyproject.toml +1 -1
  3. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/schemas/config.schema.json +26 -0
  4. atdd-0.7.3/src/atdd/coach/validators/test_session_archive_status.py +339 -0
  5. atdd-0.7.3/src/atdd/coach/validators/test_session_manifest_alignment.py +387 -0
  6. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/validators/test_session_validation.py +161 -0
  7. {atdd-0.7.2 → atdd-0.7.3/src/atdd.egg-info}/PKG-INFO +1 -1
  8. {atdd-0.7.2 → atdd-0.7.3}/src/atdd.egg-info/SOURCES.txt +2 -0
  9. {atdd-0.7.2 → atdd-0.7.3}/LICENSE +0 -0
  10. {atdd-0.7.2 → atdd-0.7.3}/README.md +0 -0
  11. {atdd-0.7.2 → atdd-0.7.3}/setup.cfg +0 -0
  12. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/__init__.py +0 -0
  13. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/__main__.py +0 -0
  14. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/cli.py +0 -0
  15. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/__init__.py +0 -0
  16. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/__init__.py +0 -0
  17. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/add_persistence_metadata.py +0 -0
  18. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/analyze_migrations.py +0 -0
  19. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/consumers.py +0 -0
  20. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/gate.py +0 -0
  21. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/infer_governance_status.py +0 -0
  22. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/initializer.py +0 -0
  23. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/interface.py +0 -0
  24. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/inventory.py +0 -0
  25. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/migration.py +0 -0
  26. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/registry.py +0 -0
  27. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/session.py +0 -0
  28. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/sync.py +0 -0
  29. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/test_interface.py +0 -0
  30. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/test_runner.py +0 -0
  31. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/tests/__init__.py +0 -0
  32. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/tests/test_telemetry_array_validation.py +0 -0
  33. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/commands/traceability.py +0 -0
  34. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/conventions/naming.convention.yaml +0 -0
  35. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/conventions/session.convention.yaml +0 -0
  36. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/overlays/__init__.py +0 -0
  37. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/overlays/claude.md +0 -0
  38. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/schemas/manifest.schema.json +0 -0
  39. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/templates/ATDD.md +0 -0
  40. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/templates/SESSION-TEMPLATE.md +0 -0
  41. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/utils/__init__.py +0 -0
  42. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/utils/config.py +0 -0
  43. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/utils/coverage_phase.py +0 -0
  44. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/utils/graph/__init__.py +0 -0
  45. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/utils/graph/urn.py +0 -0
  46. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/utils/locale_phase.py +0 -0
  47. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/utils/repo.py +0 -0
  48. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/utils/train_spec_phase.py +0 -0
  49. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/validators/__init__.py +0 -0
  50. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/validators/shared_fixtures.py +0 -0
  51. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/validators/test_enrich_wagon_registry.py +0 -0
  52. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/validators/test_registry.py +0 -0
  53. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/validators/test_release_versioning.py +0 -0
  54. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/validators/test_traceability.py +0 -0
  55. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/validators/test_train_registry.py +0 -0
  56. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/validators/test_update_feature_paths.py +0 -0
  57. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coach/validators/test_validate_contract_consumers.py +0 -0
  58. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/__init__.py +0 -0
  59. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/adapter.recipe.yaml +0 -0
  60. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/backend.convention.yaml +0 -0
  61. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/boundaries.convention.yaml +0 -0
  62. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/commons.convention.yaml +0 -0
  63. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/complexity.recipe.yaml +0 -0
  64. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/component-naming.convention.yaml +0 -0
  65. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/coverage.convention.yaml +0 -0
  66. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/design.convention.yaml +0 -0
  67. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/design.recipe.yaml +0 -0
  68. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/dto.convention.yaml +0 -0
  69. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/frontend.convention.yaml +0 -0
  70. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/green.convention.yaml +0 -0
  71. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/presentation.convention.yaml +0 -0
  72. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/refactor.convention.yaml +0 -0
  73. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/technology.convention.yaml +0 -0
  74. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/tests/__init__.py +0 -0
  75. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/tests/test_adapter_recipe.py +0 -0
  76. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/tests/test_complexity_recipe.py +0 -0
  77. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/tests/test_component_taxonomy.py +0 -0
  78. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/tests/test_component_urn_naming.py +0 -0
  79. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/tests/test_thinness_recipe.py +0 -0
  80. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/thinness.recipe.yaml +0 -0
  81. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/train.convention.yaml +0 -0
  82. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/conventions/verification.protocol.yaml +0 -0
  83. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/schemas/design_system.schema.json +0 -0
  84. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/__init__.py +0 -0
  85. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/conftest.py +0 -0
  86. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_commons_structure.py +0 -0
  87. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_complexity.py +0 -0
  88. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_cross_language_consistency.py +0 -0
  89. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_design_system_compliance.py +0 -0
  90. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_dto_testing_patterns.py +0 -0
  91. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_green_cross_stack_layers.py +0 -0
  92. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_green_layer_dependencies.py +0 -0
  93. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_green_python_layer_structure.py +0 -0
  94. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_green_supabase_layer_structure.py +0 -0
  95. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_hierarchy_coverage.py +0 -0
  96. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_i18n_runtime.py +0 -0
  97. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_import_boundaries.py +0 -0
  98. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_init_file_urns.py +0 -0
  99. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_preact_layer_boundaries.py +0 -0
  100. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_presentation_convention.py +0 -0
  101. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_python_architecture.py +0 -0
  102. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_quality_metrics.py +0 -0
  103. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_station_master_pattern.py +0 -0
  104. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_train_infrastructure.py +0 -0
  105. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_train_urns.py +0 -0
  106. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_typescript_architecture.py +0 -0
  107. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_usecase_structure.py +0 -0
  108. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/coder/validators/test_wagon_boundaries.py +0 -0
  109. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/conftest.py +0 -0
  110. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/__init__.py +0 -0
  111. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/conventions/acceptance.convention.yaml +0 -0
  112. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/conventions/appendix.convention.yaml +0 -0
  113. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/conventions/artifact-naming.convention.yaml +0 -0
  114. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/conventions/component.convention.yaml +0 -0
  115. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/conventions/coverage.convention.yaml +0 -0
  116. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/conventions/criteria.convention.yaml +0 -0
  117. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/conventions/feature.convention.yaml +0 -0
  118. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/conventions/interface.convention.yaml +0 -0
  119. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/conventions/steps.convention.yaml +0 -0
  120. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/conventions/train.convention.yaml +0 -0
  121. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/conventions/wagon.convention.yaml +0 -0
  122. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/conventions/wmbt.convention.yaml +0 -0
  123. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/schemas/acceptance.schema.json +0 -0
  124. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/schemas/appendix.schema.json +0 -0
  125. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/schemas/component.schema.json +0 -0
  126. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/schemas/feature.schema.json +0 -0
  127. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/schemas/train.schema.json +0 -0
  128. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/schemas/wagon.schema.json +0 -0
  129. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/schemas/wmbt.schema.json +0 -0
  130. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/validators/__init__.py +0 -0
  131. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/validators/conftest.py +0 -0
  132. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/validators/test_draft_wagon_registry.py +0 -0
  133. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/validators/test_hierarchy_coverage.py +0 -0
  134. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/validators/test_plan_cross_refs.py +0 -0
  135. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/validators/test_plan_uniqueness.py +0 -0
  136. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/validators/test_plan_urn_resolution.py +0 -0
  137. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/validators/test_plan_wagons.py +0 -0
  138. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/validators/test_train_validation.py +0 -0
  139. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/validators/test_wagon_urn_chain.py +0 -0
  140. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/validators/test_wmbt_consistency.py +0 -0
  141. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/planner/validators/test_wmbt_vocabulary.py +0 -0
  142. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/__init__.py +0 -0
  143. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/conventions/artifact.convention.yaml +0 -0
  144. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/conventions/contract.convention.yaml +0 -0
  145. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/conventions/coverage.convention.yaml +0 -0
  146. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/conventions/filename.convention.yaml +0 -0
  147. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/conventions/migration.convention.yaml +0 -0
  148. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/conventions/red.convention.yaml +0 -0
  149. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/conventions/routing.convention.yaml +0 -0
  150. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/conventions/security.convention.yaml +0 -0
  151. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/conventions/telemetry.convention.yaml +0 -0
  152. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/a11y.tmpl.json +0 -0
  153. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/artifact.schema.json +0 -0
  154. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/contract.schema.json +0 -0
  155. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/contract.tmpl.json +0 -0
  156. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/db.tmpl.json +0 -0
  157. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/e2e.tmpl.json +0 -0
  158. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/edge_function.tmpl.json +0 -0
  159. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/event.tmpl.json +0 -0
  160. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/http.tmpl.json +0 -0
  161. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/job.tmpl.json +0 -0
  162. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/load.tmpl.json +0 -0
  163. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/locale_manifest.schema.json +0 -0
  164. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/metric.tmpl.json +0 -0
  165. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/pack.schema.json +0 -0
  166. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/realtime.tmpl.json +0 -0
  167. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/rls.tmpl.json +0 -0
  168. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/script.tmpl.json +0 -0
  169. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/sec.tmpl.json +0 -0
  170. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/storage.tmpl.json +0 -0
  171. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/telemetry.schema.json +0 -0
  172. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/telemetry_tracking_manifest.schema.json +0 -0
  173. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/test_filename.schema.json +0 -0
  174. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/test_intent.schema.json +0 -0
  175. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/unit.tmpl.json +0 -0
  176. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/visual.tmpl.json +0 -0
  177. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/schemas/ws.tmpl.json +0 -0
  178. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/utils/__init__.py +0 -0
  179. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/utils/filename.py +0 -0
  180. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/__init__.py +0 -0
  181. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/cleanup_duplicate_headers.py +0 -0
  182. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/cleanup_duplicate_headers_v2.py +0 -0
  183. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/conftest.py +0 -0
  184. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/coverage_gap_report.py +0 -0
  185. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/fix_dual_ac_references.py +0 -0
  186. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/remove_duplicate_lines.py +0 -0
  187. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_acceptance_urn_filename_mapping.py +0 -0
  188. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_acceptance_urn_separator.py +0 -0
  189. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_artifact_naming_category.py +0 -0
  190. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_contract_schema_compliance.py +0 -0
  191. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_contract_security.py +0 -0
  192. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_contracts_structure.py +0 -0
  193. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_coverage_adequacy.py +0 -0
  194. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_dual_ac_reference.py +0 -0
  195. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_fixture_validity.py +0 -0
  196. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_hierarchy_coverage.py +0 -0
  197. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_isolation.py +0 -0
  198. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_locale_coverage.py +0 -0
  199. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_migration_coverage.py +0 -0
  200. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_migration_criteria.py +0 -0
  201. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_migration_generation.py +0 -0
  202. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_python_test_naming.py +0 -0
  203. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_red_layer_validation.py +0 -0
  204. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_red_python_layer_structure.py +0 -0
  205. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_red_supabase_layer_structure.py +0 -0
  206. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_telemetry_structure.py +0 -0
  207. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_train_backend_e2e.py +0 -0
  208. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_train_frontend_e2e.py +0 -0
  209. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_train_frontend_python.py +0 -0
  210. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_typescript_test_naming.py +0 -0
  211. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/tester/validators/test_typescript_test_structure.py +0 -0
  212. {atdd-0.7.2 → atdd-0.7.3}/src/atdd/version_check.py +0 -0
  213. {atdd-0.7.2 → atdd-0.7.3}/src/atdd.egg-info/dependency_links.txt +0 -0
  214. {atdd-0.7.2 → atdd-0.7.3}/src/atdd.egg-info/entry_points.txt +0 -0
  215. {atdd-0.7.2 → atdd-0.7.3}/src/atdd.egg-info/requires.txt +0 -0
  216. {atdd-0.7.2 → atdd-0.7.3}/src/atdd.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: atdd
3
- Version: 0.7.2
3
+ Version: 0.7.3
4
4
  Summary: ATDD Platform - Acceptance Test Driven Development toolkit
5
5
  License: MIT
6
6
  Requires-Python: >=3.10
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "atdd"
7
- version = "0.7.2"
7
+ version = "0.7.3"
8
8
  description = "ATDD Platform - Acceptance Test Driven Development toolkit"
9
9
  requires-python = ">=3.10"
10
10
  readme = "README.md"
@@ -132,6 +132,32 @@
132
132
  }
133
133
  },
134
134
  "additionalProperties": false
135
+ },
136
+ "coach": {
137
+ "type": "object",
138
+ "description": "Coach agent validation settings",
139
+ "properties": {
140
+ "session_gate_command_prefixes": {
141
+ "type": "array",
142
+ "description": "Allowed prefixes for gate commands in session files",
143
+ "items": {"type": "string"},
144
+ "default": ["atdd", "pytest", "python", "npm", "supabase"],
145
+ "examples": [["atdd", "pytest", "npm run test"]]
146
+ },
147
+ "session_gate_command_exceptions": {
148
+ "type": "array",
149
+ "description": "Session files exempt from gate command prefix validation (by filename pattern)",
150
+ "items": {"type": "string"},
151
+ "default": [],
152
+ "examples": [["SESSION-00-*.md", "SESSION-01-legacy.md"]]
153
+ },
154
+ "archive_status_warnings": {
155
+ "type": "boolean",
156
+ "description": "Warn when COMPLETE sessions not in archive or archived sessions not COMPLETE",
157
+ "default": true
158
+ }
159
+ },
160
+ "additionalProperties": false
135
161
  }
136
162
  },
137
163
  "required": ["version", "release"],
@@ -0,0 +1,339 @@
1
+ """
2
+ Session archive status validation.
3
+
4
+ Validates archive placement aligns with session status:
5
+ 1. COMPLETE sessions should be in archive/ (warning)
6
+ 2. Sessions in archive/ should be COMPLETE or OBSOLETE (warning)
7
+
8
+ These are warnings, not failures, to allow migration flexibility.
9
+
10
+ Convention: src/atdd/coach/conventions/session.convention.yaml
11
+ Config: .atdd/config.yaml (coach.archive_status_warnings)
12
+
13
+ Run: atdd validate coach
14
+ """
15
+ import pytest
16
+ import yaml
17
+ import fnmatch
18
+ from pathlib import Path
19
+ from typing import Dict, List, Any, Optional
20
+
21
+ from atdd.coach.utils.repo import find_repo_root
22
+ from atdd.coach.utils.config import load_atdd_config
23
+
24
+
25
+ # ============================================================================
26
+ # Configuration
27
+ # ============================================================================
28
+
29
+ REPO_ROOT = find_repo_root()
30
+ SESSIONS_DIR = REPO_ROOT / "atdd-sessions"
31
+ ARCHIVE_DIR = SESSIONS_DIR / "archive"
32
+
33
+ # Terminal statuses that should be archived
34
+ ARCHIVABLE_STATUSES = {"COMPLETE", "OBSOLETE"}
35
+
36
+
37
+ # ============================================================================
38
+ # Fixtures
39
+ # ============================================================================
40
+
41
+ @pytest.fixture
42
+ def config() -> Dict[str, Any]:
43
+ """Load ATDD configuration."""
44
+ return load_atdd_config(REPO_ROOT)
45
+
46
+
47
+ @pytest.fixture
48
+ def archive_warnings_enabled(config: Dict[str, Any]) -> bool:
49
+ """Check if archive status warnings are enabled."""
50
+ return config.get("coach", {}).get("archive_status_warnings", True)
51
+
52
+
53
+ @pytest.fixture
54
+ def session_files() -> List[Path]:
55
+ """Get all session files in main directory (not archive)."""
56
+ if not SESSIONS_DIR.exists():
57
+ return []
58
+
59
+ return sorted([
60
+ f for f in SESSIONS_DIR.glob("SESSION-*.md")
61
+ if f.name != "SESSION-TEMPLATE.md"
62
+ ])
63
+
64
+
65
+ @pytest.fixture
66
+ def archived_files() -> List[Path]:
67
+ """Get all session files in archive directory."""
68
+ if not ARCHIVE_DIR.exists():
69
+ return []
70
+
71
+ return sorted(ARCHIVE_DIR.glob("SESSION-*.md"))
72
+
73
+
74
+ def parse_session_status(path: Path) -> Optional[str]:
75
+ """Parse status from session file frontmatter."""
76
+ content = path.read_text()
77
+
78
+ if not content.startswith("---"):
79
+ return None
80
+
81
+ parts = content.split("---", 2)
82
+ if len(parts) < 3:
83
+ return None
84
+
85
+ try:
86
+ frontmatter = yaml.safe_load(parts[1])
87
+ status = str(frontmatter.get("status", "")).upper()
88
+ # Handle status with extra info (e.g., "ACTIVE - working")
89
+ return status.split()[0] if status else None
90
+ except yaml.YAMLError:
91
+ return None
92
+
93
+
94
+ # ============================================================================
95
+ # Archive Status Validation Tests
96
+ # ============================================================================
97
+
98
+ @pytest.mark.coach
99
+ def test_complete_sessions_should_be_archived(
100
+ session_files: List[Path],
101
+ archive_warnings_enabled: bool
102
+ ):
103
+ """
104
+ SPEC-COACH-ARCHIVE-001: COMPLETE sessions should be in archive/
105
+
106
+ Given: Session files in main directory
107
+ When: Checking status
108
+ Then: Sessions with COMPLETE/OBSOLETE status should be in archive/
109
+
110
+ Note: This is a warning, not a failure, to allow migration flexibility.
111
+ """
112
+ if not archive_warnings_enabled:
113
+ pytest.skip("Archive status warnings disabled in config")
114
+
115
+ if not session_files:
116
+ pytest.skip("No session files found")
117
+
118
+ should_archive = []
119
+
120
+ for path in session_files:
121
+ status = parse_session_status(path)
122
+ if status in ARCHIVABLE_STATUSES:
123
+ should_archive.append(f"{path.name} (status: {status})")
124
+
125
+ if should_archive:
126
+ print(
127
+ f"\n⚠️ Found {len(should_archive)} completed sessions not in archive/:\n" +
128
+ "\n".join(f" - {s}" for s in should_archive) +
129
+ "\n\nConsider running 'atdd session archive <id>' to move them."
130
+ )
131
+
132
+
133
+ @pytest.mark.coach
134
+ def test_archived_sessions_should_be_complete(
135
+ archived_files: List[Path],
136
+ archive_warnings_enabled: bool
137
+ ):
138
+ """
139
+ SPEC-COACH-ARCHIVE-002: Archived sessions should have COMPLETE/OBSOLETE status
140
+
141
+ Given: Session files in archive/ directory
142
+ When: Checking status
143
+ Then: All archived sessions should have terminal status
144
+
145
+ Note: This is a warning, not a failure, to allow migration flexibility.
146
+ """
147
+ if not archive_warnings_enabled:
148
+ pytest.skip("Archive status warnings disabled in config")
149
+
150
+ if not archived_files:
151
+ pytest.skip("No archived session files found")
152
+
153
+ not_complete = []
154
+
155
+ for path in archived_files:
156
+ status = parse_session_status(path)
157
+ if status and status not in ARCHIVABLE_STATUSES:
158
+ not_complete.append(f"{path.name} (status: {status})")
159
+
160
+ if not_complete:
161
+ print(
162
+ f"\n⚠️ Found {len(not_complete)} archived sessions without terminal status:\n" +
163
+ "\n".join(f" - {s}" for s in not_complete) +
164
+ "\n\nEither update status to COMPLETE/OBSOLETE or move back to atdd-sessions/."
165
+ )
166
+
167
+
168
+ @pytest.mark.coach
169
+ def test_archive_directory_structure():
170
+ """
171
+ SPEC-COACH-ARCHIVE-003: Archive directory exists if sessions directory exists
172
+
173
+ Given: atdd-sessions/ directory exists
174
+ When: Checking for archive/ subdirectory
175
+ Then: archive/ directory should exist (create if missing)
176
+ """
177
+ if not SESSIONS_DIR.exists():
178
+ pytest.skip("Sessions directory not found")
179
+
180
+ if not ARCHIVE_DIR.exists():
181
+ print(
182
+ f"\n⚠️ Archive directory does not exist: {ARCHIVE_DIR}\n"
183
+ "Consider creating it: mkdir -p atdd-sessions/archive/"
184
+ )
185
+
186
+
187
+ # ============================================================================
188
+ # Stale Session Detection
189
+ # ============================================================================
190
+
191
+ @pytest.mark.coach
192
+ def test_stale_active_sessions(session_files: List[Path]):
193
+ """
194
+ SPEC-COACH-ARCHIVE-004: Detect potentially stale ACTIVE sessions
195
+
196
+ Given: Session files with ACTIVE status
197
+ When: Checking file modification time
198
+ Then: Warn about sessions not modified in 7+ days
199
+ """
200
+ if not session_files:
201
+ pytest.skip("No session files found")
202
+
203
+ from datetime import datetime, timedelta
204
+
205
+ stale_threshold = timedelta(days=7)
206
+ now = datetime.now()
207
+ stale = []
208
+
209
+ for path in session_files:
210
+ status = parse_session_status(path)
211
+ if status != "ACTIVE":
212
+ continue
213
+
214
+ mtime = datetime.fromtimestamp(path.stat().st_mtime)
215
+ age = now - mtime
216
+
217
+ if age > stale_threshold:
218
+ days = age.days
219
+ stale.append(f"{path.name} (last modified {days} days ago)")
220
+
221
+ if stale:
222
+ print(
223
+ f"\n⚠️ Found {len(stale)} potentially stale ACTIVE sessions:\n" +
224
+ "\n".join(f" - {s}" for s in stale) +
225
+ "\n\nConsider updating status to BLOCKED, COMPLETE, or OBSOLETE."
226
+ )
227
+
228
+
229
+ @pytest.mark.coach
230
+ def test_blocked_sessions_have_reason(session_files: List[Path]):
231
+ """
232
+ SPEC-COACH-ARCHIVE-005: BLOCKED sessions should document reason
233
+
234
+ Given: Session files with BLOCKED status
235
+ When: Checking session log
236
+ Then: Most recent log entry should explain the blocker
237
+ """
238
+ if not session_files:
239
+ pytest.skip("No session files found")
240
+
241
+ import re
242
+
243
+ missing_reason = []
244
+
245
+ for path in session_files:
246
+ status = parse_session_status(path)
247
+ if status != "BLOCKED":
248
+ continue
249
+
250
+ content = path.read_text()
251
+
252
+ # Check for Blocked: section in session log
253
+ has_blocked_entry = bool(re.search(
254
+ r"\*\*Blocked:\*\*\s*\n\s*-\s*\S",
255
+ content
256
+ ))
257
+
258
+ # Or check frontmatter for blocker field
259
+ if content.startswith("---"):
260
+ parts = content.split("---", 2)
261
+ if len(parts) >= 3:
262
+ try:
263
+ frontmatter = yaml.safe_load(parts[1])
264
+ has_blocked_entry = has_blocked_entry or bool(
265
+ frontmatter.get("blocker") or
266
+ frontmatter.get("blocked_by") or
267
+ frontmatter.get("blocked_reason")
268
+ )
269
+ except yaml.YAMLError:
270
+ pass
271
+
272
+ if not has_blocked_entry:
273
+ missing_reason.append(path.name)
274
+
275
+ if missing_reason:
276
+ print(
277
+ f"\n⚠️ Found {len(missing_reason)} BLOCKED sessions without documented reason:\n" +
278
+ "\n".join(f" - {m}" for m in missing_reason) +
279
+ "\n\nAdd **Blocked:** entry to Session Log or 'blocker' field to frontmatter."
280
+ )
281
+
282
+
283
+ # ============================================================================
284
+ # Summary
285
+ # ============================================================================
286
+
287
+ @pytest.mark.coach
288
+ def test_archive_status_summary(
289
+ session_files: List[Path],
290
+ archived_files: List[Path]
291
+ ):
292
+ """
293
+ Generate archive status summary.
294
+
295
+ This test always passes but prints a summary.
296
+ """
297
+ print("\n" + "=" * 60)
298
+ print("SESSION ARCHIVE STATUS SUMMARY")
299
+ print("=" * 60)
300
+
301
+ # Count by status in main directory
302
+ main_statuses: Dict[str, int] = {}
303
+ for path in session_files:
304
+ status = parse_session_status(path) or "UNKNOWN"
305
+ main_statuses[status] = main_statuses.get(status, 0) + 1
306
+
307
+ # Count by status in archive
308
+ archive_statuses: Dict[str, int] = {}
309
+ for path in archived_files:
310
+ status = parse_session_status(path) or "UNKNOWN"
311
+ archive_statuses[status] = archive_statuses.get(status, 0) + 1
312
+
313
+ print(f"\nMain directory ({len(session_files)} files):")
314
+ for status, count in sorted(main_statuses.items()):
315
+ marker = "⚠️ " if status in ARCHIVABLE_STATUSES else " "
316
+ print(f" {marker}{status}: {count}")
317
+
318
+ print(f"\nArchive directory ({len(archived_files)} files):")
319
+ for status, count in sorted(archive_statuses.items()):
320
+ marker = "⚠️ " if status not in ARCHIVABLE_STATUSES else " "
321
+ print(f" {marker}{status}: {count}")
322
+
323
+ # Summary advice
324
+ main_archivable = sum(
325
+ main_statuses.get(s, 0) for s in ARCHIVABLE_STATUSES
326
+ )
327
+ archive_active = sum(
328
+ archive_statuses.get(s, 0) for s in archive_statuses
329
+ if s not in ARCHIVABLE_STATUSES
330
+ )
331
+
332
+ if main_archivable > 0 or archive_active > 0:
333
+ print("\n⚠️ Recommendations:")
334
+ if main_archivable > 0:
335
+ print(f" - Archive {main_archivable} completed session(s)")
336
+ if archive_active > 0:
337
+ print(f" - Review {archive_active} non-terminal archived session(s)")
338
+
339
+ print("\n" + "=" * 60)