From 1e2aaf4c6496db214669b627067632c76453161e Mon Sep 17 00:00:00 2001 From: toki Date: Sat, 15 Aug 2026 10:13:02 +0900 Subject: [PATCH] =?UTF-8?q?fix(edge):=20artifact=20content=EC=99=80=20?= =?UTF-8?q?=EC=A0=9C=EC=96=B4=20=EA=B2=BD=EB=A1=9C=EB=A5=BC=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/edge/internal/openai/hot_path_selector.go | 18 +++++++++++------- .../internal/openai/hot_path_selector_test.go | 7 +++++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/apps/edge/internal/openai/hot_path_selector.go b/apps/edge/internal/openai/hot_path_selector.go index d0f84fff..043815f9 100644 --- a/apps/edge/internal/openai/hot_path_selector.go +++ b/apps/edge/internal/openai/hot_path_selector.go @@ -342,7 +342,7 @@ func reservedPathSourcesFromToolCall(tc normalizedToolCall) []string { } add(tc.Path) if tc.Arguments != nil { - collectReservedStrings(tc.Arguments, add) + collectReservedArgumentStrings(tc.Arguments, add) if tc.RawArgs == "" { return paths } @@ -351,7 +351,7 @@ func reservedPathSourcesFromToolCall(tc normalizedToolCall) []string { decoder.UseNumber() if decoder.Decode(&decoded) == nil && decoded != nil { if !reflect.DeepEqual(decoded, tc.Arguments) { - collectReservedStrings(decoded, add) + collectReservedArgumentStrings(decoded, add) } return paths } @@ -365,24 +365,28 @@ func reservedPathSourcesFromToolCall(tc normalizedToolCall) []string { decoder := json.NewDecoder(strings.NewReader(tc.RawArgs)) decoder.UseNumber() if decoder.Decode(&decoded) == nil { - collectReservedStrings(decoded, add) + collectReservedArgumentStrings(decoded, add) } else { add(tc.RawArgs) } return paths } -func collectReservedStrings(value any, add func(string)) { +func collectReservedArgumentStrings(value any, add func(string)) { switch typed := value.(type) { case string: add(typed) case map[string]any: - for _, item := range typed { - collectReservedStrings(item, add) + for key, item := range typed { + switch strings.ToLower(strings.TrimSpace(key)) { + case "content", "plan_content", "review_content": + continue + } + collectReservedArgumentStrings(item, add) } case []any: for _, item := range typed { - collectReservedStrings(item, add) + collectReservedArgumentStrings(item, add) } } } diff --git a/apps/edge/internal/openai/hot_path_selector_test.go b/apps/edge/internal/openai/hot_path_selector_test.go index 183dadd6..cf86c59d 100644 --- a/apps/edge/internal/openai/hot_path_selector_test.go +++ b/apps/edge/internal/openai/hot_path_selector_test.go @@ -42,6 +42,13 @@ func TestHotPathSelectorDecisionMatrix(t *testing.T) { {ID: "call_review", Name: "write_file", Arguments: map[string]any{"path": issued.ReviewPath}}, }}, }, + { + name: "ExactPairContentMayMentionReservedPaths", preset: preset, gate: validGate, wantMode: modeLight, wantReason: reasonLightExactPair, + output: normalizedStageOutput{ToolCalls: []normalizedToolCall{ + {ID: "call_plan", Name: "write_file", Arguments: map[string]any{"path": issued.PlanPath, "content": "Read " + issued.ReviewPath + " before handoff."}}, + {ID: "call_review", Name: "write_file", Arguments: map[string]any{"path": issued.ReviewPath, "content": "Template for " + issued.PlanPath}}, + }}, + }, { name: "PartialPair", preset: preset, gate: validGate, wantReason: reasonMalformedPartialPair, wantErr: true, output: normalizedStageOutput{ToolCalls: []normalizedToolCall{{ID: "call_plan", Name: "write_file", Arguments: map[string]any{"path": issued.PlanPath}}}},