--- id: T-305 title: 围栏前单趟 dry-run 编排 phase: 3 deps: [T-107, T-304, T-306, T-307, T-210] status: TODO created: 2026-08-04 vikunja_task_id: 44 context_ref: c1cee49 work_branch: task/t-305-prefence-dry-run needs_device: true needs_human_review: true write_paths: - docs/tasks/T-305.md - client/src/cmbuyer_client/execution/** - client/src/cmbuyer_client/core/** - client/src/cmbuyer_client/remote/** - client/src/cmbuyer_client/localstate/** - client/src/cmbuyer_client/polling/** - client/src/cmbuyer_client/ui/** - client/src/cmbuyer_client/app.py - client/tests/execution/** - client/tests/core/** - client/tests/remote/** - client/tests/localstate/** - client/tests/polling/** - client/tests/ui/** - client/tests/test_app.py - docs/api.md - docs/04-architecture.md - docs/06-tasks.md - docs/current-state.md --- ## 问题 / 背景 T-103~T-107 分段固化真机页面能力,T-303/T-304 提供本地恢复与桌面执行壳,T-306/T-307 提供三闸门证据上传和 attempt 事件/失败 sink,T-210 扩展完整三闸门证据类型。T-305 只把这些已完成能力组合为围栏前 dry-run,验证领取后同一趟执行可以安全到达最终提交控件观察点,并在任何不可逆动作前停止。 ## 关联需求与交互 - 功能:F-005、F-006、F-007、F-013、F-017 的围栏前部分。 - 用户故事:US-003、US-004、US-005。 - 依赖:T-107、T-304、T-306、T-307、T-210。 - 后续消费者:T-208 提交围栏与真实单次提交。 - 本任务不得调用 submission fence、result 或订单提交能力。 ## 方案 1. 实现窄 PreFenceDryRunOrchestrator,只依赖已冻结的 claim/renew、attempt event/fail、三闸门 EvidenceSink、T-103/T-105/T-107 页面能力和 T-304 UI 执行外壳;不直接实现 HTTP、PDD selector 或新页面判据。 2. 首次领取后把 authorization/task/attempt/generation/claim/版本快照和执行载荷原子写入 T-303 localstate;页面动作前写 action journal。重启只调和 HTTP 与展示人工恢复状态,不自动续跑任何手机点击。 3. 同一趟严格执行:规格面板闸门一 → 数量设置与闸门二 → 唯一证据绑定的确认页导航 → 闸门三与最终提交控件只读观察 → 一次安全 Back。任一前置条件、读回、价格或证据失败立即 fail closed。 4. 三闸门每次都先把原始 PNG 交 T-306 持久化固定 upload_key/metadata/hash,再用 T-307 追加对应成功事件;事件只能引用服务端确认的 AssetRef。未知上传结果只重放同键同文件,不重做页面动作或替换证据。 5. 动作日志使用固定动作类型、attempt/generation/阶段、开始时间与明确后置状态;不保存 selector、坐标、自由页面文本、XML、地址、手机号或 token。点击结果不明时停止并转人工,不以重启或超时自动重试。 6. 完成闸门三观察且一次 Back 验证安全返回后,写固定失败终止 reason DRY_RUN_COMPLETED_BEFORE_FENCE,使 attempt/task 进入围栏前人工状态。不得请求或模拟围栏,不得创建 order_submission。 7. HTTP 出站仅允许 T-303 transport 固定 loopback API;import 闭包和静态测试禁止 SubmissionPermit、fence/result client、click_permitted、submitter、submit_order_once、支付模块。 8. UI 显示当前执行阶段、已确认的最小任务摘要和滚动日志;Esc 只处理详情/当前任务切换,不取消在途请求、不清本地 journal、不释放 claim、不触发真机动作。 ## 验收要点 - 离线组合测试覆盖正常三闸门、每一步失败、价格/规格/数量漂移、证据未知结果、事件未知结果、租约/授权到期、重启和 active claim 漂移。 - 证明每个页面动作前已有 journal;不明结果和重启均零自动页面动作,只有同键 HTTP 调和。 - 证明 Gate1/Gate2/Gate3 的 PNG、captured_at 与 AssetRef 顺序正确,事件不能先于证据成功,也不能串 attempt/generation。 - 正常 dry-run 最终只产生 DRY_RUN_COMPLETED_BEFORE_FENCE,不存在 fence、order_submission、result 或提交点击。 - 静态调用图/import 闭包证明不可达 submission fence、SubmissionPermit、click_permitted、submit_order_once 与任何付款能力。 - 真机验收必须由人完成,记录设备/Android/拼多多版本、三个证据路径、三闸门读回、最终控件只读观察和一次 Back 后置状态;确认前保持 DOING。 - client 全量 unittest、compileall、wheel metadata、完整 init、上下文、Vikunja export 与 diff-check 通过。 ## 执行记录 ### 2026-08-04T14:11:20Z · ila 2026-08-04 任务定值:T-305 只做围栏前单趟 dry-run,总装已验收的 T-107/T-304/T-306/T-307/T-210 能力;正常路径最终写 DRY_RUN_COMPLETED_BEFORE_FENCE 并安全返回,不请求围栏、不创建 order_submission、不点击提交订单、不涉及付款。 ### 2026-08-06T02:58:55Z · ila 2026-08-06T02:58:54.857Z · Codex 2026-08-06 T-305 顺序改为 Gate1 → 数量/Gate2 → 保持同一合并式最终提交面板零页面点击观察 Gate3/最终控件 → 一次安全 Back。删除确认页导航动作;Gate3 最终控件金额不得用于 Gate1/Gate2。 ## 边界 - 2026-08-06 起删除确认页导航步骤:Gate2 后保持同一合并式最终提交面板,以零页面点击观察 Gate3 最终控件金额和最近可点击祖先唯一性,然后只执行一次安全 Back。任何旧导航判据都不得实现或调用。 - 只实现 `PreFenceDryRunOrchestrator` 与围栏前 UI 组合;不得在本任务的构造、import 闭包或运行时 引入 submission fence/result client、`SubmissionPermit`、`click_permitted`、submitter、 `submit_order_once()`、`order_submission` 或任何付款能力。 - 本任务不得修改 `client/src/cmbuyer_client/pdd/**` 或新增页面 selector/坐标/判据;只调用依赖任务 已完成人工验收且版本绑定的窄能力。未完成验收、版本不匹配或观察不唯一时必须停止,不能猜测。 - 同一趟动作顺序固定为闸门一、数量与闸门二、证据绑定的唯一确认页导航、闸门三/最终控件只读观察、 一次安全 Back。最终控件不得暴露节点/selector/坐标/句柄,也不得发生点击。 - 每个真机动作前必须先写固定 action journal。结果不明、超时、停止、Esc、关闭窗口或重启均不得 自动重试页面动作、续跑下一步、清 journal、释放 claim 或转领;重启只允许同键同载荷 HTTP 调和。 - 三闸门截图必须先经 T-306 取得服务端确认的 `AssetRef`,再由 T-307 写对应固定事件;不得先写成功 事件、替换不明证据、串 attempt/generation,或上传 XML/manifest/目录。 - 正常 dry-run 必须以固定 reason `DRY_RUN_COMPLETED_BEFORE_FENCE` 在围栏前安全终止;不得请求、 模拟或伪造围栏,不得创建待付款订单。本任务不编写支付、免密支付、先用后付或任何扣款代码。 - `needs_device: true` 的最终验收只能由人完成。离线验证通过后仍保持 `DOING`,直到人确认三闸门 证据、最终提交控件仅被观察、一次 Back 安全返回且没有创建订单。