Files

139 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: T-105
title: 数量设置、读回与闸门二
phase: 1
deps: [T-104]
status: DONE
created: 2026-08-04
vikunja_task_id: 40
context_ref: 67b4278
work_branch: task/t-105-quantity-gate2
needs_device: true
needs_human_review: true
write_paths:
- docs/tasks/T-105.md
- docs/02-requirements.md
- docs/04-architecture.md
- docs/05-coding-rules.md
- docs/api.md
- docs/06-tasks.md
- docs/07-user-stories.md
- docs/08-interaction-checklist.md
- docs/routes.md
- docs/design/desk-execution.html
- docs/design/web-task-detail.html
- client/src/cmbuyer_client/pdd/quantity_gate2_spike.py
- client/src/cmbuyer_client/pdd/quantity_gate2.py
- client/src/cmbuyer_client/pdd/quantity_gate2_runner.py
- client/tests/pdd/test_quantity_gate2.py
- client/tests/pdd/fixtures/quantity_gate2_initial_8_17_0.xml
- client/tests/pdd/fixtures/quantity_gate2_target_8_17_0.xml
- client/scripts/capture_quantity_gate2_spike.py
- client/scripts/run_t105_quantity_gate2.py
- docs/current-state.md
---
<!-- BEGIN VIKUNJA EXPORT id=40 synced=2026-08-06T01:53:44Z sha256=fcc45a75560c145044787020f8e994751c203763df3a4a46d0cdb765958a71f2 -->
## 问题 / 背景
T-104 将把规格选择、闸门一读价、原始截图和安全退出固化为受控能力。T-105 先对当前真机数量控件和读回位置取证,再实现规格面板内的数量设置、精确读回与闸门二;不进入确认页、不接触最终提交。
## 关联需求与交互
- 功能:F-010、F-015。
- 用户故事:US-004、US-005。
- 依赖:T-104;T-103 由其传递满足。
- 后续消费者:T-106、T-305。
- 本任务需要真机与人工证据确认。
## 方案
1. 阶段一只读取证:人分别准备初始数量与目标数量状态,脚本只采集 screenshot/XML/App/设备摘要;记录 PDD 版本、goods_id、规格、目标数量、路径和 hash。人工确认数量控件、读回位置和页面对应性前,不写点击判据。
2. 阶段二从本项目证据提取最小 fixture,固化数量显示、增减控件、选中规格和价格节点的精确唯一结构;版本/包/面板/规格/控件任一失配都零点击。
3. QuantityGate2Flow 接受 T-104 Gate1Observation、目标数量和最高总价。数量必须为服务端任务正整数,不接受浮点、字符串猜测或超上限值。
4. 每次数量修改只点击证据证明的唯一控件一次,并等待明确后置条件;超时或结果不明不得重试该次点击。达到目标前每一步都重新定位和读回,不使用裸坐标或缓存节点。
5. 闸门二重新读取颜色、尺码、数量和规格面板目标数量总额;颜色/尺码必须等于目标,数量精确等于请求,`gate2_panel_total_price` 必须唯一可读且以十进制比较不超最高总价。2026-08-06 真机证明多件优惠非线性,数量 1 为 12.88、数量 2 为 32.76,因此不得把 gate1 金额乘数量、不得要求 gate2 等于 gate1,也不得用底部“提交订单”金额作为候选或兜底。后续闸门三必须与该 Gate2 面板总额严格相等并再次不超上限,否则转人工。
6. 成功结果是不可变 Gate2Observation,包含请求/实际规格、quantity_read、gate1_unit_price、gate2_panel_total_price、max_total_price、规格面板原始 screenshot_path 与 UTC captured_at;旧 `gate2_unit_price` 语义已被真机证据否定,后续服务端契约与存储必须在 T-210/T-205 前改名迁移,禁止以旧字段名承载总额。
7. 失败、价格不可读/多候选、规格漂移、数量不符或超价都安全停止并使用 T-104 一次性安全退出;Back 结果不明不重试。
8. 能力与 T-103/T-104 分层:T-103 不能反向导入本任务;本任务不暴露确认页导航、通用 click、最终提交控件、围栏或付款能力。
## 验收要点
- 先证据后实现,执行记录包含两态截图/XML/hash、版本、设备、goods_id 与人工确认。
- 离线覆盖数量边界、每步单击一次、后置条件、超时不重试、节点缺失/重复、SystemUI/锁屏/版本漂移。
- 覆盖闸门二规格不变、数量读回、Gate2 面板总额唯一可读、Decimal 上限比较、非线性优惠反例,以及节点缺失/重复/漂移和所有失败分支零确认页动作;静态禁止把 Gate1 乘数量、底部“提交订单”金额或旧 `gate2_unit_price` 当作 Gate2 事实。
- 静态证明 T-103 不导入数量,本任务不可达确认页、围栏、submit_order_once 或付款。
- 真机人工确认目标数量、规格、Gate1 单价与 Gate2 面板总额、截图、一次安全退出,且未进入确认/提交/支付页、未创建订单。
- client 全量 unittest、compileall、完整 init、上下文校验、Vikunja 导出与 diff-check 通过;agent 保持 DOING 等人工验收。
## 执行记录
### 2026-08-04T13:58:34Z · ila
2026-08-04 预研定值:T-105 依赖 T-104 的一次安全退出,严格分“数量两态只读取证”和“人工确认后实现”两个门禁;闸门二输出显式 screenshot_path/captured_at,且不可达确认页、提交或付款。
### 2026-08-05T09:58:46Z · ila
2026-08-05 T-104 已在 git/线上完成,T-105 依赖解除,现由 root 领取;领取基线 `67b4278`,沿用工作路径 `task/t-105-quantity-gate2`。
严格按两阶段门禁:
1. 先实现只读 `quantity_gate2_spike.py` 与 CLI,只接受显式 serial、goods_id、human-declared state/quantity 和全新 output-dir;核验 PKG110/Android16/PDD8.17.0/PDD 前台/1080x2376 后,仅采 screenshot/XML/App/设备摘要并原子发布。不得 intent、页面 click、坐标、数量修改、Back、确认、提交或支付。
2. 项目所有者分别把目标商品规格面板停在黑色CHA(纯棉)+M(建议100-115)+数量1,以及相同规格+数量2;各运行一次只读取证并人工确认控件、读回、价格、规格和页面对应性。
3. 只有两态人验后才从本项目 raw 提取最小 fixture,实现逐步单击一次、每步 fresh 定位/readback、Gate2 Decimal 总价和 T-104 一次性安全退出。任一失败不进入确认页。
写路径严格限于 T-105 frontmatter;共享 current-state 由 root 合入。needs_device/needs_human_review 保持,未完成人工验收前不得 DONE。
### 2026-08-05T10:08:24Z · ila
2026-08-05 T-105 阶段一只读取证代码完成并推送,代码 commit `994b6c8`。新增 `quantity_gate2_spike.py` 与 CLI:只接受显式 serial、固定 goods_id 937122477375、人工声明 initial=1 / target=2 和全新目录;每次重新核验 PKG110 / Android 16 / PDD 8.17.0 / PDD 前台 / 1080×2376,只调用 `takeScreenshot` 与 `dumpWindowHierarchy`,保存 screenshot/XML/App 摘要/manifest,前后台或版本漂移不发布。接口与静态测试证明无 intent、click、swipe、Back、数量修改、确认、提交或支付能力。专项 13/13、客户端全量 311/311、compileall、agent-context、完整 `init.ps1` 均通过。下一步必须由人分别准备同一商品、黑色CHA(纯棉)+M(建议100-115) 的数量 1 和数量 2 两态并运行只读取证;两态人工确认前不实现数量点击、readback 或 Gate2 判据。任务保持 DOING。
### 2026-08-06T01:00:27Z · ila
2026-08-06 T-105 阶段一两态真机证据与四项人工确认完成。设备 PKG110 / Android16 / WiFi,PDD 8.17.0,goods_id 937122477375,目标规格均为黑色CHA(纯棉)+M(建议100-115)。
初态目录:`C:\Users\ila20\AppData\Local\cmbuyer\artifacts\T-105\quantity-initial-937122477375-20260806-v3`;captured_at `2026-08-06T00:53:00.023935+00:00`;screenshot SHA-256 `959c62f90d05a4d2a8e212b0286d7ad7e958e00e56915ddf733ce7fd9b11f9c0`;XML SHA-256 `f31d15ef0763d9685448aba0086b6f67b459e4991b5d01a5daae333dd3b9c16d`。人工确认数量1、目标规格、金额12.88。
目标态目录:`C:\Users\ila20\AppData\Local\cmbuyer\artifacts\T-105\quantity-target-937122477375-20260806`;captured_at `2026-08-06T00:55:30.898374+00:00`;screenshot SHA-256 `1954d9f8dbbc80b73ef5b93ae941c0501baa3f35c3f040e0cd4ef9723eb40057`;XML SHA-256 `e6ffcdc71119b8e0ac35e135afac54517f9c28c4d9da1070168901dce1988b81`。人工确认数量2、目标规格不变、金额32.76。
人工四项确认:两态数量分别1/2;颜色尺码均未变化;金额分别12.88/32.76;未进入确认/支付页、未点击“提交订单”、未创建订单。
XML 允许字段摘要:数量节点为唯一 clickable/enabled EditText,`1 [480,752][561,827]` → `2 [480,750][561,825]`;唯一加号为 clickable/enabled ImageView、content-desc 精确“增加数量”、初态 bounds `[567,752][645,827]`、目标态 `[567,750][645,825]`;顶部价格角色 `快卖完 ¥12.88` → `快卖完 ¥32.76`;底部 `提交订单 ¥...` 继续排除且禁止点击。真机事实证明多件优惠非线性,Gate2 必须读取目标数量面板总额并与最高总价比较,不能继续用旧 gate2_unit_price 等值假设。任务进入阶段二,仍保持 DOING。
### 2026-08-06T01:04:25Z · ila
2026-08-06 T-105 初态首次只读取证阻塞取证:人工已确认规格面板为目标颜色/尺码/数量1,并关闭 OPPO 游戏助手视觉层;`dumpsys window` 的 mCurrentFocus/mFocusedApp 与 `dumpsys activity activities` 的唯一 topResumedActivity 均为 `com.xunmeng.pinduoduo/.activity.NewPageActivity`,PDD versionName=8.17.0、PKG110、Android16、1080×2376 均正确,但 uiautomator2 `app_current()` 误报 `com.oplus.games`。根因是当前 adbutils 2.12.0 先执行 `dumpsys window windows`(本机 Android16 无对应焦点行),随后只识别旧式 `mResumedActivity:`,不识别实际 `topResumedActivity=`,最终错误退回 `dumpsys activity top` 的最后一项。
最小修复计划:不放宽“PDD 必须前台”,也不接受 `com.oplus.games`。T-105 阶段一改用仅限 PKG110/Android16 的窄只读 foreground reader,执行固定的 adb 参数数组:指定 serial、shell、dumpsys activity activities;只接受恰好一个 `topResumedActivity` 且 package 精确为 PDD、activity 非空;缺失/重复/其他包/命令失败全部不截图、不发布。通用 shell 不暴露给 capturer,既有只读设备协议反而移除错误的 `app_current`。离线补齐真实 Android16 行、旧格式拒绝、重复/缺失/其他包/命令失败、前后漂移测试;验证后再重跑数量1初态。任务仍 DOING。
### 2026-08-06T01:28:33Z · ila
2026-08-06 T-105 阶段二离线实现已完成并推送,代码 commit `21628a4`。从本项目两态证据提取最小 fixture,生产 Flow 只允许数量 1 零点击或数量 1→2 的唯一加号一次点击;每次 fresh 核验 PKG110 / Android 16 / PDD 8.17.0 / PDD 前台 / 1080×2376、目标颜色尺码、数量读回与顶部面板总额。数量 2 的 Gate2 事实为 `gate2_panel_total_price=32.76`,直接以 Decimal 比较 `max_total_price`;未使用 Gate1×数量推导 Gate2,底部“提交订单”金额不是候选,旧 gate2_unit_price 未进入生产代码。动作 RPC 前封存,超时/结果不明不重试;只有已知精确状态才执行 T-104 一次 Back,同商品详情需连续两帧稳定。模块不可达确认页、围栏、提交或付款。专项 32/32、客户端全量 330/330、compileall、agent-context、diff-check 与完整 init.ps1 均通过。下一步仅需项目所有者把目标面板手工恢复到数量1后运行生产验收;人工确认数量2、目标规格、12.88/32.76、Gate2 原图、一次安全退出,以及未进入确认/提交/支付页、未创建订单。任务保持 DOING。
### 2026-08-06T01:52:14Z · ila
2026-08-06 T-105 最终生产真机验收完成。证据目录:`C:\Users\ila20\AppData\Local\cmbuyer\artifacts\T-105\quantity-gate2-live-937122477375-20260806`;manifest:同目录 `manifest.json`;captured_at `2026-08-06T01:33:33.818765+00:00`;Gate2 screenshot SHA-256 `6b52c73f933934d270f0c2f5c9e37c67f7fba443ce03340807a764f80a2bf299`。manifest 固定事实:PKG110 / Android 16 / WiFi / PDD 8.17.0 / goods_id 937122477375;数量请求与读回均为2;黑色CHA(纯棉)+M(建议100-115);Gate1 单价12.88;Gate2 面板总额32.76;最高总价40.00;加号1次且 completed;Back 1次且 completed;safe_exit=completed。项目所有者随后明确完成四项人工确认:Gate2 截图显示数量2、目标规格与顶部32.76;Back 后回到同一商品详情且面板关闭;未进入确认/提交/支付页;未创建订单且无异常操作。T-105 全部验收要点满足,达到条件即停止,不追加真机测试。
<!-- END VIKUNJA EXPORT -->
## 边界
- 必须先由人在拼多多 8.17.0 的目标规格面板分别准备初始数量与目标数量状态,只读采集并人工确认
screenshot/XML/版本/goods_id/规格/数量的对应性,之后才允许从本项目证据编写数量判据和点击代码。
不得从前序项目、旧 XML、控件常识、OCR、裸坐标或推理直接实现。
- 数量控件、读回位置、规格选中态、Gate1 单价和 Gate2 面板总额都必须证据绑定且精确唯一。每次修改数量最多点击已批准
控件一次并等待明确后置条件;超时或结果不明不得重试同一次点击,不得缓存节点跨状态继续操作。
- 闸门二必须重新核对颜色/尺码未漂移、数量精确等于任务,并从证据绑定的规格面板顶部当前金额
角色唯一读取 `gate2_panel_total_price`,以十进制直接验证其不超最高总价。2026-08-06 真机已证明
多件优惠非线性:数量 1 为 `12.88`、数量 2 为 `32.76`;不得用 gate1 金额乘数量猜总额、不得要求
gate2 等于 gate1,也不得把底部“提交订单”金额作为候选或兜底。后续闸门三必须与 Gate2 面板总额
严格相等且再次不超上限;任一不符即转人工。
- 只有规格、数量、价格、总价上限和原始截图全部通过后才返回不可变 Gate2Observation;它必须显式
携带 `screenshot_path` 与 UTC `captured_at`,不得让后续任务枚举目录或读取 manifest 猜证据。
- 任一判据失败、规格漂移、数量不符、价格不可读/多候选/变化或超价都停止前进,只能调用 T-104
已验证的一次性安全退出;Back 超时或结果不明不重试,不把“面板消失”当作退出成功。
- T-103/T-104 不得反向导入本任务。本任务不进入确认页、不观察或获取最终提交控件,不实现通用 click、
事件、证据上传、围栏或结果接口;不编写或引用点击“提交订单”的代码,不编写任何付款能力。
- 旧 `gate2_unit_price` 字段名已被本项目真机证据否定,不能用旧名字承载总额来掩盖语义变化;API 与
服务端存储必须在 T-210/T-205 消费 Gate2 前迁移为 `gate2_panel_total_price`,迁移未完成时不得建立围栏。
- `needs_device: true`:agent 完成离线实现后仍保持 DOING。只有人确认真机数量、规格、Gate1 单价与 Gate2 面板总额、
截图和安全退出,且未进入确认/提交/支付页、未创建订单,才可完成任务。