chore(meta): activate T-1076 road-hub batch — Si refinement + gap resolutions (incl. scope item 0: placement-map re-tune per Jeroen)

This commit is contained in:
2026-07-16 15:35:04 +02:00
parent 9336209ea9
commit f5bb71736b
2 changed files with 114 additions and 0 deletions
+36
View File
@@ -1336,3 +1336,39 @@ INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, chang
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCDG73S4ET8KKTK62Z5KFEQM', 'status', 'in_progress', 'review', NULL, '2026-07-16 09:49:28', '2026-07-16 09:49:28.604', '2026-07-16 09:49:28.604', NULL, '7be819d7fe6d3c5613640599658348d4', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCDG73NW7SNCA5Y8JN905QMR', 'status', 'review', 'done', NULL, '2026-07-16 11:08:50', '2026-07-16 11:08:50.978', '2026-07-16 11:08:50.978', NULL, 'd29af2ba9bc5ff62a5d55990eea82614', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCDG73S4ET8KKTK62Z5KFEQM', 'status', 'review', 'done', NULL, '2026-07-16 11:08:50', '2026-07-16 11:08:50.980', '2026-07-16 11:08:50.980', NULL, '2b775e39c956ac93cd4a6bacbbc8cedc', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCDG73V9R6N024QSFDEJ4R68', 'description', 'Follow-on to T-1038 (road-graph core shipped). Hub-selection refinement, gated on the resolved settlement model (D-242).
Build on server/src/atlas/road_graph.rs:
1. Hub selection: ''real cities, scaled cap'' wiki cities anchor the MST; cap scales with body size; standalone HQs/minor settlements are non-hub.
2. Co-location collapse: group same-named settlements (defensive; the D-242 corp-HQ fix removes most at source).
3. Hybrid minor-settlement attach: snap to nearest existing road edge if close, else spur to nearest hub (add edge-split-at-attach).
4. RailHeadFacing junction pass (T-1038 step 6, deferred): junction settlements (RoadGraph::high_connectivity_junctions already computed) get FoundingOrientation::RailHeadFacing. REQUIRES a D-213 amendment (adopted enum has no RailHeadFacing) + Layer-4 skeleton_gen handling.
Needs population ranking blocked on the corp-HQ-model + population-bake tickets.', 'Follow-on to T-1038 (road-graph core shipped). Hub-selection refinement, gated on the resolved settlement model (D-242).
Build on server/src/atlas/road_graph.rs:
1. Hub selection: ''real cities, scaled cap'' wiki cities anchor the MST; cap scales with body size; standalone HQs/minor settlements are non-hub.
2. Co-location collapse: group same-named settlements (defensive; the D-242 corp-HQ fix removes most at source).
3. Hybrid minor-settlement attach: snap to nearest existing road edge if close, else spur to nearest hub (add edge-split-at-attach).
4. RailHeadFacing junction pass (T-1038 step 6, deferred): junction settlements (RoadGraph::high_connectivity_junctions already computed) get FoundingOrientation::RailHeadFacing. REQUIRES a D-213 amendment (adopted enum has no RailHeadFacing) + Layer-4 skeleton_gen handling.
Needs population ranking blocked on the corp-HQ-model + population-bake tickets.
---
Refinement (2026-07-16, /whats-next Si review + gap resolution with Jeroen):
SCOPE ITEM 0 (added placement-map correction, precedes hub work): corp_hq_placement.toml over-generalized D-242''s Standalone boundary (bulk_class != NonPhysical -> Standalone gave 95 Standalone / 60 CityTenant, incl. distilleries/wineries/leatherworks as standalone belt settlements). Jeroen''s ruling, faithful to D-242''s own examples: Standalone ONLY where the HQ is itself an industrial complex / company town extraction/mining/quarrying, heavy vehicle + shipyard manufacturing, heavy energy (refinery/extraction complexes), gate/orbital infrastructure. Everything else CityTenant, explicitly including craft/consumer manufacturing (distilleries, breweries, wineries, ceramics, textiles, furniture), agriculture (estate offices sit in market towns), and high-tech fabs. Re-author per-value (judge each of the 31 value descriptions against this boundary), regen, and amend D-242 to state the boundary explicitly so it cannot be re-coarsened; record Jeroen''s "edge of settlement / clusters" color as CityTenant rendering detail for later phases, not a third placement class.
1. Hub selection (gap: no cap formula, no HQ-row identity): RESOLUTION thread an is_standalone_hq flag through read_body_settlements/CityRecord (join corporations.headquarters_body + proper_name where hq_placement=''Standalone''; the city_context_reader.rs:1165-1170 test comment predicted exactly this threading). Hubs = top-cap by population among NON-HQ cities; cap scales with body size via a documented inline constant (existing workshop-tunable pattern in road_graph.rs), sanity-checked on 2-3 bodies of different sizes.
2. Co-location collapse (gap: zero live cases, no rule): RESOLUTION ship trivial defensive: exact (body_id, name) match collapses to one node keeping lowest id, loud log warning when it ever fires.
3. Hybrid minor-settlement attach (gap: no snap threshold, no edge-split machinery): RESOLUTION engineer''s judgment: design the edge-split representation + pick the snap threshold as a documented inline constant; extend the RoadEdge/RoadNode invariants and the ten existing unit tests accordingly.
4. RailHeadFacing (well-specified per Si): add the FoundingOrientation variant (consumers use if-let, no exhaustive-match break), assign via existing RoadGraph::high_connectivity_junctions (degree >= 3, matches D-213''s paula-round3 source), amend D-213, and make the skeleton_gen rotation call inline (Si''s suggested default: face the junction''s dominant incident-edge bearing).
Deferred (no preference given): standalone-HQ Zipf population shares stay as-is (e.g. Gate Corporation 909M on GJ251c); the item-0 re-tune shrinks standalone rows to genuine company-towns where a real share is defensible. Revisit if Atlas numbers read wrong.
Si verification notes: road_graph.rs has NO hub concept and NO edge-split machinery today (T-1038 treats every placement as a uniform MST node); RoadGraph::high_connectivity_junctions() exists (JUNCTION_DEGREE=3); FoundingOrientation consumers are founding_orientation() and coastal_edge() (if-let, safe); skeleton_gen has zero rail-facing rotation logic (new work, scoped); PR #177 data preconditions verified (population>0 + settlement_class on all rows; standalone HQs present as ordinary rows).', NULL, '2026-07-16 13:34:35', '2026-07-16 13:34:35.724', '2026-07-16 13:34:35.724', NULL, 'be7de02b5348e09ea077e14d1e7be350', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCDG73V9R6N024QSFDEJ4R68', 'status', 'backlog', 'in_progress', NULL, '2026-07-16 13:34:42', '2026-07-16 13:34:42.070', '2026-07-16 13:34:42.070', NULL, '59512cd5b886bad98a03e3bbb106b07d', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCDG73V9R6N024QSFDEJ4R68', 'assigned_to', NULL, 'dudley', NULL, '2026-07-16 13:34:49', '2026-07-16 13:34:49.724', '2026-07-16 13:34:49.724', NULL, '974c9ac15c87788ce7b7bc1af07548d5', 2) ON CONFLICT(hash) DO NOTHING;
+78
View File
@@ -1682,3 +1682,81 @@ Refinement (2026-07-16, /whats-next Si review + gap resolution):
2. settlement_class assignment (gap): RESOLUTION default every pooled city to PopulationBudget; the D-196 thresholds (>=50k active / <5k ghost) decide state from the baked population. An authored NameLocked override list (small new source TOML) pins hero cities. EconomicTriggered and OrganicGrowth are simulation-time classes per D-196 out of bake scope.
Si verification notes: 463 atlas_city_names rows, all population=0 / settlement_class NULL claim exact. match_cities (server/src/atlas/attractor_matching.rs) only READS these fields for tiering; nothing assigns them. D-242/D-223/D-211/D-196 chain is consistent; no conflicting open Q-records. Importer entry point: populate_atlas_city_names (tooling/economy-db/economy_import/atlas.py:61-141).', 'done', 'high', 'dudley', 'server', 'D-242', '2026-06-14 15:29:50', '2026-07-16 11:08:50.980', NULL, '308acb6c5b17ed676ed92d81f3dc160f', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCDG73V9R6N024QSFDEJ4R68', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Road-graph hub refinement — scaled-cap hubs + co-location collapse + hybrid minor attach + RailHeadFacing junction pass', 'Follow-on to T-1038 (road-graph core shipped). Hub-selection refinement, gated on the resolved settlement model (D-242).
Build on server/src/atlas/road_graph.rs:
1. Hub selection: ''real cities, scaled cap'' wiki cities anchor the MST; cap scales with body size; standalone HQs/minor settlements are non-hub.
2. Co-location collapse: group same-named settlements (defensive; the D-242 corp-HQ fix removes most at source).
3. Hybrid minor-settlement attach: snap to nearest existing road edge if close, else spur to nearest hub (add edge-split-at-attach).
4. RailHeadFacing junction pass (T-1038 step 6, deferred): junction settlements (RoadGraph::high_connectivity_junctions already computed) get FoundingOrientation::RailHeadFacing. REQUIRES a D-213 amendment (adopted enum has no RailHeadFacing) + Layer-4 skeleton_gen handling.
Needs population ranking blocked on the corp-HQ-model + population-bake tickets.
---
Refinement (2026-07-16, /whats-next Si review + gap resolution with Jeroen):
SCOPE ITEM 0 (added placement-map correction, precedes hub work): corp_hq_placement.toml over-generalized D-242''s Standalone boundary (bulk_class != NonPhysical -> Standalone gave 95 Standalone / 60 CityTenant, incl. distilleries/wineries/leatherworks as standalone belt settlements). Jeroen''s ruling, faithful to D-242''s own examples: Standalone ONLY where the HQ is itself an industrial complex / company town extraction/mining/quarrying, heavy vehicle + shipyard manufacturing, heavy energy (refinery/extraction complexes), gate/orbital infrastructure. Everything else CityTenant, explicitly including craft/consumer manufacturing (distilleries, breweries, wineries, ceramics, textiles, furniture), agriculture (estate offices sit in market towns), and high-tech fabs. Re-author per-value (judge each of the 31 value descriptions against this boundary), regen, and amend D-242 to state the boundary explicitly so it cannot be re-coarsened; record Jeroen''s "edge of settlement / clusters" color as CityTenant rendering detail for later phases, not a third placement class.
1. Hub selection (gap: no cap formula, no HQ-row identity): RESOLUTION thread an is_standalone_hq flag through read_body_settlements/CityRecord (join corporations.headquarters_body + proper_name where hq_placement=''Standalone''; the city_context_reader.rs:1165-1170 test comment predicted exactly this threading). Hubs = top-cap by population among NON-HQ cities; cap scales with body size via a documented inline constant (existing workshop-tunable pattern in road_graph.rs), sanity-checked on 2-3 bodies of different sizes.
2. Co-location collapse (gap: zero live cases, no rule): RESOLUTION ship trivial defensive: exact (body_id, name) match collapses to one node keeping lowest id, loud log warning when it ever fires.
3. Hybrid minor-settlement attach (gap: no snap threshold, no edge-split machinery): RESOLUTION engineer''s judgment: design the edge-split representation + pick the snap threshold as a documented inline constant; extend the RoadEdge/RoadNode invariants and the ten existing unit tests accordingly.
4. RailHeadFacing (well-specified per Si): add the FoundingOrientation variant (consumers use if-let, no exhaustive-match break), assign via existing RoadGraph::high_connectivity_junctions (degree >= 3, matches D-213''s paula-round3 source), amend D-213, and make the skeleton_gen rotation call inline (Si''s suggested default: face the junction''s dominant incident-edge bearing).
Deferred (no preference given): standalone-HQ Zipf population shares stay as-is (e.g. Gate Corporation 909M on GJ251c); the item-0 re-tune shrinks standalone rows to genuine company-towns where a real share is defensible. Revisit if Atlas numbers read wrong.
Si verification notes: road_graph.rs has NO hub concept and NO edge-split machinery today (T-1038 treats every placement as a uniform MST node); RoadGraph::high_connectivity_junctions() exists (JUNCTION_DEGREE=3); FoundingOrientation consumers are founding_orientation() and coastal_edge() (if-let, safe); skeleton_gen has zero rail-facing rotation logic (new work, scoped); PR #177 data preconditions verified (population>0 + settlement_class on all rows; standalone HQs present as ordinary rows).', 'backlog', 'medium', NULL, 'server', 'D-242', '2026-06-14 15:29:50', '2026-07-16 13:34:35.724', NULL, '532facc26c7b83e10e29b101b608f82f', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCDG73V9R6N024QSFDEJ4R68', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Road-graph hub refinement — scaled-cap hubs + co-location collapse + hybrid minor attach + RailHeadFacing junction pass', 'Follow-on to T-1038 (road-graph core shipped). Hub-selection refinement, gated on the resolved settlement model (D-242).
Build on server/src/atlas/road_graph.rs:
1. Hub selection: ''real cities, scaled cap'' wiki cities anchor the MST; cap scales with body size; standalone HQs/minor settlements are non-hub.
2. Co-location collapse: group same-named settlements (defensive; the D-242 corp-HQ fix removes most at source).
3. Hybrid minor-settlement attach: snap to nearest existing road edge if close, else spur to nearest hub (add edge-split-at-attach).
4. RailHeadFacing junction pass (T-1038 step 6, deferred): junction settlements (RoadGraph::high_connectivity_junctions already computed) get FoundingOrientation::RailHeadFacing. REQUIRES a D-213 amendment (adopted enum has no RailHeadFacing) + Layer-4 skeleton_gen handling.
Needs population ranking blocked on the corp-HQ-model + population-bake tickets.
---
Refinement (2026-07-16, /whats-next Si review + gap resolution with Jeroen):
SCOPE ITEM 0 (added placement-map correction, precedes hub work): corp_hq_placement.toml over-generalized D-242''s Standalone boundary (bulk_class != NonPhysical -> Standalone gave 95 Standalone / 60 CityTenant, incl. distilleries/wineries/leatherworks as standalone belt settlements). Jeroen''s ruling, faithful to D-242''s own examples: Standalone ONLY where the HQ is itself an industrial complex / company town extraction/mining/quarrying, heavy vehicle + shipyard manufacturing, heavy energy (refinery/extraction complexes), gate/orbital infrastructure. Everything else CityTenant, explicitly including craft/consumer manufacturing (distilleries, breweries, wineries, ceramics, textiles, furniture), agriculture (estate offices sit in market towns), and high-tech fabs. Re-author per-value (judge each of the 31 value descriptions against this boundary), regen, and amend D-242 to state the boundary explicitly so it cannot be re-coarsened; record Jeroen''s "edge of settlement / clusters" color as CityTenant rendering detail for later phases, not a third placement class.
1. Hub selection (gap: no cap formula, no HQ-row identity): RESOLUTION thread an is_standalone_hq flag through read_body_settlements/CityRecord (join corporations.headquarters_body + proper_name where hq_placement=''Standalone''; the city_context_reader.rs:1165-1170 test comment predicted exactly this threading). Hubs = top-cap by population among NON-HQ cities; cap scales with body size via a documented inline constant (existing workshop-tunable pattern in road_graph.rs), sanity-checked on 2-3 bodies of different sizes.
2. Co-location collapse (gap: zero live cases, no rule): RESOLUTION ship trivial defensive: exact (body_id, name) match collapses to one node keeping lowest id, loud log warning when it ever fires.
3. Hybrid minor-settlement attach (gap: no snap threshold, no edge-split machinery): RESOLUTION engineer''s judgment: design the edge-split representation + pick the snap threshold as a documented inline constant; extend the RoadEdge/RoadNode invariants and the ten existing unit tests accordingly.
4. RailHeadFacing (well-specified per Si): add the FoundingOrientation variant (consumers use if-let, no exhaustive-match break), assign via existing RoadGraph::high_connectivity_junctions (degree >= 3, matches D-213''s paula-round3 source), amend D-213, and make the skeleton_gen rotation call inline (Si''s suggested default: face the junction''s dominant incident-edge bearing).
Deferred (no preference given): standalone-HQ Zipf population shares stay as-is (e.g. Gate Corporation 909M on GJ251c); the item-0 re-tune shrinks standalone rows to genuine company-towns where a real share is defensible. Revisit if Atlas numbers read wrong.
Si verification notes: road_graph.rs has NO hub concept and NO edge-split machinery today (T-1038 treats every placement as a uniform MST node); RoadGraph::high_connectivity_junctions() exists (JUNCTION_DEGREE=3); FoundingOrientation consumers are founding_orientation() and coastal_edge() (if-let, safe); skeleton_gen has zero rail-facing rotation logic (new work, scoped); PR #177 data preconditions verified (population>0 + settlement_class on all rows; standalone HQs present as ordinary rows).', 'in_progress', 'medium', NULL, 'server', 'D-242', '2026-06-14 15:29:50', '2026-07-16 13:34:42.064', NULL, '0a0a8e3b1ef8ae909a9e1fd756529e8a', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FCDG73V9R6N024QSFDEJ4R68', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Road-graph hub refinement — scaled-cap hubs + co-location collapse + hybrid minor attach + RailHeadFacing junction pass', 'Follow-on to T-1038 (road-graph core shipped). Hub-selection refinement, gated on the resolved settlement model (D-242).
Build on server/src/atlas/road_graph.rs:
1. Hub selection: ''real cities, scaled cap'' wiki cities anchor the MST; cap scales with body size; standalone HQs/minor settlements are non-hub.
2. Co-location collapse: group same-named settlements (defensive; the D-242 corp-HQ fix removes most at source).
3. Hybrid minor-settlement attach: snap to nearest existing road edge if close, else spur to nearest hub (add edge-split-at-attach).
4. RailHeadFacing junction pass (T-1038 step 6, deferred): junction settlements (RoadGraph::high_connectivity_junctions already computed) get FoundingOrientation::RailHeadFacing. REQUIRES a D-213 amendment (adopted enum has no RailHeadFacing) + Layer-4 skeleton_gen handling.
Needs population ranking blocked on the corp-HQ-model + population-bake tickets.
---
Refinement (2026-07-16, /whats-next Si review + gap resolution with Jeroen):
SCOPE ITEM 0 (added placement-map correction, precedes hub work): corp_hq_placement.toml over-generalized D-242''s Standalone boundary (bulk_class != NonPhysical -> Standalone gave 95 Standalone / 60 CityTenant, incl. distilleries/wineries/leatherworks as standalone belt settlements). Jeroen''s ruling, faithful to D-242''s own examples: Standalone ONLY where the HQ is itself an industrial complex / company town extraction/mining/quarrying, heavy vehicle + shipyard manufacturing, heavy energy (refinery/extraction complexes), gate/orbital infrastructure. Everything else CityTenant, explicitly including craft/consumer manufacturing (distilleries, breweries, wineries, ceramics, textiles, furniture), agriculture (estate offices sit in market towns), and high-tech fabs. Re-author per-value (judge each of the 31 value descriptions against this boundary), regen, and amend D-242 to state the boundary explicitly so it cannot be re-coarsened; record Jeroen''s "edge of settlement / clusters" color as CityTenant rendering detail for later phases, not a third placement class.
1. Hub selection (gap: no cap formula, no HQ-row identity): RESOLUTION thread an is_standalone_hq flag through read_body_settlements/CityRecord (join corporations.headquarters_body + proper_name where hq_placement=''Standalone''; the city_context_reader.rs:1165-1170 test comment predicted exactly this threading). Hubs = top-cap by population among NON-HQ cities; cap scales with body size via a documented inline constant (existing workshop-tunable pattern in road_graph.rs), sanity-checked on 2-3 bodies of different sizes.
2. Co-location collapse (gap: zero live cases, no rule): RESOLUTION ship trivial defensive: exact (body_id, name) match collapses to one node keeping lowest id, loud log warning when it ever fires.
3. Hybrid minor-settlement attach (gap: no snap threshold, no edge-split machinery): RESOLUTION engineer''s judgment: design the edge-split representation + pick the snap threshold as a documented inline constant; extend the RoadEdge/RoadNode invariants and the ten existing unit tests accordingly.
4. RailHeadFacing (well-specified per Si): add the FoundingOrientation variant (consumers use if-let, no exhaustive-match break), assign via existing RoadGraph::high_connectivity_junctions (degree >= 3, matches D-213''s paula-round3 source), amend D-213, and make the skeleton_gen rotation call inline (Si''s suggested default: face the junction''s dominant incident-edge bearing).
Deferred (no preference given): standalone-HQ Zipf population shares stay as-is (e.g. Gate Corporation 909M on GJ251c); the item-0 re-tune shrinks standalone rows to genuine company-towns where a real share is defensible. Revisit if Atlas numbers read wrong.
Si verification notes: road_graph.rs has NO hub concept and NO edge-split machinery today (T-1038 treats every placement as a uniform MST node); RoadGraph::high_connectivity_junctions() exists (JUNCTION_DEGREE=3); FoundingOrientation consumers are founding_orientation() and coastal_edge() (if-let, safe); skeleton_gen has zero rail-facing rotation logic (new work, scoped); PR #177 data preconditions verified (population>0 + settlement_class on all rows; standalone HQs present as ordinary rows).', 'in_progress', 'medium', 'dudley', 'server', 'D-242', '2026-06-14 15:29:50', '2026-07-16 13:34:49.724', NULL, '976f4eba75344d6e3f0ab9ba6393a5df', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);