You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Highest-risk sprint in the pillar. Gates p2-s6 (Lane Carve).
The problem
regenerate_junction refuses any turn-set change, twice:
"regeneration changed the connection count; delete and recreate the junction"
"regeneration changed the turn set; delete and recreate the junction"
and the editor swallows the failure into a warning toast rather than failing the user's edit (document.cpp). So today: add a lane to a road feeding a junction → the junction does not update and stays stale until the user deletes and recreates it. GW-2 step 12 carves a turn lane "approaching the junction" — exactly the refused case.
The restriction is not incidental: regen's ability to preserve connecting-road ids (and therefore keep undo exact) depends on a fixed connection count.
Decision (maintainer, 2026-07-15): teach regen turn-set changes. A turn lane that cannot reach a junction is a hollow feature.
Scope
Regen allocates ids for new turns, erase_exacts removed ones, and rewrites the connection table, keeping undo exact. Turn matching is already by key rather than by order — that half is done.
GenericCommand's creator/erased/before/after sets already support this shape; no new command machinery.
Interior lane insert with renumbering + link remap (moved here from p2-s1: kernel lane-section foundations (split, width profiles, interior lanes) #262, maintainer-approved 2026-07-15). add_lane is outermost-only today; Lane Form and Lane Carve need an interior insert, which means renumbering lanes outward and remapping every link that named them — the neighbouring sections' predecessor/successor links andJunctionConnection::lane_links.
It moved here because that remap is the same problem this sprint already owns: junction lane_links reference only a road's end sections, and inserting a lane in an end section changes the turn set — the case regen refuses today. Implementing it in p2-s1: kernel lane-section foundations (split, width profiles, interior lanes) #262 meant writing an unexercisable end-section path against a contract this sprint redefines. remove_lane already clears those links rather than remapping; generalize that here, once.
The new lane must NOT be linked back to the neighbouring sections: a lane that appears is not connected to the original (asam.net:xodr:1.4.0:road.lane.link.new_lane_appear).
Refactorings
regenerate_junction becomes a topology-changing command. This collides with the editor's dirty-set contract: document.cpp deliberately breaks out of the regen loop when dirty.topology is set, so create/delete/split don't self-regenerate. The contract needs a third state (topology-changed-and-regenerate).
Resolve that contract on paper in this issue before writing code.
Acceptance
Add a lane to a junction arm → the junction regenerates; no warning toast. This case has no test today because the answer was "refuse".
No-op regen stays byte-identical — RegenerateJunctionIsByteEqualWhenNothingChanged must stay green.
verify_junction_welds reports no breach after a turn-set change.
Undo restores the exact connection table and connecting-road ids.
Soak driver exercises lane edits on junction arms; ASan clean.
Out of scope
Junction interior geometry changes; corner radius and per-corner materials (P4).
Note
If this sprint overruns, stop and report. p2-s6 depends on it, and the fallback (carve refuses near junction arms) is a GW-2 amendment requiring maintainer approval — not a silent deviation.
Part of the Road to Parity roadmap. Epic #251. Ground truth: p2_discovery.md §4.
Highest-risk sprint in the pillar. Gates p2-s6 (Lane Carve).
The problem
regenerate_junctionrefuses any turn-set change, twice:"regeneration changed the connection count; delete and recreate the junction""regeneration changed the turn set; delete and recreate the junction"and the editor swallows the failure into a warning toast rather than failing the user's edit (
document.cpp). So today: add a lane to a road feeding a junction → the junction does not update and stays stale until the user deletes and recreates it. GW-2 step 12 carves a turn lane "approaching the junction" — exactly the refused case.The restriction is not incidental: regen's ability to preserve connecting-road ids (and therefore keep undo exact) depends on a fixed connection count.
Decision (maintainer, 2026-07-15): teach regen turn-set changes. A turn lane that cannot reach a junction is a hollow feature.
Scope
Regen allocates ids for new turns,
erase_exacts removed ones, and rewrites the connection table, keeping undo exact. Turn matching is already by key rather than by order — that half is done.GenericCommand's creator/erased/before/after sets already support this shape; no new command machinery.Interior lane insert with renumbering + link remap (moved here from p2-s1: kernel lane-section foundations (split, width profiles, interior lanes) #262, maintainer-approved 2026-07-15).
add_laneis outermost-only today; Lane Form and Lane Carve need an interior insert, which means renumbering lanes outward and remapping every link that named them — the neighbouring sections' predecessor/successor links andJunctionConnection::lane_links.It moved here because that remap is the same problem this sprint already owns: junction
lane_linksreference only a road's end sections, and inserting a lane in an end section changes the turn set — the case regen refuses today. Implementing it in p2-s1: kernel lane-section foundations (split, width profiles, interior lanes) #262 meant writing an unexercisable end-section path against a contract this sprint redefines.remove_lanealready clears those links rather than remapping; generalize that here, once.The new lane must NOT be linked back to the neighbouring sections: a lane that appears is not connected to the original (asam.net:xodr:1.4.0:road.lane.link.new_lane_appear).
Refactorings
regenerate_junctionbecomes a topology-changing command. This collides with the editor's dirty-set contract:document.cppdeliberatelybreaks out of the regen loop whendirty.topologyis set, so create/delete/split don't self-regenerate. The contract needs a third state (topology-changed-and-regenerate).Acceptance
RegenerateJunctionIsByteEqualWhenNothingChangedmust stay green.verify_junction_weldsreports no breach after a turn-set change.Out of scope
Junction interior geometry changes; corner radius and per-corner materials (P4).
Note
If this sprint overruns, stop and report. p2-s6 depends on it, and the fallback (carve refuses near junction arms) is a GW-2 amendment requiring maintainer approval — not a silent deviation.
Supersedes
(none)