Skip to content

VIEW-2: fix camera fit on the live graph (poll until SVG+sim ready)#103

Merged
mvalancy merged 1 commit into
devfrom
fix/camera-fit-live
Jun 18, 2026
Merged

VIEW-2: fix camera fit on the live graph (poll until SVG+sim ready)#103
mvalancy merged 1 commit into
devfrom
fix/camera-fit-live

Conversation

@mvalancy

Copy link
Copy Markdown
Member

The bug

The once-per-graph framing (VIEW-1) worked in dev but left the live graph pinned in the top-left corner — the OpenCV live audit measured offMag ~0.81 / ~6% usage on the guest graph, and the screenshot confirmed the (origin-centred) nodes clustered top-left with no camera transform applied.

Root cause

The effect ran when hasNodes flipped true but svgRef.current was still null — the <svg> mounts a render later. It hit the !svgRef.current early-return and, since its deps ([hasNodes, currentGraphId]) don't change again, never retried once the SVG mounted. In dev, React StrictMode double-invokes effects, so a second run caught the mounted SVG and masked the bug. Production runs effects once → the fit never applied.

Fix

Move the readiness checks into the poll loop: the effect arms the poll whenever hasNodes && currentGraphId, and each attempt retries (250ms, up to ~15s) until svgRef + zoomBehaviorRef + the simulation's positioned nodes are all available, then fits/restores once. fitViewToNodes now returns a success boolean so the poll knows when it actually applied.

Verification

  • Production build pointed at the live cloud Worker (the exact failing scenario, via GraphDone-Cloud/scripts/verify-camera-fix.mjs): 7/7 nodes framed at 1440/1280/1920/768 (was 3/7, zoom=none).
  • Local camera.spec 4/4, OpenCV balance gate 3/3 (offMag ~0.05), typecheck clean.

Note: dev-mode E2E can't reproduce this (StrictMode masks it); the prod-build script is the real guard. Will re-run the live audit after deploy to confirm offMag drops on the live site.

🤖 Generated with Claude Code

…G+sim ready

The once-per-graph framing worked in dev but left the graph pinned top-left on
the live site (offMag ~0.81, ~6% usage on the guest graph). Root cause: the
effect ran when `hasNodes` flipped true but `svgRef.current` was still null (the
<svg> mounts a render later), so it hit the `!svgRef.current` early-return and —
because its deps don't change again — never retried once the SVG mounted. In
dev, React StrictMode double-invokes effects so a second run caught the mounted
SVG and masked the bug; production runs effects once, so the fit never applied
and the origin-centred layout rendered in the top-left corner.

Fix: move the readiness checks INTO the poll loop. The effect now sets up the
poll whenever hasNodes && currentGraphId, and each attempt retries (250ms, up to
~15s) until svgRef + zoomBehaviorRef + the simulation's positioned nodes are all
available, then fits/restores ONCE. fitViewToNodes returns a success boolean so
the poll knows when it actually applied.

Verified in a production build pointed at the live cloud Worker (the exact
failing scenario): 7/7 nodes framed at 1440/1280/1920/768 (was 3/7). Local
camera.spec 4/4, balance gate 3/3 (offMag ~0.05).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🧪 Comprehensive Test Suite

  • Unit suites (Node 18.x & 20.x) — core, web, server, mcp-server: ✅ passed
  • Installer & deploy config: ✅ passed

Full-stack smoke gate runs in the CI workflow.

@mvalancy mvalancy merged commit 222c00e into dev Jun 18, 2026
26 of 28 checks passed
@mvalancy mvalancy deleted the fix/camera-fit-live branch June 18, 2026 00:07
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