publishport-opencli 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -61
- package/README.zh-CN.md +68 -68
- package/cli-manifest.json +502 -59
- package/clis/1688/shared.js +2 -2
- package/clis/36kr/news.js +1 -1
- package/clis/_atlassian/shared.js +1 -1
- package/clis/_shared/article/auth.js +1 -1
- package/clis/_shared/article/publish.js +1 -1
- package/clis/_shared/content-guard.js +1 -1
- package/clis/_shared/self-hosted-sites.js +2 -0
- package/clis/_shared/site-auth.js +1 -1
- package/clis/_shared/token-auth.js +2 -2
- package/clis/_shared/video-publish.js +1 -1
- package/clis/aibase/news.js +1 -1
- package/clis/amazon/shared.js +2 -2
- package/clis/antigravity/SKILL.md +12 -12
- package/clis/antigravity/storage.js +1 -1
- package/clis/apple-podcasts/episodes.js +1 -1
- package/clis/archive/item.js +1 -1
- package/clis/archive/search.js +1 -1
- package/clis/archive/snapshots.js +1 -1
- package/clis/archive/wayback.js +1 -1
- package/clis/arxiv/author.js +1 -1
- package/clis/baijiahao/publish.js +1 -1
- package/clis/bbc/utils.js +1 -1
- package/clis/bloomberg/businessweek.js +1 -1
- package/clis/bloomberg/utils.js +1 -1
- package/clis/booking/search.js +1 -1
- package/clis/boss/utils.js +1 -1
- package/clis/chatgpt/ask.js +1 -1
- package/clis/chatgpt/detail.js +1 -1
- package/clis/chatgpt/history.js +1 -1
- package/clis/chatgpt/project-file-add.js +1 -1
- package/clis/chatgpt/project-list.js +1 -1
- package/clis/chatgpt/utils.js +2 -2
- package/clis/chess/utils.js +1 -1
- package/clis/claude/ask.js +1 -1
- package/clis/claude/history.js +1 -1
- package/clis/claude/utils.js +1 -1
- package/clis/codex/extract-diff.js +1 -1
- package/clis/coingecko/coin.js +1 -1
- package/clis/crates/utils.js +1 -1
- package/clis/csdn/stats.js +1 -1
- package/clis/dblp/utils.js +1 -1
- package/clis/defillama/utils.js +1 -1
- package/clis/devto/publish.js +1 -1
- package/clis/discord-app/utils.js +1 -1
- package/clis/dockerhub/utils.js +1 -1
- package/clis/douban/utils.js +1 -1
- package/clis/douyin/_shared/tos-upload.js +1 -1
- package/clis/douyin/hashtag.js +1 -1
- package/clis/douyin/publish-image.js +1 -1
- package/clis/douyin/publish.js +1 -1
- package/clis/eastmoney/announcement.js +1 -1
- package/clis/eastmoney/rank.js +1 -1
- package/clis/eastmoney/sectors.js +1 -1
- package/clis/endoflife/utils.js +1 -1
- package/clis/flathub/utils.js +1 -1
- package/clis/gemini/detail.js +1 -1
- package/clis/gemini/read.js +1 -1
- package/clis/geogebra/add-circle.js +1 -1
- package/clis/geogebra/add-line.js +1 -1
- package/clis/geogebra/add-point.js +1 -1
- package/clis/geogebra/add-polygon.js +1 -1
- package/clis/geogebra/eval.js +1 -1
- package/clis/geogebra/hexagon.js +1 -1
- package/clis/geogebra/info.js +1 -1
- package/clis/geogebra/triangle.js +1 -1
- package/clis/ghost/login.js +1 -0
- package/clis/ghost/publish.js +1 -1
- package/clis/ghost/shared.js +24 -1
- package/clis/ghost/sites.js +1 -0
- package/clis/ghost/whoami.js +1 -1
- package/clis/gitee/user.js +2 -2
- package/clis/github-trending/repos.js +1 -1
- package/clis/goproxy/utils.js +1 -1
- package/clis/grok/export-all.js +1 -1
- package/clis/grok/export.js +1 -1
- package/clis/hashnode/publish.js +1 -1
- package/clis/hf/datasets.js +1 -1
- package/clis/hf/models.js +1 -1
- package/clis/hf/paper.js +1 -1
- package/clis/hf/spaces.js +1 -1
- package/clis/homebrew/utils.js +1 -1
- package/clis/instagram/note.js +1 -1
- package/clis/jimeng/generate.js +1 -1
- package/clis/juejin/utils.js +1 -1
- package/clis/kuaishou/publish.js +1 -1
- package/clis/lesswrong/tag.js +1 -1
- package/clis/lichess/utils.js +1 -1
- package/clis/linkedin/search.js +2 -2
- package/clis/linux-do/feed.js +2 -2
- package/clis/lobsters/domain.js +1 -1
- package/clis/mastodon/login.js +1 -0
- package/clis/mastodon/post.js +1 -1
- package/clis/mastodon/shared.js +10 -10
- package/clis/mastodon/sites.js +1 -0
- package/clis/mastodon/whoami.js +1 -1
- package/clis/maven/utils.js +1 -1
- package/clis/mdn/search.js +1 -1
- package/clis/medium/tag.js +1 -1
- package/clis/notebooklm/current.js +1 -1
- package/clis/notebooklm/get.js +1 -1
- package/clis/notebooklm/history.js +1 -1
- package/clis/notebooklm/note-list.js +1 -1
- package/clis/notebooklm/notes-get.js +1 -1
- package/clis/notebooklm/open.js +1 -1
- package/clis/notebooklm/source-fulltext.js +1 -1
- package/clis/notebooklm/source-get.js +1 -1
- package/clis/notebooklm/source-guide.js +1 -1
- package/clis/notebooklm/source-list.js +1 -1
- package/clis/notebooklm/summary.js +1 -1
- package/clis/notebooklm/utils.js +1 -1
- package/clis/npm/utils.js +1 -1
- package/clis/nuget/utils.js +1 -1
- package/clis/nvd/cve.js +1 -1
- package/clis/oeis/utils.js +1 -1
- package/clis/ones/common.js +2 -2
- package/clis/ones/me.js +1 -1
- package/clis/ones/tasks.js +1 -1
- package/clis/ones/token-info.js +1 -1
- package/clis/ones/worklog.js +1 -1
- package/clis/openalex/utils.js +1 -1
- package/clis/oschina/stats.js +1 -1
- package/clis/osv/utils.js +1 -1
- package/clis/packagist/utils.js +1 -1
- package/clis/pixiv/detail.js +1 -1
- package/clis/pixiv/user.js +1 -1
- package/clis/producthunt/utils.js +1 -1
- package/clis/pypi/utils.js +1 -1
- package/clis/qiita/gql.js +2 -2
- package/clis/rest-countries/utils.js +1 -1
- package/clis/rfc/utils.js +1 -1
- package/clis/rubygems/utils.js +1 -1
- package/clis/semanticscholar/utils.js +1 -1
- package/clis/slock/errors.js +1 -1
- package/clis/spotify/spotify.js +1 -1
- package/clis/spotify/utils.js +1 -1
- package/clis/stackoverflow/utils.js +1 -1
- package/clis/steam/utils.js +1 -1
- package/clis/substack/auth.js +2 -2
- package/clis/suno/generate.js +2 -2
- package/clis/suno/list.js +3 -3
- package/clis/telegram/send.js +1 -1
- package/clis/tiktok/creator-videos.js +1 -1
- package/clis/tiktok/publish.js +1 -1
- package/clis/tiktok/utils.js +1 -1
- package/clis/trae-cn/activity.js +1 -1
- package/clis/trae-cn/approve.js +1 -1
- package/clis/trae-cn/ask.js +1 -1
- package/clis/trae-cn/dump.js +1 -1
- package/clis/trae-cn/export.js +1 -1
- package/clis/trae-cn/model.js +1 -1
- package/clis/trae-cn/new.js +1 -1
- package/clis/trae-cn/read.js +1 -1
- package/clis/trae-cn/screenshot.js +1 -1
- package/clis/trae-cn/select-model.js +1 -1
- package/clis/trae-cn/send.js +1 -1
- package/clis/trae-cn/setup.js +1 -1
- package/clis/trae-cn/status.js +1 -1
- package/clis/trae-cn/targets.js +1 -1
- package/clis/trae-cn/watch.js +1 -1
- package/clis/trae-solo/state-fs.js +1 -1
- package/clis/tumblr/publish.js +1 -1
- package/clis/tvmaze/utils.js +1 -1
- package/clis/twitter/bookmark-folder.js +1 -1
- package/clis/twitter/download.js +1 -1
- package/clis/twitter/followers.js +2 -2
- package/clis/twitter/following.js +2 -2
- package/clis/twitter/likes.js +1 -1
- package/clis/twitter/list-add-batch.js +1 -1
- package/clis/twitter/list-add-core.js +1 -1
- package/clis/twitter/list-add.js +1 -1
- package/clis/twitter/list-create.js +1 -1
- package/clis/twitter/list-delete.js +3 -3
- package/clis/twitter/list-remove-batch.js +1 -1
- package/clis/twitter/list-remove.js +1 -1
- package/clis/twitter/list-tweets.js +1 -1
- package/clis/twitter/profile.js +1 -1
- package/clis/twitter/search.js +1 -1
- package/clis/twitter/shared.js +1 -1
- package/clis/twitter/tweets.js +1 -1
- package/clis/uisdc/news.js +1 -1
- package/clis/v2ex/daily.js +2 -2
- package/clis/v2ex/me.js +2 -2
- package/clis/v2ex/notifications.js +1 -1
- package/clis/wikidata/utils.js +1 -1
- package/clis/wikipedia/page.js +2 -2
- package/clis/wikipedia/summary.js +1 -1
- package/clis/wikipedia/utils.js +1 -1
- package/clis/wordpress/login.js +1 -1
- package/clis/wordpress/publish.js +1 -1
- package/clis/wordpress/shared.js +3 -3
- package/clis/wordpress/sites.js +1 -0
- package/clis/wordpress/whoami.js +1 -1
- package/clis/woshipm/stats.js +1 -1
- package/clis/xiaoe/content.js +1 -1
- package/clis/xiaohongshu/draft-delete.js +1 -1
- package/clis/xiaohongshu/draft-open.js +1 -1
- package/clis/xiaohongshu/draft-utils.js +2 -2
- package/clis/xiaohongshu/publish-video.js +1 -1
- package/clis/xiaohongshu/publish.js +1 -1
- package/clis/xiaoyuzhou/auth.js +1 -1
- package/clis/xiaoyuzhou/transcript.js +1 -1
- package/clis/yollomi/background.js +1 -1
- package/clis/yollomi/edit.js +1 -1
- package/clis/yollomi/generate.js +1 -1
- package/clis/yollomi/try-on.js +1 -1
- package/clis/youtube/publish.js +1 -1
- package/clis/zhihu/answer-comments.js +1 -1
- package/clis/zhihu/answer-detail.js +1 -1
- package/clis/zhihu/collection.js +2 -2
- package/clis/zhihu/collections.js +1 -1
- package/clis/zhihu/question.js +1 -1
- package/clis/zhihu/search.js +1 -1
- package/clis/zhihu/target.js +1 -1
- package/clis/zhihu/user-arg.js +1 -1
- package/dist/src/adapter-shadow.js +1 -1
- package/dist/src/browser/analyze.js +1 -1
- package/dist/src/browser/article-extract.d.ts +1 -1
- package/dist/src/browser/base-page.js +3 -3
- package/dist/src/browser/cdp.js +1 -1
- package/dist/src/browser/daemon-client.d.ts +1 -1
- package/dist/src/browser/daemon-lifecycle.js +6 -6
- package/dist/src/browser/daemon-version.js +1 -1
- package/dist/src/browser/dom-snapshot.d.ts +1 -1
- package/dist/src/browser/dom-snapshot.js +2 -2
- package/dist/src/browser/errors.js +2 -2
- package/dist/src/browser/network-cache.js +1 -1
- package/dist/src/browser/profile.js +1 -1
- package/dist/src/browser/target-resolver.js +4 -4
- package/dist/src/browser/verify-fixture.js +1 -1
- package/dist/src/browser-session-lock.js +1 -1
- package/dist/src/build-manifest.d.ts +1 -1
- package/dist/src/build-manifest.js +1 -1
- package/dist/src/cli-argv-preprocess.d.ts +4 -4
- package/dist/src/cli-argv-preprocess.js +1 -1
- package/dist/src/cli.d.ts +1 -1
- package/dist/src/cli.js +19 -19
- package/dist/src/commanderAdapter.js +1 -1
- package/dist/src/commands/auth.js +2 -2
- package/dist/src/commands/daemon.d.ts +4 -4
- package/dist/src/commands/daemon.js +1 -1
- package/dist/src/completion-shared.js +12 -12
- package/dist/src/completion.d.ts +2 -2
- package/dist/src/constants.d.ts +1 -1
- package/dist/src/constants.js +1 -1
- package/dist/src/daemon-utils.d.ts +1 -1
- package/dist/src/daemon-utils.js +1 -1
- package/dist/src/daemon.d.ts +2 -2
- package/dist/src/daemon.js +1 -1
- package/dist/src/discovery.d.ts +7 -7
- package/dist/src/discovery.js +2 -2
- package/dist/src/doctor.d.ts +1 -1
- package/dist/src/doctor.js +6 -6
- package/dist/src/electron-apps.d.ts +1 -1
- package/dist/src/electron-apps.js +1 -1
- package/dist/src/errors.d.ts +2 -2
- package/dist/src/errors.js +1 -1
- package/dist/src/execution.js +1 -1
- package/dist/src/external.d.ts +1 -1
- package/dist/src/external.js +1 -1
- package/dist/src/help.d.ts +1 -1
- package/dist/src/help.js +3 -3
- package/dist/src/hooks.d.ts +1 -1
- package/dist/src/launcher.js +2 -2
- package/dist/src/logger.d.ts +1 -1
- package/dist/src/main.d.ts +1 -1
- package/dist/src/main.js +1 -1
- package/dist/src/observation/artifact.js +2 -2
- package/dist/src/package-paths.js +1 -1
- package/dist/src/package-paths.test.d.ts +1 -0
- package/dist/src/plugin-manifest.d.ts +12 -3
- package/dist/src/plugin-manifest.js +1 -1
- package/dist/src/plugin-scaffold.d.ts +2 -2
- package/dist/src/plugin-scaffold.js +9 -9
- package/dist/src/plugin.d.ts +4 -4
- package/dist/src/plugin.js +10 -10
- package/dist/src/rate-limit.js +1 -1
- package/dist/src/registry-api.d.ts +1 -1
- package/dist/src/runtime-detect.d.ts +1 -1
- package/dist/src/serialization.js +1 -1
- package/dist/src/skills.js +6 -6
- package/dist/src/user-runtime.d.ts +8 -0
- package/dist/src/user-runtime.js +1 -0
- package/dist/src/user-runtime.test.d.ts +1 -0
- package/dist/src/validate.js +1 -1
- package/dist/src/validate.test.d.ts +1 -1
- package/docs/guide/browser-bridge.md +23 -23
- package/docs/guide/electron-app-cli.md +3 -3
- package/docs/guide/exit-codes.md +3 -3
- package/docs/guide/extending-opencli.md +37 -37
- package/docs/guide/getting-started.md +19 -19
- package/docs/guide/installation.md +6 -6
- package/docs/guide/plugins.md +32 -32
- package/docs/guide/remote-orchestration.md +5 -5
- package/docs/guide/troubleshooting.md +9 -9
- package/package.json +3 -2
- package/scripts/fetch-adapters.js +6 -6
- package/scripts/postinstall.js +14 -14
- package/skills/opencli-adapter-author/SKILL.md +24 -24
- package/skills/opencli-adapter-author/references/adapter-template.md +13 -13
- package/skills/opencli-adapter-author/references/api-discovery.md +25 -25
- package/skills/opencli-adapter-author/references/coverage-matrix.md +3 -3
- package/skills/opencli-adapter-author/references/field-decode-playbook.md +10 -10
- package/skills/opencli-adapter-author/references/jsdom-fixture-pattern.md +2 -2
- package/skills/opencli-adapter-author/references/site-memory.md +11 -11
- package/skills/opencli-adapter-author/references/site-recon.md +7 -7
- package/skills/opencli-adapter-author/references/strategy-selection.md +3 -3
- package/skills/opencli-adapter-author/references/success-rate-pitfalls.md +4 -4
- package/skills/opencli-adapter-author/references/typed-errors.md +2 -2
- package/skills/opencli-autofix/SKILL.md +29 -29
- package/skills/opencli-browser/SKILL.md +55 -55
- package/skills/opencli-browser-sitemap/SKILL.md +7 -7
- package/skills/opencli-sitemap-author/SKILL.md +11 -11
- package/skills/opencli-sitemap-author/references/sitemap-schema.md +19 -19
- package/skills/opencli-usage/SKILL.md +43 -43
|
@@ -39,7 +39,7 @@ skill 明确承诺能搞定什么、搞不定什么。动手前先看一眼这
|
|
|
39
39
|
| | CSV 字符串(eastmoney kline) | ✅ | `response.split(',')` 按列序解 |
|
|
40
40
|
| | HTML 表格(tonghuashun) | 🟡 | `page.evaluate` 里用 `querySelectorAll` 拿 |
|
|
41
41
|
|
|
42
|
-
🟡 的维度意思:方法在文档里,但这一版没拿真实站点跑过端到端。第一次遇到时按文档走,遇到和文档不一致的地方记到 `~/.
|
|
42
|
+
🟡 的维度意思:方法在文档里,但这一版没拿真实站点跑过端到端。第一次遇到时按文档走,遇到和文档不一致的地方记到 `~/.ppcli/sites/<site>/notes.md`,下一次再打开就是 ✅。
|
|
43
43
|
|
|
44
44
|
---
|
|
45
45
|
|
|
@@ -74,8 +74,8 @@ skill 明确承诺能搞定什么、搞不定什么。动手前先看一眼这
|
|
|
74
74
|
|
|
75
75
|
| 类型 | 证据 adapter | 覆盖维度 |
|
|
76
76
|
|------|-------------|---------|
|
|
77
|
-
| PUBLIC + 自解释字段 + SPA | `~/.
|
|
77
|
+
| PUBLIC + 自解释字段 + SPA | `~/.ppcli/clis/coingecko/top.js`(本轮 dry run) | `Strategy.PUBLIC` + REST JSON + 自解释字段 + 列表页 |
|
|
78
78
|
| COOKIE + 代号字段 + JSONP | `clis/eastmoney/*.js` × 13(PR #1091 merged) | `Strategy.PUBLIC`(匿名 `ut=`)+ JSONP + f-代号 + 列表/详情/K 线 |
|
|
79
79
|
| COOKIE + SPA | `clis/bilibili/*.js` × 10+(已存在) | `Strategy.COOKIE + browser:true` + wbi 签名 |
|
|
80
80
|
|
|
81
|
-
**本 PR 新增的 skill 还未硬验证的维度**:🟡 行,尤其 SSR Pattern B + Bearer/CSRF + 未登记代号解码。这些放到第一批真实用户 adapter 写作中打磨,skill 文档先落,踩坑回来补 `site-memory`。合 PR 之前先拿 coingecko 跑第二轮(带着第一轮写出的 `~/.
|
|
81
|
+
**本 PR 新增的 skill 还未硬验证的维度**:🟡 行,尤其 SSR Pattern B + Bearer/CSRF + 未登记代号解码。这些放到第一批真实用户 adapter 写作中打磨,skill 文档先落,踩坑回来补 `site-memory`。合 PR 之前先拿 coingecko 跑第二轮(带着第一轮写出的 `~/.ppcli/sites/coingecko/`)验证 memory 命中 → endpoint re-verify → 字段抽查 → 写 adapter 这条回路。
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
44
|
# 如果是相对路径,拼 domain 回浏览器验证
|
|
45
|
-
|
|
45
|
+
ppcli browser eval "window.location.origin + '/<path>'"
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
---
|
|
@@ -68,8 +68,8 @@ opencli browser eval "window.location.origin + '/<path>'"
|
|
|
68
68
|
比如 eastmoney,`fid=f2`(最新价)和 `fid=f3`(涨跌幅):
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
ppcli browser eval "fetch('<url>&fid=f2&po=1').then(r=>r.json()).then(d=>d.data.diff.slice(0,3))"
|
|
72
|
+
ppcli browser eval "fetch('<url>&fid=f3&po=1').then(r=>r.json()).then(d=>d.data.diff.slice(0,3))"
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
3. **对比两组数据**:
|
|
@@ -81,7 +81,7 @@ opencli browser eval "window.location.origin + '/<path>'"
|
|
|
81
81
|
4. **用第三个参数交叉验证**
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
|
-
|
|
84
|
+
ppcli browser eval "fetch('<url>&fid=f6&po=1').then(r=>r.json()).then(d=>d.data.diff.slice(0,3))" # 成交额
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
对照网页上"成交额排行"的前三名。对得上就认。
|
|
@@ -90,11 +90,11 @@ opencli browser eval "window.location.origin + '/<path>'"
|
|
|
90
90
|
|
|
91
91
|
```bash
|
|
92
92
|
# 按价格排,拿一条观察
|
|
93
|
-
|
|
93
|
+
ppcli browser eval "fetch('https://push2.eastmoney.com/api/qt/clist/get?fs=b:MK0354&pn=1&pz=1&fid=f2&po=1&fltt=2&fields=f12,f14,f2,f3,f236,f237,f239').then(r=>r.json()).then(d=>d.data.diff[0])"
|
|
94
94
|
# 返回 {f12:'123456', f14:'XX转债', f2:180.5, f3:2.1, f236:98.5, f237:83.2, f239:-4.1}
|
|
95
95
|
|
|
96
96
|
# 按 f237 排
|
|
97
|
-
|
|
97
|
+
ppcli browser eval "fetch('...&fid=f237&po=1...').then(...)"
|
|
98
98
|
# 第一条变了,f237 值变成 400+
|
|
99
99
|
|
|
100
100
|
# 打开 eastmoney 可转债页,切"溢价率"排序,第一条的溢价率确实是 400+ —— f237 就是溢价率 %
|
|
@@ -111,13 +111,13 @@ opencli browser eval "fetch('...&fid=f237&po=1...').then(...)"
|
|
|
111
111
|
1. **先数一次嵌套路径**
|
|
112
112
|
|
|
113
113
|
```bash
|
|
114
|
-
|
|
114
|
+
ppcli browser eval "fetch('<url>').then(r=>r.json()).then(j=>({keys:Object.keys(j), type:Array.isArray(j)?'array':'object'}))"
|
|
115
115
|
```
|
|
116
116
|
|
|
117
117
|
2. **一层一层剥**
|
|
118
118
|
|
|
119
119
|
```bash
|
|
120
|
-
|
|
120
|
+
ppcli browser eval "fetch('<url>').then(r=>r.json()).then(j=>{const d=j.data; return {keys:Object.keys(d), sample: d[Object.keys(d)[0]]}})"
|
|
121
121
|
```
|
|
122
122
|
|
|
123
123
|
3. **数数组长度对照 pz / pageSize**
|
|
@@ -128,7 +128,7 @@ opencli browser eval "fetch('...&fid=f237&po=1...').then(...)"
|
|
|
128
128
|
|
|
129
129
|
```bash
|
|
130
130
|
# 取前三条的 keys,看哪些 key 的值在变(业务数据),哪些不变(常量/配置)
|
|
131
|
-
|
|
131
|
+
ppcli browser eval "fetch('<url>').then(r=>r.json()).then(d=>d.data.diff.slice(0,3).map(x=>({f2:x.f2,f3:x.f3,f152:x.f152})))"
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
---
|
|
@@ -154,7 +154,7 @@ opencli browser eval "fetch('...&fid=f237&po=1...').then(...)"
|
|
|
154
154
|
|
|
155
155
|
1. **补进 `references/field-conventions.md`**:找到对应站点的表格加一行。下次直接查。
|
|
156
156
|
2. **在 adapter 代码里留一条注释**:如果是实测推出来的不常见代号,写一行 `// f237 = convertible premium rate (verified 2026-04-20 against page)` 方便复核。
|
|
157
|
-
3. **通过 `
|
|
157
|
+
3. **通过 `ppcli browser verify` 验一次**:字段值能对上网页上眼见的数字。
|
|
158
158
|
|
|
159
159
|
---
|
|
160
160
|
|
|
@@ -40,9 +40,9 @@ the live extractor walks.
|
|
|
40
40
|
|
|
41
41
|
1. **Capture** the page's HTML from a live verify run:
|
|
42
42
|
```bash
|
|
43
|
-
|
|
43
|
+
ppcli browser open https://www.example.com/<page>
|
|
44
44
|
# In another shell, dump page.content():
|
|
45
|
-
|
|
45
|
+
ppcli browser eval 'document.documentElement.outerHTML' \
|
|
46
46
|
> /tmp/raw-<command>.html
|
|
47
47
|
```
|
|
48
48
|
|
|
@@ -11,7 +11,7 @@ skills/opencli-adapter-author/references/site-memory/<site>.md
|
|
|
11
11
|
— 公共种子。手写 + PR 审核进入。多 agent 共享的第一批起点。
|
|
12
12
|
— 已铺:eastmoney / xueqiu / bilibili / tonghuashun
|
|
13
13
|
|
|
14
|
-
~/.
|
|
14
|
+
~/.ppcli/sites/<site>/
|
|
15
15
|
— 本地累积。agent 跑 adapter 过程里自动写入,跨 session 复用。
|
|
16
16
|
— 不进 git,不进 PR。
|
|
17
17
|
```
|
|
@@ -52,16 +52,16 @@ skills/opencli-adapter-author/references/site-memory/<site>.md
|
|
|
52
52
|
|
|
53
53
|
---
|
|
54
54
|
|
|
55
|
-
## Layer 2 — 本地工作目录(`~/.
|
|
55
|
+
## Layer 2 — 本地工作目录(`~/.ppcli/sites/<site>/`)
|
|
56
56
|
|
|
57
57
|
agent 每跑一次相关 adapter 就可以自动写/读:
|
|
58
58
|
|
|
59
59
|
```
|
|
60
|
-
~/.
|
|
60
|
+
~/.ppcli/sites/<site>/
|
|
61
61
|
notes.md — 累积笔记(时间戳 + 写入人 + 发现)
|
|
62
62
|
endpoints.json — 已验证的 endpoint 目录
|
|
63
63
|
field-map.json — 字段代号 → 含义(key 为字段代号,value 为 {meaning, verified_at, source})
|
|
64
|
-
verify/ — `
|
|
64
|
+
verify/ — `ppcli browser verify` 期望值(值级校验锚点,每个 adapter 一份)
|
|
65
65
|
<cmd>.json
|
|
66
66
|
fixtures/ — 完整响应样本(给字段对比 / 离线 replay;**调试时的原始 dump 也只能落在这里或 /tmp/**)
|
|
67
67
|
<cmd>-<ts>.json
|
|
@@ -121,7 +121,7 @@ key = 字段代号(`f237` / `f152`),value 三件套:
|
|
|
121
121
|
|
|
122
122
|
### `verify/<cmd>.json` 格式(schema 锁死)
|
|
123
123
|
|
|
124
|
-
每个 adapter 一份,`
|
|
124
|
+
每个 adapter 一份,`ppcli browser verify <site>/<cmd>` 会自动读。**没有这份 = verify 只能证"能跑",证不出数据对**——所以是必填产物。
|
|
125
125
|
|
|
126
126
|
```json
|
|
127
127
|
{
|
|
@@ -194,16 +194,16 @@ key = 字段代号(`f237` / `f152`),value 三件套:
|
|
|
194
194
|
## runbook 里的读/写时机
|
|
195
195
|
|
|
196
196
|
```
|
|
197
|
-
Step 2 开始前 → 读 ~/.
|
|
197
|
+
Step 2 开始前 → 读 ~/.ppcli/sites/<site>/
|
|
198
198
|
→ 读 references/site-memory/<site>.md
|
|
199
199
|
命中后 → 不跳写 adapter,仍要跑 Step 5 (endpoint 验证) + Step 7 (字段抽查)
|
|
200
200
|
verified_at 超 30 天 → 当作过期,按冷启动走 Step 3 → 4
|
|
201
201
|
|
|
202
|
-
Step 10 verify 首轮通过后 → 写 ~/.
|
|
202
|
+
Step 10 verify 首轮通过后 → 写 ~/.ppcli/sites/<site>/verify/<cmd>.json
|
|
203
203
|
- 先 `--write-fixture` 拿种子,再手改 patterns / notEmpty / rowCount
|
|
204
204
|
- 没这份后续 verify 挡不住数据错位,**必填**
|
|
205
205
|
|
|
206
|
-
Step 11 肉眼对比通过后 → 写 ~/.
|
|
206
|
+
Step 11 肉眼对比通过后 → 写 ~/.ppcli/sites/<site>/
|
|
207
207
|
- endpoints.json:按 schema 追加或更新 verified_at
|
|
208
208
|
- field-map.json:只追加新 key,已有的不默默覆盖
|
|
209
209
|
- notes.md:顶部追加一段
|
|
@@ -214,7 +214,7 @@ Step 11 肉眼对比通过后 → 写 ~/.opencli/sites/<site>/
|
|
|
214
214
|
|
|
215
215
|
---
|
|
216
216
|
|
|
217
|
-
## 不要写进 `~/.
|
|
217
|
+
## 不要写进 `~/.ppcli/sites/` 的东西
|
|
218
218
|
|
|
219
219
|
- 真实账户 cookie / token — 不要保存任何鉴权凭据
|
|
220
220
|
- 用户私有数据(返回体里有个人敏感字段的 → 脱敏再存 fixtures)
|
|
@@ -222,10 +222,10 @@ Step 11 肉眼对比通过后 → 写 ~/.opencli/sites/<site>/
|
|
|
222
222
|
|
|
223
223
|
## 不要写进 **repo / adapter 目录** 的东西
|
|
224
224
|
|
|
225
|
-
调试过程里的临时 dump(`.dbg-*.html` / `raw-*.json` / `sample-*` / `trace-*.txt`)**只能**落在 `~/.
|
|
225
|
+
调试过程里的临时 dump(`.dbg-*.html` / `raw-*.json` / `sample-*` / `trace-*.txt`)**只能**落在 `~/.ppcli/sites/<site>/fixtures/` 或系统 `/tmp/`。PR diff 会把 repo 根目录和 `clis/<site>/` 下的文件一起带走——别人 review 时看到一堆调试副产物会很烦。
|
|
226
226
|
|
|
227
227
|
---
|
|
228
228
|
|
|
229
229
|
## 没有 site-memory 时
|
|
230
230
|
|
|
231
|
-
新站点没对应 `.md`,也没本地目录 → 完整走 recon + discovery,跑完直接写 `~/.
|
|
231
|
+
新站点没对应 `.md`,也没本地目录 → 完整走 recon + discovery,跑完直接写 `~/.ppcli/sites/<site>/`,后面就有了。
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
## 一步诊断(推荐)
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
|
|
12
|
+
ppcli browser analyze <url>
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
返回一份 JSON:
|
|
@@ -20,7 +20,7 @@ opencli browser analyze <url>
|
|
|
20
20
|
"anti_bot": { "detected": false, "vendor": null, "evidence": [], "implication": "No known anti-bot signatures. Node-side fetch may work; try COOKIE first, fall back to browser-context fetch if blocked." },
|
|
21
21
|
"initial_state": { "__INITIAL_STATE__": false, "__NUXT__": false, "__NEXT_DATA__": false, "__APOLLO_STATE__": false },
|
|
22
22
|
"nearest_adapter": { "site": "xueqiu", "example_commands": ["xueqiu search", "xueqiu hot"], "reason": "2 existing adapters target this site — reuse strategy/cookie config" },
|
|
23
|
-
"recommended_next_step": "Pick the most specific JSON endpoint from `
|
|
23
|
+
"recommended_next_step": "Pick the most specific JSON endpoint from `ppcli browser network` and try a bare Node fetch with cookies; escalate to browser-context fetch only if blocked."
|
|
24
24
|
}
|
|
25
25
|
```
|
|
26
26
|
|
|
@@ -29,9 +29,9 @@ opencli browser analyze <url>
|
|
|
29
29
|
## 手动三步诊断(analyze 给不出明确结论时)
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
ppcli browser open <url>
|
|
33
|
+
ppcli browser wait time 2
|
|
34
|
+
ppcli browser network
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
看 `network` 输出判:
|
|
@@ -46,7 +46,7 @@ opencli browser network
|
|
|
46
46
|
|
|
47
47
|
分不清时参考下面五节的其他信号。
|
|
48
48
|
|
|
49
|
-
**数据是 SPA / 异步加载时,`wait time 2` 可能不够**。改用 `
|
|
49
|
+
**数据是 SPA / 异步加载时,`wait time 2` 可能不够**。改用 `ppcli browser wait xhr '/api/path-fragment'` 直接等具体接口到场,比盲 `wait time 5` 更稳。
|
|
50
50
|
|
|
51
51
|
---
|
|
52
52
|
|
|
@@ -62,7 +62,7 @@ opencli browser network
|
|
|
62
62
|
**下一步**:`api-discovery.md` §1(network 精读)
|
|
63
63
|
|
|
64
64
|
**注意 — Pattern A 命中不等于 strategy 选 `PAGE_FETCH`**:
|
|
65
|
-
- 先看 `
|
|
65
|
+
- 先看 `ppcli browser analyze` 输出的 `api_candidates[]`:`verdict=likely_data` 的条目才是真候选;`verdict=noise`(analytics / beacon / personalization)不能算 API 信号
|
|
66
66
|
- booking #1680 反例:17 个 JSON XHR 看起来像 Pattern A,但全是 analytics side-channel,最终走 `DOM_STATE` / `UI_SELECTOR`
|
|
67
67
|
- replay 候选 endpoint 后,按 `strategy-selection.md` 的契约模型选 strategy;`PUBLIC_API` / `COOKIE_API` 都不通才考虑 `PAGE_FETCH`
|
|
68
68
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Strategy Selection
|
|
2
2
|
|
|
3
|
-
SKILL.md 顶层已给出 strategy gate 的 enum、表格和必填字段。本文件展开**为什么**这套 ladder 是按"契约"而不是"接口高度"组织的,以及具体怎么用 `
|
|
3
|
+
SKILL.md 顶层已给出 strategy gate 的 enum、表格和必填字段。本文件展开**为什么**这套 ladder 是按"契约"而不是"接口高度"组织的,以及具体怎么用 `ppcli browser analyze` 的 `api_candidates` 证据填 strategy note。
|
|
4
4
|
|
|
5
|
-
进入条件:你已经按 `site-recon.md` 跑过 `
|
|
5
|
+
进入条件:你已经按 `site-recon.md` 跑过 `ppcli browser analyze`、按 `api-discovery.md` 抓过候选 endpoint。本文件是写 note 之前的最后一站。
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -50,7 +50,7 @@ SKILL.md 顶层已给出 strategy gate 的 enum、表格和必填字段。本文
|
|
|
50
50
|
|
|
51
51
|
## 3. 怎么把 `api_candidates` 转化为 strategy note 证据
|
|
52
52
|
|
|
53
|
-
`
|
|
53
|
+
`ppcli browser analyze <url>` 的输出里 `api_candidates[]` 字段,每条带:
|
|
54
54
|
|
|
55
55
|
```json
|
|
56
56
|
{
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
**防御**:
|
|
16
16
|
- `autofix` skill 现有纪律:**verify pattern 失败 = 收紧 adapter,不是收紧 fixture**(`opencli-autofix` SKILL.md §Rules for Patching 第 6 条)
|
|
17
|
-
- 要改 fixture 的唯一合法理由:**站点本身换了格式**(例如 URL 规范迁移)。这种情况下在 `~/.
|
|
17
|
+
- 要改 fixture 的唯一合法理由:**站点本身换了格式**(例如 URL 规范迁移)。这种情况下在 `~/.ppcli/sites/<site>/notes.md` 顶部写一段说明
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
@@ -90,9 +90,9 @@
|
|
|
90
90
|
**根因**:`wait time N` 是盲等。不同站点 JS 执行速度差很多。
|
|
91
91
|
|
|
92
92
|
**防御**:
|
|
93
|
-
- 数据是异步加载时**不用 `wait time`**,用 `
|
|
93
|
+
- 数据是异步加载时**不用 `wait time`**,用 `ppcli browser wait xhr '/api/path-fragment'`,等具体 XHR 到场再 `network`
|
|
94
94
|
- 不确定 endpoint 路径时:先 `wait time 2 && network`,看到候选路径再转 `wait xhr` 确认
|
|
95
|
-
- 首诊断用 `
|
|
95
|
+
- 首诊断用 `ppcli browser analyze <url>` 一步拿 `json_responses` 数量——=0 时才真的是 Pattern C
|
|
96
96
|
|
|
97
97
|
---
|
|
98
98
|
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
|
|
114
114
|
**现象**:本地开发时用自己的登录态验 endpoint 能通,PR 一合 verify fixture 跑在 CI 环境里立刻 401——顺手把样本数据也固化进了 fixture,看起来"一切正常"。
|
|
115
115
|
|
|
116
|
-
**根因**:fixture 样本是带登录态跑出来的。存 `~/.
|
|
116
|
+
**根因**:fixture 样本是带登录态跑出来的。存 `~/.ppcli/sites/<site>/fixtures/*.json` 没脱敏,把 cookie / token / 自己的 uid / 昵称存了进去。
|
|
117
117
|
|
|
118
118
|
**防御**:
|
|
119
119
|
- `site-memory.md` 的脱敏规则:存 fixtures 前去掉 cookie / token / 用户私有字段(手机号 / 邮箱 / 昵称 / uid)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Typed Error Conventions
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
ppcli 用 5 类 typed error 让 agent 能从 exit code 直接分辨"参数错 / 没数据 / 接口挂 / 要登录 / 超时"。silent `return []` / silent `return [{sentinel}]` / scalar sentinel (`'-'`) / `Math.max/min` silent clamp / `CliError('HTTP_ERROR')` 这些"绿但错"的写法都被 audit gate 抓得越来越紧([`scripts/check-typed-error-lint.mjs`](../../../scripts/check-typed-error-lint.mjs) 的 baseline JSON 只能减不能加,新违例必须立刻收掉)。
|
|
4
4
|
|
|
5
5
|
每条 rule 都挂了真实 anti-pattern 反例(PR #1329 三轮迭代是主要素材库)。
|
|
6
6
|
|
|
@@ -209,7 +209,7 @@ if (!/id="postlist"/.test(html)) throw new EmptyResultError('1point3acres thread
|
|
|
209
209
|
|
|
210
210
|
## 6. Verify fixture 怎么挡这三类
|
|
211
211
|
|
|
212
|
-
新写 fixture 时(`~/.
|
|
212
|
+
新写 fixture 时(`~/.ppcli/sites/<site>/verify/<cmd>.json`):
|
|
213
213
|
|
|
214
214
|
- **rowCount.min ≥ 1**:保证 sentinel-row 不能伪装通过
|
|
215
215
|
- **patterns**:核心 id 列加 `^\d+$` 类正则,挡 `tid: ''` / `pid: ''` 之类空字符串污染
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: opencli-autofix
|
|
3
|
-
description: Automatically fix broken
|
|
4
|
-
allowed-tools: Bash(
|
|
3
|
+
description: Automatically fix broken ppcli adapters when commands fail. Load this skill when an ppcli command fails — it guides you through collecting a trace artifact, patching the adapter, retrying, and filing an upstream GitHub issue after a verified fix. Works with any AI agent.
|
|
4
|
+
allowed-tools: Bash(ppcli:*), Bash(gh:*), Read, Edit, Write
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
#
|
|
7
|
+
# ppcli AutoFix — Automatic Adapter Self-Repair
|
|
8
8
|
|
|
9
9
|
When an `opencli` command fails because a website changed its DOM, API, or response schema, **automatically diagnose, fix the adapter, and retry** — don't just report the error.
|
|
10
10
|
|
|
@@ -13,11 +13,11 @@ When an `opencli` command fails because a website changed its DOM, API, or respo
|
|
|
13
13
|
**Before starting any repair, check these hard stops:**
|
|
14
14
|
|
|
15
15
|
- **`AUTH_REQUIRED`** (exit code 77) — **STOP.** Do not modify code. Tell the user to log into the site in Chrome.
|
|
16
|
-
- **`BROWSER_CONNECT`** (exit code 69) — **STOP.** Do not modify code. Tell the user to run `
|
|
16
|
+
- **`BROWSER_CONNECT`** (exit code 69) — **STOP.** Do not modify code. Tell the user to run `ppcli doctor`.
|
|
17
17
|
- **CAPTCHA / rate limiting** — **STOP.** Not an adapter issue.
|
|
18
18
|
|
|
19
19
|
**Scope constraint:**
|
|
20
|
-
- **Only modify the file at `adapterSourcePath` in the trace `summary.md` front matter** — this is the authoritative adapter location (may be `clis/<site>/` in repo or `~/.
|
|
20
|
+
- **Only modify the file at `adapterSourcePath` in the trace `summary.md` front matter** — this is the authoritative adapter location (may be `clis/<site>/` in repo or `~/.ppcli/clis/<site>/` for npm installs)
|
|
21
21
|
- **Never modify** `src/`, `extension/`, `tests/`, `package.json`, or `tsconfig.json`
|
|
22
22
|
|
|
23
23
|
**Retry budget:** Max **3 repair rounds** per failure. If 3 rounds of diagnose → fix → retry don't resolve it, stop and report what was tried.
|
|
@@ -25,12 +25,12 @@ When an `opencli` command fails because a website changed its DOM, API, or respo
|
|
|
25
25
|
## Prerequisites
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
|
|
28
|
+
ppcli doctor # Verify extension + daemon connectivity
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
## When to Use This Skill
|
|
32
32
|
|
|
33
|
-
Use when `
|
|
33
|
+
Use when `ppcli <site> <command>` fails with repairable errors:
|
|
34
34
|
- **SELECTOR** — element not found (DOM changed)
|
|
35
35
|
- **EMPTY_RESULT** — no data returned (API response changed)
|
|
36
36
|
- **API_ERROR** / **NETWORK** — endpoint moved or broke
|
|
@@ -42,8 +42,8 @@ Use when `opencli <site> <command>` fails with repairable errors:
|
|
|
42
42
|
|
|
43
43
|
`EMPTY_RESULT` — and sometimes a structurally-valid `SELECTOR` that returns nothing — is often **not an adapter bug**. Platforms actively degrade results under anti-scrape heuristics, and a "not found" response from the site doesn't mean the content is actually missing. Rule this out **before** committing to a repair round:
|
|
44
44
|
|
|
45
|
-
- **Retry with an alternative query or entry point.** If `
|
|
46
|
-
- **Spot-check in a normal Chrome tab.** If the data is visible in the user's own browser but the adapter comes back empty, the issue is usually authentication state, rate limiting, or a soft block — not a code bug. The fix is `
|
|
45
|
+
- **Retry with an alternative query or entry point.** If `ppcli xiaohongshu search "X"` returns 0 but `ppcli xiaohongshu search "X 攻略"` returns 20, the adapter is fine — the platform was shaping results for the first query.
|
|
46
|
+
- **Spot-check in a normal Chrome tab.** If the data is visible in the user's own browser but the adapter comes back empty, the issue is usually authentication state, rate limiting, or a soft block — not a code bug. The fix is `ppcli doctor` / re-login, not editing source.
|
|
47
47
|
- **Look for soft 404s.** Sites like xiaohongshu / weibo / douyin return HTTP 200 with an empty payload instead of a real 404 when an item is hidden or deleted. The snapshot will look structurally correct. A retry 2-3 seconds later often distinguishes "temporarily hidden" from "actually gone".
|
|
48
48
|
- **"0 results" from a search is an answer.** If the adapter successfully reached the search endpoint, got an HTTP 200, and the platform returned `results: []`, that is a valid answer — report it to the user as "no matches for this query" rather than patching the adapter.
|
|
49
49
|
|
|
@@ -54,7 +54,7 @@ Only proceed to Step 1 if the empty/selector-missing result is **reproducible ac
|
|
|
54
54
|
Run the failing command with failure-retained trace enabled:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
|
-
|
|
57
|
+
ppcli <site> <command> [args...] --trace retain-on-failure 2>trace-error.yaml
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
On failure, stderr contains the normal error envelope plus a small `trace` block:
|
|
@@ -68,9 +68,9 @@ trace:
|
|
|
68
68
|
schemaVersion: 1
|
|
69
69
|
opencliVersion: "..."
|
|
70
70
|
traceId: "..."
|
|
71
|
-
dir: "/path/to/.
|
|
72
|
-
summaryPath: "/path/to/.
|
|
73
|
-
receiptPath: "/path/to/.
|
|
71
|
+
dir: "/path/to/.ppcli/profiles/default/traces/..."
|
|
72
|
+
summaryPath: "/path/to/.ppcli/profiles/default/traces/.../summary.md"
|
|
73
|
+
receiptPath: "/path/to/.ppcli/profiles/default/traces/.../receipt.json"
|
|
74
74
|
```
|
|
75
75
|
|
|
76
76
|
Read `summaryPath` first. It is the LLM-oriented entry point and includes front matter:
|
|
@@ -126,13 +126,13 @@ Read the trace summary and the adapter source. Classify the root cause:
|
|
|
126
126
|
|
|
127
127
|
## Step 3: Explore the Current Website
|
|
128
128
|
|
|
129
|
-
Use `
|
|
129
|
+
Use `ppcli browser` to inspect the live website. **Never use the broken adapter** — it will just fail again.
|
|
130
130
|
|
|
131
131
|
### DOM changed (SELECTOR errors)
|
|
132
132
|
|
|
133
133
|
```bash
|
|
134
134
|
# Open the page and inspect current DOM
|
|
135
|
-
|
|
135
|
+
ppcli browser open https://example.com/target-page && ppcli browser state
|
|
136
136
|
|
|
137
137
|
# Look for elements that match the adapter's intent
|
|
138
138
|
# Compare the snapshot with what the adapter expects
|
|
@@ -142,21 +142,21 @@ opencli browser open https://example.com/target-page && opencli browser state
|
|
|
142
142
|
|
|
143
143
|
```bash
|
|
144
144
|
# Open page with network interceptor, then trigger the action manually
|
|
145
|
-
|
|
145
|
+
ppcli browser open https://example.com/target-page && ppcli browser state
|
|
146
146
|
|
|
147
147
|
# Interact to trigger API calls
|
|
148
|
-
|
|
148
|
+
ppcli browser click <N> && ppcli browser network
|
|
149
149
|
|
|
150
150
|
# Narrow to the request you care about by the fields its body should have
|
|
151
|
-
|
|
151
|
+
ppcli browser network --filter author,text,likes
|
|
152
152
|
|
|
153
153
|
# Inspect specific API response (key is the `key` field from the default JSON output)
|
|
154
|
-
|
|
154
|
+
ppcli browser network --detail <key>
|
|
155
155
|
```
|
|
156
156
|
|
|
157
157
|
## Step 4: Patch the Adapter
|
|
158
158
|
|
|
159
|
-
Read the adapter source file at `adapterSourcePath` from the trace summary front matter and make targeted fixes. This path is authoritative — it may be in the repo (`clis/`) or user-local (`~/.
|
|
159
|
+
Read the adapter source file at `adapterSourcePath` from the trace summary front matter and make targeted fixes. This path is authoritative — it may be in the repo (`clis/`) or user-local (`~/.ppcli/clis/`).
|
|
160
160
|
|
|
161
161
|
Use the `Read` tool on the exact path from summary.md front matter.
|
|
162
162
|
|
|
@@ -193,13 +193,13 @@ Use the `Read` tool on the exact path from summary.md front matter.
|
|
|
193
193
|
3. **Prefer API over DOM scraping** — if you discover a JSON API during exploration, switch to it
|
|
194
194
|
4. **Use `@jackwener/opencli/*` imports only** — never add third-party package imports
|
|
195
195
|
5. **Test after patching** — run the command again to verify
|
|
196
|
-
6. **Never relax `verify/<cmd>.json` fixtures to silence a failure.** A failing `patterns` / `notEmpty` / `mustNotContain` / `mustBeTruthy` rule means the adapter's output is broken. Tighten the adapter so it produces correct values; do not loosen the fixture to accept the broken values. The one legitimate reason to edit a fixture during repair is when the **site itself** changed shape (e.g. URL format migration) — in that case update the fixture and note the change in `~/.
|
|
196
|
+
6. **Never relax `verify/<cmd>.json` fixtures to silence a failure.** A failing `patterns` / `notEmpty` / `mustNotContain` / `mustBeTruthy` rule means the adapter's output is broken. Tighten the adapter so it produces correct values; do not loosen the fixture to accept the broken values. The one legitimate reason to edit a fixture during repair is when the **site itself** changed shape (e.g. URL format migration) — in that case update the fixture and note the change in `~/.ppcli/sites/<site>/notes.md`. Otherwise editing the fixture is covering up a silent correctness regression.
|
|
197
197
|
|
|
198
198
|
## Step 5: Verify the Fix
|
|
199
199
|
|
|
200
200
|
```bash
|
|
201
201
|
# Run the command normally
|
|
202
|
-
|
|
202
|
+
ppcli <site> <command> [args...]
|
|
203
203
|
```
|
|
204
204
|
|
|
205
205
|
If it still fails, go back to Step 1 and collect a fresh trace. You have a budget of **3 repair rounds** (trace → fix → retry). If the same error persists after a fix, try a different approach. After 3 rounds, stop and report what was tried.
|
|
@@ -223,12 +223,12 @@ If the retry **passes**, the local adapter has drifted from upstream. File a Git
|
|
|
223
223
|
|
|
224
224
|
```markdown
|
|
225
225
|
## Summary
|
|
226
|
-
|
|
226
|
+
ppcli autofix repaired this adapter locally, and the retry passed.
|
|
227
227
|
|
|
228
228
|
## Adapter
|
|
229
229
|
- Site: `<site>`
|
|
230
230
|
- Command: `<command>`
|
|
231
|
-
-
|
|
231
|
+
- ppcli version: `<version from ppcli --version>`
|
|
232
232
|
|
|
233
233
|
## Original failure
|
|
234
234
|
- Error code: `<error_code>`
|
|
@@ -243,7 +243,7 @@ OpenCLI autofix repaired this adapter locally, and the retry passed.
|
|
|
243
243
|
<1-2 sentence description of what you changed and why>
|
|
244
244
|
~~~
|
|
245
245
|
|
|
246
|
-
_Issue filed by
|
|
246
|
+
_Issue filed by ppcli autofix after a verified local repair._
|
|
247
247
|
```
|
|
248
248
|
|
|
249
249
|
2. **Ask the user before filing.** Show them the draft title and body. Only proceed if they confirm.
|
|
@@ -275,20 +275,20 @@ In all stop cases, clearly communicate the situation to the user rather than mak
|
|
|
275
275
|
## Example Repair Session
|
|
276
276
|
|
|
277
277
|
```
|
|
278
|
-
1. User runs:
|
|
278
|
+
1. User runs: ppcli zhihu hot
|
|
279
279
|
→ Fails: SELECTOR "Could not find element: .HotList-item"
|
|
280
280
|
|
|
281
|
-
2. AI runs:
|
|
281
|
+
2. AI runs: ppcli zhihu hot --trace retain-on-failure 2>trace-error.yaml
|
|
282
282
|
→ Gets trace summary with final state and failed action evidence
|
|
283
283
|
|
|
284
284
|
3. AI reads summary/state: page loaded but uses ".HotItem" instead of ".HotList-item"
|
|
285
285
|
|
|
286
|
-
4. AI explores:
|
|
286
|
+
4. AI explores: ppcli browser open https://www.zhihu.com/hot && ppcli browser state
|
|
287
287
|
→ Confirms new class name ".HotItem" with child ".HotItem-content"
|
|
288
288
|
|
|
289
289
|
5. AI patches: Edit adapter at `adapterSourcePath` — replace ".HotList-item" with ".HotItem"
|
|
290
290
|
|
|
291
|
-
6. AI verifies:
|
|
291
|
+
6. AI verifies: ppcli zhihu hot
|
|
292
292
|
→ Success: returns hot topics
|
|
293
293
|
|
|
294
294
|
7. AI prepares upstream issue draft, shows it to the user
|