From ffc5b108c68f2ec9864997ef7ca691464b2dd3d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=94=AF?= Date: Sat, 17 Oct 2026 22:34:01 +0800 Subject: [PATCH] =?UTF-8?q?fix(test):=20t=5Fb7a8ed9c=20routes=20E2E=20?= =?UTF-8?q?=E8=A2=AB=20distill=20=E6=89=93=E5=88=86=E7=BC=93=E5=AD=98=20Re?= =?UTF-8?q?dis=20L2=20=E9=9D=99=E9=BB=98=E7=9F=AD=E8=B7=AF=20=E2=80=94=20T?= =?UTF-8?q?estMain=20=E5=85=B3=E7=BC=93=E5=AD=98=20+=20Once=20=E6=B4=BB?= =?UTF-8?q?=E8=AF=BB=20env?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因(非卡内假设的 flush 触发条件重构): - a162e27 打分记忆化 + ce38465 L2 改生产 Redis(zhiyi:distill-score:*,TTL 168h) 后,routes 包测试(无 TestMain 关闭开关)把「测试内容哈希→结果」写进生产 Redis; 7 天内后续 run L2 命中 → mock LLM 被短路 → 计数断言 base+1 必挂。 - 实测 TestCommitConflictGate_E2E 16.5s 固定 FAIL(got 0);日志证明 flush 正常 触发且跑完(batch=1 → DONE),缺的只是 LLM 那次 HTTP 调用。 生产残留键 TTL≈40h(2026-10-17 复核 143207s)即污染源,TTL 自然过期。 - 对齐门禁规矩③(加缓存须给该包 TestMain 加关闭开关): routes 新增 scorecache_guard_test.go TestMain 设 ZHIYI_SCORE_CACHE=0; distill.getScoreCache 的 Once 闭包活读 env(包级变量 init 时定型,跨包测试设不了; 生产语义不变,启动时 env 仍在此处生效)。 验证:go test ./internal/api/routes/ -count=1(不 -skip)ok 34.9s; go test ./internal/distill/... ./internal/api/... ./internal/selfoptimize/... 全 ok。 ⚠️ t_e5997ca4 分支同包加了 testmain_test.go(ZHIYI_DASHBOARD_PATH 护栏 TestMain), 两分支合并时须合并成一个 TestMain。 --- .../api/routes/scorecache_guard_test.go | 28 +++++++++++++++++++ go/internal/distill/score_cache.go | 7 ++++- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 go/internal/api/routes/scorecache_guard_test.go 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 }