Repository navigation
Conversation
🦋 Changeset detectedLatest commit: 9841d26 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## codex/common-render-pipeline-3-dagre-phases #7811 +/- ##
==============================================================================
- Coverage 2.95% 2.95% -0.01%
==============================================================================
Files 651 651
Lines 69258 69406 +148
Branches 973 973
==============================================================================
+ Hits 2047 2048 +1
- Misses 67211 67358 +147
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
…/common-render-pipeline-4-dagre-layoutdata
…odex/common-render-pipeline-5-dagre-shared-paint
… codex/common-render-pipeline-6-dagre-shared-nodes
… codex/common-render-pipeline-6-dagre-shared-nodes
… codex/common-render-pipeline-6-dagre-shared-nodes
…agre-shared-nodes' into codex/common-render-pipeline-6-dagre-shared-nodes
…/common-render-pipeline-4-dagre-layoutdata
…odex/common-render-pipeline-5-dagre-shared-paint
… codex/common-render-pipeline-6-dagre-shared-nodes
… codex/common-render-pipeline-6-dagre-shared-nodes
knsv-bot
left a comment
There was a problem hiding this comment.
[sisyphus-bot]
Review of Common Render pipeline 4: DAGRE LayoutData normalization (stacked on codex/common-render-pipeline-3-dagre-phases).
Verdict: COMMENT — one important question about normalization completeness, nothing blocking.
What's working well
- 🎉 [praise]
normalizeDagreNodemirrors the paint-phase offset rules exactly (clusterNode →y + margin, pure cluster →height + margin, regular →y + margin/2), and works on copies so the graph the paint phase still consumes is untouched. I traced both paths and found no double-application of offsets — including the subtle self-loop case wheregetSelfLoopPointssubtractsyOffsetand the normalizer adds it back, matching the existing paint behavior. - 🎉 [praise] The tests hit the right cases: plain edge geometry with margin offsets, merged self-loop collapsing back to one logical edge with
selfLoopstripped, and extending the phase-contract test to assert LayoutData is populated after the core phase. Focused and readable. - 🎉 [praise]
nodeByIdas aMapkeeps the write-back linear, andDAGRE_NODE_LAYOUT_PROPERTIESas a fixed allowlist (rather thanObject.assign) is the right call — it also keeps user-influenced graph keys from leaking onto LayoutData.
Security
XSS sub-agent review: no XSS or injection issues identified. The change is a pure data transformation with no DOM sinks; the property allowlist is hard-coded (no prototype-pollution surface, and the Map lookup is immune to __proto__-keyed ids); no sanitization boundary moves.
Things to address
-
🟡 [important]
applyDagreLayoutResultis silently lossy for anything beyond a flat top-level graph (dagre/index.js:458-481). Two facets:- Recursive clusters:
adjustClustersAndEdgesmoves cluster children and intra-cluster edges into the nestednode.graph(mermaid-graphlib.js:137,311), sosortNodesByHierarchy(graph)never sees those nodes — their LayoutData entries keep stale/no positions — anddata4Layout.edges = getEdgesToRender(graph, ...)drops intra-cluster edges from LayoutData entirely. - Non-merged self-loops: for diagram types where
mergeSelfLoopsis false (e.g., class diagrams), the three*-cyclic-special-*dummy segments replace the original self-edge indata4Layout.edges, leaking synthetic layout-internal edges into the public structure.
Nothing consumes the normalized LayoutData yet (paint still reads the graph), so nothing breaks today — but phase 5 presumably will consume it, and these gaps will surface there as missing clusters and phantom edges. It would be great to either handle the recursive case now (walk into
node.graphand translate to the parent coordinate space), or — if that's deliberately deferred — add a code comment plus a test documenting the current limitation so the next phase doesn't build on an assumption the data doesn't satisfy. - Recursive clusters:
-
🟢 [nit]
runDagreLayoutCore's first parameter is still named_data4Layout(dagre/index.js:730,738) — the underscore signalled "unused", but this PR now passes it toapplyDagreLayoutResult. Renaming todata4Layoutkeeps the convention honest. -
🟢 [nit]
dagre/index.js:40-49— worth a one-line comment onDAGRE_NODE_LAYOUT_PROPERTIESstating the keys must remain a fixed literal allowlist (never derived from graph data); the safety ofapplyDagreNodeLayoutdepends on it, and a future "simplify toObject.assign" refactor would reopen a property-injection surface. -
💡 [suggestion] Copying live function references (
intersect,calcIntersect) onto LayoutData nodes mixes behavior into what downstream consumers (DDLT fixtures, serialization) treat as plain data — and those closures may capture the dagre-graph node rather than the LayoutData node. If the painter is the only consumer, consider keeping them dagre-internal and passing them alongside instead. Fine to defer to the phase where they're actually consumed.
No changeset is correct for an internal refactor with no user-facing change. All CI green including the five e2e shards and Argos.
Solid continuation of the pipeline series — the normalization direction (dagre converging on the same LayoutData contract ELK already uses) is exactly right. 🚀
Address review feedback on the LayoutData normalization: - Document that applyDagreLayoutResult only normalizes the top-level graph: recursive cluster children and intra-cluster edges live in the nested cluster graph and are owned by the recursive paint path, and unmerged self-loop segments replace the original self-edge. - Pin the recursive-cluster behavior with a unit test so the next pipeline phase does not build on assumptions the data does not satisfy. - Note on DAGRE_NODE_LAYOUT_PROPERTIES that the allowlist must stay a fixed literal list (graph keys are user-controlled) and why the intersect function references are copied. - Rename the now-used _data4Layout parameter in runDagreLayoutCore.
…odex/common-render-pipeline-5-dagre-shared-paint
… codex/common-render-pipeline-6-dagre-shared-nodes
|
[sisyphus-bot] Review follow-up — the findings from the review have been addressed in 8c6f1e5 (merged up the stack into #7812 and #7813):
Stack propagation: merged into |
…cleanups - Add changeset documenting the class.defaultRenderer switch to the unified (dagre-wrapper) renderer - Drop the shared EMPTY_CLUSTER_DB singleton in favor of a fresh Map per paint call to avoid a mutable module-level default - Document why class.padding is intentionally left undefined in defaultConfig - Add hand-drawn self-referential class diagram e2e snapshot test
knsv-bot
left a comment
There was a problem hiding this comment.
[sisyphus-bot]
Re-review of Common Render pipeline 4: DAGRE LayoutData normalization — follow-up to the first review round.
Verdict: APPROVE — all findings from the previous round are resolved; no new findings. (Posted as a comment because the authoring account cannot formally approve its own PR.)
Transparency note: the remediation commit (8c6f1e5) was authored by the same automation pipeline that produced this review, so this is automation verifying automation — a human maintainer should give the delta a quick glance before merge.
Previous findings — all resolved in 8c6f1e5
- 🟡 Lossy normalization → resolved via the document-and-pin option the review offered:
applyDagreLayoutResultnow carries a doc comment spelling out both limitations (recursive cluster children and intra-cluster edges stay with the recursive paint path; unmerged self-loop segments replace the original self-edge), and a new unit test pins the recursive-cluster behavior (top-level nodes normalized, cluster children untouched, intra-cluster edges absent). This is the right scope given #7812's shared paint walks the measure graph and never depends on LayoutData completeness for nested content — and #7812 separately resolves the self-loop facet forer/classDiagram. - 🟢
_data4Layout→data4LayoutinrunDagreLayoutCore— done. - 🟢 Fixed-literal-allowlist comment on
DAGRE_NODE_LAYOUT_PROPERTIES— done, and it also covers the 💡 about theintersect/calcIntersectfunction references.
Verification
- 🎉 [praise] The pinning test asserts the limitation from three angles (normalized top-level nodes, untouched cluster child, dropped intra-cluster edge) — exactly the guard the next pipeline phase needs.
- 🎉 [praise] Full CI green on the new head: unit tests, all five e2e shards, and Argos reports no visual changes — consistent with a comments/test/rename-only delta.
Security
XSS sub-agent re-checked the delta: no XSS or injection issues identified. The commit contains only comments, a parameter rename, and a unit test with static fixture data; no DOM sinks or sanitization boundary changes.
Nothing further from this side — over to a human for the final merge call. 🚀
…-6-dagre-shared-nodes Common Render pipeline 6: DAGRE shared node measurement
…-5-dagre-shared-paint Common Render pipeline 5: DAGRE shared paint
f878d5a
into
codex/common-render-pipeline-3-dagre-phases
Summary
Verification