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,325 @@
1
+ schema_version: "1.0.0"
2
+ convention_id: "coder.train"
3
+ name: "Train Composition Root Convention"
4
+ description: "Production orchestration layer for executing user journeys across wagons"
5
+
6
+ rationale: |
7
+ Trains are PRODUCTION orchestration, not test infrastructure. They execute user journeys
8
+ defined in YAML specifications by coordinating wagons through contract-based communication.
9
+
10
+ TRANSFORMATION (SESSION-12):
11
+ - OLD: Trains in e2e/ (test-only), custom orchestration in game.py
12
+ - NEW: Trains in python/trains/ (production), game.py becomes thin Station Master
13
+
14
+ BENEFITS:
15
+ - Single source of truth (YAML defines both production AND tests)
16
+ - Declarative orchestration (change workflows via YAML, not code)
17
+ - Zero drift (tests use production TrainRunner)
18
+ - Operational visibility (train_id in logs = exact journey executed)
19
+
20
+ cross_references:
21
+ composition_hierarchy:
22
+ - file: "refactor.convention.yaml"
23
+ section: "composition_root.hierarchy"
24
+ note: "Trains add new orchestration layer between game.py and wagon.py"
25
+
26
+ boundaries:
27
+ - file: "boundaries.convention.yaml"
28
+ section: "interaction"
29
+ note: "Trains enforce boundaries via contract-based wagon communication"
30
+
31
+ specifications:
32
+ - file: "../../planner/conventions/train.convention.yaml"
33
+ note: "Planner defines train YAML structure and semantics"
34
+
35
+ # ============================================================================
36
+ # COMPOSITION ROOT HIERARCHY (with Trains)
37
+ # ============================================================================
38
+
39
+ composition_hierarchy:
40
+ description: "Trains sit between application (game.py) and wagons (wagon.py)"
41
+
42
+ levels:
43
+ application:
44
+ file: "python/game.py"
45
+ role: "Station Master - thin router"
46
+ responsibility: "Map user actions → train_ids, invoke TrainRunner"
47
+ size: "< 50 lines of routing logic"
48
+
49
+ train:
50
+ file: "python/trains/runner.py"
51
+ role: "Engine - THE orchestration layer"
52
+ responsibility: "Load YAML, orchestrate wagons, pass artifacts"
53
+ location: "python/trains/"
54
+ note: "NEW level introduced in SESSION-12"
55
+
56
+ wagon:
57
+ file: "python/{wagon}/wagon.py"
58
+ role: "Wagon - domain orchestration"
59
+ responsibility: "Expose run_train(inputs, timing) interface"
60
+
61
+ feature:
62
+ file: "python/{wagon}/{feature}/composition.py"
63
+ role: "Feature - layer wiring"
64
+ responsibility: "DI for domain/application/integration"
65
+
66
+ dependency_flow:
67
+ rule: "Dependencies flow downward only"
68
+ chain: "game.py → trains.runner → wagon.py → composition.py → src/"
69
+ forbidden: "NEVER: wagon imports from trains or game"
70
+
71
+ # ============================================================================
72
+ # TRAIN INFRASTRUCTURE
73
+ # ============================================================================
74
+
75
+ train_structure:
76
+ location: "python/trains/"
77
+
78
+ files:
79
+ runner_py:
80
+ file: "python/trains/runner.py"
81
+ class: "TrainRunner"
82
+ composition_root: true
83
+ responsibilities:
84
+ - "Load train YAML from plan/_trains/{train_id}.yaml"
85
+ - "Orchestrate wagons in sequence"
86
+ - "Pass artifacts as cargo between wagons"
87
+ - "Enforce boundaries (no direct wagon imports)"
88
+ - "Capture execution trace"
89
+
90
+ interface: |
91
+ class TrainRunner:
92
+ def __init__(self, train_yaml_path: str)
93
+ def execute(self, inputs: Dict, timing: Dict, capture_trace: bool) -> TrainResult
94
+ def get_train_info(self) -> Dict
95
+
96
+ models_py:
97
+ file: "python/trains/models.py"
98
+ models:
99
+ - "TrainSpec: Parsed train definition"
100
+ - "TrainStep: Single step in sequence"
101
+ - "TrainResult: Execution result + artifacts"
102
+ - "Cargo: Artifacts passed between wagons"
103
+
104
+ # ============================================================================
105
+ # WAGON TRAIN INTERFACE
106
+ # ============================================================================
107
+
108
+ wagon_train_mode:
109
+ description: "Wagons must implement run_train() to participate in trains"
110
+
111
+ signature: "def run_train(inputs: Dict[str, Any], timing: Dict[str, float] = None) -> Dict[str, Any]"
112
+
113
+ location: "python/{wagon}/wagon.py (module-level function or class method)"
114
+
115
+ responsibilities:
116
+ - "Extract relevant artifacts from cargo (inputs dict)"
117
+ - "Execute wagon business logic"
118
+ - "Return artifact dictionary (URN → data)"
119
+ - "Handle timing configuration (delays, timeouts)"
120
+
121
+ example: |
122
+ # python/pace_dilemmas/wagon.py
123
+ def run_train(inputs: Dict[str, Any], timing: Dict[str, float] = None) -> Dict[str, Any]:
124
+ """Train mode: Execute wagon in train orchestration."""
125
+ # Extract inputs
126
+ fragments = inputs.get("fragments", [])
127
+ domain_scores = inputs.get("domain_scores", {})
128
+
129
+ # Execute logic
130
+ dilemma = pair_fragments_use_case.execute(fragments, domain_scores)
131
+
132
+ # Return artifacts (URN → data)
133
+ return {
134
+ "match:dilemma.selected": {"dilemma_id": dilemma.id, ...},
135
+ "mechanic:quiz.progress": {"answered_count": 1, ...}
136
+ }
137
+
138
+ multi_mode_pattern:
139
+ description: "Wagons support multiple execution modes"
140
+ cli: "Interactive demo (python3 wagon.py)"
141
+ http: "API endpoints (via game.py)"
142
+ train: "Production orchestration (via TrainRunner)"
143
+
144
+ # ============================================================================
145
+ # CARGO AND ARTIFACTS
146
+ # ============================================================================
147
+
148
+ cargo_pattern:
149
+ description: "Cargo carries artifacts between wagons during execution"
150
+
151
+ cargo_model:
152
+ structure: "Dict[artifact_urn, artifact_data]"
153
+ operations:
154
+ - "cargo.add_artifact(urn, data)"
155
+ - "cargo.get_artifact(urn)"
156
+ - "cargo.has_artifact(urn)"
157
+
158
+ artifact_flow: |
159
+ Step 1: pace_dilemmas produces match:dilemma.selected
160
+ Cargo: {"match:dilemma.selected": {...}}
161
+
162
+ Step 2: resolve_dilemmas consumes match:dilemma.selected, produces mechanic:decision.choice
163
+ Cargo: {"match:dilemma.selected": {...}, "mechanic:decision.choice": {...}}
164
+
165
+ Step 3: Artifacts accumulate as train progresses
166
+
167
+ contract_validation:
168
+ validator: "e2e/shared/fixtures/contract_validator.py"
169
+ schemas: "contracts/{theme}/{domain}/{resource}.schema.json"
170
+ method: "JSON Schema Draft-07 validation"
171
+
172
+ # ============================================================================
173
+ # STATION MASTER PATTERN (game.py)
174
+ # ============================================================================
175
+
176
+ station_master:
177
+ description: "game.py becomes thin router that delegates to TrainRunner"
178
+
179
+ pattern: |
180
+ # game.py - Station Master
181
+ from trains.runner import TrainRunner
182
+
183
+ JOURNEY_MAP = {
184
+ "start_quiz": "1006-quiz-workflow-adaptive",
185
+ "start_match": "3001-solo-match-complete"
186
+ }
187
+
188
+ @app.post("/action/{action_name}")
189
+ def execute_journey(action_name: str, inputs: dict):
190
+ train_id = JOURNEY_MAP[action_name]
191
+ runner = TrainRunner(f"plan/_trains/{train_id}.yaml")
192
+ result = runner.execute(inputs=inputs)
193
+ return {"success": result.success, "artifacts": result.artifacts}
194
+
195
+ responsibilities:
196
+ - "Route user actions to train IDs"
197
+ - "Invoke TrainRunner"
198
+ - "Translate HTTP ↔ artifacts"
199
+ - "Handle errors"
200
+
201
+ anti_pattern: "Business logic in game.py (belongs in trains/wagons)"
202
+
203
+ # ============================================================================
204
+ # TESTING
205
+ # ============================================================================
206
+
207
+ testing_pattern:
208
+ description: "Tests use production TrainRunner - no mocks, zero drift"
209
+
210
+ e2e_tests:
211
+ location: "e2e/mechanic/test_1006_quiz_workflow_adaptive.py"
212
+
213
+ pattern: |
214
+ def test_ac001_all_dilemmas_selected(train_runner, contract_validator):
215
+ # Execute train (production code)
216
+ result = train_runner.execute(
217
+ train_id="1006-quiz-workflow-adaptive",
218
+ inputs={"quiz_config": {...}}
219
+ )
220
+
221
+ # Validate artifacts
222
+ assert result.success
223
+ contract_validator.validate(
224
+ result.artifacts["mechanic:quiz.completed"],
225
+ "contracts/mechanic/quiz/completed.schema.json"
226
+ )
227
+
228
+ # Assert acceptance criteria
229
+ assert result.artifacts["mechanic:quiz.completed"]["answered_count"] == 10
230
+
231
+ fixtures:
232
+ train_runner:
233
+ source: "from trains.runner import TrainRunner (production)"
234
+ location: "e2e/conftest.py"
235
+
236
+ contract_validator:
237
+ source: "e2e/shared/fixtures/contract_validator.py (real JSON schema validator)"
238
+ library: "jsonschema"
239
+
240
+ # ============================================================================
241
+ # BOUNDARIES
242
+ # ============================================================================
243
+
244
+ boundary_enforcement:
245
+ no_direct_imports:
246
+ rule: "Wagons NEVER import from other wagons"
247
+ enforcement: "TrainRunner uses dynamic imports, artifacts only"
248
+
249
+ contract_communication:
250
+ rule: "Wagons communicate exclusively via artifact contracts"
251
+ enforcement: "Contract schemas validate structure"
252
+
253
+ qualified_imports:
254
+ rule: "All imports fully qualified (from {wagon}.{feature}.src.{layer}...)"
255
+ benefit: "Prevents module shadowing"
256
+
257
+ composition_root_exception:
258
+ rule: "Composition roots may manipulate sys.path"
259
+ files: ["python/trains/runner.py", "python/{wagon}/wagon.py"]
260
+ rationale: "Entrypoints (executed, never imported)"
261
+
262
+ # ============================================================================
263
+ # OBSERVABILITY
264
+ # ============================================================================
265
+
266
+ observability:
267
+ execution_trace:
268
+ enabled: "runner.execute(capture_trace=True)"
269
+ structure: "List[{step, wagon, duration_ms, success, error}]"
270
+
271
+ logging:
272
+ include_train_id: "All log entries include train_id"
273
+ correlation: "train_id + timestamp for cross-wagon correlation"
274
+ replay: "Reproduce execution with train_id + inputs"
275
+
276
+ # ============================================================================
277
+ # MIGRATION GUIDE
278
+ # ============================================================================
279
+
280
+ migration:
281
+ step_1: "Identify user journeys in game.py"
282
+ step_2: "Create train YAML (plan/_trains/{train_id}.yaml)"
283
+ step_3: "Add run_train() to participating wagons"
284
+ step_4: "Refactor game.py to Station Master pattern"
285
+ step_5: "Update tests to use TrainRunner"
286
+
287
+ # ============================================================================
288
+ # ANTI-PATTERNS
289
+ # ============================================================================
290
+
291
+ anti_patterns:
292
+ business_logic_in_runner:
293
+ problem: "TrainRunner contains business logic"
294
+ correct: "Business logic in wagons, TrainRunner only orchestrates"
295
+
296
+ wagon_imports_wagon:
297
+ problem: "Wagon A imports from wagon B"
298
+ correct: "Wagons communicate via artifacts in cargo"
299
+
300
+ test_only_trains:
301
+ problem: "Separate trains for tests vs production"
302
+ correct: "Production trains ARE test subjects"
303
+
304
+ mocking_train_runner:
305
+ problem: "Tests mock TrainRunner"
306
+ correct: "Tests use real TrainRunner"
307
+
308
+ # ============================================================================
309
+ # EXAMPLES
310
+ # ============================================================================
311
+
312
+ examples:
313
+ simple:
314
+ train_id: "1001-decision-standard"
315
+ wagons: ["pace-dilemmas", "resolve-dilemmas", "commit-state"]
316
+
317
+ complex:
318
+ train_id: "1006-quiz-workflow-adaptive"
319
+ wagons: ["supply-fragments", "pace-dilemmas", "juggle-domains", "resolve-dilemmas"]
320
+ artifacts:
321
+ - "match:dilemma.selected"
322
+ - "mechanic:decision.choice"
323
+ - "scenario:graph.pagerank"
324
+ - "mechanic:domain.associations"
325
+ - "mechanic:quiz.completed"
@@ -0,0 +1,53 @@
1
+ protocol: refactor_verification
2
+ constraint: "ATDD - Refactor MUST preserve GREEN"
3
+
4
+ before_refactor:
5
+ - id: check_initial_state
6
+ steps:
7
+ - run: pytest
8
+ expect: all_pass
9
+ on_fail: "BLOCKED - fix tests before refactoring"
10
+
11
+ - run: git status --porcelain
12
+ expect: clean_or_staged_only
13
+ on_fail: "WARN - uncommitted changes detected"
14
+
15
+ during_refactor:
16
+ per_step:
17
+ - apply_with_journal:
18
+ before: capture_pre_state
19
+ transform: execute_step
20
+ after: capture_diff
21
+ save: journal_entry
22
+
23
+ - verify_step:
24
+ run: pytest
25
+ on_pass: continue_to_next_step
26
+ on_fail:
27
+ - rollback: journal.rollback_step(current_step_id)
28
+ - abort: "Step failed verification"
29
+
30
+ after_refactor:
31
+ - id: final_verification
32
+ steps:
33
+ - run: pytest
34
+ expect: all_pass
35
+ on_fail:
36
+ - rollback: journal.rollback_batch(all_steps)
37
+ - abort: "Final verification failed - all changes rolled back"
38
+
39
+ - report: "Refactor successful - all tests GREEN"
40
+
41
+ rollback:
42
+ method: "Git-based with structured logging"
43
+ implementation: "git restore (runtime helpers archived)"
44
+ how: "git restore --source=HEAD -- <files>"
45
+ logging: "agent.log with trace_id for auditability"
46
+
47
+ on_step_fail:
48
+ - log_refactor_step_end(step_id, "RED", trace_id)
49
+ - rollback_refactor_step(files, trace_id=trace_id)
50
+
51
+ on_final_fail:
52
+ - rollback_refactor_step(all_files, trace_id=trace_id)
53
+ - git checkout - (return to original branch)