其他
为新网站编写 OpenCLI adapter…
当需要为某个站点编写 OpenCLI adapter(或给已有站点新增命令)时,按决策树与 Runbook 从侦察、API 发现、字段解码到 verify 全流程落地。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 38/100 ×0.15
适用场景
为新网站编写 OpenCLI adapt特定
解决思路
- 调试浏览器型 adapter 时优先带上 `--trace on --keep-tab true --window foreground`:`--trace on` 每轮落 trace artifact,`summary.md` 是失败/成功复盘入口;`--keep-tab true --window foreground` 保留 tab lease 且浏览器窗口在前台,方便核对最终页面状态。
- 动手前先用 `coverage-matrix.md` 自测三个问题:数据在浏览器里看得到吗(否→先解决鉴权);数据是 HTTP/JSON/HTML 吗(否→不在范围);需要实时推送吗(是→找同数据 HTTP 接口,没有就放弃)。三个都 yes 才继续。
- 先定 strategy 再写 adapter:每次进入 Step 3/4 后、写代码前必须产出一段 strategy note(含 Strategy / Contract / Evidence),没有这段 note 不要开始写 `clis/<site>/<name>.js`。
- 按契约级别选 strategy:优先 `PUBLIC_API` / `COOKIE_API`;UI/DOM 语义稳定时不要强行升级到 `PAGE_FETCH` / `INTERCEPT`;只有公开/官方接口不可用、UI/DOM 无法表达目标数据或操作时,才承担无契约内部接口的维护成本(实测 `PAGE_FETCH` / `INTERCEPT` 的 fix 频率约为 `PUBLIC_API` 的 7-8 倍)。
- 只复用页面自己已经合法获得的数据/能力:不教破解签名、不绕验证码/风控/访问控制;遇到不可复用签名就降级到 `UI_SELECTOR` / `DOM_STATE` / `INTERCEPT`。
- Step 1:确认 `opencli doctor` 返回 "Everything looks good",否则先修桥接。
- Step 2:读站点记忆——`~/.opencli/sites/<site>/endpoints.json`、`~/.opencli/sites/<site>/notes.md`、`references/site-memory/<site>.md`;命中 endpoint + 字段后跳到第 5(endpoint 验证)+ 第 7(字段核对),不能直接跳第 9 写 adapter;memory 写入超过 30 天(看 `verified_at`)当作过期,按冷启动走 Step 3 → 4。
- Step 3 侦察:首选 `opencli browser analyze <url>` 一步拿 pattern + 反爬 + 最近 adapter + next step;`analyze` 结论模糊时再手跑 `open` → `wait time 2`(或 `wait xhr <regex>`)→ `network`;定 Pattern(A/B/C/D/E)。
- Step 4 API 发现:Pattern A → §1 network 精读;Pattern B → §2 state 抽取 + §1 深层数据;Pattern C → §3 bundle / script src 搜索;Pattern D → §4 token 来源 + 降级 §5;Pattern E → 找 HTTP 轮询接口,找不到才 §5。
- Step 4 遇到无文档 API / DOM 丢数据 / 写操作 / bundle 与 network 冲突时走 `deep-recon.md`:写 intent matrix 和明确的 mutation boundary;baseline → 单一动作 → 新请求 diff,至少一组 changed-input 对照;jsluice 只扩大候选面,候选必须进入 evidence ledger;read 候选过 occurrence/replay/completeness/auth/pagination/failure gate;write 候选有明确授权、目标绑定、幂等/不确定性与不可自动重试语义。
- Step 5 候选合同验证(memory 命中也要重跑):`PUBLIC_API / COOKIE_API / PAGE_FETCH` 用 safe replay 跨两个输入返回成功;`INTERCEPT` 用两次自然页面动作都截到属于目标 identity 的完整响应;响应含目标数据(不是 HTML / 广告 / 推荐侧栏),字段与网页对得上;分页达到 exact limit 或证明 upstream exhaustion,失败不返回 partial;write 不自动 replay,必须过 `deep-recon.md` 的额外合同门禁。
- Step 6 写 strategy note(写代码前的强制产物):从 `PUBLIC_API / COOKIE_API / PAGE_FETCH / INTERCEPT / DOM_STATE / UI_SELECTOR` 选一个;填 Contract(`stable / visible-ui / internal-unstable`);填 Evidence(observed request/state、auth source、replay result);选 `PAGE_FETCH` / `INTERCEPT` 必须解释为什么其他四类都不适合;选 `UI_SELECTOR` / `DOM_STATE` 只需说明语义锚点和 typed error 路径。
- Step 7 字段解码:自解释 → 直接用 key;已知代号 → `field-conventions.md` 查表;未知代号 → `field-decode-playbook.md`(排序键对比 / 结构差分 / 常量排查)。
- Step 8 设计 columns(`output-design.md`):命名 camelCase 且对齐邻居 adapter;类型 / 单位 / 百分比格式清楚;顺序为识别列 → 业务数字 → metadata。
- Step 9 写 adapter(`adapter-template.md`):`opencli browser init <site>/<name>`;找同站点或同类型最像的 adapter cp 过来;改 name / URL / 字段映射三处。
- Step 10 验证:`opencli browser verify <site>/<name>`;首轮通过后立刻 `--write-fixture` 生成 `~/.opencli/sites/<site>/verify/<cmd>.json` 种子;手改种子加 `patterns`(URL / 日期 / ID 格式)+ `notEmpty`(核心字段)+ 收紧 `rowCount`;再跑一次确认 ✓ matches fixture。
- Step 11:字段值 vs 网页肉眼比对一遍,别只看 "Adapter works!"。
- Step 12 回写站点记忆(verify 通过 + 肉眼比对对得上之后):`endpoints.json` 以 endpoint 短名为 key,value = `{url, method, params.{required,optional}, response, verified_at: YYYY-MM-DD, notes}`;`field-map.json` 只追加新代号,key = 字段代号,value = `{meaning, verified_at, source}`,已存在的 key 不要覆盖;`notes.md` 顶部追加 `## YYYY-MM-DD by <agent/user>` 写新坑/新结论;`verify/<cmd>.json` 必填;`fixtures/<cmd>-<YYYYMMDDHHMM>.json` 仅保存公开数据或可证明完成脱敏的样本,高敏响应改用合成 fixture 不落盘;原始 dump/capture 只短暂落 `/tmp/` 或受控 cache,任务结束清理。
- Step 13 repo 贡献收口(私人 adapter 可跳过):production-path tests(不只测 parser/helper);`npm run typecheck` + focused/site tests + `npm run build`;`node dist/src/main.js validate <site>`;`npm run check:typed-error-lint` + `npm run check:silent-column-drop`;adapter 文档,若 sitemap/site memory 有稳定新知识则同步;`git diff --check` + 敏感数据扫描 + 删除 raw capture/cache + 释放 browser session;写操作或私有协议请独立 review exact head 后再合入。
- 卡住时按降级路径跳转:Step 4 `network` 空且 `__INITIAL_STATE__` 也空 → §3 bundle 搜 baseURL;bundle 搜不到 baseURL → §5 intercept;Step 5 401/403 → §4 token 排查;200 但响应是 HTML → 回 Step 3 换 Pattern;200 但 `data: []` 空 → 参数传错/接口换版,回 §1 看真实请求头;Step 7 排序键对比推不出 → `field-decode-playbook.md` §3 结构差分,还推不出就先输出 raw 迭代;Step 10 verify 失败 → autofix skill,复现命令加 `--trace retain-on-failure`;某列永远 `null` → 字段路径错了回 Step 7;fixture mismatch 先肉眼比对网页值,值对→放宽 pattern,值不对→字段映射错;`[column] missing column` → 重新 `--update-fixture` 或修 adapter;`[type]` actual null/undefined → 回 Step 7 重抽,临时 fallback 用 union type `string|null` 仅在语义真的可空时用;Step 11 差 10000 倍 → 单位不统一("万" vs "元");百分比小 100 倍 → 响应已是 `0.025`,不要 × 100。
- 关键约定:adapter 只引 `@jackwener/opencli/registry` + `@jackwener/opencli/errors`,不用第三方;`columns` 数组和 `func` 返回对象 keys 完全对齐(含顺序);中间解析对象 key 不能跟 `columns` 任一项重叠(否则 silent-column-drop audit 误判),改成专属命名 + push row 时 destructure aliasing;`browser:` field 决定 func 签名(`browser:false → (args)`,`browser:true → (page, args)`),搞反时 `args` 实际是 debug flag,所有外部参数 silent fallback 到 default;已知失败按 `references/typed-errors.md` 5-classification 抛对应 typed error,不要 silent `return []`、不要 silent `return [{sentinel}]`、不要 `Math.max/min` silent clamp 外部参数;写私人 adapter 用 `~/.opencli/clis/<site>/<name>.js`(免 build),要提 PR 才 copy 到 `clis/<site>/<name>.js`;站点记忆每轮回写。
- “真实发生过”不等于“可作为 production contract 重放”:私有写请求、一次性风控 token、页面 runtime controller 都必须过 `deep-recon.md` 的 contract gate,过不了就记录 blocker/lift condition,不生成伪 API 命令。
- 调试过程中的原始 dump / 抓包 / HTML 样本只能短暂落在系统 `/tmp/` 或受控 cache,任务结束删除;只有通过 `site-memory.md` 数据分级、准备长期保留的公开/合成/已脱敏样本才进入 `~/.opencli/sites/<site>/fixtures/`;严禁在 repo 根目录、`clis/<site>/` 或当前工作目录留 `.dbg-*.html / raw-*.json / sample.*`。
- JSDOM unit-test fixture(`clis/<site>/__fixtures__/<command>.html`)是上述临时 dump 规则的例外——它是有意 commit 进 repo 的 review artifact,但 quality bar 更高:必须按 `references/jsdom-fixture-pattern.md` 的 5 步做完(含 mandatory `awk 'NF>0'` 空白行收紧),并 reverse-validate 一道证明 regression guard 真能挂。
- 卡住时的诊断路径:诊断类走 `opencli doctor` → 看 `notes.md` → 搜 autofix skill;字段解码类走 `field-decode-playbook.md` 全三节 → 先输出 raw 迭代;endpoint 找不到走 api-discovery §5 intercept 兜底。不要猜——猜错了 verify 能通过但数据是错的,用户看到乱码才发现。
适用边界 · 注意事项
- 数据在浏览器里看不到(需先解决鉴权)、数据不是 HTTP/JSON/HTML、或需要实时推送且找不到同数据 HTTP 接口时,不在本 skill 范围。
- 只想临时驱动浏览器、不写 adapter 时,应改用 opencli-browser;只想了解 opencli 顶层用法时,应改用 opencli-usage。
- 需要破解签名、绕验证码/风控/访问控制,或遇到必须由页面 runtime 生成且不能安全抽象的不可复用签名时,不应继续,应降级到 `UI_SELECTOR` / `DOM_STATE` / `INTERCEPT`。