diff --git a/.ua/index.json b/.ua/index.json index 8ffe080..6fdb411 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-26T12:06:51.450Z", + "generatedAt": "2026-10-26T12:29:16.234Z", "repoRoot": ".", "packages": [ { @@ -3872,7 +3872,7 @@ "MCP tool 入参 schema" ] }, - "usage": "node packages/tools/cli/bin/ua.js |docs|tokens|style|verify|commit-lint|audit:visual|mcp>;仓库内等价于 npm run index / docs / style / verify / audit:visual", + "usage": "node packages/tools/cli/bin/ua.js |docs|tokens|style|verify|commit-lint|audit:visual|doctor|mcp>;仓库内等价于 npm run index / docs / style / verify / audit:visual / doctor", "conventions": [ "零依赖:只用 node 标准库,Node >= 18", "清单是单一来源:代码注释、文档站、llms-full.txt、MCP 全部从 ua.manifest.json 派生", @@ -3881,7 +3881,7 @@ "docs": { "intro": "工程层工具包(private,不发布)。所有 Agent 与人都通过它读取组件库:清单驱动索引、文档、MCP 三件套,外加 style / verify 两道门禁。", "steps": [ - "装好依赖后先跑 npm run check 确认基线全绿(build → demo → style → typecheck → smoke → index → verify → lint-iterations → audit:visual)", + "接手先跑 ua doctor(node 版本 / 依赖 / git 钩子 / .ua 元数据一次检完,秒级),再跑 npm run check 确认基线全绿(build → demo → style → typecheck → smoke → index → verify → lint-iterations → audit:visual)", "查组件:ua list 看全量,ua search <关键词> 按 id/标题/参数名/参数说明/步骤模糊找(「处理中」这类说明里的词也能搜到,命中非 id 标题时会标出命中字段;拼错会回相近 id),ua info <组件id> 看 props/步骤/示例(ua info <包名> 看单包 api 与约定,加 --json 出原始清单)", "查配方:ua recipes 列全量(编号 / 标题 / 用到的组件),ua recipes <编号> 看骨架代码与要点(--json 给脚本用;MCP 里对应 list_recipes / get_recipe)", "查令牌:ua tokens 打印全部 --ua-* 变量(颜色带暗色值),--json 输出结构化数组;写样式前先查,禁止硬编码。令牌分十一组:颜色 / 圆角 / 间距 / 字号 / 字重行高 / 边框 / 阴影 / 动效 / 焦点环 / 控件高度 / 层级,弹层阴影用 --ua-shadow-1..4,过渡用 --ua-duration-* + --ua-ease,焦点环用 --ua-focus-ring(_inset)", diff --git a/AGENTS.md b/AGENTS.md index 009ec21..c2e0a49 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,7 +7,7 @@ 1. **包管理器必须用 pnpm**:包间依赖用 `workspace:*` 协议,npm 不支持。安装依赖:`pnpm install`。 2. **构建工具**:TypeScript 5(`tsc`)。若环境未全局安装,可使用托管工作区的副本:`C:/Users/shawn/.workbuddy/binaries/node/workspace/node_modules/typescript`(本仓库历史即如此构建)。 3. **Node**:>= 18,ESM(`"type": "module"`)。 -4. **验证自检**:装好后先跑 `npm run check`(build → demo → style → typecheck → smoke → index → verify → lint-iterations → audit:visual)确认基线全绿,再开始改代码。 +4. **环境自检 + 验证基线**:先跑 `node packages/tools/cli/bin/ua.js doctor`(秒级检查 node 版本 / 依赖安装 / git 钩子 / .ua 元数据可解析,任一失败退出码 1),通过后再跑 `npm run check`(build → demo → style → typecheck → smoke → index → verify → lint-iterations → audit:visual)确认基线全绿,再开始改代码。 ## 编码规范(强制) diff --git a/llms-full.txt b/llms-full.txt index e25aa91..f8b857f 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-26T12:06:51.450Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-26T12:29:16.234Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手 @@ -40,7 +40,7 @@ ### @ui-arch/cli -1. 装好依赖后先跑 npm run check 确认基线全绿(build → demo → style → typecheck → smoke → index → verify → lint-iterations → audit:visual) +1. 接手先跑 ua doctor(node 版本 / 依赖 / git 钩子 / .ua 元数据一次检完,秒级),再跑 npm run check 确认基线全绿(build → demo → style → typecheck → smoke → index → verify → lint-iterations → audit:visual) 2. 查组件:ua list 看全量,ua search <关键词> 按 id/标题/参数名/参数说明/步骤模糊找(「处理中」这类说明里的词也能搜到,命中非 id 标题时会标出命中字段;拼错会回相近 id),ua info <组件id> 看 props/步骤/示例(ua info <包名> 看单包 api 与约定,加 --json 出原始清单) 3. 查配方:ua recipes 列全量(编号 / 标题 / 用到的组件),ua recipes <编号> 看骨架代码与要点(--json 给脚本用;MCP 里对应 list_recipes / get_recipe) 4. 查令牌:ua tokens 打印全部 --ua-* 变量(颜色带暗色值),--json 输出结构化数组;写样式前先查,禁止硬编码。令牌分十一组:颜色 / 圆角 / 间距 / 字号 / 字重行高 / 边框 / 阴影 / 动效 / 焦点环 / 控件高度 / 层级,弹层阴影用 --ua-shadow-1..4,过渡用 --ua-duration-* + --ua-ease,焦点环用 --ua-focus-ring(_inset) @@ -2199,7 +2199,7 @@ API 速览: 一行用法: ``` -node packages/tools/cli/bin/ua.js |docs|tokens|style|verify|commit-lint|audit:visual|mcp>;仓库内等价于 npm run index / docs / style / verify / audit:visual +node packages/tools/cli/bin/ua.js |docs|tokens|style|verify|commit-lint|audit:visual|doctor|mcp>;仓库内等价于 npm run index / docs / style / verify / audit:visual / doctor ``` 约定: diff --git a/packages/tools/cli/bin/ua.js b/packages/tools/cli/bin/ua.js index f9b5812..d239e90 100644 --- a/packages/tools/cli/bin/ua.js +++ b/packages/tools/cli/bin/ua.js @@ -1576,10 +1576,43 @@ function cmdLintIterations() { console.log(`lint-iterations OK (${lines.length} entries)`); } +/*** 环境自检:新 Agent 接手前一条命令确认 node / 依赖 / git 钩子 / .ua 元数据就绪,任一失败退出码 1 ***/ +function cmdDoctor() { + const checks = []; // 逐项结果:名称 + 是否通过 + 可选失败详情 + const nodeMajor = Number(process.versions.node.split('.')[0]); + checks.push({ name: `node >= 18(当前 ${process.versions.node})`, pass: nodeMajor >= 18 }); + checks.push({ name: 'pnpm-lock.yaml 存在', pass: fs.existsSync(path.join(ROOT, 'pnpm-lock.yaml')) }); + checks.push({ name: '依赖已安装(node_modules/)', pass: fs.existsSync(path.join(ROOT, 'node_modules')) }); + const hooksPath = spawnSync('git', ['config', 'core.hooksPath'], { cwd: ROOT }).stdout?.toString().trim(); // 显式 hooksPath 优先,默认取 .git/hooks + const hookDir = hooksPath ? path.resolve(ROOT, hooksPath) : path.join(ROOT, '.git', 'hooks'); + checks.push({ name: 'commit-msg 钩子在位', pass: fs.existsSync(path.join(hookDir, 'commit-msg')) }); + const tryJson = (rel) => { // 存在且能 JSON.parse 才算过 + const p = path.join(ROOT, rel); + if (!fs.existsSync(p)) return `文件不存在`; + try { JSON.parse(fs.readFileSync(p, 'utf8')); return ''; } catch (e) { return `解析失败:${e.message}`; } + }; + for (const rel of ['.ua/backlog.json', '.ua/index.json']) { + const bad = tryJson(rel); + checks.push({ name: `${rel} 可解析`, pass: !bad, detail: bad }); + } + const logFile = path.join(INDEX_DIR, 'iterations.log'); + if (fs.existsSync(logFile)) { + const badLines = fs.readFileSync(logFile, 'utf8').split(/\r?\n/).filter((l) => l.trim()).filter((l) => { try { JSON.parse(l); return false; } catch { return true; } }); + checks.push({ name: '.ua/iterations.log 每行合法 JSON', pass: !badLines.length, detail: badLines.length ? `${badLines.length} 行非法(首行:${badLines[0].slice(0, 40)}…)` : '' }); + } else checks.push({ name: '.ua/iterations.log 存在', pass: false, detail: '尚未生成,跑一轮迭代或 ua index' }); + for (const c of checks) console.log(`${c.pass ? 'pass' : 'FAIL'} ${c.name}${c.detail ? ':' + c.detail : ''}`); + const fails = checks.filter((c) => !c.pass).length; + if (fails) { console.error(`doctor: ${fails} 项未通过,先修复再跑 npm run check`); process.exit(1); } + console.log(`doctor OK(${checks.length} 项全过)`); +} + // ---- 入口 ---- const [cmd, ...args] = process.argv.slice(2); switch (cmd) { + case 'doctor': + cmdDoctor(); + break; case 'index': cmdIndex(); break; @@ -1630,6 +1663,6 @@ switch (cmd) { cmdMcp(); break; default: - console.log('usage: ua |info |docs|tokens [--json]|style|sync-counts|verify|commit-lint|lint-iterations|audit:visual [--json|--baseline]|changelog|mcp>'); + console.log('usage: ua |info |docs|tokens [--json]|style|sync-counts|verify|doctor|commit-lint|lint-iterations|audit:visual [--json|--baseline]|changelog|mcp>'); process.exit(cmd ? 1 : 0); } diff --git a/packages/tools/cli/ua.manifest.json b/packages/tools/cli/ua.manifest.json index d534998..e1d9705 100644 --- a/packages/tools/cli/ua.manifest.json +++ b/packages/tools/cli/ua.manifest.json @@ -27,7 +27,7 @@ "MCP tool 入参 schema" ] }, - "usage": "node packages/tools/cli/bin/ua.js |docs|tokens|style|verify|commit-lint|audit:visual|mcp>;仓库内等价于 npm run index / docs / style / verify / audit:visual", + "usage": "node packages/tools/cli/bin/ua.js |docs|tokens|style|verify|commit-lint|audit:visual|doctor|mcp>;仓库内等价于 npm run index / docs / style / verify / audit:visual / doctor", "conventions": [ "零依赖:只用 node 标准库,Node >= 18", "清单是单一来源:代码注释、文档站、llms-full.txt、MCP 全部从 ua.manifest.json 派生", @@ -36,7 +36,7 @@ "docs": { "intro": "工程层工具包(private,不发布)。所有 Agent 与人都通过它读取组件库:清单驱动索引、文档、MCP 三件套,外加 style / verify 两道门禁。", "steps": [ - "装好依赖后先跑 npm run check 确认基线全绿(build → demo → style → typecheck → smoke → index → verify → lint-iterations → audit:visual)", + "接手先跑 ua doctor(node 版本 / 依赖 / git 钩子 / .ua 元数据一次检完,秒级),再跑 npm run check 确认基线全绿(build → demo → style → typecheck → smoke → index → verify → lint-iterations → audit:visual)", "查组件:ua list 看全量,ua search <关键词> 按 id/标题/参数名/参数说明/步骤模糊找(「处理中」这类说明里的词也能搜到,命中非 id 标题时会标出命中字段;拼错会回相近 id),ua info <组件id> 看 props/步骤/示例(ua info <包名> 看单包 api 与约定,加 --json 出原始清单)", "查配方:ua recipes 列全量(编号 / 标题 / 用到的组件),ua recipes <编号> 看骨架代码与要点(--json 给脚本用;MCP 里对应 list_recipes / get_recipe)", "查令牌:ua tokens 打印全部 --ua-* 变量(颜色带暗色值),--json 输出结构化数组;写样式前先查,禁止硬编码。令牌分十一组:颜色 / 圆角 / 间距 / 字号 / 字重行高 / 边框 / 阴影 / 动效 / 焦点环 / 控件高度 / 层级,弹层阴影用 --ua-shadow-1..4,过渡用 --ua-duration-* + --ua-ease,焦点环用 --ua-focus-ring(_inset)",