From 3ac0f46c7b867d9c3e83ce29964ee9deb2d37945 Mon Sep 17 00:00:00 2001 From: toki Date: Sat, 15 Aug 2026 14:03:49 +0900 Subject: [PATCH] =?UTF-8?q?fix(openai):=20atomic=20artifact=20pair=20?= =?UTF-8?q?=ED=88=AC=EC=98=81=EC=9D=84=20=EA=B5=90=EC=A0=95=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/edge/internal/openai/artifact_pair.go | 6 ++++++ apps/edge/internal/openai/artifact_pair_test.go | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/apps/edge/internal/openai/artifact_pair.go b/apps/edge/internal/openai/artifact_pair.go index 61989c44..1426815b 100644 --- a/apps/edge/internal/openai/artifact_pair.go +++ b/apps/edge/internal/openai/artifact_pair.go @@ -260,6 +260,12 @@ func (s *artifactFrontierStore) expandSelectorPair( {ID: pairProviderCallID(providerID, "plan"), ProviderCallID: pairProviderCallID(providerID, "plan"), Name: write.toolName, Arguments: map[string]any{"path": paths.PlanPath, "content": planContent}}, {ID: pairProviderCallID(providerID, "review"), ProviderCallID: pairProviderCallID(providerID, "review"), Name: write.toolName, Arguments: map[string]any{"path": paths.ReviewPath, "content": reviewContent}}, } + // Provider deltas still describe the one selector-private atomic pair call. + // The caller projection owns two replacement writes, so collect them from + // ToolCalls instead of replaying the stale one-call delta inventory. + output.Deltas = nil + output.Content = "" + output.Reasoning = "" return output, nil } diff --git a/apps/edge/internal/openai/artifact_pair_test.go b/apps/edge/internal/openai/artifact_pair_test.go index f89c30cf..0750ae59 100644 --- a/apps/edge/internal/openai/artifact_pair_test.go +++ b/apps/edge/internal/openai/artifact_pair_test.go @@ -324,6 +324,8 @@ func newArtifactPairFixture(t *testing.T, endpoint string, createsParents bool) func TestArtifactSelectorAtomicPairExpandsToCallerWrites(t *testing.T) { fixture := newArtifactPairFixture(t, "openai", true) output, err := fixture.server.artifactFrontiers.expandSelectorPair(fixture.requestID, fixture.ownerEdgeID, normalizedStageOutput{ + Content: "selector-private text", Reasoning: "selector-private reasoning", + Deltas: []normalizedStageDelta{{Kind: normalizedStageDeltaTool, ToolID: "provider_pair", ToolName: hotPathArtifactPairToolName, Arguments: `{"plan_content":"old"}`}}, ToolCalls: []normalizedToolCall{{ ID: "provider_pair", Name: hotPathArtifactPairToolName, Arguments: map[string]any{"plan_content": testLightweightPlan(t), "review_content": testPendingReview(t)}, @@ -342,6 +344,9 @@ func TestArtifactSelectorAtomicPairExpandsToCallerWrites(t *testing.T) { if output.ToolCalls[0].ProviderCallID == output.ToolCalls[1].ProviderCallID { t.Fatalf("expanded provider ids must be distinct: %+v", output.ToolCalls) } + if len(output.Deltas) != 0 || output.Content != "" || output.Reasoning != "" { + t.Fatalf("expanded caller writes retained selector-private projection: %+v", output) + } } func TestArtifactSelectorAtomicPairDropsGeminiThoughtSignatureEnvelope(t *testing.T) {