设计系统 AGI 化的前置工作:规则的形式化表达与可计算约束

📅 2026/7/19 16:15:38
设计系统 AGI 化的前置工作:规则的形式化表达与可计算约束
设计系统 AGI 化的前置工作规则的形式化表达与可计算约束一、这个对话框不能有超过两个按钮——一条无法自动检查的规则设计师在规范文档中写了模态对话框最多包含两个操作按钮确认 取消超过两个应使用下拉菜单。这是合理的 UX 规则——避免给用户太多选择。但当前的 Stylelint/ESLint 规则引擎无法检查这条规则。因为它不是属性值层面的约束而是组件结构层面的语义约束。要让 AI包括未来的 AGI能够自动执行设计系统的规则前置工作是把自然语言的设计规范转换为形式化、可计算的约束表达式。这个转换过程不是 AI 能自动完成的——它需要人类设计系统维护者明确回答这条规则到底在约束什么。二、设计规则的形式化层次设计规则的形式化遵循特定的层次结构。从设计规范文档出发经过规则类型判定规则被划分为以下五种约束类型并最终统一为可计算约束 JSON属性约束针对单一组件的视觉属性例如button.border-radius 4px这类规则可直接转换为 Stylelint 规则。结构约束涉及组件内部元素的数量或组合例如Modal 子元素中 button 数量 ≤ 2这需要结合 ESLint 规则与 AST 计数来实现。关系约束定义组件之间的依赖关系例如若存在 ErrorMessage则必存在 rolealert通常通过自定义 Lint 规则处理。语义约束关注业务含义与视觉表现的对应例如primary action 必须用 highest contrast 颜色这需要 AI 语义分析配合 Token 校验。流程约束涉及用户交互行为序列例如删除操作必须有确认步骤这是最难自动化的部分需要行为检测机制。三、设计规则的形式化表达// design-rules/formal-rules.schema.ts // 设计规则的形式化表达 Schema /** * 约束运算符 */ type ConstraintOperator | eq // 等于| neq // 不等于| gt // 大于| gte // 大于等于| lt // 小于| lte // 小于等于| in // 在枚举值中| notIn // 不在枚举值中| matches // 正则匹配| between; // 在区间内/**约束目标约束应用在什么上*/type ConstraintTarget | css-property // CSS 属性| jsx-prop // JSX Props| dom-structure // DOM 结构子元素数量/类型| component-hierarchy // 组件层级关系| user-flow; // 用户操作流/**一条形式化的设计规则设计意图每一条规则都有完整的三要素适用条件when约束内容constraint违规后果violation/interface FormalRule {/* 规则 ID唯一标识 */id: string;/** 规则分类 */category: visual | structural | behavioral | accessibility;/** 严重程度 */severity: error | warning | suggestion;/**适用条件什么情况下这条规则生效使用类似 MongoDB 查询的语法{ component: Modal, props.variant: confirm }*/when: RuleCondition;/**约束内容这条规则要求什么可以是一个简单约束单条规则或复合约束多条规则的逻辑组合*/constraint: RuleConstraint;/**违规信息模板使用 {target}、{expected}、{actual} 占位符*/violationMessage: string;/** 规则的原始文档引用可追溯 */source: string;/** 是否可自动修复 */autoFixable: boolean;/** 自动修复的 AST 操作如果 autoFixable */fix?: FixAction[];}interface RuleCondition {/** 适用的组件名/component?: string;/* Props 条件/props?: Recordstring, any;/* 父组件条件/parent?: string;/* 自定义 JavaScript 表达式用于复杂条件 */expression?: string;}interface RuleConstraint {/** 约束目标/target: ConstraintTarget;/* 目标属性路径/property?: string;/* 运算符/operator: ConstraintOperator;/* 期望值 */expected: any;}interface FixAction {type: replace | insert | remove | modify-ast;target: string;value?: any;}typescript // design-rules/example-rules.ts // 设计规则实例——从自然语言到形式化表达的转换 import { FormalRule } from ./formal-rules.schema; /** * 示例 1按钮圆角规则 * * 自然语言所有主要按钮的圆角为 4px * ↓ 形式化 */ const buttonRadiusRule: FormalRule { id: DS-BTN-001, category: visual, severity: error, when: { component: Button, props: { type: primary } }, constraint: { target: css-property, property: border-radius, operator: eq, expected: 4px }, violationMessage: 主按钮的圆角必须为 4px当前为 {actual}, source: 设计规范 v2.3 § 3.1.2, autoFixable: true, fix: [ { type: replace, target: border-radius, value: 4px } ] }; /** * 示例 2对话框按钮数量规则 * * 自然语言模态对话框最多包含两个操作按钮确认取消超过两个应使用下拉菜单 * ↓ 形式化 */ const modalButtonsRule: FormalRule { id: DS-MODAL-001, category: structural, severity: warning, when: { component: Modal, expression: true // 所有 Modal 都检查 }, constraint: { target: dom-structure, property: children.filter(c c.type Button c.props.isAction).length, operator: lte, expected: 2 }, violationMessage: 模态对话框的操作按钮不应超过 2 个当前有 {actual} 个。多余的按钮建议使用 Dropdown 菜单, source: 设计规范 v2.3 § 5.4.1, autoFixable: false // 需要人工判断哪些按钮应移入下拉菜单 }; /** * 示例 3错误信息关联规则 * * 自然语言表单错误信息必须通过 aria-describedby 关联到对应输入框 * ↓ 形式化 */ const errorMessageAssocRule: FormalRule { id: DS-FORM-003, category: accessibility, severity: error, when: { component: AccessibleInput, props: { error: { $exists: true } } }, constraint: { target: jsx-prop, property: aria-describedby, operator: neq, expected: undefined }, violationMessage: 存在错误信息的输入框必须有 aria-describedby 属性, source: WCAG 2.1 成功准则 3.3.1, autoFixable: true, fix: [ { type: modify-ast, target: aria-describedby, value: automatically-generated-id } ] }; /** * 示例 4主操作颜色规则语义约束——最难形式化 * * 自然语言页面中的主要操作按钮必须使用所有可见按钮中对比度最高的颜色 * ↓ 形式化无法完美表达只能近似 */ const primaryActionColorRule: FormalRule { id: DS-COLOR-005, category: visual, severity: warning, when: { component: Button, props: { type: primary } }, constraint: { target: css-property, property: background-color, operator: in, expected: [var(--color-brand-primary), var(--color-action-primary)] }, violationMessage: 主操作按钮应使用品牌主色当前使用了非标准颜色 {actual}, source: 设计 Token 规范 § 2.1, autoFixable: false };// design-rules/rule-engine.ts // 设计规则执行引擎 import { FormalRule } from ./formal-rules.schema; /** * 规则执行引擎 * * 加载形式化规则库对代码做合规检查 * * 设计意图规则引擎不关心规则是怎么来的人写的还是 AI 蒸馏的 * 只关心这条规则能否在当前代码片段上执行 */ class DesignRuleEngine { private rules: FormalRule[] []; loadRules(rules: FormalRule[]): void { this.rules rules; } /** * 对代码片段执行所有适用的规则 * * param ast - 组件的 AST 表示 * param context - 执行上下文文件路径、组件名等 * returns 违规列表 */ check(ast: any, context: any): Violation[] { const violations: Violation[] []; for (const rule of this.rules) { if (!this.isApplicable(rule, ast, context)) continue; const result this.evaluateConstraint(rule.constraint, ast, context); if (!result.passed) { violations.push({ ruleId: rule.id, severity: rule.severity, message: this.formatMessage( rule.violationMessage, result.actual ), autoFixable: rule.autoFixable, fix: rule.fix }); } } return violations; } /** * 判断规则是否适用于当前上下文 */ private isApplicable( rule: FormalRule, ast: any, context: any ): boolean { const { when } rule; // 组件名匹配 if (when.component context.componentName ! when.component) { return false; } // Props 条件匹配 if (when.props) { for (const [key, value] of Object.entries(when.props)) { if (context.props?.[key] ! value) return false; } } // 自定义表达式 if (when.expression) { // 在沙箱中执行表达式 // const fn new Function(ast, context, return ${when.expression}); // if (!fn(ast, context)) return false; } return true; } /** * 执行约束检查 */ private evaluateConstraint( constraint: any, ast: any, context: any ): { passed: boolean; actual?: any } { // 获取目标值 let actual: any; // CSS 属性检查 if (constraint.target css-property) { actual this.getCSSPropertyValue(ast, constraint.property); } // JSX Prop 检查 else if (constraint.target jsx-prop) { actual context.props?.[constraint.property]; } // DOM 结构检查 else if (constraint.target dom-structure) { actual this.evaluateDOMExpression(ast, constraint.property); } // 执行运算符判断 const passed this.applyOperator( actual, constraint.operator, constraint.expected ); return { passed, actual }; } private applyOperator( actual: any, operator: string, expected: any ): boolean { switch (operator) { case eq: return actual expected; case neq: return actual ! expected; case gt: return actual expected; case gte: return actual expected; case lt: return actual expected; case lte: return actual expected; case in: return Array.isArray(expected) expected.includes(actual); case notIn: return Array.isArray(expected) !expected.includes(actual); default: return false; } } private getCSSPropertyValue(ast: any, property: string): any { return null; } private evaluateDOMExpression(ast: any, expr: string): any { return null; } private formatMessage(template: string, actual: any): string { return template.replace({actual}, String(actual)); } } interface Violation { ruleId: string; severity: error | warning | suggestion; message: string; autoFixable: boolean; fix?: FixAction[]; }四、形式化的边界——什么规则永远无法形式化审美规则。这个对话框看起来不够优雅——这是真人的审美判断任何形式化表达都会丢失关键信息。上下文相关的用户体验规则。在电商场景中促销标签的颜色应该用暖色系——这条规则依赖于电商场景这个语义上下文而代码中无法自动提取当前页面是否为电商场景。创新的例外。正常情况下按钮圆角 4px但如果设计团队决定在特定营销活动页使用更大的圆角来传递活泼的氛围4px 规则可以被打破。——所有规则都有例外而自动规则引擎要么过于死板不允许例外要么过于宽松允许太多例外导致规则失效。五、总结设计系统 AGI 化的前置工作是将自然语言的设计规范转换为形式化的规则表达式。这不是 AI 的工作——是人类设计系统维护者的工作。三条核心原则规则必须可计算——给定任意代码片段计算结果是通过或不通过从简单规则开始——先形式化按钮圆角这类确定性规则再逐步处理语义约束保留人工判断出口——规则引擎的severity: warning和autoFixable: false就是为那些不确定的规则保留的空间当规则库覆盖了设计规范的 70%属性的、结构的、可计算的AI 就能在剩下的 30%语义的、审美的、需要判断的上发挥真正的推理价值。