1
04-architecture
ila edited this page 2026-08-07 16:36:16 +08:00
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.

同步来源:docs/04-architecture.md · commit afc651f75a3a

架构设计

一、系统结构

目标架构是一套后端服务、两个面向不同角色的客户端:

采购管理员
   |
   v
管理 Web(服务端渲染)
   |
   v
统一 Backend API
   |
   +--> SQLite / 文件存储
   |
   +--> Go 内存 ERP 会话 / 直连 source ----> 顺运宝 ERP
   ^
   |
Android 采购 App --------------------> VLM Provider
   |
   +--> AccessibilityService
            |
            v
        拼多多 App
  • 管理 Web 与 API 同属 backend-api/,但页面层不能直接访问数据库。
  • Android App 位于 android-buyer/,通过 API 领取任务和回传证据,在本地调用 AI。
  • 拼多多是第三方受控边界,只能由 Android 设备在已登录会话中操作。
  • VLM 配置和 Key 位于手机,Key 使用 Android Keystore 包装的加密存储;管理后端不 保存、下发或代理模型调用。
  • ERP 账号、验证码会话、Cookie 和可能的 JWT 仅存在于 Go API 进程的受锁内存会话; 浏览器和 SQLite 只接收最小化规范货运数据。

二、模块职责

2.1 Backend API

建议分层:

cmd/api/                    # 进程入口、依赖装配、信号和优雅关闭
internal/transport/http/    # Gin 路由、中间件、页面和请求/响应 DTO
internal/usecase/           # 创建、领取、状态迁移和结果归档
internal/domain/            # 实体、状态机、权限和确定性约束
internal/repository/sqlite/ # database/sql 仓储实现
internal/platform/          # 配置、日志和文件存储

职责:

  • 验证管理会话、采购人员和设备身份。
  • 创建任务并保存原始输入,不让模型结果覆盖原始事实。
  • 原子领取下一条任务,签发有期限的 claim lease。
  • 校验任务状态迁移、幂等键和设备归属。
  • 保存候选、事件、截图元数据和结果。
  • 为管理 Web 提供任务列表、详情和取消能力。

不得:

  • 根据 Web 按钮直接驱动某台手机点击。
  • 在 Gin handler 中写任务状态机、SQL 或仓储业务逻辑。
  • 保存拼多多密码、支付凭证或支付验证码。

T-201 已建立的基础包只有 config、platform/database、platform/migration 和 transport/httpapi。HTTP 进程使用非零 read-header/read/write/idle timeout、 1 MiB header 上限和 10 秒有界关闭;默认监听 127.0.0.1:8080,扩大监听范围必须 显式配置。Gin 不启用默认 Logger/CORS/Recovery,异常恢复返回稳定 JSON 且不记录 Authorization、Cookie 或 panic 内容。

SQLite 默认文件为被忽略的 backend-api/var/cmroubao.db,连接启用 foreign keys、 5 秒 busy timeout、WAL 和 immediate transaction,并限制单连接以匹配单进程 MVP。 数据库由 cmd 显式打开和关闭,不存在包级单例。Goose SQL 通过 embed.FS 加载, cmd/migrate 显式执行 up/down/status。API 启动前检查所有迁移均已应用,不在 服务进程内自动改表;T-203 已用 00002_tasks_and_assets.sql 建立任务、资产、事件 和幂等记录表。

T-204 已用正式服务端 session 替换临时来源门禁,不重写 T-203 业务规则。Web 写 操作校验浏览器 Cookie 与表单字段的随机双提交 CSRF token;Cookie 管理 API 写请求 校验 X-CSRF-Token。明文 HTTP 只能监听 loopback,非 loopback 必须配置服务端 TLS certificate/key。

2.2 Android App

建议模块:

ui/                  # 登录、任务列表、执行状态、设置
taskclient/          # 后端 API、认证、幂等和重试
tasksource/          # 统一任务源;本地探针与后端 API 实现
workflow/            # ProcurementWorkflow 状态机
automation/          # Accessibility 节点、截图、点击、输入、滑动
ai/                  # 结构化 AI、OpenAI 兼容适配器和本地安全配置
evidence/            # 截图、步骤日志、脱敏和上传

职责:

  • 检查无障碍、拼多多安装/登录可用性、网络和当前任务状态。
  • 由用户点击后领取任务;一台设备一次只运行一条。
  • 执行有界步骤:解析 -> 搜索 -> 浏览不超过 5 个候选 -> 判断 -> 停止确认。
  • 直接调用用户在本机明确配置的 VLM;没有可用模型时允许显式人工优先模式。
  • 显示当前步骤、停止原因和人工接管入口。
  • 用前台服务承载执行中任务,以服务端授权截止时间支持有限离线;进程重启后从加密 本地状态与服务端核对恢复或安全失败。
  • 回传步骤事件、候选、截图和最终结果。

不得:

  • 接收到通知就无条件开始采购。
  • 只用固定屏幕坐标定位关键控件。
  • 在验证码、登录、风险提示或未知页面上继续猜测操作。
  • 在 MVP 点击最终“提交订单”或支付相关控件。

2.3 VLM Gateway

只负责三类能力:

  1. 需求提取:参考图 + 标题 + SKU -> 类目、属性、置信度、警告;搜索词只用于 诊断和人工模式,不替代正式链路的参考图召回。
  2. 候选评估:候选详情截图/文本 + 原始约束 -> 颜色/尺码硬约束结果、匹配项、 缺失项、拒绝原因、建议分。
  3. 候选规格兜底:仅在候选发现阶段的规则定位/选中态确认失败时,把裁剪规格截图 与最多 200 个脱敏节点发送给本机 provider;定位结果只能引用当前快照 node ID, 最终只读复核必须在同一快照同时覆盖颜色和尺码。
  4. 配置连通性测试:设置页使用内置固定测试图对当前本机 provider/model 发出一次 多模态请求,只返回稳定成功或失败分类,不读取任务数据、不保存结果且不经过 Admin。

正式数据流固定为 Android App -> VLM Provider。管理后端只下发原始任务并接收 结构化结果,不保存/下发 provider 配置或 Key,也不实现 /tasks/{id}/ai/* 代理。 后台任务不能携带或覆盖本机 provider、Base URL、model、prompt 或 API Key。

App 支持两个显式模式:

  • MANUAL_FIRST:从原始标题/SKU 产生有界搜索词,由人员判断候选,不要求 VLM。
  • AI_ASSISTED:使用 App 本地配置的 OpenAI 兼容 provider 做需求提取和候选评估。

规格兜底仍服从 execution 的固定模式。自动领取时配置完整、安全且 provider 支持该 能力才进入 AI_ASSISTED;否则进入 MANUAL_FIRST 并保持确定性候选流程。模式开始后 任务 payload 和 Admin 均不能开启模型。配置中途失效时跳过无法确认的候选,不改写模式。

2.4 顺运宝 ERP 适配层

Go 直连 source 是外部系统防腐层,不属于采购任务状态机:

Admin 创建 sync run
 -> Go 后台 worker 复用受锁 ERP 内存会话
 -> Go source 查询 listTotal/list/listByStock
 -> Go source 规范化并去除收件 PII
 -> Go 同事务 upsert freight order/items
 -> Admin 复核 procurement request
 -> 显式生成不可变 purchase task
  • ERP 账号/密码只由 API 启动环境读取;浏览器不提交凭证,SQLite 和普通日志不保存凭证。
  • 精确单号只是查询条件,外部身份固定为 stock.id 和 details[].id。
  • source 不调用 Roubao/拼多多/VLM,不打印原始响应 body,只返回 allowlist 规范结构。
  • Go handler 只创建 sync run;外部查询由有界 worker 执行,避免把验证码或 ERP 延迟绑定到浏览器请求。
  • 未确认的 productThumb 只按 ERP 引用保存,不能拼接 URL 或越权下载。
  • ERP 接口由页面协议观察得到,正式生产前需确认开放 API、服务账号、调用频率、 缓存和个人信息处理权限。

T-225 冻结了 internal/platform/shunyunbao 的协议常量、请求 header、完整单号/日期范围 条件、分页、详情批量和 allowlist 归一化。T-226 增加受互斥保护的 Go 内存会话:Admin 以短期 ticket 读取验证码图片并人工输入验证码,服务端才持有 Cookie jar;账号密码只从 启动环境读取。T-227 将此会话直接作为 FreightSource:每次同步先校验会话,再以最多 100 条、每页 20 条和每批最多 100 个详情 ID 查询;响应不完整、身份冲突或会话失效均使 整批失败。进程重启即失去会话,不用 Redis 或持久化 Cookie。货运用例只识别来源中立的 “未配置、会话失效、未找到、协议异常、暂时不可用”错误。T-228 已删除旧 Python Connector、loopback 端口和服务密钥;仓库运行时仅保留 Go API 进程。

模式在 execution 开始时固定并写入结果;AI 失败后只能由人员明确切换,不能静默降级。 App 同时固定 provider ID、model、prompt/schema version 和证据 SHA-256,作为非秘密 provenance 回传。Key、Authorization、完整 endpoint 和供应商原始响应正文不回传。

provider Key 从旧设置迁移到 Android Keystore 包装的加密存储;迁移或解密失败时 拒绝真实调用。每台设备使用独立、可撤销、有限额度的 Key。Keystore 只降低静态泄露 风险,不能宣称可抵抗已 Root 或完全受控设备。

模型输出是不可信建议,必须通过 schema 和确定性校验:

  • sku、quantity 和 max_budget 使用原始任务值;数量和预算不进入模型 prompt。
  • 原始 SKU 可唯一提取的颜色、尺码由本地代码固定为硬约束。候选必须对每个硬约束 返回 MATCH/MISMATCH/UNKNOWN;只有全部为 MATCH 才能进入自动 Top 5。
  • 价格未知、超预算或关键属性无法确认时不能判为可接受。
  • T-103 探针阈值为 0.75;低于阈值或标题/图片冲突时进入人工处理,不自动扩大 浏览范围。
  • 模型不能返回点击坐标、状态迁移或“允许提交订单”等执行授权。

T-104/T-211 按候选 ordinal 串行评估,每个候选最多一次结构化调用、整批最多 5 次;首个 网络失败或无效输出停止后续调用。模型响应只允许 schema_version/candidate_index/decision/score/matched/missing_or_uncertain/ rejection_reasons/confidence/hard_constraint_results,其中 decision 仅允许 REVIEW/REJECT/MANUAL_REQUIRED。hard_constraint_results 必须逐项原样回显本地给出的 颜色和尺码期望值,并返回 MATCH/MISMATCH/UNKNOWN 与证据说明;缺项、重复、改写期望值 或 UNKNOWN 均不能进入自动 Top 5。ordinal、证据 SHA-256、建议候选、provider provenance、 manual_review_required=true 和 order_submitted=false 由本地代码确定。任务没有 预算时,模型声称价格或预算匹配会被视为无效输出。

T-103 的模型响应只允许 schema_version/search_query/category/attributes/confidence/warnings。属性来源限定为 TITLE/IMAGE/BOTH;额外字段、无效 JSON、重复或越界属性、坐标/动作语义均视为无效 输出并转人工。最终领域结果再由确定性代码补回原 SKU、数量、空预算、人工复核原因和 provider/model/prompt_version/reference_image_sha256。

技术探针和后台 execution 的每个逻辑步骤最多发出一次 VLM 请求,不沿用通用 Agent 的重试循环。该结构化 HTTP 客户端关闭连接自动重试和 HTTP/HTTPS 重定向,整体调用 超时为 75 秒;协程取消 会取消底层 HTTP call,成功响应正文上限为 64 KiB,非成功响应不读取正文。

Release 远程 provider 只允许 HTTPS;HTTP 仅允许 Debug 下无 API Key 的 localhost、 127.0.0.1 或 ::1 本机 mock。端点不得包含 userinfo、query 或 fragment。标题 和 SKU 在进入 prompt 前分别限制为 2048 和 512 个 UTF-8 字节。JPEG 在调用前复核媒体类型、20 MiB 上限、魔数和 SHA-256,按声明长度一次分配并精确读取,Android 解码后最长边限制为 2048 px。请求和响应正文、Base64、API Key 不写普通日志;Keystore-backed 密钥存储 不可用且存在 Key 时拒绝调用。

设置页连通性测试沿用同一端点策略,禁用重试和重定向,调用超时 45 秒,成功响应限制 为 64 KiB。固定测试图、Key、完整 endpoint 和供应商响应正文均不进入日志或持久化; 401/403、模型不可用、限流、服务端、网络、超时和响应异常只映射为稳定枚举。

三、核心数据流

3.1 技术探针

本机私有蝦皮订单目录
 -> Debug 导入工具按订单号配对文本和参考图
 -> 规范化为 ProbeTask
 -> Android FixtureTaskSource
 -> 校验设备就绪
 -> 校验参考图并提取 SKU 颜色/尺码硬约束
 -> 将一次执行专用参考图写入受控 MediaStore
 -> 通过拼多多可见图片搜索入口选择该图
 -> 检查图片结果页最多 5 个候选
 -> 过滤并排序颜色/尺码均确认匹配的 0..5 个候选
 -> 到达候选详情或确认页
 -> 停止并记录结论

该阶段不依赖后台,用于尽早判断 Android 自动化是否可行。

图片搜索临时资产只保存匿名执行标识,不使用订单号或标题作为文件名。App 在写入前 复核任务参考图的媒体类型、长度和 SHA-256,并在完成、失败或安全停止后 best-effort 删除自己创建的媒体。拼多多图片入口、相册页、当前图片或结果页无法唯一确认时停止; 不得从用户相册中猜选其他图片。图片搜索只负责召回,VLM 不能改变原始 SKU,也不能 把 UNKNOWN 规格提升为通过。MediaStore 图片从 pending 发布后显式通知变更并等待 750 ms 再启动拼多多,给系统媒体索引一个固定、有限的稳定窗口。

TaskSource 是工作流读取任务的唯一边界:

  • 第一层使用 FixtureTaskSource,消费 Debug 导入工具生成的本地私有样本。
  • 第二层替换为 HttpTaskSource,通过 Go-Gin 的 claim-next 和资产接口读取任务。
  • 两种实现必须产生相同的领域字段;workflow、AI 和 automation 不得判断任务来自 文件还是 HTTP。

Debug 导入工具运行在开发机上,Android App 不能假定能直接访问 Windows 绝对路径。 工具读取用户显式配置的目录,将数据写入被 Git 忽略的 .local/ 生成目录,再由 Debug 构建或测试装载。导入必须:

  • 用文件主名关联订单号,不能用文本模糊匹配图片。
  • 首版严格解析 UTF-8 四行标签 店铺名:、商品标题:、SKU:、数量:。
  • 校验店铺名、标题、SKU、正整数数量和唯一且可解码的 JPEG 参考图。
  • 对缺失、重复、编码无法识别和字段格式未知返回结构化错误。
  • 不把完整订单号、店铺名、原图路径写入普通日志。
  • 仅在用户明确配置 VLM 后发送必要的标题、SKU 和参考图;不发送订单号或店铺名。
  • RequirementProbeSource 只从固定 asset 根读取已导入任务和引用图片;随后立即进入 大小、JPEG 魔数和 SHA-256 复核,不接受任意 cache 或绝对路径。

实现边界:

  • task-contract/:纯 Kotlin ProbeTask、TaskSource 和版本化 JSON codec。
  • tools/shopee-importer/:开发机 CLI,严格校验并生成匿名资产名。
  • app/src/debug/.../FixtureTaskSource:只在 Debug 代码中读取 assets/probe-fixtures/tasks.json。
  • ProbeWorkflowCoordinator:只依赖 TaskSource,未来可无缝替换 HttpTaskSource。

私有 fixture 只有在构建显式设置 -PprobeFixturesDir 时注入 Debug APK;普通构建 必须同步清空生成资产,防止上一次真实样本残留。

T-101 的固定词搜索已落在以下运行边界:

SearchProbeScreen
 -> WorkflowRunner(timeout / retry / stop)
 -> PinduoduoSearchAutomation(纯 Kotlin)
 -> AndroidPinduoduoUiDriver
 -> BuyerAccessibilityBridge
 -> BuyerAccessibilityService
 -> 拼多多可见、启用、唯一语义节点

结果页成功不是“点击已发送”,而是同时确认精确查询词、搜索结果头和至少 3 个排序 控件。ACTION_SET_TEXT 后必须重新读取当前根节点并精确比对输入;任何稳定未知页以及 登录、验证码、风控、订单或支付边界都终止 workflow。该路径不提供坐标、ADB、 Shizuku shell、OCR 或 VLM 动作降级。

T-102/T-104 在搜索结果后追加一个有界候选步骤:

精确匹配固定词或当前结构化需求词的结果页
 -> 最多 2 次滚动预算
 -> 最多 5 个去重商品卡
 -> 验证详情页
 -> 详情页无障碍截图
 -> 受控 DISCOVERY_INSPECT 规格入口
 -> 选择目标颜色/尺码并读取组合价格
 -> 规格弹层语义和截图
 -> App cache/candidate-NN-{detail,specification}.png + manifest.json
 -> 关闭规格弹层并复核详情页
 -> 一次全局返回并复核固定词结果页

候选卡只保留语义指纹和计数,详情/规格截图保存在 App 内部 cache。manifest v4 记录 匿名文件名、卡片/详情语义 SHA-256、截图 SHA-256、字节数、尺寸、有界规格语义、 已选摘要、严格组合价格和 best-effort 页面可见标题;不保存完整页面原文。标题最多 160 字,动作、价格和纯数字文本不会作为标题。T-104/T-213/T-214 使用这些证据时 必须通过受控 evidence 边界读取,不能让 VLM adapter 自行遍历 cache。Android 10/API 29 及以下不能运行当前截图探针,应在预检时明确不支持,不使用媒体投影或 shell 绕过。

T-274 将候选的标题语义 signature 与点击身份分离。每次结果树读取为已接受卡片生成 只在当前视口存活的 locator,包含 recycler child index、接受顺序、bounds、点击目标 相对 path 以及完整语义/节点结构 SHA-256;不保留原始节点或原始文本。打开前重读树, 同时复核 signature、内容指纹和位置,只有唯一命中才对节点执行 ACTION_CLICK;位置 变化时只允许唯一指纹加 80% bounds 重叠重定位。locator 不写 manifest、进度、outbox 或 Admin。候选尝试去重使用不含位置的完整内容指纹,因此同标题不同卡片可分别尝试, 同一完整卡片滚动后不会反复尝试。初次候选需连续两次读取产生相同 locator stability keys(含位置与节点指纹)。

CandidateEvidenceSource 只接受当前 workflow 内存中的连续 ordinal 元数据,文件名 固定为 candidate-01-detail.png/candidate-01-specification.png 至第五组;每张 PNG 最多 8 MiB、全批最多 64 MiB、声明尺寸最长边不超过 10000 px,并复核规范路径、 PNG/IHDR、精确字节数、尺寸和 SHA-256。每个候选回传时必须恰好绑定 DETAIL/SPECIFICATION 两份证据,生成独立 asset ID;先验证全批 ordinal、类型和 哈希再写入加密 outbox,候选的 asset ID 数组固定按 DETAIL、SPECIFICATION 排序,重试沿用各自 idempotency key。Android gateway 再解码详情图并把最长边缩至 2048 px。当前需求快照与搜索词必须同时匹配候选 session,否则拒绝评估;另一个 关键词的结果页只允许重新进入搜索框,不能采集候选。

T-213 规格核验优先使用“选择规格/请选择规格/颜色分类/颜色款式/选择颜色/选择尺码” 或“已选/请选择”前缀的唯一入口;拼多多 8.17 没有直接入口时,DISCOVERY_INSPECT 允许从已验证详情页点击唯一“免拼购买”语义目标。弹层最多读取 160 个语义节点、 每组最多 30 个选项,目标颜色/尺码必须各自唯一、启用且每次点击后可复核选择状态。 选定后读取明确人民币组合价格;重复、缺组、禁用、滚动截断、状态未变化、多价格冲突 或无障碍语义不足一律 UNKNOWN/MISMATCH,不得继续到订单提交。

候选评估 schema/prompt v3 把本地规格结果作为权威输入;模型返回的颜色/尺码状态必须 逐项与本地结果相同,否则整批降级人工检查。详情和规格证据 SHA-256 同时绑定 assessment、重排身份和 outbox 资产,VLM 不能通过主图推断覆盖本地硬约束。

T-276 将后台采购候选搜索收敛为两轮。第一轮最多打开 6 个不同结果并保存最多 5 个 EXACT_MATCH;达到 5 个后直接封板。未达到目标时才重新导入参考图执行第二轮,第二轮 只检查默认排序前 2 个不同商品并以 FALLBACK 保存,累计快照最多仍为 5 个。每轮浏览 超时默认 100000/45000 毫秒,加图片搜索步骤后的工作流总预算为 245 秒。新 execution 不得产生第三轮;升级前已写入数据库的第三轮观察保持只读审计,不迁移、不改写。

T-272 在上述候选规格读取内增加有界兜底,而不改变订单 dry-run:采集侧同时聚合节点 自身或四层内祖先的 clickable/selected/checked;规则给出唯一结果时零模型调用。仅对 可见信息不完整、重复歧义、点击失败或点击后选中态未知构造快照,节点最多 200 个、 深度最多 12、文字最多 160 字符,并在截图前后复核结构 hash。定位输出经严格 schema、 0.92 阈值、node ID、path 和局部指纹复核后只点击一次;颜色、尺码串行处理。最后的 0.95 双规格视觉证明独立保存在规格证据中并绑定实际保存的截图 hash,不伪造节点 selected 状态。每候选最多两次定位和一次最终复核;第二轮保底不启用。

T-277 将最终规格复核 schema 升级为 v2。当颜色/尺码已经选中但“已选择”摘要或唯一组合价 缺失时,也允许使用剩余的一次最终复核调用。模型只能返回当前快照中的颜色、尺码和最多 4 个价格 node ID;App 重新确认结构 hash,按屏幕位置拼接这些节点原文并使用共享人民币 解析器生成分值。模型自报文字与节点拼接不一致、未知/重复节点、低于 0.95、旧快照或 无法解析的金额全部拒绝。接受结果将 SKU 摘要、价格、proof 和 LOCAL_VLM 来源绑定同一 规格截图 SHA-256。候选 outbox、v21 observation 和 Admin 显式保存/展示 SKU MATCH|MISMATCH|UNVERIFIED、价格 VERIFIED|UNVERIFIED 与值来源;第二轮保底固定为 两个 UNVERIFIED,不调用模型。

T-281 修正规则层过早结束首轮规格采集的问题。规则点击后必须复读选中态;点击未生效、 完整分组因别名无法定位目标或结果歧义时,允许在同一候选内进入上述 node-ID VLM 兜底, 明确 disabled 的目标仍直接失败关闭。每次模型调用独立限制为 20 秒,异常、超时、合同 不符、低置信度、节点/证据/价格无效、旧快照和点击拒绝使用稳定原因码。无价格上限的 候选仍尽力读价,但缺价本身不再消耗模型调用或否决 SKU;确定性解析额外允许固定标签 “拼单价/单买价/券后价/券后/到手价/活动价/优惠价/折后价/补贴价/限时价”加唯一金额, 区间、“起”、未知标签和多个金额继续保持未验证。

采购运行证据写入 App noBackupFilesDir 下的私有 SQLite,并合并展示在“记录”模块。 每个 execution 保存规则判定、模型阶段/稳定终态、节点摘要、合法白名单响应摘要和候选 SKU/价格状态;最多保留 50 次运行、每次 200 个事件。截图/Base64、Key、token、Cookie、 地址和完整任务描述不得入库;不符合严格 schema 的响应只留 SHA-256 与长度。后台只接收 有界的模型拒绝原因聚合,不接收节点 JSON、模型响应或图片。

PKG110 上的拼多多 8.17.0 服装详情只暴露不可点击的“颜色/款式”预览;完整颜色/尺码 和组合价格位于“单独购买/免拼购买”后的规格弹层。业务方已确认最终流程需要自动创建 待付款订单,因此 T-213 重新定义两级能力中的第一层:DISCOVERY_INSPECT 可以从 已验证详情页进入规格弹层并选择目标颜色/尺码以读取组合价格,但不能加入购物车、 提交订单或触发支付。后续 ORDER_CREATE 必须由 Admin 对确定候选签发一次性授权, 使用独立状态机和幂等/对账边界,不能复用候选探查权限。

DISCOVERY_INSPECT 从任务 SKU 的本地规范化结果取得唯一颜色/尺码,按颜色后尺码 的固定顺序选择,每次动作后重新读取 selected 与“已选择”摘要;规格区域最多向前 滚动 2 次。确定性价格只接受单一、完整的人民币文本,或 T-281 固定白名单价格标签后的 唯一人民币文本;T-277 允许本机模型从同一快照选择拆分的币种和数字节点,再由代码按 相同规则解析。普通对照促销价、区间、未知折扣条件、多实际价格冲突或无价格一律保持 未验证。 若唯一入口落到订单确认页,自动化只能 执行系统返回并跳过该候选。

评估结束后 automation 不再产生动作,UI 进入 AWAITING_CONFIRMATION、 MANUAL_REVIEW 或 NO_MATCH。人员可以把本地建议项标记为可用,或拒绝本次候选; 这只是验证结果,所有状态的 order_submitted 均为 false。

需求提取是独立探针,不启动拼多多,也不接入 MobileAgent。GUI-Owl 和 MAI-UI 输出 动作/坐标,明确不具备 supportsRequirementExtraction 能力。真实供应商未确认前, 普通测试只使用 Fake gateway;本机 OpenAI 兼容 mock 仅验证 Android 请求链路和隐私 边界,不作为真实模型效果证据。

3.2 MVP 业务闭环

管理员创建 PENDING 任务
 -> 采购员在 App 点击“获取任务”
 -> 后端事务内选取并置为 CLAIMED
 -> App 确认后置为 RUNNING,取得有限离线授权
 -> best-effort heartbeat 同步步骤和取消
 -> App 本地需求提取和拼多多自动化
 -> WAITING_CONFIRMATION
 -> 采购员接受/拒绝候选
 -> 加密 outbox 幂等回传结果和证据
 -> SUCCEEDED 或 FAILED/CANCELED
 -> 管理端展示结果

执行事件与后台共享单条 message <= 1000 UTF-8 bytes 契约。候选搜索的状态和聚合 诊断在同一个 EVENTS outbox 请求中使用两条事件,不靠截断丢失诊断;T-274 已生成但被 后台整体拒绝的旧超长候选事件,会在上传边界按 cards= 稳定拆分,并从原 event ID 确定性派生诊断 event ID,保证网络重试的请求体不变。

outbox 严格按队首顺序 flush。连接、TLS、DNS、超时或可重试 5xx 保留队首并在授权窗口 内重试;后台已经响应的不可重试错误只保存错误码、HTTP 状态和白名单校验字段,停止 同步及后续拼多多动作,不能越过、丢弃或伪装成后台离线。响应正文和字段错误内容不进入 本地持久化、UI 或日志。

四、状态机

4.1 任务状态

PENDING
  | claim
  v
CLAIMED ---- lease expired/release ----> PENDING
  | start
  v
RUNNING
  | candidate ready
  v
WAITING_CONFIRMATION
  | accept validation result
  v
SUCCEEDED

PENDING/CLAIMED/RUNNING/WAITING_CONFIRMATION
  +--> CANCELED(仅允许规则规定的主体取消)

CLAIMED/RUNNING/WAITING_CONFIRMATION
  +--> FAILED(结构化错误)

规则:

  • SUCCEEDED 是验证结果成功,不代表已下单;order_submitted=false。
  • CLAIMED 默认租约为 10 分钟;RUNNING/WAITING_CONFIRMATION 默认授权为 30 分钟,允许范围 5 至 120 分钟。App 每 30 秒 best-effort heartbeat,成功后 按服务端时间滑动续期。
  • 只有当前设备和有效 claim token 能启动、续租、上报或结束任务。
  • 终态不可回退;重试创建新的 execution attempt,不篡改历史证据。
  • App 在 claim 前生成并安全保存 256 bit Raw URL token;后端只存 SHA-256, token 与 Idempotency-Key 相互独立。
  • ���期 CLAIMED 可以原子回收;过期 RUNNING/WAITING_CONFIRMATION 保持原状态, 不自动回队列。App 到达服务端授权截止时间持久化 SAFE_STOPPED 并停止前台 执行;原设备重连 heartbeat 只同步状态且不延长已过期授权。T-207 才允许原设备 补报授权内已产生的终态结果并留下过期补报审计标志。
  • 管理取消 PENDING/CLAIMED 立即终态;执行中只设置停止请求,App 在下一个安全 检查点停止并调用 cancel-ack 后才进入 CANCELED。离线期间不能保证即时取消, App 恢复连接后必须先同步取消状态再继续页面动作。

T-206 Android 使用独立 ProcurementSecureStore 保存 backend URL、BUYER access token、设备 secret、claim token、各操作幂等 key、任务快照和 execution。存储创建 失败时整个后台采购入口 fail closed,不回退普通 SharedPreferences。登录密码只 存在于当前 Compose 输入和一次请求中;后台任务不能读取或修改 Roubao provider。 HttpTaskSource 只把已领取任务和经过 MIME/JPEG/大小/SHA-256 校验的内部参考图 映射为现有 ProbeTask,不参与领取策略。

4.2 Android 工作流状态

IDLE
 -> PREFLIGHT
 -> REQUIREMENT_ANALYSIS
 -> OPEN_PDD
 -> SEARCH
 -> SCAN_RESULTS
 -> REVIEW_CANDIDATE
 -> WAITING_USER
 -> FINISHED

任意执行态 -> STOPPING -> FAILED/CANCELED

每一步必须有:

  • 进入条件和预期页面特征。
  • 最大等待时间和最大重试次数。
  • 可观察事件。
  • 允许的下一步。
  • 安全停止条件。

五、数据模型

所有主键使用服务端生成的 UUID;时间统一为 UTC 的 ISO 8601。

users

字段 约束 说明
id PK 用户 ID
username UNIQUE, NOT NULL 登录名
password_hash NOT NULL 不保存明文
role NOT NULL MVP 为 ADMIN 或 BUYER
is_active NOT NULL 禁用后现有和新凭证均不可使用
created_at NOT NULL 创建时间

devices

字段 约束 说明
id PK 设备 ID
name NOT NULL 人类可识别名称
token_hash NOT NULL 设备令牌哈希
bound_user_id FK, nullable 当前绑定采购员
app_version nullable App 版本
android_version nullable Android 系统版本
pdd_version nullable 已验证拼多多版本
last_seen_at nullable 最近心跳
readiness_reported_at nullable 最近一次就绪上报的服务端时间
accessibility_enabled NOT NULL 无障碍连接就绪位
pdd_installed NOT NULL 拼多多安装就绪位
is_enabled NOT NULL 后端开关

设备必须先由本地管理命令预授权。首次 BUYER 联合登录可以把 bound_user_id 为空的 设备原子绑定给当前采购员,不支持客户端自助重新登记或抢占其他采购员的设备。

admin_sessions / access_tokens

  • session/access token 都使用至少 256 bit 的随机 opaque secret,原值只通过 Set-Cookie 或登录响应返回一次,数据库只存 SHA-256。
  • 管理 session 和 App access token 均固定30天绝对有效,不因请求、heartbeat 或任务 执行滚动续期。两类凭证继续隔离;既有 session/token 保留签发时的数据库到期时间。
  • 每次鉴权都联查用户/设备启用状态,因此禁用立即生效,不等待 token 到期。
  • 管理 Cookie 与 App Bearer token 使用不同 middleware,不能互相替代。
  • T-203 的 local-admin 继续作为单管理共享资源 scope;真实 user_id 另作 actor, 避免切换身份后隐藏已有任务。
  • 管理和 App 登录在 bcrypt 前共享一个内存有界限流器,但使用独立 scope + 服务端 RemoteAddr 键;成功登录清零,超限返回 429 与 Retry-After。

ERP 货运来源层

表 主要内容
erp_sync_runs 查询模式、匿名查询 hash、时间范围、状态、计数、错误码和成功水位
freight_orders creator、source system、external stock id、来源单号、店铺、状态、ERP 时间、canonical hash/revision
freight_order_items freight order、external item id、标题、规格、SKU、数量、图片引用、采购状态、canonical hash/revision
procurement_requests 货运明细 revision 的不可变采购字段、校验状态、参考图和来源变化状态
purchase_task_sources procurement request/revision 与现有 purchase task 的幂等关联

货运层只保存采购所需字段,不保存 receiver、receiverTel、receiverAddr、Cookie、JWT 或完整原始 JSON。重复同步按外部 ID upsert;内容 hash 不变时不增加 revision。 来源变化只产生新 revision/状态,绝不修改已生成的采购任务。

一个货运单可以有多个商品明细;一个采购任务仍保持单商品、单 SKU、单参考图。 缺少明确标题/SKU/正整数数量/有效参考图的请求停在 NEEDS_REVIEW/NEEDS_IMAGE。

purchase_tasks

字段 约束 说明
id PK 任务 ID
created_by_user_id FK, nullable 新任务的真实 ADMIN actor;历史任务允许为空
title NOT NULL 原始标题
description NOT NULL 原始说明,可为空字符串
sku NOT NULL 原始 SKU,不得由模型改写
image_asset_id FK, NOT NULL 原始参考图
quantity > 0 权威数量
max_budget > 0, nullable 全部数量的权威最高商品总预算,币种为 CNY
status NOT NULL 任务状态枚举
claimed_by_user_id FK, nullable 当前采购员
claimed_by_device_id FK, nullable 当前设备
claim_generation >= 0 每次领取递增,释放后保留用于审计
claim_token_hash nullable 64 位小写 SHA-256;永不保存原 token
claim_issued_at nullable 当前 claim 签发时间
claim_expires_at nullable 租约到期时间
cancel_reason nullable 管理取消原因
cancel_requested_at nullable 执行中停止请求时间
cancel_requested_by_user_id FK, nullable 请求停止的 ADMIN
canceled_at nullable 取消终态时间
version NOT NULL 乐观锁/状态并发控制
created_at/updated_at NOT NULL 审计时间

task_events

  • 事件只追加;T-205 已实现 TASK_CREATED、TASK_CLAIMED、 TASK_RECLAIMED、TASK_RELEASED、TASK_STARTED、 TASK_CANCEL_REQUESTED、TASK_CANCELED。
  • actor_user_id 是指向 users 的可空外键。新管理操作必须写入真实 ADMIN, T-203 历史事件保持为空。
  • actor_device_id 是指向 devices 的可空外键;App 状态迁移同时记录用户和设备。
  • 设备/任务 heartbeat 不写事件,避免高频审计膨胀。
  • 管理任务详情 API 可返回 actor;密码、session、设备 secret 和 access token 永不 进入事件。

task_executions

字段 约束 说明
id PK 一次执行尝试
task_id FK 所属任务
attempt_no UNIQUE(task, no) 尝试序号
claim_generation UNIQUE(task, generation) 对应的 claim 代次
device_id/user_id FK 执行设备和人员
current_step 1-64 bytes 最近 heartbeat 的执行步骤
last_heartbeat_at NOT NULL 最近运行 heartbeat
order_submitted NOT NULL, false MVP 数据库约束必须为 false
started_at/finished_at started 必填 执行耗时和安全结束

候选、模型派生结果、outcome、结构化失败和 execution evidence 属于 T-207,不在 T-205 的最小 execution 表中提前伪造。

lifecycle_requests

  • 主键为 user_id + device_id + operation + idempotency_key。
  • operation 为 CLAIM_NEXT、START、RELEASE、CANCEL_ACK;保存请求 SHA-256 与 task/generation/execution 结果引用。
  • NO_TASK 也是稳定结果;同 key 重放不会因后来新增任务而改变。
  • claim 原 token 不进入该表,请求 hash 只包含 token hash。

assets 与后续 execution_events

  • T-207 的 execution_events 只追加,记录 step、事件类型、可读消息和时间;不保存 密码或 token。
  • assets 保存文件相对路径、媒体类型、大小、哈希、创建者和保留时间。
  • 原图和截图必须通过鉴权接口读取,文件名不能直接作为公开 URL。
  • 任务参考图上传可接受 JPEG/PNG/WebP,但后端必须先真实解码、限制字节与像素,再 统一规范化为匿名 JPEG;未来 Android 读取的资产不能依赖原始扩展名或声明 MIME。

候选决策数据集(T-208)

T-208 已在 T-207 的候选、事件、截图和最小结果回传基础上,于 task_executions 下增加 独立、不可变的数据层,不把整批候选塞进 task_events、purchase_tasks JSON 或 一段不可查询的自由文本:

表 主要内容
candidate_search_runs execution、需求快照 hash、搜索词、App/拼多多版本、开始/结束时间
candidate_observations run、ordinal、可选平台商品 ID/规范化 URL、可见标题/规格/价格、采集状态和截图 asset
candidate_observation_identities execution-scoped candidate key、原 ordinal、卡片/详情语义签名、详情/规格证据 hash 和 identity 版本
model_runs provider/model、prompt/schema/阈值版本、耗时、token/成本和请求/结果 hash
candidate_evaluations observation/model run、decision、score/confidence、matched/missing/rejection reasons
candidate_recommendations run、推荐 observation、conclusion、确定性策略版本和简短理由
candidate_human_reviews run、最终 outcome、选择项、actor、理由 schema、时间和可空 supersedes_review_id
candidate_human_review_items review 下每个候选的 ACCEPT/REJECT、主要理由和可选备注
candidate_human_review_reasons review item 的多值结构化理由码

四层数据语义不可混用:

  • observation 是 App 当时实际看到的页面事实。
  • prediction 是特定模型版本的输出。
  • recommendation 是本地确定性规则的结果。
  • human label 是采购人员明确提交的结论,才可作为离线准确率标签。

现有 assets.purpose 在 T-207/T-208 migration 中按实际需要扩展 CANDIDATE_SCREENSHOT、CANDIDATE_IMAGE 和 EXECUTION_EVIDENCE。第三方商品或 图片 URL 只保存为长度受限、规范化的辅助观测值;后端不得盲目请求该 URL。主要证据 必须是 App 上传后由 assetstore 校验、脱敏和受鉴权访问的时间点快照。

T-214 后,v7 以后写入的每个 observation 在同一事务内生成 candidate_observation_identities。candidate_key 使用版本域、execution ID、原始 ordinal、详情语义签名和规格证据 hash 生成,只标识该次 execution 的持久 observation, 不冒充拼多多全局商品 ID。App 按 DETAIL、SPECIFICATION 顺序提交两个不同的 evidence asset ID;后端逐一核对其实际 SHA-256 后才接受候选。Admin API/Web 展示 key、四个指纹和受控截图;后续选品授权必须引用 key 并绑定任务内容 hash 和 review 版本,不能只信 URL 或列表 ordinal。

Admin 下单授权(T-215)

非空候选保存后,任务从 RUNNING 进入 WAITING_CONFIRMATION。Admin 选择不会调用 Android 或拼多多,而是在后端追加一版 human review 和一条 order_authorizations:

Admin task detail
 -> candidate key + 全候选结构化理由
 -> 校验 task/execution/content hash/version
 -> candidate key 映射原 observation
 -> 追加 admin human review
 -> 生成 PENDING_DELIVERY authorization 快照
 -> T-216 device command pull

授权快照固定原始任务 SKU/数量、候选规格/价格、review 版本和 T-214 四个身份指纹; 同时冻结任务最高总预算或后台默认 200 元低价总额上限及来源。候选展示价只保留为观察 数据,不再作为当前规格价格的等值授权条件。价格上限、来源和 schema v3 都参与命令哈希。 请求不能覆盖这些字段。一次 execution 最多一条 active 授权;设备领取前改选只能 追加新版本并把旧记录标记为 SUPERSEDED,设备领取后必须走显式停止/撤销协议。 浏览器不持有设备 claim token,授权表也不保存拼多多登录、支付或收货凭证。

设备命令投递(T-216)

Roubao 复用前台服务的 30 秒 heartbeat 主动 pull,不依赖 Android 后台推送:

flush candidate outbox
 -> task heartbeat keeps lease
 -> POST commands/next
 -> backend validates claim + execution + active authorization
 -> PENDING_DELIVERY -> DELIVERED and returns canonical command
 -> App validates and saves encrypted PendingOrderCommand
 -> POST commands/{id}/ack with same hash/idempotency key
 -> DELIVERED -> ACKNOWLEDGED

HTTP 响应不确定时,服务端对 DELIVERED/ACKNOWLEDGED 重放相同 command 和 hash; App 只有在加密状态提交成功后才 ACK。投递/确认与真正页面执行分离,T-216 收到命令 后仍不打开拼多多。App 本地旧候选选择不再作为后台任务完成条件。

已授权订单 dry-run(T-217)

ACKNOWLEDGED command
 -> encrypted PendingOrderDryRun
 -> idempotent dry-run start: authorization -> EXECUTING
 -> open authorized canonical Pinduoduo product
 -> normalized title + current goods_id / authorized detail fingerprint /
    bounded current-share goods_id verification
 -> deterministic color/size/price first
 -> bounded local VLM node-ID fallback when deterministic evidence is incomplete
 -> quantity + actual-price/frozen-cap verification
 -> unique specification confirmation action
 -> ORDER_CONFIRMATION read-only verification and evidence
 -> encrypted READY
 -> idempotent backend ready record

旧 ordinal 和第三方 URL 都不参与点击。旧截图 hash 是 Admin 决策证据,不要求新截图 逐像素相等;重新定位至少精确命中一个旧语义签名,并同时满足标题、SKU、实际价格与唯一性。 规格单价必须唯一可读,单价乘数量必须等于确认页总额且不超过授权冻结上限;App 与后台 各自校验一次。候选价格为空不阻断,但实际价格为空或歧义仍失败关闭。 App 可以从规格弹层进入确认订单页,但 T-217 的 accessibility action allowlist 不包含 确认订单页的提交、付款、地址或优惠选择。READY 同时存在于手机加密状态与后端审计表, 才允许 T-218 消费。

T-279 将 direct dry-run 的瞬时自动化尝试限制为两次。身份、SKU、价格或预算确定性失败 不会继续操作拼多多:App 先把稳定 failure code/message 和幂等键写入加密状态,再重传 failure API;网络恢复只重传失败结果,不重跑页面动作。后台把授权置为 FAILED,任务仍 处于 WAITING_CONFIRMATION 以便 Admin 重新选品。成功、失败和安全停止继续复用前台返回 协调器切回 Roubao。

本机 VLM 只在 Roubao 模型配置通过安全校验后启用,不依赖候选阶段的 execution mode。 每次 dry-run 最多两次规格 node-ID 定位和一次最终双规格/价格复核;点击前复核同一快照 结构,点击后重取无障碍根节点。模型无权确认订单、提交订单或点击支付。

拼多多 8.17 的结算 WebView 偶尔只暴露外层节点。此时 App 可对无障碍服务捕获的当前 确认页截图运行 bundled ML Kit 中文 OCR,但它只返回只读证据:标题必须满足有界锚点、 颜色/尺码必须通过同一 SKU 别名匹配器、数量必须位于规格与优惠边界之间,实付款必须 唯一可解析。任一条件不满足即停止,OCR 层没有点击接口。

单次订单提交与回读(T-218)

local READY + backend READY + valid lease
 -> revalidate confirmation/address/manual-payment boundary
 -> idempotent backend submission fence (authorization becomes non-repeatable)
 -> persist encrypted CLICK_ASSUMED
 -> at most one exact "提交订单" accessibility action
 -> never click payment; navigate read-only to order list
 -> unique pending-order reconciliation
 -> RECONCILED or MANUAL_REVIEW, never a second submit

submission fence 是 exactly-once 安全边界,不是“点击成功”回执。服务端创建围栏后, 任何进程恢复都假定订单可能已创建;宁可留下需要人工对账的未提交意图,也不能通过 重按产生重复订单。一个 authorization 和 dry-run 在数据库中只能对应一个 submission。 只有同一次未中断调用中新建本地 intent 并收到后台 FENCED 响应时才短暂持有点击 资格;磁盘恢复出的 intent 只能重放后台请求并进入对账。围栏已经存在后,即使 claim 租约到期也只继续对账,不恢复商品操作或提交资格。

不可逆动作前再次核对 T-217 全部商品字段,并要求明确可见的已配置地址和唯一 “提交订单”节点。地址缺失、金额变化、自动扣款方式或“立即支付/确认支付/免密支付/ 先用后付”语义均阻塞。OCR 和 VLM 只能提供只读证据,不能决定或发出提交。

点击后只读检查有限数量的最近/待付款订单。归属必须由订单编号标签、平台下单时间、 待付款状态、标题、SKU、数量和金额共同唯一确定;零个或多个匹配转人工。订单号和时间 只进入 App 加密状态与鉴权后端,不进入普通日志或模型请求。T-219 读取该对账记录展示 待付款提醒,所有支付仍由采购人员在拼多多完成。

待付款提醒(T-219)

Admin 任务详情从同一 TaskDetail 聚合读取 v11 submission,不按浏览器传入的订单号 查询。FENCED、MANUAL_REVIEW 和 RECONCILED 分别映射为正在对账、人工对账和 待人工确认付款;只有最后一种展示订单号、平台时间、金额和对账证据。受控截图继续走 现有鉴权 evidence 路由,订单号不进入 URL。Roubao 从本地加密 submission 展示同一 待付款摘要,不增加支付导航。旧 SUCCEEDED 的“未提交订单”文案只有在不存在 reconciled submission 时保留。

人工理由使用版本化 allowlist。接受或拒绝至少有一个理由且指定主要理由; OTHER 才要求 4-200 字备注。拒绝推荐后改选必须同时产生一条原推荐项负标签和一条 替代项正标签;全部无匹配时每个曝光候选都有负标签。人工修正追加新 review 并引用 旧 review,不能覆盖历史。模型理由可以展示给人员参考,但不能自动成为人工理由。

六、API 和并发边界

  • 合约以 api.md 为准。
  • claim-next 必须由 usecase 调用 repository,在一个数据库事务内完成 “幂等检查 + 就绪/单活校验 + FIFO 选取/过期回收 + 更新 + 事件”。
  • 当前设备若有自己的过期 CLAIMED,优先原子回收该任务;没有时才在全局候选中 按 created_at ASC, id ASC 选择。该例外保持设备唯一归属并避免静默清理审计状态。
  • SQLite DSN 使用 _txlock=immediate、WAL 和 busy timeout;跨两个独立数据库连接 的并发测试必须精确得到一个领取者。
  • claim/start/release/cancel-ack 支持 Idempotency-Key;heartbeat 不需要幂等表。
  • App 对网络超时不能假定失败;必须用任务详情确认服务端最终状态。
  • 后端拒绝非法状态迁移,即使客户端 UI 隐藏了对应按钮。
  • App 参考图通过 task-scoped URL 读取;每次校验当前 user/device/generation/token/ 租约,不允许用可猜测 asset ID 越权读取其他任务。
  • SQLite MVP 使用单后端进程;切换多实例前先迁移 PostgreSQL 并验证领取竞争。
  • Gin handler 只做鉴权上下文、binding、调用 usecase 和响应映射。

七、自动化与安全边界

  • 只允许目标拼多多包处于前台时发送动作。
  • 关键动作前后都校验包名、页面特征和任务取消标志。
  • 节点选择要求可见、启用且唯一匹配;优先可访问性语义、稳定文本和受限祖先层级, 不能因资源 ID 重复而任取第一个节点。
  • 已验证的首页、搜索输入和结果页路径禁止坐标降级;新页面必须先取得版本化真机 证据并在独立任务中定义识别条件。
  • 候选 session 的候选尝试与滚动预算在动作发出前扣减,retry 不得重置;详情动作 白名单只有截图和返回。
  • 截图发送给模型前裁剪无关区域并按配置脱敏。
  • 每个动作记录抽象步骤,不默认记录完整输入文本。
  • 发现验证码、风险控制、支付、生物识别或系统权限页面立即停止。
  • T-217 及更早流程用代码级 allowlist 禁止“提交订单/支付”;T-218 只在服务端围栏和 CLICK_ASSUMED 持久化后开放一次精确“提交订单”,支付动作始终禁止,不能仅靠 提示词约束模型。
  • T-246 登录后使用单协程定时 heartbeat/claim/start;本机 VLM 配置完整时自动走 AI_ASSISTED,否则走确定性 MANUAL_FIRST。repository mutex 和既有幂等键保持 单 claim、单 execution、单探针。
  • 候选商品身份是 candidate_key + PINDUODUO goods_id + canonical URL。语义读取和 本地 OCR 只能提取唯一 ID,不得推测;后端不访问 PDD URL。
  • Admin 授权快照和 schema v2 设备命令都绑定商品 ID/URL 并纳入命令哈希。Roubao 使用 限定拼多多包名的 ACTION_VIEW 定向打开,复核商品 ID/标题后才允许选择规格和数量。
  • 后台已请求取消且租约过期的执行中任务由设备 heartbeat 事务原子转为 CANCELED, 同时结束 execution、释放设备并写 TASK_CANCELED 审计事件;不会重新排队执行。

八、错误分类

错误码前缀 示例 处理
DEVICE_ 权限缺失、拼多多未安装 修复设备后再领取
AUTH_ 登录失效、设备禁用 停止并重新认证
TASK_ 租约失效、状态冲突 刷新服务端状态
AI_ 超时、输出无效、低置信度 有界重试或转人工
PDD_ 未知页面、验证码、风控 立即停止,不绕过
NETWORK_ API 超时、上传失败 保留本地证据,幂等重试
SAFETY_ 即将进入禁止动作 阻断并记录高优先级事件

九、开发顺序

  1. 接入 Android 基线并记录真实构建方式。
  2. 导入一条脱敏蝦皮样本,以固定搜索词跑通拼多多页面探针。
  3. 接入需求提取和候选判断,验证结构化输出。
  4. 建立后端数据模型、API 和简单管理 Web。
  5. 接入 App 领取、租约、进度和结果。
  6. 20 条真实任务试验;根据数据决定是否进入 V2。

十、关键风险

风险 影响 应对
拼多多 UI/风控变化 自动化失败或账号受限 有界步骤、版本基线、未知即停、人工接管
VLM 误判 候选不匹配或违反预算 schema + 硬约束复核 + 人工确认
Android 后台限制 任务中断 前台服务、心跳、恢复状态机
网络重复请求 重复领取或重复结果 幂等键、版本号、事务和状态查询
图片/截图隐私 数据泄露 鉴权存储、脱敏、保留期限、密钥后端化
需求膨胀 跳过核心可行性验证 严格按 Phase 和 P0 范围执行