Skip to content

Feature/UI - #55

Merged
AadilLatif merged 19 commits into
mainfrom
feature/ui
Jul 30, 2026
Merged

Feature/UI#55
AadilLatif merged 19 commits into
mainfrom
feature/ui

Conversation

@AadilLatif

Copy link
Copy Markdown
Collaborator

Change Summary

Related issue number

Checklist

  • The pull request title is a good summary of the changes.
  • Tests for the changes exist
  • Tests pass on CI
  • Documentation reflects the changes where applicable
  • My PR is ready to review, please add a comment including "please review" to assign reviewers

- New optional 'flow' extra: pip install nrel-shift[flow]
- POST /api/system/fix-violations endpoint runs iterative fix loop
- UI shows 'Fix Violations' button after successful system build
- Returns iteration details, action descriptions, and fixed model download
- Graceful 501 if gdm-flow not installed
- ExistingGraphRouter: road-network routing over OSM with SHIFT routing
  strategies (MST/Steiner/shortest-path) plus relaxation-embedding fallback
- get_cluster: shared capacity-and-distance clustering util; cluster_parcels
  MCP tool gains strategy + capacity/distance params
- ui_api delegates capacity-distance clustering to the shared util
- balanced_phase_mapper: clamp cluster count to sample size; drop stray breakpoint
- mappers/builder/parcels: voltage/equipment/phase fixes, PBF-first parcels
- ignore .dump/ PBF and gates_system_* build artifacts
Marry the generated topology with road-following routing: embed the
abstract graph to derive per-edge geographic 'corridors', then bias the
road-graph edge weights (via WeightedSteinerTreeStrategy weight_fn) so
segments along those corridors are cheaper. routing_strategy='biased'
with topology_bias in [0,1] (0=shortest roads, 1=hug topology).
Shared _relaxed_positions refactored out of _embed.
Add an extensible LayoutStrategy abstraction (shift/graph/layout.py) with a
SpringLayoutStrategy that force-directed-lays out an abstract topology and
confines it to a polygon (fit to bbox, pull outliers inside the shape), pinning
the source at the substation. ExistingGraphRouter gains optional polygon +
layout_strategy params and branches its embedding accordingly, reusing the same
transformer-explosion machinery so the built DistributionGraph is unchanged
downstream. New MCP tool layout_existing_graph exposes it (validates the
substation is inside the polygon); a registry lets new layouts plug in by name.
_get_closest_transformer_equipment already synthesizes from a voltage-compatible
template, but raised EquipmentNotFoundError when none existed (e.g. a 3-phase
7.2/7.2 kV request against a catalog whose only 3-phase unit is a 39.8->7.2 kV
substation transformer). Add a full-synthesis fallback: build a transformer from
any phase-compatible template (or any transformer) and override its winding
voltages/capacity to the requested values, so the build never fails on an
unusual voltage pairing. Drop the now-unused comparable_candidates logging.
…s to public API

- Replace FastMCP with MCPServer (mcp>=2.0)
- Fix Context type annotation (single generic param in 2.0)
- Fix static resources (no Context injection in 2.0)
- Extract clustering, geo, graph utils, and strategy resolver from ui_api/app.py into public modules
- Export TrunkBranchStrategy, new clustering functions, graph utilities from shift.__init__
- Update pyproject.toml mcp requirement to >=2.0
- B314: replace xml.etree.ElementTree.parse with defusedxml equivalent
- B306: replace insecure mktemp with mkstemp
- B110: suppress or fix bare try/except/pass patterns
- Add defusedxml to dependencies
- Extract snap_cluster_to_road utility from snap-to-roads endpoint
- Extract _load_road_graph_for_snap helper from create_app
- Extract _try_local_pbf_road_network from get_road_network
- Extract _fetch_road_graph_by_location from get_road_network
- Extract _filter_to_public_roads from get_road_network
- Split TrunkBranchStrategy.build into build + _build_road_trunk_branch
- Fix B110: replace bare pass with descriptive assignment in parcels.py
- Extract validateClusterInputs, validateFixLoopInputs from app.js
- Extract fetchParcelsForQuickBuild, buildQuickGraphAndSystem from quick-build
- Split _build_road_trunk_branch into smaller helpers
…xity

- Extract _is_phase_compatible and _is_voltage_compatible as static methods
- Move synthesis branches into _synthesize_transformer, _synthesize_capacity_override, _synthesize_full_override
- Eliminate nested closure functions that inflate complexity score
Decompose the 1200-line create_app() into 6 focused registration
functions grouped by domain. The orchestrator is now ~20 lines.
Individual registrars retain noqa:C901 as their complexity is inherent
to multi-route registration (not algorithmic branching).
@AadilLatif
AadilLatif merged commit 6b19a86 into main Jul 30, 2026
18 of 19 checks passed
@AadilLatif
AadilLatif deleted the feature/ui branch July 30, 2026 20:15
github-actions Bot pushed a commit that referenced this pull request Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant