D-20260704-01|主題系統三件套(token+manifest+fallback)¶
背景與驅動力¶
使用者提案:樣式 / 圖檔 / 圖示 /LOGO/ 音樂與程式碼脫鉤——程式碼只保證流程與功能(只認 token 名與資產 key),外觀交給主題;個人選單選主題、主題可分類、逐主題累積歷史(社群討論與分辨的單位)。討論兩輪定案落 spec,新立 canon 主題系統.md 與 impl 程式架構/themes.md。
考慮過的選項¶
- 分類做成程式側 enum:分類現階段無法確定、日後必須可變更,寫死程式即每次調整都是程式變更——否決。
- 主題資產共用混放 / 跨主題引用:磁碟混放、垃圾檔無從機器驗證——否決,共用一律靠 fallback。
- 主題 id 兩案皆否決:純語意名(先到先得 +review 仲裁命名)使搶名有利可圖、純 UUID(自產免仲裁)可讀性歸零——收斂混合案。
- token+manifest+fallback 三件套(採納)。
決定¶
- 三件套模型:token(CSS custom properties+ 資產 key)+manifest(
theme.json:id、內嵌多語系 name、category、authors、version、tokens、assets)+fallback(主題只放要覆蓋的、缺項 runtime 落 default;default=fallback 骨幹、CI 驗完備、SW install 預快取,其他主題 lazy 首載不含)。 - 分類 = 資料非程式 enum:
categories.json註冊表(id+i18nKey、顯示名走字典四語系);起始僅basic,累積後 PR 加分類 + 改各主題 category 欄——演化 = 純資料 patch、零程式變更。 - 資產依主題隔離:
themes/<id>/自包含、磁碟零混放、禁跨主題引用;validate 雙向查(引用檔案存在 + 資料夾檔案全被引用)。 - 主題 id= 混合案
<slug>-<6 位自產隨機尾碼>(default為唯一免尾碼保留 id;slug 不獨占、搶名無意義);id 不可改,僅授權 / 法律下架時登錄themes/retired-ids.json永久退役、CI 拒重用。 - 鐵則:只換皮、不換語意 / 佈局;gameplay 資訊視覺保留 token
THEME_RESERVED_TOKENS不可覆蓋(CI+runtime 雙防);品牌錨點(OG/manifest icons)固定;主題屬純 client 資源 =patch 發版、不上鏈不影響配對;主題與 i18n 正交。
附帶決策¶
音樂面採播放槽模型(2026-07-05 同脈絡定案):槽位名錄非檔案清單、有檔才播(槽空 = 靜音非錯誤)、default 名錄必列全但值可空;三態語意(路徑 / 省略 = 落 default/null= 明確靜音);保留 SFX 槽 THEME_RESERVED_SFX 恆取 default;轉場常數 BGM_CROSSFADE_MS=1000。同輪砍除場地綁定音樂與玩家自訂 BGM。細節見 程式架構/audio-system.md。
AudioContext 的使用者授權與即時執行狀態分離:首次手勢取得本 session 的 unlocked 能力,後續 pointerdown 或回 visible 可對已解鎖、再次 suspended 的 SFX/world context 做 state-aware、 single-flight resume;running/closed 不動,失敗留待下一手勢。此恢復不得重播 BGM。
後果與影響¶
外觀演化與程式發版脫鉤,社群主題走 PR(validate、review 含資產授權聲明、patch 隨版發);BGM 主題化承接音樂方向懸案。樣式(皮膚)面架構其後由 D-20260723-01 修訂為受控 CSS Style API;token 治理由 D-20260708-10 細化為兩層。