diff --git a/scripts/selftest.mjs b/scripts/selftest.mjs index 4771f1f..1079d47 100644 --- a/scripts/selftest.mjs +++ b/scripts/selftest.mjs @@ -265,6 +265,49 @@ check("情緒事件寫進 journal", pl.readJsonl(pl.journalPath("alpha")).some(( fs.readFileSync(catFile, "utf8").includes("換成別則了。")); } +// 慣例:程序性記憶。其餘型別都是「記得的事」,慣例是「每次都這樣做的事」 +console.log("⑤-b 習慣記憶(--type habit)"); +{ + check("habit 是合法型別", cli(["consolidate", "--persona", "alpha", "--session", S_HOST, + "--name", "不說再見", "--type", "habit", "--salience", "60", + "--body", "我們之間結束對話不說再見,直接停。"]).status === 0); + check("寫進去的型別真的是 habit", (() => { + const meta = pl.longTermEntries("alpha").find((m) => m._name === "不說再見"); + return meta?.type === "habit"; + })(), JSON.stringify(pl.longTermEntries("alpha").map((m) => `${m._name}:${m.type}`))); + check("慣例每輪注入,不必被問到(照做,不用提起它)", (() => { + const ctx = pl.turnContext("alpha", S_HOST, "今天先這樣"); + return ctx.includes("我們之間的慣例") && ctx.includes("不說再見") && ctx.includes("照做,不用提起它"); + })(), pl.turnContext("alpha", S_HOST, "今天先這樣").slice(0, 400)); + check("慣例是背景不是話題(講出來就變成在討論它)", + pl.habitBrief("alpha").includes("慣例是背景不是話題")); + check("recall 也找得到(型別不影響檢索)", + pl.recall("alpha", "再見", 5).some((r) => r._name === "不說再見"), + JSON.stringify(pl.recall("alpha", "再見", 5).map((r) => r._name))); + check("一輪最多兩條(慣例是背景,不是清單)", (() => { + for (const n of ["先講結論", "不催回覆", "週五不談公事"]) { + cli(["consolidate", "--persona", "alpha", "--session", S_HOST, "--name", n, + "--type", "habit", "--salience", "60", "--body", `我們之間${n}。`]); + } + return pl.standingHabits("alpha").length === pl.HABIT_INJECT_MAX; + })(), JSON.stringify(pl.standingHabits("alpha"))); + check("糊掉的慣例不注入(想不起來的慣例就不是慣例)", (() => { + const file = path.join(pl.longTermDir("alpha"), "不說再見.md"); + const raw = fs.readFileSync(file, "utf8"); + // 讓它很舊、強度很低 → 掉到 fuzzy + fs.writeFileSync(file, raw + .replace(/^salience:.*$/m, "salience: 20") + .replace(/^strength:.*$/m, "strength: 1") + .replace(/^last_seen:.*$/m, "last_seen: 2020-01-01T00:00:00.000Z")); + const meta = pl.longTermEntries("alpha").find((m) => m._name === "不說再見"); + const faded = pl.memoryStrength(meta).state === "fuzzy"; + const gone = !pl.standingHabits("alpha", { limit: 9 }).some((h) => h.name === "不說再見"); + fs.writeFileSync(file, raw); + return faded && gone; + })()); + check("沒有慣例的人格整段不出現", pl.habitBrief("calmsplit") === ""); +} + console.log("⑥ 短期 → 長期的轉入條件"); check("有六條成文條件", pl.PROMOTION_RULES.length === 6); check("R1 高顯著度會成為候選",