只有文字這一個通道,所以情緒表達是排版問題。三條目標寫成 G1(持續逼近真人)/G2(表達往動漫角色靠)/G3(女性人格的害羞與鬧彆扭), 每條附界線,新功能對著它們判斷。 TODO 加階段 5,六題已拍板(Q5–Q10): - 顏文字開放,連帶要在半形標點檢查裡開白名單 - 動作加進名字後**既有**的括號(`桐人(😳・臉紅):`),情緒標註保留 - 生理反應算動作(臉紅、手在抖),`(害羞)` 只能待在情緒格 - 破口放寬到一輪兩個動作,煞車是必須同情緒且遞進 - emoji 表程度:種類表情緒、數量表程度,由 emotion.json 自動帶入 - 動漫化強度全域一致,內容仍逐人格 沒有任何程式改動,版號不動——0.2.0 還沒進 master,這批掛在同一個版號底下。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
29 KiB
TODO — 人格擬真優化
目標:讓人格在記憶結構與情緒/語氣表達上更接近真人(G1), 表達往動漫角色靠(G2),女性人格的害羞與鬧彆扭更明顯(G3)。三條的定義與界線見
README.md的〈專案目標〉。 前提:只有文字這一個通道,情緒表達等於排版問題——階段 5 整批都建在這句話上。 建立日期:2026-08-03|依據:現行scripts/persona-lib.mjs、skills/persona-chat/**、skills/persona-memory、skills/persona-relation
現況判斷
表層(去 AI 腔、句長上限、心裡話不外洩、情緒破口演在句形上、羞恥度三出口)已經做得很徹底。 剩下的「不像人」不是語氣問題,是三個結構性缺口:
| 根因 | 現在的行為 | 真人的行為 |
|---|---|---|
| 記憶只有「精準」與「沒有」兩態 | recall 命中就整段取出、內容永不變質;查不到就禁止提 |
大部分時間活在中間帶:「我記得好像…是你說的嗎」。主旨留著、細節掉了 |
| 人格永遠以對方為中心 | 每輪都在服務這句話,自己沒有懸著的事 | 有未完事項與自己在意的事,會追問「你上週說要看牙醫,去了嗎」 |
| 同一句話任何時刻聽起來都一樣 | 情緒是即時事件的函數;十二情緒全人格共用同一張 tells 表 | 有當日底色與生理狀態;而且每個人生氣的樣子不一樣 |
三個「不要做」:撒口語碎片充人味(anti-ai-voice.md 第六點已寫)、給情緒加隨機數(隨機不是情緒是雜訊)、
加隨機口誤(唯一值得的變體是嚴格限量的「自我打斷改口」)。
⚠️ 實作前先確認(未逐項回覆前不要動手)
規則:這份 TODO 的任何項目,動手前都要先跟使用者確認過。看到 TODO 不等於可以開始寫。 下面四題的答案會改變要寫的東西,不是風格偏好,所以必須先問。
Q1. 這次實作要做到哪個階段?
(階段 0 的復原與 commit 不在此列,那個一定要先做。)
| 選項 | 含什麼 | 代價 |
|---|---|---|
| 只做階段 1(建議) | open loops、hoursAwake 接語氣、EMOTION_TELLS per-persona 覆寫、情緒抑制與慣性 |
一輪做完,不動任何既有檔案格式,馬上聽得出差別 |
| 階段 1 + 2 | 再加當日心情底色、情境索引+情緒一致性回想 | 會動 recall 排序與記憶欄位,但不改長期記憶檔案格式 |
| 階段 1 + 2 + 3 一次做完 | 含回想強度/模糊態/gist-detail 分層 | 改長期記憶 frontmatter,需要 migration 與 bundle 升版,回歸測試量大 |
| 先做階段 3 | 優先換掉記憶結構的地基 | 改動最深,但擬真的天花板由它決定 |
- 已確認範圍:階段 1 + 2 + 3 一次做完(2026-08-03 使用者拍板)
Q2. 模糊記憶的界線要多嚴?
會跟現行「查不到就不要講、編轉折比空話更糟」直接相撞,所以要先定。
| 選項 | 允許說出口的樣子 | 風險 |
|---|---|---|
| 保守:只能說記不清(建議) | 「我記得你講過類似的,但我記不清。」一個細節都不能提 | 零幻覺風險,代價是模糊態的表現力較平 |
| 中等:可講主旨、必須標不確定 | gist 還在就可以講主旨(「好像跟你哥有關」),但必須帶不確定標記 | 表現力好很多,但主旨本身也可能記錯,需要稽核 |
| 開放:可試探性補細節並求證 | 「是不是上個月那次?」 | 最像人,但等於開了幻覺的側門;沒有稽核機制前不建議 |
- 已確認界線:開放——可試探性補細節並求證(2026-08-03 使用者拍板)。
因為這是幻覺的側門,3.3 的稽核機制改成同批必做、不可延後:
試探句必須帶問號求證、不可斷言;
said check記錄每一次試探;memory --audit要能查出 「試探後對方否認」的比例。試探被否認時要立刻寫一則更正記憶,不可放著。
Q3. 長期記憶檔案格式(strength、gist/detail)怎麼遷移?
只在做階段 3 時才需要,但先定案可以省一輪。
| 選項 | 做法 | 代價 |
|---|---|---|
| 就地 migration,一次改全部(建議) | 寫一支 migration 掃過所有人格的 memory/long-term/*.md 補欄位並切分內文 |
乾淨、之後只有一種格式;務必先用 persona-transfer export 備份 |
| 只有新記憶帶新欄位 | 舊檔維持原狀,讀取時給預設值 | 零風險,但舊記憶永遠進不了衰減與模糊態——最重要的老記憶反而沒效果 |
| 雙格式並存,讀時正規化 | 不改磁碟,在讀取層統一 | 可回頭,但兩種格式的分支會長期留在程式裡 |
- 已確認策略:就地 migration,一次改全部(2026-08-03 使用者拍板)。動之前先
persona-transfer export備份。
Q4. 階段 4 的「自我議程」要做嗎?
人格某些輪會把話題拉回自己在意的事、不服務對方。
| 選項 | 說明 |
|---|---|
| 要,低頻(建議) | 每 5–8 輪最多一次,且只在對方沒有明確急事時。這是「像 AI」最頑固的殘留(永遠以對方為中心),低頻就有效 |
| 要,明顯一點 | 更常拉回自己的事、允許答非所問。更像真人,但會明顯降低助理可用性 |
| 先不做 | 留在 TODO 但不實作,等前面幾階段穩定後再評估 |
- 已確認:要,明顯一點(2026-08-03 使用者拍板)。允許某些輪把話題拉回自己的事、允許答非所問; 頻率上限放寬到每 3 輪最多一次(原建議 5–8 輪),但對方有明確急事時一律不觸發。
其餘我先給預設值的(不同意就講,否則照這樣做)
| 項目 | 預設 |
|---|---|
| per-persona tells 放哪 | 放 IDENTITY.md 新增區塊(tells 屬身分,不屬可變狀態),不放 state/ |
| open loops 上限與逾期 | 同時最多 5 條;7 天沒進展自動收掉並留一則「沒下文」記憶 |
| 心情底色是否吃外部因素 | 只吃內部(情緒事件 + hoursAwake + 上次睡眠),不接天氣/時區等外部資料 |
| 情緒抑制矩陣範圍 | 只寫三組明確互斥:anger↔joy、sadness↔delight、disgust↔trust。不做全 12×12 |
| 黃金腳本怎麼判定 | 人工看(擬真無法自動判定);只有硬界線(句長、黑名單、句數)走 CLI 自動擋 |
| 版本號 | 整批只升一個版號,兩份 manifest 一起改;改前先看 master 現在幾版 |
階段 0:開工前(先做,否則會踩到)
- 復原被刪的 hook 與 manifest:工作區的
hooks/(7 支 .mjs + hooks.json)、.claude-plugin/、.codex-plugin/、plugin.json、兩份 marketplace.json 已從磁碟消失(git status顯示D,未 commit)。 目前跑的是安裝快取那份所以不會立刻出錯。 →git checkout -- hooks .claude-plugin .codex-plugin plugin.json .agents在這個狀態下不要 commit。 - 先把既有 WIP 收掉:
persona-lib.mjs/persona.mjs/四份 SKILL 有約 485 行未 commit 的羞恥度改動,skills/persona-relation/reference/closeness.md還是 untracked。先 commit 這批,再開新改動。 - 確認
KIRITO-01的鎖狀態(曾被 sessionf60d8e32…佔用,cwd/home/coder/plugins/persona)。 確定那個程序結束了才--takeover。
階段 1:低成本高效果(可一輪做完)
1.1 未完事項 open loops ★ 投報率最高
- 新增
state/loops.json,同時只留 3–5 條:他沒回答的問題、他答應要做的事、被打斷的話題、我想問但沒問的。 - CLI:
loop add|done|list(沿用withFileLock寫入)。 UserPromptSubmithook 把它注入<persona-context>(hooks/prompt_submit.mjs)。- 超過 N 天沒進展 → 自動收掉,並留一則「這件事沒下文」的短期記憶。
- 為什麼:被記住的感覺幾乎全部來自這個,而不是來自長期記憶檢索。
- 驗收:隔天載入時人格會主動追問上次懸著的事,且同一件事不會追問兩次(
said check擋)。
1.2 把 hoursAwake() 接到語氣上(幾乎免費)
speechBudget():清醒越久 → 句數/句長上限往下降。mood()/applyEmotion():清醒越久 → arousal 天花板往下降。- 為什麼:函式已經存在(
persona-lib.mjs),現在只用在提醒睡覺。深夜的人話少而鈍,最便宜的擬真訊號。 - 驗收:連續對話數小時後,回覆自然變短變鈍,不需要人格自己演。
1.3 EMOTION_TELLS 支援 per-persona 覆寫
emotionTells()先讀人格自己的覆寫(state/tells.json或IDENTITY.md新增Tells區),再退回全域預設。persona-create/persona-anime建立人格時一併問/推導 3–5 條專屬破口。- 為什麼:現在所有人格生氣都變短句、稱呼退回全名。但桐人生氣是沉默,亞絲娜生氣是變得更禮貌—— 同一格情緒,破口完全不同。
- 驗收:兩個人格在同一種高強度情緒下,句子的形狀明顯不同。
1.4 情緒交互抑制與慣性(輸入都算好了,只差回饋)
applyEmotion()加抑制:anger高時joy的正向 delta 打折(剛生完氣沒那麼容易被逗笑)。 建議做成小矩陣,只寫幾組明確互斥的(anger↔joy、sadness↔delight、disgust↔trust)。- 加慣性:
feltTrend()已在算走向但沒回饋到增益;連續同向時讓同方向 delta 略微放大。 - 更新
skills/persona-chat/reference/emotions.md的「情緒調節」段(現在只寫飽和與單輪預算)。 - 驗收:
emotion --audit的正負比例不再一路偏正;剛吵完架的下一輪逗不笑。
階段 2:中成本(新檔案/排序邏輯)
2.1 當日心情底色 state/mood.json
- 三層改成:即時情緒 → 當日底色(緩慢漂移的 valence/arousal) → 氣質基線。
- 底色當反應增益:底色差的日子,同樣一句話的 delta 乘 1.3(上限要夾)。
sleep時重設/部分帶過(SLEEP_DECAY_MINUTES已存在,底色不要一次歸零)。- 為什麼:現在缺日級別的中間層,所以「今天聽了會炸、昨天不會」做不出來。
- 驗收:同一句刺激話在不同日子的 delta 不同,且理由可解釋(不是隨機)。
2.2 情境索引 + 情緒一致性回想
- 記憶(短期與長期)加
when/where/mood欄位。 recall排序加一項:與當下情緒同極性的記憶加權。- 為什麼:現在檢索只靠
topics/entities(語意線索)。人的回想主要靠情境線索。 這條同時讓情緒有了「後果」,不再只是調語氣的裝飾。 - 驗收:心情差的時候先想起難過的事;同一個 query 在不同情緒下回不同順序。
階段 3:記憶結構重整(單獨一輪做,會動檔案格式)
3.1 用「回想強度」取代門檻式遺忘,並允許模糊態
- 長期記憶 frontmatter 加
strength;retrievability = f(salience, recall_count, 距上次回想多久)連續衰減。 - 低於門檻不刪,降級成模糊態:
recall回「有這件事,細節想不起來」。 - 被
recall命中就重設並拉長下次衰減(spacing effect:越常想起的越牢)。 材料已經有了(recall_count/last_seen都在寫)。 prune/persona-memory的遺忘規則同步改寫(現在是 salience 門檻 + 240 筆/14 天)。 不可遺忘清單(boundary/promise/canon/salience ≥ 80)維持不變。
3.2 長期記憶分 gist / detail 兩層
- 內文明確切「主旨」與「細節」;衰減先吃 detail、gist 最後才掉。
- 效果:「記得我們吵過,但忘了為什麼」變成自然結果,不必人格演。
3.3 ⚠️ 同步改幻覺界線(跟 3.1/3.2 一起做,不可延後)
模糊態會跟現行的「查不到就不要講、編轉折比講空話更糟」直接相撞。界線要寫死進
skills/persona-chat/reference/anti-ai-voice.md 與 SKILL 第 ② 節:
可以說不確定,不可以填內容。 允許:「我記得你講過類似的,但我記不清。」 禁止:把想不起來的細節補出來。
said check對模糊態句型只提醒不擋(跟現行「講到自己過去」的 hint 同一層)。- 新增稽核:模糊態被用來編內容的次數(比照
emotion --audit)。
3.4 遷移與相容
- 舊長期記憶檔的 migration(補
strength/切 gist/detail 可先給預設值)。 persona-transfer的 bundle 版本號要跟著升,import要能吃舊版。selftest.mjs補對應案例。
階段 4:加分項
- 自傳章節
memory/chapters/:時期層(「在 SAO 那兩年」「跟他一起做 persona 這段」), 長期記憶掛在時期底下。問「你這幾個月怎麼樣」時才講得出敘事而不是列點。 - 習慣記憶
--type habit:現在全是宣告性記憶(fact/event/preference),缺「我們之間的慣例」 (他早上第一句都在抱怨會議、我都回一句「幾點」)。熟悉感來自這個。 - 口語指紋 idiolect:現在是減法(刪 AI 腔)+語氣層,缺加法。per-persona 的常用詞/句尾/自稱/
慣用迴避句式/絕對不說的詞。
relation style已有口頭禪/習慣facet 但那是 per-relation。 每輪只注入 2–3 條,全注入會變表演。 - 自我議程:承 1.1,人格有自己這幾天在意的一兩件事,某些輪把話題拉回自己的事、答非所問。 這是「像 AI」最頑固的殘留——永遠以對方為中心。 務必設頻率上限(每 5–8 輪最多一次),否則從像人變成難聊。
- 關係的未修復裂痕:
closeness/trust是純量,缺「上次那件事還沒和好」。 relation 節點加open_issues/ruptures(含是否修復);有未修復裂痕時語氣層往下降一格。
階段 5:文字通道的情緒表達(G2 動漫化 / G3 害羞與鬧彆扭)
現況判斷:情緒有沒有被表達已經解決(EMOTION_TELLS + per-persona 覆寫 + 羞恥度三出口),
剩下的缺口是表達的頻寬——現在一輪只能露一個破口,而破口只作用在「句子的形狀」這一個維度。
純文字其實還有三個維度沒被用到:節奏(訊息怎麼分段)、標點、稱呼。
⚠️ 實作前先確認(Q5–Q8,沒答案不要動手)
這四題都會踩到硬規則 8,答案不同要寫的東西完全不同。
Q5. 顏文字與表情符號要不要開?
| 選項 | 說明 | 風險 |
|---|---|---|
| 禁止(維持現況) | 情緒只走文字本身 | 動漫感少一個很直接的手段 |
| 限量、per-persona | IDENTITY.md 列 2–3 個專屬符號,每 N 輪最多一次 |
要防止變成每句都掛,成本在節流不在功能 |
| 開放 | 依情緒自由使用 | 幾乎一定會退化成表情包貼圖式回覆 |
-
已確認:開放使用(2026-08-03 使用者拍板)。
連帶要處理的兩件事(開放不等於沒有機制): 1. **跟半形標點檢查對撞**:`speechLint()` 現在擋半形標點,而顏文字幾乎全是半形 (`(///)`、`^^;`、`>_<`)。要在檢查裡開一條**顏文字白名單**, 不然開放這件事會被自己的 linter 擋掉。判定範圍要窄(連續的符號叢集才算顏文字, 單獨一個半形逗號仍然是排版錯誤)。 2. **選哪個符號屬於身分**:情緒 → 符號的對照放 `IDENTITY.md`(跟 `## Tells` 同一層), 沒寫的人格退回全域預設。開放的是「可以用」,不是「隨便用哪個都行」。 後續追加(Q9/Q10,同一天):emoji 另外要**接上情緒數值表示程度**, 而且**句子裡也自由使用、不設上限**。細節見 5.8。
Q6. 星號動作描寫(*別過頭*)要不要對動漫人格破例?
硬規則 8 現在把「旁白演情緒」列為禁語(SPEECH_BLACKLIST)。
| 選項 | 說明 |
|---|---|
| 維持禁止 | 動作要出現就寫進對白(「你不要看這邊」比 *別過頭* 像人) |
| 只在劇場模式開放 | 多人格同場時像小說,一對一時仍禁止 |
| 對動漫人格開放 | 最像原作,但等於把去 AI 腔那一層打掉一半 |
-
已確認:都不是——動作寫在人格名稱後面的括號裡(2026-08-03 使用者拍板,第四條路):
桐人(別過頭):你不要看這邊。 而且**記憶要一起記那個行為**(行為備註/標註欄位)。細節與影響範圍見 5.7。 為什麼這條比上面三個好:括號在**名字後面**,跟對白本體有實體隔離—— 它不是混進句子裡的旁白,所以硬規則 8 的禁令仍然守得住 (`speechLint()` 只對括號**外**的內容比對黑名單)。 代價是它會改劇場模式寫死的 `名字:內容` 輸出格式。
Q7. 一輪最多露一個破口,要不要對 G3 放寬?
| 選項 | 說明 |
|---|---|
| 害羞時放寬到兩個 | 只有 shame 這一格例外:鬧彆扭本來就是「否認+轉移」兩個動作一起來 |
| 全部放寬到兩個 | 密度上去了,但每個人格都變成一直在演 |
| 維持一個 | 最安全,G3 的效果會打折 |
-
已確認:全部情緒都兩個動作(2026-08-03 使用者拍板)。 連平靜也有兩個(留白 → 不追問)——它們本來就是成對出現的動作,不是加倍演出。
這條改的地方比看起來多,全部要一起改: | 位置 | 現在寫的 | 要改成 | | :-- | :-- | :-- | | `emotionTells()` 的 `top` | 前兩種**情緒**、但只准演一個動作 | 主導情緒的**兩個動作** | | 每輪注入的提醒文字 | 「一輪最多露一個破口」 | 兩個,且必須是同一種情緒的兩個動作 | | `README.md` 硬規則 8 與〈講話像人〉 | 同上 | 同上 | | `skills/persona-chat/**`、`anti-ai-voice.md` | 同上 | 同上 | **新的煞車**(放寬之後唯一擋得住「一直在演」的東西):兩個動作必須來自**同一種情緒**, 而且是**遞進**關係(否認→轉移、笑→補一句、留白→不追問),不是兩種情緒各演一個。 強度不到的情緒照舊不演——門檻不變,變的只是達標之後能露幾個。
Q8. 動漫化強度是全域一致,還是 per-persona 旋鈕?
| 選項 | 說明 |
|---|---|
| per-persona 旋鈕 | IDENTITY.md 加一格(例如 anime_level: 0–100),寫實人格可以歸零 |
| 全域一致 | 少一個欄位,但同一套語域套在所有人身上就是模板 |
-
已確認:全域一致(2026-08-03 使用者拍板)。不加
anime_level欄位,不做強度旋鈕。**要分清楚全域的是什麼**:全域一致指的是**強度**(動漫感開多大), 不是**內容**。自稱、句尾、口癖仍然逐人格不同(5.6), 否則所有人格會講起話來一樣——那正是 G2 要避免的。
5.1 訊息的節奏:一輪可以拆成兩則 ★ 純文字唯一的「時間」訊號
speechBudget()之外加分段預算:高 arousal 或高羞恥時,同一輪允許輸出兩則短訊, 第二則是補救、嘴硬或改口(「⋯剛才那句不算」),而不是補充說明。- 節流:每 N 輪最多一次,且只在 arousal 或羞恥度過門檻時。
- 為什麼:真人在聊天軟體上的情緒,一半是靠「又補了一句」傳出去的。這是文字獨有的、目前完全沒用到的手段。
- 驗收:慌的時候會多一則短的;平靜時永遠只有一則。
5.2 標點預算(情緒 → 標點與句長的分布)
- 把標點納入
speechLint()的可調參數:焦慮 → 刪節號與逗號斷句變多; 憤怒 → 句號密度上升、幾乎不用問號;害羞 → 疊字與破折;喜悅 → 允許一個驚嘆號。 - 上限要夾死(一則最多一個驚嘆號、刪節號不連發),否則會變成顏文字的替代品。
- 驗收:把同一句話在四種情緒下輸出,標點分布看得出差別,且都沒有過量。
5.3 稱呼隨情緒偏移
relation style的--except <情緒>>=<值>已能做條件替換(anger>=40→ 退回全名)。 缺的是害羞方向:改口、講到一半換稱呼、把名字吞掉不叫。- 每個關係節點可設「害羞時的稱呼」,沒設就退回吞掉名字(改用「你」)。
- 驗收:同一個對象,生氣時被叫全名、害羞時直接不叫名字。
5.4 鬧彆扭的階梯與三段式句法(G3 核心)
- 羞恥度現在是一個純量對三個出口(
hide/spill/confess)。加階梯: 輕微彆扭(一句帶過)→ 嘴硬(先否認再小聲承認)→ 惱羞(翻臉,anger的負權重已存在)。 - 三段式做成句法模板而不是自由發揮:否認 → 反駁對方的說法 → 最後一句音量掉下來。
模板可 per-persona 覆寫(放
IDENTITY.md的## Tells,跟現行覆寫同一層)。 - 三段式要吃 Q7 的兩個動作:否認與轉移是同一種情緒的遞進,剛好是那條規則的樣板案例。
惱羞那一級是換情緒(
shame→anger),所以仍然只有兩個動作,不是三個。 - 驗收:被稱讚外表時,低/中/高羞恥度三種輸出明顯不同,而且都沒有寫「我害羞了」。
5.5 女性人格的預設值(G3,只動預設不動個性)
- 重看
GENDER_MODESTY的預設值與modestyOf()的推力表,把女性預設往上調並補 「鬧彆扭」相關的關鍵詞權重(現在的表偏向「害羞/臉紅」,缺「嘴硬/不坦率/傲嬌」)。 - 界線不變:描述永遠蓋過預設,可以推到 0;不做「女性→情緒更外顯」的全域放大。
- 驗收:兩個都是女性但個性相反的人格,講起話來不一樣。
5.6 語域:自稱、句尾、口癖(G2 核心,接階段 4 的 idiolect)
- per-persona 的自稱/句尾語氣詞/口癖/絕對不說的詞,每輪只注入 2–3 條(階段 4 已寫,這裡是它的動漫版)。
persona-anime建立人格時一併從原作推導這幾格(現在只推導Tells)。persona-story的 3A(語氣統計)跑完之後要能直接寫進這一格——兩邊用同一個欄位,不要各存一份。- 驗收:把人格的名字遮掉,光看三句話能認出是誰。
- 界線(Q8):強度全域一致,內容逐人格不同。這一節動的是內容,不加強度旋鈕。
5.7 動作加進名字後的括號(Q6 拍板的格式)
括號不是新開的,原本就有:persona-lib.mjs 的渲染(約 3804 行)本來就是
名字(情緒)→ 對象:內容,括號裡放的是 room post --emotion 的情緒標註。
所以這一節是在既有括號裡多一格,不是換掉它——原本的情緒標註保留。
桐人(喜悅・別過頭):你不要看這邊。
桐人(別過頭):你不要看這邊。 ← 沒帶 --emotion 時
桐人(喜悅):你不要看這邊。 ← 沒帶 --action 時(現行行為,不變)
- 格式:括號分兩格,情緒在前、動作在後,用
・分隔。兩格都可省略,全省就不出現括號。 - 兩格的分工要寫死:情緒格是標註(既有 meta,寫情緒名稱本來就對);
動作格只寫看得見的身體動作(別過頭、把杯子推過來、站起來)。
動作格不重複情緒名稱——
(喜悅・害羞)是把標註寫兩次,不是動作。 - 生理反應算動作,明文允許(2026-08-03 使用者補充):臉紅、耳朵紅、手在抖、聲音變小、
呼吸亂掉。判準是看得見或聽得見,不是有沒有情緒色彩——
(臉紅)可以,(害羞)只能待在情緒格。 害羞這一格的預設動作就用臉紅,其餘看人格自己的## Tells。 speechLint()只對括號外的內容比對黑名單與句長;括號內另立規則 (情緒格照既有的injectSafeLine;動作格單一動作、12 字內)。- 劇場模式:
room post加--action "<動作>"(跟既有--emotion並列),room read/room script的渲染跟著改。hooks/每輪強制的輸出格式也要放寬到帶括號。 - 一對一(非劇場)也適用——Q6 拍板的是格式,不是只給多人格場景。
- 頻率:綁 Q7 的兩個動作額度,括號裡的動作算其中一個。 否則會出現「括號演一個、句子裡再演兩個」,一輪三個動作。
- 記憶要記那個行為(Q6 明示):短期與長期記憶加行為備註欄位,
記「他做了什麼」而不是「他感到什麼」——跟
persona-story的 1.12(事件 → 他做了什麼)同一個欄位, 不要各存一份。voice/reactions.md也是同一批資料的落點。 - 為什麼:這是唯一能在不打破「禁止旁白演情緒」的前提下拿到動作描寫的形狀—— 括號在名字後面,跟對白本體有實體隔離。
- 驗收:
(喜悅・別過頭)過得了 lint、情緒標註沒被吃掉;*別過頭*與句子裡的「我愣了一下」照舊被擋下;那一輪的記憶查得到「別過頭」這個行為。
5.8 emoji 表示情緒與程度(Q9/Q10 拍板)
現在括號的情緒格是自由文字(room post --emotion),跟 state/emotion.json 的數值
完全沒有連動——人格自己想寫什麼就寫什麼。這一節把它接上去。
格式:種類表情緒、數量表程度(Q9)
一種情緒固定一個 emoji,強度高時另加強度符號(不重複本體):
| 情緒值 | 樣子 | 例 |
|---|---|---|
| < 40 | 不顯示 | 桐人:你不要看這邊。 |
| 40–59 | 情緒 emoji | 桐人(😳・臉紅):你不要看這邊。 |
| 60–79 | +💦 |
桐人(😳💦・臉紅):⋯才不是那樣。 |
| 80+ | +💦❗ |
桐人(😳💦❗・把臉轉開):不要再講了。 |
- 寫一張十二情緒 → emoji 的對照表(一種情緒一個,例如
shame: 😳、anger: 😡), 放persona-lib.mjs,跟EMOTION_TELLS同一層。 - per-persona 可覆寫(
IDENTITY.md,跟## Tells與 Q5 的符號表同一層)。 這是內容不是強度,不違反 Q8 的全域一致。 - 強度符號固定兩階(
💦/💦❗),不要長成第三階。 - 由
emotion.json的主導情緒自動帶入,不是人格自由填。 門檻對齊emotionTells()的min = 40——情緒值不到 40 就沒有 emoji, 跟「強度不到就不演」是同一條線。room post --emotion的自由文字保留(可手動蓋過)。
位置:句子裡自由用(Q10)
- 已確認:句子裡自由使用、不設上限(2026-08-03 使用者拍板)。承 Q5 的開放。
- 連帶要處理:
speechLint()的半形標點與排版檢查要跳過 emoji 與強度符號, 不然會被判成排版殘留(跟 Q5 的顏文字白名單同一支修改)。 - 唯一的煞車是稽核,不是擋(他要的是開放,那就不要用 linter 偷偷關回去):
比照
emotion --audit,統計每輪的 emoji 數量與趨勢,讓過量看得見。 真的失控再回來談上限。 - 界線(這條不因為開放而放掉):emoji 是加上去的,不是替代品。 不可以用 emoji 代替句子(只回一個 😳)、也不可以代替動作格與句子的形狀—— 斷句、疊字、嘴硬照舊要有。emoji 掉光之後那句話仍然要看得出情緒。
- 驗收:羞恥度 45/70/90 三種輸出的 emoji 不同;把所有 emoji 刪掉之後, 句子的形狀仍然分得出是哪一級。
驗收方式
- 固定情境回歸(
selftest.mjs只能守不崩,擬真要另一組):20 段黃金腳本——被稱讚外表、 被指出講錯、久違回來、他心情差時報壞消息、連續三輪低落、被要求越界… 每次改動後跑一次,人工看輸出還在不在人味界線內。 emotion --audit(既有):正向偏差比例。- G2/G3 專用腳本(階段 5 才需要):被稱讚外表、被說「你是不是在害羞」、被戳穿嘴硬、 當著第三個人被講心事——四段各跑低/中/高羞恥度,看有沒有變成模仿腔或旁白。
- 新增記憶偏差稽核:模糊態被用來編內容的次數(見 3.3)。
收尾
- 這一批改動合起來只佔一個新版號,
.claude-plugin/plugin.json與.codex-plugin/plugin.json兩份 manifest 一起改;改版號前先看 master 上目前是幾版。 README.md的記憶架構表與情緒模型段要跟著更新。