diff --git a/internal/ctxmgr/semantic_shadow.go b/internal/ctxmgr/semantic_shadow.go deleted file mode 100644 index 370cc6ab..00000000 --- a/internal/ctxmgr/semantic_shadow.go +++ /dev/null @@ -1,48 +0,0 @@ -package ctxmgr - -import ( - "context" - "os" - "strings" -) - -// SemanticSummaryShadowEnabled reports SEMANTIC_SUMMARY_SHADOW (default off). -func SemanticSummaryShadowEnabled() bool { - v := strings.TrimSpace(os.Getenv("SEMANTIC_SUMMARY_SHADOW")) - return v == "1" || strings.EqualFold(v, "true") || strings.EqualFold(v, "yes") -} - -// MaybeApplySemanticShadow optionally annotates a deterministic summary when the -// shadow flag is on. It never drops Facts; on "model" failure it keeps the -// deterministic narrative and marks freshness. Summarizer has no tool rights. -func MaybeApplySemanticShadow(ctx context.Context, sum *ChatSummary, authorizedOnly bool) *ChatSummary { - _ = ctx - if sum == nil || !SemanticSummaryShadowEnabled() { - return sum - } - if !authorizedOnly { - // Refuse to summarize unauthorized views. - out := *sum - if out.Facts == nil { - out.Facts = map[string]string{} - } - out.Facts["semantic_shadow"] = "skipped_unauthorized_view" - return &out - } - out := *sum - if out.Facts == nil { - out.Facts = map[string]string{} - } - // Deterministic shadow stub (no external LLM in unit path). Real PI can - // replace Narrative later behind the same flag; failure keeps deterministic. - shadow := strings.TrimSpace(out.Narrative) - if shadow == "" { - shadow = "(语义摘要影子:无叙事,保留事实槽位)" - } else if !strings.Contains(shadow, "[shadow]") { - shadow = "[shadow] " + shadow - } - out.Narrative = shadow - out.Facts["semantic_shadow"] = "applied" - out.Facts["semantic_shadow_freshness"] = "deterministic_fallback_ok" - return &out -} diff --git a/internal/ctxmgr/semantic_shadow_test.go b/internal/ctxmgr/semantic_shadow_test.go deleted file mode 100644 index 23e5527f..00000000 --- a/internal/ctxmgr/semantic_shadow_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package ctxmgr - -import "testing" - -func TestSemanticSummaryShadowDefaultOff(t *testing.T) { - t.Setenv("SEMANTIC_SUMMARY_SHADOW", "") - if SemanticSummaryShadowEnabled() { - t.Fatal("default off") - } - in := &ChatSummary{SessionID: "s1", Narrative: "hello", Facts: map[string]string{"a": "1"}} - out := MaybeApplySemanticShadow(t.Context(), in, true) - if out.Narrative != "hello" || out.Facts["semantic_shadow"] != "" { - t.Fatalf("unchanged when off: %+v", out) - } -} - -func TestSemanticSummaryShadowAuthorized(t *testing.T) { - t.Setenv("SEMANTIC_SUMMARY_SHADOW", "1") - in := &ChatSummary{SessionID: "s1", Narrative: "topic", Facts: map[string]string{"k": "v"}} - out := MaybeApplySemanticShadow(t.Context(), in, true) - if !stringsHasPrefix(out.Narrative, "[shadow]") { - t.Fatalf("narrative=%q", out.Narrative) - } - if out.Facts["k"] != "v" || out.Facts["semantic_shadow"] != "applied" { - t.Fatalf("facts=%v", out.Facts) - } -} - -func TestSemanticSummaryShadowUnauthorizedSkipped(t *testing.T) { - t.Setenv("SEMANTIC_SUMMARY_SHADOW", "true") - in := &ChatSummary{SessionID: "s1", Narrative: "x", Facts: map[string]string{}} - out := MaybeApplySemanticShadow(t.Context(), in, false) - if out.Facts["semantic_shadow"] != "skipped_unauthorized_view" { - t.Fatalf("%v", out.Facts) - } -} - -func stringsHasPrefix(s, p string) bool { - return len(s) >= len(p) && s[:len(p)] == p -} diff --git a/internal/ctxmgr/summarizer.go b/internal/ctxmgr/summarizer.go index 95b053d1..a92d8b9e 100644 --- a/internal/ctxmgr/summarizer.go +++ b/internal/ctxmgr/summarizer.go @@ -199,7 +199,6 @@ func (m *ContextManager) GenerateRollingSummary(ctx context.Context, sessionID s // 保存并返回 _ = m.SaveChatSummary(ctx, newSum) - newSum = MaybeApplySemanticShadow(ctx, newSum, true) return newSum, nil }