16 KiB
当前实现状态
本文是可覆盖的项目级快照,记录代码与任务的现实状态。 执行记录写进各任务文件(
docs/tasks/T-<编号>.md)的## 执行记录,不在本文重复维护。
职责边界
tasks/:任务规格、依赖、状态(frontmatter)和执行记录,一任务一文件。06-tasks.md:只读路线图,维护阶段划分、里程碑和待办池。current-state.md:当前快照,可覆盖更新。
当前快照
- 日期:2026-08-04
- 阶段:Phase 1 · T-103 规格选择/读价与 Phase 2 安全服务端任务并行
- MVP 形态:手工填链接建单 → 批量“开始采购”并签发一次性授权 → 定时领取 → 同一趟精确 选规格 / 三道价格闸门 / 提交围栏 / 点击一次 → 待付款。管理员点击“开始采购”即授权桌面端 创建待付款订单;不再有试选后确认,系统绝不自动付款。
- 技术栈:已定。采购服务(
admin/)使用 Go 1.23+ / gin / SQLite;采购工具(client/) 使用 Python 3.11+ / uiautomator2 / PySide6。 详见03-tech-stack.md - 生产代码:
admin/已有登录/会话、手工 DRAFT 建单、批量开始采购与一次性授权、任务详情、内部 原始截图、设备身份,以及已授权任务的原子领取/幂等重放/租约续期;client/已有 Python 包、PySide6 最小入口、运行目录与日志脱敏策略,以及显式 serial 的 ADB 连接边界、本地基线取证 CLI、受限商品链接打开取证 CLI、人工声明规格面板状态的只读取证 CLI, 绑定 PKG110 / Android 16 / 拼多多 8.17.0 的证据工具,以及受控规格入口、精确规格选择、SKU 当前价 读取、原始截图和一次安全退出能力;并已具备严格 localhost claim/renew/evidence HTTP、Windows DPAPI 凭据保护、SQLite append-only 恢复状态图、Global named mutex 与 durable gateway。真机能力尚待最终人工 验收,数量/确认页/提交仍未开放。 - 测试:采购服务已覆盖登录、建单、授权、详情/证据、设备身份、迁移、原子 claim/renew 与竞态; 采购工具 189 项离线单元测试(全部 mock,不连接真机)。
- 数据:受保护迁移已落到
00005_task_claims.sql。旧两趟模型已移除;开始采购会锁定任务快照并签发 一次性授权,领取会创建唯一 attempt/claim、HMAC claim token 与有界租约。仓库不含业务实例数据。 - 标准启动路径:Windows PowerShell 运行
./init.ps1,Unix shell 运行./init.sh。Windows 入口 优先使用合规的既有 venv;仅在其缺失时才从 Python Launcher 已安装版本中选择最高的 Python 3.11+, 并且不覆盖低版本环境;成功后打印真实启动命令。 - 标准验证路径:
./init.ps1已实际跑通 admin 的 mod download / test / vet / build、client 的 editable install / 包导入 / unittest / compileall,以及仓库上下文校验。可单独运行两端命令诊断。 - 当前设备门禁:人工已确认拼多多 8.17.0、goods_id
937122477375的衣服商品只能通过“快要抢光” 打开规格面板;T-110 已获项目所有者批准,只把该证据/版本绑定的精确唯一入口作为受控导航。 T-103 的隔离 capability 仍不得包含数量、确认页、提交订单、付款或通用点击;这些动作由后续任务 分别取证后才接入生产单趟流程。T-103 的 v5 派生 XML 已由人确认无实际地址/ 手机号,并保留目标预选规格、顶部当前价“快卖完 ¥12.88”和原价“¥29.88”;底部“提交订单 ¥12.88” 继续属于硬拒绝区。派生截图虽然把顶部价格遮住一半,但项目已停止遮罩器开发,视觉完整性不再阻塞 规格选择与读价;T-204 已允许认证设备上传内部原始截图供管理员查看。入口父链证据已由人确认并 收紧为精确唯一“快要抢光”子节点及证据绑定可点击祖先,“免拼购买”仍为硬拒绝。离线实现和 112 项 测试已通过;T-103 只差人把手机置于 PDD 安全起点后完成精确规格恢复、读取12.88和一次安全退出。 完整事件链必须等待 T-107 与 T-210:先让 Gate2/Gate3 证据进入真实 schema,再实现 T-205 事件, 不用 mock 或无证据成功事件抢跑。
当前目录要点
| 路径 | 状态 | 说明 |
|---|---|---|
docs/ |
已有 | 项目规范化文档,本次已完整生成 |
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;不执行真机动作 |
client/ |
已初始化 | Python 3.11+、PySide6/uiautomator2、严格 HTTP/DPAPI/SQLite 恢复底座及受控规格选择/读价/安全退出;数量、确认页和提交未开放 |
init.ps1 / init.sh |
已完成 | 统一安装与离线验证入口;PowerShell 优先复用合规 venv,缺失时自动选择最高的 Python 3.11+,Unix 缺工具链明确失败 |
任务状态
任务状态以 docs/tasks/ 各任务文件 frontmatter 的 status 为准。本节只写项目级摘要:
- 已完成:T-005(采购服务交互原型)、T-006(采购工具交互原型)、T-007(产品名称与 源码目录契约)、T-008(Vikunja 任务权威与单向导出)、T-009(MVP 关键路径与并行波次), 以及 T-001(采购服务 Go 骨架)。
- 已完成:T-002(采购工具 Python 骨架)、T-003(双端统一初始化与验证入口)、 T-004(核心数据模型)、T-101(真机环境盘点与 USB/WiFi 双通道人工验收)、T-102(canonical 链接打开与目标商品/隐私人工验收)。
- 已完成 T-010(安全并行门禁)、T-201(管理员登录与会话)与 T-202(手工 DRAFT 建单和
基础列表)。T-202 已通过主 agent 独立审查、竞态测试与完整门禁并合入主线,仍只创建/展示
DRAFT,未实现授权、设备领取或采购执行。 - 已完成 T-110、T-111、T-203、T-204、T-301 与 T-302。服务端已能授权、认证设备、原子领取、 稳定重放和续租;claim token 不是提交许可,尚无事件、提交围栏或结果 API。
- T-103 离线
SkuSelectionFlow已实现并通过独立审计,仍为DOING等人工真机验收;T-104~T-107 按数量/确认页风险逐段开放。服务端后续顺序已收紧为 T-210 → T-205 → T-206 → T-207 → T-208。 - T-303 已完成并通过三重审查、189 项客户端测试和合并后根门禁;客户端下一步按依赖推进
T-304/T-306/T-307/T-308,再与 T-305 汇合到
T-400 离线一次性提交安全编排。围栏后管理链为 T-403 → T-402;T-401 必须在新的真实单趟重新
通过三闸门,首次点击后固定进入
UNKNOWN/人工调和,T-405 打包后由 T-404 只读验收。 - 已确认原型继续只作信息架构依据;原型假数据不调用真实接口、不驱动真机。真机结论改变 可读字段时必须先回修原型与交互清单。
当前可运行内容
Windows 统一安装、离线验证与启动命令提示已可运行:
.\init.ps1
它会在成功后输出以下真实启动命令,而不自动启动或连接设备:
采购服务:cd admin; go run ./cmd/server
采购工具:cd client; .\.venv\Scripts\python.exe -m cmbuyer_client
采购工具当前可运行的离线验证与 wheel 元数据检查:
cd client
.\.venv\Scripts\python.exe -m unittest discover -s tests -t .
.\.venv\Scripts\python.exe -m compileall -q src tests scripts
$wheelDir = Join-Path $env:TEMP ('cmbuyer-client-wheel-' + [guid]::NewGuid())
New-Item -ItemType Directory -Path $wheelDir | Out-Null
.\.venv\Scripts\python.exe -m pip wheel --no-deps . --wheel-dir $wheelDir
.\.venv\Scripts\python.exe scripts/verify_wheel_metadata.py (Get-ChildItem $wheelDir -Filter '*.whl').FullName
采购工具规范安装与本地开发入口:
# 在仓库根执行统一初始化;成功后再进入 client/
.\init.ps1
cd client
.\.venv\Scripts\python.exe -m cmbuyer_client
client/requirements.txt 是唯一依赖来源,client/pyproject.toml 动态读取它生成 wheel 的
Requires-Dist。Python 3.12 与 3.14 均已验证离线测试、编译与 wheel 元数据;完整运行时依赖安装
(pip install -e .)已通过。init.ps1 优先使用合规既有 venv,缺失时自动选择最高的 Python 3.11+;
本机 Python 3.12 与 3.14 均已验证,主工作区当前选择 Python 3.14。桌面 GUI 与真机流程未作为 T-003
验收执行。
T-101 的人工真机验收命令(先把手机切到不含收货地址、手机号、支付信息或其他无关隐私的安全页面;
必须从 adb devices -l 手工复制在线 serial,不能留空或自动选择):
# 仓库根目录;USB 和 WiFi 分开执行,每次只保留一个通道在线
D:\Portable\adb\adb.exe devices -l
.\client\.venv\Scripts\python.exe client\scripts\capture_device_baseline.py --serial <USB_SERIAL> --output-dir "$env:LOCALAPPDATA\cmbuyer\artifacts\T-101\usb-baseline" --timeout 10 --adb D:\Portable\adb\adb.exe
# WiFi 必须由人先建立通道、断开 USB 后再手工粘贴在线 WiFi serial;脚本不自动 connect/reconnect
.\client\.venv\Scripts\python.exe client\scripts\capture_device_baseline.py --serial <WIFI_SERIAL> --output-dir "$env:LOCALAPPDATA\cmbuyer\artifacts\T-101\wifi-baseline" --timeout 10 --adb D:\Portable\adb\adb.exe
脚本只读取非敏感设备元数据、拼多多版本、截图和完整 XML;不会打开商品或写页面判据。它对同机双
通道、身份读取失败、offline、unauthorized、超时或 serial 不存在均 fail closed。成功目录的
manifest.json 只记录元数据、产物路径和 SHA-256,不记录 XML 页面正文或原始 serial。T-101 已由人
完成两次验收并确认原始证据不含敏感信息;--timeout 约束 ADB 命令、ADB socket 以及截图/节点树的
公开 JSON-RPC 调用,uiautomator2 初始化仍有上游固定启动上限。截图/XML 只保留在本地,执行记录只写
路径和 SHA-256,原始证据不得提交 Git。
T-102 的人工真机验收命令(只接受唯一 canonical 链接;USB 或 WiFi 每次只保留一个通道在线):
# 仓库根目录;从输出中手工复制本次在线 serial
D:\Portable\adb\adb.exe devices -l
.\client\.venv\Scripts\python.exe client\scripts\capture_product_open.py --serial <SERIAL> --url "https://mobile.yangkeduo.com/goods.html?goods_id=<GOODS_ID>" --output-dir "$env:LOCALAPPDATA\cmbuyer\artifacts\T-102\product-open-<GOODS_ID>" --timeout 10 --adb D:\Portable\adb\adb.exe
脚本只允许 Android VIEW intent,并把 package 固定为 com.xunmeng.pinduoduo;intent 后会在
--timeout 的有限窗口内只读轮询前台 package,解决 App 异步切换造成的一次性误判,超时仍会停止。
它不点击、滑动、输入或判断商品页节点,也不打开规格、读取价格、进入下单或支付。运行拼多多版本必须精确为
8.17.0,否则在 intent 前停止。成功后由人本地查看截图/XML,确认页面确为该 goods_id 对应商品并
检查无地址、手机号、支付信息或其他无关隐私;只回报 manifest 路径及截图/XML SHA-256,原始证据
不得提交 Git。T-102 已由人确认 goods_id 958756616606 的目标商品及截图/XML 隐私,并完成验收。
T-103 已确认当前衣服商品只能从精确文案“快要抢光”进入规格面板;T-110 只批准该证据/版本绑定入口, 不授权“免拼购买 / 单独购买 / 直接拼成”等其他文案。面板刚打开时目标颜色“黑色CHA(纯棉)”与尺码 “M(建议100-115)”已经自动选中。v5 派生 XML 与人工观察已证明顶部当前价为“快卖完 ¥12.88”、 并列原价为“¥29.88”;促销前缀会变化,正式读价不能把该文案作为主判据,必须以面板结构、价格角色、 严格金额格式和唯一性组合判断,冲突时返回 unreadable。
本轮不再运行或修改截图遮罩器。T-103 先用本机证据验证真机能力;T-204 再把原始规格页截图上传采购
服务,允许页面中已显示的地址和手机号,完整 XML 不上传。代码从已确认的派生 XML 提取最小 fixture,
并在真机运行时只返回获准摘要。T-111 完成后,下一步实现 SkuSelectionFlow 的受控入口、
按维度精确选择、选中态读回、SKU 单价读取与安全退出;完成离线主审后,由人先把两个维度改成明确
记录的非目标值,再执行真机脚本确认恢复目标规格与 12.88 单价。生产原始截图展示/上传由 T-204 处理。
关键背景
本项目是 cmroubao(Go 后端 + Android AccessibilityService)与 cmpdd
(Python + uiautomator2)两个前序项目的合并重启。
- 取
cmroubao的后端任务生命周期、设备侧 API 形状、下单授权状态机、ERP 对接、管理 Web。 - 取
cmpdd的 uiautomator2 真机自动化、按维度精确选规格、订单确认页读取、付款闸门。 - 丢弃自研 Android APK 与 AccessibilityService 感知层。
前序项目是设计依据,不是事实来源。 其中的结论(尤其是拼多多页面判据)必须在本项目 用真机重新验证,且记录取证时的拼多多 App 版本。
已知风险(开工前须知)
- M2 是生死线:真机能按链接打开商品、精确勾选颜色分类和尺码、读到该 SKU 单价 (T-103)。M2 前可以写不依赖页面字段的管理员会话、DRAFT 建单和服务端授权事务;不能写 依赖未取证选择器的生产执行代码。真机结论改变字段时先回修契约与原型。
- 拼多多页面结构随版本变化,已观察到详情页无独立规格入口、价格节点被拆分等情况。
- 授权卡死:前序项目出现过
EXECUTING授权永不推进导致任务锁死。本项目在 T-207 实现围栏前超时 / 放弃,在 T-208 实现围栏后调和;围栏后不得释放或重试。 - 规格面板读价尚未形成生产判据:已人工观察当前价与原价,但 T-103 仍需把证据固化为 唯一、版本绑定且排除按钮价的读取规则;失败就转人工,不删价格闸门。
- MVP 已收窄:只做手工填链接、批量开始采购和单趟创建待付款订单。Excel、ERP、图搜、
批量顺序编排 / 暂停接管、订单自动核对、AI 辅助全部推到 V2(见
06-tasks.md的 T-501~T-508)。 - App 版本必须 fail closed:运行时拼多多版本与本项目已取证版本不一致就停止领取, 不允许用旧判据继续跑。
开始编码前检查
- 读
../AGENTS.md。 - 读
00-ai-start-here.md,特别是「本项目的四条特有纪律」。 - 读
05-coding-rules.md,特别是第 1 节红线。 - 在
docs/tasks/找status: TODO且依赖均DONE的任务文件;暂无时先按06-tasks.md落成任务文件。 - 在独立分支 / worktree 把任务改为
DOING后再改生产代码。
维护规则
实际代码状态变化时同步更新本文:新增或移动入口文件、初始化框架、新增可运行命令、 发现文档与代码不一致、阶段或 blocker 变化。
任务长期状态改在对应任务文件的 frontmatter;每轮执行记录、验证命令、阻塞点和关键决策
写进该任务文件的 ## 执行记录。本文只保留当前快照,不保留完整历史。