impeccable Craft Floor 深度解析:AI 前端设计的质量底线与反模式拒绝清单
本文以 Impeccable 技能(skill)中的 craft-floor.md 参考文档为主体,完整拆解其「Verify 验证清单」与「Refuse 拒绝清单」两大核心板块,并结合技能主文件 SKILL.md 与检测器规则注册表 antipatterns.mjs 的源码实现,说明这份"工艺底线"在 AI 辅助前端设计工作流中的加载时机、检查逻辑和自动化兜底机制。读完后你将掌握:如何把 craft floor 用作 AI 编码前端的验收标准,以及仓库中哪些检测规则实际执行了这些条目。
什么是 Craft floor,以及它何时被加载
craft floor 是 Impeccable 技能参考文档体系中的一个特殊文件。与 polish.md、bolder.md 等"方向型"参考不同,它不指导你往哪个方向设计,而是规定"无论往哪个方向,机械层面的质量底线不能破"。原文最后一句点明了它的定位:"The floor holds the mechanics; it never picks the direction."(底线管机械,从不管方向)。
从 SKILL.md 的 Setup 流程看,craft floor 的加载时机被精确定义为第 3 步:
After analysis and direction are resolved, load
reference/craft-floor.mdimmediately before editing UI. It carries the quality floor, the absolute bans, and the reflexes no detector catches. Do not load it for planning-only work.
即:只有当分析完成、设计方向已经敲定(direction is settled)之后,在真正动键盘改 UI 之前一刻加载它;纯规划任务不加载。这体现了三层设计意图:
- 优先级明确:craft floor 开头即声明,已钉住的 brief(pinned brief)或已承诺的视觉世界(committed visual world)覆盖其中的任何一条——"你的个人习惯(your own habit)不覆盖它"。
- 与检测钩子(design hook)协同:当 hook 处于激活状态时,它会在每次编辑 UI 文件后自动运行检测器并浮现发现(findings)。craft floor 明确要求:"act on its findings instead of re-auditing each rule"——直接处理钩子报告,而不是逐条规则重复自查。
- 补齐检测器盲区:SKILL.md 称之为 "reflexes no detector catches"(检测器抓不到的本能反应)。脚本 context.mjs 中的注释也印证了这一点:"reference/craft-floor.md carries the detector-blind reflexes on every build"——它承载的是检测器覆盖不到的判断力,例如浏览器原生表面(选区、光标、滚动条)的主题化。
在仓库中,这份文档同时存在多个分发副本,例如 skill/reference/craft-floor.md,内容保持一致。
Verify:对"构建结果"的九项检查
craft floor 的 Verify 一节强调一个关键方法论:这些检查针对的是"已构建出来的产物",而不是意图。文档原文:"Each of these is a check on the built result, not an intention.",并要求"Run them together in the batched inspection rounds, not as separate screenshot trips; the checks share one render"——把所有检查打包在同一轮批量检查中执行,共享同一次渲染,而不是每查一条就截一次图。这与 SKILL.md 中"Verify in bounded passes, not a loop"(有界轮次验证,不做循环自证)的核心原则一脉相承。
九项检查的完整清单
| 检查项 | 具体标准(继承自原文档) |
|---|---|
| Contrast(对比度) | 正文与占位符文本 ≥ 4.5:1,大文本 ≥ 3:1。彩色表面上,次级文字应从该色相或前景色中调出色调,绝不使用灰色 |
| Depth(深度) | 阴影必须带偏移量(offset)和柔和的模糊(soft blur)。零偏移的彩色光晕是装饰,不是深度 |
| Spacing(间距) | 相关项紧凑成组、组间分隔宽裕;标题上方的留白要多于下方。要读计算后的实际值(computed values),不是声明值 |
| Type(排版) | 正文行长 65–75ch;展示级字号上限 6rem;字距(tracking)下限 -0.04em;标题做平衡排版(balanced headings);字号与字重要有清晰的梯度变化。在每个断点用真实文案运行,修掉所有溢出 |
| Motion(动效) | 只做一个"被创作出来的时刻",不是散布的特效,也不是每个 section 用同一个入场动画。从"默认可见"状态出发做指数缓出(exponential ease-out)。不要只满足于 transform 和 opacity:blur、backdrop-filter、clip-path、mask、shadow 都是调色板的一部分——前提是不掉帧 |
| States(状态) | hover、disabled、loading、error、empty 五态齐全;外加真实内容、可用的控件、响应式构图、键盘焦点 |
| Browser surfaces(浏览器表面) | 你没画的部件也要承载设计:文本选区、光标(caret)、自定义滚动条、焦点环、下划线偏移(underline offset)、表格化数据中的数字(tabular numerals)。这些浏览器默认值"不属于任何设计系统",必须从调色板中主题化。文档直言:这是"一个页面是被构建(built)而非拼装(assembled)的最廉价信号,也是模型们最稳定地会跳过的一条" |
| Copy(文案) | 用产品自己的语言。控件要说出它执行的动作;错误要说出问题所在和恢复路径 |
| Coverage(覆盖度) | brief 中的每一条要求都真实存在,且能在几秒内被找到 |
检测器对 Verify 项的自动化兜底
craft floor 的机械子集在 antipatterns.mjs 规则注册表中有对应实现,可以逐条印证:
- Contrast:
low-contrast规则直接执行 WCAG AA 标准——"Text does not meet WCAG AA contrast requirements (4.5:1 for body, 3:1 for large text)"(见 antipatterns.mjs);gray-on-color规则则实现"彩色背景上禁用灰色文字"的条目(L336-L343)。 - Type:
line-length规则要求给文本容器加 65ch–75ch 的 max-width(L361-L369);extreme-negative-tracking规则守卫字距下限——"Tighten display type optically, not destructively"(L272-L280)。 - Spacing:
heading-rhythm规则实现"标题与它所介绍的内容绑定,渲染出的上方留白应大于下方留白"(L405-L412)。 - Motion:
bounce-easing规则禁止弹跳/弹性缓动,理由是"真实物体平滑减速——使用指数缓动(ease-out-quart/quint/expo)"(L89-L96),与 craft floor 的 "Exponential ease-out" 条目完全一致。
从源码结构看,注册表还定义了 RULE_ENGINE_SUPPORT(L577-L582),把每条规则映射到 regex / static-html / browser / visual 四种检测引擎的支持范围——这解释了为什么 craft floor 强调"读计算后的值":需要真实渲染的 browser 引擎才能拿到 computed style 来验证间距、对比度这类条目,而静态正则引擎只能覆盖源码层面的模式。
Refuse:按类别的"默认拒绝",以及唯一的绝对禁令
Refuse 一节开头做了一个重要的语义区分:"These are the category's defaults, not bans"(这些是类别默认值,不是禁令)。判断逻辑是:
- 当设计轴(the axis)是自由的——即 brief 没有指定时——伸手去拿这些默认模式,意味着"你当时并没有在做决定"(you were not deciding)。
- 认识到这一点之后的正确动作是重写这个元素(rewriting the element),而不是软化它(not softening it)。
- 例外:brief 自己的措辞可以为其中任何一条"挣回合法性"——比如需求里明确要求 neobrutalist 风格,那么硬阴影就有资格出现。
原文档同时明确指出全篇唯一的绝对禁令:标题上方的 kicker / eyebrow 标签。"This one is a ban, not a default: no brief earns it back."(这一条是禁令而非默认值:没有任何 brief 能把它挣回来。)
Page scaffolds(页面骨架类拒绝项)
原文档列出的五类页面骨架反模式,全部继承如下:
- 等大卡片阵列:图标 + 标题 + 文本的等大卡片作为页面主体结构。文档定性:"Cards are the lazy container"(卡片是懒惰容器);嵌套卡片永远错误(nested cards are always wrong)——注意这一条在原文中没有任何"brief 可以挣回"的余地。
- Hero-metric 模板:大数字 + 小标签 + 辅助统计 + 强调色,这个四件套本身就成了模板。
- Kicker / eyebrow 标签(唯一绝对禁令):标题上方的小标签。理由:"The heading carries its own weight; delete the label and let the heading speak."(标题自带重量;删掉标签,让标题自己说话。)
- 章节序号(01 / 02 / 03):除非序列本身承载了读者需要的信息,否则不用。
- 滥用模态框:对一个既不需要打断、也不需要保护专注的任务使用 modal。
Surface habits(表面习惯类拒绝项)
这部分是全文最长、信息密度最高的拒绝清单,逐条继承如下:
- 渐变文字:强调应该来自字重或字号(Emphasis comes from weight or size)。
- 玻璃拟态与模糊:作为装饰而非具体效果使用时拒绝。
- 彩色 border-left / border-right > 1px:出现在卡片、列表项、callout 或 alert 上时。
- 硬偏移阴影(如
box-shadow: 4px 4px 0):除非这个世界确实是 neobrutalist。原文的表述很锋利:"The zero-blur block shadow is a costume, not a depth system"(零模糊块状阴影是戏服,不是深度系统);一个没有选择它的世界永远不该拿它当默认值。 - 内容替身:sparkline、进度环、带柔和阴影的圆角矩形——当它们"standing in for content"(代替内容存在)时。
- 等宽字体作为"技术感"戏服:等宽字体只应服务于代码、数据、度量(measurement),不是风格装扮。
- 系统展示字体:Impact、Arial Black、平台默认无衬线体,不能当一个"自有世界页面"(own-world page)的展示声音。应该找到一款字符气质匹配已批准字体的字体并自托管(self-host);原文断言:"the closest installed font is a failure, not a fallback"(最接近的已安装字体是失败,不是降级方案)。
- Unicode 符号或 emoji 冒充图标系统:图标是被画出来的——来自真实图标库或原创 SVG,且保持统一描边与字重。
- 几何遮罩冒充有机轮廓:用圆、多边形、radial-gradient 切角去近似摄影主体的边缘,是这个效果的廉价版本,"reads worse than omitting it"(看起来比干脆不做还糟)。正确做法:从真实图像导出 alpha matte,或生产一个 cut-out 资产。
- 明暗按类别选择:不能因为"这是个深色应用/浅色应用"就选黑或白。要从使用场景选:谁、在哪里、什么环境光(who, where, under what ambient light)。
Refuse 节的追加规则(文档尾部段落)
原文档在两类分组的最后还有一批无标题的追加规则,同样是 craft floor 的组成部分:
- 字距止于 -0.04em:-0.02 到 -0.03em 通常读感更好(这是 Tracking 的"地板 + 舒适区"双重约束)。
- 高程只声明一次:要么边框、要么阴影。"宽而柔和的阴影底下垫一条 1px 边框"被称为 ghost card(幽灵卡片)。卡片圆角保持在 12–16px;药丸形状(pills)留给小控件。
- 插画要么真实要么不做:草图风 SVG 场景、
loose-sketch/doodle类名、feTurbulence噪点会显得业余。但这条禁令的边界非常精确——它禁止的是"SVG 模仿照片",永远不禁止"SVG 做几何":清晰的矢量形状、图解、动画线条、shader 驱动的效果都是一等媒体。原文的判据:"A shaded, perspectived, or figure-bearing illustration is a picture even in line-art style; geometry means shapes a session can specify exactly."(带明暗、透视或人物的插画,即使是线条风格也是"照片";几何意味着一个会话可以精确定义的形状。) - 背景是表面:纹理只能来自主题自身的世界(the subject's world)。
repeating-linear-gradient条纹和双轴网格叠加,底下必须压着真实的画布、地图、蓝图或测量工具——否则就是装饰性条纹。 - 事实与声明的来源:claims(声明)和 configuration(配置)必须来自给定的事实(supplied truth);示意性数值要诚实地标注。原文还有一句微妙的文案准则:"Naming a concept and then ironizing it is not a claim."(先命名一个概念再对它反讽,不构成一个声明。)
与检测器规则的一一映射
Refuse 清单的大多数条目在检测器注册表中有对应的自动化规则,可以对照阅读:
| craft floor 拒绝项 | 检测器规则 ID | 注册表中的判定描述(节选) |
|---|---|---|
| Kicker/eyebrow 标签 | kicker-above-heading |
"A tiny tracked uppercase ... label sitting as its own block directly above a heading is banned outright, repeated or not"(L209-L217)——与 craft floor 的"ban, not a default"措辞完全对应 |
| 章节序号 | numbered-section-labels |
"a page numbering its own chapters instead of earning structure"(L219-L228) |
| 渐变文字 | gradient-text |
"Gradient text is decorative rather than meaningful — a common AI tell"(L42-L49) |
| 嵌套卡片 | nested-cards |
"Cards inside cards create visual noise and excessive depth"(L69-L77) |
| 图标卡片阵列 | icon-tile-stack |
"the universal AI feature-card template — every generator outputs this exact shape"(L179-L187) |
| 彩色侧边粗边框 | side-tab / border-accent-on-rounded |
"Thick colored border on one side of a card — the most recognizable tell of AI-generated UIs"(L3-L20) |
| 零偏移彩色光晕 | dark-glow / radial-halo / radial-spotlight-glow |
"a zero-offset chromatic halo ... are the default 'cool' look of AI-generated UIs"(L143-L168) |
| Ghost card(细边框 + 宽阴影) | gpt-thin-border-wide-shadow |
"Commit to one — a defined edge or a soft elevation — rather than both at once"(L526-L534) |
| 装饰性条纹背景 | repeating-stripes-gradient |
"Reaching for a deliberate texture or leave the surface plain"(L536-L544) |
| 双轴网格背景 | codex-grid-background |
"Reserve grid overlays for actual canvas, map, blueprint, or measurement surfaces"(L546-L554)——与 craft floor 的 "need an actual canvas, map, blueprint, or measuring tool under them" 逐词对应 |
| 几何遮罩冒充有机轮廓 | organic-clip-path |
"Derive an alpha matte from the real image, or ship the shape as a cut-out raster; keep clip-path for geometry (cut corners, diagonals, hexagons)"(L125-L132) |
| 系统字体冒充展示字体 / 流行字体 | overused-font |
点名 Inter、Roboto、Fraunces、Geist、Plus Jakarta Sans、Space Grotesk 已"不再显得有辨识度"(L22-L30);配合 design-system-font 规则约束字体必须在 DESIGN.md 声明(L483-L491) |
| 展示级超长标题 | oversized-h1 |
"A punchy one- or two-word headline at that size is fine — the problem is a long headline blown up too large"(L262-L270),呼应 Verify 中"display max 6rem"的上限 |
advisory 与 failure 的分层
值得注意的实现细节:注册表中的规则分为失败级与 advisory(建议级) 两层。源码注释明确说明:"Advisory rules are detected and reported, but never treated as failures: the CLI lists them under a separate 'Advisory' section, they do not affect exit codes or the failure count, and the design hook skips them by default."(L588-L594)。像 numbered-section-labels、gpt-thin-border-wide-shadow、repeating-stripes-gradient 这类"生成 UI 特征"类规则被标为 advisory——因为它们可能是合法的风格选择,只报告、不计入失败数、hook 默认跳过,除非项目显式开启。这恰好落实了 craft floor 开头那句 "category's defaults, not bans" 的语义:机械上可以检出,裁决上留给人和 brief。
工作流中的位置:从加载到执行
把 craft floor 放回完整工作流中看,它的执行链路是:
- Setup 第 1 步:每会话运行一次
node <skill-base-dir>/scripts/context.mjs,加载 PRODUCT.md、DESIGN.md 与 surface brief——这是 brief 与视觉世界的来源,即"覆盖 craft floor 的更高优先级"。 - Setup 第 2 步:加载请求对应的 playbook 参考文档,确定方向。
- Setup 第 3 步:方向敲定后、编辑 UI 前一刻加载 craft floor。
- 编辑期间:如果
$impeccable hooks on已启用(SKILL.md 中 Hooks 一节说明它会"auto-runs the detector after UI file edits and surfaces findings"),每次编辑 UI 文件后自动产出发现;craft floor 要求直接处理这些发现。 - 验证阶段:按 Verify 清单做批量检查——一次渲染、多检查共享,最多再确认一轮即停(呼应 SKILL.md 的 "confirm with at most one more round, and stop polishing")。
也就是说,craft floor 同时扮演两个角色:编辑前的行为约束(Refuse 清单内化为不伸手拿这些默认模式的判断力)和编辑后的验收标准(Verify 清单作为批量检查轮的 checklist)。前者主要靠模型自身执行,后者由检测器 + 模型协同执行。
小结:底线管机械,方向归世界
craft floor 的设计哲学可以用原文的两句收尾概括:
"The floor holds the mechanics; it never picks the direction. With every check green, spend the page on the committed world, and when torn between refined and committed, commit."
(底线持有机械,从不挑选方向。当所有检查变绿,把页面花掉在已承诺的世界里;当在"精致"与"投入"之间犹豫时,选择投入。)
对使用 Impeccable 的开发者而言,这份文档的实战价值在于三点:
- 可复制的验收清单:Verify 九项中的数值标准(4.5:1 / 3:1 对比度、65–75ch 行长、-0.04em 字距下限、12–16px 卡片圆角)都是可以直接写进 code review 标准的硬指标;
- 可解释的反模式语义:Refuse 清单区分了"默认拒绝"与"绝对禁令"(kicker),并给出了每条的裁决依据——这对人类设计评审同样适用;
- 人机分工明确:能机械化的条目(对比度、行长、标题节奏、缓动函数、ghost card)已由 antipatterns.mjs 注册表 + 多引擎检测器覆盖,且 advisory/failure 分层保留了人工裁决空间;检测器抓不到的条目(浏览器表面主题化、文案是否说出动作与恢复路径、brief 覆盖度)则留在 craft floor 中由执行者负责——这正是 "detector-blind reflexes" 的含义。
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 StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00