docs(tasks): complete MVP safety task graph
This commit is contained in:
@@ -87,13 +87,15 @@ T-103 的 `SkuSelectionFlow` 只允许证据绑定的受控入口、精确选择
|
||||
|
||||
执行按任务依赖驱动,**不按 Phase 整段串行等待**。当前优先路径:
|
||||
|
||||
1. T-111 先冻结“开始采购授权”的单趟契约;同时主审并合入只创建 `DRAFT` 的 T-202。
|
||||
2. T-111 完成后恢复 **T-103 真机取证**;按依赖推进 T-104 → T-107 的分段安全判据。
|
||||
3. admin agent 先做 T-209 把旧两趟 schema / 状态机迁到单趟,再推进 T-203 服务端批量开始采购 /
|
||||
一次性授权;两者不依赖页面选择器。T-205 起的 attempt 与证据字段等待 T-103。
|
||||
4. Phase 3:双端打通与单趟围栏前 dry-run。
|
||||
5. Phase 4:单趟真实提交、待付款、调和与收尾。
|
||||
6. V2 及以后:图搜、Excel、ERP、订单自动核对、AI 辅助。
|
||||
1. 完成 **T-103 人工真机验收**,再按依赖推进 T-104 → T-107 的分段安全判据。
|
||||
2. admin agent 在 T-107 后推进 T-210 → T-205 → T-206 → T-207 → T-208,冻结三闸门证据、
|
||||
attempt 事件、围栏、一次性结果与人工调和。
|
||||
3. client agent 先做当前可领取的 T-303,再推进 T-304 / T-306 / T-307 / T-308;与 admin 写路径
|
||||
不重叠的任务继续并行。
|
||||
4. T-305 完成围栏前真机 dry-run;T-400 只用 fixture/fake port 建立离线一次性提交安全闭包。
|
||||
5. T-403 → T-402 先准备围栏后调和与人工付款事实记录;T-401 才在新真实单趟中首次点击一次,
|
||||
点击后固定报 `UNKNOWN` 并由人调和,绝不付款。
|
||||
6. T-405 生成可核验 Windows 包,T-404 对同一候选 commit 与产物做最终只读验收;V2 能力继续后置。
|
||||
|
||||
> **M2 是本项目的生死线**:真机能按链接打开商品、精确勾选颜色分类和尺码、
|
||||
> **读到该 SKU 的单价**(T-103)。前序项目正是卡在选规格和读价。
|
||||
|
||||
+12
-10
@@ -20,9 +20,9 @@ Phase 是里程碑分组,不是整段串行栅栏。推荐波次:
|
||||
| 1 | T-001 → T-004 → T-201 → T-202 | T-002 → T-101 → T-102 | T-003、原型与契约 |
|
||||
| 2 | T-209 → T-203 → T-204 | T-103 → T-104 → T-105 → T-107 | T-111 单趟重构;逐任务主审 |
|
||||
| 3 | T-210 → T-205 → T-206 → T-207 → T-208 | T-301 → T-302 → T-303,再并行 T-304 / T-306 / T-307 | 双端契约完整门禁 |
|
||||
| 4 | - | T-305 | 围栏前端到端 dry-run 主审 |
|
||||
| 5 | T-402 / T-403 | T-401 | 真机人工授权、提交与调和验收 |
|
||||
| 6 | - | T-405 | T-404 完整验收 |
|
||||
| 4 | T-403 → T-402 | T-305;T-208 / T-303 / T-307 后做 T-308;再汇合到 T-400 | 围栏前 dry-run、客户端围栏恢复与离线单次提交主审 |
|
||||
| 5 | - | T-401 | 新真实单趟、首次一次性提交与人工调和验收 |
|
||||
| 6 | - | T-405 | T-404 完整只读验收 |
|
||||
|
||||
并行门禁:
|
||||
|
||||
@@ -94,17 +94,19 @@ T-106 / T-107 是发布前只读验证,不是业务任务的第一趟。首次
|
||||
| T-304 | 定时轮询与会话边界 | T-303, T-006 | 人启动后轮询;停止只阻止下次领取;连续失败停;当前任务/记录详情双视图 |
|
||||
| T-306 | 规格面板原始截图与可靠证据上传 | T-104, T-303 | 只发布 Gate1 的显式原始 PNG;唯一恢复槽;可含页面地址/手机号;不上传 XML/路径或扩 kind |
|
||||
| T-307 | 客户端 attempt 事件与失败 sink | T-205, T-303 | 窄 events/fail HTTP 与同键恢复;不实现 ResultSink、围栏、结果、PDD 或 UI |
|
||||
| T-308 | 客户端提交围栏与结果 sink | T-208, T-303, T-307 | 复用同一 transport/localstate;首次明确且 durable 的 CREATE_ONCE 才产生当前进程 opaque permit;重启不可重建 |
|
||||
| T-305 | **单趟围栏前端到端 dry-run** | T-107, T-304, T-306, T-307, T-210 | 连续跑到三闸门及最终控件只读观察,随后一次安全 Back 并以固定 reason 停在围栏前;不申请许可、不点击提交 |
|
||||
|
||||
### Phase 4 · 真实提交与收尾
|
||||
|
||||
| ID | 任务 | 依赖 | 验收要点 |
|
||||
| --- | --- | --- | --- |
|
||||
| T-401 | **单趟采购与提交围栏端到端** | T-305, T-208 | 同一设备会话通过三闸门、首次明确围栏许可后点击一次;结果不明只调和;明确创建转待付款;绝不付款 |
|
||||
| T-402 | 待付款收口与手工完成 | T-401 | 详情展示订单证据;人付款后手工标记;待付款不等于成功 |
|
||||
| T-403 | 失败分类与证据归档 | T-401 | 覆盖需求 reason;终态原子回写;围栏后无重试 |
|
||||
| T-404 | 完整 MVP 验收 | T-402, T-403 | P0 验收、双端门禁、真机记录和 current-state 全部通过 |
|
||||
| T-405 | 采购工具打包与运行文档 | T-404 | 运营电脑可安装运行,记录产物 SHA-256 |
|
||||
| T-400 | 离线单次提交安全编排 | T-305, T-308 | 只用 fixture/fake port 证明四条件、点击意图先落盘、调用恰好一次和崩溃后只调和;生产接线仍不可达 |
|
||||
| T-403 | 失败分类、证据归档与管理员调和视图 | T-208 | 只展示已有事实并复用同一 submission 调和事务;围栏后无重试、释放或重新授权 |
|
||||
| T-402 | 待付款人工收口与付款事实记录 | T-403 | 只记录人已在外部付款的事实;三组确认、完整 lineage 与追加式审计;系统不付款 |
|
||||
| T-401 | **首次真实提交与生产接线** | T-400, T-402 | 新真实单趟重新通过三闸门;首次明确许可后点击一次;首次运行固定 UNKNOWN 并人工调和;绝不付款 |
|
||||
| T-405 | 采购工具 Windows 打包与运行文档 | T-401 | PyInstaller onedir ZIP;拒绝秘密/状态/证据/tests/XML;记录 commit 与 SHA-256 |
|
||||
| T-404 | 完整 MVP 只读验收 | T-401, T-402, T-403, T-405 | 冻结同一候选 commit/产物做 P0、双端门禁和真机记录复核;缺陷退回原任务,不在验收任务修复 |
|
||||
|
||||
### V2 及以后
|
||||
|
||||
@@ -126,8 +128,8 @@ T-106 / T-107 是发布前只读验证,不是业务任务的第一趟。首次
|
||||
- **M2**:真机按链接打开商品、精确选择颜色/尺码并读 SKU 单价。(T-103)
|
||||
- **M3**:真机设置数量、闸门二、确认页闸门三和唯一提交控件 dry-run 通过,不点击。(T-107)
|
||||
- **M4**:管理员建单并通过批量开始采购创建一次性授权;设备可安全领取。(T-203、T-302)
|
||||
- **M5**:单趟从领取到围栏前 dry-run 跑通,事件与证据齐全。(T-305)
|
||||
- **M6**:单趟真实提交只创建待付款订单,围栏/调和/人工收口闭环。(T-401~T-404)
|
||||
- **M5**:围栏前 dry-run 跑通,客户端围栏恢复和离线一次性提交安全闭包成立。(T-305、T-308、T-400)
|
||||
- **M6**:新真实单趟只创建可能的待付款订单,围栏/调和/人工收口、Windows 交付和只读验收闭环。(T-401~T-405)
|
||||
|
||||
**M2 仍是生死线。** M2 前可以并行管理会话、DRAFT 建单和开始采购的服务端授权事务,但不能编写
|
||||
依赖未取证页面字段的生产执行逻辑。提速来自两端并行、窄任务和主审复用门禁,不来自删除安全闸门。
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
| IX-004 | US-002、US-004 | web 列表行 / `/tasks/{id}` | 双击行、浏览器前进后退 | 路由化详情抽屉或完整页,显示执行证据 | P0 | 已定 |
|
||||
| IX-005 | US-005 | web 批量操作条 | 点击开始采购 | 创建一次性授权并进入 `PENDING` | P0 | 已定 |
|
||||
| IX-006 | US-006 | web 待付款详情 | 查看后手工标记 | 只记录人工付款完成,不执行支付 | P0 | 已定 |
|
||||
| IX-007 | US-003 | desk 配置 tab | 保存并检查连接 | 服务、ADB、App 版本就绪 | P0 | 已定 |
|
||||
| IX-007 | US-003 | desk 配置 tab | 保存并校验配置 | 本地字段/路径有效;服务身份与真机能力在真实流程中验证 | P0 | 已定 |
|
||||
| IX-008 | US-003、US-008 | desk 采购执行 tab | 开始 / 停止轮询、选择记录、Esc | 单趟执行和安全人工接管 | P0 | 已定 |
|
||||
| IX-009 | US-008 | web / desk 通用错误反馈 | 请求或流程失败 | 显示阶段、原因和安全下一步 | P0 | 已定 |
|
||||
| IX-010 | US-005 | web 围栏前人工处理 | 重置 / 取消 | 关闭旧授权后回 `DRAFT` 或取消 | P0 | 已定 |
|
||||
@@ -57,7 +57,8 @@
|
||||
|
||||
### IX-006 待付款核对与标记完成
|
||||
|
||||
- 页面显示商品、目标与实际规格、数量、授权上限、两次单价、确认页总额和订单截图。
|
||||
- 页面显示商品、目标与实际规格、数量、授权上限、两次单价、确认页总额和三闸门内部证据;MVP
|
||||
没有提交后结果截图类型,不把确认页图片冒充订单结果图。
|
||||
- 首屏警示:“订单已创建,系统尚未付款。请在拼多多人工核对并付款。”
|
||||
- “标记为已付款并完成”只写系统状态,不打开支付页面、不触发手机操作。
|
||||
- 提交前用简短确认对话框说明这是人工事实记录;成功转 `SUCCEEDED`,重复提交幂等。
|
||||
@@ -105,7 +106,8 @@
|
||||
1. 当前任务在同一趟内完成闸门二和闸门三,并确认提交控件精确唯一。
|
||||
2. 客户端显示“正在申请提交围栏”,提交当前验证摘要。
|
||||
3. 只有服务端首次明确返回 `click_permitted=true`,客户端才先持久化唯一点击意图,再精确点击一次。
|
||||
4. 明确创建转待付款;外部支付、安全校验、超时、断连或未知页面转待调和。
|
||||
4. MVP 首次真实点击后因没有已取证的提交后页面判据,无条件上报 `UNKNOWN` 并转待调和;只有管理员
|
||||
对同一 submission 明确调和为已创建,才转待付款。
|
||||
5. 围栏后的 web 详情只显示同一 `submission_id` 的证据、调和记录与人工结论。
|
||||
|
||||
| 状态 | 允许动作 | 禁止动作 |
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
| 路径 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `docs/` | 已有 | 项目规范化文档,本次已完整生成 |
|
||||
| `docs/tasks/` | 已有(含 T-001~T-111、T-201~T-210、T-301~T-307) | T-302 已完成;T-103 等最终真机验收,后续三闸门与双端组合任务已按依赖落成 |
|
||||
| `docs/tasks/` | 已有(含 T-001~T-111、T-201~T-210、T-301~T-308、T-400~T-405) | T-302 已完成;T-103 等最终真机验收;双端围栏、真实提交、调和、打包与只读验收均已落成任务 |
|
||||
| `docs/design/` | 已有(6 个原型) | web 登录 / 建单 / 工作台 / 详情,desk 采购执行 / 配置;均已人工确认 |
|
||||
| `scripts/` | 已有 | 上下文门禁、Vikunja 单向导出与 MCP 启动包装 |
|
||||
| `admin/` | 已初始化 | Go 1.23+ / gin / SQLite,含建单/授权/详情/证据/设备身份与原子 claim/renew;不执行真机动作 |
|
||||
@@ -75,6 +75,9 @@
|
||||
稳定重放和续租;claim token 不是提交许可,尚无事件、提交围栏或结果 API。
|
||||
- T-103 离线 `SkuSelectionFlow` 已实现并通过独立审计,仍为 `DOING` 等人工真机验收;T-104~T-107
|
||||
按数量/确认页风险逐段开放。服务端后续顺序已收紧为 T-210 → T-205 → T-206 → T-207 → T-208。
|
||||
- 客户端当前可直接领取 T-303;其后按依赖推进 T-304/T-306/T-307/T-308,再与 T-305 汇合到
|
||||
T-400 离线一次性提交安全编排。围栏后管理链为 T-403 → T-402;T-401 必须在新的真实单趟重新
|
||||
通过三闸门,首次点击后固定进入 `UNKNOWN`/人工调和,T-405 打包后由 T-404 只读验收。
|
||||
- 已确认原型继续只作信息架构依据;原型假数据不调用真实接口、不驱动真机。真机结论改变
|
||||
可读字段时必须先回修原型与交互清单。
|
||||
|
||||
|
||||
+6
-3
@@ -76,7 +76,8 @@
|
||||
2. 开始采购授权:授权 id、授权人、锁定任务版本、创建/有效期、当前状态。
|
||||
3. 设备执行:attempt、设备、App 版本、步骤时间线和失败 code。
|
||||
4. 三道闸门:两次规格面板单价、规格/数量读回、确认页总额与判定。
|
||||
5. 内部截图:规格面板、确认页和结果页;只经受保护端点读取。
|
||||
5. 内部截图:三道闸门已批准的规格面板/确认页证据;只经受保护端点读取。MVP 不存在提交后结果
|
||||
截图类型,不展示外部支付页,也不把 Gate3 图片冒充结果图。
|
||||
6. 提交围栏:submission id、是否首次明确许可、唯一点击和调和记录。
|
||||
7. 待付款收口:明确写系统尚未付款;人工核对后记录完成。
|
||||
|
||||
@@ -122,10 +123,12 @@ T-204 只显示数据库中当前实际存在的任务、授权、attempt、subm
|
||||
|
||||
### 配置 tab
|
||||
|
||||
- 采购服务 URL、设备 token(密码框,不回显完整值);
|
||||
- 采购服务 URL、设备 token(密码框,不回显完整值;首次必填,已有凭据时留空表示保留,非空表示替换);
|
||||
- ADB 路径、设备 serial、USB/WiFi 通道选择;
|
||||
- 轮询间隔与连续失败停止阈值;
|
||||
- 连接检查:服务、设备身份、拼多多安装和已取证版本。
|
||||
- 只做本地字段与路径格式检查,并提示服务身份、设备连接、拼多多安装和已取证版本将在首次真实领取/
|
||||
后续已批准真机流程中验证。配置页不调用 `claim-next`、renew、evidence 等业务 API,也不运行 ADB/PDD
|
||||
作为“连接检查”;MVP 不提供清除已保存设备凭据的命令。
|
||||
|
||||
配置凭据进入系统安全存储;日志和界面不显示完整 token。
|
||||
|
||||
|
||||
+19
-10
@@ -22,7 +22,7 @@ write_paths:
|
||||
- docs/06-tasks.md
|
||||
---
|
||||
|
||||
<!-- BEGIN VIKUNJA EXPORT id=37 synced=2026-08-04T13:36:35Z sha256=43abf519936af610d20823dfaf4e55a98529fc0cbb21a8cc3e90f00eb3daa713 -->
|
||||
<!-- BEGIN VIKUNJA EXPORT id=37 synced=2026-08-04T15:18:59Z sha256=70cde8bfacd40b2c2a7132dc0f0390689682403c7934587efb25348b40796826 -->
|
||||
## 问题 / 背景
|
||||
|
||||
T-006 已确认采购工具双 Tab 原型,T-303 将提供唯一的 HTTP、本地恢复、DPAPI 与单实例底座。T-304 把原型转换为可测试的原生 PySide6 主界面和定时轮询协调器,但在真实单趟执行器接入前不得领取真实任务,避免形成无人消费的 active claim。
|
||||
@@ -41,17 +41,20 @@ T-006 已确认采购工具双 Tab 原型,T-303 将提供唯一的 HTTP、本
|
||||
2. 采购执行页顶部显示连接、轮询、当前任务与连续失败状态,开始/停止复用同一 `QAction`。独立运行且未注入 execution consumer 时开始按钮禁用,并显示“单趟执行能力尚未接入,不能领取真实任务”。
|
||||
3. 主体使用 `QSplitter`。左侧 `QStackedWidget` 在“当前任务”和“采购记录详情”间切换;当前任务左侧文字、右侧图片约 2:1,下方为滚动日志。右侧使用 `QTableView + QAbstractTableModel` 显示按时间倒序的标题和状态,不放假记录。
|
||||
4. 记录表单击只选择;双击非控件区域、Enter、显式“查看所选记录”和上下文命令复用同一 QAction。详情态选择另一行立即更新;Esc 仅从详情返回当前任务,不停止轮询、不关闭程序、不改变服务端状态,并恢复记录选择、滚动和焦点。
|
||||
5. 配置页使用 `QScrollArea + QFormLayout` 显式保存。service URL 为只读精确 `http://127.0.0.1:8080`;设备 token 使用密码框,保存后立即清空、不回填。没有 heartbeat 时不得调用 claim-next 测试连接,只显示凭据将在首次真实领取时验证。
|
||||
6. 配置承载 device id、ADB 路径、serial/transport、轮询间隔默认 15 秒且范围 5–300、连续失败阈值默认 3 且范围 1–10、HTTP 超时默认 10 秒且范围 1–120、真机步骤超时默认 45 秒且范围 5–300。pending/active claim 时冻结 service/device 身份。
|
||||
7. 轮询协调器状态固定为 STOPPED、STARTING、BLOCKED、RECOVERING、WAITING、CLAIMING、ACTIVE、RECOVERY_REQUIRED。启动必须先取得 T-303 单实例 guard 并加载 recovery snapshot;重启不自动开始,active claim 只显示待安全恢复。
|
||||
8. 停止只设置 `accept_new_claims=false`。WAITING 取消下一计时器;CLAIMING 等待有界结果并先落库;返回 claim 后进入 RECOVERY_REQUIRED。不得中断已发请求、清 pending/active、release/abandon、生成新 key/session 或调用真机返回动作。
|
||||
9. `QTimer` 只调度下一轮;阻塞 I/O 放长期 worker QObject/QThread,worker 不接触 Widget。claim 业务结果必须先交 T-303 持久化,不能因 UI generation 过期而丢弃;迟到的纯视图结果按稳定 request id 丢弃。
|
||||
10. 连续失败只统计 T-303 标记为可用同幂等键安全重放的网络、超时、5xx 或截断;同 pending request 按轮询间隔重放,达到阈值立即停止。401、协议错误、409、DPAPI/SQLite 错误立即转持久 Banner,不进入普通重试。
|
||||
5. 配置页使用 `QScrollArea + QFormLayout` 显式保存。service URL 为只读精确 `http://127.0.0.1:8080`;token 使用密码框且永不回填,只显示“已保存/未保存”布尔状态。首次保存且 `has_stored_device_token=false` 时 token 必填;已有凭据时,规范化后的空输入表示保留现有 DPAPI 密文,非空输入才通过 T-303 原子 profile API 替换。成功后清空输入框;失败保留全部输入并聚焦首个错误。MVP 不提供清除/删除凭据命令,空值绝不能覆盖或删除既有凭据。
|
||||
6. 配置承载 device id、ADB 路径、serial/transport、轮询间隔默认 15 秒且范围 5–300、连续失败阈值默认 3 且范围 1–10、HTTP 超时默认 10 秒且范围 1–120、真机步骤超时默认 45 秒且范围 5–300。只执行必填、格式、范围以及本地路径形态/存在性校验,不执行路径所指程序;pending/active claim 时冻结 service/device 身份。
|
||||
7. 配置页不提供“检查连接/测试连接”按钮、QAction、worker 或隐藏探测。保存和本地校验不得发送 HTTP health、`claim-next`、`renew`、`evidence`,也不得调用 ADB、uiautomator2 或拼多多。稳定内联提示为“服务身份将在首次真实领取时验证;设备与 App 状态由后续已取证执行能力验证”。本地校验通过不等于服务、设备或 App 已就绪。
|
||||
8. 轮询协调器状态固定为 STOPPED、STARTING、BLOCKED、RECOVERING、WAITING、CLAIMING、ACTIVE、RECOVERY_REQUIRED。启动必须先取得 T-303 单实例 guard 并加载 recovery snapshot;重启不自动开始,active claim 只显示待安全恢复。
|
||||
9. 停止只设置 `accept_new_claims=false`。WAITING 取消下一计时器;CLAIMING 等待有界结果并先落库;返回 claim 后进入 RECOVERY_REQUIRED。不得中断已发请求、清 pending/active、release/abandon、生成新 key/session 或调用真机返回动作。
|
||||
10. `QTimer` 只调度下一轮;阻塞 I/O 放长期 worker QObject/QThread,worker 不接触 Widget。claim 业务结果必须先交 T-303 持久化,不能因 UI generation 过期而丢弃;迟到的纯视图结果按稳定 request id 丢弃。
|
||||
11. 连续失败只统计 T-303 标记为可用同幂等键安全重放的网络、超时、5xx 或截断;同 pending request 按轮询间隔重放,达到阈值立即停止。401、协议错误、409、DPAPI/SQLite 错误立即转持久 Banner,不进入普通重试。
|
||||
|
||||
## 验收要点
|
||||
|
||||
- 纯状态机覆盖开始、EMPTY、等待、停止、请求中停止、claim 落库、无重叠请求、同键恢复、失败阈值、401/403/409/本地错误和 active 阻止新领取。
|
||||
- QtTest 覆盖默认 Tab、固定 Tab 状态、按钮禁用原因、配置验证/Ctrl+S/token 不回显、记录倒序、单击/双击/Enter/按钮、详情切换、Esc 层级与焦点恢复。
|
||||
- QtTest 覆盖默认 Tab、固定 Tab 状态、按钮禁用原因、记录倒序、单击/双击/Enter/按钮、详情切换、Esc 层级与焦点恢复。
|
||||
- 配置测试覆盖:首次无凭据时空 token 拒绝且零 T-303 写入;已有凭据时空 token 原样保留既有 DPAPI 密文;非空 token 只替换一次且成功后清空输入;失败保留输入并聚焦首个错误;界面无 token 回读和清除/删除命令,日志与异常均无 token。
|
||||
- 配置页不存在连接检查命令;保存、本地校验以及 consumer 未注入时点击禁用的开始入口均产生零 HTTP health、零 `claim-next`/`renew`/`evidence`、零 ADB/uiautomator2/PDD,并显示延后验证提示。静态检查不得出现网络或 ADB 探测调用链。
|
||||
- compact/medium/wide 不重建模型或丢选择;长文案、100%–200% DPI、浅色/深色/高对比与纯键盘行为可人工复核。
|
||||
- 应用独立启动、切换 Tab、Esc、查看记录与关闭窗口均产生零 claim、零 release、零 ADB;代码不导入 PDD 点击、数量、确认页、围栏、提交或付款能力。
|
||||
- client 全量 unittest、compileall、wheel metadata、根目录完整 init、Vikunja 导出、上下文校验与 diff-check 通过。
|
||||
@@ -76,8 +79,14 @@ T-006 已确认采购工具双 Tab 原型,T-303 将提供唯一的 HTTP、本
|
||||
必须先由 T-303 原子落库再更新 UI。
|
||||
- 重启不自动开始轮询,不自动恢复任何真机点击。pending claim 只能用原 session/request 恢复;active
|
||||
claim 只显示“待安全恢复”并阻止新领取,租约过期或 409 交 T-207 人工处理。
|
||||
- 配置页不得使用 `claim-next` 充当“测试连接”,因为它会产生 EMPTY 幂等事实甚至领取任务。服务地址
|
||||
只读为精确 `http://127.0.0.1:8080`;token 保存后立即清空输入框,不回填、不入日志或异常文本。
|
||||
- 配置页只允许必填、格式、范围以及本地路径形态/存在性校验,不得提供或隐藏任何网络/ADB“连接检查”;
|
||||
保存、校验都不得调用 HTTP health、`claim-next`、`renew`、`evidence`,也不得执行 ADB、uiautomator2
|
||||
或拼多多探测。界面必须明确提示“服务身份将在首次真实领取时验证;设备与 App 状态由后续已取证执行
|
||||
能力验证”,本地校验通过不能显示服务、设备或 App 已就绪。
|
||||
- 服务地址只读为精确 `http://127.0.0.1:8080`。首次保存且没有既有 DPAPI 凭据时 token 必填;已有
|
||||
凭据时空输入表示原样保留现有密文,非空输入才通过 T-303 的原子 profile API 替换,绝不能用空值
|
||||
覆盖或删除。保存成功后清空 token 输入框且永不回填;保存失败保留输入并聚焦首个错误。MVP 不提供
|
||||
清除/删除凭据命令,token 不得进入日志或异常文本。
|
||||
- Qt worker 不得直接访问 Widget,UI 回调不得丢弃迟到的 claim 业务结果。连续失败只允许用 T-303
|
||||
已持久化的同一幂等键重放安全网络操作;`retryable` 绝不推导为页面点击、证据替换、下单或提交可重试。
|
||||
- 记录表的双击仅是非破坏性详情入口,并必须有 Enter 和显式按钮等价路径。Esc 只在详情态返回当前任务,
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
---
|
||||
id: T-308
|
||||
title: 客户端提交围栏与结果 sink
|
||||
phase: 3
|
||||
deps: [T-208, T-303, T-307]
|
||||
status: TODO
|
||||
created: 2026-08-04
|
||||
vikunja_task_id: 49
|
||||
context_ref: 8600c33
|
||||
work_branch: task/t-308-submission-sink
|
||||
needs_device: false
|
||||
needs_human_review: true
|
||||
write_paths:
|
||||
- docs/tasks/T-308.md
|
||||
- client/src/cmbuyer_client/submissions/**
|
||||
- client/src/cmbuyer_client/core/**
|
||||
- client/src/cmbuyer_client/remote/**
|
||||
- client/src/cmbuyer_client/localstate/**
|
||||
- client/tests/submissions/**
|
||||
- client/tests/core/**
|
||||
- client/tests/remote/**
|
||||
- client/tests/localstate/**
|
||||
---
|
||||
|
||||
<!-- BEGIN VIKUNJA EXPORT id=49 synced=2026-08-04T14:51:43Z sha256=ac3851bab830634e65029a7a80985946cb3aa5bf80bff1727e3e7e0fc8c30ad5 -->
|
||||
## 问题 / 背景
|
||||
|
||||
T-303 只提供 claim/renew/evidence 的严格 HTTP、本地 DPAPI/SQLite 与恢复底座,T-307 只实现围栏前 events/fail,二者都明确禁止伪造 fence/result。T-208 将冻结服务端 CREATE_ONCE、LOOKUP_ONLY、一次性 result 与同一 submission 调和语义。T-308 补齐客户端提交围栏与结果 sink,并把许可、点击意图和结果恢复事实写入 T-303 的同一 localstate;本任务不连接真机、不接 UI、不执行或暴露任何点击。
|
||||
|
||||
## 关联需求与交互
|
||||
|
||||
- 功能:F-007、F-011、F-017。
|
||||
- 用户故事:US-004、US-005、US-008。
|
||||
- 交互:IX-011;只实现后台契约和恢复状态,不实现界面。
|
||||
- 依赖:T-208、T-303、T-307。
|
||||
- 后续消费者:T-400 离线单次提交安全编排。
|
||||
- API:CREATE_ONCE / LOOKUP_ONLY submission fence 与一次性 submission result;严格消费 T-208 最终 wire。
|
||||
|
||||
## 方案
|
||||
|
||||
1. 定义窄 SubmissionSink:create_submission_fence、lookup_submission_fence、prepare_click_intent、report_submission_result。proof/result 值对象只含 T-208 固定 UUID、claim 归属、规范十进制金额、正整数、三闸门 AssetRef、精确 submit 文本/计数和固定 observation;不接收自由页面文本、XML、路径、selector、坐标或动作脚本。
|
||||
2. HTTP 必须复用 T-303 的精确 loopback、禁代理/重定向、有界请求/响应和严格 JSON 解析。每次方法最多一次传输,不在 transport 或 sink 内隐藏重试。
|
||||
3. 只扩展 T-303 的同一 SQLite/localstate,不建立第二个数据库。首次网络前原子保存 fence_key、operation、完整规范 proof、active claim 绑定和预期状态;DPAPI、SQLite 或归属校验失败时零 HTTP。
|
||||
4. CREATE_ONCE 结果不明时只允许以原 fence_key、原 proof 调用 LOOKUP_ONLY。不得换 key、再次 CREATE_ONCE 或根据本地页面猜测围栏是否存在;LOOKUP_ONLY 找到或未找到都不得产生可点击许可。
|
||||
5. 只有当前进程当前 CREATE_ONCE 调用收到首次、明确、完整且严格核对的 click_permitted=true 响应,并已把 submission 与许可事实 durable 落盘后,才由模块私有工厂返回 opaque SubmissionPermit。响应截断、协议漂移、落盘失败、重放、LOOKUP_ONLY 或 click_permitted=false 均不返回 permit。
|
||||
6. SubmissionPermit 不提供公共构造器,不可 pickle/JSON/复制,不写入 SQLite、日志或异常。SQLite 只保存围栏和恢复审计事实;重启后无论数据库记录什么都不能重建可点击 permit,只能进入同一 submission 的调和路径。
|
||||
7. prepare_click_intent 必须消费当前进程唯一 permit,在返回一次性 ArmedSubmission 前原子写入“即将发出唯一点击”。同 permit 二次调用、并发调用、active claim 漂移或已有点击意图均拒绝;重启只看到 reconcile-only 事实,不能重新 arm。
|
||||
8. result_key、固定 observation 与 submission/attempt/冻结归属在首次 result HTTP 前原子保存。结果不明和重启只能重放原 key、原载荷;明确成功后保存服务端终态。同一 submission 不得创建第二个 observation 或把 UNKNOWN 改写成 SUBMITTED。
|
||||
9. 401、403、409、非法 2xx、本地状态错误按 T-303 分类停止;网络、超时、5xx 只表示原幂等 HTTP 可调和,绝不表示 fence、permit、点击或页面动作可重试。
|
||||
10. 构造和 import 闭包不包含 pdd、device、uiautomator2、UI、execution、app、通用 click、SubmitOrderPort、submit_order_once 或任何 payment 能力。
|
||||
|
||||
## 验收要点
|
||||
|
||||
- 覆盖首次 CREATE_ONCE、同键重放、LOOKUP_ONLY 找到/未找到、响应截断/漂移、落盘失败、401/403/409/503;只有首次明确且 durable 成功返回 opaque permit。
|
||||
- 覆盖并发围栏、并发 prepare_click_intent、同 permit 二次消费、进程重启和 SQLite 恢复;任一非首次路径均无法获得或重建 permit/ArmedSubmission。
|
||||
- 证明 fence/result 首次网络前已持久化完整键、载荷与 frozen claim 绑定;不明结果只重放原 HTTP 事实,不产生新 key 或第二 observation。
|
||||
- 证明 SQLite/WAL、日志、异常和 DTO 不含明文 token、页面正文、XML、本机路径、selector、坐标或可点击对象。
|
||||
- 静态 import/AST 检查证明 pdd/device/UI/app/execution、真机 click、submit_order_once 和任何付款能力不可达。
|
||||
- client 全量 unittest、compileall、wheel metadata、完整 init、上下文、Vikunja export 与 diff-check 通过。
|
||||
- needs_human_review:人工审阅 opaque permit 的构造边界、首次许可与重启不可重建证明;确认前不得标 DONE。
|
||||
|
||||
## 执行记录
|
||||
|
||||
(暂无)
|
||||
<!-- END VIKUNJA EXPORT -->
|
||||
|
||||
## 边界
|
||||
|
||||
- 本任务只实现 T-208 已冻结的 `CREATE_ONCE`、`LOOKUP_ONLY` 与一次性 result 客户端契约,
|
||||
并复用 T-303 同一 transport/localstate。不得另建 HTTP 客户端、SQLite、DPAPI 封装或第二份
|
||||
权威恢复状态;本地与服务端事实冲突时只能停止并调和。
|
||||
- 只有当前进程当前 `CREATE_ONCE` 调用收到首次、明确、完整且已 durable 落盘的
|
||||
`click_permitted=true` 响应,才可由模块私有工厂产生 opaque `SubmissionPermit`。同键重放、
|
||||
`LOOKUP_ONLY`、响应不明、解析/落盘失败、并发输家和服务重启均不得产生许可。
|
||||
- `SubmissionPermit` 与一次性 `ArmedSubmission` 不得公开构造、序列化、复制、写入 SQLite 或从
|
||||
恢复快照重建。SQLite 只能保存围栏、点击意图与调和事实;进程退出后即使尚不能确认是否点击,
|
||||
也只能进入 `RECONCILE_ONLY`,不能重新 arm。
|
||||
- fence/result 的 key、完整规范载荷和 frozen claim 绑定必须先原子持久化再发送。HTTP 结果不明
|
||||
只能重放原 key、原载荷;不得换 key、再次 `CREATE_ONCE`、覆盖 observation 或把 HTTP 可恢复
|
||||
错误解释为页面动作可重试。
|
||||
- 本任务不得导入或修改 `client/src/cmbuyer_client/pdd/**`、`device/**`、`ui/**`、`execution/**`
|
||||
或 `app.py`,不得连接真机、持有 selector/坐标/节点/点击对象,也不得实现 `SubmitOrderPort`、
|
||||
`submit_order_once()` 或任何通用/具体点击。
|
||||
- 本任务不编写支付、免密支付、先用后付或任何扣款能力。外部支付、安全校验与未知结果只能作为
|
||||
T-208 固定 observation 保存并转调和,不能继续交互、释放围栏、重新授权、重新领取或再次提交。
|
||||
- `needs_human_review: true`:自动验证完成后仍保持 `DOING`,等待人审 opaque permit 构造边界、
|
||||
首次许可唯一性和重启不可重建证明;未经明确确认不得标 `DONE`。
|
||||
@@ -0,0 +1,93 @@
|
||||
---
|
||||
id: T-400
|
||||
title: 离线单次提交安全编排
|
||||
phase: 4
|
||||
deps: [T-305, T-308]
|
||||
status: TODO
|
||||
created: 2026-08-04
|
||||
vikunja_task_id: 50
|
||||
context_ref: 8600c33
|
||||
work_branch: task/t-400-offline-submission-orchestrator
|
||||
needs_device: false
|
||||
needs_human_review: true
|
||||
write_paths:
|
||||
- docs/tasks/T-400.md
|
||||
- client/src/cmbuyer_client/execution/submission_orchestrator.py
|
||||
- client/tests/execution/test_submission_orchestrator.py
|
||||
---
|
||||
|
||||
<!-- BEGIN VIKUNJA EXPORT id=50 synced=2026-08-04T15:04:36Z sha256=4f27bf3ca322f467cb742da1b9159cbb976f6939c0cd804021323a24fa4cc735 -->
|
||||
## 问题 / 背景
|
||||
|
||||
T-305 的正常 dry-run 会在同一设备会话完成三闸门与最终控件只读观察,随后执行一次安全 Back,并以固定 reason DRY_RUN_COMPLETED_BEFORE_FENCE 终止 attempt。它只证明围栏前代码和判据契约已验收,绝不产生可供真实提交复用的运行时 ReadyForSubmission。T-308 将提供严格 fence/result sink、当前进程唯一 permit 和不可恢复的点击意图能力。T-400 只用测试 fixture 验证纯 SinglePassSubmissionOrchestrator、四条件、一次性调用和崩溃闭包;不读取或复用 T-305 的对象、截图、证据、journal、缓存或旧 proof,不提供生产 ReadyForSubmission 构造入口,也不接入 app/UI/PDD/真机。
|
||||
|
||||
## 关联需求与交互
|
||||
|
||||
- 功能:F-006、F-007、F-011、F-017 的离线提交安全闭包。
|
||||
- 用户故事:US-003、US-005、US-008。
|
||||
- 交互:IX-011 的后台顺序;本任务无生产界面。
|
||||
- 依赖:T-305、T-308。T-305 只提供已验收的代码/判据契约,T-308 提供冻结接口;两者都不向本任务提供可提交的运行时事实。
|
||||
- 后续消费者:T-401 在全新真实任务、全新 attempt 的同一趟内重跑全部三闸门并即时构造生产 ReadyForSubmission。
|
||||
- 生产 app 的 import/call graph 在 T-401 前继续不可达本任务编排、ReadyForSubmission 生产构造和 SubmitOrderPort。
|
||||
|
||||
## 方案
|
||||
|
||||
1. 在单一窄 execution 模块实现纯 SinglePassSubmissionOrchestrator、只读 ReadyForSubmission 协议和抽象 SubmitOrderPort;只消费 T-308 已冻结的 SubmissionSink 接口,不修改 submissions/remote/localstate/core/PDD/UI/app。
|
||||
2. T-305 的 PreFenceDryRunOrchestrator、终止结果、action journal、AssetRef、截图、缓存、页面对象、attempt 或 proof 不能作为 ReadyForSubmission 输入。T-305 已 Back 且终止的 attempt 永远不能申请 fence、取得 permit 或进入提交编排。
|
||||
3. 本任务不提供任何生产 ReadyForSubmission 具体类、公共构造器、factory、adapter 或 from_dry_run/from_snapshot/from_evidence/from_localstate 路径。只有 tests 中的 immutable fixture 实现该只读协议;生产包内不存在把真实或旧事实装配成 ReadyForSubmission 的入口。
|
||||
4. 测试 fixture 必须显式给出一个虚构但内部一致的同一 task/authorization/attempt/generation/App 版本事实:未消费授权快照、Gate2/Gate3 通过、精确规格/数量/金额、三个受控 AssetRef 和提交文本/唯一计数。它只用于纯逻辑测试,不是页面证据或可发布业务事实。
|
||||
5. 编排在申请 fence 前重新校验 fixture 表达的四条件:一次性授权/claim 一致且未过期、Gate2 通过、Gate3 通过、submit 文本精确且唯一计数为一。任一缺失、漂移、金额不规范或版本不一致均零 fence、零 SubmitOrderPort 调用。
|
||||
6. 只有测试注入的 T-308 当前进程首次明确 SubmissionPermit 可继续。先调用 prepare_click_intent durable 写入唯一点击意图并取得一次性 ArmedSubmission;未成功 arm、重放许可、LOOKUP_ONLY、并发进入或重启恢复均零 SubmitOrderPort 调用。
|
||||
7. SubmitOrderPort 只暴露 submit_once(ArmedSubmission, VerifiedSubmitObservationBoundary)。编排层最多调用一次,不提供 retry、循环、回退、第二调用点或可重复 submit 函数;本任务只注入记录次数/故障点的 fake port,没有具体真机适配器。
|
||||
8. 调用前已经进入不可逆 reconcile-only 状态。fake port 返回、抛错、超时、进程停止或结果不明都不能回到可提交状态;异常只形成 UNKNOWN 待调和事实,不再次调用 port。
|
||||
9. fake port observation 只允许 SUBMITTED、EXTERNAL_PAYMENT_HANDOFF、SECURITY_CHALLENGE、UNKNOWN。编排通过 T-308 固定接口只上报一次 result;HTTP 不明只恢复原 key/载荷,不重复页面观察或提交动作。本任务不实现或测试任何基于真实页面的 SUBMITTED 推断。
|
||||
10. 停止轮询、Esc、查看历史、关闭窗口和重启不是编排的取消/重试输入;它们不能清 permit、点击意图、submission 或 result pending,也不能释放、重新授权、重新领取或推进下一任务。
|
||||
11. T-401 前生产 composition/import/call graph 必须同时证明:不可达 SinglePassSubmissionOrchestrator/SubmitOrderPort;不存在生产 ReadyForSubmission factory;T-305 dry-run 结果类型不可流入提交编排。
|
||||
|
||||
## 验收要点
|
||||
|
||||
- 参数化负例逐一移除授权/首次许可、Gate2、Gate3 或唯一控件,证明 fake SubmitOrderPort 调用数均为 0。
|
||||
- 首次明确 permit + durable 点击意图的纯测试用例证明 fake port 调用数恰好为 1;并发、二次进入、permit 重放和重复 result 均不能增加计数。
|
||||
- fake port 在调用中或返回解析时抛错/超时,结果均为 reconcile-only/UNKNOWN,调用数仍恰好为 1 且无 retry。
|
||||
- 崩溃点覆盖 fence 响应前后、permit 落盘前后、点击意图前后、fake port 调用前后和 result 上报前后;恢复全部零 SubmitOrderPort 调用。
|
||||
- 固定测试至少包含 test_missing_each_submission_condition_never_calls_port、test_first_permit_calls_port_exactly_once、test_port_exception_never_retries、test_restart_after_click_intent_is_reconcile_only、test_t305_runtime_artifacts_are_not_accepted、test_no_production_ready_for_submission_factory、test_production_app_import_closure_cannot_reach_submission。
|
||||
- AST/import/call-graph 证明生产代码不存在 ReadyForSubmission 构造入口,T-305 已终止结果/截图/缓存/proof 到编排无数据流,app/UI/PDD/device/真实 click/payment 不在本任务闭包。
|
||||
- 任务 diff 只能修改窄 execution 实现/测试;T-308 submissions/remote/localstate/core 接口保持冻结且零 diff。
|
||||
- client 全量 unittest、compileall、wheel metadata、完整 init、上下文、Vikunja export 与 diff-check 通过。
|
||||
- needs_human_review:人工审阅 T-305 零运行时复用、生产 factory 不存在、一次性 fake port 调用和全部崩溃点;确认前不得标 DONE。
|
||||
|
||||
## 执行记录
|
||||
|
||||
(暂无)
|
||||
<!-- END VIKUNJA EXPORT -->
|
||||
|
||||
## 边界
|
||||
|
||||
- T-305 正常 dry-run 已执行一次安全 Back,并以 `DRY_RUN_COMPLETED_BEFORE_FENCE` 终止 attempt。
|
||||
本任务只能复用其已验收的代码/判据契约;不得接收或复用该次/任何 dry-run 的结果对象、attempt、
|
||||
screenshot、AssetRef、action journal、缓存、页面对象、本地快照或旧 proof 来申请围栏或提交。
|
||||
- 本任务只在单一窄 execution 文件实现纯 `SinglePassSubmissionOrchestrator`、只读
|
||||
`ReadyForSubmission` 协议和抽象 `SubmitOrderPort`;仅测试 fixture 可实现/构造该协议。生产代码
|
||||
不得存在具体 `ReadyForSubmission` 类、公共构造器、factory、adapter、反序列化或
|
||||
`from_dry_run` / `from_snapshot` / `from_evidence` / `from_localstate` 路径。
|
||||
- 本任务只消费 T-308 已冻结接口,不得修改 `submissions/**`、`remote/**`、`localstate/**` 或
|
||||
`core/**`。不得修改或导入 `app.py`、`ui/**`、`pdd/**`、`device/**`,不得连接真机、使用
|
||||
uiautomator2 或实现任何具体页面点击适配器。
|
||||
- 测试 fixture 表达的四条件必须属于同一虚构 task/authorization/attempt/generation 和 App 版本:
|
||||
未消费授权与首次明确围栏许可、Gate2、Gate3、精确唯一提交控件。它只验证纯逻辑,不是可复用的
|
||||
页面或业务事实;缺失、漂移、金额/规格/数量冲突均零 fake `SubmitOrderPort` 调用。
|
||||
- 编排必须先通过 T-308 durable 写入唯一点击意图,再把当前进程的一次性 `ArmedSubmission` 交给
|
||||
fake `SubmitOrderPort.submit_once()`。该方法在纯测试生命周期最多调用一次;不得存在 retry、循环、
|
||||
fallback、第二调用点或异常后重新进入路径。
|
||||
- 点击意图落盘后即进入 `RECONCILE_ONLY`。fake port 返回、抛错、超时、停止、关闭或进程崩溃都不得
|
||||
回到可提交状态;结果不明确只能形成 `UNKNOWN` 并调和同一 submission,不能再次调用 port、重新
|
||||
申请许可、释放围栏、重新授权或重新领取。
|
||||
- 本任务不实现真实页面结果判据。fake fixture/port 的 `SUBMITTED` 只用于协议分支测试,不能成为
|
||||
生产页面事实;不得从 cmroubao/cmpdd、旧版本、页面语义或人工经验推断真实 `SUBMITTED`。
|
||||
- T-401 前 production composition/import/call graph 必须同时不可达本任务编排/`SubmitOrderPort`,
|
||||
不存在生产 `ReadyForSubmission` 构造入口,并证明 T-305 终止结果到提交编排无数据流。应用启动、
|
||||
Esc、停止轮询、查看历史和关闭窗口均保持零提交调用。
|
||||
- T-401 才能领取一条全新已授权真实任务,在新的同一趟 attempt 中重新执行全部实时闸门并即时构造
|
||||
生产 `ReadyForSubmission`。本任务不提供人工提交入口,不编写支付、免密支付、先用后付或扣款能力。
|
||||
- `needs_human_review: true`:自动验证后仍保持 `DOING`,等待人审 T-305 零运行时复用、生产 factory
|
||||
不存在、一次性 fake port 调用和全部崩溃点;未经明确确认不得标 `DONE`。
|
||||
@@ -0,0 +1,104 @@
|
||||
---
|
||||
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-04T15:06:03Z sha256=4ec2adedf5a6ab06ece40e32e6619992fbf8cc071a95977a80a796b6b1cd9d98 -->
|
||||
## 问题 / 背景
|
||||
|
||||
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。
|
||||
|
||||
## 执行记录
|
||||
|
||||
(暂无)
|
||||
<!-- END VIKUNJA EXPORT -->
|
||||
|
||||
## 边界
|
||||
|
||||
- 本任务只把 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`。
|
||||
@@ -0,0 +1,101 @@
|
||||
---
|
||||
id: T-402
|
||||
title: 待付款人工收口与付款事实记录
|
||||
phase: 4
|
||||
deps: [T-403]
|
||||
status: TODO
|
||||
created: 2026-08-04
|
||||
vikunja_task_id: 51
|
||||
context_ref: 8600c33
|
||||
work_branch: task/t-402-payment-closure
|
||||
needs_device: false
|
||||
needs_human_review: true
|
||||
write_paths:
|
||||
- docs/tasks/T-402.md
|
||||
- admin/migrations/00009_payment_closure.sql
|
||||
- admin/internal/migrations/migrations_test.go
|
||||
- admin/internal/domain/payment_closure.go
|
||||
- admin/internal/domain/payment_closure_test.go
|
||||
- admin/internal/paymentclosure/**
|
||||
- admin/internal/taskdetail/**
|
||||
- admin/internal/server/mark_paid.go
|
||||
- admin/internal/server/mark_paid_test.go
|
||||
- admin/internal/server/router.go
|
||||
- admin/internal/server/task_detail.go
|
||||
- admin/internal/server/task_detail_test.go
|
||||
- admin/internal/transport/webui/webui.go
|
||||
- admin/internal/transport/webui/templates/task-detail.html
|
||||
- admin/cmd/server/**
|
||||
- admin/README.md
|
||||
- docs/api.md
|
||||
- docs/04-architecture.md
|
||||
- docs/routes.md
|
||||
- docs/08-interaction-checklist.md
|
||||
- docs/current-state.md
|
||||
---
|
||||
|
||||
<!-- BEGIN VIKUNJA EXPORT id=51 synced=2026-08-04T15:03:09Z sha256=c9d2806cefd7ce0cbbb96bd1b764eb54ff713cfb25715daa3581933c2f74ec4c -->
|
||||
## 背景
|
||||
|
||||
T-208 已冻结创建待付款订单后的 `WAITING_PAYMENT` 事实:仅当提交记录为 `SUBMITTED`,或管理员调和结论为 `CONFIRMED_CREATED` 时,系统才知道订单已创建。T-403 负责展示这些既有事实。本任务只记录管理员已经在拼多多人工完成真实付款这一外部事实,并把任务收口为成功;系统本身没有付款,也不得验证或自动执行付款。
|
||||
|
||||
## 关联
|
||||
|
||||
- Feature:F011
|
||||
- Story:US006
|
||||
- Integration:IX006
|
||||
- 前置任务:T-403
|
||||
- 后续消费者:T-404
|
||||
|
||||
## 实现方案
|
||||
|
||||
1. 新增唯一迁移 `00009_payment_closure.sql`,建立追加式 `payment_closures`:绑定同一 lineage 的 task、submission、attempt、authorization,以及管理员 actor、服务端 UTC 记录时间、幂等键与规范化请求摘要。唯一约束保证同一任务/提交只能收口一次,并保证同一管理员幂等键不可复用为不同请求;外键/约束必须阻止跨 lineage 事实。不得保存付款方式、账户、卡号、订单凭据、地址、手机号或截图/XML。migration down 只允许在 `payment_closures` 为空时执行;存在任意事实必须在删除表或约束前原子拒绝,禁止丢失付款审计事实。
|
||||
2. 在任务详情的 `WAITING_PAYMENT` 区域明确显示“订单已创建,系统尚未付款”,同时展示商品、规格、数量、金额上限,以及 T-208/T-403 已有提交、调和和三道闸门证据。不得暗示系统已付款。
|
||||
3. 管理员必须先在拼多多外部人工完成真实付款,再完成三个且仅三个确认组:`goods_spec_quantity_confirmed` 表示商品/规格/数量已核对,`amount_within_cap_confirmed` 表示订单金额未超过授权上限,`externally_paid_confirmed` 表示管理员已在拼多多人工完成真实付款。三项 wire 值必须全部严格为 `true`;任一缺失、为 `false` 或无法严格解析均返回 400 且零写入。按钮文案明确为“记录人工付款并标记完成(不执行付款)”。
|
||||
4. `POST /tasks/{id}/mark-paid` 仅接受管理员会话与 CSRF,通过严格表单读取 UUIDv4 幂等键、expected task version、当前 submission id 和上述三个固定布尔确认组,不接受别名或额外确认字段。actor 只能来自会话,时间只能来自服务端 UTC。
|
||||
5. 在单一事务和写锁内重新读取 task、submission、attempt、authorization:四者必须属于同一 lineage;任务必须正好是 `WAITING_PAYMENT`,submission 必须正好是该任务当前唯一提交且关联同一 attempt/authorization,authorization 必须正好是 `CONSUMED`。submission 必须为 `SUBMITTED`,或为已有 T-208 `CONFIRMED_CREATED` 最终调和事实的 `MANUAL_RESOLVED`。旧 task version、错误/过期 submission 固定返回 409 且零写入;任一 lineage、authorization、submission 或 task 状态冲突也必须返回 409、零写入,并让详情进入只读安全核查,绝不能推进为 `SUCCEEDED`。
|
||||
6. 所有检查通过后,同一事务追加 payment closure,并将任务从 `WAITING_PAYMENT` 单向推进到 `SUCCEEDED`、version + 1。submission、attempt、authorization 和已消费的提交围栏永久不可变,不得重开、释放、重置、重新授权或重新提交。
|
||||
7. 幂等性必须先查事实:同 key、同规范化 payload 在响应丢失和进程重启后稳定重放同一结果;同 key、不同 payload 返回 409;不同 key 在任务已收口后返回 `payment_already_recorded` 409。规范化 payload 必须包含 task、submission、expected version 和三个固定确认组。不得仅因任务已是 `SUCCEEDED` 就伪造成功响应。
|
||||
8. 成功页/详情页显示记录 actor、服务端时间和“仅记录人工付款事实,系统未执行付款”。失败保留用户输入并给出可操作提示,焦点回到错误摘要;事实冲突时只显示安全核查,不提供重试提交、释放或重新授权动作。
|
||||
9. 自动化测试只使用本地数据库夹具构造 `WAITING_PAYMENT` 和既有提交事实,覆盖事务、冲突、幂等、重启与 UI;不得连接拼多多、请求真实资金、模拟付款控件或要求测试人员实际付款。`needs_human_review` 只验收语义、权限和交互,不代表测试中发生真实付款。
|
||||
|
||||
## 验收
|
||||
|
||||
- 三个且仅三个 wire 确认组固定为 `goods_spec_quantity_confirmed`、`amount_within_cap_confirmed`、`externally_paid_confirmed`;三项全部严格为 `true` 才能继续,逐项覆盖缺失、`false`、非法值和额外别名,均返回 400 且零写入。
|
||||
- 只有管理员、有效 CSRF、精确 task version、精确当前 submission、同 lineage 的 task/submission/attempt/authorization 和 `CONSUMED` authorization 能写入;旧版本和错误/过期 submission 稳定返回 409 且零写入。
|
||||
- 覆盖 `SUBMITTED` 与 `CONFIRMED_CREATED` 两条允许路径,以及跨 task/attempt/authorization、authorization 非 `CONSUMED`、其它任务/提交状态和事实冲突;冲突均返回 409、零写入、进入只读安全核查且绝不 `SUCCEEDED`。
|
||||
- 覆盖并发双击、同键同载荷重放、同键异载荷冲突、不同键重复收口和进程重启;事实表和任务状态在同一事务提交或回滚。
|
||||
- migration 覆盖 up、重开、外键/唯一/lineage/append-only 约束、空表 down 成功、存在任意 payment closure 时 down 在删表前原子拒绝,以及 `foreign_key_check`。
|
||||
- 页面显著显示“系统尚未付款”和“不执行付款”,键盘操作、焦点、错误摘要、安全核查态及移动宽度可用。
|
||||
- 自动测试不需要真实付款,不访问手机或拼多多;代码不得包含任何支付、免密、先用后付或扣款控件操作。
|
||||
- 运行 `go test ./...`、`go test -race ./...`、`go vet ./...`、`go build ./...`、前端交互检查、根目录初始化门禁、上下文校验、导出校验和 `git diff --check`。
|
||||
|
||||
## 执行记录
|
||||
|
||||
(暂无)
|
||||
<!-- END VIKUNJA EXPORT -->
|
||||
|
||||
## 边界
|
||||
|
||||
- `mark-paid` 只记录管理员已经在拼多多外部人工完成真实付款的事实;系统没有执行付款,也不得发起、
|
||||
验证、模拟或自动化支付,不得读取或保存付款方式、账户、卡号、订单凭据、地址或手机号。
|
||||
- 三个且仅三个确认组固定为 `goods_spec_quantity_confirmed`、`amount_within_cap_confirmed`、
|
||||
`externally_paid_confirmed`;三项 wire 值必须全部严格为 `true`。任一缺失、为 `false`、非法值或
|
||||
别名返回 400 且零写入;旧 task version 与错误/过期 submission 固定返回 409。
|
||||
- 只允许精确处于 `WAITING_PAYMENT` 的任务和精确当前 submission 收口。事务必须确认 task、
|
||||
submission、attempt、authorization 属于同一 lineage,authorization 正好为 `CONSUMED`;
|
||||
submission 必须是 `SUBMITTED`,或已有 T-208 `CONFIRMED_CREATED` 最终调和事实。任一归属、
|
||||
状态或事实冲突都返回 409、零写入并进入只读安全核查,绝不能推进为 `SUCCEEDED`。
|
||||
- actor 只能取自已认证管理员会话,记录时间只能取服务端 UTC。幂等事实必须在任何状态短路前检查:
|
||||
同 key 同规范化载荷稳定重放,同 key 异载荷返回 409;不同 key 重复收口返回
|
||||
`payment_already_recorded` 409,不得仅因任务已是 `SUCCEEDED` 就伪造成功响应。
|
||||
- payment closure 事实与 task `WAITING_PAYMENT → SUCCEEDED`、version + 1 必须在同一事务内原子
|
||||
提交或回滚。submission、authorization 和已消费围栏永久不可变,不得重开、释放、重置、重新授权、
|
||||
重新领取或重新提交。
|
||||
- 本任务唯一新增 migration 是 `00009_payment_closure.sql`;事实表只保存同一 lineage 的 task、
|
||||
submission、attempt、authorization、actor、服务端时间、幂等键和请求摘要,不保存截图、XML、
|
||||
支付凭据或新的 evidence kind。`payment_closures` 为空时才允许 migration down;存在任意事实时
|
||||
必须在删表或约束前原子拒绝,禁止丢失付款审计事实。
|
||||
- 自动化测试只使用本地数据库夹具,不访问手机或拼多多,不请求真实资金,也不要求测试人员真实付款。
|
||||
`needs_human_review` 只验收管理 UI 的未付款语义、权限、确认和无障碍交互。
|
||||
- 本任务不修改 `client/` 或拼多多页面判据,不点击支付、免密支付、先用后付或任何扣款控件。
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
id: T-403
|
||||
title: 失败分类、证据归档与管理员调和视图
|
||||
phase: 4
|
||||
deps: [T-208]
|
||||
status: TODO
|
||||
created: 2026-08-04
|
||||
vikunja_task_id: 48
|
||||
context_ref: 8600c33
|
||||
work_branch: task/t-403-failure-reconciliation-view
|
||||
needs_device: false
|
||||
needs_human_review: true
|
||||
write_paths:
|
||||
- docs/tasks/T-403.md
|
||||
- admin/internal/taskdetail/**
|
||||
- admin/internal/server/task_detail.go
|
||||
- admin/internal/server/task_detail_test.go
|
||||
- admin/internal/server/task_failure_view_test.go
|
||||
- admin/internal/transport/webui/webui.go
|
||||
- admin/internal/transport/webui/templates/task-detail.html
|
||||
- admin/README.md
|
||||
- docs/routes.md
|
||||
- docs/08-interaction-checklist.md
|
||||
- docs/current-state.md
|
||||
---
|
||||
|
||||
<!-- BEGIN VIKUNJA EXPORT id=48 synced=2026-08-04T14:51:01Z sha256=f3ddd60f4b212c01b488f92a91148bfcb299c20cc8f8084f198971c18b3a4b49 -->
|
||||
## 问题 / 背景
|
||||
|
||||
T-208 将冻结三闸门、submission fence、一次性 result 和管理员调和事务,T-206 提供状态详情底座。采购管理员仍需要在同一任务详情中看懂围栏前固定失败、围栏后结果不明、已有证据和人工调和历史,并只调用 T-208 已有的同一 submission 调和接口。T-403 只完成失败分类/证据归档事实的展示和调和 UI,不新增失败码、数据库事实或第二套调和事务。
|
||||
|
||||
## 关联需求与交互
|
||||
|
||||
- 功能:F-007、F-011、F-017 的管理展示与人工调和入口。
|
||||
- 用户故事:US-002、US-004、US-008。
|
||||
- 交互:IX-004、IX-009、IX-011。
|
||||
- 依赖:T-208;由其传递 T-205 固定事件/失败码、T-210 三类证据、T-206 状态详情和 T-207 恢复边界。
|
||||
- API:只消费 T-208 既有 POST /order-submissions/{sid}/reconcile;不新增或重复实现 reconcile store/事务。
|
||||
- 后续消费者:T-402 待付款人工收口、T-404 MVP 验收。
|
||||
|
||||
## 方案
|
||||
|
||||
1. 扩展任务详情只读模型,按同一 task/authorization/attempt/submission 展示 T-205 已保存的固定 failure code、失败阶段、最后安全步骤、事件时间线、执行摘要及 Gate1/Gate2/Gate3 内部证据;不复制、删除、重命名或重新归类原始事实。
|
||||
2. failure code 只使用 T-205/T-208 已有版本化 allowlist。UI 可为现有码提供固定中文解释和安全下一步,但必须同时显示原始 code;未知 code 显示“未知失败码/停止处理”,不得猜测、合并、改写或映射成另一个码。
|
||||
3. 围栏前 NEEDS_MANUAL 只展示失败原因、证据和 T-207 已计算的安全恢复资格;T-403 不实现新的重置/取消事务,也不让查看证据触发恢复。
|
||||
4. 围栏后以 order_submission 为唯一主线,显示 submission id、三闸门 proof、首次许可事实、result observation、append-only reconciliation records 和当前结论。task.status 与 submission 冲突时以 submission 围栏事实优先并进入安全核查。
|
||||
5. RECONCILIATION_REQUIRED 页面只渲染 T-208 已冻结的 CONFIRMED_CREATED、CONFIRMED_NOT_CREATED_OR_CANNOT_COMPLETE、STILL_UNKNOWN 三种结论,并把管理员 session、CSRF、submission id、expected task version 和幂等键提交到既有 reconcile handler。
|
||||
6. T-403 不解析或重放 T-208 事务结果,不在 UI 层直接改 task/authorization/attempt/submission。响应不明时冻结原幂等键和原表单,只允许重放既有 reconcile 请求;不生成新结论或乐观更新终态。
|
||||
7. 围栏后任何状态都持续显示“可能已创建订单,只能调和同一提交,禁止再次提交”,并彻底隐藏重试下单、重置、取消、释放、重新授权、重新领取和设备继续动作。
|
||||
8. 内部 evidence 继续通过受保护 no-store 端点延迟加载;只展示已批准的 Gate1/Gate2/Gate3 PNG。没有 SUBMISSION_RESULT kind,不展示或上传外部支付页、支付凭据、完整 XML、路径或页面全文。
|
||||
9. 完整页与抽屉共享同一模板/事实;调和表单具备可见 label、错误关联、焦点恢复、44px 目标、aria-live、响应不明提示和 reduced-motion。只读终态不渲染表单。
|
||||
|
||||
## 验收要点
|
||||
|
||||
- 覆盖每个既有固定 failure code、未知 code、最后安全步骤、三类 evidence、空证据和关联冲突;测试只断言显示,不改写原始码。
|
||||
- 覆盖 NEEDS_MANUAL、RECONCILIATION_REQUIRED、WAITING_PAYMENT、FAILED 及 submission/task 状态冲突;任何 submission 存在时均无围栏前恢复或再次提交入口。
|
||||
- 三种调和结论只调用注入的 T-208 既有 handler/store 一次;T-403 没有第二套 SQL、migration、状态机或直接数据库写入。
|
||||
- 同幂等键响应不明重放保持原载荷;异载荷、旧版本、错 submission 的错误按 T-208 原结果展示,不乐观改变页面状态。
|
||||
- 完整页/抽屉、键盘、焦点、加载/失败/空态、权限、CSRF、HTML escaping、no-store evidence 和移动宽度通过测试与人工 UI 评审。
|
||||
- 静态检查确认没有新 failure/reason 常量、migration、reconcile transaction、client/PDD、提交点击、付款或扣款能力。
|
||||
- `go test ./...`、`go test -race ./...`、`go vet ./...`、`go build ./...`、相关前端静态测试、完整 init、上下文、Vikunja export 与 diff-check 通过。
|
||||
|
||||
## 执行记录
|
||||
|
||||
(暂无)
|
||||
<!-- END VIKUNJA EXPORT -->
|
||||
|
||||
## 边界
|
||||
|
||||
- 本任务只展示 T-205/T-208 已有失败、事件、三闸门 evidence、submission 与 reconciliation 事实,
|
||||
并把管理员表单提交到 T-208 既有 reconcile handler/store;不得新增或改写 failure/reason code、
|
||||
migration、状态机、调和事务或直接数据库写入。
|
||||
- 原始 failure code 必须始终可见;固定中文解释只能附加在已有 allowlist 上。未知 code 必须安全失败并
|
||||
显示“未知失败码/停止处理”,不得猜测、合并或映射为另一个 code。
|
||||
- 任一 submission 的存在都优先于 task.status。围栏后不得显示或提供重试下单、重置、取消、释放、
|
||||
重新授权、重新领取、再次提交或设备继续动作;只能查看和调和同一 submission。
|
||||
- evidence 只读取 T-210 已批准的 Gate1/Gate2/Gate3 内部 PNG,不上传、删除、重命名或重新归类资产,
|
||||
不新增结果截图 kind,不展示外部支付页、支付凭据、完整 XML、文件路径或页面全文。
|
||||
- 调和结论只能是 T-208 已冻结的 `CONFIRMED_CREATED`、
|
||||
`CONFIRMED_NOT_CREATED_OR_CANNOT_COMPLETE`、`STILL_UNKNOWN`。响应不明时只允许用原幂等键和
|
||||
原载荷重放既有请求,不得生成新结论或乐观更新终态。
|
||||
- 本任务不修改 `client/` 或拼多多页面判据,不连接真机,不点击“提交订单”,不编写支付、免密支付、
|
||||
先用后付或任何扣款能力。
|
||||
@@ -0,0 +1,88 @@
|
||||
---
|
||||
id: T-404
|
||||
title: 完整 MVP 只读验收
|
||||
phase: 4
|
||||
deps: [T-401, T-402, T-403, T-405]
|
||||
status: TODO
|
||||
created: 2026-08-04
|
||||
vikunja_task_id: 54
|
||||
context_ref: 8600c33
|
||||
work_branch: task/t-404-mvp-acceptance
|
||||
needs_device: true
|
||||
needs_human_review: true
|
||||
write_paths:
|
||||
- docs/tasks/T-404.md
|
||||
---
|
||||
|
||||
<!-- BEGIN VIKUNJA EXPORT id=54 synced=2026-08-04T15:16:26Z sha256=3d2e1900e156174e8389af5ef372af9f94be7f719c39432eaf2ea42f4a38d311 -->
|
||||
## 问题 / 背景
|
||||
|
||||
T-401 提供唯一一次真实提交与人工调和证据,T-402/T-403 提供待付款人工收口、失败归档和同一 submission 调和,T-405 提供可核验 Windows 交付包。T-404 是 MVP 的最终只读验收任务:对同一候选 commit、服务端、客户端、真机记录和实际 ZIP 做完整 P0 复核,不承载任何修复。发现缺陷必须退回对应任务修正并重新形成候选版本,不能在验收任务中顺手改代码、契约、安全边界或共享文档。
|
||||
|
||||
## 关联需求与交互
|
||||
|
||||
- 功能:全部 MVP P0,重点 F-001、F-004、F-005、F-006、F-007、F-008、F-010、F-011、F-013、F-017、F-018。
|
||||
- 用户故事:US-001~US-008、US-010。
|
||||
- 交互:IX-001~IX-012 中适用于 MVP 的全部条目。
|
||||
- 依赖:T-401、T-402、T-403、T-405。
|
||||
- 本任务 needs_device=true 且 needs_human_review=true;agent 只能整理和运行可逆的只读/测试检查,最终结论和 DONE 只能由人确认。
|
||||
|
||||
## 方案
|
||||
|
||||
1. 冻结候选 git commit、admin/client 版本、数据库 migration 版本、T-405 ZIP 路径/SHA-256/完整依赖 manifest 和测试环境。验证期间源码、依赖集合或产物 hash 变化即作废本轮结论,回原任务修复后从头验收。
|
||||
2. 建立 P0 trace matrix,把每个功能、用户故事和交互映射到自动化测试、人工 UI 检查、T-101~T-107/T-305 真机证据或 T-401 首次真实提交记录。缺项不能用“代码已完成”代替。
|
||||
3. 采购服务检查登录/CSRF、DRAFT 创建与倒序列表、筛选/批量选择、开始采购一次性授权、设备身份隔离、claim/lease、events/evidence、三闸门围栏、UNKNOWN result、同一 submission 调和、WAITING_PAYMENT 和人工付款事实记录。围栏后任何页面均无重试/释放/重新授权。
|
||||
4. 采购工具检查固定双 Tab、配置/DPAPI/单实例、轮询停止边界、当前任务/日志/历史详情、同一趟规格/数量/三闸门、严格 HTTP/localstate、一次性 permit/点击意图和 T-400 编排。静态调用图必须只有 T-401 一个低层提交点击点且无付款能力。
|
||||
5. 复核 T-401 人工记录:项目所有者一次性批准、设备/Android/连接方式/拼多多版本/goods_id、task/authorization/attempt/submission、三闸门、首次 fence permit、点击意图先落盘、低层点击恰好一次、无重试、无点击后截图/XML、UNKNOWN/RECONCILIATION_REQUIRED、T-403 结论、订单处置和未付款。
|
||||
6. T-404 不再创建第二笔真实订单、不再次点击“提交订单”。真机部分只复核既有 T-401 原始记录。T-405 包的无设备验收只允许启动/关闭、静态配置检查,以及向精确 loopback 采购服务调用已经由服务端实现并证明无业务副作用的 GET /healthz;该请求不得携带设备 Bearer、管理 session 或 CSRF,也不得读取/修改任务、授权、attempt、evidence 或 submission。
|
||||
7. 严禁把 claim-next、lease renew、evidence、events、attempt fail、submission fence、submission result、管理员任务动作或任何其它业务 API 当作“连接健康检查”。即使使用测试 token、空任务或声称只看响应,也不得从 T-405 包调用这些端点探测,因为它们可能创建幂等事实、领取任务或推进状态。
|
||||
8. 无设备包验收不得运行 adb.exe、adb devices、uiautomator2、设备连接检查、serial 探测或任何 Android/PDD 命令。ADB 路径/serial 保持未配置,进程/日志必须证明零 ADB、零 claim、零真机动作;需要设备的事实只复核 T-401 已有人工记录。
|
||||
9. 复核 T-402 时自动化只用本地 fixture;没有人在真实订单上实际付款时,不得为了验收把生产任务标为 SUCCEEDED。WAITING_PAYMENT 是正常未付款状态,不等于失败,也不等于采购完成。
|
||||
10. 用 T-405 实际 ZIP 在脱离源码、无 Python 的 Windows 环境验证 SHA-256、commit、完整直接依赖版本、解压、启动、配置、运行数据目录、升级/卸载说明和无设备安全失败;确认包内没有 token、env、本地状态、日志、证据、tests、XML 或仓库元数据。
|
||||
11. 运行完整双端门禁:Go test/race/vet/build、client unittest/compileall/wheel metadata、打包专用校验、根 init、agent-context、Vikunja export check、git diff check。业务 API 只由隔离数据库/fixture 的自动测试覆盖,不通过实际打包客户端做“探测”;测试不连接支付或外部资金路径。
|
||||
12. 验收执行记录只写测试命令、退出码、P0 matrix 结论、证据路径/hash 和人工确认,不复制 token、地址/手机号、支付凭据、完整 XML 或原始截图。任何失败均记录 owning task 和复现命令,T-404 保持 DOING/TODO,等待原任务修复。
|
||||
|
||||
## 验收要点
|
||||
|
||||
- 所有依赖均按 git frontmatter 为 DONE;T-401/T-405 的人工记录、真实 ZIP、完整依赖 manifest 与候选 commit/hash 完整一致。
|
||||
- P0 功能/故事/交互全部有自动化或明确人工证据;不存在 WAITING_CONFIRMATION、第二趟授权、AI/V2 能力或未取证页面判据混入 MVP。
|
||||
- 三道价格闸门、提交四条件、首次许可、点击意图先落盘、底层点击恰好一次、异常后零重试和围栏后只调和均有测试与 T-401 人工证据。
|
||||
- 静态检查证明支付、免密支付、先用后付、扣款控件、人工提交按钮、通用远程 selector/坐标和第二提交调用点不存在。
|
||||
- 采购服务 375/768/1024/1440 px 与采购工具 compact/medium/wide、键盘、焦点、错误/空态/离线/结果不明、深浅色/高对比人工验收通过。
|
||||
- T-405 ZIP 在运营 Windows 环境按文档运行,SHA-256/commit/依赖版本匹配,包内容和运行目录安全。无设备验收最多调用 GET /healthz,服务端任务/授权/attempt/evidence/submission 事实前后不变;没有业务 API 请求、ADB 进程或设备连接。
|
||||
- 完整门禁全部 exit 0,仓库无本任务造成的代码/共享文档改动、无秘密/真机证据进入 Git。若有缺陷,必须回对应任务修复并重新跑全套。
|
||||
- 最终 DONE 只能由项目所有者在人审 P0 matrix、T-401 真机记录、T-405 产物和无付款证明后明确给出;agent 不得自行 DONE。
|
||||
|
||||
## 执行记录
|
||||
|
||||
(暂无)
|
||||
<!-- END VIKUNJA EXPORT -->
|
||||
|
||||
## 边界
|
||||
|
||||
- 本任务是最终只读验收,不实现或修复任何生产代码、测试、迁移、契约、页面判据、UI、构建脚本
|
||||
或共享文档;唯一允许写入的仓库文件是本任务执行记录/status。发现缺陷必须退回 owning task 修复,
|
||||
重新冻结候选 commit/产物并从头验收,不能在 T-404 顺手修改。
|
||||
- 验收只针对一个精确候选 git commit、数据库 migration 集、admin/client 版本和 T-405 ZIP SHA-256。
|
||||
源码、依赖、任务定义或产物 hash 任一变化都使本轮结论失效,不能拼接不同版本的测试证据。
|
||||
- T-404 不再创建第二笔真实订单、不再次点击“提交订单”。真机提交证据只复核 T-401 已由项目
|
||||
所有者批准的唯一真实运行;T-405 包验收不得重新执行围栏前 dry-run 或任何设备流程。
|
||||
- T-405 包的无设备验收只允许启动/关闭、静态配置检查,以及向精确 loopback 采购服务调用已经由
|
||||
服务端实现并证明无业务副作用的 `GET /healthz`。该请求不得携带设备 Bearer、管理员 session 或
|
||||
CSRF,且服务端 task/authorization/attempt/evidence/submission 事实前后必须完全不变。
|
||||
- 严禁使用 `claim-next`、lease renew、evidence、events、attempt fail、submission fence、submission
|
||||
result、管理员任务动作或任何其它业务 API 做“连接健康检查”;测试 token、空任务或只看响应都不
|
||||
构成例外,因为这些接口可能创建幂等事实、领取任务或推进状态。
|
||||
- 无设备包验收不得运行 `adb.exe`、`adb devices`、uiautomator2、serial/设备连接检查或任何
|
||||
Android/PDD 命令。ADB 路径和 serial 保持未配置,并以进程/日志证明零 ADB、零 claim、零真机动作;
|
||||
needs_device 事实只复核 T-401 已有人工记录。
|
||||
- 不得为了测试 T-402 而要求或模拟真实付款;自动化只用隔离 fixture。没有人实际付款时不得把生产
|
||||
任务标为 `SUCCEEDED`,`WAITING_PAYMENT` 是正常未付款状态,不等于失败或采购完成。
|
||||
- P0 验收必须逐项关联功能、用户故事、交互与自动/人工证据。缺项、失败、版本漂移、未知页面判据、
|
||||
真机记录不全、ZIP/hash 不一致或付款边界无法证明时均不得通过,也不能用“代码已完成”替代证据。
|
||||
- 完整门禁和静态调用链必须证明三道价格闸门、提交四条件、首次 permit、点击意图先落盘、低层点击
|
||||
恰好一次、异常后零重试、围栏后只调和,以及支付/免密/先用后付/扣款能力不存在。
|
||||
- 执行记录不得复制 token、地址/手机号、支付凭据、完整 XML、原始截图或本机秘密;只记录命令、
|
||||
退出码、非敏感证据路径/hash、P0 结论和人工确认。真实证据仍留受控本地/服务端位置。
|
||||
- `needs_device: true` 与 `needs_human_review: true`:最终 `DONE` 只能由项目所有者在人审 P0 matrix、
|
||||
T-401 真机记录、T-405 产物和无付款证明后明确给出;agent 不得自行确认或标 `DONE`。
|
||||
@@ -0,0 +1,99 @@
|
||||
---
|
||||
id: T-405
|
||||
title: 采购工具 Windows 打包与运行文档
|
||||
phase: 4
|
||||
deps: [T-401]
|
||||
status: TODO
|
||||
created: 2026-08-04
|
||||
vikunja_task_id: 53
|
||||
context_ref: 8600c33
|
||||
work_branch: task/t-405-windows-package
|
||||
needs_device: false
|
||||
needs_human_review: true
|
||||
write_paths:
|
||||
- docs/tasks/T-405.md
|
||||
- client/pyproject.toml
|
||||
- client/requirements-build.txt
|
||||
- client/cmbuyer-client.spec
|
||||
- client/scripts/build_windows.ps1
|
||||
- client/scripts/verify_windows_bundle.py
|
||||
- client/tests/test_windows_packaging.py
|
||||
- client/README.md
|
||||
- docs/03-tech-stack.md
|
||||
- .gitignore
|
||||
---
|
||||
|
||||
<!-- BEGIN VIKUNJA EXPORT id=53 synced=2026-08-04T15:16:24Z sha256=31032aac3c37c9992ba7ce04a5bb3cac406b2e8cef54106eeb9213d2c7b75e91 -->
|
||||
## 问题 / 背景
|
||||
|
||||
T-401 完成生产接线和首次真实提交人工验收后,采购工具仍需转换为运营电脑可解压运行、可追溯到准确源码、构建环境实际依赖和可检查内容的 Windows 交付包。T-405 使用 PyInstaller 生成 onedir 目录并封装 ZIP,提供构建、运行时依赖清单、校验、运行、升级与卸载文档;打包和验收不连接 Android 设备,不执行采购、提交或付款。
|
||||
|
||||
## 关联需求与交互
|
||||
|
||||
- 功能:F-005、F-013 的 Windows 交付运行部分。
|
||||
- 用户故事:US-003、US-007、US-008。
|
||||
- 交互:IX-007、IX-008;保持“采购工具”名称、固定双 Tab 和安全退出语义。
|
||||
- 依赖:T-401;只打包已经完成人工安全验收的生产 composition。
|
||||
- 后续消费者:T-404 完整 MVP 验收。
|
||||
- needs_device=false;构建、内容检查和无设备启动测试不得连接 ADB 或拼多多。
|
||||
|
||||
## 方案
|
||||
|
||||
1. 新增独立 build requirements,固定兼容的 PyInstaller 版本;运行时依赖继续只由 requirements.txt / wheel metadata 管理,不把 PyInstaller 作为运营时依赖或在应用启动时下载组件。
|
||||
2. 维护显式 PyInstaller spec,生成 windowed onedir 包。入口唯一为 cmbuyer_client.app:main,只收集运行必需的 PySide6/uiautomator2/adbutils/Pillow 模块、Qt/Shiboken 运行库和已知资源;不使用任意目录收集、隐藏执行脚本或下载器。
|
||||
3. PowerShell 构建脚本从仓库根解析并校验精确 client 目录、Python 3.11+ venv、干净的显式输出目录和当前 commit;只清理已验证位于 client 构建输出下的目录,不对仓库根、用户目录、LOCALAPPDATA 或未解析变量执行递归删除。
|
||||
4. 构建前从已安装 wheel metadata/requirements 解析全部直接运行时依赖的规范名称和实际版本,不能只读取未锁定的需求表达式。至少显式探测 PySide6、Qt runtime、Shiboken6、uiautomator2、adbutils、Pillow;Qt 版本必须来自实际 Qt runtime,其他版本来自当前构建环境中实际解析的 distribution/runtime,而不是手写常量。
|
||||
5. 构建产物为版本化 onedir 目录和其 ZIP;生成不含秘密的 manifest,记录产品/版本、git commit、Python/PyInstaller 版本、构建 UTC、入口、ZIP SHA-256,以及上述全部直接运行时依赖和 Qt/Shiboken 组件的规范名称、实际版本与探测来源。未锁依赖因此仍可追溯,但不得声称字节级可复现。
|
||||
6. PyInstaller spec 必须保留校验所需的 distribution metadata/Qt runtime 事实。校验器分别从构建环境和实际 onedir/ZIP 内解析依赖集合与版本,要求和 manifest 精确一致;缺依赖、漏记直接依赖、版本不一致、无法探测或只相信 manifest 自报都必须失败,不发布 ZIP。
|
||||
7. bundle 内容校验显式拒绝 vikunja.env、任何 .env/token、client-state.sqlite3/WAL/SHM、LOCALAPPDATA 状态、日志、artifacts、截图、XML、业务 evidence manifest、tests/fixture、__pycache__、源码仓库元数据和支付凭据。交付依赖 manifest 是允许的专用构建元数据,不能混入业务证据。
|
||||
8. 校验器检查 ZIP 防路径穿越、文件清单、入口 EXE、关键依赖、重复/绝对路径、最大体积边界、SHA-256 和依赖版本;不得仅以 PyInstaller 退出码 0、requirements 约束或版本文件存在声称可交付。
|
||||
9. 运行文档固定“解压整个目录后运行”,说明采购服务精确 loopback、ADB 路径/serial 人工配置、设备 token 安全录入、运行数据位于 %LOCALAPPDATA%/cmbuyer、日志/状态位置和常见错误。不得要求复制 vikunja.env、源码、Python 或开发 venv。
|
||||
10. 升级只替换应用目录,先退出应用并保留 %LOCALAPPDATA%/cmbuyer;卸载只删除明确的应用解压目录,不自动删除状态、日志或证据。需要清理本地数据时必须另行人工确认精确路径。
|
||||
11. 在脱离源码目录、未安装 Python 的 Windows 测试环境解压并启动,检查产品名、双 Tab、配置/错误提示和安全关闭;测试使用空闲/无设备配置,零 claim、零 ADB、零真机动作、零提交。
|
||||
12. 不在 MVP 内实现安装器、自动更新、代码签名服务或后台常驻。若产物未签名,文档如实说明 Windows 提示与人工核验 SHA-256、commit 和依赖版本 manifest 的步骤,不能诱导绕过安全软件。
|
||||
|
||||
## 验收要点
|
||||
|
||||
- 构建脚本在合规 Windows venv 生成唯一 onedir ZIP 和 manifest;manifest 枚举 wheel metadata/requirements 中全部直接运行时依赖的实际版本,并至少包含 PySide6、Qt、Shiboken6、uiautomator2、adbutils、Pillow、Python、PyInstaller 与 git commit。
|
||||
- 构建环境探测结果、实际 onedir/ZIP 内 distribution metadata/Qt runtime 和 manifest 三方逐项一致;漏项、未知项、版本漂移、无法从 bundle 复核或伪造 manifest 均使校验失败。
|
||||
- 重复构建记录各自 commit、完整实际依赖版本集合和产物 SHA-256;依赖未锁时仍能追溯本次解析结果,但不声称字节级可复现。
|
||||
- 内容负例向 staging 注入 env/token、SQLite/WAL、日志、PNG/XML、tests/fixture、绝对/穿越路径时校验均失败且不发布 ZIP。
|
||||
- ZIP 解压后目录外无写入;应用所有状态仍进入 %LOCALAPPDATA%/cmbuyer,不污染安装目录或源码树。
|
||||
- 在无源码、无 Python 的 Windows 环境启动成功;产品名/双 Tab/配置错误/关闭路径可用,且无设备时零 claim、零 ADB、零提交、零付款。
|
||||
- 文档覆盖构建、SHA-256/commit/依赖版本核验、解压运行、配置、升级、卸载、日志和故障排查;明确系统只创建待付款订单且不付款。
|
||||
- 运行 client unittest、compileall、wheel metadata、打包专用测试、完整 init、上下文、Vikunja export 与 diff-check;记录产物绝对路径与 SHA-256,但不把 ZIP、manifest 中的本机秘密或构建目录提交 Git。
|
||||
- needs_human_review:运营电脑人工检查解压、启动、文档、Windows 安全提示、SHA-256 和依赖版本 manifest;确认前保持 DOING。
|
||||
|
||||
## 执行记录
|
||||
|
||||
(暂无)
|
||||
<!-- END VIKUNJA EXPORT -->
|
||||
|
||||
## 边界
|
||||
|
||||
- 只交付 PyInstaller `windowed onedir` 目录及其版本化 ZIP,不在本任务引入安装器、自动更新、后台
|
||||
常驻、下载器或代码签名服务。未签名时必须如实说明 Windows 提示和 SHA-256 人工核验步骤,
|
||||
不得指导绕过安全软件。
|
||||
- PyInstaller 只作为固定版本的构建依赖,不能进入运营时依赖或由应用启动时联网安装。运行时依赖
|
||||
仍以 `requirements.txt` / wheel metadata 为唯一声明来源,不维护第二份手写依赖清单;manifest
|
||||
必须记录本次构建环境实际解析并打入 bundle 的版本,不能只复制未锁定的版本约束。
|
||||
- bundle 和 ZIP 绝不能包含 `vikunja.env`、任何 `.env`/token、设备/claim 凭据、本地 SQLite/
|
||||
WAL/SHM、配置状态、日志、artifacts、截图、XML、证据 manifest、tests/fixture、源码仓库元数据、
|
||||
支付凭据或本机绝对路径。发现拒绝项必须失败且不发布产物。
|
||||
- 构建脚本只能清理已经解析并验证位于 `client` 构建输出目录下的精确路径;不得对仓库根、用户目录、
|
||||
`%LOCALAPPDATA%`、空变量、通配目标或未经验证的计算路径执行递归删除。
|
||||
- 交付 manifest 必须记录产品/版本、git commit、Python/PyInstaller、UTC、入口、产物 SHA-256,
|
||||
以及 wheel metadata/requirements 中**全部直接运行时依赖**的规范名称、实际解析版本和探测来源;
|
||||
至少显式包含 `PySide6`、实际 Qt runtime、`Shiboken6`、`uiautomator2`、`adbutils`、`Pillow`。
|
||||
Qt 必须从实际 runtime 探测,其余必须来自当前构建 distribution/runtime,不能使用手写常量。
|
||||
- 校验器必须分别从构建环境和实际 onedir/ZIP 内的 distribution metadata、Qt runtime/组件文件核对
|
||||
完整依赖集合与版本,并要求与 manifest 精确一致。漏项、版本漂移、无法从 bundle 复核或只信任
|
||||
manifest 自报都必须失败且不发布 ZIP;PyInstaller spec 必须保留完成该核对所需的最小 metadata。
|
||||
- manifest 不记录 token、设备 serial、用户名、业务数据或证据路径。依赖未锁时,实际版本集合用于
|
||||
追溯本次构建,但仍不得宣称字节级可复现;版本号或文件名不能替代 SHA-256/commit 证明。
|
||||
- 运行、升级和卸载不得自动删除 `%LOCALAPPDATA%/cmbuyer`。升级只替换明确的应用目录;清理状态、
|
||||
日志或证据必须另行由人确认精确路径,不能作为卸载脚本副作用。
|
||||
- 构建与验收 `needs_device: false`:不得连接 ADB、启动拼多多、领取真实任务、执行页面动作、提交
|
||||
订单或付款。无源码/无 Python 环境的启动验收使用空闲配置,保持零 claim、零真机动作。
|
||||
- 本任务不修改 T-401 提交安全逻辑,不增加支付、免密支付、先用后付或任何扣款能力。
|
||||
`needs_human_review: true`,运营电脑人工核验 ZIP、文档、启动和 SHA-256 前不得标 `DONE`。
|
||||
Reference in New Issue
Block a user