06-font-and-fallback-policy.md 21 KB

字体授权与缺失资源降级

Type: grilling Status: resolved Labels: wayfinder:grilling Blocked by: 01, 02

Question

正式字体、图标、状态资源或装饰资源缺失、不可授权、加载失败、尺寸不合格或与部署环境不兼容时,系统如何处理?裁定 Web 字体的授权证据、可接受的回退字体、逐项资源的降级层级、用户可见提示、日志/诊断信息,以及何种缺口阻止发布、何种缺口允许带回退交付。

降级必须可见且不把临时资源误报为正式设计资产;不能因为单个资源失败而静默破坏整个驾驶舱。

进度

  • 已认领(Status: claimed);阻塞票 01/02 均 closed。票 03(token 槽位)、票 04/09(manifest 降级链)、票 05(位置符号)均已完成。
  • deck 工具已按插件要求上报本票(带 effortId=lanhu-cockpit-asset-replacement)。
  • 事实侧已自查(不向维护者提问可自得的事实):
    • tokens.css 现有 --font(Microsoft YaHei UI/Microsoft YaHei/PingFang SC/Noto Sans SC)与 --num(Bahnschrift SemiBold/Bahnschrift/DIN Alternate/Segoe UI Semibold)都是系统字体栈,非 Web 字体。
    • 票 04/09 已锁 manifest 降级链(显式 fallback → 有限链 → 内置通用资源)、核心资源整包回滚、分环境诊断;票 05 已锁位置符号降级。本票不重开这些机制。
  • 维护者指定字体目录 E:\_Design\字体,实测结论见下节。

字体目录实测事实(本票自查,非推断)

对 E:\_Design\字体 做了完整取证(递归列举 + 字体内嵌元数据提取):

  • 目录结构:68 个 zip(合计 707.7 MB)+ 中文/(65 个文件,515.8 MB)+ 英文/(15 个文件,1.3 MB)。
  • 授权文件:零命中。递归搜索 license|licence|readme|授权|许可|声明|OFL|copyright|商用 无任何命中;字体.zip 的 82 个条目同样零命中。
  • 确证开源(内嵌版权/许可文本可查):
    • SourceHanSansSC-* 与 SourceHanSansCN-VF:2014-2021 Adobe, with Reserved Font Name 'Source' → 思源黑体(OFL)。
    • SourceHanSerifCN-*:Copyright 2017 Adobe Systems Incorporated … Reserved Font Name 'Source' → 思源宋体(OFL)。
    • CrimsonText-*:Copyright (c) 2010, Sebastian Kosch … with Reserved Font Name → SIL OFL 开源西文。
  • 明确保留所有权利(与「整目录免费可商用」矛盾):Modernia-Regular(Copyright © 2019 … All rights reserved)、Furore(Copyright (c) 2009 … All rights reserved)。
  • 无许可文本(名字暗示免费但未确证):SmileySans(得意黑)、PangMenZhengDao…MianFeiBan、【MianFei】CangJi…、ZQKfreefont、Versa、SendaDisplay-BECO 等。
  • 公认商用收费字库(高风险):douyuFont(斗鱼)、PingFangLaiJiangHuFeiYangTi、JiYingHuiPianHuiSong、TaiWanQuanZiKuZhengKaiTi、UnBatang、GenShinGothic、AozoraMincho、SoukouMincho、DelagothicOne、HuXiaoBoNanShenTi、HongLeiXingShuJianTi、Mengshen-Handwritten 等。
  • 体积参考(二进制字节实测):思源黑体单字重约 15–16 MB(SourceHanSansSC-Regular 15.7 MB、SourceHanSansSC-Bold 16.2 MB);思源宋体 SourceHanSerifCN-Regular 10.7 MB;西文 CrimsonText-Regular 仅 0.1 MB。中文全量内置的体积代价远高于西文。

结论:该目录是字体文件集合,不是已核验的合规库;「整目录免费可商用」的说法与实测不符(Modernia/Furore 明确保留所有权利)。

第一轮裁定(已确认)

  • Q1=B:无书面授权证据不得内置字体文件;运行时回退到已批准的系统字体栈,并在缺口清单记为「设计字体未接入」,缺口可见但不阻断整批交付。
  • Q2=B:授权证据需书面/电子文件(许可协议、采购凭证或权利人声明),明确覆盖 Web 嵌入与商用范围,注明字体名称与版本。补充裁定:系统自带字体不属于可再分发字体,只能作回退栈,不得打包进产物。
  • Q3=B:数字字体与正文同规;若不可授权,回退必须选度量兼容(字宽/字高接近)的备选,避免大屏 KPI 数字换字后跳格。
  • Q4=B:仅三类缺口阻断发布——① 核心资源组(品牌标识、点位/设备状态形状语义、状态色)不可用;② 视觉会误导业务语义(如状态色缺失致报警与正常无法区分);③ 法规/授权风险(无授权字体、无授权品牌素材)。其余缺口允许带回退交付并列入缺口清单。
  • Q5=B:三层可见——① 运行时诊断(开发/测试可见语义 key 与失败类别);② 交付缺口清单(语义 key、缺口类型、回退结果、责任人);③ 生产界面只显示用户可理解提示,不暴露内部路径。
  • Q6=B:临时资源必须带临时标记;验收不得以临时资源作为正式视觉通过;缺口清单必须列出仍未替换的临时项。

第二轮裁定(已确认)

  • Q7(维护者原话:尽量以现有情况为基准)+ Q11=A + Q15=A:统一原则——优先沿用现有渲染尺寸与既有实现,只有素材在现有尺寸下确实不可辨时才做最小调整并记录偏差;该原则同时适用于字体,Web 字体属「可选优化」而非「必需修复」。这消除了票 05 遗留的「内层图标 10.8px 是否需调整」的处置口径。
  • Q8=A:本票只新增字体授权裁定与缺口分级,不重复定义降级链、回滚或诊断字段(避免与票 04/09/05 形成两套说法)。
  • Q9=A:字体目录采用白名单制;未入白名单者按 Q1 走回退,待逐项核验后再进白名单。
  • Q10=C:不引入任何商用字体,只用开源白名单与系统字体栈。因此不存在「向设计公司索取商用字体授权凭证」的工作项。
  • Q12=A:严格白名单——只放行本目录内确证带开源许可文本的字族:思源黑体 SourceHanSans*、思源宋体 SourceHanSerif*、CrimsonText*。其余(含名字暗示免费的得意黑 SmileySans、ZQKfreefont、PangMenZhengDao…MianFeiBan、【MianFei】CangJi…)一律按无证据处理;若要纳入,须先把上游 OFL 许可证文本归档进交付包,方可从「名字暗示」升级为「确证」。
  • Q13=A:--font / --num 的语义槽位不动(票 03 已锁),本票只给出可接入字族白名单;是否启用由实现按观感决定。明确不强制用思源黑体替换现有系统栈(体积风险)。
  • Q14=B:大体积中文字体必须子集化(仅收驾驶舱实际用字)或限定字重数量(如 Regular + Bold 两档),并在缺口清单记录被裁字符集风险。子集字体必须保留系统字体回退链——因为动态数据(设备名、点位名、事件文本)可能含子集外汉字,单独使用会出现豆腐块。

Answer

本票不重开既有降级机制,只锁定「字体授权」与「缺口分级」两件事;字体采用严格开源白名单 + 系统回退栈,任何未确证授权的字体一律不内置。

字体授权

  1. 授权门槛:字体内置需书面/电子授权证据,明确覆盖 Web 嵌入与商用范围并注明名称与版本;系统自带字体只能作回退栈、不得打包。
  2. 严格白名单(本目录内确证):思源黑体 SourceHanSans*、思源宋体 SourceHanSerif*、CrimsonText*。未入白名单者按无证据处理,走系统回退。
  3. 不引入商用字体;因此不存在商用字体授权索取工作项。
  4. 槽位归属不变:--font / --num 的语义槽位仍归票 03,本票只给可接入字族集合,不强制替换现有系统栈。
  5. 交付约束:中文字体必须子集化或限定字重档数,且必须保留系统回退链(动态数据可能含子集外汉字)。
  6. 数字字体:若不可授权,回退须度量兼容,避免大屏 KPI 数字跳格。

缺口分级(阻断 / 允许带回退)

  • 阻断发布(三类):核心资源组不可用;视觉会误导业务语义;法规/授权风险。
  • 允许带回退交付:其余缺口,条件是①记录进缺口清单(语义 key、缺口类型、回退结果、责任人);②验收不得把临时资源当正式视觉通过;③临时资源必须带临时标记。
  • 可见性三层:运行时诊断(开发/测试)→ 交付缺口清单 → 生产仅显示用户可理解提示,不暴露内部路径。

与既有裁定的关系

  • 不重开:降级链与 fallback 顺序归票 04/09;位置符号降级归票 05;token 槽位语义归票 03。
  • 统一原则:尺寸与字体一律「优先现状,仅在不可辨时最小调整并记录偏差」(Q7/Q11/Q15)。

风险与边界

  • 目录非合规库:E:\_Design\字体 零授权文件且含明确保留所有权利的字库(Modernia/Furore)与多款公认商用收费字库;因此不得以目录为单位放行。
  • 子集化风险:子集外汉字会落到回退字体,可能出现同屏字形混排;实现需在走查中确认动态文本仍可读。
  • 本票不声称已接入任何 Web 字体、已子集化或已替换现有系统栈;这些属实现工作。
  • 按 AGENTS.md,本轮未运行 build/dev/浏览器调试。

真实状态与下一步

  • 状态:已完成并关闭(Status: resolved)。Q1–Q15 全部有裁定,无遗留未决项。
  • 交付物:
    1. 本票 Answer(上述结论);
    2. 规格子票字体授权与缺失资源降级规格(ready-for-agent,已挂入同一张地图);
    3. 交叉引用修正:既有运行时资产 manifest 与版本策略规格使用了「核心资源组」与 核心标记 字段但未定义成员,已加指针指向本票规格补全的定义(只加指针,不改其原口径)。
  • 对抗式审查记录(2026-10-08):规格发布后对本次产出做了对抗式复核。
    1. 抓到并修正 1 处事实错误:曾把思源黑体体积写作 16.4 MB / 17.0 MB,二进制字节复核实为 15.7 MB / 16.2 MB(原数字取自目录列表中混入的其他条目)。已更正并复检无残留。
    2. 抓到并补全 1 处真实缺口:既有资产清单规格使用「核心资源组」概念却未定义成员,本票规格补全了成员定义并建立双向交叉引用,避免读过其中一个规格的人找不到定义。
    3. 核实通过:零授权文件断言(递归命中 0);Modernia / Furore 的 All rights reserved 原样命中;白名单文件均真实存在;能力边界表述未越界(3 处均明确「不声称判定授权合法性」);与票 03 槽位归属不冲突;未重复定义票 09 的降级链与回滚。
  • 下一步:推进设计稿差异与现有业务结构保护(其阻塞票 02–06 均已关闭);实现工作由规格子票承接。

缺口清单

执行批次归视觉的偏差与未替换临时项登记于此(唯一来源;语义 key、缺口类型、回退结果、责任人四列齐全)。

语义 key 缺口类型 回退结果 责任人
icon.brand 已关闭:已替换为蓝湖正式切图(nav/title-bg 品牌标题底板,90×34@2x) 正式切图,manifest status: formal —(2026-10-12 批次 1 关闭)
icon.layers 已关闭:已替换为蓝湖正式切图(网格,15×15@2x) 正式切图,formal —(2026-10-12 批次 1 关闭)
icon.points 已关闭:已替换为蓝湖正式切图(水滴,16×15@2x) 正式切图,formal —(2026-10-12 批次 1 关闭)
icon.event 已关闭:已替换为蓝湖正式切图(警告三角,24×24@2x) 正式切图,formal —(2026-10-12 批次 1 关闭)
icon.resource 已关闭:已替换为蓝湖正式切图(火焰,15×15@2x) 正式切图,formal —(2026-10-12 批次 1 关闭)
icon.blank 设计稿未覆盖:空面板占位图示在蓝湖稿中无对应物 维持现状:内联几何迁移的临时 SVG(manifest status: temporary)+ 标记「无设计稿依据」 维护者/设计方

(2026-10 批次 1 执行时登记,见执行-批次1:品牌/图标替换。)

2026-10 更新一(依据票 19 盘点报告):上表六条原记为「正式素材未交付(蓝湖盘点未完成)」。旧版盘点完成后事实修正为「设计稿未覆盖」——旧版蓝湖画板中品牌位无 logo 图形、四个功能图标在稿中为纯文字 chip,故不存在"待交付的正式切图"。

2026-10-12 更新二(蓝湖已更新正式切图,批次 1 重做):蓝湖 9 个画板全部升版(v3/v4,更新时间 2026-10-12),AI 生成底图与全部位图填充被移除,正式切图标记由 27 个增至 71 个。其中五枚与驾驶舱语义 key 对应(品牌标题底板、网格、水滴、警告三角、火焰),已入库并登记 formal,对应缺口关闭。「设计稿未覆盖」现仅剩 icon.blank 一条。

2026-10 更新三(批次 4 字体接入,票 17):字体白名单经维护者裁定扩展为六族(原三族 + 设计稿实际使用的 Noto Sans SC / Rajdhani / Share Tech Mono,均 OFL 且已归档上游许可证文本)。本批实际嵌入正文字族与数字/等宽字族(子集化,合计 446 KB)。下表新增字体相关条目:

语义 key / 字族 缺口类型 回退结果 责任人
font.body.*(Noto Sans SC Subset) 已关闭:设计稿正文(913 处)已接入 正式 Web 字体,licenseId=ofl-noto-sans-sc —(2026-10 批次 4 关闭)
font.num.*(Rajdhani / Share Tech Mono Subset) 已关闭:设计稿数字/等宽(163 / 134 处)已接入 正式 Web 字体,licenseId=ofl-rajdhani / ofl-share-tech-mono —(2026-10 批次 4 关闭)
全部子集字体 子集外字符走回退(预期行为,规格 11 Q14):子集只收驾驶舱静态用字 1435 字,后端动态文本(设备名 / 点位名 / 事件文本)中的生僻汉字不在子集内 落到 --font / --num 系统回退链(Microsoft YaHei / PingFang / Noto Sans SC);需走查确认动态文本无豆腐块 维护者(走查)
--num 数字字体 度量偏差(逐字差 > 0.05 em,共 16 项):Rajdhani 的 '5' '7' '-' '(' ')'(−0.06 ~ −0.17 em)与 '%'(+0.05);Share Tech Mono 的 '1' '.' ':' '/' '(' ')' '%' '-'(−0.15 ~ +0.31 em) 数字内部等宽性不劣于原字体(Rajdhani 0.203 / Share Tech Mono 0.000 vs Bahnschrift 0.236 em),未引入新的抖动来源;逐字观感偏差由走查判定 维护者(走查)
Noto Sans SC Medium 字重 字重档数限制(规格 11 Q14 允许「限定字重档数」):只嵌入 Regular + Bold,设计稿 Medium(85 处)不单独嵌入 落到 Regular/Bold 或浏览器合成字重;需走查确认可接受 维护者(走查)
思源黑体 / 思源宋体 / Crimson Text 白名单内、本批未嵌入:许可证据已归档(public/cockpit/assets/fonts/licenses/),但设计稿无消费点,嵌入即为死资源 不参与渲染;白名单内随时可启用 维护者(如需启用)
Alimama FangYuanTi VF(设计稿 18 处) 无授权证据,未接入:虽称免费商用但未归档授权证据,按无证据处理(严格白名单制) 走系统回退链;不阻断发布(非核心资源组,且不误导业务语义) 维护者/设计方(要纳入须先归档授权证据)
PingFang TC / MO / HK / SC(设计稿 99 处) Apple 系统字体,不可 Web 嵌入(规格 11 已锁) 只作回退栈;--font 回退链已含 PingFang SC,非 Apple 环境落到 Microsoft YaHei —(已锁,无需处置)

(2026-10 批次 4 执行时登记,见执行-批次4:字体接入与批次 4 验收说明。)

2026-10-13 更新五(批次 4 收口,票 17 第五至十一轮):

语义 key / 字族 缺口类型 回退结果 责任人
font.title(标小智无界黑 LogoSC Unbounded Sans) 已撤销:第五轮曾嵌入(OFL 子集 195 KB)用于顶栏菜单,第七轮维护者否决观感且 D2 取证证实设计稿菜单为 PingFang 常规体(走系统回退栈);槽位与嵌入撤销,许可证据保留归档(embedded:false),恢复只需重跑 build-fonts.py 无死资源;顶栏菜单走系统黑体(--font-topbar),主标题为切图不需字体 —(已关闭)
--font-topbar(系统黑体) 新增语义 token(第四轮):筛选条/状态 chip 等小字回系统黑体(子集 Noto 在小字号+辉光下发虚,维护者确认);非缺口,是规格 03「按需新增语义 token」的正规落点 系统黑体栈,与 --font 回退链同源 —(已关闭)
顶栏菜单字体 设计稿差异(第七轮取证):设计稿 PingFang TC-Regular/Semibold 为 Apple 系统字体 按规格 11 走系统回退栈不打包(Windows 落 Microsoft YaHei UI);选中态语义靠白色+Semibold+切图底板表达 —(已关闭)

2026-10-12 更新四(批次 2 执行时登记,见执行-批次2):

语义 key 缺口类型 回退结果 责任人
token.fs.*(可读性偏差) 设计稿字号 10–12px 运行时不可读 运行时值 11.5–14u(批次 1 维护者走查上调 +1px,经维护者确认沿用为基准);影响全部文字消费组件 维护者(已确认)
token.panel-gradient 设计稿九停、运行时三停;维护者另要求降低地图透底干扰 最终 top rgba(2,9,27,.88) / mid rgba(0,28,70,.82) / bot rgba(0,15,52,.90),CockpitPanel blur(12px) saturate(115%);原设计对应不透明度 .28/.20/.38;影响面板和详情底色 维护者(已要求并反馈基本无问题)
token.fs-standalone 品牌主标题 21u、入口页大标题 26u 为独立档位,无语义槽位 保留裸 calc(N * var(--u))(>15u,不在归并范围);影响 CockpitShell 品牌位 / CockpitIntro 标题 维护者(签收时复核)
token.column-detail-width 维护者要求两侧栏减宽并扩大设备详情 栏宽347u→330u;锚定详情默认340→480px、上限560px并按画布宽收敛;固定详情同步加宽 维护者(已确认)
token.point-status-colors 蓝湖/原实现四种中性状态共用灰色难辨 离线银灰、无设备浅灰、未知紫、未关联橙;point-* tokens同步统计、标签、地图;业务状态与优先级不变 维护者(已确认)
token.chart-categories 原单色图表难分工单及其他类别 行业四语义色、八分类色;已取消红/延期黄/结案绿;各图表共用tone映射,不声称全为设计稿实测色 维护者(已确认)
ui.section-status-dot 数据状态胶囊占宽;维护者要求圆点与标题右对齐 状态文字保留无障碍与hover/focus提示,圆点在标题行右侧;统计字段完整换行、里程独行、图例信息包在框内 维护者(已确认)

2026-10 更新六(批次 5 装饰执行时登记,见执行-批次5与批次 5 验收说明):

语义 key 缺口类型 回退结果 责任人
decor.grid-scanline-vignette 设计稿未覆盖(现状维持,P3):全局细网格、地图扫描线、地图/引导暗角、面板辉光与 L 形切角、氛围径向辉光在蓝湖 9 画板中无对应图层,属现有实现自己的氛围增强 按规格 12「设计稿未覆盖项维持现状」保留;全部代码化(CSS 渐变/mask),无位图资源;未声称有设计稿依据 维护者(走查复核)
decor.brand-pool 光池为推断消费点(P3):D6 品牌标题后方 489×128「光」位图按设计 realFrame 等比铺放,但标题在运行时定稿为 404u(非设计 470 逻辑尺寸),偏移 -19,-1 按比例换算,非像素级对位 已入 manifest icon.brand.pool(formal)+ 语义注入;观感偏差走查判定,偏差只调 CSS 不动素材 维护者(走查)
decor.unconsumed-candidates 11 个装饰候选无消费点(brand-glow-1/3、panel-corner-*×4、panel-subtitle-*×2、select-bg*×2、topbar-line):设计方切图批次里含这些图,但驾驶舱无对应落点 按共识 §1「没有消费点的图不进运行时」挪入设计归档 unconsumed-decor/(LEDGER.md sha256 台账);将来设计确认落点后从归档恢复、登记、接线 维护者/设计方
decor.panel-corner-color 四角切角色值收口(非缺口,留痕):4 处 data-URI 内联主蓝色值改为白几何母版 + mask 染 --panel-line-hi;观感应与改前完全一致 色值单一来源达成;走查若发现染色异常按走查单 §4 判缺陷 维护者(走查)