Files
persona/skills/persona-sync/SKILL.md
T
jiantw83andClaude Opus 5 41e57432ea fix(sleep): sleeper 讀得到自己的資料、sync 自己清殘留鎖(v0.1.1)
睡眠的「判斷式那半」實際上跑不起來,兩個原因:

1. `requireMember` 沒有 sleeper 分支——`requireOwner` 早就放 sleeper 寫了,
   讀(brief/show/recall)反而被當成跨人格存取擋下,等於要它閉著眼睛
   決定要固化什麼。補上分支,回傳 role `sleeper`(下游只判斷 `guest`,
   所以行為與 owner 一致)。

2. `sync` 遇到殘留的 `.git/index.lock` 會讓整區永遠失敗,而 sleeper 被隔離
   hook 擋著、連自己的鎖都刪不掉(CLI 也沒有清鎖的功能)。這些 clone 只有
   CLI 會動且每個 git 都同步跑完,所以超過 30 秒還在的鎖一定是殘骸——
   `pushArea`(兩處)與 `pullArea` 現在會自己清掉再繼續。

技能文件補上先前沒寫的部分:

- `persona-relation`:整個 bond/語氣層章節。這個功能 7c46db8 就上線,但技能
  文件從頭到尾沒提過,於是每個新建的至親都預設是生人(`note` 寫「妻子」猜不出
  `partner`,關鍵詞只認夫妻/老婆/伴侶/戀人)——症狀是「講話像在對戰友報告」。
  一併補上 `relation style` 與 `relation speaker` 的用法。
- `persona-sleep`:說明帶了身分旗標之後讀寫都算自己的資料;新增第 4 條硬相依
  ——判斷式失敗就不要跑機械性那半,`sleep` 會裁短期記憶,否則等於沒判斷就把
  今天清掉。
- `persona-sync`:新增「殘留的 git 鎖」一節。

版本號 0.0.5 → 0.1.1(master 上是 0.1.0,要跨過它),兩份 manifest 一起改。
selftest 238 項全過;另以獨立腳本(暫時 PERSONA_HOME)驗證修補前後 sleeper
的 brief/show/recall 由全數被擋變為全數通過。

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

6.3 KiB
Raw Blame History

name, description
name description
persona-sync 人格編號與 Gitea 儲存:指派人格編號(英文名全大寫+索引,例如 ASUNA-01)、在 Gitea 為每個人格開一個以編號命名的私有存取庫、把高頻的活狀態同步到檔案區、把低頻的身分與長期記憶同步到 Wiki 區,以及把既有人格遷移上去。當使用者說要把人格存到 Gitea、備份或同步人格、在另一台機器接續同一個人格、問人格的編號是什麼、想看人格在 Gitea 上的存取庫、或同步出現衝突時觸發。不適用於:建立新人格(persona-create,它會自動開存取庫)、離線的單檔匯出匯入(persona-transfer)、記憶固化(persona-memory)。

🔗 persona-sync — 人格編號與 Gitea 儲存

CLInode "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs"(一律帶 --session <PERSONA_SESSION>


人格編號

編號 = 英文名全大寫 + 兩位索引,同名才遞增:

亞絲娜(第一個) → ASUNA-01
結衣             → YUI-01
另一個亞絲娜     → ASUNA-02
  • 編號就是 Gitea 存取庫的名稱,也是新人格的本機目錄名。
  • 中文/日文名字要先轉羅馬拼音:由你提議拼法(亞絲娜 → Asuna沈宇 → Shen Yu), 拿給使用者確認再送出——拼錯了會變成一個很難改的編號。
  • 查下一個可用編號:code next --romaji Asuna --session <id>

資料放哪裡(依更新頻率切)

放什麼 什麼時候 push
檔案區(主存取庫) 高頻活狀態:state/emotion.jsonshort-term.jsonlinner.jsonl(心裡話)、said.jsonlinbox/mindmap/threads/journal/ 每輪對話後由 Stop hook 背景推送(有最小間隔)
Wiki 區 低頻設定:IDENTITYSOULAGENTSUSER人格圖示 icon.svgicon.png、長期記憶、INDEX、心智圖、人際關係圖 記憶固化、改身分、改關係圖、release

Wiki 是給人讀的設定百科:Gitea 的 wiki 只有根目錄的 .md 會變成頁面,所以 memory/long-term/xxx.md 會攤平成 Memory-xxx.md(頁面顯示為「Memory xxx」), 原始路徑記在 _paths.json,拉回來時自動還原。Home 頁會自動列出所有長期記憶的連結。

本機永遠是工作副本:hook 每輪讀寫的是本機檔案,不經過網路。Gitea 掛掉、離線、沒設 token, 人格照樣能聊天,只是不同步——同步失敗永遠不阻斷對話

人格圖示(/jsc-persona:persona-createicon generate 產生)除了同步到 Wiki 區, 也會被設成存取庫頭像,Gitea 的清單上就看得到每個人格的臉。

設定

export GITEA_HOST=https://gitea.example.com    # 或 PERSONA_GITEA_HOST
export GITEA_TOKEN=<個人存取權杖>               # 或 PERSONA_GITEA_TOKEN
export PERSONA_GITEA_OWNER=<帳號或組織>         # 選填,預設是 token 本人的帳號
export PERSONA_GITEA=off                       # 需要時整個關掉
export PERSONA_SYNC_MIN_SECONDS=60             # 檔案區背景 push 的最小間隔

存取庫預設私有(人格裡有使用者的個人記憶)。要公開必須是使用者明講,才加 --public

常用流程

# 現在的同步狀態(編號、存取庫、兩區的最後 push/pull)
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" sync status --session <PERSONA_SESSION>

# 手動推送(--area files|wiki|all
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" sync push --session <PERSONA_SESSION> --area all

# 從 Gitea 拉回(載入人格時會自動做一次)
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" sync pull --session <PERSONA_SESSION>

把既有人格遷移上去

既有人格(還沒有編號的)要兩步:

# 1) 載入它(同步只能動本 session 載入的那個人格)
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" load --persona <舊 slug> --session <PERSONA_SESSION>

# 2) 指派編號 + 開存取庫 + 首次推送;--rename 連本機目錄名也改成編號
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" code assign \
  --session <PERSONA_SESSION> --romaji "<英文名>" --rename

--rename 之後這個人格就用編號稱呼(--persona ASUNA-01)。不加 --rename 也可以, 目錄名維持原樣、只是多了一個編號與對應的存取庫。遷移前先跟使用者確認: 這會把他的個人記憶送上 Gitea(私有庫,但仍是上傳)。

在另一台機器接續同一個人格

在新機器上設好 GITEA_HOSTGITEA_TOKEN,然後:

node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" sync pull --session <PERSONA_SESSION>

(人格目錄還不存在的話,先用 /jsc-persona:persona-transfer 匯入一份,或手動 clone 存取庫。)

衝突

兩台機器都改過同一個檔案時,loadsync pull停下來不覆蓋本機,並列出衝突的檔案。 這時候:

  1. 用一句話告訴使用者哪幾個檔案兩邊都動過。
  2. 問他要哪一邊:
    • Gitea 為準 → sync pull --force(本機那份會被覆蓋)
    • 本機 為準 → sync push(會蓋掉遠端)
  3. 不要自己選。記憶被蓋掉是不可逆的。

殘留的 git 鎖

pushpull 跑到一半被中斷(sub agent 被砍、視窗關掉)會在 clone 裡留下 .git/index.lock 之後那一區的 git add 每次都失敗 → 整區同步卡住。這件事不用你處理 這些 clone 只有 CLI 會動,所以超過 30 秒還在的鎖一定是殘骸,pushpull 會自己清掉再繼續。

不要叫使用者手動進 .sync/ 刪檔案,也不要自己下 rm—— sleeper 連自己的人格目錄都不能用 shell 寫,那條路本來就是死的。 真的還是失敗(例如權限問題),照原樣把錯誤訊息轉告他就好。

邊界

  • 只能同步「本 session 目前載入的人格」——跨人格同步等於跨人格讀取,會被 hook 擋下。
  • guestpersona-guest sub agent)不能同步,它對人格檔案唯讀。
  • .sync/ 是兩區的 git clone 快取,不要手動編輯;砍掉它不會掉資料,下次 push 會重新 clone。
  • 所有面向使用者的輸出使用繁體中文(台灣用語)、UTF-8 無亂碼。