feat(自傳章節): memory/chapters/ 補上長期記憶與心智圖之間的時期層
長期記憶是一則一件事,心智圖是抽掉時間的語意結構。中間缺的是「那段日子」—— 人講自己的過去是按段講的(「在 SAO 那兩年」),不是按事件清單、也不是按概念圖。 一段一檔,chapter add|list|show|close。to 空著代表還在這一段裡,所以沒有值就 不寫那一行(全專案一致:沒有值不留空欄位)。全部收掉時 currentChapter 回 null ——那是「還沒開始新的一段」,不是退回上一段。 長期記憶的 front matter 多一格 chapter。consolidate --chapter 可以指定,省略就 掛在當下那一段:記憶寫下來的時候人就在某一段裡,事後要重建歸屬幾乎不可能。 (那個 --chapter 是人生的段,不是 novel skip --chapter 的書的章節,註解裡有寫。) chapterBrief() 每輪注入現在這一段,並講明它是時期不是事件——它解釋這陣子為什麼 在意這些事,不是要他講起這一段。 memory/chapters/ 加進 Gitea 的 Wiki 區:一段日子開一次收一次,比長期記憶更低頻。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+74
-1
@@ -1056,6 +1056,9 @@ commands.consolidate = ({ flags }) => {
|
||||
mood: str(flags.mood),
|
||||
rules: str(flags.rules),
|
||||
source: str(flags.source),
|
||||
// 自傳章節(`memory/chapters/`)的段名,**不是** `novel skip --chapter` 那個書的章節。
|
||||
// 省略就用當下進行中的那一段(見 writeLongTermMemory)。
|
||||
chapter: str(flags.chapter),
|
||||
});
|
||||
const total = pl.rebuildIndex(slug);
|
||||
// 來源短期記憶標成判斷過:不標的話這幾筆下一輪又會被算成固化候選。
|
||||
@@ -1223,6 +1226,71 @@ commands.probe = ({ flags, positional }) => {
|
||||
die("用法:`probe add|confirm|deny|audit`。");
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------- //
|
||||
// chapter:自傳章節(`memory/chapters/`)——長期記憶與心智圖之間的時期層
|
||||
//
|
||||
// 人講自己的過去是按段講的(「在 SAO 那兩年」),不是按事件清單、也不是按概念圖。
|
||||
// --------------------------------------------------------------------------- //
|
||||
|
||||
commands.chapter = ({ flags, positional }) => {
|
||||
const session = requireSession(flags);
|
||||
const slug = hostOf(flags, session);
|
||||
const action = (positional[0] || "list").toLowerCase();
|
||||
if (action === "list") {
|
||||
requireMember(slug, session, Boolean(flags["as-guest"]));
|
||||
const rows = pl.loadChapters(slug);
|
||||
const now = pl.currentChapter(slug);
|
||||
emit({ persona: slug, chapters: rows, current: now?.name || null }, flags.json, [
|
||||
`\`${slug}\` 的自傳章節(${rows.length} 段${now ? `,現在在「${now.title}」` : ",目前沒有進行中的段"}):`,
|
||||
...rows.map((c) => ` - ${c.title}|${c.from} → ${c.to || "現在"}` +
|
||||
`|記憶 ${pl.chapterMemories(slug, c.name).length} 則${c.open ? "|**進行中**" : ""}`),
|
||||
...(rows.length ? [] : [" (還沒有。用 `chapter add --name <段名> --body <這段是什麼>` 開一段)"]),
|
||||
]);
|
||||
return;
|
||||
}
|
||||
if (action === "show") {
|
||||
requireMember(slug, session, Boolean(flags["as-guest"]));
|
||||
const name = str(flags.name) || positional[1];
|
||||
if (!name) die("`chapter show` 需要 `--name`。");
|
||||
const chapter = pl.loadChapters(slug).find((c) => c.name === pl.slugify(name));
|
||||
if (!chapter) die(`找不到章節 \`${name}\`(用 \`chapter list\` 看有哪些)。`);
|
||||
const mems = pl.chapterMemories(slug, chapter.name);
|
||||
emit({ chapter, memories: mems.map((m) => m._name) }, flags.json, [
|
||||
`**${chapter.title}**(${chapter.from} → ${chapter.to || "現在"})`,
|
||||
chapter.gist || "(這一段還沒寫說明)",
|
||||
`這一段裡的長期記憶 ${mems.length} 則:`,
|
||||
...mems.map((m) => ` - ${m.title || m._name}(${m.type})`),
|
||||
]);
|
||||
return;
|
||||
}
|
||||
requireOwner(slug, session);
|
||||
if (action === "add") {
|
||||
const name = str(flags.name);
|
||||
if (!name) die("`chapter add` 需要 `--name`(例如「在 SAO 那兩年」)。");
|
||||
const res = pl.writeChapter(slug, {
|
||||
name,
|
||||
title: str(flags.title) || name,
|
||||
from: str(flags.from),
|
||||
to: str(flags.to),
|
||||
body: str(flags.body),
|
||||
});
|
||||
if (!res) die("`--name` 取不出可用的段名(全是符號?)。");
|
||||
ok(`章節「${str(flags.title) || name}」寫好了:${res.file}`);
|
||||
pushWikiLater(slug, session, flags); // memory/chapters/ 屬於 Wiki 區(低頻)
|
||||
return;
|
||||
}
|
||||
if (action === "close") {
|
||||
const name = str(flags.name) || positional[1];
|
||||
if (!name) die("`chapter close` 需要 `--name`。");
|
||||
const res = pl.closeChapter(slug, name, str(flags.at) || undefined);
|
||||
if (!res) die(`找不到章節 \`${name}\`。`);
|
||||
ok(`「${name}」這一段收掉了。開新的一段用 \`chapter add\`。`);
|
||||
pushWikiLater(slug, session, flags);
|
||||
return;
|
||||
}
|
||||
die("用法:`chapter add|list|show|close`。");
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------- //
|
||||
// voice:語氣樣本與情緒反應(`voice/`)
|
||||
//
|
||||
@@ -3102,11 +3170,16 @@ const HELP = `persona.mjs — jsc-persona 人格 / 記憶 / 情緒 / 關係圖 C
|
||||
loop add|done|drop|touch|sweep|list --session <id> [--text --kind question|promise|topic|mine --id --note]
|
||||
懸著的事(同時最多 5 條):他沒回答的問題/他答應要做的事/被打斷的話題/我想問但沒問的。
|
||||
7 天沒進展自動收掉並留一則「沒下文」。mine 那種同時是自我議程的來源。
|
||||
voice add|list|show --session <id> --kind sample|reaction
|
||||
voice add|list|show --session <id> --kind sample|reaction|idiolect
|
||||
[--text --to --scene] sample:他自己講過的原句(照抄不改寫)
|
||||
[--event --action --emotion] reaction:事件 → 他做了什麼(不記「他感覺到什麼」)
|
||||
[--facet 自稱|句尾|口癖|不說 --value] idiolect:語域(把名字遮掉還認得出是誰的那幾格)
|
||||
show 看這一輪會注入什麼(每輪最多 3 條——全注入會變成照抄舊台詞)。
|
||||
寫在 voice/ 這一層:匯入流程可以直接寫,個性(SOUL.md)只有你能改。
|
||||
chapter add|list|show|close --session <id> [--name --title --from --to --at --body]
|
||||
自傳章節(memory/chapters/):長期記憶與心智圖之間的**時期層**——
|
||||
「在 SAO 那兩年」。to 空著=還在這一段裡,close 才寫上結束日期。
|
||||
consolidate 的 --chapter 把一則記憶掛到某一段(省略就掛在當下那一段)。
|
||||
probe add|confirm|deny|audit --session <id> [--text --memory --note --id --limit]
|
||||
模糊記憶的試探紀錄:可以說不確定、可以問,**不可以斷言**(add 會擋掉沒問號的句子)。
|
||||
audit 看「試探幾次、被否認幾次」——這是開放這條界線唯一的煞車。
|
||||
|
||||
Reference in New Issue
Block a user