# 更新记录 ## 1.0.12 - **新增皮肤自带的「自立协调器」**:装不到 `@dsh-eac/ui-skin-loader` 时不再各自 standalone 生效 (那会所有面板都在、所有观感叠加),改由一个轻量协调器统一管理。 - 协调器实现与皮肤控制台同形的 5 个方法(`registerSkin` / `list` / `current` / `switchTo` / `subscribe`), 所以「皮肤」选择器、激活/停用、面板显隐全部复用既有代码 —— 一行 UI 都没改。 - 行为:同一时刻只激活一款皮肤;当前生效那款的面板里可直接切到另一款或「原生(默认观感)」; 设置页另有一个常驻的「皮肤」小节,避免选中原生后没有面板可切回来;选择持久化 (`dsh.skin.standalone.v1`),重启后按上次选择恢复。 - **只在自己的一套键下工作**,不占用加载器保留面:`window.__dshSkinStandaloneV1` / 设置键 `dsh.skin.standalone.v1` / 槽位 `skin-standalone-selector` / locale `skn-standalone` (未用 `usl-`、`dsh-ui-skin-loader`、`io.github.dsh-eac.skin.loader.*`)。 - 装了真加载器时**绝不介入**(`uiSkinLoader` 在宽限窗口内出现就走控制台路径);真加载器后到会整体让位。 - 暴露的皮肤模式新增 `coordinated`(= 协调器托管),与 `console` / `standalone` 区分,便于观测。 - 新增 `tests/standalone-coordinator.mjs`(15 项断言):无加载器时单例激活 / 切换互斥 / 回原生 / 持久化恢复 / 有加载器时不介入。CI 走内建对端,不依赖同级仓库。 - 仲裁器保留为安全网:对"未接入协议的第三方"仍保证写入有界(`tests/scheme-conflict.mjs` 已改为专测该场景)。 ## 1.0.11 - **修掉"没装加载器 + 装了多个皮肤"时的致命互写**:本皮肤与另一个同样驱动宿主亮暗开关的皮肤 (如 PRTS)同时生效时,双方的 `MutationObserver` 会互相复写 `body[data-ds-dark-theme]`, 形成**微任务级死循环**——渲染进程事件循环被完全占死(界面点不动、白屏), 同时不断分配对象,内存约 1GB/分钟暴涨(实测把 16GB 机器吃到只剩 800MB)。 - 写入权现在收敛到 `window.__dshHostSchemeArbiterV1`:同一时刻只有一个持有者能写这个属性, 未持有者只登记期望值、绝不写 DOM;持有者释放后按优先级移交给等待者。 ABYSSAL 是纯暗色皮肤(无法工作在亮色宿主下),优先级 100,高于可切亮暗的 PRTS(50), 因此结果与 bundle 加载顺序无关。 - 落败方会打一条可操作告警(提示安装 `@dsh-eac/ui-skin-loader`,由加载器保证同时只有一个皮肤生效)。 - 另配写入熔断:遇到没接入本协议的第三方反复改写时,1 秒内超过 20 次即停手并提示,不再把浏览器拖死。 - 装了加载器(同一时刻只有一个皮肤生效)时行为完全不变。 - 新增 `tests/scheme-conflict.mjs`:真 Chrome 里同时以 standalone 激活两个皮肤,断言改写次数有界、 所有权唯一、优先级生效、释放后移交。对补丁前的代码会因事件循环被卡死而失败。 ## 1.0.10 - **新增"浅底可读性"派生逻辑**(防御性):若将来加入浅色调色板,文字/标签/品牌类 token 会自动换成 同色相压暗档,保证与背景 ≥4.5:1;当前四套底(深海/午夜/墨黑/极地)都是深色,逻辑不触发、观感不变。 - 新增 `tests/contrast.mjs`(31 项):遍历每个强调色 × 深海/墨黑两种底,验证文字 token 对比度 ≥4.5:1。 - 断言总数:31 + 18 + 9 + 31 + 6 = **95 项**。 ## 1.0.9 - **修好"控制台看不到皮肤"这类竞态**:皮肤不再在加载瞬间判断"有没有控制台",改为 `ctx.inject(["uiSkinLoader"], cb)` **显式等待**服务出现 —— 控制台迟到一步也不会被误判成"没装",仍会正常登记托管。 - **没装控制台也能用**:等待 3 秒宽限后进入自立模式,自动应用外观,设置面板照常可用。 - **新增「皮肤」选择器**(设置面板),第一项是 **「原生(默认观感)」= 还原默认皮肤**: - 有控制台 → `switchTo("default")`(与控制台"还原默认观感"同一路径,持久化归它); - 自立模式 → 关掉自己(`enabled=false`),立即卸下、长期保持原生,随时可切回。 - 统一接口补充 `isActive()` / `mode`。 - 新增 `tests/console-wait.mjs`(18 项,含"控制台迟到不许误判"回归闸门)与 `tests/skin-selector.mjs`(9 项)并接入 CI;当前断言总数 **64 项**。 ## 1.0.5 - **补上"依赖皮肤加载器"这件事的可见性**。本皮肤是纯观感包,靠 `inject: ["uiSkinLoader", …]` 等待 第三方皮肤加载器(参考实现 `@dsh-eac/ui-skin-loader`)下发 SkinContext。此前若安装者没装加载器, 插件会**安静挂起**——不报错、也没效果,容易被误判成"装失败"。现在: - 宿主半新增**依赖自检**:启动后延迟 4 秒确认 `uiSkinLoader` 是否可用,缺失时打印可操作提示; - `package.json` 增加 `dsh.skin.requires` 元数据(服务名 + 参考实现 + 说明); - README 增加「前置要求」小节(含"没装会怎样"的对照表);安装脚本增加装载前预检; - 新增 `tests/dependency-check.mjs`(6 项断言:缺服务必警告 / 有服务保持安静 / `ctx.get` 亦识别 / 卸载后不再触发),并接入 CI。 - 说明:加载器是第三方插件、不随本包分发,也不写进 npm 依赖(它在 registry 上不存在,声明成 peer 反而会让安装失败)。 ## 1.0.4 - **修:宿主把应用切到亮色时,深渊会被"污染"**。宿主的亮暗开关是 `body[data-ds-dark-theme]`, 它自己会在主题切换时重写这个属性;深渊是纯暗色皮肤,此前只在激活时置位一次, 被宿主摘掉后宿主 light 分支的 `--dsw-specific-*` 等 token 就会漏进来(表面变浅、字色错位)。 现在加了 `MutationObserver` 盯住该属性并复位到皮肤的期望值,teardown 时断开。 - 新增端到端扫测覆盖该场景(模拟 `prefers-color-scheme: light`),22 项全过。 ## 1.0.3 - **命名空间去个人化(破坏性变更)**:包名统一为 `dsh-skin-abyssal`,皮肤 id 统一为 `skins.abyssal`,主题 id 为 `skins-theme-abyssal`,cordis 行 id 同步调整;作者、版权署名 与文档里的本机绝对路径一并去个人化(旧值带个人标识,此处不再复述)。 **升级需重装一次**并把 profile 里 `activeSkin` 改为 `skins.abyssal`(README 有步骤)。 - **修:主题重复注册会把整次激活回滚成默认皮肤**。皮肤被重新加载(模块重新求值)后, 新实例会在旧实例尚未拆除时注册同名主题,宿主抛 `theme "..." is already registered; rolled back to default`。 现在注册走 `registerThemeSafe`:重复 id 时自动改用带序号的 id 兜底,激活不再整体失败。 - 新增该场景的回归测试(把 fake theme API 改成"重复 id 必须抛错",并模拟皮肤重载后 第二个实例激活)。断言数 30 → 31。 ## 1.0.2 弹窗与表面可读性修复(在真实 DSH 页面上实测定位)。 - **弹窗不再透出正文**:宿主设置弹窗的面板用的是 `--dsw-alias-bg-layer-2`,此前为 `rgba(24,32,44,.54)`(半透明)。现提升浮层类表面:`bg-layer-2 → .97`、`bg-layer-3 → .90`、 `bg-overlay → .97`、`bg-module-platform → .86`、`bg-multi-select → .70`; 页面底色(`bg-base .70`)与页内卡片(`bg-layer-1 .58 → .72`)保留玻璃感。 - **浮层实色兜底规则**:`[role="dialog"] / [aria-modal="true"] / [role="menu|listbox|tooltip"]` 强制 `rgba(24,32,44,.97)` + `backdrop-filter: blur(22px)`,不依赖宿主继续用哪个 token。 - **补齐宿主 specific 表面层**:新增 `--dsw-specific-input-major`(输入框)、 `--dsw-specific-selector` / `-tip` / `-bubble` / `-bubble-highlight` / `-menu` / `-login-input`、 `--dsw-menu-surface-fill`、`--dsw-linear-gradient-think` / `--dsw-linear-think-select`。 此前这些表面留着宿主原值(输入框在暗色下偏灰、菜单不透)。 - **驱动宿主亮暗开关**:激活时置 `body[data-ds-dark-theme]`,退出时按原状还原; 避免宿主 light 分支的 `--dsw-specific-*` 定义漏进来。 ## 1.0.1 - 修 `lib/client.js` 的 `SyntaxError: Unexpected token '+'`(计算属性名需 `[ "data-" + ID ]`)。 - 补 `registerSkin` 载荷缺的 `preview` 字段。 ## 1.0.0 - 首个版本:4 底色 × 5 强调色 × 3 圆角密度 × 3 极光强度 + 胶片颗粒; `theme.overrideTokens` 承载观感,`settings.section` 席位挂外观面板; 30 项浏览器断言全过(后续版本增至 31)。