STET

agent_patch

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

9187 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1380.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/node_selection_visitor.go b/app/v2/pkg/engine/plan/node_selection_visitor.go
index bbcffd3..e053afa 100644
--- a/tmp/agent-patch-flux-pr-1380.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/plan/node_selection_visitor.go
+++ b/app/v2/pkg/engine/plan/node_selection_visitor.go
@@ -4,9 +4,11 @@ import (
 	"errors"
 	"fmt"
 	"slices"
+	"strings"
 
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/ast"
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/astvisitor"
+	"github.com/wundergraph/graphql-go-tools/v2/pkg/operationreport"
 )
 
 // nodeSelectionVisitor walks through the operation multiple times to rewrite it
@@ -290,6 +292,10 @@ func (c *nodeSelectionVisitor) handleFieldRequiredByRequires(fieldRef int, paren
 		return
 	}
 
+	if c.areRequiresFieldsSatisfiedBySelections(parentPath, requiresConfiguration) {
+		return
+	}
+
 	// we should plan adding required fields for the field
 	// they will be added in the on LeaveSelectionSet callback for the current selection set
 	// and current field ref will be added to fieldDependsOn map
@@ -770,3 +776,57 @@ func (c *nodeSelectionVisitor) updateSkipFieldRefs(changedFieldRefs map[int][]in
 		}
 	}
 }
+
+func (c *nodeSelectionVisitor) areRequiresFieldsSatisfiedBySelections(parentPath string, requiresConfiguration FederationFieldConfiguration) bool {
+	if c.nodeSuggestions == nil {
+		return false
+	}
+
+	if err := requiresConfiguration.parseSelectionSet(); err != nil {
+		return false
+	}
+
+	report := &operationreport.Report{}
+	walker := astvisitor.NewWalkerWithID(48, "RequiresSelectionSatisfactionVisitor")
+	visitor := &requiresSelectionSatisfactionVisitor{
+		walker:       &walker,
+		operation:    requiresConfiguration.parsedSelectionSet,
+		definition:   c.definition,
+		parentPath:   parentPath,
+		rootTypeName: requiresConfiguration.TypeName,
+		suggestions:  c.nodeSuggestions,
+		satisfied:    true,
+	}
+
+	walker.RegisterEnterFieldVisitor(visitor)
+	walker.Walk(requiresConfiguration.parsedSelectionSet, c.definition, report)
+
+	return !report.HasErrors() && visitor.satisfied
+}
+
+type requiresSelectionSatisfactionVisitor struct {
+	walker       *astvisitor.Walker
+	operation    *ast.Document
+	definition   *ast.Document
+	parentPath   string
+	rootTypeName string
+	suggestions  *NodeSuggestions
+	satisfied    bool
+}
+
+func (v *requiresSelectionSatisfactionVisitor) EnterField(ref int) {
+	if !v.satisfied {
+		return
+	}
+
+	fieldName := v.operation.FieldNameUnsafeString(ref)
+	typeName := v.walker.EnclosingTypeDefinition.NameString(v.definition)
+	currentPathWithoutFragments := v.walker.Path.WithoutInlineFragmentNames().DotDelimitedString()
+	parentPath := v.parentPath + strings.TrimPrefix(currentPathWithoutFragments, v.rootTypeName)
+	currentPath := parentPath + "." + fieldName
+
+	_, ok := v.suggestions.HasSuggestionForPath(typeName, fieldName, currentPath)
+	if !ok {
+		v.satisfied = false
+	}
+}
diff --git a/app/v2/pkg/engine/plan/node_selection_visitor_test.go b/app/v2/pkg/engine/plan/node_selection_visitor_test.go
new file mode 100644
index 0000000..5ba886a
--- /dev/null
+++ b/app/v2/pkg/engine/plan/node_selection_visitor_test.go
@@ -0,0 +1,163 @@
+package plan
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	"github.com/wundergraph/graphql-go-tools/v2/pkg/ast"
+	"github.com/wundergraph/graphql-go-tools/v2/pkg/internal/unsafeparser"
+)
+
+func TestNodeSelectionVisitor_HandleFieldRequiredByRequires(t *testing.T) {
+	definition := unsafeparser.ParseGraphqlDocumentStringWithBaseSchema(`
+		type Query {
+			me: User!
+		}
+
+		type User {
+			address: Address!
+		}
+
+		type Address {
+			street: String!
+			zip: String!
+		}
+	`)
+
+	operation := unsafeparser.ParseGraphqlDocumentString(`
+		query {
+			me {
+				address {
+					street
+				}
+			}
+		}
+	`)
+
+	addressSelectionSetRef := findFieldSelectionSetRefByPath(t, &operation, operation.OperationDefinitions[0].SelectionSet, "me", "address")
+	streetFieldRef := findFieldRefByPath(t, &operation, operation.OperationDefinitions[0].SelectionSet, "me", "address", "street")
+
+	ds := &dataSourceConfiguration[any]{
+		hash: 1,
+		DataSourceMetadata: &DataSourceMetadata{
+			FederationMetaData: FederationMetaData{
+				Requires: FederationFieldConfigurations{
+					{
+						TypeName:     "Address",
+						FieldName:    "street",
+						SelectionSet: "zip",
+					},
+				},
+			},
+		},
+	}
+
+	t.Run("skips pending requirements when selected suggestions already satisfy requires", func(t *testing.T) {
+		visitor := &nodeSelectionVisitor{
+			operation:                   &operation,
+			definition:                  &definition,
+			nodeSuggestions:             selectedSuggestions(newSuggestion("Address", "zip", "query.me.address.zip")),
+			selectionSetRefs:            []int{addressSelectionSetRef},
+			pendingFieldRequirements:    make(map[int]pendingFieldRequirements),
+			visitedFieldsRequiresChecks: make(map[fieldIndexKey]struct{}),
+			visitedFieldsKeyChecks:      make(map[fieldIndexKey]struct{}),
+			visitedFieldsAbstractChecks: make(map[int]struct{}),
+			fieldDependencyKind:         make(map[fieldDependencyKey]fieldDependencyKind),
+			fieldDependsOn:              make(map[fieldIndexKey][]int),
+			fieldRefDependsOn:           make(map[int][]int),
+			fieldRequirementsConfigs:    make(map[fieldIndexKey][]FederationFieldConfiguration),
+			fieldLandedTo:               make(map[int]DSHash),
+			newFieldRefs:                make(map[int]struct{}),
+		}
+
+		visitor.handleFieldRequiredByRequires(streetFieldRef, "query.me.address", "Address", "street", "query.me.address.street", ds)
+
+		assert.Empty(t, visitor.pendingFieldRequirements)
+	})
+
+	t.Run("adds pending requirements when selections do not satisfy requires", func(t *testing.T) {
+		visitor := &nodeSelectionVisitor{
+			operation:                   &operation,
+			definition:                  &definition,
+			nodeSuggestions:             NewNodeSuggestions(),
+			selectionSetRefs:            []int{addressSelectionSetRef},
+			pendingFieldRequirements:    make(map[int]pendingFieldRequirements),
+			visitedFieldsRequiresChecks: make(map[fieldIndexKey]struct{}),
+			visitedFieldsKeyChecks:      make(map[fieldIndexKey]struct{}),
+			visitedFieldsAbstractChecks: make(map[int]struct{}),
+			fieldDependencyKind:         make(map[fieldDependencyKey]fieldDependencyKind),
+			fieldDependsOn:              make(map[fieldIndexKey][]int),
+			fieldRefDependsOn:           make(map[int][]int),
+			fieldRequirementsConfigs:    make(map[fieldIndexKey][]FederationFieldConfiguration),
+			fieldLandedTo:               make(map[int]DSHash),
+			newFieldRefs:                make(map[int]struct{}),
+		}
+
+		visitor.handleFieldRequiredByRequires(streetFieldRef, "query.me.address", "Address", "street", "query.me.address.street", ds)
+
+		require.Len(t, visitor.pendingFieldRequirements, 1)
+		require.Contains(t, visitor.pendingFieldRequirements, addressSelectionSetRef)
+		assert.Len(t, visitor.pendingFieldRequirements[addressSelectionSetRef].requirementConfigs, 1)
+		assert.Equal(t, "zip", visitor.pendingFieldRequirements[addressSelectionSetRef].requirementConfigs[0].selectionSet)
+	})
+}
+
+func selectedSuggestions(suggestions ...*NodeSuggestion) *NodeSuggestions {
+	nodes := NewNodeSuggestionsWithSize(len(suggestions))
+	nodes.AddItems(suggestions...)
+	return nodes
+}
+
+func newSuggestion(typeName, fieldName, path string) *NodeSuggestion {
+	return &NodeSuggestion{
+		TypeName:       typeName,
+		FieldName:      fieldName,
+		Path:           path,
+		DataSourceHash: 1,
+		Selected:       true,
+	}
+}
+
+func findFieldRefByPath(t *testing.T, operation *ast.Document, selectionSetRef int, path ...string) int {
+	t.Helper()
+
+	currentSelectionSetRef := selectionSetRef
+	for i, segment := range path {
+		fieldRef := findFieldRefInSelectionSet(t, operation, currentSelectionSetRef, segment)
+		if i == len(path)-1 {
+			return fieldRef
+		}
+
+		nextSelectionSetRef, ok := operation.FieldSelectionSet(fieldRef)
+		require.True(t, ok, "field %s has no selection set", segment)
+		currentSelectionSetRef = nextSelectionSetRef
+	}
+
+	t.Fatalf("path %v not found", path)
+	return ast.InvalidRef
+}
+
+func findFieldSelectionSetRefByPath(t *testing.T, operation *ast.Document, selectionSetRef int, path ...string) int {
+	t.Helper()
+
+	fieldRef := findFieldRefByPath(t, operation, selectionSetRef, path...)
+	nextSelectionSetRef, ok := operation.FieldSelectionSet(fieldRef)
+	require.True(t, ok, "field %v has no selection set", path)
+	return nextSelectionSetRef
+}
+
+func findFieldRefInSelectionSet(t *testing.T, operation *ast.Document, selectionSetRef int, fieldName string) int {
+	t.Helper()
+
+	for _, selectionRef := range operation.SelectionSetFieldSelections(selectionSetRef) {
+		fieldRef := operation.Selections[selectionRef].Ref
+		if operation.FieldNameString(fieldRef) == fieldName {
+			return fieldRef
+		}
+	}
+
+	t.Fatalf("field %s not found in selection set %d", fieldName, selectionSetRef)
+	return ast.InvalidRef
+}