Page:
T-246
Pages
00-ai-start-here
01-vision
02-requirements
03-tech-stack
04-architecture
05-coding-rules
06-tasks
07-user-stories
08-interaction-checklist
Design
Home
Integrations-shunyunbao-contract
PPT
T-001
T-002
T-003
T-004
T-101
T-102
T-103
T-104
T-201
T-202
T-203
T-204
T-205
T-206
T-207
T-208
T-209
T-210
T-211
T-212
T-213
T-214
T-215
T-216
T-217
T-218
T-219
T-220
T-221
T-222
T-223
T-224
T-225
T-226
T-227
T-228
T-229
T-230
T-231
T-232
T-233
T-234
T-235
T-236
T-237
T-238
T-239
T-240
T-241
T-242
T-243
T-244
T-245
T-246
T-247
T-248
T-249
T-250
T-251
T-252
T-253
T-254
T-255
T-256
T-257
T-258
T-259
T-260
T-261
T-262
T-263
T-264
T-265
T-266
T-267
T-268
T-269
T-270
T-271
T-272
T-273
T-274
T-275
T-276
T-277
T-278
T-279
T-280
T-281
Task-Template
Tasks
agent-context
api
clean-state-checklist
current-state
routes
Clone
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.
同步来源:
docs/tasks/T-246.md· commitafc651f75a3a
id: T-246 title: 自动接单与 goods_id 直达采购闭环 phase: 2 deps:
- T-218
- T-245
status: DONE
created: 2026-07-29
context_ref:
97b2a18work_branch: null write_paths: - docs/tasks/T-246.md
- docs/current-state.md
- docs/api.md
- docs/04-architecture.md
- backend-api/migrations/**
- backend-api/internal/domain/**
- backend-api/internal/usecase/**
- backend-api/internal/repository/sqlite/**
- backend-api/internal/transport/httpapi/**
- backend-api/internal/transport/webui/**
- android-buyer/app/src/main/**
- android-buyer/app/src/test/**
需求 / 背景
低客单价采购不能依赖采购人员在手机上反复领取、开始、重新搜索和定位商品。Admin 创建 采购任务后,Roubao 应在登录、设备就绪且无其他有效任务时自动领取并开始图片搜索,将 最多 5 个候选的拼多多商品身份、链接、本地图片、标题、规格和价格保存到后台。采购员 只在 Admin 选择一次商品;之后 Roubao 自动进入该商品页、选择规格和数量、提交一笔 待付款订单并回传订单号与下单时间,付款仍由人员完成。
现有实现有四个缺口:
IDLE只在点击“获取任务”后调用 claim,CLAIMED仍需人工确认开始。RUNNING/WAITING_CONFIRMATION在授权过期后仍永久占用设备;App 的SAFE_STOPPED手动同步在真正请求后端前返回,后台取消无法完成。- 候选 observation 虽预留
product_url/image_url,Android 实际始终提交空字符串; 候选图片只有受控详情/规格证据。 - 下单授权和设备命令没有
goods_id或规范 URL,dry-run 会再次图片搜索,不能直接 进入 Admin 已确认的商品。
参考 Obsidian:
ila/项目文档/cmroubao/cmroubao-候选商品链接回传与goods_id方案.mdProjetos/cmroubao/Regras/goodsid.md
修订契约
自动调度
- App 登录且无本地任务、无后台有效任务、设备 readiness 通过时,自动 heartbeat 并
claim 最早的
PENDING任务;无任务按有界退避轮询。 - claim 后完成参考图下载、SHA-256 校验和 2 秒稳定窗口,自动开始 execution;本地安全
VLM 配置可用时采用
AI_ASSISTED,否则使用确定性MANUAL_FIRST,不能因模型配置 缺失阻塞采购。 - 自动流程同一时刻只允许一个 claim、execution、候选探针或下单动作;进程恢复复用原 幂等 key,不得重复领取、重复开始或重复提交订单。
- 当前任务进入后台确认、终态或安全失败后停止外部动作;终态清理完成后自动领取下一条。
- “获取任务”和“立即同步”保留为故障重试,不再是正常流程必需操作。
过期任务恢复
CLAIMED仍可按现有租约重新领取;RUNNING/WAITING_CONFIRMATION授权过期后不得继续 自动化,也不得永久占用设备。- 后台已请求取消且 claim 已过期时,后端在受控恢复事务中直接转
CANCELED、结束未完成 execution、清空 claim 所有权并记录审计事件。 - App 的
SAFE_STOPPED手动/自动同步必须真正查询后台;后台任务已终止或不再属于当前 设备时清理本地加密任务并回到自动接单。 - 不把过期的执行中任务重新排入
PENDING,避免在未知外部状态下重复执行。
候选商品身份和图片
- 每个真实候选提取纯数字
goods_id,并生成唯一规范 URL:https://mobile.yangkeduo.com/goods.html?goods_id=<goods_id>。 - 首选无障碍语义中的“商品编号/goods_id”,本地 OCR 仅作受控兜底;不能可靠提取时保持
空值、不得猜测。缺少
goods_id的候选可以作为审计观察,但不能创建自动下单授权。 - 候选回传保存
goods_id、规范 URL、标题、当前选中规格摘要、颜色/尺码目标、组合价格、 采集时间、PDD 版本、卡片/详情指纹以及 DETAIL/SPECIFICATION 本地证据资产。 - Admin 展示本地鉴权图片并提供规范外链。外链使用新窗口及
noopener/noreferrer; 后端只执行严格语法/域名/路径/参数校验,绝不请求 PDD URL 或保存浏览器会话。 image_url只允许作辅助字段;主要候选图片继续由本地证据 asset 提供,外链失效不影响 审计和授权。
授权和直达下单
candidate_key仍是 Admin 选择主键;新身份版本同时绑定 execution、ordinal、goods_id、详情指纹和规格证据 hash。- Admin 授权快照、设备命令和 command SHA-256 必须不可变地包含
goods_id、规范 URL、 原始 SKU、数量、候选规格/价格及现有证据指纹;URL 或 ordinal 不能单独授权。 - App 收到授权后使用显式拼多多包名的
ACTION_VIEW打开规范 URL。只能在确认进入 PRODUCT_DETAIL 且重新提取的goods_id与授权一致后继续。 - 直达失败可使用现有参考图搜索作一次受控兜底,但最终仍必须唯一复核
goods_id; 不一致、跳转、下架或提取失败立即停止。 - 颜色、尺码和数量仍按唯一可访问控件选择,每次动作后复读状态;价格、订单确认页商品 身份和总额必须通过现有 dry-run。
- 最终继续使用 T-218 submission fence,最多点击一次“提交订单”,只回读待付款订单, 不点击支付、不保存 PDD Cookie/Token。
数据与接口方案
- 新迁移为 observation/identity/authorization 增加结构化
goods_id和规范 URL; 历史记录以空值兼容,新授权只接受完整身份。 - 候选请求 schema 增加
goods_id,product_url改为严格 PDD 规范 URL;候选键升级cmroubao-candidate-v2。 - order authorization 与 device command schema 升级,command hash 覆盖新增字段。
- Android 安全存储升级并兼容旧 schema;新字段在 ACK 前落盘。
- Admin API/Web 展示
goods_id、外链和本地证据图;人工理由与 candidate key 流程不变。 - App 自动调度使用进程内单协程、有界退避和现有 repository mutex;不引入 FCM、 WebSocket 或后台常驻推送服务。
验收要点
- 新 Admin 任务在 App 已登录且 readiness 通过时无需点击即可 claim、start 并搜索。
- 无任务轮询有界;单设备/并发恢复不重复 claim、start、探针或下单。
- 过期
WAITING_CONFIRMATION加后台取消可原子终止并释放设备,App 清理旧任务后继续。 - Top 5 每项保存标题、SKU、价格、两张本地证据;可读项同时保存纯数字
goods_id和唯一规范 PDD URL。 - 非规范域名、路径、额外参数、非数字 ID 和伪造 URL 被拒绝;后端不 fetch 外链。
- Admin 可查看本地图片并安全打开候选商品;无
goods_id候选不能授权自动下单。 - 授权和设备 command hash 覆盖
goods_id/URL,网络重放仍返回同一不可变命令。 - Roubao 优先直达商品页并复核相同
goods_id,再唯一选择颜色、尺码和数量。 - 直达失败或 ID 未能复核时安全停止,不下单。
- 一次性 submission fence、待付款回读和禁止支付边界不回归。
- 上下迁移、Go 标准/race/vet/入口构建和 Android 单测/Debug/Release 构建通过。
边界
- 不承诺始终返回 5 个候选;只能返回实际曝光且证据完整的
0..5项,禁止凑数。 - 不使用分享短链、推广参数、剪贴板账号信息或服务端 PDD 抓取。
- 不把
product_url当作商品身份,不绕过 candidate key、Admin review 或授权版本。 - 不因 VLM 输出直接点击规格;VLM 只辅助语义映射,动作仍需确定性唯一匹配和复读。
- 不自动付款,不在订单已提交状态不确定时重复点击。
- Admin 工作站浏览器登录 PDD 是外部运营前提,本系统不保存其凭证。
执行记录
- 2026-07-29:读取 Obsidian 方案并复核当前代码。确认 observation 已有 URL 字段但 Android 两条候选构造路径均未赋值,Admin 只渲染本地证据;授权/设备命令没有商品 ID/URL, dry-run 使用参考图重新搜索。确认需要后端契约和迁移,不能按旧结论“后端零改动”实施。
- 2026-07-29:现场数据库确认旧
WAITING_CONFIRMATIONclaim 已过期且继续占用设备; 新任务保持PENDING。AppSAFE_STOPPED同步提前返回,后台取消不能被确认,构成自动 接单前必须修复的恢复死锁。 - 2026-07-29:新增 v18 候选商品/授权商品快照,候选键升级为 v2;Admin 只允许授权
完整
goods_id候选,schema v2 设备命令和哈希绑定规范 URL。App 增加语义+本地 OCR ID 提取、自动 claim/start/VLM 或确定性候选链路,以及显式 PDDACTION_VIEW直达。 - 2026-07-29:后端 heartbeat 已原子恢复“后台请求取消且租约过期”的旧执行,App
AUTHORIZATION_EXPIRED会真实 heartbeat 并清理服务端已结束任务。单测覆盖恢复后 同设备继续领取下一任务。 - 2026-07-29:
go test ./...、go test -race ./...、go vet ./...和三个 Go 入口 构建通过;AndroidtestDebugUnitTest、Debug/Release 构建通过。Debug APK 已通过adb install -r安装到 PKG110,保留本地数据;未在迁移 v18 应用前自动启动真实流程。