STET

agent_patch

runs/2026-02-28__13-38-10__gpt-5-1-codex-mini/flux-pr-1268/flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/agent-logs/agent.patch

27209 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go b/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go
index 316e2fc..0bbc3eb 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go
+++ b/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go
@@ -269,14 +269,6 @@ func (p *Planner[T]) DownstreamResponseFieldAlias(downstreamFieldRef int) (alias
 	return "", false
 }
 
-func (p *Planner[T]) DataSourcePlanningBehavior() plan.DataSourcePlanningBehavior {
-	return plan.DataSourcePlanningBehavior{
-		MergeAliasedRootNodes:      true,
-		OverrideFieldPathFromAlias: true,
-		IncludeTypeNameFields:      true,
-	}
-}
-
 func (p *Planner[T]) Register(visitor *plan.Visitor, configuration plan.DataSourceConfiguration[T], dataSourcePlannerConfiguration plan.DataSourcePlannerConfiguration) error {
 
 	p.visitor = visitor
@@ -1721,11 +1713,12 @@ var (
 )
 
 type Factory[T Configuration] struct {
-	executionContext   context.Context
-	httpClient         *http.Client
-	grpcClient         grpc.ClientConnInterface
-	grpcClientProvider func() grpc.ClientConnInterface
-	subscriptionClient GraphQLSubscriptionClient
+	executionContext       context.Context
+	httpClient             *http.Client
+	grpcClient             grpc.ClientConnInterface
+	grpcClientProvider     func() grpc.ClientConnInterface
+	subscriptionClient     GraphQLSubscriptionClient
+	flattenInlineFragments bool
 }
 
 // NewFactory (HTTP) creates a new factory for the GraphQL datasource planner
@@ -1743,9 +1736,10 @@ func NewFactory(executionContext context.Context, httpClient *http.Client, subsc
 	}
 
 	return &Factory[Configuration]{
-		executionContext:   executionContext,
-		httpClient:         httpClient,
-		subscriptionClient: subscriptionClient,
+		executionContext:       executionContext,
+		httpClient:             httpClient,
+		subscriptionClient:     subscriptionClient,
+		flattenInlineFragments: false,
 	}, nil
 }
 
@@ -1762,8 +1756,9 @@ func NewFactoryGRPC(executionContext context.Context, grpcClient grpc.ClientConn
 	}
 
 	return &Factory[Configuration]{
-		executionContext: executionContext,
-		grpcClient:       grpcClient,
+		executionContext:       executionContext,
+		grpcClient:             grpcClient,
+		flattenInlineFragments: true,
 	}, nil
 }
 
@@ -1782,8 +1777,9 @@ func NewFactoryGRPCClientProvider(executionContext context.Context, clientProvid
 	}
 
 	return &Factory[Configuration]{
-		executionContext:   executionContext,
-		grpcClientProvider: clientProvider,
+		executionContext:       executionContext,
+		grpcClientProvider:     clientProvider,
+		flattenInlineFragments: true,
 	}, nil
 }
 
@@ -1825,6 +1821,15 @@ func (f *Factory[T]) UpstreamSchema(dataSourceConfig plan.DataSourceConfiguratio
 	return schema, true
 }
 
+func (f *Factory[T]) DataSourcePlanningBehavior() plan.DataSourcePlanningBehavior {
+	return plan.DataSourcePlanningBehavior{
+		MergeAliasedRootNodes:      true,
+		OverrideFieldPathFromAlias: true,
+		PlanTypeNameFields:         true,
+		FlattenInlineFragments:     f.flattenInlineFragments,
+	}
+}
+
 type Source struct {
 	httpClient *http.Client
 }
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/datasource/introspection_datasource/factory.go b/app/v2/pkg/engine/datasource/introspection_datasource/factory.go
index a251521..65bbfce 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/datasource/introspection_datasource/factory.go
+++ b/app/v2/pkg/engine/datasource/introspection_datasource/factory.go
@@ -29,3 +29,11 @@ func (f *Factory[T]) Context() context.Context {
 func (f *Factory[T]) UpstreamSchema(dataSourceConfig plan.DataSourceConfiguration[T]) (*ast.Document, bool) {
 	return nil, false
 }
+
+func (f *Factory[T]) DataSourcePlanningBehavior() plan.DataSourcePlanningBehavior {
+	return plan.DataSourcePlanningBehavior{
+		MergeAliasedRootNodes:      false,
+		OverrideFieldPathFromAlias: true,
+		PlanTypeNameFields:         true,
+	}
+}
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/datasource/introspection_datasource/planner.go b/app/v2/pkg/engine/datasource/introspection_datasource/planner.go
index 2b05800..481dc3c 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/datasource/introspection_datasource/planner.go
+++ b/app/v2/pkg/engine/datasource/introspection_datasource/planner.go
@@ -45,14 +45,6 @@ func (p *Planner[T]) DownstreamResponseFieldAlias(_ int) (alias string, exists b
 	return
 }
 
-func (p *Planner[T]) DataSourcePlanningBehavior() plan.DataSourcePlanningBehavior {
-	return plan.DataSourcePlanningBehavior{
-		MergeAliasedRootNodes:      false,
-		OverrideFieldPathFromAlias: true,
-		IncludeTypeNameFields:      true,
-	}
-}
-
 func (p *Planner[T]) EnterField(ref int) {
 	fieldName := p.v.Operation.FieldNameString(ref)
 	fieldAliasOrName := p.v.Operation.FieldAliasOrNameString(ref)
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/datasource/pubsub_datasource/pubsub_datasource.go b/app/v2/pkg/engine/datasource/pubsub_datasource/pubsub_datasource.go
index 60faa27..30e0345 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/datasource/pubsub_datasource/pubsub_datasource.go
+++ b/app/v2/pkg/engine/datasource/pubsub_datasource/pubsub_datasource.go
@@ -275,14 +275,6 @@ func (p *Planner[T]) ConfigureSubscription() plan.SubscriptionConfiguration {
 	return plan.SubscriptionConfiguration{}
 }
 
-func (p *Planner[T]) DataSourcePlanningBehavior() plan.DataSourcePlanningBehavior {
-	return plan.DataSourcePlanningBehavior{
-		MergeAliasedRootNodes:      false,
-		OverrideFieldPathFromAlias: false,
-		IncludeTypeNameFields:      true,
-	}
-}
-
 func (p *Planner[T]) DownstreamResponseFieldAlias(_ int) (alias string, exists bool) {
 	return "", false
 }
@@ -316,6 +308,14 @@ func (f *Factory[T]) UpstreamSchema(dataSourceConfig plan.DataSourceConfiguratio
 	return nil, false
 }
 
+func (f *Factory[T]) DataSourcePlanningBehavior() plan.DataSourcePlanningBehavior {
+	return plan.DataSourcePlanningBehavior{
+		MergeAliasedRootNodes:      false,
+		OverrideFieldPathFromAlias: false,
+		PlanTypeNameFields:         true,
+	}
+}
+
 func buildEventDataBytes(ref int, visitor *plan.Visitor, variables *resolve.Variables) ([]byte, error) {
 	// Collect the field arguments for fetch based operations
 	fieldArgs := visitor.Operation.FieldArguments(ref)
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/datasource/staticdatasource/static_datasource.go b/app/v2/pkg/engine/datasource/staticdatasource/static_datasource.go
index 3449afb..5c3e00f 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/datasource/staticdatasource/static_datasource.go
+++ b/app/v2/pkg/engine/datasource/staticdatasource/static_datasource.go
@@ -30,6 +30,13 @@ func (f *Factory[T]) UpstreamSchema(dataSourceConfig plan.DataSourceConfiguratio
 	return nil, false
 }
 
+func (f *Factory[T]) DataSourcePlanningBehavior() plan.DataSourcePlanningBehavior {
+	return plan.DataSourcePlanningBehavior{
+		MergeAliasedRootNodes:      false,
+		OverrideFieldPathFromAlias: false,
+	}
+}
+
 type Planner[T Configuration] struct {
 	id     int
 	config Configuration
@@ -48,13 +55,6 @@ func (p *Planner[T]) DownstreamResponseFieldAlias(downstreamFieldRef int) (alias
 	return
 }
 
-func (p *Planner[T]) DataSourcePlanningBehavior() plan.DataSourcePlanningBehavior {
-	return plan.DataSourcePlanningBehavior{
-		MergeAliasedRootNodes:      false,
-		OverrideFieldPathFromAlias: false,
-	}
-}
-
 func (p *Planner[T]) Register(_ *plan.Visitor, configuration plan.DataSourceConfiguration[T], _ plan.DataSourcePlannerConfiguration) error {
 	p.config = Configuration(configuration.CustomConfiguration())
 	return nil
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/abstract_selection_rewriter.go b/app/v2/pkg/engine/plan/abstract_selection_rewriter.go
index 284ad42..bcfc9c4 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/abstract_selection_rewriter.go
+++ b/app/v2/pkg/engine/plan/abstract_selection_rewriter.go
@@ -57,16 +57,6 @@ In this case if any of rules 1-3 are not satisfied we have to rewrite this fragm
 		}
 	}
 */
-type fieldSelectionRewriter struct {
-	operation  *ast.Document
-	definition *ast.Document
-
-	upstreamDefinition *ast.Document
-	dsConfiguration    DataSource
-
-	skipFieldRefs []int
-}
-
 type RewriteResult struct {
 	rewritten        bool
 	changedFieldRefs map[int][]int // map[fieldRef][]fieldRef - for each original fieldRef list of new fieldRefs
@@ -74,19 +64,33 @@ type RewriteResult struct {
 
 var resultNotRewritten = RewriteResult{}
 
-func newFieldSelectionRewriter(operation *ast.Document, definition *ast.Document) *fieldSelectionRewriter {
+type fieldSelectionRewriter struct {
+	operation          *ast.Document
+	definition         *ast.Document
+	upstreamDefinition *ast.Document
+	dsConfiguration    DataSource
+	skipFieldRefs      []int
+}
+
+func newFieldSelectionRewriter(operation *ast.Document, definition *ast.Document, upstreamDefinition *ast.Document, dsConfiguration DataSource) *fieldSelectionRewriter {
 	return &fieldSelectionRewriter{
-		operation:  operation,
-		definition: definition,
+		operation:          operation,
+		definition:         definition,
+		upstreamDefinition: upstreamDefinition,
+		dsConfiguration:    dsConfiguration,
 	}
 }
 
-func (r *fieldSelectionRewriter) SetUpstreamDefinition(upstreamDefinition *ast.Document) {
-	r.upstreamDefinition = upstreamDefinition
-}
+func (r *fieldSelectionRewriter) shouldForceFlatten(selectionInfo selectionSetInfo) bool {
+	if r.dsConfiguration == nil {
+		return false
+	}
+
+	if !r.dsConfiguration.DataSourcePlanningBehavior().FlattenInlineFragments {
+		return false
+	}
 
-func (r *fieldSelectionRewriter) SetDatasourceConfiguration(dsConfiguration DataSource) {
-	r.dsConfiguration = dsConfiguration
+	return selectionInfo.hasInlineFragments()
 }
 
 func (r *fieldSelectionRewriter) RewriteFieldSelection(fieldRef int, enclosingNode ast.Node) (res RewriteResult, err error) {
@@ -143,7 +147,7 @@ func (r *fieldSelectionRewriter) processUnionSelection(fieldRef int, unionDefRef
 	}
 
 	needRewrite := r.unionFieldSelectionNeedsRewrite(selectionSetInfo, unionTypeNames, entityNames)
-	if !needRewrite {
+	if !needRewrite && !r.shouldForceFlatten(selectionSetInfo) {
 		return resultNotRewritten, nil
 	}
 
@@ -307,7 +311,7 @@ func (r *fieldSelectionRewriter) processObjectSelection(fieldRef int, objectDefR
 	}
 
 	needRewrite := r.objectFieldSelectionNeedsRewrite(selectionSetInfo, fieldTypeNameStr)
-	if !needRewrite {
+	if !needRewrite && !r.shouldForceFlatten(selectionSetInfo) {
 		return resultNotRewritten, nil
 	}
 
@@ -386,7 +390,7 @@ func (r *fieldSelectionRewriter) processInterfaceSelection(fieldRef int, interfa
 	selectionSetInfo.isInterfaceObject = isInterfaceObject
 
 	needRewrite := r.interfaceFieldSelectionNeedsRewrite(selectionSetInfo, interfaceTypeNames, entityNames)
-	if !needRewrite {
+	if !needRewrite && !r.shouldForceFlatten(selectionSetInfo) {
 		return resultNotRewritten, nil
 	}
 
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/abstract_selection_rewriter_info.go b/app/v2/pkg/engine/plan/abstract_selection_rewriter_info.go
index 950ccb0..8a7db3f 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/abstract_selection_rewriter_info.go
+++ b/app/v2/pkg/engine/plan/abstract_selection_rewriter_info.go
@@ -20,6 +20,10 @@ type selectionSetInfo struct {
 	hasInlineFragmentsOnUnions     bool
 }
 
+func (s selectionSetInfo) hasInlineFragments() bool {
+	return s.hasInlineFragmentsOnObjects || s.hasInlineFragmentsOnInterfaces || s.hasInlineFragmentsOnUnions
+}
+
 type fieldSelection struct {
 	fieldSelectionRef int
 	fieldName         string
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/abstract_selection_rewriter_test.go b/app/v2/pkg/engine/plan/abstract_selection_rewriter_test.go
index 11b5fc8..89236d3 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/abstract_selection_rewriter_test.go
+++ b/app/v2/pkg/engine/plan/abstract_selection_rewriter_test.go
@@ -49,9 +49,7 @@ func TestInterfaceSelectionRewriter_RewriteOperation(t *testing.T) {
 
 		node, _ := def.Index.FirstNodeByNameStr(testCase.enclosingTypeName)
 
-		rewriter := newFieldSelectionRewriter(&op, &def)
-		rewriter.SetUpstreamDefinition(&upstreamDef)
-		rewriter.SetDatasourceConfiguration(testCase.dsConfiguration)
+		rewriter := newFieldSelectionRewriter(&op, &def, &upstreamDef, testCase.dsConfiguration)
 
 		result, err := rewriter.RewriteFieldSelection(fieldRef, node)
 		require.NoError(t, err)
@@ -3822,3 +3820,77 @@ func TestInterfaceSelectionRewriter_RewriteOperation(t *testing.T) {
 		})
 	}
 }
+
+func TestFieldSelectionRewriter_FlattensInlineFragmentsFlag(t *testing.T) {
+	definition := `
+		union SearchResult = Human | Droid
+
+		type Query {
+			search: SearchResult
+		}
+
+		type Human {
+			name: String
+		}
+
+		type Droid {
+			name: String
+		}
+	`
+	operation := `
+		query {
+			search {
+				... on Human {
+					name
+				}
+				... on Droid {
+					name
+				}
+			}
+		}
+	`
+	baseDS := dsb().
+		Schema(definition).
+		RootNode("Query", "search").
+		RootNode("Human", "name").
+		RootNode("Droid", "name").
+		DS()
+	flatteningDS := dsb().
+		WithBehavior(DataSourcePlanningBehavior{
+			FlattenInlineFragments: true,
+		}).
+		Schema(definition).
+		RootNode("Query", "search").
+		RootNode("Human", "name").
+		RootNode("Droid", "name").
+		DS()
+
+	run := func(t *testing.T, ds DataSource, expectRewrite bool) {
+		t.Helper()
+
+		op := unsafeparser.ParseGraphqlDocumentString(operation)
+		def := unsafeparser.ParseGraphqlDocumentStringWithBaseSchema(definition)
+		upstreamDef := unsafeparser.ParseGraphqlDocumentStringWithBaseSchema(definition)
+
+		fieldRef := ast.InvalidRef
+		for ref := range op.Fields {
+			if op.FieldNameString(ref) == "search" {
+				fieldRef = ref
+				break
+			}
+		}
+		require.NotEqual(t, ast.InvalidRef, fieldRef)
+
+		node, exists := def.Index.FirstNodeByNameStr("Query")
+		require.True(t, exists)
+
+		rewriter := newFieldSelectionRewriter(&op, &def, &upstreamDef, ds)
+		result, err := rewriter.RewriteFieldSelection(fieldRef, node)
+		require.NoError(t, err)
+
+		assert.Equal(t, expectRewrite, result.rewritten)
+	}
+
+	run(t, baseDS, false)
+	run(t, flatteningDS, true)
+}
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/datasource_configuration.go b/app/v2/pkg/engine/plan/datasource_configuration.go
index 07ec63e..4cc0507 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/datasource_configuration.go
+++ b/app/v2/pkg/engine/plan/datasource_configuration.go
@@ -25,6 +25,7 @@ type PlannerFactory[DataSourceSpecificConfiguration any] interface {
 	// This method serves as a flag that factory should have a context
 	Context() context.Context
 	UpstreamSchema(dataSourceConfig DataSourceConfiguration[DataSourceSpecificConfiguration]) (*ast.Document, bool)
+	DataSourcePlanningBehavior() DataSourcePlanningBehavior
 }
 
 type DataSourceMetadata struct {
@@ -212,7 +213,8 @@ type dataSourceConfiguration[T any] struct {
 	factory             PlannerFactory[T] // factory is the factory for the creation of the concrete DataSourcePlanner
 	custom              T                 // custom is the datasource specific configuration
 
-	hash DSHash // hash is a unique hash for the dataSourceConfiguration used to match datasources
+	hash             DSHash // hash is a unique hash for the dataSourceConfiguration used to match datasources
+	planningBehavior DataSourcePlanningBehavior
 }
 
 func NewDataSourceConfiguration[T any](id string, factory PlannerFactory[T], metadata *DataSourceMetadata, customConfig T) (DataSourceConfiguration[T], error) {
@@ -237,6 +239,7 @@ func NewDataSourceConfigurationWithName[T any](id string, name string, factory P
 		factory:            factory,
 		custom:             customConfig,
 		hash:               DSHash(xxhash.Sum64([]byte(id))),
+		planningBehavior:   factory.DataSourcePlanningBehavior(),
 	}, nil
 }
 
@@ -257,6 +260,7 @@ type DataSource interface {
 	Id() string
 	Name() string
 	Hash() DSHash
+	DataSourcePlanningBehavior() DataSourcePlanningBehavior
 	FederationConfiguration() FederationMetaData
 	CreatePlannerConfiguration(logger abstractlogger.Logger, fetchConfig *objectFetchConfiguration, pathConfig *plannerPathsConfiguration, configuration *Configuration) PlannerConfiguration
 }
@@ -303,6 +307,10 @@ func (d *dataSourceConfiguration[T]) Hash() DSHash {
 	return d.hash
 }
 
+func (d *dataSourceConfiguration[T]) DataSourcePlanningBehavior() DataSourcePlanningBehavior {
+	return d.planningBehavior
+}
+
 type DataSourcePlannerConfiguration struct {
 	RequiredFields FederationFieldConfigurations
 	ParentPath     string
@@ -383,8 +391,12 @@ type DataSourcePlanningBehavior struct {
 	// When true expected response will be { "rootField": ..., "alias": ... }
 	// When false expected response will be { "rootField": ..., "original": ... }
 	OverrideFieldPathFromAlias bool
-	// IncludeTypeNameFields should be set to true if the planner allows to plan __typename fields
-	IncludeTypeNameFields bool
+	// PlanTypeNameFields should be set to true if the planner wants to plan __typename fields.
+	PlanTypeNameFields bool
+	// FlattenInlineFragments forces the planner to rewrite selection sets that contain inline fragments even when the
+	// standard heuristics do not require a rewrite. This is useful for datasources (like gRPC-backed GraphQL) that
+	// cannot represent inline fragments upstream.
+	FlattenInlineFragments bool
 }
 
 type DataSourceFetchPlanner interface {
@@ -392,40 +404,14 @@ type DataSourceFetchPlanner interface {
 	ConfigureSubscription() SubscriptionConfiguration
 }
 
-type DataSourceBehavior interface {
-	DataSourcePlanningBehavior() DataSourcePlanningBehavior
-	// DownstreamResponseFieldAlias allows the DataSourcePlanner to overwrite the response path with an alias
-	// It's required to set OverrideFieldPathFromAlias to true
-	// This function is useful in the following scenario
-	// 1. The downstream Query doesn't contain an alias
-	// 2. The path configuration rewrites the field to an existing field
-	// 3. The DataSourcePlanner is using an alias to the upstream
-	// Example:
-	//
-	// type Query {
-	//		country: Country
-	//		countryAlias: Country
-	// }
-	//
-	// Both, country and countryAlias have a path in the FieldConfiguration of "country"
-	// In theory, they would be treated as the same field
-	// However, by using DownstreamResponseFieldAlias, it's possible for the DataSourcePlanner to use an alias for countryAlias.
-	// In this case, the response would contain both, country and countryAlias fields in the response.
-	// At the same time, the downstream Query would only expect the response on the path "country",
-	// as both country and countryAlias have a mapping to the path "country".
-	// The DataSourcePlanner could keep track that it rewrites the upstream query and use DownstreamResponseFieldAlias
-	// to indicate to the Planner to expect the response for countryAlias on the path "countryAlias" instead of "country".
-	DownstreamResponseFieldAlias(downstreamFieldRef int) (alias string, exists bool)
-}
-
 type Identifyable interface {
 	astvisitor.VisitorIdentifier
 }
 
 type DataSourcePlanner[T any] interface {
 	DataSourceFetchPlanner
-	DataSourceBehavior
 	Identifyable
+	DownstreamResponseFieldAlias(downstreamFieldRef int) (alias string, exists bool)
 	Register(visitor *Visitor, configuration DataSourceConfiguration[T], dataSourcePlannerConfiguration DataSourcePlannerConfiguration) error
 }
 
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/datasource_filter_visitor_test.go b/app/v2/pkg/engine/plan/datasource_filter_visitor_test.go
index acf02a9..25c3432 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/datasource_filter_visitor_test.go
+++ b/app/v2/pkg/engine/plan/datasource_filter_visitor_test.go
@@ -92,7 +92,9 @@ func (b *dsBuilder) DS() DataSource {
 }
 
 func (b *dsBuilder) WithBehavior(behavior DataSourcePlanningBehavior) *dsBuilder {
-	b.behavior = &behavior
+	behaviorCopy := behavior
+	b.behavior = &behaviorCopy
+	b.ds.planningBehavior = behaviorCopy
 	return b
 }
 
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/node_selection_visitor.go b/app/v2/pkg/engine/plan/node_selection_visitor.go
index 95c4f01..bdd73d3 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/node_selection_visitor.go
+++ b/app/v2/pkg/engine/plan/node_selection_visitor.go
@@ -649,9 +649,7 @@ func (c *nodeSelectionVisitor) rewriteSelectionSetHavingAbstractFragments(fieldR
 		return
 	}
 
-	rewriter := newFieldSelectionRewriter(c.operation, c.definition)
-	rewriter.SetUpstreamDefinition(upstreamSchema)
-	rewriter.SetDatasourceConfiguration(ds)
+	rewriter := newFieldSelectionRewriter(c.operation, c.definition, upstreamSchema, ds)
 
 	result, err := rewriter.RewriteFieldSelection(fieldRef, c.walker.EnclosingTypeDefinition)
 	if err != nil {
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/path_builder_visitor.go b/app/v2/pkg/engine/plan/path_builder_visitor.go
index bd4d6b2..ea67a86 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/path_builder_visitor.go
+++ b/app/v2/pkg/engine/plan/path_builder_visitor.go
@@ -719,7 +719,7 @@ func (c *pathBuilderVisitor) isAllFieldDependenciesOnSameDataSource(fieldRef int
 
 func (c *pathBuilderVisitor) planWithExistingPlanners(fieldRef int, typeName, fieldName, currentPath, parentPath, precedingParentPath string, suggestion *NodeSuggestion) (plannerIdx int, planned bool) {
 	for plannerIdx, plannerConfig := range c.planners {
-		planningBehaviour := plannerConfig.DataSourcePlanningBehavior()
+		planningBehaviour := plannerConfig.DataSourceConfiguration().DataSourcePlanningBehavior()
 		dsConfiguration := plannerConfig.DataSourceConfiguration()
 		currentPlannerDSHash := dsConfiguration.Hash()
 
@@ -1247,7 +1247,7 @@ func (c *pathBuilderVisitor) addPlannerPathForTypename(
 	if fieldName != typeNameField {
 		return false
 	}
-	if !planningBehaviour.IncludeTypeNameFields {
+	if !planningBehaviour.PlanTypeNameFields {
 		return false
 	}
 
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/planner_configuration.go b/app/v2/pkg/engine/plan/planner_configuration.go
index 69e23e8..c796cda 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/planner_configuration.go
+++ b/app/v2/pkg/engine/plan/planner_configuration.go
@@ -23,11 +23,11 @@ type plannerConfigurationOptions struct {
 }
 
 type PlannerConfiguration interface {
-	DataSourceBehavior
 	PlannerPathConfiguration
 
 	ObjectFetchConfiguration() *objectFetchConfiguration
 	DataSourceConfiguration() DataSource
+	DownstreamResponseFieldAlias(downstreamFieldRef int) (alias string, exists bool)
 
 	RequiredFields() *FederationFieldConfigurations
 
@@ -62,10 +62,6 @@ func (p *plannerConfiguration[T]) ObjectFetchConfiguration() *objectFetchConfigu
 	return p.objectFetchConfiguration
 }
 
-func (p *plannerConfiguration[T]) DataSourcePlanningBehavior() DataSourcePlanningBehavior {
-	return p.planner.DataSourcePlanningBehavior()
-}
-
 func (p *plannerConfiguration[T]) DownstreamResponseFieldAlias(downstreamFieldRef int) (alias string, exists bool) {
 	return p.planner.DownstreamResponseFieldAlias(downstreamFieldRef)
 }
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/planner_test.go b/app/v2/pkg/engine/plan/planner_test.go
index 0a498ad..4cf576c 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/planner_test.go
+++ b/app/v2/pkg/engine/plan/planner_test.go
@@ -1006,7 +1006,6 @@ func (f *FakeFactory[T]) Planner(logger abstractlogger.Logger) DataSourcePlanner
 	return &FakePlanner[T]{
 		source:         source,
 		upstreamSchema: f.upstreamSchema,
-		behavior:       f.behavior,
 	}
 }
 
@@ -1014,11 +1013,21 @@ func (f *FakeFactory[T]) Context() context.Context {
 	return context.TODO()
 }
 
+func (f *FakeFactory[T]) DataSourcePlanningBehavior() DataSourcePlanningBehavior {
+	if f.behavior == nil {
+		return DataSourcePlanningBehavior{
+			MergeAliasedRootNodes:      false,
+			OverrideFieldPathFromAlias: false,
+		}
+	}
+
+	return *f.behavior
+}
+
 type FakePlanner[T any] struct {
 	id             int
 	source         *StatefulSource
 	upstreamSchema *ast.Document
-	behavior       *DataSourcePlanningBehavior
 }
 
 func (f *FakePlanner[T]) ID() int {
@@ -1050,17 +1059,6 @@ func (f *FakePlanner[T]) ConfigureSubscription() SubscriptionConfiguration {
 	return SubscriptionConfiguration{}
 }
 
-func (f *FakePlanner[T]) DataSourcePlanningBehavior() DataSourcePlanningBehavior {
-	if f.behavior == nil {
-		return DataSourcePlanningBehavior{
-			MergeAliasedRootNodes:      false,
-			OverrideFieldPathFromAlias: false,
-		}
-	}
-
-	return *f.behavior
-}
-
 func (f *FakePlanner[T]) DownstreamResponseFieldAlias(downstreamFieldRef int) (alias string, exists bool) {
 	return
 }
diff --git a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/visitor.go b/app/v2/pkg/engine/plan/visitor.go
index 848c5cc..1c9dcb8 100644
--- a/tmp/agent-patch-flux-pr-1268.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/visitor.go
+++ b/app/v2/pkg/engine/plan/visitor.go
@@ -1021,7 +1021,7 @@ func (v *Visitor) resolveFieldPath(ref int) []string {
 
 	aliasOverride := false
 	if plannerConfig != nil && plannerConfig.Planner() != nil {
-		aliasOverride = plannerConfig.DataSourcePlanningBehavior().OverrideFieldPathFromAlias
+		aliasOverride = plannerConfig.DataSourceConfiguration().DataSourcePlanningBehavior().OverrideFieldPathFromAlias
 	}
 
 	for i := range v.Config.Fields {