From 1321cc65fb78ea87a5bb00240bb274ee251fd98c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AI=E4=B8=8D=E6=AD=A2=E8=AF=AD?= <12096460+jnMetaCode@users.noreply.github.com> Date: Fri, 7 Aug 2026 21:54:48 +0800 Subject: [PATCH] =?UTF-8?q?test(audit):=20=E6=96=B0=E5=A2=9E=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E8=AE=A1=E6=95=B0=E4=B8=80=E8=87=B4=E6=80=A7=E6=A3=80?= =?UTF-8?q?=E6=9F=A5=EF=BC=9B=E4=BF=AE=20bash=203.2=20=E4=B8=8B=20CJK=20?= =?UTF-8?q?=E6=8A=A5=E9=94=99=E4=BF=A1=E6=81=AF=E4=B9=B1=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 审核 v1.7.2 时发现三个问题,一并修掉。 1) 工具计数散落十几处,没有任何检查兜着(audit 新增 Category 5,+24 项) 加一款工具要同步简繁 README(各 6 处)、package.json、CLAUDE.md、 site/build.mjs(三语言 15 处)、3 份 plugin manifest —— 这次全靠人工 grep 才 没漏。现在改为从 installer 的 TARGETS 推导期望值并逐处断言。 口径写进注释:TARGETS 是「安装目标」共 21 个;Copilot CLI 与 CC 共用 .claude/skills(别名 copilot 映射过去)不占独立条目,但文案里作为独立产品 单独计数,所以「文案数 = TARGETS 数 + 1 = 22」。 除逐处计数外还加了两条结构性断言: - README 工具表的实际表格行数必须等于宣称数(防漏加/多加行) - Category 2 实际回归测试的工具数必须等于宣称数(宣称了就必须测) 已验证这个检查真的会拦:把标题改成 23 款、删掉一行工具表,两种漂移都被抓到。 2) bash 3.2 下 CJK 报错信息乱码(真 bug,只在检查失败时才暴露) macOS 自带 bash 3.2.57 解析标识符时不识别多字节字符,`$file「` 会把「的首字节 (0xE3) 吞进变量名,导致变量展开为空且字符被截断 —— 报错信息变成 「计数不一致: ����= ��应为 22」。写检查的人看不到,因为只有失败时才打印。 复现:bash -c 'f=README.md; echo "文件: $f「标签」结束"' -> 文件: ��标签」结束 修法是给紧跟 CJK 标点的变量加花括号。全仓扫描 `$var` 紧跟非 ASCII 字节的模式, 命中 3 处:audit.sh 2 处(本次新增)、verify-release.sh 1 处(上个提交带进来的, 因为检测项一直全通过所以从没暴露)。修后报错信息可读: 计数不一致: README.md「工具表标题」= 23,应为 22 检测 .clinerules/ -> 得到「Cline」,期望「错误期望值」 3) .gitignore 漏了新工具的安装产物 .trae/、.qoder/ 等都在忽略列表里,但 .cline/、.clinerules/、.kilocode/ 没加 —— 在本仓库内跑安装器自测会留一堆未跟踪文件。已补上并验证 git status 干净。 验证:audit.sh 154 pass / 0 fail(原 130,+24 为 Category 5) verify-release.sh 82 pass / 0 fail --- .gitignore | 3 ++ scripts/audit.sh | 76 +++++++++++++++++++++++++++++++++++++++ scripts/verify-release.sh | 2 +- 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 8f6e23d..ca63f7c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,9 @@ triage/ site/dist/ # 安装器生成的 skills 副本(源在 skills/ 目录) +.cline/ +.clinerules/ +.kilocode/ .codex/skills/ .gemini/skills/ .hermes/skills/ diff --git a/scripts/audit.sh b/scripts/audit.sh index a24e670..688295f 100755 --- a/scripts/audit.sh +++ b/scripts/audit.sh @@ -225,6 +225,82 @@ fi popd >/dev/null rm -rf "$TMP" +#============================================================================== +hdr "Category 5: 工具计数一致性" +#============================================================================== +# 文案里宣称的工具数必须与 installer 实际支持的数量一致。 +# +# 口径说明:installer 的 TARGETS 是「安装目标」;Copilot CLI 与 Claude Code 共用 +# .claude/skills(别名 copilot -> Claude Code),在 TARGETS 里不占独立条目,但文案 +# 里作为独立产品单独计数 —— 所以「文案工具数 = TARGETS 条目数 + 1」。 +# +# 加新工具时最容易漏改文案:计数散落在简繁 README、package.json、CLAUDE.md、 +# site/build.mjs、3 份 plugin manifest 十几处。这一类检查专门堵这个。 + +TARGET_COUNT=$(sed -n '/^const TARGETS = \[/,/^\];/p' "$INSTALLER" | grep -cE "^ \{ name: '") +EXPECTED_TOOLS=$((TARGET_COUNT + 1)) +echo " installer TARGETS = $TARGET_COUNT 个安装目标 -> 文案应宣称 $EXPECTED_TOOLS 款" + +# check_count <文件> <正则> <说明>:正则匹配到的所有数字都必须等于 EXPECTED_TOOLS +check_count() { + local file="$1" re="$2" label="$3" got n + if [ ! -f "$file" ]; then bad "计数检查: $file 不存在"; return; fi + got=$(grep -oE "$re" "$file" 2>/dev/null | grep -oE '[0-9]+' | sort -u) + if [ -z "$got" ]; then + bad "计数检查: ${file} 里没匹配到「${label}」—— 文案改动过?正则需同步更新" + return + fi + for n in $got; do + if [ "$n" != "$EXPECTED_TOOLS" ]; then + bad "计数不一致: ${file}「${label}」= ${n},应为 ${EXPECTED_TOOLS}" + return + fi + done + ok +} + +# ── 简体 README ── +check_count README.md '等 \*\*[0-9]+ 款 AI 编程工具\*\*' '首屏标语' +check_count README.md '\*\*[0-9]+ 款\*\*:上述' '对比表支持工具' +check_count README.md '\*\*\+\*\* [0-9]+ 款工具一键适配' '一句话总结' +check_count README.md '### 🤖 支持 [0-9]+ 款主流' '工具表标题' +check_count README.md '等 [0-9]+ 款工具真正会干活' '页脚标语' +check_count README.md 'across [0-9]+ AI coding tools' '英文简介' + +# ── 繁體 README ── +check_count README.zh-Hant.md '等 \*\*[0-9]+ 款 AI 編程工具\*\*' '首屏標語' +check_count README.zh-Hant.md '\*\*[0-9]+ 款\*\*:上述' '對比表支援工具' +check_count README.zh-Hant.md '\*\*\+\*\* [0-9]+ 款工具一鍵適配' '一句話總結' +check_count README.zh-Hant.md '### 🤖 支援 [0-9]+ 款主流' '工具表標題' +check_count README.zh-Hant.md '等 [0-9]+ 款工具真正會幹活' '頁腳標語' +check_count README.zh-Hant.md 'across [0-9]+ AI coding tools' '英文簡介' + +# ── 元数据与 manifest ── +check_count package.json '等 [0-9]+ 款工具' 'npm description' +check_count CLAUDE.md '支持 [0-9]+ 款 IDE/CLI' '贡献者指南' +check_count .claude-plugin/plugin.json '等 [0-9]+ 款工具' 'plugin manifest' +check_count .claude-plugin/marketplace.json '等 [0-9]+ 款工具' 'marketplace manifest' +check_count .cursor-plugin/plugin.json '等 [0-9]+ 款工具' 'cursor manifest' + +# ── 官网(三语言) ── +check_count site/build.mjs '[0-9]+ 款 AI 编程工具装上' '官网简体标语' +check_count site/build.mjs '[0-9]+ 款 AI 編程工具裝上' '官网繁體標語' +check_count site/build.mjs '共 [0-9]+ 款:' '官网 FAQ 枚举' +check_count site/build.mjs 'into [0-9]+ AI coding tools' '官网英文标语' +check_count site/build.mjs '^ \{ q: .Which AI coding tools are supported.*[0-9]+ tools:' '官网英文 FAQ' + +# ── 结构性检查:README 工具表的实际行数 ── +rows=$(awk '/^### 🤖 支持 [0-9]+ 款主流/,/^> 运行 `npx/' README.md | grep -cE '^\| \[') +if [ "$rows" = "$EXPECTED_TOOLS" ]; then ok; else + bad "README 工具表有 $rows 行,应为 $EXPECTED_TOOLS 行(漏加/多加了表格行)" +fi + +# ── 自检:Category 2 测的工具数应等于宣称数(宣称了就必须测) ── +tools_tested=$(grep -oE '^declare -a TOOLS=\(.*\)' "$0" | sed -E 's/^declare -a TOOLS=\(//; s/\)$//' | wc -w | tr -d ' ') +if [ "$tools_tested" = "$EXPECTED_TOOLS" ]; then ok; else + bad "Category 2 只测了 $tools_tested 款,但文案宣称 $EXPECTED_TOOLS 款(宣称的工具必须都有回归测试)" +fi + #============================================================================== echo "" echo "==========================================" diff --git a/scripts/verify-release.sh b/scripts/verify-release.sh index 6f8022f..2c822a1 100755 --- a/scripts/verify-release.sh +++ b/scripts/verify-release.sh @@ -90,7 +90,7 @@ for entry in "${DETECT[@]}"; do T=$(mktemp -d); cd "$T"; mkdir -p "$marker" got=$(node "$INS" 2>&1 | grep -oE '✅ [A-Za-z][A-Za-z ]*(\[|:)' | sed 's/✅ //; s/ *[:[]$//' | sort -u | tr '\n' ',' | sed 's/,$//') if [ "$got" != "$want" ]; then - bad "检测 $marker/ -> 得到「$got」,期望「$want」" + bad "检测 ${marker}/ -> 得到「${got}」,期望「${want}」" else ok fi