112 lines
13 KiB
Markdown
112 lines
13 KiB
Markdown
---
|
||
id: T-401
|
||
title: 首次真实提交与生产接线
|
||
phase: 4
|
||
deps: [T-400, T-402]
|
||
status: TODO
|
||
created: 2026-08-04
|
||
vikunja_task_id: 52
|
||
context_ref: 8600c33
|
||
work_branch: task/t-401-first-real-submission
|
||
needs_device: true
|
||
needs_human_review: true
|
||
write_paths:
|
||
- docs/tasks/T-401.md
|
||
- client/src/cmbuyer_client/pdd/order_submission.py
|
||
- client/src/cmbuyer_client/execution/**
|
||
- client/src/cmbuyer_client/ui/**
|
||
- client/src/cmbuyer_client/app.py
|
||
- client/tests/pdd/test_order_submission.py
|
||
- client/tests/execution/**
|
||
- client/tests/ui/**
|
||
- client/tests/test_app.py
|
||
---
|
||
|
||
<!-- BEGIN VIKUNJA EXPORT id=52 synced=2026-08-06T02:59:12Z sha256=e388ed4e91052ce9d8a0a7b5ac0aa55f7721a3133c17cc5eff948dae4167ce21 -->
|
||
## 问题 / 背景
|
||
|
||
T-107 已把订单确认页、闸门三与精确唯一“提交订单”控件限制为证据/App 版本绑定的只读能力,T-308 将只在当前进程首次明确围栏许可后产生不可恢复 permit,T-400 只用测试 fixture 证明四条件与一次性编排。T-305 的真实 dry-run 已安全 Back 并以 DRY_RUN_COMPLETED_BEFORE_FENCE 终止 attempt,只能提供已验收代码/判据契约,任何运行对象、截图、缓存或 proof 都不能提交。T-401 必须领取一条新的已授权真实任务,在全新 attempt 的同一设备会话中从打开商品开始实时重跑 Gate1、数量/Gate2、确认页/Gate3,并在仍停留于当前确认页时即时构造生产 ReadyForSubmission,随后才可申请围栏和精确点击一次。系统只创建可能的待付款订单,绝不付款;首次提交后页面无本项目证据,因此点击后无条件上报 UNKNOWN 并由 T-403 调和。
|
||
|
||
## 关联需求与交互
|
||
|
||
- 功能:F-005、F-006、F-007、F-011、F-017。
|
||
- 用户故事:US-003、US-004、US-005、US-008。
|
||
- 交互:IX-008、IX-011;执行员没有人工“提交订单”按钮。
|
||
- 依赖:T-400、T-402;T-400 传递 T-305/T-308 的已验收契约但不传递任何运行时 ReadyForSubmission,T-402 传递 T-403 并保证点击后已有安全调和与待付款收口。
|
||
- 需要真机和人工安全验收;agent 只能实现、离线验证和准备命令,不得自行触发真实提交或标 DONE。
|
||
|
||
## 方案
|
||
|
||
1. 生产执行只接受本次新领取的 PENDING + ACTIVE 授权任务,由服务端创建新的 active attempt/generation。已有 DRY_RUN_COMPLETED_BEFORE_FENCE、FAILED、FENCED、ABANDONED 或其它结束 attempt,以及 T-305 的 task/attempt id 都必须在任何页面动作和 fence 前拒绝。
|
||
2. 在一个不中断的全新设备会话中按固定顺序执行:打开本次任务 canonical 商品 → 受控入口/精确选规格 → Gate1 当前 SKU 单价 → 设置并读回数量 → 重读规格与 Gate2 单价 → 进入订单确认页 → Gate3 规格/数量/总额 → 只读确认精确唯一最终控件。每一步都使用当前 attempt 的实时事实和新证据,不能跳步或使用历史值。
|
||
3. 生产 ReadyForSubmission 构造入口首次且仅在 T-401 composition 内出现:只有上述当前步骤全部成功、当前 claim/authorization/attempt/generation/App 版本仍一致、三个 AssetRef 均属于本次 attempt,并且仍停留在刚验证的确认页时,才即时构造不可持久化的临时对象交 T-400 编排。
|
||
4. ReadyForSubmission 不写入 SQLite、文件、缓存、日志或恢复快照,不提供 from_dry_run/from_snapshot/from_evidence/from_localstate。构造后页面 Back/导航、claim/lease/授权变化、App 版本/前台包变化、证据或任务版本漂移都立即使其失效并零 fence/零点击;不能重新加载或跨重启恢复。
|
||
5. 静态和运行边界显式拒绝 T-305 PreFenceDryRunResult、DRY_RUN_COMPLETED_BEFORE_FENCE attempt、dry-run screenshot/AssetRef、action journal、缓存页面对象和旧 proof。T-305 已 Back 的页面不能“返回去继续”,必须领取新任务从商品打开开始。
|
||
6. 在生产 composition root 接入 T-400 SinglePassSubmissionOrchestrator、T-308 SubmissionSink 与极窄 PDD SubmitOrderPort。UI 只显示自动阶段和安全状态,不提供执行员可点击的提交、重试、释放围栏或继续按钮。
|
||
7. 具体 SubmitOrderPort 只接受当前进程一次性 ArmedSubmission 和本次 T-107 判据生成的 VerifiedSubmitObservationBoundary。点击前在当前确认页再次执行精确文本、唯一可点击祖先、前台包与 App 版本检查;不得接受任务下发 selector/坐标、通用 click、相似文案、OCR 或旧项目常量。
|
||
8. T-308 必须已 durable 写入“即将发出唯一点击”且本地状态进入 RECONCILE_ONLY,才允许调用底层真机点击。低层点击语句在生产调用图中恰好一个调用点、执行恰好一次;不能放在循环、重试器、finally、恢复回调或可重复 signal handler 中。
|
||
9. 四条件任一缺失、页面实时复核漂移、围栏响应不明、许可不是首次、持久化失败、App/设备/claim 状态变化均零点击并停止。停止轮询、Esc、查看历史、关闭窗口、超时、异常和进程重启都不得重构 ReadyForSubmission、重新 arm、重做页面动作或再次点击。
|
||
10. 点击调用返回、抛错或超时后不再与页面交互。首次真实运行没有提交后页面判据,客户端必须无条件以固定 UNKNOWN 上报同一 submission,任务进入 RECONCILIATION_REQUIRED;即使人看到待付款页,也不得由客户端推断或改报 SUBMITTED。
|
||
11. T-401 不采集、持久化或上传点击后的截图/XML,不新增 SUBMISSION_RESULT evidence kind,不把 Gate3 图冒充结果图。尤其不得截取或上传外部支付页、支付凭据、安全校验页面;点击后结果只由管理员在 T-403 调和同一 submission。
|
||
12. UNKNOWN result HTTP 不明时只由 T-308 用原 result_key、原载荷调和;不得重复观察页面、生成新 key、重新提交、释放围栏、重新授权、重新领取或推进下一任务。
|
||
13. 首次真实运行必须使用项目所有者专门创建并授权的低风险新任务,在 T-305 dry-run 和全部离线门禁通过后,由项目所有者在执行记录中给出针对本次运行的一次性明确批准。额外批准只是首次发布验收,不新增产品内第二授权按钮。
|
||
14. 真实点击后由人检查手机和采购服务,只通过 T-403 选择 CONFIRMED_CREATED、CONFIRMED_NOT_CREATED_OR_CANNOT_COMPLETE 或 STILL_UNKNOWN。系统不支付、不自动取消外部订单;人负责说明订单是否产生及如何处置。
|
||
|
||
## 验收要点
|
||
|
||
- 测试证明只有新领取、未结束且当前归属一致的 attempt 能开始;T-305/DRY_RUN_COMPLETED_BEFORE_FENCE、FAILED、FENCED、ABANDONED、旧 generation 和跨 task/authorization 均零页面动作、零 fence、零点击。
|
||
- 动作/事件序列严格证明本次新 attempt 在同一会话执行商品打开→Gate1→数量/Gate2→确认页/Gate3→即时 ReadyForSubmission→fence→点击;不得出现引用 T-305 截图、缓存、AssetRef、journal 或 proof。
|
||
- ReadyForSubmission factory 仅 T-401 production composition 可达,输入只来自本次内存实时结果;AST/数据流测试证明无 dry-run/storage/cache/restart factory,Back/导航/版本/claim 漂移后对象失效。
|
||
- 离线 fake-device/port 测试覆盖四条件缺一、控件 0/2 个、文本/版本/前台包漂移、非首次 permit、点击意图落盘失败、并发进入、停止/关闭/重启,所有负例底层点击数为 0。
|
||
- 唯一成功调用测试证明点击意图已先落盘、底层点击调用数恰好为 1;底层返回、异常和超时后再次进入/重启的累计点击数仍为 1,没有 retry/fallback。
|
||
- 点击后的所有离线分支都只生成 UNKNOWN;静态测试禁止 SUBMITTED 推断、提交后截图/XML/evidence 上传,以及页面观察或第二次点击。
|
||
- AST/import/call graph 证明只有一个生产低层提交点击点,且支付、免密支付、先用后付、扣款控件、人工提交按钮和通用 click 不可达。
|
||
- 运行 client 全量 unittest、compileall、wheel metadata、完整 init、上下文、Vikunja export 与 diff-check;人工放行前不得运行真机提交命令。
|
||
- 真机记录必须包含“全新任务/授权/attempt”证明、设备型号、Android、连接方式、拼多多版本、goods_id、task/authorization/attempt/submission id、本次三闸门值/AssetRef、唯一控件计数、fence 首次许可、点击意图先落盘、低层点击恰好一次、UNKNOWN/RECONCILIATION_REQUIRED、T-403 人工结论、订单是否产生/如何处置和“未付款”。不得记录 token、地址/手机号字段、支付凭据或点击后截图/XML。
|
||
- 真机运行与最终结论只能由项目所有者明确批准并人工确认;确认前保持 DOING,agent 不得自行执行、推断成功或标 DONE。
|
||
|
||
## 执行记录
|
||
|
||
### 2026-08-06T02:58:55Z · ila
|
||
|
||
2026-08-06T02:58:54.857Z · Codex
|
||
2026-08-06 生产单趟删除“进入确认页”步骤:数量/Gate2 后保持同一最终面板,实时读取结构化最终控件金额作为 Gate3,再申请围栏。真实点击仍必须四条件全过且只一次;点击会直接创建待付款订单并进入付款界面,随后立即停止、绝不付款。
|
||
<!-- END VIKUNJA EXPORT -->
|
||
|
||
## 边界
|
||
|
||
- 2026-08-06 起生产单趟在数量/Gate2 后保持同一合并式最终提交面板,读取结构化最终控件金额作为
|
||
Gate3;不存在确认页导航。最终点击会直接创建待付款订单并进入付款界面,仍须四条件全过、只点
|
||
一次,点击后立即停止并调和,绝不执行付款。
|
||
|
||
- 本任务只把 T-107 已取证且绑定拼多多 App 版本的精确唯一最终控件、T-308 当前进程首次明确
|
||
`SubmissionPermit` / 一次性 `ArmedSubmission` 和 T-400 离线编排接入生产。不得接收服务端
|
||
selector/坐标/动作脚本,不得使用相似文案、OCR、通用 click、旧项目常量或未取证页面能力。
|
||
- 每次生产执行必须领取一条新的 `PENDING` + `ACTIVE` 授权真实任务,并由服务端创建新的 active
|
||
attempt/generation。在一个全新且不中断的同一设备会话内,严格重新执行商品打开 → Gate1 → 数量
|
||
设置/读回与 Gate2 → 确认页/Gate3 → 当前最终控件只读复核;不能从中间页面或旧 attempt 续跑。
|
||
- T-305 正常 dry-run 已安全 Back,并以 `DRY_RUN_COMPLETED_BEFORE_FENCE` 终止 attempt。其任何
|
||
结果对象、task/attempt id、screenshot/AssetRef、action journal、缓存页面对象、本地快照或旧 proof
|
||
永远不得用于生产 `ReadyForSubmission`、申请 fence 或提交;结束/失败/围栏后的其它 attempt 同样拒绝。
|
||
- 生产 `ReadyForSubmission` 只能在本次新 attempt 的 Gate3 与唯一控件刚刚实时通过、仍停留当前
|
||
确认页且 claim/lease/authorization/generation/App 版本全部一致时即时构造。对象不得持久化、缓存、
|
||
序列化或跨导航/Back/重启恢复;任一事实漂移立即失效并零 fence、零点击。
|
||
- 只有一次性授权与服务端首次围栏许可、Gate2、Gate3、精确唯一提交控件四条件同时成立,并且
|
||
T-308 已 durable 写入点击意图和 `RECONCILE_ONLY`,才可调用低层提交点击。生产调用图中低层
|
||
点击恰好一个调用点、运行恰好一次;不得位于循环、retry、fallback、`finally` 或恢复回调。
|
||
- 围栏/许可/持久化/页面复核任一失败均零点击。点击调用返回、抛错、超时、停止轮询、Esc、查看
|
||
历史、关闭窗口或重启都不得重新 arm、重复页面动作或再次点击,也不得释放围栏、重新授权、
|
||
重新领取或推进下一任务。
|
||
- 首次真实提交后的页面尚无本项目真机证据。点击后客户端必须无条件上报固定 `UNKNOWN` 并进入
|
||
`RECONCILIATION_REQUIRED`;不得解析页面、根据人眼结论推断 `SUBMITTED`,也不得把结果改报为
|
||
其他 observation。订单是否产生只由管理员通过 T-403 调和同一 submission。
|
||
- 本任务不得采集、持久化或上传点击后的截图/XML,不新增结果 evidence kind,不把 Gate3 图冒充
|
||
结果图。尤其不得保存或上传外部支付页、支付凭据或安全校验页面。
|
||
- 采购工具不得提供人工“提交订单”、重试提交、释放围栏或继续执行按钮。UI 只能显示后台自动阶段、
|
||
submission id 和“可能已创建订单,禁止再次提交,只能人工调和”的安全状态。
|
||
- 系统不点击支付、免密支付、先用后付或任何扣款控件,不自动取消外部订单。真实订单是否产生、
|
||
是否付款和如何处置均由人负责;`WAITING_PAYMENT` 不等于成功。
|
||
- 真实运行除管理员“开始采购”的业务授权外,还必须由项目所有者在任务执行记录中针对本次首次
|
||
发布验收给出明确一次性批准。agent 不得自行运行真实提交命令、确认真机结论或标 `DONE`;
|
||
`needs_device` 与 `needs_human_review` 未同时由人确认前必须保持 `DOING`。
|