143 lines
9.9 KiB
Markdown
143 lines
9.9 KiB
Markdown
---
|
||
id: T-213
|
||
title: 拼多多候选 SKU 组合与价格核验
|
||
phase: 2
|
||
deps:
|
||
- T-212
|
||
status: DONE
|
||
created: 2026-07-27
|
||
context_ref: 9a8388f
|
||
work_branch: null
|
||
write_paths:
|
||
- android-buyer/app/build.gradle.kts
|
||
- docs/tasks/T-213.md
|
||
- docs/00-ai-start-here.md
|
||
- docs/04-architecture.md
|
||
- docs/06-tasks.md
|
||
- docs/current-state.md
|
||
- android-buyer/app/src/main/java/com/roubao/autopilot/MainActivity.kt
|
||
- android-buyer/app/src/main/java/com/roubao/autopilot/accessibility/**
|
||
- android-buyer/app/src/main/java/com/roubao/autopilot/pinduoduo/**
|
||
- android-buyer/app/src/main/java/com/roubao/autopilot/procurement/**
|
||
- android-buyer/app/src/main/java/com/roubao/autopilot/ui/screens/SearchProbeScreen.kt
|
||
- android-buyer/app/src/main/java/com/roubao/autopilot/vlm/**
|
||
- android-buyer/app/src/test/java/com/roubao/autopilot/pinduoduo/**
|
||
- android-buyer/app/src/test/java/com/roubao/autopilot/procurement/**
|
||
- android-buyer/app/src/test/java/com/roubao/autopilot/vlm/**
|
||
---
|
||
|
||
## 问题 / 背景
|
||
|
||
T-211 目前只用候选详情页首屏截图判断颜色和尺码。真机已确认拼多多 8.17.0 把完整
|
||
颜色、尺码和组合价格放在“单独购买/免拼购买”后的规格弹层,旧版只读入口策略无法
|
||
取得可靠证据。新业务流程明确要求候选阶段选择目标 SKU 并核对实际组合价格,再把
|
||
匹配候选回传 Admin;Admin 授权后的真正下单由后续独立任务实现。
|
||
|
||
## 关联需求与交互
|
||
|
||
- 功能:F-005、F-007、F-009。
|
||
- 用户故事:US-004、US-005、US-009。
|
||
- 交互:IX-006、IX-007、IX-010 的候选检查、人工确认和安全停止。
|
||
- 架构/API:扩展 Android candidate evidence;后端沿用每个候选最多 5 个鉴权
|
||
evidence asset 的现有能力,不抓取第三方图片或商品 URL。
|
||
- 权限:本任务只实现 `DISCOVERY_INSPECT`,不是后续 `ORDER_CREATE`。
|
||
|
||
## 方案
|
||
|
||
1. 从已验证商品详情页允许唯一识别“选择规格”等直接入口;没有直接入口时,允许按
|
||
固定优先级点击唯一“免拼购买”语义目标,仅用于进入规格弹层。不得点击“提交订单”
|
||
或支付控件。
|
||
2. 弹层必须识别颜色、尺码、当前选择、组合价格、库存/禁用语义。使用任务原始 SKU
|
||
的本地规范化结果依次选择唯一颜色和尺码选项,每次点击后重新读取并验证页面状态。
|
||
3. 目标选项缺失、重复、禁用、不可见、自绘无语义或点击后状态未改变时返回
|
||
`UNKNOWN/MISMATCH`,不得用 VLM 猜测后继续点击。VLM 只辅助解释截图和文本。
|
||
4. 两项选择完成后必须从当前规格弹层读取明确的已选组合和人民币价格;保存规范化
|
||
分值金额、原始可见价格文本、规格语义和截图。价格区间过滤在后续任务契约中使用。
|
||
5. 采集后使用全局返回关闭弹层,复核详情页,再返回原图片结果页。若购买入口直接
|
||
进入订单确认页,立即返回并把候选标为不支持;不能点击页面内任何确认按钮。
|
||
6. 候选评估同时绑定详情/规格证据 SHA-256 和所选规格、组合价格;VLM 不能覆盖本地
|
||
SKU、价格和状态结果。
|
||
|
||
## 验收要点
|
||
|
||
- [x] 页面分类覆盖详情、规格弹层、订单确认、订单列表、登录、验证码、风控和支付。
|
||
- [x] `DISCOVERY_INSPECT` 只允许进入规格弹层、选择目标 SKU、读取价格和返回;代码
|
||
中不存在提交订单、支付或加入购物车动作。
|
||
- [x] 颜色/尺码必须各自唯一匹配;依次点击后验证 selected/已选语义,禁用、重复、
|
||
缺失、截断和状态未变化均有测试。
|
||
- [x] 组合价格使用严格人民币解析并保存分值;模糊区间价、券后条件价、多价格冲突和
|
||
无价格均不能形成自动匹配证据。
|
||
- [x] 若购买入口直接进入订单确认页,自动化不点击任何页面控件并安全返回。
|
||
- [x] 每个候选的详情/规格证据、所选规格和价格不会在重排/outbox 中串位。
|
||
- [x] Android 单元测试、Debug 构建和后端回归通过。
|
||
- [x] PKG110、Android 16、肉包/拼多多版本真机 smoke 完成进入弹层、选择测试 SKU、
|
||
读取组合价格、关闭和返回;确认未创建订单、未进入支付。
|
||
|
||
## 边界
|
||
|
||
- 允许在候选探查阶段选择具体颜色/尺码,但不加入购物车、不提交订单、不支付。
|
||
- 不滚动无界规格列表,不覆盖拼多多未提供无障碍语义的自绘控件。
|
||
- VLM 截图判断只能辅助解释;SKU 选择、价格解析和执行授权必须由确定性代码完成。
|
||
- 不判断优惠券、运费、地址和最终应付总额;这些属于后续订单预览任务。
|
||
- 只支持一个任务 SKU 对应一个颜色和一个尺码;多维规格和组合库存扩展后置。
|
||
|
||
## 执行记录
|
||
|
||
- 2026-07-27:根据 T-211 真机链路的证据缺口登记。任务依赖 T-212,避免规格证据被
|
||
关联到错误的重排候选。
|
||
- 2026-07-27:T-212 完成提交 `4b795a4` 后领取。先冻结拼多多 8.17 规格弹窗的只读
|
||
页面/动作边界和候选多证据模型,再进行真机验证。
|
||
- 2026-07-27:实现规格弹层分类、安全入口 allowlist、颜色/尺码有界解析、本地确定性
|
||
硬匹配、candidate evaluation schema/prompt v3,以及每个候选详情/规格两份证据的
|
||
cache 校验、重排身份绑定和加密 outbox 关联。模型返回状态与本地状态不一致时强制
|
||
降级人工检查。
|
||
- 2026-07-27:Android `testDebugUnitTest` 24 个 suite、128 个测试全部通过,
|
||
`assembleDebug` 通过;后端 `go test ./...` 通过。Debug APK `1.4.3 (8)` 已安装到
|
||
PKG110,拼多多版本为 `8.17.0 (81700)`。
|
||
- 2026-07-27:真机检查图片结果中的定制商品和文字搜索 `black tshirt L` 的普通服装
|
||
商品。服装详情只暴露不可点击的“颜色/款式”预览,完整颜色/尺码弹层只能通过
|
||
“单独购买/免拼购买”控件进入;前两个定制商品甚至没有规格预览。全程未点击购买、
|
||
拼单、购物车、订单或支付控件。
|
||
- 2026-07-27:任务标记 `BLOCKED`。代码在缺少独立可点击规格入口时按
|
||
`UNKNOWN_PAGE` 安全停止,符合边界但无法完成“打开/采集/关闭/返回”的真机验收。
|
||
外部解除条件是:确认允许把购买语义控件仅用于打开规格弹层,或提供不经过购买控件
|
||
的稳定规格入口/受支持数据源。重新安装后 ColorOS 也关闭了肉包无障碍服务,继续
|
||
smoke 前需采购员在系统设置手动重新启用。
|
||
- 2026-07-27:用户确认最终业务必须在 Admin 选择候选后由 Roubao 自动选 SKU、数量
|
||
并创建待付款订单,采购员最后在拼多多人工确认和付款。外部决策已解除旧阻塞,本
|
||
任务重新置为 `DOING`,权限缩小为候选阶段的 `DISCOVERY_INSPECT`;真正
|
||
`ORDER_CREATE` 仍须一次性 Admin 授权和独立任务。
|
||
- 2026-07-27:完成 `DISCOVERY_INSPECT` 实现。任务 SKU 先由本地确定性规则唯一提取
|
||
颜色/尺码,再从直接规格入口或唯一“免拼购买”入口打开弹层;颜色、尺码依次选择并
|
||
复核 selected/“已选择”摘要,规格滚动上限为 2 次。严格解析单一人民币组合价为
|
||
分值,区间价、券后价、条件价、多价格冲突和无价格均不能形成自动匹配证据。
|
||
- 2026-07-27:候选 manifest 升级到 v3,所选规格摘要、原始价格、价格分值和冲突状态
|
||
随详情/规格双截图证据进入候选草稿;本地结果是 VLM 不可覆盖的硬约束。若入口直接
|
||
到订单确认页,只调用系统返回并跳过候选,接口中没有“确定”、提交订单、购物车或
|
||
支付动作。
|
||
- 2026-07-27:Android Debug 24 个 suite、143 个测试全部通过,`assembleDebug` 和
|
||
Release 回归通过;根 `init.ps1` 完成 Go 全包测试、vet、gofmt 和三个二进制构建。
|
||
APK `1.4.4 (9)` 已覆盖安装并冷启动于 PKG110。
|
||
- 2026-07-27:任务暂置 `BLOCKED`,仅剩真机自动化 smoke。设备授权列表中没有肉包
|
||
无障碍服务,解除条件是采购员在 ColorOS 系统设置中手动启用肉包无障碍;不得通过
|
||
ADB 绕过。启用后需验证自动进入规格弹层、选择测试 SKU、读取组合价、关闭并返回,
|
||
同时确认拼多多没有生成订单或进入支付。
|
||
- 2026-07-28:采购员手动启用肉包无障碍后继续真机 smoke。补齐拼多多 8.17 详情页
|
||
短文本“客服”分类、每次图片任务冷启动拼多多、任务切换时清空探针状态,以及 App
|
||
恢复时用 heartbeat 对账本地 claim;后台已取消或已换任务时不再保留旧候选和旧
|
||
claim。对应策略均有单元测试。
|
||
- 2026-07-28:拼多多规格弹层现场价格为 `首件¥16.7`,同时显示非当前的对照文本
|
||
`大促价¥20.7`。严格价格解析增加唯一白名单前缀“首件”,保存原始文本和
|
||
`1670` 分;对照促销价、券后价、区间价和多个实际价格仍不能形成自动匹配证据。
|
||
MediaStore 发布后增加通知和 750 ms 有界稳定等待,避免刚写入的参考图被相册索引
|
||
过早读取。
|
||
- 2026-07-28:最终真机任务 `418c23d8-92ea-46fd-9d1a-294eaeb89ce7` 在 PKG110
|
||
Android 16、肉包 `1.4.10 (15)`、拼多多 `8.17.0 (81700)` 上完成。App 从参考图
|
||
进入图片结果,打开规格弹层,自动选择 `红色` 和 `XL码/裙长90胸围89`,后台候选
|
||
保存 `已选择:XL码/裙长90胸围89 红色` 与 `首件 ¥16.7`。验收后由 Admin 请求
|
||
安全停止,手机确认后任务为 `CANCELED`、`order_submitted=false`,前台返回肉包;
|
||
全程没有确认规格弹层底部按钮、创建订单或进入支付。
|
||
- 2026-07-28:Android Debug 25 个 suite、148 个测试全部通过,
|
||
`assembleDebug` 通过,APK 已覆盖安装;根 `init.ps1` 继续通过 Android
|
||
Debug/Release 回归和 Go 全包测试。任务完成并解除 T-208 的依赖。
|