agent_patch
runs/2026-02-28__13-38-10__gpt-5-1-codex-mini/flux-pr-1293/flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/agent-logs/agent.patch
34208 bytes
diff --git a/tmp/agent-patch-flux-pr-1293.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 3acdd07..0c4d72c 100644
--- a/tmp/agent-patch-flux-pr-1293.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
@@ -1823,6 +1823,7 @@ func (f *Factory[T]) PlanningBehavior() plan.DataSourcePlanningBehavior {
OverrideFieldPathFromAlias: true,
AllowPlanningTypeName: true,
AlwaysFlattenFragments: f.grpcClient != nil || f.grpcClientProvider != nil,
+ BuildFetchReasons: true,
}
return b
}
diff --git a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource_federation_test.go b/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource_federation_test.go
index 2e881ca..3a765cb 100644
--- a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource_federation_test.go
+++ b/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource_federation_test.go
@@ -3092,35 +3092,63 @@ func TestGraphQLDataSourceFederation(t *testing.T) {
FetchID: 0,
},
DataSourceIdentifier: []byte("graphql_datasource.Source"),
- FetchConfiguration: resolve.FetchConfiguration{
- Input: `{"method":"POST","url":"http://user.service","body":{"query":"{user {account {address {line1 line2 __typename id}}}}"}}`,
- DataSource: &Source{},
- PostProcessing: DefaultPostProcessingConfiguration,
- FieldFetchReasons: []resolve.FetchReason{
- {
- TypeName: "Address",
- FieldName: "id",
- BySubgraphs: []string{
- "account.service",
- "address-enricher.service",
- "address.service",
- },
- IsKey: true,
- },
- {
- TypeName: "Address",
- FieldName: "line1",
- BySubgraphs: []string{"account.service"},
- IsRequires: true,
- },
- {
- TypeName: "Address",
- FieldName: "line2",
- BySubgraphs: []string{"account.service"},
- IsRequires: true,
- },
+ FetchConfiguration: resolve.FetchConfiguration{
+ Input: `{"method":"POST","url":"http://user.service","body":{"query":"{user {account {address {line1 line2 __typename id}}}}"}}`,
+ DataSource: &Source{},
+ PostProcessing: DefaultPostProcessingConfiguration,
+ },
+ Info: &resolve.FetchInfo{
+ DataSourceID: "user.service",
+ DataSourceName: "user.service",
+ FetchReasons: []resolve.FetchReason{
+ {
+ TypeName: "Address",
+ FieldName: "id",
+ BySubgraphs: []string{
+ "account.service",
+ "address-enricher.service",
+ "address.service",
+ },
+ IsKey: true,
+ },
+ {
+ TypeName: "Address",
+ FieldName: "line1",
+ BySubgraphs: []string{"account.service"},
+ IsRequires: true,
+ },
+ {
+ TypeName: "Address",
+ FieldName: "line2",
+ BySubgraphs: []string{"account.service"},
+ IsRequires: true,
+ },
+ },
+ PropagatedFetchReasons: []resolve.FetchReason{
+ {
+ TypeName: "Address",
+ FieldName: "id",
+ BySubgraphs: []string{
+ "account.service",
+ "address-enricher.service",
+ "address.service",
+ },
+ IsKey: true,
+ },
+ {
+ TypeName: "Address",
+ FieldName: "line1",
+ BySubgraphs: []string{"account.service"},
+ IsRequires: true,
+ },
+ {
+ TypeName: "Address",
+ FieldName: "line2",
+ BySubgraphs: []string{"account.service"},
+ IsRequires: true,
},
},
+ },
}),
resolve.SingleWithPath(&resolve.SingleFetch{
FetchDependencies: resolve.FetchDependencies{
@@ -3128,45 +3156,86 @@ func TestGraphQLDataSourceFederation(t *testing.T) {
DependsOnFetchIDs: []int{0},
},
DataSourceIdentifier: []byte("graphql_datasource.Source"),
- FetchConfiguration: resolve.FetchConfiguration{
- Input: `{"method":"POST","url":"http://address-enricher.service","body":{"query":"query($representations: [_Any!]!){_entities(representations: $representations){... on Address {__typename country city}}}","variables":{"representations":[$$0$$]}}}`,
- DataSource: &Source{},
- CoordinateDependencies: []resolve.FetchDependency{
- {
- Coordinate: resolve.GraphCoordinate{
- TypeName: "Address",
- FieldName: "country",
- },
- DependsOn: []resolve.FetchDependencyOrigin{
- {
- FetchID: 0,
- Subgraph: "user.service",
- Coordinate: resolve.GraphCoordinate{
- TypeName: "Address",
- FieldName: "id",
+ FetchConfiguration: resolve.FetchConfiguration{
+ Input: `{"method":"POST","url":"http://address-enricher.service","body":{"query":"query($representations: [_Any!]!){_entities(representations: $representations){... on Address {__typename country city}}}","variables":{"representations":[$$0$$]}}}`,
+ DataSource: &Source{},
+ PostProcessing: SingleEntityPostProcessingConfiguration,
+ RequiresEntityFetch: true,
+ Variables: []resolve.Variable{
+ &resolve.ResolvableObjectVariable{
+ Renderer: resolve.NewGraphQLVariableResolveRenderer(&resolve.Object{
+ Nullable: true,
+ Fields: []*resolve.Field{
+ {
+ Name: []byte("__typename"),
+ Value: &resolve.String{
+ Path: []string{"__typename"},
+ },
+ OnTypeNames: [][]byte{[]byte("Address")},
+ },
+ {
+ Name: []byte("id"),
+ Value: &resolve.Scalar{
+ Path: []string{"id"},
+ },
+ OnTypeNames: [][]byte{[]byte("Address")},
+ },
},
- IsKey: true,
- },
+ }),
},
},
- {
- Coordinate: resolve.GraphCoordinate{
- TypeName: "Address",
- FieldName: "city",
+ SetTemplateOutputToNullOnVariableNull: true,
+ },
+ Info: &resolve.FetchInfo{
+ DataSourceID: "address-enricher.service",
+ DataSourceName: "address-enricher.service",
+ CoordinateDependencies: []resolve.FetchDependency{
+ {
+ Coordinate: resolve.GraphCoordinate{
+ TypeName: "Address",
+ FieldName: "country",
+ },
+ DependsOn: []resolve.FetchDependencyOrigin{
+ {
+ FetchID: 0,
+ Subgraph: "user.service",
+ Coordinate: resolve.GraphCoordinate{
+ TypeName: "Address",
+ FieldName: "id",
+ },
+ IsKey: true,
+ },
+ },
},
- DependsOn: []resolve.FetchDependencyOrigin{
- {
- FetchID: 0,
- Subgraph: "user.service",
- Coordinate: resolve.GraphCoordinate{
- TypeName: "Address",
- FieldName: "id",
+ {
+ Coordinate: resolve.GraphCoordinate{
+ TypeName: "Address",
+ FieldName: "city",
+ },
+ DependsOn: []resolve.FetchDependencyOrigin{
+ {
+ FetchID: 0,
+ Subgraph: "user.service",
+ Coordinate: resolve.GraphCoordinate{
+ TypeName: "Address",
+ FieldName: "id",
+ },
+ IsKey: true,
},
- IsKey: true,
},
},
},
},
+ }, "user.account.address", resolve.ObjectPath("user"), resolve.ObjectPath("account"), resolve.ObjectPath("address")),
+ resolve.SingleWithPath(&resolve.SingleFetch{
+ FetchDependencies: resolve.FetchDependencies{
+ FetchID: 2,
+ DependsOnFetchIDs: []int{0, 1},
+ },
+ DataSourceIdentifier: []byte("graphql_datasource.Source"),
+ FetchConfiguration: resolve.FetchConfiguration{
+ Input: `{"method":"POST","url":"http://address.service","body":{"query":"query($representations: [_Any!]!, $a: String!){_entities(representations: $representations){... on Address {__typename line3(test: $a) zip}}}","variables":{"a":"BOOM","representations":[$$0$$]}}}`,
+ DataSource: &Source{},
PostProcessing: SingleEntityPostProcessingConfiguration,
RequiresEntityFetch: true,
Variables: []resolve.Variable{
@@ -3188,24 +3257,29 @@ func TestGraphQLDataSourceFederation(t *testing.T) {
},
OnTypeNames: [][]byte{[]byte("Address")},
},
+ {
+ Name: []byte("country"),
+ Value: &resolve.String{
+ Path: []string{"country"},
+ },
+ OnTypeNames: [][]byte{[]byte("Address")},
+ },
+ {
+ Name: []byte("city"),
+ Value: &resolve.String{
+ Path: []string{"city"},
+ },
+ OnTypeNames: [][]byte{[]byte("Address")},
+ },
},
}),
},
},
SetTemplateOutputToNullOnVariableNull: true,
},
- }, "user.account.address", resolve.ObjectPath("user"), resolve.ObjectPath("account"), resolve.ObjectPath("address")),
- resolve.SingleWithPath(&resolve.SingleFetch{
- FetchDependencies: resolve.FetchDependencies{
- FetchID: 2,
- DependsOnFetchIDs: []int{0, 1},
- },
- DataSourceIdentifier: []byte("graphql_datasource.Source"),
- FetchConfiguration: resolve.FetchConfiguration{
- Input: `{"method":"POST","url":"http://address.service","body":{"query":"query($representations: [_Any!]!, $a: String!){_entities(representations: $representations){... on Address {__typename line3(test: $a) zip}}}","variables":{"a":"BOOM","representations":[$$0$$]}}}`,
- DataSource: &Source{},
- PostProcessing: SingleEntityPostProcessingConfiguration,
- RequiresEntityFetch: true,
+ Info: &resolve.FetchInfo{
+ DataSourceID: "address.service",
+ DataSourceName: "address.service",
CoordinateDependencies: []resolve.FetchDependency{
{
Coordinate: resolve.GraphCoordinate{
@@ -3260,7 +3334,7 @@ func TestGraphQLDataSourceFederation(t *testing.T) {
},
},
},
- FieldFetchReasons: []resolve.FetchReason{
+ FetchReasons: []resolve.FetchReason{
{
TypeName: "Address",
FieldName: "line3",
@@ -3274,44 +3348,20 @@ func TestGraphQLDataSourceFederation(t *testing.T) {
IsRequires: true,
},
},
- Variables: []resolve.Variable{
- &resolve.ResolvableObjectVariable{
- Renderer: resolve.NewGraphQLVariableResolveRenderer(&resolve.Object{
- Nullable: true,
- Fields: []*resolve.Field{
- {
- Name: []byte("__typename"),
- Value: &resolve.String{
- Path: []string{"__typename"},
- },
- OnTypeNames: [][]byte{[]byte("Address")},
- },
- {
- Name: []byte("id"),
- Value: &resolve.Scalar{
- Path: []string{"id"},
- },
- OnTypeNames: [][]byte{[]byte("Address")},
- },
- {
- Name: []byte("country"),
- Value: &resolve.String{
- Path: []string{"country"},
- },
- OnTypeNames: [][]byte{[]byte("Address")},
- },
- {
- Name: []byte("city"),
- Value: &resolve.String{
- Path: []string{"city"},
- },
- OnTypeNames: [][]byte{[]byte("Address")},
- },
- },
- }),
+ PropagatedFetchReasons: []resolve.FetchReason{
+ {
+ TypeName: "Address",
+ FieldName: "line3",
+ BySubgraphs: []string{"account.service"},
+ IsRequires: true,
+ },
+ {
+ TypeName: "Address",
+ FieldName: "zip",
+ BySubgraphs: []string{"account.service"},
+ IsRequires: true,
},
},
- SetTemplateOutputToNullOnVariableNull: true,
},
}, "user.account.address", resolve.ObjectPath("user"), resolve.ObjectPath("account"), resolve.ObjectPath("address")),
resolve.SingleWithPath(&resolve.SingleFetch{
@@ -3324,7 +3374,6 @@ func TestGraphQLDataSourceFederation(t *testing.T) {
Input: `{"method":"POST","url":"http://account.service","body":{"query":"query($representations: [_Any!]!){_entities(representations: $representations){... on Address {__typename fullAddress}}}","variables":{"representations":[$$0$$]}}}`,
DataSource: &Source{},
PostProcessing: SingleEntityPostProcessingConfiguration,
- CoordinateDependencies: []resolve.FetchDependency{
{
Coordinate: resolve.GraphCoordinate{
TypeName: "Address",
diff --git a/tmp/agent-patch-flux-pr-1293.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 2601a43..af5e545 100644
--- a/tmp/agent-patch-flux-pr-1293.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
@@ -444,6 +444,9 @@ type DataSourcePlanningBehavior struct {
// If true then planner will rewrite the operation
// to flatten inline fragments to only the concrete types.
AlwaysFlattenFragments bool
+
+ // BuildFetchReasons controls whether the planner should compute fetch reason metadata for this datasource.
+ BuildFetchReasons bool
}
type DataSourceFetchPlanner interface {
diff --git a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/federation_metadata.go b/app/v2/pkg/engine/plan/federation_metadata.go
index b4479a4..ed260f9 100644
--- a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/federation_metadata.go
+++ b/app/v2/pkg/engine/plan/federation_metadata.go
@@ -82,15 +82,10 @@ type FederationFieldConfiguration struct {
}
type KeyCondition struct {
- Coordinates []KeyConditionCoordinate `json:"coordinates"`
+ Coordinates []FieldCoordinate `json:"coordinates"`
FieldPath []string `json:"field_path"`
}
-type KeyConditionCoordinate struct {
- TypeName string `json:"type_name"`
- FieldName string `json:"field_name"`
-}
-
func (f *FederationFieldConfiguration) parseSelectionSet() error {
if f.parsedSelectionSet != nil {
return nil
diff --git a/tmp/agent-patch-flux-pr-1293.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 6a1259a..2273710 100644
--- a/tmp/agent-patch-flux-pr-1293.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
@@ -45,7 +45,7 @@ type nodeSelectionVisitor struct {
hasNewFields bool // hasNewFields is used to determine if we need to run the planner again. It will be true in case required fields were added
hasUnresolvedFields bool // hasUnresolvedFields is used to determine if we need to run the planner again. We should set it to true in case we have unresolved fields
- fieldPathCoordinates []KeyConditionCoordinate // currentFieldPathCoordinates is a stack of field path coordinates // TODO: remove me
+ fieldPathCoordinates []FieldCoordinate // currentFieldPathCoordinates is a stack of field path coordinates // TODO: remove me
rewrittenFieldRefs []int
}
@@ -128,7 +128,7 @@ func (c *nodeSelectionVisitor) EnterDocument(operation, definition *ast.Document
}
if c.fieldPathCoordinates == nil {
- c.fieldPathCoordinates = make([]KeyConditionCoordinate, 0, 8)
+ c.fieldPathCoordinates = make([]FieldCoordinate, 0, 8)
} else {
c.fieldPathCoordinates = c.fieldPathCoordinates[:0]
}
@@ -219,7 +219,7 @@ func (c *nodeSelectionVisitor) EnterField(fieldRef int) {
c.rewriteSelectionSetHavingAbstractFragments(fieldRef, ds)
}
- c.fieldPathCoordinates = append(c.fieldPathCoordinates, KeyConditionCoordinate{
+ c.fieldPathCoordinates = append(c.fieldPathCoordinates, FieldCoordinate{
FieldName: fieldName,
TypeName: typeName,
})
diff --git a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/type_field.go b/app/v2/pkg/engine/plan/type_field.go
index e3dfa26..521a62a 100644
--- a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/plan/type_field.go
+++ b/app/v2/pkg/engine/plan/type_field.go
@@ -8,3 +8,8 @@ type TypeField struct {
}
type TypeFields []TypeField
+
+type FieldCoordinate struct {
+ TypeName string `json:"type_name"`
+ FieldName string `json:"field_name"`
+}
diff --git a/tmp/agent-patch-flux-pr-1293.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 382be28..5c0b878 100644
--- a/tmp/agent-patch-flux-pr-1293.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
@@ -1326,18 +1326,20 @@ func (v *Visitor) configureFetch(internal *objectFetchConfiguration, external re
}
if !v.Config.DisableIncludeInfo {
- singleFetch.Info = &resolve.FetchInfo{
+ info := &resolve.FetchInfo{
DataSourceID: internal.sourceID,
DataSourceName: internal.sourceName,
RootFields: internal.rootFields,
OperationType: internal.operationType,
QueryPlan: external.QueryPlan,
}
- }
-
- if !v.Config.DisableIncludeFieldDependencies {
- singleFetch.CoordinateDependencies = v.resolveFetchDependencies(internal.fetchID)
- singleFetch.FieldFetchReasons = v.buildFetchReasons(internal.fetchID)
+ if !v.Config.DisableIncludeFieldDependencies {
+ info.CoordinateDependencies = v.resolveFetchDependencies(internal.fetchID)
+ if dsConfig := v.planners[internal.fetchID].DataSourceConfiguration(); dsConfig != nil && dsConfig.PlanningBehavior().BuildFetchReasons {
+ info.FetchReasons, info.PropagatedFetchReasons = v.buildFetchReasons(internal.fetchID, dsConfig)
+ }
+ }
+ singleFetch.Info = info
}
return singleFetch
@@ -1398,12 +1400,11 @@ func (v *Visitor) resolveFetchDependencies(fetchID int) []resolve.FetchDependenc
return dependencies
}
-func (v *Visitor) buildFetchReasons(fetchID int) []resolve.FetchReason {
+func (v *Visitor) buildFetchReasons(fetchID int, dsConfig DataSource) ([]resolve.FetchReason, []resolve.FetchReason) {
fields, ok := v.plannerFields[fetchID]
if !ok {
- return nil
+ return nil, nil
}
- dsConfig := v.planners[fetchID].DataSourceConfiguration()
type typedField struct {
typeName string
@@ -1418,9 +1419,6 @@ func (v *Visitor) buildFetchReasons(fetchID int) []resolve.FetchReason {
continue
}
typeName := v.fieldEnclosingTypeNames[fieldRef]
- if !dsConfig.RequiresFetchReason(typeName, fieldName) {
- continue
- }
byUser := !v.skipField(fieldRef)
dependants, ok := v.fieldRefDependants[fieldRef]
@@ -1471,14 +1469,14 @@ func (v *Visitor) buildFetchReasons(fetchID int) []resolve.FetchReason {
reasons[i].IsRequires = reasons[i].IsRequires || isRequires
}
} else {
- reasons = append(reasons, resolve.FetchReason{
- TypeName: typeName,
- FieldName: fieldName,
- BySubgraphs: subgraphs,
- ByUser: byUser,
- IsKey: isKey,
- IsRequires: isRequires,
- })
+ reasons = append(reasons, resolve.FetchReason{
+ TypeName: typeName,
+ FieldName: fieldName,
+ BySubgraphs: subgraphs,
+ ByUser: byUser,
+ IsKey: isKey,
+ IsRequires: isRequires,
+ })
i = len(reasons) - 1
index[key] = i
}
@@ -1495,5 +1493,15 @@ func (v *Visitor) buildFetchReasons(fetchID int) []resolve.FetchReason {
cmp.Compare(a.FieldName, b.FieldName),
)
})
- return reasons
+ if dsConfig == nil {
+ return reasons, nil
+ }
+
+ var propagated []resolve.FetchReason
+ for _, reason := range reasons {
+ if dsConfig.RequiresFetchReason(reason.TypeName, reason.FieldName) {
+ propagated = append(propagated, reason)
+ }
+ }
+ return reasons, propagated
}
diff --git a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/postprocess/create_concrete_single_fetch_types.go b/app/v2/pkg/engine/postprocess/create_concrete_single_fetch_types.go
index 3d6a00b..89f3b08 100644
--- a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/postprocess/create_concrete_single_fetch_types.go
+++ b/app/v2/pkg/engine/postprocess/create_concrete_single_fetch_types.go
@@ -76,8 +76,6 @@ func (d *createConcreteSingleFetchTypes) createEntityBatchFetch(fetch *resolve.S
return &resolve.BatchEntityFetch{
FetchDependencies: fetch.FetchDependencies,
- CoordinateDependencies: fetch.CoordinateDependencies,
- FieldFetchReasons: fetch.FieldFetchReasons,
Info: fetch.Info,
Input: resolve.BatchInput{
Header: resolve.InputTemplate{
@@ -123,8 +121,6 @@ func (d *createConcreteSingleFetchTypes) createEntityFetch(fetch *resolve.Single
return &resolve.EntityFetch{
FetchDependencies: fetch.FetchDependencies,
- CoordinateDependencies: fetch.CoordinateDependencies,
- FieldFetchReasons: fetch.FieldFetchReasons,
Info: fetch.Info,
Input: resolve.EntityInput{
Header: resolve.InputTemplate{
diff --git a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/postprocess/deduplicate_single_fetches_test.go b/app/v2/pkg/engine/postprocess/deduplicate_single_fetches_test.go
index 9a0121b..3256351 100644
--- a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/postprocess/deduplicate_single_fetches_test.go
+++ b/app/v2/pkg/engine/postprocess/deduplicate_single_fetches_test.go
@@ -97,8 +97,8 @@ func TestDeduplicateSingleFetches_ProcessFetchTree(t *testing.T) {
FetchID: 1,
DependsOnFetchIDs: []int{0},
},
- FetchConfiguration: resolve.FetchConfiguration{
- Input: "a",
+ FetchConfiguration: resolve.FetchConfiguration{Input: "a"},
+ Info: &resolve.FetchInfo{
CoordinateDependencies: []resolve.FetchDependency{
{
DependsOn: []resolve.FetchDependencyOrigin{
@@ -121,8 +121,8 @@ func TestDeduplicateSingleFetches_ProcessFetchTree(t *testing.T) {
FetchID: 2,
DependsOnFetchIDs: []int{0},
},
- FetchConfiguration: resolve.FetchConfiguration{
- Input: "a",
+ FetchConfiguration: resolve.FetchConfiguration{Input: "a"},
+ Info: &resolve.FetchInfo{
CoordinateDependencies: []resolve.FetchDependency{
{
DependsOn: []resolve.FetchDependencyOrigin{
@@ -145,8 +145,8 @@ func TestDeduplicateSingleFetches_ProcessFetchTree(t *testing.T) {
FetchID: 4,
DependsOnFetchIDs: []int{0, 2},
},
- FetchConfiguration: resolve.FetchConfiguration{
- Input: "b",
+ FetchConfiguration: resolve.FetchConfiguration{Input: "b"},
+ Info: &resolve.FetchInfo{
CoordinateDependencies: []resolve.FetchDependency{
{
DependsOn: []resolve.FetchDependencyOrigin{
@@ -172,8 +172,8 @@ func TestDeduplicateSingleFetches_ProcessFetchTree(t *testing.T) {
FetchID: 3,
DependsOnFetchIDs: []int{0, 1},
},
- FetchConfiguration: resolve.FetchConfiguration{
- Input: "b",
+ FetchConfiguration: resolve.FetchConfiguration{Input: "b"},
+ Info: &resolve.FetchInfo{
CoordinateDependencies: []resolve.FetchDependency{
{
DependsOn: []resolve.FetchDependencyOrigin{
@@ -217,8 +217,8 @@ func TestDeduplicateSingleFetches_ProcessFetchTree(t *testing.T) {
FetchID: 1,
DependsOnFetchIDs: []int{0},
},
- FetchConfiguration: resolve.FetchConfiguration{
- Input: "a",
+ FetchConfiguration: resolve.FetchConfiguration{Input: "a"},
+ Info: &resolve.FetchInfo{
CoordinateDependencies: []resolve.FetchDependency{
{
DependsOn: []resolve.FetchDependencyOrigin{
@@ -241,8 +241,8 @@ func TestDeduplicateSingleFetches_ProcessFetchTree(t *testing.T) {
FetchID: 4,
DependsOnFetchIDs: []int{0, 1},
},
- FetchConfiguration: resolve.FetchConfiguration{
- Input: "b",
+ FetchConfiguration: resolve.FetchConfiguration{Input: "b"},
+ Info: &resolve.FetchInfo{
CoordinateDependencies: []resolve.FetchDependency{
{
DependsOn: []resolve.FetchDependencyOrigin{
diff --git a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/resolve/fetch.go b/app/v2/pkg/engine/resolve/fetch.go
index 137670b..69430b4 100644
--- a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/resolve/fetch.go
+++ b/app/v2/pkg/engine/resolve/fetch.go
@@ -102,11 +102,17 @@ func (s *SingleFetch) Dependencies() *FetchDependencies {
}
func (s *SingleFetch) DependenciesCoordinates() []FetchDependency {
- return s.CoordinateDependencies
+ if s.Info == nil {
+ return nil
+ }
+ return s.Info.CoordinateDependencies
}
func (s *SingleFetch) FetchReasons() []FetchReason {
- return s.FieldFetchReasons
+ if s.Info == nil {
+ return nil
+ }
+ return s.Info.PropagatedFetchReasons
}
func (s *SingleFetch) DataSourceInfo() DataSourceInfo {
@@ -176,8 +182,6 @@ type BatchEntityFetch struct {
DataSourceIdentifier []byte
Trace *DataSourceLoadTrace
Info *FetchInfo
- CoordinateDependencies []FetchDependency
- FieldFetchReasons []FetchReason
}
func (b *BatchEntityFetch) Dependencies() *FetchDependencies {
@@ -185,11 +189,17 @@ func (b *BatchEntityFetch) Dependencies() *FetchDependencies {
}
func (b *BatchEntityFetch) DependenciesCoordinates() []FetchDependency {
- return b.CoordinateDependencies
+ if b.Info == nil {
+ return nil
+ }
+ return b.Info.CoordinateDependencies
}
func (b *BatchEntityFetch) FetchReasons() []FetchReason {
- return b.FieldFetchReasons
+ if b.Info == nil {
+ return nil
+ }
+ return b.Info.PropagatedFetchReasons
}
func (b *BatchEntityFetch) DataSourceInfo() DataSourceInfo {
@@ -229,8 +239,6 @@ type EntityFetch struct {
DataSourceIdentifier []byte
Trace *DataSourceLoadTrace
Info *FetchInfo
- CoordinateDependencies []FetchDependency
- FieldFetchReasons []FetchReason
}
func (e *EntityFetch) Dependencies() *FetchDependencies {
@@ -238,11 +246,17 @@ func (e *EntityFetch) Dependencies() *FetchDependencies {
}
func (e *EntityFetch) DependenciesCoordinates() []FetchDependency {
- return e.CoordinateDependencies
+ if e.Info == nil {
+ return nil
+ }
+ return e.Info.CoordinateDependencies
}
func (e *EntityFetch) FetchReasons() []FetchReason {
- return e.FieldFetchReasons
+ if e.Info == nil {
+ return nil
+ }
+ return e.Info.PropagatedFetchReasons
}
func (e *EntityFetch) DataSourceInfo() DataSourceInfo {
@@ -277,11 +291,11 @@ func (p *ParallelListItemFetch) Dependencies() *FetchDependencies {
}
func (p *ParallelListItemFetch) DependenciesCoordinates() []FetchDependency {
- return p.Fetch.CoordinateDependencies
+ return p.Fetch.DependenciesCoordinates()
}
func (p *ParallelListItemFetch) FetchReasons() []FetchReason {
- return p.Fetch.FieldFetchReasons
+ return p.Fetch.FetchReasons()
}
func (*ParallelListItemFetch) FetchKind() FetchKind {
@@ -341,17 +355,6 @@ type FetchConfiguration struct {
QueryPlan *QueryPlan
- // CoordinateDependencies contain a list of GraphCoordinates (typeName+fieldName)
- // and which fields from other fetches they depend on.
- // This information is useful to understand why a fetch depends on other fetches,
- // and how multiple dependencies lead to a chain of fetches
- CoordinateDependencies []FetchDependency
-
- // FieldFetchReasons contains provenance for fields that require fetch reason to be propagated
- // to their subgraph. It is optional propagation via request extensions;
- // it does not affect execution.
- FieldFetchReasons []FetchReason
-
// OperationName is non-empty when the operation name is propagated to the upstream subgraph fetch.
OperationName string
}
@@ -367,11 +370,6 @@ func (fc *FetchConfiguration) Equals(other *FetchConfiguration) bool {
}
// Note: we do not compare datasources, as they will always be a different instance.
- // Note: we do not compare CoordinateDependencies, as they contain more detailed
- // dependencies information that is already present in the FetchDependencies on the fetch itself.
- // Note: we do not compare FieldFetchReasons, as it is derived data for an extension
- // and does not affect fetch execution semantics.
-
if fc.RequiresParallelListItemFetch != other.RequiresParallelListItemFetch {
return false
}
@@ -435,6 +433,13 @@ type FetchInfo struct {
RootFields []GraphCoordinate
OperationType ast.OperationType
QueryPlan *QueryPlan
+ // CoordinateDependencies contain a list of GraphCoordinates (typeName+fieldName)
+ // and which fields from other fetches they depend on.
+ CoordinateDependencies []FetchDependency
+ // FetchReasons contains all computed reasons for the fields planned on this fetch.
+ FetchReasons []FetchReason
+ // PropagatedFetchReasons lists the subset of reasons that should be sent to the upstream subgraph.
+ PropagatedFetchReasons []FetchReason
}
type GraphCoordinate struct {
diff --git a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/resolve/fetchtree.go b/app/v2/pkg/engine/resolve/fetchtree.go
index ad1eb2f..5088938 100644
--- a/tmp/agent-patch-flux-pr-1293.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/resolve/fetchtree.go
+++ b/app/v2/pkg/engine/resolve/fetchtree.go
@@ -209,6 +209,10 @@ func (n *FetchTreeNode) queryPlan() *FetchTreeQueryPlanNode {
case FetchTreeNodeKindSingle:
switch f := n.Item.Fetch.(type) {
case *SingleFetch:
+ var dependencies []FetchDependency
+ if f.Info != nil {
+ dependencies = f.Info.CoordinateDependencies
+ }
queryPlan.Fetch = &FetchTreeQueryPlan{
Kind: "Single",
FetchID: f.FetchDependencies.FetchID,
@@ -216,7 +220,7 @@ func (n *FetchTreeNode) queryPlan() *FetchTreeQueryPlanNode {
SubgraphName: f.Info.DataSourceName,
SubgraphID: f.Info.DataSourceID,
Path: n.Item.ResponsePath,
- Dependencies: f.FetchConfiguration.CoordinateDependencies,
+ Dependencies: dependencies,
}
if f.Info.QueryPlan != nil {
@@ -224,6 +228,10 @@ func (n *FetchTreeNode) queryPlan() *FetchTreeQueryPlanNode {
queryPlan.Fetch.Representations = f.Info.QueryPlan.DependsOnFields
}
case *EntityFetch:
+ var dependencies []FetchDependency
+ if f.Info != nil {
+ dependencies = f.Info.CoordinateDependencies
+ }
queryPlan.Fetch = &FetchTreeQueryPlan{
Kind: "Entity",
FetchID: f.FetchDependencies.FetchID,
@@ -231,7 +239,7 @@ func (n *FetchTreeNode) queryPlan() *FetchTreeQueryPlanNode {
SubgraphName: f.Info.DataSourceName,
SubgraphID: f.Info.DataSourceID,
Path: n.Item.ResponsePath,
- Dependencies: f.CoordinateDependencies,
+ Dependencies: dependencies,
}
if f.Info.QueryPlan != nil {
@@ -239,6 +247,10 @@ func (n *FetchTreeNode) queryPlan() *FetchTreeQueryPlanNode {
queryPlan.Fetch.Representations = f.Info.QueryPlan.DependsOnFields
}
case *BatchEntityFetch:
+ var dependencies []FetchDependency
+ if f.Info != nil {
+ dependencies = f.Info.CoordinateDependencies
+ }
queryPlan.Fetch = &FetchTreeQueryPlan{
Kind: "BatchEntity",
FetchID: f.FetchDependencies.FetchID,
@@ -246,7 +258,7 @@ func (n *FetchTreeNode) queryPlan() *FetchTreeQueryPlanNode {
SubgraphName: f.Info.DataSourceName,
SubgraphID: f.Info.DataSourceID,
Path: n.Item.ResponsePath,
- Dependencies: f.CoordinateDependencies,
+ Dependencies: dependencies,
}
if f.Info.QueryPlan != nil {