fix(web): pin actor nodes to leftmost layer#99
Merged
Conversation
ELK's layered algorithm placed the actor (e.g. `user` / `browser`) at whichever layer minimized total edge length, which could push it inward when it had both outgoing and incoming traffic. Set `elk.layered.layering.layerConstraint=FIRST` for actor-typed nodes so the human/external initiator always reads as the leftmost column. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
WalkthroughThis PR modifies ELK graph layout computation to pin actor-typed nodes to the leftmost layer by conditionally adding layer constraints. It refactors per-node layout options configuration and adds a test verifying actor nodes remain at the minimum x-coordinate. ChangesActor Node Layer Pinning
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
naorsabag
added a commit
that referenced
this pull request
May 10, 2026
2 tasks
naorsabag
added a commit
that referenced
this pull request
May 11, 2026
Flows with two actors connected to each other (e.g. user → agent-cfg, both type=actor) crashed ELK with: org.eclipse.elk.core.UnsupportedConfigurationException: Node 'openhop-flow.user' has its layer constraint set to FIRST, but has at least one incoming edge that does not come from a FIRST_SEPARATE node. ELK rejects intra-layer FIRST→FIRST edges. The actor-pin from #99 was unconditional: every type=actor node got layerConstraint=FIRST. When two actors connect, both land in layer 0 and ELK refuses to lay it out. useFlowGraphLayout silently catches and falls back to computeFallbackPositions, which uses tighter FALLBACK_COLUMN_GAP=220 vs ELK's 200+80 — the visible result was "all the nodes are too close together" on the affected flows. Tighten the pin predicate: skip the FIRST constraint only when the actor is fed by ANOTHER actor. The common case where an actor is the final response target (e.g. user ← api in orion-main) still pins correctly because the response edge's source is an endpoint/service, not an actor — so user stays leftmost. Tested against: - examples/order-flow (1 actor, response loop) — user is leftmost ✓ - claude-sandbox flow NdFjXxlxv717 (2 actors connected) — ELK no longer crashes, gaps are 200/80 px as expected ✓ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
naorsabag
added a commit
that referenced
this pull request
May 11, 2026
* fix(web): don't pin actor to FIRST when another actor feeds it Flows with two actors connected to each other (e.g. user → agent-cfg, both type=actor) crashed ELK with: org.eclipse.elk.core.UnsupportedConfigurationException: Node 'openhop-flow.user' has its layer constraint set to FIRST, but has at least one incoming edge that does not come from a FIRST_SEPARATE node. ELK rejects intra-layer FIRST→FIRST edges. The actor-pin from #99 was unconditional: every type=actor node got layerConstraint=FIRST. When two actors connect, both land in layer 0 and ELK refuses to lay it out. useFlowGraphLayout silently catches and falls back to computeFallbackPositions, which uses tighter FALLBACK_COLUMN_GAP=220 vs ELK's 200+80 — the visible result was "all the nodes are too close together" on the affected flows. Tighten the pin predicate: skip the FIRST constraint only when the actor is fed by ANOTHER actor. The common case where an actor is the final response target (e.g. user ← api in orion-main) still pins correctly because the response edge's source is an endpoint/service, not an actor — so user stays leftmost. Tested against: - examples/order-flow (1 actor, response loop) — user is leftmost ✓ - claude-sandbox flow NdFjXxlxv717 (2 actors connected) — ELK no longer crashes, gaps are 200/80 px as expected ✓ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(web): exclude actor self-loops from the incoming-from-actor guard CodeRabbit on #129: an actor self-loop (source === target) was incorrectly treated as 'fed by another actor', which would unpin a standalone actor that happens to have a self-loop step. Self-loops don't introduce a second FIRST-pinned node, so they can't trigger the ELK FIRST-FIRST intra-layer error this guard exists to prevent. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci: prettier-format flow-layout.ts --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
user/browserinward when it also appeared as a final response target.elk.layered.layering.layerConstraint=FIRSTfortype: actornodes so the actor always anchors the leftmost column.__tests__/flow-layout.test.tsasserts thatuserlands atmin(x)across the order-flow example layout.Test plan
npm testinpackages/web(41/41 passing — new test included)npx openhop@beta demoafter merge:browseron far left of the auth flow🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests