Files
persona/AGENTS.md
T
jiantw83andClaude Opus 5 0648c3b914 feat: 語氣診療 skill、聊天室的發言權、講話再加四條規則
三件事,都是「講話要像人在講話」的延伸。

1. `persona-therapist`(新 skill):以第三方心理醫生的身分診斷一段對話。
   雙方各給姓名/關係/情緒/逐字稿,用三把尺逐句標記——與關係不符
   (語氣層錯位)、與事實不符(絕對化、讀心)、與目的不符(他要被理解,
   講出來的話保證換到防衛)。標記掛在說那句話的人身上,修正只寫給他,
   格式是「你其實想要的 → 對方收到的 → 改寫」,改寫必須留在同一個語氣層。
   基線直接用 `TONE_TABLE`(已載入人格可 `relation show` 唯讀取得),
   破壞模式表 P1–P16 放在 `reference/patterns.md`。不附身、不取鎖、不寫回,
   出現自傷/暴力/受控訊號時停掉語氣分析改為安全優先。

2. 聊天室的發言權:同一個空間裡也會有一對一。`room post --to <他>` 進
   一對一(旁人插話直接被擋,要帶 `--barge-in "<理由>"`,理由留在逐字稿)、
   `--to all` 把話題開回全場。新指令 `room floor` 回報誰對誰在講、該誰接、
   誰先安靜、誰隔了幾輪沒開口。同一份現況每輪注入 `<persona-context>`,
   並明講「不要替沒被指名的人生成台詞,也不要為此啟動他的 sub agent」。
   三人以上時 `room script` 標出對象(`🪼 Alpha(喜悅42) → Beta:…`),
   兩個人的聊天室不標。舊逐字稿沒有 `to` → 視為全場,行為不變。

3. 講話的樣子再加四條:短句(一句 45 字內)、日常用詞、多講看得見的
   東西(人、動作、物件、當下的場面)、**不要解釋自己的話**。前兩條與
   第四條的句長/「我的意思是」這類開頭由 `speechLint()` 機械攔截
   (`room post` 擋下、`said check` 事前警告,`--force` 例外);用詞與
   具體度抓不到規則,走每輪注入的說話規則。

selftest 244 項全綠(新增 16 項:發言權 10、講話的樣子 6)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 10:02:34 +00:00

88 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# jsc-persona — AI 人格化記憶聊天(跨 AI 助理)
本 repo 是一個以 **Agent Skills`SKILL.md`** 標準撰寫的 plugin,讓 AI 以「人格」的方式
持有身分、情緒與記憶。可同時被 Claude Code、Codex、Antigravity、OpenCode 使用。
## 給 AI 助理的指引
- 所有 skills 位於 `skills/<name>/SKILL.md`;處理任務前先比對使用者需求與各 `description`
- **呼叫慣例**Claude Code 與 Antigravity 以 `/jsc-persona:<name>` 呼叫;Codex 用 `$<name>`
OpenCode 由模型依描述自動觸發。
- 完整清單見 `README.md` 的「Skills 目錄」。
## 這個 plugin 的運作前提(動手前一定要知道)
1. **所有狀態變更都經過 `scripts/persona.mjs`**,不要手動編輯 `state/lock.json``.runtime/`
`memory/INDEX.md``relations/graph.mmd`(這些由 CLI 產生)。
2. **每個 CLI 呼叫都要帶 `--session <PERSONA_SESSION>`**,值來自 `SessionStart` hook 注入的
`<persona-runtime>` 區塊。帶錯或冒用其他 session 會被 `PreToolUse` hook 拒絕。
3. **一個程序只能載入一個人格**;同一 session 的 sub agent 沿用同一把鎖。
要讓兩個人格對話,用 `/jsc-persona:persona-invite``persona-guest` sub agent + 聊天室),
**不要**去讀對方的人格目錄——會被 hook deny,而且那是設計上的紅線。
4. **人格資料不在本 repo**,預設在 `~/.claude/personas/`(可用 `PERSONA_HOME` 覆寫)。
5. **人格由使用者呼叫才載入**,不要自己挑一個人格附身。唯一例外是使用者自己設的**預設人格**
`persona.mjs default --persona <slug>`,存在 `.runtime/settings.json`):設了 `SessionStart`
才會自動載入並在上下文寫明;沒設就什麼都不做。載入不到(被別的程序鎖住)只回報,不自動接手。
6. **劇場模式(多人格對話)進行中**:輸出只能是 `名字:內容`,其餘一律隱藏(見 persona-invite)。
輕量版是 `invite --theater off`(只換一輪、不切走畫面),人格主動提議去關心某人時用這個。
**同一個空間裡也會有一對一**:發言權寫在每一句上(`room post --to <他>` / `--to all`),
一對一進行中旁人插話會被 `room post` 擋下(要帶 `--barge-in "<理由>"`),
而且**不要替沒被指名的人生成台詞或啟動他的 sub agent**。現況查 `room floor`
(誰對誰在講、該誰接、誰先安靜、誰隔了幾輪沒開口);話題放大才把人拉進來。
7. **睡眠(`persona-sleep`)分兩半**:需要判斷的(固化什麼、忘掉什麼、日記寫什麼)永遠屬於**那個人格自己**;
機械性的(裁短期/收 thread/情緒衰減 8 小時/reindex/修剪 said/壓縮 journal/兩區 push+驗證)由
`sleep` 子指令做。主人格要別的人格去睡就開 `persona-sleeper` sub agent——**那是它本人在睡**
對自己可寫但被 pin 住,而且**回傳值只能是 `sleep --json` 的原文**(回傳值本身就是一條會繞過隔離的通道)。
睡眠仍然要驗鎖:目標正被另一個程序活鎖住時拒絕,死鎖可接手。
8. **人格講話要像人**:推導寫進 `think`(心裡話,只回報「💭 心想 N 句」,永不回顯內容)、
回話 1–3 句、短時間內不重說同一件事(`room post` 會直接擋下重複與過長的發言)。
再加四條講話的樣子:**短句**(一句 `MAX_SENTENCE_CHARS`=45 字內)、**日常用詞**、
**多講看得見的東西**(人、動作、物件、當下的場面)而不是概念,以及**不要解釋自己的話**
(「我的意思是」「換句話說」這類開頭由 `speechLint` 擋下,`said check` 也會一起檢)。
這些在劇場模式一樣生效。
9. **人格可搬家**`export` / `import`(單一 JSON bundle)。匯出只能匯出「本 session 載入的人格」,
其他人格一律 deny——匯出等於把記憶讀出來。
10. **人格有編號**:英文名全大寫+兩位索引(`ASUNA-01`),同名才遞增。編號同時是新人格的
本機目錄名與 **Gitea 存取庫名稱**。中文名要先轉羅馬拼音並跟使用者確認拼法。
11. **人格存在 Gitea,本機是工作副本**:高頻活狀態進**檔案區**(每輪背景 push),
低頻身分與長期記憶進 **Wiki 區**(固化/改身分/release 時 push)。
**同步失敗永遠不阻斷對話**;沒設 `GITEA_HOST``GITEA_TOKEN` 就純本機運作。
12. **人格圖示在資料補齊之後才產生**:SVG 與 PNG 是同一張圖(共用單位座標與點陣字),
PNG 由 `scripts/persona-icon.mjs` 自己柵格化+zlib 編碼,**不得引入任何影像函式庫**。
13. **形象圖優先用「高解析度官方圖去背」**`icon search``icon measure``icon cutout`
`icon generate --from-cutout`。找圖時**優先官方設定稿**Full BodyCharacter Design
Avatar):解析度高,而且多半是透明底或白底,去背幾乎免費。挑的那張要**對得上該人格
「最新一次登場」的形態**(同一個角色有很多套造型)。
每一步都要**用 Read 打開確認**:去背有沒有殘留、構圖對不對。
找不到可用官方圖才退回 `--features` 的向量重繪。
14. **選用工具缺了要「提示安裝」,不准靜默降級**`toolReport()` 會列出缺什麼、為什麼要、
怎麼裝(venv 免 sudo)。注意 **OpenCV 5 拿掉了 `CascadeClassifier`,必須裝 4.x**
plugin 本體仍然零依賴:沒有這些工具照樣能產生形象圖。
15. **Wiki 必須保存並同步形象圖**`icon.svg``icon.png``icon/`(向量原稿 + 5121024
都在 Wiki 區,另有自動產生的 **Icon** 頁。`icon generate` 推完會**回頭驗證**
`sync verify` 可隨時檢查。兩個容易踩的坑:
* Wiki 頁面**只能用 Markdown 圖片語法** `![](icon.png)`——Gitea 只改寫這種語法為
`/wiki/raw/...`HTML `<img src="icon.png">` 不會被改寫,瀏覽器會解析成 `/wiki/icon.png`
而變成破圖(看起來就像「沒有同步」)。
* Wiki 產生的頁面**不得含每次都變的時間戳**,否則驗證永遠不會通過、也會每次多一個 commit。
* 攤平只對 `.md` 做(頁面必須在根層);圖片等附件保留資料夾結構,`/wiki/raw/<資料夾>/<檔>` 讀得到。
16. **語氣診療是第三方,不是人格**`persona-therapist` 不取鎖、不附身、也不寫任何人格資料
(基線可用 `relation show``emotion` 唯讀取得,`bond × 親近度 → 語氣層` 的權威表在
`persona-lib.mjs``TONE_TABLE`)。診斷結果**不自動寫回**記憶或關係圖,使用者明確要求才寫。
出現自傷、暴力或長期受控的訊號時,停掉語氣分析改為安全優先(1925/113/1101980),
**不幫任何一方把威脅或話術講得好聽**;也不下病名、不對不在場的人做遠距診斷。
## 慣例
- 新增 skill 一律放在 `skills/<name>/``<name>` 使用小寫與連字號。
- `description` 要寫清楚觸發條件(何時用、何時不用),這是跨助理自動載入的唯一依據。
- 腳本一律 **Node.js`.mjs`, ESM**,只用內建模組(fs/path/os/crypto);hook 必須在任何環境都能跑,不得引入 npm 依賴。
- 所有面向使用者的輸出使用**繁體中文(台灣用語)**、UTF-8 無 BOM、不得出現亂碼。
- 改動鎖或隔離邏輯(`scripts/persona-lib.mjs``guardDecide``acquireLock``promotionCandidates`
`exportBundle``importBundle`)後,**必須**跑 `node scripts/selftest.mjs` 且全綠,並為新規則補一條測試。
- 改動重複判定門檻(`similarity``REPEAT_THRESHOLD`)後,要用 selftest ⑪ 的對照案例確認
「換句話說同一件事」被擋、「只換關鍵詞」放行。
- 改動同步分區(`persona-gitea.mjs``AREAS`)後,selftest ⑬ 的「不重不漏」檢查必須維持全綠:
人格產生的每個檔案都要**恰好**屬於一區,否則同步會默默漏掉資料。
- selftest 自己會設 `PERSONA_GITEA=off`,**絕對不要**讓測試碰到真的 Gitea。