feat(記憶與目標): 專案目標三條 + 固化候選不再重算(0.2.1) #17

Merged
admin merged 41 commits from develop into master 2026-08-03 09:15:21 +00:00
3 changed files with 29 additions and 6 deletions
Showing only changes of commit 06774ceb2b - Show all commits
+7 -6
View File
@@ -46,7 +46,7 @@ Q5Q10 六題已於 2026/08/03 由使用者拍板,設計不再需要確認
--- ---
- [ ] **5.7 動作加進名字後的括號(Q6 拍板格式,其他項目的基礎,先做)** - [x] **5.7 動作加進名字後的括號(Q6 拍板格式,其他項目的基礎,先做)**2026/08/03 16:15:37 完成)
- 括號**原本就有**`persona-lib.mjs` 的渲染(約 3804 行)本來就是 `名字(情緒)→ 對象:內容` - 括號**原本就有**`persona-lib.mjs` 的渲染(約 3804 行)本來就是 `名字(情緒)→ 對象:內容`
括號裡是 `room post --emotion` 的情緒標註。這一節是**在既有括號裡多一格**,不是換掉它。 括號裡是 `room post --emotion` 的情緒標註。這一節是**在既有括號裡多一格**,不是換掉它。
- [x] 格式:括號分兩格,**情緒在前、動作在後,用 `・` 分隔**。兩格都可省略,全省就不出現括號 - [x] 格式:括號分兩格,**情緒在前、動作在後,用 `・` 分隔**。兩格都可省略,全省就不出現括號
@@ -71,12 +71,13 @@ Q5Q10 六題已於 2026/08/03 由使用者拍板,設計不再需要確認
- [x] 頻率綁 Q7 的兩個動作額度,**括號裡的動作算其中一個**(否則會變成一輪三個動作) - [x] 頻率綁 Q7 的兩個動作額度,**括號裡的動作算其中一個**(否則會變成一輪三個動作)
—— 每輪指示補上「名字後面括號裡的動作**算在這個額度裡**——括號演一個、 —— 每輪指示補上「名字後面括號裡的動作**算在這個額度裡**——括號演一個、
句子裡再演兩個就是三個」(2026/08/03 16:06:10 完成) 句子裡再演兩個就是三個」(2026/08/03 16:06:10 完成)
- [ ] **記憶要記那個行為**(Q6 明示):短期與長期記憶加行為備註欄位,記「他做了什麼」而不是「他感到什麼」。 - [x] **記憶要記那個行為**(Q6 明示):短期與長期記憶加行為備註欄位,記「他做了什麼」而不是「他感到什麼」。
`persona-story` 的 1.12 同一個欄位,**不要各存一份**;`voice/reactions.md` 是同一批資料的落點 `persona-story` 的 1.12 同一個欄位,**不要各存一份**;`voice/reactions.md` 是同一批資料的落點
**已完成一半**`remember --behavior` `behavior` 欄位有了,寫入時跑 `actionLint()` —— `remember --behavior` 寫入短期記憶時,同一筆也用 `addVoiceReaction()`
> ⏭️ 待人工處理:`persona-story` 這個 skill 目前不在 `develop`(在 `feat/persona-story-import` 分支), `voice/reactions.md`(事件=記憶原文、反應=行為、情緒=最大正向 delta)。
> 所以「跟它 1.12 用同一個欄位」無法在這裡對齊;`voice/reactions.md` 全 repo 零引用 記憶留時間軸、語氣層供每輪注入,是同一批資料的兩個用途
> 兩件都要等那條分支併進來才能一次決定欄位,先做只會變成各存一份——正是這條要避免的事。 **只有人格自己的行為進語氣層**`role === "persona"`)——對方做了什麼是記憶,
不是他的反應方式(2026/08/03 16:15:37 完成)
- 驗收:`(喜悅・別過頭)` 過得了 lint、情緒標註沒被吃掉;`*別過頭*` 與句子裡的「我愣了一下」照舊被擋下; - 驗收:`(喜悅・別過頭)` 過得了 lint、情緒標註沒被吃掉;`*別過頭*` 與句子裡的「我愣了一下」照舊被擋下;
那一輪的記憶查得到「別過頭」這個行為 那一輪的記憶查得到「別過頭」這個行為
+13
View File
@@ -783,6 +783,19 @@ commands.remember = ({ flags }) => {
} }
pl.rememberShort(slug, entry); pl.rememberShort(slug, entry);
const kept = pl.pruneShortTerm(slug); const kept = pl.pruneShortTerm(slug);
// 行為備註與 `voice/reactions.md` 是**同一批資料**(事件 → 他做了什麼),不是各存一份:
// 記憶留時間軸(那一天發生過這件事),語氣層供每輪注入(他遇到這種事會怎麼反應)。
// 只有**人格自己的**行為才進語氣層——對方做了什麼是記憶,不是他的反應方式。
if (entry.behavior && entry.role === "persona") {
const [top] = Object.entries(entry.emotion_deltas)
.filter(([, d]) => Number(d) > 0)
.sort((a, b) => Number(b[1]) - Number(a[1]));
pl.addVoiceReaction(slug, {
event: text,
action: entry.behavior,
emotion: top ? pl.EMOTIONS[top[0]]?.zh || "" : "",
});
}
if (Object.keys(entry.emotion_deltas).length) { if (Object.keys(entry.emotion_deltas).length) {
const state = pl.updateEmotion(slug, (s) => pl.applyEmotion(s, entry.emotion_deltas, text.slice(0, 80), { slug })); const state = pl.updateEmotion(slug, (s) => pl.applyEmotion(s, entry.emotion_deltas, text.slice(0, 80), { slug }));
pl.appendJsonl(pl.journalPath(slug), { pl.appendJsonl(pl.journalPath(slug), {
+9
View File
@@ -1157,6 +1157,15 @@ check("行為備註寫情緒名稱會被擋", (() => {
"--text", "測試行為備註的界線", "--behavior", "覺得害羞"], { expectOk: false }); "--text", "測試行為備註的界線", "--behavior", "覺得害羞"], { expectOk: false });
return out.status !== 0 && String(out.stderr).includes("是情緒不是動作"); return out.status !== 0 && String(out.stderr).includes("是情緒不是動作");
})()); })());
check("行為備註同時進 voice/reactions.md(同一批資料,不是各存一份)", (() => {
const r = pl.loadVoice("alpha").reactions;
return r.some((x) => x.action === "把手縮回來" && String(x.event).includes("修得比上次穩"));
})(), JSON.stringify(pl.loadVoice("alpha").reactions.slice(-3)));
check("對方的行為不進語氣層(那是記憶,不是他的反應方式)", (() => {
cli(["remember", "--persona", "alpha", "--session", S_SPEAK, "--role", "user",
"--text", "他把門關上就走了", "--behavior", "把門關上", "--salience", "40"]);
return !pl.loadVoice("alpha").reactions.some((x) => x.action === "把門關上");
})(), JSON.stringify(pl.loadVoice("alpha").reactions.slice(-3)));
// 鬧彆扭的階梯:40 分一句帶過、60 分嘴硬三段式、75 分以上惱羞 // 鬧彆扭的階梯:40 分一句帶過、60 分嘴硬三段式、75 分以上惱羞
console.log("⑥-d 鬧彆扭的階梯與三段式"); console.log("⑥-d 鬧彆扭的階梯與三段式");