atdd 0.6.1__tar.gz → 0.7.1__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 (213) hide show
  1. {atdd-0.6.1/src/atdd.egg-info → atdd-0.7.1}/PKG-INFO +1 -1
  2. {atdd-0.6.1 → atdd-0.7.1}/pyproject.toml +3 -1
  3. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/inventory.py +10 -3
  4. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/schemas/config.schema.json +11 -0
  5. atdd-0.7.1/src/atdd/coach/utils/locale_phase.py +97 -0
  6. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/validators/shared_fixtures.py +49 -0
  7. atdd-0.7.1/src/atdd/coder/validators/test_i18n_runtime.py +171 -0
  8. atdd-0.7.1/src/atdd/tester/schemas/locale_manifest.schema.json +53 -0
  9. atdd-0.7.1/src/atdd/tester/validators/test_locale_coverage.py +451 -0
  10. {atdd-0.6.1 → atdd-0.7.1/src/atdd.egg-info}/PKG-INFO +1 -1
  11. {atdd-0.6.1 → atdd-0.7.1}/src/atdd.egg-info/SOURCES.txt +4 -0
  12. {atdd-0.6.1 → atdd-0.7.1}/LICENSE +0 -0
  13. {atdd-0.6.1 → atdd-0.7.1}/README.md +0 -0
  14. {atdd-0.6.1 → atdd-0.7.1}/setup.cfg +0 -0
  15. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/__init__.py +0 -0
  16. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/__main__.py +0 -0
  17. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/cli.py +0 -0
  18. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/__init__.py +0 -0
  19. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/__init__.py +0 -0
  20. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/add_persistence_metadata.py +0 -0
  21. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/analyze_migrations.py +0 -0
  22. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/consumers.py +0 -0
  23. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/gate.py +0 -0
  24. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/infer_governance_status.py +0 -0
  25. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/initializer.py +0 -0
  26. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/interface.py +0 -0
  27. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/migration.py +0 -0
  28. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/registry.py +0 -0
  29. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/session.py +0 -0
  30. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/sync.py +0 -0
  31. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/test_interface.py +0 -0
  32. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/test_runner.py +0 -0
  33. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/tests/__init__.py +0 -0
  34. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/tests/test_telemetry_array_validation.py +0 -0
  35. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/commands/traceability.py +0 -0
  36. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/conventions/session.convention.yaml +0 -0
  37. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/overlays/__init__.py +0 -0
  38. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/overlays/claude.md +0 -0
  39. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/schemas/manifest.schema.json +0 -0
  40. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/templates/ATDD.md +0 -0
  41. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/templates/SESSION-TEMPLATE.md +0 -0
  42. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/utils/__init__.py +0 -0
  43. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/utils/config.py +0 -0
  44. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/utils/coverage_phase.py +0 -0
  45. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/utils/graph/__init__.py +0 -0
  46. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/utils/graph/urn.py +0 -0
  47. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/utils/repo.py +0 -0
  48. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/utils/train_spec_phase.py +0 -0
  49. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/validators/__init__.py +0 -0
  50. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/validators/test_enrich_wagon_registry.py +0 -0
  51. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/validators/test_registry.py +0 -0
  52. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/validators/test_release_versioning.py +0 -0
  53. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/validators/test_session_validation.py +0 -0
  54. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/validators/test_traceability.py +0 -0
  55. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/validators/test_train_registry.py +0 -0
  56. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/validators/test_update_feature_paths.py +0 -0
  57. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coach/validators/test_validate_contract_consumers.py +0 -0
  58. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/__init__.py +0 -0
  59. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/adapter.recipe.yaml +0 -0
  60. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/backend.convention.yaml +0 -0
  61. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/boundaries.convention.yaml +0 -0
  62. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/commons.convention.yaml +0 -0
  63. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/complexity.recipe.yaml +0 -0
  64. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/component-naming.convention.yaml +0 -0
  65. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/coverage.convention.yaml +0 -0
  66. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/design.convention.yaml +0 -0
  67. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/design.recipe.yaml +0 -0
  68. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/dto.convention.yaml +0 -0
  69. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/frontend.convention.yaml +0 -0
  70. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/green.convention.yaml +0 -0
  71. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/presentation.convention.yaml +0 -0
  72. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/refactor.convention.yaml +0 -0
  73. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/technology.convention.yaml +0 -0
  74. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/tests/__init__.py +0 -0
  75. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/tests/test_adapter_recipe.py +0 -0
  76. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/tests/test_complexity_recipe.py +0 -0
  77. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/tests/test_component_taxonomy.py +0 -0
  78. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/tests/test_component_urn_naming.py +0 -0
  79. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/tests/test_thinness_recipe.py +0 -0
  80. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/thinness.recipe.yaml +0 -0
  81. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/train.convention.yaml +0 -0
  82. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/conventions/verification.protocol.yaml +0 -0
  83. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/schemas/design_system.schema.json +0 -0
  84. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/__init__.py +0 -0
  85. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/conftest.py +0 -0
  86. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_commons_structure.py +0 -0
  87. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_complexity.py +0 -0
  88. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_cross_language_consistency.py +0 -0
  89. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_design_system_compliance.py +0 -0
  90. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_dto_testing_patterns.py +0 -0
  91. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_green_cross_stack_layers.py +0 -0
  92. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_green_layer_dependencies.py +0 -0
  93. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_green_python_layer_structure.py +0 -0
  94. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_green_supabase_layer_structure.py +0 -0
  95. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_hierarchy_coverage.py +0 -0
  96. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_import_boundaries.py +0 -0
  97. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_init_file_urns.py +0 -0
  98. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_preact_layer_boundaries.py +0 -0
  99. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_presentation_convention.py +0 -0
  100. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_python_architecture.py +0 -0
  101. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_quality_metrics.py +0 -0
  102. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_station_master_pattern.py +0 -0
  103. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_train_infrastructure.py +0 -0
  104. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_train_urns.py +0 -0
  105. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_typescript_architecture.py +0 -0
  106. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_usecase_structure.py +0 -0
  107. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/coder/validators/test_wagon_boundaries.py +0 -0
  108. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/conftest.py +0 -0
  109. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/__init__.py +0 -0
  110. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/conventions/acceptance.convention.yaml +0 -0
  111. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/conventions/appendix.convention.yaml +0 -0
  112. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/conventions/artifact-naming.convention.yaml +0 -0
  113. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/conventions/component.convention.yaml +0 -0
  114. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/conventions/coverage.convention.yaml +0 -0
  115. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/conventions/criteria.convention.yaml +0 -0
  116. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/conventions/feature.convention.yaml +0 -0
  117. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/conventions/interface.convention.yaml +0 -0
  118. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/conventions/steps.convention.yaml +0 -0
  119. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/conventions/train.convention.yaml +0 -0
  120. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/conventions/wagon.convention.yaml +0 -0
  121. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/conventions/wmbt.convention.yaml +0 -0
  122. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/schemas/acceptance.schema.json +0 -0
  123. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/schemas/appendix.schema.json +0 -0
  124. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/schemas/component.schema.json +0 -0
  125. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/schemas/feature.schema.json +0 -0
  126. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/schemas/train.schema.json +0 -0
  127. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/schemas/wagon.schema.json +0 -0
  128. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/schemas/wmbt.schema.json +0 -0
  129. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/validators/__init__.py +0 -0
  130. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/validators/conftest.py +0 -0
  131. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/validators/test_draft_wagon_registry.py +0 -0
  132. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/validators/test_hierarchy_coverage.py +0 -0
  133. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/validators/test_plan_cross_refs.py +0 -0
  134. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/validators/test_plan_uniqueness.py +0 -0
  135. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/validators/test_plan_urn_resolution.py +0 -0
  136. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/validators/test_plan_wagons.py +0 -0
  137. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/validators/test_train_validation.py +0 -0
  138. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/validators/test_wagon_urn_chain.py +0 -0
  139. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/validators/test_wmbt_consistency.py +0 -0
  140. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/planner/validators/test_wmbt_vocabulary.py +0 -0
  141. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/__init__.py +0 -0
  142. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/conventions/artifact.convention.yaml +0 -0
  143. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/conventions/contract.convention.yaml +0 -0
  144. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/conventions/coverage.convention.yaml +0 -0
  145. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/conventions/filename.convention.yaml +0 -0
  146. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/conventions/migration.convention.yaml +0 -0
  147. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/conventions/red.convention.yaml +0 -0
  148. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/conventions/routing.convention.yaml +0 -0
  149. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/conventions/security.convention.yaml +0 -0
  150. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/conventions/telemetry.convention.yaml +0 -0
  151. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/a11y.tmpl.json +0 -0
  152. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/artifact.schema.json +0 -0
  153. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/contract.schema.json +0 -0
  154. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/contract.tmpl.json +0 -0
  155. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/db.tmpl.json +0 -0
  156. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/e2e.tmpl.json +0 -0
  157. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/edge_function.tmpl.json +0 -0
  158. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/event.tmpl.json +0 -0
  159. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/http.tmpl.json +0 -0
  160. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/job.tmpl.json +0 -0
  161. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/load.tmpl.json +0 -0
  162. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/metric.tmpl.json +0 -0
  163. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/pack.schema.json +0 -0
  164. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/realtime.tmpl.json +0 -0
  165. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/rls.tmpl.json +0 -0
  166. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/script.tmpl.json +0 -0
  167. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/sec.tmpl.json +0 -0
  168. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/storage.tmpl.json +0 -0
  169. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/telemetry.schema.json +0 -0
  170. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/telemetry_tracking_manifest.schema.json +0 -0
  171. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/test_filename.schema.json +0 -0
  172. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/test_intent.schema.json +0 -0
  173. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/unit.tmpl.json +0 -0
  174. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/visual.tmpl.json +0 -0
  175. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/schemas/ws.tmpl.json +0 -0
  176. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/utils/__init__.py +0 -0
  177. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/utils/filename.py +0 -0
  178. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/__init__.py +0 -0
  179. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/cleanup_duplicate_headers.py +0 -0
  180. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/cleanup_duplicate_headers_v2.py +0 -0
  181. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/conftest.py +0 -0
  182. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/coverage_gap_report.py +0 -0
  183. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/fix_dual_ac_references.py +0 -0
  184. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/remove_duplicate_lines.py +0 -0
  185. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_acceptance_urn_filename_mapping.py +0 -0
  186. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_acceptance_urn_separator.py +0 -0
  187. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_artifact_naming_category.py +0 -0
  188. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_contract_schema_compliance.py +0 -0
  189. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_contract_security.py +0 -0
  190. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_contracts_structure.py +0 -0
  191. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_coverage_adequacy.py +0 -0
  192. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_dual_ac_reference.py +0 -0
  193. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_fixture_validity.py +0 -0
  194. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_hierarchy_coverage.py +0 -0
  195. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_isolation.py +0 -0
  196. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_migration_coverage.py +0 -0
  197. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_migration_criteria.py +0 -0
  198. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_migration_generation.py +0 -0
  199. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_python_test_naming.py +0 -0
  200. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_red_layer_validation.py +0 -0
  201. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_red_python_layer_structure.py +0 -0
  202. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_red_supabase_layer_structure.py +0 -0
  203. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_telemetry_structure.py +0 -0
  204. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_train_backend_e2e.py +0 -0
  205. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_train_frontend_e2e.py +0 -0
  206. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_train_frontend_python.py +0 -0
  207. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_typescript_test_naming.py +0 -0
  208. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/tester/validators/test_typescript_test_structure.py +0 -0
  209. {atdd-0.6.1 → atdd-0.7.1}/src/atdd/version_check.py +0 -0
  210. {atdd-0.6.1 → atdd-0.7.1}/src/atdd.egg-info/dependency_links.txt +0 -0
  211. {atdd-0.6.1 → atdd-0.7.1}/src/atdd.egg-info/entry_points.txt +0 -0
  212. {atdd-0.6.1 → atdd-0.7.1}/src/atdd.egg-info/requires.txt +0 -0
  213. {atdd-0.6.1 → atdd-0.7.1}/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.6.1
3
+ Version: 0.7.1
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.6.1"
7
+ version = "0.7.1"
8
8
  description = "ATDD Platform - Acceptance Test Driven Development toolkit"
9
9
  requires-python = ">=3.10"
10
10
  readme = "README.md"
@@ -39,4 +39,6 @@ markers = [
39
39
  "tester: marks tests as tester validators",
40
40
  "platform: marks tests as platform validators",
41
41
  "security: marks tests as security validators",
42
+ "locale: marks tests as localization validators (Localization Manifest Spec v1)",
43
+ "coder: marks tests as coder phase validators",
42
44
  ]
@@ -148,9 +148,16 @@ class RepositoryInventory:
148
148
  by_theme[theme] += 1
149
149
 
150
150
  # Gap analysis
151
- expectations = train.get("expectations", {})
152
- test_fields = train.get("test", {})
153
- code_fields = train.get("code", {})
151
+ expectations = train.get("expectations")
152
+ test_fields = train.get("test")
153
+ code_fields = train.get("code")
154
+
155
+ if not isinstance(expectations, dict):
156
+ expectations = {}
157
+ if test_fields is None:
158
+ test_fields = {}
159
+ if code_fields is None:
160
+ code_fields = {}
154
161
 
155
162
  # Normalize test/code to dict form
156
163
  if isinstance(test_fields, str):
@@ -121,6 +121,17 @@
121
121
  }
122
122
  },
123
123
  "additionalProperties": false
124
+ },
125
+ "localization": {
126
+ "type": "object",
127
+ "description": "Localization validation settings (Localization Manifest Spec v1)",
128
+ "properties": {
129
+ "manifest": {
130
+ "type": "string",
131
+ "description": "Path to localization manifest.json relative to repo root (e.g., web/locales/manifest.json)"
132
+ }
133
+ },
134
+ "additionalProperties": false
124
135
  }
125
136
  },
126
137
  "required": ["version", "release"],
@@ -0,0 +1,97 @@
1
+ """
2
+ Localization Manifest Spec v1 Rollout Phase Controller.
3
+
4
+ Manages the phased rollout of localization validation rules:
5
+ - Phase 1 (WARNINGS_ONLY): All validators emit warnings only
6
+ - Phase 2 (TESTER_ENFORCEMENT): Tester phase validators (LOCALE-TEST-*) strict
7
+ - Phase 3 (FULL_ENFORCEMENT): All validators including Coder (LOCALE-CODE-*) strict
8
+
9
+ Usage in validators:
10
+ from atdd.coach.utils.locale_phase import LocalePhase, should_enforce_locale
11
+
12
+ if should_enforce_locale(LocalePhase.TESTER_ENFORCEMENT):
13
+ assert condition, "Error message"
14
+ else:
15
+ if not condition:
16
+ emit_locale_warning("LOCALE-TEST-1.1", "Warning message", LocalePhase.TESTER_ENFORCEMENT)
17
+ """
18
+
19
+ from enum import IntEnum
20
+ from typing import Optional
21
+ import warnings
22
+
23
+
24
+ class LocalePhase(IntEnum):
25
+ """
26
+ Rollout phases for Localization Manifest Spec v1.
27
+
28
+ Phases are ordered by strictness level:
29
+ - WARNINGS_ONLY (1): All new validators emit warnings, no assertions
30
+ - TESTER_ENFORCEMENT (2): Tester phase validators (LOCALE-TEST-*) strict
31
+ - FULL_ENFORCEMENT (3): All validators including Coder (LOCALE-CODE-*) strict
32
+ """
33
+ WARNINGS_ONLY = 1
34
+ TESTER_ENFORCEMENT = 2
35
+ FULL_ENFORCEMENT = 3
36
+
37
+
38
+ # Current rollout phase - update this to advance through phases
39
+ CURRENT_LOCALE_PHASE = LocalePhase.WARNINGS_ONLY
40
+
41
+
42
+ def should_enforce_locale(validator_phase: LocalePhase) -> bool:
43
+ """
44
+ Check if a locale validator should enforce strict mode.
45
+
46
+ Args:
47
+ validator_phase: The phase at which this validator becomes strict
48
+
49
+ Returns:
50
+ True if current phase >= validator_phase (should enforce)
51
+ False if current phase < validator_phase (should warn only)
52
+
53
+ Example:
54
+ # This validator becomes strict in Phase 2
55
+ if should_enforce_locale(LocalePhase.TESTER_ENFORCEMENT):
56
+ assert all_keys_match, "Keys must match reference locale"
57
+ else:
58
+ if not all_keys_match:
59
+ emit_locale_warning("LOCALE-TEST-1.4", "Keys don't match", LocalePhase.TESTER_ENFORCEMENT)
60
+ """
61
+ return CURRENT_LOCALE_PHASE >= validator_phase
62
+
63
+
64
+ def get_current_locale_phase() -> LocalePhase:
65
+ """Get the current locale rollout phase."""
66
+ return CURRENT_LOCALE_PHASE
67
+
68
+
69
+ def get_locale_phase_name(phase: Optional[LocalePhase] = None) -> str:
70
+ """Get human-readable name for a locale phase."""
71
+ phase = phase or CURRENT_LOCALE_PHASE
72
+ return {
73
+ LocalePhase.WARNINGS_ONLY: "Phase 1: Warnings Only",
74
+ LocalePhase.TESTER_ENFORCEMENT: "Phase 2: Tester Enforcement",
75
+ LocalePhase.FULL_ENFORCEMENT: "Phase 3: Full Enforcement",
76
+ }.get(phase, "Unknown Phase")
77
+
78
+
79
+ def emit_locale_warning(
80
+ spec_id: str,
81
+ message: str,
82
+ validator_phase: LocalePhase = LocalePhase.TESTER_ENFORCEMENT
83
+ ) -> None:
84
+ """
85
+ Emit a locale validation warning with phase context.
86
+
87
+ Args:
88
+ spec_id: The SPEC ID (e.g., "LOCALE-TEST-1.1")
89
+ message: The warning message
90
+ validator_phase: Phase when this becomes an error
91
+ """
92
+ phase_name = get_locale_phase_name(validator_phase)
93
+ warnings.warn(
94
+ f"[{spec_id}] {message} (will become error in {phase_name})",
95
+ category=UserWarning,
96
+ stacklevel=3
97
+ )
@@ -599,3 +599,52 @@ def wagon_to_train_mapping(train_files: List[Tuple[Path, Dict]]) -> Dict[str, Li
599
599
  mapping[wagon_slug].append(train_id)
600
600
 
601
601
  return mapping
602
+
603
+
604
+ # ============================================================================
605
+ # LOCALIZATION FIXTURES (Localization Manifest Spec v1)
606
+ # ============================================================================
607
+
608
+
609
+ @pytest.fixture(scope="module")
610
+ def locale_manifest_path(atdd_config: Dict[str, Any]) -> Optional[Path]:
611
+ """
612
+ Get path to localization manifest file from config.
613
+
614
+ Returns:
615
+ Path to manifest file, or None if localization not configured
616
+ """
617
+ manifest_rel = atdd_config.get("localization", {}).get("manifest")
618
+ if not manifest_rel:
619
+ return None
620
+ return REPO_ROOT / manifest_rel
621
+
622
+
623
+ @pytest.fixture(scope="module")
624
+ def locale_manifest(locale_manifest_path: Optional[Path]) -> Optional[Dict[str, Any]]:
625
+ """
626
+ Load localization manifest from configured path.
627
+
628
+ Returns:
629
+ Manifest dict with reference, locales, namespaces, or None if not configured
630
+ """
631
+ if locale_manifest_path is None:
632
+ return None
633
+ if not locale_manifest_path.exists():
634
+ return None
635
+
636
+ with open(locale_manifest_path) as f:
637
+ return json.load(f)
638
+
639
+
640
+ @pytest.fixture(scope="module")
641
+ def locales_dir(locale_manifest_path: Optional[Path]) -> Optional[Path]:
642
+ """
643
+ Get locales directory (parent of manifest file).
644
+
645
+ Returns:
646
+ Path to locales directory, or None if not configured
647
+ """
648
+ if locale_manifest_path is None:
649
+ return None
650
+ return locale_manifest_path.parent
@@ -0,0 +1,171 @@
1
+ """
2
+ i18n runtime validation (Localization Manifest Spec v1).
3
+
4
+ Validates that runtime code uses the centralized locale manifest:
5
+ - LOCALE-CODE-2.1: i18nConfig.ts imports from manifest (not hardcoded arrays)
6
+ - LOCALE-CODE-2.2: LanguageSwitcher uses shared SUPPORTED_LOCALES
7
+ """
8
+
9
+ import re
10
+ import pytest
11
+ from pathlib import Path
12
+ from typing import Optional
13
+
14
+ from atdd.coach.utils.locale_phase import (
15
+ LocalePhase,
16
+ should_enforce_locale,
17
+ emit_locale_warning,
18
+ )
19
+ from atdd.coach.utils.repo import find_repo_root
20
+
21
+ # Path constants
22
+ REPO_ROOT = find_repo_root()
23
+ WEB_DIR = REPO_ROOT / "web"
24
+
25
+
26
+ def _find_file(base_dir: Path, *possible_paths: str) -> Optional[Path]:
27
+ """Find first existing file from list of possible paths."""
28
+ for rel_path in possible_paths:
29
+ full_path = base_dir / rel_path
30
+ if full_path.exists():
31
+ return full_path
32
+ return None
33
+
34
+
35
+ def _read_file_content(path: Path) -> Optional[str]:
36
+ """Read file content, return None on error."""
37
+ try:
38
+ return path.read_text()
39
+ except Exception:
40
+ return None
41
+
42
+
43
+ @pytest.mark.locale
44
+ @pytest.mark.coder
45
+ def test_i18n_config_uses_manifest(locale_manifest, locale_manifest_path):
46
+ """
47
+ LOCALE-CODE-2.1: i18nConfig.ts imports from manifest (not hardcoded arrays)
48
+
49
+ Given: Web application with i18n configuration
50
+ When: Checking i18nConfig.ts or i18n.ts
51
+ Then: Configuration imports locales from manifest or shared constant
52
+ NOT hardcoded locale arrays like ['en', 'es', 'fr']
53
+ """
54
+ if locale_manifest is None:
55
+ pytest.skip("Localization not configured")
56
+
57
+ i18n_config = _find_file(
58
+ WEB_DIR,
59
+ "src/i18nConfig.ts",
60
+ "src/i18n/config.ts",
61
+ "src/i18n.ts",
62
+ "src/lib/i18n.ts",
63
+ "src/config/i18n.ts",
64
+ )
65
+
66
+ if i18n_config is None:
67
+ pytest.skip("No i18n config file found in web/src/")
68
+
69
+ content = _read_file_content(i18n_config)
70
+ if content is None:
71
+ pytest.skip(f"Cannot read {i18n_config}")
72
+
73
+ hardcoded_array_pattern = re.compile(
74
+ r"(?:locales|supportedLocales|SUPPORTED_LOCALES|languages)\s*[=:]\s*\[\s*['\"][a-z]{2}",
75
+ re.IGNORECASE
76
+ )
77
+
78
+ if hardcoded_array_pattern.search(content):
79
+ manifest_import_patterns = [
80
+ r"from\s+['\"].*manifest",
81
+ r"import.*manifest",
82
+ r"require\s*\(\s*['\"].*manifest",
83
+ r"SUPPORTED_LOCALES",
84
+ r"getSupportedLocales",
85
+ ]
86
+
87
+ has_manifest_usage = any(
88
+ re.search(pattern, content, re.IGNORECASE)
89
+ for pattern in manifest_import_patterns
90
+ )
91
+
92
+ if not has_manifest_usage:
93
+ msg = (
94
+ f"i18n config has hardcoded locale array: {i18n_config.relative_to(REPO_ROOT)}\n"
95
+ f" Should import from manifest.json or use shared SUPPORTED_LOCALES constant"
96
+ )
97
+ if should_enforce_locale(LocalePhase.FULL_ENFORCEMENT):
98
+ pytest.fail(msg)
99
+ else:
100
+ emit_locale_warning("LOCALE-CODE-2.1", msg, LocalePhase.FULL_ENFORCEMENT)
101
+ pytest.skip(msg)
102
+
103
+
104
+ @pytest.mark.locale
105
+ @pytest.mark.coder
106
+ def test_language_switcher_uses_shared_locales(locale_manifest, locale_manifest_path):
107
+ """
108
+ LOCALE-CODE-2.2: LanguageSwitcher uses shared SUPPORTED_LOCALES
109
+
110
+ Given: Web application with language switcher component
111
+ When: Checking LanguageSwitcher component
112
+ Then: Component imports locales from shared constant or manifest
113
+ NOT hardcoded locale arrays
114
+ """
115
+ if locale_manifest is None:
116
+ pytest.skip("Localization not configured")
117
+
118
+ switcher_patterns = [
119
+ "src/components/LanguageSwitcher.tsx",
120
+ "src/components/LocaleSwitcher.tsx",
121
+ "src/components/ui/LanguageSwitcher.tsx",
122
+ "src/components/common/LanguageSwitcher.tsx",
123
+ "src/features/i18n/LanguageSwitcher.tsx",
124
+ ]
125
+
126
+ switcher_file = _find_file(WEB_DIR, *switcher_patterns)
127
+
128
+ if switcher_file is None:
129
+ switcher_files = list(WEB_DIR.rglob("*[Ll]anguage*[Ss]witcher*.tsx"))
130
+ if not switcher_files:
131
+ switcher_files = list(WEB_DIR.rglob("*[Ll]ocale*[Ss]witcher*.tsx"))
132
+ if switcher_files:
133
+ switcher_file = switcher_files[0]
134
+
135
+ if switcher_file is None:
136
+ pytest.skip("No LanguageSwitcher component found")
137
+
138
+ content = _read_file_content(switcher_file)
139
+ if content is None:
140
+ pytest.skip(f"Cannot read {switcher_file}")
141
+
142
+ hardcoded_array_pattern = re.compile(
143
+ r"(?:locales|languages|options)\s*[=:]\s*\[\s*(?:\{[^}]*locale[^}]*['\"][a-z]{2}|['\"][a-z]{2})",
144
+ re.IGNORECASE
145
+ )
146
+
147
+ if hardcoded_array_pattern.search(content):
148
+ shared_patterns = [
149
+ r"SUPPORTED_LOCALES",
150
+ r"getSupportedLocales",
151
+ r"from\s+['\"].*manifest",
152
+ r"from\s+['\"].*i18n",
153
+ r"from\s+['\"].*config",
154
+ r"useLocales",
155
+ ]
156
+
157
+ has_shared_usage = any(
158
+ re.search(pattern, content, re.IGNORECASE)
159
+ for pattern in shared_patterns
160
+ )
161
+
162
+ if not has_shared_usage:
163
+ msg = (
164
+ f"LanguageSwitcher has hardcoded locale array: {switcher_file.relative_to(REPO_ROOT)}\n"
165
+ f" Should import from shared SUPPORTED_LOCALES or manifest"
166
+ )
167
+ if should_enforce_locale(LocalePhase.FULL_ENFORCEMENT):
168
+ pytest.fail(msg)
169
+ else:
170
+ emit_locale_warning("LOCALE-CODE-2.2", msg, LocalePhase.FULL_ENFORCEMENT)
171
+ pytest.skip(msg)
@@ -0,0 +1,53 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://atdd.dev/schemas/tester/locale_manifest.schema.json",
4
+ "title": "Locale Manifest",
5
+ "description": "Schema for localization manifest.json - single source of truth for supported locales and namespaces (Localization Manifest Spec v1)",
6
+ "type": "object",
7
+ "required": ["reference", "locales", "namespaces"],
8
+ "properties": {
9
+ "reference": {
10
+ "type": "string",
11
+ "pattern": "^[a-z]{2}(-[A-Z]{2})?$",
12
+ "description": "Reference locale code (e.g., 'en', 'en-US'). All other locales must match this locale's keys."
13
+ },
14
+ "locales": {
15
+ "type": "array",
16
+ "minItems": 1,
17
+ "items": {
18
+ "type": "string",
19
+ "pattern": "^[a-z]{2}(-[A-Z]{2})?$"
20
+ },
21
+ "uniqueItems": true,
22
+ "description": "List of supported locale codes. Must include the reference locale."
23
+ },
24
+ "namespaces": {
25
+ "type": "array",
26
+ "minItems": 1,
27
+ "items": {
28
+ "type": "string",
29
+ "pattern": "^[a-z][a-z0-9_-]*$"
30
+ },
31
+ "uniqueItems": true,
32
+ "description": "Required namespaces that must exist for all locales (e.g., 'common', 'ui', 'errors')"
33
+ },
34
+ "optional_namespaces": {
35
+ "type": "array",
36
+ "items": {
37
+ "type": "string",
38
+ "pattern": "^[a-z][a-z0-9_-]*$"
39
+ },
40
+ "uniqueItems": true,
41
+ "description": "Optional namespaces that may not exist for all locales. If present, must match reference keys."
42
+ }
43
+ },
44
+ "additionalProperties": false,
45
+ "examples": [
46
+ {
47
+ "reference": "en",
48
+ "locales": ["en", "es", "fr", "de", "ja"],
49
+ "namespaces": ["common", "ui", "errors"],
50
+ "optional_namespaces": ["landing", "marketing"]
51
+ }
52
+ ]
53
+ }