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.
- atdd/__init__.py +0 -0
- atdd/cli.py +404 -0
- atdd/coach/__init__.py +0 -0
- atdd/coach/commands/__init__.py +0 -0
- atdd/coach/commands/add_persistence_metadata.py +215 -0
- atdd/coach/commands/analyze_migrations.py +188 -0
- atdd/coach/commands/consumers.py +720 -0
- atdd/coach/commands/infer_governance_status.py +149 -0
- atdd/coach/commands/initializer.py +177 -0
- atdd/coach/commands/interface.py +1078 -0
- atdd/coach/commands/inventory.py +565 -0
- atdd/coach/commands/migration.py +240 -0
- atdd/coach/commands/registry.py +1560 -0
- atdd/coach/commands/session.py +430 -0
- atdd/coach/commands/sync.py +405 -0
- atdd/coach/commands/test_interface.py +399 -0
- atdd/coach/commands/test_runner.py +141 -0
- atdd/coach/commands/tests/__init__.py +1 -0
- atdd/coach/commands/tests/test_telemetry_array_validation.py +235 -0
- atdd/coach/commands/traceability.py +4264 -0
- atdd/coach/conventions/session.convention.yaml +754 -0
- atdd/coach/overlays/__init__.py +2 -0
- atdd/coach/overlays/claude.md +2 -0
- atdd/coach/schemas/config.schema.json +34 -0
- atdd/coach/schemas/manifest.schema.json +101 -0
- atdd/coach/templates/ATDD.md +282 -0
- atdd/coach/templates/SESSION-TEMPLATE.md +327 -0
- atdd/coach/utils/__init__.py +0 -0
- atdd/coach/utils/graph/__init__.py +0 -0
- atdd/coach/utils/graph/urn.py +875 -0
- atdd/coach/validators/__init__.py +0 -0
- atdd/coach/validators/shared_fixtures.py +365 -0
- atdd/coach/validators/test_enrich_wagon_registry.py +167 -0
- atdd/coach/validators/test_registry.py +575 -0
- atdd/coach/validators/test_session_validation.py +1183 -0
- atdd/coach/validators/test_traceability.py +448 -0
- atdd/coach/validators/test_update_feature_paths.py +108 -0
- atdd/coach/validators/test_validate_contract_consumers.py +297 -0
- atdd/coder/__init__.py +1 -0
- atdd/coder/conventions/adapter.recipe.yaml +88 -0
- atdd/coder/conventions/backend.convention.yaml +460 -0
- atdd/coder/conventions/boundaries.convention.yaml +666 -0
- atdd/coder/conventions/commons.convention.yaml +460 -0
- atdd/coder/conventions/complexity.recipe.yaml +109 -0
- atdd/coder/conventions/component-naming.convention.yaml +178 -0
- atdd/coder/conventions/design.convention.yaml +327 -0
- atdd/coder/conventions/design.recipe.yaml +273 -0
- atdd/coder/conventions/dto.convention.yaml +660 -0
- atdd/coder/conventions/frontend.convention.yaml +542 -0
- atdd/coder/conventions/green.convention.yaml +1012 -0
- atdd/coder/conventions/presentation.convention.yaml +587 -0
- atdd/coder/conventions/refactor.convention.yaml +535 -0
- atdd/coder/conventions/technology.convention.yaml +206 -0
- atdd/coder/conventions/tests/__init__.py +0 -0
- atdd/coder/conventions/tests/test_adapter_recipe.py +302 -0
- atdd/coder/conventions/tests/test_complexity_recipe.py +289 -0
- atdd/coder/conventions/tests/test_component_taxonomy.py +278 -0
- atdd/coder/conventions/tests/test_component_urn_naming.py +165 -0
- atdd/coder/conventions/tests/test_thinness_recipe.py +286 -0
- atdd/coder/conventions/thinness.recipe.yaml +82 -0
- atdd/coder/conventions/train.convention.yaml +325 -0
- atdd/coder/conventions/verification.protocol.yaml +53 -0
- atdd/coder/schemas/design_system.schema.json +361 -0
- atdd/coder/validators/__init__.py +0 -0
- atdd/coder/validators/test_commons_structure.py +485 -0
- atdd/coder/validators/test_complexity.py +416 -0
- atdd/coder/validators/test_cross_language_consistency.py +431 -0
- atdd/coder/validators/test_design_system_compliance.py +413 -0
- atdd/coder/validators/test_dto_testing_patterns.py +268 -0
- atdd/coder/validators/test_green_cross_stack_layers.py +168 -0
- atdd/coder/validators/test_green_layer_dependencies.py +148 -0
- atdd/coder/validators/test_green_python_layer_structure.py +103 -0
- atdd/coder/validators/test_green_supabase_layer_structure.py +103 -0
- atdd/coder/validators/test_import_boundaries.py +396 -0
- atdd/coder/validators/test_init_file_urns.py +593 -0
- atdd/coder/validators/test_preact_layer_boundaries.py +221 -0
- atdd/coder/validators/test_presentation_convention.py +260 -0
- atdd/coder/validators/test_python_architecture.py +674 -0
- atdd/coder/validators/test_quality_metrics.py +420 -0
- atdd/coder/validators/test_station_master_pattern.py +244 -0
- atdd/coder/validators/test_train_infrastructure.py +454 -0
- atdd/coder/validators/test_train_urns.py +293 -0
- atdd/coder/validators/test_typescript_architecture.py +616 -0
- atdd/coder/validators/test_usecase_structure.py +421 -0
- atdd/coder/validators/test_wagon_boundaries.py +586 -0
- atdd/conftest.py +126 -0
- atdd/planner/__init__.py +1 -0
- atdd/planner/conventions/acceptance.convention.yaml +538 -0
- atdd/planner/conventions/appendix.convention.yaml +187 -0
- atdd/planner/conventions/artifact-naming.convention.yaml +852 -0
- atdd/planner/conventions/component.convention.yaml +670 -0
- atdd/planner/conventions/criteria.convention.yaml +141 -0
- atdd/planner/conventions/feature.convention.yaml +371 -0
- atdd/planner/conventions/interface.convention.yaml +382 -0
- atdd/planner/conventions/steps.convention.yaml +141 -0
- atdd/planner/conventions/train.convention.yaml +552 -0
- atdd/planner/conventions/wagon.convention.yaml +275 -0
- atdd/planner/conventions/wmbt.convention.yaml +258 -0
- atdd/planner/schemas/acceptance.schema.json +336 -0
- atdd/planner/schemas/appendix.schema.json +78 -0
- atdd/planner/schemas/component.schema.json +114 -0
- atdd/planner/schemas/feature.schema.json +197 -0
- atdd/planner/schemas/train.schema.json +192 -0
- atdd/planner/schemas/wagon.schema.json +281 -0
- atdd/planner/schemas/wmbt.schema.json +59 -0
- atdd/planner/validators/__init__.py +0 -0
- atdd/planner/validators/conftest.py +5 -0
- atdd/planner/validators/test_draft_wagon_registry.py +374 -0
- atdd/planner/validators/test_plan_cross_refs.py +240 -0
- atdd/planner/validators/test_plan_uniqueness.py +224 -0
- atdd/planner/validators/test_plan_urn_resolution.py +268 -0
- atdd/planner/validators/test_plan_wagons.py +174 -0
- atdd/planner/validators/test_train_validation.py +514 -0
- atdd/planner/validators/test_wagon_urn_chain.py +648 -0
- atdd/planner/validators/test_wmbt_consistency.py +327 -0
- atdd/planner/validators/test_wmbt_vocabulary.py +632 -0
- atdd/tester/__init__.py +1 -0
- atdd/tester/conventions/artifact.convention.yaml +257 -0
- atdd/tester/conventions/contract.convention.yaml +1009 -0
- atdd/tester/conventions/filename.convention.yaml +555 -0
- atdd/tester/conventions/migration.convention.yaml +509 -0
- atdd/tester/conventions/red.convention.yaml +797 -0
- atdd/tester/conventions/routing.convention.yaml +51 -0
- atdd/tester/conventions/telemetry.convention.yaml +458 -0
- atdd/tester/schemas/a11y.tmpl.json +17 -0
- atdd/tester/schemas/artifact.schema.json +189 -0
- atdd/tester/schemas/contract.schema.json +591 -0
- atdd/tester/schemas/contract.tmpl.json +95 -0
- atdd/tester/schemas/db.tmpl.json +20 -0
- atdd/tester/schemas/e2e.tmpl.json +17 -0
- atdd/tester/schemas/edge_function.tmpl.json +17 -0
- atdd/tester/schemas/event.tmpl.json +17 -0
- atdd/tester/schemas/http.tmpl.json +19 -0
- atdd/tester/schemas/job.tmpl.json +18 -0
- atdd/tester/schemas/load.tmpl.json +21 -0
- atdd/tester/schemas/metric.tmpl.json +19 -0
- atdd/tester/schemas/pack.schema.json +139 -0
- atdd/tester/schemas/realtime.tmpl.json +20 -0
- atdd/tester/schemas/rls.tmpl.json +18 -0
- atdd/tester/schemas/script.tmpl.json +16 -0
- atdd/tester/schemas/sec.tmpl.json +18 -0
- atdd/tester/schemas/storage.tmpl.json +18 -0
- atdd/tester/schemas/telemetry.schema.json +128 -0
- atdd/tester/schemas/telemetry_tracking_manifest.schema.json +143 -0
- atdd/tester/schemas/test_filename.schema.json +194 -0
- atdd/tester/schemas/test_intent.schema.json +179 -0
- atdd/tester/schemas/unit.tmpl.json +18 -0
- atdd/tester/schemas/visual.tmpl.json +18 -0
- atdd/tester/schemas/ws.tmpl.json +17 -0
- atdd/tester/utils/__init__.py +0 -0
- atdd/tester/utils/filename.py +300 -0
- atdd/tester/validators/__init__.py +0 -0
- atdd/tester/validators/cleanup_duplicate_headers.py +116 -0
- atdd/tester/validators/cleanup_duplicate_headers_v2.py +135 -0
- atdd/tester/validators/conftest.py +5 -0
- atdd/tester/validators/coverage_gap_report.py +321 -0
- atdd/tester/validators/fix_dual_ac_references.py +179 -0
- atdd/tester/validators/remove_duplicate_lines.py +93 -0
- atdd/tester/validators/test_acceptance_urn_filename_mapping.py +359 -0
- atdd/tester/validators/test_acceptance_urn_separator.py +166 -0
- atdd/tester/validators/test_artifact_naming_category.py +307 -0
- atdd/tester/validators/test_contract_schema_compliance.py +706 -0
- atdd/tester/validators/test_contracts_structure.py +200 -0
- atdd/tester/validators/test_coverage_adequacy.py +797 -0
- atdd/tester/validators/test_dual_ac_reference.py +225 -0
- atdd/tester/validators/test_fixture_validity.py +372 -0
- atdd/tester/validators/test_isolation.py +487 -0
- atdd/tester/validators/test_migration_coverage.py +204 -0
- atdd/tester/validators/test_migration_criteria.py +276 -0
- atdd/tester/validators/test_migration_generation.py +116 -0
- atdd/tester/validators/test_python_test_naming.py +410 -0
- atdd/tester/validators/test_red_layer_validation.py +95 -0
- atdd/tester/validators/test_red_python_layer_structure.py +87 -0
- atdd/tester/validators/test_red_supabase_layer_structure.py +90 -0
- atdd/tester/validators/test_telemetry_structure.py +634 -0
- atdd/tester/validators/test_typescript_test_naming.py +301 -0
- atdd/tester/validators/test_typescript_test_structure.py +84 -0
- atdd-0.1.0.dist-info/METADATA +191 -0
- atdd-0.1.0.dist-info/RECORD +183 -0
- atdd-0.1.0.dist-info/WHEEL +5 -0
- atdd-0.1.0.dist-info/entry_points.txt +2 -0
- atdd-0.1.0.dist-info/licenses/LICENSE +674 -0
- 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()
|