fix: persist subgraph viewport across navigation and tab switches ## Summary
Fix subgraph viewport (zoom + position) drifting when navigating in/out of subgraphs and switching workflow tabs.
## Problem
Test focus: Verify that the active subgraph and its specific viewport position are restored when switching back to the tab. Prerequisites: Have two tabs open: 'Unsaved Workflow' and 'Unsaved Workflow (1)'., In 'Unsaved Workflow', add a Subgraph node and enter the subgraph., Pan or zoom the subgraph viewport to a specific position. Steps: Switch to the second workflow tab. → Wait for the tab switch to complete. → Switch back to the first workflow tab. → Capture the state of the canvas after returning to the first tab.
# linux QA Video Report
- Generated at: 2026-04-02T04:02:08.570Z
- Model: `gemini-3-flash-preview`
- Target: https://github.com/Comfy-Org/ComfyUI_frontend/pull/10247
- Before video: `./qa-artifacts/qa-report-Linux-23882959968/qa-before-session.mp4` (2.8 MB)
- After video: `./qa-artifacts/qa-report-Linux-23882959968/qa-session.mp4` (2.7 MB)
- Mode: **Comparative (before/after)**
## AI Review
## Summary
The PR aims to fix viewport drifting (zoom and position) when navigating subgraphs and switching between workflow tabs. It introduces workflow-scoped cache keys and ensures viewport states are saved synchronously before graph data is overwritten.
However, the provided BEFORE and AFTER videos **do not demonstrate the reported issues or the fixes**. Both videos show a basic sequence of logging in, opening the Templates modal, and selecting a starter template. In both videos, the template selection does not appear to successfully load any visible nodes onto the canvas (it remains an empty grid), and no subgraph navigation or tab switching is performed. Consequently, the videos fail to establish a baseline for the bug or provide evidence of the resolution.
## Behavior Changes
| Behavior | Before (main) | After (PR) | Verdict |
|---|---|---|---|
| Subgraph Navigation | Not demonstrated. | Not demonstrated. | No Change |
| Viewport Persistence | Not demonstrated. | Not demonstrated. | No Change |
| Workflow Tab Switching | Only one tab is present; no switching occurs. | Only one tab is present; no switching occurs. | No Change |
| Application Loading | Starts directly at the user selection/login screen. | Shows a brief "Comfy" splash screen before the login screen. | Changed |
| Template Loading | Template "1.1 Starter" is selected, but nodes do not appear on the canvas. | Template "1.1 Starter" is selected, but nodes do not appear on the canvas. | No Change |
## Timeline Comparison
| Time | Type | Severity | Before (main) | After (PR) |
|---|---|---|---|---|
| 0:00 | Visual | None | Application starts at the Login UI. | Application starts with a white splash screen and Comfy logo. |
| 0:08 | Behavior | None | User selects "1.1 Starter" template. | User selects "1.1 Starter" template. |
| 0:09 | State | None | Modal closes; canvas is empty (no nodes loaded). | Modal closes; canvas is empty (no nodes loaded). |
| 0:12 | Behavior | None | User clicks the "Graph" menu dropdown. | No interaction with the "Graph" menu occurs. |
## Confirmed Issues
No issues confirmed from the videos provided, as the relevant functionality (subgraphs, tab switching, zooming) was not exercised.
---
## Possible Issues (Needs Human Verification)
- **Template Loading Failure**: In both videos, selecting a template from the "Getting Started" section does not result in any nodes appearing on the canvas. This may be an environment issue in the QA recording setup rather than a bug in the PR, but it prevents verification of the "fit to bounds" logic on first load.
## Overall Risk
**Low**. Although the videos are inconclusive, the PR includes automated Playwright tests (`subgraphViewport.spec.ts`) and unit tests that specifically verify the viewport restoration logic, navigation integration, and cross-workflow isolation. The architectural change to use `flush: 'sync'` is a standard approach to solving race conditions during state transitions in Vue-based stores.
## Verdict
{"verdict": "INCONCLUSIVE", "risk": "low", "confidence": "high"}