feat: 形象圖改為「依人格資料重繪」,並驗證 Wiki 同步

1. 不再直接使用網路上找到的圖片
   舊版把裁下來的官方美術當圖示(photo 樣式)。現在改成:
     找圖 → `icon headshot` 裁出**大頭照當底稿** → AI 用 Read 親眼看過 →
     讀出髮型/瀏海/眼型/表情/髮飾/領口等特徵 → **由本工具重新繪製**。
   * 底稿寫在 <人格>/.sync/headshot.png,**不是圖示、不同步、不發佈**。
   * 產出的 SVG 不得有 <image>/base64/外連(selftest 會擋)。
   * 移除 photo 樣式與 photoSvg;config 裡殘留的舊樣式會被忽略而非退回徽章。

2. 重繪引擎:五官與造型可參數化
   新增 --features:hairstyle(5) / length(4) / fringe(4) / eyes(4) /
   expression(4) / accessory(5) / side / collar(4) / ahoge。
   渲染器新增 polygon 圖元(呆毛、緞帶、V 領、銳利眼角),SVG 與自寫柵格器
   仍共用同一份圖形清單,兩邊必然一致。
   另外調了臉部比例:眉毛用「髮色偏膚色」避免深髮角色眉毛與瀏海連成黑帶、
   加了鼻子(否則嘴會被看成鼻子)、眼與嘴的縱向配置重排。

3. Wiki 形象圖必須同步(並且會被驗證)
   新增 `sync verify`(不一致以非零結束)與 verifyIconInWiki();
   `icon generate` 推完 Wiki 會自動回頭確認 icon.svg + icon.png 真的在遠端
   且與本機一致。
   修掉一個會讓驗證永遠失敗的 bug:Wiki 首頁內嵌了 `最後同步 ${now}`,
   每次產生都不同 → 永遠 dirty、每次 push 都多一個 commit。改用圖示的
   generated_at。porcelain 解析也從固定位移改為正規式。

已重繪兩個真實人格(皆為 portrait 樣式,並通過 Wiki 同步驗證):
  ASUNA-01  底稿=《Unanswered//butterfly》(2026) 主視覺左側;金蜜色極長直髮、
            中分瀏海、呆毛、紅褐杏眼、沉靜神情、紅上衣 V 領
  YUI-01    底稿=AniList 官方角色圖;藍黑極長直髮、齊瀏海、圓大棕眼、燦爛笑容,
            髮飾與配色採現行 Unital Ring 導航妖精造型(淡粉洋裝、藍花)

selftest 161 項全綠(新增第 ⑰ 節:特徵解析、換髮型/眼型/表情會畫出不同的圖、
polygon 兩邊一致、舊樣式不污染、SVG 無內嵌影像、Wiki 首頁無時間戳)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-30 02:57:18 +00:00
co-authored by Claude Opus 5
parent 15e4eea8ac
commit d0c42f0c15
10 changed files with 527 additions and 197 deletions
+58 -31
View File
@@ -1,13 +1,17 @@
---
name: persona-icon
description: 產生或更新人格的形象圖(icon.svg + icon.png盡量看得到臉):先上網找出該人格「最新一次登場」的官方視覺(新作動畫主視覺、官方角色圖),親看過那張圖,接著優先用臉部偵測從圖上裁出臉當頭像;缺少裁圖工具時改畫有五官的向量人物形象並提示如何安裝工具,完全沒有參考圖才退回編號徽章。來源網址與裁切框會存進 config 備查,圖示同時同步到 Gitea Wiki 與存取庫頭像。當使用者說要做人格頭像/形象圖/icon、要依角色最新造型更新圖示、說現在的圖示不像或看不到臉、或剛建立完人格要補圖示時觸發。不適用於:建立人格本身(persona-createpersona-anime,它們會叫用本技能的步驟)、同步到 Gitea(persona-sync)。
description: 產生或更新人格的形象圖(icon.svg + icon.png人物頭像、看得到臉):先上網找出該人格「最新一次登場」的官方視覺,裁出**大頭照當底稿**,親看過之後萃取髮色/瞳色/服裝色與髮型、眼型、表情、配件等特徵,再**由本工具依人格資料重新繪製**——絕不把找到的圖片直接當圖示。來源網址、底稿裁切框與重繪依據都會存進 config 備查,圖示同步到 Gitea Wiki(SVG + PNG)並設為存取庫頭像,且會回頭驗證同步結果。當使用者說要做人格頭像/形象圖/icon、要依角色最新造型更新圖示、說現在的圖示不像或看不到臉、或剛建立完人格要補圖示時觸發。不適用於:建立人格本身(persona-createpersona-anime,它們會叫用本技能的步驟)、同步到 Gitea(persona-sync)。
---
# 🎨 persona-icon — 依最新造型產生人格形象圖(有臉)
**CLI**`node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs"`(帶 `--session <PERSONA_SESSION>`
**時機****人格建立且 IDENTITY/SOUL 補齊之後**——形象綁在最終身分上。
**目標**:圖示要是**人物形象圖,盡量看得到臉**;退而求其次才是抽象徽章。
**目標**:圖示要是**人物形象圖,看得到臉**;退而求其次才是抽象徽章。
> **鐵則:找到的圖片只能當底稿,不能當圖示。**
> 網路上的角色圖是別人的美術作品。這裡的做法是「裁出大頭照 → 看清楚 →
> **依人格資料重新繪製**」,產出的每一個像素都是本工具畫的。
---
@@ -58,27 +62,22 @@ description: 產生或更新人格的形象圖(icon.svg + icon.png,盡量看
| `secondary` | 服裝的第二色/配件色 |
| `light` | 最亮的部位(白袖、皮膚亮面) |
### 4. 裁出臉(有工具的話,這是首選)
**圖示必須是人物形象,盡量看得到臉。** 環境裡如果有 Pillow(+OpenCV 動漫臉模型),
就直接從參考圖裁臉:
### 4. 裁出大頭照當底稿
```bash
# 先看看圖裡有幾張臉——多角色的主視覺一定要先看
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" icon faces --session <PERSONA_SESSION> --photo "<圖片網址或路徑>"
# 挑一張(索引由左到右;也可以用 largest/leftmost/rightmost,或 --face x,y,w,h 自己框)
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" icon generate --session <PERSONA_SESSION> --force \
--photo "<圖片網址或路徑>" --pick <索引> \
--palette "hair=#..,eye=#..,accent=#..,secondary=#..,light=#.." \
--source-url "<那張圖的網址>" --source-note "<作品(年份)+造型描述>"
# 裁出底稿(索引由左到右;也可以用 largest/leftmost/rightmost,或 --face x,y,w,h 自己框)
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" icon headshot --session <PERSONA_SESSION> --photo "<圖片網址或路徑>" --pick <索引>
```
**多角色的圖務必自己看過再挑**`icon faces` 只會告訴你座標,哪張臉是本人要由你判斷
(把裁出來的圖用 Read 打開確認一次最保險)。挑錯就是別人的臉。
底稿寫到 `<人格>/.sync/headshot.png`,**不是圖示、不會同步、不會發佈**。
工具不齊時 CLI 會**印出安裝指令**並自動退回第 5 步的向量形象——不會靜默失敗
需要的工具:
**多角色的圖務必自己看過再挑**`icon faces` 只給座標,哪張臉是本人要由你判斷
裁完**一定要用 Read 打開確認是本人**——挑錯就是別人的臉。
工具不齊時 CLI 會**印出安裝指令**——不會靜默失敗。需要的工具:
| 工具 | 做什麼 | 怎麼裝(免 sudo) |
| --- | --- | --- |
@@ -89,17 +88,36 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" icon generate --session <PERSON
> OpenCV **5.x 拿掉了 `CascadeClassifier`**,一定要裝 4.x。
> venv 放在 `~/.cache/jsc-persona/venv` 會被自動偵測到;也可以用 `PERSONA_PYTHON` 指定別的。
### 5. 沒有工具時:向量人物形象(一樣有臉)
### 5. 看著底稿,把特徵讀出來
用 Read 打開 `.sync/headshot.png`**同時**讀這個人格的 `IDENTITY.md``SOUL.md`canon 記憶。
形象要同時對得起「他長什麼樣」與「他是誰」:
| 特徵 | 可選值 | 從哪裡判斷 |
| --- | --- | --- |
| `hairstyle` | straight / twintails / ponytail / bob / braid | 底稿的髮型 |
| `length` | short / medium / long / very-long | 底稿的髮長 |
| `fringe` | blunt / parted / swept / curtain | 底稿的瀏海 |
| `eyes` | round / almond / sharp / droopy | 底稿的眼型 |
| `expression` | gentle / bright / calm / neutral | **SOUL 的 Vibe** 底稿的神情 |
| `accessory` | none / ribbon / clip / flower / hairband | 底稿或最新造型的髮飾 |
| `side` | left / right | 髮飾在哪一側 |
| `collar` | round / v / high / sailor | 服裝領口 |
| `ahoge` | yes / no | 有沒有呆毛 |
### 6. 重新繪製
```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" icon generate \
--session <PERSONA_SESSION> --force \
--palette "hair=#d9a45b,eye=#9e5b3e,accent=#c0392b,secondary=#e77a8e,light=#f2ebe3" \
--source-url "<你剛才看的那張圖的網址>" \
--source-note "<作品(年份)+造型描述:髮色、瞳色、服裝>" \
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" icon generate --session <PERSONA_SESSION> --force \
--palette "hair=#d9a45b,eye=#9e5b3e,accent=#c0392b,secondary=#e77a8e,light=#f2ebe3,skin=#f7ddc4" \
--features "hairstyle=straight,length=very-long,fringe=parted,eyes=almond,expression=calm,accessory=none,collar=v,ahoge=yes" \
--source-url "<底稿那張圖的網址>" \
--source-note "<作品(年份)+底稿是誰+重繪依據:髮型、眼型、神情、服裝>" \
--source-date <YYYY-MM-DD>
```
**畫完一定要用 Read 打開產出的 `icon.png` 看一眼**,不像就調特徵重畫(`--force`)。
- **`--palette` 一定要配 `--source-url`**:配色是從哪張圖來的必須留得下來(CLI 會強制)。
- 兩者都會寫進 `state/config.json` 的 `icon` 欄位,之後 `icon show` 查得到。
- 產出的 `icon.svg` + `icon.png` 會自動設成 Gitea 存取庫頭像、同步到 Wiki 區,
@@ -108,7 +126,7 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" icon generate \
找不到可靠的參考圖 → **不要硬掰**,直接 `icon generate` 不帶 `--palette`
用編號雜湊出的配色,並告訴使用者「沒找到最新造型的官方圖,先用預設配色」。
### 6. 回報
### 7. 回報
一句話說明:用了哪部作品哪一年的視覺、取到什麼配色、圖示放哪裡。
把來源網址附上,讓使用者可以自己核對。
@@ -117,25 +135,34 @@ node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" icon generate \
| 樣式 | 什麼時候用 | 長什麼樣 |
| --- | --- | --- |
| `photo` | 有參考圖 **且**工具齊全(最佳) | 從官方視覺**裁出的臉**,圓角+瞳色外框 |
| `portrait` | 有參考圖但沒工具 | 向量人物形象:髮型、瞳色、服裝色都取自照片,**有五官** |
| `portrait` | 有底稿(有調色盤)→ **預設** | 依特徵重繪的人物頭像:髮型、瀏海、眼型、表情、髮飾、領口全部照特徵畫 |
| `badge` | 完全沒有參考圖(原創人格) | 雙色漸層徽章 + 編號前兩個字母 |
- `portrait` 與 `badge` 由 Node 自己柵格化,SVG 與 PNG **共用同一份圖形清單**,兩邊必然一致;
PNG 是自寫的柵格器 + zlib 編碼,不依賴任何影像函式庫。
- `photo` 的 SVG 會把裁好的 PNG 以 base64 內嵌,一樣自成一體(不外連
- 兩種樣式都由 Node 自己柵格化,SVG 與 PNG **共用同一份圖形清單**(橢圓/矩形/多邊形),
兩邊必然一致;PNG 是自寫的柵格器 + zlib 編碼,不依賴任何影像函式庫。
- SVG **不會內嵌任何影像**——沒有 `<image>`、沒有 base64、沒有外連。
- `badge` 樣式下若兩個顏色一深一淺(藍黑髮 + 淡粉洋裝),程式會把較亮的一端往較暗的壓,
確保字讀得到——顏色仍然是照片來的,只是收斂色階
確保字讀得到。
## 界線
裁出來的是**角色臉部的縮圖**,用途是人格身分辨識(頭像)。原始美術作品的權利屬於原作者,
存取庫預設私有;不要把它當成可以散布的素材,也不要重製整張原圖
- **找到的圖片只能當底稿**:裁出來的大頭照留在 `.sync/`,不進圖示、不同步、不發佈。
圖示的每個像素都是本工具依特徵畫出來的
- 底稿的來源網址會記在 `config.json`,方便日後核對,但不重製原圖。
## Wiki 必須同步
`icon generate` 推完 Wiki 會**自動回頭驗證**,確認 `icon.svg` 與 `icon.png` 真的在 Wiki 上
而且與本機一致;不一致會直接報錯。也可以手動查:
```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" sync verify --session <PERSONA_SESSION> --area wiki
```
## 邊界
- 只能對「本 session 已載入的人格」產生圖示。
- 已有圖示時要重畫必須加 `--force`。
- 不帶 `--palette` 重畫會**沿用 config 裡已存的配色**(不會突然變回雜湊色)。
- `.sync/reference.*` 是下載回來的參考圖快取,可以安全刪除。
- `.sync/reference.*` 與 `.sync/headshot.png` 是底稿快取,可以安全刪除(不會同步出去)
- 所有面向使用者的輸出使用**繁體中文(台灣用語)**、UTF-8 無亂碼。