atdd 0.1.0__py3-none-any.whl

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 (183) hide show
  1. atdd/__init__.py +0 -0
  2. atdd/cli.py +404 -0
  3. atdd/coach/__init__.py +0 -0
  4. atdd/coach/commands/__init__.py +0 -0
  5. atdd/coach/commands/add_persistence_metadata.py +215 -0
  6. atdd/coach/commands/analyze_migrations.py +188 -0
  7. atdd/coach/commands/consumers.py +720 -0
  8. atdd/coach/commands/infer_governance_status.py +149 -0
  9. atdd/coach/commands/initializer.py +177 -0
  10. atdd/coach/commands/interface.py +1078 -0
  11. atdd/coach/commands/inventory.py +565 -0
  12. atdd/coach/commands/migration.py +240 -0
  13. atdd/coach/commands/registry.py +1560 -0
  14. atdd/coach/commands/session.py +430 -0
  15. atdd/coach/commands/sync.py +405 -0
  16. atdd/coach/commands/test_interface.py +399 -0
  17. atdd/coach/commands/test_runner.py +141 -0
  18. atdd/coach/commands/tests/__init__.py +1 -0
  19. atdd/coach/commands/tests/test_telemetry_array_validation.py +235 -0
  20. atdd/coach/commands/traceability.py +4264 -0
  21. atdd/coach/conventions/session.convention.yaml +754 -0
  22. atdd/coach/overlays/__init__.py +2 -0
  23. atdd/coach/overlays/claude.md +2 -0
  24. atdd/coach/schemas/config.schema.json +34 -0
  25. atdd/coach/schemas/manifest.schema.json +101 -0
  26. atdd/coach/templates/ATDD.md +282 -0
  27. atdd/coach/templates/SESSION-TEMPLATE.md +327 -0
  28. atdd/coach/utils/__init__.py +0 -0
  29. atdd/coach/utils/graph/__init__.py +0 -0
  30. atdd/coach/utils/graph/urn.py +875 -0
  31. atdd/coach/validators/__init__.py +0 -0
  32. atdd/coach/validators/shared_fixtures.py +365 -0
  33. atdd/coach/validators/test_enrich_wagon_registry.py +167 -0
  34. atdd/coach/validators/test_registry.py +575 -0
  35. atdd/coach/validators/test_session_validation.py +1183 -0
  36. atdd/coach/validators/test_traceability.py +448 -0
  37. atdd/coach/validators/test_update_feature_paths.py +108 -0
  38. atdd/coach/validators/test_validate_contract_consumers.py +297 -0
  39. atdd/coder/__init__.py +1 -0
  40. atdd/coder/conventions/adapter.recipe.yaml +88 -0
  41. atdd/coder/conventions/backend.convention.yaml +460 -0
  42. atdd/coder/conventions/boundaries.convention.yaml +666 -0
  43. atdd/coder/conventions/commons.convention.yaml +460 -0
  44. atdd/coder/conventions/complexity.recipe.yaml +109 -0
  45. atdd/coder/conventions/component-naming.convention.yaml +178 -0
  46. atdd/coder/conventions/design.convention.yaml +327 -0
  47. atdd/coder/conventions/design.recipe.yaml +273 -0
  48. atdd/coder/conventions/dto.convention.yaml +660 -0
  49. atdd/coder/conventions/frontend.convention.yaml +542 -0
  50. atdd/coder/conventions/green.convention.yaml +1012 -0
  51. atdd/coder/conventions/presentation.convention.yaml +587 -0
  52. atdd/coder/conventions/refactor.convention.yaml +535 -0
  53. atdd/coder/conventions/technology.convention.yaml +206 -0
  54. atdd/coder/conventions/tests/__init__.py +0 -0
  55. atdd/coder/conventions/tests/test_adapter_recipe.py +302 -0
  56. atdd/coder/conventions/tests/test_complexity_recipe.py +289 -0
  57. atdd/coder/conventions/tests/test_component_taxonomy.py +278 -0
  58. atdd/coder/conventions/tests/test_component_urn_naming.py +165 -0
  59. atdd/coder/conventions/tests/test_thinness_recipe.py +286 -0
  60. atdd/coder/conventions/thinness.recipe.yaml +82 -0
  61. atdd/coder/conventions/train.convention.yaml +325 -0
  62. atdd/coder/conventions/verification.protocol.yaml +53 -0
  63. atdd/coder/schemas/design_system.schema.json +361 -0
  64. atdd/coder/validators/__init__.py +0 -0
  65. atdd/coder/validators/test_commons_structure.py +485 -0
  66. atdd/coder/validators/test_complexity.py +416 -0
  67. atdd/coder/validators/test_cross_language_consistency.py +431 -0
  68. atdd/coder/validators/test_design_system_compliance.py +413 -0
  69. atdd/coder/validators/test_dto_testing_patterns.py +268 -0
  70. atdd/coder/validators/test_green_cross_stack_layers.py +168 -0
  71. atdd/coder/validators/test_green_layer_dependencies.py +148 -0
  72. atdd/coder/validators/test_green_python_layer_structure.py +103 -0
  73. atdd/coder/validators/test_green_supabase_layer_structure.py +103 -0
  74. atdd/coder/validators/test_import_boundaries.py +396 -0
  75. atdd/coder/validators/test_init_file_urns.py +593 -0
  76. atdd/coder/validators/test_preact_layer_boundaries.py +221 -0
  77. atdd/coder/validators/test_presentation_convention.py +260 -0
  78. atdd/coder/validators/test_python_architecture.py +674 -0
  79. atdd/coder/validators/test_quality_metrics.py +420 -0
  80. atdd/coder/validators/test_station_master_pattern.py +244 -0
  81. atdd/coder/validators/test_train_infrastructure.py +454 -0
  82. atdd/coder/validators/test_train_urns.py +293 -0
  83. atdd/coder/validators/test_typescript_architecture.py +616 -0
  84. atdd/coder/validators/test_usecase_structure.py +421 -0
  85. atdd/coder/validators/test_wagon_boundaries.py +586 -0
  86. atdd/conftest.py +126 -0
  87. atdd/planner/__init__.py +1 -0
  88. atdd/planner/conventions/acceptance.convention.yaml +538 -0
  89. atdd/planner/conventions/appendix.convention.yaml +187 -0
  90. atdd/planner/conventions/artifact-naming.convention.yaml +852 -0
  91. atdd/planner/conventions/component.convention.yaml +670 -0
  92. atdd/planner/conventions/criteria.convention.yaml +141 -0
  93. atdd/planner/conventions/feature.convention.yaml +371 -0
  94. atdd/planner/conventions/interface.convention.yaml +382 -0
  95. atdd/planner/conventions/steps.convention.yaml +141 -0
  96. atdd/planner/conventions/train.convention.yaml +552 -0
  97. atdd/planner/conventions/wagon.convention.yaml +275 -0
  98. atdd/planner/conventions/wmbt.convention.yaml +258 -0
  99. atdd/planner/schemas/acceptance.schema.json +336 -0
  100. atdd/planner/schemas/appendix.schema.json +78 -0
  101. atdd/planner/schemas/component.schema.json +114 -0
  102. atdd/planner/schemas/feature.schema.json +197 -0
  103. atdd/planner/schemas/train.schema.json +192 -0
  104. atdd/planner/schemas/wagon.schema.json +281 -0
  105. atdd/planner/schemas/wmbt.schema.json +59 -0
  106. atdd/planner/validators/__init__.py +0 -0
  107. atdd/planner/validators/conftest.py +5 -0
  108. atdd/planner/validators/test_draft_wagon_registry.py +374 -0
  109. atdd/planner/validators/test_plan_cross_refs.py +240 -0
  110. atdd/planner/validators/test_plan_uniqueness.py +224 -0
  111. atdd/planner/validators/test_plan_urn_resolution.py +268 -0
  112. atdd/planner/validators/test_plan_wagons.py +174 -0
  113. atdd/planner/validators/test_train_validation.py +514 -0
  114. atdd/planner/validators/test_wagon_urn_chain.py +648 -0
  115. atdd/planner/validators/test_wmbt_consistency.py +327 -0
  116. atdd/planner/validators/test_wmbt_vocabulary.py +632 -0
  117. atdd/tester/__init__.py +1 -0
  118. atdd/tester/conventions/artifact.convention.yaml +257 -0
  119. atdd/tester/conventions/contract.convention.yaml +1009 -0
  120. atdd/tester/conventions/filename.convention.yaml +555 -0
  121. atdd/tester/conventions/migration.convention.yaml +509 -0
  122. atdd/tester/conventions/red.convention.yaml +797 -0
  123. atdd/tester/conventions/routing.convention.yaml +51 -0
  124. atdd/tester/conventions/telemetry.convention.yaml +458 -0
  125. atdd/tester/schemas/a11y.tmpl.json +17 -0
  126. atdd/tester/schemas/artifact.schema.json +189 -0
  127. atdd/tester/schemas/contract.schema.json +591 -0
  128. atdd/tester/schemas/contract.tmpl.json +95 -0
  129. atdd/tester/schemas/db.tmpl.json +20 -0
  130. atdd/tester/schemas/e2e.tmpl.json +17 -0
  131. atdd/tester/schemas/edge_function.tmpl.json +17 -0
  132. atdd/tester/schemas/event.tmpl.json +17 -0
  133. atdd/tester/schemas/http.tmpl.json +19 -0
  134. atdd/tester/schemas/job.tmpl.json +18 -0
  135. atdd/tester/schemas/load.tmpl.json +21 -0
  136. atdd/tester/schemas/metric.tmpl.json +19 -0
  137. atdd/tester/schemas/pack.schema.json +139 -0
  138. atdd/tester/schemas/realtime.tmpl.json +20 -0
  139. atdd/tester/schemas/rls.tmpl.json +18 -0
  140. atdd/tester/schemas/script.tmpl.json +16 -0
  141. atdd/tester/schemas/sec.tmpl.json +18 -0
  142. atdd/tester/schemas/storage.tmpl.json +18 -0
  143. atdd/tester/schemas/telemetry.schema.json +128 -0
  144. atdd/tester/schemas/telemetry_tracking_manifest.schema.json +143 -0
  145. atdd/tester/schemas/test_filename.schema.json +194 -0
  146. atdd/tester/schemas/test_intent.schema.json +179 -0
  147. atdd/tester/schemas/unit.tmpl.json +18 -0
  148. atdd/tester/schemas/visual.tmpl.json +18 -0
  149. atdd/tester/schemas/ws.tmpl.json +17 -0
  150. atdd/tester/utils/__init__.py +0 -0
  151. atdd/tester/utils/filename.py +300 -0
  152. atdd/tester/validators/__init__.py +0 -0
  153. atdd/tester/validators/cleanup_duplicate_headers.py +116 -0
  154. atdd/tester/validators/cleanup_duplicate_headers_v2.py +135 -0
  155. atdd/tester/validators/conftest.py +5 -0
  156. atdd/tester/validators/coverage_gap_report.py +321 -0
  157. atdd/tester/validators/fix_dual_ac_references.py +179 -0
  158. atdd/tester/validators/remove_duplicate_lines.py +93 -0
  159. atdd/tester/validators/test_acceptance_urn_filename_mapping.py +359 -0
  160. atdd/tester/validators/test_acceptance_urn_separator.py +166 -0
  161. atdd/tester/validators/test_artifact_naming_category.py +307 -0
  162. atdd/tester/validators/test_contract_schema_compliance.py +706 -0
  163. atdd/tester/validators/test_contracts_structure.py +200 -0
  164. atdd/tester/validators/test_coverage_adequacy.py +797 -0
  165. atdd/tester/validators/test_dual_ac_reference.py +225 -0
  166. atdd/tester/validators/test_fixture_validity.py +372 -0
  167. atdd/tester/validators/test_isolation.py +487 -0
  168. atdd/tester/validators/test_migration_coverage.py +204 -0
  169. atdd/tester/validators/test_migration_criteria.py +276 -0
  170. atdd/tester/validators/test_migration_generation.py +116 -0
  171. atdd/tester/validators/test_python_test_naming.py +410 -0
  172. atdd/tester/validators/test_red_layer_validation.py +95 -0
  173. atdd/tester/validators/test_red_python_layer_structure.py +87 -0
  174. atdd/tester/validators/test_red_supabase_layer_structure.py +90 -0
  175. atdd/tester/validators/test_telemetry_structure.py +634 -0
  176. atdd/tester/validators/test_typescript_test_naming.py +301 -0
  177. atdd/tester/validators/test_typescript_test_structure.py +84 -0
  178. atdd-0.1.0.dist-info/METADATA +191 -0
  179. atdd-0.1.0.dist-info/RECORD +183 -0
  180. atdd-0.1.0.dist-info/WHEEL +5 -0
  181. atdd-0.1.0.dist-info/entry_points.txt +2 -0
  182. atdd-0.1.0.dist-info/licenses/LICENSE +674 -0
  183. atdd-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,188 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Analyze which migrations should be kept vs deleted based on refined criteria.
4
+
5
+ Shows a clear diff before any deletion happens.
6
+ """
7
+
8
+ import json
9
+ from pathlib import Path
10
+ from collections import defaultdict
11
+
12
+ # Import the refined criteria function
13
+ from migration import contract_needs_migration, REPO_ROOT, CONTRACTS_DIR, MIGRATIONS_DIR
14
+
15
+
16
+ def analyze_migration_status():
17
+ """Analyze all contracts and migrations, show what should be kept/deleted."""
18
+
19
+ print("=" * 80)
20
+ print("MIGRATION ANALYSIS - Refined Criteria")
21
+ print("=" * 80)
22
+ print()
23
+
24
+ # Scan all contracts
25
+ contracts = list(CONTRACTS_DIR.rglob("*.schema.json"))
26
+
27
+ keep_migrations = []
28
+ delete_migrations = []
29
+ missing_migrations = []
30
+
31
+ for contract in contracts:
32
+ relative_path = contract.relative_to(CONTRACTS_DIR)
33
+ parts = relative_path.parts
34
+
35
+ if len(parts) < 3:
36
+ continue
37
+
38
+ theme = parts[0]
39
+ domain = parts[1]
40
+ aspect = contract.stem.replace(".schema", "")
41
+ table_name = f"{theme}_{domain}_{aspect}".replace("-", "_")
42
+
43
+ # Check if contract needs migration
44
+ needs_migration = contract_needs_migration(contract)
45
+
46
+ # Find existing migration
47
+ existing_migration = None
48
+ for mig in MIGRATIONS_DIR.glob("*.sql"):
49
+ if f"CREATE TABLE {table_name}" in mig.read_text() or \
50
+ f"CREATE TABLE IF NOT EXISTS {table_name}" in mig.read_text():
51
+ existing_migration = mig
52
+ break
53
+
54
+ # Categorize
55
+ if needs_migration:
56
+ if existing_migration:
57
+ keep_migrations.append({
58
+ "contract": relative_path,
59
+ "migration": existing_migration.name,
60
+ "table": table_name,
61
+ "reason": _get_reason(contract)
62
+ })
63
+ else:
64
+ missing_migrations.append({
65
+ "contract": relative_path,
66
+ "table": table_name,
67
+ "reason": _get_reason(contract)
68
+ })
69
+ else:
70
+ if existing_migration:
71
+ delete_migrations.append({
72
+ "contract": relative_path,
73
+ "migration": existing_migration.name,
74
+ "table": table_name,
75
+ "reason": _get_exclusion_reason(contract)
76
+ })
77
+
78
+ # Print summary
79
+ print(f"šŸ“Š SUMMARY")
80
+ print(f" Total contracts: {len(contracts)}")
81
+ print(f" āœ… Keep migrations: {len(keep_migrations)}")
82
+ print(f" āŒ Delete migrations: {len(delete_migrations)}")
83
+ print(f" āš ļø Missing migrations: {len(missing_migrations)}")
84
+ print()
85
+
86
+ # Show migrations to KEEP
87
+ print("=" * 80)
88
+ print("āœ… MIGRATIONS TO KEEP")
89
+ print("=" * 80)
90
+ for item in keep_migrations:
91
+ print(f"\n šŸ“„ {item['migration']}")
92
+ print(f" Contract: {item['contract']}")
93
+ print(f" Table: {item['table']}")
94
+ print(f" Reason: {item['reason']}")
95
+
96
+ # Show migrations to DELETE
97
+ print()
98
+ print("=" * 80)
99
+ print("āŒ MIGRATIONS TO DELETE")
100
+ print("=" * 80)
101
+ for item in delete_migrations:
102
+ print(f"\n šŸ—‘ļø {item['migration']}")
103
+ print(f" Contract: {item['contract']}")
104
+ print(f" Table: {item['table']}")
105
+ print(f" Reason: {item['reason']}")
106
+
107
+ # Show missing migrations
108
+ if missing_migrations:
109
+ print()
110
+ print("=" * 80)
111
+ print("āš ļø MISSING MIGRATIONS (need to generate)")
112
+ print("=" * 80)
113
+ for item in missing_migrations:
114
+ print(f"\n āš ļø {item['table']}")
115
+ print(f" Contract: {item['contract']}")
116
+ print(f" Reason: {item['reason']}")
117
+
118
+ print()
119
+ print("=" * 80)
120
+ print()
121
+
122
+ return keep_migrations, delete_migrations, missing_migrations
123
+
124
+
125
+ def _get_reason(contract_path: Path) -> str:
126
+ """Get the reason why a contract needs migration."""
127
+ with open(contract_path) as f:
128
+ contract = json.load(f)
129
+
130
+ metadata = contract.get("x-artifact-metadata", {})
131
+ properties = contract.get("properties", {})
132
+ aspect = contract_path.stem.replace(".schema", "")
133
+
134
+ if "persistent" in metadata and metadata["persistent"]:
135
+ return "Explicit persistent: true"
136
+
137
+ if "id" in properties:
138
+ if aspect.endswith("ed"):
139
+ return "Has id field (overrides event pattern)"
140
+ return "Has id field (entity)"
141
+
142
+ if metadata.get("to") == "external" and len(properties) > 0:
143
+ return "Conservative default (external + properties)"
144
+
145
+ return "Unknown"
146
+
147
+
148
+ def _get_exclusion_reason(contract_path: Path) -> str:
149
+ """Get the reason why a contract doesn't need migration."""
150
+ with open(contract_path) as f:
151
+ contract = json.load(f)
152
+
153
+ metadata = contract.get("x-artifact-metadata", {})
154
+ properties = contract.get("properties", {})
155
+ description = contract.get("description", "").lower()
156
+ aspect = contract_path.stem.replace(".schema", "")
157
+
158
+ if "persistent" in metadata and not metadata["persistent"]:
159
+ return "Explicit persistent: false"
160
+
161
+ if len(properties) == 0:
162
+ return "Empty contract (pure signal)"
163
+
164
+ has_id = "id" in properties
165
+ is_event_pattern = aspect.endswith("ed")
166
+
167
+ if is_event_pattern and not has_id:
168
+ return "Event pattern without id"
169
+
170
+ if metadata.get("to") == "internal":
171
+ return "Internal contract (transient DTO)"
172
+
173
+ compute_keywords = ["computed", "calculated", "derived", "aggregated", "aggregate"]
174
+ is_computed = any(keyword in description for keyword in compute_keywords)
175
+ if is_computed and not has_id:
176
+ return "Computed value without id"
177
+
178
+ return "Fallback (no migration needed)"
179
+
180
+
181
+ if __name__ == "__main__":
182
+ keep, delete, missing = analyze_migration_status()
183
+
184
+ print(f"\nšŸ“ Next steps:")
185
+ print(f" 1. Review the analysis above")
186
+ print(f" 2. Confirm deletion of {len(delete)} migrations")
187
+ print(f" 3. Generate {len(missing)} missing migrations")
188
+ print()