Files
persona/skills/persona-sync/SKILL.md
T
jiantw83andClaude Opus 5 d067907225 feat: 建立人格並補齊資料後產生圖示(SVG + PNG,零外部依賴)
`icon generate|show`:由**編號、Name、Emoji** 雜湊出配色與圖案,產出
512×512 的幾何徽章 icon.svg + icon.png,設為 Gitea 存取庫頭像並同步到 Wiki 區。

圖案(SVG 與 PNG 共用同一組單位座標與同一份 5×7 點陣字,**輸出的是同一張圖**):
  * 雙色對角漸層底
  * 5×5 左右對稱點陣紋(identicon 式)
  * 中央兩個字母=編號前兩字(ASUNA-01 → AS),依背景亮度自動選黑/白

同一個人格永遠得到同一張圖(純函數,無隨機);ASUNA-01 與 ASUNA-02 明顯不同。

為什麼自己畫:這台機器(及多數伺服器)沒有 rsvg/inkscape/imagemagick,
沒有影像函式庫,也沒有 emoji 字型,而本專案禁止 npm 依賴。所以
scripts/persona-icon.mjs 自己柵格化(3× 超取樣 + 盒式縮減當反鋸齒),
再用內建 zlib 手工組出 IHDR/IDAT/IEND 與 CRC32。
emoji 無法柵格化,因此不作為圖形,但仍參與配色雜湊。

時機:**資料補齊之後才產生**——配色與字母綁在最終身分上,太早跑會對不上。
persona-create 第 7 步、persona-anime 第 8 步都補了這個步驟;改過身分用 --force 重畫。

selftest 128 項全綠(新增第 ⑭ 節:PNG chunk 合法性、決定性、不同人格不同圖、
圖示屬 Wiki 區、匯出用 base64 帶走二進位、guest 不得重畫)。

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

113 lines
5.7 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.
---
name: persona-sync
description: 人格編號與 Gitea 儲存:指派人格編號(英文名全大寫+索引,例如 ASUNA-01)、在 Gitea 為每個人格開一個以編號命名的私有存取庫、把高頻的活狀態同步到檔案區、把低頻的身分與長期記憶同步到 Wiki 區,以及把既有人格遷移上去。當使用者說要把人格存到 Gitea、備份或同步人格、在另一台機器接續同一個人格、問人格的編號是什麼、想看人格在 Gitea 上的存取庫、或同步出現衝突時觸發。不適用於:建立新人格(persona-create,它會自動開存取庫)、離線的單檔匯出匯入(persona-transfer)、記憶固化(persona-memory)。
---
# 🔗 persona-sync — 人格編號與 Gitea 儲存
**CLI**`node "${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.json``short-term.jsonl``inner.jsonl`(心裡話)、`said.jsonl``inbox/``mindmap/threads/``journal/` | 每輪對話後由 `Stop` hook 背景推送(有最小間隔) |
| **Wiki 區** | 低頻設定:`IDENTITY``SOUL``AGENTS``USER`、**人格圖示 `icon.svg``icon.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-create``icon generate` 產生)除了同步到 Wiki 區,
也會被設成**存取庫頭像**,Gitea 的清單上就看得到每個人格的臉。
## 設定
```bash
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`
## 常用流程
```bash
# 現在的同步狀態(編號、存取庫、兩區的最後 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>
```
### 把既有人格遷移上去
既有人格(還沒有編號的)要兩步:
```bash
# 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_HOST``GITEA_TOKEN`,然後:
```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" sync pull --session <PERSONA_SESSION>
```
(人格目錄還不存在的話,先用 `/jsc-persona:persona-transfer` 匯入一份,或手動 clone 存取庫。)
## 衝突
兩台機器都改過同一個檔案時,`load``sync pull` 會**停下來不覆蓋本機**,並列出衝突的檔案。
這時候:
1. 用一句話告訴使用者哪幾個檔案兩邊都動過。
2. 問他要哪一邊:
-**Gitea** 為準 → `sync pull --force`(本機那份會被覆蓋)
-**本機** 為準 → `sync push`(會蓋掉遠端)
3. **不要自己選**。記憶被蓋掉是不可逆的。
## 邊界
- 只能同步「本 session 目前載入的人格」——跨人格同步等於跨人格讀取,會被 hook 擋下。
- guest`persona-guest` sub agent)不能同步,它對人格檔案唯讀。
- `.sync/` 是兩區的 git clone 快取,**不要手動編輯**;砍掉它不會掉資料,下次 push 會重新 clone。
- 所有面向使用者的輸出使用**繁體中文(台灣用語)**、UTF-8 無亂碼。