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

110 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: T-104
title: 接入候选评估并停在人工确认点
phase: 1
deps:
- T-102
- T-103
status: DONE
created: 2026-07-25
context_ref: 32d5310
work_branch: main
write_paths:
- 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/vlm/**
- android-buyer/app/src/test/java/com/roubao/autopilot/pinduoduo/**
- android-buyer/app/src/test/java/com/roubao/autopilot/vlm/**
- docs/**
- progress.md
---
## 问题 / 背景
T-102 已能有界采集最多 5 份匿名候选截图证据,T-103 已能从私有任务得到严格的结构化
需求,但两者尚未使用同一搜索词连接,候选也没有匹配项、缺失项和拒绝原因。T-104
只完成候选建议和人员确认闭环,不提交订单、不进入支付。
## 方案
1. 需求提取成功后,候选探针使用该提取结果的搜索词;固定脱敏词仍保留给 T-101/T-102
独立回归。
2. 只有搜索词与当前需求一致且 workflow 成功的候选证据可以评估。
3. 受控 evidence source 按内存中的候选元数据读取匿名 PNG,复核数量、文件名、路径、
字节数、PNG 尺寸和 SHA-256;VLM adapter 不自行遍历 cache。
4. 每次用户操作按 ordinal 串行评估,单个候选最多调用一次、全批最多 5 次;任一网络
失败或无效输出都会停止后续付费调用。
5. 本地代码从有效评估中稳定产生建议项;预算缺失、低分、不确定或模型输出无效时保持
人工处理。无论模型输出如何,都不能产生页面动作或订单授权。
6. UI 展示匹配项、缺失项、拒绝原因和建议项,并停在人工确认点;人员只能标记候选
可用或拒绝本次候选,结果始终记录 `order_submitted=false`。
## 验收要点
- [x] 候选搜索使用当前结构化需求的搜索词,旧搜索结果不能冒充当前任务证据。
- [x] 最多 5 份候选 PNG 经受控边界验证后才进入评估 gateway。
- [x] 模型请求不含订单号、店铺名、本机路径、数量或支付信息。
- [x] 严格 schema 输出每个候选的判断、分数、匹配项、缺失项和拒绝原因。
- [x] 缺候选、ordinal 不一致、额外字段、动作语义和证据篡改均安全失败或转人工。
- [x] UI 明确停在人工确认,不包含提交订单或支付动作。
- [x] Fake gateway、证据读取、动态搜索和人工确认状态均有自动化测试。
- [x] `lintDebug test assembleDebug` 通过,默认 APK 不含私有 fixture。
- [x] 无真实模型凭证时只用本机 mock 验证集成,不宣称真实匹配质量。
## 执行记录
### 2026-07-25:任务开始
- 基于 T-103 提交 `32d5310` 开始。
- 当前外部 blocker 仍是真实 VLM 供应商、凭证、费用、数据留存和模型效果;先完成
provider-neutral 契约、Fake 测试和本机 mock 集成。
### 2026-07-25:实现
- 动态搜索使用当前 `RequirementExtraction.searchQuery`,同时绑定完整需求快照、
搜索词、成功 workflow 和本次候选 metadata;任一不一致都拒绝评估。
- `CandidateEvidenceSource` 只按内存 allowlist 读取 `candidate-01.png` 等固定匿名
文件,复核规范路径、8 MiB 单图/32 MiB 总量、PNG/IHDR、尺寸和 SHA-256。
- `CandidateEvaluator` 按 ordinal 串行调用,单候选一次、全批最多 5 次;无效输出、
provider 失败或取消立即停止后续调用,无效批次不保留先前自动建议。
- 严格解析候选 ordinal、判断、分数、匹配项、缺失项、拒绝原因和置信度;拒绝额外
字段、数字字符串、坐标/动作/提交/支付语义,以及无预算时的价格匹配声明。
- 推荐候选由本地按分数、置信度和 ordinal 稳定产生;人工接受必须对应实际存在的
`REVIEW` 建议项,批次和 UI 均固定 `order_submitted=false`。
- UI 展示每个候选的评估理由、警告和人工操作,只提供“标记建议候选可用”和
“拒绝本次候选”,没有提交订单或支付控件。
### 2026-07-25:自动化验证
- 执行
`.\gradlew.bat :app:lintDebug test assembleDebug --no-daemon`,构建与 lint 通过。
- App Debug/Release、task contract 和导入器共 26 份报告、166 次测试,0 failure、
0 error、0 skipped。
- 覆盖动态搜索、其他关键词结果页、受控证据路径/大小/PNG/尺寸/哈希、每候选调用
次数与停止规则、严格 schema、隐私字段、确定性推荐、人工确认和订单未提交状态。
- 不带 `probeFixturesDir` 重建默认 Debug APK,`assets/probe-fixtures/` 条目为 0。
### 2026-07-25:真机 smoke
- 在 OnePlus PKG110、Android 16/API 36、拼多多 8.17.0 上,用私有 fixture 完成
动态搜索和 5/5 候选证据采集。
- 一次性本机 OpenAI 兼容 mock 精确收到 5 次 POST,ordinal 为 1 至 5,每次只有
一张 JPEG data URL;订单、店铺、本机路径和数量字段命中均为 false。
- 严格响应进入“等待人工确认”,5 个候选均可见;点击“标记建议候选可用”后显示
候选已由人员标记可用且订单未提交,页面没有提交或支付按钮。
- 候选流程后的 logcat 中私有 sentinel、Base64、原始 mock 响应及 schema/prompt
命中均为 0;设备 provider 已恢复,ADB reverse 已移除。
### 未验证项
- 未使用真实远程 VLM 凭证,不宣称真实商品匹配质量、成本或供应商可用性。
- 当前证据是整页截图,尚无确定性商品标题和价格采集;第一层预算为空,因此任何
价格或预算匹配都转人工。
### 后续
- T-201 建立 Go-Gin、SQLite 和迁移骨架。
- T-202 生成并确认 P0 Web/App 低保真原型。