diff --git a/AGENTS.md b/AGENTS.md index 4fe067b..11b8ea0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -27,7 +27,7 @@ - `apps/demo`(@ui-arch/demo):交互演示,产物 apps/demo/dist/demo.html - `apps/docs`:文档站,纯产物(ua docs 生成) -**门禁一条龙**:`npm run check` = build + demo + style + typecheck + smoke + index + verify,提交前必过。`ua verify` 校验清单 ↔ 文档 ↔ 演示一致(docs.components 的 id 必须在 api.exports 有对应条目、props 必须带 n/t/d、每个文档字段名必须在组件实现源码里真实出现(改名后忘改文档会直接报错)、反向也校验 `src/types.ts` 里 `<组件>Props`(可用清单的 `propsType` 覆盖接口名,`false` 表示无入参)每个字段都在文档 props 表登记(新加字段忘了写文档会报错)、demo 锚点必须在 `apps/demo/main.ts` 中存在,且该组件必须被 demo 真实调用 `id(` / `id.`),检查皮肤包样式表无硬编码颜色(`#hex` 一律禁止,必须走 `--ua-*` 令牌)与令牌引用有效(`var(--ua-*)` 必须是 tokens.css 已定义或组件自设的变量),核对 README 的 `` 区块与「分组:」行都覆盖清单组件集合(漏写/多写/重复都报错),并交叉校验 backlog 的 done 条目与 `.ua/iterations.log` 的 done 留痕一一对应。 +**门禁一条龙**:`npm run check` = build + demo + style + typecheck + smoke + index + verify,提交前必过。`ua verify` 校验清单 ↔ 文档 ↔ 演示一致(docs.components 的 id 必须在 api.exports 有对应条目、props 必须带 n/t/d、每个文档字段名必须在组件实现源码里真实出现(改名后忘改文档会直接报错)、反向也校验 `src/types.ts` 里 `<组件>Props`(可用清单的 `propsType` 覆盖接口名,`false` 表示无入参)每个字段都在文档 props 表登记(新加字段忘了写文档会报错)、demo 锚点必须在 `apps/demo/main.ts` 中存在,且该组件必须被 demo 真实调用 `id(` / `id.`),检查皮肤包样式表无硬编码颜色(`#hex` 一律禁止,必须走 `--ua-*` 令牌)与令牌引用有效(`var(--ua-*)` 必须是 tokens.css 已定义或组件自设的变量)、核对每个 `--ua-color-*` 都在 `[data-theme='dark']` 里有覆盖值且暗色块没有凭空多出的变量名(新增颜色令牌漏写暗色值直接报错),核对 README 的 `` 区块与「分组:」行都覆盖清单组件集合(漏写/多写/重复都报错),并交叉校验 backlog 的 done 条目与 `.ua/iterations.log` 的 done 留痕一一对应。 **变更日志**:`CHANGELOG.md` 由 git 提交史生成(`npm run changelog`),**不进 `npm run check`**——它包含每个提交自身,提交后必然与历史差一条,只能作为「发版前刷新」步骤;`npm run changelog:check` 用于确认是否漂移。 diff --git a/packages/tools/cli/bin/ua.js b/packages/tools/cli/bin/ua.js index aaed144..678a832 100644 --- a/packages/tools/cli/bin/ua.js +++ b/packages/tools/cli/bin/ua.js @@ -551,7 +551,7 @@ function cmdTokens(args) { console.log(JSON.stringify(picked, null, 2)); return; } - for (const t of picked) console.log(`${t.cssVar.padEnd(26)} ${t.value}${t.dark && t.dark !== t.value ? ' / 暗色 ' + t.dark : ''}`); + for (const t of picked) console.log(`${t.cssVar.padEnd(26)} ${t.value}${t.dark && t.dark !== t.value ? ' / 暗色 ' + t.dark : t.cssVar.startsWith('--ua-color-') && !t.dark ? ' / 缺暗色' : ''}`); console.log(`共 ${picked.length} 个令牌${keyword ? `(匹配 ${keyword})` : ''}`); } @@ -950,6 +950,22 @@ function cmdSyncCounts() { console.log(`sync-counts: 清单实际 ${actual} 个组件,改写 ${changed} 个文件`); } +/*** 暗色令牌齐全校验:每个 --ua-color-* 都得在 [data-theme='dark'] 里有覆盖值,反向也查暗色块里的变量先在 :root 定义过(防改名漏改) ***/ +function checkDarkTokens(issues) { + const p = path.join(ROOT, 'packages', 'design', 'tokens', 'tokens.css'); + if (!fs.existsSync(p)) return; // 卫语句:令牌文件缺失交给其它校验兜底 + const src = fs.readFileSync(p, 'utf8').replace(/\r\n/g, '\n'); + const names = (block) => [...block.matchAll(/(--ua-[\w-]+)\s*:/g)].map((m) => m[1]); // 块内变量名,按出现顺序 + const rootNames = names((src.match(/:root\s*\{([\s\S]*?)\}/) ?? [, ''])[1]); + const darkNames = names((src.match(/\[data-theme='dark'\]\s*\{([\s\S]*?)\}/) ?? [, ''])[1]); + const darkSet = new Set(darkNames); + const rootSet = new Set(rootNames); + for (const n of rootNames) { + if (!n.startsWith('--ua-color-')) continue; // 卫语句:只有颜色需要暗色重定值,间距/字号/圆角通用 + if (!darkSet.has(n)) issues.push(`tokens: 颜色令牌 ${n} 缺 [data-theme='dark'] 覆盖(暗色下会沿用亮色值)`); + } + for (const n of darkNames) if (!rootSet.has(n)) issues.push(`tokens: 暗色块里的 ${n} 未在 :root 定义(改名后忘了同步)`); +} /*** llms-full.txt 同步校验:内联重渲染 Agent 文档(时间戳归一化)与落盘产物比对,防 manifest 改后忘跑 docs ***/ function checkLlmsFull(pkgs, issues) { if (!fs.existsSync(LLMS_FULL)) return; // 卫语句:产物缺失不算漂移(可能是新仓库) @@ -1194,6 +1210,7 @@ function cmdVerify() { .flatMap((p) => p.docs?.components ?? []).length; issues.push(...checkCountDocs(skinTotal)); issues.push(...checkReadme(pkgs)); + checkDarkTokens(issues); checkLlmsFull(pkgs, issues); issues.push(...checkIterations()); @@ -1202,7 +1219,7 @@ function cmdVerify() { console.error(`${issues.length} violation(s)`); process.exit(1); } - console.log('verify OK (manifest ↔ docs ↔ demo 一致,文档 props ↔ 入参接口双向一致,皮肤无硬编码颜色与未定义令牌,README 组件清单与分组同步,backlog ↔ 留痕一致,组合配方结构完整,MCP 工具清单三处一致)'); + console.log('verify OK (manifest ↔ docs ↔ demo 一致,文档 props ↔ 入参接口双向一致,皮肤无硬编码颜色与未定义令牌、暗色令牌齐全,README 组件清单与分组同步,backlog ↔ 留痕一致,组合配方结构完整,MCP 工具清单三处一致)'); } /*** 校验 git 提交信息是否符合 COMMITTING.md 规范(参数为 message 文件路径或直接 message 文本),违规退出码 1 ***/