diff --git a/go/internal/api/routes/scorecache_guard_test.go b/go/internal/api/routes/scorecache_guard_test.go new file mode 100644 index 0000000..bcca7d0 --- /dev/null +++ b/go/internal/api/routes/scorecache_guard_test.go @@ -0,0 +1,28 @@ +// 织忆 MemoryWeave — routes 包测试护栏(t_b7a8ed9c):默认关闭 distill 打分缓存。 +// +// 背景:distill 打分记忆化(0dc571d)+ Redis L2(36db9bb,键 zhiyi:distill-score:*, +// TTL 168h)后,**本包 E2E 测试(zz_commit_conflict_gate_test.go)会读写生产 Redis**: +// 第一次 run L2 miss → 真调 mock LLM 并把「测试内容哈希 → 结果」写进生产; +// 7 天内后续 run L2 hit → LLM 被静默短路 → 数 LLM 调用次数的断言(base+1)必挂。 +// 实测 2026-10-17:TestCommitConflictGate_E2E 16.5s 固定 FAIL, +// 「expected >= 1 LLM distill calls, got 0」,生产键 TTL≈40h 残留即污染源。 +// +// 治法(对齐项目门禁规矩③:加缓存必须给该包 TestMain 加关闭开关): +// TestMain 里 Setenv ZHIYI_SCORE_CACHE=0 —— distill.getScoreCache 的 Once 闭包 +// 活读 env(包级变量在 init 时已定型,跨包设不了),本进程内缓存整体禁用: +// 不读 L2(LLM 真被调用,计数断言有覆盖)、不写 L2(不再污染生产)。 +// +// ⚠️ 合并提示:t_e5997ca4 分支在 routes 加了 testmain_test.go(ZHIYI_DASHBOARD_PATH +// 护栏,另一个 TestMain)。两卡分支合并到 main 后同包两个 TestMain 编译冲突, +// 合并时必须把两个 TestMain 体合并进一个文件。 +package routes + +import ( + "os" + "testing" +) + +func TestMain(m *testing.M) { + _ = os.Setenv("ZHIYI_SCORE_CACHE", "0") + os.Exit(m.Run()) +} diff --git a/go/internal/distill/score_cache.go b/go/internal/distill/score_cache.go index d587297..5446f6a 100644 --- a/go/internal/distill/score_cache.go +++ b/go/internal/distill/score_cache.go @@ -82,7 +82,12 @@ var ( func getScoreCache() *scoreCache { scoreCacheOnce.Do(func() { - if scoreCacheDisabled { + // 活读 env(而非只认包级变量):包级变量在进程 init 时定型,跨包测试 + // (如 routes)在 TestMain 里 Setenv 时已太迟 —— 让 TestMain 能真正关掉 + // 缓存(测试进程确定性:数 LLM 调用次数的断言不被 L2 命中短路)。 + // 生产语义不变:env 在进程生命周期内稳定,启动时的 ZHIYI_SCORE_CACHE=0 + // 依然在此处被读到。 + if scoreCacheDisabled || os.Getenv("ZHIYI_SCORE_CACHE") == "0" { log.Printf("[scorecache] 已禁用(环境变量 ZHIYI_SCORE_CACHE=0 或测试环境)") return }