# 需求:第三方分发点版本一致性纳入机检(Uptodown-正在发旧包)
状态: done(2026-10-10 已落地:10-10 当日落地读数机检:products.py 新增 third_party_version(取页面 softwareVersion 与自家 feed 逐段数值比对,不等=缺口,取不到=pending 不吃 HTTP 200);五桌面产品登记 third_party 条目;正对照组 EF 实报滞后(0.9.4<0.9.6),反向注入坏页报「页面已失效:HTTP 404」;test_products_third_party.py 10 用例绿+ops 全量 425 passed/1 skipped;日报第六节三行缺口在列;口径正本 ops/README.md 数据口径+产品登记两行。发版动作按票划在票外(渠道写操作,须过 channel_check 闸门))
归属: 公司运营
来源: 登记缺口(ops/products/#easy-flow)
日期: 2026-10-10
建议: 做,10-08 Uptodown 五产品收录上线,但平台挂的是提交时版本(与自家 feed 逐一比对:EF/ES/ED 三仓滞后,EC/EI 一致);缺口静默两天无人知,因为 products.py check 只盘官网/R2/feed/skill 四端点,第三方分发点不在盘点范围

## 现状

10-08 23:39~23:41 Uptodown 编辑批准五产品全部上线(进件通知 #419~#423),我按外部可见实证逐页核过:`https://<slug>.en.uptodown.com/windows` 五页 HTTP 200、title 与 developer 均对得上。**但同一批页面报出的版本号是提交时的旧版**:

| 产品 | Uptodown 现挂 | 对外最新(feed) | 判定 |
| --- | --- | --- | --- |
| Easy Flow | 0.9.4 | 0.9.6 | **滞后**(且平台无 mac 包:mac 已对外却不在这儿) |
| Easy Clipboard | 0.5.11 | 0.5.11 | 一致 |
| Easy Image | 0.4.6 | 0.4.6 | 一致 |
| Easy Screenshot | 0.10.0 | 0.11.0 | **滞后** |
| Easy Disk | 0.9.8 | 0.9.9 | **滞后** |

「对外最新」这一列取的是**口径正本=自家 feed**(`https://updates.pinnadash.com/updates/<id>/latest.json` 的 `version`,10-10 逐个实读:EF 0.9.6 / EC 0.5.11 / EI 0.4.6 / ES 0.11.0 / ED 0.9.9),**不是产品仓 package.json**——建票时我曾把 EC 写成「0.5.12」,那正是仓里未发版的 WIP 号,拿它当对外口径就误报了一个滞后项,这恰是本票要机检的那类口径混淆,先在自己身上验过一次。

结构性缺口:`python ops/products.py check` 的标配四端点=官网/R2 分发/feed/skill,**第三方分发点(Uptodown、AlternativeTo、MajorGeeks、未来的 Softpedia 等)不在盘点内**。所以「外部分发页在发旧包、且 mac 用户在那边根本看不到 mac 包」这件事没有任何机检会报,这次是靠我人肉读邮件才发现的——已经静默两天(10-08 上线→10-10 才发现)。

## 方案

分两步,第一步是纯读数机检(可跨仓代做,只读,不碰渠道账号):

1. **登记表加 `third_party` 字段**(`ops/products/<id>.yaml`):记 `{channel: uptodown, url: https://<slug>.en.uptodown.com/windows, evidence: "<version> via <developer>"}`——按渠道声明「我们在哪儿还分发」,而不是靠人记。
2. **`products.py check` 新增一类盘点项 `third_party_version`**:抓页面提取版本号(取法与官网/R2 探活同套 UA+代理兜底,走 `_lib.http_raw`),与登记表/feed 当前版本比对,不等则挂日报「产品盘点」节,口径写「分发点滞后」;抓不到版本号=挂 pending 而不是 ok(不吃「页面 200」当一致)。
3. **发新版本身是渠道写操作,不在本票顺手做**:须先过 `ops/channel_check.mjs uptodown` 闸门(本轮实测 EXIT 8=ASK 未清、且 10-02 织的 uptodown 技能与登录态在 `weave/.weave/skills/` 已查无,需重织+正向实证),按渠道纪律交 boss。本票只保证「滞后会被机检发现并挂账」,发版动作另立排工。

## 验收标准

- [x] `ops/products/<id>.yaml` 五桌面产品各含 `third_party` 条目,渠道+URL+实证字段齐全(五页 10-10 实取,`load_registry` 解析回读五条均在)
- [x] `python ops/products.py check` 输出含 `third_party_version` 盘点项,对 EF 实报「滞后(0.9.4 < 0.9.6)」而不是 ok(正对照组成立:实跑报三条——EF 0.9.4<0.9.6、ES 0.10.0<0.11.0、ED 0.9.8<0.9.9;EC/EI 判 ok,与 10-10 人肉读邮件的结论逐字一致)
- [x] 反向注入证红:把某仓 URL 改成不存在的页面 → 该项报 pending/error,不得静默变 ok(真数据真网络注入 `easy-clipboard/.../windows-does-not-exist-9527` → `state=gap`,盘点行「分发点[uptodown] 登记的页面已失效:HTTP 404」;同一条注入前现场项报 ok=0.5.11 一致)
- [x] 页面取不到版本号时判 pending(单测覆盖),不得因 HTTP 200 就放行(`ops/test_products_third_party.py::test_http_200_without_version_is_pending_not_ok`;同文件另覆盖网络失败、404、feed 取不到=无法比对、版本逐段数值比较、出口必须 `_lib.http_raw(proxy_first=True)`、未登记 third_party 不得多打一次请求,共 10 用例)
- [x] 当日日报「产品盘点」节出现该缺口,清零前每天在列(`ops/reports/2026-10-10.md` 第六节三行「缺口:分发点[uptodown] 正在发旧包」)
- [x] `ops/README.md`「数据口径」节补 `third_party_version` 判据一句话(口径先落正本;另在「产品登记」口径表补 `third_party` 字段行=声明制登记,不填不探测)

## 遗留(不在本票验收范围)

- **三仓在 Uptodown 发新版(EF 0.9.6 / ES 0.11.0 / ED 0.9.9)= 渠道写操作,本票只做机检**:须先清 `channel_check.mjs uptodown` 那条 10-01 的过期 ASK、重织 10-02 已查无的 uptodown 技能+登录态正向实证,再过闸门交 boss;现由每日盘点「正在发旧包」缺口天天挂着,不会静默。
- 机检目前只认 Schema.org `softwareVersion` 一种形态(Uptodown 实测形态)。AlternativeTo/MajorGeeks/Softpedia 接入时若页面不带该字段,该项判 pending(不猜、不判绿),届时拿真实样本再补提取规则。
- 平台侧只有 Windows 页(`/mac`、`/linux` 实测 404):mac 包已对外的 EF/EI 在那边分发不到,属渠道覆盖缺口,归渠道线排工时一并谈。

