# Implementation Plan ## Checklist 1. Capture a parity baseline before product-code edits. 2. Add `blender/osmassets/roads.py` with current GeoJSON road layer assembly and OSM fallback logic. 3. Import `roads.py` in `blender/generate_scene.py`. 4. Remove inline `add_geojson_layer()` from `generate_scene.py`. 5. Replace the GeoJSON road layer call site with `roads.assemble_geojson_layer(...)`. 6. Replace the OSM fallback loop with `roads.assemble_osm_fallback(...)`. 7. Run Python validation: - `python3 -m py_compile blender/osmassets/roads.py` - `python3 -m py_compile blender/generate_scene.py` - `python3 -m unittest blender/tests/test_pure.py` 8. Capture parity after the refactor. 9. Compare before/after parity snapshots and inspect any non-ignored diff. 10. Update `.trellis/spec` and `docs/changelog.md` only for durable status or convention changes discovered during implementation. 11. Commit, archive the task, and record the journal entry. ## Validation Commands ```bash node scripts/parity.js capture road-module-before --stages blender,cesium python3 -m py_compile blender/osmassets/roads.py python3 -m py_compile blender/generate_scene.py python3 -m unittest blender/tests/test_pure.py node scripts/parity.js capture road-module-after --stages blender,cesium node scripts/parity.js compare road-module-before road-module-after ``` ## Risk Points - `ROAD_LAYERS` order is load-bearing. Do not reorder, filter, or copy it into a second list. - `road_counts` must remain owned by `generate_scene.py`; fallback roads must still leave it unchanged. - `Layer catalog warning:` print text must remain unchanged because it is the only runtime warning for JS/Python layer drift. - `Road_` and `OSM_Road_` names affect parity digests. - `clip_polygon()` and `feature_in_bounds()` behavior must be reused exactly; do not replace with new geometry logic. - Parity is mandatory because this is a pure refactor of bpy-layer scene generation.