Bytebase 前端 UX 技术债清零迁移:一份从 814 处违规走向零容忍强制的完整执行指南
2026/9/15 15:13:21 网站建设 项目流程

Bytebase 前端 UX 技术债清零迁移:一份从 814 处违规走向零容忍强制的完整执行指南

【免费下载链接】bytebaseDatabase governance built for humans and agents — controlling changes and access across every major database.项目地址: https://gitcode.com/GitHub_Trending/by/bytebase

本文以 Bytebase 仓库中的前端 UX 技术债迁移计划(docs/superpowers/plans/2026-08-24-frontend-ux-legacy-debt-migration.md)为主体,结合 UX 规范、静态扫描器与共享组件源码展开。你将看到:这 557 个违规指纹、814 处出现、横跨 218 个文件的债务如何被拆解为 12 个可独立审查的任务逐步清除;每个任务在什么约束下执行、产出什么、提交什么;以及最终的零债务状态下,扫描器如何从"基线比对"演进为"零容忍强制"。读完你可以直接复用这套"棘轮式"技术债治理方法论。

一、背景:UX 指南与"棘轮"机制

Bytebase 的 React 产品前端自 2026-03-30 引入(见docs/agents/frontend-ux.md的 Evolution References),随后通过 Base UI、shadcn 风格封装、Tailwind 语义 token 与 CVA 模式建立了统一的 UI 契约。这份契约的权威文本是docs/agents/frontend-ux.md,它声明自己是 Bytebase 产品 UI 的"canonical design and composition contract",适用于frontend/src/下所有 React 代码。

该规范最核心的设计理念是一个词:棘轮(ratchet)。规范原文指出:

The guideline is an incremental ratchet. New shared UI and every UI element modified by a change must follow it. Unrelated legacy violations may remain, but they are not examples to copy and must not increase.

也就是说:新代码和改动的 UI 必须遵守规范;历史遗留违规可以暂时存在,但只减不增。这份"允许存在"的债务被记录在检入仓库的基线文件frontend/scripts/ui-guideline-legacy-debt.json中——它是对未改动代码的"宽限额度",而非设计备选方案。

迁移计划的终极目标正是打破这个"允许存在"的状态:移除每一条当前的 UX 指南违规、删除临时的 legacy-debt 文件、让扫描器在零违规状态下强制运行

技术栈与规范分层

计划文档明确列出了技术栈:React、TypeScript、Base UI、Tailwind CSS v4 语义工具类、CVA、StyleX、Vitest。而frontend-ux.md给出了"实现所有权"(Implementation Ownership)的分工表,这是理解所有迁移任务的前提:

关注点归属规则
行为与无障碍frontend/src/components/ui/下的 Base UI 封装先用共享原语,再考虑原生控件或特性自有交互代码
变体共享原语中的 CVA消费者需要相同视觉状态时添加具名变体
重复测量frontend/src/components/ui/styles.stylex.ts把稳定的控件/表单/行/布局测量放入 StyleX
上下文布局Tailwind 工具类使用语义、非任意的工具类做局部流式与响应式组合
颜色与主题frontend/src/assets/css/tailwind.css中的 token使用语义 token;禁止裸调色板颜色或手写dark:覆盖
页面组合共享布局与下述配方不要按特性重建页面、表单、Sheet、表格框架

规范还强调"不要引入第二套样式框架"——StyleX、Tailwind、CVA 是当前系统的互补部分。

二、债务全景:当前库存(Current Inventory)

计划以 2026-08-24 的frontend/scripts/ui-guideline-legacy-debt.json快照为基线,给出了完整的违规清单。这份清单不是随意枚举,而是按"规则 × 指纹 × 出现次数 × 涉及文件 × 迁移难度"五个维度建模:

规则指纹出现次数文件数难度
no-space-between994简单,机械化替换
no-off-scale-gap273027简单,但需选择关系本意的间距
no-arbitrary-type152215简单到中等,层级决策
no-manual-dark561简单,在复杂属主内做语义 token 替换
no-off-scale-radius518643普通框架简单,拼接控件中等
no-ad-hoc-sheet-width774中等,工作流宽度决策
no-raw-color25934196中等,视觉语义迁移
no-button-dimension-override588450中等;部分消费者需要共享方形按钮契约
no-raw-table565中等到困难,取决于操作型还是嵌入型内容
no-native-control119220102最难,因为原语替换后行为必须存活
no-literal-color232困难,功能性颜色收尾
合计557814218 个独立文件

一个关键洞察是债务的结构性分布:前 73 个文件只包含间距、排版、圆角、主题和语义颜色类债务,合计 150 个指纹、202 处出现。这些是"机械安全"的叶级样式迁移,计划要求它们在交互式迁移开始前全部完成——先把低风险的做了,把最难的no-native-control(220 处出现)和no-raw-color(341 处出现)留到后面,让每个任务都有独立的、可验证的产出。

三、可用的权威 API:Allowed APIs

迁移不是无中生有,而是"把特性代码迁到共享原语上"。计划文档给出了完整的允许 API 清单,每条都指向仓库中的真实实现:

  • 基础与工作流配方docs/agents/frontend-ux.md中的 Foundations(间距、控件、排版、颜色、边框圆角焦点层级)与表单/表格/Sheet 工作流配方。
  • 控件测量frontend/src/components/ui/styles.stylex.ts——只允许xssmmdlg四档。从源码看,这四档的完整契约是:
档位高度内联 padding字号/行高图标内部 gap
xs24px6px12/16px14px6px
sm28px8px12/16px16px6px
md36px12px14/20px16px8px
lg40px16px14/20px20px8px
  • 命令按钮frontend/src/components/ui/button.tsx——使用ButtonButtonPropsbuttonVariants,禁止原生命令按钮。源码显示其 CVA 提供了variant(default/destructive)、appearance(solid/outline/secondary/link)与size(default/xs/sm/md/lg)三个维度,defaultmd的别名。
  • 文本输入frontend/src/components/ui/input.tsxtextarea.tsxsearch-input.tsxnumber-input.tsx
  • 选择控件select.tsxcombobox.tsxcheckbox.tsxradio-group.tsxswitch.tsxsegmented-control.tsx
  • Sheetfrontend/src/components/ui/sheet.tsx——具名宽度层级为narrowpanelmediumstandardwidelargexlargehugeworkspace。从源码看,这些层级对应 384px、500px、640px、704px、832px、1024px、1120px、95vw 以及响应式上限 960px 的workspace
  • 表格frontend/src/components/ui/table.tsx——TableTableHeaderTableBodyTableRowTableHeadTableCellTableEmptyView。源码确认TableHead内置了sortablesortActivesortDironSort排序协议和resizable拖拽调宽能力,TableEmptyView承载空态。
  • 语义颜色frontend/src/assets/css/tailwind.css

语义颜色 token 在tailwind.css中通过 CSS 自定义属性定义(均为 RGB 三元组形式,消费时经rgb(var(--color-x))使用),例如:

--color-accent: 79 70 229; /* #4f46e5 主操作与选中态 */ --color-main: 24 24 27; /* #18181b 主文本 */ --color-control: 82 82 91; /* #52525b 控件与次级文本 */ --color-control-light: 113 113 122; --color-control-bg: 243 244 246; --color-block-border: 229 231 235; --color-control-border: 209 213 219; --color-info: 37 99 235; /* #2563eb 状态色 */ --color-warning: 245 158 11; --color-error: 220 38 38; --color-success: 22 163 74; --color-background: 255 255 255; --color-overlay: 0 0 0;

主题切换通过"主题作用域重定义这些语义 token"实现,因此规范禁止手写dark:变体——这就是no-manual-dark规则存在的根本原因。

四、全局约束:迁移的底线

计划为所有任务设定了全局约束(Global Constraints),它们是审查每个 PR 的标尺:

  1. 路径约定:任务作用域块中的路径相对于frontend/,除非另有前缀。
  2. 行为保全清单:必须保留 API 调用、路由、权限、变更操作、加载状态、选择语义、键盘行为、拖拽/上传、焦点、编辑器命令与分页。
  3. 属主完整性:一个任务必须移除其直接编辑的每个文件的所有基线指纹——不能修一个 class 却留下同一属主内相邻的债务。
  4. 基线纪律:绝不手工增加或编辑violations;只有在作用域报告为空后才运行node frontend/scripts/check-ui-guideline.mjs --write-baseline
  5. 语义角色而非视觉猜测:主文本用main,次级层级用control/control-light,表面用background/control-bg,边界用block-border/control-border,状态用状态 token。
  6. 禁止逃逸:不得直接从特性代码导入 Base UI 原语来躲避扫描器;不得用样式化的div替换原生控件(须经共享原语保留原生语义);不得新增一次性语义 token、任意测量值、消费者自有的控件高度、手写暗色变体或内联字面颜色。
  7. 隐藏输入豁免:隐藏表单输入不是可见 UI,应由扫描器精确排除;文件输入仍在范围内,应使用共享包装。
  8. 可独立审查:每个任务独立可审查,且随该任务提交缩减后的债务文件。

这些约束回答了迁移中最常见的三个"捷径"诱惑:直接改基线、绕过共享原语、把 div 伪装成按钮——全部被明确禁止。

五、12 个任务的执行路线图

计划把整个迁移编排为 12 个任务,从"机械安全的叶级样式"逐步走向"行为敏感的共享控件、操作工作流、嵌入式渲染器与 SQL 编辑器表面"。下面逐一拆解。

Task 1:修复扫描器假阳性(Remove Scanner False Positives)

改动文件frontend/scripts/check-ui-guideline.mjscheck-ui-guideline.test.mjsui-guideline-legacy-debt.json(经写入器)。

产出:原生<input type="hidden">元素被排除——因为它们不渲染任何 UI;可见输入与文件输入仍然强制。

这是一个"先写测试"的任务:先添加包含 hidden、file、text 三种输入的失败测试,断言只有 file 和 text 输入产生no-native-control;运行CI=true pnpm --dir frontend exec vitest run scripts/check-ui-guideline.test.mjs确认 hidden 输入被错误报告;然后在 JSX native-control 访问器中只跳过静态type属性恰好为hidden的 input(不跳过动态类型或type="file");重跑测试、写入缩减后的快照并运行扫描器;确认 OAuth consent 指纹减少 7 处且没有其他原生输入条目消失。提交信息为refactor(frontend): ignore nonvisual hidden inputs

这个任务之所以排在第一位,是因为它直接决定了后续所有no-native-control迁移的噪音水平——如果 OAuth 表单的 hidden 字段一直报违规,Task 6 就永远无法"清空作用域报告"。

Task 2:迁移单出现 CSS-only 属主

文件:36 个各含 1 处出现的文件,包括src/app/layouts/SplashLayout.tsxsrc/components/DashboardFrameShell.tsxsrc/components/LearnMoreLink.tsxsrc/components/monaco/MonacoEditor.tsxsrc/components/UserAvatar.tsxsrc/modules/schema-diagram/SchemaDiagram.tsxsrc/modules/sql-editor/components/Welcome.tsxsrc/routes/auth/PasswordForgotPage.tsxsrc/routes/auth/SetupPage.tsxsrc/routes/project/plan-detail/components/deploy/DeployStageCard.tsx等。

执行要点

  • node frontend/scripts/check-ui-guideline.mjs --report-only捕获作用域报告,把确切的前置计数记入提交信息或 PR 说明。
  • 按角色替换每个 token:间距使用最近记录的文档关系;文本使用text-xstext-sm及自有的行高;普通框架使用rounded-sm;裸颜色使用语义工具类。
  • 对含行为逻辑的属主运行最近的既有测试;纯 token 的展示型属主以扫描器覆盖代替源码字符串测试。
  • 预期减少:36 个指纹、36 处出现。提交为refactor(frontend): remove singleton UX styling debt

Task 3:迁移小型 CSS-only 属主

文件:28 个含 2~5 处出现的属主,例如src/components/ClassificationTree.tsxsrc/components/DashboardSidebar.tsxsrc/components/monaco/DiffMonaco.tsxsrc/routes/auth/SigninPage.tsxsrc/routes/workspace/profile/AccountSettingsPage.tsxsrc/routes/workspace/two-factor/RecoveryCodesView.tsx等。

要点:编辑前运行聚焦的属主测试;使用与 Task 2 相同的角色映射迁移整个属主——拼接控件允许使用方向性rounded-l-sm/rounded-r-sm,普通卡片必须用rounded-sm;Monaco、树图标、状态图标和侧边栏的改动需目视或经组件测试检查,因为它们的颜色编码了含义。预期减少 64 指纹、82 处出现,提交为refactor(frontend): remove small UX styling debt

Task 4:迁移集中式 CSS-only 工作流

文件:9 个(ReleaseInfoCard.tsxIssueDetailApprovalFlow.tsxIssueDetailCommentList.tsxIssueDetailDatabaseCreateView.tsxIssueDetailTaskRunTable.tsxPlanDetailRollbackSheet.tsxProjectPlanDetailPage.tsxProjectGitOpsPage.tsxProjectMaskingExemptionPage.tsx)。

要点:编辑前运行 issue-detail、plan-detail、GitOps、masking 四个聚焦套件;替换作用域内所有裸颜色、任意排版、不支持圆角、超规模间距与space-*token,同时保留层级与状态含义;SQL 或任务状态颜色按状态(success/warning/error/info)映射而非旧色相;在桌面与窄宽度下验证 issue 与回滚表面布局。预期减少 50 指纹、84 处出现。Task 2-4 完成后,全部 73 个 CSS-only 属主即零债务。提交为refactor(frontend): unify concentrated workflow styling

Task 5:补上缺失的方形按钮契约(The Missing Square Button Contract)

改动文件frontend/src/components/ui/button.tsxbutton.test.tsxstyles.stylex.test.tsxcheck-ui-guideline.test.mjs

产出Button接受shape="square",而size继续拥有高度、宽度、内边距、排版、gap 与图标测量。

要点

  • 先添加失败测试:在xs/sm/md/lg下渲染方形按钮,断言 24、28、36、40px 的方形契约且无消费者尺寸类。
  • 扩展 Button CVA,加入shape: { default, square }与尺寸/形状复合变体size-6size-7size-9size-10,每个零内联 padding。
  • 保持shape="default"为默认,保留所有既有外观与意图。
  • 新增扫描器测试:<Button shape="square" size="sm" />通过,而<Button className="size-7" />失败。
  • 明确禁止:不添加size="auto"appearance="unstyled"或任何无测量的逃逸口。既有h-autoh-full、20px、22px、34px 消费者必须采用最近的文档化契约或重构布局。

提交为feat(frontend): add square button sizing。这个契约之所以必要,是因为债务清单中no-button-dimension-override有 84 处出现——大量图标按钮通过h-*/size-*覆盖共享按钮的高度,而正确做法是让共享组件直接支持方形变体。

Task 6:迁移应用与认证控件

文件:7 个(SessionExpiredSurface.tsxEmailCodeSigninForm.tsxPasswordSigninForm.tsxUserPasswordFields.tsxMultiFactorPage.tsxOAuth2ConsentPage.tsxPasswordResetPage.tsx)。

要点:可见的原生命令按钮换成Button,密码可见性操作换成shape="square",裸颜色/圆角换成语义角色。必须原样保留 OAuth 表单的原生 POST 动作与 hidden 字段名——Task 1 已让这些 hidden 输入对扫描器中立,无需替换;同时保留提交按钮 name/value、Enter 提交、禁用态与浏览器密码管理器行为。提交为refactor(frontend): unify authentication controls

Task 7:迁移工作区资源与设置工作流

文件:15 个,覆盖src/routes/workspace/下的 EnvironmentsPage、GlobalMaskingPage、GroupsPage、LandingPage、MembersPage、RolesPage、ServiceAccountsPage、BrandingSection、SecuritySection、ThemePreview、UserPasswordSection、TwoFactorSetupPage、UserFormSheet 等。

要点:编辑前运行CI=true pnpm --dir frontend exec vitest run src/routes/workspace;原生选择换成Select/Combobox,可见文本/文件控件换成共享Input,命令换成带具名尺寸与形状的Button;Branding 与 Semantic Types 的文件输入accept、重置、ref 点击、同文件重选行为必须保留,替换原生节点前先添加聚焦上传测试;保留表格选择、角色/成员授权、环境重排、双因素恢复与表单脏状态。当前快照预期作用域为 63 指纹、100 处出现(Task 1 缩减前)。提交为refactor(frontend): unify workspace workflows

Task 8:迁移项目 Sheet、表格与操作

文件:23 个,覆盖 ProjectIssueDetailPage、ProjectPlanDashboardPage、ProjectSettingsPage、ProjectSyncSchemaPage、DatabaseDetailHeader、TableDetailDialog、ImportRevisionSheet、IssueDetailActionBar、PlanDetailHeader、DeployTaskFilter、PlanStatusAction 等。

要点:把四个 ad hoc Sheet 契约换成具名宽度——Import Revision 与 Target Selection 保持wide(去掉消费者宽度类)、移动端 review sheet 用panel、pending-task 预览用narrow;两张 Table Detail 表与 Project Sync 表换成共享表格原语,保留可排序表头、列宽、行操作、滚动与空/加载态;文件输入换成共享Input(保留acceptmultiple、拖拽、refs 与重置);命令按钮与尺寸覆盖换成具名Button尺寸与shape="square",保留 tab ARIA 与键盘导航;桌面与移动宽度下验证宽表与宽 Sheet。提交为refactor(frontend): unify project workflows

Task 9:迁移共享与实例复合控件

文件:34 个,包括AccountMultiSelect.tsxAdvancedSearch.tsxAuditLogTable.tsxExprEditor.tsxIssueTable.tsxMarkdownEditor.tsxQuickstart.tsxsql-review/下四个文件、instance/下九个文件等。

要点:简单场景用共享控件;Advanced Search 与 ExprEditor 保留既有复合状态机,只把叶级 input/textarea/命令节点换成Input/Textarea/Button;Instance Assignment 换成共享表格原语且不改变水平溢出、选择与最小宽度行为;原生 select 换成Select,需搜索或自定义创建时用Combobox不得为复合行添加通用 pressable 逃逸口——命令用Button,非命令行语义保持显式。Watermark.tsx留到 Task 12;本任务列出的每个文件离开本任务时都必须零债务。提交为refactor(frontend): unify shared composite controls

Task 10:迁移 Schema、AI 与 Agent 嵌入式表面

文件:19 个,覆盖schema-editor/Panels/(IndexesEditor、PartitionsEditor、PreviewPane、TableColumnEditor、TableList)、schema-diagram/ER/TableNode.tsxschema-diagram/Navigator/modules/ai/下六个文件与modules/agent/下三个文件。

要点:编辑前运行四个模块目录的全部测试;schema-editor 的方形行操作通过共享 Button 契约统一且不改变周围网格尺寸;ER TableNode 换成共享表格原语但保留table-fixed、节点尺寸、端口、拖拽/选择行为与图专属密度;AgentChat 的 Markdown 表格渲染换成共享表格原语,用渲染器局部的紧凑 class 覆盖——不要把操作型表头高度强加给散文表格;AI/Agent 的原生控件与裸颜色在保留流式、中止、重试、历史选择、键盘提交、textarea 增长与覆盖层的前提下替换;原语替换前先为 Markdown 表格输出、ER 节点几何、提示键盘行为与历史选择添加聚焦测试。提交为refactor(frontend): unify embedded agent and schema UI

Task 11:最后迁移 SQL 编辑器控件

文件:42 个,覆盖src/modules/sql-editor/下的 ConnectChooser、HistorySearchInput、VirtualDataTable、SharePopoverBody、SQLUploadButton、TabItem、TabList、TerminalPanel 等。快照中(排除 CSS-only 属主后)为 42 文件、58 指纹、71 处出现,多数是按钮尺寸;行为敏感尾部包括 ConnectChooser、HistorySearchInput、VirtualDataTable、SharePopoverBody、SQLUploadButton、TabItem、TabList 与 TerminalPanel。

要点:先在完整 SQL Editor 模块套件上运行并保存行为基线;按四个独立提交的子波次迁移——连接/工具栏控件、Schema/面板控件、结果视图控件、然后是标签/上传/终端;尺寸映射:20px 与 22px 控件换xs、28px 换sm、36px 换md、方形控件换shape="square"——不要为了迁就偶然的相邻测量而缩小本应共享的控件;原生搜索/文本/文件控件换成共享原语但保留 IME、Enter/Escape 处理、文件选择、焦点恢复、尺寸调整、虚拟化、剪贴板与编辑器快捷键;保留结果表单元格几何与虚拟化测量,共享 Button 样式不得改变行高或测量的画布/表格尺寸;每个子波次后运行聚焦测试,四个波次后运行完整 SQL Editor 套件。提交每个子波次。

Task 12:解决功能颜色并移除债务系统

改动文件frontend/src/components/Watermark.tsxfrontend/src/assets/css/tailwind.css(仅当确实需要新语义角色时)、check-ui-guideline.mjscheck-ui-guideline.test.mjs删除frontend/scripts/ui-guideline-legacy-debt.json;更新docs/agents/frontend-ux.mdfrontend/AGENTS.md

要点

  • 添加失败的 Watermark 测试:证明两个水印层仍生成带预期不透明度的非空 data URL,且主题解析不会产生无效 canvas 颜色。
  • Task 9 期间把AccountMultiSelect的字面蓝换成bg-info
  • Watermark 颜色从既有语义errorcontrolCSS 通道解析,在 canvas 适配器中应用安全专属 alpha——不得把字面 RGB 字符串搬到另一个 TypeScript 文件,也不得添加扫描器忽略路径。
  • 运行node frontend/scripts/check-ui-guideline.mjs --report-only并断言输出No UI guideline violations found
  • 添加零债务状态下无债务文件运行的失败集成测试。
  • 简化扫描器:普通模式对任何违规失败、对零违规成功;移除基线比对、陈旧条目处理、元数据与--write-baseline支持。
  • 删除ui-guideline-legacy-debt.json,更新权威文档与 Agent 指南为"零容忍强制"。
  • 即使移除基线比对测试,也要为每条规则保留单元覆盖。
  • 提交为refactor(frontend): enforce zero UX guideline debt

至此,债务系统完成了它的全部生命周期:记录债务 → 缩减债务 → 归零 → 拆除债务记录机制本身

六、扫描器源码级原理:它到底在检查什么

理解迁移计划的最好方式,是读懂执行者——frontend/scripts/check-ui-guideline.mjs。它自称"conservative static scanner, not a complete Tailwind evaluator",即一个保守的静态扫描器,不是完整的 Tailwind 求值器。

规则引擎与正则词汇

扫描器定义了legacyRules(7 条历史规则)与enforcedRules(12 条,按字母排序),并维护两组批准词汇:

  • 间距approvedGapValues = {"0","1","1.5","2","3","4","6","8"}——对应产品间距词汇 4/6/8/12/16/24/32 中的可用档位与相邻档位。
  • 圆角approvedRadiusValues = {"none","xs","sm","full"},CSS 侧为0var(--radius-xs)var(--radius-sm)var(--radius-full)
  • 裸颜色家族rawColorFamilies覆盖 slate/gray/zinc/neutral/stone 到 rose/black/white 全部 Tailwind 调色板,配合rawColorProperties(accent/bg/border/caret/divide/fill/outline/placeholder/ring/shadow/stroke/text)组成rawColorPattern
  • 字面颜色literalColorPattern匹配十六进制(#[\da-f]{3,8})与rgb/rgba/hsl/hsla函数形式,但排除var(--...)引用——这正是语义 token 体系合法性的来源。

每个 token 依次经rulesForToken判定,可同时命中多条规则(例如space-x-2命中no-space-betweenbg-gray-100命中no-raw-colordark:bg-gray-900命中no-manual-darkgap-[10px]命中no-arbitrary-gaptext-[13px]leading-[18px]命中no-arbitrary-type)。

特殊访问器

除通用 token 扫描外,扫描器还有四个专用访问器:

  • scanSheetWidth:对SheetContent的 className 检查w-/min-w-/max-w-前缀,命中即no-ad-hoc-sheet-width——强制消费端使用width变体(如width="wide")。
  • scanButtonDimensions:对非共享原语文件中的Button检查h-/size-覆盖,但豁免h-auto(内容派生高度)与断点前缀响应式覆盖——这正是文档中"h-auto可用于内容派生高度"与"布局属主可用标准断点前缀类应用完整响应式尺寸契约"两条规则的机器化。
  • scanLiteralColor:只检查 CSS 颜色属性(color或以 Color 结尾的属性)的字面值。
  • scanInlineRadius:检查内联样式对象中的borderRadiusborderTopLeftRadiusborder-bottom-right-radius等,命中即no-off-scale-radius——测试用例中4px50%var(--card-radius)均被判违规。

基线比对与棘轮语义

核心是compareWithBaseline:把当前违规与基线按[path, rule, token]键比对,产生三类问题——new(新增或计数增长)、stale(基线里有但当前已消失,即债务已被移除却未更新基线)、shared(共享原语内的违规,永远不许进基线)。getBaselineUpdateIssues则保证--write-baseline只能"删除既有债务",若新指纹或已强制规则的计数增长会直接以退出码 1 拒绝。

check-ui-guideline.test.mjs用 18 个测试用例固化了这套语义,包括"允许语义工具类与共享组件"、"拒绝新/变更指纹"、"拒绝债务移除后的陈旧基线条目"、"拒绝共享原语豁免"、"仅当债务缩减时允许基线更新"。这些测试既保护扫描器自身,也充当了计划 Task 1 与 Task 12 的行为基线。

三个运行模式

模式命令行为
普通(棘轮)node frontend/scripts/check-ui-guideline.mjs比对基线,违规或陈旧条目则以退出码 1 失败
报告node frontend/scripts/check-ui-guideline.mjs --report-only打印全部当前指纹,零违规输出No UI guideline violations found
写基线node frontend/scripts/check-ui-guideline.mjs --write-baseline仅当作用域报告为空时重写快照(含版本、规则与违规)

七、迁移的度量标准:每个任务的预期收缩

计划为几乎每个任务都标注了精确的预期减少量,构成了一张可核对的"进度表":

任务预期指纹减少预期出现减少
Task 2(36 个单出现属主)3636
Task 3(28 个小属主)6482
Task 4(9 个集中工作流)5084
Task 7(15 个工作区文件)63(Task 1 缩减前)100(Task 1 缩减前)
Task 11(SQL 编辑器尾部)58(剩余)71(剩余)

配合 Task 1 的 7 处 OAuth hidden 输入缩减,所有数字在最终状态下归零——而 557 指纹的完整清单以frontend/scripts/ui-guideline-legacy-debt.json为唯一事实来源,每一次--write-baseline都必须发生在对应任务作用域报告为空之后。

八、最终验证:零债务状态的验收清单

Task 12 之后,计划给出了完整的最终验证序列:

CI=true pnpm --dir frontend fix CI=true pnpm --dir frontend check CI=true pnpm --dir frontend type-check CI=true pnpm --dir frontend test node frontend/scripts/check-ui-guideline.mjs --report-only git diff --check

附加的人工核对项:

  • 确认frontend/scripts/ui-guideline-legacy-debt.json不存在。
  • 确认没有特性文件直接导入 Base UI 控件来躲避共享原语。
  • 确认没有新语义 CSS token 与既有角色重复。
  • 审查 Tasks 7-11 改动的每个 Sheet、表格、表单与编辑器工作流的桌面/移动截图。
  • 已知无关的frontend/src/react/结构失败若仍存在须单独处理——不得被本次迁移掩盖,也不得被误判为 UX 回归

九、方法论总结:这套迁移计划可以复用到任何前端项目

回看整个计划,它其实是"规模化技术债治理"的一个可移植模板:

  1. 先有契约,后有扫描器docs/agents/frontend-ux.md定义语义(spacing 词汇、控件尺寸、语义 token、工作流配方),check-ui-guideline.mjs把可客观化的子集变成机器规则。
  2. 债务显式化ui-guideline-legacy-debt.json把"违反规范"从口头批评变成可审计、可缩减、不可增长的数据。
  3. 棘轮机制:基线只减不增,--write-baseline被实现为"只能删除既有债务"的操作,杜绝"顺手洗白"。
  4. 按风险排序:先机械安全的 CSS-only 迁移(73 个文件),再共享原语增强(方形按钮契约),再交互工作流,最后行为最敏感的 SQL 编辑器——每个任务独立审查、独立提交、有预期数字。
  5. 以测试锁定行为:每个原语替换前先补聚焦测试(上传行为、Markdown 表格、ER 几何、键盘行为),确保"原语换了,行为活了"。
  6. 终态是系统自毁:债务归零后,删除债务文件、简化扫描器为"零违规即通过",把治理从"允许存量"推进到"零容忍"。

这套"先测量、再分层、后归零"的路径,正是 Bytebase 把 814 处 UI 违规清出代码库的完整方法论,也回答了本文开头的问题:从"可以欠债"到"不允许欠债",迁移计划本身就是一份可执行、可验证、可复用的工程路线图。

如需深入,推荐按以下顺序阅读仓库资料:计划全文(docs/superpowers/plans/2026-08-24-frontend-ux-legacy-debt-migration.md)→ 规范(docs/agents/frontend-ux.md)→ 扫描器与测试(frontend/scripts/check-ui-guideline.mjscheck-ui-guideline.test.mjs)→ 共享原语(frontend/src/components/ui/下的 button、sheet、table、styles.stylex)→ 语义 token(frontend/src/assets/css/tailwind.css)→ 债务快照(frontend/scripts/ui-guideline-legacy-debt.json)。

【免费下载链接】bytebaseDatabase governance built for humans and agents — controlling changes and access across every major database.项目地址: https://gitcode.com/GitHub_Trending/by/bytebase

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询