diff --git a/T-207.-.md b/T-207.-.md new file mode 100644 index 0000000..572b8dc --- /dev/null +++ b/T-207.-.md @@ -0,0 +1,134 @@ + +> 同步来源:[`docs/tasks/T-207.md`](/chengma/mroubao/src/commit/afc651f75a3abc2676bb13aa8a80f6aa6a25a72e/docs/tasks/T-207.md) · commit `afc651f75a3a` + +--- +id: T-207 +title: 接入 App 本地 VLM、候选、事件和结果回传 +phase: 2 +deps: + - T-206 +status: DONE +created: 2026-07-27 +context_ref: 45d1436 +work_branch: null +write_paths: + - README.md + - android-buyer/** + - backend-api/** + - 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/07-user-stories.md + - docs/08-interaction-checklist.md + - docs/api.md + - docs/current-state.md + - docs/routes.md + - docs/tasks/T-207.md + - progress.md +--- + +## 问题 / 背景 + +T-206 跑通任务领取和有限离线生命周期后,还需要把现有 App 本地 VLM、最多 5 个 +候选、截图、事件、失败和人工结论接入后台任务,并在网络恢复后可靠回传。 + +手机独立执行意味着后端不保存 VLM Key、不代理模型请求,也不决定具体 provider。 +代价是不同设备的模型和提示词可能不同,因此结果必须携带非秘密 provenance,管理端 +才能区分搜索、模型和人工判断。端上 Key 只能做到受控保护,Root/受控设备仍可能在 +运行时提取,所以必须使用独立、可撤销、有限额度的设备 Key。 + +## 关联需求与交互 + +- 功能:F-002、F-004、F-005、F-006、F-007、F-009。 +- 用户故事:US-002、US-004、US-005、US-006、US-009。 +- 交互:IX-003、IX-006、IX-007、IX-008、IX-010。 +- 架构/API:App 本地 VLM Gateway、候选/事件/资产、加密 outbox、 + `complete`/`fail` 和管理任务详情。 + +## 已定合约 + +1. 数据流固定为:App 从管理后端领取任务;App 直接调用本机已配置的 OpenAI 兼容 + VLM;App 操作拼多多并人工确认;App 向管理后端回传结构化结果和证据。 +2. 管理后端不保存或下发 VLM provider、Base URL、model、prompt 或 API Key,不实现 + `/tasks/{id}/ai/*` 代理接口,也不根据候选外链请求第三方网络。 +3. 后台任务不能覆盖 App 的 VLM 配置。执行开始时 App 把 provider ID、model、 + prompt version、schema version 和相关证据 SHA-256 固定为 execution provenance; + API Key、Authorization 和完整 Base URL 不进入结果。 +4. App 支持 `MANUAL_FIRST` 与 `AI_ASSISTED`。前者直接从原始标题/SKU产生有界搜索词并 + 由人员判断;后者调用本地 VLM 做需求提取和候选评估。VLM 不可用不能阻止人员完成 + 任务,但模式切换必须显式记录,不能静默降级。 +5. 现有 provider 设置保留,API Key 从普通 SharedPreferences 迁移到 + Android Keystore 包装的加密存储;迁移成功后删除旧明文,失败时不继续真实调用。 +6. 每台采购设备使用独立、可撤销、有限额度的 provider Key。Release 远程端点只允许 + HTTPS,禁止 userinfo/query/fragment/重定向;HTTP 只用于 Debug 无 Key 本机 mock。 +7. 每个 execution 最多一次需求提取、最多 5 次按 ordinal 串行候选评估。模型输出经 + 严格 schema、大小、置信度和确定性约束校验,不能授权点击、人工结论或订单提交。 +8. SKU、数量、预算和参考图来自后端原任务。App 不把订单号、店铺名、数量或本机路径 + 发给 provider,只发送必要标题、SKU、参考图和当前候选受控证据。 +9. 候选观测、模型判断、本地确定性推荐和人工理由分开序列化。T-207 要求简短 + `operator_reason`;T-208 再增加逐候选结构化 reason code 和修订版本。 +10. App 使用加密 outbox 幂等上传事件、截图、候选、complete/fail。后端以 + task/execution/device/claim 重新授权,校验任务哈希、asset、状态和幂等键。 +11. App 可以在执行授权内完成后离线上传。授权过期后的补报标记 + `received_after_execution_expiry=true`,但服务端不把补报等同于允许过期后继续 + 自动化;管理详情必须显示该审计状态。 +12. 所有终态强制 `order_submitted=false`。人员确认后不恢复自动点击,安全/取消错误 + 不重试,后端结果 API 没有订单或支付权限。 + +## 方案 + +1. Android 把现有 SettingsManager/provider secret 迁移到 Keystore-backed store, + 保留 Roubao 独立模式;为后台 execution 增加不可变本地 provenance snapshot。 +2. 用已有 RequirementExtractor、CandidateEvaluator 和 workflow 处理 + `HttpTaskSource` 任务,增加 `MANUAL_FIRST` 显式分支和禁止任务覆盖 provider 的 + 契约测试。 +3. 新增本地加密 execution/outbox,按事件、资产、候选和终态的依赖顺序上传;网络 + 结果不确定时复用原幂等键,进程重启后继续同步但不继续已停止的自动化。 +4. 后端新增候选、执行事件、outcome/error 和 evidence migration,以及鉴权 asset、 + events、candidates、complete、fail API;不新增 provider 表、Key 或第三方 HTTP。 +5. 完整结果保存 task/execution ID、任务内容哈希、App/Android/拼多多版本、模式、 + 搜索词、最多 5 个候选、VLM provenance/判断、本地推荐、人工结论、错误和 + `order_submitted=false`。 +6. 管理任务详情展示原始输入、设备/版本、候选、模型判断、推荐、人工理由、事件、 + 离线补报标志和鉴权证据,各层信息不合并。 + +## 验收要点 + +- [x] Roubao 原有独立模式和 provider 选择可继续使用;旧 Key 成功迁移后普通 + SharedPreferences 无明文,迁移/解密失败安全阻断真实调用。 +- [x] 后台任务 payload 无 provider 地址、模型或 Key;伪造这些字段被拒绝/忽略且 + 不能修改 App 设置。 +- [x] `MANUAL_FIRST` 在无 VLM 时能完成候选采集和人工确认;`AI_ASSISTED` 由 App + 直连配置的 HTTPS provider,抓包/测试证明管理后端不代理模型。 +- [x] 最多一次需求提取、最多 5 个候选评估;SKU/数量/预算保持原值,低置信度、 + 无效 schema、超预算、证据不足和越权输出转人工或拒绝。 +- [x] 结果包含 provider/model/prompt/schema 和证据哈希但不含 Key、Authorization、 + 完整 endpoint、订单号、店铺名或供应商原始响应正文。 +- [x] 事件、截图、候选、complete/fail 在断网、进程重启和响应丢失后不重复;授权 + 过期补报可审计,后台不会把 RUNNING 自动分给其他设备。 +- [x] 接受、拒绝、无匹配和转人工均要求 `operator_reason`;管理详情可还原执行过程, + 并明确显示 `order_submitted=false`。 +- [ ] migration up/down/up、Go unit/integration/race/vet、Android unit/instrumented、 + Playwright 三视口、根 `init.ps1` 和 OnePlus PKG110 真机 smoke 通过。 + +## 边界 + +- 不实现后端 VLM 配置/代理、多设备统一模型、自动 provider 路由或费用报表。 +- 不实现 T-208 的结构化人工标签、修订历史、离线评估或训练管线。 +- 不下载客户端提交的任意商品/图片 URL,不自动提交订单、支付或绕过风险控制。 +- 不承诺 Keystore 能抵抗已 Root/完全受控设备;不提交真实 Key、订单或证据。 + +## 执行记录 + +- 2026-07-27:开始实现后端 execution 结果审计、Android 加密 outbox 与本地 VLM/ + 候选流程接入。 +- 2026-07-27:实现 `00005_execution_results`、设备结果 API、管理详情审计展示和 + Android Keystore 凭证 fail-closed 迁移。Android 候选流程按手工/AI 模式生成加密 + outbox,结果以同一幂等键重放;Go HTTP 集成测试和 Android debug/unit test 已通过。 +- 2026-07-27:未执行真实 VLM、真实后台或 OnePlus PKG110 端到端 smoke;没有真实凭证 + 的真实模型调用未执行。OnePlus PKG110 已安装 Debug APK 并启动到任务登录页,无 + crash/ANR;真实后台和端到端候选回传仍需要单独的测试账号/任务。 +- 2026-07-27:根目录 `init.ps1`(`RUN_START_COMMAND=1`)通过,覆盖 Android + 全模块测试与 Debug 构建、Go 测试/vet/构建,并重新安装、冷启动 Debug APK。