{"id":"c8218606-3206-4932-a325-6b0208b6476b","entityType":"agent","slug":"clawhub-dengjiawei1226-ielts-reading-review","name":"IELTS Reading Review 雅思阅读复盘","canonicalUrl":"https://www.xpersona.co/agent/clawhub-dengjiawei1226-ielts-reading-review","canonicalPath":"/agent/clawhub-dengjiawei1226-ielts-reading-review","generatedAt":"2026-10-10T01:50:10.698Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:03:24.236Z","emptyReason":null},"description":"IELTS Reading passage review, scoring, and progress tracking skill. Generates structured review data (JSON) and deploys to www.liuxue.online via saveReview A...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 2K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s171z5dmkr3hr6e5vrt1whgtt583m22s:ielts-reading-review","sourceUrl":"https://clawhub.ai/dengjiawei1226/ielts-reading-review","homepage":"https://clawhub.ai/dengjiawei1226/skills/ielts-reading-review","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/dengjiawei1226/ielts-reading-review","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/dengjiawei1226/skills/ielts-reading-review","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":45,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"IELTS Reading Review 雅思阅读复盘 technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:03:24.236Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:03:24.236Z","emptyReason":null},"stars":null,"forks":null,"downloads":2046,"packageName":null,"latestVersion":"5.5.2","tractionLabel":"2K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:03:24.236Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T20:03:24.236Z","lastCrawledAt":"2026-10-09T20:03:24.236Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T20:03:24.236Z","lastVerifiedAt":null,"highlights":[{"version":"5.5.2","createdAt":"2026-06-23T03:06:56.232Z","changelog":"v5.5.2: 域名迁移 tuyaya.online → www.liuxue.online（旧域名因 ICP 备案审核全站 403 不可用）。setup-client-mode.sh 的 API_BASE/AUTH_PAGE/login.html 及 CORS Allow-Origin 全部切换；SKILL/README/CLIENT_MODE_ONBOARDING 文档默认域名更新。SSH 隧道 ssh.tuyaya.online 保留不变。同时补发 v5.5.1（rejectedOptions[] 字段，review.html 红框渲染'为什么不选'）。","fileCount":20,"zipByteSize":63826},{"version":"5.5.1","createdAt":"2026-06-01T14:41:58.451Z","changelog":"rejectedOptions 扩展支持判断题(tfng)：Y/N/NG 错误选项也可逐个排除，不再仅限选择题(multipleChoice)","fileCount":20,"zipByteSize":63137},{"version":"5.5.0","createdAt":"2026-06-01T14:33:57.567Z","changelog":"选择题错题新增 rejectedOptions[] 字段：review.html 以红色边框卡片渲染'为什么不选'区域，逐个排除错误选项（A/C/D）","fileCount":20,"zipByteSize":63240},{"version":"5.4.2","createdAt":"2026-05-22T15:04:50.907Z","changelog":"v5.4.2: 把【必须入库】提升为最高铁律 (1) SKILL.md 顶部新增「最高铁律」段：只要主人发了雅思阅读题，就必须一气呵成跑完 读截图→错题确认→错题分析→生成v4.0 JSON→saveReview/upload入库→getReviews 回查 ✅→汇报线上链接 闭环 (2) 新增 Step 8 Final Gate 强制 checklist：4 个 Gate 全 ✅ 才允许结束对话；任意一条 ❌ 一律返回继续干 (3) 修复历史血泪：剑8 T3P1+T3P2 等只写文字分析没入库的假完成模式被永久封杀。不影响其他用户使用，纯文档加固。\\n\\nv5.4.1: 文档大改造，README/SKILL/CLIENT_MODE_ONBOARDING 全面阐释 v5.4.0 OAuth 风格授权流。\\n\\nv5.4.0: 优雅授权流上线。","fileCount":20,"zipByteSize":62944},{"version":"5.4.1","createdAt":"2026-05-20T12:24:41.635Z","changelog":"v5.4.1: 文档大改造，README/SKILL/CLIENT_MODE_ONBOARDING 全面阐释 v5.4.0 OAuth 风格授权流——新增 What's New 段、安全设计五大保障表、三系统命令矩阵、兜底 --manual 流程说明。同步推送 GitHub。\\n\\nv5.4.0: 优雅授权流上线 (1) setup-client-mode.sh 改造为浏览器授权模式 (2) site/authorize.html OAuth 风格确认页 (3) 修复 localStorage.token → ielts_user_token (4) 保留 --manual 兜底。","fileCount":19,"zipByteSize":59729},{"version":"5.4.0","createdAt":"2026-05-20T06:56:17.004Z","changelog":"v5.4.0: 优雅授权流上线 (1) setup-client-mode.sh 改造为浏览器授权模式——脚本启本地随机端口 HTTP 服务 + 自动 open 浏览器到 tuyaya.online/authorize.html，用户在网页点「授权」即把 token 经 <img> 回传到本机，全程不再 F12 复制 token (2) site/authorize.html OAuth 风格授权确认页，仅允许回调到 127.0.0.1/localhost http，state 参数防 CSRF，未登录自动跳登录后回跳 (3) 修复历史 bug：localStorage.token → localStorage.ielts_user_token (4) 保留 --manual 兜底模式。\\n\\nv5.3.0: 多用户客户端模式正式上线，新增 Step 0a 运行模式检测、Step 7-Client batchImport 简化部署、setup-client-mode.sh 一键配置。","fileCount":19,"zipByteSize":58853},{"version":"5.3.0","createdAt":"2026-05-20T06:36:57.193Z","changelog":"v5.3.0: 多用户客户端模式正式上线 (1) 新增 Step 0a 运行模式检测——根据 ~/.ssh/workbuddy.pem + IELTS_USER_TOKEN 自动分流作者/客户端模式 (2) 新增 Step 7-Client 简化部署流程——客户端走 batchImport API 直接入库个人主页，不需 SSH/scp/部署 (3) 新增 setup-client-mode.sh 一键配置——浏览器取 token + curl 验证 + 写 .zshrc (4) 新增 references/CLIENT_MODE_ONBOARDING.md 客户端教程 (5) 客户端红线明确禁止 ssh/scp/gzip/systemctl/site/reviews 部署","fileCount":19,"zipByteSize":57151},{"version":"5.2.0","createdAt":"2026-05-18T02:34:35.625Z","changelog":"v5.2.0: (1) 修复 review.html 旧格式JSON错题重复渲染+标签重复 (2) 明确 type=题型 vs badge=错误分类字段规范 (3) 大文件传输改为 gzip 流(废弃 split 分块) (4) 新增多平台截图标记识别规则+雅思哥复制文本解析","fileCount":17,"zipByteSize":50519}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s171z5dmkr3hr6e5vrt1whgtt583m22s:ielts-reading-review","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s171z5dmkr3hr6e5vrt1whgtt583m22s:ielts-reading-review` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/dengjiawei1226/ielts-reading-review before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dengjiawei1226-ielts-reading-review/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dengjiawei1226-ielts-reading-review/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dengjiawei1226-ielts-reading-review/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-dengjiawei1226-ielts-reading-review/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-dengjiawei1226-ielts-reading-review/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-dengjiawei1226-ielts-reading-review/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T01:50:10.695Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dengjiawei1226-ielts-reading-review/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dengjiawei1226-ielts-reading-review/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dengjiawei1226-ielts-reading-review/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dengjiawei1226-ielts-reading-review/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T20:03:24.236Z","emptyReason":null},"readme":"Skill: IELTS Reading Review 雅思阅读复盘\n\nOwner: dengjiawei1226\n\nSummary: IELTS Reading passage review, scoring, and progress tracking skill. Generates structured review data (JSON) and deploys to www.liuxue.online via saveReview A...\n\nTags: latest:5.5.2\n\nVersion history:\n\nv5.5.2 | 2026-06-23T03:06:56.232Z | user\n\nv5.5.2: 域名迁移 tuyaya.online → www.liuxue.online（旧域名因 ICP 备案审核全站 403 不可用）。setup-client-mode.sh 的 API_BASE/AUTH_PAGE/login.html 及 CORS Allow-Origin 全部切换；SKILL/README/CLIENT_MODE_ONBOARDING 文档默认域名更新。SSH 隧道 ssh.tuyaya.online 保留不变。同时补发 v5.5.1（rejectedOptions[] 字段，review.html 红框渲染'为什么不选'）。\n\nv5.5.1 | 2026-06-01T14:41:58.451Z | user\n\nrejectedOptions 扩展支持判断题(tfng)：Y/N/NG 错误选项也可逐个排除，不再仅限选择题(multipleChoice)\n\nv5.5.0 | 2026-06-01T14:33:57.567Z | user\n\n选择题错题新增 rejectedOptions[] 字段：review.html 以红色边框卡片渲染'为什么不选'区域，逐个排除错误选项（A/C/D）\n\nv5.4.2 | 2026-05-22T15:04:50.907Z | user\n\nv5.4.2: 把【必须入库】提升为最高铁律 (1) SKILL.md 顶部新增「最高铁律」段：只要主人发了雅思阅读题，就必须一气呵成跑完 读截图→错题确认→错题分析→生成v4.0 JSON→saveReview/upload入库→getReviews 回查 ✅→汇报线上链接 闭环 (2) 新增 Step 8 Final Gate 强制 checklist：4 个 Gate 全 ✅ 才允许结束对话；任意一条 ❌ 一律返回继续干 (3) 修复历史血泪：剑8 T3P1+T3P2 等只写文字分析没入库的假完成模式被永久封杀。不影响其他用户使用，纯文档加固。\\n\\nv5.4.1: 文档大改造，README/SKILL/CLIENT_MODE_ONBOARDING 全面阐释 v5.4.0 OAuth 风格授权流。\\n\\nv5.4.0: 优雅授权流上线。\n\nv5.4.1 | 2026-05-20T12:24:41.635Z | user\n\nv5.4.1: 文档大改造，README/SKILL/CLIENT_MODE_ONBOARDING 全面阐释 v5.4.0 OAuth 风格授权流——新增 What's New 段、安全设计五大保障表、三系统命令矩阵、兜底 --manual 流程说明。同步推送 GitHub。\\n\\nv5.4.0: 优雅授权流上线 (1) setup-client-mode.sh 改造为浏览器授权模式 (2) site/authorize.html OAuth 风格确认页 (3) 修复 localStorage.token → ielts_user_token (4) 保留 --manual 兜底。\n\nv5.4.0 | 2026-05-20T06:56:17.004Z | user\n\nv5.4.0: 优雅授权流上线 (1) setup-client-mode.sh 改造为浏览器授权模式——脚本启本地随机端口 HTTP 服务 + 自动 open 浏览器到 tuyaya.online/authorize.html，用户在网页点「授权」即把 token 经 <img> 回传到本机，全程不再 F12 复制 token (2) site/authorize.html OAuth 风格授权确认页，仅允许回调到 127.0.0.1/localhost http，state 参数防 CSRF，未登录自动跳登录后回跳 (3) 修复历史 bug：localStorage.token → localStorage.ielts_user_token (4) 保留 --manual 兜底模式。\\n\\nv5.3.0: 多用户客户端模式正式上线，新增 Step 0a 运行模式检测、Step 7-Client batchImport 简化部署、setup-client-mode.sh 一键配置。\n\nv5.3.0 | 2026-05-20T06:36:57.193Z | user\n\nv5.3.0: 多用户客户端模式正式上线 (1) 新增 Step 0a 运行模式检测——根据 ~/.ssh/workbuddy.pem + IELTS_USER_TOKEN 自动分流作者/客户端模式 (2) 新增 Step 7-Client 简化部署流程——客户端走 batchImport API 直接入库个人主页，不需 SSH/scp/部署 (3) 新增 setup-client-mode.sh 一键配置——浏览器取 token + curl 验证 + 写 .zshrc (4) 新增 references/CLIENT_MODE_ONBOARDING.md 客户端教程 (5) 客户端红线明确禁止 ssh/scp/gzip/systemctl/site/reviews 部署\n\nv5.2.0 | 2026-05-18T02:34:35.625Z | user\n\nv5.2.0: (1) 修复 review.html 旧格式JSON错题重复渲染+标签重复 (2) 明确 type=题型 vs badge=错误分类字段规范 (3) 大文件传输改为 gzip 流(废弃 split 分块) (4) 新增多平台截图标记识别规则+雅思哥复制文本解析\n\nv5.1.1 | 2026-05-13T08:11:46.977Z | user\n\nv5.1.0: 三道防线避免历史坑——(1) 发布脚本自动同步本地副本到 ~/.workbuddy/skills (2) Step 7g 强制入库回归验证 saveReview 已生效 (3) Step 0 强制展示版本横幅落后必告警。\n\nv2.5.0 | 2026-05-12T09:52:22.051Z | user\n\n链接改为阅读首页 reading.html，README 新增4张产品效果截图\n\nv5.1.0 | 2026-05-12T02:44:01.416Z | user\n\nv5.1.0: 三道防线避免历史坑——(1) 发布脚本自动同步本地副本到 ~/.workbuddy/skills (2) Step 7g 强制入库回归验证 saveReview 已生效 (3) Step 0 强制展示版本横幅落后必告警。\n\nv5.0.0 | 2026-05-11T13:39:04.753Z | user\n\nv5.0.0: 重大简化部署流程——服务端已预置 C4-C20 全量 answer-key（204条）+ bilingual_data（100条核心双语），复盘流程无需再维护这两个文件；部署清单从5个文件缩减到3个；首页UI修复：整本未做的 book 自动隐藏。\n\nv4.0.1 | 2026-05-09T07:08:22.910Z | user\n\nv4.0.1: 修复 answer-key.json key 格式（P→R）+ 新增 key 格式防呆提醒。\n\nv4.0.0 | 2026-05-09T03:05:18.764Z | user\n\nv4.0.0: JSON-only 架构 —— 不再生成复盘 HTML，后端 review.html 统一渲染 JSON。大文件部署方案（split 分块传输）。新增 7d 服务端代码部署指引。新增 extractMeta/diffReviews/validateContent/ocrPdf API 支持。词库 5805 词。\n\nv3.9.1 | 2026-04-29T03:42:34.530Z | user\n\nv3.9.1: 自动版本检查 —— 新增 scripts/check-update.js，Skill 每次激活时自动比对本地版本与 ClawHub 最新版，有更新时提示用户并支持 --auto 一键更新。v3.9.0: 词库覆盖校验 + saveReview API 入库 + answers字段规范。\n\nv3.9.0 | 2026-04-29T03:22:09.091Z | user\n\nv3.9.0: 词库覆盖校验 + saveReview API 入库 + answers[] 字段规范 —— Step 7 新增词库覆盖校验（dict_full.json 缺词=词卡展开不工作，强制校验+补词）；新增 saveReview API 入库步骤（文件部署≠数据入库）；answers[] 字段名规范（my/correct字符串/result字符串）；线上验证新增词卡展开检查；Common Pitfalls 新增3条（段落匹配信息密度干扰/Summary近义词混用/专有名称不完整）。v3.8.0: JSON v4.0 schema + 模板页。\n\nv3.8.0 | 2026-04-28T10:59:54.350Z | user\n\nv3.8.0: JSON v4.0 schema + 模板页 + 动态化收尾 —— JSON 升级到 v4.0（新增 progressNote/alertNote/answers[]/actionItems[]/wrongQuestions 增加 badge/quote/quoteRef/analysisPoints，v3.0 仍兼容）。Web 端新增 review.html 通用模板页，可直接渲染 JSON。后端 buildReviewFileIndex 优先索引 .json 文件。Step 3b 简化：不再生成独立双语 HTML，只维护 bilingual_data.json（Web 已全面动态化）。error-taxonomy 扩至 18 类。v3.7.0: 部署检查清单 + 错误分类扩充。\n\nv3.7.0 | 2026-04-28T02:29:38.782Z | user\n\nv3.7.0: 部署检查清单 + 错误分类扩充 —— 新增 Step 7 Deploy Checklist (MANDATORY)，8项必检防止文件遗漏/部署遗漏/数据遗漏。Step 3b 重写为'Generate Bilingual Data & Page'，强调必须追加 bilingual_data.json。error-taxonomy 从12类扩至17类（新增 heading-example-reuse/concessive-clause-confusion/double-negative-misread/summary-no-source/comparison-signal-ignored）。Common Pitfalls 从4条扩至10条。v3.6.0: Step 3b 双语对照自动生成。v3.5.0: 文件命名强制规范。\n\nv3.5.0 | 2026-04-22T02:25:34.310Z | user\n\nv3.5.0: 文件命名强制规范 —— SKILL.md Step 2 增加命名规则强制章节，固化'剑{book}-Test{test}-Passage{passage}-{titleCN}复盘.html'格式，要求 titleCN 必须和 source.titleCN/HTML/JSON 三处完全一致，必须以'复盘'结尾，禁止和 answer-key 既有 title 漂移。防止历史上出现过的'火山专题积累.html'（缺'复盘'）、'识字女性育儿复盘.html'（和 title 里'与'字不一致）这类 404 隐患。v3.4.0: Auto-Discovery。v3.3.0: Batch Import Mode。v3.2.0: timing 必问项。v3.1.0: Web hand-off mode。\n\nv3.4.0 | 2026-04-21T15:59:04.038Z | user\n\nv3.4.0: Auto-Discovery —— scan-legacy-reviews.js 支持 --auto 模式（默认），自动扫描 cwd/~/Documents/~/Desktop/~/Downloads/iCloud/WorkBuddy 等常见位置，按命中数智能推荐复盘目录（父子目录去重，保留最深层命中点）。SKILL.md 新增 Step B0 自动发现章节，Buddy 不再开口就问路径。触发词扩充：扫一下我电脑里的复盘 / 帮我找出所有历史笔记 / 自动发现复盘 / auto scan。v3.3.0: Batch Import Mode 基础能力。v3.2.0: timing 字段升级为必问项。v3.1.0: Web hand-off mode。\n\nv3.3.0 | 2026-04-21T15:45:00.105Z | user\n\nv3.3.0: Batch Import Mode —— 新增 scripts/scan-legacy-reviews.js 扫描脚本，自动识别目录下历史复盘文件（HTML/MD/PDF/DOCX/截图）并按篇目聚合。SKILL.md 新增 Batch Import Mode 章节，定义 scan → confirm → loop → summary 四步流程与强制规则（先 confirm 再跑、失败不阻塞、缺数据置 null 绝不编造、正确答案查本地答案库、产物隔离到 ./batch-output/）。触发词扩充：批量导入历史复盘 / 历史笔记转 JSON / batch import。v3.2.0: timing 字段升级为必问项。v3.1.0: Web hand-off mode，生成 v3.0 schema JSON，拖入 tuyaya.online/ielts/submit.html?mode=json 批量同步。\n\nv3.1.0 | 2026-04-21T15:31:30.806Z | user\n\nv3.1.0: Web hand-off mode. Skill generates v3.0 schema JSON locally, user drops JSON files into tuyaya.online/ielts/submit.html?mode=json for bulk sync. No network calls from skill itself.\n\nv2.4.0 | 2026-04-10T07:01:07.928Z | user\n\nv2.4.0: Multi-tenant cloud sync with anonymous user ID, security hardening (removed external HTTP calls), updated README\n\nv3.0.0 | 2026-04-09T15:30:19.861Z | user\n\nV2 design system: purple gradient hero, card layout, Lucide icons, CSS Variables. New bilingual page template. Site deployment workflow. Expanded review sections. All APIs migrated to tuyaya.online.\n\nv2.3.0 | 2026-04-09T06:46:00.837Z | user\n\nMigrate all API endpoints from CloudBase to tuyaya.online lightweight cloud server\n\nv1.3.0 | 2026-04-08T03:44:57.703Z | user\n\nv1.3.0: Error taxonomy expanded to 12 categories (word-form error, cross-generational confusion, category-membership reasoning, adjacent distractors). New fill-in-the-blank 4-step readback checklist. Correct answer confirmation with synonym mapping. Progress highlight box and per-question-type trend visualization.\n\nv1.2.0 | 2026-04-01T14:21:36.998Z | user\n\nv1.2.0: 新增打分与Band换算、每套题成绩单（P1/P2/P3分段得分+用时）、多套考试进步趋势统计表、速度vs正确率分析。New: score-to-band conversion, per-test scorecards, cumulative progress tracking.\n\nv1.1.0 | 2026-03-27T08:45:46.512Z | user\n\nAdded complete usage guide with real case study (Cambridge 4 Test 3 Passage 1). Step-by-step quick start, full input/output walkthrough showing all 5 review modules.\n\nv1.0.0 | 2026-03-26T07:21:15.630Z | user\n\nInitial release: per-question error analysis, synonym tracking, vocabulary tagging with 538 keywords + COCA 5000, recurring mistake detection, HTML review notes with PDF export.\n\nArchive index:\n\nArchive v5.5.2: 20 files, 63826 bytes\n\nFiles: _meta.json (139b), assets/bilingual-template.html (3858b), assets/review-template.html (18589b), hooks/auto-update.sh (1507b), hooks/hooks.json (589b), README.md (10416b), references/538-keywords-guide.md (2186b), references/CLIENT_MODE_ONBOARDING.md (3828b), references/error-taxonomy.md (12187b), references/review-style-guide.md (8450b), references/score-band-table.md (2357b), scripts/check-update.js (5674b), scripts/generate-pdf.js (2416b), scripts/scan-legacy-reviews.js (10347b), scripts/setup-client-mode.sh (8447b), skill-card.md (2889b), SKILL.md (44679b), stats-worker/deploy.sh (2013b), stats-worker/worker.js (5286b), stats-worker/wrangler.toml (283b)\n\nFile v5.5.2:SKILL.md\n\n---\nname: ielts-reading-review\ndescription: \"IELTS Reading passage review, scoring, and progress tracking skill. Generates structured review data (JSON) and deploys to www.liuxue.online via saveReview API. The server's review.html template renders JSON into unified pages. No standalone HTML generation needed. Supports batch import of legacy reviews with auto-discovery of review folders. Trigger phrases: 雅思复盘, 帮我复盘阅读, IELTS reading review, 分析错题, 阅读错题分析, 成绩单, 打分, 统计, 进步趋势, 批量导入历史复盘, 历史笔记转 JSON, 把文件夹里的复盘都生成 JSON, 扫一下我电脑里的复盘, 帮我找出所有历史笔记, 自动发现复盘, score, band, progress, batch import, auto scan.\"\n---\n\n# IELTS Reading Review Skill\n\n## Purpose\n\n帮用户把雅思阅读做题结果变成结构化数据（JSON），通过 saveReview API 入库后由后端 review.html 模板统一渲染页面。\n\n## 🔴🔴🔴 最高铁律 (v5.5.2 — Cannot Be Skipped)\n\n**只要主人在对话里发了雅思阅读题（截图 / 文字答案 / 错题列表 / 任何阅读相关材料），就必须一气呵成跑完以下闭环，不允许中途停在文字分析阶段：**\n\n```\n读截图 → 错题确认 → 写错题分析 → ★生成 v4.0 JSON★ → ★saveReview/upload 入库★ → ★getReviews 回查 ✅★ → 汇报线上链接\n```\n\n**判定\"复盘完成\"的唯一标准 = `getReviews` 回查显示该篇已入库（不是\"我写完文字分析了\"）。**\n\n**绝对禁止的\"假完成\"模式（历史血泪）：**\n- ❌ 写完错题分析就交卷，不生成 JSON → 主人在 www.liuxue.online 看不到记录\n- ❌ 生成 JSON 但忘了 saveReview / upload.js → 文件部署 ≠ 数据入库\n- ❌ 调了 saveReview 但没 getReviews 回查 → API 静默失败也不知道\n- ❌ 等主人催\"怎么没上传\"才补救 → 这就是失败\n\n**本铁律覆盖所有其他流程**。即使主人只说\"帮我看看这题对不对\"\"分析这道错题\"\"这套该几分\"，**只要内容是雅思阅读，就走完整闭环**。\n\n> 历史教训（2026-05-22）：剑8 T3P1+T3P2 复盘只在聊天里写了文字分析没入库，主人在 dashboard 看不到，22:49 提醒后才补救。**这种事再也不能发生**。\n\n## Architecture (v5.5.2 — Locked-in Closed Loop)\n\n**⚠️ v5.5.2 变更**（2026-06-23）：**域名迁移** tuyaya.online → www.liuxue.online。旧域名因 ICP 备案审核已全站 403 不可用。所有脚本（setup-client-mode.sh 含 CORS Allow-Origin）、文档默认域名全部切到 www.liuxue.online。SSH 隧道 `ssh.tuyaya.online` 保留不变（cloudflared 隧道不经 nginx，不受影响）。\n\n**⚠️ v5.5.1 变更**（2026-06-01）：选择题和判断题错题新增 `rejectedOptions[]` 字段，在 review.html 中以红色边框卡片渲染\"为什么不选\"区域，逐个排除错误选项。\n\n**⚠️ v5.4.2 最重大变更**（2026-05-22）：将\"必须入库\"提升为最高铁律。SKILL.md 顶部新增「最高铁律」段，加入 Step 8 Final Gate 强制 checklist——任何复盘任务，未通过 `getReviews` 回查 ✅ 不允许结束，不允许只交付文字分析。\n\n**⚠️ v5.1 新增三道防线**（防 saveReview 漏调 / 本地副本陈旧）：\n1. **发布脚本自动同步本地副本**：publish-clawhub.sh 跑完后自动 `clawhub install --force` 到 `~/.workbuddy/skills/`\n2. **Step 7g 强制入库回归验证**：调 saveReview 后必须再用 getReviews 回查确认入库，**部署 ≠ 入库**\n3. **Step 0 强制展示版本横幅**：每次激活时输出本地+远程版本号，落后必告警\n\n**⚠️ v5.0 重大简化**：服务端已预置 C4-C20 全量 answer-key（204条 reading）+ bilingual_data（100条核心双语），**复盘流程不再需要更新这两个文件**，部署清单大幅缩减。\n\n**⚠️ 不再生成复盘 HTML！** 后端 `review.html` 模板页统一渲染 JSON，单独生成的 HTML 完全无用。\n\n产出物：\n1. **结构化 JSON（v4.0）** — 成绩、错题、词汇、同义替换的全量数据。通过 saveReview API 入库后，`review.html?file=xxx.json` 在线渲染\n\n> **v5.1 变更（2026-05-11 晚）**：三道防线避免再犯 saveReview 漏调 + 本地副本不更新的坑。\n\n> **v5.0 变更（2026-05-11）**：服务端预置 C4-C20 全量 answer-key + bilingual_data，复盘流程不再需要本地维护这两个文件。仅当复盘 C20 之后的新书才需要扩展。部署清单从 5 个文件缩减到 4 个（仅 JSON + 词汇相关）。\n\n> **v4.0 变更**：不再生成复盘 HTML。后端 review.html 模板页统一渲染 JSON，单独生成 HTML 无用。复盘只需 JSON + saveReview API 入库。\n\n> **v3.9.1 新增**：Step 0 自动版本检查（scripts/check-update.js），每次激活时比对本地与 ClawHub 版本。\n\n> **v3.9.0 新增**：词库覆盖校验（dict_full.json 缺词 = 词卡展开不工作）、saveReview API 入库步骤、answers[] 字段名规范、线上词卡验证步骤。\n\n## When to Activate\n\n- 用户发做题截图/答案，提到\"复盘\"\"错题分析\"\"阅读复盘\"\n- 用户问成绩、分数、进步趋势\n- 用户要生成复盘笔记或 PDF\n\n## Step 0a: 运行模式检测 (Auto — Run on Every Activation)\n\n**第一件事**：判断当前是「作者模式」还是「客户端模式」。两种模式行为完全不同，绝不能搞错。\n\n```bash\n# 模式判定逻辑（执行下列检测）：\ntest -f ~/.ssh/workbuddy.pem && grep -q \"openclaw-tunnel\" ~/.ssh/config 2>/dev/null && echo \"作者机\" || echo \"客户端机\"\n```\n\n| 信号 | 模式 | 行为 |\n|---|---|---|\n| 检测到 `~/.ssh/workbuddy.pem` + `openclaw-tunnel` SSH 别名 | **作者模式** | Step 7 走完整 SSH 部署链路（gzip 流、cat 管道、systemctl restart） |\n| 找不到上述凭据，但有 `IELTS_USER_TOKEN` 环境变量 | **客户端模式** | Step 7 跳过所有 SSH 操作，只走 HTTPS batchImport 入库 |\n| 都没有 | **未配置客户端模式** | 提示用户先配 `IELTS_USER_TOKEN`（详见客户端 onboarding 章节），然后切到客户端模式 |\n\n**模式横幅必须输出**（每次激活时）：\n\n```\n🎯 IELTS Reading Review · vX.Y.Z\n🔐 运行模式：作者模式 / 客户端模式\n👤 token 主体：dengjiawei / lishuzhuo / (匿名)\n```\n\n**作者模式与客户端模式的关键差异**（必读）：\n\n| 步骤 | 作者模式 | 客户端模式 |\n|---|---|---|\n| Step 7a 词库覆盖校验 | ✅ 必跑（要部署 dict_full.json） | ⏭️ 跳过（词库由作者维护，客户端无写权限） |\n| Step 7b 部署 site/reviews/ JSON | ✅ SCP 到服务器 | ⏭️ 跳过（batchImport 已写入数据库） |\n| Step 7b 部署 dict_full.json + synonym_data.json | ✅ gzip 流推送 | ⏭️ 跳过 |\n| Step 7c saveReview API | ✅ ssh + localhost:3100 | ⏭️ 改用 batchImport（HTTPS + token） |\n| Step 7d 后端代码部署 | ✅ 必要时执行 | 🚫 严禁触碰 |\n| Step 7e 后端重启 | ✅ systemctl restart | 🚫 严禁触碰 |\n| Step 7g 入库回查 | ✅ getReviews 校验 | ✅ getReviews 校验（HTTPS） |\n| 本地保存 JSON | ✅ `site/reviews/` | ✅ 用户自选目录（如 `~/Documents/雅思复盘/`） |\n\n> **客户端模式下绝对禁止**：执行 `ssh openclaw-tunnel`、`scp`、`gzip -c | ssh`、`systemctl restart`、修改 `/var/www/ielts/` 任何文件。\n\n## Step 0b: Version Check (Auto — Run on Every Activation)\n\n**每次 Skill 被激活时，第一件事必须显式输出当前版本横幅**：\n\n```bash\nnode ~/.workbuddy/skills/ielts-reading-review/scripts/check-update.js\n```\n\n**强制行为规范**：\n1. **必须把 check-update.js 的输出原样展示给用户**（包含本地版本号 + 远程版本号），不能省略\n2. 如果输出包含 `🆕 有新版本可用` → **立即提示用户并询问是否更新**：\n   ```\n   ⚠️ ielts-reading-review 有新版本 vX.Y.Z（当前 vA.B.C），强烈建议先更新再开始复盘。\n   现在更新？\n   ```\n3. 用户同意后执行 `node ~/.workbuddy/skills/ielts-reading-review/scripts/check-update.js --auto`，等待安装完成后**让用户重新激活 Skill**（已加载的 context 不会热更）\n4. 用户拒绝更新 → 在回复开头加红字告警：`⚠️ 正在使用旧版本 vA.B.C，可能错过 v5.0+ 的简化流程`\n\n> 如果 `check-update.js` 不存在（旧版本安装），跳过版本检查继续工作。\n> **绝对禁止**：不输出版本号、隐瞒版本差距、用户没同意就开始复盘流程。\n\n## Workflow\n\n### Step 1: Collect Input\n\n确保以下信息齐全（缺什么问什么）：\n\n- **来源**：哪本书、哪套题、哪篇（如剑5 Test1 Passage2）\n- **原文**或答题上下文\n- **正确答案**\n- **用户答案**及错题\n- **🔴 用时（MUST ASK）**：做题用时（格式 `MM:SS`，如 `28:01`）。**必问项**，不能标\"可选\"——Web 端进步趋势图依赖此字段。用户若没计时，明确询问\"这套大概做了多久\"让其估算，别直接跳过\n- **可选**：翻译、自我反思\n\n### Step 1b: Screenshot Wrong Answer Protocol (CRITICAL)\n\n**用户发答题截图时必须执行 3 步**：\n\n1. **逐题读截图标记**：识别每题的对/错状态（参考下方多平台标记规则），不能跳题，不能用自己的判断代替截图标记\n2. **先报错题清单等确认**：输出\"根据截图，错题为 QX/QY/QZ（共N道），请确认\"，**确认后才能写分析**\n3. **截图标记是唯一真相**：截图 vs 自己判断冲突时，信截图\n\n**禁止**：跳过确认直接写分析、用 answer comparison 覆盖截图标记。\n\n#### 多平台截图标记识别规则\n\n不同 App/平台的答案标记方式各不相同，AI 必须能识别以下所有变体：\n\n| 平台/场景 | 正确标记 | 错误标记 | 额外特征 |\n|-----------|---------|---------|---------|\n| 官方答题卡手批 | 绿色/✓ | 红色/✗ | 手写批注 |\n| **雅思哥 (IELTSBro)** | 绿色圆圈/✓/对号 | 红色圆圈/✗/叉号 | 界面有\"答案解析\"按钮；题号左侧有状态图标；底部显示得分统计（如 8/13）；可能同时显示\"你的答案\"和\"正确答案\"两列 |\n| 雅思哥成绩单复制文本 | 格式可能为：`1. D ✓` 或 `Q1: D (正确)` | `2. A ✗ → 正确: C` 或 `Q2: A (错误，正确答案: C)` | 复制文本可能包含：题号、用户答案、对错标记、正确答案 |\n| 小站雅思 | 蓝色/✓ | 橙色/✗ | 卡片式布局 |\n| 新东方雅思 | 绿色背景 | 红色背景 | 答案对比表格 |\n| 剑桥官方 CBT | 显示最终得分 | — | 不逐题标记 |\n| 其他 App（通用） | ✓/✔/☑/✅/绿色/蓝色 | ✗/✘/☒/❌/红色/橙色 | — |\n\n**识别策略（按优先级）**：\n\n1. **先找得分统计**：截图中如果有 \"8/13\"、\"得分：8\"、\"Score: 8/13\" 等信息，先记下总分\n2. **再找逐题标记**：逐题看状态图标/颜色/符号，判断每题对错\n3. **提取用户答案**：如果截图同时显示了用户答案和正确答案，直接记录两列数据\n4. **处理模糊情况**：如果某题标记看不清楚，输出 \"Q7 标记不确定（看起来像 ✓），请确认\"\n5. **利用 answer-key 交叉验证**：识别出来源（如 剑5 Test1）后，从 `site/answer-key.json` 读取正确答案，可辅助验证截图识别结果是否合理（但截图仍是第一真相）\n\n**🔴 当截图来自第三方 App 时的特殊处理**：\n\n- **不要假设标记规则**——不同 App 版本可能改 UI，先观察截图整体布局再判断哪个是\"对\"哪个是\"错\"\n- **看图例/得分摘要**——很多 App 顶部或底部有总分（如 8/13），用它来验证你逐题识别的正确率是否对得上\n- **如果实在识别不了**——直接告诉用户：\"这张截图的标记方式我不太确定，能告诉我哪些题错了吗？或者告诉我你用的是什么 App？\"\n\n#### 雅思哥复制文本解析规则\n\n用户可能直接从雅思哥 App 复制答案记录粘贴过来，常见格式：\n\n```\n# 格式 A：逐题结果（最常见）\n1. TRUE ✓\n2. FALSE ✗ (正确答案: NOT GIVEN)\n3. NOT GIVEN ✓\n4. B ✗ (正确答案: D)\n...\n\n# 格式 B：成绩概要\nCambridge 5 Test 1 Reading Passage 1\n得分：10/13\n错题：Q2, Q7, Q11\n\n# 格式 C：答案对照表\n题号 | 我的答案 | 正确答案 | 结果\n1    | TRUE     | TRUE     | ✓\n2    | FALSE    | NG       | ✗\n...\n```\n\n**解析要点**：\n1. 先识别来源（哪套题哪篇）——从标题/文件名/用户说明中提取\n2. 从文本中提取每题的：用户答案 + 对错状态 + 正确答案（如果有）\n3. 如果复制文本没有正确答案，从 `site/answer-key.json` 补充\n4. 格式不在上述三种之内 → 尽力解析，解析不了就问用户\n\n### Step 2: Generate Review Data JSON (v4.0)\n\n**⚠️ 不再生成复盘 HTML！** 后端 `review.html` 模板页统一渲染 JSON，单独生成 HTML 无用。\n\n直接生成结构化 JSON 文件，供 saveReview API 入库 + 后端 review.html 模板渲染。\n\n**输出文件命名规则**：`剑X-TestX-PassageX-中文主题复盘.json`\n\n示例：\n- JSON: `剑5-Test1-Passage2-鲸鱼感官复盘.json`\n- `source.titleCN`: `\"鲸鱼感官\"`\n\n> **命名说明**：文件名使用中文标题（`source.titleCN`），方便用户在文件管理器中一眼识别内容。Web 端导入时通过 JSON 内的 `source.book/test/passage` 识别篇目，不依赖文件名。\n\n**🔴 timing 字段必须填充**：\n- `minutes`：数值型分钟（支持小数，如 `28.0` / `35.4`）\n- `formatted`：`\"MM:SS\"` 字符串（如 `\"28:01\"`）\n- MM:SS → minutes 换算：`分钟 + 秒/60`，保留 1 位小数\n- 用户实在给不出用时，才能置 `null`，但必须在回复里提醒\"缺用时，进步图将缺一个点\"\n\n```json\n{\n  \"version\": \"4.0.0\",\n  \"generatedAt\": \"2026-04-28T10:00:00.000Z\",\n  \"source\": {\n    \"book\": 7,\n    \"test\": 1,\n    \"passage\": 3,\n    \"title\": \"English Title\",\n    \"titleCN\": \"中文标题\"\n  },\n  \"score\": {\n    \"correct\": 9,\n    \"total\": 14,\n    \"band\": \"6.0\",\n    \"breakdown\": {\n      \"fillBlank\": { \"correct\": 4, \"total\": 6 },\n      \"tfng\": { \"correct\": 3, \"total\": 4 },\n      \"matching\": { \"correct\": 2, \"total\": 4 }\n    }\n  },\n  \"timing\": {\n    \"minutes\": 25,\n    \"formatted\": \"25:00\"\n  },\n  \"date\": \"2026-04-28\",\n  \"progressNote\": \"简短进步总评（如'比上次提升2分'）\",\n  \"alertNote\": \"核心告警信息（如'Summary填空全军覆没'，可选）\",\n  \"answers\": [\n    { \"q\": 1, \"my\": \"TRUE\", \"correct\": \"TRUE\", \"result\": \"correct\" },\n    { \"q\": 2, \"my\": \"FALSE\", \"correct\": \"NOT GIVEN\", \"result\": \"wrong\" }\n  ],\n  \"wrongQuestions\": [\n    {\n      \"q\": 3,\n      \"type\": \"tfng\",\n      \"badge\": \"TFNG\",\n      \"myAnswer\": \"TRUE\",\n      \"correctAnswer\": \"NOT GIVEN\",\n      \"errorCategory\": \"ng-false-confusion\",\n      \"analysis\": \"错因分析文字\",\n      \"lesson\": \"教训一句话\",\n      \"quote\": \"原文引用（英文）\",\n      \"quoteRef\": \"Para B, Line 3\",\n      \"analysisPoints\": [\"分析要点1\", \"分析要点2\"],\n      \"rejectedOptions\": [\n        { \"option\": \"A\", \"reason\": \"原文未提及该关系，属于无中生有\" },\n        { \"option\": \"C\", \"reason\": \"与原文事实矛盾，原文说的是...\" },\n        { \"option\": \"D\", \"reason\": \"范围扩大/信息不匹配\" }\n      ]\n    }\n  ],\n  \"actionItems\": [\n    \"下次做 TFNG 前必须标注否定词\",\n    \"Summary 填空必须三步走\"\n  ],\n  \"synonyms\": [\n    {\n      \"original\": \"原文表达\",\n      \"replacement\": \"题目表达\",\n      \"meaning\": \"中文释义\",\n      \"questionRef\": \"Q3\"\n    }\n  ],\n  \"vocabulary\": [\n    {\n      \"word\": \"exemplify\",\n      \"phonetic\": \"/ɪɡˈzemplɪfaɪ/\",\n      \"pos\": \"v.\",\n      \"definition\": \"举例说明\",\n      \"ieltsFreq\": 3,\n      \"source\": \"538 #42\",\n      \"appearance\": \"剑7T1P3\"\n    }\n  ],\n  \"problems\": [\n    {\n      \"type\": \"同义替换识别失败\",\n      \"detail\": \"具体表现\",\n      \"questions\": \"Q3, Q7\",\n      \"improvement\": \"改进方法\"\n    }\n  ]\n}\n```\n\n**v4.0 相对 v3.0 新增字段**（均可选，v3.0 JSON 仍能被模板页渲染）：\n- `progressNote`：进步总评\n- `alertNote`：告警信息\n- `answers[]`：全部答案对照表（含 result: correct/wrong/skipped）\n- `actionItems[]`：行动清单\n- `wrongQuestions[].badge`：**错误分类**简写标签（如 \"NG/FALSE混淆\"、\"过度推理选TRUE\"、\"Summary填空定位错误\"），与 `type`（题型）区分开\n- `wrongQuestions[].quote` / `quoteRef`：原文引用 + 定位\n- `wrongQuestions[].analysisPoints[]`：分析要点列表\n- `wrongQuestions[].rejectedOptions[]`：**选择题和判断题专用**——为什么不选其他选项。仅 `type === \"multipleChoice\"` 或 `type === \"tfng\"` 时填写。数组每项 `{ option: \"A\", reason: \"原因...\" }`（选择题用 A/B/C/D，判断题用 Y/N/NG），列出除正确答案外所有错误选项的排除理由。review.html 会以红色边框卡片渲染（标题\"为什么不选\"，每个选项带圆圈字母+排除原因）\n\n**🔴 wrongQuestions 中 type 与 badge 的区别（MUST FOLLOW）**：\n- `type`：**题型**标识，使用标准 ID（`tfng` / `fillBlank` / `summary` / `multipleChoice` / `matching` / `heading` / `sentenceCompletion`）\n- `badge`：**错误分类**标签（如 \"NG/FALSE混淆\"、\"过度推理\"、\"Summary填空没回原文\"）\n- 两者含义不同，**禁止互相赋值**。旧格式 JSON 中 `error_analysis` 只有 `error_type`（错误分类），没有题型信息，review.html 会从 `questions[]` 交叉获取题型\n\n**🔴 answers[] 字段名规范（MUST FOLLOW）**：\n\n`answers` 数组中每条记录的字段名**必须**严格使用以下格式：\n```json\n{ \"q\": 1, \"my\": \"TRUE\", \"correct\": \"TRUE\", \"result\": \"correct\" }\n```\n- `my`：用户答案（不是 `myAnswer`）\n- `correct`：正确答案字符串（不是布尔值）\n- `result`：`\"correct\"` / `\"wrong\"` / `\"skipped\"`（字符串，不是布尔值）\n\n> **注意**：`wrongQuestions[]` 里用的是 `myAnswer` / `correctAnswer`（全拼），和 `answers[]` 的缩写不同。这是历史设计，review.html 模板已做兼容处理，两种格式都能正确渲染。\n\n### Step 3b: Bilingual Data (v5.0 — 已预置，无需操作)\n\n> **⚠️ v5.0 变更（2026-05-11）**：服务端已预置 C4-C20 100 篇核心双语数据，复盘流程**不再需要**生成或维护 bilingual_data.json。\n>\n> 仅以下场景需要扩展：\n> - 复盘 C20 之后的新书（C21+）\n> - 用户明确要求为某篇生成精翻双语\n>\n> 默认跳过此步骤。\n\n#### ~~3b-2: 双语 HTML 文件~~（已废弃）\n\n> **v3.8 起不再需要**。旧 `bilingual/*.html` 已清理，Web 端通过 `bilingual.html` 模板页动态加载 `bilingual_data.json` 渲染。\n\n### Step 4: Generate PDF (Optional — Rarely Used)\n\n如果用户明确需要 PDF，可从线上复盘页面打印。本地不再生成 HTML，因此也不支持 puppeteer PDF 生成。\n\n### Step 5: Update Memory\n\n复盘完成后更新 working memory：新增的错误模式、词汇、成绩数据。\n\n### Step 6: Apply to Web (Automatic — saveReview API)\n\n复盘 JSON 生成后，**必须立即通过 saveReview API 入库**（Step 7c），不需要用户手动操作。\n\n完成后输出：\n\n---\n\n📤 **复盘完成！**\n\nJSON 已入库，线上查看 👉 [review.html?file=剑X-TestX-PassageX-主题复盘.json](https://www.liuxue.online/ielts/review.html?file=剑X-TestX-PassageX-主题复盘.json)\n\n---\n\n#### 其他同步方式（备选）\n\n**方式 B：Skill 伴侣脚本**（私有部署场景）\n\n如果有 `ielts-server-sync` skill（个人专用），可命令行批量上传：\n\n```bash\n# 单文件上传\nnode ~/.workbuddy/skills/ielts-server-sync/scripts/upload.js 剑5-T1-P2.json\n\n# 批量上传目录\nnode ~/.workbuddy/skills/ielts-server-sync/scripts/upload.js --batch ./reviews/\n```\n\n**方式 C：手动上传**\n\n打开 [submit.html?mode=json](https://www.liuxue.online/ielts/submit.html?mode=json) 拖入 JSON 文件。\n\n### Step 7: Deploy Checklist (MANDATORY — DO NOT SKIP)\n\n**🔴 每次复盘完成后，必须逐项执行以下检查清单。不能靠记忆，必须逐条过。**\n\n**🔀 先看 Step 0a 模式横幅，按模式走对应分支**：\n- **作者模式** → 走下面的 7a-7g 完整部署链路\n- **客户端模式** → 跳到本节末尾的「Step 7-Client」客户端简化流程，**不要碰 7a-7g 的 SSH 操作**\n\n---\n\n#### 7a. 本地文件归位（仅作者模式）\n\n- [ ] 复盘 JSON 已复制到 `site/reviews/`\n- [ ] `generate_vocab_synonym.py` 已运行，更新 dict_full.json + synonym_data.json\n- [ ] **🔴 词库覆盖校验（MUST — 否则词卡展开不工作）**：运行以下检查，确保本篇所有 vocabulary 词汇都在 `dict_full.json` 中有完整条目（含 meaning_cn + examples）\n\n> **v5.0 变更**：~~answer-key.json 更新~~ 和 ~~bilingual_data.json 更新~~ 已从清单中移除。服务端已预置 C4-C20 全量数据，复盘流程无需再维护这两个文件。复盘 C21+ 时才需要扩展 answer-key（参考末尾「扩展新书」章节）。\n\n```python\n# 词库覆盖校验（复盘生成后必跑）\nimport json\nwith open('site/dict_full.json') as f:\n    dmap = {w['word'].lower(): w for w in json.load(f) if 'word' in w}\nwith open('site/reviews/剑X-TestX-PassageX-主题复盘.json') as f:\n    vocab = json.load(f).get('vocabulary', [])\nmissing = [v['word'] for v in vocab if v['word'].lower() not in dmap]\nif missing:\n    print(f'❌ dict_full.json 缺失 {len(missing)} 词：{missing}')\n    print('→ 必须补充这些词（含 meaning_cn/examples/synonyms）后再部署')\nelse:\n    print('✅ 词库覆盖完整')\n```\n\n如果有缺失词：**立即补充到 dict_full.json**（每词需含 meaning_cn、phonetic、root、examples、synonyms、antonyms），补完重新部署。\n**绝不能跳过此步**——缺词 = 线上词卡点击无响应 = 用户体验崩坏。\n\n#### 7b. 部署到线上\n\n**v5.0 精简后只需部署以下 3 个文件**（answer-key/bilingual 已服务端预置）：\n\n```\nsite/reviews/剑X-TestX-PassageX-主题复盘.json    → /var/www/ielts/reviews/\nsite/dict_full.json                              → /var/www/ielts/\nsite/synonym_data.json                           → /var/www/ielts/\n```\n\n**🔴 大文件传输规则（>1MB 用 gzip 流，不要分块！）**：\n\n大于 1MB 的文件（如 dict_full.json ~6MB）**禁止直接 SCP，禁止 split 分块**，必须用 gzip 管道一行秒传：\n\n```bash\n# 🔴 唯一正确方式：gzip 流 + 先落临时文件再 mv（原子写，防止中途断流留下 0 字节空文件）\ngzip -c site/dict_full.json | ssh openclaw-tunnel \"gunzip > /var/www/ielts/dict_full.json.tmp && mv /var/www/ielts/dict_full.json.tmp /var/www/ielts/dict_full.json\"\n\n# 验证完整性（🔴 必须显式加 encoding='utf-8'，否则服务器 locale 非 UTF-8 时会误报 UnicodeDecodeError）\nssh openclaw-tunnel \"python3 -c \\\"import json; d=json.load(open('/var/www/ielts/dict_full.json', encoding='utf-8')); print(f'OK: {len(d)} words')\\\"\"\n```\n\n> **⚠️ 教训（2026-06-23）**：直接 `gunzip > 目标文件` 若管道中途失败，会把目标文件清成 0 字节（覆盖了原好文件）。务必走 `.tmp` + `mv` 原子替换，验证报错时也只丢临时文件。\n\n> **⚠️ 教训（2026-06-23 二）**：服务器 `python3 open()` 不指定 `encoding='utf-8'` 时会按系统 locale 解码，含中文的 dict_full.json 会抛 `UnicodeDecodeError`，让人误以为文件损坏。验证 JSON 一律加 `encoding='utf-8'`。文件大小本地/服务器一致(`wc -c`)即证明传输无误，别被解码报错骗了。\n\n> **⚠️ 历史教训**：split 分块传输复杂且易出错（分批 SCP 超时、拼合顺序错乱），已于 2026-05-08 彻底弃用。gzip 流利用 SSH 隧道的持久连接，一次性完成压缩传输，稳定可靠。\n\n**小文件（<1MB）仍可直接 SCP**：\n```bash\nscp -o ConnectTimeout=15 \\\n    -o StrictHostKeyChecking=accept-new \\\n    -o UserKnownHostsFile=~/.ssh/known_hosts_cfd \\\n    -o \"ProxyCommand=/Users/dengjiawei/bin/cloudflared access tcp --hostname ssh.tuyaya.online\" \\\n    -i ~/.ssh/workbuddy.pem \\\n    <本地文件> ubuntu@ssh.tuyaya.online:/var/www/ielts/\n```\n\n**或用 SSH stdin 管道（<500KB 的文件最快）**：\n```bash\nssh openclaw-tunnel \"cat > /var/www/ielts/synonym_data.json\" < site/synonym_data.json\n```\n\n#### 7c. saveReview API 入库（MANDATORY）\n\n复盘数据必须写入后端数据库，否则首页进度图看不到这篇：\n\n```bash\nssh openclaw-tunnel 'python3 -c \"\nimport json, urllib.request\npayload = json.dumps({\n    \\\"action\\\": \\\"saveReview\\\",\n    \\\"token\\\": \\\"<USER_TOKEN>\\\",\n    \\\"book\\\": X, \\\"test\\\": Y, \\\"passage\\\": Z,\n    \\\"score\\\": <correct>, \\\"total\\\": <total>, \\\"duration\\\": <minutes>,\n    \\\"date\\\": \\\"YYYY-MM-DD\\\",\n    \\\"answers\\\": {}\n})\nreq = urllib.request.Request(\\\"http://localhost:3100/api/ielts\\\", data=payload.encode(), headers={\\\"Content-Type\\\": \\\"application/json\\\"})\nresp = urllib.request.urlopen(req)\nprint(resp.read().decode())\n\"'\n```\n\n> API 路径是 `POST /api/ielts`，通过 `action` 字段分发（不是 `/api/ielts/saveReview`）。\n\n#### 7d. 后端代码部署（仅当 server/index.js 有改动时）\n\n如果本次涉及 server 代码变更，需同步后端：\n\n```bash\n# 后端小文件可直接 stdin 传\nssh openclaw-tunnel \"cat > /home/ubuntu/ielts-api/index.js\" < server/index.js\n\n# 新增的 lib/ 目录\nssh openclaw-tunnel \"mkdir -p /home/ubuntu/ielts-api/lib\"\nssh openclaw-tunnel \"cat > /home/ubuntu/ielts-api/lib/llmExtractor.js\" < server/lib/llmExtractor.js\nssh openclaw-tunnel \"cat > /home/ubuntu/ielts-api/lib/schemaUpgrader.js\" < server/lib/schemaUpgrader.js\nssh openclaw-tunnel \"cat > /home/ubuntu/ielts-api/lib/tencentOcr.js\" < server/lib/tencentOcr.js\n\n# 如有新 npm 依赖\nssh openclaw-tunnel \"cd /home/ubuntu/ielts-api && npm install\"\n```\n\n**🔴 部署红线**：\n- **严禁覆盖 `/etc/systemd/system/ielts-api.service`**——里面有 AI_API_URL/KEY/MODEL 等生产密钥\n- 新密钥只通过 drop-in 追加：`/etc/systemd/system/ielts-api.service.d/secrets.conf`\n- 详见 `.workbuddy/upload-upgrade-ops.md`\n\n#### 7e. 后端重启\n\n```bash\nssh openclaw-tunnel \"sudo systemctl restart ielts-api\"\n```\n\n**必须重启**——后端启动时 `buildReviewFileIndex()` 扫描 `reviews/` 目录建索引。不重启 = 新文件不出现在首页。\n\n#### 7f. 线上验证\n\n- [ ] `getReadingPageData` API 返回新篇目数据（`POST /api/ielts` + `action: getReadingPageData`）\n- [ ] 复盘链接可正常访问：`review.html?file=剑X-TestX-PassageX-主题复盘.json`\n- [ ] **🔴 词卡展开验证**：打开复盘页面，点击词汇表中至少 1 个词，确认能弹出详情卡（含释义/例句/近义词）。如果点击无反应 → dict_full.json 缺词，回 7a 补词\n- [ ] （v5.0 已预置）双语数据 C4-C20 已服务端预置，无需逐篇验证；C21+ 新书需手动确认 `bilingual.html?book=X&test=Y&passage=Z`\n\n#### 7g. 🔴 强制入库回归验证（v5.1 新增 — 防止 saveReview 漏调）\n\n**血泪教训（2026-05-11）**：复盘 JSON 部署成功了，但 saveReview API 没调通，导致首页看不到新篇。**部署 ≠ 入库**，必须**回查数据库**验证。\n\n完成 7c 后必须立即执行以下检查：\n\n```bash\n# 用 getReviews 回查本篇是否真的入库（替换 BOOK/TEST/PASSAGE）\ncurl -s https://www.liuxue.online/api/ielts -H 'Content-Type: application/json' \\\n  -d '{\"action\":\"getReviews\",\"token\":\"<USER_TOKEN>\",\"book\":<BOOK>,\"test\":<TEST>}' \\\n  | python3 -c \"\nimport json,sys\nd = json.load(sys.stdin)\nrecords = [r for r in d.get('data',[]) if r['book']==<BOOK> and r['test']==<TEST> and r['passage']==<PASSAGE>]\nif records:\n    print('✅ 入库成功:', records[0])\nelse:\n    print('❌ 入库失败！必须重新调 saveReview API')\n    sys.exit(1)\n\"\n```\n\n**如果验证失败**：立即重新调 saveReview API，再回查，直到 ✅。**绝对不能跳过此步**——本步骤 PASS 才算复盘真正完成。\n\n**曾犯的典型遗漏**（引以为戒）：\n1. 文件生成在根目录没 cp 到 site/reviews/\n2. 没重启后端导致 review 索引没刷新\n3. JSON 文件没 SCP 到 reviews/\n4. **dict_full.json 缺词导致词卡展开不工作**——复盘新增词汇不在词库中，必须做词库覆盖校验\n5. **没调 saveReview API 导致首页进度图缺数据**——文件部署 ≠ 数据入库，两者都要做\n6. **answers[] 用了错误字段名**——必须用 `my`/`correct`(字符串)/`result`(字符串)，不能用布尔值\n7. **不要生成复盘 HTML**——后端 review.html 模板统一渲染 JSON，单独生成 HTML 无用\n8. **dict_full.json 大文件传输用 gzip 流**——禁止 split 分块（复杂且易错），一行 `gzip -c | ssh gunzip >` 搞定\n9. **旧格式 JSON 错题重复渲染**——`questions[]` 和 `error_analysis[]` 都有错题时，review.html 会去重。但生成 v4.0 JSON 时应**只用 wrongQuestions[]**，不要同时写两种格式\n10. **type/badge 混用导致标签重复**——`type` 是题型（tfng/fillBlank），`badge` 是错误分类（NG/FALSE混淆）。禁止互相赋值\n\n---\n\n## Step 7-Client: 客户端模式部署流程（NO SSH）\n\n**何时走这条**：Step 0a 检测到「客户端模式」（如老婆机器、外部用户机器）。\n\n**核心原则**：客户端没 SSH 凭据、没 `/var/www/ielts/` 写权限，**只能通过 HTTPS 接口写数据库**。词库、模板、双语数据全部由作者机维护，客户端不参与。\n\n### 7-Client-a. 本地保存 JSON\n\n让用户选个保存目录（推荐 `~/Documents/雅思复盘/` 或当前工作目录的 `reviews/`），把生成的 JSON 写进去。**不要往 `site/reviews/` 写**——客户端没这个目录或者目录是别人的。\n\n### 7-Client-b. 通过 batchImport 入库（替代 saveReview）\n\nbatchImport 是带 token 的官方 HTTPS 通道，能吃 v4.0 富 JSON（服务端 schemaUpgrader 自动转换扁平字段写入），最适合客户端：\n\n```bash\n# 单篇上传（推荐用 review-upload skill 的脚本）\nbash ~/.workbuddy/skills/ielts-review-upload/scripts/sync-review.sh \\\n  ~/Documents/雅思复盘/剑X-TestX-PassageX-主题复盘.json\n```\n\n或者直接 curl：\n\n```bash\nTOKEN=\"$IELTS_USER_TOKEN\"  # 从环境变量读\nJSON_FILE=\"~/Documents/雅思复盘/剑X-TestX-PassageX-主题复盘.json\"\n\nPAYLOAD=$(python3 -c \"\nimport json, sys\nwith open(sys.argv[1]) as f:\n    review = json.load(f)\nprint(json.dumps({\n    'action': 'batchImport',\n    'token': sys.argv[2],\n    'reviews': [review]\n}, ensure_ascii=False))\n\" \"$JSON_FILE\" \"$TOKEN\")\n\ncurl -s -X POST https://www.liuxue.online/api/ielts \\\n  -H 'Content-Type: application/json' \\\n  -d \"$PAYLOAD\"\n```\n\n预期返回：\n```json\n{\"code\":0,\"message\":\"导入完成：1 条成功，0 条跳过\",\"data\":{\"imported\":1,\"skipped\":0,\"upgraded\":1}}\n```\n\n`upgraded:1` 表示服务端识别到 v4.0 富格式并跑了 schemaUpgrader。\n\n### 7-Client-c. 入库回查（必做）\n\n```bash\ncurl -s https://www.liuxue.online/api/ielts \\\n  -H 'Content-Type: application/json' \\\n  -d \"{\\\"action\\\":\\\"getReviews\\\",\\\"token\\\":\\\"$IELTS_USER_TOKEN\\\",\\\"book\\\":<BOOK>,\\\"test\\\":<TEST>}\" \\\n  | python3 -m json.tool | head -30\n```\n\n确认返回的 data 数组里有刚上传那篇（`book`/`test`/`passage` 三元组匹配），并且 `username` 是登录账号（如 `lishuzhuo`），不是 `dengjiawei`。\n\n### 7-Client-d. 给用户的最终输出\n\n```\n✅ 复盘已入库\n\n📊 在主页查看进度图、词汇本、错题本：\n👉 https://www.liuxue.online/ielts/reading.html\n   （登录账号：<username>）\n\n📄 复盘详情页：\n👉 https://www.liuxue.online/ielts/review.html?file=剑X-TestX-PassageX-主题复盘.json\n```\n\n> **客户端模式注意**：复盘详情页 `review.html?file=...` 依赖服务端 `/var/www/ielts/reviews/` 下的 JSON 文件。客户端模式只把数据写进数据库，**不上传 JSON 文件到服务器**，所以详情页可能 404。但首页进度图、词汇本、错题本能正常工作（这些数据都从数据库读）。\n>\n> 如果用户特别想要详情页可访问，提醒他把 JSON 发给作者人工部署，或者作者机用 `ielts-server-sync` skill 同步。\n\n### 7-Client 红线（绝对禁止）\n\n- 🚫 `ssh openclaw-tunnel ...`\n- 🚫 `scp ... ubuntu@ssh.tuyaya.online:...`\n- 🚫 `gzip -c | ssh openclaw-tunnel \"gunzip > /var/www/...\"`\n- 🚫 `sudo systemctl restart ielts-api`\n- 🚫 修改 `dict_full.json` / `synonym_data.json` / `bilingual_data.json` / `answer-key.json` 后试图部署\n- 🚫 部署 `site/reviews/` 下的 JSON 文件到服务器\n\n**客户端只做两件事**：本地存 JSON + HTTPS batchImport 入库。\n\n### 7-Client onboarding（首次配置）\n\n如果用户首次跑客户端模式，缺 `IELTS_USER_TOKEN`，按以下流程引导：\n\n1. 浏览器登录 https://www.liuxue.online/ielts/login.html\n2. F12 打开 DevTools → Console\n3. 输入 `localStorage.token`，回车，复制返回字符串（一长串 base64）\n4. 在 `~/.zshrc` 末尾加：\n   ```bash\n   export IELTS_USER_TOKEN='粘贴token'\n   ```\n5. `source ~/.zshrc` 或重开终端\n6. 验证：`echo \"${IELTS_USER_TOKEN:0:20}...\"` 应输出前 20 个字符\n\ntoken 默认有效期 10 年，配一次基本一劳永逸。\n\n## 扩展新书（C21+）\n\n服务端预置数据仅覆盖 C4-C20。复盘剑21及以后的书时，需要额外做：\n\n1. 在 `site/answer-key.json` 追加条目（格式：`C{book}-T{test}-R{passage}`，**R 不是 P**）\n2. SCP 到 `/var/www/ielts/answer-key.json`\n3. （可选）追加 `site/bilingual_data.json` 并 SCP\n4. 重启后端：`ssh openclaw-tunnel \"sudo systemctl restart ielts-api\"`\n\nC4-C20 范围内的复盘**不需要**这一步。\n\n## Batch Import Mode (v3.8 — Legacy Review Folder → JSON)\n\n**触发场景**：用户说\"帮我把 XX 目录下的历史复盘都转成 JSON\"、\"批量导入我以前的复盘笔记\"、\"扫一下我电脑里的复盘\"、\"帮我找出所有历史笔记\"等。\n\n此模式下 Buddy 自主循环，**无需用户自己找路径、无需一篇篇喂**。\n\n### Step B0: Auto-Discovery（🔍 推荐默认起点）\n\n**不要开口就问用户\"复盘文件夹在哪？\"**——先自动扫常见位置：\n\n```bash\nnode ~/.workbuddy/skills/ielts-reading-review/scripts/scan-legacy-reviews.js --auto\n```\n\n脚本会扫描以下位置并按命中数推荐：\n- 当前工作目录 (cwd)\n- `~/Documents`、`~/Documents/个人`、`~/Documents/个人/WorkBuddy`\n- `~/Desktop`、`~/Downloads`\n- `~/Library/Mobile Documents/com~apple~CloudDocs`（iCloud）\n- `~/WorkBuddy`、`~/WorkBuddy/Claw`\n\n输出 `discoveries`（去重后的真实命中目录，命中数多的子目录优先）和 `recommended`（首选目录）。\n\n**把发现结果呈现给用户**：\n\n```\n我扫了你电脑常见位置，找到你的复盘应该在这里：\n\n🎯 推荐：/Users/xxx/Documents/个人/WorkBuddy/雅思学习（60 个候选文件）\n   样例：剑6-Test3-Passage3-抗衰老药物复盘.html / 剑4-Test1-听力Part2-河滨工业村复盘.html …\n\n其他候选：\n  - /Users/xxx/Downloads（4 个）\n\n要用推荐目录还是选其他的？\n```\n\n用户点头后进入 Step B1 做精扫。**只有当自动发现完全找不到候选（discoveries 为空）时**，才问用户要具体路径。\n\n### Step B1: Scan the Folder\n\n调用扫描脚本生成候选清单：\n\n```bash\n# 默认只扫顶层\nnode ~/.workbuddy/skills/ielts-reading-review/scripts/scan-legacy-reviews.js <目录> --out=/tmp/ielts-scan.json\n\n# 需要递归子目录\nnode ~/.workbuddy/skills/ielts-reading-review/scripts/scan-legacy-reviews.js <目录> --deep --out=/tmp/ielts-scan.json\n```\n\n输出 JSON 结构（groups 按篇目聚合）：\n\n```json\n{\n  \"totalFiles\": 18,\n  \"identifiedPassages\": 6,\n  \"groups\": [\n    {\n      \"passage\": \"C5-T1-P2\",\n      \"fileCount\": 3,\n      \"files\": [\n        { \"path\": \"...\", \"ext\": \".html\", \"hints\": { \"book\": 5, \"test\": 1, \"passage\": 2, \"title\": \"鲸鱼感官\" } },\n        { \"path\": \"...\", \"ext\": \".md\" },\n        { \"path\": \"...\", \"ext\": \".png\" }\n      ]\n    },\n    { \"passage\": \"__unknown__\", \"files\": [...] }\n  ]\n}\n```\n\n### Step B2: Show Plan & Confirm\n\n读取 scan 结果后，**必须先给用户一份执行计划**，不要直接开干：\n\n```\n扫描完成，找到 18 个候选文件，识别出 6 篇复盘：\n\n✅ 可识别：\n  1. 剑5-T1-P2 · 鲸鱼感官（HTML + MD + 截图，共 3 个文件）\n  2. 剑5-T1-P3 · 儿童认知（HTML）\n  3. 剑6-T2-P1 · ...\n  ...\n\n⚠️ 无法识别篇目（需你人工分配）：\n  - notes-2026-03-15.md\n  - 错题整理.docx\n\n我将逐篇处理可识别的 6 篇，每篇生成一个 JSON。预计 10-15 分钟。\n确认开始？\n```\n\n用户点头后才进入 Step B3。\n\n### Step B3: Loop — Generate JSON for Each Passage\n\n**逐篇循环**，每次处理一组：\n\n1. 读取该组所有文件内容（HTML 提纯文字、MD 直读、图片用视觉 OCR）\n2. 从内容中提取：原文/正确答案/用户答案/错题/时长/日期\n3. **关键兜底**：\n   - 内容里找不到\"正确答案\" → 查 `site/answer-key.json`（本地答案库，401 题全覆盖）\n   - 找不到用户答案 → 标注 `score.correct = null` 让用户后续补\n   - 错题列表不清晰 → 只生成基础成绩单 JSON，`wrongQuestions: []`\n4. 按 v4.0 schema 生成 JSON（v3.0 新增字段可选），文件名 `剑X-TestX-PassageX-中文主题复盘.json`\n5. 写入用户指定的输出目录（默认 `./batch-output/`）\n6. 输出一行进度：`✅ [3/6] 剑5-T1-P3 · 儿童认知 → 剑5-Test1-Passage3-儿童认知复盘.json`\n\n### Step B4: Summary Report\n\n全部完成后输出总结：\n\n```\n批量导入完成！\n\n✅ 成功：5 篇（已生成 5 个 JSON 到 ./batch-output/）\n⚠️ 部分数据缺失：1 篇（剑6-T2-P1 找不到用户答案，score.correct 置空）\n❌ 跳过：0 篇\n\n下一步：\n👉 打开 https://www.liuxue.online/ielts/submit.html?mode=json\n👉 把 ./batch-output/ 里所有 JSON 拖进去，一键导入\n```\n\n### Batch Mode Rules (MUST FOLLOW)\n\n1. **永远先 scan + confirm，绝不跳过计划确认**\n2. **每篇独立处理，失败不阻塞下一篇**（捕获异常，记录到 skip 列表）\n3. **绝不编造数据**：用户答案缺失就置 null 或空数组，不要瞎填\n4. **同义替换/词汇/错因分析是可选项**：老笔记里没有就不生成，不要硬凑\n5. **答案库优先**：正确答案一律从 `site/answer-key.json` 核对，笔记里的可能是老婆写错的\n6. **产物隔离**：批量输出统一放 `./batch-output/`，不污染用户工作目录\n\n## Error Analysis Rules\n\n### TRUE / FALSE / NOT GIVEN 三步法\n\n1. **找话题** — 文章有没有讨论题目中的对象？→ 没讨论 = **NOT GIVEN**\n2. **找立场** — 讨论了的话，是同意还是矛盾？→ **TRUE** / **FALSE**\n3. **验证** — \"如果选 TRUE/FALSE，能指出原文哪句话吗？\" 指不出来 → 大概率 **NOT GIVEN**\n\n关键区分：\n- FALSE 需要**直接矛盾证据**，\"没提到\"= NG 不是 FALSE\n- 概括性表达覆盖题目对象 = 算讨论过，不是 NG\n- `however + adj` = `no matter how`（让步），不是因果\n\n### Fill-in-the-blank\n\n- 答案不能重复题干已有的词\n- 填完必须通读：语法/词性/语义/字数 四项检查\n- `such as ___` → 必须填具体例子\n- `the ___ of X` → 必须填能和 \"of X\" 搭配的名词\n\n### Common Pitfalls\n\n- **过度推理**：只看作者明确写了什么，不推导\n- **被绝对词吓到**：all/never 不一定错，看原文证据\n- **人名观点混淆**：先在文中标注每个人说了什么\n- **邻近干扰词**：从定位句提取答案，不要被旁边的句子污染\n- **Heading 复用 Example**：做 Heading 题第一步永远是划掉 Example 已用的选项\n- **Although 从句看错重点**：主句才是作者立场，让步从句只是背景\n- **双重否定读反了**：not unusual=usual, not uncommon=common, rarely+isn't=几乎总是。看到双重否定立刻翻译成肯定\n- **Summary 填空凭感觉**：必须先回原文找对应句，再从选项中匹配。不回原文 = 全靠蒙\n- **对比信号词忽略**：\"difference from X\" 本身就是对比框架，后面的内容就是证据\n- **选择题选了和全文论点相反的**：选完后反问\"这个选项和作者核心主张一致吗？\"\n- **段落匹配被信息密度干扰**：题目问 \"term\"（定义），选了有数字的段落而非有 \"refer to as\" 的段落。精确锁定每个关键词含义\n- **Summary 填空近义词混用**：同段落两个近义表达，看题目限定词（如 Britain）对应原文哪个子语境\n- **Summary 填空专有名称不完整**：看到引号/大写开头名称，先数字数，限制内写全称不缩写\n\n## Error Categories\n\n参见 `references/error-taxonomy.md`，共 18 类错误分类。JSON 中 `errorCategory` 字段使用以下 ID：\n\n| ID | 错误类型 |\n|----|---------|\n| `synonym-failure` | 同义替换识别失败 |\n| `ng-false-confusion` | NOT GIVEN / FALSE 混淆 |\n| `over-inference` | 过度推理 |\n| `stem-repetition` | 填空重复题干词 |\n| `grammar-mismatch` | 语法/让步句理解错 |\n| `incomplete-option` | 选项不完全匹配 |\n| `vocab-gap` | 词汇缺口 |\n| `carelessness` | 粗心/时间压力 |\n| `word-form-error` | 填空词形/词性错 |\n| `scope-confusion` | 跨代/范围混淆 |\n| `category-reasoning` | 类别推理误判 |\n| `adjacent-distractor` | 邻近干扰词 |\n| `heading-example-reuse` | Heading匹配复用Example已用选项 |\n| `concessive-clause-confusion` | Although/While让步从句混淆主句 |\n| `double-negative-misread` | 双重否定读不出肯定 |\n| `summary-no-source` | Summary填空没回原文定位 |\n| `comparison-signal-ignored` | 对比信号词(difference from等)忽略 |\n| `selection-contradicts-thesis` | 选择题选了和全文论点矛盾的选项 |\n\n## Style Guidelines\n\n- 简洁直接，不废话\n- 错题分析直说问题，不糖衣炮弹\n- 中文为主，英语术语保留原文\n\n## 🔴 Step 8: Final Gate (v5.5.2 — Mandatory before any ending)\n\n**任何复盘对话，在你即将给出收尾回复（\"复盘完成 / 总结 / 错题分析全部跑完\"）之前，必须先逐条过完以下 4 个 Gate。任何一条 ❌ 一律返回继续干，禁止结束。**\n\n| Gate | 自检问题 | 判定来源 |\n|---|---|---|\n| **Gate 1** | 我有没有为本次每一篇生成 v4.0 富 JSON 写到 `site/reviews/`？ | `ls site/reviews/` 看到对应文件 |\n| **Gate 2** | 我有没有调 `saveReview`（作者模式）或 `upload.js`/`batchImport`（客户端模式）？ | 看上面命令的返回值是 `success/code:0` |\n| **Gate 3** | 我有没有用 `getReviews` 回查确认入库 ✅？ | 回查 JSON 里有匹配 book/test/passage 的 record |\n| **Gate 4** | 我有没有把线上链接（`www.liuxue.online/ielts/review.html?file=...`）写进给主人的最终回复？ | 检查最终回复文本 |\n\n**自检模板（在收尾前内部默念一遍）：**\n\n```\nGate 1: site/reviews/剑X-TestX-PassageX-主题复盘.json  ✅ / ❌\nGate 2: saveReview / upload.js  ✅ / ❌\nGate 3: getReviews 回查命中  ✅ / ❌\nGate 4: 最终回复包含线上链接  ✅ / ❌\n```\n\n**若任意一条 ❌**：立即回到对应 Step 补做，绝不允许\"先交付文字版，再说\"。\n\n**作者机一键回查命令（复制即用）：**\n\n```bash\nTOKEN=$(cat ~/.ielts-tuyaya-token | python3 -c \"import json,sys; print(json.load(sys.stdin)['token'])\")\ncurl -s 'https://www.liuxue.online/api/ielts' -H 'Content-Type: application/json' \\\n  -d \"{\\\"action\\\":\\\"getReviews\\\",\\\"token\\\":\\\"$TOKEN\\\",\\\"book\\\":<BOOK>,\\\"test\\\":<TEST>}\" \\\n  | python3 -c \"import json,sys; d=json.load(sys.stdin); recs=[r for r in d.get('data',[]) if r['book']==<BOOK> and r['test']==<TEST>]; print('✅ 已入库篇目:', [(r['passage'], r['score'], r['total']) for r in recs])\"\n```\n\n**若主人对话里只发了某一两篇阅读题**：完成那几篇的 4 个 Gate 即可，不要扩展到整个 Test。\n\n**若做完一篇主人立刻发下一篇**：先把当前篇 4 Gate 全过 ✅，再开下一篇。绝对不允许积压。\n\n> 这道 Gate 是 v5.5.2 的灵魂。其他所有 step 都可以小幅偷懒，唯独这道 Gate 必须 100% 过完。\n\n## 客户端模式参考\n\n外部用户/老婆机器首次配置看这里：[`references/CLIENT_MODE_ONBOARDING.md`](references/CLIENT_MODE_ONBOARDING.md)\n\n一键脚本：`bash ~/.workbuddy/skills/ielts-reading-review/scripts/setup-client-mode.sh`\n\nFile v5.5.2:README.md\n\n# IELTS Reading Review 雅思阅读复盘助手\n\n> Finish a reading passage, hand it to AI, get a complete review — error analysis, synonym tracking, vocabulary tagging, and mistake pattern detection, all in one go.\n\n做完阅读题，丢给 AI，自动出复盘笔记——错题拆解、同义替换积累、考点词标注、易错模式追踪，一步到位。\n\n---\n\n## 🆕 What's New in v5.4 — OAuth 风格浏览器授权流\n\n**告别 F12 复制 token 的笨流程**——客户端模式绑定账号体验彻底重做：\n\n### 🎯 30 秒上手（替代原来 5 分钟）\n\n```bash\nbash ~/.workbuddy/skills/ielts-reading-review/scripts/setup-client-mode.sh\n```\n\n脚本自动完成 4 件事：\n\n1. **本机起临时 HTTP 服务**（随机空闲端口监听 OAuth 回调）\n2. **唤起浏览器**到 `https://www.liuxue.online/ielts/authorize.html`\n3. **页面显示 OAuth 风格卡片**：客户端名 / 本机回调地址 / 当前账号 / 权限列表 / 【拒绝】【授权】\n4. **点【授权】** → token 通过 `<img>` 请求回传本机 → 自动写入 `~/.zshrc` → 显示绑定账号名\n\n### 🔒 安全设计\n\n| 风险点 | 防护机制 |\n|---|---|\n| token 被中间人截获 | 全程仅浏览器 ↔ 本机 127.0.0.1，不走第三方 |\n| token 进 URL bar 被记录 | 用 `<img src=...?token>` GET 而非 `location.href`，不留浏览历史 |\n| CORS / Private Network 拦截 | 用图片请求绕过预检 |\n| 跨站伪造请求 | `secrets.token_urlsafe(16)` 生成 state，服务端校验 |\n| 恶意回调地址 | 授权页强制白名单：仅 `127.0.0.1 / localhost / ::1` + http |\n\n### 🪟 三系统全覆盖\n\n- macOS：`open` 命令唤起浏览器\n- Linux：`xdg-open`\n- 兜底：打印链接，用户手动复制到浏览器\n\n### 🛟 兜底模式\n\n浏览器/网络异常时：\n\n```bash\nbash setup-client-mode.sh --manual\n```\n\n回退到 F12 → Console → `localStorage.ielts_user_token` 复制粘贴的老流程。\n\n---\n\n## 🆕 What's New in v3.1 — Web Hand-off\n\n### 🌐 生成物一键上传到 Web 端\n\nv3.1 在保持纯离线生成的同时，**明确了 JSON 产出物与 Web 端的对接路径**：\n\n- 访问 https://www.liuxue.online/ielts/submit.html 切到「**上传 JSON**」Tab\n- 把 skill 生成的 `.json` 文件拖进去 → 成绩、答案、用时自动入库\n- 首页成绩矩阵、词汇本、同义替换本实时更新\n\n### 📊 Web 端新增 JSON 导入能力\n\nWeb 端 `submit.html` 新增第 4 种提交模式（粘贴文本 / PDF / 拍照 / **上传 JSON**），与 skill 的产出物严格对齐 v3.0 schema。\n\n## 🆕 What's New in v3.0 — Offline-First\n\n### 🔌 去服务器依赖，纯本地生成\n\nv3.0 重构为**纯离线模式**：\n\n- ✅ 复盘 HTML — 专业排版，浏览器直接查看\n- ✅ 复盘 PDF — 一键导出，存档分享\n- ✅ 结构化 JSON — 包含成绩、错题、词汇、同义替换等全量数据\n- 🔜 数据上传 — 后续通过 Web 端功能将 JSON 导入云系统，实现多设备同步\n\n**不再依赖任何远程 API**，AI Agent 在本地完成所有分析和生成工作。\n\n### 📋 填空回填 4 步检查\n\n每道填空题强制 4 步验证：语法 → 词性 → 语义 → 字数，杜绝低级失误。\n\n### ✅ 正确题确认 + 进步表扬\n\n- 做对的题也会简要确认，展示同义替换映射帮你强化记忆\n- 每篇开头先肯定你的进步点，保持刷题动力\n\n### 🔢 错误分类扩展到 12 类\n\n涵盖：同义替换识别失败、NG/FALSE 混淆、过度推理、填空重复题干、语法误解、选项不完全匹配、词汇缺口、粗心、词形错误、跨代/范围混淆、类别推理误判、邻近干扰词。\n\n---\n\n## 🚀 快速开始（3 步上手）\n\n### 第一步：安装 Skill\n\n```bash\n# ClawHub 安装（推荐）\nclawhub install ielts-reading-review\n\n# 或手动复制到 skills 目录\ncp -r ielts-reading-review ~/.workbuddy/skills/\n```\n\n### 第二步：做完一篇阅读题\n\n用剑桥雅思真题（Cambridge IELTS）做完一篇阅读，准备好：\n- ✅ 原文（拍照/截图/粘贴文字都行）\n- ✅ 正确答案\n- ✅ 你的答案（标出哪些做错了）\n- ⭕ 可选：翻译、用时\n\n### 第三步：发给 AI，说\"帮我复盘\"\n\n就这么简单。AI 会自动生成：\n1. **复盘 HTML** — 专业排版的复盘笔记\n2. **复盘 JSON** — 结构化数据文件，供后续导入 Web 系统\n3. **复盘 PDF**（可选）— 从 HTML 生成，便于存档\n\n---\n\n## 📖 完整使用案例\n\n> 以下是一个真实的使用过程，以剑4 Test 3 Passage 1 为例。\n\n### 你发给 AI 的内容\n\n```\n我做完了剑4 Test3 Passage1，帮我复盘。\n\n文章：Micro-Enterprise Credit for Street Youth\n用时：34:40\n得分：7/13\n\n我的答案 vs 正确答案：\nQ1: 我选D → 正确A\nQ2: 我选C → 正确D\nQ3: ✅\nQ4: ✅\nQ5: 我填 Sudan and India → 正确 Sudan\nQ6: ✅\nQ7: 我填 shoe shine → 正确 Shoe Shine Collective\nQ8-Q10: ✅\nQ11: 我选 NOT GIVEN → 正确 NO\nQ12: ✅\nQ13: 我选D → 正确A\n\n（然后把原文和翻译也贴上来）\n```\n\n### AI 自动产出\n\nAI 会在本地生成三个文件：\n\n#### 📄 复盘 HTML — `剑4-Test3-Passage1-街头青年信贷复盘.html`\n\n包含以下模块：\n- 得分总览 + Band 分换算 + 核心问题一句话\n- 进步点肯定\n- 逐题错因分析（定位原文、映射同义替换、分类错因、给出教训）\n- 正确题确认\n- 同义替换积累表\n- 考点词表\n- 核心问题总结\n- 行动清单\n\n#### 📊 结构化 JSON — `剑4-Test3-Passage1-街头青年信贷复盘.json`\n\n```json\n{\n  \"version\": \"3.0.0\",\n  \"source\": { \"book\": 4, \"test\": 3, \"passage\": 1 },\n  \"score\": { \"correct\": 7, \"total\": 13, \"band\": \"5.0\" },\n  \"wrongQuestions\": [...],\n  \"synonyms\": [...],\n  \"vocabulary\": [...],\n  \"problems\": [...]\n}\n```\n\n后续可通过 Web 端将此 JSON 上传到云系统，实现多设备同步和进度追踪。\n\n#### 📑 复盘 PDF（可选）\n\n```bash\nnode scripts/generate-pdf.js 剑4-Test3-Passage1-街头青年信贷复盘.html\n```\n\n---\n\n## 🎯 Features\n\n| 功能 | 说明 |\n|------|------|\n| **逐题错因分析** | 定位原文、映射同义替换、分类错因（12 类）、给出 1 句话教训 |\n| **正确题确认** | 正确答案也简要展示同义替换映射，强化记忆 |\n| **同义替换积累** | 自动提取题目-原文同义替换对，跨篇持续积累 |\n| **考点词标注** | 基于刘洪波 538 考点词（⭐⭐⭐/⭐⭐/⭐）+ COCA 5000 词频 |\n| **易错模式追踪** | 跨篇检测反复犯的错 |\n| **📋 填空回填检查** | 每道填空题 4 步强制验证（语法/词性/语义/字数） |\n| **📊 打分 & Band 换算** | 原始分→雅思 Band 分数换算（学术类） |\n| **📄 结构化 JSON 输出** | 成绩、错题、词汇、同义替换全量数据，供 Web 系统导入 |\n| **HTML + PDF 输出** | 排版专业的复盘笔记，支持打印和存档 |\n\n## 📂 File Structure\n\n```\nielts-reading-review/\n├── SKILL.md                          # Skill 定义（AI 读这个文件理解工作流）\n├── README.md                         # 使用说明（你正在看的这个）\n├── assets/\n│   ├── review-template.html          # HTML 模板 + CSS 样式\n│   └── bilingual-template.html       # 双语对照页面模板\n├── references/\n│   ├── error-taxonomy.md             # 12 类错误分类体系\n│   ├── 538-keywords-guide.md         # 考点词评级指南\n│   ├── score-band-table.md           # 分数→Band 换算表\n│   └── review-style-guide.md         # 写作风格规范\n└── scripts/\n    └── generate-pdf.js               # PDF 生成脚本\n```\n\n## 🧠 内置做题方法论\n\n### T/F/NG 三步判断法\n1. **找话题** — 原文有没有讨论题目说的这个话题？→ 没有 → **NOT GIVEN**\n2. **找立场** — 如果话题存在，作者同意还是反对？→ **TRUE** / **FALSE**\n3. **验证** — \"如果我选 TRUE/FALSE，能指出原文哪一句吗？\"指不出来 → 大概率 **NOT GIVEN**\n\n### 填空题防重复规则\n答案不要重复题目中已有的词。填完后把答案放回原句完整读一遍。\n\n### 选择题逐词验证法\n选项中的**每个关键词**都要在原文找到对应。\"大致相关\" ≠ \"能选\"。前半句对但后半句多了信息 → 干扰项。\n\n## 📤 数据导入 Web 系统\n\nv3.1 起，生成的 JSON 文件可**直接通过 Web 端导入**（已上线）：\n\n### 方式 1：Web 端拖拽上传（推荐）\n\n1. 访问 **https://www.liuxue.online/ielts/submit.html**\n2. 登录账号（第一次使用会引导注册）\n3. 切换到顶部 Tab「**📊 上传 JSON**」\n4. 把 skill 生成的 `.json` 文件拖入上传区（或点击选择）\n5. 点「导入到我的记录」\n\n导入成功后，以下页面会自动刷新：\n- **首页成绩矩阵** — 新篇目变绿，显示得分\n- **词汇本** — JSON 中的考点词自动合并\n- **同义替换本** — JSON 中的同义替换对自动入库\n- **个人中心** — 统计总数、均分、Band 分更新\n\n### 方式 2：命令行批量上传（进阶）\n\n需要额外安装 `ielts-server-sync` skill（作者个人维护，不公开发布）：\n\n```bash\n# 单文件\nnode ~/.workbuddy/skills/ielts-server-sync/scripts/upload.js 剑5-T1-P2.json\n# 批量\nnode ~/.workbuddy/skills/ielts-server-sync/scripts/upload.js --batch ./reviews/\n# 查服务器记录\nnode ~/.workbuddy/skills/ielts-server-sync/scripts/upload.js --status\n```\n\n### 方式 3：HTML 本地存档\n\n直接双击生成的 `.html` 文件，浏览器打开即可阅读 / 打印，不依赖任何服务器，隐私可控。\n\n## 👤 Who It's For\n\n雅思备考者，尤其是：\n- 阅读 5-7 分想突破的\n- 复盘效率低，做完题不知道怎么分析的\n- 同样的错反复犯，需要系统追踪的\n- 想把词汇积累和真题练习结合起来的\n\n## ⚙️ Requirements\n\n- 支持 SKILL.md 的 AI Agent（如 OpenClaw、Claude Code、WorkBuddy/CodeBuddy）\n- PDF 导出需要：Node.js + puppeteer-core + 本地 Chrome（可选，不装也能用 HTML）\n\n## 🤝 Contact & Feedback\n\nIf this Skill helps your IELTS prep, a ⭐ Star would mean a lot!\n\n如果这个 Skill 对你备考有帮助，欢迎点个 ⭐ 支持！\n\n- 💡 **Feature requests / Bug reports**: [Open an Issue](https://github.com/dengjiawei1226/ielts-reading-review/issues)\n\n## License\n\nMIT-0\n\nFile v5.5.2:_meta.json\n\n{\n  \"ownerId\": \"kn7dr93fbgrvymnk8d9r9y0tws83mhrk\",\n  \"slug\": \"ielts-reading-review\",\n  \"version\": \"5.5.2\",\n  \"publishedAt\": 1782184016232\n}\n\nFile v5.5.2:references/538-keywords-guide.md\n\n# 538 IELTS Keywords Reference Guide\n\n## About This Resource\n\nThe 538 Keywords list comes from Liu Hongbo's \"Cambridge IELTS Reading Keywords\" (刘洪波《剑桥雅思阅读考点词真经》). It categorizes high-frequency words that appear repeatedly in IELTS Academic Reading questions.\n\n## How to Use for Vocabulary Rating\n\nWhen building the vocabulary table in a review note, look up each word against the 538 list:\n\n### Rating Scale\n\n| Rating | Category | Count | Question Appearance Rate |\n|--------|----------|-------|------------------------|\n| ⭐⭐⭐ | Category 1 | 54 words | ~90% of passages contain these |\n| ⭐⭐ | Category 2 | 171 words | ~60% of passages contain these |\n| ⭐ | Category 3 | 300+ words | Common but less predictable |\n| — | Not listed | N/A | Check COCA 5000 for general frequency |\n\n### Lookup Procedure\n\n1. Search the full 538 list (provided as `雅思阅读538考点词-刘洪波真经.txt` in the workspace) for the target word\n2. If found, note its category number and rank\n3. Record in the vocabulary table as: `⭐⭐⭐ 538考点词 #XXX` (where XXX is the rank)\n4. If not found in the 538 list, check COCA 5000 for general English frequency\n5. Words below COCA 3000 that are not in the 538 list can be marked as low-priority\n\n### COCA 5000 Supplementary Use\n\nThe COCA (Corpus of Contemporary American English) 5000 frequency list (`COCA_5000词频表.csv`) provides general English word frequency rankings. Use it to:\n\n- Determine if an unknown word is commonly used in English (not just IELTS)\n- Prioritize learning: COCA top 2000 = essential everyday English; 2000-5000 = academic/professional English\n- A word in COCA top 3000 but not in the 538 list is still worth learning for general proficiency\n\n### Cambridge Test Appearance Column\n\nThe \"真题出现\" (Cambridge Appearance) column tracks where a word has actually appeared in Cambridge IELTS tests. Format:\n\n- Single appearance: `剑4T3P2`\n- Multiple appearances: `剑4T3P2, 剑7T1P1, 剑9T2P3`\n- This column is **cumulative** — add new appearances as more passages are reviewed\n- High-frequency words appearing across multiple books indicate they are particularly important\n\nFile v5.5.2:references/CLIENT_MODE_ONBOARDING.md\n\n# 👩‍🎓 给老婆/外部用户：跑通整套 Skill 复盘流程\n\n这份文档教你怎么把 `ielts-reading-review` + `ielts-review-upload` 两个 Skill 跑成「客户端模式」，让 AI 帮你做完整复盘后**自动同步到你 www.liuxue.online 账号下的进度图、词汇本、错题本**。\n\n> 不是给作者本人用的——作者机直接走 SSH 部署链路。这份文档专门给**没有 openclaw-tunnel SSH 凭据**的机器准备。\n\n## 你能得到什么\n\n- ✅ 发截图给 AI → AI 自动识别错题、生成富 JSON 复盘\n- ✅ 复盘自动入库 → 网站首页进度图实时更新\n- ✅ 词汇/错题/同义替换 → 自动同步到你账号下的复习本\n- ✅ 不需要任何 SSH 知识、不需要碰服务器\n\n## 前置条件\n\n1. 已在 https://www.liuxue.online/ielts/login.html 注册账号（如 lishuzhuo）\n2. 本机装了 WorkBuddy / CodeBuddy（能用 `Skill` 工具）\n3. 装好 `ielts-reading-review` + `ielts-review-upload` 这两个 Skill\n\n## 一次性配置（30 秒搞定）\n\n```bash\nbash ~/.workbuddy/skills/ielts-reading-review/scripts/setup-client-mode.sh\n```\n\n**这是浏览器授权流（v5.4 新版）**：\n1. 脚本启动一个本地随机端口的 HTTP 服务（监听本机回调）\n2. 自动打开浏览器到 `www.liuxue.online/authorize.html`\n3. 在页面看到客户端信息卡片，点击 **「授权」**\n4. token 经浏览器以 `<img>` 请求方式回传到本机（**永远不离开你的电脑**）\n5. 脚本自动校验 + 写入 `~/.zshrc`，显示绑定的账号名\n\n> 网络/浏览器异常时可手动跑兜底模式：`bash setup-client-mode.sh --manual`\n> 这种情况下需要 F12 → Console → 输入 `localStorage.ielts_user_token` 复制 token 粘贴到终端。\n\n完成后重开终端或 `source ~/.zshrc`。\n\n**验证成功标志**：\n```bash\necho \"${IELTS_USER_TOKEN:0:20}...\"   # 应该看到 eyJ1Ijoi... 之类的前缀\n```\n\n## 日常用法\n\n直接对 AI 说：\n\n```\n复盘剑8 Test1 Passage2，错题截图：[贴图]，用时 32:15\n```\n\nAI 会自动：\n1. 检测到客户端模式\n2. 读截图识别错题（先报清单等你确认）\n3. 生成富 JSON 复盘到本地（默认 `~/Documents/雅思复盘/`）\n4. 通过 HTTPS batchImport 上传到你账号\n5. 回查 getReviews 确认入库\n6. 给你主页链接：`https://www.liuxue.online/ielts/reading.html`\n\n## 数据归属\n\n- 上传通道：`POST https://www.liuxue.online/api/ielts {action:'batchImport', token}`\n- 数据落点：主库 `ielts_reviews` 表，`username` 字段 = 你的登录账号\n- 主页效果：登录后能看到进度图、词汇本、错题本同步更新（和作者本人完全同等待遇）\n\n## 限制（客户端模式做不到的）\n\n- ❌ 不能部署复盘 JSON 文件到服务器，所以「复盘详情页」`review.html?file=...` 可能 404\n  - **绕过**：把复盘 JSON 发给作者人工部署，或继续在本地查看\n- ❌ 不能扩展词库（dict_full.json）/双语数据（bilingual_data.json）\n  - **绕过**：作者机已预置 C4-C20 全量数据，C21+ 才需要扩展\n\n但**首页进度图、词汇本、错题本完全可用**——这些数据都从数据库读，不依赖文件部署。\n\n## 出问题怎么办\n\n| 症状 | 解决 |\n|---|---|\n| `echo $IELTS_USER_TOKEN` 没输出 | `source ~/.zshrc` 或重开终端 |\n| AI 说\"token 过期\" | 重新登录 www.liuxue.online，重跑 setup-client-mode.sh |\n| 主页看不到新复盘 | 确认 AI 输出里有 `imported:1, upgraded:1`，没有就是 batchImport 没调通 |\n| AI 误走 SSH 部署 | 检查 Step 0a 模式横幅，应该是「客户端模式」，否则升级 Skill |\n\n## Token 安全\n\n- token 默认有效期 10 年\n- 写在本地 `~/.zshrc`，不要发到群里/截图给别人\n- 怀疑泄漏可以登录后端管理页面手动重置（联系作者）\n\nFile v5.5.2:references/error-taxonomy.md\n\n# Error Taxonomy for IELTS Reading Review\n\nThis document classifies common IELTS reading errors into categories. When analyzing a wrong answer, identify which category applies and use the corresponding improvement advice.\n\n## Category 1: Synonym / Paraphrase Recognition Failure\n\n**Description:** The passage uses a synonym or paraphrase of the question's keyword, and the test-taker fails to recognize the equivalence.\n\n**Examples:**\n- Question says \"financial__(adj)\" → Passage says \"economic\"\n- Question says \"\n\n\n\" → Passage says \"children / young people\"\n- Question says \"\n\n\n\" → Passage says \"the\n\n\n of the world\"\n\n**Improvement:** Actively build a synonym accumulation table after every passage. Reference the 538 keywords list for known IELTS synonyms.\n\n---\n\n## Category 2: NOT GIVEN vs FALSE Confusion\n\n**Description:** Choosing FALSE when the passage simply doesn't discuss the topic (should be NOT GIVEN), or choosing NOT GIVEN when there is direct contradicting evidence (should be FALSE).\n\n**Key Rule:**\n- **FALSE** = The passage explicitly says the **opposite** of the question\n- **NOT GIVEN** = The passage does **not discuss** the topic at all, or discusses it but without taking a clear position that matches or contradicts\n\n**Improvement:** Apply the Three-Step Method every time — find topic → find stance → verify with a specific sentence.\n\n---\n\n## Category 3: Over-Inference\n\n**Description:** Drawing a conclusion that the passage does not explicitly state. The test-taker adds their own reasoning or world knowledge on top of what the author wrote.\n\n**Examples:**\n- Passage discusses ancient archaeological methods → Test-taker infers \"translating ancient texts\" was also mentioned (it wasn't)\n- Passage says a task requires \"a wider range of skills\" → Test-taker infers \"more demanding\" (not the same thing)\n\n**Improvement:** Ask: \"Can I point to the **exact sentence** that says this?\" If no → do not choose it.\n\n---\n\n## Category 4: Repeating Stem Words in Fill-in-the-blank\n\n**Description:** Writing a word that is already present in the question stem, making the answer grammatically redundant.\n\n**Examples:**\n- Stem: \"...about their ___\" → Wrong answer: \"about their experiences\" (duplicates \"about\" or \"their\")\n- Stem: \"The ___ of...\" → Wrong answer: \"The the process of...\" (duplicates \"The\")\n\n**Improvement:** After writing the answer, **re-read the complete sentence** with the answer filled in. Check for any duplication.\n\n---\n\n## Category 5: Grammar Mismatch (Concessive / Conditional Clauses)\n\n**Description:** Misunderstanding sentence structure, especially:\n- Concessive clauses (`however + adj/adv` = `no matter how`)\n- Conditional clauses that don't assert facts\n- Double negatives\n\n**Examples:**\n- \"However far from reality...\" = \"No matter how far from reality...\" (acknowledges it IS far from reality)\n- NOT \"This is close to reality\"\n\n**Improvement:** Parse the sentence structure before interpreting meaning. Identify the main clause vs. subordinate clauses.\n\n---\n\n## Category 6: Incomplete Option Matching (Multiple Choice)\n\n**Description:** Selecting an option where only the first half matches the passage. The second half introduces information not present in the passage.\n\n**Improvement:** Check **every keyword** in the option against the passage. All must match, not just some.\n\n---\n\n## Category 7: Vocabulary Gap\n\n**Description:** Not knowing a critical word in the passage or question, leading to misunderstanding.\n\n**Note:** This is only flagged when the unknown word is a high-frequency IELTS word (in the 538 list or COCA top 3000). Low-frequency/specialist vocabulary gaps are noted but not treated as a core error.\n\n**Improvement:** Focus vocabulary building on the 538 keywords list and accumulate words encountered in real Cambridge tests.\n\n---\n\n## Category 8: Time Pressure / Carelessness\n\n**Description:** The test-taker understood the passage and could have answered correctly but made an error due to rushing or insufficient checking.\n\n**Improvement:** Build in a final checking step for every passage before moving on.\n\n---\n\n## Category 9: Fill-in-the-blank Word Form / Part-of-Speech Error\n\n**Description:** The answer has the right root word but wrong form (e.g., adjective instead of noun, singular instead of plural), making it grammatically incorrect when placed back into the sentence.\n\n**Examples:**\n- Stem: \"where ___ are unpredictable\" → Wrong: `temperate` (adjective) → Correct: `temperatures` (noun plural)\n- Stem: \"the ___ of plants\" → Wrong: `classify` (verb) → Correct: `classification` (noun)\n\n**Key Rule:** After filling in the answer, **read the complete sentence aloud**. If the grammar doesn't work (e.g., \"where temperate are unpredictable\"), the word form is wrong.\n\n**Improvement:** Apply the **Fill-in-the-blank Readback Checklist** (see style guide) for every single blank — grammar check, part-of-speech check, semantic check, word count check.\n\n---\n\n## Category 10: Cross-generational / Scope Confusion\n\n**Description:** Confusing what happens to **one individual** vs. **the next generation** or **the species as a whole**. Also applies to mistaking individual cases for general trends.\n\n**Examples:**\n- \"Bamboos flower, fruit and die\" → One bamboo flowers once in its life cycle (then dies). The *next generation* flowering later is NOT the same plant flowering again.\n- \"life cycle\" = one individual's life span, not the species' multi-generational history\n\n**Key Rule:** When the passage mentions generations, cycles, or \"the next...\", track **whose** life cycle or **which** generation is being discussed.\n\n**Improvement:** Circle the subject of each clause. \"Every bamboo flowered\" vs. \"The next generation flowered\" — different subjects, different events.\n\n---\n\n## Category 11: Category-Membership Reasoning Treated as Inference\n\n**Description:** When the passage establishes \"Category A has property B\" and then states \"X belongs to Category A\", concluding \"X has property B\" is **direct information**, not inference. The test-taker wrongly treats this as over-inference and chooses NOT GIVEN.\n\n**Examples:**\n- Passage: \"Shade-tolerant plants have lower growth rates\" + \"Eastern hemlock is shade-tolerant\" → Eastern hemlock has lower growth rates. This is NOT inference — it's stated through category membership.\n- Test-taker chose NOT GIVEN thinking \"the passage doesn't directly say eastern hemlock has lower growth rates\"\n\n**Key Rule:** If the passage says \"A-type things have X\" and \"Y is A-type\", then \"Y has X\" is **a stated fact**, not inference. This is TRUE/FALSE territory, not NOT GIVEN.\n\n**Improvement:** When you're leaning toward NOT GIVEN, check: did the passage put the subject into a category that was already described? If yes, the category's properties apply.\n\n---\n\n## Category 12: Adjacent Distractor Words\n\n**Description:** The correct answer word is near other plausible-looking words in the passage. The test-taker picks a nearby word instead of the one that actually fits the sentence structure.\n\n**Examples:**\n- Passage: \"This **classification** is commonly used in forestry and horticulture.\" The word `habitat` appears nearby in the next sentence. Test-taker fills `habitat` instead of `classification`.\n- Passage: \"like **sugarcane**, never reach a maximum, but continue to increase photosynthesis rate as light intensity rises.\" Test-taker fills `light intensity rises` instead of `sugarcane`.\n\n**Key Rule:** After locating the relevant sentence, **only extract the answer from that specific sentence**. Don't let nearby sentences contaminate your answer.\n\n**Improvement:** Underline the exact sentence that corresponds to the question structure, then extract only from within that sentence.\n\n---\n\n## Category 13: Heading Match — Using Example's Answer\n\n**Description:** In List of Headings questions, the test-taker selects a heading that was already used by the worked Example, effectively double-assigning it.\n\n**Examples:**\n- Example assigns heading `iii` to Section A. Test-taker picks `iii` again for Section D.\n- The correct heading for Section D was `v`, but test-taker forgot to cross off `iii`.\n\n**Key Rule:** **First step of any Heading Match question**: cross off ALL headings already used by Examples. They are eliminated and cannot be reused (unless the question says \"NB You may use any heading more than once\").\n\n**Improvement:** Before even reading the paragraphs, physically cross off used headings. Mark positive/negative tone for remaining headings, then match.\n\n---\n\n## Category 14: Concessive Clause Main-Clause Confusion\n\n**Description:** In sentences with Although/While/Despite/Even though, the test-taker bases their judgment on the concessive (subordinate) clause instead of the main clause. The main clause carries the author's actual position.\n\n**Examples:**\n- \"Although industrial output has soared, water consumption has slowed\" → Author's point = consumption slowed (main clause), NOT output soared (concessive clause)\n- Test-taker judges Y/N/NG based on \"industrial output soared\" and ignores the main clause contradiction\n\n**Key Rule:** In Although/While/Despite sentences: concessive clause = acknowledged background; **main clause = author's real position**. Y/N/NG judgment must be based on the main clause.\n\n**Improvement:** Circle the main clause. Ask: \"What is the author actually asserting?\" The Although-clause is just context.\n\n---\n\n## Category 15: Double Negative Misread\n\n**Description:** Failing to recognize that two negatives cancel out to make a positive. This error has appeared in multiple forms and keeps recurring.\n\n**Complete checklist of double-negative patterns:**\n- `not unusual` = usual / common\n- `not uncommon` = common\n- `not insignificant` = significant\n- `not unimportant` = important\n- `not unlikely` = likely\n- `rarely + isn't` = almost always is\n- `seldom + not` = almost always\n- `hardly + negative` = positive\n\n**Key Rule:** When you see ANY negative prefix (un-, in-, im-) or negative adverb (rarely, seldom, hardly) combined with another negative (not, isn't, wasn't), immediately translate to the positive equivalent.\n\n**Improvement:** Highlight every negative word in the sentence. Count them. Even number of negatives = positive meaning.\n\n---\n\n## Category 16: Summary Fill-in-the-blank Without Source Location\n\n**Description:** Attempting Summary completion by looking at the answer options and guessing which \"feels right\" for each blank, without first locating the corresponding passage sentences.\n\n**The 0/4 Disaster (C7T1P3 Q37-40):** All four blanks wrong because the test-taker never went back to the passage to find the matching sentences.\n\n**Mandatory Three-Step Process:**\n1. **Locate** the corresponding paragraph(s) in the passage\n2. **Find** the specific sentence that matches the summary statement\n3. **Match** the option word to the original passage word/concept\n\n**Key Rule:** Summary blanks are NOT a vocabulary test — they are a paraphrase-matching exercise. The answer is always findable in the passage. If you can't point to the passage sentence, you're guessing.\n\n**Improvement:** Before filling ANY blank, write down the passage paragraph and sentence number where the answer comes from. No source = don't fill.\n\n---\n\n## Category 17: Comparison Signal Words Ignored\n\n**Description:** Missing comparison frameworks like \"difference from X\", \"unlike X\", \"in contrast to X\" which establish that the subject has a different property from X.\n\n**Examples:**\n- \"Another difference from conventional teaching is the evidence that students can learn 1000 new words\" → suggestopedia students learn MORE than conventional (1000 words IS the difference)\n- Test-taker chose FALSE because \"no direct number comparison is given\" — but \"difference from X\" IS the comparison framework\n\n**Key Rule:** \"Difference from X\" = the subject is NOT like X in this respect. The rest of the sentence describes HOW it differs. You don't need two numbers side-by-side.\n\n**Improvement:** Circle comparison markers (difference from, unlike, in contrast to, compared with). These are implicit comparisons — the sentence after them IS the evidence.\n\nFile v5.5.2:references/review-style-guide.md\n\n# Review Note Style Guide (V2)\n\n## General Tone\n\n- **Concise and direct** — No decorative language, no marketing-speak\n- **Function-oriented** — Every sentence exists to help the user improve\n- **Honest about errors** — Sugar-coating doesn't help learning; be blunt about what went wrong\n- **Chinese as primary language** — English terms, vocabulary, and passage quotes preserved as-is\n\n## V2 Design System\n\nThe review notes use a modern card-based design with CSS Variables, Lucide SVG icons, and a purple gradient hero header. All icons come from Lucide (CDN: `unpkg.com/lucide@latest`), no emoji in the HTML.\n\n### CSS Class Reference\n\n| V2 Class | Purpose | Notes |\n|----------|---------|-------|\n| `.container` | Main content wrapper | `max-width: 960px` |\n| `.hero` | Purple gradient header | Contains `.book-tag`, `h1`, `.subtitle`, `.stats-row` |\n| `.hero-nav` | Top-right nav buttons | Links to index + bilingual page |\n| `.book-tag` | Source tag (e.g. \"剑6 · Test 1 · Passage 1\") | Inside `.hero` |\n| `.stats-row` > `.stat-item` | Score stats in hero | `.stat-value` + `.stat-label` |\n| `.time-badge` | Time spent badge | Inside `.subtitle` |\n| `.card` | Generic content card | White bg, rounded corners, shadow |\n| `.card-title` | Card header with icon | `.icon-box` + text |\n| `.status-chip.good` | Progress highlight | Green icon, success theme |\n| `.status-chip.warn` | Alert / core problem | Amber icon, warning theme |\n| `.error-item` | Error analysis card | Red left border, contains sub-components |\n| `.q-header` | Question header row | `.q-num` + `.badge` tags |\n| `.badge-fill` | Blue info badge | Question type tag |\n| `.badge-type` | Gray badge | Sub-type tag |\n| `.answer-compare` | Answer comparison row | `.ans-box.mine` + `.ans-box.correct` |\n| `.quote-block` | Passage quote | Gray bg, `.quote-label` header |\n| `.analysis-block` | Error cause analysis | `.section-label` + `<ul>` |\n| `.lesson-box` | Lesson learned | Purple-tinted bg |\n| `.data-table` | Data tables (vocab, synonyms) | Dark header (`#1e1b4b`), rounded |\n| `.overview-table` | Answer overview table | Accent-colored header |\n| `.problem-table` | Problem summary table | Red header |\n| `.freq-stars` | IELTS frequency stars | Lucide `<i data-lucide=\"star\">` with `.empty` class |\n| `.takeaway` | Action items card | Purple gradient bg, white text |\n| `.result-correct` | Correct answer indicator | Green text + check icon |\n| `.result-wrong` | Wrong answer indicator | Red text + x icon |\n\n### Key CSS Variables\n\n```css\n:root {\n  --bg: #f0f2f5;        /* Page background */\n  --card: #ffffff;       /* Card background */\n  --text: #1d1d1f;       /* Primary text */\n  --text-secondary: #6b7280;  /* Secondary text */\n  --accent: #4f46e5;     /* Brand purple */\n  --accent-light: #eef2ff;    /* Light purple bg */\n  --success: #059669;    /* Green (correct) */\n  --danger: #dc2626;     /* Red (wrong) */\n  --warning: #d97706;    /* Amber (alert) */\n  --info: #2563eb;       /* Blue (info) */\n  --border: #e5e7eb;     /* Border color */\n  --radius: 16px;        /* Card radius */\n  --radius-sm: 10px;     /* Small radius */\n}\n```\n\n### Icon Usage\n\nAll icons use Lucide SVG via `<i data-lucide=\"icon-name\"></i>`. Common icons:\n- `home` — Index link\n- `book-open` — Bilingual page link / passage quote\n- `clock` — Time spent\n- `trending-up` — Progress highlight\n- `alert-triangle` — Core problem alert\n- `x-circle` — Error section header\n- `x` — Wrong answer\n- `check` — Correct answer\n- `brain` — Error analysis\n- `lightbulb` — Lesson learned\n- `repeat` — Synonym section\n- `book-marked` — Vocabulary section\n- `alert-circle` — Problem summary\n- `zap` — Action items\n- `star` — IELTS frequency rating (`.freq-stars`)\n\n## Section-by-Section Guidelines\n\n### Hero Header\n- Purple gradient with `.book-tag`, title, subtitle with time badge\n- `.stats-row` shows score breakdown (总分 / 填空 / 判断 / 匹配)\n- `.hero-nav` top-right with links to index and bilingual page\n\n### Progress & Alert Chips\n- `.status-chip.good` — Always find at least 1 positive point, even in a bad score\n- `.status-chip.warn` — ONE sentence identifying the biggest scoring pattern\n- Be specific: \"T/F/NG 前 4 道全对\" is good; \"有进步\" is bad\n- Bad example: \"阅读理解能力有待提升\" ← too vague\n- Good example: \"3道判断题全错，均为 NG 误判为 FALSE——没区分「没提到」和「相反」\" ← specific and actionable\n\n### Error Analysis Blocks (`.error-item`)\n- `.q-header` with question number and type badges\n- `.answer-compare` showing user's wrong answer vs correct answer\n- `.quote-block` with passage quote and location label\n- `.analysis-block` with error cause bullets\n- `.lesson-box` with single-sentence takeaway\n- Error cause should reference the error taxonomy category\n\n### Correct Answer Brief Analysis\nFor correct answers on non-trivial questions (especially T/F/NG), include within the answer overview table or as a brief note. Keep to 2-3 lines showing the synonym mapping. Purpose: reinforce synonym recognition.\n\n### Synonym Table (`.data-table`)\n- Only include synonyms relevant to the questions (not every synonym in the passage)\n- Columns: 原文表达 | 题目表达 | 出处\n- Include the question number for cross-reference\n\n### Vocabulary Table (`.data-table`)\n- Include phonetic transcription (IPA) after the word\n- Part of speech before the definition\n- IELTS frequency rating is mandatory — use `.freq-stars` with Lucide star icons\n- \"真题出现\" column tracks which real tests the word has appeared in\n- Skip low-frequency specialist terms unless they caused an error\n\n### Problem Summary (`.problem-table`)\n- Red header table\n- Columns: 问题类型 | 具体表现 | 对应错题 | 改进方法\n\n### Takeaway Card (`.takeaway`)\n- Purple gradient background, white text\n- Numbered action items with `<strong>` in gold (`#fde68a`)\n- Include synonym additions as `<code>` items\n\n### Fill-in-the-blank Readback Checklist\nWhen fill-in errors exist, include as a `.status-chip.warn`:\n1. 语法检查 — 放回去读一遍\n2. 词性检查 — 空格前后决定词性\n3. 语义检查 — 答案和题目主题匹配\n4. 字数检查 — 不超过限制\n\n### Per-question-type Progress Trend\nWhen 3+ passages of the same question type exist, include a trend table inside a `.status-chip.good`:\n- Bold the current passage row\n- Add ↑/↑↑/↓ indicators\n- After the table, 2-3 sentences of specific analysis\n\n### Test Scorecard (Full Test)\n- Generated when user completes all 3 passages\n- Use `.data-table` format\n- Format: P1/P2/P3 scores, 总计/40, 总用时, 雅思分数\n- Band score from `references/score-band-table.md`\n\n### Cumulative Progress Table\n- Generated when 2+ full tests exist\n- Rows ordered chronologically\n- After the table: accuracy trend, speed analysis, strategy advice, per-passage pattern\n\n## Naming Convention\n\n### Review notes\n`剑X-TestX-PassageX-TopicKeyword复盘.html`\n\nExamples:\n- `剑4-Test3-Passage1-街头青年信贷复盘.html`\n- `剑6-Test1-Passage1-澳洲体育成功复盘.html`\n\n### Bilingual pages\n`剑X-TestX-PassageX-TopicKeyword双语对照.html`\n\nExamples:\n- `剑5-Test4-Passage3-光对动植物影响双语对照.html`\n- `剑6-Test1-Passage1-澳洲体育成功双语对照.html`\n\n## Formatting Rules\n\n- Use the V2 CSS classes documented above (NOT the deprecated V1 classes)\n- Icons use Lucide SVG (`<i data-lucide=\"...\"></i>`), not emoji\n- Tables use `.data-table`, `.overview-table`, or `.problem-table` styling\n- Keep `break-inside: avoid` on cards and error items for clean PDF output\n- All pages load Lucide from CDN at the end of `<body>`:\n  ```html\n  <script src=\"https://unpkg.com/lucide@latest\"></script>\n  <script>lucide.createIcons();</script>\n  ```\n\n### Deprecated V1 Classes (DO NOT USE)\n\nThese classes belong to the old V1 template and should NOT appear in new reviews:\n\n| Deprecated Class | V2 Replacement |\n|-----------------|----------------|\n| `.correct` | `.result-correct` |\n| `.wrong` | `.result-wrong` |\n| `.tag-yes` / `.tag-no` / `.tag-ng` | `.badge` with appropriate styling |\n| `.alert-box` | `.status-chip.warn` |\n| `.good-box` | `.status-chip.good` |\n| `h1/h2/h3` section headers | `.card-title` with `.icon-box` |\n| `blockquote` for quotes | `.quote-block` with `.quote-label` |\n| `max-width: 800px` | `max-width: 960px` via `.container` |\n| `#4A90D9` hardcoded blue | `var(--accent)` CSS variable |\n\nFile v5.5.2:references/score-band-table.md\n\n# IELTS Academic Reading: Score-to-Band Conversion Table\n\nThis table maps raw scores (number of correct answers out of 40) to IELTS band scores for the **Academic** reading module.\n\n> **Source**: Based on publicly available IELTS scoring data and Cambridge official practice test score converters. Actual band scores may vary slightly between test versions.\n\n## Conversion Table\n\n| Raw Score (/40) | Band Score |\n|-----------------|------------|\n| 39-40           | 9.0        |\n| 37-38           | 8.5        |\n| 35-36           | 8.0        |\n| 33-34           | 7.5        |\n| 30-32           | 7.0        |\n| 27-29           | 6.5        |\n| 23-26           | 6.0        |\n| 19-22           | 5.5        |\n| 15-18           | 5.0        |\n| 13-14           | 4.5        |\n| 10-12           | 4.0        |\n| 8-9             | 3.5        |\n| 6-7             | 3.0        |\n| 4-5             | 2.5        |\n| 2-3             | 2.0        |\n| 1               | 1.0        |\n| 0               | 0.0        |\n\n## How to Use\n\n1. Sum the user's correct answers across all 3 passages (total out of 40)\n2. Look up the raw score in the table above\n3. If the score falls on the boundary between two bands (e.g., 29 could be 6.5, 30 could be 7.0), show as a range: `6.5-7.0`\n4. Always specify this is an **estimate** — actual IELTS scoring uses a more complex algorithm\n\n## Boundary Scores (Important)\n\nThese are the key thresholds users care about:\n\n| Target Band | Minimum Raw Score | Meaning |\n|-------------|-------------------|---------|\n| 5.0         | 15                | Basic competence |\n| 5.5         | 19                | Common university minimum |\n| 6.0         | 23                | Standard university requirement |\n| 6.5         | 27                | Competitive university requirement |\n| 7.0         | 30                | Top university / immigration threshold |\n| 7.5         | 33                | Excellence benchmark |\n| 8.0         | 35                | Near-native proficiency |\n\n## Notes\n\n- This conversion is for **Academic Reading only** (General Training has a different scale)\n- Cambridge practice tests tend to be slightly easier than the real exam\n- Use this for progress tracking, not as a guarantee of actual test performance\n- Encourage users who are close to a boundary (within 2-3 marks) — small improvements yield band jumps\n\nFile v5.5.2:skill-card.md\n\n## Description:\n\nIELTS Reading passage review, scoring, and progress tracking skill that generates structured review JSON and can upload results to www.liuxue.online for web rendering.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[dengjiawei1226](https://clawhub.ai/user/dengjiawei1226)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nIELTS learners and tutors use this skill to convert reading passage results, screenshots, and answer lists into structured review data with scores, wrong-question analysis, vocabulary, synonyms, and progress tracking.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Prompt-triggered auto-update behavior can change skill code before review.\n\nMitigation: Disable or remove the auto-update hook and review the installed version before using the skill.\n\nRisk: The skill can upload review data and use long-lived account tokens.\n\nMitigation: Use a dedicated short-lived token stored outside shell startup files and require explicit confirmation before any upload.\n\nRisk: Folder scanning can touch broad personal directories during legacy review import.\n\nMitigation: Limit scans to an explicit user-selected directory and confirm the scan plan before processing files.\n\nRisk: Author mode includes SSH deployment and service restart commands.\n\nMitigation: Avoid author mode on machines with production SSH access unless the operator intentionally needs deployment capability.\n\nRisk: The README contains older offline-first claims while the current release is web-connected.\n\nMitigation: Treat the current release as network-connected and review upload/API behavior before installation.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/dengjiawei1226/skills/ielts-reading-review)\n- [Client Mode Onboarding](artifact/references/CLIENT_MODE_ONBOARDING.md)\n- [Review Style Guide](artifact/references/review-style-guide.md)\n- [Error Taxonomy](artifact/references/error-taxonomy.md)\n- [Score-to-Band Conversion Table](artifact/references/score-band-table.md)\n- [538 IELTS Keywords Reference Guide](artifact/references/538-keywords-guide.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, JSON, Files, Shell commands, Configuration guidance]\n\n**Output Format:** [Markdown guidance with structured JSON review data and shell commands when setup, upload, or validation actions are needed.]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May create local review files and use configured web upload endpoints for progress tracking.]\n\n## Skill Version(s):\n\n5.5.2 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v5.5.2:hooks/hooks.json\n\n{\n  \"description\": \"IELTS Reading Review Skill hooks — 复盘触发词自动检测版本更新\",\n  \"hooks\": {\n    \"UserPromptSubmit\": [\n      {\n        \"name\": \"ielts-skill-version-check\",\n        \"matcher\": \"复盘|雅思阅读|阅读错题|IELTS|ielts-reading-review|帮我复盘|错题分析|阅读分析|剑[0-9]|剑桥[0-9]\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"bash \\\"${CODEBUDDY_SKILL_ROOT:-$HOME/.workbuddy/skills/ielts-reading-review}/hooks/auto-update.sh\\\"\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ]\n  }\n}\n\nFile v5.5.2:stats-worker/wrangler.toml\n\nname = \"ielts-skill-stats\"\nmain = \"worker.js\"\ncompatibility_date = \"2026-03-30\"\n\n# KV Namespace 绑定（部署前需先创建）\n# 运行: wrangler kv namespace create STATS\n# 然后把返回的 id 填到下面\n[[kv_namespaces]]\nbinding = \"STATS\"\nid = \"TO_BE_FILLED_AFTER_CREATION\"\n\nArchive v5.5.1: 20 files, 63137 bytes\n\nFiles: _meta.json (139b), assets/bilingual-template.html (3858b), assets/review-template.html (18589b), hooks/auto-update.sh (1507b), hooks/hooks.json (589b), README.md (10404b), references/538-keywords-guide.md (2186b), references/CLIENT_MODE_ONBOARDING.md (3804b), references/error-taxonomy.md (12187b), references/review-style-guide.md (8450b), references/score-band-table.md (2357b), scripts/check-update.js (5674b), scripts/generate-pdf.js (2416b), scripts/scan-legacy-reviews.js (10347b), scripts/setup-client-mode.sh (8421b), skill-card.md (2900b), SKILL.md (43409b), stats-worker/deploy.sh (2013b), stats-worker/worker.js (5286b), stats-worker/wrangler.toml (283b)\n\nFile v5.5.1:SKILL.md\n\n---\nname: ielts-reading-review\ndescription: \"IELTS Reading passage review, scoring, and progress tracking skill. Generates structured review data (JSON) and deploys to tuyaya.online via saveReview API. The server's review.html template renders JSON into unified pages. No standalone HTML generation needed. Supports batch import of legacy reviews with auto-discovery of review folders. Trigger phrases: 雅思复盘, 帮我复盘阅读, IELTS reading review, 分析错题, 阅读错题分析, 成绩单, 打分, 统计, 进步趋势, 批量导入历史复盘, 历史笔记转 JSON, 把文件夹里的复盘都生成 JSON, 扫一下我电脑里的复盘, 帮我找出所有历史笔记, 自动发现复盘, score, band, progress, batch import, auto scan.\"\n---\n\n# IELTS Reading Review Skill\n\n## Purpose\n\n帮用户把雅思阅读做题结果变成结构化数据（JSON），通过 saveReview API 入库后由后端 review.html 模板统一渲染页面。\n\n## 🔴🔴🔴 最高铁律 (v5.5.1 — Cannot Be Skipped)\n\n**只要主人在对话里发了雅思阅读题（截图 / 文字答案 / 错题列表 / 任何阅读相关材料），就必须一气呵成跑完以下闭环，不允许中途停在文字分析阶段：**\n\n```\n读截图 → 错题确认 → 写错题分析 → ★生成 v4.0 JSON★ → ★saveReview/upload 入库★ → ★getReviews 回查 ✅★ → 汇报线上链接\n```\n\n**判定\"复盘完成\"的唯一标准 = `getReviews` 回查显示该篇已入库（不是\"我写完文字分析了\"）。**\n\n**绝对禁止的\"假完成\"模式（历史血泪）：**\n- ❌ 写完错题分析就交卷，不生成 JSON → 主人在 tuyaya.online 看不到记录\n- ❌ 生成 JSON 但忘了 saveReview / upload.js → 文件部署 ≠ 数据入库\n- ❌ 调了 saveReview 但没 getReviews 回查 → API 静默失败也不知道\n- ❌ 等主人催\"怎么没上传\"才补救 → 这就是失败\n\n**本铁律覆盖所有其他流程**。即使主人只说\"帮我看看这题对不对\"\"分析这道错题\"\"这套该几分\"，**只要内容是雅思阅读，就走完整闭环**。\n\n> 历史教训（2026-05-22）：剑8 T3P1+T3P2 复盘只在聊天里写了文字分析没入库，主人在 dashboard 看不到，22:49 提醒后才补救。**这种事再也不能发生**。\n\n## Architecture (v5.5.1 — Locked-in Closed Loop)\n\n**⚠️ v5.5.1 变更**（2026-06-01）：选择题和判断题错题新增 `rejectedOptions[]` 字段，在 review.html 中以红色边框卡片渲染\"为什么不选\"区域，逐个排除错误选项。\n\n**⚠️ v5.4.2 最重大变更**（2026-05-22）：将\"必须入库\"提升为最高铁律。SKILL.md 顶部新增「最高铁律」段，加入 Step 8 Final Gate 强制 checklist——任何复盘任务，未通过 `getReviews` 回查 ✅ 不允许结束，不允许只交付文字分析。\n\n**⚠️ v5.1 新增三道防线**（防 saveReview 漏调 / 本地副本陈旧）：\n1. **发布脚本自动同步本地副本**：publish-clawhub.sh 跑完后自动 `clawhub install --force` 到 `~/.workbuddy/skills/`\n2. **Step 7g 强制入库回归验证**：调 saveReview 后必须再用 getReviews 回查确认入库，**部署 ≠ 入库**\n3. **Step 0 强制展示版本横幅**：每次激活时输出本地+远程版本号，落后必告警\n\n**⚠️ v5.0 重大简化**：服务端已预置 C4-C20 全量 answer-key（204条 reading）+ bilingual_data（100条核心双语），**复盘流程不再需要更新这两个文件**，部署清单大幅缩减。\n\n**⚠️ 不再生成复盘 HTML！** 后端 `review.html` 模板页统一渲染 JSON，单独生成的 HTML 完全无用。\n\n产出物：\n1. **结构化 JSON（v4.0）** — 成绩、错题、词汇、同义替换的全量数据。通过 saveReview API 入库后，`review.html?file=xxx.json` 在线渲染\n\n> **v5.1 变更（2026-05-11 晚）**：三道防线避免再犯 saveReview 漏调 + 本地副本不更新的坑。\n\n> **v5.0 变更（2026-05-11）**：服务端预置 C4-C20 全量 answer-key + bilingual_data，复盘流程不再需要本地维护这两个文件。仅当复盘 C20 之后的新书才需要扩展。部署清单从 5 个文件缩减到 4 个（仅 JSON + 词汇相关）。\n\n> **v4.0 变更**：不再生成复盘 HTML。后端 review.html 模板页统一渲染 JSON，单独生成 HTML 无用。复盘只需 JSON + saveReview API 入库。\n\n> **v3.9.1 新增**：Step 0 自动版本检查（scripts/check-update.js），每次激活时比对本地与 ClawHub 版本。\n\n> **v3.9.0 新增**：词库覆盖校验（dict_full.json 缺词 = 词卡展开不工作）、saveReview API 入库步骤、answers[] 字段名规范、线上词卡验证步骤。\n\n## When to Activate\n\n- 用户发做题截图/答案，提到\"复盘\"\"错题分析\"\"阅读复盘\"\n- 用户问成绩、分数、进步趋势\n- 用户要生成复盘笔记或 PDF\n\n## Step 0a: 运行模式检测 (Auto — Run on Every Activation)\n\n**第一件事**：判断当前是「作者模式」还是「客户端模式」。两种模式行为完全不同，绝不能搞错。\n\n```bash\n# 模式判定逻辑（执行下列检测）：\ntest -f ~/.ssh/workbuddy.pem && grep -q \"openclaw-tunnel\" ~/.ssh/config 2>/dev/null && echo \"作者机\" || echo \"客户端机\"\n```\n\n| 信号 | 模式 | 行为 |\n|---|---|---|\n| 检测到 `~/.ssh/workbuddy.pem` + `openclaw-tunnel` SSH 别名 | **作者模式** | Step 7 走完整 SSH 部署链路（gzip 流、cat 管道、systemctl restart） |\n| 找不到上述凭据，但有 `IELTS_USER_TOKEN` 环境变量 | **客户端模式** | Step 7 跳过所有 SSH 操作，只走 HTTPS batchImport 入库 |\n| 都没有 | **未配置客户端模式** | 提示用户先配 `IELTS_USER_TOKEN`（详见客户端 onboarding 章节），然后切到客户端模式 |\n\n**模式横幅必须输出**（每次激活时）：\n\n```\n🎯 IELTS Reading Review · vX.Y.Z\n🔐 运行模式：作者模式 / 客户端模式\n👤 token 主体：dengjiawei / lishuzhuo / (匿名)\n```\n\n**作者模式与客户端模式的关键差异**（必读）：\n\n| 步骤 | 作者模式 | 客户端模式 |\n|---|---|---|\n| Step 7a 词库覆盖校验 | ✅ 必跑（要部署 dict_full.json） | ⏭️ 跳过（词库由作者维护，客户端无写权限） |\n| Step 7b 部署 site/reviews/ JSON | ✅ SCP 到服务器 | ⏭️ 跳过（batchImport 已写入数据库） |\n| Step 7b 部署 dict_full.json + synonym_data.json | ✅ gzip 流推送 | ⏭️ 跳过 |\n| Step 7c saveReview API | ✅ ssh + localhost:3100 | ⏭️ 改用 batchImport（HTTPS + token） |\n| Step 7d 后端代码部署 | ✅ 必要时执行 | 🚫 严禁触碰 |\n| Step 7e 后端重启 | ✅ systemctl restart | 🚫 严禁触碰 |\n| Step 7g 入库回查 | ✅ getReviews 校验 | ✅ getReviews 校验（HTTPS） |\n| 本地保存 JSON | ✅ `site/reviews/` | ✅ 用户自选目录（如 `~/Documents/雅思复盘/`） |\n\n> **客户端模式下绝对禁止**：执行 `ssh openclaw-tunnel`、`scp`、`gzip -c | ssh`、`systemctl restart`、修改 `/var/www/ielts/` 任何文件。\n\n## Step 0b: Version Check (Auto — Run on Every Activation)\n\n**每次 Skill 被激活时，第一件事必须显式输出当前版本横幅**：\n\n```bash\nnode ~/.workbuddy/skills/ielts-reading-review/scripts/check-update.js\n```\n\n**强制行为规范**：\n1. **必须把 check-update.js 的输出原样展示给用户**（包含本地版本号 + 远程版本号），不能省略\n2. 如果输出包含 `🆕 有新版本可用` → **立即提示用户并询问是否更新**：\n   ```\n   ⚠️ ielts-reading-review 有新版本 vX.Y.Z（当前 vA.B.C），强烈建议先更新再开始复盘。\n   现在更新？\n   ```\n3. 用户同意后执行 `node ~/.workbuddy/skills/ielts-reading-review/scripts/check-update.js --auto`，等待安装完成后**让用户重新激活 Skill**（已加载的 context 不会热更）\n4. 用户拒绝更新 → 在回复开头加红字告警：`⚠️ 正在使用旧版本 vA.B.C，可能错过 v5.0+ 的简化流程`\n\n> 如果 `check-update.js` 不存在（旧版本安装），跳过版本检查继续工作。\n> **绝对禁止**：不输出版本号、隐瞒版本差距、用户没同意就开始复盘流程。\n\n## Workflow\n\n### Step 1: Collect Input\n\n确保以下信息齐全（缺什么问什么）：\n\n- **来源**：哪本书、哪套题、哪篇（如剑5 Test1 Passage2）\n- **原文**或答题上下文\n- **正确答案**\n- **用户答案**及错题\n- **🔴 用时（MUST ASK）**：做题用时（格式 `MM:SS`，如 `28:01`）。**必问项**，不能标\"可选\"——Web 端进步趋势图依赖此字段。用户若没计时，明确询问\"这套大概做了多久\"让其估算，别直接跳过\n- **可选**：翻译、自我反思\n\n### Step 1b: Screenshot Wrong Answer Protocol (CRITICAL)\n\n**用户发答题截图时必须执行 3 步**：\n\n1. **逐题读截图标记**：识别每题的对/错状态（参考下方多平台标记规则），不能跳题，不能用自己的判断代替截图标记\n2. **先报错题清单等确认**：输出\"根据截图，错题为 QX/QY/QZ（共N道），请确认\"，**确认后才能写分析**\n3. **截图标记是唯一真相**：截图 vs 自己判断冲突时，信截图\n\n**禁止**：跳过确认直接写分析、用 answer comparison 覆盖截图标记。\n\n#### 多平台截图标记识别规则\n\n不同 App/平台的答案标记方式各不相同，AI 必须能识别以下所有变体：\n\n| 平台/场景 | 正确标记 | 错误标记 | 额外特征 |\n|-----------|---------|---------|---------|\n| 官方答题卡手批 | 绿色/✓ | 红色/✗ | 手写批注 |\n| **雅思哥 (IELTSBro)** | 绿色圆圈/✓/对号 | 红色圆圈/✗/叉号 | 界面有\"答案解析\"按钮；题号左侧有状态图标；底部显示得分统计（如 8/13）；可能同时显示\"你的答案\"和\"正确答案\"两列 |\n| 雅思哥成绩单复制文本 | 格式可能为：`1. D ✓` 或 `Q1: D (正确)` | `2. A ✗ → 正确: C` 或 `Q2: A (错误，正确答案: C)` | 复制文本可能包含：题号、用户答案、对错标记、正确答案 |\n| 小站雅思 | 蓝色/✓ | 橙色/✗ | 卡片式布局 |\n| 新东方雅思 | 绿色背景 | 红色背景 | 答案对比表格 |\n| 剑桥官方 CBT | 显示最终得分 | — | 不逐题标记 |\n| 其他 App（通用） | ✓/✔/☑/✅/绿色/蓝色 | ✗/✘/☒/❌/红色/橙色 | — |\n\n**识别策略（按优先级）**：\n\n1. **先找得分统计**：截图中如果有 \"8/13\"、\"得分：8\"、\"Score: 8/13\" 等信息，先记下总分\n2. **再找逐题标记**：逐题看状态图标/颜色/符号，判断每题对错\n3. **提取用户答案**：如果截图同时显示了用户答案和正确答案，直接记录两列数据\n4. **处理模糊情况**：如果某题标记看不清楚，输出 \"Q7 标记不确定（看起来像 ✓），请确认\"\n5. **利用 answer-key 交叉验证**：识别出来源（如 剑5 Test1）后，从 `site/answer-key.json` 读取正确答案，可辅助验证截图识别结果是否合理（但截图仍是第一真相）\n\n**🔴 当截图来自第三方 App 时的特殊处理**：\n\n- **不要假设标记规则**——不同 App 版本可能改 UI，先观察截图整体布局再判断哪个是\"对\"哪个是\"错\"\n- **看图例/得分摘要**——很多 App 顶部或底部有总分（如 8/13），用它来验证你逐题识别的正确率是否对得上\n- **如果实在识别不了**——直接告诉用户：\"这张截图的标记方式我不太确定，能告诉我哪些题错了吗？或者告诉我你用的是什么 App？\"\n\n#### 雅思哥复制文本解析规则\n\n用户可能直接从雅思哥 App 复制答案记录粘贴过来，常见格式：\n\n```\n# 格式 A：逐题结果（最常见）\n1. TRUE ✓\n2. FALSE ✗ (正确答案: NOT GIVEN)\n3. NOT GIVEN ✓\n4. B ✗ (正确答案: D)\n...\n\n# 格式 B：成绩概要\nCambridge 5 Test 1 Reading Passage 1\n得分：10/13\n错题：Q2, Q7, Q11\n\n# 格式 C：答案对照表\n题号 | 我的答案 | 正确答案 | 结果\n1    | TRUE     | TRUE     | ✓\n2    | FALSE    | NG       | ✗\n...\n```\n\n**解析要点**：\n1. 先识别来源（哪套题哪篇）——从标题/文件名/用户说明中提取\n2. 从文本中提取每题的：用户答案 + 对错状态 + 正确答案（如果有）\n3. 如果复制文本没有正确答案，从 `site/answer-key.json` 补充\n4. 格式不在上述三种之内 → 尽力解析，解析不了就问用户\n\n### Step 2: Generate Review Data JSON (v4.0)\n\n**⚠️ 不再生成复盘 HTML！** 后端 `review.html` 模板页统一渲染 JSON，单独生成 HTML 无用。\n\n直接生成结构化 JSON 文件，供 saveReview API 入库 + 后端 review.html 模板渲染。\n\n**输出文件命名规则**：`剑X-TestX-PassageX-中文主题复盘.json`\n\n示例：\n- JSON: `剑5-Test1-Passage2-鲸鱼感官复盘.json`\n- `source.titleCN`: `\"鲸鱼感官\"`\n\n> **命名说明**：文件名使用中文标题（`source.titleCN`），方便用户在文件管理器中一眼识别内容。Web 端导入时通过 JSON 内的 `source.book/test/passage` 识别篇目，不依赖文件名。\n\n**🔴 timing 字段必须填充**：\n- `minutes`：数值型分钟（支持小数，如 `28.0` / `35.4`）\n- `formatted`：`\"MM:SS\"` 字符串（如 `\"28:01\"`）\n- MM:SS → minutes 换算：`分钟 + 秒/60`，保留 1 位小数\n- 用户实在给不出用时，才能置 `null`，但必须在回复里提醒\"缺用时，进步图将缺一个点\"\n\n```json\n{\n  \"version\": \"4.0.0\",\n  \"generatedAt\": \"2026-04-28T10:00:00.000Z\",\n  \"source\": {\n    \"book\": 7,\n    \"test\": 1,\n    \"passage\": 3,\n    \"title\": \"English Title\",\n    \"titleCN\": \"中文标题\"\n  },\n  \"score\": {\n    \"correct\": 9,\n    \"total\": 14,\n    \"band\": \"6.0\",\n    \"breakdown\": {\n      \"fillBlank\": { \"correct\": 4, \"total\": 6 },\n      \"tfng\": { \"correct\": 3, \"total\": 4 },\n      \"matching\": { \"correct\": 2, \"total\": 4 }\n    }\n  },\n  \"timing\": {\n    \"minutes\": 25,\n    \"formatted\": \"25:00\"\n  },\n  \"date\": \"2026-04-28\",\n  \"progressNote\": \"简短进步总评（如'比上次提升2分'）\",\n  \"alertNote\": \"核心告警信息（如'Summary填空全军覆没'，可选）\",\n  \"answers\": [\n    { \"q\": 1, \"my\": \"TRUE\", \"correct\": \"TRUE\", \"result\": \"correct\" },\n    { \"q\": 2, \"my\": \"FALSE\", \"correct\": \"NOT GIVEN\", \"result\": \"wrong\" }\n  ],\n  \"wrongQuestions\": [\n    {\n      \"q\": 3,\n      \"type\": \"tfng\",\n      \"badge\": \"TFNG\",\n      \"myAnswer\": \"TRUE\",\n      \"correctAnswer\": \"NOT GIVEN\",\n      \"errorCategory\": \"ng-false-confusion\",\n      \"analysis\": \"错因分析文字\",\n      \"lesson\": \"教训一句话\",\n      \"quote\": \"原文引用（英文）\",\n      \"quoteRef\": \"Para B, Line 3\",\n      \"analysisPoints\": [\"分析要点1\", \"分析要点2\"],\n      \"rejectedOptions\": [\n        { \"option\": \"A\", \"reason\": \"原文未提及该关系，属于无中生有\" },\n        { \"option\": \"C\", \"reason\": \"与原文事实矛盾，原文说的是...\" },\n        { \"option\": \"D\", \"reason\": \"范围扩大/信息不匹配\" }\n      ]\n    }\n  ],\n  \"actionItems\": [\n    \"下次做 TFNG 前必须标注否定词\",\n    \"Summary 填空必须三步走\"\n  ],\n  \"synonyms\": [\n    {\n      \"original\": \"原文表达\",\n      \"replacement\": \"题目表达\",\n      \"meaning\": \"中文释义\",\n      \"questionRef\": \"Q3\"\n    }\n  ],\n  \"vocabulary\": [\n    {\n      \"word\": \"exemplify\",\n      \"phonetic\": \"/ɪɡˈzemplɪfaɪ/\",\n      \"pos\": \"v.\",\n      \"definition\": \"举例说明\",\n      \"ieltsFreq\": 3,\n      \"source\": \"538 #42\",\n      \"appearance\": \"剑7T1P3\"\n    }\n  ],\n  \"problems\": [\n    {\n      \"type\": \"同义替换识别失败\",\n      \"detail\": \"具体表现\",\n      \"questions\": \"Q3, Q7\",\n      \"improvement\": \"改进方法\"\n    }\n  ]\n}\n```\n\n**v4.0 相对 v3.0 新增字段**（均可选，v3.0 JSON 仍能被模板页渲染）：\n- `progressNote`：进步总评\n- `alertNote`：告警信息\n- `answers[]`：全部答案对照表（含 result: correct/wrong/skipped）\n- `actionItems[]`：行动清单\n- `wrongQuestions[].badge`：**错误分类**简写标签（如 \"NG/FALSE混淆\"、\"过度推理选TRUE\"、\"Summary填空定位错误\"），与 `type`（题型）区分开\n- `wrongQuestions[].quote` / `quoteRef`：原文引用 + 定位\n- `wrongQuestions[].analysisPoints[]`：分析要点列表\n- `wrongQuestions[].rejectedOptions[]`：**选择题和判断题专用**——为什么不选其他选项。仅 `type === \"multipleChoice\"` 或 `type === \"tfng\"` 时填写。数组每项 `{ option: \"A\", reason: \"原因...\" }`（选择题用 A/B/C/D，判断题用 Y/N/NG），列出除正确答案外所有错误选项的排除理由。review.html 会以红色边框卡片渲染（标题\"为什么不选\"，每个选项带圆圈字母+排除原因）\n\n**🔴 wrongQuestions 中 type 与 badge 的区别（MUST FOLLOW）**：\n- `type`：**题型**标识，使用标准 ID（`tfng` / `fillBlank` / `summary` / `multipleChoice` / `matching` / `heading` / `sentenceCompletion`）\n- `badge`：**错误分类**标签（如 \"NG/FALSE混淆\"、\"过度推理\"、\"Summary填空没回原文\"）\n- 两者含义不同，**禁止互相赋值**。旧格式 JSON 中 `error_analysis` 只有 `error_type`（错误分类），没有题型信息，review.html 会从 `questions[]` 交叉获取题型\n\n**🔴 answers[] 字段名规范（MUST FOLLOW）**：\n\n`answers` 数组中每条记录的字段名**必须**严格使用以下格式：\n```json\n{ \"q\": 1, \"my\": \"TRUE\", \"correct\": \"TRUE\", \"result\": \"correct\" }\n```\n- `my`：用户答案（不是 `myAnswer`）\n- `correct`：正确答案字符串（不是布尔值）\n- `result`：`\"correct\"` / `\"wrong\"` / `\"skipped\"`（字符串，不是布尔值）\n\n> **注意**：`wrongQuestions[]` 里用的是 `myAnswer` / `correctAnswer`（全拼），和 `answers[]` 的缩写不同。这是历史设计，review.html 模板已做兼容处理，两种格式都能正确渲染。\n\n### Step 3b: Bilingual Data (v5.0 — 已预置，无需操作)\n\n> **⚠️ v5.0 变更（2026-05-11）**：服务端已预置 C4-C20 100 篇核心双语数据，复盘流程**不再需要**生成或维护 bilingual_data.json。\n>\n> 仅以下场景需要扩展：\n> - 复盘 C20 之后的新书（C21+）\n> - 用户明确要求为某篇生成精翻双语\n>\n> 默认跳过此步骤。\n\n#### ~~3b-2: 双语 HTML 文件~~（已废弃）\n\n> **v3.8 起不再需要**。旧 `bilingual/*.html` 已清理，Web 端通过 `bilingual.html` 模板页动态加载 `bilingual_data.json` 渲染。\n\n### Step 4: Generate PDF (Optional — Rarely Used)\n\n如果用户明确需要 PDF，可从线上复盘页面打印。本地不再生成 HTML，因此也不支持 puppeteer PDF 生成。\n\n### Step 5: Update Memory\n\n复盘完成后更新 working memory：新增的错误模式、词汇、成绩数据。\n\n### Step 6: Apply to Web (Automatic — saveReview API)\n\n复盘 JSON 生成后，**必须立即通过 saveReview API 入库**（Step 7c），不需要用户手动操作。\n\n完成后输出：\n\n---\n\n📤 **复盘完成！**\n\nJSON 已入库，线上查看 👉 [review.html?file=剑X-TestX-PassageX-主题复盘.json](https://tuyaya.online/ielts/review.html?file=剑X-TestX-PassageX-主题复盘.json)\n\n---\n\n#### 其他同步方式（备选）\n\n**方式 B：Skill 伴侣脚本**（私有部署场景）\n\n如果有 `ielts-server-sync` skill（个人专用），可命令行批量上传：\n\n```bash\n# 单文件上传\nnode ~/.workbuddy/skills/ielts-server-sync/scripts/upload.js 剑5-T1-P2.json\n\n# 批量上传目录\nnode ~/.workbuddy/skills/ielts-server-sync/scripts/upload.js --batch ./reviews/\n```\n\n**方式 C：手动上传**\n\n打开 [submit.html?mode=json](https://tuyaya.online/ielts/submit.html?mode=json) 拖入 JSON 文件。\n\n### Step 7: Deploy Checklist (MANDATORY — DO NOT SKIP)\n\n**🔴 每次复盘完成后，必须逐项执行以下检查清单。不能靠记忆，必须逐条过。**\n\n**🔀 先看 Step 0a 模式横幅，按模式走对应分支**：\n- **作者模式** → 走下面的 7a-7g 完整部署链路\n- **客户端模式** → 跳到本节末尾的「Step 7-Client」客户端简化流程，**不要碰 7a-7g 的 SSH 操作**\n\n---\n\n#### 7a. 本地文件归位（仅作者模式）\n\n- [ ] 复盘 JSON 已复制到 `site/reviews/`\n- [ ] `generate_vocab_synonym.py` 已运行，更新 dict_full.json + synonym_data.json\n- [ ] **🔴 词库覆盖校验（MUST — 否则词卡展开不工作）**：运行以下检查，确保本篇所有 vocabulary 词汇都在 `dict_full.json` 中有完整条目（含 meaning_cn + examples）\n\n> **v5.0 变更**：~~answer-key.json 更新~~ 和 ~~bilingual_data.json 更新~~ 已从清单中移除。服务端已预置 C4-C20 全量数据，复盘流程无需再维护这两个文件。复盘 C21+ 时才需要扩展 answer-key（参考末尾「扩展新书」章节）。\n\n```python\n# 词库覆盖校验（复盘生成后必跑）\nimport json\nwith open('site/dict_full.json') as f:\n    dmap = {w['word'].lower(): w for w in json.load(f) if 'word' in w}\nwith open('site/reviews/剑X-TestX-PassageX-主题复盘.json') as f:\n    vocab = json.load(f).get('vocabulary', [])\nmissing = [v['word'] for v in vocab if v['word'].lower() not in dmap]\nif missing:\n    print(f'❌ dict_full.json 缺失 {len(missing)} 词：{missing}')\n    print('→ 必须补充这些词（含 meaning_cn/examples/synonyms）后再部署')\nelse:\n    print('✅ 词库覆盖完整')\n```\n\n如果有缺失词：**立即补充到 dict_full.json**（每词需含 meaning_cn、phonetic、root、examples、synonyms、antonyms），补完重新部署。\n**绝不能跳过此步**——缺词 = 线上词卡点击无响应 = 用户体验崩坏。\n\n#### 7b. 部署到线上\n\n**v5.0 精简后只需部署以下 3 个文件**（answer-key/bilingual 已服务端预置）：\n\n```\nsite/reviews/剑X-TestX-PassageX-主题复盘.json    → /var/www/ielts/reviews/\nsite/dict_full.json                              → /var/www/ielts/\nsite/synonym_data.json                           → /var/www/ielts/\n```\n\n**🔴 大文件传输规则（>1MB 用 gzip 流，不要分块！）**：\n\n大于 1MB 的文件（如 dict_full.json ~6MB）**禁止直接 SCP，禁止 split 分块**，必须用 gzip 管道一行秒传：\n\n```bash\n# 🔴 唯一正确方式：gzip 流（一行搞定，不分块）\ngzip -c site/dict_full.json | ssh openclaw-tunnel \"gunzip > /var/www/ielts/dict_full.json\"\n\n# 验证完整性\nssh openclaw-tunnel \"python3 -c \\\"import json; d=json.load(open('/var/www/ielts/dict_full.json')); print(f'OK: {len(d)} words')\\\"\"\n```\n\n> **⚠️ 历史教训**：split 分块传输复杂且易出错（分批 SCP 超时、拼合顺序错乱），已于 2026-05-08 彻底弃用。gzip 流利用 SSH 隧道的持久连接，一次性完成压缩传输，稳定可靠。\n\n**小文件（<1MB）仍可直接 SCP**：\n```bash\nscp -o ConnectTimeout=15 \\\n    -o StrictHostKeyChecking=accept-new \\\n    -o UserKnownHostsFile=~/.ssh/known_hosts_cfd \\\n    -o \"ProxyCommand=/Users/dengjiawei/bin/cloudflared access tcp --hostname ssh.tuyaya.online\" \\\n    -i ~/.ssh/workbuddy.pem \\\n    <本地文件> ubuntu@ssh.tuyaya.online:/var/www/ielts/\n```\n\n**或用 SSH stdin 管道（<500KB 的文件最快）**：\n```bash\nssh openclaw-tunnel \"cat > /var/www/ielts/synonym_data.json\" < site/synonym_data.json\n```\n\n#### 7c. saveReview API 入库（MANDATORY）\n\n复盘数据必须写入后端数据库，否则首页进度图看不到这篇：\n\n```bash\nssh openclaw-tunnel 'python3 -c \"\nimport json, urllib.request\npayload = json.dumps({\n    \\\"action\\\": \\\"saveReview\\\",\n    \\\"token\\\": \\\"<USER_TOKEN>\\\",\n    \\\"book\\\": X, \\\"test\\\": Y, \\\"passage\\\": Z,\n    \\\"score\\\": <correct>, \\\"total\\\": <total>, \\\"duration\\\": <minutes>,\n    \\\"date\\\": \\\"YYYY-MM-DD\\\",\n    \\\"answers\\\": {}\n})\nreq = urllib.request.Request(\\\"http://localhost:3100/api/ielts\\\", data=payload.encode(), headers={\\\"Content-Type\\\": \\\"application/json\\\"})\nresp = urllib.request.urlopen(req)\nprint(resp.read().decode())\n\"'\n```\n\n> API 路径是 `POST /api/ielts`，通过 `action` 字段分发（不是 `/api/ielts/saveReview`）。\n\n#### 7d. 后端代码部署（仅当 server/index.js 有改动时）\n\n如果本次涉及 server 代码变更，需同步后端：\n\n```bash\n# 后端小文件可直接 stdin 传\nssh openclaw-tunnel \"cat > /home/ubuntu/ielts-api/index.js\" < server/index.js\n\n# 新增的 lib/ 目录\nssh openclaw-tunnel \"mkdir -p /home/ubuntu/ielts-api/lib\"\nssh openclaw-tunnel \"cat > /home/ubuntu/ielts-api/lib/llmExtractor.js\" < server/lib/llmExtractor.js\nssh openclaw-tunnel \"cat > /home/ubuntu/ielts-api/lib/schemaUpgrader.js\" < server/lib/schemaUpgrader.js\nssh openclaw-tunnel \"cat > /home/ubuntu/ielts-api/lib/tencentOcr.js\" < server/lib/tencentOcr.js\n\n# 如有新 npm 依赖\nssh openclaw-tunnel \"cd /home/ubuntu/ielts-api && npm install\"\n```\n\n**🔴 部署红线**：\n- **严禁覆盖 `/etc/systemd/system/ielts-api.service`**——里面有 AI_API_URL/KEY/MODEL 等生产密钥\n- 新密钥只通过 drop-in 追加：`/etc/systemd/system/ielts-api.service.d/secrets.conf`\n- 详见 `.workbuddy/upload-upgrade-ops.md`\n\n#### 7e. 后端重启\n\n```bash\nssh openclaw-tunnel \"sudo systemctl restart ielts-api\"\n```\n\n**必须重启**——后端启动时 `buildReviewFileIndex()` 扫描 `reviews/` 目录建索引。不重启 = 新文件不出现在首页。\n\n#### 7f. 线上验证\n\n- [ ] `getReadingPageData` API 返回新篇目数据（`POST /api/ielts` + `action: getReadingPageData`）\n- [ ] 复盘链接可正常访问：`review.html?file=剑X-TestX-PassageX-主题复盘.json`\n- [ ] **🔴 词卡展开验证**：打开复盘页面，点击词汇表中至少 1 个词，确认能弹出详情卡（含释义/例句/近义词）。如果点击无反应 → dict_full.json 缺词，回 7a 补词\n- [ ] （v5.0 已预置）双语数据 C4-C20 已服务端预置，无需逐篇验证；C21+ 新书需手动确认 `bilingual.html?book=X&test=Y&passage=Z`\n\n#### 7g. 🔴 强制入库回归验证（v5.1 新增 — 防止 saveReview 漏调）\n\n**血泪教训（2026-05-11）**：复盘 JSON 部署成功了，但 saveReview API 没调通，导致首页看不到新篇。**部署 ≠ 入库**，必须**回查数据库**验证。\n\n完成 7c 后必须立即执行以下检查：\n\n```bash\n# 用 getReviews 回查本篇是否真的入库（替换 BOOK/TEST/PASSAGE）\ncurl -s https://tuyaya.online/api/ielts -H 'Content-Type: application/json' \\\n  -d '{\"action\":\"getReviews\",\"token\":\"<USER_TOKEN>\",\"book\":<BOOK>,\"test\":<TEST>}' \\\n  | python3 -c \"\nimport json,sys\nd = json.load(sys.stdin)\nrecords = [r for r in d.get('data',[]) if r['book']==<BOOK> and r['test']==<TEST> and r['passage']==<PASSAGE>]\nif records:\n    print('✅ 入库成功:', records[0])\nelse:\n    print('❌ 入库失败！必须重新调 saveReview API')\n    sys.exit(1)\n\"\n```\n\n**如果验证失败**：立即重新调 saveReview API，再回查，直到 ✅。**绝对不能跳过此步**——本步骤 PASS 才算复盘真正完成。\n\n**曾犯的典型遗漏**（引以为戒）：\n1. 文件生成在根目录没 cp 到 site/reviews/\n2. 没重启后端导致 review 索引没刷新\n3. JSON 文件没 SCP 到 reviews/\n4. **dict_full.json 缺词导致词卡展开不工作**——复盘新增词汇不在词库中，必须做词库覆盖校验\n5. **没调 saveReview API 导致首页进度图缺数据**——文件部署 ≠ 数据入库，两者都要做\n6. **answers[] 用了错误字段名**——必须用 `my`/`correct`(字符串)/`result`(字符串)，不能用布尔值\n7. **不要生成复盘 HTML**——后端 review.html 模板统一渲染 JSON，单独生成 HTML 无用\n8. **dict_full.json 大文件传输用 gzip 流**——禁止 split 分块（复杂且易错），一行 `gzip -c | ssh gunzip >` 搞定\n9. **旧格式 JSON 错题重复渲染**——`questions[]` 和 `error_analysis[]` 都有错题时，review.html 会去重。但生成 v4.0 JSON 时应**只用 wrongQuestions[]**，不要同时写两种格式\n10. **type/badge 混用导致标签重复**——`type` 是题型（tfng/fillBlank），`badge` 是错误分类（NG/FALSE混淆）。禁止互相赋值\n\n---\n\n## Step 7-Client: 客户端模式部署流程（NO SSH）\n\n**何时走这条**：Step 0a 检测到「客户端模式」（如老婆机器、外部用户机器）。\n\n**核心原则**：客户端没 SSH 凭据、没 `/var/www/ielts/` 写权限，**只能通过 HTTPS 接口写数据库**。词库、模板、双语数据全部由作者机维护，客户端不参与。\n\n### 7-Client-a. 本地保存 JSON\n\n让用户选个保存目录（推荐 `~/Documents/雅思复盘/` 或当前工作目录的 `reviews/`），把生成的 JSON 写进去。**不要往 `site/reviews/` 写**——客户端没这个目录或者目录是别人的。\n\n### 7-Client-b. 通过 batchImport 入库（替代 saveReview）\n\nbatchImport 是带 token 的官方 HTTPS 通道，能吃 v4.0 富 JSON（服务端 schemaUpgrader 自动转换扁平字段写入），最适合客户端：\n\n```bash\n# 单篇上传（推荐用 review-upload skill 的脚本）\nbash ~/.workbuddy/skills/ielts-review-upload/scripts/sync-review.sh \\\n  ~/Documents/雅思复盘/剑X-TestX-PassageX-主题复盘.json\n```\n\n或者直接 curl：\n\n```bash\nTOKEN=\"$IELTS_USER_TOKEN\"  # 从环境变量读\nJSON_FILE=\"~/Documents/雅思复盘/剑X-TestX-PassageX-主题复盘.json\"\n\nPAYLOAD=$(python3 -c \"\nimport json, sys\nwith open(sys.argv[1]) as f:\n    review = json.load(f)\nprint(json.dumps({\n    'action': 'batchImport',\n    'token': sys.argv[2],\n    'reviews': [review]\n}, ensure_ascii=False))\n\" \"$JSON_FILE\" \"$TOKEN\")\n\ncurl -s -X POST https://tuyaya.online/api/ielts \\\n  -H 'Content-Type: application/json' \\\n  -d \"$PAYLOAD\"\n```\n\n预期返回：\n```json\n{\"code\":0,\"message\":\"导入完成：1 条成功，0 条跳过\",\"data\":{\"imported\":1,\"skipped\":0,\"upgraded\":1}}\n```\n\n`upgraded:1` 表示服务端识别到 v4.0 富格式并跑了 schemaUpgrader。\n\n### 7-Client-c. 入库回查（必做）\n\n```bash\ncurl -s https://tuyaya.online/api/ielts \\\n  -H 'Content-Type: application/json' \\\n  -d \"{\\\"action\\\":\\\"getReviews\\\",\\\"token\\\":\\\"$IELTS_USER_TOKEN\\\",\\\"book\\\":<BOOK>,\\\"test\\\":<TEST>}\" \\\n  | python3 -m json.tool | head -30\n```\n\n确认返回的 data 数组里有刚上传那篇（`book`/`test`/`passage` 三元组匹配），并且 `username` 是登录账号（如 `lishuzhuo`），不是 `dengjiawei`。\n\n### 7-Client-d. 给用户的最终输出\n\n```\n✅ 复盘已入库\n\n📊 在主页查看进度图、词汇本、错题本：\n👉 https://tuyaya.online/ielts/reading.html\n   （登录账号：<username>）\n\n📄 复盘详情页：\n👉 https://tuyaya.online/ielts/review.html?file=剑X-TestX-PassageX-主题复盘.json\n```\n\n> **客户端模式注意**：复盘详情页 `review.html?file=...` 依赖服务端 `/var/www/ielts/reviews/` 下的 JSON 文件。客户端模式只把数据写进数据库，**不上传 JSON 文件到服务器**，所以详情页可能 404。但首页进度图、词汇本、错题本能正常工作（这些数据都从数据库读）。\n>\n> 如果用户特别想要详情页可访问，提醒他把 JSON 发给作者人工部署，或者作者机用 `ielts-server-sync` skill 同步。\n\n### 7-Client 红线（绝对禁止）\n\n- 🚫 `ssh openclaw-tunnel ...`\n- 🚫 `scp ... ubuntu@ssh.tuyaya.online:...`\n- 🚫 `gzip -c | ssh openclaw-tunnel \"gunzip > /var/www/...\"`\n- 🚫 `sudo systemctl restart ielts-api`\n- 🚫 修改 `dict_full.json` / `synonym_data.json` / `bilingual_data.json` / `answer-key.json` 后试图部署\n- 🚫 部署 `site/reviews/` 下的 JSON 文件到服务器\n\n**客户端只做两件事**：本地存 JSON + HTTPS batchImport 入库。\n\n### 7-Client onboarding（首次配置）\n\n如果用户首次跑客户端模式，缺 `IELTS_USER_TOKEN`，按以下流程引导：\n\n1. 浏览器登录 https://tuyaya.online/ielts/login.html\n2. F12 打开 DevTools → Console\n3. 输入 `localStorage.token`，回车，复制返回字符串（一长串 base64）\n4. 在 `~/.zshrc` 末尾加：\n   ```bash\n   export IELTS_USER_TOKEN='粘贴token'\n   ```\n5. `source ~/.zshrc` 或重开终端\n6. 验证：`echo \"${IELTS_USER_TOKEN:0:20}...\"` 应输出前 20 个字符\n\ntoken 默认有效期 10 年，配一次基本一劳永逸。\n\n## 扩展新书（C21+）\n\n服务端预置数据仅覆盖 C4-C20。复盘剑21及以后的书时，需要额外做：\n\n1. 在 `site/answer-key.json` 追加条目（格式：`C{book}-T{test}-R{passage}`，**R 不是 P**）\n2. SCP 到 `/var/www/ielts/answer-key.json`\n3. （可选）追加 `site/bilingual_data.json` 并 SCP\n4. 重启后端：`ssh openclaw-tunnel \"sudo systemctl restart ielts-api\"`\n\nC4-C20 范围内的复盘**不需要**这一步。\n\n## Batch Import Mode (v3.8 — Legacy Review Folder → JSON)\n\n**触发场景**：用户说\"帮我把 XX 目录下的历史复盘都转成 JSON\"、\"批量导入我以前的复盘笔记\"、\"扫一下我电脑里的复盘\"、\"帮我找出所有历史笔记\"等。\n\n此模式下 Buddy 自主循环，**无需用户自己找路径、无需一篇篇喂**。\n\n### Step B0: Auto-Discovery（🔍 推荐默认起点）\n\n**不要开口就问用户\"复盘文件夹在哪？\"**——先自动扫常见位置：\n\n```bash\nnode ~/.workbuddy/skills/ielts-reading-review/scripts/scan-legacy-reviews.js --auto\n```\n\n脚本会扫描以下位置并按命中数推荐：\n- 当前工作目录 (cwd)\n- `~/Documents`、`~/Documents/个人`、`~/Documents/个人/WorkBuddy`\n- `~/Desktop`、`~/Downloads`\n- `~/Library/Mobile Documents/com~apple~CloudDocs`（iCloud）\n- `~/WorkBuddy`、`~/WorkBuddy/Claw`\n\n输出 `discoveries`（去重后的真实命中目录，命中数多的子目录优先）和 `recommended`（首选目录）。\n\n**把发现结果呈现给用户**：\n\n```\n我扫了你电脑常见位置，找到你的复盘应该在这里：\n\n🎯 推荐：/Users/xxx/Documents/个人/WorkBuddy/雅思学习（60 个候选文件）\n   样例：剑6-Test3-Passage3-抗衰老药物复盘.html / 剑4-Test1-听力Part2-河滨工业村复盘.html …\n\n其他候选：\n  - /Users/xxx/Downloads（4 个）\n\n要用推荐目录还是选其他的？\n```\n\n用户点头后进入 Step B1 做精扫。**只有当自动发现完全找不到候选（discoveries 为空）时**，才问用户要具体路径。\n\n### Step B1: Scan the Folder\n\n调用扫描脚本生成候选清单：\n\n```bash\n# 默认只扫顶层\nnode ~/.workbuddy/skills/ielts-reading-review/scripts/scan-legacy-reviews.js <目录> --out=/tmp/ielts-scan.json\n\n# 需要递归子目录\nnode ~/.workbuddy/skills/ielts-reading-review/scripts/scan-legacy-reviews.js <目录> --deep --out=/tmp/ielts-scan.json\n```\n\n输出 JSON 结构（groups 按篇目聚合）：\n\n```json\n{\n  \"totalFiles\": 18,\n  \"identifiedPassages\": 6,\n  \"groups\": [\n    {\n      \"passage\": \"C5-T1-P2\",\n      \"fileCount\": 3,\n      \"files\": [\n        { \"path\": \"...\", \"ext\": \".html\", \"hints\": { \"book\": 5, \"test\": 1, \"passage\": 2, \"title\": \"鲸鱼感官\" } },\n        { \"path\": \"...\", \"ext\": \".md\" },\n        { \"path\": \"...\", \"ext\": \".png\" }\n      ]\n    },\n    { \"passage\": \"__unknown__\", \"files\": [...] }\n  ]\n}\n```\n\n### Step B2: Show Plan & Confirm\n\n读取 scan 结果后，**必须先给用户一份执行计划**，不要直接开干：\n\n```\n扫描完成，找到 18 个候选文件，识别出 6 篇复盘：\n\n✅ 可识别：\n  1. 剑5-T1-P2 · 鲸鱼感官（HTML + MD + 截图，共 3 个文件）\n  2. 剑5-T1-P3 · 儿童认知（HTML）\n  3. 剑6-T2-P1 · ...\n  ...\n\n⚠️ 无法识别篇目（需你人工分配）：\n  - notes-2026-03-15.md\n  - 错题整理.docx\n\n我将逐篇处理可识别的 6 篇，每篇生成一个 JSON。预计 10-15 分钟。\n确认开始？\n```\n\n用户点头后才进入 Step B3。\n\n### Step B3: Loop — Generate JSON for Each Passage\n\n**逐篇循环**，每次处理一组：\n\n1. 读取该组所有文件内容（HTML 提纯文字、MD 直读、图片用视觉 OCR）\n2. 从内容中提取：原文/正确答案/用户答案/错题/时长/日期\n3. **关键兜底**：\n   - 内容里找不到\"正确答案\" → 查 `site/answer-key.json`（本地答案库，401 题全覆盖）\n   - 找不到用户答案 → 标注 `score.correct = null` 让用户后续补\n   - 错题列表不清晰 → 只生成基础成绩单 JSON，`wrongQuestions: []`\n4. 按 v4.0 schema 生成 JSON（v3.0 新增字段可选），文件名 `剑X-TestX-PassageX-中文主题复盘.json`\n5. 写入用户指定的输出目录（默认 `./batch-output/`）\n6. 输出一行进度：`✅ [3/6] 剑5-T1-P3 · 儿童认知 → 剑5-Test1-Passage3-儿童认知复盘.json`\n\n### Step B4: Summary Report\n\n全部完成后输出总结：\n\n```\n批量导入完成！\n\n✅ 成功：5 篇（已生成 5 个 JSON 到 ./batch-output/）\n⚠️ 部分数据缺失：1 篇（剑6-T2-P1 找不到用户答案，score.correct 置空）\n❌ 跳过：0 篇\n\n下一步：\n👉 打开 https://tuyaya.online/ielts/submit.html?mode=json\n👉 把 ./batch-output/ 里所有 JSON 拖进去，一键导入\n```\n\n### Batch Mode Rules (MUST FOLLOW)\n\n1. **永远先 scan + confirm，绝不跳过计划确认**\n2. **每篇独立处理，失败不阻塞下一篇**（捕获异常，记录到 skip 列表）\n3. **绝不编造数据**：用户答案缺失就置 null 或空数组，不要瞎填\n4. **同义替换/词汇/错因分析是可选项**：老笔记里没有就不生成，不要硬凑\n5. **答案库优先**：正确答案一律从 `site/answer-key.json` 核对，笔记里的可能是老婆写错的\n6. **产物隔离**：批量输出统一放 `./batch-output/`，不污染用户工作目录\n\n## Error Analysis Rules\n\n### TRUE / FALSE / NOT GIVEN 三步法\n\n1. **找话题** — 文章有没有讨论题目中的对象？→ 没讨论 = **NOT GIVEN**\n2. **找立场** — 讨论了的话，是同意还是矛盾？→ **TRUE** / **FALSE**\n3. **验证** — \"如果选 TRUE/FALSE，能指出原文哪句话吗？\" 指不出来 → 大概率 **NOT GIVEN**\n\n关键区分：\n- FALSE 需要**直接矛盾证据**，\"没提到\"= NG 不是 FALSE\n- 概括性表达覆盖题目对象 = 算讨论过，不是 NG\n- `however + adj` = `no matter how`（让步），不是因果\n\n### Fill-in-the-blank\n\n- 答案不能重复题干已有的词\n- 填完必须通读：语法/词性/语义/字数 四项检查\n- `such as ___` → 必须填具体例子\n- `the ___ of X` → 必须填能和 \"of X\" 搭配的名词\n\n### Common Pitfalls\n\n- **过度推理**：只看作者明确写了什么，不推导\n- **被绝对词吓到**：all/never 不一定错，看原文证据\n- **人名观点混淆**：先在文中标注每个人说了什么\n- **邻近干扰词**：从定位句提取答案，不要被旁边的句子污染\n- **Heading 复用 Example**：做 Heading 题第一步永远是划掉 Example 已用的选项\n- **Although 从句看错重点**：主句才是作者立场，让步从句只是背景\n- **双重否定读反了**：not unusual=usual, not uncommon=common, rarely+isn't=几乎总是。看到双重否定立刻翻译成肯定\n- **Summary 填空凭感觉**：必须先回原文找对应句，再从选项中匹配。不回原文 = 全靠蒙\n- **对比信号词忽略**：\"difference from X\" 本身就是对比框架，后面的内容就是证据\n- **选择题选了和全文论点相反的**：选完后反问\"这个选项和作者核心主张一致吗？\"\n- **段落匹配被信息密度干扰**：题目问 \"term\"（定义），选了有数字的段落而非有 \"refer to as\" 的段落。精确锁定每个关键词含义\n- **Summary 填空近义词混用**：同段落两个近义表达，看题目限定词（如 Britain）对应原文哪个子语境\n- **Summary 填空专有名称不完整**：看到引号/大写开头名称，先数字数，限制内写全称不缩写\n\n## Error Categories\n\n参见 `references/error-taxonomy.md`，共 18 类错误分类。JSON 中 `errorCategory` 字段使用以下 ID：\n\n| ID | 错误类型 |\n|----|---------|\n| `synonym-failure` | 同义替换识别失败 |\n| `ng-false-confusion` | NOT GIVEN / FALSE 混淆 |\n| `over-inference` | 过度推理 |\n| `stem-repetition` | 填空重复题干词 |\n| `grammar-mismatch` | 语法/让步句理解错 |\n| `incomplete-option` | 选项不完全匹配 |\n| `vocab-gap` | 词汇缺口 |\n| `carelessness` | 粗心/时间压力 |\n| `word-form-error` | 填空词形/词性错 |\n| `scope-confusion` | 跨代/范围混淆 |\n| `category-reasoning` | 类别推理误判 |\n| `adjacent-distractor` | 邻近干扰词 |\n| `heading-example-reuse` | Heading匹配复用Example已用选项 |\n| `concessive-clause-confusion` | Although/While让步从句混淆主句 |\n| `double-negative-misread` | 双重否定读不出肯定 |\n| `summary-no-source` | Summary填空没回原文定位 |\n| `comparison-signal-ignored` | 对比信号词(difference from等)忽略 |\n| `selection-contradicts-thesis` | 选择题选了和全文论点矛盾的选项 |\n\n## Style Guidelines\n\n- 简洁直接，不废话\n- 错题分析直说问题，不糖衣炮弹\n- 中文为主，英语术语保留原文\n\n## 🔴 Step 8: Final Gate (v5.5.1 — Mandatory before any ending)\n\n**任何复盘对话，在你即将给出收尾回复（\"复盘完成 / 总结 / 错题分析全部跑完\"）之前，必须先逐条过完以下 4 个 Gate。任何一条 ❌ 一律返回继续干，禁止结束。**\n\n| Gate | 自检问题 | 判定来源 |\n|---|---|---|\n| **Gate 1** | 我有没有为本次每一篇生成 v4.0 富 JSON 写到 `site/reviews/`？ | `ls site/reviews/` 看到对应文件 |\n| **Gate 2** | 我有没有调 `saveReview`（作者模式）或 `upload.js`/`batchImport`（客户端模式）？ | 看上面命令的返回值是 `success/code:0` |\n| **Gate 3** | 我有没有用 `getReviews` 回查确认入库 ✅？ | 回查 JSON 里有匹配 book/test/passage 的 record |\n| **Gate 4** | 我有没有把线上链接（`tuyaya.online/ielts/review.html?file=...`）写进给主人的最终回复？ | 检查最终回复文本 |\n\n**自检模板（在收尾前内部默念一遍）：**\n\n```\nGate 1: site/reviews/剑X-TestX-PassageX-主题复盘.json  ✅ / ❌\nGate 2: saveReview / upload.js  ✅ / ❌\nGate 3: getReviews 回查命中  ✅ / ❌\nGate 4: 最终回复包含线上链接  ✅ / ❌\n```\n\n**若任意一条 ❌**：立即回到对应 Step 补做，绝不允许\"先交付文字版，再说\"。\n\n**作者机一键回查命令（复制即用）：**\n\n```bash\nTOKEN=$(cat ~/.ielts-tuyaya-token | python3 -c \"import json,sys; print(json.load(sys.stdin)['token'])\")\ncurl -s 'https://tuyaya.online/api/ielts' -H 'Content-Type: application/json' \\\n  -d \"{\\\"action\\\":\\\"getReviews\\\",\\\"token\\\":\\\"$TOKEN\\\",\\\"book\\\":<BOOK>,\\\"test\\\":<TEST>}\" \\\n  | python3 -c \"import json,sys; d=json.load(sys.stdin); recs=[r for r in d.get('data',[]) if r['book']==<BOOK> and r['test']==<TEST>]; print('✅ 已入库篇目:', [(r['passage'], r['score'], r['total']) for r in recs])\"\n```\n\n**若主人对话里只发了某一两篇阅读题**：完成那几篇的 4 个 Gate 即可，不要扩展到整个 Test。\n\n**若做完一篇主人立刻发下一篇**：先把当前篇 4 Gate 全过 ✅，再开下一篇。绝对不允许积压。\n\n> 这道 Gate 是 v5.5.1 的灵魂。其他所有 step 都可以小幅偷懒，唯独这道 Gate 必须 100% 过完。\n\n## 客户端模式参考\n\n外部用户/老婆机器首次配置看这里：[`references/CLIENT_MODE_ONBOARDING.md`](references/CLIENT_MODE_ONBOARDING.md)\n\n一键脚本：`bash ~/.workbuddy/skills/ielts-reading-review/scripts/setup-client-mode.sh`\n\nFile v5.5.1:README.md\n\n# IELTS Reading Review 雅思阅读复盘助手\n\n> Finish a reading passage, hand it to AI, get a complete review — error analysis, synonym tracking, vocabulary tagging, and mistake pattern detection, all in one go.\n\n做完阅读题，丢给 AI，自动出复盘笔记——错题拆解、同义替换积累、考点词标注、易错模式追踪，一步到位。\n\n---\n\n## 🆕 What's New in v5.4 — OAuth 风格浏览器授权流\n\n**告别 F12 复制 token 的笨流程**——客户端模式绑定账号体验彻底重做：\n\n### 🎯 30 秒上手（替代原来 5 分钟）\n\n```bash\nbash ~/.workbuddy/skills/ielts-reading-review/scripts/setup-client-mode.sh\n```\n\n脚本自动完成 4 件事：\n\n1. **本机起临时 HTTP 服务**（随机空闲端口监听 OAuth 回调）\n2. **唤起浏览器**到 `https://tuyaya.online/ielts/authorize.html`\n3. **页面显示 OAuth 风格卡片**：客户端名 / 本机回调地址 / 当前账号 / 权限列表 / 【拒绝】【授权】\n4. **点【授权】** → token 通过 `<img>` 请求回传本机 → 自动写入 `~/.zshrc` → 显示绑定账号名\n\n### 🔒 安全设计\n\n| 风险点 | 防护机制 |\n|---|---|\n| token 被中间人截获 | 全程仅浏览器 ↔ 本机 127.0.0.1，不走第三方 |\n| token 进 URL bar 被记录 | 用 `<img src=...?token>` GET 而非 `location.href`，不留浏览历史 |\n| CORS / Private Network 拦截 | 用图片请求绕过预检 |\n| 跨站伪造请求 | `secrets.token_urlsafe(16)` 生成 state，服务端校验 |\n| 恶意回调地址 | 授权页强制白名单：仅 `127.0.0.1 / localhost / ::1` + http |\n\n### 🪟 三系统全覆盖\n\n- macOS：`open` 命令唤起浏览器\n- Linux：`xdg-open`\n- 兜底：打印链接，用户手动复制到浏览器\n\n### 🛟 兜底模式\n\n浏览器/网络异常时：\n\n```bash\nbash setup-client-mode.sh --manual\n```\n\n回退到 F12 → Console → `localStorage.ielts_user_token` 复制粘贴的老流程。\n\n---\n\n## 🆕 What's New in v3.1 — Web Hand-off\n\n### 🌐 生成物一键上传到 Web 端\n\nv3.1 在保持纯离线生成的同时，**明确了 JSON 产出物与 Web 端的对接路径**：\n\n- 访问 https://tuyaya.online/ielts/submit.html 切到「**上传 JSON**」Tab\n- 把 skill 生成的 `.json` 文件拖进去 → 成绩、答案、用时自动入库\n- 首页成绩矩阵、词汇本、同义替换本实时更新\n\n### 📊 Web 端新增 JSON 导入能力\n\nWeb 端 `submit.html` 新增第 4 种提交模式（粘贴文本 / PDF / 拍照 / **上传 JSON**），与 skill 的产出物严格对齐 v3.0 schema。\n\n## 🆕 What's New in v3.0 — Offline-First\n\n### 🔌 去服务器依赖，纯本地生成\n\nv3.0 重构为**纯离线模式**：\n\n- ✅ 复盘 HTML — 专业排版，浏览器直接查看\n- ✅ 复盘 PDF — 一键导出，存档分享\n- ✅ 结构化 JSON — 包含成绩、错题、词汇、同义替换等全量数据\n- 🔜 数据上传 — 后续通过 Web 端功能将 JSON 导入云系统，实现多设备同步\n\n**不再依赖任何远程 API**，AI Agent 在本地完成所有分析和生成工作。\n\n### 📋 填空回填 4 步检查\n\n每道填空题强制 4 步验证：语法 → 词性 → 语义 → 字数，杜绝低级失误。\n\n### ✅ 正确题确认 + 进步表扬\n\n- 做对的题也会简要确认，展示同义替换映射帮你强化记忆\n- 每篇开头先肯定你的进步点，保持刷题动力\n\n### 🔢 错误分类扩展到 12 类\n\n涵盖：同义替换识别失败、NG/FALSE 混淆、过度推理、填空重复题干、语法误解、选项不完全匹配、词汇缺口、粗心、词形错误、跨代/范围混淆、类别推理误判、邻近干扰词。\n\n---\n\n## 🚀 快速开始（3 步上手）\n\n### 第一步：安装 Skill\n\n```bash\n# ClawHub 安装（推荐）\nclawhub install ielts-reading-review\n\n# 或手动复制到 skills 目录\ncp -r ielts-reading-review ~/.workbuddy/skills/\n```\n\n### 第二步：做完一篇阅读题\n\n用剑桥雅思真题（Cambridge IELTS）做完一篇阅读，准备好：\n- ✅ 原文（拍照/截图/粘贴文字都行）\n- ✅ 正确答案\n- ✅ 你的答案（标出哪些做错了）\n- ⭕ 可选：翻译、用时\n\n### 第三步：发给 AI，说\"帮我复盘\"\n\n就这么简单。AI 会自动生成：\n1. **复盘 HTML** — 专业排版的复盘笔记\n2. **复盘 JSON** — 结构化数据文件，供后续导入 Web 系统\n3. **复盘 PDF**（可选）— 从 HTML 生成，便于存档\n\n---\n\n## 📖 完整使用案例\n\n> 以下是一个真实的使用过程，以剑4 Test 3 Passage 1 为例。\n\n### 你发给 AI 的内容\n\n```\n我做完了剑4 Test3 Passage1，帮我复盘。\n\n文章：Micro-Enterprise Credit for Street Youth\n用时：34:40\n得分：7/13\n\n我的答案 vs 正确答案：\nQ1: 我选D → 正确A\nQ2: 我选C → 正确D\nQ3: ✅\nQ4: ✅\nQ5: 我填 Sudan and India → 正确 Sudan\nQ6: ✅\nQ7: 我填 shoe shine → 正确 Shoe Shine Collective\nQ8-Q10: ✅\nQ11: 我选 NOT GIVEN → 正确 NO\nQ12: ✅\nQ13: 我选D → 正确A\n\n（然后把原文和翻译也贴上来）\n```\n\n### AI 自动产出\n\nAI 会在本地生成三个文件：\n\n#### 📄 复盘 HTML — `剑4-Test3-Passage1-街头青年信贷复盘.html`\n\n包含以下模块：\n- 得分总览 + Band 分换算 + 核心问题一句话\n- 进步点肯定\n- 逐题错因分析（定位原文、映射同义替换、分类错因、给出教训）\n- 正确题确认\n- 同义替换积累表\n- 考点词表\n- 核心问题总结\n- 行动清单\n\n#### 📊 结构化 JSON — `剑4-Test3-Passage1-街头青年信贷复盘.json`\n\n```json\n{\n  \"version\": \"3.0.0\",\n  \"source\": { \"book\": 4, \"test\": 3, \"passage\": 1 },\n  \"score\": { \"correct\": 7, \"total\": 13, \"band\": \"5.0\" },\n  \"wrongQuestions\": [...],\n  \"synonyms\": [...],\n  \"vocabulary\": [...],\n  \"problems\": [...]\n}\n```\n\n后续可通过 Web 端将此 JSON 上传到云系统，实现多设备同步和进度追踪。\n\n#### 📑 复盘 PDF（可选）\n\n```bash\nnode scripts/generate-pdf.js 剑4-Test3-Passage1-街头青年信贷复盘.html\n```\n\n---\n\n## 🎯 Features\n\n| 功能 | 说明 |\n|------|------|\n| **逐题错因分析** | 定位原文、映射同义替换、分类错因（12 类）、给出 1 句话教训 |\n| **正确题确认** | 正确答案也简要展示同义替换映射，强化记忆 |\n| **同义替换积累** | 自动提取题目-原文同义替换对，跨篇持续积累 |\n| **考点词标注** | 基于刘洪波 538 考点词（⭐⭐⭐/⭐⭐/⭐）+ COCA 5000 词频 |\n| **易错模式追踪** | 跨篇检测反复犯的错 |\n| **📋 填空回填检查** | 每道填空题 4 步强制验证（语法/词性/语义/字数） |\n| **📊 打分 & Band 换算** | 原始分→雅思 Band 分数换算（学术类） |\n| **📄 结构化 JSON 输出** | 成绩、错题、词汇、同义替换全量数据，供 Web 系统导入 |\n| **HTML + PDF 输出** | 排版专业的复盘笔记，支持打印和存档 |\n\n## 📂 File Structure\n\n```\nielts-reading-review/\n├── SKILL.md                          # Skill 定义（AI 读这个文件理解工作流）\n├── README.md                         # 使用说明（你正在看的这个）\n├── assets/\n│   ├── review-template.html          # HTML 模板 + CSS 样式\n│   └── bilingual-template.html       # 双语对照页面模板\n├── references/\n│   ├── error-taxonomy.md             # 12 类错误分类体系\n│   ├── 538-keywords-guide.md         # 考点词评级指南\n│   ├── score-band-table.md           # 分数→Band 换算表\n│   └── review-style-guide.md         # 写作风格规范\n└── scripts/\n    └── generate-pdf.js               # PDF 生成脚本\n```\n\n## 🧠 内置做题方法论\n\n### T/F/NG 三步判断法\n1. **找话题** — 原文有没有讨论题目说的这个话题？→ 没有 → **NOT GIVEN**\n2. **找立场** — 如果话题存在，作者同意还是反对？→ **TRUE** / **FALSE**\n3. **验证** — \"如果我选 TRUE/FALSE，能指出原文哪一句吗？\"指不出来 → 大概率 **NOT GIVEN**\n\n### 填空题防重复规则\n答案不要重复题目中已有的词。填完后把答案放回原句完整读一遍。\n\n### 选择题逐词验证法\n选项中的**每个关键词**都要在原文找到对应。\"大致相关\" ≠ \"能选\"。前半句对但后半句多了信息 → 干扰项。\n\n## 📤 数据导入 Web 系统\n\nv3.1 起，生成的 JSON 文件可**直接通过 Web 端导入**（已上线）：\n\n### 方式 1：Web 端拖拽上传（推荐）\n\n1. 访问 **https://tuyaya.online/ielts/submit.html**\n2. 登录账号（第一次使用会引导注册）\n3. 切换到顶部 Tab「**📊 上传 JSON**」\n4. 把 skill 生成的 `.json` 文件拖入上传区（或点击选择）\n5. 点「导入到我的记录」\n\n导入成功后，以下页面会自动刷新：\n- **首页成绩矩阵** — 新篇目变绿，显示得分\n- **词汇本** — JSON 中的考点词自动合并\n- **同义替换本** — JSON 中的同义替换对自动入库\n- **个人中心** — 统计总数、均分、Band 分更新\n\n### 方式 2：命令行批量上传（进阶）\n\n需要额外安装 `ielts-server-sync` skill（作者个人维护，不公开发布）：\n\n```bash\n# 单文件\nnode ~/.workbuddy/skills/ielts-server-sync/scripts/upload.js 剑5-T1-P2.json\n# 批量\nnode ~/.workbuddy/skills/ielts-server-sync/scripts/upload.js --batch ./reviews/\n# 查服务器记录\nnode ~/.workbuddy/skills/ielts-server-sync/scripts/upload.js --status\n```\n\n### 方式 3：HTML 本地存档\n\n直接双击生成的 `.html` 文件，浏览器打开即可阅读 / 打印，不依赖任何服务器，隐私可控。\n\n## 👤 Who It's For\n\n雅思备考者，尤其是：\n- 阅读 5-7 分想突破的\n- 复盘效率低，做完题不知道怎么分析的\n- 同样的错反复犯，需要系统追踪的\n- 想把词汇积累和真题练习结合起来的\n\n## ⚙️ Requirements\n\n- 支持 SKILL.md 的 AI Agent（如 OpenClaw、Claude Code、WorkBuddy/CodeBuddy）\n- PDF 导出需要：Node.js + puppeteer-core + 本地 Chrome（可选，不装也能用 HTML）\n\n## 🤝 Contact & Feedback\n\nIf this Skill helps your IELTS prep, a ⭐ Star would mean a lot!\n\n如果这个 Skill 对你备考有帮助，欢迎点个 ⭐ 支持！\n\n- 💡 **Feature requests / Bug reports**: [Open an Issue](https://github.com/dengjiawei1226/ielts-reading-review/issues)\n\n## License\n\nMIT-0\n\nFile v5.5.1:_meta.json\n\n{\n  \"ownerId\": \"kn7dr93fbgrvymnk8d9r9y0tws83mhrk\",\n  \"slug\": \"ielts-reading-review\",\n  \"version\": \"5.5.1\",\n  \"publishedAt\": 1780324918451\n}\n\nFile v5.5.1:references/538-keywords-guide.md\n\n# 538 IELTS Keywords Reference Guide\n\n## About This Resource\n\nThe 538 Keywords list comes from Liu Hongbo's \"Cambridge IELTS Reading Keywords\" (刘洪波《剑桥雅思阅读考点词真经》). It categorizes high-frequency words that appear repeatedly in IELTS Academic Reading questions.\n\n## How to Use for Vocabulary Rating\n\nWhen building the vocabulary table in a review note, look up each word against the 538 list:\n\n### Rating Scale\n\n| Rating | Category | Count | Question Appearance Rate |\n|--------|----------|-------|------------------------|\n| ⭐⭐⭐ | Category 1 | 54 words | ~90% of passages contain these |\n| ⭐⭐ | Category 2 | 171 words | ~60% of passages contain these |\n| ⭐ | Category 3 | 300+ words | Common but less predictable |\n| — | Not listed | N/A | Check COCA 5000 for general frequency |\n\n### Lookup Procedure\n\n1. Search the full 538 list (provided as `雅思阅读538考点词-刘洪波真经.txt` in the workspace) for the target word\n2. If found, note its category number and rank\n3. Record in the vocabulary table as: `⭐⭐⭐ 538考点词 #XXX` (where XXX is the rank)\n4. If not found in the 538 list, check COCA 5000 for general English frequency\n5. Words below COCA 3000 that are not in the 538 list can be marked as low-priority\n\n### COCA 5000 Supplementary Use\n\nThe COCA (Corpus of Contemporary American English) 5000 frequency list (`COCA_5000词频表.csv`) provides general English word frequency rankings. Use it to:\n\n- Determine if an unknown word is commonly used in English (not just IELTS)\n- Prioritize learning: COCA top 2000 = essential everyday English; 2000-5000 = academic/professional English\n- A word in COCA top 3000 but not in the 538 list is still worth learning for general proficiency\n\n### Cambridge Test Appearance Column\n\nThe \"真题出现\" (Cambridge Appearance) column tracks where a word has actually appeared in Cambridge IELTS tests. Format:\n\n- Single appearance: `剑4T3P2`\n- Multiple appearances: `剑4T3P2, 剑7T1P1, 剑9T2P3`\n- This column is **cumulative** — add new appearances as more passages are reviewed\n- High-frequency words appearing across multiple books indicate they are particularly important\n\nFile v5.5.1:references/CLIENT_MODE_ONBOARDING.md\n\n# 👩‍🎓 给老婆/外部用户：跑通整套 Skill 复盘流程\n\n这份文档教你怎么把 `ielts-reading-review` + `ielts-review-upload` 两个 Skill 跑成「客户端模式」，让 AI 帮你做完整复盘后**自动同步到你 tuyaya.online 账号下的进度图、词汇本、错题本**。\n\n> 不是给作者本人用的——作者机直接走 SSH 部署链路。这份文档专门给**没有 openclaw-tunnel SSH 凭据**的机器准备。\n\n## 你能得到什么\n\n- ✅ 发截图给 AI → AI 自动识别错题、生成富 JSON 复盘\n- ✅ 复盘自动入库 → 网站首页进度图实时更新\n- ✅ 词汇/错题/同义替换 → 自动同步到你账号下的复习本\n- ✅ 不需要任何 SSH 知识、不需要碰服务器\n\n## 前置条件\n\n1. 已在 https://tuyaya.online/ielts/login.html 注册账号（如 lishuzhuo）\n2. 本机装了 WorkBuddy / CodeBuddy（能用 `Skill` 工具）\n3. 装好 `ielts-reading-review` + `ielts-review-upload` 这两个 Skill\n\n## 一次性配置（30 秒搞定）\n\n```bash\nbash ~/.workbuddy/skills/ielts-reading-review/scripts/setup-client-mode.sh\n```\n\n**这是浏览器授权流（v5.4 新版）**：\n1. 脚本启动一个本地随机端口的 HTTP 服务（监听本机回调）\n2. 自动打开浏览器到 `tuyaya.online/authorize.html`\n3. 在页面看到客户端信息卡片，点击 **「授权」**\n4. token 经浏览器以 `<img>` 请求方式回传到本机（**永远不离开你的电脑**）\n5. 脚本自动校验 + 写入 `~/.zshrc`，显示绑定的账号名\n\n> 网络/浏览器异常时可手动跑兜底模式：`bash setup-client-mode.sh --manual`\n> 这种情况下需要 F12 → Console → 输入 `localStorage.ielts_user_token` 复制 token 粘贴到终端。\n\n完成后重开终端或 `source ~/.zshrc`。\n\n**验证成功标志**：\n```bash\necho \"${IELTS_USER_TOKEN:0:20}...\"   # 应该看到 eyJ1Ijoi... 之类的前缀\n```\n\n## 日常用法\n\n直接对 AI 说：\n\n```\n复盘剑8 Test1 Passage2，错题截图：[贴图]，用时 32:15\n```\n\nAI 会自动：\n1. 检测到客户端模式\n2. 读截图识别错题（先报清单等你确认）\n3. 生成富 JSON 复盘到本地（默认 `~/Documents/雅思复盘/`）\n4. 通过 HTTPS batchImport 上传到你账号\n5. 回查 getReviews 确认入库\n6. 给你主页链接：`https://tuyaya.online/ielts/reading.html`\n\n## 数据归属\n\n- 上传通道：`POST https://tuyaya.online/api/ielts {action:'batchImport', token}`\n- 数据落点：主库 `ielts_reviews` 表，`username` 字段 = 你的登录账号\n- 主页效果：登录后能看到进度图、词汇本、错题本同步更新（和作者本人完全同等待遇）\n\n## 限制（客户端模式做不到的）\n\n- ❌ 不能部署复盘 JSON 文件到服务器，所以「复盘详情页」`review.html?file=...` 可能 404\n  - **绕过**：把复盘 JSON 发给作者人工部署，或继续在本地查看\n- ❌ 不能扩展词库（dict_full.json）/双语数据（bilingual_data.json）\n  - **绕过**：作者机已预置 C4-C20 全量数据，C21+ 才需要扩展\n\n但**首页进度图、词汇本、错题本完全可用**——这些数据都从数据库读，不依赖文件部署。\n\n## 出问题怎么办\n\n| 症状 | 解决 |\n|---|---|\n| `echo $IELTS_USER_TOKEN` 没输出 | `source ~/.zshrc` 或重开终端 |\n| AI 说\"token 过期\" | 重新登录 tuyaya.online，重跑 setup-client-mode.sh |\n| 主页看不到新复盘 | 确认 AI 输出里有 `imported:1, upgraded:1`，没有就是 batchImport 没调通 |\n| AI 误走 SSH 部署 | 检查 Step 0a 模式横幅，应该是「客户端模式」，否则升级 Skill |\n\n## Token 安全\n\n- token 默认有效期 10 年\n- 写在本地 `~/.zshrc`，不要发到群里/截图给别人\n- 怀疑泄漏可以登录后端管理页面手动重置（联系作者）\n\nFile v5.5.1:references/error-taxonomy.md\n\n# Error Taxonomy for IELTS Reading Review\n\nThis document classifies common IELTS reading errors into categories. When analyzing a wrong answer, identify which category applies and use the corresponding improvement advice.\n\n## Category 1: Synonym / Paraphrase Recognition Failure\n\n**Description:** The passage uses a synonym or paraphrase of the question's keyword, and the test-taker fails to recognize the equivalence.\n\n**Examples:**\n- Question says \"financial__(adj)\" → Passage says \"economic\"\n- Question says \"\n\n\n\" → Passage says \"children / young people\"\n- Question says \"\n\n\n\" → Passage says \"the\n\n\n of the world\"\n\n**Improvement:** Actively build a synonym accumulation table after every passage. Reference the 538 keywords list for known IELTS synonyms.\n\n---\n\n## Category 2: NOT GIVEN vs FALSE Confusion\n\n**Description:** Choosing FALSE when the passage simply doesn't discuss the topic (should be NOT GIVEN), or choosing NOT GIVEN when there is direct contradicting evidence (should be FALSE).\n\n**Key Rule:**\n- **FALSE** = The passage explicitly says the **opposite** of the question\n- **NOT GIVEN** = The passage does **not discuss** the topic at all, or discusses it but without taking a clear position that matches or contradicts\n\n**Improvement:** Apply the Three-Step Method every time — find topic → find stance → verify with a specific sentence.\n\n---\n\n## Category 3: Over-Inference\n\n**Description:** Drawing a conclusion that the passage does not explicitly state. The test-taker adds their own reasoning or world knowledge on top of what the author wrote.\n\n**Examples:**\n- Passage discusses ancient archaeological methods → Test-taker infers \"translating ancient texts\" was also mentioned (it wasn't)\n- Passage says a task requires \"a wider range of skills\" → Test-taker infers \"more demanding\" (not the same thing)\n\n**Improvement:** Ask: \"Can I point to the **exact sentence** that says this?\" If no → do not choose it.\n\n---\n\n## Category 4: Repeating Stem Words in Fill-in-the-blank\n\n**Description:** Writing a word that is already present in the question stem, making the answer grammatically redundant.\n\n**Examples:**\n- Stem: \"...about their ___\" → Wrong answer: \"about their experiences\" (duplicates \"about\" or \"their\")\n- Stem: \"The ___ of...\" → Wrong answer: \"The the process of...\" (duplicates \"The\")\n\n**Improvement:** After writing the answer, **re-read the complete sentence** with the answer filled in. Check for any duplication.\n\n---\n\n## Category 5: Grammar Mismatch (Concessive / Conditional Clauses)\n\n**Description:** Misunderstanding sentence structure, especially:\n- Concessive clauses (`however + adj/adv` = `no matter how`)\n- Conditional clauses that don't assert facts\n- Double negatives\n\n**Examples:**\n- \"However far from reality...\" = \"No matter how far from reality...\" (acknowledges it IS far from reality)\n- NOT \"This is close to reality\"\n\n**Improvement:** Parse the sentence structure before interpreting meaning. Identify the main clause vs. subordinate clauses.\n\n---\n\n## Category 6: Incomplete Option Matching (Multiple Choice)\n\n**Description:** Selecting an option where only the first half matches the passage. The second half introduces information not present in the passage.\n\n**Improvement:** Check **every keyword** in the option against the passage. All must match, not just some.\n\n---\n\n## Category 7: Vocabulary Gap\n\n**Description:** Not knowing a critical word in the passage or question, leading to misunderstanding.\n\n**Note:** This is only flagged when the unknown word is a high-frequency IELTS word (in the 538 list or COCA top 3000). Low-frequency/specialist vocabulary gaps are noted but not treated as a core error.\n\n**Improvement:** Focus vocabulary building on the 538 keywords list and accumulate words encountered in real Cambridge tests.\n\n---\n\n## Category 8: Time Pressure / Carelessness\n\n**Description:** The test-taker understood the passage and could have answered correctly but made an error due to rushing or insufficient checking.\n\n**Improvement:** Build in a final checking step for every passage before moving on.\n\n---\n\n## Category 9: Fill-in-the-blank Word Form / Part-of-Speech Error\n\n**Description:** The answer has the right root word but wrong form (e.g., adjective instead of noun, singular instead of plural), making it grammatically incorrect when placed back into the sentence.\n\n**Examples:**\n- Stem: \"where ___ are unpredictable\" → Wrong: `temperate` (adjective) → Correct: `temperatures` (noun plural)\n- Stem: \"the ___ of plants\" → Wrong: `classify` (verb) → Correct: `classification` (noun)\n\n**Key Rule:** After filling in the answer, **read the complete sentence aloud**. If the grammar doesn't work (e.g., \"where temperate are unpredictable\"), the word form is wrong.\n\n**Improvement:** Apply the **Fill-in-the-blank Readback Checklist** (see style guide) for every single blank — grammar check, part-of-speech check, semantic check, word count check.\n\n---\n\n## Category 10: Cross-generational / Scope Confusion\n\n**Description:** Confusing what happens to **one individual** vs. **the next generation** or **the species as a whole**. Also applies to mistaking individual cases for general trends.\n\n**Examples:**\n- \"Bamboos flower, fruit and die\" → One bamboo flowers once in its life cycle (then dies). The *next generation* flowering later is NOT the same plant flowering again.\n- \"life cycle\" = one individual's life span, not the species' multi-generational history\n\n**Key Rule:** When the passage mentions generations, cycles, or \"the next...\", track **whose** life cycle or **which** generation is being discussed.\n\n**Improvement:** Circle the subject of each clause. \"Every bamboo flowered\" vs. \"The next generation flowered\" — different subjects, different events.\n\n---\n\n## Category 11: Category-Membership Reasoning Treated as Inference\n\n**Description:** When the passage establishes \"Category A has property B\" and then states \"X belongs to Category A\", concluding \"X has property B\" is **direct information**, not inference. The test-taker wrongly treats this as over-inference and chooses NOT GIVEN.\n\n**Examples:**\n- Passage: \"Shade-tolerant plants have lower growth rates\" + \"Eastern hemlock is shade-tolerant\" → Eastern hemlock has lower growth rates. This is NOT inference — it's stated through category membership.\n- Test-taker chose NOT GIVEN thinking \"the passage doesn't directly say eastern hemlock has lower growth rates\"\n\n**Key Rule:** If the passage says \"A-type things have X\" and \"Y is A-type\", then \"Y has X\" is **a stated fact**, not inference. This is TRUE/FALSE territory, not NOT GIVEN.\n\n**Improvement:** When you're leaning toward NOT GIVEN, check: did the passage put the subject into a category that was already described? If yes, the category's properties apply.\n\n---\n\n## Category 12: Adjacent Distractor Words\n\n**Description:** The correct answer word is near other plausible-looking words in the passage. The test-taker picks a nearby word instead of the one that actually fits the sentence structure.\n\n**Examples:**\n- Passage: \"This **classification** is commonly used in forestry and horticulture.\" The word `habitat` appears nearby in the next sentence. Test-taker fills `habitat` instead of `classification`.\n- Passage: \"like **sugarcane**, never reach a maximum, but continue to increase photosynthesis rate as light intensity rises.\" Test-taker fills `light intensity rises` instead of `sugarcane`.\n\n**Key Rule:** After locating the relevant sentence, **only extract the answer from that specific sentence**. Don't let nearby sentences contaminate your answer.\n\n**Improvement:** Underline the exact sentence that corresponds to the question structure, then extract only from within that sentence.\n\n---\n\n## Category 13: Heading Match — Using Example's Answer\n\n**Description:** In List of Headings questions, the test-taker selects a heading that was already used by the worked Example, effectively double-assigning it.\n\n**Examples:**\n- Example assigns heading `iii` to Section A. Test-taker picks `iii` again for Section D.\n- The correct heading for Section D was `v`, but test-taker forgot to cross off `iii`.\n\n**Key Rule:** **First step of any Heading Match question**: cross off ALL headings already used by Examples. They are eliminated and cannot be reused (unless the question says \"NB You may use any heading more than once\").\n\n**Improvement:** Before even reading the paragraphs, physically cross off used headings. Mark positive/negative tone for remaining headings, then match.\n\n---\n\n## Category 14: Concessive Clause Main-Clause Confusion\n\n**Description:** In sentences with Although/While/Despite/Even though, the test-taker bases their judgment on the concessive (subordinate) clause instead of the main clause. The main clause carries the author's actual position.\n\n**Examples:**\n- \"Although industrial output has soared, water consumption has slowed\" → Author's point = consumption slowed (main clause), NOT output soared (concessive clause)\n- Test-taker judges Y/N/NG based on \"industrial output soared\" and ignores the main clause contradiction\n\n**Key Rule:** In Although/While/Despite sentences: concessive clause = acknowledged background; **main clause = author's real position**. Y/N/NG judgment must be based on the main clause.\n\n**Improvement:** Circle the main clause. Ask: \"What is the author actually asserting?\" The Although-clause is just context.\n\n---\n\n## Category 15: Double Negative Misread\n\n**Description:** Failing to recognize that two negatives cancel out to make a positive. This error has appeared in multiple forms and keeps recurring.\n\n**Complete checklist of double-negative patterns:**\n- `not unusual` = usual / common\n- `not uncommon` = common\n- `not insignificant` = significant\n- `not unimportant` = important\n- `not unlikely` = likely\n- `rarely + isn't` = almost always is\n- `seldom + not` = almost always\n- `hardly + negative` = positive\n\n**Key Rule:** When you see ANY negative prefix (un-, in-, im-) or negative adverb (rarely, seldom, hardly) combined with another negative (not, isn't, wasn't), immediately translate to the positive equivalent.\n\n**Improvement:** Highlight every negative word in the sentence. Count them. Even number of negatives = positive meaning.\n\n---\n\n## Category 16: Summary Fill-in-the-blank Without Source Location\n\n**Description:** Attempting Summary completion by looking at the answer options and guessing which \"feels right\" for each blank, without first locating the corresponding passage sentences.\n\n**The 0/4 Disaster (C7T1P3 Q37-40):** All four blanks wrong because the test-taker never went back to the passage to find the matching sentences.\n\n**Mandatory Three-Step Process:**\n1. **Locate** the corresponding paragraph(s) in the passage\n2. **Find** the specific sentence that matches the summary statement\n3. **Match** the option word to the original passage word/concept\n\n**Key Rule:** Summary blanks are NOT a vocabulary test — they are a paraphrase-matching exercise. The answer is always findable in the passage. If you can't point to the passage sentence, you're guessing.\n\n**Improvement:** Before filling ANY blank, write down the passage paragraph and sentence number where the answer comes from. No source = don't fill.\n\n---\n\n## Category 17: Comparison Signal Words Ignored\n\n**Description:** Missing comparison frameworks like \"difference from X\", \"unlike X\", \"in contrast to X\" which establish that the subject has a different property from X.\n\n**Examples:**\n- \"Another difference from conventional teaching is the evidence that students can learn 1000 new words\" → suggestopedia students learn MORE than conventional (1000 words IS the difference)\n- Test-taker chose FALSE because \"no direct number comparison is given\" — but \"difference from X\" IS the comparison framework\n\n**Key Rule:** \"Difference from X\" = the subject is NOT like X in this respect. The rest of the sentence describes HOW it differs. You don't need two numbers side-by-side.\n\n**Improvement:** Circle comparison markers (difference from, unlike, in contrast to, compared with). These are implicit comparisons — the sentence after them IS the evidence.\n\nFile v5.5.1:references/review-style-guide.md\n\n# Review Note Style Guide (V2)\n\n## General Tone\n\n- **Concise and direct** — No decorative language, no marketing-speak\n- **Function-oriented** — Every sentence exists to help the user improve\n- **Honest about errors** — Sugar-coating doesn't help learning; be blunt about what went wrong\n- **Chinese as primary language** — English terms, vocabulary, and passage quotes preserved as-is\n\n## V2 Design System\n\nThe review notes use a modern card-based design with CSS Variables, Lucide SVG icons, and a purple gradient hero header. All icons come from Lucide (CDN: `unpkg.com/lucide@latest`), no emoji in the HTML.\n\n### CSS Class Reference\n\n| V2 Class | Purpose | Notes |\n|----------|---------|-------|\n| `.container` | Main content wrapper | `max-width: 960px` |\n| `.hero` | Purple gradient header | Contains `.book-tag`, `h1`, `.subtitle`, `.stats-row` |\n| `.hero-nav` | Top-right nav buttons | Links to index + bilingual page |\n| `.book-tag` | Source tag (e.g. \"剑6 · Test 1 · Passage 1\") | Inside `.hero` |\n| `.stats-row` > `.stat-item` | Score stats in hero | `.stat-value` + `.stat-label` |\n| `.time-badge` | Time spent badge | Inside `.subtitle` |\n| `.card` | Generic content card | White bg, rounded corners, shadow |\n| `.card-title` | Card header with icon | `.icon-box` + text |\n| `.status-chip.good` | Progress highlight | Green icon, success theme |\n| `.status-chip.warn` | Alert / core problem | Amber icon, warning theme |\n| `.error-item` | Error analysis card | Red left border, contains sub-components |\n| `.q-header` | Question header row | `.q-num` + `.badge` tags |\n| `.badge-fill` | Blue info badge | Question type tag |\n| `.badge-type` | Gray badge | Sub-type tag |\n| `.answer-compare` | Answer comparison row | `.ans-box.mine` + `.ans-box.correct` |\n| `.quote-block` | Passage quote | Gray bg, `.quote-label` header |\n| `.analysis-block` | Error cause analysis | `.section-label` + `<ul>` |\n| `.lesson-box` | Lesson learned | Purple-tinted bg |\n| `.data-table` | Data tables (vocab, synonyms) | Dark header (`#1e1b4b`), rounded |\n| `.overview-table` | Answer overview table | Accent-colored header |\n| `.problem-table` | Problem summary table | Red header |\n| `.freq-stars` | IELTS frequency stars | Lucide `<i data-lucide=\"star\">` with `.empty` class |\n| `.takeaway` | Action items card | Purple gradient bg, white text |\n| `.result-correct` | Correct answer indicator | Green text + check icon |\n| `.result-wrong` | Wrong answer indicator | Red text + x icon |\n\n### Key CSS Variables\n\n```css\n:root {\n  --bg: #f0f2f5;        /* Page background */\n  --card: #ffffff;       /* Card background */\n  --text: #1d1d1f;       /* Primary text */\n  --text-secondary: #6b7280;  /* Secondary text */\n  --accent: #4f46e5;     /* Brand purple */\n  --accent-light: #eef2ff;    /* Light purple bg */\n  --success: #059669;    /* Green (correct) */\n  --danger: #dc2626;     /* Red (wrong) */\n  --warning: #d97706;    /* Amber (alert) */\n  --info: #2563eb;       /* Blue (info) */\n  --border: #e5e7eb;     /* Border color */\n  --radius: 16px;        /* Card radius */\n  --radius-sm: 10px;     /* Small radius */\n}\n```\n\n### Icon Usage\n\nAll icons use Lucide SVG via `<i data-lucide=\"icon-name\"></i>`. Common icons:\n- `home` — Index link\n- `book-open` — Bilingual page link / passage quote\n- `clock` — Time spent\n- `trending-up` — Progress highlight\n- `alert-triangle` — Core problem alert\n- `x-circle` — Error section header\n- `x` — Wrong answer\n- `check` — Correct answer\n- `brain` — Error analysis\n- `lightbulb` — Lesson learned\n- `repeat` — Synonym section\n- `book-marked` — Vocabulary section\n- `alert-circle` — Problem summary\n- `zap` — Action items\n- `star` — IELTS frequency rating (`.freq-stars`)\n\n## Section-by-Section Guidelines\n\n### Hero Header\n- Purple gradient with `.book-tag`, title, subtitle with time badge\n- `.stats-row` shows score breakdown (总分 / 填空 / 判断 / 匹配)\n- `.hero-nav` top-right with links to index and bilingual page\n\n### Progress & Alert Chips\n- `.status-chip.good` — Always find at least 1 positive point, even in a bad score\n- `.status-chip.warn` — ONE sentence identifying the biggest scoring pattern\n- Be specific: \"T/F/NG 前 4 道全对\" is good; \"有进步\" is bad\n- Bad example: \"阅读理解能力有待提升\" ← too vague\n- Good example: \"3道判断题全错，均为 NG 误判为 FALSE——没区分「没提到」和「相反」\" ← specific and actionable\n\n### Error Analysis Blocks (`.error-item`)\n- `.q-header` with question number and type badges\n- `.answer-compare` showing user's wrong answer vs correct answer\n- `.quote-block` with passage quote and location label\n- `.analysis-block` with error cause bullets\n- `.lesson-box` with single-sentence takeaway\n- Error cause should reference the error taxonomy category\n\n### Correct Answer Brief Analysis\nFor correct answers on non-trivial questions (especially T/F/NG), include within the answer overview table or as a brief note. Keep to 2-3 lines showing the synonym mapping. Purpose: reinforce synonym recognition.\n\n### Synonym Table (`.data-table`)\n- Only include synonyms relevant to the questions (not every synonym in the passage)\n- Columns: 原文表达 | 题目表达 | 出处\n- Include the question number for cross-reference\n\n### Vocabulary Table (`.data-table`)\n- Include phonetic transcription (IPA) after the word\n- Part of speech before the definition\n- IELTS frequency rating is mandatory — use `.freq-stars` with Lucide star icons\n- \"真题出现\" column tracks which real tests the word has appeared in\n- Skip low-frequency specialist terms unless they caused an error\n\n### Problem Summary (`.problem-table`)\n- Red header table\n- Columns: 问题类型 | 具体表现 | 对应错题 | 改进方法\n\n### Takeaway Card (`.takeaway`)\n- Purple gradient background, white text\n- Numbered action items with `<strong>` in gold (`#fde68a`)\n- Include synonym additions as `<code>` items\n\n### Fill-in-the-blank Readback Checklist\nWhen fill-in errors exist, include as a `.status-chip.warn`:\n1. 语法检查 — 放回去读一遍\n2. 词性检查 — 空格前后决定词性\n3. 语义检查 — 答案和题目主题匹配\n4. 字数检查 — 不超过限制\n\n### Per-question-type Progress Trend\nWhen 3+ passages of the same question type exist, include a trend table inside a `.status-chip.good`:\n- Bold the current passage row\n- Add ↑/↑↑/↓ indicators\n- After the table, 2-3 sentences of specific analysis\n\n### Test Scorecard (Full Test)\n- Generated when user completes all 3 passages\n- Use `.data-table` format\n- Format: P1/P2/P3 scores, 总计/40, 总用时, 雅思分数\n- Band score from `references/score-band-table.md`\n\n### Cumulative Progress Table\n- Generated when 2+ full tests exist\n- Rows ordered chronologically\n- After the table: accuracy trend, speed analysis, strategy advice, per-passage pattern\n\n## Naming Convention\n\n### Review notes\n`剑X-TestX-PassageX-TopicKeyword复盘.html`\n\nExamples:\n- `剑4-Test3-Passage1-街头青年信贷复盘.html`\n- `剑6-Test1-Passage1-澳洲体育成功复盘.html`\n\n### Bilingual pages\n`剑X-TestX-PassageX-TopicKeyword双语对照.html`\n\nExamples:\n- `剑5-Test4-Passage3-光对动植物影响双语对照.html`\n- `剑6-Test1-Passage1-澳洲体育成功双语对照.html`\n\n## Formatting Rules\n\n- Use the V2 CSS classes documented above (NOT the deprecated V1 classes)\n- Icons use Lucide SVG (`<i data-lucide=\"...\"></i>`), not emoji\n- Tables use `.data-table`, `.overview-table`, or `.problem-table` styling\n- Keep `break-inside: avoid` on cards and error items for clean PDF output\n- All pages load Lucide from CDN at the end of `<body>`:\n  ```html\n  <script src=\"https://unpkg.com/lucide@latest\"></script>\n  <script>lucide.createIcons();</script>\n  ```\n\n### Deprecated V1 Classes (DO NOT USE)\n\nThese classes belong to the old V1 template and should NOT appear in new reviews:\n\n| Deprecated Class | V2 Replacement |\n|-----------------|----------------|\n| `.correct` | `.result-correct` |\n| `.wrong` | `.result-wrong` |\n| `.tag-yes` / `.tag-no` / `.tag-ng` | `.badge` with appropriate styling |\n| `.alert-box` | `.status-chip.warn` |\n| `.good-box` | `.status-chip.good` |\n| `h1/h2/h3` section headers | `.card-title` with `.icon-box` |\n| `blockquote` for quotes | `.quote-block` with `.quote-label` |\n| `max-width: 800px` | `max-width: 960px` via `.container` |\n| `#4A90D9` hardcoded blue | `var(--accent)` CSS variable |\n\nFile v5.5.1:references/score-band-table.md\n\n# IELTS Academic Reading: Score-to-Band Conversion Table\n\nThis table maps raw scores (number of correct answers out of 40) to IELTS band scores for the **Academic** reading module.\n\n> **Source**: Based on publicly available IELTS scoring data and Cambridge official practice test score converters. Actual band scores may vary slightly between test versions.\n\n## Conversion Table\n\n| Raw Score (/40) | Band Score |\n|-----------------|------------|\n| 39-40           | 9.0        |\n| 37-38           | 8.5        |\n| 35-36           | 8.0        |\n| 33-34           | 7.5        |\n| 30-32           | 7.0        |\n| 27-29           | 6.5        |\n| 23-26           | 6.0        |\n| 19-22           | 5.5        |\n| 15-18           | 5.0        |\n| 13-14           | 4.5        |\n| 10-12           | 4.0        |\n| 8-9             | 3.5        |\n| 6-7             | 3.0        |\n| 4-5             | 2.5        |\n| 2-3             | 2.0        |\n| 1               | 1.0        |\n| 0               | 0.0        |\n\n## How to Use\n\n1. Sum the user's correct answers across all 3 passages (total out of 40)\n2. Look up the raw score in the table above\n3. If the score falls on the boundary between two bands (e.g., 29 could be 6.5, 30 could be 7.0), show as a range: `6.5-7.0`\n4. Always specify this is an **estimate** — actual IELTS scoring uses a more complex algorithm\n\n## Boundary Scores (Important)\n\nThese are the key thresholds users care about:\n\n| Target Band | Minimum Raw Score | Meaning |\n|-------------|-------------------|---------|\n| 5.0         | 15                | Basic competence |\n| 5.5         | 19                | Common university minimum |\n| 6.0         | 23                | Standard university requirement |\n| 6.5         | 27                | Competitive university requirement |\n| 7.0         | 30                | Top university / immigration threshold |\n| 7.5         | 33                | Excellence benchmark |\n| 8.0         | 35                | Near-native proficiency |\n\n## Notes\n\n- This conversion is for **Academic Reading only** (General Training has a different scale)\n- Cambridge practice tests tend to be slightly easier than the real exam\n- Use this for progress tracking, not as a guarantee of actual test performance\n- Encourage users who are close to a boundary (within 2-3 marks) — small improvements yield band jumps\n\nFile v5.5.1:skill-card.md\n\n## Description: <br>\nIELTS Reading passage review, scoring, and progress tracking skill. Generates structured review data (JSON) and deploys to tuyaya.online via saveReview API. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[dengjiawei1226](https://clawhub.ai/user/dengjiawei1226) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nIELTS learners and tutors use this skill to turn reading passage attempts, screenshots, answer lists, and legacy notes into structured review records with scoring, error analysis, vocabulary, synonym tracking, and progress updates. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The security evidence reports automatic installed-code updates. <br>\nMitigation: Review or disable the auto-update hook before installation, and update manually after inspecting release contents. <br>\nRisk: The security evidence reports long-lived account tokens stored in shell startup files. <br>\nMitigation: Avoid shell-profile token persistence where possible, restrict token access on shared machines, and rotate tokens after testing or if exposure is suspected. <br>\nRisk: The security evidence reports broad folder discovery for legacy review imports. <br>\nMitigation: Use a user-selected import folder and review candidate files before allowing batch conversion or upload. <br>\nRisk: The skill can sync review data to tuyaya.online. <br>\nMitigation: Confirm the target account and review JSON contents before upload, especially when working with private study notes or screenshots. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/dengjiawei1226/ielts-reading-review) <br>\n- [Publisher profile](https://clawhub.ai/user/dengjiawei1226) <br>\n- [Client Mode Onboarding](references/CLIENT_MODE_ONBOARDING.md) <br>\n- [Error Taxonomy](references/error-taxonomy.md) <br>\n- [Score Band Table](references/score-band-table.md) <br>\n- [538 Keywords Guide](references/538-keywords-guide.md) <br>\n- [Review Style Guide](references/review-style-guide.md) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance] <br>\n**Output Format:** [Markdown guidance with JSON review data, shell commands, and configuration instructions] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [May create local JSON review files and invoke tuyaya.online API workflows when configured.] <br>\n\n## Skill Version(s): <br>\n5.5.1 (source: evidence.release.version and target metadata; artifact/_meta.json reports 5.4.2) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v5.5.1:hooks/hooks.json\n\n{\n  \"description\": \"IELTS Reading Review Skill hooks — 复盘触发词自动检测版本更新\",\n  \"hooks\": {\n    \"UserPromptSubmit\": [\n      {\n        \"name\": \"ielts-skill-version-check\",\n        \"matcher\": \"复盘|雅思阅读|阅读错题|IELTS|ielts-reading-review|帮我复盘|错题分析|阅读分析|剑[0-9]|剑桥[0-9]\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"bash \\\"${CODEBUDDY_SKILL_ROOT:-$HOME/.workbuddy/skills/ielts-reading-review}/hooks/auto-update.sh\\\"\",\n            \"timeout\": 30\n          }\n        ]\n      }\n    ]\n  }\n}\n\nFile v5.5.1:stats-worker/wrangler.toml\n\nname = \"ielts-skill-stats\"\nmain = \"worker.js\"\ncompatibility_date = \"2026-03-30\"\n\n# KV Namespace 绑定（部署前需先创建）\n# 运行: wrangler kv namespace create STATS\n# 然后把返回的 id 填到下面\n[[kv_namespaces]]\nbinding = \"STATS\"\nid = \"TO_BE_FILLED_AFTER_CREATION\"\n\nArchive v5.5.0: 20 files, 63240 bytes\n\nFiles: _meta.json (139b), assets/bilingual-template.html (3858b), assets/review-template.html (18589b), hooks/auto-update.sh (1507b), hooks/hooks.json (589b), README.md (10404b), references/538-keywords-guide.md (2186b), references/CLIENT_MODE_ONBOARDING.md (3804b), references/error-taxonomy.md (12187b), references/review-style-guide.md (8450b), references/score-band-table.md (2357b), scripts/check-update.js (5674b), scripts/generate-pdf.js (2416b), scripts/scan-legacy-reviews.js (10347b), scripts/setup-client-mode.sh (8421b), skill-card.md (3212b), SKILL.md (43315b), stats-worker/deploy.sh (2013b), stats-worker/worker.js (5286b), stats-worker/wrangler.toml (283b)\n\nFile v5.5.0:SKILL.md\n\n---\nname: ielts-reading-review\ndescription: \"IELTS Reading passage review, scoring, and progress tracking skill. Generates structured review data (JSON) and deploys to tuyaya.online via saveReview API. The server's review.html template renders JSON into unified pages. No standalone HTML generation needed. Supports batch import of legacy reviews with auto-discovery of review folders. Trigger phrases: 雅思复盘, 帮我复盘阅读, IELTS reading review, 分析错题, 阅读错题分析, 成绩单, 打分, 统计, 进步趋势, 批量导入历史复盘, 历史笔记转 JSON, 把文件夹里的复盘都生成 JSON, 扫一下我电脑里的复盘, 帮我找出所有历史笔记, 自动发现复盘, score, band, progress, batch import, auto scan.\"\n---\n\n# IELTS Reading Review Skill\n\n## Purpose\n\n帮用户把雅思阅读做题结果变成结构化数据（JSON），通过 saveReview API 入库后由后端 review.html 模板统一渲染页面。\n\n## 🔴🔴🔴 最高铁律 (v5.5.0 — Cannot Be Skipped)\n\n**只要主人在对话里发了雅思阅读题（截图 / 文字答案 / 错题列表 / 任何阅读相关材料），就必须一气呵成跑完以下闭环，不允许中途停在文字分析阶段：**\n\n```\n读截图 → 错题确认 → 写错题分析 → ★生成 v4.0 JSON★ → ★saveReview/upload 入库★ → ★getReviews 回查 ✅★ → 汇报线上链接\n```\n\n**判定\"复盘完成\"的唯一标准 = `getReviews` 回查显示该篇已入库（不是\"我写完文字分析了\"）。**\n\n**绝对禁止的\"假完成\"模式（历史血泪）：**\n- ❌ 写完错题分析就交卷，不生成 JSON → 主人在 tuyaya.online 看不到记录\n- ❌ 生成 JSON 但忘了 saveReview / upload.js → 文件部署 ≠ 数据入库\n- ❌ 调了 saveReview 但没 getReviews 回查 → API 静默失败也不知道\n- ❌ 等主人催\"怎么没上传\"才补救 → 这就是失败\n\n**本铁律覆盖所有其他流程**。即使主人只说\"帮我看看这题对不对\"\"分析这道错题\"\"这套该几分\"，**只要内容是雅思阅读，就走完整闭环**。\n\n> 历史教训（2026-05-22）：剑8 T3P1+T3P2 复盘只在聊天里写了文字分析没入库，主人在 dashboard 看不到，22:49 提醒后才补救。**这种事再也不能发生**。\n\n## Architecture (v5.5.0 — Locked-in Closed Loop)\n\n**⚠️ v5.5.0 变更**（2026-06-01）：选择题错题新增 `rejectedOptions[]` 字段，在 review.html 中以红色边框卡片渲染\"为什么不选\"区域，逐个排除错误选项。\n\n**⚠️ v5.4.2 最重大变更**（2026-05-22）：将\"必须入库\"提升为最高铁律。SKILL.md 顶部新增「最高铁律」段，加入 Step 8 Final Gate 强制 checklist——任何复盘任务，未通过 `getReviews` 回查 ✅ 不允许结束，不允许只交付文字分析。\n\n**⚠️ v5.1 新增三道防线**（防 saveReview 漏调 / 本地副本陈旧）：\n1. **发布脚本自动同步本地副本**：publish-clawhub.sh 跑完后自动 `clawhub install --force` 到 `~/.workbuddy/skills/`\n2. **Step 7g 强制入库回归验证**：调 saveReview 后必须再用 getReviews 回查确认入库，**部署 ≠ 入库**\n3. **Step 0 强制展示版本横幅**：每次激活时输出本地+远程版本号，落后必告警\n\n**⚠️ v5.0 重大简化**：服务端已预置 C4-C20 全量 answer-key（204条 reading）+ bilingual_data（100条核心双语），**复盘流程不再需要更新这两个文件**，部署清单大幅缩减。\n\n**⚠️ 不再生成复盘 HTML！** 后端 `review.html` 模板页统一渲染 JSON，单独生成的 HTML 完全无用。\n\n产出物：\n1. **结构化 JSON（v4.0）** — 成绩、错题、词汇、同义替换的全量数据。通过 saveReview API 入库后，`review.html?file=xxx.json` 在线渲染\n\n> **v5.1 变更（2026-05-11 晚）**：三道防线避免再犯 saveReview 漏调 + 本地副本不更新的坑。\n\n> **v5.0 变更（2026-05-11）**：服务端预置 C4-C20 全量 answer-key + bilingual_data，复盘流程不再需要本地维护这两个文件。仅当复盘 C20 之后的新书才需要扩展。部署清单从 5 个文件缩减到 4 个（仅 JSON + 词汇相关）。\n\n> **v4.0 变更**：不再生成复盘 HTML。后端 review.html 模板页统一渲染 JSON，单独生成 HTML 无用。复盘只需 JSON + saveReview API 入库。\n\n> **v3.9.1 新增**：Step 0 自动版本检查（scripts/check-update.js），每次激活时比对本地与 ClawHub 版本。\n\n> **v3.9.0 新增**：词库覆盖校验（dict_full.json 缺词 = 词卡展开不工作）、saveReview API 入库步骤、answers[] 字段名规范、线上词卡验证步骤。\n\n## When to Activate\n\n- 用户发做题截图/答案，提到\"复盘\"\"错题分析\"\"阅读复盘\"\n- 用户问成绩、分数、进步趋势\n- 用户要生成复盘笔记或 PDF\n\n## Step 0a: 运行模式检测 (Auto — Run on Every Activation)\n\n**第一件事**：判断当前是「作者模式」还是「客户端模式」。两种模式行为完全不同，绝不能搞错。\n\n```bash\n# 模式判定逻辑（执行下列检测）：\ntest -f ~/.ssh/workbuddy.pem && grep -q \"openclaw-tunnel\" ~/.ssh/config 2>/dev/null && echo \"作者机\" || echo \"客户端机\"\n```\n\n| 信号 | 模式 | 行为 |\n|---|---|---|\n| 检测到 `~/.ssh/workbuddy.pem` + `openclaw-tunnel` SSH 别名 | **作者模式** | Step 7 走完整 SSH 部署链路（gzip 流、cat 管道、systemctl restart） |\n| 找不到上述凭据，但有 `IELTS_USER_TOKEN` 环境变量 | **客户端模式** | Step 7 跳过所有 SSH 操作，只走 HTTPS batchImport 入库 |\n| 都没有 | **未配置客户端模式** | 提示用户先配 `IELTS_USER_TOKEN`（详见客户端 onboarding 章节），然后切到客户端模式 |\n\n**模式横幅必须输出**（每次激活时）：\n\n```\n🎯 IELTS Reading Review · vX.Y.Z\n🔐 运行模式：作者模式 / 客户端模式\n👤 token 主体：dengjiawei / lishuzhuo / (匿名)\n```\n\n**作者模式与客户端模式的关键差异**（必读）：\n\n| 步骤 | 作者模式 | 客户端模式 |\n|---|---|---|\n| Step 7a 词库覆盖校验 | ✅ 必跑（要部署 dict_full.json） | ⏭️ 跳过（词库由作者维护，客户端无写权限） |\n| Step 7b 部署 site/reviews/ JSON | ✅ SCP 到服务器 | ⏭️ 跳过（batchImport 已写入数据库） |\n| Step 7b 部署 dict_full.json + synonym_data.json | ✅ gzip 流推送 | ⏭️ 跳过 |\n| Step 7c saveReview API | ✅ ssh + localhost:3100 | ⏭️ 改用 batchImport（HTTPS + token） |\n| Step 7d 后端代码部署 | ✅ 必要时执行 | 🚫 严禁触碰 |\n| Step 7e 后端重启 | ✅ systemctl restart | 🚫 严禁触碰 |\n| Step 7g 入库回查 | ✅ getReviews 校验 | ✅ getReviews 校验（HTTPS） |\n| 本地保存 JSON | ✅ `site/reviews/` | ✅ 用户自选目录（如 `~/Documents/雅思复盘/`） |\n\n> **客户端模式下绝对禁止**：执行 `ssh openclaw-tunnel`、`scp`、`gzip -c | ssh`、`systemctl restart`、修改 `/var/www/ielts/` 任何文件。\n\n## Step 0b: Version Check (Auto — Run on Every Activation)\n\n**每次 Skill 被激活时，第一件事必须显式输出当前版本横幅**：\n\n```bash\nnode ~/.workbuddy/skills/ielts-reading-review/scripts/check-update.js\n```\n\n**强制行为规范**：\n1. **必须把 check-update.js 的输出原样展示给用户**（包含本地版本号 + 远程版本号），不能省略\n2. 如果输出包含 `🆕 有新版本可用` → **立即提示用户并询问是否更新**：\n   ```\n   ⚠️ ielts-reading-review 有新版本 vX.Y.Z（当前 vA.B.C），强烈建议先更新再开始复盘。\n   现在更新？\n   ```\n3. 用户同意后执行 `node ~/.workbuddy/skills/ielts-reading-review/scripts/check-update.js --auto`，等待安装完成后**让用户重新激活 Skill**（已加载的 context 不会热更）\n4. 用户拒绝更新 → 在回复开头加红字告警：`⚠️ 正在使用旧版本 vA.B.C，可能错过 v5.0+ 的简化流程`\n\n> 如果 `check-update.js` 不存在（旧版本安装），跳过版本检查继续工作。\n> **绝对禁止**：不输出版本号、隐瞒版本差距、用户没同意就开始复盘流程。\n\n## Workflow\n\n### Step 1: Collect Input\n\n确保以下信息齐全（缺什么问什么）：\n\n- **来源**：哪本书、哪套题、哪篇（如剑5 Test1 Passage2）\n- **原文**或答题上下文\n- **正确答案**\n- **用户答案**及错题\n- **🔴 用时（MUST ASK）**：做题用时（格式 `MM:SS`，如 `28:01`）。**必问项**，不能标\"可选\"——Web 端进步趋势图依赖此字段。用户若没计时，明确询问\"这套大概做了多久\"让其估算，别直接跳过\n- **可选**：翻译、自我反思\n\n### Step 1b: Screenshot Wrong Answer Protocol (CRITICAL)\n\n**用户发答题截图时必须执行 3 步**：\n\n1. **逐题读截图标记**：识别每题的对/错状态（参考下方多平台标记规则），不能跳题，不能用自己的判断代替截图标记\n2. **先报错题清单等确认**：输出\"根据截图，错题为 QX/QY/QZ（共N道），请确认\"，**确认后才能写分析**\n3. **截图标记是唯一真相**：截图 vs 自己判断冲突时，信截图\n\n**禁止**：跳过确认直接写分析、用 answer comparison 覆盖截图标记。\n\n#### 多平台截图标记识别规则\n\n不同 App/平台的答案标记方式各不相同，AI 必须能识别以下所有变体：\n\n| 平台/场景 | 正确标记 | 错误标记 | 额外特征 |\n|-----------|---------|---------|---------|\n| 官方答题卡手批 | 绿色/✓ | 红色/✗ | 手写批注 |\n| **雅思哥 (IELTSBro)** | 绿色圆圈/✓/对号 | 红色圆圈/✗/叉号 | 界面有\"答案解析\"按钮；题号左侧有状态图标；底部显示得分统计（如 8/13）；可能同时显示\"你的答案\"和\"正确答案\"两列 |\n| 雅思哥成绩单复制文本 | 格式可能为：`1. D ✓` 或 `Q1: D (正确)` | `2. A ✗ → 正确: C` 或 `Q2: A (错误，正确答案: C)` | 复制文本可能包含：题号、用户答案、对错标记、正确答案 |\n| 小站雅思 | 蓝色/✓ | 橙色/✗ | 卡片式布局 |\n| 新东方雅思 | 绿色背景 | 红色背景 | 答案对比表格 |\n| 剑桥官方 CBT | 显示最终得分 | — | 不逐题标记 |\n| 其他 App（通用） | ✓/✔/☑/✅/绿色/蓝色 | ✗/✘/☒/❌/红色/橙色 | — |\n\n**识别策略（按优先级）**：\n\n1. **先找得分统计**：截图中如果有 \"8/13\"、\"得分：8\"、\"Score: 8/13\" 等信息，先记下总分\n2. **再找逐题标记**：逐题看状态图标/颜色/符号，判断每题对错\n3. **提取用户答案**：如果截图同时显示了用户答案和正确答案，直接记录两列数据\n4. **处理模糊情况**：如果某题标记看不清楚，输出 \"Q7 标记不确定（看起来像 ✓），请确认\"\n5. **利用 answer-key 交叉验证**：识别出来源（如 剑5 Test1）后，从 `site/answer-key.json` 读取正确答案，可辅助验证截图识别结果是否合理（但截图仍是第一真相）\n\n**🔴 当截图来自第三方 App 时的特殊处理**：\n\n- **不要假设标记规则**——不同 App 版本可能改 UI，先观察截图整体布局再判断哪个是\"对\"哪个是\"错\"\n- **看图例/得分摘要**——很多 App 顶部或底部有总分（如 8/13），用它来验证你逐题识别的正确率是否对得上\n- **如果实在识别不了**——直接告诉用户：\"这张截图的标记方式我不太确定，能告诉我哪些题错了吗？或者告诉我你用的是什么 App？\"\n\n#### 雅思哥复制文本解析规则\n\n用户可能直接从雅思哥 App 复制答案记录粘贴过来，常见格式：\n\n```\n# 格式 A：逐题结果（最常见）\n1. TRUE ✓\n2. FALSE ✗ (正确答案: NOT GIVEN)\n3. NOT GIVEN ✓\n4. B ✗ (正确答案: D)\n...\n\n# 格式 B：成绩概要\nCambridge 5 Test 1 Reading Passage 1\n得分：10/13\n错题：Q2, Q7, Q11\n\n# 格式 C：答案对照表\n题号 | 我的答案 | 正确答案 | 结果\n1    | TRUE     | TRUE     | ✓\n2    | FALSE    | NG       | ✗\n...\n```\n\n**解析要点**：\n1. 先识别来源（哪套题哪篇）——从标题/文件名/用户说明中提取\n2. 从文本中提取每题的：用户答案 + 对错状态 + 正确答案（如果有）\n3. 如果复制文本没有正确答案，从 `site/answer-key.json` 补充\n4. 格式不在上述三种之内 → 尽力解析，解析不了就问用户\n\n### Step 2: Generate Review Data JSON (v4.0)\n\n**⚠️ 不再生成复盘 HTML！** 后端 `review.html` 模板页统一渲染 JSON，单独生成 HTML 无用。\n\n直接生成结构化 JSON 文件，供 saveReview API 入库 + 后端 review.html 模板渲染。\n\n**输出文件命名规则**：`剑X-TestX-PassageX-中文主题复盘.json`\n\n示例：\n- JSON: `剑5-Test1-Passage2-鲸鱼感官复盘.json`\n- `source.titleCN`: `\"鲸鱼感官\"`\n\n> **命名说明**：文件名使用中文标题（`source.titleCN`），方便用户在文件管理器中一眼识别内容。Web 端导入时通过 JSON 内的 `source.book/test/passage` 识别篇目，不依赖文件名。\n\n**🔴 timing 字段必须填充**：\n- `minutes`：数值型分钟（支持小数，如 `28.0` / `35.4`）\n- `formatted`：`\"MM:SS\"` 字符串（如 `\"28:01\"`）\n- MM:SS → minutes 换算：`分钟 + 秒/60`，保留 1 位小数\n- 用户实在给不出用时，才能置 `null`，但必须在回复里提醒\"缺用时，进步图将缺一个点\"\n\n```json\n{\n  \"version\": \"4.0.0\",\n  \"generatedAt\": \"2026-04-28T10:00:00.000Z\",\n  \"source\": {\n    \"book\": 7,\n    \"test\": 1,\n    \"passage\": 3,\n    \"title\": \"English Title\",\n    \"titleCN\": \"中文标题\"\n  },\n  \"score\": {\n    \"correct\": 9,\n    \"total\": 14,\n    \"band\": \"6.0\",\n    \"breakdown\": {\n      \"fillBlank\": { \"correct\": 4, \"total\": 6 },\n      \"tfng\": { \"correct\": 3, \"total\": 4 },\n      \"matching\": { \"correct\": 2, \"total\": 4 }\n    }\n  },\n  \"timing\": {\n    \"minutes\": 25,\n    \"formatted\": \"25:00\"\n  },\n  \"date\": \"2026-04-28\",\n  \"progressNote\": \"简短进步总评（如'比上次提升2分'）\",\n  \"alertNote\": \"核心告警信息（如'Summary填空全军覆没'，可选）\",\n  \"answers\": [\n    { \"q\": 1, \"my\": \"TRUE\", \"correct\": \"TRUE\", \"result\": \"correct\" },\n    { \"q\": 2, \"my\": \"FALSE\", \"correct\": \"NOT GIVEN\", \"result\": \"wrong\" }\n  ],\n  \"wrongQuestions\": [\n    {\n      \"q\": 3,\n      \"type\": \"tfng\",\n      \"badge\": \"TFNG\",\n      \"myAnswer\": \"TRUE\",\n      \"correctAnswer\": \"NOT GIVEN\",\n      \"errorCategory\": \"ng-false-confusion\",\n      \"analysis\": \"错因分析文字\",\n      \"lesson\": \"教训一句话\",\n      \"quote\": \"原文引用（英文）\",\n      \"quoteRef\": \"Para B, Line 3\",\n      \"analysisPoints\": [\"分析要点1\", \"分析要点2\"],\n      \"rejectedOptions\": [\n        { \"option\": \"A\", \"reason\": \"原文未提及该关系，属于无中生有\" },\n        { \"option\": \"C\", \"reason\": \"与原文事实矛盾，原文说的是...\" },\n        { \"option\": \"D\", \"reason\": \"范围扩大/信息不匹配\" }\n      ]\n    }\n  ],\n  \"actionItems\": [\n    \"下次做 TFNG 前必须标注否定词\",\n    \"Summary 填空必须三步走\"\n  ],\n  \"synonyms\": [\n    {\n      \"original\": \"原文表达\",\n      \"replacement\": \"题目表达\",\n      \"meaning\": \"中文释义\",\n      \"questionRef\": \"Q3\"\n    }\n  ],\n  \"vocabulary\": [\n    {\n      \"word\": \"exemplify\",\n      \"phonetic\": \"/ɪɡˈzemplɪfaɪ/\",\n      \"pos\": \"v.\",\n      \"definition\": \"举例说明\",\n      \"ieltsFreq\": 3,\n      \"source\": \"538 #42\",\n      \"appearance\": \"剑7T1P3\"\n    }\n  ],\n  \"problems\": [\n    {\n      \"type\": \"同义替换识别失败\",\n      \"detail\": \"具体表现\",\n      \"questions\": \"Q3, Q7\",\n      \"improvement\": \"改进方法\"\n    }\n  ]\n}\n```\n\n**v4.0 相对 v3.0 新增字段**（均可选，v3.0 JSON 仍能被模板页渲染）：\n- `progressNote`：进步总评\n- `alertNote`：告警信息\n- `answers[]`：全部答案对照表（含 result: correct/wrong/skipped）\n- `actionItems[]`：行动清单\n- `wrongQuestions[].badge`：**错误分类**简写标签（如 \"NG/FALSE混淆\"、\"过度推理选TRUE\"、\"Summary填空定位错误\"），与 `type`（题型）区分开\n- `wrongQuestions[].quote` / `quoteRef`：原文引用 + 定位\n- `wrongQuestions[].analysisPoints[]`：分析要点列表\n- `wrongQuestions[].rejectedOptions[]`：*\n\nArchive v5.4.2: 20 files, 62944 bytes\n\nFiles: assets/bilingual-template.html (3858b), assets/review-template.html (18589b), hooks/auto-update.sh (1507b), hooks/hooks.json (589b), README.md (10404b), references/538-keywords-guide.md (2186b), references/CLIENT_MODE_ONBOARDING.md (3804b), references/error-taxonomy.md (12187b), references/review-style-guide.md (8450b), references/score-band-table.md (2357b), scripts/check-update.js (5674b), scripts/generate-pdf.js (2416b), scripts/scan-legacy-reviews.js (10347b), scripts/setup-client-mode.sh (8421b), skill-card.md (3346b), SKILL.md (42478b), stats-worker/deploy.sh (2013b), stats-worker/worker.js (5286b), stats-worker/wrangler.toml (283b), _meta.json (139b)\n\nArchive v5.4.1: 19 files, 59729 bytes\n\nFiles: assets/bilingual-template.html (3858b), assets/review-template.html (18589b), hooks/auto-update.sh (1507b), hooks/hooks.json (589b), README.md (10404b), references/538-keywords-guide.md (2186b), references/CLIENT_MODE_ONBOARDING.md (3804b), references/error-taxonomy.md (12187b), references/review-style-guide.md (8450b), references/score-band-table.md (2357b), scripts/check-update.js (5674b), scripts/generate-pdf.js (2416b), scripts/scan-legacy-reviews.js (10347b), scripts/setup-client-mode.sh (8421b), SKILL.md (38628b), stats-worker/deploy.sh (2013b), stats-worker/worker.js (5286b), stats-worker/wrangler.toml (283b), _meta.json (139b)\n\nArchive v5.4.0: 19 files, 58853 bytes\n\nFiles: assets/bilingual-template.html (3858b), assets/review-template.html (18589b), hooks/auto-update.sh (1507b), hooks/hooks.json (589b), README.md (8827b), references/538-keywords-guide.md (2186b), references/CLIENT_MODE_ONBOARDING.md (3804b), references/error-taxonomy.md (12187b), references/review-style-guide.md (8450b), references/score-band-table.md (2357b), scripts/check-update.js (5674b), scripts/generate-pdf.js (2416b), scripts/scan-legacy-reviews.js (10347b), scripts/setup-client-mode.sh (8421b), SKILL.md (38628b), stats-worker/deploy.sh (2013b), stats-worker/worker.js (5286b), stats-worker/wrangler.toml (283b), _meta.json (139b)\n\nArchive v5.3.0: 19 files, 57151 bytes\n\nFiles: assets/bilingual-template.html (3858b), assets/review-template.html (18589b), hooks/auto-update.sh (1507b), hooks/hooks.json (589b), README.md (8827b), references/538-keywords-guide.md (2186b), references/CLIENT_MODE_ONBOARDING.md (3340b), references/error-taxonomy.md (12187b), references/review-style-guide.md (8450b), references/score-band-table.md (2357b), scripts/check-update.js (5674b), scripts/generate-pdf.js (2416b), scripts/scan-legacy-reviews.js (10347b), scripts/setup-client-mode.sh (4305b), SKILL.md (38628b), stats-worker/deploy.sh (2013b), stats-worker/worker.js (5286b), stats-worker/wrangler.toml (283b), _meta.json (139b)\n\nArchive v5.2.0: 17 files, 50519 bytes\n\nFiles: assets/bilingual-template.html (3858b), assets/review-template.html (18589b), hooks/auto-update.sh (1507b), hooks/hooks.json (589b), README.md (8827b), references/538-keywords-guide.md (2186b), references/error-taxonomy.md (12187b), references/review-style-guide.md (8450b), references/score-band-table.md (2357b), scripts/check-update.js (5674b), scripts/generate-pdf.js (2416b), scripts/scan-legacy-reviews.js (10347b), SKILL.md (31802b), stats-worker/deploy.sh (2013b), stats-worker/worker.js (5286b), stats-worker/wrangler.toml (283b), _meta.json (139b)\n\nArchive v5.1.1: 17 files, 48726 bytes\n\nFiles: assets/bilingual-template.html (3858b), assets/review-template.html (18589b), hooks/auto-update.sh (1507b), hooks/hooks.json (589b), README.md (8827b), references/538-keywords-guide.md (2186b), references/error-taxonomy.md (12187b), references/review-style-guide.md (8450b), references/score-band-table.md (2357b), scripts/check-update.js (5674b), scripts/generate-pdf.js (2416b), scripts/scan-legacy-reviews.js (10347b), SKILL.md (27952b), stats-worker/deploy.sh (2013b), stats-worker/worker.js (5286b), stats-worker/wrangler.toml (283b), _meta.json (139b)\n\nArchive v2.5.0: 16 files, 45770 bytes\n\nFiles: assets/bilingual-template.html (3858b), assets/review-template.html (18589b), README.md (10368b), references/538-keywords-guide.md (2186b), references/error-taxonomy.md (7757b), references/review-style-guide.md (8450b), references/score-band-table.md (2357b), scripts/batch-import.js (17723b), scripts/extract-pdf-text.py (3566b), scripts/generate-pdf.js (2407b), scripts/sync-review.sh (4213b), SKILL.md (22902b), stats-worker/deploy.sh (2013b), stats-worker/worker.js (5286b), stats-worker/wrangler.toml (283b), _meta.json (139b)","readmeExcerpt":"Skill: IELTS Reading Review 雅思阅读复盘 Owner: dengjiawei1226 Summary: IELTS Reading passage review, scoring, and progress tracking skill. Generates structured review data (JSON) and deploys to www.liuxue.online via saveReview A... Tags: latest:5.5.2 Version history: v5.5.2 | 2026-06-23T03:06:56.232Z | user v5.5.2: 域名迁移 tuyaya.online → www.liuxue.online（旧域名因 ICP 备案审核全站 403 不可用）。setup-client-mode.sh 的 API_BASE/AUTH_PAGE/lo","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"读截图 → 错题确认 → 写错题分析 → ★生成 v4.0 JSON★ → ★saveReview/upload 入库★ → ★getReviews 回查 ✅★ → 汇报线上链接"},{"language":"bash","snippet":"# 模式判定逻辑（执行下列检测）：\ntest -f ~/.ssh/workbuddy.pem && grep -q \"openclaw-tunnel\" ~/.ssh/config 2>/dev/null && echo \"作者机\" || echo \"客户端机\""},{"language":"text","snippet":"🎯 IELTS Reading Review · vX.Y.Z\n🔐 运行模式：作者模式 / 客户端模式\n👤 token 主体：dengjiawei / lishuzhuo / (匿名)"},{"language":"bash","snippet":"node ~/.workbuddy/skills/ielts-reading-review/scripts/check-update.js"},{"language":"text","snippet":"⚠️ ielts-reading-review 有新版本 vX.Y.Z（当前 vA.B.C），强烈建议先更新再开始复盘。\n   现在更新？"},{"language":"text","snippet":"# 格式 A：逐题结果（最常见）\n1. TRUE ✓\n2. FALSE ✗ (正确答案: NOT GIVEN)\n3. NOT GIVEN ✓\n4. B ✗ (正确答案: D)\n...\n\n# 格式 B：成绩概要\nCambridge 5 Test 1 Reading Passage 1\n得分：10/13\n错题：Q2, Q7, Q11\n\n# 格式 C：答案对照表\n题号 | 我的答案 | 正确答案 | 结果\n1    | TRUE     | TRUE     | ✓\n2    | FALSE    | NG       | ✗\n..."}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: ielts-reading-review\ndescription: \"IELTS Reading passage review, scoring, and progress tracking skill. Generates structured review data (JSON) and deploys to www.liuxue.online via saveReview API. The server's review.html template renders JSON into unified pages. No standalone HTML generation needed. Supports batch import of legacy reviews with auto-discovery of review folders. Trigger phrases: 雅思复盘, 帮我复盘阅读, IELTS reading review, 分析错题, 阅读错题分析, 成绩单, 打分, 统计, 进步趋势, 批量导入历史复盘, 历史笔记转 JSON, 把文件夹里的复盘都生成 JSON, 扫一下我电脑里的复盘, 帮我找出所有历史笔记, 自动发现复盘, score, band, progress, batch import, auto scan.\"\n---\n\n# IELTS Reading Review Skill\n\n## Purpose\n\n帮用户把雅思阅读做题结果变成结构化数据（JSON），通过 saveReview API 入库后由后端 review.html 模板统一渲染页面。\n\n## 🔴🔴🔴 最高铁律 (v5.5.2 — Cannot Be Skipped)\n\n**只要主人在对话里发了雅思阅读题（截图 / 文字答案 / 错题列表 / 任何阅读相关材料），就必须一气呵成跑完以下闭环，不允许中途停在文字分析阶段：**\n\n```\n读截图 → 错题确认 → 写错题分析 → ★生成 v4.0 JSON★ → ★saveReview/upload 入库★ → ★getReviews 回查 ✅★ → 汇报线上链接\n```\n\n**判定\"复盘完成\"的唯一标准 = `getReviews` 回查显示该篇已入库（不是\"我写完文字分析了\"）。**\n\n**绝对禁止的\"假完成\"模式（历史血泪）：**\n- ❌ 写完错题分析就交卷，不生成 JSON → 主人在 www.liuxue.online 看不到记录\n- ❌ 生成 JSON 但忘了 saveReview / upload.js → 文件部署 ≠ 数据入库\n- ❌ 调了 saveReview 但没 getReviews 回查 → API 静默失败也不知道\n- ❌ 等主人催\"怎么没上传\"才补救 → 这就是失败\n\n**本铁律覆盖所有其他流程**。即使主人只说\"帮我看看这题对不对\"\"分析这道错题\"\"这套该几分\"，**只要内容是雅思阅读，就走完整闭环**。\n\n> 历史教训（2026-05-22）：剑8 T3P1+T3P2 复盘只在聊天里写了文字分析没入库，主人在 dashboard 看不到，22:49 提醒后才补救。**这种事再也不能发生**。\n\n## Architecture (v5.5.2 — Locked-in Closed Loop)\n\n**⚠️ v5.5.2 变更**（2026-06-23）：**域名迁移** tuyaya.online → www.liuxue.online。旧域名因 ICP 备案审核已全站 403 不可用。所有脚本（setup-client-mode.sh 含 CORS Allow-Origin）、文档默认域名全部切到 www.liuxue.online。SSH 隧道 `ssh.tuyaya.online` 保留不变（cloudflared 隧道不经 nginx，不受影响）。\n\n**⚠️ v5.5.1 变更**（2026-06-01）：选择题和判断题错题新增 `rejectedOptions[]` 字段，在 review.html 中以红色边框卡片渲染\"为什么不选\"区域，逐个排除错误选项。\n\n**⚠️ v5.4.2 最重大变更**（2026-05-22）：将\"必须入库\"提升为最高铁律。SKILL.md 顶部新增「最高铁律」段，加入 Step 8 Final Gate 强制 checklist——任何复盘任务，未通过 `getReviews` 回查 ✅ 不允许结束，不允许只交付文字分析。\n\n**⚠️ v5.1 新增三道防线**（防 saveReview 漏调 / 本地副本陈旧）：\n1. **发布脚本自动同步本地副本**：publish-clawhub.sh 跑完后自动 `clawhub install --force` 到 `~/.workbuddy/skills/`\n2. **Step 7g 强制入库回归验证**：调 saveReview 后必须再用 getReviews 回查确认入库，**部署 ≠ 入库**\n3. **Step 0 强制展示版本横幅**：每次激活时输出本地+远程版本号，落后必告警\n\n**⚠️ v5.0 重大简化**：服务端已预置 C4-C20 全量 answer-key（204条 reading）+ bilingual_data（100条核心双语），**复盘流程不再需要更新这两个文件**，部署清单大幅缩减。\n\n**⚠️ 不再生成复盘 HTML！** 后端 `review.html` 模板页统一渲染 JSON，单独生成的 HTML 完全无用。\n\n产出物：\n1. **结构化 JSON（v4.0）** — 成绩、错题、词汇、同义替换的全量数据。通过 saveReview API 入库后，`review.html?file=xxx.json` 在线渲染\n\n> **v5.1 变更（2026-05-11 晚）**：三道防线避免再犯 saveReview 漏调 + 本地副本不更新的坑。\n\n> **v5.0 变更（2026-05-11）**：服务端预置 C4-C20 全量 answer-key + bilingual_data，复盘流程不再需要本地维护这两个文件。仅当复盘 C20 之后的新书才需要扩展。部署清单从 5 个文件缩减到 4 个（仅 JSON + 词汇相关）。\n\n> **v4.0 变更**：不再生成复盘 HTML。后端 review.html 模板页统一渲染 JSON，单独生成 HTML 无用。复盘只需 JSON + saveReview API 入库。\n\n> **v3.9.1 新增**：Step 0 自动版本检查（scripts/check-update.js），每次激活时比对本地与 ClawHub 版本。\n\n> **v3.9.0 新增**：词库覆盖校验（dict_full.json 缺词 = 词卡展开不工作）、saveReview API 入库步骤、answers[] 字段名规范、线上词卡验证步骤。\n\n## When to Activate\n\n- 用户发做题截图/答案，提到\"复盘\"\"错题"},{"path":"README.md","content":"# IELTS Reading Review 雅思阅读复盘助手\n\n> Finish a reading passage, hand it to AI, get a complete review — error analysis, synonym tracking, vocabulary tagging, and mistake pattern detection, all in one go.\n\n做完阅读题，丢给 AI，自动出复盘笔记——错题拆解、同义替换积累、考点词标注、易错模式追踪，一步到位。\n\n---\n\n## 🆕 What's New in v5.4 — OAuth 风格浏览器授权流\n\n**告别 F12 复制 token 的笨流程**——客户端模式绑定账号体验彻底重做：\n\n### 🎯 30 秒上手（替代原来 5 分钟）\n\n```bash\nbash ~/.workbuddy/skills/ielts-reading-review/scripts/setup-client-mode.sh\n```\n\n脚本自动完成 4 件事：\n\n1. **本机起临时 HTTP 服务**（随机空闲端口监听 OAuth 回调）\n2. **唤起浏览器**到 `https://www.liuxue.online/ielts/authorize.html`\n3. **页面显示 OAuth 风格卡片**：客户端名 / 本机回调地址 / 当前账号 / 权限列表 / 【拒绝】【授权】\n4. **点【授权】** → token 通过 `<img>` 请求回传本机 → 自动写入 `~/.zshrc` → 显示绑定账号名\n\n### 🔒 安全设计\n\n| 风险点 | 防护机制 |\n|---|---|\n| token 被中间人截获 | 全程仅浏览器 ↔ 本机 127.0.0.1，不走第三方 |\n| token 进 URL bar 被记录 | 用 `<img src=...?token>` GET 而非 `location.href`，不留浏览历史 |\n| CORS / Private Network 拦截 | 用图片请求绕过预检 |\n| 跨站伪造请求 | `secrets.token_urlsafe(16)` 生成 state，服务端校验 |\n| 恶意回调地址 | 授权页强制白名单：仅 `127.0.0.1 / localhost / ::1` + http |\n\n### 🪟 三系统全覆盖\n\n- macOS：`open` 命令唤起浏览器\n- Linux：`xdg-open`\n- 兜底：打印链接，用户手动复制到浏览器\n\n### 🛟 兜底模式\n\n浏览器/网络异常时：\n\n```bash\nbash setup-client-mode.sh --manual\n```\n\n回退到 F12 → Console → `localStorage.ielts_user_token` 复制粘贴的老流程。\n\n---\n\n## 🆕 What's New in v3.1 — Web Hand-off\n\n### 🌐 生成物一键上传到 Web 端\n\nv3.1 在保持纯离线生成的同时，**明确了 JSON 产出物与 Web 端的对接路径**：\n\n- 访问 https://www.liuxue.online/ielts/submit.html 切到「**上传 JSON**」Tab\n- 把 skill 生成的 `.json` 文件拖进去 → 成绩、答案、用时自动入库\n- 首页成绩矩阵、词汇本、同义替换本实时更新\n\n### 📊 Web 端新增 JSON 导入能力\n\nWeb 端 `submit.html` 新增第 4 种提交模式（粘贴文本 / PDF / 拍照 / **上传 JSON**），与 skill 的产出物严格对齐 v3.0 schema。\n\n## 🆕 What's New in v3.0 — Offline-First\n\n### 🔌 去服务器依赖，纯本地生成\n\nv3.0 重构为**纯离线模式**：\n\n- ✅ 复盘 HTML — 专业排版，浏览器直接查看\n- ✅ 复盘 PDF — 一键导出，存档分享\n- ✅ 结构化 JSON — 包含成绩、错题、词汇、同义替换等全量数据\n- 🔜 数据上传 — 后续通过 Web 端功能将 JSON 导入云系统，实现多设备同步\n\n**不再依赖任何远程 API**，AI Agent 在本地完成所有分析和生成工作。\n\n### 📋 填空回填 4 步检查\n\n每道填空题强制 4 步验证：语法 → 词性 → 语义 → 字数，杜绝低级失误。\n\n### ✅ 正确题确认 + 进步表扬\n\n- 做对的题也会简要确认，展示同义替换映射帮你强化记忆\n- 每篇开头先肯定你的进步点，保持刷题动力\n\n### 🔢 错误分类扩展到 12 类\n\n涵盖：同义替换识别失败、NG/FALSE 混淆、过度推理、填空重复题干、语法误解、选项不完全匹配、词汇缺口、粗心、词形错误、跨代/范围混淆、类别推理误判、邻近干扰词。\n\n---\n\n## 🚀 快速开始（3 步上手）\n\n### 第一步：安装 Skill\n\n```bash\n# ClawHub 安装（推荐）\nclawhub install ielts-reading-review\n\n# 或手动复制到 skills 目录\ncp -r ielts-reading-review ~/.workbuddy/skills/\n```\n\n### 第二步：做完一篇阅读题\n\n用剑桥雅思真题（Cambridge IELTS）做完一篇阅读，准备好：\n- ✅ 原文（拍照/截图/粘贴文字都行）\n- ✅ 正确答案\n- ✅ 你的答案（标出哪些做错了）\n- ⭕ 可选：翻译、用时\n\n### 第三步：发给 AI，说\"帮我复盘\"\n\n就这么简单。AI 会自动生成：\n1. **复盘 HTML** — 专业排版的复盘笔记\n2. **复盘 JSON** — 结构化数据文件，供后续导入 Web 系统\n3. **复盘 PDF**（可选）— 从 HTML 生成，便于存档\n\n---\n\n## 📖 完整使用案例\n\n> 以下是一个真实的使用过程，以剑4 Test 3 Passage 1 为例。\n\n### 你发给 AI 的内容\n\n```\n我做完了剑4 Test3 Passage1，帮我复盘。\n\n文章：Micro-Enterprise Credit for Street Youth\n用时：34:40\n得分：7/13\n\n我的答案 vs 正确答案：\nQ1: 我选D → 正确A\nQ2: 我选C → 正确D\nQ3: ✅\nQ4: ✅\nQ5: 我填 Sudan and India → 正确 Sudan\nQ6: ✅\nQ7: 我填 shoe shine → 正确 Shoe Shine Collective\nQ8-Q10: ✅\nQ11: 我选 NOT GIVEN → 正确 NO\nQ12: ✅\nQ13: 我选D → 正确A\n\n（然后把原文和翻译也贴上来）\n```\n\n### AI 自动产出\n\nAI 会在本地生成三个文件：\n\n#### 📄 复盘 HTML — `剑4-Test3-Passage1-"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7dr93fbgrvymnk8d9r9y0tws83mhrk\",\n  \"slug\": \"ielts-reading-review\",\n  \"version\": \"5.5.2\",\n  \"publishedAt\": 1782184016232\n}"},{"path":"references/538-keywords-guide.md","content":"# 538 IELTS Keywords Reference Guide\n\n## About This Resource\n\nThe 538 Keywords list comes from Liu Hongbo's \"Cambridge IELTS Reading Keywords\" (刘洪波《剑桥雅思阅读考点词真经》). It categorizes high-frequency words that appear repeatedly in IELTS Academic Reading questions.\n\n## How to Use for Vocabulary Rating\n\nWhen building the vocabulary table in a review note, look up each word against the 538 list:\n\n### Rating Scale\n\n| Rating | Category | Count | Question Appearance Rate |\n|--------|----------|-------|------------------------|\n| ⭐⭐⭐ | Category 1 | 54 words | ~90% of passages contain these |\n| ⭐⭐ | Category 2 | 171 words | ~60% of passages contain these |\n| ⭐ | Category 3 | 300+ words | Common but less predictable |\n| — | Not listed | N/A | Check COCA 5000 for general frequency |\n\n### Lookup Procedure\n\n1. Search the full 538 list (provided as `雅思阅读538考点词-刘洪波真经.txt` in the workspace) for the target word\n2. If found, note its category number and rank\n3. Record in the vocabulary table as: `⭐⭐⭐ 538考点词 #XXX` (where XXX is the rank)\n4. If not found in the 538 list, check COCA 5000 for general English frequency\n5. Words below COCA 3000 that are not in the 538 list can be marked as low-priority\n\n### COCA 5000 Supplementary Use\n\nThe COCA (Corpus of Contemporary American English) 5000 frequency list (`COCA_5000词频表.csv`) provides general English word frequency rankings. Use it to:\n\n- Determine if an unknown word is commonly used in English (not just IELTS)\n- Prioritize learning: COCA top 2000 = essential everyday English; 2000-5000 = academic/professional English\n- A word in COCA top 3000 but not in the 538 list is still worth learning for general proficiency\n\n### Cambridge Test Appearance Column\n\nThe \"真题出现\" (Cambridge Appearance) column tracks where a word has actually appeared in Cambridge IELTS tests. Format:\n\n- Single appearance: `剑4T3P2`\n- Multiple appearances: `剑4T3P2, 剑7T1P1, 剑9T2P3`\n- This column is **cumulative** — add new appearances as more passages are reviewed\n- High-frequency words appearing across multiple books indicate they are particularly important"},{"path":"references/CLIENT_MODE_ONBOARDING.md","content":"# 👩‍🎓 给老婆/外部用户：跑通整套 Skill 复盘流程\n\n这份文档教你怎么把 `ielts-reading-review` + `ielts-review-upload` 两个 Skill 跑成「客户端模式」，让 AI 帮你做完整复盘后**自动同步到你 www.liuxue.online 账号下的进度图、词汇本、错题本**。\n\n> 不是给作者本人用的——作者机直接走 SSH 部署链路。这份文档专门给**没有 openclaw-tunnel SSH 凭据**的机器准备。\n\n## 你能得到什么\n\n- ✅ 发截图给 AI → AI 自动识别错题、生成富 JSON 复盘\n- ✅ 复盘自动入库 → 网站首页进度图实时更新\n- ✅ 词汇/错题/同义替换 → 自动同步到你账号下的复习本\n- ✅ 不需要任何 SSH 知识、不需要碰服务器\n\n## 前置条件\n\n1. 已在 https://www.liuxue.online/ielts/login.html 注册账号（如 lishuzhuo）\n2. 本机装了 WorkBuddy / CodeBuddy（能用 `Skill` 工具）\n3. 装好 `ielts-reading-review` + `ielts-review-upload` 这两个 Skill\n\n## 一次性配置（30 秒搞定）\n\n```bash\nbash ~/.workbuddy/skills/ielts-reading-review/scripts/setup-client-mode.sh\n```\n\n**这是浏览器授权流（v5.4 新版）**：\n1. 脚本启动一个本地随机端口的 HTTP 服务（监听本机回调）\n2. 自动打开浏览器到 `www.liuxue.online/authorize.html`\n3. 在页面看到客户端信息卡片，点击 **「授权」**\n4. token 经浏览器以 `<img>` 请求方式回传到本机（**永远不离开你的电脑**）\n5. 脚本自动校验 + 写入 `~/.zshrc`，显示绑定的账号名\n\n> 网络/浏览器异常时可手动跑兜底模式：`bash setup-client-mode.sh --manual`\n> 这种情况下需要 F12 → Console → 输入 `localStorage.ielts_user_token` 复制 token 粘贴到终端。\n\n完成后重开终端或 `source ~/.zshrc`。\n\n**验证成功标志**：\n```bash\necho \"${IELTS_USER_TOKEN:0:20}...\"   # 应该看到 eyJ1Ijoi... 之类的前缀\n```\n\n## 日常用法\n\n直接对 AI 说：\n\n```\n复盘剑8 Test1 Passage2，错题截图：[贴图]，用时 32:15\n```\n\nAI 会自动：\n1. 检测到客户端模式\n2. 读截图识别错题（先报清单等你确认）\n3. 生成富 JSON 复盘到本地（默认 `~/Documents/雅思复盘/`）\n4. 通过 HTTPS batchImport 上传到你账号\n5. 回查 getReviews 确认入库\n6. 给你主页链接：`https://www.liuxue.online/ielts/reading.html`\n\n## 数据归属\n\n- 上传通道：`POST https://www.liuxue.online/api/ielts {action:'batchImport', token}`\n- 数据落点：主库 `ielts_reviews` 表，`username` 字段 = 你的登录账号\n- 主页效果：登录后能看到进度图、词汇本、错题本同步更新（和作者本人完全同等待遇）\n\n## 限制（客户端模式做不到的）\n\n- ❌ 不能部署复盘 JSON 文件到服务器，所以「复盘详情页」`review.html?file=...` 可能 404\n  - **绕过**：把复盘 JSON 发给作者人工部署，或继续在本地查看\n- ❌ 不能扩展词库（dict_full.json）/双语数据（bilingual_data.json）\n  - **绕过**：作者机已预置 C4-C20 全量数据，C21+ 才需要扩展\n\n但**首页进度图、词汇本、错题本完全可用**——这些数据都从数据库读，不依赖文件部署。\n\n## 出问题怎么办\n\n| 症状 | 解决 |\n|---|---|\n| `echo $IELTS_USER_TOKEN` 没输出 | `source ~/.zshrc` 或重开终端 |\n| AI 说\"token 过期\" | 重新登录 www.liuxue.online，重跑 setup-client-mode.sh |\n| 主页看不到新复盘 | 确认 AI 输出里有 `imported:1, upgraded:1`，没有就是 batchImport 没调通 |\n| AI 误走 SSH 部署 | 检查 Step 0a 模式横幅，应该是「客户端模式」，否则升级 Skill |\n\n## Token 安全\n\n- token 默认有效期 10 年\n- 写在本地 `~/.zshrc`，不要发到群里/截图给别人\n- 怀疑泄漏可以登录后端管理页面手动重置（联系作者）"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1393,"uniquenessScore":44,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T20:03:24.236Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T20:03:24.236Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T01:50:10.698Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}