From 7b20dba6dbd4afde2f4fed75626d6e159b874cab Mon Sep 17 00:00:00 2001 From: Jeffery Date: Mon, 3 Aug 2026 03:17:29 +0000 Subject: [PATCH] =?UTF-8?q?docs(skills):=20=E8=A6=8F=E5=89=87=E8=B7=9F?= =?UTF-8?q?=E4=B8=8A=E9=97=9C=E4=BF=82=E5=9C=96=E5=B0=8D=E6=8E=A5=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=A6=AA=E5=AF=86=E5=BA=A6=E5=88=A4=E6=96=B7?= =?UTF-8?q?=E5=8F=83=E8=80=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit persona-chat:人名要對得上關係圖(--entities/--about);新人物當場進關係圖 改成硬規則,但屬於第 ⑥ 步記憶回寫,不佔第 ⑤ 步的回話句數,也不要宣告。 persona-relation:補「記憶怎麼指回節點」與 relation doctor 的四類報告 (同名歧義、解析不到的 id、孤兒節點、對不上的人名),並說明壞檔會以非零 exit 結束而不是裝成空圖。 新增 reference/closeness.md:初次建節點時 bond/closeness/trust 怎麼從 對話判斷——一輪之內查完就填,不要憑感覺,也不要為了安全全部填 15。 Co-Authored-By: Claude Opus 5 (1M context) --- skills/persona-chat/SKILL.md | 40 ++++- skills/persona-chat/reference/semantic.md | 9 +- skills/persona-memory/SKILL.md | 9 +- skills/persona-relation/SKILL.md | 67 +++++++- .../persona-relation/reference/closeness.md | 144 ++++++++++++++++++ 5 files changed, 264 insertions(+), 5 deletions(-) create mode 100644 skills/persona-relation/reference/closeness.md diff --git a/skills/persona-chat/SKILL.md b/skills/persona-chat/SKILL.md index 19a1fb6..b2791c9 100644 --- a/skills/persona-chat/SKILL.md +++ b/skills/persona-chat/SKILL.md @@ -246,13 +246,49 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" remember \ 顯著度基準:**80+** 承諾/秘密/重大事件;**60–79** 偏好、明確情緒事件; **40–59** 一般脈絡;**<40** 閒聊(會很快被淘汰)。 -若這輪出現新的人/新的關係變化 → 順手更新人際關係圖: +**人名要對得上**:`--entities`(短期)與 `--about`(長期)寫的人名, +必須跟關係圖節點的 `name` 或 `id` **一字不差**——解析只認完全相等, +子字串與簡稱都不算(今天寫「小林」明天寫「林先生」,後者解析不到任何節點), +同名撞到多個節點時視為歧義、直接不寫 id。 + +對不上**不會報錯**,只是那筆記憶少一個 `entity_ids`/`about_ids`: +R5(同一個人 ≥ 2 筆)不會觸發,`` 也不會附上那個人的節點摘要。 +先看 `` 的「人際關係:」那段照抄節點名;事後要查用 +`relation doctor`(見 `/jsc-persona:persona-relation`)。 + +#### 新人物一定要當場進關係圖(硬規則) + +**觸發條件(兩個都成立才做)**: + +1. 這輪出現的人物**不在** `` 的「人際關係:」那段裡;**且** +2. **人格認識這個人**——設定(`IDENTITY.md`/`SOUL.md`/`canon` 記憶)裡有他, + 或這輪對話已經講清楚他是誰(誰的什麼人、做什麼的)。 + +只是被提到一個陌生名字、人格根本不知道那是誰 → **不要建節點**, +寫進短期記憶的 `--entities` 就好;等他再出現、講清楚了再建。 + +**動作**:當場建節點,`bond`/`closeness`/`trust` 依 `reference/closeness.md` 判斷 +(那份表是**初次建節點**用的,一輪內查完就填,不要填保守初值): ```bash node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" relation node \ - --persona --session --name "小林" --kind human --closeness 25 --trust 30 --note "使用者的同事" + --persona --session --name "小林" --kind human \ + --bond ally --closeness 45 --trust 35 --note "使用者的同事,Q3 專案 PM;依據:叫全名+直接請求" ``` +- `--bond` **不可省略**:語氣層是 `bond` × `closeness` 算的,省略會被猜成生人,整輪距離感就歪了。 +- 節點的 `name` 要跟這輪 `--entities` 寫的人名**完全一樣**(差一個字就解析不到)。 +- `name` 用**會被說出口的完整稱呼**(「小林」「結城明日奈」),不要用「明」「先生」這種 + 單字或稱謂當節點名——那種名字誰都套得上,不相干的句子會被算到同一個人頭上。 +- 其他人格用 `--kind persona --id <他的 slug>`。 + +**不要宣告這件事。** 這屬於第 ⑥ 步(記憶回寫),不佔第 ⑤ 步的 1–3 句, +也不要在回覆裡講「我把某某加進關係圖了」——那是系統動作,不是人會說的話。 +使用者主動問起才說。 + +關係發生**質變**(同事變朋友、決裂、信任被打破)→ 除了更新節點, +同時固化一則 `relationship` 長期記憶(見 `/jsc-persona:persona-memory`)。 + 若形成一條需要追蹤的推理鏈(未證實的猜測、待驗證的假設)→ 開思維導圖,別寫進長期記憶: ```bash diff --git a/skills/persona-chat/reference/semantic.md b/skills/persona-chat/reference/semantic.md index 0f53be7..4d51686 100644 --- a/skills/persona-chat/reference/semantic.md +++ b/skills/persona-chat/reference/semantic.md @@ -17,7 +17,14 @@ ## 3. 實體 entities -人/專案/地點/時間。人名一律同步到人際關係圖(`persona.mjs relation node`)。 +人/專案/地點/時間。人名要寫成關係節點的 `name` 或 `id`,且**一字不差**: +解析只接受完全相等,簡稱與加稱謂(「林先生」對「小林」)解析不到、也不會報錯, +同名撞到多個節點時算歧義、直接不寫 `entity_ids`。寫之前先照抄 `` 的節點名。 + +**認識的人**才同步到人際關係圖(`persona.mjs relation node`,親密度查 +`persona-relation/reference/closeness.md`);只是被提到、你根本不知道那是誰的名字, +留在 `entities` 就好,不要建節點。 +建節點時 `name` 用會被說出口的完整稱呼,不要用單字或稱謂(「明」「先生」)當節點名。 ## 4. 情感極性與強度 diff --git a/skills/persona-memory/SKILL.md b/skills/persona-memory/SKILL.md index 1098f64..f9b4405 100644 --- a/skills/persona-memory/SKILL.md +++ b/skills/persona-memory/SKILL.md @@ -36,7 +36,7 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" candidates --session ` 不附節點摘要、R5 不觸發。 + 用 `relation doctor` 查——對不上的人名會出現在「長期記憶 `about` 對不到節點」那段, + **不是**孤兒那段(孤兒 `unmentioned_nodes` 反過來,是有節點卻沒有任何記憶提到)。 - `--rules` 記下是哪條條件把它送上來的(之後回頭檢討記憶品質很有用)。 - `--forget 40` 可在固化後順手淘汰顯著度 < 40 的短期記憶(R6 容量壓力時特別有用)。 - 內文請寫「依據」與「還不確定」,讓下次的自己知道這則有多可靠。 diff --git a/skills/persona-relation/SKILL.md b/skills/persona-relation/SKILL.md index f02a4ec..0f43f8b 100644 --- a/skills/persona-relation/SKILL.md +++ b/skills/persona-relation/SKILL.md @@ -21,6 +21,28 @@ description: 維護人格的人際關係圖:新增或更新人物/人格/群 - 人格自己是 `self`,不必建節點。其他人格用 `--kind persona`、`--id <他的 slug>`。 - `kind` 是「這是什麼東西」,`bond` 是「跟我什麼關係」——**語氣只能靠後者分**。 +### 記憶怎麼指回節點 + +記憶那一側寫的是**人名字串**,節點 id 由 CLI 在寫入時自動解析並存進對應欄位: + +| 記憶 | 人名欄位(你寫的) | id 欄位(CLI 自動解析) | +| --- | --- | --- | +| 長期記憶 | `about` | `about_ids` | +| 短期記憶 | `entities` | `entity_ids` | + +解析規則是**完全相等**:你寫的字串要跟某個節點的 `id` 或 `name` **一字不差**才算命中。 +子字串、簡稱、加稱謂都不算(節點叫「小林」,寫「林先生」「小林哥」一律對不到); +**同名有多個候選時視為歧義,直接不寫 id**,不會替你挑一個。 + +對不上**不會報錯**,只會安靜地少一個 id,後果是: +`` 不附那個人的節點摘要、R5(同一個 entity ≥ 2 筆)不會觸發。 +要查只能跑 `relation doctor`——它會把這種人名列在「對不到節點」的那兩段, +**不是**孤兒那段(孤兒 `unmentioned_nodes` 是相反的情況:有節點、卻沒有任何記憶提到他)。 + +命名實務:節點的 `name` 用**會被說出口的完整稱呼**(「小林」「結城明日奈」), +不要用「明」「先生」這種單字或稱謂當節點名——那種名字誰都套得上, +不同的人會被寫成同一個字串、對到同一個節點。 + ## bond 與語氣層(最容易漏的一步) `bond` × `closeness` 查表算出**語氣層**,那是距離感;情緒只負責溫度與句長,不會蓋過它。 @@ -42,6 +64,22 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" relation node \ > > 自我檢查:這句話換成對一個「禮貌層」的人說也毫無違和 → 就代表你沒進到那一層。 +### 初次建節點:親密度從對話判斷(`reference/closeness.md`) + +新節點的 `bond`/`closeness`/`trust` **不給保守初值**,從對話裡的**稱呼與語氣**判斷。 +查表流程在 `reference/closeness.md`(關係詞 → 稱呼 → 語氣三軸,附裁決順序與數值帶)。 + +什麼時候查它: + +| 情境 | 查不查 | +| --- | --- | +| 這輪出現關係圖裡還沒有的人,要當場建節點 | **查**(persona-chat 第 ⑥ 步的硬規則) | +| 補建一個以前漏掉的人(`relation doctor` 撈出來、而且確認人格認識他) | **查**,用他歷來記憶裡的稱呼與語氣當依據 | +| 節點已經存在,這輪有互動 | **不查**,用下面「調整幅度(單次)」累積 | +| 使用者直接說「他跟你比較不熟」之類的指定 | **不查**,照他說的填 | + +已存在的節點每輪重算會讓語氣忽遠忽近——那張表只給第一次。 + ### 個人化的稱呼規則(`style`) 他本人要求過的講法優先於查表——查表算距離,`style` 記「他要你怎麼叫他」: @@ -85,6 +123,31 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" relation edge \ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" relation render --session ``` +### 健檢:`relation doctor`(唯讀) + +```bash +node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" relation doctor --session +``` + +只讀不寫,分**三段**列出(`--json` 可取結構化輸出): + +| 段 | 它報什麼 | 意思 | 怎麼處理 | +| --- | --- | --- | --- | +| 1 | 長期記憶 `about` 對不到節點的人名 | 記憶那側寫了人名,找不到 `id`/`name` 完全相等的節點 | 人格認識他 → 補建節點(查 `reference/closeness.md`);只是被提到、不知道是誰 → 不用管;名字寫錯 → 改成節點的正式寫法 | +| 2 | 短期記憶 `entities` 對不到節點的人名 | 同上,來源是短期記憶 | 同上。這一段最常見的是簡稱/加稱謂(「林先生」對不到「小林」) | +| 3 | 關係圖裡有節點、但沒有任何記憶提到(`--json` 欄位 `unmentioned_nodes`) | 建了節點卻從沒被記憶引用 | 先核對 `name`/`id` 跟記憶那側的寫法是否一致(多半是這個);真的久沒互動就照衰減調 `closeness` | + +第 1、2 段與第 3 段是**相反**的兩件事,不要混著看:前者是「記憶指不到節點」,後者才是孤兒節點。 + +另外會一併報: + +- **同名歧義**:有多個節點的 `name`/`id` 撞同一個字串 → 那個名字永遠解析不出 id,改掉其中一個節點的 `name`(加姓、加辨識詞)。 +- **解析不到節點的 `about_ids`/`entity_ids`**:id 欄位裡留著已被刪除或改名的節點 id → 更新那則記憶,或把節點補回來。 +- `graph.json` **解析失敗**時會明講是壞檔並以**非零 exit** 結束,不會裝成空圖。 + 所以 doctor 非零離開 = 檔案有問題,先修檔再說;「什麼都沒報」才是真的乾淨。 + +整理記憶(`/jsc-persona:persona-memory`)或睡眠收尾前跑一次,比等問題浮出來便宜。 + ## 調整幅度(單次) | 事件 | closeness | trust | @@ -100,7 +163,9 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" relation render --session ⚠️ `bond` 填錯比 `closeness` 填錯嚴重得多:語氣層是 `bond` × `closeness` 查表算的, +> `bond` 一歪,整輪的距離感就歪(至親掉進「禮貌」層,講話像對戰友報告)。 +> 數字可以之後慢慢修,`bond` 要一次填對。 + +--- + +## 0. 先確認一件事:這是「誰的」關係 + +`bond` 的主語永遠是**人格自己**(`self`),不是說話的人。 + +| 對話裡出現 | 節點的 `bond` | 為什麼 | +| --- | --- | --- | +| 使用者說「我老婆美咲」 | **不是** `partner` | 那是使用者的伴侶。對人格來說多半是 `stranger`/`friend` | +| 人格設定裡「我的妻子美咲」 | `partner` | 主語是人格自己 | + +第三人的關係要記在**連線**上,不是節點上: +`relation edge --from user --to misaki --label "夫妻" --affinity 95`。 +節點的 `closeness` 只回答「**我**跟他多近」。 + +## 1. 三軸訊號與裁決順序 + +同一輪讀到互相矛盾的訊號時,**上面的贏下面的**: + +1. **關係詞**(句子直接定位關係)→ 決定 `bond` 與距離帶,最強 +2. **稱呼**(怎麼叫他)→ 沒有關係詞時用它定距離帶 +3. **語氣**(怎麼對他講話)→ 只在帶內微調 ±5~10,**不跨帶** + +同一軸有多個訊號 → 取**最近一次**出現的那個(人會改口,最新的才是現況)。 + +## 2. 關係詞(最強訊號) + +| 句子裡的詞 | `bond` | 距離帶 | +| --- | --- | --- | +| 我老婆/我先生/我伴侶/我男(女)朋友 | `partner` | 家人帶 | +| 我兒子/我女兒/我孩子 | `child` | 家人帶 | +| 我爸/我媽/我父親/我母親 | `parent` | 家人帶 | +| 我哥/我姐/我弟/我妹/我兄弟(有血緣) | `sibling` | 家人帶 | +| 我朋友/我兄弟(沒血緣)/我死黨 | `friend` | 朋友帶(說「最好的朋友」「認識十年」→ 摯友帶) | +| 我同事/同一組的/我下屬 | `ally` | 朋友帶 | +| 我主管/我老闆/我隊長 | `ally`(敬重且從他身上學東西 → `mentor`) | 朋友帶偏低 | +| 我老師/我師父/帶我的人 | `mentor` | 認識帶~摯友帶(看有沒有並肩過) | +| 我對手/我競爭對手/死對頭 | `rival` | **看有沒有交手**:只是敵人 → 認識帶;長期互相認可 → 摯友帶 | +| 他朋友/他們那邊的人/某某的同事 | `stranger` | 生人帶(那是別人的關係,不是我的) | + +`rival` 不等於疏遠——長年互相認定的對手可以 `closeness 85`。 +恨與親近是兩件事,那筆恨要寫在 `note` 與 `trust`,不要用 `closeness` 表達。 + +## 3. 稱呼軸(沒有關係詞時用這個定帶) + +| 怎麼叫他 | 例 | 距離帶 | +| --- | --- | --- | +| 綽號/暱稱/疊字/略稱 | 阿明、小結、絅(單字暱稱) | 摯友帶~家人帶 | +| 直呼名字(去姓、不加敬語) | 明日奈、俊彥 | 朋友帶~摯友帶 | +| 全名 | 結城明日奈 | 認識帶(正式,但已經知道他是誰) | +| 姓+敬語 | 結城先生、林小姐、桐谷桑 | 認識帶(禮貌距離) | +| 頭銜職稱 | 老師、社長、隊長 | 認識帶~朋友帶。**歧義**:職稱在並肩久了的關係裡也會留著(叫「隊長」的戰友可以很親)→ 交給語氣軸裁決 | +| 第三人稱代稱、不指名 | 那個人、他們那邊的人、某某的朋友 | 生人帶 | + +同一個人被用兩種稱呼(正式場合叫全名、私下叫暱稱)→ 取**私下那個**,那才是真距離。 + +## 4. 語氣軸(帶內微調,最多 ±10) + +| 語氣 | 例 | 調整 | +| --- | --- | --- | +| 命令、指派 | 「這個你去處理」 | +5~+10(**歧義**:也可能只是上下關係。搭配敬語就是階級不是親近 → 不加) | +| 直接請求(沒鋪陳、沒道歉) | 「幫我看一下」 | +5 | +| 玩笑、吐槽、當面抱怨對方 | 「你又遲到」 | +10(能開玩笑是最可靠的親近訊號之一) | +| 客套、鋪陳、過度致謝 | 「不好意思麻煩您」 | −5~−10 | +| 迴避、轉移話題、只給最短回答 | 「就那樣」「沒什麼」 | −10,且 `trust` 再往下壓 5 | + +## 5. 距離帶 → 數值 + +| 距離帶 | 判斷依據 | `closeness` | 常見 `bond` | +| --- | --- | --- | --- | +| **生人帶** | 知道他是誰(誰的什麼人),但跟人格沒有互動描述 | 10–25 | `stranger` | +| **認識帶** | 認識但不熟,有禮貌距離 | 25–40 | `stranger`/`ally` | +| **朋友帶** | 朋友、同事,會一起做事 | 45–65 | `friend`/`ally` | +| **摯友帶** | 摯友、長期並肩、共同經歷 | 75–90 | `friend`/`mentor`/`rival` | +| **家人帶** | 家人、伴侶、子女 | 85–97 | `partner`/`child`/`parent`/`sibling` | + +帶內取值:訊號只有一個 → 取**下緣**;三軸互相印證 → 往上緣走。 +`100` 留白不要用,關係還有成長空間。 + +## 6. `trust` 怎麼填 + +**預設 `trust` = `closeness` − 10**(範圍 −5~−15,訊號少就扣多一點)。 + +理由要記住:**親近不等於信得過。** 天天見面的同事、吵得很熟的家人, +都可能是「很熟但不會把重要的事交給他」。兩個數字獨立,不要圖方便填一樣。 + +例外 —— 對話裡出現**明確託付**,才把 `trust` 拉到跟 `closeness` 齊平或 +5: + +- 交代事情(「這件事交給你」「你幫我盯著」) +- 講秘密、講還沒對別人講的事 +- 把決定權交出去(「你決定就好」) + +反向訊號 → 再往下壓:講過話不算、有隱瞞、對他的說法要再查一次 → `trust` 比 `closeness` 低 25 以上, +並在 `note` 寫下是哪件事。 + +## 7. 已經確認認識他,但親密度判斷不出來 + +**適用範圍只有一種情況**:已經確認「人格認識這個人」(設定/`canon` 裡有他,或這輪已講清楚他是誰), +但三軸訊號太少,`bond`/`closeness`/`trust` 填不出來。這時候**照樣建節點**,填低值並在 `note` 註明依據不足。 + +**反面(更常見):不知道那是誰就不要建節點。** 只是句子裡被提到一個名字、 +人格根本不知道他是誰的什麼人 → 只寫進短期記憶的 `entities`,**不建節點**,等他再出現、講清楚了再建。 +這不是潔癖:短名與稱謂節點一多,名字解析就會誤配(「我先生」被寫成同事節點的 id 這種事發生過), +寧可少一個節點,也不要多一個對錯人的節點。 + +```bash +node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" relation node \ + --session --name "小林" --kind human \ + --bond stranger --closeness 15 --trust 10 \ + --note "依據不足:使用者的同事(2026-08-03 講到 Q3 專案時提過),但沒有稱呼與語氣訊號可判斷距離" +``` + +規則: + +- 先過一次「認識嗎」這關,**再**談數字填多少;不認識就不會走到這一節。 +- `bond` 拿不準 → 填 `stranger`(語氣層退到「禮貌」,那是**可以修正**的錯;填成 `partner` + 卻其實是陌生人,是**當場失禮**的錯)。 +- `note` 一定要寫「依據不足」四個字,加上**他是誰的依據**與出處那句話, + 下次互動時你才知道這組數字不可信、要重估。 +- `name` 用會被說出口的完整稱呼,不要拿「明」「先生」這種單字或稱謂當節點名(會誤配)。 +- 之後每次互動用 SKILL.md 的「調整幅度(單次)」慢慢調,**不要**回頭重跑這張表。 + +## 8. 一輪之內的四步 + +1. 這輪有**關係詞**嗎?有 → `bond` 與距離帶都定了,跳到第 3 步。 +2. 沒有 → 用**稱呼軸**定距離帶,`bond` 從該帶的「常見 `bond`」裡挑最貼近的。 +3. 用**語氣軸**在帶內 ±5~10 定出 `closeness`(不跨帶)。 +4. `trust` = `closeness` − 10;有明確託付才拉平。寫 `note`(依據哪一句、日期)。