From 1081cefc425a361fefc822b3c74b97cee6ea5855 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: Wed, 2 Sep 2026 21:19:58 +0800
Subject: [PATCH] =?UTF-8?q?fix(docs,site):=20README=20=E6=8A=8A=202=20?=
=?UTF-8?q?=E4=B8=AA=E4=B8=8A=E6=B8=B8=20skill=20=E7=AE=97=E6=88=90?=
=?UTF-8?q?=E3=80=8C=E4=B8=AD=E5=9B=BD=E7=89=B9=E8=89=B2=E3=80=8D=EF=BC=9B?=
=?UTF-8?q?=E4=BA=8C=E7=BB=B4=E7=A0=81=E7=BC=BA=20height=EF=BC=9B=E5=AE=98?=
=?UTF-8?q?=E7=BD=91=E5=A4=96=E9=93=BE=E6=B2=A1=E4=BA=BA=E9=AA=8C=E6=B4=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
按主站逐项核对时查出的三处,都不是新引入的,是一直没人发现。
## ① README 的「中国特色 Skills(6 个)」与官网自相矛盾
三处口径本来就不一致:
| 位置 | 原来的说法 |
|---|---|
| 官网统计块 | 4 中国原创 |
| `.claude-plugin/plugin.json` | 20 个 skills(14 翻译 + 4 中国原创 + 2 上游历史保留)|
| 两版 README | **6 个中国特色 Skills** ← 只有它是 6 |
README 把 `mcp-builder` 和 `workflow-runner` 也算进了「中国特色」。用 GitHub API 核过:
**上游 obra/superpowers 现有 14 个 skill,本仓 20 个,多出的正是 4 个 `chinese-*` 加这两个。**
它们来自上游、上游后来移除、本 fork 保留继续维护 —— 跟中国特色没有任何关系,把它们
算成中国原创等于虚报了 50% 的原创量。
改:规模表列名改「中国原创 Skills」值改 4(附注另有 2 个上游历史保留);小节标题拆成
「中国原创(4 个)· 上游历史保留(2 个)」;表格里这两行的「上游有吗?」由「无」改为
「曾有,上游已移除」——原来写「无」会被读成「我们原创的」,正是错误的来源。简繁同步。
(`using-superpowers` 正文里的「中国特色技能路由」是真实存在的小节名,不动。)
## ② 页脚三个二维码缺 height,加载时把页脚顶下去
`` 没有 height,浏览器算不出宽高比,图一到位就发生布局偏移(CLS)。
赞助商 banner 和 logo 都是齐的,只有二维码漏了。
没有写死数字,而是新增零依赖的 `imageSize()`(PNG 读 IHDR、JPEG 逐段找 SOFn),
构建时从文件读真实尺寸:258×258 / 1125×1680 / 316×316,与 `sips` 实测逐一吻合。
换二维码时属性自动跟随,不会悄悄退回错的比例。
顺带用同一个函数补了一条门禁:**赞助商声明的 `w`/`h` 必须与素材真实尺寸一致** ——
换了 banner 忘了改数字,页面就会按错的宽高比预留位置。
## ③ 外链验活门禁扫不到官网,三条付费展位链接一直无人看守
`verify-release` H 段只扫 `docs/*.md` 与两版 README,`site/build.mjs` 不在列。也就是
旗舰赞助商与两个常规位的推广链接挂掉了不会有任何人知道 —— 而这是要赔的。
扫描范围加上 `site/build.mjs`,并把 `compshare|cubence` 移出排除名单(原来被当噪音跳过),
正则补 `?=&` 让带 aff/referral 参数的推广链接被完整验证而不是截断到路径。
覆盖链接 45 → 52 条。
排除名单新增 `googletagmanager|google-analytics`:它们在 build.mjs 里是 **CSP 白名单条目
不是链接**,裸域 `googletagmanager.com` 实测返回 404,纳入等于凭空造一条误报 ——
这条门禁最忌讳的就是误报。
## 反向验证(三条逐一造错,必须拦下)
- 把官网的 book.aibuzhiyu.com 改成不存在的路径 -> `死链(404)`,FAIL 1
- 把 infistar banner 的 w/h 改成 800×368 -> 构建退出码 1,
`banner 尺寸对不上:声明 800×368,实际 1269×337`
- 二维码尺寸不再有写死数字(`width="158"` 已从源码消失)
## 全量测试
官网 66 页构建 / 站内死链 0 / 无效 href="#" 0 / **缺 height 的 img 0**(原为 3);
audit 170 pass 0 fail;verify-release 115 pass 0 fail;CI 等价 20 skills 0 错误 v1.7.11;
tests/kimi · pi · opencode · brainstorm-server 全 PASS。
---
README.md | 12 ++++++-----
README.zh-Hant.md | 12 ++++++-----
scripts/verify-release.sh | 12 +++++++++--
site/build.mjs | 44 ++++++++++++++++++++++++++++++++++++---
4 files changed, 65 insertions(+), 15 deletions(-)
diff --git a/README.md b/README.md
index 716c050..5d05ae3 100644
--- a/README.md
+++ b/README.md
@@ -27,9 +27,9 @@ Chinese community edition of [superpowers](https://github.com/obra/superpowers)
### 📊 项目规模
-| 📦 翻译 Skills | 🇨🇳 中国特色 Skills | 🤖 支持工具 |
+| 📦 翻译 Skills | 🇨🇳 中国原创 Skills | 🤖 支持工具 |
|:---:|:---:|:---:|
-| **14** | **6** | **Claude Code / Copilot CLI / Hermes Agent / Cursor / Windsurf / Kiro / Gemini CLI / Codex / Aider / Trae / VS Code (Copilot) / DeerFlow / OpenCode / OpenClaw / Qwen Code / Antigravity / Claw Code / Qoder / CodeBuddy(腾讯)/ CodeArts(华为云码道)/ Cline / Kilo Code / Crush** |
+| **14** | **4**
另有 2 个上游历史保留 | **Claude Code / Copilot CLI / Hermes Agent / Cursor / Windsurf / Kiro / Gemini CLI / Codex / Aider / Trae / VS Code (Copilot) / DeerFlow / OpenCode / OpenClaw / Qwen Code / Antigravity / Claw Code / Qoder / CodeBuddy(腾讯)/ CodeArts(华为云码道)/ Cline / Kilo Code / Crush** |
---
@@ -191,10 +191,12 @@ AI:在开始实现之前,我需要了解几个关键问题:
| **编写 Skills** (writing-skills) | 创建新 skill 的方法论 |
| **使用 Superpowers** (using-superpowers) | 元技能:如何调用和优先使用 skills |
-### 🇨🇳 中国特色 Skills(6 个)
+### 🇨🇳 中国原创 Skills(4 个)· 上游历史保留(2 个)
> ⚠️ **下表前 4 个 chinese-\* 为「手动调用」skill**——不会自动触发,需在对话中显式输入 `/chinese-xxx` 才会加载。
> 设计为参考资料而非工作流,避免污染上游 skill 的自动调度(如 `requesting-code-review`、`brainstorming` 等)。
+>
+> ⚠️ **表格最后两个(mcp-builder / workflow-runner)不是中国原创** —— 它们来自上游,上游后来移除了,本 fork 保留下来继续维护。全仓 20 个 skill = 14 翻译 + 4 中国原创 + 2 上游历史保留。
| Skill | 用途 | 调用方式 | 上游有吗? |
|-------|------|---------|:---:|
@@ -202,8 +204,8 @@ AI:在开始实现之前,我需要了解几个关键问题:
| **中文 Git 工作流** (chinese-git-workflow) | 适配 Gitee/Coding/极狐 GitLab/CNB | `/chinese-git-workflow`(手动) | 无 |
| **中文技术文档** (chinese-documentation) | 中文排版规范、中英混排、告别机翻味 | `/chinese-documentation`(手动) | 无 |
| **中文提交规范** (chinese-commit-conventions) | 适配国内团队的 commit message 规范 | `/chinese-commit-conventions`(手动) | 无 |
-| **MCP 服务器构建** (mcp-builder) | 构建生产级 MCP 工具,扩展 AI 能力边界 | 自动 | 无 |
-| **工作流执行器** (workflow-runner) | 在 AI 工具内运行多角色 YAML 工作流 | 自动 | 无 |
+| **MCP 服务器构建** (mcp-builder) | 构建生产级 MCP 工具,扩展 AI 能力边界 | 自动 | 曾有,上游已移除 |
+| **工作流执行器** (workflow-runner) | 在 AI 工具内运行多角色 YAML 工作流 | 自动 | 曾有,上游已移除 |
---
diff --git a/README.zh-Hant.md b/README.zh-Hant.md
index cf7cae4..fd11f86 100644
--- a/README.zh-Hant.md
+++ b/README.zh-Hant.md
@@ -27,9 +27,9 @@ Chinese community edition of [superpowers](https://github.com/obra/superpowers)
### 📊 專案規模
-| 📦 翻譯 Skills | 🇨🇳 中國特色 Skills | 🤖 支援工具 |
+| 📦 翻譯 Skills | 🇨🇳 中國原創 Skills | 🤖 支援工具 |
|:---:|:---:|:---:|
-| **14** | **6** | **Claude Code / Copilot CLI / Hermes Agent / Cursor / Windsurf / Kiro / Gemini CLI / Codex / Aider / Trae / VS Code (Copilot) / DeerFlow / OpenCode / OpenClaw / Qwen Code / Antigravity / Claw Code / Qoder / CodeBuddy(騰訊)/ CodeArts(華為雲碼道)/ Cline / Kilo Code / Crush** |
+| **14** | **4**
另有 2 個上游歷史保留 | **Claude Code / Copilot CLI / Hermes Agent / Cursor / Windsurf / Kiro / Gemini CLI / Codex / Aider / Trae / VS Code (Copilot) / DeerFlow / OpenCode / OpenClaw / Qwen Code / Antigravity / Claw Code / Qoder / CodeBuddy(騰訊)/ CodeArts(華為雲碼道)/ Cline / Kilo Code / Crush** |
---
@@ -191,10 +191,12 @@ AI:在開始實作之前,我需要了解幾個關鍵問題:
| **編寫 Skills** (writing-skills) | 建立新 skill 的方法論 |
| **使用 Superpowers** (using-superpowers) | 元技能:如何呼叫和優先使用 skills |
-### 🇨🇳 中國特色 Skills(6 個)
+### 🇨🇳 中國原創 Skills(4 個)· 上游歷史保留(2 個)
> ⚠️ **下表前 4 個 chinese-\* 為「手動呼叫」skill**——不會自動觸發,需在對話中顯式輸入 `/chinese-xxx` 才會載入。
> 設計為參考資料而非工作流,避免污染上游 skill 的自動排程(如 `requesting-code-review`、`brainstorming` 等)。
+>
+> ⚠️ **表格最後兩個(mcp-builder / workflow-runner)不是中國原創** —— 它們來自上游,上游後來移除了,本 fork 保留下來繼續維護。全倉 20 個 skill = 14 翻譯 + 4 中國原創 + 2 上游歷史保留。
| Skill | 用途 | 呼叫方式 | 上游有嗎? |
|-------|------|---------|:---:|
@@ -202,8 +204,8 @@ AI:在開始實作之前,我需要了解幾個關鍵問題:
| **中文 Git 工作流** (chinese-git-workflow) | 適配 Gitee/Coding/極狐 GitLab/CNB | `/chinese-git-workflow`(手動) | 無 |
| **中文技術文件** (chinese-documentation) | 中文排版規範、中英混排、告別機翻味 | `/chinese-documentation`(手動) | 無 |
| **中文提交規範** (chinese-commit-conventions) | 適配國內團隊的 commit message 規範 | `/chinese-commit-conventions`(手動) | 無 |
-| **MCP 伺服器建置** (mcp-builder) | 建置生產級 MCP 工具,擴展 AI 能力邊界 | 自動 | 無 |
-| **工作流執行器** (workflow-runner) | 在 AI 工具內執行多角色 YAML 工作流 | 自動 | 無 |
+| **MCP 伺服器建置** (mcp-builder) | 建置生產級 MCP 工具,擴展 AI 能力邊界 | 自動 | 曾有,上游已移除 |
+| **工作流執行器** (workflow-runner) | 在 AI 工具內執行多角色 YAML 工作流 | 自動 | 曾有,上游已移除 |
---
diff --git a/scripts/verify-release.sh b/scripts/verify-release.sh
index 047cad5..5fb1567 100755
--- a/scripts/verify-release.sh
+++ b/scripts/verify-release.sh
@@ -259,8 +259,16 @@ if curl -sS -o /dev/null --max-time 5 https://github.com 2>/dev/null; then
# 第一遍并行快扫。注意这一遍**会误报** —— 实测 docs.codeium.com 在 8s 上限下
# 偶发超时,而它其实活着。一个会误报的门禁比没有门禁更糟:人会学会忽略它。
# 所以第一遍只产出「嫌疑名单」,不下结论。
- grep -rhoE "https://[a-zA-Z0-9./_-]+" "$REPO"/docs/*.md "$REPO"/README.md "$REPO"/README.zh-Hant.md 2>/dev/null \
- | grep -viE "jnmetacode|aiolaola|user-images|shields\.io|opensource\.org|makeapullrequest|npmjs\.com|compshare|cubence|claude\.ai/code" \
+ # 扫描范围含 site/build.mjs:官网的外链此前完全没人验活,而其中三条是**付费展位**的
+ # 推广链接(旗舰 + 两个常规位)—— 赞助链接挂掉是要赔的,比文档死链更该守。
+ # 正则含 ?=& :推广链接的 aff / referral 参数在 query 里,截断了就等于没验真正那条。
+ # 排除项说明:
+ # jnmetacode / aiolaola —— 自家域名(含站点自引用),挂了自己会先知道
+ # npmjs / shields / user-images / opensource / makeapullrequest —— 已知对爬虫不友好或纯徽章
+ # googletagmanager / google-analytics —— 它们在 build.mjs 里是 **CSP 白名单条目**不是链接;
+ # 裸域 googletagmanager.com 本身返回 404,纳入就是凭空造一条误报
+ grep -rhoE "https://[a-zA-Z0-9./_?=&-]+" "$REPO"/docs/*.md "$REPO"/README.md "$REPO"/README.zh-Hant.md "$REPO"/site/build.mjs 2>/dev/null \
+ | grep -viE "jnmetacode|aiolaola|user-images|shields\.io|opensource\.org|makeapullrequest|npmjs\.com|claude\.ai/code|googletagmanager|google-analytics" \
| sed 's/[.,)]*$//' | sort -u \
| xargs -P 10 -I{} sh -c 'c=$(curl -sS -o /dev/null -w "%{http_code}" -L --max-time 8 "$1" 2>/dev/null); case "$c" in 2*|3*|401|403|405|429) ;; *) echo "$1" ;; esac' _ {} \
> "$LINKTMP" 2>/dev/null
diff --git a/site/build.mjs b/site/build.mjs
index 5043e48..74bd908 100644
--- a/site/build.mjs
+++ b/site/build.mjs
@@ -24,11 +24,42 @@ const PKG = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8'));
const cssVer = createHash('sha256').update(readFileSync(join(TEMPLATE, 'styles.css'))).digest('hex').slice(0, 10);
const jsVer = createHash('sha256').update(readFileSync(join(TEMPLATE, 'app.js'))).digest('hex').slice(0, 10);
+// 页脚二维码的真实像素尺寸,构建时从文件读取(见 imageSize 的注释)
+const QR = {
+ wechat: imageSize(join(TEMPLATE, 'assets', 'qr-wechat.jpg')),
+ douyin: imageSize(join(TEMPLATE, 'assets', 'qr-douyin.jpg')),
+ x: imageSize(join(TEMPLATE, 'assets', 'qr-x.png')),
+};
+
// SEO:站点根 URL(用于 canonical / hreflang / og:url / sitemap)
const SITE_URL = 'https://sp.aiolaola.com';
// 仓库源码基址(skill 详情页的相对链接解析到这里)
const GH_BLOB = 'https://github.com/jnMetaCode/superpowers-zh/blob/main';
+// 读 PNG / JPEG 的真实像素尺寸(零依赖)。
+// 用途: 必须带 width+height,浏览器才能在图加载前按宽高比预留位置,
+// 否则图一到位就把下面的内容顶下去(CLS)。页脚三个二维码此前只有 width。
+// 不写死数字而是读文件:换二维码时属性自动跟着变,不会悄悄变回错的比例。
+function imageSize(file) {
+ const b = readFileSync(file);
+ if (b.length > 24 && b[0] === 0x89 && b[1] === 0x50) { // PNG: IHDR 定长在头部
+ return { w: b.readUInt32BE(16), h: b.readUInt32BE(20) };
+ }
+ if (b[0] === 0xff && b[1] === 0xd8) { // JPEG: 逐段找 SOFn
+ let i = 2;
+ while (i < b.length - 9) {
+ if (b[i] !== 0xff) { i++; continue; }
+ const m = b[i + 1];
+ // SOF0-SOF3 / SOF5-SOF7 / SOF9-SOF11 / SOF13-SOF15 都带尺寸;DHT(c4)/JPG(c8)/DAC(cc) 不是
+ if (m >= 0xc0 && m <= 0xcf && m !== 0xc4 && m !== 0xc8 && m !== 0xcc) {
+ return { h: b.readUInt16BE(i + 5), w: b.readUInt16BE(i + 7) };
+ }
+ i += 2 + b.readUInt16BE(i + 2);
+ }
+ }
+ throw new Error(`无法解析图片尺寸:${file}`);
+}
+
const esc = s => String(s).replace(/&/g, '&').replace(//g, '>');
// ---- frontmatter 解析 ----
@@ -246,6 +277,13 @@ function assertSponsors() {
if (!existsSync(join(ROOT, 'assets', 'sponsors', f))) {
throw new Error(`赞助商 ${s.name?.zh || '?'} 的素材不存在:assets/sponsors/${f}`);
}
+ // 声明的 w/h 必须与素材真实尺寸一致 —— 换了图忘了改数字,页面就按错的宽高比预留位置
+ if (f === s.img) {
+ const real = imageSize(join(ROOT, 'assets', 'sponsors', f));
+ if (real.w !== s.w || real.h !== s.h) {
+ throw new Error(`赞助商 ${s.name?.zh || '?'} 的 banner 尺寸对不上:声明 ${s.w}×${s.h},实际 ${real.w}×${real.h}`);
+ }
+ }
}
const textKeys = s.tier === 'flagship'
? ['name', 'tagline', 'alt', 'perk', 'perkShort']
@@ -772,9 +810,9 @@ ${body}