--- id: RAIL-FAB-WP-0022 type: workplan title: "Promote graph zones to first-class visualization entities" domain: railiance repo: railiance-fabric status: finished owner: codex topic_slug: railiance-fabric created: "2026-05-24" updated: "2026-05-24" state_hub_workstream_id: "343f8383-ba5e-4d60-b55e-81611954d9b9" --- # Promote Graph Zones To First-Class Visualization Entities ## Context RAIL-FAB-WP-0021 introduced labeled zone boundary overlays in the graph explorer. That gave the operator a useful visual grouping by deployment environment and access zone, but the zones are still derived directly inside the UI as overlay rectangles around already-rendered nodes. The next direction is described in `docs/ZoneEntityVisualization.md`: zones should become first-class visualization entities beside nodes and edges. A zone is a drawing surface for part of the graph, with declarative membership rules, optional attraction rules, rendering height, diagnostics, and eventually collapse/drill-down behavior. This workplan moves toward that model without forcing a large rewrite in one step. ## Task 1: Define The Zone View Model ```task id: RAIL-FAB-WP-0022-T01 status: done priority: high state_hub_task_id: "636b14f7-e5c7-4d5d-acda-40f0c270cd29" ``` Define an internal zone view model that can represent: - zone definitions - resolved zone instances - node assignments - edge summaries - cross-zone boundary edges - membership and attraction diagnostics - presentation metadata such as label, color, and height The model should be serializable enough to support saved graph profiles later, but it does not need a persistence store in this task. Expected result: a small typed model or schema with tests for construction and basic serialization. Result: Added `railiance_fabric.zone_view` dataclasses for zone definitions, attraction rules, layout, presentation, collapse settings, resolved zone instances, node assignments, boundary edges, diagnostics, and serializable resolution output. Covered definition round-trip and resolution serialization in `tests/test_zone_view.py`. ## Task 2: Implement A Pure Zone Resolver ```task id: RAIL-FAB-WP-0022-T02 status: done priority: high state_hub_task_id: "d0ca41d2-f7c4-4409-8799-4c0099192af5" ``` Implement a pure resolver that accepts graph nodes, graph edges, and zone definitions, then returns resolved zone instances. The first resolver should support a conservative rule subset: - membership operators: `equals`, `in`, `exists` - rule composition: `all`, `any` - attraction by edge type, direction, and depth - single-zone assignment invariant - conflict diagnostics when rules overlap Expected result: resolver unit tests that prove deterministic node assignment, seed-vs-attraction precedence, conflict reporting, and depth-limited attraction. Result: Implemented `resolve_zones()` as a pure resolver over Cytoscape-style or raw node/edge mappings. It supports `equals`, `in`, `exists`, `all`, `any`, membership `rules`, edge-type/direction/depth attraction, seed precedence, height/order conflict resolution, single-zone node assignments, boundary edge summaries, and conflict diagnostics. Covered the core behavior in `tests/test_zone_view.py`. ## Task 3: Back The Existing Overlays With Zone Definitions ```task id: RAIL-FAB-WP-0022-T03 status: done priority: high state_hub_task_id: "c89d8d53-72a4-4590-a0e5-67b012c3550c" ``` Replace the graph explorer's hard-coded environment/access overlay grouping logic with resolver-backed default zone definitions. The current operator-facing behavior should remain available: - deployment environment grouping renders `dev-tegwick`, `test`, and `prod` - legacy `staging` evidence maps to `test` - `all` is not rendered as a deployment environment zone - access-zone grouping remains available when access-zone metadata exists - visible nodes must be assigned to no more than one rendered zone Expected result: existing graph explorer tests continue to pass, with new tests showing that the UI obtains zone rectangles from resolved zone instances. Result: Refactored the graph explorer overlay to use explicit default zone definitions and a client-side `resolveZoneInstances()` path. Deployment environment zones now resolve through declarative membership rules with `deploymentEnvironment` normalization for `dev` -> `dev-tegwick`, `test`/`staging` -> `test`, `prod` -> `prod`, and ignored `all` values. Access zone overlays are generated as dynamic definitions from visible graph evidence. The overlay keeps the single-zone visible-node assignment behavior while preserving edge evidence in zone details. ## Task 4: Add Zone Diagnostics To The Explorer ```task id: RAIL-FAB-WP-0022-T04 status: done priority: medium state_hub_task_id: "d140cb5b-6a35-4cb0-ab68-e39e708c08e9" ``` Expose zone resolver diagnostics in the graph explorer without overwhelming the map. Diagnostics should include at least: - node matched by more than one zone - node attracted by more than one zone - zone definition produced no seed nodes - attraction reached its configured depth limit - edge crosses zone boundaries Expected result: zone detail panels show scoped diagnostics, and tests verify that diagnostics are generated by the resolver rather than ad hoc UI checks. Result: Added resolver diagnostics for empty seed sets, overlapping zone membership, attraction depth-limit stops, and boundary-crossing edges. The graph explorer now surfaces scoped zone diagnostics in the selected zone detail panel and orientation context, with assertions proving diagnostics come from the zone resolver path. ## Task 5: Persist Zone View Settings In Profiles ```task id: RAIL-FAB-WP-0022-T05 status: done priority: medium state_hub_task_id: "765caa50-f372-4ab4-adb4-87660e684c54" ``` Extend saved graph profile state so profiles can remember zone configuration. At minimum, preserve: - whether zones are visible - active zone definition set - active zone grouping - zone presentation preferences that are already supported by the UI Expected result: saved views restore the same zone mode and default definition set after reload. Result: Added explicit nested zone state to graph explorer profiles with `visible`, `grouping`, `definitionSet`, and `presentation` fields while keeping legacy URL aliases for `zoneBoundaries`, `zoneGrouping`, and `zoneDefinitionSet`. Saved and copied views now preserve the active zone definition set and presentation state, and profile restore normalizes unknown future definition sets back to the Fabric default. ## Task 6: Prototype Collapse-To-Zone-Node ```task id: RAIL-FAB-WP-0022-T06 status: done priority: medium state_hub_task_id: "7f3676cb-3d2e-417c-a385-f95545bcd738" ``` Prototype collapsing a resolved zone into a representative node while preserving external connectivity in the visible graph. The prototype should: - hide nodes assigned to the collapsed zone - render a zone node with summary metadata - reconnect external edges to the zone node for the current view - hide or summarize internal edges - expand back to the original view without data loss Expected result: collapse behavior works for one zone at a time and is covered by focused tests. Multi-zone hierarchy can remain future work. Result: Added a view-only zone collapse prototype to the graph explorer. Zone detail panels now offer `Collapse Zone`; collapsed zones hide member nodes, render a synthetic zone node with node/internal-edge/boundary-edge summaries, draw synthetic boundary edges to visible external neighbors, and expose `Expand Zone` from the collapsed zone node. Expanding removes synthetic elements and restores the original graph view without changing the underlying payload. ## Task 7: Prepare For Per-Zone Layout ```task id: RAIL-FAB-WP-0022-T07 status: done priority: low state_hub_task_id: "4b6f0b7e-a066-490d-8160-ba23b03cf820" ``` Identify the UI and Cytoscape integration changes needed for each zone to use a different layout algorithm for its assigned subgraph. This task should not attempt a full layout rewrite unless the preceding tasks make it small and safe. It should produce either a narrow implementation step or a follow-up workplan for two-phase layout. Expected result: the codebase has a documented path toward per-zone layouts without destabilizing the current graph explorer. Result: Documented the per-zone layout preparation path in `docs/ZoneEntityVisualization.md`. The recommended direction is a two-phase layout: resolve zones and containers first, then compute local zone coordinates and project them into Cytoscape space. The note identifies the prerequisites already established by WP-0022 and avoids a premature nested-layout rewrite. ## Acceptance Criteria - Zone entity behavior is documented in `docs/ZoneEntityVisualization.md`. - Zone definitions and resolved zone instances exist as explicit internal concepts. - The current deployment/access overlay behavior is implemented through the zone resolver. - The graph explorer keeps the single-zone assignment invariant for visible nodes. - Zone diagnostics are available to the operator. - Saved graph views can preserve supported zone settings. - Collapse-to-zone-node is prototyped behind clear UI behavior or an explicit experimental switch.