STET

agent_patch

runs/2026-02-28__13-38-10__gpt-5-3-codex/flux-pr-828/flux-pr-828.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/agent-logs/agent.patch

15339 bytes

Back to adjudication
diff --git a/app/v2/pkg/astminifier/astminifier.go b/app/v2/pkg/astminifier/astminifier.go
new file mode 100644
index 0000000..7e4c520
--- /dev/null
+++ b/app/v2/pkg/astminifier/astminifier.go
@@ -0,0 +1,282 @@
+package astminifier
+
+import (
+	"fmt"
+	"sort"
+
+	"github.com/wundergraph/graphql-go-tools/v2/pkg/ast"
+	"github.com/wundergraph/graphql-go-tools/v2/pkg/astparser"
+	"github.com/wundergraph/graphql-go-tools/v2/pkg/astprinter"
+	"github.com/wundergraph/graphql-go-tools/v2/pkg/operationreport"
+)
+
+// MinifySubgraphOperationIfSmaller deduplicates repeated inline-fragment selection sets by
+// extracting them into named fragments. It returns the minified operation only when it is smaller.
+func MinifySubgraphOperationIfSmaller(operation []byte) (out []byte, applied bool, err error) {
+	minified, changed, err := MinifySubgraphOperation(operation)
+	if err != nil {
+		return nil, false, err
+	}
+	if !changed || len(minified) >= len(operation) {
+		return operation, false, nil
+	}
+	return minified, true, nil
+}
+
+// MinifySubgraphOperation deduplicates repeated inline-fragment selection sets by extracting
+// them into named fragments.
+func MinifySubgraphOperation(operation []byte) (out []byte, changed bool, err error) {
+	doc := ast.NewSmallDocument()
+	report := &operationreport.Report{}
+	parser := astparser.NewParser()
+	doc.Input.ResetInputBytes(operation)
+	parser.Parse(doc, report)
+	if report.HasErrors() {
+		return nil, false, fmt.Errorf("astminifier: parse operation failed: %w", report)
+	}
+
+	changed = dedupeInlineFragmentSelectionSets(doc)
+
+	minified, err := astprinter.PrintString(doc, nil)
+	if err != nil {
+		return nil, false, fmt.Errorf("astminifier: print operation failed: %w", err)
+	}
+
+	return []byte(minified), changed, nil
+}
+
+func dedupeInlineFragmentSelectionSets(doc *ast.Document) bool {
+	inlineFragmentRefsByType := make(map[string][]int)
+	for inlineFragmentRef := range doc.InlineFragments {
+		inlineFragment := doc.InlineFragments[inlineFragmentRef]
+		if !inlineFragment.HasSelections || inlineFragment.SelectionSet == ast.InvalidRef {
+			continue
+		}
+		if inlineFragment.TypeCondition.Type == ast.InvalidRef {
+			continue
+		}
+		typeName := doc.InlineFragmentTypeConditionNameString(inlineFragmentRef)
+		inlineFragmentRefsByType[typeName] = append(
+			inlineFragmentRefsByType[typeName],
+			inlineFragmentRef,
+		)
+	}
+
+	if len(inlineFragmentRefsByType) == 0 {
+		return false
+	}
+
+	usedFragmentNames := make(map[string]struct{}, len(doc.FragmentDefinitions))
+	for i := range doc.FragmentDefinitions {
+		usedFragmentNames[doc.FragmentDefinitionNameString(i)] = struct{}{}
+	}
+	for i := range doc.FragmentSpreads {
+		usedFragmentNames[doc.FragmentSpreadNameString(i)] = struct{}{}
+	}
+
+	fragmentSequence := 0
+	changed := false
+
+	typeNames := make([]string, 0, len(inlineFragmentRefsByType))
+	for typeName := range inlineFragmentRefsByType {
+		typeNames = append(typeNames, typeName)
+	}
+	sort.Strings(typeNames)
+
+	for _, typeName := range typeNames {
+		inlineFragmentRefs := inlineFragmentRefsByType[typeName]
+		groups := findEqualSelectionSetGroups(doc, inlineFragmentRefs)
+		for _, group := range groups {
+			if len(group) < 2 {
+				continue
+			}
+
+			fragmentName := nextFragmentName(usedFragmentNames, &fragmentSequence)
+			addFragmentDefinitionForGroup(doc, group, fragmentName)
+			replaceGroupSelectionsWithSpread(doc, group, fragmentName)
+			changed = true
+		}
+	}
+
+	return changed
+}
+
+func findEqualSelectionSetGroups(doc *ast.Document, inlineFragmentRefs []int) [][]int {
+	visited := make([]bool, len(inlineFragmentRefs))
+	groups := make([][]int, 0, len(inlineFragmentRefs)/2)
+
+	for i := range inlineFragmentRefs {
+		if visited[i] {
+			continue
+		}
+		visited[i] = true
+
+		baseRef := inlineFragmentRefs[i]
+		baseSetRef := doc.InlineFragments[baseRef].SelectionSet
+
+		group := []int{baseRef}
+		for j := i + 1; j < len(inlineFragmentRefs); j++ {
+			if visited[j] {
+				continue
+			}
+
+			candidateRef := inlineFragmentRefs[j]
+			candidateSetRef := doc.InlineFragments[candidateRef].SelectionSet
+			if !selectionSetsEqual(doc, baseSetRef, candidateSetRef) {
+				continue
+			}
+
+			visited[j] = true
+			group = append(group, candidateRef)
+		}
+
+		if len(group) > 1 {
+			groups = append(groups, group)
+		}
+	}
+
+	return groups
+}
+
+func selectionSetsEqual(doc *ast.Document, leftSetRef, rightSetRef int) bool {
+	if leftSetRef == rightSetRef {
+		return true
+	}
+
+	leftSelections := doc.SelectionSets[leftSetRef].SelectionRefs
+	rightSelections := doc.SelectionSets[rightSetRef].SelectionRefs
+	if len(leftSelections) != len(rightSelections) {
+		return false
+	}
+
+	for i := range leftSelections {
+		if !selectionsEqual(doc, leftSelections[i], rightSelections[i]) {
+			return false
+		}
+	}
+
+	return true
+}
+
+func selectionsEqual(doc *ast.Document, leftSelectionRef, rightSelectionRef int) bool {
+	leftSelection := doc.Selections[leftSelectionRef]
+	rightSelection := doc.Selections[rightSelectionRef]
+	if leftSelection.Kind != rightSelection.Kind {
+		return false
+	}
+
+	switch leftSelection.Kind {
+	case ast.SelectionKindField:
+		return fieldsEqual(doc, leftSelection.Ref, rightSelection.Ref)
+	case ast.SelectionKindInlineFragment:
+		return inlineFragmentsEqual(doc, leftSelection.Ref, rightSelection.Ref)
+	case ast.SelectionKindFragmentSpread:
+		return fragmentSpreadsEqual(doc, leftSelection.Ref, rightSelection.Ref)
+	default:
+		return false
+	}
+}
+
+func fieldsEqual(doc *ast.Document, leftFieldRef, rightFieldRef int) bool {
+	leftField := doc.Fields[leftFieldRef]
+	rightField := doc.Fields[rightFieldRef]
+
+	if !doc.FieldNameBytes(leftFieldRef).Equals(doc.FieldNameBytes(rightFieldRef)) {
+		return false
+	}
+	if !doc.FieldAliasBytes(leftFieldRef).Equals(doc.FieldAliasBytes(rightFieldRef)) {
+		return false
+	}
+	if !doc.ArgumentSetsAreEquals(leftField.Arguments.Refs, rightField.Arguments.Refs) {
+		return false
+	}
+	if !doc.DirectiveSetsAreEqual(leftField.Directives.Refs, rightField.Directives.Refs) {
+		return false
+	}
+	if leftField.HasSelections != rightField.HasSelections {
+		return false
+	}
+	if !leftField.HasSelections {
+		return true
+	}
+
+	return selectionSetsEqual(doc, leftField.SelectionSet, rightField.SelectionSet)
+}
+
+func inlineFragmentsEqual(doc *ast.Document, leftInlineFragmentRef, rightInlineFragmentRef int) bool {
+	leftInlineFragment := doc.InlineFragments[leftInlineFragmentRef]
+	rightInlineFragment := doc.InlineFragments[rightInlineFragmentRef]
+
+	if leftInlineFragment.TypeCondition.Type != rightInlineFragment.TypeCondition.Type {
+		return false
+	}
+	if !doc.DirectiveSetsAreEqual(leftInlineFragment.Directives.Refs, rightInlineFragment.Directives.Refs) {
+		return false
+	}
+	if leftInlineFragment.HasSelections != rightInlineFragment.HasSelections {
+		return false
+	}
+	if !leftInlineFragment.HasSelections {
+		return true
+	}
+
+	return selectionSetsEqual(doc, leftInlineFragment.SelectionSet, rightInlineFragment.SelectionSet)
+}
+
+func fragmentSpreadsEqual(doc *ast.Document, leftFragmentSpreadRef, rightFragmentSpreadRef int) bool {
+	if !doc.FragmentSpreadNameBytes(leftFragmentSpreadRef).Equals(doc.FragmentSpreadNameBytes(rightFragmentSpreadRef)) {
+		return false
+	}
+	return doc.DirectiveSetsAreEqual(
+		doc.FragmentSpreads[leftFragmentSpreadRef].Directives.Refs,
+		doc.FragmentSpreads[rightFragmentSpreadRef].Directives.Refs,
+	)
+}
+
+func nextFragmentName(usedNames map[string]struct{}, sequence *int) string {
+	for {
+		name := fmt.Sprintf("_wgf%d", *sequence)
+		*sequence = *sequence + 1
+		if _, exists := usedNames[name]; exists {
+			continue
+		}
+		usedNames[name] = struct{}{}
+		return name
+	}
+}
+
+func addFragmentDefinitionForGroup(doc *ast.Document, inlineFragmentRefs []int, fragmentName string) {
+	firstInlineFragment := doc.InlineFragments[inlineFragmentRefs[0]]
+	selectionSetRef := doc.CopySelectionSet(firstInlineFragment.SelectionSet)
+
+	fragmentDefinitionRef := len(doc.FragmentDefinitions)
+	doc.FragmentDefinitions = append(doc.FragmentDefinitions, ast.FragmentDefinition{
+		Name: doc.Input.AppendInputString(fragmentName),
+		TypeCondition: ast.TypeCondition{
+			Type: firstInlineFragment.TypeCondition.Type,
+		},
+		SelectionSet:  selectionSetRef,
+		HasSelections: !doc.SelectionSetIsEmpty(selectionSetRef),
+	})
+	doc.RootNodes = append(doc.RootNodes, ast.Node{
+		Kind: ast.NodeKindFragmentDefinition,
+		Ref:  fragmentDefinitionRef,
+	})
+}
+
+func replaceGroupSelectionsWithSpread(doc *ast.Document, inlineFragmentRefs []int, fragmentName string) {
+	for _, inlineFragmentRef := range inlineFragmentRefs {
+		selectionSetRef := doc.InlineFragments[inlineFragmentRef].SelectionSet
+		doc.EmptySelectionSet(selectionSetRef)
+
+		fragmentSpreadRef := doc.AddFragmentSpread(ast.FragmentSpread{
+			FragmentName: doc.Input.AppendInputString(fragmentName),
+		})
+		doc.AddSelection(selectionSetRef, ast.Selection{
+			Kind: ast.SelectionKindFragmentSpread,
+			Ref:  fragmentSpreadRef,
+		})
+
+		doc.InlineFragments[inlineFragmentRef].HasSelections = true
+	}
+}
diff --git a/app/v2/pkg/astminifier/astminifier_test.go b/app/v2/pkg/astminifier/astminifier_test.go
new file mode 100644
index 0000000..9194229
--- /dev/null
+++ b/app/v2/pkg/astminifier/astminifier_test.go
@@ -0,0 +1,46 @@
+package astminifier
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestMinifySubgraphOperationIfSmaller(t *testing.T) {
+	t.Run("extracts duplicate inline-fragment selection sets", func(t *testing.T) {
+		sharedSelectionSet := `id name username email phone profilePic(size:50){url width height} bestFriend{firstName lastName} friends{count edges{node{id name}}}`
+
+		var builder strings.Builder
+		builder.WriteString("query{")
+		for i := 0; i < 20; i++ {
+			builder.WriteString(fmt.Sprintf("f%d:user{... on User{%s}}", i, sharedSelectionSet))
+		}
+		builder.WriteString("}")
+		operation := []byte(builder.String())
+
+		candidate, changed, err := MinifySubgraphOperation(operation)
+		require.NoError(t, err)
+		require.True(t, changed)
+
+		minified, applied, err := MinifySubgraphOperationIfSmaller(operation)
+		require.NoError(t, err)
+		require.True(t, applied)
+		require.Less(t, len(minified), len(operation))
+		require.Less(t, len(candidate), len(operation))
+
+		minifiedString := string(minified)
+		require.Contains(t, minifiedString, "fragment _wgf0 on User")
+		require.Equal(t, 20, strings.Count(minifiedString, "..._wgf0"))
+	})
+
+	t.Run("keeps original operation when result is not smaller", func(t *testing.T) {
+		operation := []byte(`query{a{... on User{id}}b{... on User{id}}}`)
+
+		minified, applied, err := MinifySubgraphOperationIfSmaller(operation)
+		require.NoError(t, err)
+		require.False(t, applied)
+		require.Equal(t, operation, minified)
+	})
+}
diff --git a/tmp/agent-patch-flux-pr-828.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go b/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go
index d9ea5f5..a9c350c 100644
--- a/tmp/agent-patch-flux-pr-828.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go
+++ b/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go
@@ -16,6 +16,7 @@ import (
 	"github.com/tidwall/sjson"
 
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/ast"
+	"github.com/wundergraph/graphql-go-tools/v2/pkg/astminifier"
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/astnormalization"
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/astparser"
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/astprinter"
@@ -1353,7 +1354,17 @@ func (p *Planner[T]) printOperation() []byte {
 		return nil
 	}
 
-	return buf.Bytes()
+	printedQuery := bytes.Clone(buf.Bytes())
+	if !p.dataSourcePlannerConfig.EnableOperationMinifier {
+		return printedQuery
+	}
+
+	minified, applied, err := astminifier.MinifySubgraphOperationIfSmaller(printedQuery)
+	if err != nil || !applied {
+		return printedQuery
+	}
+
+	return minified
 }
 
 func (p *Planner[T]) stopWithError(msg string, args ...interface{}) {
diff --git a/tmp/agent-patch-flux-pr-828.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/plan/configuration.go b/app/v2/pkg/engine/plan/configuration.go
index 6bb384b..bc7df64 100644
--- a/tmp/agent-patch-flux-pr-828.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/plan/configuration.go
+++ b/app/v2/pkg/engine/plan/configuration.go
@@ -12,6 +12,9 @@ type Configuration struct {
 	DataSources                []DataSource
 	Fields                     FieldConfigurations
 	Types                      TypeConfigurations
+	// EnableOperationMinifier enables optional subgraph operation minification.
+	// The minified operation will only be used when it is smaller than the original operation.
+	EnableOperationMinifier bool
 	// DisableResolveFieldPositions should be set to true for testing purposes
 	// This setting removes position information from all fields
 	// In production, this should be set to false so that error messages are easier to understand
diff --git a/tmp/agent-patch-flux-pr-828.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/plan/datasource_configuration.go b/app/v2/pkg/engine/plan/datasource_configuration.go
index 05b0b5b..1cc741e 100644
--- a/tmp/agent-patch-flux-pr-828.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/plan/datasource_configuration.go
+++ b/app/v2/pkg/engine/plan/datasource_configuration.go
@@ -159,11 +159,12 @@ func (d *dataSourceConfiguration[T]) Hash() DSHash {
 }
 
 type DataSourcePlannerConfiguration struct {
-	RequiredFields FederationFieldConfigurations
-	ProvidedFields *NodeSuggestions
-	ParentPath     string
-	PathType       PlannerPathType
-	IsNested       bool
+	RequiredFields          FederationFieldConfigurations
+	ProvidedFields          *NodeSuggestions
+	ParentPath              string
+	PathType                PlannerPathType
+	IsNested                bool
+	EnableOperationMinifier bool
 }
 
 type PlannerPathType int
diff --git a/tmp/agent-patch-flux-pr-828.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/plan/planner_configuration.go b/app/v2/pkg/engine/plan/planner_configuration.go
index 0485948..414c3ee 100644
--- a/tmp/agent-patch-flux-pr-828.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/plan/planner_configuration.go
+++ b/app/v2/pkg/engine/plan/planner_configuration.go
@@ -36,11 +36,12 @@ type PlannerConfiguration interface {
 
 func (p *plannerConfiguration[T]) Register(visitor *Visitor) error {
 	dataSourcePlannerConfig := DataSourcePlannerConfiguration{
-		RequiredFields: p.requiredFields,
-		ProvidedFields: p.providedFields,
-		ParentPath:     p.parentPath,
-		PathType:       p.parentPathType,
-		IsNested:       p.IsNestedPlanner(),
+		RequiredFields:          p.requiredFields,
+		ProvidedFields:          p.providedFields,
+		ParentPath:              p.parentPath,
+		PathType:                p.parentPathType,
+		IsNested:                p.IsNestedPlanner(),
+		EnableOperationMinifier: visitor.Config.EnableOperationMinifier,
 	}
 
 	return p.planner.Register(visitor, p.dataSourceConfiguration, dataSourcePlannerConfig)