Files
cmroubao/docs/tasks/T-102.md
T

6.3 KiB

id, title, phase, deps, status, created, context_ref, work_branch, write_paths
id title phase deps status created context_ref work_branch write_paths
T-102 浏览并采集最多 5 个候选 1
T-101
DONE 2026-07-25 f226d0f main
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/ui/screens/SearchProbeScreen.kt
android-buyer/app/src/main/java/com/roubao/autopilot/workflow/WorkflowModels.kt
android-buyer/app/src/main/res/xml/buyer_accessibility_service.xml
android-buyer/app/src/test/java/com/roubao/autopilot/pinduoduo/**
docs/00-ai-start-here.md
docs/02-requirements.md
docs/03-tech-stack.md
docs/04-architecture.md
docs/05-coding-rules.md
docs/current-state.md
docs/tasks/T-102.md
progress.md

问题 / 背景

T-101 已能稳定进入固定词结果页,但尚未证明可以识别独立商品卡、进入详情、保存证据 并返回同一结果页。T-102 只验证有界候选浏览,不进行匹配判断、下单或支付。

关联需求与交互

  • 功能:F-005 的最多 5 个候选采集部分、F-007 安全失败。
  • 用户故事:US-004、US-006。
  • 交互:Android“探针”页展示候选计数和当前步骤。
  • 架构:WorkflowRunner + PinduoduoCandidateAutomation + 无障碍 driver + App 内部缓存证据。

方案

  1. 只从已确认的搜索结果页识别主 RecyclerView 的直属商品卡。
  2. 商品卡必须可见、启用、可点击,包含图片和有限文本;用文本 SHA-256 去重,不在 日志或 UI 展示标题。
  3. 每次只打开一个候选;详情页必须由稳定语义组合确认,保存全屏 PNG、文本指纹和 节点计数后立即返回结果页。
  4. 最多采集 5 个不同候选,最多滚动结果列表 2 次;没有无界循环或翻页。
  5. 登录、验证码、风控、未知页、订单和支付边界立即阻塞;绝不点击详情页购买控件。

验收要点

  • 从 T-101 结果页依次进入候选详情并返回。
  • 采集数量始终不超过 5,结果滚动次数始终不超过 2。
  • 每个候选有内部缓存 PNG、SHA-256、尺寸和语义节点证据。
  • 证据文件名匿名,普通日志和 UI 不输出商品标题。
  • 全流程不使用坐标,不点击购买、订单或支付控件。
  • 页面未知或安全边界出现时产生可区分的 BLOCKED。
  • Fake driver 自动化测试覆盖成功、去重、上限和安全停止。
  • 拼多多 8.17.0 真机 smoke 采集 5 个候选并返回结果页。
  • lintDebug test assembleDebug 通过,默认 APK 不含私有 fixture。

边界

  • 不评估候选是否匹配;T-104 才接入候选评估。
  • 不把候选证据上传网络;T-202 以后再接后端证据接口。
  • 不点击购买、拼单、加入购物车、订单或支付相关节点。
  • 不保存真实蝦皮输入或把商品详情文本写入普通日志。

执行记录

2026-07-25:任务开始

  • 基于 T-101 提交 f226d0f 开始。
  • 脱敏结构审计确认拼多多 8.17.0 结果页主 RecyclerView 和双列商品卡;详情页有 可点击返回语义以及联系客服、收藏、店铺语义,当前未出现订单或支付边界。

2026-07-25:实现

  • 新增 PinduoduoCandidateAutomation 和复合探针 workflow。一次 session 最多尝试 5 个不同卡片、最多发出 2 次结果滚动;预算在动作前消耗,runner retry 不会重置。
  • 主结果 RecyclerView 必须可滚动、覆盖至少 90% 宽度且拥有足够节点。候选卡必须 至少 80% 可见、宽度在单列范围、含图片/价格/至少 2 个语义文本;根不可点击时 只接受唯一覆盖卡片至少 85% 面积的点击目标,小型嵌套按钮不会被选中。
  • 详情页同时要求可点击返回、联系客服/收藏/店铺至少两类语义、宽 ViewPager 和宽 可滚动主列表。详情页动作白名单只有截图和一次全局返回,返回后必须重新确认固定 查询结果页。
  • Android 11/API 30+ 使用声明了 canTakeScreenshot 的无障碍截图 API。Hardware buffer 在独立执行器转换和压缩并始终关闭;8 秒超时后结构化失败,不绕过安全窗口。
  • 每个候选只保存匿名 PNG、卡片/详情语义 SHA-256、节点计数、文件 SHA-256、字节数 和尺寸到 App cache;manifest 不保存标题或页面原文,文件写入在 IO dispatcher。
  • 探针页增加候选 0/5 计数和第五步;仅记录 workflow/候选阶段枚举与截图错误码。

2026-07-25:自动化验证

  • gradlew.bat lintDebug test assembleDebug --no-daemon 成功。
  • App Debug/Release、task contract 和导入器共 14 份报告、78 次测试,0 failure、 0 error、0 skipped。
  • Fake driver 覆盖 5 个去重候选、候选硬上限、旧页面有界过渡、两次滚动上限、 空列表、安全阻塞、截图失败以及从已验证详情页安全恢复。
  • 普通 Debug APK 中 assets/probe-fixtures/ 条目数为 0。

2026-07-25:真机 smoke

  • OnePlus PKG110、Android 16/API 36、拼多多 8.17.0 上,从肉包按钮启动后 20 秒内 依次采集 5 个候选并返回固定词结果页;肉包显示 5 / 5 和五步完成。
  • cache manifest 为 5 条,匿名文件名合法;5 个 PNG 均为 1080x2376,字节数为 正数,文件 SHA-256 与 manifest 全部一致。
  • 最终结果页订单/支付边界计数为 0;logcat 没有肉包崩溃或 ANR,阶段日志不含商品 标题或页面原文。
  • 真机审计 XML/PNG 位于被忽略的 .local/,候选证据位于 App 内部 cache,均未纳入 Git。

2026-07-25:修正记录

  • 首次运行在候选点击后把短暂保留的旧结果页误判为未知。改为只在固定 20 次观测 预算内等待结果页和详情页过渡;任何安全阻塞仍立即停止。
  • 调试期间旧 Activity 造成终态读取混淆;最终 smoke 先清理肉包任务栈,再用 FLAG_ACTIVITY_REORDER_TO_FRONT 返回原实例核验,未创建第二个 workflow。

后续

  • T-103 使用 T-004 的私有 ProbeTask 接入结构化需求提取;不能把订单号或店铺名发给 模型。
  • T-104 才把候选截图交给评估适配器;T-102 不声明任何候选匹配结论。