--- id: RAIL-FAB-WP-0024 type: workplan title: "Stabilize zone containers and layout zone subgraphs" domain: railiance repo: railiance-fabric status: finished owner: codex topic_slug: railiance-fabric created: "2026-05-25" updated: "2026-05-25" state_hub_workstream_id: "63202459-2f73-409a-8881-307a5fc1835a" --- # Stabilize Zone Containers And Layout Zone Subgraphs ## Context RAIL-FAB-WP-0022 made zones first-class visualization entities and RAIL-FAB-WP-0023 added plain labels plus view-only zone dragging. The current prototype still derives a zone rectangle directly from the current positions of its member nodes. When the operator changes the layout algorithm or reruns layout, the zone surface moves with the global graph layout instead of staying where the operator placed it. The current resolver also treats every edge attached to a zoned node as zone context. That includes display-only repository declaration edges. Those edges help explain where graph declarations came from, but they should not be read as direct deployment or operational connections across a zone boundary. This workplan moves the graph explorer toward the intended model: a zone is a stable drawing surface, and the assigned subgraph is laid out inside that surface as a separate view concern. ## Task 1: Separate Context Edges From Zone Boundary Connectivity ```task id: RAIL-FAB-WP-0024-T01 status: done priority: high state_hub_task_id: "5e018a70-5aff-41bb-b0f9-0f59302c58ae" ``` Exclude display-only/context edges, especially repository `declares` edges, from zone boundary diagnostics and collapsed-zone boundary edges. Expected result: zone detail may still mention contextual evidence when useful, but display-only declaration edges do not make it look as if every zoned node is directly connected to an unzoned repository. Result: Display-only edges and repository `declares` edges are now treated as context-only in both the shared zone resolver and the browser view. They do not create boundary diagnostics, attraction paths, or collapsed-zone boundary edges. ## Task 2: Persist Stable Zone Container Positions ```task id: RAIL-FAB-WP-0024-T02 status: done priority: high state_hub_task_id: "ffa3f7b8-ee85-461a-89b8-007e4879171c" ``` Introduce a view-level zone container state keyed by stable zone id. The implementation should: - remember zone container center and size after layout and drag; - keep user-moved zone positions stable when the global layout algorithm changes; - keep saved/copied view state compatible with the nested `zone` object; - avoid mutating the Fabric graph payload. Expected result: switching between layout algorithms keeps zone papers in the same operator-chosen positions. Result: The graph explorer now stores stable zone containers in view state. Containers remember graph-coordinate position and size, survive global layout reruns, can be saved/copied through the nested `zone` state, and remain separate from Fabric graph payload data. ## Task 3: Layout Zone Subgraphs Inside Containers ```task id: RAIL-FAB-WP-0024-T03 status: done priority: high state_hub_task_id: "f2f5adfa-4de4-4606-aa9f-51dbf10c6443" ``` Add a per-zone layout pass that positions assigned visible nodes inside their zone container after the global layout places the surrounding graph. The first implementation may use a deterministic compact layout rather than a full nested Cytoscape layout, as long as it: - only moves visible nodes assigned to the zone; - keeps each node inside the zone's drawing surface; - treats unzoned nodes as part of the base canvas; - keeps edge routing intact through Cytoscape's normal renderer. Expected result: the visible subgraph inside each zone is arranged by the zone view model, not merely enclosed after the global layout. Result: After global layout, each visible zone projects its assigned nodes into a local compact layout inside its stable container. New, not-yet-moved zones are packed into readable rows so the default deployment-environment papers start as separate drawing surfaces. ## Task 4: Verify And Document Zone Layout Semantics ```task id: RAIL-FAB-WP-0024-T04 status: done priority: medium state_hub_task_id: "cd418134-cacc-42f6-a6ea-0bfd1cda9965" ``` Update the graph explorer contract and run focused validation. Verification should cover: - static UI assertions for context-edge filtering and zone container helpers; - JavaScript syntax validation; - focused graph explorer and zone resolver tests; - a visual smoke check of the graph explorer. Expected result: documentation and tests describe the new semantics, and the running UI shows stable zone containers with locally arranged member nodes. Result: Updated the graph explorer contract and zone entity documentation. Focused tests, generated JavaScript syntax validation, full tests, CLI validation, and a headless Edge visual smoke check all passed.