2026/10/29 3:12:55

impeccable:为AI coding agent构建前端设计质量约束层

impeccable:为AI coding agent构建前端设计质量约束层 1. 从“impeccable”这个词说起一个被低估的前端质量信号第一次看到“impeccable”作为项目标题我脑子里蹦出来的不是词典释义而是一个很具体的场景你让 AI coding agent 帮你改一个按钮的 hover 态它改完了功能也对但间距差了 2px圆角从 8px 变成了 6px阴影方向反了。你说不出哪里不对但就是“不对劲”。impeccable 这个词恰恰戳中了这个痛点——它要解决的不是“能不能跑”而是“够不够无懈可击”。我把它理解成一个面向 AI coding agents 的前端设计质量层。核心逻辑是当 agent 通过 CLI 或 browser extension 介入你的开发流程时它不只是执行代码修改还要对产出的 UI 做一轮“设计意图对齐”的校验。这个校验不是跑测试用例而是把设计规范、视觉一致性、交互细节这些通常靠人眼盯的东西变成 agent 能理解和执行的约束。适合谁来参考三类人最直接受益。第一类是已经在用 codex cli、zcode cli 这类工具做日常开发的工程师你肯定遇到过 agent 改完样式后你还要手动回滚几个属性第二类是做 design system 的前端架构师你需要一套机制让 agent 遵守你的 token 体系第三类是独立开发者你没有设计团队但希望 AI 帮你把界面做到“能拿得出手”的水平。这篇文章我会从设计思路、核心机制、实操流程到踩坑记录完整拆一遍。2. 整体设计思路为什么是“约束层”而不是“生成层”2.1 核心问题定位agent 的“设计盲区”从哪来AI coding agents 在前端任务上的表现有一个很明显的断层。逻辑层面它们已经相当可靠——你让它加一个表单校验、接一个 API、写一个状态管理基本不会出大问题。但一到视觉和交互层面问题就密集出现。我观察下来根源有三个。第一个是训练数据的偏差。大量开源代码里的 CSS 本身就是“能跑就行”的水平agent 学到的模式是“差不多就行”而不是“精确对齐”。第二个是缺乏上下文锚点。你给 agent 一个 Figma 链接它读不了你给它一张截图它只能猜它手里没有设计 token 的权威来源。第三个是反馈回路缺失。代码写完agent 没有“看一眼”的能力它不知道自己的产出在浏览器里长什么样。impeccable 的设计思路就是在这三个缺口上各补一块用结构化规范替代模糊描述用 CLI 注入 token 上下文用 browser extension 建立视觉反馈回路。2.2 方案选型CLI Browser Extension 的双通道架构为什么是 CLI 加 browser extension 的组合而不是纯插件或者纯命令行这个选型背后有很实际的考量。CLI 通道负责的是“事前约束”和“事后校验”。事前它把设计规范以配置文件的形式注入项目agent 在生成代码前就能读到这些约束。事后它跑一轮静态检查把违反规范的代码标出来。CLI 的优势在于它可以嵌入任何工作流——你用的是 codex cli 还是 trae cli都能挂上去。Browser extension 通道负责的是“实时视觉反馈”。agent 改完代码extension 在浏览器里截取渲染结果提取关键视觉属性——间距、颜色、字体、层级——回传给 agent 作为下一轮迭代的输入。这个回路是纯 CLI 做不到的因为 CLI 看不到渲染结果。两条通道的分工很清晰CLI 管“应该是什么”extension 管“实际是什么”两者的差值就是 agent 需要修正的方向。2.3 与现有工具链的边界划分这里要说清楚 impeccable 不做什么。它不做代码生成那是 codex cli 的活。它不做设计稿解析那是 Figma 插件的活。它不做组件库那是你自己的 design system 的活。它只做一件事在 agent 的工作流里插入一个“设计质量守门员”的角色。这个边界很重要因为很多团队一开始就想做一个“全能设计 AI”结果什么都做不深。impeccable 的克制恰恰是它的优势——它足够薄所以能嵌进任何现有流程它足够专所以在设计一致性这一件事上能做到可用的精度。3. 核心机制拆解规范注入、视觉提取与差异对齐3.1 设计 token 的结构化注入方式impeccable 的规范注入不是丢一个 CSS 文件给 agent 就完事。它用的是一套结构化的 token 描述我把它叫做“设计契约”。这个契约包含几个层次。最底层是原子 token颜色值、间距单位、圆角半径、字体大小、行高、阴影参数。这些是硬约束agent 不能随意偏离。中间层是语义 token比如spacing.card.padding、color.text.secondary、radius.button.default这些是 agent 实际引用的东西。最上层是组合规则比如“卡片内边距必须是间距单位的整数倍”、“按钮圆角必须与输入框圆角一致”。注入方式上impeccable 会在项目根目录生成一个.impeccable/contract.json同时通过 CLI 的 pre-command hook 把这个契约的摘要注入 agent 的上下文。摘要不是全文而是当前任务相关的子集——你改按钮它就注入按钮相关的 token你改布局它就注入间距和栅格相关的 token。这个“按需注入”的设计是为了避免上下文过载agent 的注意力是有限资源。{ atoms: { spacing: [4, 8, 12, 16, 24, 32, 48, 64], radius: { sm: 4, md: 8, lg: 12, full: 9999 }, color: { text: { primary: #1a1a1a, secondary: #666666 }, surface: { default: #ffffff, raised: #f5f5f5 } } }, semantics: { card.padding: spacing.16, button.radius: radius.md, button.padding.x: spacing.16 }, rules: [ spacing values must be from atoms.spacing, button.radius must equal input.radius ] }这个契约文件是整个机制的地基。我试过把它写得太细结果 agent 每次改动都要读一大堆无关约束反而降低了效率也试过写得太粗agent 就开始自由发挥。经验是原子 token 控制在 30 个以内语义 token 控制在 50 个以内规则不超过 10 条。超过这个量级维护成本会超过收益。3.2 Browser Extension 的视觉属性提取逻辑Browser extension 这一端做的事情本质上是把“人眼看界面”这个过程拆解成可量化的步骤。它不截图做图像识别——那个精度不够且太慢——而是直接读 DOM 的计算样式。具体流程是这样的agent 完成一轮代码修改后extension 通过 CLI 收到一个“检查点”信号然后在当前页面定位到被修改的组件通过 data 属性或选择器匹配提取这个组件及其子元素的关键计算样式。提取的字段包括margin、padding、border-radius、box-shadow、font-size、line-height、color、background-color、gap、以及元素的实际渲染尺寸。提取完之后extension 做两件事。第一件是“规范符合性检查”把提取到的值与契约里的 token 做比对标出偏离项。第二件是“视觉一致性检查”把当前组件与同页面其他同类组件的样式做比对标出不一致项。比如你改了卡片 A 的内边距但卡片 B 还是旧值这个不一致会被抓出来。// extension 侧的核心提取逻辑简化示意 function extractVisualProps(element) { const cs getComputedStyle(element); const rect element.getBoundingClientRect(); return { padding: [cs.paddingTop, cs.paddingRight, cs.paddingBottom, cs.paddingLeft], margin: [cs.marginTop, cs.marginRight, cs.marginBottom, cs.marginLeft], radius: cs.borderRadius, shadow: cs.boxShadow, fontSize: cs.fontSize, lineHeight: cs.lineHeight, color: cs.color, background: cs.backgroundColor, gap: cs.gap, size: [rect.width, rect.height] }; }这里有个实操细节计算样式返回的是像素值但契约里可能是 token 名。所以 extension 需要维护一个“像素到 token”的反查表。这个反查表在契约加载时生成把每个 token 的像素值映射回 token 名。反查时允许 1px 的容差因为浏览器渲染会有亚像素舍入。3.3 差异对齐agent 如何“看懂”视觉偏差提取出视觉属性后下一步是把偏差转化成 agent 能理解的指令。这一步是整个机制里最需要设计的地方因为如果你只是丢给 agent 一句“padding 应该是 16px 不是 14px”它可能会改但下次还会犯。impeccable 的做法是把偏差分类每类偏差对应不同的修正策略。第一类是“token 偏离”用了不在 token 集合里的值。这类偏差的修正指令是“替换为最近的合法 token”同时附上为什么这个 token 更合适。第二类是“一致性偏离”同类组件之间样式不一致。修正指令是“对齐到多数值”并指出参考组件。第三类是“规则违反”比如圆角不匹配。修正指令是“根据规则 X将 A 调整为 B”。这个分类的意义在于它让 agent 的修正行为变得可预测。我实测下来分类处理比笼统的“这里不对”要有效得多agent 的修正准确率大概能从六成提到八成以上。4. 实操流程从零接入 impeccable 的完整步骤4.1 环境准备与 CLI 安装先说环境要求。Node 版本建议 18 以上因为 impeccable 的 CLI 用了一些较新的 API。包管理器用 npm 或 pnpm 都行我习惯用 pnpm装得快且磁盘占用小。浏览器端目前支持 Chromium 内核的浏览器extension 需要开发者模式加载。安装 CLI 的命令很直接pnpm add -D impeccable-cli # 或者全局安装 pnpm add -g impeccable-cli装完之后跑一次初始化npx impeccable init这个命令会做三件事在项目根目录创建.impeccable/目录生成一份默认的contract.json模板以及在package.json里注入几个 script 快捷命令。默认模板里的 token 是一套通用的设计系统值你需要根据自己的项目替换。注意init 命令不会覆盖已有的.impeccable/目录。如果你之前初始化过它会提示你手动合并。这个设计是为了防止误删你辛苦调好的契约。4.2 契约文件的编写与调优契约文件是整个机制的核心值得花时间打磨。我的建议是分三步走。第一步先把项目里现有的设计 token 提取出来。如果你用的是 Tailwind可以直接从tailwind.config.js里读如果用的是 CSS 变量从:root里读如果是 styled-components 的 theme从 theme 文件读。impeccable 提供了一个辅助命令npx impeccable extract --from tailwind npx impeccable extract --from css-vars这个命令会扫描你的配置文件生成一份初始契约。但别直接用它提取出来的东西往往太全太杂需要手动精简。第二步精简原子 token。把那些实际用到的值留下把“理论上存在但没人用”的值删掉。我见过一个项目提取出来 47 个间距值实际上常用的就 8 个。精简之后 agent 的决策空间小了输出反而更稳定。第三步写规则。规则不要多但要准。我常用的几条规则包括间距必须是原子间距的整数倍、同类组件的圆角必须一致、文字颜色只能从语义色里选、阴影只能从预设的几档里选。规则写完之后用npx impeccable validate跑一遍它会检查你的契约本身有没有矛盾。4.3 Browser Extension 的加载与配对Extension 的加载流程从 impeccable 的发布页下载 extension 包解压到一个固定目录然后在浏览器的扩展管理页开启开发者模式选择“加载已解压的扩展程序”指向解压目录。加载完之后需要和 CLI 配对。配对的方式是在项目目录跑npx impeccable pair它会生成一个配对码然后在 extension 的弹窗里输入这个配对码。配对成功后extension 会和 CLI 建立一个本地连接后续的检查点信号和视觉数据都通过这个连接传输。npx impeccable pair # 输出Pairing code: IMP-7X3K-9F2M # 在 extension 弹窗中输入此码完成配对提示配对码有时效性默认 10 分钟。如果超时了重新生成即可。配对关系是持久的除非你手动解除否则下次打开浏览器还是配对的。4.4 与 codex cli 等 agent 工具的挂接这一步是把 impeccable 嵌进你的 agent 工作流。以 codex cli 为例你需要在它的配置里加一个 pre-command hook 和一个 post-command hook。Pre-command hook 的作用是在 agent 执行任务前把相关的契约摘要注入上下文。Post-command hook 的作用是在 agent 完成任务后触发视觉检查。# 在 codex cli 的配置中 hooks: pre-command: npx impeccable inject --task $TASK post-command: npx impeccable check --diffinject命令会根据任务描述匹配相关的 token 子集输出一段格式化的约束文本agent 会把它当作系统提示的一部分。check命令会触发 extension 做视觉提取然后把偏差报告输出到终端。如果你用的是其他 CLI 工具比如 trae cli 或 minimax cli挂接方式类似核心就是找到它们的 hook 机制。有些工具没有原生 hook那就用 shell 包装一层在调用 agent 命令前后手动插入 impeccable 的命令。5. 常见问题与排查技巧实录5.1 契约注入后 agent 仍然不遵守怎么办这是最高频的问题。我排查下来原因通常有三个。第一个是注入的 token 子集不匹配任务。比如 agent 在改一个 modal 组件但 inject 命令匹配到的是 button 相关的 token。解决方法是检查 inject 的匹配逻辑必要时手动指定任务标签npx impeccable inject --task modal --tags modal,dialog,overlay。第二个是契约里的规则表述太模糊。比如“间距要合理”这种规则agent 没法执行。规则必须是可判定的比如“间距值必须属于 [4,8,12,16,24,32]”。我建议每条规则都写成“条件 判定标准”的形式。第三个是 agent 的上下文窗口被其他内容占满了。如果你的任务描述很长或者项目文件很大注入的契约可能被挤到后面agent 的注意力分配不到。解决方法是精简注入内容只保留最相关的 5 到 8 条约束。5.2 视觉提取结果与实际不符的排查Extension 提取的样式和你在 DevTools 里看到的不一致这种情况我也遇到过几次。常见原因和对策整理成表现象可能原因排查方法提取的 padding 比实际小元素有伪元素或子元素撑开检查::before::after的样式颜色值对不上存在透明度叠加或混合模式检查opacity和mix-blend-mode尺寸偏差超过 2px浏览器缩放不是 100%重置缩放到 100% 再提取找不到目标元素选择器匹配到了隐藏元素检查元素的display和visibility提取超时页面有持续动画或懒加载等待页面稳定后再触发检查注意提取前确保页面处于稳定状态。如果页面有 loading 动画或过渡效果提取到的值可能是中间态。我的做法是在 extension 里加一个 300ms 的延迟等渲染稳定后再提取。5.3 多 agent 协作时的冲突处理如果你同时用多个 agent 工具——比如 codex cli 改逻辑另一个工具改样式——契约的注入可能会出现冲突。一个 agent 改了 token 引用另一个 agent 还在用旧值。处理方式是给契约加版本号并在注入时带上版本。agent 完成任务后check 命令会验证它用的契约版本是否是最新的。如果不是会提示重新注入。另外我建议把契约文件纳入 git 管理这样多人的修改可以合并和追溯。npx impeccable inject --task $TASK --version $(git rev-parse --short HEAD)5.4 性能开销与优化建议impeccable 的检查流程会增加一些开销。CLI 侧的注入和校验很快通常在 200ms 以内。Extension 侧的视觉提取慢一些取决于页面复杂度简单页面 100ms 左右复杂页面可能到 500ms。如果你的开发流程对延迟敏感可以调整检查频率。默认是每次 agent 任务后都检查你可以改成只在涉及样式文件变更时检查npx impeccable check --diff --only **/*.css,**/*.scss,**/*.tsx另一个优化点是缓存。Extension 可以缓存上一次提取的结果如果 DOM 没有变化直接复用缓存。这个在反复微调同一个组件时很有用。6. 我在实际项目中的几点体会接入 impeccable 大概三个月跑了两个中型项目说几个文档里不会写的感受。第一个感受是契约的维护成本比想象中高。一开始我以为写一次就行了实际上随着项目演进token 会增删规则会调整。我现在养成的习惯是每次 sprint 结束花 15 分钟 review 一下契约把不再用的 token 删掉把新出现的模式加进去。这个投入是值得的因为契约一旦腐化agent 的输出质量会肉眼可见地下降。第二个感受是不要追求 100% 的规范覆盖率。我试过把契约写得极其严格结果 agent 每改一行代码都要触发一堆检查开发体验很差。后来我调整了策略只对核心组件和高频模式做强制约束边缘场景允许一定程度的自由发挥。这个平衡点大概在 70% 到 80% 的覆盖率既能保证整体一致性又不会让 agent 束手束脚。第三个感受是视觉提取的精度受浏览器影响。同样的代码在 Chrome 和 Edge 里提取出来的值可能有细微差异主要是亚像素渲染的舍入方式不同。如果你的团队用不同浏览器建议统一检查环境或者在契约里把容差设大一点比如 1.5px 而不是 1px。最后分享一个我常用的小技巧把 impeccable 的检查结果导出成一份“设计债务报告”每周看一次。报告里会列出所有偏离契约的地方按严重程度排序。这份报告不仅能指导 agent 的修正也能帮你发现设计系统本身的漏洞——有些偏离反复出现说明契约里的 token 设置得不合理需要调整的是契约而不是代码。这个视角的转换是我用 impeccable 最大的收获。