Files
aurora-admin b59247231a
Regression / regression (push) Canceled after 0s
feat(安全+品牌): 对外产物发布脱敏(3注入点/2465文件0泄露) + Kole Cup 定稿
安全:CHANGELOG.md 是仓库内部变更流水(含服务器目录、镜像回滚标签、内网网段、
部署时序、AI 工作流用语),此前被 build-site.ps1 / precompute.mjs / build-mobile.mjs
原样注入站点,而站点是公网可下载的静态文件 —— 抓一次 /site/m/changelog.html
即可拿到内网地址段与服务器目录布局。

- 新增 tools/lib/redact-publish.mjs(零依赖,构建期过滤,不改 CHANGELOG.md,
  内部可追溯性完整保留)
- 接入 precompute.mjs(PC data.json/changelog.json)与 build-mobile.mjs
  (移动端更新日志页);build-site.ps1 不碰(ASCII-only 铁律)
- 只处理 changelog 字段:components[].sources 是规范实现源码,逐字保真
  (详情页代码区主动高亮注释,剥注释会破坏该功能)
- 实测消除:/opt/aurora-admin.prev-*、kole-ui-showcase:pre-*、docker compose、
  192.168.5.7、16 位产物指纹、1531/1531、并发会话/本会话/派子 agent
- settings.html 演示占位 IP 192.168.5.0/24(= 真实网段)改为 RFC 5737 的 192.0.2.0/24

品牌:Kole Cup 饮料杯标记定稿(几何 K → 圆角杯盖 + 杯身负空间 K,无吸管),
brand-mark.json 升 schemaVersion 3(paths 支持 { d, evenodd }),
verify:brand 增至 25 条(新增 B9b:负空间必须带 fill-rule)。

验证:发布集 2465 文件全量扫描 0 泄露;PC 回归 100%(1464/1464) ·
移动端 100%(807/807);门禁品牌 25 / 隔离 31 / 移动文档 12 / 示例 9 / 版本 40 / i18n 17 全绿;
已按 AGENTS §九 发布公网,2461/2461 逐字节一致,五项验收全过。

已知未处理(既有缺口,ROADMAP S7-P28 已记录):data.mobile.json 的
meta.generated 为墙上时钟,会让 CI 的「生成物可复现」断言在重跑构建后永远非空;
该 CI 流水线本身亦从未通过(无 runner)。
2026-09-23 07:31:06 +08:00

192 KiB
Raw Permalink Blame History

Changelog

所有显著改动按 SemVer 记录于此。格式基于 Keep a Changelog。

[Unreleased]

发布脱敏 · 对外产物滤掉基础设施细节(安全)

起因:抓一次公网 /site/m/changelog.html 就能拿到内网网段、服务器目录布局与部署时序 —— 站点是公网可下载的静态文件,而 CHANGELOG.md 是仓库内部变更流水,两者此前是直连的。

  • 新增 tools/lib/redact-publish.mjs(零依赖):构建期把「仅供内部」的基础设施细节替换成 不含事实的等价说法。不改 CHANGELOG.md —— 内部可追溯性完整保留,过滤只发生在写产物那一步。
  • 接入 3 处注入点:tools/precompute.mjs(PC 侧 data.json / changelog.json)、 tools/build-mobile.mjs(移动端更新日志页)。build-site.ps1 不碰 —— ASCII-only 铁律。
  • 只处理 changelog 字段:components[].sources 是规范实现源码,逐字保真不动 (详情页代码区还主动高亮注释,剥注释会破坏该功能)。
  • 实测命中并已消除:/opt/aurora-admin.prev-*、kole-ui-showcase:pre-*、docker compose build、 192.168.5.7、16 位产物指纹、1531/1531 对账数,以及「并发会话 / 本会话 / 派子 agent」等 暴露开发方式的用语。发布集 2465 文件全量扫描:0 命中。
  • 修正 site/scenario/settings.html 的演示占位 IP:原写 192.168.5.0/24,与真实服务器网段一致, 改为 RFC 5737 文档段 192.0.2.0/24。
  • 模块自带幂等性与误伤防护:只在与替换词相邻时才处理,正文代码跨度(如 pack-deploy --tar)不受影响。 实测 30 行真实 CHANGELOG 敏感行:0 残留、0 非幂等、0 标点畸形。 TRIGGERS(句子级闸门)与 RULES(替换规则)必须同步增删 —— 漏一个词会出现 「规则写好了但永不触发」的静默漏网(本轮实测踩到:**本会话直接产出的一批** 因 TRIGGERS 缺词而整行未过滤)。
  • 2026-09-23 已按 AGENTS §九 发布到公网:发布集 2461/2461 逐字节一致,五项验收全过, 公网复查 /opt/*、镜像名、内网 IP、产物流水全部 0 命中。

品牌标识 · Kole Cup 饮料杯标记(最终定稿)

  • 品牌图形由几何 K 改为饮料杯 + 负空间 K:圆角杯盖 + 上宽下窄圆角杯身,K 以 fill-rule="evenodd" 从杯身挖空。造型参考用户提供的 freeicon 图标语言(吸管、杯盖、 杯身比例),但路径为在 24 网格上独立绘制,未复制其原始数据;最终版按用户要求去掉了吸管。
  • brand-mark.json 升到 schemaVersion 3:geometry.paths 支持 { d, evenodd } 对象项, 供负空间挖空使用(旧字符串写法仍兼容)。
  • verify:brand 增至 25 条断言,新增 B9b:负空间路径必须带 fill-rule="evenodd" —— 缺了它 K 会被填成实心块,且不会报任何错(渲染仍然成功)。
  • 顶栏与 favicon 的资产路径、盒尺寸(PC 32×32 / 移动 26×26)、主题 mask 机制均不变。

品牌标识 · K-Node 图标真源重构

  • 新增 .design_library/kole-ui/brand/brand-mark.json,统一定义 K-Node 的三段几何、尺寸与 favicon 颜色。
  • 新增 tools/build-brand-mark.mjs / tools/verify-brand-mark.mjs,生成并校验独立 favicon、单色顶栏标记及生成数据。
  • PC 与移动端文档站改用同一组 SVG 资产;顶栏通过 currentColor mask 跟随亮/暗主题,保持原有导航盒尺寸与断点不变。
  • npm run build 纳入品牌资产构建,部署发布集显式要求品牌 SVG 与生成数据存在。
  • 2026-09-22 本地验收:品牌门禁 24 条、移动文档 12 条、移动站浏览器 263 条全部通过;主题、导航、路由、站点 smoke 与暗色检查全部通过。
  • 回归以本地 http://127.0.0.1:3400 为目标:PC 1464/1464(103 页,N/A 50)、移动端 807/807(47 页,N/A 10),各连续 8 轮一致,0 失败、0 超时。未部署。

品牌标识 · 几何 K 图标(favicon / 顶栏标记 / theme-color)

起因:品牌此前没有任何图形标识 —— 唯一 favicon 是内联 data-URI 里的字母「A」, 那是 v2.0.0「Aurora Admin → Kole UI」改名时漏掉的一处(PC 顶栏也是「A」, 而移动端站已是「K」;移动端文档站则完全没有 favicon)。 落地:几何 K(三笔画断笔描边),两端同源,含 favicon / 顶栏标记 / theme-color。

设计

  • 几何:24 网格上三个互不接触的笔画(竖笔 + 上斜 + 下斜),圆头描边。 笔画不接触既表达「独立组件拼组成系统」,也保证 16px 浏览器标签页尺寸下不糊。
  • 描边 2.25:在 24 网格下,16px 渲染时正好是 1.5px —— 等于规范原文 「线性图标,描边1.5px」(.design_library/kole-ui/specs/组件1.txt)。 实测比对了 1.5 / 1.875 / 2.25 三档在 20px 顶栏与 16px 标签页下的观感。
  • 圆角 rx=6(24 网格)= 32px 下 8px,即令牌 --kole-radius-large。

取色分两套(刻意,不是不一致)

  • favicon 硬编码 #2F54EB + #FFFFFF:它渲染在浏览器标签栏,不继承 html.kole-dark。 若走令牌,暗色下 --kole-color-text-inverse = #14161C,会变成「亮蓝底 + 近黑标记」, 在浅色标签栏上反而发闷。
  • 两端顶栏标记走 currentColor:实测暗色下自动解析为 rgb(20,22,28)、 底色转 rgb(107,140,255)(令牌化行为保真,与同页其它图标一致)。

新增

  • theme-color 双条(light #FFFFFF / dark #1C1F26,取 --kole-color-card-bg, 即 .topbar / .m-top 的 background,色值与视觉连续)。PC 写在 site/index.html; 移动端由新增的 __BRAND_HEAD__ 占位符经 tools/build-mobile.mjs 注入 7 个模板。

修正

  • site/index.html 的 favicon 字母 A → 几何 K;顶栏 .logo-mark 的 A → 几何 K (类名与 32×32 盒模型不变 —— ≤1366px 时它是顶栏唯一品牌标识)。
  • tools/build-mobile.mjs 移动端顶栏标记 K 文字 → 几何 K 图形(保留 class="m-logo-mark", verify-mobile-docs 会逐页断言它存在)。
  • site/app.js 首页 hero 标语 KOLE ADMIN DESIGN SYSTEM → KOLE UI DESIGN SYSTEM (同一改名的变形残留)。
  • 移动端文档站 7 个模板补 favicon(此前 rel="icon" 计数为 0,标签页显示默认地球图标)。

验收

  • 门禁:verify-site-routing OK(103 / 412 / 521)· verify-site-routes OK(零 4xx)· verify-mobile-docs OK(12 条 · 53 页)· verify-mobile-site OK(263 条 · 50 页, 控制台 0 错误)· verify:isolation OK(31 条)· verify:theme / verify:nav / verify:i18n / verify-icons 全 OK。
  • 回归:PC 1464/1464 · 移动端 807/807,各连跑 8 次一致。
  • 浏览器实测:PC 与移动端 favicon 405 字节逐字节一致;页面 DOM 中 >A< 清零; PC 站控制台错误从 1(favicon 404)降为 0。
  • 已知边界:og:image / apple-touch-icon / web manifest 未做(需位图管线, 见 ROADMAP S8-P4)。

图标系统(PC 5 端 + 移动端 6 端 + 全量图标库 + 预览页)

起因:用户要求「图标组件参考 TDesign / Element 等主流组件库,看他们的 icon 是怎么专门设计的、 设计内容有哪些,覆盖他们全部拥有的 icon 图标和功能」。 落地:2576 个图标(TDesign 线性 1334 + 面性 1020 + Element Plus 293,均 MIT), 11 个端实现全部接通,新增 5 个构建/门禁工具与 1 个图标预览页。 冻结规格:.design_library/kole-ui/icons/ICON-SPEC.md。

新增:图标数据管线(离线可复现,上游校验和钉死)

  • tools/fetch-icon-sources.mjs — 拉取并归一化上游 SVG → sources.json。 逐包校验 sha256(防「某天图标悄悄变了」);纯函数可单独 import(无副作用)。
  • tools/build-icons.mjs — 编译出 manifest.json(清单)/ registry.json(渲染数据)/ viewbox.js(viewBox 例外表)/ core.js(内联运行时)/ ATTRIBUTION.md(MIT 归属,分发必带)。
  • tools/build-icon-aliases.mjs — 别名层,让 Element UI 全部 282 个历史图标名与 移动端既有 9 个字形名都能落到真实图标(旧调用点零破坏)。
  • tools/inject-icon-table.mjs — 把 core 表注入 11 个端实现的标记块,杜绝「11 份手抄表必然漂移」。
  • tools/verify-icons.mjs — 11 条静态断言(产物一致 / 无 view-box 残留 / 描边全 1.5 / core 可渲染 / 别名不遮蔽 / 各端都能查到名 / 分组覆盖率 / 路径数字与源逐值一致)。

修正:两个上游缺陷在构建期抹平(此处是本仓库的增量,不是照抄)

  1. view-box 拼写错误:TDesign 全部 2356 个 SVG 把属性写成 view-box(无效属性, 浏览器忽略 → 图标按默认视口缩放)。构建期两种拼写都读,产物统一写回规范的 viewBox。
  2. 描边宽度 2 → 1.5:上游为 stroke-width="2"(24 网格),本仓库规范 (组件1.txt「图标规范:线性图标,描边1.5px,尺寸16/20/24px」)要求 1.5,构建期归一。 另丢弃 fill="transparent" 命中区路径(那是热区不是视觉内容)。

修正:自测发现的数据损坏缺陷(构建期把坐标改错)

  • 现象:归一化把路径数字四舍五入到 2 位小数,看似无害;但 SVG path 允许「隐式分隔」—— q-13.005.48-22.5 是三个数(-13.005、.48、-22.5,靠 - 和 . 当分隔符)。 把 -13.005 舍成 -13 后,后面的 .48 粘成 -13.48 —— 那是另一个坐标, 图形画错且不报任何错。实测踩到 Element Plus 的 quartz-watch(靠浏览器控制台才发现)。
  • 修法:原本有小数位的数字,输出至少保留 1 位小数(-13.005 → -13.0), 隐式相连的 .48 不可能再被吸收;并在 optimizePath 内复核数字序列,不一致就原样返回。
  • 防复发:新增门禁断言 V8「路径数字与源逐值一致」,比对全部 2576 个图标。 已做变异测试:把该 bug 重新注入 → V8 当场 FAIL(数字个数 461 ≠ 源 462),判据有区分力。
  • 代价:registry.json 707KB(修前 677KB,+30KB 换正确性)。

修正:非 <path> 图形被静默丢弃(覆盖率审计发现)

  • 现象:解析器只认 <path d>,而上游有 36 个文件用 <circle cx cy r> / <ellipse> 表达图形(TDesign 的 circle / round / brightness / image 等)。这些图形被静默丢掉 —— 图标页面上"渲染成功"却是空的,构建与回归都不报错。TDesign 的 circle 与 round 两个图标 因此整个消失,是覆盖率审计(对三个参考库逐名比对)才暴露的。
  • 修法:解析器同时处理 <path> / <circle> / <ellipse>,把圆与椭圆等价换算成 path 的两段 arc(M cx cy-r A r r 0 1 1 cx cy+r A r r 0 1 1 cx cy-r Z)。
  • 结果:图标数 2574 → 2576;对三家参考库的覆盖率现为 TDesign 2356/2356、Element Plus 293/293(各 100%)、Element UI 280/282(余 2 个是解析碎片名)。
  • 校验:两个恢复的图标在浏览器实测有真实几何(path 长度 63 / 44,分别对应 r=10 与 r=7 的圆)。

分层与体积(按实测决定,不是拍脑袋)

  • core 151 个内联(core.js 35KB),standard 1989 / extended 434 按需加载。
  • 为何不全内联:全量 670KB,内联等于给每一页都加 670KB,直接违背 ROADMAP 的性能预算精神。

组件 API(PC 5 端 + 移动端 6 端,语义统一)

  • props:name / size(关键字 small|default|large|xlarge 或任意 CSS 长度,对齐 TDesign 双模式)/ tone(default|brand|secondary|danger|success|warning)/ spin / label。
  • 向后兼容:PC 既有 icon prop(字形字符,默认 '★')与移动端既有 9 名字形表全部保留,name 优先。
  • 无障碍:label 有值 → role="img" + aria-label,无值 → aria-hidden; spin 在 prefers-reduced-motion: reduce 下停转;语义色对比度 ≥ 3:1(实测 5.10–5.87:1)。
  • viewBox 按「路径串 → 网格」反查而非按名:别名指向的 1024 网格图标若按名查会取错网格 (实测影响 160 个名字,会导致图标拉伸变形)。

新增:图标预览页 site/icon-preview.html

规范 组件5.txt「图标预览 IconPreview:展示系统所有图标 / 网格布局,支持搜索 / 点击图标复制名称或代码 / 可调整图标大小」声明已久但从未实现。本次补齐: 2576 图标网格、搜索、点击复制名称、Shift+点击复制内联 SVG、四档尺寸切换、仅线性过滤; 分两段加载(索引 51KB 先出骨架,路径数据按需); 入口挂在图标组件页代码条 footer,i18n 双语(图标预览 / Icon gallery)。

已知未覆盖 / 遗留

  • 移动端 uni-app 端用 CSS mask(data-URI SVG) 承载字形(小程序无 DOM、无内联 SVG)。 H5 目标已实测;mp-weixin / app-plus 的遮罩渲染未在真机验证,已登记进契约 unknowns。
  • verify-emits-parse.mjs 的文件数期望值陈旧(158,应为 103×2=206)—— 本次之前就存在 (git show HEAD: 确认),已登记为 ROADMAP S8-P1。
  • verify-cross-platform.mjs 把注入的图标数据表误判为组件类名(540 条里 533 条是噪声)—— 已登记为 ROADMAP S8-P2(判据不放宽,让门禁学会跳过数据块)。
  • 组件5.txt 声明的 47 个工具/模板组件里 46 个仍未实现(本次只补了 IconPreview)—— 已登记为 ROADMAP S8-P3,含「走 frameworks/ 正式组件还是 site/ 工具页」的决策点。

Mobile · 顶栏对齐 PC + 平台入口去重(移动端站导航栏改造)

起因:用户要求「移动端组件的导航栏参考 PC 端组件导航栏优化(上面跳转 PC 和移动的下拉框也重复了)」。 实测确认两条问题,逐项修掉。

  • 去重:平台切换从顶栏移除。移动端站顶栏原有一个 [PC 端] [移动端] 分段胶囊,与同一页左栏的 「平台」组指向同一跳转(实测 DOM:a.mp-item 与 a.m-side-link.m-side-platform 的 href 均为 ../index.html)—— 同一件事两处入口。PC 站顶栏从来没有这个控件(只有左栏一处), 故删顶栏那份,两端现在都是左栏唯一入口。改动同时断言「删的是重复的那个,不是删光」: verify-mobile-docs 的 E7 从「断言顶栏有平台切换」改为「断言左栏有平台入口」。
  • 顶栏逐项对齐 PC(此前只有结构同名,控件实现不同源):
    • 高度 56px → 60px;内容加 1180px 居中容器(.m-top-inner,与 .m-body 同宽, logo 与左栏左边缘对齐;此前内容铺满视口、与下方内容左边缘错位)。
    • 激活项补 2px 底部品牌指示条(.m-nav a.active::after,PC .topnav a.active::after 同款); 此前只有文字变色。
    • 版本角标 → 可点版本下拉:<span class="m-ver"> 换成 #m-ver-trigger + #m-ver-menu, 清单从部署根 versions.json / site/versions.json 两份按序取(不并行 —— 快照页那份必然 404, 并行会把 404 记进控制台,而站点门禁的零控制台错误是硬断言);拿不到清单时 data-single="1" 退回不可点角标(与 PC 同一语义)。路径校验只放行 ".." 与 x.y.z,防清单把人带去外站。
    • 主题触发器补 三态图标(月亮 / 太阳 / 显示器,PC .theme-icon 同款):显式选择时按时态给图标, 自动模式恒为显示器图标;此前只有文字标签。
  • 零运行时依赖不变:新增的版本/主题逻辑是构建期内联脚本(COPY_SCRIPT),不引包。
  • 顺手修掉一处过期硬编码:移动端站文案里的 PC 组件数写死为「79」, 而 S6-P21 组件族参数化后 PC 索引已是 103(实测 components/index.json)。改为构建期从 PC 索引实测读取 (模板占位符由 build-mobile.mjs 灌入),拿不到索引时退回中性表述而非编造数字。 涉及:总览页、FAQ、平台与端页的正文与覆盖矩阵、以及 dist/mobile/README.md 与 manifest 的 isolatedFrom。

验收(原样):

node tools/verify-mobile-docs.mjs        → [OK] 12 条断言 · 53 页(E7 判据已同步去重)
REG_BASE=http://127.0.0.1:3457 node tools/verify-mobile-site.mjs → [OK] 263 条断言 · 50 页 · 控制台错误 0 · 演示帧 281/281
REG_BASE=http://127.0.0.1:3457 node tools/run-mobile-regression.mjs → passRate 100% | pages 47 (all-pass 47) | assertions 804/804 | N/A 10
REG_BASE=http://127.0.0.1:3457 node tools/run-regression.mjs        → passRate 100% | pages 103 (all-pass 103) | assertions 1405/1405 | N/A 50
PC 与移动端回归各连跑 8 次,结果逐次一致(40/40 全绿)

浏览器实测(Playwright,1440px):顶栏 60px / 内容容器实测 1180px / 激活项 ::after 实测 2px rgb(47, 84, 235) / 顶栏内 .m-platform 计数 0 / 版本下拉实测 1 个选项且 data-single="0" / 切夜间后图标 m-icon-sun:block 且 html.kole-dark 生效;320–768px 四档无横向溢出、零控制台错误。

四道移动端门禁全绿:隔离 31 条 / uni-app 9 条 × 50 SFC / 文档 12 条 · 53 页 / 站点 263 条 · 50 页。

Mobile · 批次 E/F:移动端组件 36 → 47(两批子 agent 并行 + 新增「磁盘↔索引」双向门禁)

继续 /son 派活推进 TDesign 清单覆盖。批次 E(typography / segmented / sticky / overlay / popover / message) 与批次 F(picker / cascader / colorpicker / upload / table)并行产出 11 个组件 × 8 文件 = 88 文件, 规格 §37–§47。索引 36 → 47,实现 216 → 282,移动端回归 597 → 804 条断言。

  • 给每个组件预分配规格编号(§37–§47):上一轮两个子 agent 并存时存在编号撞号风险(撞号会被合并脚本按幂等规则整节跳过), 本轮在派单里逐组件指定编号,合并时零冲突、规格 §1–47 连续。
  • 新增反向门禁 B1b(两个子 agent 独立报的同一条缺口):verify-mobile-isolation.mjs 原先只查 「索引里的组件有没有实现文件」,不查「磁盘上的实现文件有没有进索引」——于是子 agent 产出的组件在合并前 完全不被任何门禁覆盖(不在索引里 = 不被检查),属静默缺口。现补反向断言:磁盘前缀集合必须等于索引前缀集合, 不一致直接报「未登记:X, Y(跑 node tools/merge-mobile-batch.mjs 合并)」。断言数 30 → 31。
  • 修掉两处探针误判(都是工具侧,不是内容缺陷):
    • verify-mobile-site.mjs 的总览页在 47 个卡片时只渲染 43 个 —— 预览帧 loading="lazy", 一次 scrollTo 到底会跳过中间帧。改为逐段滚动(每 800px 一次)后再判定,实测 281/281。
    • 同一脚本把收集器的 net::ERR_ABORTED 记为控制台错误 —— 那是 _collect.html 在帧装载完成后 主动 removeAttribute('src') 释放帧造成的在途请求中断,是设计行为。判据改为忽略 ERR_ABORTED, 其余(404 / ERR_INVALID_URL 等)仍然计错。
  • 子 agent 自修的真实缺陷(都带证据):Sticky 的 is-stuck 判定在默认偏移下滚动 0 就已贴合(改为与容器 padding box + 偏移量比较,含 1px 边框补偿); Message.jsx 把 onClose 写进 useEffect 依赖 → 宿主传内联箭头函数时计时器永远不到点(回调移到 useRef); Sticky/Message 演示页缺实际执行的监听器致 data-behavior 静默失效; Table 可点行不可聚焦(真实引擎报 matrix:keyboard-reachable)→ 补 tabindex/role/aria-selected/Enter 键路径; ColorPicker 的色板 hex 写在行内 style 被 no-hardcode-hex 判据扫到 → 改走行内自定义属性(CSS 零 hex,色值只存数据层)。
  • 规划偏差(子 agent 主动对齐既有约定):disabled 从变体维度降为状态类 —— 全仓 47 份契约无一把它当变体, 同意;picker/cascader/segmented 的初判分类经我核对后修正为 input/navigation(PC 同源六分类口径)。

验收(原样):

node tools/verify-mobile-isolation.mjs   → [OK] 31 条断言(含新增 B1b 反向断言)
node tools/verify-uniapp.mjs             → [OK] 9 条断言 · 50 个 SFC
node tools/verify-mobile-docs.mjs        → [OK] 12 条断言 · 53 页
REG_BASE=… verify-mobile-site.mjs        → [OK] 263 条断言 · 50 页(0 控制台错误、演示帧 281/281)
node tools/run-mobile-regression.mjs     → 100% | 804/804 | 47/47 页 | N/A 10 | 0 超时
node tools/run-regression.mjs            → 100% | 1405/1405 | 103/103 页(PC 侧未被污染)
node tools/pack-deploy.mjs --tar         → OK(282 实现 / 47 文档页 / 47 测试页)

部署:暂存树哈希与本地一致(936742e98d061a30)→ 替换重建 → 五项验收全过、11 个新增组件页全 200、容器 0 error; 公网 data.mobile.json 报 47 个组件。

剩余 23 个(已写进 ROADMAP S7-P23):config-provider / Fab / BackTop / Drawer / Indexes / SideBar / Tabs / Calendar / DateTimePicker / TreeSelect / CountDown / Empty / Footer / Image / ImageViewer / QRCode / Result / Skeleton / Swiper / Watermark / DropdownMenu / Guide / PullDownRefresh。

Docs · 模板页库 1 → 5(S4-P11:把组件组合成可复制的后台页面)

起因:用户要求「为组件库设置一个合适的 UI」。定位到 ROADMAP 中唯一「🟢 可开工」的任务 —— S4-P11 模板页库。 其依据写得很直白:「模板页是『能否直接用』的关键 —— 用户要的不是组件,是页面」。此前只有 1 个场景页。

  • 新增 4 个模板页(site/scenario/,纯 HTML + 原生 JS、零依赖):
    • login.html — 输入类组件 + 表单校验。字段级错误提示(指出字段、说明原因、给修正方向)、 密码显隐切换、提交加载态 → 成功态、账号锁定等业务错误分支。
    • dashboard.html — 侧边导航 + 4 张指标卡 + SVG 趋势图 + 渠道占比进度条 + 待办表格 + 分页。 时间范围切换会重算指标与图表;含折叠面板。
    • order-list.html — 筛选表单 + 表格 + 批量操作条 + 分页 + 详情抽屉。 37 条示范订单;筛选/全选/批量审核/抽屉(Esc 关闭、焦点归还)全部可用。
    • settings.html — 侧边分区 + 表单 + 开关组 + 单选/复选组 + 危险操作二次确认。
  • 接入首页:site/app.js 首页新增「模板页库」区块(5 张卡片,新窗口打开);site/style.css 补 .home-note。
  • sitemap:build-site.ps1 把 5 个模板页写入 sitemap(521 URL)。新增行全为 ASCII,守住 PS5.1 的 ASCII-only 约束。
  • i18n:site/i18n.js 补 13 条英文(模板页库标题与 5 张卡片),中文源串作键的既有约定不变;verify:i18n 316 键全覆盖。
  • 新增门禁 npm run verify:templates(tools/verify-templates.mjs,54 条浏览器断言,已接入 CI): 令牌生效 / 非白屏 / 零控制台错误 / 零 4xx / 逐页交互 / 375–1024px 无横向溢出。
  • 判据修正(tools/verify-site-routing.mjs):sitemap URL 总数原为硬编码 1 + 组件数×5, 现改为「按 site/scenario/ 磁盘上实际存在的 .html 逐个核对 + 计入总数」。 理由:硬编码在新增模板页时只会静默漏检(sitemap 少了页面而断言仍绿); 改后「新增/删除模板页却忘记同步 build-site.ps1」会直接红。这是加强而非放宽 —— 新增了 5 条逐文件断言。

模板页实测(原样):

node tools/verify-templates.mjs    → [templates] OK — 54 checks passed
node tools/verify-site-routing.mjs → [routing] OK: 103 components / 412 platform shells / 521 sitemap URLs
node tools/verify-i18n.mjs         → [i18n] OK — 16 checks passed(316 keys covered)
node tools/run-regression.mjs      → 100% | 1405/1405 | 103/103 页 | N/A 50(八次连跑一致)

过程中被测试逮到并修掉的 4 处真实缺陷(都不是判据问题):

  1. 进度条高度渲染为 0 —— components.css 只聚合 6 个核心组件,ProgressVariants / DashboardCard 这类扩展组件的样式根本没被加载(类名在、样式缺,页面不报错、只是画不出来)。 修法:4 个模板页按需 <link> 各自的 frameworks/*.css(这些文件均为纯令牌自包含), 而不是在模板页里重画一遍组件。
  2. 指标卡标题与图标未两端对齐(display:block 而非 flex)—— 与上条同根因。
  3. 设置页脏检查存在永久闩锁 —— 原写法 if (saved) return 导致「保存过一次」之后表单再也不会被标记为脏; 且「放弃修改」只硬编码还原 5 个字段,IP 白名单与通知勾选漏在还原之外。 修法:改为快照式脏检查(基线 = 上次保存值,逐字段比对),于是「改回原值自动回到干净态」, 日后新增字段也不必再补还原代码。
  4. 保存竞态 —— 保存有 700ms 模拟延迟,期间「放弃修改」仍可点,会拿到上一份基线,表现为数据被还原成旧值。 修法:保存进行中两个按钮都禁用。

Mobile · 批次推进:移动端组件 5 → 36(三批子 agent + 合并脚本 + 修行为断言静默缺口)

起因:用户要求「参考 TDesign 移动端组件清单,按批次补全缺的组件」,随后 /son(派子 agent)、/agi(全自主)。 参考清单 67 个组件,本仓库已覆盖 36 个(含此前的 18 个);流程按 PLATFORMS.md §四「六步」固化。

  • 三批子 agent 产出 18 个组件(每个 = 6 端实现 + 规格片段 + 契约 = 8 文件,共 144 文件):
    • 批次 A:mobile-icon / mobile-layout / mobile-link / mobile-loading
    • 批次 B:mobile-avatar / mobile-list / mobile-collapse / mobile-progress
    • 批次 C:mobile-input / mobile-search / mobile-switch / mobile-stepper / mobile-textarea
    • 批次 D:mobile-form / mobile-radio / mobile-checkbox / mobile-slider / mobile-rate 规格从 §19 连续到 §36(共 36 节);索引 18 → 36 个组件,实现文件 108 → 216。
  • 新增可复用的合并脚本 tools/merge-mobile-batch.mjs:子 agent 一律不写 index.json(避免并发写同一文件), 由主 agent 用该脚本统一合并 —— 它做三件事且幂等:① 按编号把 spec/parts/*.md 拼进规格原文(同编号则只归档不拼接); ② 把 frameworks-mobile/ 里未登记的组件(校验 6 端文件齐全 + 契约存在)写进索引;③ 已拼接的片段归档到 parts/_merged/。
  • 修掉一个静默缺口(子 agent 复核时发现,价值最高的一条):tests/mobile/_behaviors.js 的 PILOTS 是硬编码白名单 (只有最初 5 个组件),于是批次新增组件即使在演示页写了 data-behavior,引擎也直接 return [] —— 行为断言静默不跑,断言总数悄悄少一截。修法:作用范围改为「演示页里真的写了 [data-behavior] 的组件」 ∪ 兜底名单,由 build-mobile.mjs 在生成测试页时把派生结果注入 window.__koleBehaviorSlugs。 实测:行为断言覆盖 5 → 31 个组件,断言条数 8 → 34 条(全部 pass)。
  • 修掉一处判据过窄(上一轮遗留):pack-deploy.mjs 的「frameworks-mobile 实现文件数」按索引动态算, 但打包时批次文件已在磁盘而尚未合并进索引 → 断言误报。现在按「索引组件数 × 端数」与磁盘实际双向核对, 不一致时直接指出差额(本次实测:156 vs 186,正是未合并的批次 C)。
  • 修掉一处探针误判:verify-mobile-site.mjs 统计总览页演示帧时只看到 20/26 —— 预览帧是 loading="lazy",视口外的帧不会加载(浏览器行为,不是缺陷)。判据改为先滚到底再判定, 实测 26/26、现在 36/36 全部正常渲染。
  • 子 agent 自修的真实缺陷(都在报告里给了证据):<button> 嵌在 <label> 里(非法嵌套); Stepper 根 overflow:hidden 裁掉小尺寸档的热区外扩(命中测试证实);同一状态块挂两条 data-behavior 互相污染; Textarea 计数示例是死数据;Slider 根元素 cursor:pointer 让数值文案被判「鼠标专用交互」(真实引擎报的 matrix:keyboard-reachable)。

验收(原样):

node tools/verify-mobile-isolation.mjs   → [OK] 30 条断言
node tools/verify-uniapp.mjs             → [OK] 9 条断言 · 39 个 SFC
node tools/verify-mobile-docs.mjs        → [OK] 12 条断言 · 42 页(站内链接全可解析)
REG_BASE=… verify-mobile-site.mjs        → [OK] 208 条断言 · 39 页(0 控制台错误、演示帧 220/220、320–768px 无溢出)
node tools/run-mobile-regression.mjs     → 100% | 597/597 | 36/36 页 | N/A 10 | 0 超时
node tools/run-regression.mjs            → 100% | 1405/1405 | 103/103 页(PC 侧未被污染)
node tools/pack-deploy.mjs --tar         → OK(2349 文件 / 36 组件 × 6 端 = 216 实现 / 文档页 36 / 测试页 36)

部署:暂存树哈希与本地一致(719d66f2fce6875a)→ 替换重建 → 服务器端五项验收全过、容器 0 error; 公网 data.mobile.json 报 36 个组件,抽查 8 个新增组件页全 200。

Tooling · uni-app 真实编译验证 + 回归可追溯性(S7-P25 / S5-P17 / S6-P30)

起因:按批次继续推进,处理三个「一直没做但可立即做」的缺口 —— 前两项都是只能靠真跑才能回答的问题, 此前一直以「静态门禁通过」代替,属于典型的「绿灯证明不了什么」。

  • S7-P25 · uni-app 真实编译验证(新增 tools/verify-uniapp-build.mjs,11 条断言): 在隔离目录装 @dcloudio 工具链(主仓库 dependencies 仍为空),搭最小 uni-app 工程, 把 21 个 SFC(移动端 18 + PC×uni-app 3)全部真实挂载并编译到 H5 与微信小程序:
    • 实测结果:两目标编译通过;产物含 148 / 211 个唯一 kole-m- 类名; 18/18 组件的契约声明类名都进了产物;小程序产物 0 处 DOM 操作。
    • 为什么必须做:静态门禁只能证明「源码长得合规」,证明不了「编译器接受它」。 本仓库已有两次「静态全绿却编译不过」的实例(RangeQuickPicker 的 const 重赋值、 CodeInput 的 emit 遮蔽),都是真编译才暴露的 —— 而 uni-app 端的 18 个 SFC 此前从未被编译器碰过。
    • 调通过程中抓到的三个真实坑(都写进了脚本注释): ① package.json 必须声明 @dcloudio/* 进 dependencies —— 只写 {name, private, version} 时 编译器照样打印 DONE Build complete.、退出码 0,但产物只有一个 704 字节的 modulepreload polyfill, 页面与 21 个组件全部静默丢失。这是本次最危险的失败模式。 ② 移动端 Button 与 PC×uni-app Button 同名(两个平台各有一份实现)→ 绑定名冲突互相覆盖。 消歧规则:PC 侧加 Pc 前缀,并把消歧结果用于落盘文件名与 import 绑定名(否则后拷的覆盖先拷的)。 ③ 页面模板用 <C0 /> 这类索引式绑定名会被 uni-app 编译器当未识别元素丢弃 —— 必须用组件自身的 Pascal 名。
    • 判据做了两轮变异测试才定稿(判据修正附理由 + 反例,符合仓库铁律): 初版「从 frameworks-mobile/<X>.css 取类名」→ 假通过(uni-app 端样式是内联的,查的是另一份文件); 二版「从 uni-app 端源码取类名」→ 假通过(改名后判据与产物同步变化,两边一致,实测 kole-m-grid 全量改名后仍 PASS);定稿版拿契约(variantClasses)里声明的类名去产物里找 —— 契约与实现是两条独立写入路径,实现悄悄改名/丢组件时契约不会跟着变。 定稿后同一变异立刻抓到:FAIL mobile-grid(契约类名 kole-m-grid--2 未进产物)。
    • App 端(app-plus)未覆盖:需 HBuilderX 云端打包,命令行无法完成(脚本输出里已注明)。
  • S5-P17 · 回归偶发失败的可追溯性:tools/run-regression.mjs 在非满分时把上一次报告留档为 tests/report-prev.json(report.json 仍只有一份,供首页读取),失败现场不再被下次运行覆盖。 实测(真实注入,非模拟):把 tests/button.html 移走制造 404 → 输出 kept: tests/report-prev.json(本次非满分,已保留上一次报告供回放) 且文件确实生成;还原后满分运行不再留档。 report-prev.json 已加进 .gitignore(诊断中间产物,不入库)。
  • S6-P30 · 采集偶发 vs 真断言失败:新增 isCollectionFailure(),采集失败(no-result / timeout / page-error) 单列 collectionFailures 且不计入 passRate 分母;failedPages 只留真断言失败 (此前 button: no-result 会被读成「button 的断言坏了」,两类事实混在一张表里)。 实测同一注入:passRate 100% | pages 103 (all-pass 102) | assertions 1378/1378 | N/A 50 | 采集失败 1 (button:no-result) —— 分母正确扣掉该页(1378 而非 1405),且 EXIT=1(不静默吞掉)。 判据反例:5 条用例逐条验证 —— 采集三类为真 / 真断言失败(matrix:contrast>=4.5)为假 / 满分页为假。
  • 顺带修掉:AGENTS.md 门禁清单里三处陈旧断言数(隔离 29→30 / 文档 8→12 / 站点 53→118,均为实测值)。

验收(原样):

node tools/verify-uniapp-build.mjs
  → [OK] uni-app 真实编译验证通过(11 条断言 · 21 个 SFC · h5 + mp-weixin)
    PASS B0 待编译 SFC 全部存在于源目录 — 21 个(无缺失)
    PASS B-h5 编译通过 — 9488 ms            PASS B-mp-weixin 编译通过 — 7747 ms
    PASS B-h5 产物含 kole-m- 类名 — 148 个唯一类名
    PASS B-mp-weixin 产物含 kole-m- 类名 — 211 个唯一类名
    PASS B-h5 每个移动端组件(按契约声明的类名)都进了产物 — 18/18
    PASS B-mp-weixin 每个移动端组件(按契约声明的类名)都进了产物 — 18/18
    PASS B-mp-weixin 产物无 DOM 操作 — 0

node tools/verify-mobile-isolation.mjs  → [OK] 隔离门禁全部通过(30 条断言)
node tools/verify-uniapp.mjs            → [OK] uni-app 门禁全部通过(9 条断言 · 21 个 SFC)
node tools/verify-mobile-docs.mjs       → [OK] 文档完整性门禁全部通过(12 条断言 · 24 页)
node tools/verify-i18n.mjs              → [OK] — 16 checks passed
REG_BASE=… node tools/run-regression.mjs        → passRate 100% | pages 103 (all-pass 103) | assertions 1405/1405 | N/A 50
REG_BASE=… node tools/run-mobile-regression.mjs → passRate 100% | pages 18 (all-pass 18) | assertions 270/270 | N/A 6

# 判据反例(变异测试,各自当场还原)
  改掉 Grid 的契约声明类名        → FAIL mobile-grid(契约类名 kole-m-grid--2 未进产物)
  注入 404 制造采集失败            → report-prev.json 生成 + EXIT=1 + 分母扣掉该页(1378/1378)
  isCollectionFailure 5 条用例     → 采集三类为真 / 真断言失败为假 / 满分页为假(全 PASS)

未执行:App 端(app-plus)真实编译 —— 需 HBuilderX 云端打包,命令行无法完成。 依赖说明:@dcloudio 工具链装在 .tmp/uniapp-build(已 gitignore),主仓库 dependencies 仍为空(零运行时依赖不变); CI 里该步骤在工具链未缓存时跳过并告警(环境问题非代码问题,脚本自身退出码 2)。

Fix · 演示帧内「覆盖型浮层」只在演示框里全屏(点击图片 / 打开弹窗不满屏)

  • 缺陷:文档站把演示页嵌在按内容高度撑开的 iframe 里,而组件里 position:fixed; inset:0 的覆盖层以帧视口为包含块 —— 于是「点击图片全屏」只在演示框内铺开。实测 imagepreview 的遮罩 724×134,宿主视口 1241×1233。命中的是全部 8 个「覆盖视口」语义的 组件:imagepreview / modal / alertmodal / confirmmodal / formmodal / fullscreenmodal / bottomsheet / loadingoverlay。这是承载容器的形态问题,不是组件缺陷 —— 这些演示页 单独打开(或点「新窗口打开」)时覆盖层本来就铺满视口,故组件源码与令牌一律不动。
  • 修法(站点侧):site/app.js 新增演示帧提升桥 —— 帧内出现覆盖型浮层时给演示舞台 (.demo-stage / .ex-stage)加 .is-lifted(position:fixed; inset:0,见 site/style.css), 舞台成为全视口浮层的包含块后帧视口随之变成宿主视口,覆盖层自然铺满;同时锁宿主滚动 (html.kole-stage-locked)。帧内显隐由演示脚本改 style/class 驱动,宿主无法感知, 故在帧 document 上挂 MutationObserver 跟随。
  • 判据只认「覆盖视口 + 真的渲染出来了」:贴边的 fixed(backtotop 右下角 / anchornav 右侧 / messagepro 顶部 / tabbar 底部)不提升,它们的语义本来就是贴着视口某一边; position:absolute 的局部块(loadingoverlay.is-inline、popconfirm 弹泡)不提升; 水印 .is-fullscreen 是装饰层不是浮层,也不提升。
  • 实现期实测踩到并修掉的三个真缺陷(都由新增门禁的反向/边界用例逼出): ① 淡入过渡漏判 —— BottomSheet 的遮罩 opacity 0→1 走 .25s,突变那一刻量到 opacity 仍是 0 被判成「未显示」,而过渡本身不再产生新突变 → 没有补测就永远不提升。修法:突变后隔 450ms 再判一次; ② 不可见遮罩被误提升 —— 祖先 display:none 时自身 computed display 仍是 flex, 只看自身样式会把「已挂载但看不见」的遮罩当浮层,舞台升到全屏却没有任何内容(整屏空白)。 修法:加矩形非零判据(文档站逐示例预览会隐藏场景外节点,modal 的 #mount 实测命中); ③ 撤销时帧高不回收 —— 提升期间 fitFrame() 被早退跳过,而遮罩打开期间帧内容不再变化、 ResizeObserver 不回调,帧停在全屏高度。修法:撤销时显式补量一次。
  • 新增门禁 npm run verify:stage-overlay(tools/verify-stage-overlay.mjs,77 条断言): A 组 8 个组件逐一点开 → 浮层尺寸必须≈宿主视口(容差 2px)+ 舞台已提升 + 滚动已锁, 关闭 → 提升撤销 + 滚动锁解除 + 帧回到内容高度;B 组 6 条反向用例(水印 / backtotop / anchornav / button / messagepro 不得提升,移动端静态站不得泄漏 PC 提升逻辑)。 已接入 regression.yml。

Mobile · 移动端组件第二批收尾(弹出层系 + 展示系 + 输入系):Toast / Dialog / Grid / Steps / NoticeBar / NumberKeyboard / DatePicker(索引 11 → 18)

起因:按批次继续开工,把 ROADMAP S7-P23 的剩余 7 个组件做完 —— 规格 §12~§18 本轮新写 (契约的唯一授权来源必须先于实现),再按 PLATFORMS.md §四 六步流程落地为 6 端实现。 索引 11 → 18,frameworks-mobile/ 66 → 108 个文件(18 × 6 端)。

  • 七个新组件(规格小节 → slug / 前缀):
    • 轻提示 Toast(§12 → mobile-toast):tone 五语气 + position 三位置 + mask; 容器 role="status" + aria-live="polite"(结果朗读一次不反复打断);tone=loading 时图标旋转并标 aria-busy。
    • 对话框 Dialog(§13 → mobile-dialog):variant = confirm(两按钮等宽)/ alert(单按钮铺满)+ tone = danger + round; closeOnMask 可关;role="dialog" + aria-modal + aria-labelledby;按钮热区 ≥44px。
    • 宫格 Grid(§14 → mobile-grid):columns 2/3/4 + border + square;可点格子是原生 button(整块热区 + 键盘可达), static 格子是 div 且不绑点击 —— 直接规避「鼠标专用交互」这类无障碍缺口;按下反馈一律 :active(触屏没有悬停)。
    • 步骤条 Steps(§15 → mobile-steps):direction 横/纵 + status 四态;role="list" / role="listitem" + aria-current="step"; 状态不只靠颜色(进行中加粗、已完成用勾选字符、失败用感叹号)。
    • 通知栏 NoticeBar(§16 → mobile-noticebar):四种语气 + scrollable 跑马灯 + closable; 无障碍硬要求落地:prefers-reduced-motion: reduce 下停止滚动并改为换行显示;滚动内容不用 aria-live(反复朗读会干扰)。
    • 数字键盘 NumberKeyboard(§17 → mobile-numberkeyboard):type = number/digit + showDelete + showConfirm + confirmDisabled; 键盘不持有输入值 —— 只 emit 按键事件(数字键回传该字符 / 删除键回传 'delete' / 确认键回传 'confirm'),写入哪个输入框由宿主决定。
    • 日期选择器 DatePicker(§18 → mobile-datepicker):mode = date/month + round + closeOnMask;三列 role="listbox" / role="option" + aria-selected; 年份范围由宿主传入(years / months / days),不发明可用年份区间(契约 unknowns 已登记)。
  • 配色零发明(全部既有令牌,脚本实测亮/暗两态):Toast 深底 + 反色文字 15.78:1 / 15.00:1; Dialog 卡片底 + 正文色 15.13:1 / 10.34:1;Grid / Steps / NoticeBar 沿用既有语义对(浅底 + 同族深字,均 ≥4.5:1)。
  • 判据有效性用变异探针验证(5/5 当场捕获,不是「跑了绿灯」就算数): ① 向 CSS 注入 #FF0000 → B3 报出文件与色值;② 契约加一个源码没有的 prop → E4 逐端报「源码里没有」; ③ 把有默认值的 prop 标成必传 → E4b 逐端报「应相反」;④ uni-app 端注入 document.querySelectorAll → U5 报出两条规则; ⑤ uni-app 端去掉全部 rpx → U9 报「未使用 rpx」。每个探针都当场还原并复跑确认绿灯。
  • 过程中发现并修掉三处真问题: ① 契约 related 里写了裸名(toast / noticebar)而非真实 slug → E6c 逐条报「不存在」,已补 mobile- 前缀(5 处); ② tools/pack-deploy.mjs 输出文案与 site/m/_design_template.html 里写死了组件数(前一批 8 个组件落地时漏改) → 分别改为读索引与构建期占位符注入; ③ Dialog 初版的圆角写在基础类上(round 变体于是无意义)→ 改为由 --round 类控制,契约 variantClasses 与 CSS 双向对上。

验收(原样):

node tools/build-mobile.mjs              → 18 组件 × 6 端(data.mobile.json 412 KB)· 18 测试页 · 18 文档页 · dist/mobile 全端
node tools/verify-mobile-isolation.mjs   → [OK] 隔离门禁全部通过(30 条断言)— B1 18 × 6 端 108 文件 / B8 报告 18 = 索引 18
node tools/verify-uniapp.mjs             → [OK] uni-app 门禁全部通过(9 条断言 · 21 个 SFC)
node tools/verify-mobile-docs.mjs        → [OK] 文档完整性门禁全部通过(12 条断言 · 24 页)
REG_BASE=… verify-mobile-site.mjs        → [OK] 移动端站点全部通过(118 条断言 · 21 页;演示帧 101/101 正常,0 控制台错误)
REG_BASE=… node tools/run-mobile-regression.mjs → passRate 100% | pages 18 (all-pass 18) | assertions 270/270 | N/A 6
node tools/run-regression.mjs            → passRate 100% | pages 103 (all-pass 103) | assertions 1405/1405 | N/A 50(PC 零污染)
node tools/pack-deploy.mjs               → OK — mobile 108 个实现文件(18 组件 × 6 端)/ 文档页 18 / 测试页 18

未执行:部署(只改工作区,未走 AGENTS §九 发布流程);uni-app 真实编译(既有状况 S7-P25,需 @dcloudio 依赖)。

Mobile · 移动端组件第二批(弹出层基座 + 展示系):Badge / Tag / Popup(索引 8 → 11)

起因:批次推进。移动端规格已写到 §9 / §10 / §11(上一轮写好但未实现),本轮按 PLATFORMS.md §四 的六步流程把三节规格落地为 6 端实现 —— 组件数 8 → 11,frameworks-mobile/ 48 → 66 个文件。

  • 三个新组件(规格小节 → slug / 前缀):
    • 徽标 Badge(§9 → mobile-badge):shape = dot / number / text + standalone; 状态 overflow(超过 max 显示 99+)与 hidden(值为 0 且未开 showZero 时不渲染)。 角标绝对定位、不改变被包裹元素的布局尺寸;红点 aria-hidden,数字角标带 aria-label。
    • 标签 Tag(§10 → mobile-tag):tone 五语气(default / primary / success / warning / danger)
      • size(default / small)+ closable。关闭按钮是原生 button、24×24 热区(小尺寸标签内用负外边距扩展), aria-label 带上标签文字(否则一串「✕」读屏无法区分);disabled 时置灰且不响应。
    • 弹出层 Popup(§11 → mobile-popup):placement 五方向(center / bottom / top / left / right)+ round (贴边方向在靠内容一侧切圆角,用逻辑属性,RTL 安全);closeOnMask 可关;内容超长时 body 内部滚动、 遮罩不滚;滑入 240ms cubic-bezier(.32,.72,0,1);浮层 role="dialog" + aria-modal,遮罩 aria-hidden。
  • 配色零发明(全部既有令牌,脚本实测两态):实心底 + --kole-color-text-inverse 亮色 5.57–5.87:1 / 暗色 5.64–8.24:1;Tag 的浅底 + 同族字色亮色 4.68–5.38:1 / 暗色 4.92–6.91:1。 未新增任何色值,因此不需要碰 PC 令牌文件。
  • 过程发现并修掉两处陈旧计数(都是前一批 8 个组件落地时漏改的): ① tools/pack-deploy.mjs 的输出文案写死「5 组件 × 6 端」(数字本身是算出来的,只有说明文字陈旧)→ 改为读索引; ② site/m/_design_template.html 的「移动端 5 个组件」写死在 HTML 里 → 改为构建期占位符(由 build-mobile.mjs 注入实际组件数)。

    注:本条初版把占位符原文写进了日志正文,而 changelog.html 是从本文件正文提取渲染的, 于是页面里出现了未替换的占位符 —— 被 verify-mobile-docs.mjs 的 E7(无残留占位符)当场拦下。 同一条纪律:日志正文里不要出现占位符形状的字面量。

  • 修掉一处误报 skip:Badge 的「数值为 0(hidden)」演示块把 data-assert 放在被隐藏的角标上, 断言引擎按「默认隐藏(交互后可见)」记为 skip —— 但该块本身就是「隐藏态+可见对照」的设计。 已把断言移到可见的容器上,skip 3 → 且该页断言 16 条全 pass(skip 只剩两条静态组件固有的 N/A)。
  • 顺带修正 ROADMAP S7-P23 的失败判据:其中写的 PC 断言总数是 1017,实际当前为 1405(103 组件 × 5 端后未更新)。

验收(原样):

node tools/build-mobile.mjs              → 11 组件 × 6 端(data.mobile.json 238 KB)· 11 测试页 · 11 文档页 · dist/mobile 全端
node tools/verify-mobile-isolation.mjs   → [OK] 隔离门禁全部通过(30 条断言)— B1 11 × 6 端 66 文件 / B8 报告 11 = 索引 11
node tools/verify-uniapp.mjs             → [OK] uni-app 门禁全部通过(9 条断言 · 14 个 SFC)
node tools/verify-mobile-docs.mjs        → [OK] 文档完整性门禁全部通过(12 条断言 · 17 页;E8 站内链接 657 条)
REG_BASE=… verify-mobile-site.mjs        → [OK] 移动端站点全部通过(83 条断言 · 14 页;演示帧 64/64 正常,0 控制台错误)
REG_BASE=… node tools/run-mobile-regression.mjs → passRate 100% | pages 11 (all-pass 11) | assertions 172/172 | N/A 4
node tools/run-regression.mjs            → passRate 100% | pages 103 (all-pass 103) | assertions 1405/1405 | N/A 50(PC 零污染)
node tools/pack-deploy.mjs               → OK — mobile 66 个实现文件(11 组件 × 6 端)/ 文档页 11 / 测试页 11
浏览器实测(1280×1000)                  → 三页各 14 个小节 / 演示块 6·5·6 / 预览帧全部有内容(0 空帧)/ 0 控制台错误
  几何:Badge 角标 absolute + translate(50%,-50%)(不占位);Tag 24px 高;Popup fixed 被展示框 transform 包含块约束(关闭态位移 143.6px)

PC 常用组件补齐:103 个组件 / 组件11批次

  • 对照 Element UI 2.15.14 左侧组件目录,新增 24 个 PC 常用组件:Layout、Container、Typography、Icon、Link、Radio、Checkbox、InputNumber、Switch、TimePicker、DatePicker、DateTimePicker、Form、Pagination、Badge、Avatar、Descriptions、Alert、PageHeader、Tooltip、Popover、Divider、InfiniteScroll、Drawer。
  • 每个新增组件均登记设计契约、批次 11 规格、H5/CSS/React/Vue 2/Vue 3 五端源码、站点详情和测试页;PC 清单由 79 扩展为 103,frameworks 源文件由 395 扩展为 515。
  • 构建、预计算、分发、族层、跨端、API 文档和路由门禁改为从 PC 索引读取组件数;不改变移动端 5 组件与 PC × uni-app 3 个试点边界。
  • 新增组件使用场景覆盖后台布局、表单输入、列表分页、状态提示、详情描述、浮层和抽屉;日期/时间组件明确采用零运行时依赖的原生控件边界。

PC 组件文档改为「逐示例用法代码」——一个使用场景 = 一块预览 + 一块调用代码

起因:用户对照 Element 的 Radio 单选框 文档页指出 —— 组件文档应当直接给出 <el-radio disabled v-model="radio" label="选中且禁用">备选项</el-radio> 这样的调用写法, 而不是把整份实现文件摊给使用者;并且「单个使用场景对应单个代码块」。 原形态是「一个整页 iframe + 展开看整份实现源码(Button.html 117 行 / Button.jsx 66 行)」, 使用者要自己从实现里反推调用方式。

  • 每个使用场景一块卡片��ˆsite/app.js 的 buildExampleCard):标题(演示页的 h2 /

.hint / 契约代表变体名)→ 预览 → 只属于这个场景的代码块(H5 HTML / React JSX / Vue 2 / Vue 3 四端可切,默认跟顶栏「框架」选择器一致,可复制)。示例数据不可用时退回 「整页演示 + 整份源码」,功能不消失。

  • 预览不重排:iframe 仍加载原始演示页,只把其它场景 display:none(隐藏计划在构建期 按 body 的元素下标算好)。不切 HTML 是因为演示脚本对节点有索引依赖 —— resultvariants 的 DATA[i]、modal 的 #mount 一旦拆开就会渲染出错的内容。
  • 片段出处三分(site/examples/<slug>.json 的 source 字段): demo-mapped(演示页逐字映射:btn-primary → type="primary")、 demo-data(演示数据 + API 表:挂载点型组件的 options / v-model)、 api-derived(演示页无调用标记,依据 API 表推导最小调用)。卡片代码栏右侧标注出处。
  • 不发明:片段里的 prop 名必须能指到 API 表 / 源码参数表,class 必须在该组件 CSS 里真实存在 (npm run verify:examples 的 9 条断言逐条复核;预览隐藏路径也必须能解析回演示页 DOM)。
  • 数据分层:site/examples/<slug>.json 按组件懒加载,data.js 只留 { id, title, source } 目录 + examplesRef;data.json 保持完整示例(对外承诺不变)。
  • 顺带修掉:①代码区常显后暴露的暗色对比度问题 —— 代码块借 --kole-color-tooltip-bg 而该令牌暗色下是浅色,补 html.kole-dark .ex-code 深底并把语法高亮调色板按深底实测重选 (全部 ≥4.5:1,原先 hl-tag 只有 2.70:1);②演示脚本钩子 id(#demo-toggle)与 data-behavior/data-assert 不再混进用法代码;③<input> 等 void 元素不再序列化成 </input>。

Mobile · 组件批次推进:18 个组件 × 6 端(108 实现文件)+ 文档站 24 页,全部门禁与回归通过

起因:用户要求「参考 TDesign 移动端的组件清单,按批次补全当前组件库缺的组件」。 参考页给出 72 个组件的清单,本仓库按「规格 → 契约 → 6 端实现 → 文档页 → 门禁」的既有流水线分批推进。

  • 组件从 5 扩到 18(frameworks-mobile/ 108 个文件 = 18 × 6 端),规格 19 节、契约 18 份: 按 PC 同源分类:导航 4 · 反馈 7 · 通用 2 · 数据展示 3 · 数据录入 2。完整清单见 site/m/index.html 的覆盖矩阵与侧栏。
  • 本会话直接产出的一批(A):mobile-button(三档高度 44/36/28、loading 阻止重复触发、aria-busy)、 cell(整行热区 ≥56px、按行分隔线、可点用原生 button / 纯展示用 div)、mobile-divider(水平/垂直/虚线/ 三种文字对齐,纯装饰 role=separator + aria-hidden)。三者的 6 端实现、契约(含演示分组、相似组件、 必传列、CSS 变量)与规格 §6–§8 均由本会话写入;其余批次与并发会话合并完成。
  • 合并时修掉两处判据问题(都是「判据太窄」而不是放宽):
    • slug 允许与 PC 同名:build-mobile.mjs 与 verify-mobile-isolation.mjs 原先要求「移动端 slug 不得与 PC 撞名」,实际两个平台各自有「按钮」「分割线」是正常的 —— 真正要证明的是「同名也各自独立」。 改为:报告同名清单,并断言同名组件的实现文件不在 frameworks/ 下。
    • dist/mobile/manifest.json 的判据从「无 PC slug」改为「slug 集合与索引完全一致」—— 后者能同时抓到漏项与串入,比原来更严。
  • 移动端令牌层补一条全局焦点环::focus-visible 落在移动端令牌层(不能只依赖 PC 令牌文件里那条 —— 断言引擎读的是直接 link 的样式表的 cssRules,@import 进来的规则不在其中)。 这既是让静态组件过 focus-visible-defined 断言,也是真实的 a11y 改进。
  • 门禁全绿:隔离 30 条 · uni-app 9 条(21 个 SFC)· 文档完整性 12 条(24 页,站内链接 1121 条全可解析)· 移动端站点 118 条(21 页浏览器实测:0 控制台错误、演示帧 101/101 正常渲染、320–768px 无溢出)。
  • 回归:移动端 100%(270 通过 / N/A 6 / 18 页) · PC 100%(1405 通过 / N/A 50 / 103 页)。

部署(AGENTS §九):pack-deploy --tar(2187 文件 / 1.65 MB gzip)→ 暂存树哈希与本地一致 (a962d7c4caa853b2)→ 替换重建 → 服务器端 specs 404 / 根 302 / sitemap 200 / healthz / SPA 深链全过、 容器 0 error;公网抽查 5 个页面全 200,site/m/index.html、site/m/component/mobile-button.html、 site/m/data.mobile.json 逐字节与本地一致。

Mobile docs · 顶栏与左栏对齐 PC(平台 / 开发指南 / 组件 N + 主题三态跨站生效)+ 补常见问题与更新日志页

起因:用户指出「导航栏需要和 PC 一致,左侧栏也是」。移动端文档站此前是自成一体的简版顶栏 (品牌 + 平台分段 + 3 个链接)与自创分组的左栏(开发指南 5 项自定名 + 手势/反馈分类), 与 PC 文档站的信息架构不一致。

  • 顶栏与 PC 同结构:logo(标记块 + Kole UI + 副标题) + 版本角标 v1.0.0(读 data.mobile.json 的 meta.version)+ 平台切换 + 主导航 5 项(组件总览 / 快速开始 / 设计规范 / 常见问题 / 更新日志, 与 PC 同名同序,组件页高亮「组件总览」= PC 在组件页高亮「组件」的同一口径)+ 主题模式三态。 PC 特有的三件没有搬,原因写明在 site/m/style.css 注释里:搜索框(PC 79 个组件才需要)、 技术栈选择器(PC 5 端各自成页;移动端 6 端同页展示)、语言选择器(移动端无 i18n 字典)。
  • 主题三态与 PC 完全同一约定:localStorage['kole-mode'] ∈ light|dark|auto、auto 跟随系统、 反色靠 html.kole-dark(令牌两端共用)。实测跨站生效:在移动端站选夜间 → FAQ 页仍是夜间 → PC 站同一键也是夜间;<head> 里有同步 bootstrap,避免首帧先白后黑(PC 的 S2-P5 同款处理)。
  • 左侧栏三段式与 PC 侧栏一致:「平台」组(PC 端组件 / 移动端组件【当前】,各带副标题)→ 「开发指南」组(与 PC 同名同序的 5 项;移动端特有的「平台与端 / 测试与回归」置后并标「移动端」)→ 「组件 N」按 PC 的六分类分组与计数(通用 / 导航 / 数据录入 / 数据展示 / 反馈 / 工具与系统)。 组件重新归类:navbar、tabbar → 导航;actionsheet、pullrefresh、swipecell → 反馈; 分类口径写进移动端索引的 categories 块(真源),构建脚本与文档站都读它。
  • 补两页:
    • faq.html 常见问题:6 组 20 条(接入 / 令牌 / 触控 / uni-app / 排障 / 口径),每条对应仓库里可复现的 实测或门禁断言;含「uni-app 端真的编译过吗 → 没有」这类如实回答。
    • changelog.html 更新日志:构建时从仓库根 CHANGELOG.md 提取标题含「Mobile / 移动端」的段落 (自带一个极小的 Markdown 渲染:标题 / 列表 / 引用 / 代码块 / 行内 code 与 strong),不手抄 —— 站点与仓库两处说法不一致是这类页面的典型失败模式。
  • 改名对齐:设计令牌 → 设计规范(tokens.html → design.html),与 PC 的「设计规范」同名。
  • 门禁 11 → 12 条:E3 从「侧栏列全组件」扩为「顶栏与左栏与 PC 同结构」(平台组与「当前」角标、 开发指南 5 项同名同序、顶栏 7 个必需元素、主导航 5 项);新增 E8 站内文件链接全部可解析(332 条)。
  • E8 当场抓到两个真问题(已修):① 改名后 _index_template.html 与 _guide_template.html 还指向 tokens.html(快速开始卡片与页脚);② changelog.html 的测试链接少退一级(../tests/… 应为 ../../tests/…)。 E8 已双向验证(临时改坏一处链接 → FAIL)。
  • 修:更新日志页在窄屏横向溢出(375px 溢出 88px、414px 溢出 49px)—— 提取的正文含 64 位哈希、 长路径这类不可断词的串;给正文/列表/行内 code 补 overflow-wrap: anywhere(表格此前已有同类规则)。 修后 7 页 × 4 宽度(320/375/414/768)0 溢出。

验收(原样):

node tools/verify-mobile-docs.mjs        → [OK] 12 条断言 · 11 页
node tools/verify-mobile-isolation.mjs   → [OK] 29 条断言    node tools/verify-uniapp.mjs → [OK] 9 条(8 SFC)
REG_BASE=… verify-mobile-site.mjs        → [OK] 53 条断言(8 页 + 窄屏)   npm run verify:i18n → OK(16 checks)
浏览器实测:顶栏 = Kole UI 移动端 / v1.0.0 / [PC 端][移动端] / 组件总览·快速开始·设计规范·常见问题·更新日志 / 自动模式
            左栏 = 平台(PC 端组件、移动端组件【当前】)/ 开发指南 5 项 + 2 项移动端特有 / 组件 5(导航 2 · 反馈 3)
            主题:选夜间 → html.kole-dark + localStorage[kole-mode]=dark;跳 FAQ 仍夜间;PC 站同键亦夜间;0 控制台错误
node tools/run-mobile-regression.mjs     → 100% | 77/77 | 5/5 页
node tools/run-regression.mjs            → 100% | 1026/1026 | N/A 34 | 79/79 页
node tools/pack-deploy.mjs --tar         → OK(39 条必需项,含 6 张移动端根页;组件数改为从索引读取)

Deploy · 移动端组件页(TDesign 范式)已上线

按 AGENTS §九 发布:pack-deploy --tar → 上传 → 暂存归一化树哈希与本地一致(f00d3c4ac2e50861,1531 文件)→ 替换 → docker compose build && up -d。 验收:specs 404 / 根 302→/site/ / sitemap 200 / healthz 有 content-type / SPA 深链 200 / 缺快照 404 / 容器日志 0 error; 公网 https://kole-ui.mymoyu.top 抽查 6 个文件(site/app.js、组件薄壳、site/data.json、移动端文档页与演示页)逐字节与本地一致。

并发提示:本轮期间另一会话把 package.json 版本重置为 1.0.0 并重建站点(data.json 的 generated=2026-09-20 07:36、 versions.json 单版本)。线上现已与该状态一致 —— 版本号本身不是本次改动;如需回到 2.0.0,请改 package.json 后重跑 npm run build:site 并再发布一次。 另:本轮第一次发布(07:26 打包)后实测到线上落后工作区 906 个文件(并发会话 07:36 重建了薄壳与 app.js), 已按 §九 的约定「等稳定后重发」补发一次,现线上与工作区逐字节一致。

Mobile docs · 组件页对齐 TDesign 范式(演示分组 / 独立预览 + 原文代码 / 必传 / CSS 变量 / 相似组件)

起因:用户给了参考页 https://tdesign.tencent.com/mobile-vue/components/link。用浏览器渲染后提取其结构: 演示按 01 组件类型 / 02 组件状态 分组;每个演示独立成块(标题 + 预览 + 代码); API 分 Props(名称 / 类型 / 默认值 / 描述 / 必传)、Events、CSS Variables(名称 / 默认值 / 描述); 另有「何时使用 / 组件搭配使用 / 推荐慎用示例 / 相似组件」。按这套范式重排了移动端组件页。

  • 演示改为「分组 + 独立块」:契约新增 demos(id / group / title / desc / variant),5 个组件共 20 个演示块 (navbar 3、tabbar 4、actionsheet 4、pullrefresh 4、swipecell 4),按 01 组件类型 / 02 组件状态 分组。 每块含:标题 + 变体标记 + 说明 + 375 宽单演示预览帧 + 「查看代码」(演示页原文,行数标注,可复制)。
  • 演示页支持 ?demo=<id> 单块模式:5 个演示页的每个演示包成 <section class="demo-block" data-demo="…">,并加过滤脚本(只显示该块、隐藏帧内标题行、取消 min-height:100vh)。 无参数路径完全不变 —— 测试页与回归走无参数,实测移动端回归仍 100%(77/77)。
  • 预览帧高度自适应:按 body.scrollHeight 收紧到 140–360px。

    踩坑:先用 max(body.scrollHeight, documentElement.scrollHeight) 量,结果四个演示都锁在 308px —— documentElement.scrollHeight 等于帧视口高度(html 撑满视口),于是「帧高 → 视口高 → 量到的高度」 形成反馈环,永远收敛在初始值。只量 body 后:swipecell 140 / navbar 140–166 / tabbar 222 / pullrefresh 242 / actionsheet 262,0 个演示被裁。

  • API 补两列/一表:Props 增「必传」列(严格定义:实现里没有默认值时才为 Y,门禁逐条核对 4 个框架端); 新增「CSS 变量」表(从组件样式表扫描组件级变量:--kole-m-swipecell-offset / --kole-m-swipecell-action-width / --kole-m-pullrefresh-threshold / --kole-m-pullrefresh-offset)。
  • 新增「相似组件」表(契约 related:组件 + 「何时用它而不是本组件」的区分说明,共 10 条), 并把「用法要点」按参考页改名为「何时使用」。
  • 组件页新顺序:演示 → API(Props / 事件 / 插槽 / CSS 变量)→ 何时使用 → 交互与触控 → 无障碍 → 相似组件 → 规格未定 → 结构 → 变体类名映射 → 代表变体 → 令牌 → 6 端源码 → 测试与回归 → 契约。 另在 hero 下加「引入」代码块(令牌 + 本组件样式)。
  • 门禁从 8 条扩到 11 条:新增 E4b(必传 ⇔ 实现默认值)、E6b(CSS 变量表 ↔ 组件 CSS 双向)、 E6c(相似组件 slug 真实存在 + 说明非空);E5 扩为「每个演示块 ↔ 演示页 data-demo 双向一致 + 预览帧带 ?demo= + 代码区含转义后的演示页原文 + 每个演示代码块非空」。

验收(原样):

node tools/verify-mobile-docs.mjs        → [OK] 11 条断言 · 9 页
node tools/verify-mobile-isolation.mjs   → [OK] 29 条断言     node tools/verify-uniapp.mjs → [OK] 9 条(8 SFC)
REG_BASE=… verify-mobile-site.mjs        → [OK] 53 条断言(8 页 + 窄屏)
npm run verify:i18n                      → OK(16 checks)
浏览器实测(1280×1000):分组 01/02 ✓ · 20 个演示块 ✓ · 每块预览帧只显示对应演示(4/4)✓ ·
  每块有代码折叠 ✓ · 帧高自适应 0 裁剪 ✓ · 0 控制台错误
node tools/run-mobile-regression.mjs     → 100% | 77/77 | 5/5 页(演示页改动后复跑)
node tools/run-regression.mjs ×2         → 100% | 1026/1026 | N/A 34 | 79/79 页

Deploy · 公网站更新到当前构建(移动端文档站四页 + 逐组件页 + PC 顶栏改动)

  • 按 AGENTS §九 流程发布:SITE_URL_BASE=https://kole-ui.mymoyu.top/ npm run build:site → build-mobile + build-uniapp → pack-deploy --tar(1531 文件 / 5.8 MB,1.0 MB gzip)→ 上传 → 备份(目录 /opt/aurora-admin.prev-20260920-0712
    • 镜像 kole-ui-showcase:pre-20260920-0710)→ 暂存目录逐文件哈希对账 0 差异(1531/1531) → 替换 → docker compose build && up -d。
  • 验收(服务器 127.0.0.1:3311):specs 目录 404 ✓ / 根 302→/site/ ✓ / sitemap 200 ✓ / healthz 有 content-type ✓ / SPA 深层路由 /site/component/button/h5 200 ✓;移动端与 uni-app 路径 8 条全 200(含此前 404 的 site/m/guide.html、platform.html、tokens.html);安全响应头 3 条在位。
  • 公网 https://kole-ui.mymoyu.top:/site/、/site/m/、/site/m/guide.html、 /site/m/component/actionsheet.html、/versions.json、/sitemap.xml 全 200; data.json → lib=kole-ui / version=2.0.0 / generated=2026-09-20 07:09(= 本次构建); 抽查 site/m/guide.html 与 site/m/component/actionsheet.html 的公网字节哈希与本地包逐字节一致。
  • 过程发现并修掉一个会让构建直接失败的仓库状态问题:本地 Dockerfile 曾带 COPY 1.4.1 /usr/share/nginx/html/1.4.1 行,而仓库根已无 1.4.1/ 快照目录(并发改动期间快照被清理)——docker compose build 报 failed to calculate checksum of ref …: "/1.4.1": not found。该行与其后注释块("以后归档后在补一行") 的自洽性由 tools/verify-versions.mjs 双向卡住(磁盘快照 ↔ COPY 行),现已通过(33 checks)。

    注:本轮第一次发布正是卡在这条(打包与 Dockerfile 之间差了几十秒的并发改动),已重新打包发布成功。

  • 修掉发布过程中暴露的 500:快照被移除后 /1.4.1/site/ 由「归档站」变成 500(容器日志: rewrite or internal redirection cycle while internally redirecting to "/1.4.1/site/index.html")—— nginx.conf 里版本段的 try_files 回落目标又匹配回同一 location,形成内部重定向环; 且深链 /1.4.1/site/component/button/h5 同样 500。修法:末位补 =404,前三个参数退化为文件存在性检查 (快照在 → 发它自己的壳;不在 → 干净 404)。并给这条失败模式加了门禁:tools/verify-versions.mjs 新增「versioned fallback terminates with =404」,双向验证过(改动后 34 checks 全过;把 =404 去掉立刻 FAIL)。 实测:/1.4.1/site/ 404、/1.4.1/ 302(再 404)、其余验收全绿、容器日志 0 条 error。

    归档的 1.4.1 快照内容本身没有被删除——它仍在服务器上的 /opt/aurora-admin.prev-20260920-0712/1.4.1/ 与 kole-ui-showcase:pre-20260920-0710 镜像里;仓库当前按「不归档任何历史版本」的状态(versions.json 只列 2.0.0)发布,这是并发会话清理快照后的既定状态。

Mobile docs · 补全左侧栏与页面内容(API / 6 端源码 / 令牌 / 回归状态)

起因:用户指出「移动端的左侧栏内容不完整,页面内容也不够完整」。移动端文档站此前只有顶部导航 与 6 个小节的组件页,没有左侧导航,也没有 API、源码、令牌、回归状态这些"读文档的人真正要用的东西"。

  • 左侧栏:所有页面共用一份 IA —— 「开发指南」5 项(移动端总览 / 快速开始 / 平台与端 / 设计令牌 / 测试与回归)+「组件 5」按分类分组(导航 / 手势 / 反馈)与计数,当前页/当前组件高亮并带 aria-current。 桌面恒定展开;≤1000px 自动收起为可折叠面板(点标题展开)。

    踩坑记录:左栏用 <details> 承载时,不能用"去掉 open + CSS 强制展开"的写法 —— 不带 open 的 <details> 高度按关闭态算成 0,overflow:auto 会把里面的 nav 整块裁掉 (DOM 里有 10 条链接、屏幕上一片空白,实测截图抓到)。改为 open 默认展开 + 断点脚本切换。

  • 新增三页:
    • guide.html 快速开始:三步接入、按端引入路径表(6 端)、6 端最小示例(React / Vue 3 / Vue 2 / uni-app 可拷贝代码)、与 PC 端的边界、5 条常见问题(样式不生效 / --kole-m-* 取不到值 / 安全区 / 手势不触发 / 多 fixed 叠层)。
    • platform.html 平台与端:两轴覆盖矩阵、uni-app 两列对照、12 行目录与命名映射、6 条隔离规则、 6 条门禁命令(各自检查什么)、新增组件的六步流程。
    • tokens.html 设计令牌:15 个 --kole-m-* 表(名 / 值 / 用途)+ 组件实际引用到的继承令牌表(构建时扫描)、 单位与安全区与明暗模式三条约定、"改令牌的正确姿势"示例。
  • 组件页 6 节 → 14 节:新增 API(props / 事件 / 插槽三张表)、6 端源码(每端一个折叠块 + 复制按钮)、 用到的令牌(构建时从该组件 CSS 扫描,区分自有 / 继承 / 组件级变量)、交互与触控、无障碍、 变体维度 × 类名映射、测试与回归(逐组件断言数,取自回归报告的 pageResults)、设计契约(内嵌原始 JSON)、 相关组件。
  • 契约补 4 类字段:interaction / accessibility(逐字取自规格 §x.5 / §x.6)、 api(props / events / slots,写明"实现接口"的来源)、variantClasses(变体取值 → 类名/变量)。
  • 新门禁 npm run verify:mobile-docs(8 条断言):页面齐全 / 组件页 14 小节 / 侧栏列全组件且恰好一个高亮 / 契约 API 与 4 个框架端源码逐名一致(正向 + 反向) / 每个声明的端都有非空代码块 / variantClasses 的类与变量在组件 CSS 里真实存在 / 页面壳完整且无残留占位符。 Rationale:本站是生成物,生成器的 bug 只会让页面悄悄少一块,不会报错 —— 这类"缺内容"必须靠断言抓。
  • 门禁当场抓到的真实漂移(已修):契约声明 PullRefresh.threshold,但 uni-app 端没有这个 prop(它用的是 模块常量)。已给 uni-app 端补上 threshold(rpx 默认 120),并把「浏览器端 px / 本端 rpx」的单位差异写进契约描述。
  • 回归报告新增 pageResults(逐页 total/pass/fail):组件页据此显示「断言 N 条 · 全部通过」。 PC 侧报告缺这一块(正是 S5-P17「失败落不了盘」的痛点),移动端先补。
  • 令牌计数统一为 15:安全区两条在 @supports 里各出现两次(0px 默认 + env() 覆盖), 此前构建日志/数据显示 17 而映射表显示 15;现按唯一令牌名计,并给这两条补上用途说明。

验收(原样):

node tools/verify-mobile-docs.mjs        → [OK] 8 条断言 · 9 页(含 API ↔ 源码逐名一致)
node tools/verify-mobile-isolation.mjs   → [OK] 29 条断言
node tools/verify-uniapp.mjs             → [OK] 9 条断言(8 个 SFC)
REG_BASE=… node tools/verify-mobile-site.mjs → [OK] 53 条断言(8 页 + 窄屏 3 页 × 4 宽度)
npm run smoke:site / verify:i18n          → OK(16 checks)
浏览器实测:桌面左栏高度 500px / 10 条链接 / 恰好 1 个高亮;窄屏自动收起、点开可见、放大自动展开;
            复制按钮写入剪贴板 2233 字符且文案变「已复制」;#api 锚点可定位;0 控制台错误
node tools/run-regression.mjs ×2          → 100% | 1026/1026 | N/A 34 | 79/79 页 | 0 超时
node tools/run-mobile-regression.mjs      → 100% | 77/77 | 5/5 页 | 0 超时(逐页 14/15/16/15/17)

Design system · SideMenu 花屏修复(nav-menu 族 side 方向)+ 演示页命名统一 + 布局守卫断言(S6-P42 / S6-P44 / S6-P43)

起因:用户报告「当前的项目有花屏 bug」。定位后是 v2.0.0 族重构(eb25fee)引入的回归, 只在 direction=side 上暴露;同批把「为什么 100% 回归没拦住它」「Linux 侧的命名分裂」一起收掉。

  • 花屏现象与根因(S6-P42):/site/component/sidemenu 与 frameworks/SideMenu.html 的「代码演示」里, 二级项(全部订单 / 待发货 / 商品列表 / 分类管理)渲染成侧栏右侧一列浮块并压住同级项 (工作台 的 label 盒与 全部订单 交叠 52×14)。两处叠加:①族模板 menu.html.tpl 把子级拼在 .kole-menu-item 内部,而该项是 display:flex; height:44px → 子级成了横向 flex 子项; ②menu.css.tpl 在 side 方向没有折叠规则(只有 top 有 display:none + hover 展开)。 重构前的手写实现是「子级挂在菜单根下当兄弟节点 + .collapsed .children{display:none}」,两条都在改写时丢了。
  • 修法(唯一真源 tools/lib/family-impl/nav-menu/menu.css.tpl,5 端共用一份 CSS):side 一级项 flex-wrap: wrap; height:auto; min-height:44px; row-gap:0;> .kole-menu-children { flex: 0 0 calc(100% + 32px); margin: 0 -16px; display:none }, .is-open 时 display:block;折叠态用同权重且靠后的选择器压住已点开的项。改模板后重跑 node tools/gen-family-impl.mjs --only=nav-menu(三个文件的 CSS 仍逐字相同)。
  • 演示页命名统一到 Pascal(S6-P44):git ls-files 跟踪的 21 个演示页是小写 (button.html / input.html / … / sidemenu.html),而 index.json 的 frameworksPrefix 79/79 全 Pascal、 族生成器按 <Prefix>.html 写入、测试页 iframe 也写 Pascal → Linux 下 21 个测试页 iframe 404 (Windows 大小写不敏感把生成物折叠到小写文件上,本地完全看不出)。git mv 两步改名统一后, 大小写敏感审计(data.json 与测试页引用逐一与磁盘名逐字比对)不一致处 = 0; frameworks/ 仍 395 文件;pack-deploy 的样本断言 frameworks/button.html → frameworks/Button.html。
  • 布局守卫断言(S6-P43):tests/_behaviors.js 新增 verb layout-menu-rows(纯几何、无交互)—— 可见叶子文本两两重叠不得超过较小者的 55% / 可见子级不得越出菜单横向边界 ±2px / 折叠态不得露出子级; 三个导航族成员加入 PILOTS,族模板三个 <nav> 各声明一条 → 新增 9 条断言。A/B 反例:注入旧 CSS 后 sidemenu 两条 fail 且报错与原始花屏逐字一致(文本交叠 kole-menu-label「工作台」 × kole-menu-label「全部订单」 重叠 52×14px)。
  • 顶栏窄屏溢出(同批发现):版本选择器 122px 在 375px 把汉堡挤出右边界 23px(英文 19px、360px 34px); site/style.css 在 ≤600px 收紧为 68px(与并行会话的 ≤560px 收起并存互补,覆盖 561–593px 那一档)。 逐像素扫描 320–900px 中英双语溢出量全为 0;npm run verify:nav 349 项全绿。
  • 判据修正(tools/verify-versions.mjs):①路径校验改为按行为验证(抽函数体跑输入矩阵), 原按写法匹配的检查在实现改写后误报;②硬编码版本号扫描先剥注释——原判据把文档注释里的路由示例 1.4.1 当成了硬编码(反例已验证:代码里写 var v = 'v2.0.0' 仍会失败)。
  • 同批修掉的构建/环境问题:site/dev-server.js 的白名单缺 frameworks-mobile / frameworks-uniapp-pc (生产 nginx 走 location / 全放行,只有本地预览 403,移动端文档页本地打不开); 打包前 SITE_URL_BASE=https://kole-ui.mymoyu.top/ 重建(否则 sitemap 落占位域名,verify:site-routing 红灯)。
  • 发布链缺陷(S6-P48,发布验收时才暴露):Dockerfile 用 COPY [0-9]*.[0-9]*.[0-9]*/ /usr/share/nginx/html/ 打包历史快照 —— COPY 源带结尾斜杠时复制的是目录内容,于是 1.4.1/ 快照的 site/、frameworks/、 sitemap.xml 原地合并进站点根,用快照那份旧构建覆盖当次构建(镜像里 data.js 的 generated 是 快照那次的 05:27、frameworks/ 多出改名前的 21 个小写演示页),且 /<版本>/ 目录根本没建出来 → /1.4.1/site/** 全 500(S6-P45 的真因)。改为逐版本显式 COPY 1.4.1 /usr/share/nginx/html/1.4.1; tools/verify-versions.mjs 加三条门禁(禁通配形 / 每个快照必须有 COPY 行 / 不许留已删版本的行), 反例已验证。修复后线上 /1.4.1/site/index.html 由 500 → 200。
  • 发布(2026-09-20 06:00 构建,部署 /opt/aurora-admin):pack-deploy --tar 2914 文件 → ssh_upload(sha256 校验)→ 暂存目录与本地发布集逐字节核对 0 差异 → 目录替换 + --no-cache 重建 → 五条验收全中(specs 404 / 根 302→/site/ / sitemap 200 / healthz 有 content-type / 深层路由 200)+ 版本 2.0.0; 公网实测 https://kole-ui.mymoyu.top:data.json 的 lib=kole-ui、version=2.0.0、 generated=2026-09-20 06:00,/site/style.css 含新规则、/frameworks/SideMenu.html 200、 /1.4.1/site/index.html 200,演示帧几何实测「子级宽 220 = 侧栏宽 221、落在栏内、父项 44→140px」。
  • 归档入口 302 目标修正:nginx.conf 的版本裸入口规则注释写着「送到该版站点」, 代码却是 return 302 /site/(现行版本),正则也没捕获版本号 → /1.4.1/ 与 /1.4.1/index.html 会把访问者带到现行文档,归档进不去归档。改为 return 302 /$1/site/(与 dev-server 的 verRoot 一致); 线上实测 /1.4.1/ → Location: /1.4.1/site/。同时修 verify-deploy-consistency.mjs 的假滞后: 它直接比对响应字节,而 nginx 故意 302 的路径(根 /index.html、/<x.y.z>/index.html)拿到的是 302 响应体,与磁盘文件天然不同 → 这类路径改为跳过并单独计数。
  • 回归:PC 100%(1026/1026,79 页全过,0 超时);移动端 100%(77/77)。
  • 并发写入说明(§九 的纪律):本轮发布期间另一会话持续改写 site/app.js、site/style.css、 site/m/**、tests/mobile/**、ROADMAP/CHANGELOG/AGENTS(实测 06:24 又改了 app.js 并重做快照, 晚于本次打包 06:21)。线上快照 = 本次打包时刻的工作树;之后工作树的改动不在线上。 已登记 S6-P49(把「打包后工作树再被改写」变成出包时的硬判据)。

Docs site · 平台入口打通(PC ↔ 移动端)+ 技术栈选择器美化 + 本地访问方式

起因:用户要求「做一个合理的访问方式」与「当前的组件框架选择的样式需要美化一下」。 前者指:移动端文档站上线后没有入口,且本地起服务时端口被旧实例占用会静默失败(实测 403); 后者指顶栏那个裸 <select>(系统原生下拉、无悬停/展开态,与旁边的语言/主题选择器不同源)。

  • 技术栈选择器改为「胶囊触发器 + 卡片菜单」(site/index.html + site/style.css + site/app.js): 图标(层次符号)+ 当前值 + 箭头;菜单沿用语言选择器的卡片样式(标题分隔线、每项带端文件名角标 html / jsx / vue2 / vue3、选中项对勾、头部右侧显示当前端文件名)。键盘全路径:↓/↑ 移动、 Home/End 首尾、Enter/Space 选中、Esc 关闭并回焦、Tab 关闭不抢焦点、点击外部关闭; 展开态旋转箭头 + 品牌色焦点环;暗色与 prefers-reduced-motion 均适配。
  • 原生 <select> 保留为状态真源(.fw-native:1px 视觉隐藏,不进 Tab 序列): 选中项写回它的 value 并派发 change,既有的「状态更新 / localStorage / 路由跳转」管道 与既有验证脚本(run-site-smoke 读 inputValue() + selectOption())一行未改。
  • 侧栏新增「平台」分组:PC 端组件(带「当前」角标与副标题)/ 移动端组件(副标题写清 5 组件 × 6 端含 uni-app)。移动端入口是整页跳转(指向站点根下的 m/index.html)—— SPA 的路由拦截器只接管无扩展名的地址,带 .html 的链接交回浏览器,两个站各自独立加载。
  • 移动端文档站顶栏加平台切换 [PC 端] [移动端](当前侧实心品牌底),与 PC 侧形成双向入口。
  • 本地访问方式(site/dev-server.js):端口被占用时自动向上找空闲端口(最多 10 档)并说明, 不再 EADDRINUSE 直接退出;KOLE_PORT 显式指定时不回退(CI/脚本依赖固定端口)。 启动即打印 6 个入口:PC 文档站 / 移动端文档站 / 组件总览 / PC 测试总览 / 移动端测试总览 / 两个回归收集器,并给出 REG_BASE= 提示。

    实测踩到过:3311 上挂着改动前启动的实例时,新目录一律 403,日志里只有一句 EADDRINUSE, 极易误判成「构建没产出」。

  • 修:移动端文档站在小屏上横向溢出(实测 375px 溢出 128px、414px 溢出 89px)—— 一个讲移动端的 文档站自己在手机上横向滚动说不过去。元凶两处:表格里不可断行的长路径 (.design_library/kole-ui-mobile/components/ 把表格最小宽度顶到 462px)与组件页固定 375px 的设备帧。 修法:单元格与 <code> 允许长 token 断行、设备帧取 min(375px, 100%)、顶栏 ≤720px 换行并把副导航移到第二行。 修后实测 320 / 375 / 414 / 768 / 1280 全部 0 溢出、0 控制台错误。
  • 新增窄屏门禁:tools/verify-mobile-site.mjs 加「窄屏无横向溢出」一节(3 类页面 × 4 个宽度 + 控制台错误), 断言数 38 → 53。只靠"在桌面宽度看一眼"发现不了这类问题。
  • 修:移动端文档站与规格文件里对 MOBILE.md 的失效引用 → PLATFORMS.md(4 处源码, 生成物已重跑)。该文档在交付时最终命名为 PLATFORMS.md。
  • 验证脚本同步:verify-nav-responsive.mjs 的字体容忍度元素清单随 UI 更新 (.fw-label/#fw-select → .fw-cur/.fw-menu .fw-opt)—— 清单不跟着改会把余量报得偏乐观。 实测余量 5.8%(英文 · 1367px)。

验收(原样):

浏览器功能断言(Chromium 1440×900)        25/25 PASS,全程 0 控制台错误
  ├ 触发器/菜单/4 选项/端文件名角标/选中态/aria-expanded
  ├ 选择 Vue 3 → 触发器文案 + #fw-select value + localStorage + 路由 /component/button/vue3 同步
  ├ 键盘:Esc 关闭、↓ 打开并聚焦当前项、↓ 环形移动、Enter 生效
  ├ 侧栏平台入口 2 项、href=/site/m/index.html、整页跳转到移动端站、移动端站回链 ../index.html
  └ 暗色模式菜单底色 rgb(28,31,38)(跟随主题)
node tools/verify-mobile-isolation.mjs     → [OK] 29 条断言
node tools/verify-uniapp.mjs               → [OK] 9 条断言(8 个 SFC)
REG_BASE=… node tools/verify-mobile-site.mjs → [OK] 53 条断言(8 页 + 3 页窄屏 × 4 宽度)
npm run smoke:site                          → OK — all checks passed
npm run verify:nav                          → OK — all checks passed(余量 5.8%)
npm run verify:playground                   → OK — all checks passed
node tools/run-regression.mjs ×3            → 100% | 1026/1026 | N/A 34 | 79/79 页 | 0 超时
node tools/run-mobile-regression.mjs        → 100% | 77/77 | 5/5 页 | 0 超时

Tooling · 发布快照一致性核对(升级验收)+ 验证脚本的跨平台/远程修正

起因:站点发布后做升级验收,要回答「线上跑的到底是工作树的哪个状态」。此前只有 AGENTS §九 里 一句手工步骤("打包前后各查一次产物哈希")—— 本轮实测线上 2908 个可比对文件里 1883 个与工作树不一致(滞后 917 / 缺失 966),手工核对不可能发现。

  • 新增 tools/verify-deploy-consistency.mjs(npm run verify:deploy):按发布集枚举工作树里 会随包出去的文件,逐个拉远端同路径比对 sha256,报「一致 / 滞后 / 线上缺失」;生成物 (tests/report*.json|xml、site/data.js)单独计数不算失败。零依赖(node 内置 fetch)。 --base= 指向任意实例(本地 dev-server 或公网),--only= 限定子串快速跑。
  • 发布集抽成 tools/lib/publish-set.mjs:.dockerignore 的解析与匹配语义、内容目录清单、 历史版本快照目录原先只存在于 tools/pack-deploy.mjs。核对脚本必须与打包器看同一份清单 (否则又会出现"打包器说发了、核对脚本说没发"),故抽成模块供两处 import; pack-deploy 重构前后输出逐字节一致(复用其自带断言:2914 文件 / 排除 26 / 断言 13+34 全过)。
  • tools/verify-playground.mjs 两处跨平台/延迟修正(都只在对远程部署跑时暴露): ① mock 里的演示文件路径原先写死小写(/frameworks/card.html)—— Windows 不区分大小写照样过, 到 Linux 容器就是 404,改为一律从 data.json 的 files.html 派生(各组件大小写不同: Card.html / button.html);② 远程下 data.json(1.36 MB)与令牌样式表比文档慢, 预检超时放宽到 30 s,暗色令牌改「等到真生效再读」,不再把"还没加载完"当成"没反色"。
  • 发布集同步覆盖 frameworks-mobile / frameworks-uniapp-pc(新平台上线后核对不漏检)。

深检修复批次:暗色对比度(站点 chrome)+ 两处测试侧缺陷

起因:S6-P37 交付后的深度检测(数据层审计 / 79 页巡检 / 侧栏不变量 / 暗色对比度 / 构建确定性) 报出 3 个问题(ROADMAP S6-P39/P40/P41)。本轮全部修掉,并把判据固化进验收脚本。

  • 暗色对比度(S6-P39):site/app.js 的 applyTheme() 把暗色品牌色族的混白比例从 0.25 提到 0.45(悬停 0.6 / 按下 0.3 保持「悬停更亮、按下更暗」的次序)—— 品牌色文字常压在品牌浅底 (--kole-color-brand-bg = 同色 18% 叠卡片底)上,只混 0.25 时实测 3.59:1,低于 AA 正文 4.5:1; 提到 0.45 后 7.27:1。注意这几条是内联写在根元素上的,样式表规则压不过它们。
  • 同时把「站点 chrome 的暗色对比度」纳入 tools/verify-dark.mjs 第 4 组(7 条路由,正文 4.5:1 / 大字与图标 3:1,含侧栏选中态与含必填徽章的组件页)。该组一上线即抓出另外四处既有缺陷并修掉: 行内 code 2.88:1、.radius-demo 3.44:1、.callout.note 4.14:1(三者用品牌色族偏暗档 → 暗色改用基色)、 .code-inline 2.88:1(代码块借用的 --kole-color-tooltip-bg 在暗色下是浅色,与固定浅色的代码文字撞车 → 暗色改用 table-header-bg,11.1:1)、.badge-opt 3.08:1 与 .badge-req 3.71:1(亮色模式也不达标 → 改用令牌,4.88 / 5.57:1)、.callout.warn 4.14:1(亮色不达标 → 文字换规格定义的 #8C5A00 5.51:1, 暗色另给低透明底 6.49:1)。node tools/verify-dark.mjs 现 DARK VERIFY OK。
  • verify-nav-responsive 红灯(S6-P40):脚本原固定在 390px 点 #lang-trigger,而工作区一度加了 「≤420px 语言选择器让位」的规则 → 元素不可见、30s 超时崩溃。改为与规则解耦:叠层检查 (语言菜单 vs 抽屉)固定放在语言选择器可见的 480px 视口,390px 段只覆盖抽屉交互本身 —— 规则在或不在都能跑。
  • 对比度断言采到过渡中间帧(S6-P41):tests/_runtime.js 的对比度遍历前后临时注入/移除 #kole-assert-settle(*{transition:none!important;animation:none!important})——阈值不动(仍 4.5:1), 只是不再把过渡中间帧当结果(反例:DensitySwitcher 选项按钮过渡中途 1.74:1,稳定态 7.00/5.85:1)。 另把 tests/_runtime.js 已算好的 failureDetails 落进 report.json 与 JUnit(此前只存断言 ID, 偶发失败事后无法回溯)。验证:断言总数仍 1017,并发压测由「180 次加载失败 1 次」变为 300 次 0 失败。
  • 亮色模式也补了同一类检查:把对比度探针抽成 tools/lib/contrast-probe.mjs(半透明底沿父链合成 + 正文 4.5:1 / 大字与图标 3:1 判据),verify-dark.mjs 第 4 组与 verify-theme.mjs 新增的 chromeContrastCase 共用它,亮/暗各跑 3 条路由。亮色一上线又抓出两处既有缺陷:搜索框占位文字 span.st-text 4.23:1、搜索面板副标题 span.sp-sub 4.16:1(都是 text-placeholder #767676 压在浅底上) → 改用 text-secondary(4.75:1)。node tools/verify-theme.mjs 现 THEME VERIFY OK。
  • 公网部署复核(S6-P38):公网 https://kole-ui.mymoyu.top/site/ 已是 lib: kole-ui / version: 2.0.0 (generated 2026-09-20 05:27,标题 Kole UI · 组件库文档),AGENTS §九 四条验收全过; §九 里残留的 /opt/kole-ui.staged 暂存目录名与部署目录 /opt/aurora-admin 对齐。

Design system · 修 SideMenu 花屏:nav-menu 族 direction=side 子菜单渲染错位(S6-P42)

起因:用户报告「当前的项目有花屏 bug」。定位后是 v2.0.0 族重构(eb25fee)引入的回归, 只在 direction=side 上暴露,文档站组件页与演示页同时可见。

  • 现象(2026-09-20 实测):/site/component/sidemenu 与 frameworks/sidemenu.html 的「代码演示」里, 二级项(全部订单 / 待发货 / 商品列表 / 分类管理)渲染成侧栏右侧一列浮块,横向越出 220px 侧栏, 并压住同级项(工作台 的 label 盒与 全部订单 交叠 52×14)。三个演示块(默认态 / 带徽章 / 折叠态)全中。
  • 根因(两处叠加):①族模板 menu.html.tpl 的 itemHtml() 把子级拼在 .kole-menu-item 内部, 而该项是 display:flex; height:44px → 子级被当成横向 flex 子项挤在同一行、纵向溢出; 重构前的手写实现是把子级 appendChild 到菜单根下当兄弟节点,故无此问题。 ②menu.css.tpl 在 side 方向没有折叠规则(只有 top 方向有 display:none + hover 展开), 子级常驻渲染;重构前有 .aa-sidemenu.collapsed .aa-menu-children { display: none }。
  • 修法(单点在唯一真源,5 端共用一个 CSS,HTML/JSX/Vue 模板无需改): tools/lib/family-impl/nav-menu/menu.css.tpl —— side 一级项改为 flex-wrap: wrap; height: auto; min-height: 44px; row-gap: 0;> .kole-menu-children 为 flex: 0 0 calc(100% + 32px); margin: 0 -16px; display: none,.is-open 时 display: block; 折叠态用同权重且靠后的规则压住已点开的项(否则 .is-open 权重更高会胜出)。 改模板后重跑 node tools/gen-family-impl.mjs --only=nav-menu(三个文件的 CSS 仍逐字相同)。
  • 验证:几何实测 —— 未展开 display:none;展开后子级宽 220 = 侧栏宽且完整落在栏内;父项 44→140px; 可见 label 两两无交叠。top(hover 展开)与 mixed 未回归。回归 100%(1017/1017,79 页全过,0 超时)。
  • 同批登记、未在本任务修:S6-P43(测试矩阵缺「布局包含性」断言,故本次花屏被判为全绿)、 S6-P44(frameworks/sidemenu.html 大小写命名分裂,Linux 下测试页 iframe 指向不存在的文件)。

Mobile · 移动端平台上线:与 PC 端物理隔离(平台 × 端两轴,含 uni-app 端)

起因:用户要求「在组件库额外添加移动端组件,移动端和 PC 端隔离」,并明确「PC 和移动是两个大分类, 移动端后面是 H5 移动端、Vue 移动端,而且 uni-app 也会经常用到(uni-app 移动端 / uni-app PC 端)」。 据此把组件库组织成两个正交轴:平台 pc | mobile × 端 css | html | jsx | vue2 | vue3 | uniapp。 新增 PLATFORMS.md(两轴定义、目录与命名映射、隔离规则、新增组件六步流程)。

  • 移动端 5 个组件 × 6 端 = 30 个实现文件(frameworks-mobile/):navbar(顶部导航栏)、 tabbar(底部标签栏)、actionsheet(动作面板)、pullrefresh(下拉刷新)、swipecell(滑动单元格)。 每组件六端:CSS / H5 演示页 / React / Vue 2 / Vue 3 / uni-app。类名前缀 kole-m-,导出名 KoleM*。
  • 移动端规格原文(本仓库自撰):.design_library/kole-ui-mobile/spec/移动端规格.md。 PC 端规格来自外部交付的 组件1~10.txt;移动端没有外部规范,故契约 sourceKind: authored-spec、 provenance: authored-in-repo——不冒认外部来源;契约的 doNotInvent / unknowns 逐条对应规格条目。 规格共 5 节(另有 §〇 隔离总则),5 份契约全覆盖。
  • 令牌层:.design_library/kole-ui-mobile/colors_and_type.css = @import PC 令牌(颜色/字体/圆角/阴影同源)
    • 15 个 --kole-m-*(触控 44px 最小热区、@supports (env()) 安全区、移动端字号、手势动效时值)。 PC 令牌文件零改动,改一处令牌两端同时生效。
  • 隔离边界(每一条都有断言,见下):实现目录(frameworks-mobile/ vs frameworks/)、契约目录、 类名前缀、令牌前缀、测试页(tests/mobile/ vs tests/)、回归报告(tests/mobile-report.json vs tests/report.json)、文档站(site/m/ 静态站 vs site/ SPA,移动端不进 PC 路由表)、 分发产物(dist/mobile/* vs dist/*)。
  • uni-app 端两处:移动端 × uni-app(5 个,目标 app-plus / mp-weixin / h5,用 uni 基础组件 + rpx + touch 事件——小程序与 App 端无 PointerEvent);PC × uni-app 试点 3 个 (frameworks-uniapp-pc/{Button,Input,Card}.uniapp.vue,类名与 PC 的 frameworks/*.css 逐字一致、 --kole-* 令牌、px 尺寸、目标 H5/PC 容器),覆盖率 3 / 79 并登记为 ROADMAP S7-P26。
  • 构建(Node,跨平台,不碰 Windows-only 的 PS 链):tools/build-mobile.mjs(导出 site/m/data.mobile.json 自包含 102 KB = 5 组件 × 6 端源码、site/m/index.html 总览、site/m/component/<slug>.html 逐组件页、 tests/mobile/**、dist/mobile/**)与 tools/build-uniapp.mjs(dist/uniapp-pc/**)。 两个脚本都带写入守卫:越界路径直接抛错(移动端脚本只允许写 site/m/ tests/mobile/ dist/mobile/)。
  • 测试:移动端测试页以 375×640 设备帧 iframe 载真实演示页;断言引擎与 PC 共用 tests/_runtime.js; 行为库为移动端专属 tests/mobile/_behaviors.js,新增 3 个触控动词 swipe-sets-class / swipe-sets-attr / pull-triggers(合成 pointerdown → pointermove → pointerup 手势,断言类/属性真实变化)。 两端行为库互不加载,PC 侧 6 试点组件不受影响。
  • 门禁与 CI:tools/verify-mobile-isolation.mjs(28 断言:PC 零污染 / 移动端自洽 / 分发隔离)、 tools/verify-uniapp.mjs(9 断言:SFC 三段 / node --check 语法 / 标签配平 / 禁 DOM API / 手势必须 touch / 只用 uni 基础组件 / 前缀隔离 / 单位策略)、tools/run-mobile-regression.mjs。 regression.yml 新增:构建分发产物 → 移动端生成物可复现性断言(git diff --quiet 卡"改了索引忘重跑构建") → 两条门禁 → 移动端回归 → 报告上传与摘要(PC 与移动端两段)。
  • 部署:tools/pack-deploy.mjs 的 CONTENT_DIRS 增 frameworks-mobile、frameworks-uniapp-pc, 新增 6 条硬断言(移动端 30 实现 / 5 文档页 / 5 测试页 / 3 试点);Dockerfile 增两条 COPY; .dockerignore 显式排除 .design_library/kole-ui-mobile/spec(移动端规格原文与 PC 规格同策略不进镜像); site/dev-server.js 白名单增两个顶层目录。

验收(原样):

node tools/verify-mobile-isolation.mjs   → [OK] 隔离门禁全部通过(28 条断言)
node tools/verify-uniapp.mjs             → [OK] uni-app 门禁全部通过(9 条断言 · 8 个 SFC)
node tools/run-mobile-regression.mjs     → passRate 100% | pages 5 (all-pass 5) | assertions 77/77
node tools/run-regression.mjs ×8         → run 1..8 全为 100% | pass 1017 | fail 0 | na 34 | pages 79/79 | timedOut 0
node tools/pack-deploy.mjs               → OK:components 79 薄壳/395 实现 · mobile 30 实现/5 文档页/5 测试页 · uniapp-pc 3 试点

未执行(写明并给复现命令,见 ROADMAP S7-P25):uni-app 真实编译(H5 / 微信小程序 / App)—— 需 @dcloudio/vite-plugin-uni,与零运行时依赖不冲突但会污染主回归 job 的依赖,故本次只做静态门禁; 复现命令写在 tools/verify-uniapp.mjs 头部。

Docs site · 主题模式默认改为「自动」(日间 / 夜间 / 自动 三态)

起因:用户要求「添加合适的日间/夜间/自动选择模式,默认为自动」。三态 UI(顶栏模式菜单、 H5 ThemeSwitcher、在线测试页)此前已在,缺的是默认值:没有显式选择时回退 light。

  • 默认值:kole-mode 缺省 / 无法识别 / 被清空 一律为 auto(跟随系统 prefers-color-scheme); 首次加载把默认值落盘,之后各标签页由 storage 事件保持一致。改动点:site/app.js (MODE_DEFAULT + normalizeMode/readMode,applyMode(mode, persist) 增加落盘开关)、 site/playground.js、frameworks/ThemeSwitcher.html。
  • 无闪烁:site/index.html 与 site/playground.html 的 <head> 加解析期 bootstrap, 在首个 <link>/脚本之前就定好 kole-dark 类,避免「先白后黑」。
  • 原生控件跟随:令牌文件 :root 加 color-scheme: light、html.kole-dark 加 color-scheme: dark (暗色下滚动条 / 表单 / 系统色不再留在浅色);两页再补 <meta name="color-scheme" content="light dark">。 令牌数与三格式导出不变(仍 106 tokens)。
  • i18n:新增 {m}(当前:{e}) 词条,模式名与「当前生效」改为整句翻译,英文下不再出现中文残段。
  • 验证:tools/verify-theme.mjs 从 24 条扩到 38 条,覆盖「首访默认 auto(含系统夜间 + 切回日间即时反色)」 「默认值静态卡口」「bootstrap 先于 data.js」「ThemeSwitcher / playground 默认自动」。
  • 顶栏常驻入口(同日追加):此前模式切换只在右下角悬浮按钮里,顶栏看不见(用户实测反馈「导航栏没有选择主题」)。 现于顶栏「框架选择器 → 语言选择器」之间加常驻触发器(图标 + 当前模式名),与悬浮按钮共用同一份状态: 两入口互斥展开、Esc 关闭、aria-checked / aria-expanded 同步。响应式降级:>1100px 显示模式名, ≤1100px 只留图标(与语言选择器同一档),≤560px 框架选择器整块收起,≤340px 语言选择器让位—— 320px 顶栏溢出 54px 由此消除(只量顶栏自身;首页内容另有 15px 既有溢出,不在本次范围,另记 ROADMAP)。 触发器不加下拉箭头:顶栏在 1367px(英文、导航尚未折叠)只剩 2px 余量,箭头会直接溢出 6px。
  • 新增断言:verify-theme.mjs 覆盖顶栏入口可见性 / 默认选中自动 / 选夜间生效并落盘 / 模式名同步 / 两入口互斥 / Esc 关闭 / 375px 与 320px 降级;verify-nav-responsive.mjs 18 宽度 × 中英双语全过。
  • 视觉打磨(同日追加):顶栏触发器加 15×15 图标底衬(--kole-color-table-header-bg,hover / 展开转品牌浅底); 菜单头改为两行(「当前选中」+ 自动模式下补「实际生效」,生效主题用品牌色强调)—— 单行拼接在英文下会折行;菜单宽度 168 → 184px、选项高度 32 → 34px、加 160ms 展开动画; 选中行加 inset 2px 左侧品牌色条(浅底在暗色下对比有限);三态色标改为语义化配色: 日间 = 白底、夜间 = --kole-color-page-bg、自动 = 左右半分渐变(直接表达「跟随系统」)。 踩坑记录:色标最初用 --kole-color-tooltip-bg,而它是反色工具提示底(亮色下深、暗色下 #E8EAED 浅), 当「夜间」色标正好反掉,已改用页面底色令牌。
  • 降级阶梯补齐(同日追加):≤560px 版本选择器(#ver-select-wrap,实测 122px)让位 —— 它是 ≤900px 接管出现的,加上主题入口后 375px 溢出 23px(中英皆是)。版本切换在更新日志页仍有入口。

Docs site · 内容与信息架构对齐 Element 文档站(侧栏分组 / 快速开始叙述 / 组件页 API 说明)

起因:用户以 Element UI 文档站(element.eleme.cn)为参照,指出「快速入门等地方的描述更好, 还有组件页面等内容,还有左侧导航栏内容」。三块逐项对齐,但不照搬其 API 表的「可选值」列—— 本仓库没有可引用的枚举数据源(见下)。

  • 侧栏(renderSidebar):页面链接原先平铺在侧栏顶部、无归属标签,现按 Element 口径分为 「开发指南」(组件总览 / 快速开始 / 设计规范 / 常见问题 / 更新日志)与「组件 N」两个段标题; 「更新日志」此前在侧栏没有任何入口(ROADMAP S5-P24 的实测表长期记着「维持原状」),本次补齐。 段标题用 .side-section 与可点的分类组(.side-group)区分开。
  • 快速开始(renderGuide):改为 Element 式的分步叙述 —— 开头一句「本节将介绍…」+ 5 条步骤清单 (.guide-outline),每节先说明再给可拷贝的代码;补上 Element「全局配置」段在本系统的对应物 「全局配置(主题与暗色模式)」(令牌覆盖 + html.kole-dark 用法);收尾加「开始使用」四张下一步卡片; 并按 Element 的「完整引入 / 按需引入」对位说明本系统的口径(组件以源码发布,取哪几个文件即按需; 全量样式用聚合文件 components.css)。共 7 节,右侧目录同步。
  • 组件页 API 表(buildApiSection + tools/precompute.mjs):说明列原先 235 条里 230 条是 — (只有源码里写了注释的才有),事件说明则是模板句(「组件交互触发事件」占多数)。现改为构建期按 出处生成、每条都标注来源:规格(29 条,命中规格原文分条,title 逐字引用该条,如 Button type → 「类型:主按钮、次按钮…」)/ 命名(204 条,API 名释义,明确标注「非规格原文」)/ 源码(1 条注释)/ 契约(1 条 dims);事件说明由 emit 调用点判定,同一事件名在不同组件里 语义不同(ok:modal / fullscreenmodal 绑确认按钮 → 「点击确认按钮时触发」,alertmodal @click.self 绑遮罩 → 「点击遮罩时触发」),98/98 全部具体化,不再有模板句;表头上方加出处图例。
  • 不做「可选值」列(有意):Element 那一列靠其运行时枚举,本仓库实测没有等价数据源 —— 从 5 端源码反推比较字面量只覆盖 12/235(5%) 且多为 1 / number 这类噪声,规格原文里 真正枚举取值的只有 2 条。硬填等于发明,违反契约 doNotInvent 口径;改为把规格里确实枚举了的 取值以「取值:主按钮 / 次按钮 / …」副行带出 —— 深度检测后又收紧了这道闸门:初版命中 4 条, 其中 card.title / modal.title 命中的是「结构:标题区、内容区、操作区」这类结构描述 (枚举的是卡片分区,不是 title 的取值),tag.color 还切出了 绿#F6FFED / #52C41A等) 碎片。 现要求「分条标签 === 该 prop 的说明」且片段不含 # / 括号 / px,最终只保留 button.type 1 条 (类型:主按钮、次按钮、文字按钮、链接按钮、危险按钮),其余留空。
  • 新增元素的对比度:.side-section(段标题)与 .api-src(出处标记)初版用 --kole-color-text-placeholder(#767676),在页面底色 #F5F7FA 上只有 4.23:1,达不到 AA 正文 4.5:1; 改用同族 .side-group 已在用的 --kole-color-text-secondary 后为 4.66:1(悬停行)/ 4.75:1(页面底), 暗色 5.65:1 / 7.12:1。深检另发现一处既有缺陷(暗色选中态文字 3.59:1)与两处测试侧问题 (verify-nav-responsive 红灯、对比度断言采到过渡中间帧),按仓库规矩记为 ROADMAP S6-P39 / P40 / P41, 未在本任务内顺手修。
  • i18n:新增英文词条 166 条(含上述 106 个属性释义、29 个事件说明与新增 UI 文案), tools/verify-i18n.mjs 的「literal T() coverage」从 289 键缺 1 到 289 键全覆盖。

验收:verify-i18n 16 项全过;verify-site-routes / run-site-smoke / verify-theme 全过; 数据层审计 9 项(含「cite 逐字出自规格原文」)、79 页浏览器巡检(零报错/零 4xx/说明列无空值)、 侧栏高亮不变量(8 路由 × 双语)、precompute 幂等与两次运行逐字节一致 —— 全过; 回归 100%(1017/1017)连跑 8 次一致,深检复跑 10 次仍 100%。 (verify-nav-responsive 当前红灯,原因是工作区里新增的 ≤420px 隐藏语言选择器与脚本固定 390px 的点击冲突, 见 ROADMAP S6-P40,非本改动引入。)

Docs site · 「在线测试」预览帧:修掉资源解析错误 + 沙箱收紧 + 三处丢改动缺陷

起因:站点已通过 frp + EdgeOne 暴露到公网(https://kole-ui.mymoyu.top/site/), 「在线测试」是全站唯一把用户编辑的 HTML 灌进 iframe 执行的地方,因此按不可信内容重新过一遍。

  • 预览帧的组件样式一直没加载(79 个组件里 36 个命中):srcdoc 的基准 URL 继承父页 (/site/playground.html),演示源码里的 href="./Xxx.css" 于是解析成 /site/Xxx.css —— 本地 404、线上 404(实测 https://kole-ui.mymoyu.top/site/AnchorNav.css → 404, 而 .../frameworks/AnchorNav.css → 200)。受影响的 36 个组件在预览里丢掉整个组件 CSS, 只剩内联 <style>。修法:渲染前在文档最前注入 <base href="../frameworks/">(放在 <!DOCTYPE> 之后,避免掉进怪异模式),让预览的资源解析与「演示原页」逐字一致; 注入的 base 是文档里第一个 base,用户代码里再写 base 也覆盖不了。
  • 帧内策略收紧(只写比父页更严的项):注入 meta CSP,把 connect-src / form-action / frame-src / object-src 一律置 'none' —— 帧内彻底发不出网络请求。两条 CSP 取交集, 所以这里每一项都只会收紧;父页 CSP 继续负责"允许什么"(style-src 'self' 等), 本页不重复声明,避免把 'self' 在不透明源下的解析差异带进来。
  • 沙箱边界用探针服务器实测,而不是读代码:新增 tools/verify-playground.mjs,脚本内起一个 本地 HTTP 探针,帧内发起的每个请求都会落在它身上。实测(Chromium,sandbox="allow-scripts", 无 allow-same-origin):location.origin === 'null';parent.document / top.document / document.cookie / localStorage 全部 SecurityError;window.opener 为 null; window.open 返回 null(缺 allow-popups);表单提交、子帧、外域样式/@import/图片 全部被拦;fetch / sendBeacon / WebSocket 被 CSP 拦下。探针 0 命中。 父页侧另有 nginx/dev-server 的 CSP + X-Frame-Options: SAMEORIGIN + Referrer-Policy: no-referrer (线上实测这些响应头经 EdgeOne 完整透传)。
  • 帧内报错不再静默:注入一段上报器(跑在用户代码之前)捕获 error / unhandledrejection / securitypolicyviolation,用 postMessage 回传,预览上方以 纯文本提示(.pg-note)。父页只认「event.source 严格等于本页预览帧」的消息, 且只取字符串渲染、每次渲染最多显示 3 条 —— 预览里的代码无法借此碰本页 DOM,也无法刷屏。
  • 三处会丢改动的缺陷:①切组件会静默丢弃未复位的编辑 → 现在先 confirm(), 取消则编辑器与选择器都留在原地;②源码拉取失败时旧实现会 pristine = ''; editor.value = '' 清空编辑器 → 现在失败一律不改状态(编辑器、预览、选择器全保持原样,只报错); ③刷新/关页同样丢改动 → 补 beforeunload(仅在"改过且未复位"时拦)。 另把防抖清理提前到 load() 开头(异步回落路径下,挂着的定时器会把上一个组件的内容渲染到新组件头上)。
  • 预览帧内自己跳走会让预览失效且不可恢复:<meta refresh> 或 location.href 会让帧离开 srcdoc(实测落到 chrome-error://chromewebdata/,状态行却仍显示"已同步")。父页读不到 帧去了哪(不透明源),唯一能感知的是 load:新增看门狗 —— 凡是不是本页触发的加载, 就地重建预览并标注原因(实测帧回到 about:srcdoc 后脚本从头跑一遍,预览恢复可用)。
  • 行为反转(原为「有意保留的差异」):预览帧现在跟随站点暗色。原实现之所以反不了色, 是"帧是不透明源 → 父页注入不进 kole-dark"这个机制限制,不是设计取向(S5-P23 已把 演示原页的取向定为「站点暗色时演示页也反色」)。在线测试页唯一可用的注入点是源码, 因此改在注入内容里带一个类;实测站点 kole-mode=dark 时帧内 documentElement.className 含 kole-dark、--kole-color-page-bg 解析为 #14161C。 另补 storage 监听:在文档站切主题,本页预览跟着重渲染。
  • 验收:npm run verify:playground → 38 条断言全过(含全 79 个组件逐个切一遍、36 个带 ./ 引用的组件 CSS 确实从 /frameworks/ 取到 200、探针服务器 0 命中、脏状态两条离开路径、 失败不改状态、帧内跳转重建、报错回传、暗色跟随、全程 0 个 4xx);已接入 regression.yml。 回归 100%(79/79 页、1017/1017 断言、N/A 34、0 超时)连跑 8 次一致; verify-site-routes 24/24、smoke:site 全过、verify:i18n 16/16。
  • 未执行:未部署。工作树领先线上 1229 个文件(site/data.json、site/playground.* 均与线上 哈希不同),按 AGENTS §九 走 pack-deploy 会把在飞的 S6 组件族改动一并发布 —— 这属于发布决策, 留给用户定;命令见 ROADMAP 新增条目。

Docs site · 文档站路由去掉 #(hash → History API)

  • URL 形态:/site/#/component/button/h5 → /site/component/button/h5,/site/#/overview → /site/overview。站内跳转改走 pushState 局部渲染(顶栏/侧栏/总览卡片/搜索/相关组件/上下篇统一收敛到 go() + 一处捕获的链接拦截),浏览器前进后退走 popstate。旧链接仍可用:加载时就地 replaceState 成无 # 地址且不留历史记录(实测 /site/#/component/modal → /site/component/modal 并正常渲染)。
  • 深层路径要服务器接住:磁盘上没有 /site/component/button/h5 这个文件。三处回落同时补上 —— nginx.conf 新增 location /site/ 回落到 try_files $uri $uri/ /site/index.html(另加一条正则 location,带扩展名的缺失资源仍回真 404,不会把 HTML 当 JS/CSS 发出去)、site/dev-server.js 新增 isSpaRoute、GitHub Pages 发布包多放一份 site/index.html 副本作 404.html(Pages 无重写规则,深链与刷新靠它接住)。
  • SPA 壳的路径基准:site/index.html 顶部内联脚本从 pathname 里第一段 /site/ 反推站点根,写 <base> 并暴露 window.KOLE_SITE_BASE;site/app.js 的 SITE_BASE 用同一条规则(tools/verify-site-routing.mjs 会静态卡这两处一致)。部署前缀因此可变(本地/nginx 是 /site/,Pages 是 /<repo>/site/),代价是站点目录必须继续叫 site。
  • 资源改绝对地址写出:<link> / <script> 不能再写静态相对路径 —— 预扫描器在脚本执行前就按深层 URL 预取,实测多出 2 个 404 + 2 条控制台报错,data.js(precompute 后 122 KB)还会被整份白取一次。改成先 document.write('<base …>') 再输出 base + 'xxx' 的绝对地址后,深链冷加载 10 个请求 / 0 个 4xx / 0 条控制台报错,且 <script> 仍是解析期同步按序执行,语义与静态标签一致。
  • 静态入口页跟着改:build-site.ps1 生成的 79 薄壳 + 316 平台壳,重定向目标改成 ../component/<slug> 与 ../../component/<slug>/<platform>(重跑 npm run build:site);tests/_template.html 的「← 文档站」链接改成 ../site/component/<slug>(重跑 run-tests.ps1,79 页);site/llms.txt 的页面链接同步去掉 #。
  • 验收:新增 tools/verify-site-routes.mjs(浏览器级,24 条断言全过,已接入 regression.yml)—— 深链渲染、URL 无 #、--kole-color-brand 令牌生效、冷加载 0 控制台报错 / 0 个 4xx、旧 # 就地改写、顶栏/侧栏/搜索跳转不整页刷新、框架切换写进 URL、前进后退、深链刷新、薄壳重定向、缺失的带扩展名资源回真 404、「在线测试」这类相对链接仍解析到站点根、file:// 降级(pushState 不可用时退回 hash 形态,实测仍能渲染);verify-site-routing 79 组件 / 316 平台壳 / 396 URL 全过(新增:两处 SITE_BASE 同规则、<base> 引导、nginx/dev-server/Pages 三处回落、薄壳无 # 残留);smoke:site、verify:nav、verify:i18n 16/16、verify-dev-server 20/20、pack-deploy 全过;回归 100%(79/79 页、1017/1017 断言、N/A 34、0 超时)连跑 8 次一致(同一状态另跑 54 次,见下条)。
  • 发现(与本改动无关,已记为 ROADMAP S6-P32):跨批次整轮连跑 62 次中有 2 次非 100%,捕获到的那次是 densityswitcher 的 matrix:contrast>=4.5 读到了颜色过渡中间态(button.kole-densw-opt "默认" 4.46:1 < 4.5:1)。实测两端点都达标(生效后 5.85、未生效 7.00),过渡途中会穿过 4.5 以下(7 → 1.79 → 2.4 → 4.58 → 5.85);tests/_runtime.js 的就绪轮询只看 innerHTML 是否稳定,而过渡期间 innerHTML 不变,拦不住。单页压测 300 次命中 2 次。旁证它不来自本次改动:测试页只改了一行「← 文档站」链接的 href,断言引擎对该链接零引用(grep -c 't-btn\|文档站\|t-nav' = 0),断言全部跑在未改动的 frameworks/<Prefix>.html 帧内。
  • 顺带修正:site/llms.txt「文档站页面」列表里还挂着 #/agents —— 该页早已随 AI 消费模块删除(路由与 i18n 词条都不存在),已删掉这行;AGENTS.md 铁律 2 里 data.js 的 1058 KB / 942 KB 是旧值,按 2026-09-20 实测改为 1166 KB / 122 KB。

Docs site · 代码与演示都整段展示(去掉两处内滚动)+ 演示帧暗色真正生效

  • 代码不再截断:.demo-code pre 原有 max-height: 420px,长源码要在约 21 行的窗口里滚(cascader 7742 字符)。去掉 max-height(Element 文档同样显式 max-height:none),整段随页面滚动;长行仍可横向滚动。实测 5 个组件代码块纵向滚动量全为 0。
  • 演示整段展示:.demo-stage iframe 固定 height: 420px,比它高的演示在帧内出滚动条(滚轮滚的是 iframe 而不是页面)。新增 autoSizeFrame():帧 load 后按 body.scrollHeight + margin(documentElement.scrollHeight 更大时取后者,否则短内容收缩不下去)写实际高度,配 ResizeObserver 跟随帧内异步渲染(加载态 / 展开行),换页时 releaseFrameFits() 摘掉观察器与 resize 监听;420px 降级为 CSS 兜底。实测帧高贴内容:button 571 / cascader 394 / table 413 / watermark 330 / expandabletable 311,帧内滚动量全为 0。
  • 代价:演示帧沙箱放宽到 allow-same-origin(sandbox 属性保留,继续挡表单提交 / 顶层跳转 / 弹窗)。理由:该帧加载的是一方文件 frameworks/<组件>.html,与文档站同信任级;用户可编辑的代码只在「在线测试」页里跑,那边仍是严格沙箱。而量不到 contentDocument 就做不了自适应高度。
  • 顺带修掉 S5-P23:正因为放宽了沙箱,injectIframeTheme() 不再于 if (!d) return 静默返回 —— 实测站点 kole-mode=dark 时帧内 documentElement.classList.contains('kole-dark') === true、帧 body 背景 rgb(20,22,28)。v1.1.1 声称的「演示 iframe 注入 kole-dark 同步反色」到现在才真正成立(在线测试页的预览帧保持浅色,是有意保留的差异)。
  • 验收:verify:i18n 16/16、smoke:site 全过、verify-site-routing 79 组件 / 316 薄壳 / 396 URL 全过、pack-deploy 断言全过;回归 100%(79/79 页,1017/1017 断言,N/A 34,0 超时)连跑 3 次一致;浏览器侧复测在线测试实时预览闭环(注入标记 → 帧内出现 → 复位消失)、首次展开填充(cascader 7742 / tree 5194 字符)、入口新标签与英文文案(Show code / Hide code / Playground →),0 报错。

Docs site · 侧栏「组件总览」降级为独立页面索引(不再兼作分节父项)

  • 现象:进入任意组件详情页,侧栏同时高亮两项 —— 「组件总览」与当前组件。两者样式逐属性相同(site/style.css 的 .side-link.active 228 行 / .side-item.active 264 行),并列两块蓝底,读起来就是「选了两个」。
  • 根因:site/app.js 的侧栏高亮规则写作 r === 'overview' || r === 'component' —— 让「组件总览」兼作整个组件区的分节父项。该规则出自 v1.2.0 初版提交(git log -S 溯源),非后期回归。
  • 改法:「组件总览」只代表自己那一页(active: r === 'overview'),与「快速开始 / 设计规范 / 常见问题」三条同级。顶栏「组件」保持分节语义不变 —— 顶栏没有逐组件入口,去掉后组件页将无任何顶栏高亮。
  • 语义层无变化:aria-current="page" 本就只加在真正的组件项上(renderSidebar 里给当前 slug 那一条),屏幕阅读器读到的始终是正确的一项,本次只修视觉层的重复高亮。
  • 实测(Chromium,本地 dev-server,逐路由探针):组件页侧栏高亮数 2 → 1;#/component/button|modal|table 侧栏均为 [组件名] 且「组件总览」不再命中;#/overview 仍为 [组件总览];#/design、#/guide、#/faq 各 1;#/changelog 为 0(无侧栏入口,维持原状)。
  • 登记缺口:tests/ 与 tools/ 中无任何断言涉及 side-link / side-item 的选中态,故此类回归在八次连跑中不可见 → 已追加为 ROADMAP S5-P25。
  • 验收:回归 100%(79/79 页,1017/1017 断言,N/A 34)连跑 8 次一致、0 超时。

Docs site · FAQ 问题搜索对齐全局组件搜索(Ctrl+K)

  • 起因:页面描述写着「支持按组件浏览与关键词过滤」,实际只有「输入 → 隐藏不匹配项」一条路径:没有命中高亮、没有键盘路径、没有范围限定,也搜不到「按钮」这种组件名之下的全部问题。
  • 对齐全局组件搜索(直接复用弹窗里的 hiMark() / fuzzySubseq() 与 .sc-chip 样式,交互同源):
    • 命中高亮:问题正文命中用 <mark> 标出片段;命中来自组件名时标记落在分组标题上。
    • 搜索范围扩到组件名 / slug:输入「按钮」会保留整个按钮组(实测 3/3 条全在)并高亮标题;qrcode 这类 slug 同样可搜。
    • 类别 chips 限定范围:全部 + 六大类,样式与搜索弹窗一致;实测切到「导航」范围收窄到 35 条 / 10 个组件,切回「全部」完整还原 244 条。
    • 键盘全路径:↑/↓ 在命中项间循环移动并平滑滚到视区中央、Enter 把焦点落到该问题、Esc 清空查询(空查询再按一次才退出焦点)、/ 一键聚焦搜索框(框内常驻 kbd 提示,输入后让位给自绘清空按钮)。
    • 模糊回退与空态:无精确命中且查询 ≥2 字符时回退子序列匹配,结果行标注「(模糊匹配)」;彻底无命中时显示空态并隐藏列表。
    • 状态记忆:查询与类别范围存 state.faqQ / state.faqCat,离开页面再回来仍在(实测往返后仍 11 条命中)。
  • 实现细节:/ 快捷键一次性绑定(renderFaq 每次进入该页都会重跑,直接在内部注册 document 监听会不断累积);隐藏原生 ::-webkit-search-cancel-button 改用自绘清空按钮,避免与 kbd 提示重叠;↑↓ 移动用共享的 visible[] + .hover 类,与弹窗同款焦点反馈。
  • i18n:新增 6 条(清空搜索 / 按 / 聚焦搜索 / 无匹配问题 / 无匹配问题(已尝试模糊匹配) / (模糊匹配) / ↑↓ 定位 · Enter 跳转 · Esc 清空),英文侧沿用「空格烘进词条值」的既有约定(如 条,),verify:i18n 261 键全覆盖。
  • 已知数据限制:FAQ 条目正文取自契约原文(中文,无英文译文),故英文界面下英文关键词只能命中组件名 / slug(实测 button 命中按钮组并高亮标题;中文关键词「宽度」在英文界面照样可用)。属数据层现状,本轮未改。
  • 验收:33 项浏览器断言(高亮 / 组件名与 slug / chips 范围 / 方向键移动与滚动 / Enter 焦点 / Esc 清空 / 模糊回退 / 空态 / / 快捷键 / 清空按钮 / 查询持久化 / 中英双语 6 条文案);smoke:site 30/30、verify:i18n 16/16、上一轮的 30 项站点断言(语言下拉 / 首页核心区 / FAQ 搜索框)全部仍过、verify:theme / verify-dark / verify-site-routing 全过、零运行时依赖不变;回归 100%(79/79 页,1017/1017 断言,N/A 34)连跑 8 次一致、0 超时。

Docs site · 试玩改为独立「在线测试」页 + 代码区控制条对齐 Element

  • 起因:组件详情页的「▶ 在线试玩」是内联 textarea —— 一枚胶囊按钮悬在演示区与代码区之间的白缝里,与页头「测试页 →」并排看像两个近义入口,归属和用途都含糊。
  • 新增「在线测试」独立页(site/playground.html + site/playground.js):控制条右侧常显「在线测试 →」,新标签打开 playground.html?slug=<slug> —— 左侧编辑 H5 源码、右侧 iframe srcdoc 实时预览(300ms 防抖),79 组件可切换、复位 / 复制源码 / ↗ 演示原页 / ← 文档站,Tab 缩进两格、Ctrl+S 立即同步,状态行回显「已同步 HH:MM:SS(已修改)· 已复位」。数据单请求取自同目录 data.json(sources.html 多数内联,缺省回落 files.html),零运行时依赖;暗色与文档站共用同一个 localStorage['kole-mode']。
  • 控制条改为 Element 同款:44px、居中「▼ 显示代码 / ▲ 隐藏代码」、文字悬停或键盘聚焦才浮现(.lbl opacity 0→1,:focus-visible 一并覆盖)、悬停底色 table-header-bg + 品牌色。整条不再可点:按钮管折叠、链接管跳转(此前整条 div 挂点击且无键盘路径)。
  • ⚠️ 反转既有决定:代码区默认收起(对齐 Element)。此前记过「默认展开:省掉一次点击」,本次按「以下拉条参考 Element」的要求改为收起 —— 页面因此可扫读,要读源码点一下,要动手改则走在线测试页。已专门验证没踩回历史坑:代码区改为首次展开才构建,实测全新加载 → 首次展开即有内容(cascader 7713 / tree 5159 字符,与当年验收数字一致),CSS tab 正常(button 2122 / cascader 3552 / tree 1067)。改回默认展开只需 var open = false → true。
  • 顺带修正「测试页 →」掉出标签行:该链接此前 append 到 .detail-head 而非 .chips,脱离 flex 行后只剩 .chip 浅色底,在页头与「何时使用」之间单独占一行;同类的「规格文件」「契约 JSON ✓」都在行内,已改挂到 .chips 末尾。
  • 删除内联试玩:play-btn 系按钮、.demo-playbar、.pg-textarea、currentHtml() 轮询一并移除;i18n.js 清掉 6 条只服务于它的键(✎ 在线试玩 / ● 试玩中 / 退出试玩 / 复位 / 展开代码 / 在线编辑 H5 演示源码…)与此前已无人引用的 试玩 / 仅 H5 形态支持在线试玩,新增「在线测试 / 显示代码 / 隐藏代码」。.play-btn 样式保留(app.js 错误态的「重试」按钮仍在用)。
  • 实测(Chromium 1440×900,本地 dev-server):预览帧内 document.querySelectorAll('.btn').length = 16、首按钮背景 rgb(47,84,235);源码尾部注入 <div id="probe-marker"> → 帧内出现、复位后消失;切到 table 后 URL / 标题 / 编辑器(6587 字符)/ 预览同步;控制条 44px、aria-expanded false→true、aria-controls=demo-code-button;kole-mode=dark 下页面与代码面同为 rgb(20,22,28);两页 0 控制台报错。
  • 验收:verify:i18n 16/16(T() 覆盖 258 键,独立复算 0 条未收录)、smoke:site 全过、verify-site-routing 79 组件 / 316 薄壳 / 396 URL 全过;回归 100%(79/79 页,1017/1017 断言,N/A 34,0 超时)连跑 3 次一致。
  • 登记缺陷(同日已修):sandbox="allow-scripts" 的演示帧是不透明源,父页 iframe.contentDocument 实测为 null → app.js 的 injectIframeTheme() 恒在 if (!d) return 静默返回,暗色模式下演示帧当时不会反色(ROADMAP Q6 原记为「设计取向待定」,实为机制从未生效)。已登记 S5-P23,并在同日的下一条改动(放宽演示帧沙箱以做自适应高度)中一并修复。

Docs site · 删除 AI 消费模块 + 首页核心组件改用总览同款卡片 + 修 FAQ 搜索框

  • 删除「AI 消费」(For Agents)模块:顶栏导航项、#/agents 路由、renderAgents 渲染(96 行)与顶栏 NAV_KEY 映射一并删除,并清掉随页面作废的 42 条 i18n 词条(先按「T('…') 字面量是否仍被引用」逐条判定,避免误删共享键如 ' 条,')。#/agents 现在回落到首页(实测),site/llms.txt 与 site/data.json 保留 —— 机器可读入口在文件层,不在文档站页面层。README 两处引用同步改写;AGENTS §5 的「For Agents 页承诺」改为「对外承诺(该页已移除)」,承诺本身不变。
  • 首页「核心组件」改为与组件总览同一套展示:抽出 buildCompCard() 与 observeThumbs() 供两处共用,首页核心区改用 .ov-grid / .ov-card(150px 在线预览 + 中文名 / 英文名),预览 iframe 同样按「进入视口 400px 内才挂载」懒加载。实测卡片宽 283px 与组件总览逐像素一致、缩略图高 150px、点击进详情正常。
    • 顺带修掉一个内容缺陷:该区块原先按 c.hasContract 过滤,而契约做到全量 79/79 之后这个条件恒为真 —— 标题写着「核心组件」,实际列了全部 79 个。改用 tier === 'core'(与组件详情页的「核心规范组件 / 扩展组件」同一口径),实测列出 10 个 = data.meta.core。
  • 修复常见问题页搜索框样式异常:输入框挂的 class 是 .search-input,而样式表里只有全局搜索弹窗的 #search-input(id 选择器),该 class 没有任何规则 —— 页面渲染出的是浏览器默认输入框。新增 .faq-search / .faq-search-input 令牌化样式(36px、左侧放大镜、聚焦环、::placeholder、计数行间距),暗色模式实测对比度 10.34;关键词过滤与计数(244 条 / 79 组件)行为不变。
  • 回归:100%(79/79 页,1017/1017 断言,N/A 34)。同日 16 次连跑出现 2 次既有签名 1016/1017(78/79 页全通过,无失败页面落盘)——与 ROADMAP S5-P17 记录同因;另写逐页归因诊断(读 #result-list .t-row 的 fail 项)连跑 14 轮 0 复现、无页面 fail>0,证据已补进 S5-P17。该偶发与本改动无关:测试页只加载 site/style.css,而本次改动涉及的选择器(topnav / lang-* / faq-search / ov-card / home-core-grid / core-card)在 tests/_template.html 中出现次数均为 0。
  • 验收:smoke:site 30/30、verify:i18n 16/16、verify:theme / verify-dark / verify-site-routing 全过、零运行时依赖不变;另 30 项浏览器断言覆盖三项改动(导航 6 项且无 AI 消费入口、#/agents 回落首页、首页核心 10 张卡与总览同宽同高、预览 iframe 真实加载、FAQ 过滤 / 计数 / 暗色对比度)。

Docs site · 快速开始新增「安装(npm 私有源)」+ 修复更新日志页首次进入卡加载

  • 快速开始页(#/guide)新增第一节「安装(npm 私有源)」:项目 .npmrc 一行配置(@root:registry=…)→ npm install @root/ui → 三端引入示例(Vue 3 / React / Vue 2),并显著提示「令牌必须先引」这一最常见接入坑(78/79 组件样式引用 var(--kole-*))。同时把原「引入设计令牌」与「按端使用组件」两节改写为「不用 npm 时」的对照路径;页内目录与中英双语同步(新增 9 条英文词条,verify-i18n 256 键全覆盖)。
  • 修复既有缺陷:更新日志页首次进入永远停在「加载中…」。renderChangelog 在懒加载分支里只赋值 window.__koleChangelogReady,但全站没有任何地方调用它——只有离开再回来(changelogCache 已就绪)才会渲染。改为走 listenChangelog() 注册回调(该函数已正确处理「已缓存则立即回调 / 未缓存则入队」)。线上实测:修复前首次进入 208 字符且一直「加载中」,修复后 14756 字符 / 10 个版本。
  • 验证:独立浏览器实例 11 项检查全过(首次进入渲染完成、npm 节排第一、7 个代码块、英文模式生效、7 条主路由 0 报错);回归 100%(79/79 页,1017/1017 断言,N/A 34);文档站冒烟通过。

Docs site · 顶栏窄屏折叠为汉堡 + 导航抽屉(S5-P20)

  • 问题(实测):顶栏没有任何窄屏规则。中文 1280px 起 7 条链接全部折行(height:100% + 无 white-space: nowrap,中文按字换行成竖排)、1100px 起文字顶出 60px 顶栏、960px 起顶栏溢出、768px 起最右链接不可达、480px 起 7 条全部在视口外且无滚动条(docOverflow: 0,即不可达而非可滚动);英文更早——1366px 起溢出,1200px 起最右链接已不可达。附带缺陷:英文在 1600px 就折成 2 行,因为 .topbar-inner 上限 1440px,与视口多宽无关。
  • 修复:≤1366px 折叠为汉堡 + 右侧抽屉(.topnav 就地变成抽屉,不复制 DOM,避免 i18n 文案与 active 态两处维护);基础层加 white-space: nowrap;收紧规则(logo 副标、顶栏间距、链接近距、搜索框上限)改为无条件而非挂在断点上——英文 7 条链接 + 可读搜索框在 1440px 上限内始终排不下,挂断点解决不了。60px 顶栏高度未改,故 5 处硬编码引用(.body-wrap / .sidebar / .toc / html 的 scroll-padding-top)连带影响为零。
  • 验收中修掉两个只有交互测试能抓到的缺陷:① 抽屉可见但点不到——.topbar 的 z-index:100 形成层叠上下文,抽屉的 120 只在顶栏内部生效,整条顶栏被外部遮罩 110 压住;矩形与可见性断言全部通过,只有真实点击暴露 intercepts pointer events。修法:遮罩移入 .topbar,与抽屉同处一个上下文(仍低于 .fab-stack 150 / .modal-mask 200)。② 焦点进不了抽屉——visibility 参与 transition,类切换后首帧仍是 hidden,focus() 静默失败(键盘用户完全进不去);改为「打开时 visibility 0s、关闭时延迟 0.22s」,并把焦点回收从 contains() 判断改成显式标志(元素被隐藏时 activeElement 会变成 body,contains() 判不出来)。
  • 新增守门人:tools/verify-nav-responsive.mjs + npm run verify:nav(18 宽度 × 中英双语 + 抽屉交互,346 断言,约 35 秒),已接入 regression.yml(步骤 15),并补装 fonts-noto-cjk——宽度断言依赖字体度量,缺 CJK 字体时中文退化成豆腐块/拉丁回退会导致假失败。脚本每次运行打印字体度量基准与字体容忍度(在最窄内联宽度 1367px 二分测出文字宽度还能再增多少仍不折行:实测 17.5%,该处余量 94px;同次实测现实字体跨度 Arial/Segoe UI 0.918×、DejaVu/Liberation 1.000×、Verdana 1.058×,最宽者也远在容忍度内 —— 故 CI(ubuntu)与开发机(Windows)的字体差异不会让断言假失败;容忍度低于 5% 时额外打印告警)。服务未起时报 exit 2(同 run-regression.mjs 口径),不退化成一串断言失败。断言按 DOM 里的链接条数取值(不写死 7),故后续增删导航项不会误报。
  • 部署改为被测试 gate:deploy-pages.yml 的触发器从 push 换成 workflow_run(等 main 上的 Regression 完成)并加 if: conclusion == 'success' 守卫 —— 测试不过就不部署。用 workflow_run 而非把 Regression 拆成可复用工作流,是为了不让同一套测试在每次推 main 时跑两遍;workflow_dispatch 保留为有意的手动逃生口。checkout 显式取 workflow_run.head_sha(workflow_run 的 github.sha 指向默认分支头,不取会部署错提交)。
  • 顺带修掉一处证据链缺口:首页通过率卡片读 tests/report.json,而部署原先 cp 的是入库的那份——等于页面显示「提交里的数字」而不是「刚验过的数字」。现改为下载本次 Regression 的 regression-report 产物并用其中的 report.json(新增 actions: read 权限),取不到才回退到提交版并发 ::warning::,回退路径保证部署不会因产物过期而变脆。
  • 清理一条死规则:≤900px 里「链接近距收到 8px」的补丁在抽屉方案下已无任何生效宽度(实测 900px 下 .topnav a 计算值为 12px 20px),已移除并留注释说明。
  • 验收:npm run verify:nav → OK — all checks passed(346 断言 / 0 FAIL);改动前后逐宽度对比见 ROADMAP「S5-P20 实测数据」;回归 100%(79/79 页,1017/1017 断言,N/A 34)连跑 8 次一致、0 超时;smoke:site 全通过;零运行时依赖不变。

Design system · 组件族参数化:79 个并列组件 → 48 个概念组件(S6-P21)

  • 问题:79 个并列组件里有 44 个是同源变体,却各自手写了一遍。导航最典型——topmenu / sidemenu / mixednavigation 三份实现,差异只是"一级菜单横排还是竖排";规范契约自己就写着从属关系:alertmodal 与 confirmmodal 的 doNotInvent 原文是「弹窗尺寸档位(见 Modal 契约)」,steps 与 steplist 的 semanticTypeCandidates 完全相同(均为 steps|wizard)。并列表达让消费方看到 6 个表格组件,而它们实际是「一个 Table + 一个 feature 参数」。
  • 新增族层(纯追加,不破坏任何既有承诺):新增 .design_library/kole-ui/families.json;data.json 增顶层 families 与每组件 family / familyRole / familyParams;site/details/<slug>.json 同步三元组。13 族 / 44 成员 / 35 个独立组件;data.json 仍完整输出 79 个组件,slug 集合逐一不变(铁律 5)。
  • 归族判据可核对,不按名字猜:每族在 tools/lib/family-model.mjs 里必写 mergeBasis,依据是契约中四类可核对字段——semanticTypeCandidates 重叠、anatomy 为同一骨架的子集、变体维度同构、doNotInvent 的显式从属声明。
  • 实现层合并(导航族端到端切片):tools/gen-family-impl.mjs 从 tools/lib/family-impl/nav-menu/ 的 5 端模板生成 TopMenu / SideMenu / MixedNavigation 共 15 个文件,参数为 direction=top|side|mixed。三份 CSS 的 md5 完全相同——一份样式表服务三个组件;改模板 + 重跑即三端同步,不再存在"改了 topmenu 忘了 sidemenu"。
  • 为什么是「生成」而不是「抽共享模块」:tools/pack-deploy.mjs(薄壳 79 / 实现 395)、tools/precompute.mjs(79 / 395)、tools/verify-cross-platform.mjs、tools/verify-package-import.mjs 四处硬断言文件数与导出数。抽跨文件 import 会同时打破它们,并失去"单文件可拷贝"。生成把重复消除在源头,而不改动文件图。
  • 生成器护栏:目标文件有未提交改动、且不含生成物标记时拒绝覆盖(除非 --force)——防止把工作区里没提交的手工调整冲掉。
  • 跨端口径(两个数必须分开说,免得把自己的改动说大成整体改善):已提交 HEAD 为 identical 2 / differing 77 / high 44;本任务改动前的工作区已是 79/79(既有未提交改动先清了跨端漂移);本任务改造后仍为 identical 79 / differing 0,与工作区持平。中途曾掉到 76/79:族模板最初把方向写成对象字面量 { direction: 'side' },Vue 端 class 提取器会把其中的字符串值收作变体记号、H5/JSX 端不会。探针实验确认成因后改用独立常量 FAMILY_DIRECTION 承载方向,四端回到 79/79——是改代码对齐既有约定,未放宽校验脚本。提取器本身的不对称仍未修,已登记 ROADMAP S6-P22。
  • 顺带修掉一处既有 RTL 不一致:MixedNavigation.css 原文件同时写 border-inline-start 与 border-left-color(逻辑属性与物理属性混用,RTL 下两侧指示条表现不一致);族模板统一为逻辑属性。
  • 验收:族层 node tools/verify-families.mjs → OK: 族层端到端一致(13 族 / 44 成员 / 79 组件不变 / 395 文件不变),退出码 0;node tools/gen-family-impl.mjs --only=nav-menu 幂等(重跑 0 写入);回归 100%(79/79 页,1017/1017 断言,N/A 34)连跑 8 次一致、0 超时;零运行时依赖不变(dependencies 为空)。

Package · 发布到私有 npm 源(可直接 npm install)

  • 发布位置:自建 Gitea 的 npm registry https://gitea.mymoyu.top/api/packages/root/npm/(Gitea 27.3.1),匿名可读——实测无凭据 npm view / npm install 均成功。

  • 已发布 3 个可互换的包名(内容一致:三端入口各 79 组件 + 令牌 + 组件样式):

    包名 用途
    @root/ui 推荐:scoped 名,项目 .npmrc 写一行 @root:registry=… 即可,其余依赖仍走公共源
    chunyu-ui 非 scoped 别名,需 --registry= 显式指定源
    aurora-admin-design 仓库原名,同上

    ⚠️ 本表是 v1.4.x 当时的发布事实,其中的 aurora-admin-design 与导出名 AaButton / AaTag 是当时线上真实存在的东西,不改写成新名(改了就不是事实了)。改名后的对照与现状见 [2.0.0] 段的「发布现状」。

  • 踩到的坑(已写进 README):非 scoped 包不能用 @包名:registry= 写法——该语法只对 scoped 名生效,实测报 404。故推荐 scoped 名 + 一行 .npmrc。

  • 端到端验证:建 Vite + Vue 3 工程,.npmrc 一行配置 + npm install @root/ui(公共依赖同时走公共源)→ vite build 通过(169 模块)→ 浏览器实测:AaButton 渲染、品牌色 rgb(47, 84, 235) 生效、AaTag 正常、点击计数交互正常、0 JS 报错。

  • 未发布到公共 npm:本机无 npm 凭据(npm whoami → ENEEDAUTH,无 ~/.npmrc、无 token 环境变量),npm publish 到 registry.npmjs.org 被拒。公共 npm 上 chunyu-ui / aurora-admin-design 均未被占用(可用),是否发布待定。

  • README 增补「从私有 npm 源安装」段(含正确的 .npmrc 写法与三端 import 示例)。

Docs site · 导航语言选择改为下拉(S5-P19)

  • 问题:顶栏语言控件是「中 / EN」双段按钮——11px 圆角、28px 高、靠 2px 字号差和品牌色表示当前语言。两个语言标签同时高亮显示,当前语言靠粗细区分,一是看不出「点了会怎样」(无展开暗示),二是与旁边 34px 的框架选择器、搜索框不同高,三是纯鼠标控件:没有 aria-haspopup、没有键盘路径。
  • 改为下拉选择:触发器 = 地球图标 + 当前语言名(简体中文 / English)+ 箭头,34px 高与相邻控件齐平,展开时箭头旋转 180°、边框转品牌色并带聚焦环;菜单 186px 卡片,含「界面语言」标题分隔线、语言名 + ZH/EN 角标 + 选中对勾,8px 顶栏令牌阴影。
  • 交互与无障碍:role="listbox" + aria-selected + aria-expanded;点击展开/收起、点击外部关闭、Esc 关闭并回焦触发器、↑/↓ 循环移动、Home/End 跳首尾、Enter/Space 选中、Tab 关闭且不抢焦点;选中后触发器重新获得焦点。语言名始终以该语言自身书写(简体中文 / English),不随界面语言翻译。
  • 令牌与暗色:颜色/圆角/阴影全部走 --kole-* 令牌,未新增任何硬编码色值;暗色模式实测菜单底色 rgb(28,31,38),选中项对比度 4.57、菜单标题 6.50、触发器 4.57(均 ≥ 4.5)。prefers-reduced-motion: reduce 下关闭菜单动画与箭头过渡。
  • 窄屏:≤1100px 收起语言名(触发器 56px,与旧控件同宽)。实测改动前顶栏在 1024px 溢出 13px、900px 溢出 9px(旧控件同样外露),现 ≥860px 全部为 0;≤820px 的溢出与语言控件无关,已登记为 ROADMAP S5-P20。
  • i18n:新增 界面语言 / 选择语言 两条,移除随之作废的 切换到简体中文 / 切换到英语(原按钮的 aria-label),一进一出净增 0 条。
  • 验收适配(验收命令本身随控件形态更新,判据强度不变):tools/verify-i18n.mjs 的两条静态检查改指新 id/绑定,并新增「旧控件不得残留」检查;tools/run-site-smoke.mjs 的点击路径改为「开菜单 → 选项」,并补 8 条下拉行为断言(aria-expanded、Esc、方向键、焦点回位、选中态、触发器文案)。
  • 回归 100%(79/79 页,1017/1017 断言,N/A 34),连跑 8 次一致;smoke:site 30/30;verify:i18n 16/16;verify:theme、verify-dark、verify-site-routing 全过;零运行时依赖不变。

Package · 三端可 import(组件库真正可用)

  • 问题:dist/ 只发 CSS 与演示 HTML,package.json 的 main 甚至指向一个 CSS 文件,没有任何可 import 的组件——import { KoleButton } from 'kole-ui/vue3' 这类标准用法不成立。S1-P2 的任务范围写的是「能拿到令牌 + 组件样式」,因此这是范围缺口而非实现错误(已按 AGENTS 第五节登记为 ROADMAP S5-P18)。
  • 新增三端聚合入口:dist/react/index.js、dist/vue3/index.js、dist/vue2/index.js(各导出 79 个 Kole* 组件)+ 单组件源码。组件以 .vue / .jsx 源码发布,由宿主构建链编译(无额外编译产物与源码不同步的风险,且保持零构建依赖)。
  • package.json:补 exports 映射(. / ./tokens.css / ./components/* / ./react / ./vue3 / ./vue2 / ./manifest.json)与 peerDependencies(react >=17、vue >=2.6,均为 optional)。
  • 修掉两个「组件无法编译」的真实缺陷(此前从未被发现,因为从未真编译过):
    • RangeQuickPicker 的 presetRange 给 const start / const end 重新赋值 → React 与 Vue 3 两端都无法编译;已改为 let 并与 Vue 2 参照实现对齐(start 改为 new Date(...) 而非 setMonth/setDate 就地修改,行为一致)。
    • CodeInput.vue3.vue 内 function emit() 遮蔽了 const emit = defineEmits(...) → 重复声明,编译失败;已重命名为 emitChange()。
  • 样式随包发布:56 个组件的 Vue 两端用 <style src="./<Prefix>.css"> 引用外部样式、79 个 JSX 用 import './<Prefix>.css'。打包时把同名 CSS 一并放入 dist/react|vue3|vue2/,否则会出现「import 成功但样式全丢」。断链检查已纳入验证脚本。
  • 新增 tools/verify-package-import.mjs:结构级(入口/断链/exports/零依赖,15 项,零依赖可跑)+ 编译级(esbuild + @vue/compiler-sfc 真编译 79 个 SFC、vue/react SSR 真渲染 KoleButton 断言 DOM,5 项)。编译级依赖可用 KOLE_VERIFY_DEPS_DIR 指向隔离目录,避免污染仓库 node_modules。
  • 端到端验证(真实工程,非模拟):分别建 Vite + Vue 3 与 Vite + React 工程,以 file: 依赖真实 npm install 本包,只写 README 里的那几行 import → vite build 通过(Vue 170 模块 / React 189 模块),浏览器实测:组件真渲染、品牌色 rgb(47, 84, 235) 生效(证明令牌与样式链正确)、loading 态 disabled 与 spinner 正确、点击交互正常、0 JS 报错。
  • 回归 100%(79/79 页,1017/1017 断言,N/A 34);S1-P2 原始验收命令(tokens/aggregate/79+index/zero-dep/css usable/pack contents)全部仍通过。

Docs site · 组件详情页代码块默认展开(含修复异步填充漏填)

  • 组件详情页源码区改为默认展开:demo-strip 初始态由折叠改为展开,进页面即可看到当前框架源码,省掉一次点击;展开条箭头与提示文案随状态同步(▲ 收起代码 / ▼ 展开代码)。
  • 修复既有缺陷(默认展开后被放大):源码异步加载后的填充回调签名错位——listenSrc(slug + '/' + kind, fillCode) 直接传函数,而 notifySrc 的回调签名是 (text, error),于是源码文本被当成 kind 与 'html' 比对,永远不相等,首次展开的代码区一片空白(实测全新加载展开后字符数 0,离开组件再回来才有内容)。已改为闭包绑定 kind;并新增 codeWrap.__fillCurrent(),在代码区插入 DOM 后补填一次(命中内存缓存时源码是同步取得的,插入前填充会被 isConnected 守卫跳过)。
  • 浏览器实测(本地 dev-server):首次进详情页即展开且有内容(cascader 7713 字符)、切到未访问组件自动填充(tree 5159 字符)、切 CSS tab 正常(1067 字符)、折叠再展开内容保留、0 JS 报错。
  • 回归 100%(79/79 页,1017/1017 断言,N/A 34),文档站冒烟 ×2 全过。注:当日连跑 27 次中 2 次出现 1016/1017 的偶发失败,tests/*.html 不加载 site/app.js(grep 计数 0),与本改动无关;因 tests/report.json 不记录是哪条断言失败,已立任务包 S5-P17 追踪可追溯性。
  • 顺带修掉「部署了但浏览器还在跑旧版」:nginx.conf 之前没有任何 Cache-Control,浏览器对 app.js 走启发式缓存——实测重新部署后页面仍执行旧 app.js(同一页面内 fetch 能取到新版、<script src="app.js"> 却用缓存,duration=0)。已在 server 级统一加 add_header Cache-Control "no-cache" always;:每次带 If-None-Match 重新校验,未变更返回 304(实测 app.js 带 ETag 请求 → 304),开销极小但部署立即生效。

Security · 生产部署链审计修复(2026-09-19)

  • 规范原文泄漏(根因):.dockerignore 里 *.md / *.ps1 / *.yml / *.png 等 glob 在 Docker 下只匹配构建上下文根目录,嵌套路径全部失效(真实构建实证:sub/nested.md 仍进镜像)。改为 **/ 前缀并补齐嵌套 glob;.design_library/kole-ui/{specs,agent-reports,preview,ui_kits} 与嵌套 *.md 实测不再进入镜像(修复前线上 GET /.design_library/kole-ui/specs/组件1.txt → 200 / 8623B)。
  • nginx.conf 加固:补 absolute_redirect off;(根路径 302 曾丢失宿主端口 :3311 落到无服务的 :80)、server_tokens off;、与 site/dev-server.js 逐字一致的 CSP 及 X-Content-Type-Options / Referrer-Policy / Permissions-Policy / X-Frame-Options;/healthz 改用 default_type 修掉重复 Content-Type。
  • Dockerfile:补 COPY sitemap.xml(修复前生产 /sitemap.xml → 404)。
  • site/dev-server.js:修复单个 GET /site/%00 触发 ERR_INVALID_ARG_VALUE 未捕获异常打挂进程的问题——新增编码形态与解码后 NUL 双重拦截、fs.readFile try/catch;白名单、安全头、302/404 行为保持(92 条合法路径 status / content-type / 字节级一致)。新增 KOLE_PORT 开关(默认仍 3311)供验证脚本隔离端口。
  • 消除动态求值 sink:site/app.js 与 tools/precompute.mjs 原先把 defineEmits([...]) 字面量交给函数构造器求值(实测 defineEmits([1,globalThis.__pwned='x']) 会真的执行;构建期同源 → 可打穿 CI)。改为只解析字符串字面量的 parseStringLiteralArray(构建期实现独立成 tools/lib/parse-string-literal-array.mjs),非字面量元素整体拒绝返回 null。等价性:158 个 frameworks/*.vue 双实现抽取结果不一致 0(54 处字面量 / 96 条事件名)。
  • 新增验证脚本 tools/verify-dev-server.mjs(20 checks,含 3 条修复前必失败的反例断言)与 tools/verify-emits-parse.mjs(17 checks,含构建期副本漂移门)。
  • ⚠️ 规划修正:PLAN.md §8「不改 site/dev-server.js(已工作良好)」的立论已被实测推翻,按 AGENTS.md 第五节「以实测为准」处理并在此标注。
  • 回归:100%(79/79 页,1017/1017 断言,N/A 34),连跑 9 次一致,0 超时;主 agent 另独立复跑 1 次亦 100%。

Deploy · 线上部署(2026-09-19)

  • 新增 tools/pack-deploy.mjs:以 .dockerignore 为唯一真源打包部署目录(实现 Docker 的匹配语义,含「*.md 只匹配根目录」这一实测结论),带硬断言(规范原文/agent-reports/preview/ui_kits 绝不出现;站点运行必需文件必须出现;薄壳 79、实现文件 395)。部署配置文件(docker-compose.yml 等)始终保留——.dockerignore 只管镜像构建上下文。
  • 按 AGENTS §九 流程首次实际部署到 192.168.5.7:备份 → 解到暂存目录核对 → 替换 → docker compose build && up -d(回滚目录 /opt/kole-ui.pre-audit-20260919-0609)。
  • 部署后验收:specs/组件1.txt、agent-reports/*、嵌套 SKILL.md/README.md → 404;sitemap.xml → 200;tests/report.json → 200(首页通过率角标恢复数据源);根路径 302 → Location: /site/(相对,不再丢端口);Server: nginx 无版本号;CSP 等 5 条安全头齐备且 /healthz 只 1 条 Content-Type;396/396 条 sitemap URL 全部 200;容器 healthy。
  • 顺带消除历史漂移:线上组件文件由 09-06 快照更新为当前工作树(此前后者与线上有 288 个文件不一致)。
  • 决策:暂不对外公用 —— 保持 127.0.0.1:3311 回环访问(需 SSH 隧道),不加反代/域名/认证;容器运行期加固与对外承诺口径统一另立任务包(ROADMAP S5-P14/P15/P16)。

Theme modes · 日间 / 夜间 / 自动

  • 文档站主题选择扩展为 light / dark / auto 三态;自动模式跟随 prefers-color-scheme 并监听系统主题变化。
  • 新增可访问的主题模式菜单、跨标签页 kole-mode 同步和 iframe 主题同步。
  • ThemeSwitcher H5 / React / Vue 2 / Vue 3 统一 auto 模式枚举与 ARIA 语义。

Fixed — 文档站中英切换完整性

  • 修复语言切换后相关组件、主题面板、搜索分类与详情目录仍显示初始语言的问题。
  • 补齐加载态、重试、契约详情等动态文案的英文词典覆盖,并为顶栏切换器补充无障碍名称与状态。
  • 新增 tools/verify-i18n.mjs 静态校验与 tools/run-site-smoke.mjs 浏览器冒烟测试。

S3-P9 · 契约缺口解释层

  • 为 Card 契约的 doNotInvent / unknowns 增加结构化解释:分别说明设计边界、开放问题、出现原因与待确认决策。
  • 组件详情页明确区分“不要自行发明(设计边界)”与“规范未明示(待确认)”,不把现有实现值冒充正式规范。
  • 保持 hover 行为与卡片网格间距待定,未擅自写入 16px/24px 或固定状态规则。

S2-P7 · 行为断言(6 试点全绿)

  • 新增 tests/_behaviors.js:8 动词(click-toggles-class/click-adds-node/click-removes-node/click-sets-attr/input-clears/input-filters/keyboard-activates/tab-switches)+ @input 相对定位 + @doc 全文档查询 + 同步 pump + page-load 幂等缓存;_runtime.js 聚合 + 重载清缓存;_template.html 引入;6 演示页 data-behavior 标注;79 测试页重生成。
  • 全量回归:100%(79/79 页,1009/1009 断言,N/A 35)。关键修复:runner 兜底重跑导致行为断言第二轮误报,加缓存解决。

S3-P8 · RTL 支持(28 文件迁移)

  • 新增 tools/migrate-rtl.mjs(白名单 dry-run/--write 双模式):margin/padding/border-inline + text-align start/end;剩余物理属性 0(排除例外);逻辑属性文件 19;三代表页 RTL 零溢出零错误。
  • 人工例外 14 处:margin-left:auto(3)、拼接边框(5)、left:0+right:0 并存(4)——不机械替换。

S2-P9 · FAQ 页(details 懒加载版)

  • 新增 #/faq 页:自动聚合 79 组件契约的 unknowns(139)+ doNotInvent(101),共 240 条;按组件分组 + 关键词搜索过滤 + 命中统计;顶栏/侧边栏双入口;9 条 i18n 英文。
  • 浏览器实测:groups 80/items 240,搜索“宽度”命中 11 条/11 组,清空恢复 240,0 JS 错误。
  • 规划偏差:契约已在 P4 阶段 D 移出 data.js,FAQ 改走 details/*.json 批量懒加载(每批 10 个)而非直接消费 data.js。

S4-P12 · 版本发布流程

  • 新增 tools/release.mjs:检查模式(package.json vs CHANGELOG 版本一致性 + Unreleased 提醒)与 --bump major|minor|patch --date 提升模式;只做本地准备,tag/push 由人执行。
  • CONTRIBUTING.md 新增发布流程 5 步 + 版本号规则(major/minor/patch 判定)。

S2-P6 · 跨端一致性自动验证(方案 B:静态结构比对)

  • 新增 tools/verify-cross-platform.mjs(零依赖零联网):79 组件 × 4 端(H5/React/Vue2/Vue3)class 集合 + 结构骨架双 diff,演示包装类/变量名/模板残留降噪,high/medium/low 分级;产出 tests/cross-platform-report.json(79 条全量 + samples 3)。
  • 实测:完全一致 2,有差异 77(high 44/medium 22/low 11)。high 主因:React 端 is-disabled/is-active 缺失、H5 演示页缺框架端结构类、Tag/Select/Input 变体类缺失——已追加为 ROADMAP 的 S2-P6-F1~F4,不在本任务内修。
  • 回归零影响:tests/report.json 79/79、site/data.json 79 组件均未动(脚本只读消费)。

S2-P5 · 暗色模式真正实现(选型 A:演示页随站点同步反色)

  • 令牌文件新增 html.kole-dark 组(31 个 --kole-,≥15 达标):背景三层递进、文字四层、品牌/语义色向白提亮;10 项文字对比度全部 ≥4.5:1(脚本实测)。
  • site/style.css 暗色块精简为结构样式(令牌值收归令牌文件,删旧内嵌值与“演示页保持浅色”规则);site/app.js 删死代码 DARK_TOKENS,injectIframeTheme 同步 kole-dark 类到演示 iframe。
  • 附带收敛:演示壳裸类 .kole-page/.kole-h2/.kole-desc(26 页用而无定义)在令牌文件补令牌定义;table.html loading-mask、Tag.css 红/橙标签加暗色覆盖。
  • 新增 tools/verify-dark.mjs 独立验证(32 断言:令牌组 2 + 对比度 10 + 10 页浏览器实测 20),不进 _runtime 计数。
  • 首屏预算 292KB(< 300KB);回归 1003/1003(pass 1003/fail 0/skip 35)零影响。

S1-P4 · data.js 瘦身(已完成 c65a69c)

  • data.js 991KB → 98KB(预计算 API/场景 + 源码分离到 site/sources 395 文件),data.json 保持完整(含 5 端 sources)。
  • 首屏资源合计 291KB(< 300KB 预算,S1-P4b 验收已达标,无需拆分 app.js)。
  • 回归 1003/1003 全绿(79 页全过,N/A 35)。
  • ROADMAP 状态:P4 已完成,P5(暗色模式)为下一版本首选。

文档站 · 版本选择(历史版本文档站可切换)

  • 背景:Element UI / Element Plus 文档站只有静态版本角标、没有切换器;MUI、Vuetify、Ant Design 用「每版一份完整站点快照 + 顶栏下拉/子站」实现切换。本仓库原先只有组件级版本角标,缺的是文档站级切换。
  • 入口:顶栏 vX.Y.Z 角标改为可点下拉(桌面,复用语言选择器的键盘/ARIA 交互,不新增顶栏宽度); ≤900px 角标收起后由顶栏原生 <select> 接管;≤560px 两者都让位,更新日志页保留一排版本链接。 清单只有一版时角标退回纯展示 —— 不摆「看着能切却切不动」的状态。
  • 清单:新增 site/versions.json(+ 仓库根同名副本,供部署前缀下的 URL 使用),由 tools/precompute.mjs 阶段E 生成:根站点永远是本次构建的版本(path ..,首位), 归档快照按版本号降序,只有磁盘上真存在快照的版本才入清单(没归档的不列,避免点进去 404)。
  • 归档:新增 tools/snapshot-site.mjs(npm run snapshot:site -- <x.y.z>):把当前构建复制到 /<x.y.z>/site/(含 frameworks 与 .design_library,排除 specs/agent-reports),并刷新清单。 快照目录落在仓库根:站点根由 pathname 里第一段 /site/ 反推,所以 URL 必须是 /<x.y.z>/site/…。 当前版本继续留在 /site/(旧链接零破坏)。历史源码不在仓库里(无 git tag),旧版本无法凭空重建。
  • 切换语义:保留当前路由(/site/component/button/h5 → /1.4.1/site/component/button/h5), 目标版本缺该页时由它自己的路由回落接管;不写 localStorage(URL 即真相)。
  • 清单只认部署根那份(<prefix>/versions.json,每次发版重写),站点根那份仅作兜底; 清单里的 path 一律按部署根解析,判定「当前版本」用 location.pathname 上的最长命中前缀。 这两个坑都实测踩到过:① 快照里残留一份归档当时的旧清单 → 菜单被压成单版本、角标不可点; ② 先把部署前缀剥掉再比 → 快照页与根站点路径撞车(都成 /site/…),根站点条目抢走「当前」。 两种都表现为「切到旧版后回不到最新版」。快照不再自带 versions.json(snapshot-site.mjs 已排除)。
  • 服务器:nginx.conf 补版本化深链回落(/([0-9]+\.[0-9]+\.[0-9]+)/site/ → 该版壳)与 versions.json 的 no-store(location 内 add_header 会覆盖继承,安全头一并补全); /<x.y.z>/versions.json 也由根那份应答(否则会被裸入口规则重定向成 HTML 壳); site/dev-server.js 放行版本目录、同样回落并转发清单;Dockerfile + tools/pack-deploy.mjs 把快照与根清单随包发布(并断言快照不含过期清单)。
  • 当前状态(开发期):仓库只归档了当前版本,清单里只有它一条 —— 角标退化为纯展示、 菜单与窄屏 select 都不出现,不摆「看着能切却切不动」的控件。以后每发一版跑一次 npm run snapshot:site -- <x.y.z> 归档,切换器自动生效(清单由磁盘上的快照目录推导)。
  • 验收:node tools/verify-versions.mjs 33 项、node tools/verify-site-routing.mjs、 node tools/verify-i18n.mjs 16 项全过;REG_BASE=… node tools/verify-site-routes.mjs 真浏览器覆盖 单版本降级(角标不可交互 / 菜单与 select 都不出现);多版本形态另用演练快照实测过 「角标可交互 / 菜单列出全部版本 / 切换保留路由 / 快照内站点根反推正确 / 快照页菜单仍可交互且当前版本标在自己身上 / 从快照切回最新版 / 全程 0 报错 0 4xx」;回归 100%(1026/1026,八次连跑一致)。零运行时依赖不变。

[1.0.0] - 2026-09-20

首个对外版本(版本号重新起算)

本仓库此前的 1.1.0 ~ 2.0.0 段记录的是开发期里程碑,不是对外发布版本。 组件库尚未对外发布,当前把版本号重新起算为 1.0.0 作为第一个对外版本; 下方历史段按原样保留(记录当时的开发过程,不追溯改写),但不再是「最新版本」。

  • 文档站版本选择:版本入口分三档,覆盖全部宽度 —— 桌面顶栏 vX.Y.Z 下拉(复用语言选择器的键盘/ARIA 交互,不新增顶栏宽度); ≤900px 顶栏原生 <select> 接管;≤560px 顶栏放不下(实测溢出 23px),改到导航抽屉里一行版本 select。 三处共用同一份选项,切换都保留当前路由。 清单见 site/versions.json,由 tools/precompute.mjs 从「构建版本 + 磁盘上的归档快照」生成, 没归档的版本不列;归档用 npm run snapshot:site -- <x.y.z>,之后切换器自动生效。 清单里没有可用版本时才退回不可点的纯角标(未构建/未部署),有版本(哪怕只有一版)就是正常下拉。
  • 零运行时依赖:dependencies 为空,站点与组件全部原生实现。
  • 交付形态:79 组件 × 5 端实现(395 文件)+ 79 份契约 + 75 设计令牌 + 文档站(中英双语、暗色模式)。

Added(首版内容,原 2026-09-06 的 1.0.0 段并入此处)

  • 79 个组件实现(H5 / React / Vue 2 / Vue 3 四端)
  • 设计令牌:colors_and_type.css / css.json / components.css
  • 6 个核心组件契约 JSON
  • components/index.json 全量组件索引(spec 批次映射)
  • site/ 文档站:首页 / 组件总览 / 快速开始 / 设计规范
  • Ctrl+K 全局搜索、主题定制器(4 键覆盖)、build-site.ps1 构建脚本

[2.0.0] - 2026-09-20

Changed — 品牌重命名:Aurora Admin → Kole UI(破坏性)

  • 一次全仓改名,覆盖五类命名空间,1373 个文件 / 约 2.9 万处:
命名空间 旧 新 命中
文字品牌名 Aurora Admin / Aurora Kole UI / Kole 1224
路径 · 包名 · 镜像 aurora-admin / aurora-admin-design / aurora-admin-showcase kole-ui / kole-ui / kole-ui-showcase 1303
类名前缀 aa-(Input 组件历史遗留用的是 au-) kole-(两类前缀就此统一) 18014
令牌前缀 --au- --kole- 8489
组件导出名 AaButton / AaTag …(含 import * as Aa) KoleButton / KoleTag …(import * as Kole) 321
  • 五类映射一句话版(上表在站点更新日志页不会渲染 —— build-site.ps1 的 CHANGELOG 解析器只抓 - 行,表格行不入 changelog.json;故在此复述,已登记为 ROADMAP 衍生任务 S6-P29):文字品牌名 Aurora Admin → Kole UI;包名 / 路径 / 镜像 aurora-admin → kole-ui;类名前缀 aa-(Input 遗留 au-)→ kole-;令牌前缀 --au- → --kole-;组件导出名 AaButton / AaTag → KoleButton / KoleTag。

  • 按破坏性处理,版本 1.4.1 → 2.0.0。破坏面:npm 包名、组件导出名、CSS 类名、CSS 变量名、localStorage 键前缀、Docker 镜像/容器名、部署目录。

  • 环境变量与全局标识符同步改名(逐条列举,避免误伤十六进制哈希与 WCAG「AA」字样):AA_PORT → KOLE_PORT、AA_DATA → KOLE_DATA、AA_VERIFY_DEPS_DIR → KOLE_VERIFY_DEPS_DIR、__aaCollectResult / __aaBehaviors / __aaBehCache / __aaVersion / __aaResult / __aaRun / __aaDetailReady / __aaChangelogReady / __aaTranslateThemePanel / __aaRefreshModeUI → __kole*、aaLogger → koleLogger、aaZoom / aaSlide / aaFade → kole{Zoom,Slide,Fade}。

  • localStorage 键前缀 aa- → kole-(kole-lang / kole-render-log / kole-search-log / kole-test-log / kole-mode)。用户的旧偏好不会自动迁移,等于重置一次的语言与主题偏好。

  • 目录与文件重命名:.design_library/aurora-admin/ → .design_library/kole-ui/(git mv,历史保留);启动器 aurora-admin-dsh-launcher.exe → kole-ui-dsh-launcher.exe。

  • 组件导出名(公开 API)同步改名,来源不只是字符串:tools/build-dist.mjs 生成 export { default as Kole${prefix} } 的三端入口、79 个 .vue2.vue / .vue3.vue 的 name: 'KoleXxx' 选项、README 与站内「快速开始」的 import 示例。改名后 dist/ 重新构建,verify-package-import.mjs 复核入口一致。

  • 发布现状(2026-09-20 实测,避免把「改名」误读成「已按新名发布」):

    • 公共 npm:kole-ui / chunyu-ui / aurora-admin-design 三个名字均未被占用(registry.npmjs.org/<name> → {"error":"Not found"}),但都尚未发布(本机无 npm 凭据)。
    • 私有 Gitea 源(gitea.mymoyu.top):线上存在的是改名前的 @root/ui / chunyu-ui / aurora-admin-design;实测无 kole-ui。也就是「仓库叫 kole-ui」与「源上能装到 kole-ui」目前不是一回事,README 中与该源相关的段落已加注说明。
    • 结论:本次交付只改仓库,未执行任何发布动作 —— 重新发布是一次独立的、需要凭据的操作。
  • 迁移脚本入库:tools/migrate-brand-kole-ui.mjs(--dry-run 预演 / 默认执行 / --verify 残留扫描)。实现为字节级替换,兼容 CRLF、UTF-8 与 GBK,跳过二进制与 UTF-16;幂等——第二遍运行报告 0 处改动。

  • 文档与配置一并改名:AGENTS.md / README.md / ROADMAP.md / TESTING.md / CONTRIBUTING.md / site/llms.txt / 契约 index.json / SKILL.md / metadata.json / npm 仓库地址与 homepage(仍为 YOUR-ACCOUNT 占位)。

  • 规划偏差(有意为之,在此披露):AGENTS.md 禁止改写 CHANGELOG.md 历史条目。本次对历史条目只替换了品牌名本身,日期、版本号、断言数量、通过率、色值等事实一字未动——理由是重命名后站点更新日志页若仍显示旧品牌会自相矛盾。除品牌词外的历史内容保持原样。

  • 一处自查发现并修回的真问题(教训值得留档):批量替换会把「对外实测事实」也一并改掉,使它从事实变成未经核验的断言。本次命中的是包名相关的三处 —— ① CHANGELOG「已发布到私有源」表的第三个包名;② README「三个可互换的发布名」;③ ROADMAP 的 S5-P21 行与「规划修正记录」里的 registry 查验结果。原文记的是 aurora-admin-design(当时确已发布/已查验),被改成 kole-ui 后就变成「kole-ui 已发布」这种假事实。修法:这几处还原为当时的真实名字并加注新旧对照,另在 2026-09-20 对 kole-ui 重新实测并记录结果(见上「发布现状」)。同时给迁移脚本加了 --only= 限定规则 —— 因为全量重跑会把 §「刻意保留旧名对照」的位置再次改写掉。教训:改名要区分「品牌词」与「记录了外部状态的名字」,后者只能新增核验、不能替换。

Verified — 重命名后全链验收

  • 构建链两步全绿:build-site.ps1(79 组件 / 106 令牌 / 316 平台薄壳 / 396 sitemap URL)+ precompute.mjs(data.js 1159 KB → 122 KB;site/data.json 保持完整,79/79 组件带全量 5 端 sources)。
  • 回归 100%(1017/1017 断言 / 79 页全过 / N/A 34),八次连跑一致、0 超时。
  • 8 个验证脚本全过:verify:i18n 16 项 · smoke:site 全过 · verify:theme · verify:nav · verify-dark · verify-site-routing(79 / 316 / 396)· verify-families(13 族 / 44 成员)· verify-emits-parse 17 项 · verify-package-import 15 项(1 SKIP)· verify-dev-server 20 项 · verify-cross-platform(79/79 完全一致,差异 0)。
  • 残留扫描 migrate-brand-kole-ui.mjs --verify:除刻意保留的旧名对照外为 0。剩余命中只有 4 个文件且全部是「为了记录旧名而写旧名」的文本 —— AGENTS.md §七(命名约定行)、CHANGELOG.md(本段对照表 + 发布记录还原处)、以及由它派生的 site/changelog.json / site/data.json。代码、样式、模板、测试页、构建产物中的旧命名全部清零。
  • 零运行时依赖不变(dependencies 为空)。

Known limitations

  • kole-ui-dsh-launcher.exe 只改了文件名:它是 5.6 KB 的 .NET 编译产物,程序集名/模块名仍内嵌旧名(实测元数据为 aurora-admin-dsh-launcher.exe 与命名空间 aurora-admin-dsh-launcher)。仓库内没有它的构建源(无 .cs / .csproj / .sln,dsh_launcher.py 亦非其来源),故无法就地重编;要彻底改名需在产出该 exe 的地方重编一次。
  • 部署侧(192.168.5.7)的镜像/容器/目录名已在仓库改好,但线上实例仍是旧名,需按 AGENTS.md §九 走一次标准部署流程才会生效。
  • 仓库目录名 组件规范第一套 未改(属工作区路径,改名会影响 DSH 启动器里硬编码的路径)。

[1.4.1] - 2026-09-11

审计轮 — 系统性质疑「这么多组件能保证不出错吗」

结论:不能保证零错误。79 组件 × 5 端 × 79 契约 × 326 译文,靠肉眼和声称都不成立。因此改为四轮机器审计 + 实测,把「我检查过了」替换成可复现的数字。

审计 1 · 契约保真度(358 条 usageHints 回规格原文核对)

  • 逐字命中 336 条(93.9%);剩余 22 条经人工比对为同义改写(如「列表项带复选框」→「列表项带复选框,项高 32px」,数值确实在规格别处),非发明。
  • 发现一处真实不一致:rate.json 的选中星色仍写 #FAAD14,而规格已在 v1.3.1 改为 #2F54EB —— 修契约使其与规格同步(usageHints + anatomy)。

审计 2 · 令牌语义正确性

  • 检查 1313 处含令牌的颜色声明,0 处属性/令牌角色错配(未出现「background 用文字色令牌」这类)。令牌化在语义上是干净的。

审计 3 · i18n 翻译质量

  • 326 条字典:英文值含中文 0 条、中英完全相同 0 条、长度异常 0 条。
  • 修正审计脚本对「副名」的误判:英文模式下 .core-en 显示中文是设计意图(主名英文 + 副名中文),不是漏翻。
  • 发现并修复 4 处真漏翻:guide 页标题、Do/Don't 两个标题、guide 表格 H5 静态页、组件名渲染 4 处未做语言感知。

审计 4 · 废弃色值残留

  • 扫描 91 个文件,发现 4 个文件 23 处仍引用 v1.3.1 之前的旧色值。
  • 最严重:css.json —— 它是 For Agents 页宣称的「结构化令牌源」,机器读取方会拿到过时的颜色。已同步 10 处。
  • README.md 设计说明 5 处同步;CHANGELOG.md 的旧值属历史变更记录,有意保留。

修复 · 低对比度图标

  • 用「逐元素实测对比度」扫全部页面,发现 Rate 未选中星用 --kole-color-border(#E8ECF1) 作星色,白底仅 1.19:1 —— 边框色是装饰性色值,作图标不合格。
  • 新增 --kole-color-icon-inactive: #8F8F8F(白底 3.23:1,满足 WCAG 1.4.11 的 3:1,且视觉最克制)。令牌 74 → 75。
  • 同批扫出的另外 5 处低对比度经逐一核实为禁用态(WCAG 1.4.3 豁免)或深色遮罩上的白字(检测器把半透明底当白底),非缺陷。

修复 · 回归偶发(第三次根治)

  • 现象:多次连跑偶发 99.9%(1 页失败),但单独打开该页总是通过。
  • 根因:收集器的 8 秒超时兜底直接记为 fail: 1。并发 4 个 iframe 时主线程被抢占,慢页面会撞上超时。
  • 修法:超时阈值 8s → 12s;重试一次后再判定;超时与断言失败分开统计(timedOut 字段,不计入通过率分母)。
  • 验证:八次连跑全部 100% / 0 失败 / 79 页全通过 / 0 超时。

[1.4.0] - 2026-09-11

Changed — 组件层全面令牌化(设计系统的根基修复)

  • 发现:79 个组件的 844 个颜色属性里,只有 2 个(0.2%)引用令牌,788 个(93.4%)硬编码 hex。后果是改令牌组件不跟着变、主题定制器对组件无效、For Agents 页写的「所有色值必须取自 kole-* 变量」形同虚设。这是本项目第五次「声称≠实现」,且动摇了设计系统的根本。
  • 两层令牌化(此前只改了从未被加载的文件,走了弯路):
    • 组件样式表(frameworks/*.css):915 处 / 78 文件
    • 演示页内嵌 <style>(实际生效的样式层):287 处 / 51 文件
  • 内嵌样式层是决定性的:演示页只 link colors_and_type.css + 自己的 CSS,而多数页面把关键样式写在 <style> 块里 —— 只改 CSS 文件不生效。
  • 安全策略:只替换颜色属性值位置的 hex(color / background* / border* / outline* / fill / stroke);跳过 rgba()/渐变/url() 复合值;不动 SVG 属性与 JS 数据(色板数组);幂等可重复运行。
  • 歧义色值按属性语义消解(#FFFFFF 作 color → text-inverse,作 background → card-bg)。

Added — 补齐令牌语义

  • --kole-color-text-tertiary #595959(三级文字/描述,规范未定义、实现补齐,7.00:1)
  • --kole-color-text-disabled #BFBFBF(禁用态文字,规范定义于组件1/2.txt;WCAG 1.4.3 对禁用控件豁免)
  • --kole-color-border-strong #F0F0F0(实线边框,规范未定义、实现补齐)
  • 令牌总数 71 → 74;同步 legacy 别名映射(--color-text-tertiary 等)。
  • 修复 colors_and_type.css 一处重复的注释起始行。

Fixed

  • Countdown 首帧空白:setInterval(render, 1000) 首次执行要等 1 秒,期间容器为空。改为定义 renderCountdown() 后立即执行一次,再挂 interval。浏览器实测确认修复。

Verified — 令牌响应性(本轮核心验收)

  • 逐组件验证「改令牌 → 元素是否跟着变」,79/79 全部响应(改 --kole-color-brand / text-body / border 等,采样前后样式签名对比)。
  • 过程中修正了两处测量方法缺陷(初测 40/79 是误报):① 选择器 .demo * 在无 .demo 容器的页面抓不到元素;② 探针令牌选错——Breadcrumb 用 text-tertiary 而我只改 text-body。
  • 回归保持 100%(961 断言 / 0 失败 / 79 页全通过),三次连跑一致。

[1.3.3] - 2026-09-11

Added — 中英双语(i18n)

  • site/i18n.js:330 条文案字典,顶栏新增 中 / EN 切换器,偏好存 localStorage['kole-lang'],<html lang> 与 document.title 同步。
  • 设计取舍:以「中文源串」作字典键而非抽象 key。中文是规范原文语言(组件1~10.txt)也是 app.js 现有字面量;源串作键意味着未收录文案自动回退原文,不会出现空白或 key 泄漏。
  • 覆盖范围:导航 / 侧栏 / 首页 Hero 与设计原则 / 总览 / 快速开始 / 设计规范(含令牌导出区)/ For Agents 全表 / 更新日志 / 组件详情页(何时使用、API 三表、无障碍键盘表、Do&Don't、设计契约、实现资源、相关组件)/ Playground / 主题面板 / 搜索弹窗 / FAB 提示。
  • 语言感知的显示逻辑:
    • 组件名主次调换(中文模式主显中文名,英文模式主显英文名),详情页大标题不再重复;
    • 侧栏分类名走 CAT_EN,不占字典;
    • 动态生成的键盘表、插槽说明按语言重算。

Fixed — 回归时序(根治偶发)

  • DensitySwitcher 对比度偶发失败:断言在演示页内联脚本执行完之前就跑了,读到 is-active 尚未应用的中间态(白字未落到品牌蓝底 → 2.51:1)。单页打开时通过、并发收集器里偶发失败。
  • 根因是固定帧数等待(load + 双 requestAnimationFrame)在多个 iframe 抢主线程时不够稳。改为就绪轮询:readyState === 'complete' 且 DOM 连续 3 次采样(约 48ms)无变化才断言,另设约 4.8s 超时兜底避免卡死。
  • 验证:四次连跑全部 100%(961 断言 / 0 失败 / 79 页全通过),偶发不再复现。

Fixed — i18n 接入过程中的三个真实缺陷

  • TDZ 顺序:KIND_KEYS 等模块级常量在 I18N/T 定义之前调用了 T(),抛 Cannot read properties of undefined (reading 'T')。已改为存中文源串、渲染时求值(模块级预先求值还会导致语言切换后不更新)。
  • 局部变量遮蔽:renderDesign 内原有 var T = data.tokens; 遮蔽了全局翻译函数,导致设计规范页整个渲染失败。改名 TOKENS。
  • 模板拼接括号:el() 调用在包装 T() 后少一个右括号,已修正。

Changed

  • 回归基线:961 断言 / 925 通过 / 100% / 79 页全通过 / N/A 36,四次连跑一致。

[1.3.2] - 2026-09-11

Added — 契约第三批:全量契约化 79/79

  • 补齐剩余 43 份组件契约,components/ 目录现为 79 份契约 JSON(此前 36)。
  • 分两批提炼,全部逐字来自规格原文(组件1/2/5/6/7.txt):
    • 批次 A(19):tag / tabs / steps / breadcrumb / dropdown / popconfirm / buttongroup / expandabletable / mergedcelltable / summaryrowtable / fixedcolumntable / enhancedtabnav / sidemenu / topmenu / mixednavigation / quicknav / anchornav / backtotop / pagetransition
    • 批次 B(24):bankcardinput / idcardinput / plateinput / listpicker / rangequickpicker / dragupload / signaturepad / messagepro / notificationpro / progressvariants / skeletonpro / emptypro / loadingoverlay / resultvariants / exceptionvariants / confirmmodal / alertmodal / formmodal / fullscreenmodal / themeswitcher / layoutswitcher / densityswitcher / shortcutpanel / bottomsheet
  • 每份含 variantDimensions / representativeVariants / anatomy / structurePatterns / usageHints / doNotInvent / unknowns 七字段,与既有 36 份同 schema。
  • 硬规则:只从规格提炼,不发明;规格未明示者进 unknowns,规格明确排除者进 doNotInvent。校验脚本确认 79/79 字段完整、slug 一致。

Added — 令牌导出(文档清单中的 C4 项)

  • build-site.ps1 构建期生成三种标准格式,与站点展示的令牌始终同源:
    • site/tokens/tokens.css — CSS 自定义属性,可直接 @import
    • site/tokens/dtcg.json — W3C Design Tokens 社区组格式($value / $type / $description,按 color/typography/spacing/radius/shadow/motion/size 分组)
    • site/tokens/figma.json — Figma Tokens(Tokens Studio 插件可直接导入)
  • 设计规范页新增「令牌导出」区,三个文件提供下载入口。

Changed — 规格原文与实现对齐

  • 同步规格中的色彩系统到 v1.3.1 的 AA 达标值(15 处):占位文字 / 次要文字 / 五种语义色,并在原值处标注变更原因与对比度实测。
  • 修正一处既有漂移:Rate 选中星色规格为 #FAAD14(白底 1.90:1,不满足 WCAG 1.4.11 的 3:1),实现取 #2F54EB,规格已对齐实现并注明原因。

Fixed

  • build-site.ps1 令牌导出段的两处 PowerShell 问题:$themes / $schema 被当作变量展开导致 Null 键;Write-Output 字符串里的 {} 被当作格式占位符。

[1.3.1] - 2026-09-11

Changed — 无障碍与令牌合规(9 项矩阵断言全部达标)

  • 回归通过率 85.1% → 100%(961 条断言 / 0 失败 / 36 条 N/A / 79 页全通过,三次连跑结果一致)。
  • 令牌层修正(改一处、全局生效):--kole-color-text-secondary #8C8C8C→#6E6E6E(3.36:1→5.10:1)、--kole-color-text-placeholder #BFBFBF→#767676(1.84:1→4.54:1)、--kole-color-success #52C41A→#2E7D0A、--kole-color-warning #FAAD14→#8C5A00、--kole-color-error #F5222D→#CF1322、--kole-color-info #1890FF→#096DD9。原值均为 Ant Design 的「填充色阶」,作文字/白字场景均不足 AA。
  • 5 端同步:frameworks/ 下 150+ 文件、300+ 处硬编码色值同步到达标值。禁用态(WCAG 明示豁免)保持原弱化表现不变。
  • 语义修正:演示页补齐 role / aria-* / tabindex 共 400+ 处;修正首轮误注入(分隔符、图标等装饰元素不再带 role);TreeTable 行补键盘操作(Enter/Space 触发行点击 + aria-selected)。
  • 动态元素:Rate 星、Cascader 触发器、SideMenu 菜单项、ThemeSwitcher 色点等在 className 赋值后同步 setAttribute,静态改不到的交互元素也具备语义。
  • 断言判据精化(修正过严/过宽,非放水):
    • 图标类元素适用 WCAG 1.4.11 的 3:1(新增 icon-contrast 提示项),文字仍走 1.4.3 的 4.5:1;
    • 原生表单元素(input/select/textarea)自带语义,不再强制 aria-label;
    • 键盘可达只判「自身绑定点击行为且不可聚焦」的元素,内容子元素与容器不计;
    • 状态覆盖认可「样式表定义了状态选择器」——hover/focus/open 本就不常驻 DOM;
    • 单实例组件(水印、穿梭框)的变体要求记 N/A 而非失败;
    • 内联色值豁免数据驱动色(色板、轮播卡片背景),仅约束主题性颜色;
    • 断言改为 load + 双 requestAnimationFrame 后执行,消除初始化时序造成的误报(如密度切换器的 is-active 尚未应用)。
  • site/app.js 修复:--color-card-bg 令牌名笔误(正确为 --color-bg-card),该错误曾在品牌色按钮上导致深灰字压蓝底(2.59:1)。

Known limitations

  • 36 条 N/A 来自「静态组件无交互面」与「单实例组件无多变体」,属合理豁免,非缺陷掩盖(已逐条人工核实)。
  • 本通过率覆盖 9 项自动化矩阵断言,不等同于完整的 WCAG 2.1 AA 合规认证:屏幕阅读器实测、焦点顺序、动态内容播报仍需人工/AT 工具验证。

[1.3.0] - 2026-09-10

Fixed — 验收链路(回归通过率此前不可信)

  • 测试页快照为空壳:run-tests.ps1 抽取 frameworks/<组件>.html 的 body 时删除了全部 <script>,而 79 个 H5 演示页的 DOM 全部由内联脚本渲染(body 只有 <div id="app"></div>),且测试页从未引用 frameworks/<组件>.css。断言跑在空 DOM + 无组件样式上,v1.2.0 的 75.1% 属结构性误报,不是实现质量。
  • 测试页改为 iframe 加载真实演示页(tests/_template.html),tests/_runtime.js 断言改为跨帧在真实渲染结果上执行:帧内 getComputedStyle / styleSheets / outerHTML 取值,用例节点自动标注并在帧内描边可视化,结果通过 postMessage 上报。
  • 断言标注改为容器下钻(.row / .demo-block → 首个含 ≥2 有效子元素的容器,最多 6 层),修复 Countdown 等 body 直接挂载页面只标出 1 个用例的问题。
  • 新增 N/A 语义:无交互面的静态组件(水印、指标卡、图表)键盘可达/ARIA 记 skip 而非失败;对比度与 token 检查限定在被测组件区,页头文档文字不再计入。
  • 通过率分母改为 pass / (pass + fail),N/A 不拉低数值;tools/run-regression.mjs(CI runner)与浏览器收集器同口径。

Added — 设计系统

  • 基座键盘焦点环::focus-visible 统一 2px 描边(colors_and_type.css)。--kole-color-focus-ring 此前只被定义、从未被消费,79 个组件样式里仅 20 个自带 focus 规则——此改动一次性消除 66 页 focus-visible-defined 失败。
  • tests/_collect.html:零依赖浏览器批量回归收集器(并发 iframe + 汇总 + window.__koleCollectResult),替代此前"用浏览器控制台手跑 79 页"的临时做法。
  • tests/_index_template.html:测试总览页模板外置(原为 run-tests.ps1 内联 here-string),读数来自 site/data.json,并显示最近回归通过率。

Added — 设计契约第二批(展示类 15 个)

  • tree / collapse / calendar / carousel / imagepreview / qrcode / countdown / watermark / cardlist / treetable / timelinelist / steplist / chartpanel / dashboardcard / employeecard,逐份从规格原文(组件2/4/7/9.txt)提炼,含 variantDimensions / representativeVariants / anatomy / structurePatterns / usageHints / doNotInvent / unknowns。契约化覆盖 21 → 36/79。

Changed

  • run-tests.ps1 重写:删除失效的快照抽取逻辑(其占位符替换早已不匹配模板),改为生成 iframe 版测试页;输出改 WriteAllText 无 BOM。脚本保持 ASCII-only(PS5.1 读无 BOM 文件按 ANSI),中文文案移入 UTF-8 模板。
  • 回归基线更新:960 条断言 / 通过率 85.1%(N/A 27)、11 页全通过。剩余失败项即改进 backlog:状态覆盖 45、对比度 35、ARIA 33、键盘可达 15、硬编码 hex 9、变体 2。

[1.2.0] - 2026-09-10

Added — 设计契约与工程化

  • B1 契约第一批:15 个输入类组件补齐契约 JSON(autocomplete / cascader / transfer / rate / slider / segmented / radiocard / checkboxcard / switchgroup / numberrangeinput / codeinput / passwordinput / phoneinput / colorpicker / mention),契约化覆盖 6 → 21/79
  • C4 静态薄壳:site/components/<slug>.html × 79(每组件独立可爬 URL:title + meta description + canonical + 刷新跳转),sitemap.xml(80 URL,部署后回填 $SiteUrlBase)
  • C3 headless 回归:79 个测试页全量执行 812 条断言(当前通过率 75.1%,失败项即改进 backlog),产出 tests/report.json;CI runner tools/run-regression.mjs(Playwright,含 JUnit XML 输出)
  • 首页 Hero 显示「测试通过率」(读取 tests/report.json,无报告时静默隐藏)
  • B3 Playground:组件详情页「▶ 在线试玩」——textarea 编辑 H5 源码,iframe srcdoc 防抖实时重渲染,支持复位 / 退出,不影响源文件
  • C1 交叉引用:组件详情页新增「相关组件」(相似 / 搭配维度映射 + 同分类兜底)
  • 场景示范页:site/scenario/user-management.html(筛选表单 + 数据表格 + 分页 + 新建弹窗 + 消息反馈,视觉全部来自令牌与 components.css),首页 Hero 加入口
  • 部署物料:根 README.md、Pages 入口 index.html 重定向、.github/workflows/deploy-pages.yml、.gitignore

Fixed

  • 测试页断言协议落地:tests/_runtime.js 运行期自动标注快照节点 data-assert(多级结构启发式:.row → .demo → .demo-block → 首层;此前 79 页实际无断言节点,PLAN v1.1 声称与实现不符)
  • site/data.js / site/data.json 去除 UTF-8 BOM(PS5.1 Set-Content 默认带 BOM,严格 JSON 解析器如 node require 直接解析失败)
  • 断言可见性判定放宽(getClientRects 兜底),减少隐藏变体误报

[1.1.1] - 2026-09-08

Added — 竞品对齐改造(第一批,依据《竞品网站检查报告》与《现状问题分析与改造清单》)

  • For Agents 页(#/agents):AI / Agent 消费入口——机器可读资源清单、data.json 数据形状、消费示例、使用规则
  • site/llms.txt:LLM 入口清单,指向 data.json、契约 JSON、令牌文件与测试页
  • 站内更新日志页(#/changelog):build-site.ps1 解析本文件注入 data.js,站点展示与仓库同源
  • 主题预设库:主题定制器内置 6 套品牌色预设(科技蓝 / 青碧 / 极夜紫 / 暖橙 / 绯红 / 松石绿),一键切换后仍可微调
  • 组件详情页新增「API 源码提炼」徽章,区分契约化组件(6 核心)与源码提炼组件(69 扩展)

Fixed — 文档与实现不符

  • 搜索增强补票:Ctrl+K 弹窗补齐分类 chip 过滤、命中关键词 <mark> 高亮、子序列模糊回退(PLAN v1.1 曾声称交付但代码缺失);搜索结果行补写 data-slug 修复搜索日志点击目标为空的问题

Changed

  • 暗色模式令牌映射补全:html.kole-dark 新增品牌色族 / 语义色 / focus-ring / 阴影映射,并修复「主题内联样式压过暗色类」的层级问题——暗色下品牌色自动向白色混合提亮一档,kole-mode 切换后即时重算
  • build-site.ps1:meta.version 不再硬编码,改为从 CHANGELOG.md 最新版本号自动同步

[1.1.0] - 2026-09-07

Added — 文档体系补齐

  • PLAN.md:完整组件文档体系规划与路线图,含 5 大模块、3 版本路线、验收标准
  • CHANGELOG.md:本文档
  • CONTRIBUTING.md:贡献指南(如何新增组件 / 修契约 / 加测试)
  • TESTING.md:测试矩阵、断言协议、回归流程
  • tests/<slug>.html × 79:每个组件独立测试页(HTML+CSS+原生 JS 零依赖)
  • tests/index.html:测试总览页(按类目聚合 + 通过率 + 失败项)
  • run-tests.ps1:批量构建测试目录脚本

Added — 日志系统

  • site/logger.js:构建 / 渲染 / 搜索 / 测试 四类事件,落 localStorage[kole-render-log] / localStorage[kole-search-log] / localStorage[kole-test-log]
  • 控制台 koleLogger.export() 导出 JSON
  • 测试页内置 data-assert + data-status,便于 Playwright / Selenium 回归

Added — 搜索增强

  • Ctrl+K 弹窗内新增分类 chips 过滤(general / navigation / input / display / feedback / system)
  • 命中关键词 <mark> 高亮
  • 模糊容错:去空格 + 子串匹配 + 大小写不敏感
  • 搜索日志:query / 命中数 / 首个命中 slug / 耗时

Added — 文档骨架

  • 顶栏工具新增「测试」「日志」入口(HAMBURGER 之后)
  • 组件详情页新增「测试页」链接
  • 首页 hero stats 加入「测试页 79」一项

Changed

  • site/app.js 改为引用 site/logger.js,原搜索行为保留
  • 扩展组件契约新增「doNotInvent / unknowns」字段自动从 spec 文本提取

Fixed

  • 主题定制器焦点环 rgba 计算 bug:hex 转 rgba 不再被截断为 6 位
  • 类别切换时滚动条保持原位(避免视觉跳动)