agent_patch
runs/2026-02-28__13-38-10__gpt-5-1-codex-mini/flux-pr-1232/flux-pr-1232.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/agent-logs/agent.patch
8833 bytes
diff --git a/tmp/agent-patch-flux-pr-1232.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/postprocess/deduplicate_single_fetches.go b/app/v2/pkg/engine/postprocess/deduplicate_single_fetches.go
index 9fb8c1c..115cf62 100644
--- a/tmp/agent-patch-flux-pr-1232.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/engine/postprocess/deduplicate_single_fetches.go
+++ b/app/v2/pkg/engine/postprocess/deduplicate_single_fetches.go
@@ -14,9 +14,18 @@ func (d *deduplicateSingleFetches) ProcessFetchTree(root *resolve.FetchTreeNode)
if d.disable {
return
}
+ if root == nil || len(root.ChildNodes) <= 1 {
+ return
+ }
+ replacements := make(map[int]int)
for i := range root.ChildNodes {
for j := i + 1; j < len(root.ChildNodes); j++ {
if root.ChildNodes[i].Item.Equals(root.ChildNodes[j].Item) {
+ keptID := root.ChildNodes[i].Item.Fetch.Dependencies().FetchID
+ removedID := root.ChildNodes[j].Item.Fetch.Dependencies().FetchID
+ if keptID != removedID {
+ replacements[removedID] = keptID
+ }
root.ChildNodes[i].Item.FetchPath = d.mergeFetchPath(root.ChildNodes[i].Item.FetchPath, root.ChildNodes[j].Item.FetchPath)
root.ChildNodes = append(root.ChildNodes[:j], root.ChildNodes[j+1:]...)
@@ -24,6 +33,7 @@ func (d *deduplicateSingleFetches) ProcessFetchTree(root *resolve.FetchTreeNode)
}
}
}
+ d.updateDependencies(root.ChildNodes, replacements)
}
func (d *deduplicateSingleFetches) mergeFetchPath(left, right []resolve.FetchItemPathElement) []resolve.FetchItemPathElement {
@@ -34,6 +44,57 @@ func (d *deduplicateSingleFetches) mergeFetchPath(left, right []resolve.FetchIte
return left
}
+func (d *deduplicateSingleFetches) updateDependencies(nodes []*resolve.FetchTreeNode, replacements map[int]int) {
+ if len(replacements) == 0 {
+ return
+ }
+ for _, node := range nodes {
+ if node == nil || node.Item == nil {
+ continue
+ }
+ switch fetch := node.Item.Fetch.(type) {
+ case *resolve.SingleFetch:
+ d.updateSingleFetchDependencies(fetch, replacements)
+ }
+ }
+}
+
+func (d *deduplicateSingleFetches) updateSingleFetchDependencies(fetch *resolve.SingleFetch, replacements map[int]int) {
+ fetch.FetchDependencies.DependsOnFetchIDs = d.replaceFetchIDs(fetch.FetchDependencies.DependsOnFetchIDs, replacements)
+ for i := range fetch.FetchConfiguration.CoordinateDependencies {
+ for j := range fetch.FetchConfiguration.CoordinateDependencies[i].DependsOn {
+ fetch.FetchConfiguration.CoordinateDependencies[i].DependsOn[j].FetchID = d.resolveFetchID(fetch.FetchConfiguration.CoordinateDependencies[i].DependsOn[j].FetchID, replacements)
+ }
+ }
+}
+
+func (d *deduplicateSingleFetches) replaceFetchIDs(ids []int, replacements map[int]int) []int {
+ if len(ids) == 0 {
+ return ids
+ }
+ out := make([]int, 0, len(ids))
+ seen := make(map[int]struct{}, len(ids))
+ for _, id := range ids {
+ mapped := d.resolveFetchID(id, replacements)
+ if _, ok := seen[mapped]; ok {
+ continue
+ }
+ seen[mapped] = struct{}{}
+ out = append(out, mapped)
+ }
+ return out
+}
+
+func (d *deduplicateSingleFetches) resolveFetchID(id int, replacements map[int]int) int {
+ for {
+ mapped, ok := replacements[id]
+ if !ok || mapped == id {
+ return id
+ }
+ id = mapped
+ }
+}
+
func (d *deduplicateSingleFetches) mergeTypeNames(left []string, right []string) []string {
if len(left) == 0 || len(right) == 0 {
return nil // if either side is empty, fetch is unscoped
diff --git a/tmp/agent-patch-flux-pr-1232.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 88cf2be..77ff7f5 100644
--- a/tmp/agent-patch-flux-pr-1232.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
@@ -115,4 +115,108 @@ func TestDeduplicateSingleFetches_ProcessFetchTree(t *testing.T) {
assert.Equal(t, output, input)
})
+
+ t.Run("update dependencies after merging duplicates", func(t *testing.T) {
+ keep := &resolve.FetchTreeNode{
+ Kind: resolve.FetchTreeNodeKindSingle,
+ Item: &resolve.FetchItem{
+ FetchPath: []resolve.FetchItemPathElement{{Kind: resolve.FetchItemPathElementKindObject, Path: []string{"a"}}},
+ Fetch: &resolve.SingleFetch{
+ FetchDependencies: resolve.FetchDependencies{FetchID: 0},
+ FetchConfiguration: resolve.FetchConfiguration{Input: "a"},
+ },
+ },
+ }
+
+ duplicate := &resolve.FetchTreeNode{
+ Kind: resolve.FetchTreeNodeKindSingle,
+ Item: &resolve.FetchItem{
+ FetchPath: []resolve.FetchItemPathElement{{Kind: resolve.FetchItemPathElementKindObject, Path: []string{"a"}}},
+ Fetch: &resolve.SingleFetch{
+ FetchDependencies: resolve.FetchDependencies{FetchID: 1},
+ FetchConfiguration: resolve.FetchConfiguration{Input: "a"},
+ },
+ },
+ }
+
+ dependent := &resolve.FetchTreeNode{
+ Kind: resolve.FetchTreeNodeKindSingle,
+ Item: &resolve.FetchItem{
+ FetchPath: []resolve.FetchItemPathElement{{Kind: resolve.FetchItemPathElementKindObject, Path: []string{"b"}}},
+ Fetch: &resolve.SingleFetch{
+ FetchDependencies: resolve.FetchDependencies{FetchID: 2, DependsOnFetchIDs: []int{1}},
+ FetchConfiguration: resolve.FetchConfiguration{
+ Input: "b",
+ CoordinateDependencies: []resolve.FetchDependency{
+ {
+ Coordinate: resolve.GraphCoordinate{TypeName: "T", FieldName: "f"},
+ DependsOn: []resolve.FetchDependencyOrigin{{FetchID: 1}},
+ },
+ },
+ },
+ },
+ },
+ }
+
+ root := &resolve.FetchTreeNode{
+ ChildNodes: []*resolve.FetchTreeNode{keep, duplicate, dependent},
+ }
+
+ dedup := &deduplicateSingleFetches{}
+ dedup.ProcessFetchTree(root)
+
+ assert.Len(t, root.ChildNodes, 2)
+ remaining := root.ChildNodes[1].Item.Fetch.(*resolve.SingleFetch)
+ assert.Equal(t, []int{0}, remaining.FetchDependencies.DependsOnFetchIDs)
+ assert.Equal(t, 0, remaining.FetchConfiguration.CoordinateDependencies[0].DependsOn[0].FetchID)
+ })
+
+ t.Run("ignores coordinate dependencies when deduping", func(t *testing.T) {
+ a := &resolve.FetchTreeNode{
+ Kind: resolve.FetchTreeNodeKindSingle,
+ Item: &resolve.FetchItem{
+ FetchPath: []resolve.FetchItemPathElement{{Kind: resolve.FetchItemPathElementKindObject, Path: []string{"a"}}},
+ Fetch: &resolve.SingleFetch{
+ FetchDependencies: resolve.FetchDependencies{FetchID: 0},
+ FetchConfiguration: resolve.FetchConfiguration{
+ Input: "a",
+ CoordinateDependencies: []resolve.FetchDependency{
+ {
+ Coordinate: resolve.GraphCoordinate{TypeName: "T"},
+ DependsOn: []resolve.FetchDependencyOrigin{{FetchID: 1}},
+ },
+ },
+ },
+ },
+ },
+ }
+
+ b := &resolve.FetchTreeNode{
+ Kind: resolve.FetchTreeNodeKindSingle,
+ Item: &resolve.FetchItem{
+ FetchPath: []resolve.FetchItemPathElement{{Kind: resolve.FetchItemPathElementKindObject, Path: []string{"a"}}},
+ Fetch: &resolve.SingleFetch{
+ FetchDependencies: resolve.FetchDependencies{FetchID: 1},
+ FetchConfiguration: resolve.FetchConfiguration{
+ Input: "a",
+ CoordinateDependencies: []resolve.FetchDependency{
+ {
+ Coordinate: resolve.GraphCoordinate{TypeName: "T"},
+ DependsOn: []resolve.FetchDependencyOrigin{{FetchID: 2}},
+ },
+ },
+ },
+ },
+ },
+ }
+
+ root := &resolve.FetchTreeNode{
+ ChildNodes: []*resolve.FetchTreeNode{a, b},
+ }
+
+ dedup := &deduplicateSingleFetches{}
+ dedup.ProcessFetchTree(root)
+
+ assert.Len(t, root.ChildNodes, 1)
+ })
}
diff --git a/tmp/agent-patch-flux-pr-1232.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 9979256..7446adf 100644
--- a/tmp/agent-patch-flux-pr-1232.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
@@ -319,23 +319,6 @@ func (fc *FetchConfiguration) Equals(other *FetchConfiguration) bool {
if fc.SetTemplateOutputToNullOnVariableNull != other.SetTemplateOutputToNullOnVariableNull {
return false
}
- if !slices.EqualFunc(fc.CoordinateDependencies, other.CoordinateDependencies, func(a, b FetchDependency) bool {
- if a.Coordinate != b.Coordinate {
- return false
- }
- if a.IsUserRequested != b.IsUserRequested {
- return false
- }
- return slices.EqualFunc(a.DependsOn, b.DependsOn, func(x, y FetchDependencyOrigin) bool {
- return x.FetchID == y.FetchID &&
- x.Subgraph == y.Subgraph &&
- x.Coordinate == y.Coordinate &&
- x.IsKey == y.IsKey &&
- x.IsRequires == y.IsRequires
- })
- }) {
- return false
- }
return true
}