STET

agent_patch

runs/2026-02-28__13-38-10__gpt-5-4/flux-pr-1184/flux-pr-1184.1-of-1.2026-02-28__13-38-10__gpt-5-4/agent-logs/agent.patch

16301 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1184.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter.go b/app/v2/pkg/engine/plan/abstract_selection_rewriter.go
index 3484ce9..ed594f0 100644
--- a/tmp/agent-patch-flux-pr-1184.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter.go
+++ b/app/v2/pkg/engine/plan/abstract_selection_rewriter.go
@@ -177,6 +177,10 @@ func (r *fieldSelectionRewriter) unionFieldSelectionNeedsRewrite(selectionSetInf
 		return true
 	}
 
+	if r.unionFragmentsRequiresCleanup(selectionSetInfo.inlineFragmentsOnUnions, unionTypeNames) {
+		return true
+	}
+
 	// when we do not have fragments on objects, but only on interfaces
 	// we need to check that all entities implementing each interface have a root node with the requested fields
 	// e.g. { ... on Interface { a } }
@@ -222,6 +226,10 @@ func (r *fieldSelectionRewriter) rewriteUnionSelection(fieldRef int, fieldInfo s
 		r.flattenFragmentOnInterface(inlineFragmentOnInterface.selectionSetInfo, inlineFragmentOnInterface.typeNamesImplementingInterface, unionTypeNames, &newSelectionRefs)
 	}
 
+	for _, inlineFragmentOnUnion := range fieldInfo.inlineFragmentsOnUnions {
+		r.flattenFragmentOnUnion(inlineFragmentOnUnion.selectionSetInfo, inlineFragmentOnUnion.unionMemberTypeNames, unionTypeNames, &newSelectionRefs)
+	}
+
 	// filter existing fragments by type names exists in the current datasource
 	// TODO: do not need to iterate 2 times in filter and here
 	filteredObjectFragments, _ := r.filterFragmentsByTypeNames(fieldInfo.inlineFragmentsOnObjects, unionTypeNames)
@@ -360,6 +368,12 @@ func (r *fieldSelectionRewriter) interfaceFieldSelectionNeedsRewrite(selectionSe
 		}
 	}
 
+	if selectionSetInfo.hasInlineFragmentsOnUnions {
+		if r.unionFragmentsRequiresCleanup(selectionSetInfo.inlineFragmentsOnUnions, interfaceTypeNames) {
+			return true
+		}
+	}
+
 	if selectionSetInfo.hasInlineFragmentsOnInterfaces && selectionSetInfo.hasInlineFragmentsOnObjects {
 		if len(entitiesWithoutFragment) > 0 {
 			if !r.allEntitiesImplementsInterfaces(selectionSetInfo.inlineFragmentsOnInterfaces, entitiesWithoutFragment) {
@@ -440,6 +454,46 @@ func (r *fieldSelectionRewriter) flattenFragmentOnInterface(selectionSetInfo sel
 
 		r.flattenFragmentOnInterface(inlineFragmentInfo.selectionSetInfo, inlineFragmentInfo.typeNamesImplementingInterface, filteredImplementingTypes, selectionRefs)
 	}
+
+	for _, inlineFragmentInfo := range selectionSetInfo.inlineFragmentsOnUnions {
+		r.flattenFragmentOnUnion(inlineFragmentInfo.selectionSetInfo, inlineFragmentInfo.unionMemberTypeNames, filteredImplementingTypes, selectionRefs)
+	}
+}
+
+func (r *fieldSelectionRewriter) flattenFragmentOnUnion(selectionSetInfo selectionSetInfo, unionMemberTypeNames []string, allowedTypeNames []string, selectionRefs *[]int) {
+	if len(unionMemberTypeNames) == 0 {
+		return
+	}
+
+	filteredMemberTypes := make([]string, 0, len(unionMemberTypeNames))
+	for _, typeName := range unionMemberTypeNames {
+		if slices.Contains(allowedTypeNames, typeName) {
+			filteredMemberTypes = append(filteredMemberTypes, typeName)
+		}
+	}
+
+	if selectionSetInfo.hasFields {
+		for _, typeName := range filteredMemberTypes {
+			*selectionRefs = append(*selectionRefs, r.createFragmentSelection(typeName, selectionSetInfo.fields))
+		}
+	}
+
+	for _, inlineFragmentInfo := range selectionSetInfo.inlineFragmentsOnObjects {
+		if !slices.Contains(filteredMemberTypes, inlineFragmentInfo.typeName) {
+			continue
+		}
+
+		fragmentSelectionRef := r.operation.CopySelection(inlineFragmentInfo.selectionRef)
+		*selectionRefs = append(*selectionRefs, fragmentSelectionRef)
+	}
+
+	for _, inlineFragmentInfo := range selectionSetInfo.inlineFragmentsOnInterfaces {
+		r.flattenFragmentOnInterface(inlineFragmentInfo.selectionSetInfo, inlineFragmentInfo.typeNamesImplementingInterface, filteredMemberTypes, selectionRefs)
+	}
+
+	for _, inlineFragmentInfo := range selectionSetInfo.inlineFragmentsOnUnions {
+		r.flattenFragmentOnUnion(inlineFragmentInfo.selectionSetInfo, inlineFragmentInfo.unionMemberTypeNames, filteredMemberTypes, selectionRefs)
+	}
 }
 
 func (r *fieldSelectionRewriter) collectChangedRefs(fieldRef int, fieldRefsPaths map[int]string) (map[int][]int, error) {
diff --git a/tmp/agent-patch-flux-pr-1184.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter_helpers.go b/app/v2/pkg/engine/plan/abstract_selection_rewriter_helpers.go
index 17a53e1..56d6cd7 100644
--- a/tmp/agent-patch-flux-pr-1184.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter_helpers.go
+++ b/app/v2/pkg/engine/plan/abstract_selection_rewriter_helpers.go
@@ -45,7 +45,7 @@ func (r *fieldSelectionRewriter) entitiesImplementingInterface(typesImplementing
 		}
 	}
 
-	return entityNames
+	return out
 }
 
 func (r *fieldSelectionRewriter) entityNamesWithoutFragments(inlineFragments []inlineFragmentSelection, entityNames []string) []string {
@@ -168,17 +168,54 @@ func (r *fieldSelectionRewriter) interfaceFragmentsRequiresCleanup(inlineFragmen
 	return false
 }
 
-func (r *fieldSelectionRewriter) objectFragmentNeedCleanup(inlineFragment inlineFragmentSelection) bool {
-	if !r.hasTypeOnDataSource(inlineFragment.typeName) {
+func (r *fieldSelectionRewriter) unionFragmentsRequiresCleanup(inlineFragments []inlineFragmentSelectionOnUnion, parentSelectionValidTypes []string) bool {
+	for _, fragment := range inlineFragments {
+		if r.unionFragmentNeedCleanup(fragment, parentSelectionValidTypes) {
+			return true
+		}
+	}
+
+	return false
+}
+
+func (r *fieldSelectionRewriter) intersectTypeNames(left, right []string) []string {
+	if len(left) == 0 || len(right) == 0 {
+		return nil
+	}
+
+	out := make([]string, 0, len(left))
+	for _, typeName := range left {
+		if slices.Contains(right, typeName) {
+			out = append(out, typeName)
+		}
+	}
+
+	return out
+}
+
+func (r *fieldSelectionRewriter) objectFragmentNeedCleanup(inlineFragment inlineFragmentSelection, parentSelectionValidTypes []string) bool {
+	if !r.hasTypeOnDataSource(inlineFragment.typeName) || !slices.Contains(parentSelectionValidTypes, inlineFragment.typeName) {
 		return true
 	}
 
+	for _, fragmentOnObject := range inlineFragment.selectionSetInfo.inlineFragmentsOnObjects {
+		if r.objectFragmentNeedCleanup(fragmentOnObject, []string{inlineFragment.typeName}) {
+			return true
+		}
+	}
+
 	for _, fragmentOnInterface := range inlineFragment.selectionSetInfo.inlineFragmentsOnInterfaces {
 		if r.interfaceFragmentNeedCleanup(fragmentOnInterface, []string{inlineFragment.typeName}) {
 			return true
 		}
 	}
 
+	for _, fragmentOnUnion := range inlineFragment.selectionSetInfo.inlineFragmentsOnUnions {
+		if r.unionFragmentNeedCleanup(fragmentOnUnion, []string{inlineFragment.typeName}) {
+			return true
+		}
+	}
+
 	return false
 }
 
@@ -191,10 +228,9 @@ func (r *fieldSelectionRewriter) interfaceFragmentNeedCleanup(inlineFragment inl
 	// We need to check if interface type in the given datasource is implemented by parent selection valid types
 	// because it could happen that in the given ds we have all types from union but not all of them implements interface
 	// so we need to rewrite, because otherwise we won't get responses for all possible types, but only for implementing interface
-	for _, typeName := range parentSelectionValidTypes {
-		if !slices.Contains(inlineFragment.typeNamesImplementingInterfaceInCurrentDS, typeName) {
-			return true
-		}
+	currentValidTypes := r.intersectTypeNames(inlineFragment.typeNamesImplementingInterfaceInCurrentDS, parentSelectionValidTypes)
+	if len(currentValidTypes) != len(parentSelectionValidTypes) {
+		return true
 	}
 
 	// if interface fragment has inline fragments on objects
@@ -202,11 +238,7 @@ func (r *fieldSelectionRewriter) interfaceFragmentNeedCleanup(inlineFragment inl
 	// check each fragment for the presence of other interface fragments
 	if inlineFragment.selectionSetInfo.hasInlineFragmentsOnObjects {
 		for _, fragmentOnObject := range inlineFragment.selectionSetInfo.inlineFragmentsOnObjects {
-			if !slices.Contains(parentSelectionValidTypes, fragmentOnObject.typeName) {
-				return true
-			}
-
-			if r.objectFragmentNeedCleanup(fragmentOnObject) {
+			if r.objectFragmentNeedCleanup(fragmentOnObject, currentValidTypes) {
 				return true
 			}
 		}
@@ -216,15 +248,65 @@ func (r *fieldSelectionRewriter) interfaceFragmentNeedCleanup(inlineFragment inl
 	// recursively check each fragment for the presence of other interface fragments with the same parent selection valid types
 	if inlineFragment.selectionSetInfo.hasInlineFragmentsOnInterfaces {
 		for _, fragmentOnInterface := range inlineFragment.selectionSetInfo.inlineFragmentsOnInterfaces {
-			if r.interfaceFragmentNeedCleanup(fragmentOnInterface, parentSelectionValidTypes) {
+			if r.interfaceFragmentNeedCleanup(fragmentOnInterface, currentValidTypes) {
 				return true
 			}
 		}
 	}
 
+	if inlineFragment.selectionSetInfo.hasInlineFragmentsOnUnions {
+		for _, fragmentOnUnion := range inlineFragment.selectionSetInfo.inlineFragmentsOnUnions {
+			if r.unionFragmentNeedCleanup(fragmentOnUnion, currentValidTypes) {
+				return true
+			}
+		}
+	}
+
+	if inlineFragment.selectionSetInfo.hasFields {
+		for _, typeName := range currentValidTypes {
+			if !r.typeHasAllFieldLocal(typeName, inlineFragment.selectionSetInfo.fields) {
+				return true
+			}
+
+			if r.hasRequiresConfigurationForField(typeName, inlineFragment.selectionSetInfo.fields) {
+				return true
+			}
+		}
+	}
+
+	return false
+}
+
+func (r *fieldSelectionRewriter) unionFragmentNeedCleanup(inlineFragment inlineFragmentSelectionOnUnion, parentSelectionValidTypes []string) bool {
+	if len(inlineFragment.unionMemberTypeNamesInCurrentDS) == 0 {
+		return true
+	}
+
+	currentValidTypes := r.intersectTypeNames(inlineFragment.unionMemberTypeNamesInCurrentDS, parentSelectionValidTypes)
+	if len(currentValidTypes) != len(parentSelectionValidTypes) {
+		return true
+	}
+
+	for _, fragmentOnObject := range inlineFragment.selectionSetInfo.inlineFragmentsOnObjects {
+		if r.objectFragmentNeedCleanup(fragmentOnObject, currentValidTypes) {
+			return true
+		}
+	}
+
+	for _, fragmentOnInterface := range inlineFragment.selectionSetInfo.inlineFragmentsOnInterfaces {
+		if r.interfaceFragmentNeedCleanup(fragmentOnInterface, currentValidTypes) {
+			return true
+		}
+	}
+
+	for _, fragmentOnUnion := range inlineFragment.selectionSetInfo.inlineFragmentsOnUnions {
+		if r.unionFragmentNeedCleanup(fragmentOnUnion, currentValidTypes) {
+			return true
+		}
+	}
+
 	if inlineFragment.selectionSetInfo.hasFields {
-		// NOTE: maybe we need to filter this typenames by parentSelectionValidTypes?
-		for _, typeName := range inlineFragment.typeNamesImplementingInterfaceInCurrentDS {
+		for _, typeName := range currentValidTypes {
 			if !r.typeHasAllFieldLocal(typeName, inlineFragment.selectionSetInfo.fields) {
 				return true
 			}
diff --git a/tmp/agent-patch-flux-pr-1184.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter_info.go b/app/v2/pkg/engine/plan/abstract_selection_rewriter_info.go
index 950ccb0..2085abf 100644
--- a/tmp/agent-patch-flux-pr-1184.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter_info.go
+++ b/app/v2/pkg/engine/plan/abstract_selection_rewriter_info.go
@@ -171,7 +171,7 @@ func (r *fieldSelectionRewriter) collectInlineFragmentInformation(
 				unionMemberTypeNamesFromCurrentDS, _ := r.upstreamDefinition.UnionTypeDefinitionMemberTypeNames(upstreamNode.Ref)
 				entityNames, _ := r.datasourceHasEntitiesWithName(unionMemberTypeNamesFromCurrentDS)
 
-				inlineFragmentSelectionOnUnion.unionMemberTypeNames = unionMemberTypeNamesFromCurrentDS
+				inlineFragmentSelectionOnUnion.unionMemberTypeNamesInCurrentDS = unionMemberTypeNamesFromCurrentDS
 				inlineFragmentSelectionOnUnion.unionMemberEntityNames = entityNames
 			}
 		}
diff --git a/tmp/agent-patch-flux-pr-1184.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter_test.go b/app/v2/pkg/engine/plan/abstract_selection_rewriter_test.go
index c58465a..c47a177 100644
--- a/tmp/agent-patch-flux-pr-1184.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/abstract_selection_rewriter_test.go
+++ b/app/v2/pkg/engine/plan/abstract_selection_rewriter_test.go
@@ -2167,6 +2167,101 @@ func TestInterfaceSelectionRewriter_RewriteOperation(t *testing.T) {
 						}
 					}
 				}`,
+			expectedOperation: `
+				query {
+					iface {
+						... on Admin {
+							name
+						}
+						... on User {
+							name
+							isUser
+						}
+					}
+			}`,
+			shouldRewrite: true,
+		},
+		{
+			name: "interface field rewrites nested union fragments inside interface fragments",
+			definition: `
+				interface HasName {
+					name: String!
+				}
+
+				type User implements HasName {
+					id: ID!
+					name: String!
+					isUser: Boolean!
+				}
+
+				type Admin implements HasName {
+					id: ID!
+					name: String!
+				}
+
+				type Moderator implements HasName {
+					id: ID!
+					name: String!
+				}
+
+				union Account = User | Admin | Moderator
+
+				type Query {
+					iface: HasName!
+				}`,
+			upstreamDefinition: `
+				interface HasName {
+					name: String!
+				}
+
+				type User implements HasName {
+					id: ID!
+					name: String!
+					isUser: Boolean!
+				}
+
+				type Admin implements HasName {
+					id: ID!
+					name: String! @external
+				}
+
+				union Account = User | Admin
+
+				type Query {
+					iface: HasName!
+				}`,
+			dsConfiguration: dsb().
+				RootNode("Query", "iface").
+				RootNode("User", "id", "name", "isUser").
+				RootNode("Admin", "id").
+				ChildNode("HasName", "name").
+				KeysMetadata(FederationFieldConfigurations{
+					{
+						TypeName:     "User",
+						SelectionSet: "id",
+					},
+					{
+						TypeName:     "Admin",
+						SelectionSet: "id",
+					},
+				}).
+				DS(),
+			operation: `
+				query {
+					iface {
+						... on HasName {
+							name
+							... on Account {
+								... on User {
+									isUser
+								}
+								... on Moderator {
+									name
+								}
+							}
+						}
+					}
+				}`,
 			expectedOperation: `
 				query {
 					iface {
@@ -2263,6 +2358,102 @@ func TestInterfaceSelectionRewriter_RewriteOperation(t *testing.T) {
 						}
 					}
 				}`,
+			expectedOperation: `
+				query {
+					returnsUnion {
+						... on Admin {
+							name
+						}
+						... on User {
+							name
+							isUser
+						}
+					}
+			}`,
+			shouldRewrite: true,
+		},
+		{
+			name:      "union field rewrites nested union fragments inside interface fragments",
+			fieldName: "returnsUnion",
+			definition: `
+				interface HasName {
+					name: String!
+				}
+
+				type User implements HasName {
+					id: ID!
+					name: String!
+					isUser: Boolean!
+				}
+
+				type Admin implements HasName {
+					id: ID!
+					name: String!
+				}
+
+				type Moderator implements HasName {
+					id: ID!
+					name: String!
+				}
+
+				union Account = User | Admin | Moderator
+
+				type Query {
+					returnsUnion: Account!
+				}`,
+			upstreamDefinition: `
+				interface HasName {
+					name: String!
+				}
+
+				type User implements HasName {
+					id: ID!
+					name: String!
+					isUser: Boolean!
+				}
+
+				type Admin implements HasName {
+					id: ID!
+					name: String! @external
+				}
+
+				union Account = User | Admin
+
+				type Query {
+					returnsUnion: Account!
+				}`,
+			dsConfiguration: dsb().
+				RootNode("Query", "returnsUnion").
+				RootNode("User", "id", "name", "isUser").
+				RootNode("Admin", "id").
+				ChildNode("HasName", "name").
+				KeysMetadata(FederationFieldConfigurations{
+					{
+						TypeName:     "User",
+						SelectionSet: "id",
+					},
+					{
+						TypeName:     "Admin",
+						SelectionSet: "id",
+					},
+				}).
+				DS(),
+			operation: `
+				query {
+					returnsUnion {
+						... on HasName {
+							name
+							... on Account {
+								... on User {
+									isUser
+								}
+								... on Moderator {
+									name
+								}
+							}
+						}
+					}
+				}`,
 			expectedOperation: `
 				query {
 					returnsUnion {