diff --git a/cmd/cyrene/wire_memory_review_test.go b/cmd/cyrene/wire_memory_review_test.go index 9b4459a..31b5d47 100644 --- a/cmd/cyrene/wire_memory_review_test.go +++ b/cmd/cyrene/wire_memory_review_test.go @@ -75,6 +75,12 @@ func TestMemoryReviewIsWired(t *testing.T) { "a.memoryT1RateLimit()", "T1PerWindow: t1PerWindow", "T1Window: time.Duration(t1WindowSec) * time.Second", + // 临时记忆 TTL(design/03 §9.6):第五态 `defer` 写进 `expires_at` 的 + // 存活秒数,同样来自那个文件(`tempTtlSec`),缺位/坏值回落代码默认 + // 7 天。**它没有 `.env` 档**(`.env` 已冻结,本键在那里从来没有出处), + // 因此这一行被摘掉 = 面板配了也不生效,正是本缝断言要拦的回归。 + "a.memoryTempTTL()", + "TempTTL: tempTTL", }, "main.go": { "a.memoryReview.Start(ctx)", diff --git a/internal/config/runtimeconfig/memorytidy_seed_test.go b/internal/config/runtimeconfig/memorytidy_seed_test.go index 0e8242b..c2a90b1 100644 --- a/internal/config/runtimeconfig/memorytidy_seed_test.go +++ b/internal/config/runtimeconfig/memorytidy_seed_test.go @@ -248,6 +248,25 @@ func TestSeedMemoryTidy_RefusesIncompleteSeed(t *testing.T) { } } +// tidySeedLeakedValues 是「不许出现在日志里的配置值」的哨兵,**刻意带 `=` 前缀** +// (断言的形态是「字段值」而不是裸数字)。 +// +// 为什么必须带 `=`:这条用例的日志里**合法地**带 `path=<临时目录>`,而 +// `t.TempDir()` 的目录名带随机数十进制 —— 裸数字扫整行会**偶发假红**(实测命中过 +// `…WithoutValues4091800659\001\config\…` 里的 `1800`,约个位数/10000 的窗口)。 +// 带 `=` 的形态只可能来自 slog 的 `key=value` 字段;路径里的随机数前面是路径分隔 +// 片段而不是 `=`,因此不受影响(值的**位置**语义也没变松)。 +// +// 为什么不用另一个备选「只扫 `keys=` 之后的内容」:那会把断言缩成「keys 列表里 +// 没有值」,于是任何以**别的**字段名打出来的值(`interval_sec=4242`、将来新加的 +// 字段)都会溜过去 —— 那等于把这条防护改成空壳,而不是修掉它的假红。 +// +// 259200 是 tempTtlSec(completeSeedTuning 里显式给的值),与其余三个同为「一眼可 +// 辨、且与代码默认值不同」的哨兵。 +func tidySeedLeakedValues() []string { + return []string{"=4242", "=10800", "=1800", "=259200"} +} + // TestSeedMemoryTidy_LogsPathAndReasonWithoutValues 钉住「可观测」:写盘与跳过都有 // 日志(带路径与原因、带 source),且**不打任何配置值**(本仓配置日志的既有口径)。 func TestSeedMemoryTidy_LogsPathAndReasonWithoutValues(t *testing.T) { @@ -277,9 +296,9 @@ func TestSeedMemoryTidy_LogsPathAndReasonWithoutValues(t *testing.T) { if !strings.Contains(out, "已按当时生效值播种落盘") { t.Fatalf("播种日志没说明做了什么:%s", out) } - for _, value := range []string{"4242", "10800", "1800"} { + for _, value := range tidySeedLeakedValues() { if strings.Contains(out, value) { - t.Fatalf("日志里出现了配置值 %s(配置日志只许打键名):%s", value, out) + t.Fatalf("日志里出现了配置值 %s(配置日志只许打键名):%s", strings.TrimPrefix(value, "="), out) } } @@ -299,9 +318,9 @@ func TestSeedMemoryTidy_LogsPathAndReasonWithoutValues(t *testing.T) { if !strings.Contains(skipped, memoryTidySeedReasonExists) { t.Fatalf("跳过播种的日志没带 reason 字段:%s", skipped) } - for _, value := range []string{"4242", "10800", "1800"} { + for _, value := range tidySeedLeakedValues() { if strings.Contains(skipped, value) { - t.Fatalf("跳过日志里出现了配置值 %s:%s", value, skipped) + t.Fatalf("跳过日志里出现了配置值 %s:%s", strings.TrimPrefix(value, "="), skipped) } }