From 1b75fb46d7ced2a3ec84a09c5072a2d0561bf96b Mon Sep 17 00:00:00 2001 From: HIsheR Date: Mon, 26 Oct 2026 10:27:06 +0800 Subject: [PATCH] =?UTF-8?q?iter(g12):=20verify=20=E5=A2=9E=E5=8A=A0=20back?= =?UTF-8?q?log=20=E4=B8=8E=E7=95=99=E7=97=95=E4=BA=A4=E5=8F=89=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 2 +- packages/tools/cli/bin/ua.js | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 2333b39..947db98 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 + style + typecheck + smoke + index + verify,提交前必过。`ua verify` 校验清单 ↔ 文档 ↔ 演示一致(docs.components 的 id 必须在 api.exports 有对应条目、props 必须带 n/t/d、demo 锚点必须在 `apps/demo/main.ts` 中存在),检查皮肤包样式表无硬编码颜色(`#hex` 一律禁止,必须走 `--ua-*` 令牌),并核对 README 的 `` 区块与清单组件集合完全一致。 +**门禁一条龙**:`npm run check` = build + style + typecheck + smoke + index + verify,提交前必过。`ua verify` 校验清单 ↔ 文档 ↔ 演示一致(docs.components 的 id 必须在 api.exports 有对应条目、props 必须带 n/t/d、demo 锚点必须在 `apps/demo/main.ts` 中存在),检查皮肤包样式表无硬编码颜色(`#hex` 一律禁止,必须走 `--ua-*` 令牌),核对 README 的 `` 区块与清单组件集合完全一致,并交叉校验 backlog 的 done 条目与 `.ua/iterations.log` 的 done 留痕一一对应。 **提交信息规范**:`COMMITTING.md`(`(): <中文祈使句>`),`ua commit-lint` + commit-msg 钩子自动校验,迭代提交用 `iter(<条目id>): `。 diff --git a/packages/tools/cli/bin/ua.js b/packages/tools/cli/bin/ua.js index 83c63a1..8176edb 100644 --- a/packages/tools/cli/bin/ua.js +++ b/packages/tools/cli/bin/ua.js @@ -635,6 +635,28 @@ function checkLlmsFull(pkgs, issues) { } } +/*** 交叉校验留痕与条目:done 条目必须有一条 done 留痕,留痕 id 必须存在于 backlog(防「标完成无记录 / 记录指向幽灵条目」) ***/ +function checkIterations() { + const issues = []; + const backlogPath = path.join(ROOT, '.ua', 'backlog.json'); + const logPath = path.join(ROOT, '.ua', 'iterations.log'); + if (!fs.existsSync(backlogPath) || !fs.existsSync(logPath)) return issues; // 卫语句:产物缺失不校验 + const items = JSON.parse(fs.readFileSync(backlogPath, 'utf8')).items ?? []; + const ids = new Set(items.map((i) => i.id)); + const done = new Set(); // 有 done 留痕的条目 id + for (const line of fs.readFileSync(logPath, 'utf8').split(/\r?\n/)) { + if (!line.trim()) continue; // 空行跳过 + let row; + try { row = JSON.parse(line); } catch { continue; } // 行格式归 lint-iterations 管,这里不重复报 + if (!ids.has(row.id)) issues.push(`iterations.log: 留痕 id ${row.id} 在 backlog 中不存在`); + if (row.result === 'done') done.add(row.id); + } + for (const item of items) { + if (item.status === 'done' && !done.has(item.id)) issues.push(`backlog: ${item.id} 已置 done 但 iterations.log 无 done 留痕`); + } + return issues; +} + /*** 清单一致性校验:组件文档块的 id / props 说明 / demo 锚点必须与代码和演示产物对齐 ***/ function cmdVerify() { const issues = []; @@ -676,13 +698,14 @@ function cmdVerify() { issues.push(...checkCountDocs(skinTotal)); issues.push(...checkReadme(pkgs)); checkLlmsFull(pkgs, issues); + issues.push(...checkIterations()); if (issues.length) { for (const it of issues) console.error('verify: ' + it); console.error(`${issues.length} violation(s)`); process.exit(1); } - console.log('verify OK (manifest ↔ docs ↔ demo 一致,皮肤无硬编码颜色,README 组件清单同步)'); + console.log('verify OK (manifest ↔ docs ↔ demo 一致,皮肤无硬编码颜色,README 组件清单同步,backlog ↔ 留痕一致)'); } /*** 校验 git 提交信息是否符合 COMMITTING.md 规范(参数为 message 文件路径或直接 message 文本),违规退出码 1 ***/