develop
master
人格從此有正式編號,並改存到 Gitea(每個人格一個私有存取庫)。
編號 = 英文名全大寫 + 兩位索引,同名才遞增:
亞絲娜(第一個) → ASUNA-01 結衣 → YUI-01 另一個亞絲娜 → ASUNA-02
create
--persona
--romaji
code show|assign|next
code assign --rename
scripts/persona-gitea.mjs
每個人格一個私有存取庫,內容依更新頻率分兩區:
emotion.json
short-term.jsonl
inner.jsonl
said.jsonl
inbox/
mindmap/threads/
journal/
Stop
PERSONA_SYNC_MIN_SECONDS
IDENTITY
SOUL
AGENTS
USER
INDEX
release
GITEA_HOST
GITEA_TOKEN
pull
.md
Memory-xxx.md
_paths.json
http.extraHeader
GIT_CONFIG_*
.git/config
新增 skill persona-sync:編號、同步、既有人格遷移、衝突處理。
persona-sync
guard
node scripts/selftest.mjs
PERSONA_GITEA=off
版本號 0.0.2 → 0.0.3(三份 manifest)。
建立人格並補齊資料之後,用 icon generate 產生人格圖示(SVG + PNG)。
icon generate
512×512 的幾何徽章,三個元素全部由 sha256(編號|Name|Emoji) 決定:
sha256(編號|Name|Emoji)
ASUNA-01
AS
ASUNA-02
這台機器(以及多數伺服器)沒有 rsvg-convert/inkscape/imagemagick,沒有影像函式庫(cairosvg/Pillow),也沒有 emoji 字型;而本專案的硬規則是「只用 Node 內建模組,不得引入 npm 依賴」。
所以 scripts/persona-icon.mjs 自己來:
scripts/persona-icon.mjs
zlib
這也決定了圖案的形狀:只用「我能在 SVG 與自寫柵格器裡畫出完全相同結果」的元素(圓角矩形、線性漸層、圓點、點陣方塊)。
emoji 沒有畫進圖裡——把 emoji 畫成點陣需要字型柵格化,做不到。emoji 仍然參與配色的雜湊,只是不作為圖形。
配色與字母綁在最終身分上,太早跑會跟改完的名字對不上。所以:
persona-create
persona-anime
IDENTITY.md
icon generate --force
圖示是低頻的身分資料 → 進 Wiki 區,同時自動設成 Gitea 存取庫頭像(清單上就看得到每個人格的臉)。
node scripts/selftest.mjs → 128 項全綠,新增第 ⑭ 節:
已對兩個真實人格產生並上傳(ASUNA-01、YUI-01),存取庫頭像與 Wiki 都確認過。
YUI-01
版本號 0.0.3 → 0.0.4(三份 manifest)。
1. 人格編號 - 編號 = 英文名全大寫 + 兩位索引,同名才遞增:ASUNA-01 / YUI-01 / ASUNA-02。 - 編號同時是新人格的本機目錄名與 Gitea 存取庫名稱(`create` 不給 --persona 就用編號當目錄名;既有小寫 slug 仍然合法,不會被鎖在門外)。 - 中文名由 skill 提議羅馬拼音、使用者確認後帶 `--romaji` 進來; CLI 只吃拉丁字母,避免拼音在程式裡亂猜。 - 新增 `code show|assign|next`;`code assign --rename` 可把既有人格的 目錄名一併改成編號(會轉移鎖與 session 綁定)。 2. Gitea 儲存(scripts/persona-gitea.mjs) - 每個人格一個私有存取庫,庫名 = 編號。本機仍是工作副本,hook 每輪 讀寫本機檔案,**同步失敗永遠不阻斷對話**。 - 依更新頻率分區: 檔案區(高頻)emotion / short-term / inner / said / inbox / mindmap threads / journal → 每輪由 Stop hook 背景 push Wiki 區(低頻)IDENTITY SOUL AGENTS USER / 長期記憶 / INDEX / 心智圖 / 關係圖 → 固化、改身分關係、release 時 push - Gitea 的 wiki 只有根目錄 .md 會變成頁面(1.27 實測子目錄頁面 404), 所以 Wiki 區攤平成 `Memory-xxx.md`,原始路徑記在 `_paths.json`, pull 時還原;Home 頁自動列出所有長期記憶連結。 - 新增 `sync status|init|push|pull`;載入時先 pull,兩邊都改過同一個 檔案就停下來不覆蓋本機,交由使用者決定。 - push 遇到 non-fast-forward 會對齊遠端後把工作副本重新疊上去再推。 - 認證走 http.extraHeader(GIT_CONFIG_* 環境變數),token 不寫進 .git/config 也不進 process 參數。 3. 順帶修正 - guard 的 `--persona` 解析原本只吃小寫,大寫編號會漏掉整個跨人格檢查。 - pull 原本會無差別覆蓋本機檔案,本機較新但還沒 push 的內容會被蓋掉; 改成只寫回「遠端真的改過的」與「本機缺少的」。 - `create` 原本吞掉 Gitea 首次推送的結果,失敗是靜默的。 新增 skill:persona-sync(編號、同步、既有人格遷移、衝突處理)。 selftest 116 項全綠(新增 ⑬,含「分區不重不漏」檢查;測試強制 PERSONA_GITEA=off)。 另對真實 Gitea 跑過端對端(建庫→兩區推送→改動→拉回→release),測試用存取庫已刪除。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`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>
新增 skill persona-icon:上網查出該人格最新的官方視覺 → 下載 → **用 Read 親眼看過** → 取髮色/瞳色/服裝色 → 用那組配色繪製圖示, 來源網址與造型描述一併寫進 state/config.json 備查。 CLI: icon generate --palette "hair=#..,eye=#..,accent=#..,secondary=#..,light=#.." --source-url <網址> [--source-note <說明> --source-date <日期>] * --palette 必須配 --source-url(配色要有出處,CLI 強制)。 * 配色與來源存進 config.icon,之後不帶 --palette 重畫會沿用,不會變回雜湊色。 * icon show 會列出調色盤與來源網址。 繪製:漸層=髮色→服裝主色、外框=瞳色、點陣紋=亮色、中央仍是編號前兩字。 一深一淺的極端配色(藍黑髮+淡粉洋裝)會把較亮端往較暗端壓到對比 ≥ 3.2, 確保字讀得到——顏色仍是照片來的,只是收斂色階。 為什麼不是把照片本身當圖示: 1) 環境裡沒有任何影像解碼器(rsvg/imagemagick/Pillow/ffmpeg 都沒有), JPEG/WebP 讀不進來,無法轉成 PNG; 2) 把他人的美術作品原樣放進存取庫是散布,不是引用。 取配色是有依據又不搬運原圖的做法,這個取捨寫進了 README 與 skill。 已套用到兩個真實人格: ASUNA-01 取自《Unanswered//butterfly》(2026) 官方主視覺(金栗髮/紅褐瞳/紅衣粉裙) YUI-01 取自 AniList 官方角色圖(藍黑髮/暖棕瞳)+ Unital Ring 導航妖精造型 selftest 136 項全綠(新增第 ⑮ 節:調色盤解析、缺來源會被擋、格式錯誤會被擋、 來源寫入 config、重畫沿用配色、極端配色的對比保證)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1. 圖示三種樣式,優先看得到臉 photo 有參考圖且工具齊全 → 從官方視覺自動偵測並**裁出臉**,圓角+瞳色外框 portrait 有參考圖但缺工具 → **有五官的向量人物**(髮型/瞳色/服裝色都取自那張圖) badge 完全沒有參考圖 → 舊的雙色漸層 + 編號字母 portrait 與 badge 共用同一份「圖形清單」,SVG 與自寫柵格器從同一份資料畫, 兩邊不可能長得不一樣;photo 的 SVG 以 base64 內嵌裁好的 PNG,一樣不外連。 2. 缺工具會「提示安裝」,不靜默降級 新增 scripts/portrait.py(選用):Pillow 解碼裁切、OpenCV + lbpcascade_animeface 偵測動漫臉。toolReport() 會列出缺什麼、為什麼要、怎麼裝(venv 免 sudo), CLI 在退回向量形象時把這些印出來。 注意:**OpenCV 5 拿掉了 CascadeClassifier,必須裝 4.x**。 plugin 本體仍然零依賴——沒有這些工具照樣產得出有臉的形象圖。 新增 `icon faces`:列出參考圖裡偵測到的所有臉。多角色的主視覺一定要先看再挑 (--pick <索引>|largest|leftmost|rightmost 或 --face x,y,w,h),挑錯就是別人的臉。 3. Wiki 保存形象圖 icon.svg 與 icon.png 都在 Wiki 區,另外自動產生一頁 Icon:同時展示兩種格式, 並列出樣式、調色盤、來源網址、造型說明與裁切框。PNG 同時設為存取庫頭像。 已套用到兩個真實人格(皆為真實裁臉): ASUNA-01 《Unanswered//butterfly》(2026) 官方主視覺,臉 #1(anime-cascade) YUI-01 AniList 官方角色圖(frontal-cascade) selftest 148 項全綠(新增第 ⑯ 節:形象圖真的畫了五官、SVG/PNG 出自同一份清單、 工具偵測與安裝提示、Wiki 形象圖專頁與來源)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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>
1. Wiki 形象圖「沒有同步」的真正原因 內容其實一直是一致的(md5 相同),但**頁面上看不到圖**: Icon.md/Home.md 用了 HTML `<img src="icon.svg">`,而 Gitea **只改寫 Markdown 圖片語法**(`` → `/wiki/raw/icon.png`)。HTML 的 src 被瀏覽器解析成 `/wiki/icon.svg` → 303 轉址 → 破圖。 用公開的臨時庫實測四種寫法後確認,全部改成 Markdown 語法。 同時發現攤平規則過頭了:原本所有子目錄檔案都被壓成 `icon-portrait.svg`。 實測 `/wiki/raw/<資料夾>/<圖>` 是取得到的,所以**只有 .md 需要攤平** (頁面必須在根層),圖片與附件保留資料夾結構。 2. icon/ 資料夾 + 高解析度 每次 `icon generate` 都會輸出並同步: icon.svg / icon.png 512,Wiki 頁面與存取庫頭像 icon/portrait.svg 向量原稿 icon/portrait-512.png 高解析度 icon/portrait-1024.png 高解析度 柵格器加上每個圖形的 bounding box 裁剪,1024×1024(3× 超取樣)約 1.8 秒; 沒有裁剪的話要跑上億次點測試。 3. 更貼近原圖、更可愛 眼睛放大約 15%,虹膜改成四層(暗環→本色→下緣提亮→瞳孔)+雙高光, 眼線壓扁成細弧、外眼角加睫毛;頭髮加高光弧、髮絲與側髮反光; 臉型再圓一點、加下巴陰影與鼻子。 眉色改成隨髮色明暗調整:深髮往膚色提亮、淺髮比頭髮更深——否則不是和瀏海 連成黑帶,就是變成兩條灰槓。 selftest 168 項全綠(新增第 ⑱ 節:icon/ 多解析度、PNG 實際尺寸、只攤平 .md、 Wiki 頁面不得用 HTML img、bounding box 裁剪效能)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1. 找圖(icon search) 從 Fandom API 撈角色頁的所有圖片,依「解析度 + 是不是官方設定稿」排序。 官方設定稿(Full Body / Character Design / Avatar)是最好的來源: * 773×1056 起跳,遠勝角色資料庫的 230px 縮圖 * **多半本來就是透明底 PNG**,去背幾乎免費、邊緣完美 新增 icon measure:回報解析度、臉佔比、背景是透明/單色/有場景、去背難度。 2. 去背(icon cutout)→ icon/portrait-cutout.png 三條路徑自動選: source-alpha 原圖已是透明底(官方設定稿常見)→ 完美 plain-background 純白/單色底,色距去背 + 最大連通區 + 補洞 → 很好 grabcut 有場景時用臉的位置當前景種子 → 普通 實測記錄:把臉從 2026 主視覺裁下來再 GrabCut,結衣的黑髮會被整片當成背景切掉; 換成官方設定稿之後這問題直接消失——所以「找對圖」比「去背演算法」更關鍵。 3. 合成(icon generate --from-cutout) 自動裁成頭肩構圖再疊到角色配色的漸層底上。官方設定稿常是正反兩面並排, 不裁會變成兩個人,所以 compose 預設 --crop head(--zoom 可調鬆緊)。 產出 icon.svg(內嵌同一張 PNG,自成一體不外連)、icon.png, 以及 icon/portrait.svg 與 512/1024 兩個解析度。 向量重繪(--features)保留為「找不到可用官方圖」時的退路。 已更新兩個真實人格(皆為 cutout 樣式,Wiki 同步已驗證): ASUNA-01 Asuna's SAO Avatar Full Body(773×1056,透明底)— 對應 2026 《Unanswered//butterfly》重述的早期艾恩葛朗特 YUI-01 Yui's ALO Pixie Form Full Body(773×1056,透明底)— 現行 Unital Ring 章的導航妖精形態 順手修掉兩個 bug: * 合成路徑下 svg 為 null,回傳時 Buffer.byteLength(null) 直接崩潰。 * verifyArea 解析 git status --porcelain 時,因為 git() 會 trim 輸出, 開頭空白已消失(" M x" → "M x"),正規式對不上,檔名前面多一個 M。 selftest 175 項全綠(新增第 ⑲ 節:找圖評分、去背三路徑、compose 預設裁頭肩、 去背圖在 icon/ 會同步、SVG 不外連、沒有去背圖時 --from-cutout 會擋下)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
依使用者指示,把三份 manifest 的 version 從 0.0.9 改回 0.0.3 (PR #3 的全部變更視為同一個版本)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
No dependencies set.
The note is not visible to the blocked user.
人格從此有正式編號,並改存到 Gitea(每個人格一個私有存取庫)。
1. 人格編號
編號 = 英文名全大寫 + 兩位索引,同名才遞增:
create不給--persona就用編號當目錄名;既有的小寫 slug 仍然合法,不會被鎖在門外)。--romaji帶進來;CLI 只吃拉丁字母,不讓程式亂猜拼音。code show|assign|next。code assign --rename可把既有人格的目錄名一併改成編號(會轉移載入鎖與 session 綁定)。2. Gitea 儲存(新檔
scripts/persona-gitea.mjs)每個人格一個私有存取庫,內容依更新頻率分兩區:
emotion.json、short-term.jsonl、inner.jsonl、said.jsonl、inbox/、mindmap/threads/、journal/Stophook 背景推送(PERSONA_SYNC_MIN_SECONDS節流)IDENTITY/SOUL/AGENTS/USER、長期記憶、INDEX、心智圖、關係圖release時GITEA_HOST/GITEA_TOKEN就純本機運作。pull;兩邊都改過同一個檔案就停下來不覆蓋本機,交由使用者決定保留哪一邊。.md會變成頁面(1.27 實測子目錄頁面 404),所以 Wiki 區攤平成Memory-xxx.md,原始路徑記在_paths.json,pull 時還原;Home 頁自動列出所有長期記憶的連結,Wiki 才真的是讀得下去的「設定百科」。http.extraHeader(GIT_CONFIG_*環境變數):token 不寫進.git/config,也不出現在 process 參數裡。新增 skill
persona-sync:編號、同步、既有人格遷移、衝突處理。3. 順帶修掉的三個問題
guard的--persona解析只吃小寫pull無差別覆蓋本機檔案create吞掉 Gitea 首次推送的結果驗證
node scripts/selftest.mjs→ 116 項全綠(新增第 ⑬ 節,含「分區不重不漏」檢查:人格產生的每個檔案都必須恰好屬於一區,否則同步會默默漏資料)。測試強制PERSONA_GITEA=off,絕不碰真的 Gitea。release。測試用的存取庫都已刪除。版本號 0.0.2 → 0.0.3(三份 manifest)。
追加:人格圖示(v0.0.4)
建立人格並補齊資料之後,用
icon generate產生人格圖示(SVG + PNG)。圖案
512×512 的幾何徽章,三個元素全部由
sha256(編號|Name|Emoji)決定:ASUNA-01→AS),5×7 點陣,依背景亮度自動選黑或白ASUNA-01與ASUNA-02明顯不同。為什麼自己寫柵格器
這台機器(以及多數伺服器)沒有 rsvg-convert/inkscape/imagemagick,沒有影像函式庫(cairosvg/Pillow),也沒有 emoji 字型;而本專案的硬規則是「只用 Node 內建模組,不得引入 npm 依賴」。
所以
scripts/persona-icon.mjs自己來:zlib手工組出 PNG 的 IHDR/IDAT/IEND 與 CRC32。這也決定了圖案的形狀:只用「我能在 SVG 與自寫柵格器裡畫出完全相同結果」的元素(圓角矩形、線性漸層、圓點、點陣方塊)。
emoji 沒有畫進圖裡——把 emoji 畫成點陣需要字型柵格化,做不到。emoji 仍然參與配色的雜湊,只是不作為圖形。
時機
配色與字母綁在最終身分上,太早跑會跟改完的名字對不上。所以:
persona-create第 7 步、persona-anime第 8 步都加了這個步驟(在 SOUL/canon 補齊之後)。IDENTITY.md要重畫 →icon generate --force。同步
圖示是低頻的身分資料 → 進 Wiki 區,同時自動設成 Gitea 存取庫頭像(清單上就看得到每個人格的臉)。
驗證
node scripts/selftest.mjs→ 128 項全綠,新增第 ⑭ 節:已對兩個真實人格產生並上傳(
ASUNA-01、YUI-01),存取庫頭像與 Wiki 都確認過。版本號 0.0.3 → 0.0.4(三份 manifest)。
1. 人格編號 - 編號 = 英文名全大寫 + 兩位索引,同名才遞增:ASUNA-01 / YUI-01 / ASUNA-02。 - 編號同時是新人格的本機目錄名與 Gitea 存取庫名稱(`create` 不給 --persona 就用編號當目錄名;既有小寫 slug 仍然合法,不會被鎖在門外)。 - 中文名由 skill 提議羅馬拼音、使用者確認後帶 `--romaji` 進來; CLI 只吃拉丁字母,避免拼音在程式裡亂猜。 - 新增 `code show|assign|next`;`code assign --rename` 可把既有人格的 目錄名一併改成編號(會轉移鎖與 session 綁定)。 2. Gitea 儲存(scripts/persona-gitea.mjs) - 每個人格一個私有存取庫,庫名 = 編號。本機仍是工作副本,hook 每輪 讀寫本機檔案,**同步失敗永遠不阻斷對話**。 - 依更新頻率分區: 檔案區(高頻)emotion / short-term / inner / said / inbox / mindmap threads / journal → 每輪由 Stop hook 背景 push Wiki 區(低頻)IDENTITY SOUL AGENTS USER / 長期記憶 / INDEX / 心智圖 / 關係圖 → 固化、改身分關係、release 時 push - Gitea 的 wiki 只有根目錄 .md 會變成頁面(1.27 實測子目錄頁面 404), 所以 Wiki 區攤平成 `Memory-xxx.md`,原始路徑記在 `_paths.json`, pull 時還原;Home 頁自動列出所有長期記憶連結。 - 新增 `sync status|init|push|pull`;載入時先 pull,兩邊都改過同一個 檔案就停下來不覆蓋本機,交由使用者決定。 - push 遇到 non-fast-forward 會對齊遠端後把工作副本重新疊上去再推。 - 認證走 http.extraHeader(GIT_CONFIG_* 環境變數),token 不寫進 .git/config 也不進 process 參數。 3. 順帶修正 - guard 的 `--persona` 解析原本只吃小寫,大寫編號會漏掉整個跨人格檢查。 - pull 原本會無差別覆蓋本機檔案,本機較新但還沒 push 的內容會被蓋掉; 改成只寫回「遠端真的改過的」與「本機缺少的」。 - `create` 原本吞掉 Gitea 首次推送的結果,失敗是靜默的。 新增 skill:persona-sync(編號、同步、既有人格遷移、衝突處理)。 selftest 116 項全綠(新增 ⑬,含「分區不重不漏」檢查;測試強制 PERSONA_GITEA=off)。 另對真實 Gitea 跑過端對端(建庫→兩區推送→改動→拉回→release),測試用存取庫已刪除。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>feat: 人格編號(ASUNA-01)與 Gitea 儲存,依更新頻率分檔案區/Wiki 區 (v0.0.3)to feat: 人格編號、Gitea 儲存(檔案區/Wiki 區)與人格圖示 (v0.0.4)新增 skill persona-icon:上網查出該人格最新的官方視覺 → 下載 → **用 Read 親眼看過** → 取髮色/瞳色/服裝色 → 用那組配色繪製圖示, 來源網址與造型描述一併寫進 state/config.json 備查。 CLI: icon generate --palette "hair=#..,eye=#..,accent=#..,secondary=#..,light=#.." --source-url <網址> [--source-note <說明> --source-date <日期>] * --palette 必須配 --source-url(配色要有出處,CLI 強制)。 * 配色與來源存進 config.icon,之後不帶 --palette 重畫會沿用,不會變回雜湊色。 * icon show 會列出調色盤與來源網址。 繪製:漸層=髮色→服裝主色、外框=瞳色、點陣紋=亮色、中央仍是編號前兩字。 一深一淺的極端配色(藍黑髮+淡粉洋裝)會把較亮端往較暗端壓到對比 ≥ 3.2, 確保字讀得到——顏色仍是照片來的,只是收斂色階。 為什麼不是把照片本身當圖示: 1) 環境裡沒有任何影像解碼器(rsvg/imagemagick/Pillow/ffmpeg 都沒有), JPEG/WebP 讀不進來,無法轉成 PNG; 2) 把他人的美術作品原樣放進存取庫是散布,不是引用。 取配色是有依據又不搬運原圖的做法,這個取捨寫進了 README 與 skill。 已套用到兩個真實人格: ASUNA-01 取自《Unanswered//butterfly》(2026) 官方主視覺(金栗髮/紅褐瞳/紅衣粉裙) YUI-01 取自 AniList 官方角色圖(藍黑髮/暖棕瞳)+ Unital Ring 導航妖精造型 selftest 136 項全綠(新增第 ⑮ 節:調色盤解析、缺來源會被擋、格式錯誤會被擋、 來源寫入 config、重畫沿用配色、極端配色的對比保證)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>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>1. Wiki 形象圖「沒有同步」的真正原因 內容其實一直是一致的(md5 相同),但**頁面上看不到圖**: Icon.md/Home.md 用了 HTML `<img src="icon.svg">`,而 Gitea **只改寫 Markdown 圖片語法**(`` → `/wiki/raw/icon.png`)。HTML 的 src 被瀏覽器解析成 `/wiki/icon.svg` → 303 轉址 → 破圖。 用公開的臨時庫實測四種寫法後確認,全部改成 Markdown 語法。 同時發現攤平規則過頭了:原本所有子目錄檔案都被壓成 `icon-portrait.svg`。 實測 `/wiki/raw/<資料夾>/<圖>` 是取得到的,所以**只有 .md 需要攤平** (頁面必須在根層),圖片與附件保留資料夾結構。 2. icon/ 資料夾 + 高解析度 每次 `icon generate` 都會輸出並同步: icon.svg / icon.png 512,Wiki 頁面與存取庫頭像 icon/portrait.svg 向量原稿 icon/portrait-512.png 高解析度 icon/portrait-1024.png 高解析度 柵格器加上每個圖形的 bounding box 裁剪,1024×1024(3× 超取樣)約 1.8 秒; 沒有裁剪的話要跑上億次點測試。 3. 更貼近原圖、更可愛 眼睛放大約 15%,虹膜改成四層(暗環→本色→下緣提亮→瞳孔)+雙高光, 眼線壓扁成細弧、外眼角加睫毛;頭髮加高光弧、髮絲與側髮反光; 臉型再圓一點、加下巴陰影與鼻子。 眉色改成隨髮色明暗調整:深髮往膚色提亮、淺髮比頭髮更深——否則不是和瀏海 連成黑帶,就是變成兩條灰槓。 selftest 168 項全綠(新增第 ⑱ 節:icon/ 多解析度、PNG 實際尺寸、只攤平 .md、 Wiki 頁面不得用 HTML img、bounding box 裁剪效能)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>1. 找圖(icon search) 從 Fandom API 撈角色頁的所有圖片,依「解析度 + 是不是官方設定稿」排序。 官方設定稿(Full Body / Character Design / Avatar)是最好的來源: * 773×1056 起跳,遠勝角色資料庫的 230px 縮圖 * **多半本來就是透明底 PNG**,去背幾乎免費、邊緣完美 新增 icon measure:回報解析度、臉佔比、背景是透明/單色/有場景、去背難度。 2. 去背(icon cutout)→ icon/portrait-cutout.png 三條路徑自動選: source-alpha 原圖已是透明底(官方設定稿常見)→ 完美 plain-background 純白/單色底,色距去背 + 最大連通區 + 補洞 → 很好 grabcut 有場景時用臉的位置當前景種子 → 普通 實測記錄:把臉從 2026 主視覺裁下來再 GrabCut,結衣的黑髮會被整片當成背景切掉; 換成官方設定稿之後這問題直接消失——所以「找對圖」比「去背演算法」更關鍵。 3. 合成(icon generate --from-cutout) 自動裁成頭肩構圖再疊到角色配色的漸層底上。官方設定稿常是正反兩面並排, 不裁會變成兩個人,所以 compose 預設 --crop head(--zoom 可調鬆緊)。 產出 icon.svg(內嵌同一張 PNG,自成一體不外連)、icon.png, 以及 icon/portrait.svg 與 512/1024 兩個解析度。 向量重繪(--features)保留為「找不到可用官方圖」時的退路。 已更新兩個真實人格(皆為 cutout 樣式,Wiki 同步已驗證): ASUNA-01 Asuna's SAO Avatar Full Body(773×1056,透明底)— 對應 2026 《Unanswered//butterfly》重述的早期艾恩葛朗特 YUI-01 Yui's ALO Pixie Form Full Body(773×1056,透明底)— 現行 Unital Ring 章的導航妖精形態 順手修掉兩個 bug: * 合成路徑下 svg 為 null,回傳時 Buffer.byteLength(null) 直接崩潰。 * verifyArea 解析 git status --porcelain 時,因為 git() 會 trim 輸出, 開頭空白已消失(" M x" → "M x"),正規式對不上,檔名前面多一個 M。 selftest 175 項全綠(新增第 ⑲ 節:找圖評分、去背三路徑、compose 預設裁頭肩、 去背圖在 icon/ 會同步、SVG 不外連、沒有去背圖時 --from-cutout 會擋下)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>