feat(t214): persist candidate observation identities

This commit is contained in:
QiuSW
2026-07-28 12:21:55 +08:00
parent acd3c85b5b
commit 56e7a2be33
29 changed files with 622 additions and 94 deletions
+2 -2
View File
@@ -57,8 +57,8 @@
T-205 原子领取/租约状态机、T-206 Android 登录/有限离线、T-207 本地 VLM/候选/
证据回传、T-211 参考图召回和 SKU 硬匹配、T-212 候选身份映射,以及 T-213 受控
规格组合/价格核验均已完成。T-208 的原始候选观测、模型评估、确定性推荐、逐候选
结构化人工理由和修订历史也已完成。当前正在实现 T-214 商品持久身份和重新定位
指纹;之后才能实现 Admin 下单授权,不得直接把候选链接或列表 ordinal 当成授权。
结构化人工理由和修订历史也已完成。T-214 商品持久身份和重新定位指纹也已完成;
下一步实现 T-215 Admin 下单授权,不得直接把候选链接或列表 ordinal 当成授权。
手机从管理后端领取任务并回传结果,VLM、拼多多自动化和人工确认在 App 本地完成。
T-206 增加有限离线执行;T-207 已复用 Roubao 端上 OpenAI 兼容适配器并加密本地 Key。
管理后端不保存/代理 VLM,后台任务不能覆盖手机 provider 配置。
+1
View File
@@ -43,6 +43,7 @@
| 默认分支 | `main` |
| 核实时 `main` commit | `c8a6d7f03422eb01744b01f3ee77bf7757741f7e` |
| `main` 应用版本 | 1.4.2(`versionCode 7`) |
| 当前采购验证版 | 1.4.12(`versionCode 17`) |
| 开发 IDE | Android Studio Hedgehog 2023.1.1 或更高 |
| JDK / JVM target | 17 / 17 |
| Android SDK | compileSdk 34、targetSdk 34、minSdk 26 |
+16 -6
View File
@@ -267,12 +267,13 @@ T-102/T-104 在搜索结果后追加一个有界候选步骤:
-> 一次全局返回并复核固定词结果页
```
候选卡只保留语义指纹和计数,详情/规格截图保存在 App 内部 cache。manifest v3 记录
匿名文件名、截图 SHA-256、字节数、尺寸、有界规格语义、已选摘要和严格组合价格,
不保存商品标题或完整页面
原文。T-104/T-213 使用这些证据时必须通过受控 evidence 边界读取,不能让 VLM adapter
自行遍历 cache。Android 10/API 29 及以下不能运行当前截图探针,应在预检时明确
不支持,不使用媒体投影或 shell 绕过。
候选卡只保留语义指纹和计数,详情/规格截图保存在 App 内部 cache。manifest v4 记录
匿名文件名、卡片/详情语义 SHA-256、截图 SHA-256、字节数、尺寸、有界规格语义、
已选摘要、严格组合价格和 best-effort 页面可见标题;不保存完整页面原文。标题最多
160 字,动作、价格和纯数字文本不会作为标题。T-104/T-213/T-214 使用这些证据时
必须通过受控 evidence 边界读取,不能让 VLM adapter 自行遍历 cache。Android
10/API 29 及以下不能运行当前截图探针,应在预检时明确不支持,不使用媒体投影或
shell 绕过。
`CandidateEvidenceSource` 只接受当前 workflow 内存中的连续 ordinal 元数据,文件名
固定为 `candidate-01-detail.png`/`candidate-01-specification.png` 至第五组;每张
@@ -539,6 +540,7 @@ T-208 已在 T-207 的候选、事件、截图和最小结果回传基础上,
| --- | --- |
| `candidate_search_runs` | execution、需求快照 hash、搜索词、App/拼多多版本、开始/结束时间 |
| `candidate_observations` | run、ordinal、可选平台商品 ID/规范化 URL、可见标题/规格/价格、采集状态和截图 asset |
| `candidate_observation_identities` | execution-scoped candidate key、原 ordinal、卡片/详情语义签名、详情/规格证据 hash 和 identity 版本 |
| `model_runs` | provider/model、prompt/schema/阈值版本、耗时、token/成本和请求/结果 hash |
| `candidate_evaluations` | observation/model run、decision、score/confidence、matched/missing/rejection reasons |
| `candidate_recommendations` | run、推荐 observation、conclusion、确定性策略版本和简短理由 |
@@ -558,6 +560,14 @@ T-208 已在 T-207 的候选、事件、截图和最小结果回传基础上,
图片 URL 只保存为长度受限、规范化的辅助观测值;后端不得盲目请求该 URL。主要证据
必须是 App 上传后由 assetstore 校验、脱敏和受鉴权访问的时间点快照。
T-214 后,v7 以后写入的每个 observation 在同一事务内生成
`candidate_observation_identities`。`candidate_key` 使用版本域、execution ID、原始
ordinal、详情语义签名和规格证据 hash 生成,只标识该次 execution 的持久 observation,
不冒充拼多多全局商品 ID。App 按 `DETAIL`、`SPECIFICATION` 顺序提交两个不同的
evidence asset ID;后端逐一核对其实际 SHA-256 后才接受候选。Admin API/Web 展示
key、四个指纹和受控截图;后续选品授权必须引用 key 并绑定任务内容 hash 和 review
版本,不能只信 URL 或列表 ordinal。
人工理由使用版本化 allowlist。接受或拒绝至少有一个理由且指定主要理由;
`OTHER` 才要求 4-200 字备注。拒绝推荐后改选必须同时产生一条原推荐项负标签和一条
替代项正标签;全部无匹配时每个曝光候选都有负标签。人工修正追加新 review 并引用
+30 -6
View File
@@ -498,9 +498,16 @@ SKU 伪装成图片检索词:
"title": "页面可见标题",
"sku_text": "BLACK-L",
"price": "189.00",
"product_url": "https://mobile.yangkeduo.com/goods.html?goods_id=example",
"image_url": "https://example.invalid/short-lived-image",
"evidence_asset_ids": ["7b733922-f90f-4bc4-a9ad-3e8ec4769122"],
"product_url": "",
"image_url": "",
"card_signature": "64-char-lowercase-hex",
"detail_signature": "64-char-lowercase-hex",
"detail_evidence_sha256": "detail-asset-64-char-lowercase-hex",
"specification_evidence_sha256": "specification-asset-64-char-lowercase-hex",
"evidence_asset_ids": [
"7b733922-f90f-4bc4-a9ad-3e8ec4769122",
"4095ea37-eb4f-47c7-989b-adf060e45a32"
],
"evaluation": {
"decision": "REVIEW",
"score": 0.82,
@@ -539,8 +546,14 @@ SKU 伪装成图片检索词:
`recommendation` 只能指向颜色和尺码均为 `MATCH`、分数和置信度均不低于 `0.75`
且没有拒绝原因的原始 ordinal;没有满足项时只省略 recommendation,不能删除原始
候选。后端在同一事务内写入 search run、observation、model evaluation 和
recommendation,并保留旧 JSON 审计副本;不请求 `product_url` 或 `image_url`,
主要证据必须是已鉴权 asset。
recommendation,并保留旧 JSON 审计副本。每个非空候选必须按
`DETAIL`、`SPECIFICATION` 顺序绑定两个不同的 evidence asset ID,且两个声明哈希
必须分别等于后端保存的实际 asset 哈希;卡片和详情语义签名也必须是小写 SHA-256。
后端用版本化的 execution、原 ordinal、详情签名和规格证据哈希生成稳定的
execution-scoped `candidate_key`。Admin 任务详情在 observation 的 `identity` 中
返回该 key、四个指纹及 identity 版本;旧 v6 observation 可没有 identity。
`product_url` 和 `image_url` 只有设备实际取得可信 URL 时才提交,不能伪造;后端不
请求这些 URL,主要证据必须是已鉴权 asset。
### `POST /api/v1/tasks/{task_id}/human-reviews`
@@ -598,8 +611,19 @@ recommendation,并保留旧 JSON 审计副本;不请求 `product_url` 或 `i
"candidate": {
"ordinal": 1,
"title": "页面可见标题",
"sku_text": "BLACK-L",
"price": "189.00",
"evidence_asset_ids": ["7b733922-f90f-4bc4-a9ad-3e8ec4769122"]
"product_url": "",
"image_url": "",
"card_signature": "64-char-lowercase-hex",
"detail_signature": "64-char-lowercase-hex",
"detail_evidence_sha256": "detail-asset-64-char-lowercase-hex",
"specification_evidence_sha256": "specification-asset-64-char-lowercase-hex",
"evidence_asset_ids": [
"7b733922-f90f-4bc4-a9ad-3e8ec4769122",
"4095ea37-eb4f-47c7-989b-adf060e45a32"
],
"evaluation": null
},
"order_submitted": false
}
+16 -12
View File
@@ -5,9 +5,9 @@
## 当前快照
- 日期:2026-07-28
- 阶段:T-214 候选商品持久身份与重新定位指纹进行中
- 阶段:T-214 已完成;下一步 T-215 Admin 候选确认与下单授权
- Git:当前分支为 `main`;T-001 至 T-004、T-101 至 T-104、T-201 至 T-207、T-209、
T-208、T-210、T-211、T-212、T-213 均已纳入 Git 历史
T-208、T-210、T-211、T-212、T-213、T-214 均已纳入 Git 历史
- 生产代码:`android-buyer/` 已接入 Roubao Android 源码
- Android:固定 `main@c8a6d7f03422eb01744b01f3ee77bf7757741f7e`;MIT 许可证已保留
@@ -17,10 +17,10 @@
- 本机 Android 工具:JDK 17.0.13、Command-line Tools 22.0、SDK 34、
Build Tools 34.0.0、Platform Tools/ADB 37.0.0;用户级 SDK 环境变量已设置
- Android Studio:未安装;`winget` 静默安装卡住后已终止,不阻塞命令行构建
- 测试:T-208 Android 单元测试、Debug/Release 构建和根 `init.ps1` 通过;
Debug APK `1.4.11 (16)` 已安装并启动于 PKG110
- 后端测试:T-208 运行 `go test ./...`、`go test -race ./...`、migration
`up/down/up` 和带 review 数据的降级保护均通过
- 测试:T-214 Android 单元测试、Debug/Release 构建和根 `init.ps1` 通过;
Debug APK `1.4.12 (17)` 已安装并启动于 PKG110
- 后端测试:T-214 运行 `go test ./...`、`go test -race ./...`、`go vet ./...`、
migration `up/down/up` 和带 identity 数据的降级保护均通过
- 原型:4 个管理 Web 页面和 7 个 Android 页面均可离线独立打开;Playwright
以 1440×900、390×844、360×800 验证 36 个页面/视口组合,无页面横向溢出、
脚本错误或外部请求,Android 可见交互控件均不小于 44px
@@ -60,6 +60,10 @@
人民币组合价和详情/规格双证据,并允许明确的“首件¥金额”当前单件价。区间、
券后、对照促销、冲突或缺失价格降级 `UNKNOWN`,直达订单确认页只系统返回。候选
探查不能加入购物车、提交订单或触发支付。
- T-214 候选身份:App 回传卡片/详情语义签名和详情/规格双证据 hash;后端逐一核对
已上传 asset 后,在 v7 表中生成 execution-scoped `candidate_key`。Admin API/Web
展示 key、指纹、原始 observation、模型/人工结论和截图;缺少真实平台 URL 时保持
空值,后端不请求第三方 URL。
- Workflow:纯 Kotlin runner 已支持步骤 timeout、最多 3 次 retry、安全阻塞、
用户停止和单 runner 并发拒绝;T-102 已接入搜索加有界候选采集五步
- TaskSource:严格 CLI 已生成并验证真实私有 ProbeTask;默认 APK 不含私有 fixture
@@ -73,7 +77,7 @@
- 离线执行:默认 30 分钟有限授权和 30 秒 best-effort heartbeat 已实现;PKG110
真机断开临时后端 95 秒后保持同一 execution,重连后滑动续期;到期持久安全停止,
RUNNING 不自动重新分配
- 测试设备:OnePlus PKG110,Android 16/API 36;肉包 `1.4.11 (16)`;拼多多
- 测试设备:OnePlus PKG110,Android 16/API 36;肉包 `1.4.12 (17)`;拼多多
`8.17.0 (81700)`
- 设备就绪:拼多多首页、文字/图片搜索、双列候选卡、详情截图和返回均已通过 8.17.0
真机验证;采购员已在 ColorOS 设置中手动启用肉包采购无障碍,APK 覆盖安装后授权
@@ -88,7 +92,7 @@
已用 CLI 真实导入并逐字段/图片哈希验证,生成物位于被忽略的 `.local/`
- 标准启动路径:`$env:RUN_START_COMMAND="1"; .\init.ps1`
- 标准验证路径:`.\init.ps1`
- 当前 blocker:T-208 无阻塞。真实 VLM 服务地址、模型、设备级测试凭证、成本上限
- 当前 blocker:T-214 无阻塞。真实 VLM 服务地址、模型、设备级测试凭证、成本上限
和数据留存尚未确认;当前只支持单 SKU/JPEG;候选探针截图要求 Android 11/API 30+
## 当前目录
@@ -118,7 +122,7 @@
| `docs/tasks/T-212.md` | DONE | 修复重排候选、推荐、证据与人工接受的身份映射 |
| `docs/tasks/T-213.md` | DONE | 真机选择目标 SKU、读取组合价并安全返回 |
| `docs/tasks/T-208.md` | DONE | 归一化候选决策数据并增加结构化人工 review |
| `docs/tasks/T-214.md` | DOING | 建立 execution-scoped candidate key 与设备采集指纹 |
| `docs/tasks/T-214.md` | DONE | 建立 execution-scoped candidate key 与设备采集指纹 |
| `docs/design/` | 已确认 | T-202 原型索引、4 个管理页和 7 个 Android 页面 |
| `deepseek总结.txt` | 已有 | 历史讨论摘要,不是正式需求权威 |
| `android-buyer/` | 已有 | Roubao `main` 固定 commit 的 Android 基线 |
@@ -129,9 +133,9 @@
## 任务摘要
- 已完成:T-001 至 T-004、T-101 至 T-104、T-201 至 T-213。
- 正在进行:T-214 商品持久身份与重新定位指纹。
- 下一步:依次实现 Admin 下单授权、设备命令、订单 dry-run、单次提交对账和
- 已完成:T-001 至 T-004、T-101 至 T-104、T-201 至 T-214。
- 正在进行:无。
- 下一步:依次实现 T-215 Admin 下单授权、设备命令、订单 dry-run、单次提交对账和
付款提醒。
## 当前可运行内容
+18 -8
View File
@@ -5,13 +5,14 @@ phase: 2
deps:
- T-208
- T-213
status: DOING
status: DONE
created: 2026-07-28
context_ref: e7f4c3e
work_branch: null
write_paths:
- docs/tasks/T-214.md
- docs/00-ai-start-here.md
- docs/03-tech-stack.md
- docs/04-architecture.md
- docs/06-tasks.md
- docs/api.md
@@ -71,13 +72,13 @@ T-208 已能保存原始候选 observation 和人工结论,但 Admin 与后续
## 验收要点
- [ ] v7 migration `up/down/up` 可重复;有 identity 数据时破坏性 down 失败。
- [ ] App 回传全部 observation 的卡片/详情/双证据 SHA-256,不因模型拒绝而缺失。
- [ ] 后端拒绝格式错误、跨 execution、与 evidence 实际哈希不一致的指纹。
- [ ] 同一请求重放 candidate key 稳定,不同 observation key 不同。
- [ ] Admin API/Web 可按 candidate key 查看 observation、模型判断、人工结论和截图。
- [ ] 后端不会请求候选 URL;没有真实 URL 时保持空值而不是生成伪链接。
- [ ] Android/Go 测试、race、migration、Debug/Release 和根验证通过。
- [x] v7 migration `up/down/up` 可重复;有 identity 数据时破坏性 down 失败。
- [x] App 回传全部 observation 的卡片/详情/双证据 SHA-256,不因模型拒绝而缺失。
- [x] 后端拒绝格式错误、跨 execution、与 evidence 实际哈希不一致的指纹。
- [x] 同一请求重放 candidate key 稳定,不同 observation key 不同。
- [x] Admin API/Web 可按 candidate key 查看 observation、模型判断、人工结论和截图。
- [x] 后端不会请求候选 URL;没有真实 URL 时保持空值而不是生成伪链接。
- [x] Android/Go 测试、race、migration、Debug/Release 和根验证通过。
## 边界
@@ -91,3 +92,12 @@ T-208 已能保存原始候选 observation 和人工结论,但 Admin 与后续
- 2026-07-28:T-208 实现提交 `e7f4c3e` 后领取。确认当前 observation 已有可选
product/image URL 和受控 evidence,但 App 实际无法从拼多多无障碍树取得可信 URL,
因此冻结 execution-scoped candidate key 与多指纹方案。
- 2026-07-28:App manifest 升级到 v4,保存 best-effort 可见标题、卡片/详情语义
SHA-256 和详情/规格双截图哈希;候选出站固定提交两个不同的 evidence asset。
- 2026-07-28:后端 migration v7 增加 `candidate_observation_identities`,候选写入
同事务生成稳定 key,并按顺序核对两个 evidence 的实际哈希。Admin API/Web 已能
查看 identity、原始 observation、模型/人工结论和受控截图。
- 2026-07-28:`go test ./...`、`go test -race ./...`、`go vet ./...`,migration
CLI `up/down/up`,Android `test assembleDebug assembleRelease` 和根
`.\init.ps1` 全部通过。Debug APK `1.4.12 (17)` 已覆盖安装到 PKG110,采购无障碍
仍在启用列表。