缺陷:采购规格已选中但最终复核因候选滚出视口而误判失败 #171

Open
opened 2026-08-31 15:42:19 +08:00 by ila · 1 comment
Owner

基本信息

  • 类型:缺陷
  • 所属 Epic:无
  • 所属 MVP / 版本:采购正式执行安全闭环
  • 阶段:待验收

依赖与并行

  • 前置工单:无;关联历史修复 #151、#160、#164
  • 是否允许与前置工单并行:是
  • 原因:本单修复最终核单阶段的独立假阴性,不改变既有规格映射或规格探测流程。

子项目影响

  • 仅影响的子项目 / 交付单元:android
  • 是否跨子项目:否
  • 是否修改共享接口或契约:否;继续使用 PURCHASE_SPEC_SELECTION_UNCONFIRMED
  • 各子项目需要执行的验证:Android 单元测试与 Debug APK 构建;真机正式采购另行授权

原始需求

  • 来源:用户对话
  • 提出时间:2026-08-31
  • 关键原话或脱敏摘要:最新 APK 执行采购任务 38,页面已选中杏色和 XL,但连续两次报“最终规格复核未能确认精确选中状态”;用户确认按分析建议建单修复。
  • Gitea 交互说明:本会话未提供可用 Gitea MCP 工具,按仓库规则回退项目已配置的 Gitea API 创建本工单;凭据仅从 gitea.env 读取,未写入工单或日志。

要解决什么

  • 当前代码事实:
    • 设备安装版本为 versionCode=48、versionName=0.9.35。
    • 采购任务 38 固化规格为颜色 杏色、尺码 XL 建议120-140斤左右。
    • 2026-08-31 15:29~15:30 的两次 attempt 均以 PURCHASE_SPEC_SELECTION_UNCONFIRMED / 最终规格复核未能确认精确选中状态 结束。
    • 两次均未进入不可逆边界,未创建 PDD 订单。
    • Android isExactSpecSelected 在当前节点未暴露 selected/checked 时,要求“已选摘要命中”且当前视口仍存在唯一精确候选;选择后页面重排或查找后一维规格发生滚动时,前一维候选可能已不可见。
    • verifySummary 在单个最终快照中依次复核全部目标维度;任一维度候选滚出视口,即使已选摘要仍正确也会返回统一失败。
    • 现有 Fake 驱动始终同时渲染颜色、尺码与摘要,未覆盖最终核单时某一维度候选不可见的真实布局。
  • 复现步骤:
    1. 使用任务 38 的同类双维度商品,先选颜色,再定位位于面板下方的尺码。
    2. PDD 因规格选择重排,或 Agent 为定位尺码滚动面板,使颜色候选离开当前视口。
    3. 页面“已选”摘要仍显示目标颜色与尺码,进入 verifyOrderSummary。
    4. 最终复核因当前候选列表为空或不完整返回 PURCHASE_SPEC_SELECTION_UNCONFIRMED。
  • 实际结果:规格视觉上已选中,但任务失败;相同商品与布局重试会确定性复现。
  • 目标契约 / 用户期望:最终核单既不因候选滚出视口误报,也不能仅凭模糊摘要把 XL 错认成 2XL,或在同一主尺码 Token 对应多个候选时猜测。
  • 假设与未确认项:历史记录按安全规则不保存原始控件树和整屏截图,无法追溯本次具体丢失颜色还是尺码证据;实现必须补充不含规格文案、坐标或原始节点的安全诊断。

做什么 / 不做什么

  • 做:
    • 在每个规格完成即时精确确认时,内存中保存该维度的选择证明:维度、规范化目标、当时唯一候选关系及确认来源。
    • 最终复核优先接受当前节点明确的 selected/checked;节点已不可见时,只在“当前摘要精确 Token 命中 + 该维度存在先前唯一选择证明”同时成立时确认。
    • 尺码继续使用边界明确的主 Token,确保 XL 不匹配 2XL;同一 Token 对应多个原始候选时仍失败。
    • 最终失败保留稳定错误码,并记录安全的失败维度、面板类型、摘要是否存在/命中、候选数量和确认来源;不记录目标文案、坐标、控件树或截图。
    • 增加候选滚出视口、长尺码摘要缩写、XL/2XL、重复主 Token、摘要缺失和证据漂移测试。
  • 不做:
    • 不放宽服务端规格映射,不点击相近规格,不使用 OCR/VLM。
    • 不修改采购规则快照、API、数据库、权限、支付边界或任务重试语义。
    • 不执行付款。
    • 未经单独真机授权,不重跑正式采购任务、不修改地址、不创建待付款订单。

已确认方案

以“即时唯一选择证明 + 最终当前摘要”替代“最终摘要 + 最终视口候选”的错误耦合:

  1. 选择颜色/尺码时仍必须从当前解析候选中逐字定位唯一目标,并在点击后通过当前节点状态或安全摘要确认。
  2. 只有即时确认成功才生成内存选择证明;证明绑定维度和完整规范化目标,不跨任务、不持久化、不跨 attempt 复用。
  3. 最终核单时:
    • 当前可见唯一目标节点带 selected/checked:直接通过;
    • 目标节点不可见:必须同时满足本 attempt 的唯一选择证明仍与完整目标一致,且当前已选摘要精确命中颜色或尺码 Token;
    • 证明缺失、目标变化、摘要缺失、Token 不精确或候选歧义:继续安全失败。
  4. 保持 PURCHASE_SPEC_SELECTION_UNCONFIRMED 和创建订单前停止语义不变。

预计修改文件:

  • android/app/src/main/java/cn/ilapage/goauto/agent/automation/PurchaseRehearsalExecutor.kt
  • android/app/src/test/java/cn/ilapage/goauto/agent/PurchaseRehearsalExecutorTest.kt
  • 若安全诊断复用需要,最小修改 Android 采购执行相关测试/诊断类型,不扩展服务端契约。

需求变化记录

日期 变化内容 原因 用户确认
2026-08-31 按上述根因与修复建议建单 任务 38 连续两次假阴性 是

设计与原型门禁

  • 修改类型:恢复既有行为的 Bug / 非 UI
  • 所需设计证据:原设计和任务 38 复现证据、上述安全判定流程
  • 可编辑设计源、线上原型链接和访问检查:不适用
  • 审核版本、revision、复制版本或确认日期及识别方式:2026-08-31 用户确认文字方案
  • 本地 HTML 导出:未要求
  • 本地 HTML 路径、版本和资源检查(仅显式导出时填写):不适用
  • 状态:已确认
  • 确认人、确认时间和覆盖范围:用户,2026-08-31;覆盖最终规格复核假阴性修复,不覆盖下单真机验收
  • 无需 UI 原型或无需任何原型的原因:不改变页面、交互、接口或数据,仅修复 Android 创建订单前的内部安全判定。

文档影响

  • 不影响长期文档,原因:不改变“只执行精确规格、无法确认即失败”的长期业务规则与 API 错误码,仅修复实现对滚出视口的误判。
  • 更新项目档案或本地开发与验证 Wiki
  • 更新常见修改或故障排查 Wiki
  • 更新架构与代码地图 Wiki
  • 更新业务规则与术语 Wiki
  • 更新 API 契约 Wiki
  • 更新产品需求、常见修改或故障排查 Wiki

交付文档影响

  • 无交付文档影响,原因:无用户流程或运维方式变化。
  • 更新已有交付文档,受众与页面:
  • 新增交付文档,受众与页面:
  • 需要目标岗位或客户代表验证:是;验证方式:另行授权后在同一设备、同一 App 版本、同一规则快照下真机验证,永久不支付。

任务记录与可选快照

  • 单次任务事实来源:当前 Gitea 工单正文与评论
  • 默认不创建任务快照
  • 用户明确要求专项快照;用途和范围:
  • 项目专用规则要求任务快照;规则入口:

验收标准

  • 双维度商品选择尺码后颜色候选滚出视口,当前摘要精确包含目标颜色和目标尺码时,最终规格复核通过。
  • 尺码候选滚出视口但本 attempt 已建立唯一选择证明,摘要只显示长尺码的唯一主 Token(如 XL)时可以通过。
  • 摘要中的 2XL 不能证明目标 XL。
  • 同一主 Token 对应多个原始尺码候选时不得凭短摘要通过。
  • 任一维度没有即时唯一选择证明、摘要缺失/不精确或目标发生漂移时,仍返回 PURCHASE_SPEC_SELECTION_UNCONFIRMED,且不进入修改地址或创建订单。
  • 诊断只包含安全枚举/计数,不包含规格文案、坐标、控件树、截图、账号、地址、订单或支付数据。
  • 既有采购执行单元测试通过,Debug APK 构建成功。
  • 不修改共享 API、数据库和长期 Wiki。

验证方式

  • cd android; .\gradlew.bat testDebugUnitTest --tests cn.ilapage.goauto.agent.PurchaseRehearsalExecutorTest
  • cd android; .\gradlew.bat assembleDebug
  • 只读确认任务 38 两次历史失败和不可逆边界均为空。
  • 真机验证:本单代码验证完成后另行取得人工授权;只验证至最终核单/创建订单前门禁,永久不支付。若正式规则会继续执行创建订单,则必须使用受控方式在不可逆动作前停止,或由独立授权明确允许创建待付款订单。

风险和回退

  • 风险:错误复用历史证明可能放行错误规格,进而创建错误的待付款订单。
  • 控制:证明只存在当前 executor / 当前 attempt 内;绑定维度和完整目标;仍要求当前摘要精确 Token;歧义、缺失和漂移全部失败;不跨任务持久化。
  • 回退:恢复为现有最终视口强校验逻辑;任务仍安全失败,不影响数据库和接口。
  • 高风险门禁:这是正式采购创建订单前的安全判定修改。创建工单后先等待人工实施确认;真机或正式采购重跑前再次取得独立授权,且永久禁止支付。
## 基本信息 - 类型:缺陷 - 所属 Epic:无 - 所属 MVP / 版本:采购正式执行安全闭环 - 阶段:待验收 ## 依赖与并行 - 前置工单:无;关联历史修复 #151、#160、#164 - 是否允许与前置工单并行:是 - 原因:本单修复最终核单阶段的独立假阴性,不改变既有规格映射或规格探测流程。 ## 子项目影响 - 仅影响的子项目 / 交付单元:android - 是否跨子项目:否 - 是否修改共享接口或契约:否;继续使用 `PURCHASE_SPEC_SELECTION_UNCONFIRMED` - 各子项目需要执行的验证:Android 单元测试与 Debug APK 构建;真机正式采购另行授权 ## 原始需求 - 来源:用户对话 - 提出时间:2026-08-31 - 关键原话或脱敏摘要:最新 APK 执行采购任务 38,页面已选中杏色和 XL,但连续两次报“最终规格复核未能确认精确选中状态”;用户确认按分析建议建单修复。 - Gitea 交互说明:本会话未提供可用 Gitea MCP 工具,按仓库规则回退项目已配置的 Gitea API 创建本工单;凭据仅从 `gitea.env` 读取,未写入工单或日志。 ## 要解决什么 - 当前代码事实: - 设备安装版本为 `versionCode=48`、`versionName=0.9.35`。 - 采购任务 38 固化规格为颜色 `杏色`、尺码 `XL 建议120-140斤左右`。 - 2026-08-31 15:29~15:30 的两次 attempt 均以 `PURCHASE_SPEC_SELECTION_UNCONFIRMED / 最终规格复核未能确认精确选中状态` 结束。 - 两次均未进入不可逆边界,未创建 PDD 订单。 - Android `isExactSpecSelected` 在当前节点未暴露 `selected/checked` 时,要求“已选摘要命中”且当前视口仍存在唯一精确候选;选择后页面重排或查找后一维规格发生滚动时,前一维候选可能已不可见。 - `verifySummary` 在单个最终快照中依次复核全部目标维度;任一维度候选滚出视口,即使已选摘要仍正确也会返回统一失败。 - 现有 Fake 驱动始终同时渲染颜色、尺码与摘要,未覆盖最终核单时某一维度候选不可见的真实布局。 - 复现步骤: 1. 使用任务 38 的同类双维度商品,先选颜色,再定位位于面板下方的尺码。 2. PDD 因规格选择重排,或 Agent 为定位尺码滚动面板,使颜色候选离开当前视口。 3. 页面“已选”摘要仍显示目标颜色与尺码,进入 `verifyOrderSummary`。 4. 最终复核因当前候选列表为空或不完整返回 `PURCHASE_SPEC_SELECTION_UNCONFIRMED`。 - 实际结果:规格视觉上已选中,但任务失败;相同商品与布局重试会确定性复现。 - 目标契约 / 用户期望:最终核单既不因候选滚出视口误报,也不能仅凭模糊摘要把 `XL` 错认成 `2XL`,或在同一主尺码 Token 对应多个候选时猜测。 - 假设与未确认项:历史记录按安全规则不保存原始控件树和整屏截图,无法追溯本次具体丢失颜色还是尺码证据;实现必须补充不含规格文案、坐标或原始节点的安全诊断。 ## 做什么 / 不做什么 - 做: - 在每个规格完成即时精确确认时,内存中保存该维度的选择证明:维度、规范化目标、当时唯一候选关系及确认来源。 - 最终复核优先接受当前节点明确的 `selected/checked`;节点已不可见时,只在“当前摘要精确 Token 命中 + 该维度存在先前唯一选择证明”同时成立时确认。 - 尺码继续使用边界明确的主 Token,确保 `XL` 不匹配 `2XL`;同一 Token 对应多个原始候选时仍失败。 - 最终失败保留稳定错误码,并记录安全的失败维度、面板类型、摘要是否存在/命中、候选数量和确认来源;不记录目标文案、坐标、控件树或截图。 - 增加候选滚出视口、长尺码摘要缩写、`XL/2XL`、重复主 Token、摘要缺失和证据漂移测试。 - 不做: - 不放宽服务端规格映射,不点击相近规格,不使用 OCR/VLM。 - 不修改采购规则快照、API、数据库、权限、支付边界或任务重试语义。 - 不执行付款。 - 未经单独真机授权,不重跑正式采购任务、不修改地址、不创建待付款订单。 ## 已确认方案 以“即时唯一选择证明 + 最终当前摘要”替代“最终摘要 + 最终视口候选”的错误耦合: 1. 选择颜色/尺码时仍必须从当前解析候选中逐字定位唯一目标,并在点击后通过当前节点状态或安全摘要确认。 2. 只有即时确认成功才生成内存选择证明;证明绑定维度和完整规范化目标,不跨任务、不持久化、不跨 attempt 复用。 3. 最终核单时: - 当前可见唯一目标节点带 `selected/checked`:直接通过; - 目标节点不可见:必须同时满足本 attempt 的唯一选择证明仍与完整目标一致,且当前已选摘要精确命中颜色或尺码 Token; - 证明缺失、目标变化、摘要缺失、Token 不精确或候选歧义:继续安全失败。 4. 保持 `PURCHASE_SPEC_SELECTION_UNCONFIRMED` 和创建订单前停止语义不变。 预计修改文件: - `android/app/src/main/java/cn/ilapage/goauto/agent/automation/PurchaseRehearsalExecutor.kt` - `android/app/src/test/java/cn/ilapage/goauto/agent/PurchaseRehearsalExecutorTest.kt` - 若安全诊断复用需要,最小修改 Android 采购执行相关测试/诊断类型,不扩展服务端契约。 ## 需求变化记录 | 日期 | 变化内容 | 原因 | 用户确认 | |---|---|---|---| | 2026-08-31 | 按上述根因与修复建议建单 | 任务 38 连续两次假阴性 | 是 | ## 设计与原型门禁 - 修改类型:恢复既有行为的 Bug / 非 UI - 所需设计证据:原设计和任务 38 复现证据、上述安全判定流程 - 可编辑设计源、线上原型链接和访问检查:不适用 - 审核版本、revision、复制版本或确认日期及识别方式:2026-08-31 用户确认文字方案 - 本地 HTML 导出:未要求 - 本地 HTML 路径、版本和资源检查(仅显式导出时填写):不适用 - 状态:已确认 - 确认人、确认时间和覆盖范围:用户,2026-08-31;覆盖最终规格复核假阴性修复,不覆盖下单真机验收 - 无需 UI 原型或无需任何原型的原因:不改变页面、交互、接口或数据,仅修复 Android 创建订单前的内部安全判定。 ## 文档影响 - [x] 不影响长期文档,原因:不改变“只执行精确规格、无法确认即失败”的长期业务规则与 API 错误码,仅修复实现对滚出视口的误判。 - [ ] 更新项目档案或本地开发与验证 Wiki - [ ] 更新常见修改或故障排查 Wiki - [ ] 更新架构与代码地图 Wiki - [ ] 更新业务规则与术语 Wiki - [ ] 更新 API 契约 Wiki - [ ] 更新产品需求、常见修改或故障排查 Wiki ## 交付文档影响 - [x] 无交付文档影响,原因:无用户流程或运维方式变化。 - [ ] 更新已有交付文档,受众与页面: - [ ] 新增交付文档,受众与页面: - [x] 需要目标岗位或客户代表验证:是;验证方式:另行授权后在同一设备、同一 App 版本、同一规则快照下真机验证,永久不支付。 ## 任务记录与可选快照 - 单次任务事实来源:当前 Gitea 工单正文与评论 - [x] 默认不创建任务快照 - [ ] 用户明确要求专项快照;用途和范围: - [ ] 项目专用规则要求任务快照;规则入口: ## 验收标准 - [ ] 双维度商品选择尺码后颜色候选滚出视口,当前摘要精确包含目标颜色和目标尺码时,最终规格复核通过。 - [ ] 尺码候选滚出视口但本 attempt 已建立唯一选择证明,摘要只显示长尺码的唯一主 Token(如 `XL`)时可以通过。 - [ ] 摘要中的 `2XL` 不能证明目标 `XL`。 - [ ] 同一主 Token 对应多个原始尺码候选时不得凭短摘要通过。 - [ ] 任一维度没有即时唯一选择证明、摘要缺失/不精确或目标发生漂移时,仍返回 `PURCHASE_SPEC_SELECTION_UNCONFIRMED`,且不进入修改地址或创建订单。 - [ ] 诊断只包含安全枚举/计数,不包含规格文案、坐标、控件树、截图、账号、地址、订单或支付数据。 - [ ] 既有采购执行单元测试通过,Debug APK 构建成功。 - [ ] 不修改共享 API、数据库和长期 Wiki。 ## 验证方式 - `cd android; .\gradlew.bat testDebugUnitTest --tests cn.ilapage.goauto.agent.PurchaseRehearsalExecutorTest` - `cd android; .\gradlew.bat assembleDebug` - 只读确认任务 38 两次历史失败和不可逆边界均为空。 - 真机验证:本单代码验证完成后另行取得人工授权;只验证至最终核单/创建订单前门禁,永久不支付。若正式规则会继续执行创建订单,则必须使用受控方式在不可逆动作前停止,或由独立授权明确允许创建待付款订单。 ## 风险和回退 - 风险:错误复用历史证明可能放行错误规格,进而创建错误的待付款订单。 - 控制:证明只存在当前 executor / 当前 attempt 内;绑定维度和完整目标;仍要求当前摘要精确 Token;歧义、缺失和漂移全部失败;不跨任务持久化。 - 回退:恢复为现有最终视口强校验逻辑;任务仍安全失败,不影响数据库和接口。 - 高风险门禁:这是正式采购创建订单前的安全判定修改。创建工单后先等待人工实施确认;真机或正式采购重跑前再次取得独立授权,且永久禁止支付。
Author
Owner

实施完成,等待验收

实施结果:

  • 在 PurchaseRehearsalExecutor 的单次 execute 调用内保存颜色/尺码的精确选择证明;证明不持久化、不跨任务或 attempt 复用。
  • 选择证明只在短摘要 Token 能唯一对应完整规范化目标时生成;同一 Token 存在多个候选时不生成证明。
  • 最终核单优先使用当前唯一 selected/checked 节点;候选滚出视口时,只有“本 attempt 证明 + 当前摘要精确 Token + 当前可见候选无冲突”同时成立才通过。
  • XL 不匹配 2XL;摘要缺失、可见同 Token 冲突、证明缺失继续返回 PURCHASE_SPEC_SELECTION_UNCONFIRMED,不会进入修改地址或创建订单。
  • 失败消息增加安全诊断:维度、原因、面板类型、摘要/Token 命中、候选数量、证明是否存在;不含规格文案、坐标、控件树、截图、账号、地址、订单或支付数据。

验证:

  • cd android; .\gradlew.bat testDebugUnitTest:通过,232 tests / 0 failures / 0 errors / 0 skipped。
  • cd android; .\gradlew.bat assembleDebug:通过。
  • git diff --cached --check:通过。
  • 新增覆盖:颜色候选滚出视口、长尺码只显示唯一短 Token、摘要消失、XL/2XL 不一致、最终可见同 Token 候选漂移冲突。

提交:40aea6a fix(android): preserve exact spec proof for final verification (#171),已推送 origin/main。

文档影响:无长期事实变化;未修改 Wiki,未执行 sync;未创建任务快照。

未验证/安全边界:按用户授权仅完成代码与自动测试;未安装 APK、未进行真机采购、未修改地址、未创建订单、未支付。真机或正式采购验证仍需独立人工授权。

## 实施完成,等待验收 实施结果: - 在 `PurchaseRehearsalExecutor` 的单次 `execute` 调用内保存颜色/尺码的精确选择证明;证明不持久化、不跨任务或 attempt 复用。 - 选择证明只在短摘要 Token 能唯一对应完整规范化目标时生成;同一 Token 存在多个候选时不生成证明。 - 最终核单优先使用当前唯一 `selected/checked` 节点;候选滚出视口时,只有“本 attempt 证明 + 当前摘要精确 Token + 当前可见候选无冲突”同时成立才通过。 - `XL` 不匹配 `2XL`;摘要缺失、可见同 Token 冲突、证明缺失继续返回 `PURCHASE_SPEC_SELECTION_UNCONFIRMED`,不会进入修改地址或创建订单。 - 失败消息增加安全诊断:维度、原因、面板类型、摘要/Token 命中、候选数量、证明是否存在;不含规格文案、坐标、控件树、截图、账号、地址、订单或支付数据。 验证: - `cd android; .\gradlew.bat testDebugUnitTest`:通过,232 tests / 0 failures / 0 errors / 0 skipped。 - `cd android; .\gradlew.bat assembleDebug`:通过。 - `git diff --cached --check`:通过。 - 新增覆盖:颜色候选滚出视口、长尺码只显示唯一短 Token、摘要消失、`XL/2XL` 不一致、最终可见同 Token 候选漂移冲突。 提交:`40aea6a fix(android): preserve exact spec proof for final verification (#171)`,已推送 `origin/main`。 文档影响:无长期事实变化;未修改 Wiki,未执行 sync;未创建任务快照。 未验证/安全边界:按用户授权仅完成代码与自动测试;未安装 APK、未进行真机采购、未修改地址、未创建订单、未支付。真机或正式采购验证仍需独立人工授权。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#171