diff --git a/docs/00-ai-start-here.md b/docs/00-ai-start-here.md index 2723bc2..501f726 100644 --- a/docs/00-ai-start-here.md +++ b/docs/00-ai-start-here.md @@ -56,8 +56,8 @@ 验证。T-201 后端骨架、T-202 P0 原型、T-203 任务 API/管理 Web、T-204 最小鉴权 T-205 原子领取/租约状态机、T-206 Android 登录/有限离线、T-207 本地 VLM/候选/ 证据回传、T-211 参考图召回和 SKU 硬匹配、T-212 候选身份映射,以及 T-213 受控 -规格组合/价格核验均已完成。下一步做 T-208 的逐候选结构化人工理由、修订历史和优化 -数据闭环;不得提前建设报表、训练管线或外部商品抓取。 +规格组合/价格核验均已完成。当前正在实现 T-208 的逐候选结构化人工理由、修订历史 +和优化数据闭环;不得提前建设报表、训练管线或外部商品抓取。 手机从管理后端领取任务并回传结果,VLM、拼多多自动化和人工确认在 App 本地完成。 T-206 增加有限离线执行;T-207 已复用 Roubao 端上 OpenAI 兼容适配器并加密本地 Key。 管理后端不保存/代理 VLM,后台任务不能覆盖手机 provider 配置。 diff --git a/docs/current-state.md b/docs/current-state.md index 95acaad..65da750 100644 --- a/docs/current-state.md +++ b/docs/current-state.md @@ -5,7 +5,7 @@ ## 当前快照 - 日期:2026-07-28 -- 阶段:T-213 已完成;下一任务为 T-208 候选决策数据与人工理由闭环 +- 阶段:T-208 候选决策数据与人工理由闭环进行中 - Git:当前分支为 `main`;T-001 至 T-004、T-101 至 T-104、T-201 至 T-207、T-209、 T-210、T-211、T-212、T-213 均已纳入 Git 历史 - 生产代码:`android-buyer/` 已接入 Roubao Android 源码 @@ -115,6 +115,7 @@ | `docs/tasks/T-211.md` | DONE | 参考图召回、SKU 颜色尺码硬匹配与 0..5 候选回传 | | `docs/tasks/T-212.md` | DONE | 修复重排候选、推荐、证据与人工接受的身份映射 | | `docs/tasks/T-213.md` | DONE | 真机选择目标 SKU、读取组合价并安全返回 | +| `docs/tasks/T-208.md` | DOING | 归一化候选决策数据并增加结构化人工 review | | `docs/design/` | 已确认 | T-202 原型索引、4 个管理页和 7 个 Android 页面 | | `deepseek总结.txt` | 已有 | 历史讨论摘要,不是正式需求权威 | | `android-buyer/` | 已有 | Roubao `main` 固定 commit 的 Android 基线 | @@ -127,8 +128,8 @@ - 已完成:T-001 至 T-004、T-101 至 T-104、T-201 至 T-207、T-209、T-210、T-211、 T-212、T-213。 -- 正在进行:无。 -- 下一个可领取任务:T-208 候选决策数据与人工理由闭环。 +- 正在进行:T-208 候选决策数据与人工理由闭环。 +- 下一个可领取任务:无;先完成 T-208。 - 后置任务:T-208 完成后依次实现商品 持久身份、Admin 下单授权、设备命令、订单 dry-run、单次提交对账和付款提醒。 diff --git a/docs/tasks/T-208.md b/docs/tasks/T-208.md new file mode 100644 index 0000000..8ea0e46 --- /dev/null +++ b/docs/tasks/T-208.md @@ -0,0 +1,157 @@ +--- +id: T-208 +title: 候选决策数据与结构化人工理由闭环 +phase: 2 +deps: + - T-207 + - T-213 +status: DOING +created: 2026-07-28 +context_ref: 4c3b962 +work_branch: null +write_paths: + - docs/tasks/T-208.md + - docs/00-ai-start-here.md + - docs/02-requirements.md + - docs/04-architecture.md + - docs/05-coding-rules.md + - docs/06-tasks.md + - docs/08-interaction-checklist.md + - docs/api.md + - docs/current-state.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/build.gradle.kts + - android-buyer/app/src/main/java/com/roubao/autopilot/MainActivity.kt + - 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/test/java/com/roubao/autopilot/procurement/** + - android-buyer/app/src/test/java/com/roubao/autopilot/ui/** +--- + +## 问题 / 背景 + +T-207 已能回传候选批次、模型评估、本地推荐和一段 `operator_reason`,但后端仍把候选 +主体保存在不可查询 JSON 中,人工说明也不是可用于离线评估的标签。AI 模式还会在 +回传前过滤模型拒绝项,导致无法还原同一次图片搜索实际曝光的候选集合,也无法区分 +召回、模型、推荐策略和人工判断各自的问题。 + +本任务在 20 条真实采购试验前建立可信的数据闭环。它不建设训练管线、外部抓取或 +报表,也不改变候选阶段 `order_submitted=false` 的安全边界。 + +## 关联需求与交互 + +- 功能:F-008。 +- 用户故事:US-008。 +- 交互:IX-009。 +- 依赖:沿用 T-207 的 execution、受控 evidence、加密 outbox 和结果终态;沿用 + T-213 的规格选择摘要与组合价格证据。 + +## 冻结合约 + +### 候选数据层 + +1. 每个 execution 第一版只允许一个候选 search run。`execution_id` 同时作为 run + identity,保存任务内容 hash、精确搜索审计值、App/Android/拼多多版本、开始/接收 + 时间和采集完整性。 +2. `POST /api/v1/tasks/{task_id}/candidates` 继续作为 App 的批量入口,但候选数组改为 + 实际检查的原始连续 ordinal `0..5` 项,不再只上传模型通过项。每项 observation + 保存可见标题、规格、价格、受限外链和已鉴权 evidence;后端绝不请求外链。 +3. AI 模式逐 observation 保存 model evaluation。确定性 recommendation 可指向任一 + 原始 ordinal,但目标必须满足本地颜色/尺码硬约束和当前阈值;不得通过重排改写 + observation ordinal。MANUAL_FIRST 没有 model run/evaluation/recommendation。 +4. 后端在保存候选批次的同一事务内写入 + `candidate_search_runs`、`candidate_observations`、`model_runs`、 + `candidate_evaluations` 和 `candidate_recommendations`;旧 JSON 只作为兼容审计 + 副本,不能继续作为新查询的唯一来源。 + +### 人工 review API + +新增设备鉴权、claim-scoped、幂等的 +`POST /api/v1/tasks/{task_id}/human-reviews`: + +```json +{ + "execution_id": "uuid", + "claim_generation": 1, + "task_content_sha256": "64-char-lowercase-hex", + "reason_schema_version": 1, + "outcome": "CANDIDATE_ACCEPTED", + "selected_candidate_ordinal": 2, + "primary_reason_code": "SELECTED_BEST_MATCH", + "note": "", + "supersedes_review_id": null, + "items": [ + { + "candidate_ordinal": 1, + "label": "REJECT", + "primary_reason_code": "NOT_BEST_MATCH", + "reason_codes": ["NOT_BEST_MATCH"], + "note": "" + }, + { + "candidate_ordinal": 2, + "label": "ACCEPT", + "primary_reason_code": "SKU_MATCH", + "reason_codes": ["SKU_MATCH", "IMAGE_MATCH"], + "note": "" + } + ] +} +``` + +- review 主理由:`SELECTED_BEST_MATCH`、`NO_ACCEPTABLE_CANDIDATE`、 + `INSUFFICIENT_EVIDENCE`、`OTHER`。 +- ACCEPT 理由:`SKU_MATCH`、`IMAGE_MATCH`、`PRICE_ACCEPTABLE`、 + `EVIDENCE_SUFFICIENT`、`OTHER`。 +- REJECT 理由:`SKU_MISMATCH`、`IMAGE_MISMATCH`、`PRICE_TOO_HIGH`、 + `OUT_OF_STOCK`、`EVIDENCE_INSUFFICIENT`、`NOT_BEST_MATCH`、`OTHER`。 +- `OTHER` 的对应备注必须为 4-200 个字符;其他备注可空,非空时同样最多 200 个字符。 +- 无预算任务拒绝 `PRICE_ACCEPTABLE` 和 `PRICE_TOO_HIGH`。 +- 非空候选批次的 review 必须按 ordinal 恰好覆盖每个 observation。接受时恰好一个 + ACCEPT 且等于 `selected_candidate_ordinal`,其余全部 REJECT;拒绝、无匹配或转 + 人工时全部为 REJECT。零候选只允许 `NO_MATCH/MANUAL_REQUIRED` 和空 items。 +- 修订必须引用同一 execution 当前最新 review;服务端追加新版本并建立 + `supersedes_review_id`,不得更新或删除旧版本。 + +### App 与管理端 + +1. App 人工确认不再使用自由文本作为唯一输入。人员必须显式选择候选、接受主理由和 + 其余候选拒绝主理由,或选择全部拒绝理由;模型理由只读且不会预选人工理由。 +2. 第一版 UI 允许人员明确把同一拒绝理由批量应用到所有未选候选,但提交 payload + 仍展开成逐 observation item。 +3. App 先把 HUMAN_REVIEW 放入加密 outbox,再加入兼容的 COMPLETE;网络失败保留 + 同一 idempotency key 和草稿顺序。 +4. Admin 任务详情按 observation、model prediction、deterministic recommendation、 + human review 四个独立区块显示,修订历史按版本可见;受控截图继续走鉴权接口。 + +## 验收要点 + +- [ ] migration `up/down/up` 可重复;有 review 数据时破坏性 down 明确失败。 +- [ ] 最多 5 个原始曝光 observation 按原 ordinal 可查询,模型拒绝项不会丢失。 +- [ ] observation、model evaluation、recommendation 和 human label 分表且引用一致。 +- [ ] human review API 校验理由 allowlist、标签兼容、预算适用性、全候选覆盖、唯一 + 接受项、幂等重放和追加式 supersedes。 +- [ ] App 支持选择推荐项、改选、全部拒绝和零候选;每种路径都产生结构化逐候选理由。 +- [ ] 模型理由不会预填人工理由,旧 `operator_reason` 只保留兼容审计含义。 +- [ ] Admin/API 能读取当前 review 和历史版本,外链不会触发任何服务端网络请求。 +- [ ] Android/Go 单元测试、race、migration、Debug/Release 构建和根验证通过。 + +## 边界 + +- 不实现模型训练、指标报表、数据导出、自动标注或跨任务聚合分析。 +- 不抓取商品页、图片 URL 或平台全量结果,不宣称为全平台 Top 5。 +- 不在本任务创建订单、加入购物车或支付;Admin 下单授权属于后续独立任务。 +- 不把 VLM Key、Authorization、完整 endpoint、供应商原始响应或模型理由写成人工 + 标签。 + +## 执行记录 + +- 2026-07-28:T-213 真机验收提交 `4c3b962` 后领取。审计确认现有 + `execution_candidate_batches`/`execution_outcomes` 只能提供 JSON 审计副本和自由 + 文本说明,AI 模式还会过滤拒绝候选;因此冻结以上归一化数据层和结构化 review + 合约后再开始实现。