UI: Fix Graph layout for TaskGroup tasks wired to external nodes - #67720

Merged
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped
Jun 1, 2026
Merged

UI: Fix Graph layout for TaskGroup tasks wired to external nodes#67720
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped

Conversation

@vatsrahul1001

@vatsrahul1001vatsrahul1001 commented May 29, 2026

Copy link
Copy Markdown
Contributor

Closes#67714.

#65031 could be cause of it

Fix

  • Tighten hasUniformExternalConnectivity to require every externally-connected child to share the same full (sources, targets) profile. Mixed entry/exit shapes (like the reporter's repro) now fall back to rendering individual crossing edges, preserving the author's explicit dependency intent. The canonical "cleanup group" fan-in/fan-out pattern that the optimization was designed for (every child has same upstream AND same downstream) still triggers the collapse.
  • Add a preserveInternal option to rewriteGroupEdges. The open-group call site sets it so the collapse optimization preserves internal edges for the subsequent extraction loop; the closed-group call site keeps the default (drop internals — they're not laid out when the group is collapsed).

Tests

New elkGraphUtils.test.ts covers:

Verified the new tests fail against main without the fix and pass with it.

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.7)

Generated-by: Claude Code (Opus 4.7) following the guidelines

Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
Closes: #67714
@vatsrahul1001

Copy link
Copy Markdown
ContributorAuthor

cc: @pierrejeambrun@bbovenzi

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Tested locally looks good. Code looks good.

@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.3 milestone Jun 1, 2026
@pierrejeambrun
pierrejeambrun merged commit 55780f2 into mainJun 1, 2026
83 checks passed
@pierrejeambrun
pierrejeambrun deleted the fix-graph-taskgroup-internal-edges-dropped branch June 1, 2026 09:50
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

github-actionsBot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
aws-airflow-bot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
pierrejeambrun pushed a commit that referenced this pull request Jun 1, 2026
…l nodes (#67720) (#67830)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Closes: #67714
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:TaskGrouparea:UIRelated to UI/UX. For Frontend Developers.kind:bugThis is a clearly a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3.2.2 Graph View breaks when TaskGroup outputs connect internal tasks to external downstream tasks

2 participants

@vatsrahul1001@pierrejeambrun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

UI: Fix Graph layout for TaskGroup tasks wired to external nodes - #67720

Merged
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped
Jun 1, 2026
Merged

UI: Fix Graph layout for TaskGroup tasks wired to external nodes#67720
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped

Conversation

@vatsrahul1001

@vatsrahul1001vatsrahul1001 commented May 29, 2026

Copy link
Copy Markdown
Contributor

Closes#67714.

#65031 could be cause of it

Fix

  • Tighten hasUniformExternalConnectivity to require every externally-connected child to share the same full (sources, targets) profile. Mixed entry/exit shapes (like the reporter's repro) now fall back to rendering individual crossing edges, preserving the author's explicit dependency intent. The canonical "cleanup group" fan-in/fan-out pattern that the optimization was designed for (every child has same upstream AND same downstream) still triggers the collapse.
  • Add a preserveInternal option to rewriteGroupEdges. The open-group call site sets it so the collapse optimization preserves internal edges for the subsequent extraction loop; the closed-group call site keeps the default (drop internals — they're not laid out when the group is collapsed).

Tests

New elkGraphUtils.test.ts covers:

Verified the new tests fail against main without the fix and pass with it.

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.7)

Generated-by: Claude Code (Opus 4.7) following the guidelines

Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
Closes: #67714
@vatsrahul1001

Copy link
Copy Markdown
ContributorAuthor

cc: @pierrejeambrun@bbovenzi

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Tested locally looks good. Code looks good.

@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.3 milestone Jun 1, 2026
@pierrejeambrun
pierrejeambrun merged commit 55780f2 into mainJun 1, 2026
83 checks passed
@pierrejeambrun
pierrejeambrun deleted the fix-graph-taskgroup-internal-edges-dropped branch June 1, 2026 09:50
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

github-actionsBot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
aws-airflow-bot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
pierrejeambrun pushed a commit that referenced this pull request Jun 1, 2026
…l nodes (#67720) (#67830)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Closes: #67714
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:TaskGrouparea:UIRelated to UI/UX. For Frontend Developers.kind:bugThis is a clearly a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3.2.2 Graph View breaks when TaskGroup outputs connect internal tasks to external downstream tasks

2 participants

@vatsrahul1001@pierrejeambrun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

UI: Fix Graph layout for TaskGroup tasks wired to external nodes - #67720

Merged
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped
Jun 1, 2026
Merged

UI: Fix Graph layout for TaskGroup tasks wired to external nodes#67720
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped

Conversation

@vatsrahul1001

@vatsrahul1001vatsrahul1001 commented May 29, 2026

Copy link
Copy Markdown
Contributor

Closes#67714.

#65031 could be cause of it

Fix

  • Tighten hasUniformExternalConnectivity to require every externally-connected child to share the same full (sources, targets) profile. Mixed entry/exit shapes (like the reporter's repro) now fall back to rendering individual crossing edges, preserving the author's explicit dependency intent. The canonical "cleanup group" fan-in/fan-out pattern that the optimization was designed for (every child has same upstream AND same downstream) still triggers the collapse.
  • Add a preserveInternal option to rewriteGroupEdges. The open-group call site sets it so the collapse optimization preserves internal edges for the subsequent extraction loop; the closed-group call site keeps the default (drop internals — they're not laid out when the group is collapsed).

Tests

New elkGraphUtils.test.ts covers:

Verified the new tests fail against main without the fix and pass with it.

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.7)

Generated-by: Claude Code (Opus 4.7) following the guidelines

Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
Closes: #67714
@vatsrahul1001

Copy link
Copy Markdown
ContributorAuthor

cc: @pierrejeambrun@bbovenzi

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Tested locally looks good. Code looks good.

@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.3 milestone Jun 1, 2026
@pierrejeambrun
pierrejeambrun merged commit 55780f2 into mainJun 1, 2026
83 checks passed
@pierrejeambrun
pierrejeambrun deleted the fix-graph-taskgroup-internal-edges-dropped branch June 1, 2026 09:50
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

github-actionsBot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
aws-airflow-bot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
pierrejeambrun pushed a commit that referenced this pull request Jun 1, 2026
…l nodes (#67720) (#67830)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Closes: #67714
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:TaskGrouparea:UIRelated to UI/UX. For Frontend Developers.kind:bugThis is a clearly a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3.2.2 Graph View breaks when TaskGroup outputs connect internal tasks to external downstream tasks

2 participants

@vatsrahul1001@pierrejeambrun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

UI: Fix Graph layout for TaskGroup tasks wired to external nodes - #67720

Merged
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped
Jun 1, 2026
Merged

UI: Fix Graph layout for TaskGroup tasks wired to external nodes#67720
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped

Conversation

@vatsrahul1001

@vatsrahul1001vatsrahul1001 commented May 29, 2026

Copy link
Copy Markdown
Contributor

Closes#67714.

#65031 could be cause of it

Fix

  • Tighten hasUniformExternalConnectivity to require every externally-connected child to share the same full (sources, targets) profile. Mixed entry/exit shapes (like the reporter's repro) now fall back to rendering individual crossing edges, preserving the author's explicit dependency intent. The canonical "cleanup group" fan-in/fan-out pattern that the optimization was designed for (every child has same upstream AND same downstream) still triggers the collapse.
  • Add a preserveInternal option to rewriteGroupEdges. The open-group call site sets it so the collapse optimization preserves internal edges for the subsequent extraction loop; the closed-group call site keeps the default (drop internals — they're not laid out when the group is collapsed).

Tests

New elkGraphUtils.test.ts covers:

Verified the new tests fail against main without the fix and pass with it.

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.7)

Generated-by: Claude Code (Opus 4.7) following the guidelines

Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
Closes: #67714
@vatsrahul1001

Copy link
Copy Markdown
ContributorAuthor

cc: @pierrejeambrun@bbovenzi

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Tested locally looks good. Code looks good.

@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.3 milestone Jun 1, 2026
@pierrejeambrun
pierrejeambrun merged commit 55780f2 into mainJun 1, 2026
83 checks passed
@pierrejeambrun
pierrejeambrun deleted the fix-graph-taskgroup-internal-edges-dropped branch June 1, 2026 09:50
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

github-actionsBot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
aws-airflow-bot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
pierrejeambrun pushed a commit that referenced this pull request Jun 1, 2026
…l nodes (#67720) (#67830)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Closes: #67714
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:TaskGrouparea:UIRelated to UI/UX. For Frontend Developers.kind:bugThis is a clearly a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3.2.2 Graph View breaks when TaskGroup outputs connect internal tasks to external downstream tasks

2 participants

@vatsrahul1001@pierrejeambrun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

UI: Fix Graph layout for TaskGroup tasks wired to external nodes - #67720

Merged
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped
Jun 1, 2026
Merged

UI: Fix Graph layout for TaskGroup tasks wired to external nodes#67720
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped

Conversation

@vatsrahul1001

@vatsrahul1001vatsrahul1001 commented May 29, 2026

Copy link
Copy Markdown
Contributor

Closes#67714.

#65031 could be cause of it

Fix

  • Tighten hasUniformExternalConnectivity to require every externally-connected child to share the same full (sources, targets) profile. Mixed entry/exit shapes (like the reporter's repro) now fall back to rendering individual crossing edges, preserving the author's explicit dependency intent. The canonical "cleanup group" fan-in/fan-out pattern that the optimization was designed for (every child has same upstream AND same downstream) still triggers the collapse.
  • Add a preserveInternal option to rewriteGroupEdges. The open-group call site sets it so the collapse optimization preserves internal edges for the subsequent extraction loop; the closed-group call site keeps the default (drop internals — they're not laid out when the group is collapsed).

Tests

New elkGraphUtils.test.ts covers:

Verified the new tests fail against main without the fix and pass with it.

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.7)

Generated-by: Claude Code (Opus 4.7) following the guidelines

Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
Closes: #67714
@vatsrahul1001

Copy link
Copy Markdown
ContributorAuthor

cc: @pierrejeambrun@bbovenzi

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Tested locally looks good. Code looks good.

@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.3 milestone Jun 1, 2026
@pierrejeambrun
pierrejeambrun merged commit 55780f2 into mainJun 1, 2026
83 checks passed
@pierrejeambrun
pierrejeambrun deleted the fix-graph-taskgroup-internal-edges-dropped branch June 1, 2026 09:50
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

github-actionsBot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
aws-airflow-bot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
pierrejeambrun pushed a commit that referenced this pull request Jun 1, 2026
…l nodes (#67720) (#67830)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Closes: #67714
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:TaskGrouparea:UIRelated to UI/UX. For Frontend Developers.kind:bugThis is a clearly a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3.2.2 Graph View breaks when TaskGroup outputs connect internal tasks to external downstream tasks

2 participants

@vatsrahul1001@pierrejeambrun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

UI: Fix Graph layout for TaskGroup tasks wired to external nodes - #67720

Merged
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped
Jun 1, 2026
Merged

UI: Fix Graph layout for TaskGroup tasks wired to external nodes#67720
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped

Conversation

@vatsrahul1001

@vatsrahul1001vatsrahul1001 commented May 29, 2026

Copy link
Copy Markdown
Contributor

Closes#67714.

#65031 could be cause of it

Fix

  • Tighten hasUniformExternalConnectivity to require every externally-connected child to share the same full (sources, targets) profile. Mixed entry/exit shapes (like the reporter's repro) now fall back to rendering individual crossing edges, preserving the author's explicit dependency intent. The canonical "cleanup group" fan-in/fan-out pattern that the optimization was designed for (every child has same upstream AND same downstream) still triggers the collapse.
  • Add a preserveInternal option to rewriteGroupEdges. The open-group call site sets it so the collapse optimization preserves internal edges for the subsequent extraction loop; the closed-group call site keeps the default (drop internals — they're not laid out when the group is collapsed).

Tests

New elkGraphUtils.test.ts covers:

Verified the new tests fail against main without the fix and pass with it.

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.7)

Generated-by: Claude Code (Opus 4.7) following the guidelines

Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
Closes: #67714
@vatsrahul1001

Copy link
Copy Markdown
ContributorAuthor

cc: @pierrejeambrun@bbovenzi

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Tested locally looks good. Code looks good.

@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.3 milestone Jun 1, 2026
@pierrejeambrun
pierrejeambrun merged commit 55780f2 into mainJun 1, 2026
83 checks passed
@pierrejeambrun
pierrejeambrun deleted the fix-graph-taskgroup-internal-edges-dropped branch June 1, 2026 09:50
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

github-actionsBot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
aws-airflow-bot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
pierrejeambrun pushed a commit that referenced this pull request Jun 1, 2026
…l nodes (#67720) (#67830)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Closes: #67714
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:TaskGrouparea:UIRelated to UI/UX. For Frontend Developers.kind:bugThis is a clearly a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3.2.2 Graph View breaks when TaskGroup outputs connect internal tasks to external downstream tasks

2 participants

@vatsrahul1001@pierrejeambrun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

UI: Fix Graph layout for TaskGroup tasks wired to external nodes - #67720

Merged
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped
Jun 1, 2026
Merged

UI: Fix Graph layout for TaskGroup tasks wired to external nodes#67720
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped

Conversation

@vatsrahul1001

@vatsrahul1001vatsrahul1001 commented May 29, 2026

Copy link
Copy Markdown
Contributor

Closes#67714.

#65031 could be cause of it

Fix

  • Tighten hasUniformExternalConnectivity to require every externally-connected child to share the same full (sources, targets) profile. Mixed entry/exit shapes (like the reporter's repro) now fall back to rendering individual crossing edges, preserving the author's explicit dependency intent. The canonical "cleanup group" fan-in/fan-out pattern that the optimization was designed for (every child has same upstream AND same downstream) still triggers the collapse.
  • Add a preserveInternal option to rewriteGroupEdges. The open-group call site sets it so the collapse optimization preserves internal edges for the subsequent extraction loop; the closed-group call site keeps the default (drop internals — they're not laid out when the group is collapsed).

Tests

New elkGraphUtils.test.ts covers:

Verified the new tests fail against main without the fix and pass with it.

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.7)

Generated-by: Claude Code (Opus 4.7) following the guidelines

Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
Closes: #67714
@vatsrahul1001

Copy link
Copy Markdown
ContributorAuthor

cc: @pierrejeambrun@bbovenzi

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Tested locally looks good. Code looks good.

@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.3 milestone Jun 1, 2026
@pierrejeambrun
pierrejeambrun merged commit 55780f2 into mainJun 1, 2026
83 checks passed
@pierrejeambrun
pierrejeambrun deleted the fix-graph-taskgroup-internal-edges-dropped branch June 1, 2026 09:50
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

github-actionsBot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
aws-airflow-bot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
pierrejeambrun pushed a commit that referenced this pull request Jun 1, 2026
…l nodes (#67720) (#67830)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Closes: #67714
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:TaskGrouparea:UIRelated to UI/UX. For Frontend Developers.kind:bugThis is a clearly a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3.2.2 Graph View breaks when TaskGroup outputs connect internal tasks to external downstream tasks

2 participants

@vatsrahul1001@pierrejeambrun
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

UI: Fix Graph layout for TaskGroup tasks wired to external nodes - #67720

Merged
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped
Jun 1, 2026
Merged

UI: Fix Graph layout for TaskGroup tasks wired to external nodes#67720
pierrejeambrun merged 1 commit into
mainfrom
fix-graph-taskgroup-internal-edges-dropped

Conversation

@vatsrahul1001

@vatsrahul1001vatsrahul1001 commented May 29, 2026

Copy link
Copy Markdown
Contributor

Closes#67714.

#65031 could be cause of it

Fix

  • Tighten hasUniformExternalConnectivity to require every externally-connected child to share the same full (sources, targets) profile. Mixed entry/exit shapes (like the reporter's repro) now fall back to rendering individual crossing edges, preserving the author's explicit dependency intent. The canonical "cleanup group" fan-in/fan-out pattern that the optimization was designed for (every child has same upstream AND same downstream) still triggers the collapse.
  • Add a preserveInternal option to rewriteGroupEdges. The open-group call site sets it so the collapse optimization preserves internal edges for the subsequent extraction loop; the closed-group call site keeps the default (drop internals — they're not laid out when the group is collapsed).

Tests

New elkGraphUtils.test.ts covers:

Verified the new tests fail against main without the fix and pass with it.

Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 4.7)

Generated-by: Claude Code (Opus 4.7) following the guidelines

Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
Closes: #67714
@vatsrahul1001

Copy link
Copy Markdown
ContributorAuthor

cc: @pierrejeambrun@bbovenzi

@pierrejeambrunpierrejeambrun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Tested locally looks good. Code looks good.

@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.3 milestone Jun 1, 2026
@pierrejeambrun
pierrejeambrun merged commit 55780f2 into mainJun 1, 2026
83 checks passed
@pierrejeambrun
pierrejeambrun deleted the fix-graph-taskgroup-internal-edges-dropped branch June 1, 2026 09:50
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-2-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

StatusBranchResult
v3-2-testPR Link

github-actionsBot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
aws-airflow-bot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Jun 1, 2026
…l nodes (apache#67720)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from apache#65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in apache#67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Closes: apache#67714
pierrejeambrun pushed a commit that referenced this pull request Jun 1, 2026
…l nodes (#67720) (#67830)
Open ``@task_group`` rendered with vertically-stacked internals and edges
crossing the boundary whenever an internal task had a direct dependency
on a node outside the group (an "escape edge" that bypassed the group's
entry/exit interface). Dag execution was unaffected.
Two underlying issues, both in the ELK graph-layout refactor from #65031:
1. ``hasUniformExternalConnectivity`` was too lenient — it fired whenever
externally-connected children separately shared the same external
sources OR the same external targets, instead of the canonical
fan-in/fan-out pattern where every child has the same full
``(sources, targets)`` profile. On mixed-profile groups (entry +
exits), it incorrectly fired and collapsed the author's deliberately-
wired escape edges into a single group-level edge, hiding the intent.
2. When the optimisation did fire on an open group, ``rewriteGroupEdges``
was tuned for closed groups and dropped the group's internal edges
too, leaving ELK with no internal-layout information for the children
(the visible symptom in #67714).
Fix: tighten ``hasUniformExternalConnectivity`` to require the full
profile to match across externally-connected children, and add a
``preserveInternal`` option to ``rewriteGroupEdges`` so the canonical
fan-in/fan-out path keeps internals intact.
(cherry picked from commit 55780f2)
Closes: #67714
Co-authored-by: Rahul Vats <43964496+vatsrahul1001@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:TaskGrouparea:UIRelated to UI/UX. For Frontend Developers.kind:bugThis is a clearly a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3.2.2 Graph View breaks when TaskGroup outputs connect internal tasks to external downstream tasks

2 participants

@vatsrahul1001@pierrejeambrun