docs: import wiki at afc651f75a3a
+156
@@ -0,0 +1,156 @@
|
||||
<!-- docs-wiki-sync:docs/tasks/T-256.md@afc651f75a3abc2676bb13aa8a80f6aa6a25a72e -->
|
||||
> 同步来源:[`docs/tasks/T-256.md`](/chengma/mroubao/src/commit/afc651f75a3abc2676bb13aa8a80f6aa6a25a72e/docs/tasks/T-256.md) · commit `afc651f75a3a`
|
||||
|
||||
---
|
||||
id: T-256
|
||||
title: 允许少于目标数量的有效候选进入人工确认
|
||||
phase: 2
|
||||
deps:
|
||||
- T-254
|
||||
status: DOING
|
||||
created: 2026-07-30
|
||||
context_ref: c488e50
|
||||
work_branch: null
|
||||
write_paths:
|
||||
- docs/tasks/T-256.md
|
||||
- docs/current-state.md
|
||||
- android-buyer/app/src/main/**
|
||||
- android-buyer/app/src/test/**
|
||||
---
|
||||
|
||||
## 问题 / 背景
|
||||
|
||||
T-254 的真机计数分布显示,第一轮已经采集到一个**完全合格**的候选:
|
||||
|
||||
| 轮次 | resolved | target | skuMismatch | identityFail | reason |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| 1 | **1** | 2 | 0 | 0 | `CANDIDATE_TARGET_NOT_FOUND` |
|
||||
| 2 | 0 | 1 | 0 | 0 | `CANDIDATE_ALL_EXCLUDED` |
|
||||
| 3 | 0 | 2 | 0 | 0 | `CANDIDATE_ALL_EXCLUDED` |
|
||||
|
||||
该候选颜色尺码硬约束匹配、商品身份解析成功、双证据齐全,但因为
|
||||
`PROCUREMENT_CANDIDATE_TARGET = 2` 而未达标,整条任务判 `FAILED`,候选没有提交给
|
||||
Admin,人工连看都看不到。
|
||||
|
||||
这与需求直接冲突。`docs/02-requirements.md`:
|
||||
|
||||
- 范围决策:「以 SKU 颜色/尺码硬约束过滤后回传 **`0..5` 个**」
|
||||
- F-005 验收:「匹配项按评估结果排序且最多 5 个,**不足时不得凑数**」
|
||||
- 业务规则 20:「回传可以少于 5 个,禁止用弱匹配凑数」
|
||||
|
||||
需求要求的是「不足就少回传」,当前实现做成了「不足就整体失败」。这是本轮采购任务
|
||||
失败的**直接可修复原因**,且不依赖 T-255 对卡片识别率的根治。
|
||||
|
||||
## 关联需求与交互
|
||||
|
||||
- 功能:F-005、F-006、F-007
|
||||
- 用户故事:US-004、US-005
|
||||
- 交互:沿用 Admin 任务详情候选确认区,不新增页面
|
||||
- 架构/API:候选回传与人工确认接口契约不变,**后端零改动**
|
||||
|
||||
## 行为契约
|
||||
|
||||
### 一、候选采集完成判定
|
||||
|
||||
`candidateCollectionReady` 改为:**存在至少一个 `hasResolvedIdentity` 为真的候选**
|
||||
即视为可提交,不再要求达到 `PROCUREMENT_CANDIDATE_TARGET`。
|
||||
|
||||
`PROCUREMENT_CANDIDATE_TARGET = 2` 保留原值和原语义,继续用于计算每轮
|
||||
`roundCandidateTarget`(即「本轮还想再找几个」),但**不再作为成败门槛**。
|
||||
|
||||
### 二、三轮预算继续走满
|
||||
|
||||
有效候选数未达 `PROCUREMENT_CANDIDATE_TARGET` 时,剩余轮次**仍然要执行**,尽量补足。
|
||||
不得因为已经拿到 1 个就提前终止搜索——目标仍是尽量凑够 2 个,只是凑不够不算失败。
|
||||
|
||||
三轮跑完后:
|
||||
|
||||
- 累计有效候选 **≥ 1** → 提交候选并进入 `WAITING_CONFIRMATION`,不写 `FAIL` 终态
|
||||
- 累计有效候选 **= 0** → 维持 T-251 现有的 `CANDIDATE_SEARCH_EXHAUSTED` 可重试 `FAIL`
|
||||
|
||||
### 三、不得凑数
|
||||
|
||||
只有 `hasResolvedIdentity` 为真、且经过既有颜色/尺码硬约束校验的候选才能计入。
|
||||
`identityFailureCode` 非空的观测候选**不计入**这个「至少一个」的判定,其既有的
|
||||
观测保存行为不变。
|
||||
|
||||
### 四、诊断可见性
|
||||
|
||||
提交时的 search run 必须如实记录本次实际提交的候选数与 `PROCUREMENT_CANDIDATE_TARGET`
|
||||
的差距,让 Admin 知道这是「不足目标但可用」而不是「完整 Top N」。沿用 T-254 的
|
||||
诊断 message 机制,不新增字段格式。
|
||||
|
||||
## 方案
|
||||
|
||||
1. `MainActivity.candidateCollectionReady`:判定改为「至少一个 EXACT 或 FALLBACK 的
|
||||
已解析候选」。
|
||||
2. 三轮流程收尾处:区分「有候选 → 提交并进人工确认」与「零候选 → 沿用 T-251 终态」
|
||||
两条路径。
|
||||
3. `roundCandidateTarget` 的计算方式不变,继续按缺口驱动后续轮次。
|
||||
4. 单测覆盖:1 个候选跑完三轮后提交且不写 FAIL、2 个候选行为与现状一致、0 个候选仍
|
||||
写 `CANDIDATE_SEARCH_EXHAUSTED`、仅有未解析身份的观测候选不满足「至少一个」。
|
||||
|
||||
## 验收要点
|
||||
|
||||
- [ ] 三轮累计恰好 1 个有效候选时,任务进入 `WAITING_CONFIRMATION` 且不写 `FAIL` 终态。
|
||||
- [ ] 三轮累计 0 个有效候选时,仍写 T-251 的 `CANDIDATE_SEARCH_EXHAUSTED` 可重试终态。
|
||||
- [ ] 累计 ≥ 2 个时行为与本任务前完全一致,有回归测试证明。
|
||||
- [ ] 只有身份未解析的观测候选时不满足提交条件。
|
||||
- [ ] 已拿到 1 个候选后,剩余轮次仍然执行,不提前终止。
|
||||
- [ ] `PROCUREMENT_CANDIDATE_TARGET` 常量值未改变。
|
||||
- [ ] Android Debug/Release 单测、`lintDebug`、`assembleDebug`、`assembleRelease` 全部通过。
|
||||
- [ ] 真机复跑 T-254 那条任务:第一轮那个候选出现在 Admin 候选确认区,可查看双证据。
|
||||
|
||||
## 边界
|
||||
|
||||
- 不改 `PROCUREMENT_CANDIDATE_TARGET` 的值,也不改 `MAX_CANDIDATES_PER_PROBE`。
|
||||
- 不改 `PinduoduoImageCandidateRoundPolicy` 的三轮预算、timeout、attempts、scrolls。
|
||||
- 不改卡片识别、签名算法或跨轮去重——那是 T-255 的范围。
|
||||
- 不改 T-254 的诊断计数与失败码语义。
|
||||
- 不降低颜色、尺码、身份解析、双证据任何一项校验,不允许用弱匹配或未解析身份的
|
||||
观测候选充数。
|
||||
- 不改后端代码、数据库、API 契约或 Admin 模板。
|
||||
- 不新增第四轮搜索。
|
||||
- 不启动真实下单,不进入订单提交或支付。
|
||||
|
||||
## 执行记录
|
||||
|
||||
开工后记录修改、命令、结果、环境、决策和 blocker。
|
||||
|
||||
### 2026-07-30
|
||||
|
||||
- 状态:开工时由 `TODO` 改为 `DOING`;按用户要求未改为 `DONE`。
|
||||
- 修改:
|
||||
- `MainActivity.candidateCollectionReady` 现在只判断累计候选中是否存在
|
||||
`hasResolvedIdentity` 为真的候选;身份未解析的诊断观测不会满足提交条件。
|
||||
- 新增 `CandidateCollectionPolicy`,将“已有有效候选”“已达到原目标”和“达到第三轮
|
||||
后允许以不足目标数量收尾”分开判定;`PROCUREMENT_CANDIDATE_TARGET = 2`、三轮门禁、
|
||||
`roundCandidateTarget`、`MAX_CANDIDATES_PER_PROBE` 和图片候选预算未修改。
|
||||
- 首轮只有一个有效候选时继续执行第二、第三轮;第三轮结束后将累计有效候选排入
|
||||
`WAITING_CONFIRMATION`,不写 `CANDIDATE_SEARCH_EXHAUSTED`。零个有效候选仍沿用
|
||||
`CANDIDATE_SEARCH_EXHAUSTED` 终态。
|
||||
- 三轮耗尽后的进程恢复也先检查持久化候选;已有有效候选回到正常提交路径,只有零个
|
||||
有效候选才执行既有耗尽失败恢复。
|
||||
- 成功收尾和恢复收尾的 `recordCandidateSearchAttempt` 均复用 T-254 诊断 message,
|
||||
并把本次实际累计提交候选数写入 `resolved`、目标写入 `target`,以显示不足目标但可用。
|
||||
- 新增 `CandidateCollectionPolicyTest`,覆盖 1 个候选三轮收尾、2 个候选原目标行为、
|
||||
0 个候选失败路径和仅身份未解析观测不满足提交条件。
|
||||
- 未修改 `backend-api`、API 契约、数据库、候选识别/去重、SKU 硬约束、三轮预算、下单
|
||||
提交或支付逻辑;未运行 `init.ps1`,未执行 git commit 或 push。
|
||||
- 命令与结果(工作目录:`D:\chengma\cmroubao\android-buyer`,PowerShell):
|
||||
- `.\gradlew.bat testDebugUnitTest --no-daemon`:`BUILD SUCCESSFUL`。
|
||||
- `.\gradlew.bat testReleaseUnitTest --no-daemon`:`BUILD SUCCESSFUL`。
|
||||
- `.\gradlew.bat lintDebug --no-daemon`:`BUILD SUCCESSFUL`。
|
||||
- `.\gradlew.bat assembleDebug --no-daemon`:`BUILD SUCCESSFUL`。
|
||||
- `.\gradlew.bat assembleRelease --no-daemon`:`BUILD SUCCESSFUL`。
|
||||
- 五项命令均退出码 0。
|
||||
- 环境:Windows PowerShell;JDK 17.0.13;Android SDK 34;Gradle Wrapper 8.2。构建输出
|
||||
的 SDK XML 版本提示为既有环境警告,不影响五项目标成功。
|
||||
- 决策:保留既有“达到 2 个 exact 或 2 个 fallback 可提前收尾”的行为;只有累计有效候选
|
||||
少于目标时才要求继续到第三轮。第三轮结束时只要有至少一个已解析身份候选即可提交,
|
||||
以满足不足时少回传而非整体失败的需求。
|
||||
- 未验证 / blocker:无法连接并操作测试真机,也无法在 Admin 任务详情确认候选双证据,
|
||||
因此 T-256 的最终 on-device verification 未完成;需要在测试设备上复跑 T-254 任务并
|
||||
确认一个有效候选进入人工确认区。该 blocker 不影响本次五项 Android Gradle 验证。
|
||||
- 最终复核:补充进程恢复门禁后,以上五条 Gradle 命令均重新执行并再次以退出码 0
|
||||
`BUILD SUCCESSFUL` 结束。
|
||||
Reference in New Issue
Block a user