diff --git a/intercept/intercept.go b/intercept/intercept.go index 796b9fb..21a376b 100644 --- a/intercept/intercept.go +++ b/intercept/intercept.go @@ -316,7 +316,7 @@ const ( // Judge default values. const ( defaultJudgeTimeoutSecs = 15 - defaultJudgeFailAction = "allow" + defaultJudgeFailAction = "ask" defaultJudgeAskTimeoutSecs = 300 defaultJudgeAskTimeoutAction = "deny" // DefaultIncompleteScriptAction keeps incomplete snapshots with the judge. diff --git a/intercept/judge_retry_test.go b/intercept/judge_retry_test.go index 885e96f..b71c715 100644 --- a/intercept/judge_retry_test.go +++ b/intercept/judge_retry_test.go @@ -31,6 +31,28 @@ func retryTestInterceptor(t *testing.T, settings map[string]string) *Interceptor return New(&db.DB{DB: d}) } +func TestJudgeFailActionDefaultsAndOverrides(t *testing.T) { + for _, tc := range []struct { + name, value, want string + }{ + {"missing", "", "ask"}, + {"invalid", "invalid", "ask"}, + {"saved_allow", "allow", "allow"}, + {"saved_ask", "ask", "ask"}, + {"saved_deny", "deny", "deny"}, + } { + t.Run(tc.name, func(t *testing.T) { + settings := map[string]string{} + if tc.value != "" { + settings[settingJudgeFailAction] = tc.value + } + if got := retryTestInterceptor(t, settings).GetJudgeConfig().FailAction; got != tc.want { + t.Fatalf("fail action=%s want=%s", got, tc.want) + } + }) + } +} + func TestJudgeRetryConfigDefaultsAndBounds(t *testing.T) { for _, tc := range []struct { name string @@ -63,14 +85,19 @@ func TestJudgeRetriesBeforeApplyingFailurePolicy(t *testing.T) { {"recover", "deny", "allow", 2, 3, "allow", false}, {"valid_deny_is_final", "allow", "deny", 0, 1, "deny", false}, {"valid_ask_is_final", "allow", "ask", 0, 1, "ask", false}, + {"exhaust_default", "", "allow", 9, 3, "ask", true}, {"exhaust_allow", "allow", "allow", 9, 3, "allow", true}, {"exhaust_ask", "ask", "allow", 9, 3, "ask", true}, {"exhaust_deny", "deny", "allow", 9, 3, "deny", true}, } { t.Run(tc.name, func(t *testing.T) { - i := retryTestInterceptor(t, map[string]string{ - settingJudgeEnabled: "true", settingJudgeRetryCount: "2", settingJudgeRetryIntervalMS: "0", settingJudgeFailAction: tc.failAction, - }) + settings := map[string]string{ + settingJudgeEnabled: "true", settingJudgeRetryCount: "2", settingJudgeRetryIntervalMS: "0", + } + if tc.failAction != "" { + settings[settingJudgeFailAction] = tc.failAction + } + i := retryTestInterceptor(t, settings) calls := 0 var first ReviewInput i.SetReviewer(func(ctx context.Context, id int64, prompt string, input ReviewInput) (Decision, error) { diff --git a/web/src/app/(main)/system/intercept/page.tsx b/web/src/app/(main)/system/intercept/page.tsx index 597e67c..90eab2f 100644 --- a/web/src/app/(main)/system/intercept/page.tsx +++ b/web/src/app/(main)/system/intercept/page.tsx @@ -203,7 +203,7 @@ const defaultJudge = (): JudgeConfig => ({ timeout_seconds: 15, retry_count: 0, retry_interval_ms: 1000, - fail_action: "allow", + fail_action: "ask", ask_timeout_seconds: 300, ask_timeout_action: "deny", incomplete_script_action: "model", diff --git a/web/src/lib/mock/handler.ts b/web/src/lib/mock/handler.ts index eb072aa..83f27ac 100644 --- a/web/src/lib/mock/handler.ts +++ b/web/src/lib/mock/handler.ts @@ -2514,7 +2514,7 @@ function route(m: string, path: string, seg: string[], q: URLSearchParams, b: Re timeout_seconds: 15, retry_count: 0, retry_interval_ms: 1000, - fail_action: "allow", + fail_action: "ask", ask_timeout_seconds: 300, ask_timeout_action: "deny", incomplete_script_action: "model",