iop/apps/edge/internal/openai/hot_path_review_test.go
toki c9939edf24 fix(edge): caller workspace 하이브리드 경계를 복구한다
실제 provider 요청과 작업 공간 handoff가 같은 PLAN/REVIEW 계약을 사용해야 하며, 단계별 prepare와 pair-write 의미가 테스트와 런타임에서 일치해야 한다.
2026-08-15 04:01:21 +09:00

79 lines
3.6 KiB
Go

package openai
import (
"net/http"
"strings"
"testing"
)
func TestHotPathReviewPass(t *testing.T) {
for _, endpoint := range []string{"openai", "anthropic"} {
endpoint := endpoint
t.Run(endpoint, func(t *testing.T) {
fixture := newScriptedLightFixture(t, endpoint, false)
final := fixture.run()
if final.Code != http.StatusOK || !strings.Contains(final.Body.String(), "PASS and DEFECT prose") {
t.Fatalf("review pass response: status=%d body=%s", final.Code, final.Body.String())
}
fixture.assertCleanupCommitted(7)
})
}
}
func TestHotPathReviewDefectRepair(t *testing.T) {
for _, endpoint := range []string{"openai", "anthropic"} {
endpoint := endpoint
t.Run(endpoint, func(t *testing.T) {
fixture := newScriptedLightFixture(t, endpoint, true)
final := fixture.run()
if final.Code != http.StatusOK || !strings.Contains(final.Body.String(), "repair-complete-visible") {
t.Fatalf("review repair response: status=%d body=%s", final.Code, final.Body.String())
}
fixture.assertCleanupCommitted(8)
// A completed review has no second tool frontier. Replaying the last
// repair result is rejected before another provider submission.
before := len(fixture.service.snapshots())
replay := fixture.request()
if replay.Code != http.StatusBadRequest {
t.Fatalf("second review replay status=%d body=%s", replay.Code, replay.Body.String())
}
if after := len(fixture.service.snapshots()); after != before {
t.Fatalf("second review dispatched provider calls: before=%d after=%d", before, after)
}
})
}
}
func TestHotPathReviewStructureIgnoresProseVerdict(t *testing.T) {
completion := normalizedStageOutput{Content: "DEFECT FAIL words do not control state"}
evidence := hotPathReviewEvidence{planRead: true, reviewRead: true, inspected: true}
if kind, cleanup, err := classifyHotPathReviewOutput("req_review", hotPathPhaseReviewActive, completion, evidence); err != nil || kind != "" || !cleanup {
t.Fatalf("completion structure did not pass: kind=%q cleanup=%t err=%v", kind, cleanup, err)
}
repair := normalizedStageOutput{
Content: "PASS words do not control state",
ToolCalls: []normalizedToolCall{{ID: "provider_repair", Name: "run_command", Arguments: map[string]any{"command": "go test"}}},
}
if kind, cleanup, err := classifyHotPathReviewOutput("req_review", hotPathPhaseReviewActive, repair, evidence); err != nil || kind != hotPathPendingReviewRepair || cleanup {
t.Fatalf("repair structure did not stay active: kind=%q cleanup=%t err=%v", kind, cleanup, err)
}
}
func TestHotPathReviewRequiresInspectionAndNonEmptyTerminal(t *testing.T) {
completion := normalizedStageOutput{Content: "reviewed"}
if _, _, err := classifyHotPathReviewOutput("req_review", hotPathPhaseReviewActive, completion, hotPathReviewEvidence{}); err == nil || !strings.Contains(err.Error(), "artifact reads") {
t.Fatalf("skipped inspection error = %v", err)
}
evidence := hotPathReviewEvidence{planRead: true, reviewRead: true, inspected: true}
if _, _, err := classifyHotPathReviewOutput("req_review", hotPathPhaseReviewActive, normalizedStageOutput{}, evidence); err == nil || !strings.Contains(err.Error(), "non-empty") {
t.Fatalf("empty terminal error = %v", err)
}
reservedRepair := normalizedStageOutput{ToolCalls: []normalizedToolCall{{
ID: "provider_second_review", Name: "read_file",
Arguments: map[string]any{"path": newReservedPaths("req_review").ReviewPath},
}}}
if _, _, err := classifyHotPathReviewOutput("req_review", hotPathPhaseReviewRepair, reservedRepair, evidence); err == nil || !strings.Contains(err.Error(), "second review cycle") {
t.Fatalf("second review cycle error = %v", err)
}
}