Impeccable harden 命令实战:一套面向生产环境的 UI 加固手册——文本溢出、i18n、错误态与边界条件
impeccable 是一个为 AI 编程助手提供设计语言的技能仓库,其中的 harden 命令是技能体系里 Refine(精修)类别的成员,专门把"只在完美数据下才能工作的界面"改造为能扛住真实用户输入的界面。本文以仓库中的 harden 参考文档 为核心,完整继承其评估流程、七大加固维度与验证清单,并结合仓库源码中配套的自动化检测器实现,讲清这套加固手册的完整工作方式。
1. harden 在 impeccable 技能体系中的位置
harden.md 并不是一篇孤立的教程,而是 impeccable 技能的命令手册之一。技能主文件 SKILL.src.md 中的 Commands 表格将它登记为:
| 命令 | 类别 | 说明 |
|---|---|---|
harden [target] |
Refine | Production-ready: errors, i18n, edge cases |
当用户输入 harden [target] 时,Agent 会先运行 context.mjs 加载项目上下文,再加载这份参考文档并按其流程执行。它的定位在文档开头一句话就写明了:
Designs that only work with perfect data aren't production-ready.(只在完美数据下工作的设计不算生产就绪。)
从文档结构看,harden 的执行链路是:评估加固需求 → 沿七个维度系统加固 → 用极端输入做验证 → 交接给 /impeccable polish 做最终 pass。仓库中还存在同源文件 skill/reference/harden.md(使用 {{command_prefix}} 模板占位符,由构建脚本针对不同 Harness 渲染出不同的命令前缀,.agent 目录下渲染的结果即为 /impeccable 前缀),两者仅命令前缀一行不同,本文以 .agent 版本为准。
2. 评估加固需求:三类系统性弱点排查
文档要求先识别弱点与边界情况,而不是直接改代码。排查分三类,以下是完整继承的清单。
2.1 极端输入测试(Test with extreme inputs)
- 超长文本(姓名、描述、标题)
- 超短文本(空值、单字符)
- 特殊字符(emoji、RTL 文本、变音符号)
- 大数值(百万、十亿级)
- 大量条目(1000+ 列表项、50+ 下拉选项)
- 无数据(空状态)
2.2 错误场景测试(Test error scenarios)
- 网络故障(离线、慢速、超时)
- API 错误(400、401、403、404、500)
- 校验错误
- 权限错误
- 限流(rate limiting)
- 并发操作
2.3 国际化测试(Test internationalization)
- 长译文(德语通常比英语长 30%)
- RTL 语言(阿拉伯语、希伯来语)
- 字符集(中日韩文字、emoji)
- 日期/时间格式
- 数字格式(
1,000vs1.000) - 货币符号
文档在此给出了一条 CRITICAL 级别的原则:只在完美数据下工作的设计不具备生产就绪资格,必须对现实做加固。
3. 加固维度一:文本溢出与换行
这是文档中代码示例最密集的一节,给出三组可直接复用的 CSS 模式。
长文本处理:
/* 单行 + 省略号 */
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* 多行 + 截断 */
.line-clamp {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* 允许换行 */
.wrap {
word-wrap: break-word;
overflow-wrap: break-word;
hyphens: auto;
}
Flex/Grid 溢出(这是最常被忽视的一类:子项内容撑破弹性容器):
/* 防止 flex 子项溢出 */
.flex-item {
min-width: 0; /* 允许收缩到小于内容尺寸 */
overflow: hidden;
}
/* 防止 grid 子项溢出 */
.grid-item {
min-width: 0;
min-height: 0;
}
响应式字号:使用 clamp() 做流式排版;正文最小可读尺寸为 16px(移动端,与 impeccable 排版指引一致),14px 仅用于真正的次要文本——文档特别指出 iOS Safari 会对小于 16px 的聚焦输入框强制缩放,破坏表单布局;把浏览器缩放到 200% 测试文字缩放;确保容器能随文本撑开。
3.1 仓库佐证:detect 器的 text-overflow 规则
这一节与仓库中已有的自动化能力直接对应。impeccable 的检测引擎在 checks.mjs 中实现了浏览器端的 text-overflow 规则 checkElementTextOverflowDOM:它只检查"真正拥有溢出文本"的元素(祖先元素会继承更宽的 scrollWidth,因此被排除),当 scrollWidth - clientWidth >= 16px 时上报溢出;对于内联元素(clientWidth 为 0),则退化为用 getBoundingClientRect 与最近块级容器的 padding box 右缘比较,捕捉 nowrap 内联元素溢出固定宽度网格单元的场景。规则同时排除了滚动区域(overflow: auto/scroll)、SVG 内容、屏幕阅读器专用文本(sr-only)和隐藏图层,以避免误报。
配套的测试夹具 text-overflow.html 用 FLAG/PASS 两列分别覆盖"nowrap 长行溢出""超长单词""内联 span 溢出"等应报场景,以及"真滚动区域""<pre> 预格式化""正常换行文本""滚动祖先内的 nowrap 行"等不应报场景。这意味着在 harden 流程的验证阶段,文本溢出这类问题可以被项目的 hook(每次 UI 文件编辑后自动运行检测器,见 SKILL.src.md 中的 Hooks 说明)半自动地兜住,而不是完全依赖人眼。
4. 加固维度二:国际化(i18n)
文本膨胀:为译文预留 30–40% 的空间预算;使用能随内容自适应的 flexbox/grid;用最长语言(通常是德语)测试;避免给文本容器设固定宽度。文档用一个 JSX 对比示例说明:
// ❌ 坏:假设短英文文本
<button className="w-24">Submit</button>
// ✅ 好:随内容自适应
<button className="px-4 py-2">Submit</button>
RTL(从右到左)支持:优先使用逻辑属性(logical properties),或者用 dir 属性做镜像:
/* 使用逻辑属性 */
margin-inline-start: 1rem; /* 而非 margin-left */
padding-inline: 1rem; /* 而非 padding-left/right */
border-inline-end: 1px solid; /* 而非 border-right */
/* 或使用 dir 属性 */
[dir="rtl"] .arrow { transform: scaleX(-1); }
字符集支持:全链路使用 UTF-8 编码;用 CJK 字符测试;测试 emoji(可占 2–4 字节);覆盖不同文字系统(拉丁、西里尔、阿拉伯等)。
日期/时间格式化:使用 Intl API 而非手写拼接:
// ✅ 使用 Intl API 做正确的格式化
new Intl.DateTimeFormat('en-US').format(date); // 1/15/2024
new Intl.DateTimeFormat('de-DE').format(date); // 15.1.2024
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(1234.56); // $1,234.56
复数规则:英语的 count !== 1 ? 's' : '' 写法对其他语言的复数规则不成立(如俄语的多复数形式),文档要求使用真正的 i18n 库:
// ❌ 坏:假设英语复数规则
`${count} item${count !== 1 ? 's' : ''}`
// ✅ 好:使用正确的 i18n 库
t('items', { count }) // 处理复杂复数规则
5. 加固维度三:错误处理
网络错误四要素:展示清晰的错误信息、提供重试按钮、解释发生了什么、在适用时提供离线模式,并处理超时场景。文档给出的示例是"带恢复路径的错误态":
// 带恢复路径的错误态
{error && (
<ErrorMessage>
<p>Failed to load data. {error.message}</p>
<button onClick={retry}>Try again</button>
</ErrorMessage>
)}
表单校验错误:错误信息内联在字段附近;消息清晰具体;给出修正建议;不要不必要地阻塞提交;出错时保留用户已输入的内容。
API 错误:按状态码分别处理——
400:展示校验错误401:重定向到登录403:展示权限错误404:展示 not found 状态429:展示限流提示500:展示通用错误并提供支持入口
优雅降级:核心功能在无 JavaScript 时可用;图片带 alt 文本;渐进增强;为不支持的特性提供 fallback。
6. 加固维度四:边界条件与极端情况
文档按六种子场景列出要求:
空状态(Empty states):列表无条目、搜索无结果、无通知、无数据可展示——每一种都要提供明确的下一步行动(next action),而不是留白。
加载状态(Loading states):覆盖初始加载、分页加载、刷新三类时机;说明正在加载什么("Loading your projects...");长操作给出时间估计。
大数据集:分页或虚拟滚动;提供搜索/过滤能力;做性能优化;不要一次加载 10,000 条。
并发操作:防止重复提交(loading 时禁用按钮);处理竞态条件;乐观更新要带回滚;冲突要有解决机制。
权限状态:无查看权限、无编辑权限、只读模式——都要清楚解释"为什么"。
浏览器兼容:现代特性配 polyfill;不支持的 CSS 有 fallback;用特性检测(feature detection)而不是浏览器嗅探;在目标浏览器上实测。
7. 加固维度五:输入校验与消毒
客户端校验:必填项、格式校验(email、电话、URL)、长度限制、模式匹配、自定义规则。
服务端校验(永远需要):绝不只信任客户端;对所有输入做校验与消毒;防注入攻击;加限流。
约束表达:HTML 层面把约束显式声明出来,并用 aria-describedby 把提示与输入框关联:
<!-- 显式声明约束 -->
<input
type="text"
maxlength="100"
pattern="[A-Za-z0-9]+"
required
aria-describedby="username-hint"
/>
<small id="username-hint">
Letters and numbers only, up to 100 characters
</small>
8. 加固维度六:无障碍韧性
- 键盘导航:所有功能可键盘到达;Tab 顺序符合逻辑;模态框内做焦点管理;长页面提供跳过链接(skip links)。
- 屏幕阅读器:正确的 ARIA 标签;动态变化用 live region 播报;描述性的 alt 文本;语义化 HTML。
- 高对比模式:在 Windows 高对比模式下测试;不依赖颜色作为唯一视觉通道;提供替代性视觉线索。
这一维度与仓库中 audit.md 的可访问性检查项(对比度、ARIA、键盘导航、表单问题)在关注点上高度重叠,可以推断两者在流程上的分工是:harden 负责动手补齐缺失的韧性,audit 负责打分式地量化这些维度的达成度(0–4 分制,并给出 P0–P3 严重级别的问题清单与建议命令)。
9. 加固维度七:性能韧性
慢速连接:图片渐进加载;骨架屏(skeleton screens);乐观 UI 更新;用 service worker 支持离线。
内存泄漏:清理事件监听器;取消订阅;清除 timer/interval;组件卸载时中止未完成请求(abort pending requests)。
节流与防抖:
// 搜索输入防抖
const debouncedSearch = debounce(handleSearch, 300);
// 滚动处理器节流
const throttledScroll = throttle(handleScroll, 100);
10. 测试策略
手动测试六项:用极端数据测(超长、超短、空);用不同语言测;离线测;把网络节流到 3G 测;用屏幕阅读器测;纯键盘导航测,外加在旧浏览器上测。
自动化测试五类:边界情况的单元测试;错误场景的集成测试;关键路径的 E2E 测试;视觉回归测试;无障碍测试(axe、WAVE)。
文档在此标注了一条 IMPORTANT:加固的本质是"预期不可预期"——真实用户会做出你从未想象过的事。
11. 红线清单:harden 的七条 NEVER
文档最后以 NEVER 列表封死常见失误:
- 绝不假设完美输入(一切皆需校验)
- 绝不忽视国际化(按全球化设计)
- 绝不写通用错误信息("Error occurred" 不可接受)
- 绝不遗忘离线场景
- 绝不只信任客户端校验
- 绝不对文本使用固定宽度
- 绝不假设英语长度的文本
- 绝不让单个组件出错就阻塞整个界面
12. 验证加固:极端输入验收清单与 polish 交接
当上述加固完成后,文档给出九项逐项可勾选的验证清单:
- 长文本:用 100+ 字符的姓名测试
- Emoji:在所有文本字段中使用 emoji
- RTL:用阿拉伯语或希伯来语测试
- CJK:用中/日/韩文字测试
- 网络问题:断网、节流连接
- 大数据集:用 1000+ 条目测试
- 并发操作:快速连点提交 10 次
- 错误:强制触发 API 错误,测试所有错误态
- 空数据:清空所有数据,测试空状态
验证阶段可以借助仓库已有的工具链做交叉验证:hook 在 UI 文件编辑后自动运行检测器(SKILL.src.md Hooks 一节),像文本溢出这类有 DOM 几何证据的问题会被 checks.mjs 中的规则自动捕获(见第 3.1 节的实现说明),夹具 text-overflow.html 展示了这些规则的报/不报边界。
当边界情况全部覆盖后,流程的最后一步是交接:执行 /impeccable polish 做最终 pass。这与 polish.md 的内容相互印证——polish 的"Interaction and state"章节明确要求"在产品可能遇到的地方验证长内容、缺失内容、本地化、离线、慢速与权限受限场景",即 polish 消费 harden 建立起来的韧性;其分诊顺序中的第 2 项也正是"补齐缺失的 loading、empty、error、success、disabled 和 permission 状态"。至此,harden 与 polish、audit 在 impeccable 的 Refine 流水线中形成了清晰的上下游关系:harden 补韧性,audit 量分,polish 收尾。
13. 小结
harden.md 的价值在于把"生产就绪"从一句口号拆成了可执行的方法:三类弱点评估(极端输入、错误场景、国际化)确定范围,七个加固维度(文本溢出、i18n、错误处理、边界条件、输入校验、无障碍韧性、性能韧性)给出带代码示例的修复模式,极端输入验收清单提供可勾选的完成标准,NEVER 清单封住常见失误。结合仓库中可自动运行的 text-overflow 检测规则与 polish/audit 参考文档,这套手册既可作为 Agent 的技能手册驱动 AI 助手完成加固,也可直接作为人类开发者评审前端代码时的加固检查表使用。
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 StartedRust0623
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