Skip to content

Improve memory graph playground readability#973

Open
Dhravya wants to merge 1 commit into
mainfrom
codex/memory-graph-playground-clusters
Open

Improve memory graph playground readability#973
Dhravya wants to merge 1 commit into
mainfrom
codex/memory-graph-playground-clusters

Conversation

@Dhravya
Copy link
Copy Markdown
Member

@Dhravya Dhravya commented May 19, 2026

Summary

  • add a container tag selector to the memory graph playground, including a proxy for /v3/container-tags/list
  • improve dense graph readability with stable append placement, wider memory clustering, dynamic zoom bounds, and relation-edge level-of-detail
  • add cluster-colored nodes, clearer update-chain markers, stronger focused update edges, and an expanded legend explaining colors/edge semantics
  • make the playground converter match current API response shapes (memoryEntries, type, relation fields)

Verification

  • bun --filter @supermemory/memory-graph test
  • bun run build in packages/memory-graph
  • bun run build in apps/memory-graph-playground
  • git diff --cached --check

@claude
Copy link
Copy Markdown

claude Bot commented May 19, 2026

Claude finished @Dhravya's task in 2m 12s —— View job


Review Complete

  • Get PR diff and analyze changes
  • Review new container-tags API route for security issues
  • Review graph API route changes
  • Review page.tsx changes for bugs/security
  • Review memory-graph package changes
  • Submit review summary

Summary: Reviewed 1,694 additions across 19 files. No bugs, security issues, or logic errors found. The PR cleanly implements container tag filtering, cluster coloring, level-of-detail edge rendering, and dynamic zoom bounds. Code is well-structured with good test coverage.

Score: 10/10 — Ready to ship.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
supermemory-mcp aefeec2 May 19 2026, 05:57 PM

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview: This PR improves memory graph readability with container tag filtering, cluster-colored nodes, dynamic zoom bounds, and level-of-detail edge rendering for dense graphs.

Issues found: None — this looks good to ship.

The code is well-structured with solid test coverage. Key observations:

  • Container tags proxy (/api/container-tags/route.ts): Clean API proxy pattern appropriate for a playground app. Error handling is thorough.

  • Simulation changes (simulation.ts): The new stop() method and dynamic getDocMemoryDistance() based on memory count are correctly implemented. The append-only pagination logic in memory-graph.tsx properly preserves existing node positions.

  • Cluster assignments (use-graph-data.ts): The BFS-based clustering algorithm correctly merges cross-document relation clusters and assigns consistent colors via deterministic hashing.

  • Level-of-detail rendering (renderer.ts): Smart edge sampling at low zoom levels using getRelationEdgeStride() and shouldDrawRelationEdge(). Structural "derives" edges are always drawn, while relation edges are deterministically sampled to reduce visual noise.

  • Version chain inference (version-chain.ts): Good fix for backends that repeat v1 across update chains — the code now infers display versions from chain order when needed.

  • Dynamic zoom bounds (viewport.ts): setMinZoomForNodes() properly allows zooming out further for large graphs while clamping to reasonable limits.

Score: 10/10

@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
supermemory-app aefeec2 Commit Preview URL

Branch Preview URL
May 19 2026, 05:59 PM

Copy link
Copy Markdown
Contributor

@vorflux vorflux Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the full diff. A few real bugs and a design concern below.

@@ -142,10 +443,10 @@ export function useGraphData(
for (const [id] of nodeCache.current.entries()) {
if (!currentIds.has(id)) nodeCache.current.delete(id)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: nodeCache.current is mutated inside useMemo.

useMemo is supposed to be side-effect-free. Mutating nodeCache.current (.clear(), .delete(), .set()) here violates that contract — React is allowed to re-run useMemo callbacks multiple times in StrictMode and Concurrent Mode without committing the result, leaving the cache in an inconsistent state.

The original split (useEffect for cache eviction, a separate useMemo for reads) was intentional. Move the eviction back into a useEffect and restrict the useMemo to reading the cache only.

if (Math.abs(dy) > minDistance) continue
if (dx * dx + dy * dy < minDistance * minDistance) return false
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance: isAppendCandidateOpen is O(n) per candidate, called up to 144 times per new node.

With 500 nodes this is ~72,000 distance checks per new document, all inside useMemo. At larger graph sizes this causes noticeable jank on every update.

Consider a bounding-box pre-filter before the exact distance check, or a grid/spatial-hash so the nearest-neighbour test is O(1) amortised.

}
}

function hashString(value: string): number {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplication: hashString is defined identically in both renderer.ts and use-graph-data.ts.

Extract to a shared utility and import from both.


const chain: ChainEntry[] = all.map((m) => ({
const shouldInferVersions = all.some((m, index) => {
if (!Number.isFinite(m.version) || m.version < 1) return true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aggressive version inference: shouldInferVersions flips to true if any adjacent pair is non-monotonic, which causes every entry in the chain to fall back to positional indices. A single stale or out-of-order record silently discards all real version numbers for the whole chain.

Consider falling back per-entry — assign index + 1 only to entries whose version is invalid or duplicates the previous — rather than replacing the entire chain.

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