STET

agent_patch

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

11513 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-870.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/resolve/extensions_test.go b/app/v2/pkg/engine/resolve/extensions_test.go
index 6d16e3e..4573cbc 100644
--- a/tmp/agent-patch-flux-pr-870.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/resolve/extensions_test.go
+++ b/app/v2/pkg/engine/resolve/extensions_test.go
@@ -120,7 +120,7 @@ func TestExtensions(t *testing.T) {
 		ctx.ctx = SetTraceStart(ctx.ctx, true)
 
 		return res, ctx,
-			`{"errors":[{"message":"Unauthorized request to Subgraph 'users' at Path 'query', Reason: test."},{"message":"Failed to fetch from Subgraph 'reviews' at Path 'query.me'.","extensions":{"errors":[{"message":"Failed to render Fetch Input","path":["me"]}]}},{"message":"Failed to fetch from Subgraph 'products' at Path 'query.me.reviews.@.product'.","extensions":{"errors":[{"message":"Failed to render Fetch Input","path":["me","reviews","@","product"]}]}}],"data":{"me":null},"extensions":{"authorization":{"missingScopes":[["read:users"]]},"rateLimit":{"Policy":"policy","Allowed":0,"Used":0},"trace":{"version":"1","info":{"trace_start_time":"","trace_start_unix":0,"parse_stats":{"duration_nanoseconds":0,"duration_pretty":"","duration_since_start_nanoseconds":0,"duration_since_start_pretty":""},"normalize_stats":{"duration_nanoseconds":0,"duration_pretty":"","duration_since_start_nanoseconds":0,"duration_since_start_pretty":""},"validate_stats":{"duration_nanoseconds":0,"duration_pretty":"","duration_since_start_nanoseconds":0,"duration_since_start_pretty":""},"planner_stats":{"duration_nanoseconds":0,"duration_pretty":"","duration_since_start_nanoseconds":0,"duration_since_start_pretty":""}},"fetches":{"kind":"Sequence","children":[{"kind":"Single","fetch":{"kind":"Single","path":"query","trace":{"raw_input_data":{},"single_flight_used":false,"single_flight_shared_response":false,"load_skipped":false}}},{"kind":"Single","fetch":{"kind":"Single","path":"query.me","trace":{"single_flight_used":false,"single_flight_shared_response":false,"load_skipped":false}}},{"kind":"Single","fetch":{"kind":"Single","path":"query.me.reviews.@.product","trace":{"single_flight_used":false,"single_flight_shared_response":false,"load_skipped":false}}}]}}}}`,
+			`{"errors":[{"message":"Unauthorized request to Subgraph 'users' at Path 'query', Reason: test."},{"message":"Failed to fetch from Subgraph 'reviews' at Path 'query.me'.","extensions":{"errors":[{"message":"Failed to render Fetch Input","path":["me"]}]}},{"message":"Failed to fetch from Subgraph 'products' at Path 'query.me.reviews.@.product'.","extensions":{"errors":[{"message":"Failed to render Fetch Input","path":["me","reviews","@","product"]}]}}],"data":{"me":null},"extensions":{"authorization":{"missingScopes":[["read:users"]]},"rateLimit":{"Policy":"policy","Allowed":0,"Used":0},"trace":{"version":"1","info":{"trace_start_time":"","trace_start_unix":0,"parse_stats":{"duration_nanoseconds":0,"duration_pretty":"","duration_since_start_nanoseconds":0,"duration_since_start_pretty":""},"normalize_stats":{"duration_nanoseconds":0,"duration_pretty":"","duration_since_start_nanoseconds":0,"duration_since_start_pretty":""},"validate_stats":{"duration_nanoseconds":0,"duration_pretty":"","duration_since_start_nanoseconds":0,"duration_since_start_pretty":""},"planner_stats":{"duration_nanoseconds":0,"duration_pretty":"","duration_since_start_nanoseconds":0,"duration_since_start_pretty":""}},"fetches":{"kind":"Sequence","children":[{"kind":"Single","fetch":{"kind":"Single","path":"query","trace":{"data_source_id":"users","raw_input_data":{},"single_flight_used":false,"single_flight_shared_response":false,"load_skipped":false}}},{"kind":"Single","fetch":{"kind":"Single","path":"query.me","trace":{"data_source_id":"reviews","single_flight_used":false,"single_flight_shared_response":false,"load_skipped":false}}},{"kind":"Single","fetch":{"kind":"Single","path":"query.me.reviews.@.product","trace":{"data_source_id":"products","single_flight_used":false,"single_flight_shared_response":false,"load_skipped":false}}}]}}}}`,
 			func(t *testing.T) {}
 	}))
 }
diff --git a/tmp/agent-patch-flux-pr-870.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/resolve/fetch.go b/app/v2/pkg/engine/resolve/fetch.go
index 138664e..203cd43 100644
--- a/tmp/agent-patch-flux-pr-870.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/resolve/fetch.go
+++ b/app/v2/pkg/engine/resolve/fetch.go
@@ -276,6 +276,7 @@ type GraphCoordinate struct {
 }
 
 type DataSourceLoadTrace struct {
+	DataSourceID               string          `json:"data_source_id,omitempty"`
 	RawInputData               json.RawMessage `json:"raw_input_data,omitempty"`
 	Input                      json.RawMessage `json:"input,omitempty"`
 	Output                     json.RawMessage `json:"output,omitempty"`
diff --git a/tmp/agent-patch-flux-pr-870.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/resolve/loader.go b/app/v2/pkg/engine/resolve/loader.go
index 0957b3f..36406be 100644
--- a/tmp/agent-patch-flux-pr-870.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/resolve/loader.go
+++ b/app/v2/pkg/engine/resolve/loader.go
@@ -941,6 +941,7 @@ func (l *Loader) loadSingleFetch(ctx context.Context, fetch *SingleFetch, fetchI
 	l.itemsData(items, buf.input)
 	if l.ctx.TracingOptions.Enable {
 		fetch.Trace = &DataSourceLoadTrace{}
+		setTraceDataSourceID(fetch.Trace, fetch.Info)
 		if !l.ctx.TracingOptions.ExcludeRawInputData {
 			inputCopy := make([]byte, buf.input.Len())
 			copy(inputCopy, buf.input.Bytes())
@@ -1000,6 +1001,7 @@ func (l *Loader) loadEntityFetch(ctx context.Context, fetchItem *FetchItem, fetc
 
 	if l.ctx.TracingOptions.Enable {
 		fetch.Trace = &DataSourceLoadTrace{}
+		setTraceDataSourceID(fetch.Trace, fetch.Info)
 		if !l.ctx.TracingOptions.ExcludeRawInputData {
 			itemDataCopy := make([]byte, buf.itemData.Len())
 			copy(itemDataCopy, buf.itemData.Bytes())
@@ -1110,6 +1112,7 @@ func (l *Loader) loadBatchEntityFetch(ctx context.Context, fetchItem *FetchItem,
 
 	if l.ctx.TracingOptions.Enable {
 		fetch.Trace = &DataSourceLoadTrace{}
+		setTraceDataSourceID(fetch.Trace, fetch.Info)
 		if !l.ctx.TracingOptions.ExcludeRawInputData {
 			buf := &bytes.Buffer{}
 			l.itemsData(items, buf)
@@ -1277,6 +1280,13 @@ func setSingleFlightStats(ctx context.Context, stats *SingleFlightStats) context
 	return context.WithValue(ctx, singleFlightStatsKey{}, stats)
 }
 
+func setTraceDataSourceID(trace *DataSourceLoadTrace, info *FetchInfo) {
+	if trace == nil || info == nil {
+		return
+	}
+	trace.DataSourceID = info.DataSourceID
+}
+
 func (l *Loader) setTracingInput(fetchItem *FetchItem, input []byte, trace *DataSourceLoadTrace) {
 	trace.Path = fetchItem.ResponsePath
 	if !l.ctx.TracingOptions.ExcludeInput {
diff --git a/tmp/agent-patch-flux-pr-870.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/resolve/resolvable.go b/app/v2/pkg/engine/resolve/resolvable.go
index c4d0830..e213473 100644
--- a/tmp/agent-patch-flux-pr-870.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/resolve/resolvable.go
+++ b/app/v2/pkg/engine/resolve/resolvable.go
@@ -270,6 +270,7 @@ func (r *Resolvable) printRateLimitingExtension() error {
 
 func (r *Resolvable) printTraceExtension(ctx context.Context, fetchTree *FetchTreeNode) error {
 	trace := GetTrace(ctx, fetchTree)
+	normalizeTraceFetches(trace.Fetches)
 	content, err := json.Marshal(trace)
 	if err != nil {
 		return err
@@ -282,6 +283,45 @@ func (r *Resolvable) printTraceExtension(ctx context.Context, fetchTree *FetchTr
 	return nil
 }
 
+func normalizeTraceFetches(node *FetchTreeTraceNode) {
+	if node == nil {
+		return
+	}
+	if node.Fetch != nil {
+		normalizeTraceLoad(node.Fetch.Fetch)
+		for i := range node.Fetch.Fetches {
+			normalizeTraceLoad(node.Fetch.Fetches[i])
+		}
+	}
+	for i := range node.Children {
+		normalizeTraceFetches(node.Children[i])
+	}
+}
+
+func normalizeTraceLoad(trace *DataSourceLoadTrace) {
+	if trace == nil {
+		return
+	}
+	trace.RawInputData = normalizeRawJSON(trace.RawInputData)
+	trace.Input = normalizeRawJSON(trace.Input)
+	trace.Output = normalizeRawJSON(trace.Output)
+}
+
+func normalizeRawJSON(data json.RawMessage) json.RawMessage {
+	if len(data) == 0 {
+		return data
+	}
+	var payload any
+	if err := json.Unmarshal(data, &payload); err != nil {
+		return data
+	}
+	normalized, err := json.Marshal(payload)
+	if err != nil {
+		return data
+	}
+	return normalized
+}
+
 func (r *Resolvable) hasExtensions() bool {
 	if r.ctx.authorizer != nil && r.ctx.authorizer.HasResponseExtensionData(r.ctx) {
 		return true
diff --git a/tmp/agent-patch-flux-pr-870.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/resolve/resolvable_test.go b/app/v2/pkg/engine/resolve/resolvable_test.go
index 24c1e22..5d15cf9 100644
--- a/tmp/agent-patch-flux-pr-870.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/resolve/resolvable_test.go
+++ b/app/v2/pkg/engine/resolve/resolvable_test.go
@@ -6,6 +6,7 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/ast"
 )
@@ -575,3 +576,44 @@ func TestResolvable_WithTracing(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Equal(t, `{"data":{"topProducts":[{"name":"Table","stock":8,"reviews":[{"body":"Love Table!","author":{"name":"user-1"}},{"body":"Prefer other Table.","author":{"name":"user-2"}}]},{"name":"Couch","stock":2,"reviews":[{"body":"Couch Too expensive.","author":{"name":"user-1"}}]},{"name":"Chair","stock":5,"reviews":[{"body":"Chair Could be better.","author":{"name":"user-2"}}]}]},"extensions":{"trace":{"version":"1","info":{"trace_start_time":"","trace_start_unix":0,"parse_stats":{"duration_nanoseconds":5,"duration_pretty":"5ns","duration_since_start_nanoseconds":5,"duration_since_start_pretty":"5ns"},"normalize_stats":{"duration_nanoseconds":5,"duration_pretty":"5ns","duration_since_start_nanoseconds":10,"duration_since_start_pretty":"10ns"},"validate_stats":{"duration_nanoseconds":5,"duration_pretty":"5ns","duration_since_start_nanoseconds":15,"duration_since_start_pretty":"15ns"},"planner_stats":{"duration_nanoseconds":5,"duration_pretty":"5ns","duration_since_start_nanoseconds":20,"duration_since_start_pretty":"20ns"}},"fetches":{"kind":"Sequence"}}}}`, out.String())
 }
+
+func TestResolvable_TraceOutputCompactsAndDeduplicatesJSON(t *testing.T) {
+	res := NewResolvable()
+	ctx := NewContext(SetTraceStart(context.Background(), true))
+	ctx.TracingOptions.Enable = true
+	ctx.TracingOptions.IncludeTraceOutputInResponseExtensions = true
+	ctx.TracingOptions.EnablePredictableDebugTimings = true
+
+	err := res.Init(ctx, []byte(`{"hello":"world"}`), ast.OperationTypeQuery)
+	require.NoError(t, err)
+
+	object := &Object{
+		Fields: []*Field{
+			{
+				Name: []byte("hello"),
+				Value: &String{
+					Path: []string{"hello"},
+				},
+			},
+		},
+	}
+
+	fetchTree := Sequence(
+		SingleWithPath(
+			&SingleFetch{
+				Trace: &DataSourceLoadTrace{
+					DataSourceID: "users",
+					Input:        []byte(` { "a" : 1 , "a" : 2 } `),
+					Output:       []byte(` { "x" : { "y" : 1 , "y" : 2 } } `),
+				},
+			},
+			"query",
+		),
+	)
+
+	out := &bytes.Buffer{}
+	err = res.Resolve(ctx.ctx, object, fetchTree, out)
+	require.NoError(t, err)
+	assert.Contains(t, out.String(), `"input":{"a":2}`)
+	assert.Contains(t, out.String(), `"output":{"x":{"y":2}}`)
+}