impeccable typeset 全流程指南:在不推翻视觉身份的前提下打磨字体层次、阅读体验与字体交付
字体的本质是信息、层级与声音的载体。impeccable 项目的 typeset 命令(定义为 "Improve typography hierarchy and fonts")是一条面向 AI 设计助手(Agent)的排版专项参考指令,它的工作原则很克制:在既有视觉世界内部改良字体,除非用户明确要求,否则绝不擅自替换产品身份。本文以 .rovodev/skills/impeccable/reference/typeset.md 为骨架,结合同一技能库的 SKILL.md、live.md、new-work.md 与 iOS/Android 平台规范,完整还原并深入讲解这套排版的评估—设系统—落地—验证工作流,读完你将掌握:如何按访问者模式决定排版的表达边界、如何用双通道独立评估找出真正的问题、如何用最少角色与字族建立不可混淆的层级、如何保证阅读度量(measure)、行高、字距、深色表面补偿等细节落地,以及如何在 Live 变体模式下用受控的 scale 参数为字体排印开放试错空间。
一切从既有世界出发:先确认"是否换脸"
排版改良不是从白纸开始的。文档开篇即给出铁律:Typography carries information, hierarchy, and voice. Improve it inside the established visual world; do not replace the identity unless the user asked to. 即先确认当前代码与 DESIGN.md 中已确立的字族、字重与角色分工,再在其上改良使用方式。
这里有一条关键的边界判定:
- 如果替换字体会产生一套新的视觉身份,必须改道走 new-work.md 的"新视觉工作"流程,并在完成后更新 DESIGN.md——因为 DESIGN.md 是产品持久视觉决策的载体,字体身份的变更属于系统级决策,不能作为一次局部排版微调悄悄完成。
- 否则,保留已确认的字族,只改进它们的使用方式。
new-work 流程(见 .rovodev/skills/impeccable/reference/new-work.md)给出了判断既有事实的方法论:DESIGN.md 缺失不等于绿地项目;缺失的 DESIGN.md 不抹去代码中已经一致的视觉身份——"Visual authority is evidence, not a filename"。排版评估同样适用这一原则:已确认的字族是权威证据,要在它们之上建立更清晰的排印,而不是用"换个更好看的字体"来回避结构问题。
用访问者模式决定表达边界
impeccable 的核心框架是四种访问者模式(来自 SKILL.md:Persuade / Operate / Read / Experience),模式命名的是"这个表面的成功长什么样"。typeset 指令把模式直接映射为排版的表达权限:
| 模式 | 排版表达边界 |
|---|---|
| Persuade + Experience | 展示级(display)字体可以承担"声音/性格"的职责;当构图受益时,允许果断的对比与响应式字号 |
| Operate + Read | 稳定、可扫读、度量优先;一个精调的字族加一套固定的角色刻度往往就是正确答案 |
| Native(iOS / Android) | 遵循对应平台规范,包括平台缩放与无障碍行为 |
一句话概括:营销与作品集页面允许展示字体替产品发声,而工具型、文档型界面要的是稳定与可扫读,展示欲让位于任务完成。模式的判定依据是请求的表面对应什么模式,而不是产品整体——一个工具的落地页仍是 Persuade,一个时装品牌的文档仍是 Read。
原生平台的排版铁律
当目标是原生平台时,typeset 要求你遵循 ios.md 或 android.md。这两份文档对排版划定了不容妥协的基线:
iOS(ios.md):
- 使用系统文本样式(Large Title 到 Caption),让文字跟随用户的阅读字号,禁止硬编码 point 尺寸;
- 界面字体由 San Francisco(SF Pro / SF Compact)承担,品牌字体只允许出现在展示(display)场景;
- 有明确下限:正文 17 pt,最小 11 pt;44×44 pt 是每个可点击控件的最低触达面积。
Android(android.md):
- 使用 Material 3 的 type scale(Display / Headline / Title / Body / Label,各含 large/medium/small 分级),把文本映射到角色,绝不逐屏手挑字号;
- Roboto 是系统字体,品牌字体通过 type scale 主题化进入界面;
- 单位必须用 sp,绝不使用固定 px,字号才能跟随系统设置。
双通道独立评估:审美判断与机械扫描互不污染
改代码之前,先做诊断。typeset 要求两套彼此隔离的评估,且明确警告:不要让检测器的发现先入为主地锚定设计评估(Do not let detector findings anchor the design assessment)。如果有可用的子 Agent 工具且被允许,两条通道应独立并行运行;否则按顺序由自己执行。
通道一:字体排印评估(typographic assessment)
检查代表性页面与样式,对下列每个问题都必须用文件、选择器或计算值作答,而不是凭感觉:
- 权威性与契合度(Authority and fit):当前确立了哪些字体、字重与角色?它们契合产品与所选视觉世界,还是未经审视的默认值?每个字族都是必要的吗?
- 层级(Hierarchy):标题、正文、标签、元数据、数据等角色能否一眼区分?相邻的字号或字重是否过于接近,以至于无法承担不同职责?
- 刻度与一致性(Scale and consistency):存在有意的角色刻度,还是一堆任意值?同一角色在不同屏幕与状态间是否保持一致?
- 阅读(Reading):正文行长是否落在舒适的 45–75 字符(ch) 区间?行高、段落节奏、对比度与字距(tracking)是否针对真实的字体、字宽、语言与表面做了调校?
- 压力测试(Stress):长标题、本地化膨胀、缩放、窄容器、缺失字重、字体回退(fallback)时会发生什么?
- 交付(Delivery):是否只加载了实际使用的资源?回退度量(fallback metrics)、加载策略与可变字体(variable-font)设置是否避免了不可见文字与破坏性 reflow?
通道二:机械扫描(mechanical scan)
随后运行检测器:
node .rovodev/skills/impeccable/scripts/detect.mjs --json --scope type [target files or dirs]
--json输出结构化结果,便于后续程序化处理;--scope type把扫描范围收窄到字体排印相关信号;- 末尾的
[target files or dirs]传入本次要检查的文件或目录。
同时,检测器无法解读的动态或任意字体值(例如由 JS 注入、或来自 CSS 变量拼接的字体值)需要人工另行检查。编辑前必须综合两通道的结论,并记录哪些发现是某一通道单独捕捉到的。一个关键认知是:干净的扫描结果只是地板(floor),不是字体排印优秀的证明——机械扫描证明"没有明显的坏信号",但证明不了层级设计得对。
先设系统,再动手:把排版决策写下来
动手编辑前,typeset 要求你**陈述(state)**这次排版系统的设计意图:
- 界面需要哪些角色(role);
- 角色之间预期的对比度;
- 阅读度量与密度(measure 与 density);
- 哪些既有字体与字重是权威的;
- 有哪些性能、本地化或无障碍约束。
陈述这些不是走形式,它把"审美偏好"变成"可验证的设计契约"。在此基础上遵循两条原则:
- 用最少的角色与字族让层级不可混淆(Use the fewest roles and families that make the hierarchy unmistakable);
- 刻意地组合字号、字重、间距与调性(tone),而不是让字号独自承担全部工作;
- 角色名与 token 应描述用途而非数值(purpose over value)——例如用
--text-body、--text-eyebrow这类语义名,而不是--font-16这类裸值名,这样后续调整数值不会污染调用方语义。
落地细则:从 16px 地板到深色表面的三维补偿
typeset 的 Apply 部分给出了一组可执行、可复现的排版施工规则,逐条展开如下:
- 正文地板:正文应保持舒适的可读性与可缩放性。Web 普通正文以 1rem / 16px 为地板,除非高密度角色、平台惯例或用户设置证明确有理由更低。
- 阅读度量:散文类内容保持在 45–75ch。行高与度量成反比调校:行越宽通常需要越多 leading(行距),避免长行加紧凑行高造成串行。
- 深色表面的浅色文字补偿:浅色文字压在深色表面上会产生光学收缩,需要在三个感知轴上同时补偿——略微加大行高、略微增加字距、在字体需要时再加一档字重。只加一档是不够的。
- 行高要按字体/宽度/语言/对比度调,而不是套一个万能比例(如一律 1.5);不同字族的 x-height、字宽与字形密度差异很大。
- 重复角色跨屏幕、跨状态保持一致——这是可扫读性的根基。
- 善用 OpenType 特性:当内容受益时使用数字特性(numeric)、等宽表格数字(tabular)、代码样式(code)与标签(label)特性。
- 字体交付:只加载用到的字体资源与字重;提供度量兼容的回退字体;避免阻塞文字渲染。
- 展示字体与密集界面的区别对待:营销类展示文字在空间允许时响应可用空间是有益的;而密集的产品界面与阅读表面要保持空间可预测(spatially predictable)。
- 保留平台无障碍机制:浏览器缩放、用户字体设置、iOS Dynamic Type、平台文字缩放都必须原样保留。
- 段落节奏单一化:用段间距或首行缩进之一作为主要段落节奏信号;两者并用通常会造成边界被双重标记(double-marking)。
两条不可逾越的底线:不要让字体装饰性凌驾于可理解性之上;不要引入第二个字族,除非存在只有它能单独完成的明确角色。
验证:每一条都要给出证据,不许用"是"敷衍
改完不是结束。typeset 的 Verify 清单要求逐项用渲染或源码证据作答:
- 主(primary)、次(secondary)、正文(body)、元数据(metadata)角色不读文字也能被认出;
- 长文本在相关宽度与语言下依然舒适;
- 这套字体排印属于这个产品及其已确立的视觉世界;
- 加载过程不产生破坏性 reflow,也没有不可见文字;
- 缩放、文字缩放、焦点、对比度、收窄视口等路径依然可用;
- 最终的机械扫描没有无法解释的发现。
每回答一项都要给证据(render 截图或源码行),然后重跑一遍扫描。禁止用光秃秃的"是"来替代验证。这与 impeccable 全局的"用有界的一轮验证,而不是无限自循环"哲学一致:批量检查一轮,一次性修复,最多再确认一轮,然后停止打磨。
当层级确实立住之后,把工作移交给 /impeccable polish(对应 polish.md)做最终的质量收尾——typeset 负责把层级做对,polish 负责在交付前的最后一公里查漏补缺。
在 Live 变体模式下为字体排印保留参数
如果这次排版工作需要进入 impeccable 的 Live 可视化变体模式(在浏览器里选中元素、生成并对比多个变体),typeset 定义了**签名参数(signature params)**契约:
Every variant declares a coarse
scaleparameter and authors its type ramp againstvar(--p-scale, 1).
即:每个变体都必须声明一个粗粒度(coarse)的 scale 参数,并把整套字号刻度(type ramp)写成相对该 CSS 变量的表达式。声明的 JSON 结构是:
{"id":"scale","kind":"range","min":0.85,"max":1.3,"step":0.05,"default":1,"label":"Scale"}
字段语义与 live.md 的参数契约(见 live.md)对齐:
kind: "range"对应滑杆控件,运行时通过 CSS 变量--p-scale驱动排版刻度;CSS 中应写成var(--p-scale, 1),第二个参数1是默认回退值;min: 0.85/max: 1.3给出了合理的收放边界(压缩至 85%、放大至 130%),step: 0.05控制滑杆粒度;default: 1是变体初始值——live.md 明确指出"Reset on variant switch is a known limitation: each variant starts at its declared defaults",所以默认值必须审慎;label是浏览器停靠栏(dock)上展示给用户的控件名。
live.md 的其余参数纪律同样适用:硬上限是每个变体 4 个参数(four per variant);除了 scale,typeset 允许至多再加一个配对(pairing)或字重(weight)参数,且前提是它代表一个真实的系统级选择,而不是一次性的微调——live.md 的准则是"若用户可能嘀咕'再紧一点'或'多一点强调'就值得开一条参数轴,而微小的边距与一次性微调不是参数"。按 action 加载子命令参考(SKILL.md 的 live 段写明 typeset 等 action 的 MUST params 要叠加在预算之上),排版类变体即须携带本 scale 参数。
参数本身属于设计的一部分:在规划阶段就要命名好每个变体的 2–3 个旋钮(knobs),而不是事后补救。range 参数在预览 CSS 里用 var(--p-<id>, default) 承接;最终被接受(accept)的值会被 live-accept.mjs 记录,carbonize 清理阶段再把它们烘焙成字面量或更新变量的默认值(详见 live.md 的 carbonize 步骤)。
工作流全景:从判定到收尾的一体化闭环
把散落的步骤串起来,一次完整的 typeset 改良遵循这样的顺序:
- 判定边界:确认这是在既有世界内的改良;若替换字体会创造新身份 → 改道 new-work + 更新 DESIGN.md;若是原生平台 → 先读 ios/android 规范。
- 双通道评估:字体排印评估 +
detect.mjs --json --scope type机械扫描,独立进行、综合裁决,并补充检查检测器读不到的动态字体值。 - 陈述系统:写下角色清单、角色间对比度、度量与密度、权威字族字重、性能/本地化/无障碍约束。
- 落地修改:按 Apply 细则施工(16px 地板、45–75ch、行高与度量反比、深色表面三维补偿、语义化 token、最小字族数)。
- 证据化验证:对 Verify 清单逐项给出渲染/源码证据,重跑扫描确认无未解释发现。
- 交接:层级成立后交
/impeccable polish;需要 Live 变体试错时,为每个变体声明scale参数并遵守 live.md 的参数契约。
整体上,这条指令把"把字体弄好看"这种模糊诉求,改造成了一个有证据、有边界、可验证、可交接的工程流程。它与 impeccable 的整体原则一脉相承:任何局部改良都要服务于产品真相与已确立的视觉权威,评估要有界、证据要落到文件与计算值、打磨要止于该止的地方。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00