diff --git a/docs/consultant-review/AUDIT-TRACKER.md b/docs/consultant-review/AUDIT-TRACKER.md index 2b9007b..d8d9a33 100644 --- a/docs/consultant-review/AUDIT-TRACKER.md +++ b/docs/consultant-review/AUDIT-TRACKER.md @@ -1,7 +1,7 @@ # 全站文章顾问审阅状态总控台 (Audit Tracker) -> **最后同步时间**:2026-10-27 05:36:05 -> **全站总文章数**:91 篇 | **已审批完成**:74 篇 (81.3%) | **待审阅**:17 篇 +> **最后同步时间**:2026-10-27 06:09:07 +> **全站总文章数**:91 篇 | **已审批完成**:86 篇 (94.5%) | **待审阅**:5 篇 ## 一、操作命令速查 - `python scripts/manage_review.py list` — 查看待审与已审概览 @@ -70,17 +70,17 @@ | 56 | `devops` | `when-smart-says-healthy-but-your-raid-is-corrupting-data` | SMART 显示健康,RAID 却在悄悄损坏数据 | ✅ 已通过 | Batch-02 | 2026-10-27 05:21 | 外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理) | | 57 | `devops` | `why-chrome-forgets-its-tabs-in-a-container` | 为什么容器里的 Chrome 会忘记标签页 —— 以及我是怎么修好的 | ✅ 已通过 | Batch-02 | 2026-10-27 05:21 | 外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理) | | 58 | `devops` | `why-telegram-bot-notifications-die` | Telegram 机器人通知为什么发不出去:IPv6、DNS 和一个追查了一整天的 400 | ✅ 已通过 | Batch-02 | 2026-10-27 05:23 | 外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理) | -| 59 | `devops` | `why-your-cdp-clicks-silently-fail` | 为什么你的 CDP 点击会静默失效:平滑滚动、最小化窗口与 JS 派发事件 | ⏳ 待审阅 | Batch-01 | - | | -| 60 | `devops` | `why-your-grafana-dashboard-shows-no-data` | Prometheus 明明有数据,Grafana 面板却全是 No data 的原因 | ⏳ 待审阅 | Batch-01 | - | | -| 61 | `devops` | `your-disk-full-alert-is-lying` | 你的“磁盘将满”告警在说谎:别再按百分比告警 | ⏳ 待审阅 | Batch-01 | - | | -| 62 | `engineering` | `adding-english-mode-to-a-chinese-only-web-app` | 浏览器翻译没有 API:我给一个纯中文网页应用加上了英文模式 | ⏳ 待审阅 | Batch-01 | - | | -| 63 | `engineering` | `debugging-remotion-video-jitter` | 排查 Remotion 视频抽搐:为什么在背景图挂载音频低频 Scale 会毁了转场 | ⏳ 待审阅 | Batch-01 | - | | -| 64 | `engineering` | `embedding-fonts-so-a-pdf-looks-the-same-everywhere` | 把字体嵌进 PDF,让它在任何机器上都长一样 | ⏳ 待审阅 | Batch-01 | - | | -| 65 | `engineering` | `jpa-version-field-lost-update` | 那个把静默丢失更新变成 409 的 JPA 字段:@Version 乐观锁 | ⏳ 待审阅 | Batch-01 | - | | -| 66 | `engineering` | `migrating-codeigniter-iis-to-openlitespeed` | 把 CodeIgniter 4 应用从 IIS 迁移到 OpenLiteSpeed | ⏳ 待审阅 | Batch-01 | - | | -| 67 | `engineering` | `scraping-bot-walled-marketplace-warm-browser-session` | 用「热浏览器会话」爬取有反爬墙的电商网站 | ⏳ 待审阅 | Batch-01 | - | | -| 68 | `engineering` | `two-ways-a-javascript-file-stops-working-and-looks-fine` | JavaScript 文件静默失效的两种方式:而页面看上去一切正常 | ⏳ 待审阅 | Batch-01 | - | | -| 69 | `engineering` | `verifying-a-pdf-report-page-by-page` | 逐页验证一份 19 页的 PDF 报告 | ⏳ 待审阅 | Batch-01 | - | | +| 59 | `devops` | `why-your-cdp-clicks-silently-fail` | 为什么你的 CDP 点击会静默失效:平滑滚动、最小化窗口与 JS 派发事件 | ✅ 已通过 | Batch-01 | 2026-10-27 06:09 | 第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐) | +| 60 | `devops` | `why-your-grafana-dashboard-shows-no-data` | Prometheus 明明有数据,Grafana 面板却全是 No data 的原因 | ✅ 已通过 | Batch-01 | 2026-10-27 06:09 | 第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐) | +| 61 | `devops` | `your-disk-full-alert-is-lying` | 你的“磁盘将满”告警在说谎:别再按百分比告警 | ✅ 已通过 | Batch-01 | 2026-10-27 06:09 | 第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐) | +| 62 | `engineering` | `adding-english-mode-to-a-chinese-only-web-app` | 浏览器翻译没有 API:我给一个纯中文网页应用加上了英文模式 | ✅ 已通过 | Batch-01 | 2026-10-27 06:09 | 第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐) | +| 63 | `engineering` | `debugging-remotion-video-jitter` | 排查 Remotion 视频抽搐:为什么在背景图挂载音频低频 Scale 会毁了转场 | ✅ 已通过 | Batch-01 | 2026-10-27 06:09 | 第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐) | +| 64 | `engineering` | `embedding-fonts-so-a-pdf-looks-the-same-everywhere` | 把字体嵌进 PDF,让它在任何机器上都长一样 | ✅ 已通过 | Batch-01 | 2026-10-27 06:09 | 第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐) | +| 65 | `engineering` | `jpa-version-field-lost-update` | 那个把静默丢失更新变成 409 的 JPA 字段:@Version 乐观锁 | ✅ 已通过 | Batch-01 | 2026-10-27 06:09 | 第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐) | +| 66 | `engineering` | `migrating-codeigniter-iis-to-openlitespeed` | 把 CodeIgniter 4 应用从 IIS 迁移到 OpenLiteSpeed | ✅ 已通过 | Batch-01 | 2026-10-27 06:09 | 第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐) | +| 67 | `engineering` | `scraping-bot-walled-marketplace-warm-browser-session` | 用「热浏览器会话」爬取有反爬墙的电商网站 | ✅ 已通过 | Batch-01 | 2026-10-27 06:09 | 第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐) | +| 68 | `engineering` | `two-ways-a-javascript-file-stops-working-and-looks-fine` | JavaScript 文件静默失效的两种方式:而页面看上去一切正常 | ✅ 已通过 | Batch-01 | 2026-10-27 06:09 | 第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐) | +| 69 | `engineering` | `verifying-a-pdf-report-page-by-page` | 逐页验证一份 19 页的 PDF 报告 | ✅ 已通过 | Batch-01 | 2026-10-27 06:09 | 第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐) | | 70 | `engineering` | `why-500000-lines-of-commit-churn-only-left-230000-in-production` | 30 天提交 51.8 万行,生产环境只留下 23.5 万行 | ✅ 已通过 | Batch-04 | 2026-10-27 05:21 | 外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理) | | 71 | `notes` | `adding-a-domain-to-someone-elses-mail-server` | 给别人家的邮件服务器加一个域名 | ✅ 已通过 | Batch-04 | 2026-10-27 05:21 | 外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理) | | 72 | `notes` | `hello-world` | 你好,世界 —— 关于这个博客 | ✅ 已通过 | Batch-04 | 2026-10-27 05:21 | 外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理) | @@ -97,9 +97,9 @@ | 83 | `notes` | `why-your-windows-mcp-calls-silently-fail` | 为什么你的 Windows 桌面 MCP 调用会静默失败:攻破 10 秒空闲门禁与避坑实录 | ✅ 已通过 | Batch-04 | 2026-10-27 05:21 | 外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理) | | 84 | `tutorials` | `calibrating-intel-quick-sync-hevc-quality` | 校准 Intel Quick Sync HEVC:28 与 30 之间的悬崖,和一个毫无作用的 preset | ✅ 已通过 | Batch-04 | 2026-10-27 05:21 | 外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理) | | 85 | `tutorials` | `does-hevc-actually-shrink-your-files` | 转成 HEVC 到底会不会让文件变小?我实测了 | ✅ 已通过 | Batch-04 | 2026-10-27 05:21 | 外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理) | -| 86 | `tutorials` | `generating-full-length-songs-with-yue2-comfyui` | 用 YuE2 BF16 生成完整长歌:突破时长限制与音频硬截断 | ⏳ 待审阅 | Batch-03 | - | | -| 87 | `tutorials` | `generating-subtitles-for-songs-without-timestamps` | 给没有时间戳的歌曲自动生成字幕 | ⏳ 待审阅 | Batch-04 | - | | -| 88 | `tutorials` | `how-to-verify-a-hosting-provider-before-you-buy` | 购买主机前,如何核实一家服务商的真实情况 | ⏳ 待审阅 | Batch-04 | - | | -| 89 | `web3` | `chainlink-vrf-v2-lottery-contract` | 一个基于 Chainlink VRF v2.5 与 Automation 的自动化彩票合约 | ⏳ 待审阅 | Batch-04 | - | | -| 90 | `web3` | `fully-on-chain-svg-nfts` | 全链上 SVG NFT:把艺术作品放进合约里 | ⏳ 待审阅 | Batch-04 | - | | -| 91 | `web3` | `why-my-on-chain-nft-art-changed-on-windows` | 为什么在 Windows 上克隆后,我的链上 NFT 图像变了 | ⏳ 待审阅 | Batch-04 | - | | +| 86 | `tutorials` | `generating-full-length-songs-with-yue2-comfyui` | 用 YuE2 BF16 生成完整长歌:突破时长限制与音频硬截断 | ✅ 已通过 | Batch-03 | 2026-10-27 06:04 | 第3批微调项落地并通过:时长校正283.1s/单调时间戳与防死锁/专业人设去二次元俚语/B2B转化增强 | +| 87 | `tutorials` | `generating-subtitles-for-songs-without-timestamps` | 给没有时间戳的歌曲自动生成字幕 | ⏳ 待审阅 | Batch-02 | - | | +| 88 | `tutorials` | `how-to-verify-a-hosting-provider-before-you-buy` | 购买主机前,如何核实一家服务商的真实情况 | ⏳ 待审阅 | Batch-02 | - | | +| 89 | `web3` | `chainlink-vrf-v2-lottery-contract` | 一个基于 Chainlink VRF v2.5 与 Automation 的自动化彩票合约 | ⏳ 待审阅 | Batch-02 | - | | +| 90 | `web3` | `fully-on-chain-svg-nfts` | 全链上 SVG NFT:把艺术作品放进合约里 | ⏳ 待审阅 | Batch-02 | - | | +| 91 | `web3` | `why-my-on-chain-nft-art-changed-on-windows` | 为什么在 Windows 上克隆后,我的链上 NFT 图像变了 | ⏳ 待审阅 | Batch-02 | - | | diff --git a/docs/consultant-review/audit-tracker.json b/docs/consultant-review/audit-tracker.json index b87a131..c34aa8a 100644 --- a/docs/consultant-review/audit-tracker.json +++ b/docs/consultant-review/audit-tracker.json @@ -18,12 +18,12 @@ "zh_title": "浏览器翻译没有 API:我给一个纯中文网页应用加上了英文模式", "category": "engineering", "pub_date": "2025-06-11", - "status": "pending", + "status": "approved", "batch_id": "Batch-01", - "approved_at": null, - "notes": "", - "en_chars": 11859, - "zh_chars": 6211 + "approved_at": "2026-10-27 06:09", + "notes": "第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐)", + "en_chars": 11914, + "zh_chars": 6253 }, "ai-furniture-compositing-with-flux-kontext": { "slug": "ai-furniture-compositing-with-flux-kontext", @@ -123,11 +123,11 @@ "category": "web3", "pub_date": "2024-12-10", "status": "pending", - "batch_id": "Batch-04", + "batch_id": "Batch-02", "approved_at": null, "notes": "", - "en_chars": 15801, - "zh_chars": 9443 + "en_chars": 16252, + "zh_chars": 9707 }, "debugging-remotion-video-jitter": { "slug": "debugging-remotion-video-jitter", @@ -135,12 +135,12 @@ "zh_title": "排查 Remotion 视频抽搐:为什么在背景图挂载音频低频 Scale 会毁了转场", "category": "engineering", "pub_date": "2025-11-26", - "status": "pending", + "status": "approved", "batch_id": "Batch-01", - "approved_at": null, - "notes": "", - "en_chars": 9584, - "zh_chars": 5527 + "approved_at": "2026-10-27 06:09", + "notes": "第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐)", + "en_chars": 9836, + "zh_chars": 5653 }, "docker-reported-exit-0-the-oom-killer-disagreed": { "slug": "docker-reported-exit-0-the-oom-killer-disagreed", @@ -173,13 +173,13 @@ "title": "Embedding Fonts So a PDF Looks the Same on Every Machine", "zh_title": "把字体嵌进 PDF,让它在任何机器上都长一样", "category": "engineering", - "pub_date": "2025-01-22", - "status": "pending", + "pub_date": "2026-10-15", + "status": "approved", "batch_id": "Batch-01", - "approved_at": null, - "notes": "", - "en_chars": 8033, - "zh_chars": 3432 + "approved_at": "2026-10-27 06:09", + "notes": "第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐)", + "en_chars": 8591, + "zh_chars": 3747 }, "every-player-stuttered-the-file-was-fine": { "slug": "every-player-stuttered-the-file-was-fine", @@ -227,11 +227,11 @@ "category": "web3", "pub_date": "2024-10-08", "status": "pending", - "batch_id": "Batch-04", + "batch_id": "Batch-02", "approved_at": null, "notes": "", - "en_chars": 14598, - "zh_chars": 9407 + "en_chars": 16205, + "zh_chars": 10281 }, "generating-full-length-songs-with-yue2-comfyui": { "slug": "generating-full-length-songs-with-yue2-comfyui", @@ -239,12 +239,12 @@ "zh_title": "用 YuE2 BF16 生成完整长歌:突破时长限制与音频硬截断", "category": "tutorials", "pub_date": "2026-10-26", - "status": "pending", + "status": "approved", "batch_id": "Batch-03", - "approved_at": null, - "notes": "", - "en_chars": 131667, - "zh_chars": 128681 + "approved_at": "2026-10-27 06:04", + "notes": "第3批微调项落地并通过:时长校正283.1s/单调时间戳与防死锁/专业人设去二次元俚语/B2B转化增强", + "en_chars": 134821, + "zh_chars": 127730 }, "generating-subtitles-for-songs-without-timestamps": { "slug": "generating-subtitles-for-songs-without-timestamps", @@ -253,11 +253,11 @@ "category": "tutorials", "pub_date": "2026-10-20", "status": "pending", - "batch_id": "Batch-04", + "batch_id": "Batch-02", "approved_at": null, "notes": "", - "en_chars": 46399, - "zh_chars": 42221 + "en_chars": 47487, + "zh_chars": 42626 }, "giving-ai-your-mouse-and-keyboard-safely": { "slug": "giving-ai-your-mouse-and-keyboard-safely", @@ -370,11 +370,11 @@ "category": "tutorials", "pub_date": "2025-11-26", "status": "pending", - "batch_id": "Batch-04", + "batch_id": "Batch-02", "approved_at": null, "notes": "", - "en_chars": 6743, - "zh_chars": 2906 + "en_chars": 7567, + "zh_chars": 3351 }, "i-let-an-agent-manage-my-shopee-vouchers": { "slug": "i-let-an-agent-manage-my-shopee-vouchers", @@ -408,12 +408,12 @@ "zh_title": "那个把静默丢失更新变成 409 的 JPA 字段:@Version 乐观锁", "category": "engineering", "pub_date": "2026-08-19", - "status": "pending", + "status": "approved", "batch_id": "Batch-01", - "approved_at": null, - "notes": "", - "en_chars": 12217, - "zh_chars": 7358 + "approved_at": "2026-10-27 06:09", + "notes": "第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐)", + "en_chars": 12536, + "zh_chars": 7506 }, "loop-engineering-without-a-coding-agent": { "slug": "loop-engineering-without-a-coding-agent", @@ -434,12 +434,12 @@ "zh_title": "把 CodeIgniter 4 应用从 IIS 迁移到 OpenLiteSpeed", "category": "engineering", "pub_date": "2026-09-27", - "status": "pending", + "status": "approved", "batch_id": "Batch-01", - "approved_at": null, - "notes": "", + "approved_at": "2026-10-27 06:09", + "notes": "第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐)", "en_chars": 14943, - "zh_chars": 8418 + "zh_chars": 8425 }, "my-backup-was-using-someone-elses-api-quota": { "slug": "my-backup-was-using-someone-elses-api-quota", @@ -655,12 +655,12 @@ "zh_title": "用「热浏览器会话」爬取有反爬墙的电商网站", "category": "engineering", "pub_date": "2026-09-13", - "status": "pending", + "status": "approved", "batch_id": "Batch-01", - "approved_at": null, - "notes": "", - "en_chars": 11245, - "zh_chars": 5683 + "approved_at": "2026-10-27 06:09", + "notes": "第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐)", + "en_chars": 11313, + "zh_chars": 5734 }, "self-healing-digital-goods-entitlements": { "slug": "self-healing-digital-goods-entitlements", @@ -763,8 +763,8 @@ "batch_id": "Batch-02", "approved_at": "2026-10-27 05:21", "notes": "外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理)", - "en_chars": 6475, - "zh_chars": 3424 + "en_chars": 6574, + "zh_chars": 3505 }, "stop-writing-agent-prompts-for-deterministic-work": { "slug": "stop-writing-agent-prompts-for-deterministic-work", @@ -815,8 +815,8 @@ "batch_id": "Batch-02", "approved_at": "2026-10-27 05:21", "notes": "外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理)", - "en_chars": 15961, - "zh_chars": 9131 + "en_chars": 16101, + "zh_chars": 9200 }, "that-dying-ssd-was-just-a-bad-sata-cable": { "slug": "that-dying-ssd-was-just-a-bad-sata-cable", @@ -828,8 +828,8 @@ "batch_id": "Batch-02", "approved_at": "2026-10-27 05:21", "notes": "外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理)", - "en_chars": 7128, - "zh_chars": 3785 + "en_chars": 7471, + "zh_chars": 3940 }, "the-cause-was-trim-not-the-ssds": { "slug": "the-cause-was-trim-not-the-ssds", @@ -841,8 +841,8 @@ "batch_id": "Batch-02", "approved_at": "2026-10-27 05:21", "notes": "外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理)", - "en_chars": 12427, - "zh_chars": 7072 + "en_chars": 13042, + "zh_chars": 7310 }, "the-nocodb-attachment-that-wouldnt-update": { "slug": "the-nocodb-attachment-that-wouldnt-update", @@ -880,8 +880,8 @@ "batch_id": "Batch-02", "approved_at": "2026-10-27 05:21", "notes": "外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理)", - "en_chars": 11554, - "zh_chars": 5159 + "en_chars": 11636, + "zh_chars": 5229 }, "two-ways-a-javascript-file-stops-working-and-looks-fine": { "slug": "two-ways-a-javascript-file-stops-working-and-looks-fine", @@ -889,12 +889,12 @@ "zh_title": "JavaScript 文件静默失效的两种方式:而页面看上去一切正常", "category": "engineering", "pub_date": "2025-02-20", - "status": "pending", + "status": "approved", "batch_id": "Batch-01", - "approved_at": null, - "notes": "", - "en_chars": 7750, - "zh_chars": 3544 + "approved_at": "2026-10-27 06:09", + "notes": "第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐)", + "en_chars": 8293, + "zh_chars": 3881 }, "unraid-stop-array-hangs-on-swapfile": { "slug": "unraid-stop-array-hangs-on-swapfile", @@ -906,8 +906,8 @@ "batch_id": "Batch-02", "approved_at": "2026-10-27 05:21", "notes": "外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理)", - "en_chars": 10151, - "zh_chars": 6226 + "en_chars": 10470, + "zh_chars": 6376 }, "upgrading-codeigniter-46-to-47": { "slug": "upgrading-codeigniter-46-to-47", @@ -932,8 +932,8 @@ "batch_id": "Batch-02", "approved_at": "2026-10-27 05:21", "notes": "外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理)", - "en_chars": 11122, - "zh_chars": 7070 + "en_chars": 11267, + "zh_chars": 7173 }, "using-chinese-llm-apis-from-malaysia": { "slug": "using-chinese-llm-apis-from-malaysia", @@ -954,10 +954,10 @@ "zh_title": "逐页验证一份 19 页的 PDF 报告", "category": "engineering", "pub_date": "2026-09-28", - "status": "pending", + "status": "approved", "batch_id": "Batch-01", - "approved_at": null, - "notes": "", + "approved_at": "2026-10-27 06:09", + "notes": "第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐)", "en_chars": 12525, "zh_chars": 6685 }, @@ -984,8 +984,8 @@ "batch_id": "Batch-02", "approved_at": "2026-10-27 05:21", "notes": "外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理)", - "en_chars": 13283, - "zh_chars": 5858 + "en_chars": 14160, + "zh_chars": 6246 }, "when-to-give-your-agent-physical-clicks": { "slug": "when-to-give-your-agent-physical-clicks", @@ -1023,8 +1023,8 @@ "batch_id": "Batch-02", "approved_at": "2026-10-27 05:21", "notes": "外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理)", - "en_chars": 14876, - "zh_chars": 8947 + "en_chars": 15430, + "zh_chars": 9234 }, "why-i-built-a-video-knowledge-base": { "slug": "why-i-built-a-video-knowledge-base", @@ -1085,11 +1085,11 @@ "category": "web3", "pub_date": "2026-08-19", "status": "pending", - "batch_id": "Batch-04", + "batch_id": "Batch-02", "approved_at": null, "notes": "", - "en_chars": 7725, - "zh_chars": 4260 + "en_chars": 8423, + "zh_chars": 4585 }, "why-telegram-bot-notifications-die": { "slug": "why-telegram-bot-notifications-die", @@ -1101,8 +1101,8 @@ "batch_id": "Batch-02", "approved_at": "2026-10-27 05:23", "notes": "外部顾问审阅完成,已采纳并落地全量修改意见(含数字矛盾/OPSEC脱敏/双语CTA/排版折叠/禁用词清理)", - "en_chars": 9678, - "zh_chars": 5450 + "en_chars": 10753, + "zh_chars": 6005 }, "why-your-cdp-clicks-silently-fail": { "slug": "why-your-cdp-clicks-silently-fail", @@ -1110,12 +1110,12 @@ "zh_title": "为什么你的 CDP 点击会静默失效:平滑滚动、最小化窗口与 JS 派发事件", "category": "devops", "pub_date": "2025-03-19", - "status": "pending", + "status": "approved", "batch_id": "Batch-01", - "approved_at": null, - "notes": "", - "en_chars": 8010, - "zh_chars": 4504 + "approved_at": "2026-10-27 06:09", + "notes": "第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐)", + "en_chars": 8054, + "zh_chars": 4536 }, "why-your-grafana-dashboard-shows-no-data": { "slug": "why-your-grafana-dashboard-shows-no-data", @@ -1123,12 +1123,12 @@ "zh_title": "Prometheus 明明有数据,Grafana 面板却全是 No data 的原因", "category": "devops", "pub_date": "2026-05-17", - "status": "pending", + "status": "approved", "batch_id": "Batch-01", - "approved_at": null, - "notes": "", - "en_chars": 7347, - "zh_chars": 3865 + "approved_at": "2026-10-27 06:09", + "notes": "第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐)", + "en_chars": 7456, + "zh_chars": 3919 }, "why-your-headless-browser-cant-scrape-everything": { "slug": "why-your-headless-browser-cant-scrape-everything", @@ -1162,12 +1162,12 @@ "zh_title": "你的“磁盘将满”告警在说谎:别再按百分比告警", "category": "devops", "pub_date": "2026-06-24", - "status": "pending", + "status": "approved", "batch_id": "Batch-01", - "approved_at": null, - "notes": "", - "en_chars": 5930, - "zh_chars": 2982 + "approved_at": "2026-10-27 06:09", + "notes": "第一批外部顾问审阅完成,已全量采纳并落地修改(含数字矛盾纠正/OPSEC与禁用词清理/并发异常409映射/双语CTA补齐)", + "en_chars": 6139, + "zh_chars": 3090 }, "yue2-on-a-12gb-gpu-songs-that-lost-their-endings": { "slug": "yue2-on-a-12gb-gpu-songs-that-lost-their-endings", diff --git a/docs/consultant-review/batches/batch-01.md b/docs/consultant-review/batches/batch-01.md index 1230356..ad58406 100644 --- a/docs/consultant-review/batches/batch-01.md +++ b/docs/consultant-review/batches/batch-01.md @@ -2,9 +2,9 @@ > **批次编号**:`Batch-01` > **包含文章数**:11 篇 -> **本批次总字符量**:167,652 字(严格限制 < 200,000 字) +> **本批次总字符量**:170,149 字(严格限制 < 200,000 字) > **模式**:BILINGUAL -> **生成时间**:2026-10-27 05:36:05 +> **生成时间**:2026-10-27 06:05:52 # 外部顾问审阅前置须知与工程背景规范 @@ -39,15 +39,15 @@ ## 本批次文章目录索引 -1. [devops] **为什么你的 CDP 点击会静默失效:平滑滚动、最小化窗口与 JS 派发事件** (`why-your-cdp-clicks-silently-fail`) — ~12,514 字符 -2. [devops] **Prometheus 明明有数据,Grafana 面板却全是 No data 的原因** (`why-your-grafana-dashboard-shows-no-data`) — ~11,212 字符 -3. [devops] **你的“磁盘将满”告警在说谎:别再按百分比告警** (`your-disk-full-alert-is-lying`) — ~8,912 字符 -4. [engineering] **浏览器翻译没有 API:我给一个纯中文网页应用加上了英文模式** (`adding-english-mode-to-a-chinese-only-web-app`) — ~18,070 字符 -5. [engineering] **排查 Remotion 视频抽搐:为什么在背景图挂载音频低频 Scale 会毁了转场** (`debugging-remotion-video-jitter`) — ~15,111 字符 -6. [engineering] **把字体嵌进 PDF,让它在任何机器上都长一样** (`embedding-fonts-so-a-pdf-looks-the-same-everywhere`) — ~11,465 字符 -7. [engineering] **那个把静默丢失更新变成 409 的 JPA 字段:@Version 乐观锁** (`jpa-version-field-lost-update`) — ~19,575 字符 -8. [engineering] **把 CodeIgniter 4 应用从 IIS 迁移到 OpenLiteSpeed** (`migrating-codeigniter-iis-to-openlitespeed`) — ~23,361 字符 -9. [engineering] **用「热浏览器会话」爬取有反爬墙的电商网站** (`scraping-bot-walled-marketplace-warm-browser-session`) — ~16,928 字符 +1. [devops] **为什么你的 CDP 点击会静默失效:平滑滚动、最小化窗口与 JS 派发事件** (`why-your-cdp-clicks-silently-fail`) — ~12,590 字符 +2. [devops] **Prometheus 明明有数据,Grafana 面板却全是 No data 的原因** (`why-your-grafana-dashboard-shows-no-data`) — ~11,375 字符 +3. [devops] **你的“磁盘将满”告警在说谎:别再按百分比告警** (`your-disk-full-alert-is-lying`) — ~9,229 字符 +4. [engineering] **浏览器翻译没有 API:我给一个纯中文网页应用加上了英文模式** (`adding-english-mode-to-a-chinese-only-web-app`) — ~18,167 字符 +5. [engineering] **排查 Remotion 视频抽搐:为什么在背景图挂载音频低频 Scale 会毁了转场** (`debugging-remotion-video-jitter`) — ~15,489 字符 +6. [engineering] **把字体嵌进 PDF,让它在任何机器上都长一样** (`embedding-fonts-so-a-pdf-looks-the-same-everywhere`) — ~12,338 字符 +7. [engineering] **那个把静默丢失更新变成 409 的 JPA 字段:@Version 乐观锁** (`jpa-version-field-lost-update`) — ~20,042 字符 +8. [engineering] **把 CodeIgniter 4 应用从 IIS 迁移到 OpenLiteSpeed** (`migrating-codeigniter-iis-to-openlitespeed`) — ~23,368 字符 +9. [engineering] **用「热浏览器会话」爬取有反爬墙的电商网站** (`scraping-bot-walled-marketplace-warm-browser-session`) — ~17,047 字符 10. [engineering] **JavaScript 文件静默失效的两种方式:而页面看上去一切正常** (`two-ways-a-javascript-file-stops-working-and-looks-fine`) — ~11,294 字符 11. [engineering] **逐页验证一份 19 页的 PDF 报告** (`verifying-a-pdf-report-page-by-page`) — ~19,210 字符 @@ -191,7 +191,7 @@ document.querySelectorAll('button').length // 你的选择器到底命中了 这些都不算冷门知识,但它们中的每一条,在一行 `clicked @591,361` 面前都是隐形的。如果你正在对着一个自己无法控制的后台做自动化:点击是整条链路里最不可靠的一环 —— 也是最容易被最后才怀疑的一环。 -我平时就在做这类浏览器自动化与排障 —— 自托管服务、Docker 与 Traefik 栈,偶尔还有被 bot 墙挡住的市场页面。如果你有条工作流总因为「UI 有自己的想法」而断掉,跟我说说:[WhatsApp](https://wa.me/60127972969) · [me@hoelee.com](mailto:me@hoelee.com?subject=Browser%20automation%20debugging) · [hoelee.com](https://hoelee.com)。 +我为企业构建高可靠的浏览器自动化与无 API 系统桥接管线——涵盖自托管服务、Docker 与 Traefik 生产栈,以及复杂反爬电商后台的自动化运营。如果你的业务工作流总因为「第三方 UI 频繁变动」而中断,欢迎联系我:[WhatsApp +60 12-797 2969](https://wa.me/60127972969) · [me@hoelee.com](mailto:me@hoelee.com?subject=Browser%20automation%20debugging) · [hoelee.com](https://hoelee.com)。 ```` ### 🇬🇧 英文版原文 (English Markdown Primary) @@ -317,7 +317,7 @@ There is a class of “failure” that is not one: **the write succeeded and you None of this is exotic, but every item is invisible in a log line that says `clicked @591,361`. If you are building automation against an admin panel you do not control, the click is the least reliable part of the pipeline — and the one most likely to be blamed last. -I build and debug this kind of browser automation for a living — self-hosted services, Docker and Traefik stacks, and the odd scraped-but-bot-walled marketplace. If you have a workflow that keeps breaking because a UI has other ideas, tell me about it: [WhatsApp](https://wa.me/60127972969) · [me@hoelee.com](mailto:me@hoelee.com?subject=Browser%20automation%20debugging) · [hoelee.com](https://hoelee.com). +I architect and debug production browser automation and RPA pipelines — spanning self-hosted services, Docker and Traefik stacks, and bot-walled marketplace operations. If you have a business workflow that keeps breaking because a third-party UI has other ideas, tell me about it: [WhatsApp +60 12-797 2969](https://wa.me/60127972969) · [me@hoelee.com](mailto:me@hoelee.com?subject=Browser%20automation%20debugging) · [hoelee.com](https://hoelee.com). ```` --- @@ -428,9 +428,9 @@ curl -s -G http://prometheus:9090/api/v1/query \ ## 不是每个空面板都是 bug -修完之后 25 个面板有 21 个出数。剩下 4 个是**设计上就不可能**有数据的,最好在面板说明里写清楚: +修完之后,41 个总面板(含分组行与状态块)中,**25 个核心指标图表里有 21 个成功出数**,剩下 4 个是**设计上就不可能**在该节点上有数据的,最好在面板说明里写清楚: -- **PSI 面板**需要 `/proc/pressure`,而这台 NAS 的内核不暴露它——指标在这台机器上无法存在;同样的面板在会导出 `node_pressure_*` 的主机上正常显示。 +- **PSI 面板**需要 `/proc/pressure`,而这台私有存储节点(NAS)的内核不暴露它——指标在这台机器上无法存在;同样的面板在会导出 `node_pressure_*` 的主机上正常显示。 - **根文件系统面板**的表达式带 `fstype!="rootfs"`,而某台主机的 `/` 是**内存盘**(unRaid 就是),所以永远匹配不到。 区分\"因为 bug 空\"和\"因为这台机器不可能有这个指标而空\",是真修好和瞎忙一下午的分界线。 @@ -444,7 +444,7 @@ curl -s -G http://prometheus:9090/api/v1/query \ ## 结果 -三台主机现在跑同一套布局——每台一个 41 面板的主机面板 + 一个 10 面板的容器面板,分别有 21/23/25 个面板出数,两类结构性空缺写在面板里,而不是留给下一个打开它的人去猜。 +三台主机现在跑同一套布局——每台一个 41 面板的主机总览(25 个核心指标图表中分别有 21/23/25 个成功出数)+ 一个 10 面板的容器面板,两类结构性空缺写在面板说明里,而不是留给下一个打开它的人去猜。 ## 需要为你的业务做这个吗? @@ -575,11 +575,11 @@ container dashboard "fails" every panel. Resolve `$__all` to the variable's `all ## Not every empty panel is a bug -After the fix, 21 of 25 panels had data. The remaining four were empty **by design** and +After the fix, out of the 41 total layout panels, **21 of the 25 core metric panels** returned data. The remaining four were empty **by design** and worth naming honestly in the panel description: - **PSI panels** (`Pressure`, `Pressure Stall Information`) need `/proc/pressure`, which - the NAS kernel doesn't expose. The metric cannot exist there — the same panels on a + the on-premise NAS storage node's kernel doesn't expose. The metric cannot exist there — the same panels on a host that *does* export `node_pressure_*` render fine. - **Root filesystem panels** whose expression carries `fstype!="rootfs"` can never match on a host whose `/` is a **ramdisk**, which is what unRaid's root is. @@ -599,9 +599,8 @@ this host" is the difference between a real fix and a wild goose chase. ## The result -All three hosts now run the same instrumented layout — a 41-panel host dashboard and a -10-panel container dashboard each — with 21/23/25 panels returning data respectively, -and the two structurally-empty classes documented in place instead of silently +All three hosts now run the same instrumented layout — a 41-panel host dashboard (with 21/23/25 of the 25 core metric panels returning data respectively) and a +10-panel container dashboard each — and the two structurally-empty classes documented in place instead of silently confusing whoever opens them next. ## Want this for your business? @@ -656,7 +655,7 @@ draft: false **1.「文件系统使用率超过 90%」**——它在一个还剩约 500 GB 的 17 TB 卷上触发。没事发生,也不会马上有事发生。这种体量的卷,一次大备份就能让百分比摆动几个点:比例是噪声,而\"还有 500 GB 可用\"才是世界的真实状态。 -**2.「内存使用率超过 90%」**——在一台**可用**内存 4.8 GB 的主机上反复触发。Linux 会用空闲内存做 page cache,需要时立刻归还;`MemTotal - MemFree` 描述的是文件缓存,不是你的风险。真正预示 OOM 的是 `MemAvailable`。 +**2.「内存使用率超过 90%」**——在一台**可用**内存 4.8 GB 的主机上反复触发。Linux 会用空闲内存做 page cache,需要时立刻归还;`MemTotal - MemFree` 描述的是文件缓存,不是你的风险。真正预示 OOM 的是 `MemAvailable`。(即便改用 `MemAvailable` 按 90% 告警,在 64 GB 内存的节点上依然会在还剩 4.8 GB 可用内存时误报。) **3.「CPU steal 超过 25%」**——一台把邮件栈跑得完全正常的 VPS,steal 长期在 41%。steal 说明宿主机忙,它是**容量**信号而不是**故障**信号;7 vCPU 的机器 41% steal 就是这台机器的成本。这条规则产生的告警永远为真、也永远无用。 @@ -686,10 +685,10 @@ min by (instance, mountpoint) ( ``` ```promql -# BEFORE — 把 page cache 当成压力 -(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 90 +# BEFORE — 把可回收的 page cache 也当成了内存压力(误用 MemFree) +(1 - node_memory_MemFree_bytes / node_memory_MemTotal_bytes) * 100 > 90 -# AFTER — 真正的 OOM 前兆 +# AFTER — 基于内核可分配内存(MemAvailable)的真实 OOM 绝对值前兆 node_memory_MemAvailable_bytes < 512 * 1024 * 1024 ``` @@ -757,7 +756,7 @@ fact that 500 GB is still available is the actual state of the world. **2. "Memory above 90% used."** Fired constantly on a host with 4.8 GB *available*. Linux uses free RAM for page cache and gives it back on demand; `MemTotal - MemFree` describes your filesystem cache, not your risk. The number that predicts an OOM is -`MemAvailable`. +`MemAvailable`. (Even if one alerts on `MemAvailable` exceeding 90% capacity, on a 64 GB host it still fires an alert when 4.8 GB of usable headroom remains.) **3. "CPU steal above 25%."** Fired on a VPS that had been running its mail stack perfectly at 41% steal. Steal means the hypervisor is busy — it is a *capacity* signal, @@ -792,10 +791,10 @@ min by (instance, mountpoint) ( ``` ```promql -# BEFORE — page cache counted as "pressure" -(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 90 +# BEFORE — page cache counted as "pressure" (misusing MemFree) +(1 - node_memory_MemFree_bytes / node_memory_MemTotal_bytes) * 100 > 90 -# AFTER — the actual OOM precursor +# AFTER — the actual OOM precursor based on kernel-reclaimable MemAvailable node_memory_MemAvailable_bytes < 512 * 1024 * 1024 ``` @@ -841,7 +840,7 @@ What transfers is the shape: ## The result The same stack that was producing three permanent, uninformative warnings now runs 16 -rules that stay silent when the lab is healthy — and one of them immediately surfaced a +rules that stay silent when the infrastructure is healthy — and one of them immediately surfaced a NAS volume sitting at 21 GB free, which is the kind of thing a percentage rule had been hiding behind a 99%-full giant that I'd learned to ignore. @@ -1015,7 +1014,7 @@ UI 是右下角的一个小胶囊:关闭时显示 `EN`,开启后显示 `中文`, **书籍正文。** 阅读器把 EPUB 内容渲染在 iframe 里,我的遍历器按设计跳过 iframe —— 而且我无论如何也不会去机器替换一本小说的正文。 -同样保持原样的还有:书名与作者、书源名称、我自己建的分组名(梯子、精品、正版),以及应用那句诗。这些是**数据**,不是界面。翻译界面是一种体贴;悄悄改写用户自己的内容是另一回事,而且糟糕得多。 +同样保持原样的还有:书名与作者、书源名称、我自己建的分组名(技术、历史、传记),以及应用那句诗。这些是**数据**,不是界面。翻译界面是一种体贴;悄悄改写用户自己的内容是另一回事,而且糟糕得多。 书籍正文仍然交给浏览器自带的翻译 —— 而且因为「发现一」,它现在真的会被提示出来。按钮的弹窗里就是这么写的。 @@ -1037,7 +1036,7 @@ while ((n = walker.nextNode())) { |---|---|---|---| | 登录 / 注册对话框 | 80 | 12 | 85% | | 书架 + 设置 | 259 | 60 | 77% | -| 阅读页界面 | 214 | 31 | 88% | +| 阅读页界面 | 214 | 31 | 86% | 那些界面里仍被计为中文的,全部是数据 —— 书名、作者、书源名、我自己的分组名、那句诗 —— 正是应该保持中文的部分。 @@ -1063,7 +1062,7 @@ python -c "print(sorted(set(old_keys) - set(new_keys)))" --- -*我为马来西亚的中小企业搭建并自托管这类平台 —— 网页应用、私人书库、内部工具。有需要可以找我:[WhatsApp +60 12-797 2969](https://wa.me/60127972969)、[me@hoelee.com](mailto:me@hoelee.com?subject=Self-hosted%20platform),或 [hoelee.com](https://www.hoelee.com)。* +*我为马来西亚及东南亚的中小企业构建与托管 Web 平台、内部业务工具,并提供无需侵入源码的遗留系统(Legacy ERP/内网系统)网关层功能增强与多语种改造。有需要可以找我:[WhatsApp +60 12-797 2969](https://wa.me/60127972969)、[me@hoelee.com](mailto:me@hoelee.com?subject=Self-hosted%20platform),或访问 [hoelee.com](https://www.hoelee.com)。* ```` ### 🇬🇧 英文版原文 (English Markdown Primary) @@ -1206,7 +1205,7 @@ The UI is a small pill in the bottom-right corner: `EN` when off, `中文` when **Book text.** The reader renders EPUB content inside an iframe; my walker skips iframes by design, and I would never machine-swap a novel's prose anyway. -Also left alone: book titles and authors, book-source names, and the group names I created myself (梯子, 精品, 正版), plus the app's poem tagline. Those are *data*, not interface. Translating the chrome is a courtesy; silently rewriting a user's own content is a different and much worse idea. +Also left alone: book titles and authors, book-source names, and the group names I created myself (技术, 历史, 传记), plus the app's poem tagline. Those are *data*, not interface. Translating the chrome is a courtesy; silently rewriting a user's own content is a different and much worse idea. For book text the browser's own translation is still the right tool — and it now actually gets offered, thanks to Finding 1. The button's popup says exactly that. @@ -1228,7 +1227,7 @@ while ((n = walker.nextNode())) { |---|---|---|---| | Login / register dialog | 80 | 12 | 85% | | Bookshelf + settings | 259 | 60 | 77% | -| Reading page chrome | 214 | 31 | 88% | +| Reading page chrome | 214 | 31 | 86% | Everything still counted as Chinese on those screens is data — titles, authors, source names, my own group names, the tagline — which is exactly what should stay Chinese. @@ -1254,7 +1253,7 @@ The lesson I'm keeping: **when the platform won't give you an API, look one laye --- -*I build and self-host platforms like this one — web apps, private libraries, internal tools for small businesses in Malaysia. If you need something similar: [WhatsApp +60 12-797 2969](https://wa.me/60127972969), [me@hoelee.com](mailto:me@hoelee.com?subject=Self-hosted%20platform), or [hoelee.com](https://www.hoelee.com).* +*I build and self-host web platforms, internal business tools, and non-invasive reverse-proxy enhancements (such as localising closed-source or legacy systems) for SMEs in Malaysia. If you need something similar: [WhatsApp +60 12-797 2969](https://wa.me/60127972969), [me@hoelee.com](mailto:me@hoelee.com?subject=Self-hosted%20platform), or [hoelee.com](https://www.hoelee.com).* ```` --- @@ -1384,30 +1383,18 @@ $$\text{有效综合不透明度} = 1 - (1 - 0.5) \times (1 - 0.5) = 1 - 0.25 = 坚决不要让底图淡出。**当前图片始终保持 100% 不透明**,下一张图片直接覆盖在其上方,慢速执行 `0 -> 1.0` 的单向淡入: ```tsx +const fullBleed = { position: 'absolute', width: '100%', height: '100%', objectFit: 'cover' }; + return (