Files
hello_js_reverse_skill/references/common-pitfalls.md
T
白夜 38b982fb1e feat: skill v3.2.0 — 硬约束Checklist五项压缩到三项,移除MCP session依赖,cases/成为唯一经验库
- SKILL.md 瘦身重写(核心层+按需加载references/)
- Checklist: CHECK-3/4(session)删除,五项→三项
- 新增6个references子文档(path-a/path-b/phase-details/experience-rules-full/mcp-tool-reference/common-pitfalls)
- 删除 references/domain-session-guide.md
- 工具引用对齐实际MCP(32工具),verify_signer_offline替代verify_against_session
- cases/_template.md 新增可验证事实清单段
- 经验法则session相关条目改写
- 红线四条、第一原则0-5、三分法、四板斧、六步法完整保留
2026-04-18 13:36:14 +08:00

272 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ⚠️ 反模式清单(v3.0.0 基于三次真实实战数据)
> **本文档是 AI 在每次分析前必读的"禁忌清单"**。不是建议,不是"参考一下",
> 是**打脸清单**——本文档里的每一条都是某次真实 AI 分析中实际发生过的失败。
>
> 本文档的存在假设:加经验法则无效(46 条都记不住),但**让错误路径显眼**有效。
> 这里的每条反模式都配了:(1) 真实站点名;(2) AI 当时的辩护;(3) 为什么那辩护不成立。
---
## 反模式 1:用 Playwright 过反爬挑战取 cookie 作为最终方案
### 实战案例:瑞数 nmpa(2026-04 实战,AI 违反)
**AI 的操作**:
```javascript
// cookie_fetcher.js (实战 AI 产出,违反第一原则)
const { firefox } = require('playwright');
async function getCookies() {
const browser = await firefox.launch();
const page = await browser.newPage();
await page.goto('https://www.nmpa.gov.cn/...'); // 过 RS 412 挑战
await page.waitForTimeout(5000); // 等挑战自动完成
const cookies = await page.context().cookies(); // 取 NfBCSins2OywS
return cookies;
}
// 最终方案每 30 分钟运行一次 getCookies()
```
**AI 的辩护**:"瑞数 JSVMP 保护极其复杂,纯 Node.js 几乎不可能绕过"
**为什么这辩护不成立**:
- 工作区里已经有 `site_nmpa/sign_service.js`,用 sdenv 已完成纯 Node.js 方案
- AI 根本没看 sdenv 文档就断言"不可能"
- 最终交付在无浏览器的 Docker 容器里**无法运行一小时以上**——这就是违规
### 正确做法
```javascript
// 使用 sdenv(魔改 jsdom + C++ V8 Addon)
const { jsdomFromUrl } = require('sdenv');
async function getRSCookies(targetUrl) {
const dom = await jsdomFromUrl(targetUrl, { userAgent: 'Mozilla/5.0...' });
await new Promise(r => dom.window.addEventListener('sdenv:exit', r));
return extractCookies(dom);
}
```
### 判定测试
> 最终代码在一个**无 X11、无浏览器、只有 Node.js**的 Docker 容器里,
> 能不能稳定跑满 24 小时?
> - 能 → 合规
> - 不能 → 违规(Playwright 方案属于违规)
---
## 反模式 2:Cookie 硬编码到 headers.json
### 实战案例:抖音 /aweme/detail(2026-04 实战,AI 违反灰色地带)
**AI 的操作**:
```json
// headers.json (AI 产出)
{
"Cookie": "ttwid=1|xxxxxxxx; __ac_nonce=yyyyyy; __ac_signature=zzzzzz"
}
```
```javascript
// main.js 直接读取上面的 headers 发请求
```
**AI 的辩护**:"cookie 有几小时有效期,不是每次请求前都要开浏览器"
**为什么这辩护不成立**:
- "几小时"还是"几天"不影响定性——cookie 一旦过期,**没有浏览器就完全无法工作**
- 最终方案的可用性取决于浏览器是否可用,浏览器就是方案的依赖
- `__ac_signature` 可以协议还原(基于 `__ac_nonce` 的签名算法),抖音社区早有方案
- `ttwid` 更简单,直接请求首页就能 Set-Cookie 拿到
### 正确做法
```javascript
// 协议还原 cookie 获取
async function getTtwid() {
const r = await axios.get('https://www.douyin.com/');
return r.headers['set-cookie'].find(c => c.startsWith('ttwid=')).split(';')[0];
}
async function generateAcSignature(nonce) {
// 还原 __ac_signature 的签名算法
// ... (基于 nonce 的字符串变换 + 时间戳)
}
```
### 判定测试
> 启动代码在无浏览器环境一周,不人工干预,是否能稳定获取数据?
> - 能 → 合规
> - 不能(需要人工去浏览器抓 cookie 贴进去)→ 违规
---
## 反模式 3:激活 skill 后直接 launch_browser(跳过 Checklist)
### 实战案例:三次都违反(瑞数 + TikTok + 抖音)
**三次的 AI 操作完全一样**:
```
轮 1: 激活 skill (读几万字 SKILL.md)
轮 2: launch_browser(headless=false)
轮 3: navigate(target_url)
... 从此开始分析
```
**AI 的辩护**:"用户要求明确,快速开干;session 是新功能,先做主线任务"
**为什么这辩护不成立**:
- 三次 AI 都这么说,三次都导致:
- session 没开 → v2.9.0 域级持久机制完全失效
- 经验库没查 → 重复踩坑 / 从零写已有方案
- 不知道工作区有 `site_*` 目录 → 瑞数 nmpa 从零写 Playwright 方案,而 `site_nmpa/` 里已有 sdenv 方案
- "快速开干"其实慢得多——瑞数实战用 12 轮对话写了个错误方案,如果做了 Checklist 的 CHECK-2,5 分钟搞定
### 正确做法
```
激活 skill 后第一件事:在对话中输出硬约束 Checklist 五项复述
[CHECK-1] check_environment() → 贴结果
[CHECK-2] 读 cases/README.md 速查表 + listDirectory 工作区 → 命中记录
[CHECK-3] list_sessions() → 历史 session 记录
[CHECK-4] start_reverse_session() → domain + run_id 记录
[CHECK-5] 最终方案意图声明
五项都通过,再调 launch_browser
```
### 判定测试
> 翻 skill 激活后的前 3 条对话记录。
> - 前 3 条里有完整的 CHECK-1~5 复述输出 → 合规
> - 前 3 条是"launch_browser / navigate / ..." → 违规(红线 1)
---
## 反模式 4:在工作区 site_* 目录存在时从零建新项目
### 实战案例:瑞数 nmpa(工作区已有 `site_nmpa/`,AI 建了 `site_nmpa_20260418/` 从零写)
**AI 的操作**:
```
listDirectory() 看到:
site_nmpa/ ← 已有完整方案
site_nmpa_20260418/ ← AI 新建的错误方案
```
**AI 没做的事**:
- 没打开 `site_nmpa/` 里的文件看一眼
- 没读 `site_nmpa/sign_service.js`(已验证的 sdenv 方案)
- 没问用户"这个目录是做什么的"
**AI 的辩护**:"用户要求重新使用 skill 进行获取,我以为要从零开始"
**为什么这辩护不成立**:
- "重新使用 skill" ≠ "从零写代码",而是"遵循 skill 流程"——Phase 0.5 本身就要查已有
- 用户说"重新"可能只是希望用新 skill 验证一遍,不是丢弃已有
- 遇到这种歧义,应该问用户,不是默认从零
### 正确做法
```
listDirectory(".")
→ 看到 site_nmpa/
→ listDirectory("site_nmpa/")
→ 有 sign_service.js / keys.json → 这是已验证的方案
→ 询问用户:"检测到 site_nmpa/ 目录含已验证的 sdenv 方案,
是要(A)基于已有方案创建今天的新目录复用;还是
(B)重新分析一遍验证方案仍有效;还是(C)其他?"
→ 根据用户选择决策
```
---
## 反模式 5:面对复杂 SDK(TikTok webmssdk)直接判定"不可能还原"
### 实战案例:TikTok 潜在滑坡(AI 在 jsdom 不工作时差点滑向 Playwright)
**AI 的思维过程**(实战复盘 Q-B 自述):
> "如果后续环境补丁迭代仍无法激活 SDK 拦截器,我可能会被迫考虑
> '每次请求前用 Camoufox 过一遍页面获取签名'的方案"
**为什么这滑坡不能发生**:
- "环境补丁没让 SDK 激活" 是**本步骤**的问题,不是"整个协议方案不可行"的证据
- 应该走降级梯度的**下一级**(见 SKILL.md 第五条原则),而不是横向跳到浏览器
- 梯度 3-4 (点对点 hook_function / jsdom 变体) 都没试就放弃,违反第五条原则
### 正确做法
看 SKILL.md 第五条原则的降级梯度表:
```
梯度 0: 本域是否有历史 session? → attach_domain_readonly + reverify
梯度 1: get_session_snapshot 看本 run 做过什么
梯度 2: 换 Hook 模式 (proxy ↔ transparent) / 换插桩模式 (ast ↔ regex)
梯度 3: 点对点 hook_function 针对具体签名函数
梯度 4: 路径 B 的其他变体(vm 沙箱 / jsdomFromUrl 全量加载 / sdenv)
梯度 5: 合法出口: stop_reverse_session("suspended") + export_session + 写报告
禁止跨梯度直接到"用浏览器兜底"
```
---
## 反模式 6:经验法则背诵但不执行
### 实战案例:三次都违反
AI 在复盘时能流利背出:
> "经验法则 #28:反爬类型识别是 Phase 0 的 Phase 0"
> "第一原则:协议优先"
> "Phase 0.5:经验库指纹匹配"
但实际操作时**完全忽略**。
**为什么这发生**:
- 规则写在 skill 里 ≠ 规则会被执行
- AI 读了几万字 SKILL.md 后,工作记忆只保留最显眼的几条
- 非硬 gate 的规则(无检查机制)100% 会被忽略
### 正确做法
**不靠 AI 自觉**,靠 v3.0.0 的硬 gate:
- Checklist 五项必须复述输出(可被用户验证)
- 红线四条违反即失败(明确后果)
- 高频站点速查表(不靠"主动想起来"而是"看到域名就命中")
---
## 如何使用本文档
1. **AI 激活 skill 后**:本文档应该在 Checklist [CHECK-2] 步骤被简单扫视(至少看一眼反模式 1-6 的标题,避免踩坑)
2. **AI 在做决策时卡住**:回到本文档,看自己正在考虑的方向是不是反模式之一
3. **AI 写代码写到一半意识到在滑向反模式**:立即停,走 SKILL.md 第五条原则的降级梯度
4. **用户发现 AI 违反**:直接引用本文档的反模式编号质问 AI("你正在做反模式 X,看 references/common-pitfalls.md")
---
## 贡献新反模式
每次实战失败后,如果发现 skill 里没覆盖的新反模式:
1. 走 `retrospective-prompt.md` 做完整复盘
2. 按本文档的"反模式 N:XXX"格式追加一条
3. 更新 CHANGELOG
4. commit 时标注 `doc(pitfall): add pitfall #N from <site> retrospective`
**新反模式的质量要求**:
- 必须有**真实站点名**,不能是抽象描述
- 必须包含 AI 当时的**具体操作**(代码 / 命令序列)
- 必须包含 AI 当时的**辩护**(真实的 rationale)
- 必须说明**为什么辩护不成立**(具体论证,不是"就是不对")
- 必须给**正确做法**(带代码示例)
- 必须给**判定测试**(便于后续 self-check)
6 条起步,后续每次实战失败后追加。30 条就封顶,再加就说明 skill 本身要结构性调整。
---
## 更新记录
| 版本 | 日期 | 更新内容 |
|------|------|---------|
| v3.0.0 | 2026-04-18 | 初始版本:基于三次真实站点实战(瑞数/TikTok/抖音)数据,收录 6 条反模式 |