diff --git a/cmd/cyrene/wire_memory_review_test.go b/cmd/cyrene/wire_memory_review_test.go index 4c05f01..aca7659 100644 --- a/cmd/cyrene/wire_memory_review_test.go +++ b/cmd/cyrene/wire_memory_review_test.go @@ -3,10 +3,12 @@ package main import ( "context" "os" + "path/filepath" "strings" "testing" "time" + "git.yeij.top/AskaEth/Cyrene_v2/internal/config" "git.yeij.top/AskaEth/Cyrene_v2/internal/db" "git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/embedding" "git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/history" @@ -54,6 +56,10 @@ func TestMemoryReviewIsWired(t *testing.T) { "Audit: a.auditMemoryReview", // 接到 store 的唯一写入路径上。 "a.memStore.AttachIngestReviewer(reviewer)", + // 同步入库闸(2026-10-07)的开关来自 `$DATA_DIR/config/memory-tidy.json` + // 的 `{"ingestGate": false}`(**零新 env 键**,`.env` 已冻结)。 + "a.memoryIngestGateOff()", + "DisableIngestGate: gateOff", }, "main.go": { "a.memoryReview.Start(ctx)", @@ -75,13 +81,53 @@ func TestMemoryReviewIsWired(t *testing.T) { } } - // store 侧的唯一写入路径必须投递审查(否则新记忆永远不进队列)。 + // store 侧的唯一写入路径必须投递审查(否则新记忆永远不进队列), + // 且必须**先过同步入库闸**(2026-10-07:闸就摆在写路径上,重复当场落 merged)。 storeSrc, err := os.ReadFile("../../internal/runtime/memory/store.go") if err != nil { t.Fatalf("read memory/store.go: %v", err) } - if !strings.Contains(string(storeSrc), "s.enqueueReview(item)") { - t.Fatal("memory/store.go 的写入路径上没有投递审查(写路径唯一)") + for _, want := range []string{"s.enqueueReview(item)", "s.planIngest(ctx, item)", "s.finishIngest(ctx, item, plan)"} { + if !strings.Contains(string(storeSrc), want) { + t.Fatalf("memory/store.go 的写入路径上找不到 %q(唯一写路径上的闸/投递断了)", want) + } + } +} + +// TestMemoryIngestGate_ReadsDataDirConfig 钉住**同步入库闸**的开关确实来自 +// `$DATA_DIR/config/memory-tidy.json`(它没有 env 键:`.env` 已冻结)—— +// 若组合根没读那个文件,「一键回到只插不审」就是一句空话。 +// +// 口径与自动档同一条:没配 = 开;显式 false = 关;坏文件 = 回落代码默认(开) +// 并记 WARN,**绝不静默把一处防护关掉**。 +func TestMemoryIngestGate_ReadsDataDirConfig(t *testing.T) { + t.Parallel() + + empty := &app{cfg: &config.Config{DataDir: t.TempDir()}, log: tidyTestLog()} + if empty.memoryIngestGateOff() { + t.Fatal("没配过时入库闸应当保持代码默认(开)") + } + + dataDir := t.TempDir() + dir := filepath.Join(dataDir, "config") + if err := os.MkdirAll(dir, 0o700); err != nil { + t.Fatalf("mkdir: %v", err) + } + path := filepath.Join(dir, "memory-tidy.json") + if err := os.WriteFile(path, []byte(`{"ingestGate": false}`), 0o600); err != nil { + t.Fatalf("write: %v", err) + } + off := &app{cfg: &config.Config{DataDir: dataDir}, log: tidyTestLog()} + if !off.memoryIngestGateOff() { + t.Fatal("ingestGate: false 没被读到(闸没有一键关掉的路径)") + } + + if err := os.WriteFile(path, []byte(`{"ingestGate": "nope"}`), 0o600); err != nil { + t.Fatalf("write broken: %v", err) + } + broken := &app{cfg: &config.Config{DataDir: dataDir}, log: tidyTestLog()} + if broken.memoryIngestGateOff() { + t.Fatal("坏配置把入库闸静默关掉了:必须回落代码默认(开)") } }