Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTDbDcwbDw1TSAcE6wfh2F
116 KiB
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Business-Rules-and-Glossary wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Business-Rules-and-Glossary.- wiki_revision: 7bb3997cfbe96343f63d4f6ef80201146c27c142 synchronized_at: 2026-09-22T02:56:27Z
业务规则与术语
当前范围
当前已实施范围包含 PDD 商品最新档案与采集闭环、虾皮商品档案、SYB 商品与后台导入、采购任务服务、Admin 采购任务与人工处理页面、Android 采购演练,以及 #36 的正式地址后缀与创建待付款订单能力。#36 尚未获得真机创建订单授权和验收;物流采集与自动回填仍由独立工单推进。
PDD 商品
- PDD URL 由管理员人工录入。
- 服务端必须规范化 URL 并提取
goods_id;提取失败时拒绝保存。 goods_id唯一;相同goods_id再次添加时提示“商品已存在”。- 已存在商品允许修改当前 URL,但不自动改变已创建任务的 URL 快照。
- 最简创建只输入 URL,新商品状态为
pending;人工完整保存或首次成功采集后转为active,人工可设为disabled。 - 商品只保存标题、店铺、数字销量/评价和规格的最新值,不保存价格或字段变更历史。
specs_json使用通用多维结构,角色为color、size、other;只有颜色规格值保存非负整数分价格,规格值同时保存是否可选择。- 人工保存为完整覆盖。
completed采集结果全量覆盖;completed_partial只合并明确采集到的字段和规格,不删除原有缺失部分;failed不修改商品。 - 人工停用的商品不会被后续采集结果自动重新启用;假售罄、临时售罄和采集失败也不会自动停用商品。
虾皮商品
-
shopee_item_id全局唯一,仅在存活记录之间生效;软删除的记录不占用该唯一性,重新创建或 #41 重新导入均可成功。 -
pdd_product_id可为空,且不加唯一约束:一个虾皮商品最多关联一个 PDD 商品,但多个虾皮商品可以共用同一个 PDD 商品。 -
关联 PDD 商品时校验目标存在且非
disabled;不提供手工输入商品 ID 的入口,只能通过搜索选择。 -
参考售价
sale_price_cent为整数分,currency为 ISO 4217 代码;币种取系统配置默认值,不逐商品选择,缺省回退为TWD。 -
规格值来源分
import(SYB 导入,不可人工删除,只能清除映射)与manual(人工添加,可删除);导入与人工值按「维度 + 名称」合并,不重复创建。 -
映射来源分
manual(人工,允许创建时即为已确认)、exact_match(名称标准化后唯一一致)、ai_match(AI 建议)。通用SetMapping入口仍将exact_match与ai_match一律写为pending,必须人工确认后才生效;#188 的 SYB 商品页批量 AI 匹配与 #194 的 Admin 蝦皮商品详情一键匹配是两个独立例外。#188 的进入条件已由 #190 放开:只要蝦皮与 PDD 关联完整、PDD 当前为active且能给出可选颜色/尺码候选、并且已解析出至少一个目标颜色或尺码,即可进入批量匹配。解析状态(含parse_status=uncertain与failed)、PDD 含颜色尺码之外的可选规格、蝦皮档案中未找到目标颜色或尺码、缺少完整可售 SKU 组合证据,自 #190 起都不再阻断匹配;本项目为内部系统,由此产生的“以错误目标规格进行匹配并保存映射”的风险由人工承担。唯一确定性exact_match不调用外部 AI,可直接保存为confirmed;SYB 商品页批量ai_match只要 Provider 成功返回规格结果且理由非空、返回值属于当前可选候选即可直接持久化为confirmed,置信度仅记录供审计、不作为放行门槛。若当前 PDD 档案存在完整可售颜色+尺码 SKU 组合证据,结果还必须命中其中同一个组合;人工录入或外部导入导致组合证据缺失时不阻断保存或创建采购。无结果、已有组合证据中的无效组合或 Provider 异常不得改写现有映射。 -
颜色映射只能从关联 PDD 商品当前可选颜色中选择,不允许自由输入;未使用颜色优先显示,已被其他蝦皮颜色使用的颜色仍可选择并显示占用者,因此支持多对一。
-
Admin 蝦皮商品详情只保留一个“一键匹配颜色和尺码”入口。已确认且目标仍存在的映射保留;名称标准化后的唯一确定结果直接写为
exact_match + confirmed;其余只有在 AI 置信度达到服务端当前阈值、理由非空、返回值仍属于当前可选候选时才写为ai_match + confirmed。低置信度或无结果保持未匹配;Provider 失败、AI 未启用、关联或规格上下文变化时本次不写入。操作前有未保存的人工修改时禁用一键匹配;保存只改映射,不改蝦皮或 PDD 原始规格。 -
PDD 重新采集或更换关联后,目标规格仍存在则映射继续有效;目标规格消失时详情标记“已失效”,服务端拒绝保存不存在的目标,采购预检和创建也拒绝使用失效映射并提示重新选择。
-
批量软删除逐条校验引用(虾皮商品被 SYB 明细或采购任务引用时不可删除)并逐条返回结果;已删除商品默认不出现在列表,可筛选查看并恢复。
-
#257:蝦皮颜色与尺码建议/一键匹配先保留仍有效的已确认映射,再复用相同标准化比较:简体、空白、全半角与大小写统一。颜色标准化后仅命中一个当前可选 PDD 候选时,不调用 AI,建议标为 matched,一键匹配按既有流程保存 exact_match + confirmed;未命中或多个不同候选标准化后相同,仍走原 AI 与置信度/候选校验。只转换比较键,蝦皮/PDD 原规格名不改,映射目标保存 PDD 原始候选名称;不引入颜色同义词猜测、不自动重算历史映射。
SYB 商品明细
-
一行对应 SYB 一条明确的商品/颜色/尺码/数量明细;唯一键为「蝦皮订单号
code+ 来源明细id」组合,不是全局唯一 ID(未在多货运单样本中验证过全局唯一性)。 -
productSpec自由文本解析:按最后一个逗号切分为颜色/尺码 → 剥离【】备注 → 判断残留分隔符;解析状态分success/uncertain/failed,永不猜测原文中不存在的颜色或尺码。 -
采购放行不以 uncertain 单独阻断:success 与已提取出至少一个非空颜色或尺码的 uncertain 明细,都可继续进入规格匹配和采购预检;只有 failed 或颜色、尺码均为空的异常明细才要求人工处理。uncertain 状态与解析说明继续保留供审计,不会自动猜测规格。
-
只有
success状态的解析结果会合并进虾皮商品档案的规格值(来源标记import);uncertain/failed只停留在明细行上供人工复核,不污染共享档案。 -
金额单位按接口分别定义:
/am/stock/detail/listByStock的productPrice是十进制金额,与/am/stock/list的amtOrder(×100 整数)不是同一套换算,不可共用。 -
关联虾皮商品档案:命中存活记录直接关联;命中软删除记录则复活并保留原有人工映射;均不存在时创建最小档案。命中既有档案时只补写为空的参考图与售价,不覆盖人工修改过的标题、店铺和映射。
-
重新解析只读取已保存的原始 JSON,不请求 SYB 接口,永不改写
RawJSON;标记manuallyConfirmed的明细默认跳过重新解析,除非显式指定强制覆盖。 -
人工修正的颜色/尺码视为与解析成功同等可信,同样会合并进虾皮商品档案;标记为已人工确认。
-
Admin 商品列表的订单号筛选每行一个、去空去重后精确匹配,最多 100 个且单项最长 64 字符;店铺名称使用包含匹配。店铺、订单号与解析状态之间使用 AND,不再用该筛选框搜索蝦皮商品 ID 或商品标题。
-
SYB 商品数据本身不保存 PDD 订单号、快递单号、支付或有效订单状态;Admin 的采购任务创建入口位于 SYB 商品列表,任务事实仍写入独立采购域。
SYB 商品处理阶段
- SYB 商品页保留“解析状态”,另按 SYB、蝦皮、PDD、采集任务和采购任务的当前事实动态派生唯一“处理阶段”;不在
syb_product保存容易过期的阶段字段。 - 对采购人员展示的阶段固定为:待人工处理、未关联 PDD、PDD 待采集、PDD 采集中、PDD 采集失败、规格待匹配、可创建采购、已创建任务、采购成功、待人工核对。
- 主阶段优先级为:待人工核对 → 采购成功 → 已创建任务 → 待人工处理 → 未关联 PDD → PDD 待采集/采集中/采集失败 → 规格待匹配 → 可创建采购。每行只显示一个阶段和对应下一步。
- “待人工核对”表示订单结果不明确,必须先人工核查并禁止自动重试;“采购成功”表示已取得 PDD 订单号和下单时间,不代表已经支付。
- 一个 PDD 订单号只能属于一个采购任务,该唯一性在采购任务保存路径上全局强制(#241)。人工处理结果未知、取消及 lifecycle 保存路径撞号时返回
PURCHASE_ORDER_NUMBER_ALREADY_USED,提示订单号已属于哪个任务,由采购员人工核对,不静默覆盖原值。 - 不可逆边界之后的
order_created结果回传是上述规则的例外:此时 PDD 真单已创建,发现订单号已属于其他任务时不回滚、不判失败,而是把任务降级为order_result_unknown,冲突订单号以「读到订单号 X,但该号已属于任务 CG-yy」保存在任务与 attempt 的error_message,pdd_order_no留空以维持唯一性,保留下单时间与不可逆时间,进入既有人工处理结果未知通道。首要目标是保住「真单已存在」这一事实,不制造无记录的真实订单。 - Agent 可按收货地址后缀
_cg<任务号>批量回填订单号与下单时间(#241)。 - Agent 侧回填为人工触发的只读扫描(#242):入口在采购记录页搜索按钮右侧,输入天数(默认 2)后确认启动。天数口径为滚动 N×24 小时,基准是页面读到的下单时间。采集、采购、回填三者互斥,复用既有任务互斥锁并加原子防重入,忙碌时拒绝启动而不排队、不抢占。
- 回填扫描不假设订单列表有序:只有连续观察到至少 5 单且下单时间严格递减、期间无缺失时间时,才允许「超过指定时间即停止」;一旦出现时间回升或缺失,改为扫至内部上限并明确标记「未完整扫描」,不得把不完整结果显示为已扫完。内部上限用于限制设备占用,不作为用户可配置的门禁。
- 回填扫描全程只读:确认收货、申请退款、催发货、去支付、立即支付、提交订单、付款、退款、取消订单、再次购买、删除订单永久排除为点击目标;点击目标必须自身可点、子树不含上述词,且不与任何含上述词的可见控件几何重叠;不得按固定坐标盲点。遇登录、验证码或风控立即停止并报告。
- 解析不出规范后缀的订单一律跳过,其订单数据不缓存、不上传、不入日志;上传载荷只含后缀、订单号、可选下单时间,以及 #306 的可选实付金额。本地缓存只采纳服务端确认的事实,并区分页面读到的真实时间与
irreversible_at回落估算值。后缀只承载任务号,请求不含地址全文或收件人信息;只允许回填该设备自己的正式采购任务;页面下单时间优先,缺失时回落该任务的irreversible_at并标记时间来源,两者皆空则该条失败。 - 已失败、已取消或演练完成的旧采购任务不单独占用主阶段;当前数据仍满足条件时恢复显示“可创建采购”,旧任务继续在采购管理留痕和按既有规则处理。
- 未选择处理阶段时,商品列表仍先返回,当前页阶段和采购准备继续异步批量读取且不调用 AI Provider;选择阶段筛选时,服务端必须先对完整查询结果派生并筛选阶段,再计算总数和分页,不能只过滤当前页。
SYB 店铺过滤
syb_shop保存允许导入的 SYB 店铺;店铺名比较前统一去除首尾空白、转换全角/半角字符并忽略大小写。规范化后同名的店铺只能保留一条有效记录。- 版本迁移会对历史存活店铺回填
normalized_name = Normalize(display_name);回填只改匹配键且可重复执行。若两个存活店铺回填后会得到同一键,迁移必须整体失败并保留原数据,管理员先人工消除歧义后再执行,不能静默合并、删除或改变店铺启用状态。 - 店铺可以从 SYB 真实货运单列表发现,也允许管理员手工补充。只有管理员可以新增、改名、启停和软删除,采购员等其他角色只读。
- 没有任何启用店铺时,导入必须在读取凭据、建立会话、验证码 OCR 和任意 SYB 网络请求之前失败,并给出“请先启用店铺”的可读提示。
- 同步先预检全范围总数及上限,每页校验原始列表条数、合法 ID 和重复,再按冻结店铺快照获取明细并页事务保存;整日结束核对总数。过滤不能降低完整性校验范围,已保存不能冒充整日完整(#239,c6a962d,已于 2026-09-08 随
d403f3b部署线上)。 - 只有列表与明细响应的店铺名都非空且命中启用快照时才允许写入。明细店铺名为空、变化为未启用店铺或无法匹配时跳过,并计入跳过数量。
- 停用或软删除店铺只影响后续导入,不删除历史 SYB 商品、虾皮商品或任务数据。已有错误导入数据的清理必须先给出精确 SQL 和影响行数,再由用户单独确认。
SYB 后台导入记录
- 导入允许管理员和采购员(purchaser)创建,创建成功后立即转入后台执行;页面关闭不取消任务。其他已登录角色只能查看同步记录,不能开始导入(#236)。
- 系统同一时刻只运行一个 SYB 导入任务。
syb_sync_run的唯一执行槽负责跨进程互斥,内存锁减少同一进程内的竞争;服务重启后遗留的执行中记录标记为“已中断”。 - 导入失败或中断时保留已写入商品,记录明确的失败原因和已处理进度;重新导入相同范围按「订单号 + 明细 ID」覆盖,不产生重复商品。
- 创建同步记录时冻结本次启用店铺的规范化匹配集合、展示名称快照及 SHA-256 哈希;后台执行必须只使用这一份快照,不得在开始后重新读取
syb_shop。同步详情保存并返回快照可用标记、快照店铺名称、哈希及各店铺“已导入/已跳过”数量。#212 之前的历史记录只有哈希和统计,明确标记为无完整快照。上述记录不保存账号、密码、Cookie、Token、验证码图片或 SYB 原始响应。 - 后台任务创建前的内部失败仍向普通用户显示“服务端处理失败”,但使用稳定错误码区分阶段:店铺预检为
SYNC_SHOP_PREFLIGHT_FAILED,同步记录创建为SYNC_RUN_CREATE_FAILED。服务端只记录阶段和经过脱敏、截断的底层原因,不记录请求体、凭据、Cookie、Token、验证码或原始响应。
采集规则
-
规则创建后立即可用,不存在草稿、发布、版本或停用流程。
-
规则允许编辑;新任务读取编辑后的当前内容。
-
创建任务时保存完整
rule_snapshot;规则编辑不影响正在执行的当前 attempt。人工重新采集会归档旧 attempt,并按来源刷新规则:Admin 来源读取原rule_id的当前存活内容,Agent 当前页来源读取当前手动采集默认规则;规则已删除、不可用或设备能力不兼容时拒绝重采且不修改原任务。 -
删除采用软删除;删除后不能创建新任务,但已有任务继续执行自身快照。
-
商品详情步骤应声明精确
activityName,并与包名和唯一控件共同作为页面证据;进入 PDD 登录 Activity 必须返回PDD_LOGIN_REQUIRED,不能提交采集成功。 -
唯一文字节点不可点击时,Agent 只可点击其最近的可点击父容器;不得改点兄弟节点或相似文字。
-
商品页规格入口只接受带明确选择语义的规格摘要,或底部真实“购买/拼单”文字按钮。若“请选择”和颜色/尺码语义分散在同一可点击父容器的子节点中,也只能在该容器唯一、位于非底部动作区且同时具备两类语义时作为规格入口;规则别名只能收窄已识别的安全候选,不能按页面原始文字扩张。底部购买入口在通过全部安全过滤后仍存在多个候选时,按最右优先(
centerX降序,并列时可点击面积升序)确定性选出唯一入口,不再因候选不唯一直接失败;该情形记为bottom_purchase_rightmost,唯一候选仍记为bottom_purchase。“单独购买”与“发起拼单”打开同一规格面板,但对应不同成交形态与价格,最右优先是经人工确认的取舍。评价、评论、晒单、问答、订单、提交订单、支付和付款区域及其父容器一律排除。商品评价页与详情页共用 Activity 时,首次误触只允许安全返回并重新定位一次,重复误触明确失败;点击无变化、误入评价页和面板结构无法确认使用不同错误码。 -
v2 规则使用类型化动作和固定阶段钩子。已由 Agent 支持的选择器、别名、超时、滑动方向和有限次数可以只更新规则;新增动作类型或页面算法才需要升级 Agent。
-
v2 任务首次未进入精确商品详情页时,可以按规则显式重开同一浏览器 URL 一次;登录、验证码、风控、无效链接和详情页内采集失败不触发该恢复。
-
假售罄恢复只使用主商品规格/购买强证据判断页面是否正常;顶部“相似商品”可以作为受控兜底证据,推荐卡片的标题、价格和销量不得冒充主商品证据。
-
商品规格遍历必须用已识别规格节点锁定横向颜色容器和纵向面板容器;颜色按视觉行蛇形遍历,滑动完成后重新读取节点,尺码只读并允许在标题滚出后沿已锁定容器续页。
-
PDD 已选规格的订单确认形态只可由详情页、选择摘要、唯一数量控件、支付区、唯一底部提交动作和唯一主要滚动容器的组合证据确认;底部提交动作只读且永久禁止点击。Agent 只在该已确认容器内最多三次向下拖动回顶,每次重新读取节点;“参考分类”作为尺码的精确标题别名处理。
-
PDD 完整规格选择器若无主滚动容器且尚未选择规格而没有已选摘要,仍可识别为非滚动规格面板,但必须同时出现至少两个已解析维度、至少两个可选项、唯一数量控件和唯一底部订单动作;缺少其中任一强证据时保持未识别。该订单动作仍仅作页面证据,永久禁止点击。
-
Agent 可扩展,但规则必须按任务类型授权:采集规则不能创建订单,采购规则只能使用独立审核的创建订单能力。当前项目不实现支付动作、入口或测试;支付、下单和订单相关文字可以作为只读页面证据配置,但不得成为点击目标。后续支付能力必须单独评估并至少具备显式能力位、服务端开关、单笔金额上限和人工授权。
-
#256(Android 0.9.73,实现 43703e0):采集执行器可识别无“已选/请选择”摘要且当前仅一个规格标题的滚动规格面板。必须匹配 PDD 包名、任务详情 Activity 与选择器,无登录/验证等异常,并同时具备唯一有界规格滚动区域、唯一标题及非空候选、关闭、唯一数量输入/增减、支付区和唯一下方提交订单只读动作;缺失任一证据仍拒绝。此分支只由采集上下文启用,不生成虚假选中摘要,采购与其他解析调用维持原条件。订单动作仍仅作只读证据,采集绝不点击。
采集任务
- 任务与结果共用
collection_task主表,不建立独立collection_result主表。 - 创建任务时固化
url_snapshot、goods_id_snapshot和rule_snapshot。 - 设备默认人工指定;未指定时由在线空闲设备原子领取。
- 一台设备同时只执行一个任务。
- 同一 PDD 商品不能同时存在多个
pending或running任务。 - 手机离线时运行中任务失败;默认不自动重试、不自动换机。
- 所有
failed任务,无论由 Admin 还是 Agent 当前页创建,都允许采购员人工“重新采集”;必须复用原collection_task.id,不得为同一次重采新建任务。Admin 来源继续允许重置completed、completed_partial,Agent 当前页来源只允许失败后重采;running禁止重置和删除。 collection_task.attempt_number表示当前执行次数。重采事务先把旧终态执行归档到collection_task_attempt,保留当次来源、设备、规则 ID/快照、终态、结构化错误、结果摘要与时间,再递增 attempt、清理主表当前错误/结果/租约并恢复为pending;不保存原始控件树、截图、Token 或个人数据。- 重采使用最新有效规则:Admin 来源刷新原规则当前内容,Agent 当前页来源刷新当前手动采集默认规则。全部资格、规则、设备、商品冲突和幂等检查必须在事务写入前通过;相同
requestId重放不得重复归档或递增。 - Agent 当前页任务在身份识别前失败时,下一 attempt 允许首次绑定商品;已经绑定商品时必须重新识别为相同 goods_id,不同商品明确失败且不得覆盖原身份。当前页发起重采前仍要求无障碍就绪、最近 PDD 前台证据、设备在线空闲及本地冷却通过。
- 任务自身结果仍只在任务详情查看;任务完成后会按完整/部分完成规则更新 PDD 商品最新档案,商品页不替代任务结果审计。
- PDD 商品列表批量操作只选择当前页,最多 100 个商品;每个商品仍创建一个独立采集任务。
- 已停用、没有可用采集规则或已有
pending/running任务的商品不能勾选,并显示普通人可理解的原因。 - 一批商品统一选择一个规则和一个可选设备;设备留空时仍由空闲设备领取。服务端提交时逐商品重新校验。
- 批量创建按商品分别执行现有单任务事务,允许部分成功;失败项返回稳定错误码和可读原因,不回滚已成功任务。
- 批次
requestId为每个商品派生稳定的创建请求标识,同一批次重放不会重复创建任务。 - 批量采集不创建采购任务、PDD 订单或支付动作。
采集字段
- PDD 标题、店铺名、销量、评价数量。
- 通用规格维度和值,当前重点是颜色和尺码。
- 采集时按颜色读取价格;同一颜色下不同尺码默认价格相同。
- 逐颜色价格只在精确点击后取得目标选中、已选摘要或规格面板变化证据,并等待候选价格连续稳定后保存;其他颜色残留的选中标记不能阻塞当前颜色。点击无效果时不能沿用旧价格,相同价格允许保存;无法确认选择、找不到价格和价格不稳定只记录结构化原因并按缺失价格提交。
- 存储时展开 SKU 组合,将颜色价格复制到该颜色各尺码 SKU。
- SKU 不完整仍提交已有结果并标记
completed_partial。
采购任务契约
- 采购域使用独立的
purchase_task、purchase_task_attempt和可选pdd_account引用;PDD、虾皮和 SYB 商品表不保存采购订单、支付、物流或回填字段。 purchase_task.task_type区分syb_order与stock。旧任务迁移为syb_order;备货任务只引用已完成采集且处于active的 PDD 商品,颜色/尺码必须逐字命中当前可选规格,规格来源固定为direct_select,SYB/虾皮身份快照为空。- 备货任务不占用 SYB 活动槽,同一 PDD 商品可存在多个待执行备货任务,但设备、可选账号和执行期互斥仍沿用采购安全边界。备货任务不参与商品替换、批量重试、重新采购授权或 SYB 回填;失败后由人员重新创建备货任务。
- Admin 在处于
active且具有当前可选颜色价格(有尺码维度时还须有可选尺码)的 PDD 商品详情创建备货任务;颜色、尺码只能从最新采集档案选择,不允许自由输入,颜色切换后按已采集价格更新默认上下限。采购管理列表和详情用“订单采购 / 备货采购”区分类型;备货任务的 SYB/虾皮字段显示为空、失败任务不提供重试,并明确提示“备货采购不参与库存扣减与订单关联。” - 正式任务必须引用一条 SYB 商品明细;演练任务可以从 PDD 商品人工创建且不引用 SYB。
- 创建时固化三个商品身份、蝦皮订单号、目标和映射规格、数量、价格区间、币种、URL、
goods_id、规则、设备和可选账号引用。商品档案后续修改不改变任务解释。正式任务的蝦皮订单号来自 SYB 商品order_code,同一订单号可以对应多条商品和多个采购任务,不作为唯一键。 - Android 无法可靠识别登录中的 PDD 账号,因此账号引用可空;已知账号才参与账号级串行,未知账号不会阻止采购任务。
- 同一 SYB 明细可以保留多个历史采购任务,但最多只能有一个活动任务。重新采购新建任务,旧订单不删除、不覆盖。
execution_mode创建后不可变:rehearsal只能完成商品、规格、数量和价格复核;live才可能获得改地址和创建订单能力。任何模式都不支持可执行支付动作;规则中的支付相关文字只可作为只读识别信号。- 演练规则在服务端契约层拒绝改地址、创建订单和核单动作;正式动作还必须通过版本化能力协商。规则只包含类型化动作,禁止任意脚本。
- 价格保护保存参考单价、最低单价、最高单价和币种,执行时以 PDD App 实际单价判断;价格越界明确失败,不考虑优惠券。
- Admin 从 SYB 当前页选择商品,可在“创建采购”和“重新解析”两种批量用途间切换;采购模式只允许选择预检合格行,表头全选不跨页。批量预检和正式创建均最多 100 条并逐条重新校验,每条 SYB 明细只创建一个独立任务;部分失败不回滚其他成功项。
- SYB 商品列表在列表数据返回后立即展示,采购准备状态独立异步加载;只读批量预检只执行批量数据库读取和本地确定性识别,禁止调用 AI Provider。自 #215 起,未保存或已失效的长期规格映射不再阻断创建采购;满足商品关联、PDD 状态、价格、规则、设备和订单安全门禁后即可创建任务,每个新 SYB 采购任务都在首个 attempt 以当次 PDD 页面候选重新决策。
- SYB 商品页的 PDD 采集资格独立于采购处理阶段:只要已关联的 PDD 商品未停用、没有
pending/running采集任务且存在可用采集规则,即可创建采集任务;因此已完成采集并进入“可创建采购”的商品也可以重新采集。相同 PDD 商品在批量创建前按商品去重,服务端创建时仍按最新状态复核。 - 批量创建读取管理员选定的当前采购规则并重新执行契约校验,每条任务保存不可变快照;当前规则缺失或无效时明确阻断,不回退到代码常量。设备默认人工指定,也可以留空由符合能力的空闲设备领取。
- 批量创建的价格保护来自 PDD 商品档案而不是 SYB/Shopee 的 TWD 售价:当前采购规则可用
priceGuard.minRatio(0.1~1.0)和maxRatio(1.0~3.0)配置比例,缺省仍为 0.2 / 1.5;最低价向下取整、最高价向上取整到人民币分。已确认颜色映射时按该颜色计算,待规格探测时以全部可用颜色的最低/最高价计算,参考价取最高价;没有可用颜色价格时不能创建。 - 地址后缀为
_cg{purchase_task.id}。精确规格、数量、价格和摘要核验通过后,若仍处于已识别的规格面板,Agent 只允许点击唯一、可见、启用、可点击且文案精确命中“确定/确认”别名的规格确认控件;不得点击提交订单、确认购买、付款、支付、地址修改或地址保存控件,也不使用中心手势兜底。点击后必须重新读取并确认已出现订单确认页或地址入口强证据,否则明确失败。进入订单确认页后,若收货地址被面板裁切,只允许在唯一、可见且占据主要宽度的纵向滚动容器内有限向下拉动来显示地址,禁止按页面最大滚动区域盲目滑动。Agent 只在唯一地址入口、唯一修改按钮和唯一详细地址输入框均成立时修改;脱敏手机号文字本身不可点击时,仍以该唯一文字节点的中心坐标执行一次精确手势点击,不沿用可能覆盖整个下单面板的可点击祖先。“修改”“保存”和“提交订单”等文字节点即使依赖可点击父节点,也必须保留原始文字节点作为每次重新定位的锚点,父节点只用于验证存在可点击路径。近乎完全重叠的无障碍重复节点按一个目标处理,仍有多个独立目标或页面切换超时则明确失败。按首个-或_截取地址主体后追加当前后缀,保存后必须回读完整新地址。修改或回读失败时禁止创建订单,地址全文和控件树不落库。 - 地址编辑页可以同时存在收货人、手机号和详细地址等多个输入框;Agent 只选择与“详细地址”标签纵向重叠且位于其右侧的唯一输入框,不能用页面输入框总数或顺序猜测。
- 点击创建订单前,Agent 必须先在本地事务保存
order_submit_started、不可逆时间、稳定请求 ID 和不含地址全文的最终确认快照,再用同一请求 ID通知服务端;两侧成功后才允许精确点击唯一创建订单按钮一次。 - 进入不可逆边界后,进程重启、断网、点击结果不明或无法取得唯一订单号/下单时间时只允许只读核单并进入
order_result_unknown,禁止再次点击;任务与订单正式关联仍以完整 PDD 订单号为准。 - 创建订单后出现 Android 多微信应用选择器时,Agent 只有在系统包和
ChooserActivity/ResolverActivity白名单、已知选择器标题、微信候选三类证据同时成立时,才允许按一次返回,绝不点击微信候选。若已进入真实微信包com.tencent.mm,Agent 不点击、不输入、不登录、不支付、不强制停止微信,只允许用一次无参数 PDD 启动 Intent 把既有 PDD 任务栈拉回前台;第二次仍见微信或拉起失败即保持结果未知。回到 PDD 已知支付 Activity 或明确支付动作页面后最多再返回一次,再只读读取唯一订单号和下单时间;下单成功页仅可点击唯一、精确的“查看订单”或“订单详情”入口一次,进入 PDD 订单详情后才允许有限向上手势下翻读取折叠内容。PDD 页面出现“待付款”“待支付”“订单编号”或“下单时间”等订单结果信号时,该只读信号优先于复用的支付 Activity 名称:允许在唯一主要纵向容器内有限下翻并重新读取,仍不得点击支付;没有任何订单结果信号的支付页或未知页面不得盲目滑动。入口缺失或不唯一、点击后未出现详情证据、任一页面不在白名单、恢复动作重复或结果不唯一时保持order_result_unknown,禁止重下单或支付。 - Agent 本地 SQLite/Outbox 负责断网和重启恢复,服务端以
task_id + task_attempt_id幂等接收并保存最终事实。 - 人工支付复核只记录
paid/unpaid;系统不执行或识别支付。快递单号与回填状态属于采购任务,后续物流工单实现。 - 采购任务领取时同时占用设备租约和可选 PDD 账号租约;租约过期后才可释放并重新领取。设备还存在采集任务时不能领取采购任务。
- 自 #215 起,每个新 SYB 采购任务无论是否存在已确认长期映射,都先由 Agent 在当次 PDD 规格面板内有界遍历颜色和尺码并回传原始候选。服务端只以任务冻结的 SYB 目标规格与当次候选先做唯一确定性匹配(繁体转简体、空格/全半角/大小写统一,以及公斤/斤换算),仍无唯一结果才调用已启用的服务端 AI。AI 必须逐字返回当次候选集中的原始标签;候选不完整、集合外返回、歧义、AI 无结果或服务不可用均明确失败,不派发第二趟、更不创建订单。
- Agent 选择服务端下发的精确颜色或尺码时,只能在已确认打开的规格面板内有限纵向滑动、每次重新读取可选节点并按完整原始文字点击;连续没有新证据或达到上限即停止,不得点击相近规格。第一趟探测并固化规格后,第二趟仍无法精确选择而再次提交探测时,服务端必须明确失败并释放活动槽,保留第一次决策证据,禁止清空决策、循环派发或进入地址与创建订单动作。
- 采购 Agent 在确认进入 PDD 商品页后、打开规格前,复用采集侧的假售罄识别;规格面板已打开且当前解析到的规格值全部不可选时也按售罄处理。两种情况都只允许关闭规格面板后对商品页执行一次有界恢复(默认下拉 2 次、间隔 1000 毫秒、等待 2000 毫秒),恢复动作失败或恢复后仍售罄时返回
PDD_GOODS_SOLD_OUT,恢复后商品页证据丢失时按页面规则不匹配失败;不得继续选择规格、修改地址或创建订单。该失败码继续进入既有替代商品资格判定。 - 所有新 SYB 采购任务的规则都必须具有
purchase.spec-probe.v1;创建时任务级mappedColor/mappedSize为空且spec_source=unresolved,长期映射和 PDD 档案候选都不能跳过首趟探测。第一趟只探测规格并释放租约,服务端固化同一 attempt 的决策后才派发第二趟;探测阶段从服务端拒绝进入order_submit_started。Android 不自行匹配或猜测,只在第二趟接收并精确选择服务端固化的当次 PDD 原始标签。 - Agent 提交的相同 attempt 最终结果只能写入一次;相同请求重放返回原事实,不同内容拒绝覆盖。
order_result_unknown不参与自动派发,只能人工解除。 - 已创建订单默认禁止再次采购;管理员或采购员可以做一次性重新采购授权,新任务创建成功时在同一事务消耗授权,旧任务和旧订单保留。已标记为已支付的订单不能授权或创建重新采购任务。
- 人工回填候选只允许从已支付订单选择;同一 SYB 明细后来选择的订单覆盖旧候选,但不删除旧订单事实。
- Admin 采购管理只查看和处理已有任务,不提供创建入口或支付按钮;单条和批量采购任务都从 SYB 商品列表发起。订单结果未知时必须先人工核对并解除;处于该状态时页面不提供重新采购授权。
- 采购失败任务可在采购管理当前页批量勾选重试,最多 100 条。重试不修改旧任务,而是用当前 SYB/PDD 档案、目标规格、当前价格保护和当前采购规则创建新的
pending任务,并生成新任务编号与地址后缀;来源蝦皮订单号沿用失败任务的不可变快照。新任务不复用旧任务或长期档案的执行规格,仍必须先完成当次真机规格探测。 - 只有正式采购、未进入不可逆边界、没有订单号或下单时间、且仍是同一 SYB 最新记录的
failed任务可重试。原设备离线、停用、忙碌或能力不足时该项失败且不自动换机;未指定设备时仍由空闲设备领取。 - 批量重试逐项处理并允许部分成功;同一请求幂等重放不会重复创建。失败任务不再使用一次性重新采购授权,该授权只保留给已经创建过订单且满足条件的任务。
管理端角色与权限
- 管理端固定支持
admin(管理员)和purchaser(采购员)两类业务角色;用户必须绑定一个存在且启用的角色,role_id=0或停用角色不能创建或保存。 - 采购员可读取设备状态,维护 PDD/虾皮商品和规格映射,查看与修正 SYB 商品,读取 SYB 店铺及同步记录,读取采集规则,创建/重置/删除采集任务,并创建、查看、重试及人工处理采购任务。
- 仅管理员可管理用户、角色、菜单、接口、部门和岗位;停用设备或吊销 Device Token;新增、改名、启停、删除或发现 SYB 店铺;新增、编辑或删除采集规则;保存或测试 AI Provider 配置。
- AI 规格匹配菜单对采购员硬排除:采购员不显示该菜单,角色配置也不能为采购员选中该模块;既有 API 权限不变,仍只允许读取是否启用,不得读取 Provider 地址、模型、API Key,也不得保存或测试。
- GoAuto 菜单由代码维护的模块定义幂等写入系统菜单和菜单/API 关联;迁移只为采购员追加首次引入且默认开放的模块,不会把采购员人工取消勾选的既有模块重新加回。
- 采购员 Casbin API 白名单由代码权限矩阵全量重建,不从角色菜单勾选反推;减少权限时旧策略必须删除。菜单勾选只控制可见模块,不能扩大采购员 API 权限。
- GoAuto 管理接口使用 Casbin 按 HTTP 方法和路径授权;设备凭据、规则和外部服务配置等高风险写操作另有管理员角色守卫,前端隐藏入口不能替代服务端授权。
- 管理员继续使用
admin旁路;采购员必须由明确的purchaser策略授权,不得通过赋予管理员角色临时解决登录或权限问题。 - 任何角色都不得执行自动支付。
自动化边界
- 浏览器“打开拼多多APP”和系统确认框“打开”属于允许动作。
- 登录失效、验证码、风控、人机验证和找不到唯一控件时失败并给出具体错误。
- Android Agent 到 GoAuto 服务端默认使用 HTTPS。管理员可在明确接受 Device Token、任务内容、设备状态和执行结果被链路监听或篡改的风险后,通过服务端
GOAUTO_ALLOW_INSECURE_AGENT_HTTP=true显式允许全部/api/agent/v1/**使用 HTTP;该例外不放宽 PDD、SYB、OCR 或其他第三方服务约束。 - Android Agent 端不使用 OCR/VLM 兜底,不保存原始控件树或截图。采集阶段不猜测缺失数据。
- 服务端顺云宝(SYB)登录例外:允许调用配置的线上 OCR 服务识别登录验证码(见 #48)。验证码图片会离开本项目发送到该服务,更换服务地址前必须重新评估。此例外只适用于 SYB 登录,不扩大到 Agent 端或任何 PDD 相关流程。
- 采购阶段的规格匹配由服务端决策(见 #46、#62):Agent 本地不得自行猜测规格或点击相近候选,只执行服务端下发的精确规格;AI Provider 只有一个 OpenAI-compatible 配置,由管理员维护。根据 #62 已确认的内部部署例外,API Key 明文保存在专用设置表,并只向管理员设置接口返回以便查看和替换;它仍不得写入代码、日志、工单、Wiki、任务快照、采购员接口或 Android 接口。Provider Base URL 不限制内网或公网,支持 HTTP/HTTPS;HTTP 不加密传输中的 API Key,生产环境建议 HTTPS。
- 采购规则的
openSpecPanel默认不写死页面文字。Agent 只在已由页面语义确认的规格入口或底部购买入口中选择;规则若提供textAliases,只能进一步缩小这些安全候选,不能把任意同名页面文字变成可点击入口。 - 采购规则的
probeSpecs.dimensionAliases是只读规格维度标题的服务端下发事实源;颜色别名可由管理员增加“组合”等 PDD 页面文案,尺码别名单独维护。该字段只影响探测和 AI 匹配输入,不能改变selectSpec的精确点击目标;旧任务快照缺省时才使用 Agent 内置兼容值。 - PDD 采集规则的
collector.textAliases是规格面板、维度标题、选择摘要、评价入口、售罄主商品证据和购买入口等只读识别文案的服务端下发事实源;缺省字段只为旧快照兼容使用 Agent 内置默认值。颜色/尺码分类不得再用代码字面量扩大dimensionAliases。订单和支付文字可以参与只读页面判定,但 Agent 内不可配置的创建订单/确认订单/支付/付款点击拒绝清单始终优先,规则不能放宽;修改地址和收货地址在只读及点击字段中都禁止。 - PDD 颜色采集对首屏已识别为多行或网格的颜色区执行动态行发现:每次动作后重新解析全部可见行,单列不做无效横向滑动,并复用规则中的
specVerticalSwipes与stableEdgeReads有界纵向翻页;颜色结束后规格面板归顶,再进入尺码发现。选项重排或已选项从无障碍节点消失时,不得静默跳过仍未尝试的可用颜色。 - 正式采购规则可以调用独立审核的改地址、创建待付款订单和只读核单动作;采集规则和演练规则不能调用。真机首次安装或验证仍需独立人工授权。
- 系统当前不提供自动支付、实时屏幕或管理端远程控制。付款、免密支付及任何等价动作不能配置为点击目标;只读识别字段可以包含支付或订单文字。后续若新增支付能力,必须由独立工单和显式控制重新评估。
设备身份与认证
- Android Agent 首次安装生成唯一
install_id;服务端收到合法设备信息即注册或更新设备,不使用硬件标识作为唯一键。 install_id在设备表中唯一,不存在注册码、注册申请或设备审核记录。- Device Token 明文只返回给客户端,服务端数据库只保存不可逆摘要。
- 设备状态只保存在线、离线或停用;是否忙碌由运行中的任务关系确定。
- Agent 默认每 15 秒心跳一次,45 秒没有心跳即离线;离线扫描每 15 秒执行。
- 心跳上报的
currentTaskId必须与服务端该设备唯一运行任务一致;采集任务和采购任务共用这一设备级忙碌事实,异常出现跨域同时运行时按服务端一致性错误处理。 - 设备超时离线时,运行中的采集任务和尚未提交订单的采购任务立即以
DEVICE_OFFLINE失败,清除租约及运行槽且不自动重试;采购 attempt 同步结束并标为失败。 - 采购任务已进入
order_submit_started后设备离线时,任务转为order_result_unknown并释放设备/账号运行槽,必须人工核对,禁止自动重派或再次点击创建订单。
术语
| 术语 | 含义 |
|---|---|
| 规则快照 | 创建任务时复制到任务中的完整规则内容 |
| URL 快照 | 创建任务时复制到任务中的 PDD URL 和 goods_id |
| 空闲领取 | 未指定设备的待执行任务由在线且无活动任务的设备原子领取 |
| 部分完成 | 结果已提交,但一个或多个规格/SKU 缺失 |
| 重置任务 | 保留任务输入快照,清除原结果后重新进入待执行状态 |
| Portal/Agent | Android 端注册、保活、执行规则和提交结果的程序 |
| 虾皮 | Shopee 的中文展示名。管理端界面一律用「虾皮」,数据库表名、字段名、API 路径等程序标识符保持 shopee_product(单数)/ shopee_item_id 不变 |
| SYB | 顺云宝 ERP(ShunYunBao,域名 shunyunbaoerp.com),虾皮订单与货运单的外部来源系统。管理端界面一律用「SYB」,不再使用「货运宝」「顺云宝」等别名;数据库表名与字段保持 syb_products |
| 货运单 | SYB 中的一张单据(code,如 260728TB95MJTQ),下挂一条或多条商品明细。与系统名「SYB」区分,不可混用 |
| AI 规格匹配 | 人工映射后仍无法以确定性标准化唯一匹配时,服务端才调用单一 OpenAI-compatible Provider,把虾皮目标颜色尺码匹配到 PDD 实际可选规格;结果必须是候选原始标签,无结果、歧义或 Provider 不可用即失败 |
| 快路径 / 慢路径 | 采购执行的两种路径:Agent 能直接定位到下发的目标规格为快路径;定位不到则触发全量遍历采集并重新匹配,为慢路径 |
| 两趟执行 | 慢路径的实现方式:第一趟采集规格后结束并释放设备,服务端离线匹配,第二趟重新派发下单,复用 task_attempt 机制 |
| 采购探测 | 采购时对 PDD 商品页的实时规格采集,同时作为一次商品信息更新写回档案,按 completed / completed_partial 语义处理 |
| spec_source | 采购任务的规格来源标记:manual_mapping / exact_match / ai_match,用于事后批量追溯 |
SYB 自动同步
- 服务端内置 go-admin 定时任务“SYB 每小时自动同步”,默认每小时第 5 分钟执行;同步日期按 Asia/Shanghai 计算,覆盖当天和前一天。
- 定时同步与保留的手动导入 API 共用同一个导入服务和
syb_sync_run记录;定时任务的操作人显示为“系统定时同步”。 - 同一时刻只允许一个 SYB 同步任务运行。上一次仍在运行时,本次定时触发直接跳过,不排队、不并发,也不立即重试;等待下一小时再次触发。
- 定时任务失败时明确记录失败原因,不自动重试。服务重启后由既有启动恢复逻辑处理遗留的运行中记录。
- 单次同步内部的 SYB 只读请求(货运单总数、列表和明细)遇到暂时网络故障、5xx 或异常响应时最多执行 3 次,分别退避 1 秒、2 秒,单次 HTTP 总超时 60 秒;这不等于失败任务自动重试。明确未登录、业务失败、数据完整性错误以及任何写操作均不自动重试。
- SYB 商品页不再提供“导入”和“同步记录”快捷按钮,也不查询、展示或轮询同步状态;后台同步成功、失败或中断均不在商品页弹出消息,商品数据由用户主动查询或刷新获取。
- 独立“SYB 同步记录”页面是同步结果的唯一 Web 展示位置,保留运行状态、进度、数量、失败原因和店铺统计;go-admin 定时任务中的
GoAutoSYBHourlySync提供“执行记录”入口。管理员和采购员可在同步记录页人工发起覆盖昨天和今天的同步,其他角色只读(#236);人工与定时同步共用导入服务、执行记录和互斥,不排队、不并发,也不立即重试。
cmautobuy 商品导入
- 这是人工触发的单向离线导入,不是持续双写或双库同步;不随服务启动执行。
- 来源只读取未软删除的 PDD、蝦皮商品及蝦皮 SKU;不导入 SYB、任务、订单、物流、设备、用户、规则和旧组合规格映射。
- 目标已有相同
goods_id或存活shopee_item_id时,按用户确认由来源商品档案覆盖;PDD 人工disabled状态保留,不能被导入自动启用。 - PDD 销量和评价、蝦皮参考售价在来源没有对应值时覆盖为空;蝦皮币种读取 GoAuto 系统设置,缺省 TWD。
- 同一颜色只有唯一有效价格时才保存颜色价格;出现多个价格时价格留空、PDD 商品保持
pending并报告,禁止取最低价、最高价或平均价。 - 蝦皮只聚合来源已解析的颜色和尺码,未解析内容不猜测。来源 PDD 关联不存在、已删除或无法转换时,蝦皮记录作为冲突跳过,不能静默关联其他商品。
- 默认 dry-run 不写数据库;
--apply前必须查看精确影响并再次人工确认。apply 在目标单事务中执行,提交前校验 JSON、唯一键和关联完整性。
Agent 当前设备历史
- Agent 只可查看当前 Device Token 对应设备最近 30 天的采集和采购任务,不能跨设备查看。
- 采集历史可以查看结构化采集结果和错误;采购历史可以查看结构化采购数据和错误。采购记录不提供取消订单、修改订单或支付入口;只有服务端明确标记可重试的当前设备失败任务,才提供受控“重试采购”。
- 历史接口遵循数据最小化:不下发 Device Token、规则快照、PDD URL、收货地址、原始控件树或截图。
- 实际采购单价只在 Agent 确实观察到时保存;旧任务或未观察到价格时显示“未记录”,不推算、不回填。
Agent 受控重新采集
- 当前设备可以从自身采集任务详情重新采集已完成、部分完成或失败任务。
Agent 受控重试采购
- 当前设备只可重试自身最近 30 天内、服务端标记
retryable=true的正式采购失败任务;列表和详情都只能发起单任务重试,不支持多选、批量或自动重试。 - 普通“重试采购”调用就地
/reset:复用原purchase_task.id,只新增 attempt;新 attempt 使用当前有效采购规则和最新版 Agent 代码,商品、目标规格、执行规格、数量、价格、地址及既有规格决策等业务快照保持不变。 - 就地重试不恢复已经消耗的真机规格探测资格;目标规格存在但对应执行规格为空时必须拒绝,不能进入正式采购阶段。需要按替代商品或已变化业务规格重新决策时,必须走明确的新任务流程。
- 已出现
order_submit_started证据,或存在不可逆时间、订单提交请求、PDD 订单号、下单时间的任务一律拒绝重试,并提示走既有“授权重新采购”流程,防止重复下单。 requestId按“任务 + 重置请求”幂等;相同请求重放返回同一 task ID 和 attempt,不重复递增。- Android 只在服务端
retryable=true且状态为failed时显示普通“重试采购”。确认和成功反馈必须说明复用原任务、新增一次执行、使用当前规则但业务快照不变、可能创建待付款订单且系统不会支付。 /reset不得把“目标规格存在但对应执行规格为空”的任务恢复到正式采购阶段;此类异常快照必须拒绝,并提示使用明确的新任务流程。- 替代商品匹配完成后的“继续采购”继续调用
AgentRetry → BatchRetry → Create,按当前档案创建不同 task ID;Admin 批量重试也保持新任务语义。取消订单、修改既有订单和支付仍禁止。真机重试可能进入创建待付款订单流程,执行前必须再次取得人工授权。
Agent 状态页手动检查任务
- Agent 保留既有每 15 秒自动检查。状态 Tab 顶部下拉只触发一次合并到现有调度器的立即检查,不新增轮询器、不改变采购优先和单设备串行。
- 当前任务执行中、无障碍未就绪、未配置服务端或设备身份异常时不领取新任务,并显示普通人可理解的恢复提示。
- 检查中合并重复请求;无任务、领取采集、领取采购、设备忙和网络失败都有文字反馈。网络失败后退出手动刷新状态,既有自动检查继续运行。
- 状态 Tab 只读显示无障碍状态;“打开无障碍设置”只保留在设置 Tab。
- 手动检查不创建、重置或重试任务,不修改任务资格,不打开 PDD、不修改地址、不创建订单、不支付。
Agent 任务记录刷新与同步
- 采集和采购 Tab 顶部下拉只刷新当前 Tab、当前筛选、当前编号搜索和当前页;不领取新任务,也不执行、重置、重新采集或重新采购。加载失败页必须保留可见重试入口,空列表也允许下拉。
- 设置页记录范围支持手动输入任意 1~30 天整数,默认 7 天、最大 30 天;空值、非整数或越界时不发起同步且就近提示。同步只读取当前 Device Token 对应设备的采集与采购摘要。
- 两类记录可以独立成功;界面必须明确显示同步完成、范围内无记录、部分完成或失败以及最近同步时间。
- 本地仅保存列表摘要和同步时间,详情仍按需读取;不缓存 Token、完整规则快照、PDD URL、地址、控件树或截图。
- 记录同步是服务端到 Agent 的单向只读能力,不打开 PDD、不修改地址、不创建订单、不支付。
Agent 采集任务间隔
- Agent 设置页提供设备本地“采集任务执行间隔”,起止值均只接受 0~600 秒整数,默认
15~15;每次在闭区间内等概率随机一个整数秒。0~0表示不等待,范围包含 0 时允许本次抽到 0。设置只影响之后结束的采集任务,已开始的间隔不随设置修改。 - 只有采集任务已经开始且成功向服务端提交完成、部分完成或失败结果后,Agent 才按当时保存的范围随机一次并开始间隔;领取前失败、配置/认证错误或结果未安全提交不随机也不开始间隔。采购任务结束不开始采集间隔。
- 间隔只阻止下一次采集任务的请求、领取和开始;心跳、采购任务优先领取与执行、采购 Outbox、历史刷新和同步继续运行。间隔结束只触发现有调度器一次,不新增轮询器。
- 状态页下拉检查和采集记录“重新采集”不得绕过间隔,统一提示“采集间隔中,还需 N 秒”。
- 本次抽中的秒数、开始时间和截止时间作为同一间隔票据持久保存在设备本地;Agent 进程或前台服务重启、设置修改都只恢复剩余时间,不重新随机。系统时间回拨时最多按该次已抽中的原始秒数截断,避免无限等待。
- 间隔期间保持屏幕常亮;既有“任务结束 5 秒后返回 Agent”是独立机制,返回 Agent 不清除采集间隔。采购任务接管执行时不重复持有间隔亮屏锁,采购完成后若间隔尚未结束则恢复。
- 该设置不上传服务端,不改变采集任务状态、租约、规则快照或服务端接口,不打开 PDD、不修改地址、不创建订单、不支付。
Agent 当前 PDD 商品页临时采集
- 操作员先人工在 PDD App 打开并停留在目标商品详情页,再从 Agent 采集 Tab 点击“采集”;该入口采集当前页面,不是重置历史任务。
- Agent 在请求服务端前取得采集/采购共用的本地互斥锁。服务端原子校验设备在线、空闲、跨域活动任务、默认规则和能力,创建固定当前设备且已进入
running的标准采集任务。 - Agent 启动当前页面采集前先保持自身在前台并启动既有前台服务。恢复时若 PDD 已在前台则不返回;若 Agent 仍在前台且近期见过 PDD,只尝试一次系统返回;仍未恢复时只使用 PDD 自身的不带参数启动 Intent 拉回现有任务,不附加清栈/重置标志。恢复后必须重新验证包名、精确 Activity 与页面强证据;不得启动浏览器、构造深链、自动搜索或自动选择相似商品。
- 恢复详情页后先按规则唯一点击“分享”与“复制链接”,只读取本次复制后的单条、有限长度剪贴板文本。Android 优先选择含 goods_id 的白名单长链;短链只在手机侧以无 Cookie、无项目凭据、逐跳白名单校验的有限请求展开,失败时可把原短链交给服务端兜底。服务端始终重新校验链接、裁决并规范化 goods_id;Agent 不建档、不猜测商品身份。原始剪贴板、分享文案、链接、响应正文、控件树和截图都不保存。
- goods_id 已存在时复用唯一 PDD 商品,成功或部分成功结果按既有最新档案覆盖规则更新;不存在时创建 PDD 商品。该流程不自动停用或替换旧商品,也不修改虾皮到 PDD 的关联。
- 管理员必须配置一条存活的 PDD 商品详情 v2 规则作为 Agent 手动采集默认规则;迁移只做一次安全初选,创建任务时仍实时验证规则与设备
collector.pdd.current-page-share.v1能力。 - 当前页面任务身份确认前允许
pdd_product_id为空、URL/goods_id 快照为空;普通管理端任务不放宽。身份确认后不可改成其他商品,结果 goods_id 必须与任务一致。 - 当前页面任务不能使用“重新采集”重置;失败后重新打开目标商品并新建任务。成功提交完成、部分完成或失败结果后,继续进入设备的采集任务执行间隔。
- 分享入口、复制链接、剪贴板、链接、页面或身份不唯一时明确失败并释放任务槽;不使用 OCR/VLM,不猜测商品身份。
- 该能力只采集商品资料;不创建采购任务、不选择采购规格、不修改地址、不创建订单,也不执行支付动作。
SYB 档口入库码导入、匹配与回写
- 只接受不超过 10 MB、最多 5000 条非空数据行且包含“标签入库码映射”工作表的 Excel。一次文件只能包含一个营业日期;同日单件入库码必须唯一,同一业务键按营业日期、订单号、档口和规范化规格合并并保留 Excel 顺序。
- 导入事务提交后自动创建并启动只读匹配任务,不提供独立“匹配”按钮。再次导入同日数据只允许整体替换仍处于等待匹配的数据;存在匹配或回写证据时拒绝覆盖。
- 匹配必须按精确订单号取得唯一货运单,再以规格、原始 SKU 和档口证据确定唯一商品;歧义、冲突或数量不一致均不猜测。匹配阶段不能调用任何 SYB 写接口。
- 回写前弹窗展示业务记录数、入库码总数、预计占位明细数和替换旧码数。只有
ready记录可提交;所有服务实例共用数据库租约全局串行执行。 - 每个远端写动作只发送一次,动作前重读整张货运单并校验匹配计划未漂移;每件写入后重读确认目标码唯一位于预期明细。超时、5xx、响应无法确认或服务在写入期间重启时转为
needs_check,禁止自动重试;“只读复核”只能读取远端状态。 - 列表支持勾选后批量物理删除。删除必须再次确认;选中项包含
queued、applying或needs_check时整批拒绝,不做部分删除。其余选中业务记录、逐件码、计划和终态执行证据在同一事务中物理删除;已写入 SYB 的远端值不会撤销。
PDD 失效或售罄商品替换(#129)
- 商品替换是“失效的旧 PDD 商品 → 已成功采集的替代 PDD 商品”的即时生效审计事实,可由失败采集任务或失败采购任务发起;Agent 只提交明确的来源类型、任务编号和采集结果,服务端负责最终校验和登记。
- 替换记录不删除。同一源商品同时只允许一条生效记录;替代商品必须为
active,不得与源商品相同,不得形成替换环,并必须由同一发起设备的一条completed或completed_partial采集任务证明。 - 一个 PDD 商品可能被多个虾皮商品共用,因此规格匹配按受影响的每个虾皮商品分项记录。主表只表达总体进度;Agent 展示和“继续采购”资格必须读取当前任务对应虾皮商品的分项状态。
- 选错替代商品时,连续执行 B→C 不等于撤销 A→B,因为 B 可能还关联其他虾皮商品。正确纠错语义是把原 A→B 记录置为
superseded,再建立 A→C,并只处理原记录分项中冻结的影响集合。 - 创建请求按
create_request_id幂等;重放时源商品、替代商品、来源类型、来源任务、采集证据和发起设备必须一致,否则返回幂等冲突,不能静默覆盖。 created_by_device_id只代表 Agent 设备。设备可由管理员绑定到一个采购员账号;一个采购员可拥有多台设备,一台设备最多归属一个采购员,也允许暂不归属。SYB 商品一键关联/替换按当前采购员选择的归属设备读取该设备最新临时采集,不使用其他账号或其他设备的全局最新记录。
PDD 商品替换生效与规格匹配(#131)
- 替代商品采集成功后,服务端自动、原子生效,无人工审批。受影响虾皮商品改指替代商品并清除旧规格映射;旧 PDD 商品置为停用但不删除。
- 原有
pending/spec_probe_pending采购任务取消并标记PDD_PRODUCT_REPLACED,释放租约与运行守卫,之后只能由既有重试流程按最新档案创建新任务;不得把新商品外键与旧 URL、goods_id、价格或规格快照拼在同一任务中。 running/order_submit_started与所有终态采购任务继续保留原商品外键和全部快照,按原任务事实收敛或留作历史;TargetColorSnapshot/TargetSizeSnapshot始终是虾皮需求,不因商品替换而清除。- 规格匹配按虾皮商品分项持久执行。AI 开关关闭、无结果或未通过自动确认门槛时转人工;确定性唯一
exact_match可不带置信度自动确认。 - 用户于 2026-08-28 确认放宽 #46 的 AI 口径:
ai_match仅在置信度存在且不低于服务端阈值(默认 0.9)、结果严格属于当前候选、颜色/尺码角色唯一完整、原因非空且写入前输入版本未变化时自动确认。否则不得猜测或选择相近候选,转manual_required。 - 自动确认必须保存来源、实际置信度和脱敏限长原因;人工确认完成后同步对应分项及主表总体状态。worker 不得覆盖已由人工改变的映射。
- 纠错不能简单执行 B→C;必须把原 A→B 记录置为
superseded,建立 A→C,并只处理原记录冻结的虾皮商品影响集合。
历史:创建采购任务时的异步规格匹配(#148,#215 后仅兼容存量)
- #215 起,新建 SYB 采购任务不再根据 PDD 档案创建
purchase_spec_match_work_item,也不在首次派发前调用外部 AI;规格决策统一来自首趟真机探测的当次候选。 - 部署前已存在的匹配工作项继续保留审计、恢复、重试和人工处理能力;其 AI 封闭候选、置信度、输入指纹、退避和最长 60 秒调用边界不变,但不能成为新任务跳过当次探测的依据。
SYB 采购强制当次规格探测(#215)
- 每个新 SYB 采购任务固定执行“首趟只读探测 → 服务端确定性优先/必要时 AI → 固化任务级精确规格 → 第二趟正式采购”。首趟只打开一次浏览器商品链接;匹配期间当前设备保留给同一任务,不领取其他采购或采集任务。连续进入第二趟且当前仍有 PDD 商品页或规格面板强证据时复用当前页、不再次打开链接;手动同任务重试,或当前处于 Agent、其他应用及缺少上述强证据时,重新打开任务固化的商品 URL。复用或重开均不严格核验标题、goodsId 或页面指纹,但仍要求 PDD 包名与商品/规格/订单页面结构安全证据。已有长期映射只作商品档案事实,不直接进入任务执行规格。
- 首趟候选与
taskId、taskAttemptId、deviceId、规则快照哈希和幂等结果哈希关联;第二趟失败不得回到首趟循环探测。备货stock/direct_select没有 SYB 目标规格,继续使用用户逐字选择的档案规格,不进入本规则。 - 候选和 Provider 结果仅保存颜色、尺码原始标签及结构化决策,不保存控件树、整屏截图、账号、地址、订单或支付数据;付款仍永久禁止。
Agent 手动采集替代商品(#130)
- 采集来源不再按任务状态或错误码白名单限制“采集替代商品”:同一设备的采集任务只要仍关联 PDD 商品、该商品没有进行中的替换,且名下不存在
running、order_submit_started、order_result_unknown采购任务,即可由人工判断是否替换。命中这三种采购状态时必须硬拦截并提示等待任务结束,不提供强制绕过。采购来源仍只允许失败任务且错误码逐字等于PDD_LINK_INVALID或PDD_GOODS_SOLD_OUT;Android 只呈现服务端资格,不自行放宽。 - Agent 创建当前页面采集任务时携带
replacementOrigin.type(collection/purchase)和来源taskId。服务端再次校验设备、来源对应的资格边界、源商品、既有替换与进行中的替换流程,并把来源和激活状态持久化到采集任务,保证进程重启后仍可恢复。采集来源确认替换时必须明确提示:所有关联虾皮商品会改指新商品并清空规格映射、尚未开始的采购任务会取消、原商品会停用且暂不能自动撤销。 - 替代商品采集结果先按普通采集事务完整保存。随后调用 #131 的原子生效流程;生效失败不得回滚或覆盖已采集商品、规格和 SKU,而是记录稳定的
failed激活状态与限长错误,服务启动后可按同一幂等键仅重试生效,不重新采集。 - 任务详情的
replacementMappingStatus必须由来源任务对应的替换分项推导,不能只读取主表总体状态。状态为matching时等待自动匹配,manual_required时由 Admin 人工处理,matched后才进入 #132 的继续采购流程。 - 替换采集沿用设备级单任务互斥、采集间隔、无障碍安全边界和禁止支付规则;不会增加轮询,也不会创建采购任务或订单。
替换匹配完成后继续采购(#132)
- 只有采购来源对应的替换分项为
matched,且既有采购重试的任务终态、最新任务、不可逆边界、当前档案、持久化规格映射、PDD 候选、价格、设备在线/空闲与能力门禁全部通过时,Agent 详情才返回continuePurchaseEligible=true。 - 继续资格的详情查询不调用 AI,也不把当前可重新推导的确定性匹配当作已确认映射;映射被人工清空、PDD 重新采集导致候选变化或价格缺失时返回服务端原因。点击时再次执行同一前置门禁,防止详情读取后的状态漂移。
- Agent 的“继续采购”复用既有
AgentRetry → BatchRetry → Create,请求仍只有来源任务号和requestId;不新增采购创建接口。旧失败任务保持不可变,创建的新任务重新固化当前替代商品、规格、价格、规则和设备快照。 matching/manual_required只展示匹配状态;matched但资格不通过时展示服务端下发原因。Admin 批量重试行为不变。- 真机点击“继续采购”可能创建新的正式采购任务,必须先取得独立人工授权;永久禁止支付。
颜色规格图片(#133)
- 颜色图片是 PDD 商品最新档案的可选数据;缺失、截图不支持、定位、裁剪、压缩或上传失败均不得加入
missing,也不得改变completed/completed_partial或既有规格、价格结果。 - Android Agent 仅在既有颜色遍历中,在颜色卡片子树内查找与该卡片同
content-desc的ImageView;禁止全局查找同名图片节点,不新增颜色点击、页面跳转或用户操作。 - API 30 及以上设备可以在内存中取得整屏位图,并严格按图片节点边界裁剪为 JPEG(质量 85);整屏位图用后立即回收,不落盘、不上传、不入库。低于 API 30 或截图受限时安全跳过。
- 单张 JPEG 最大 512 KiB、最长边不超过 1024 像素;Agent 单任务最多保留 64 张、总量最多 8 MiB。结果提交成功后才逐张独立上传,上传不重试到影响任务时长。
- 服务端只接受该任务已提交颜色维度中的 JPEG,校验 Device Token、任务归属、终态、内容、尺寸和数量;按“PDD 商品 + 颜色值”维护最新一张,记录来源 task、device,并沿任务关联不可变规则快照。
- 只允许保存裁剪后的商品图片区域;裁剪结果不得包含账号、地址、订单、支付及其他个人数据。原始控件树、XML、整屏截图仍禁止保存。
- 诊断阶段
COLOR_IMAGE只记录成功及不支持、定位失败、裁剪失败、压缩失败、上传失败分类,不记录颜色文案、坐标或图片内容。 - Agent 采集任务详情只返回并展示当前仍以该任务为
source_task_id的颜色图片,按颜色分组提供缩略图、明确空态/加载失败占位和只读放大查看;同商品同颜色被后续任务覆盖后,旧任务详情不再显示该图。图片仍沿用既有受控商品裁剪文件,不新增整屏截图、原始控件树、下载、分享或编辑能力。
Admin 采集采购与采采管理导航(#142)
- 「采集采购」固定顺序为:SYB 商品、SYB 同步记录、档口入库码、虾皮商品、PDD 商品、采集任务、采购管理。
- 「采采管理」固定顺序为:SYB 店铺、采集规则、采购规则、设备列表、AI 规格匹配。
- Admin 可见两个分组及全部 12 个页面;采购员可见两个分组和除采购规则、AI 规格匹配外的 10 个页面。父组只承担导航结构,不新增业务权限。
- 分组迁移保留既有页面菜单 ID、URL、组件和 API 权限关联,删除旧的 12 个一级模块根菜单;菜单只保留“分组 → 页面”两级。
采购规则与 Agent 版本管理
purchase_rule保存管理员维护的采购规则;单例purchase_rule_setting指向当前规则。迁移以现有默认正式规则原字节播种首条记录。新建、批量预检、批量创建和安全重试读取当前规则;已有采购任务始终执行自身快照。priceGuard缺省或enabled=true时继续按参考价倍率保护:minRatio为 0.1~1.0,maxRatio为 1.0~3.0;旧规则未声明enabled时按启用处理。- 管理员可以设置
priceGuard.enabled=false关闭参考价倍率保护,但必须同时配置整数分absoluteMaxUnitPriceCent,范围 1~100000(¥0.01~¥1000.00),且不能混入倍率字段。服务端仍保留参考价用于预检和审计,并把新任务价格范围固化为 0~绝对上限;不存在无金额上限的采购模式。 - Admin 保存关闭倍率保护的规则前必须二次确认,并在列表摘要和切换当前规则确认中显示绝对上限。规则编辑只影响新任务;既有任务继续使用自身规则和业务价格快照,安全的同任务重试也不得悄悄扩大原价格范围。
- Android 始终以任务固化的
minUnitPriceCent/maxUnitPriceCent为执行边界,在核价、订单摘要和创建订单前 fail-closed 校验;价格越界失败应回传实际观察单价供服务端保存和诊断。支付仍永久禁止。 - Agent 采购历史必须分开显示任务原始目标规格与服务端最终映射的执行规格;映射缺失不等于目标规格缺失。本地历史缓存同时保存两组字段,自动化始终只消费执行规格。
- “采购规则”是“采采管理”下与“采集规则”同级的管理员菜单,采购员角色没有菜单和 API 权限。
- Agent APK 版本由管理员在设备页抽屉中上传、核对并显式设为当前。服务端从 APK Manifest 读取整数
versionCode和versionName,保存 SHA-256、大小、说明和创建人;APK 位于非公开目录,Admin 与设备下载均需认证。 - Agent 只以整数
versionCode判断更新。启动时静默检查一次,设置页可手动检查、显示下载进度并取消;下载完成必须校验大小和 SHA-256。设备有活动任务时禁止检查、下载和安装;安装始终交给 Android 系统确认,项目不绕过未知来源权限。
Android 采购规格动作安全执行(#214)
- 规格入口与精确规格选择统一按“重新定位唯一目标 → 执行一次无障碍点击 → 读取新页面验证”执行;不得复用旧无障碍节点,不选择相近规格,也不在多候选时默认点击第一个。
- 无障碍点击后页面完全无变化时,只允许对解析器已确认的安全规格入口或服务端下发且唯一命中的精确规格执行一次中心手势兜底。目标必须可见、启用、边界有效,手势后仍须以规格面板强证据或精确选中证据确认结果。
- 页面发生变化但规格面板强证据不足时,默认明确失败;#243 的同商品页安全入口恢复是限定例外:确认包/Activity 未变、商品标题非空且未变、入口来源与语义未变,无面板、关闭、数量、已选、支付、订单或页面异常信号时,重新定位入口并最多执行一次受控手势。整页普通动态节点变化不单独阻断该恢复;入口缺失或显式/嵌套入口歧义仍拒绝。商品标题一致是当前上下文约束,不宣称已从页面核验 goods_id。诊断只记录入口来源、点击结果/原因、恢复结果和面板数量/布尔等无敏感标量。原始控件树、节点文字集合和整屏截图仍不得保存或上传。
- 规格已处于精确选中状态时不得重复点击。规格查找只在解析器唯一识别的规格面板容器内有限滚动,每次滚动后重新定位容器与目标;容器缺失、歧义、到边或验证失败均 fail-closed。
- 中心手势兜底不得用于修改/保存地址、创建或提交订单、订单详情入口以及任何支付/付款目标;正式创建订单的一次性不可逆门禁与永久禁止支付规则不变。
PDD 商品反向关联与继续订单采购(#161)
- 一个 PDD 商品可被多个虾皮商品共用。PDD 详情返回全部关联虾皮商品摘要;订单行由独立统一分页接口读取,不按虾皮商品伪造嵌套分页。
scope=actionable固定包含purchase_ready、pdd_pending、pdd_collecting、pdd_collection_failed、color_mapping;scope=all才显示其他阶段。该集合由服务端维护,前端不复制。- 规格映射摘要使用
specMappingStatus=complete|incomplete|not_required、确认数和总数。not_required只表示虾皮商品没有颜色或尺码维度;商品摘要不替代订单行采购资格。 - “关联订单继续采购”只处理已有 SYB 订单;“创建备货采购”不关联 SYB 订单。两者入口和文案必须明确区分。继续采购复用既有批量预检和批量创建,价格、映射、并发、订单和不可逆门禁不变。
- SYB 订单号、目标颜色/尺码、数量和当前采购任务状态只允许管理员与采购员读取;其他角色由服务端拒绝。查询路径不调用 AI Provider。
定时与手动蝦皮规格自动匹配(#195)
- 系统只扫描存活且已关联
activePDD 商品、两边至少共享颜色或尺码角色、并且至少存在一个未确认或已失效映射的蝦皮商品。 - 每个商品复用详情页“一键匹配颜色和尺码”的规则:保留当前仍有效的
confirmed映射;唯一确定匹配和达到服务端阈值、理由非空、候选仍有效的 AI 结果直接保存为confirmed;低置信度、无结果、Provider 异常或上下文漂移不猜测、不写入错误映射。 - 定时与管理员手动执行共用全局活动槽和逐商品工作状态。单批默认最多 20 个商品;同一规格上下文与 AI 设置更新时间未变化时,已完成、低置信度或无结果商品不重复调用 AI。
- Provider 临时失败最多尝试 3 次,间隔至少 60 分钟;输入变化后重新计算指纹并允许重新处理。运行记录只保存结构化计数和脱敏限长错误,不保存 API Key、Provider 原始响应、商品原始 JSON 或个人数据。
- 系统定时任务迁移后默认关闭,须由管理员明确启用。该能力仅维护蝦皮与 PDD 颜色/尺码映射,不创建采购任务、PDD 订单,不触发 Agent,也不执行付款。
SYB 异常采购规格 AI 解析(#198)
- SYB 采购规格采用两阶段流程:先把货运单明细
productSpec解析为目标颜色/尺码,再由 #195 把蝦皮规格匹配到 PDD 规格;两阶段不得混为同一匹配事实。 - 定时任务只处理未人工确认且确定性解析为
uncertain/failed的明细。每条先重跑确定性解析;空productSpec、无关联蝦皮商品、无颜色/尺码候选或同一角色存在多个候选维度时不调用 AI,继续人工处理。 - AI 只在关联蝦皮商品的封闭候选集合中返回原始颜色/尺码,并必须提供达到当前自动确认阈值的置信度和非空理由;集合外值、缺失角色、低置信度、歧义、无结果和输入漂移都不得确认。
parse_status保留确定性解析器结论;AI 与人工确认分别记录,人工优先级最高。重复同步不得覆盖人工值;完全相同输入保留 AI 值,来源或关联变化会清除旧 AI 确认。- 同一输入的低置信度或无结果不重复调用 Provider;临时故障至少 60 分钟后重试,最多 3 次。任务不创建采集/采购任务、订单,不执行 Android 动作或付款。
设备身份恢复
-
管理员可在设备管理对未停用设备发起“重置设备身份”。此动作不删除设备记录、不改变设备 ID、能力或已绑定的待领取任务;它立即使旧 Token 无效,并只生成一次、有效期 10 分钟的恢复码。
-
恢复码仅显示给发起操作的管理员一次,服务端只保存摘要;不得进入列表、日志、任务记录、Android 持久化或普通接口。手机操作员必须在同一安装实例的 Agent 设置中手动输入。
-
服务端只接受同一
installId、未过期且尚未使用的恢复码完成重新注册,成功后签发新 Token 并使恢复码失效。过期、重复使用、installId 不符或停用均明确失败;不能通过清空数据、直接改库或“吊销 Token”恢复原任务归属。 -
自 #223 起,任务创建时把与冻结 SYB 目标对应的已确认商品规格映射保存为不可变的探测指导快照,但仍不得跳过首趟真机探测。探测完成后,每个角色先验证快照映射能否按既有规范化规则唯一对应当次候选,能对应时固化当次候选原文;不能对应时只对该未解决角色执行确定性匹配,仍无结果才调用 AI。已解决角色不重复交给 AI,任一最终值仍必须逐字属于当次候选;历史映射失效、规范化后歧义或角色不符时不得复用。候选完整但无法决策时提示“已采集到当前规格,但未能确定颜色或尺码映射”,不再误报候选不存在。
采购商品深链入口(#232)
- Android 采购新任务(含探测与人工重试)打开商品时,优先使用指定 PDD 包名的 ACTION_VIEW,并设置 NEW_TASK 与 CLEAR_TASK,以清理旧任务栈后交付该任务链接。清理的是 Activity 返回历史,不是清除应用数据或强制停止进程。
- 直接启动失败(包括无可处理 Activity)时回退既有浏览器入口;启动请求被接受后仍由执行器验证稳定商品页面,停留首页不会仅因启动成功而判定完成。
- 清栈不用于改地址后返回、下单后回到 PDD、订单核查;采集入口继续使用既有浏览器流程,避免绕过规则中的浏览器步骤。
- 当前通用商品页面结构验证不能独立证明页面 goods_id;解析结果携带的任务 goodsId 不是页面回读证据。首次直接深链上线仍需以实际目标商品真机核对,ADB 实验不替代 Agent 上下文验证。
SYB 批量采购设备偏好(#233)
- SYB 商品页“批量创建采购任务”按当前登录用户 ID、当前浏览器来源与 API 环境记住最近一次设备选择;主动清空也记忆为不指定设备。只保存设备 ID,不保存 Token、账号凭据或订单信息。
- 弹窗打开后先按现有在线/可选/采购能力条件加载设备,再恢复选择并以相同设备预检。记忆设备当前不可用时保留偏好并提示用户重新选择或明确清空,不静默切换设备或自动领取。
- 预检加载中、失败或记忆设备不可用时不能提交;过期预检结果不覆盖新的设备选择。服务端原有设备及采购资格校验不变。
- 偏好只作用于此入口,不影响采集、其他创建入口和采购重试。浏览器存储失败时仍允许手动操作;刷新或关闭再打开浏览器可恢复,清理浏览器数据或沿用现有退出登录清理存储行为后需重新选择。
客户端密钥与可编辑模块授权(#237)
以下为提交 71f7751 已实现的规则;2026-09-07 本机已迁移并验证管理页面可用,2026-09-08 已随 d403f3b 完成线上迁移与部署,真实客户端密钥执行闭环尚未验证。
- 仅管理员创建、查看、编辑授权或停用密钥。首版不提供密钥改名、到期、轮换、恢复启用、删除或任意接口授权。
- 模块选择复用“采集采购/采采管理”现有 12 个业务模块;分组勾选只影响当前子模块,新菜单不会自动获得授权。客户端密钥管理、系统账号权限及支付不在可授权模块中。
- 勾选模块默认只读,至少保留一个模块。读写仅开放清单中的普通写操作;同步、采集、采购、删除、导入、重解析、匹配、回写及切换当前采购规则分别独立授权,默认关闭。没有普通写接口的模块不允许勾选读写。
- 编辑既有密钥不会更换密钥,名称和前缀只读;移除模块同时移除其动作。取消保留原授权;失败保留输入;版本冲突要求刷新重开。停用不可编辑或恢复。
- 保存后新请求按最新授权校验,已经通过校验的在途请求可能完成,不追溯回滚。模块授权不是行级、店铺级或租户隔离,授予读取即允许读取该模块明确接口可返回的业务范围。
- 用户于 2026-09-07 明确接受明文风险:密钥管理及客户端接口默认兼容 HTTP/HTTPS,无需开关。HTTP 会明文传输密钥与业务数据,建议优先使用 HTTPS;兼容不改变管理员身份与模块授权边界。
- 客户端与 Admin 登录 JWT、Agent Device Token 独立。响应排除凭据及原始载荷字段;AI 设置只返回 enabled,不开放 Provider 配置读写或连接测试。设备仅开放列表,不开放身份重置、令牌或解锁接口。
- 执行动作复用既有业务门禁、幂等参数及状态机;客户端采购 batch-retry 沿用 Admin 原有语义,不等同于 Agent 就地 reset。授权重采购、支付复核、取消订单等未列入接口不开放;永久禁止付款。
- 创建响应丢失时不可找回完整密钥,应核对列表并停用可能已创建的记录,再明确创建新密钥,不能盲目自动重试。完整密钥只在创建结果弹窗内存中显示,关闭或离开页面清空,不写浏览器持久存储。
打开采购规格面板后按需滚动(#238)
- Android 0.9.60 / versionCode 73,代码
58a6c1c起,规则openSpecPanel.swipeAfter保留格式校验与旧快照兼容,但不执行打开面板后的固定次数预滑动;不以“必须滑两次成功”作为进入规格探测/选择的条件。动作后的waitAfterMs仍生效。 - 首趟规格探测和第二趟精确选择仍使用各自既有的按需横向/纵向、有界与稳定终止策略。取消预滑动不等于不探测隐藏规格,也不等于只看首屏。目标不存在、歧义、页面证据不足或必要的有界查找失败时仍明确失败。
- 此调整覆盖所有已经安全识别打开的面板,不再仅特判 NON_SCROLLABLE_CONFIRMATION;不弱化面板验证、精确选中、地址、价格、任务租约、创建订单边界或禁止支付规则。
- 其他动作的后置滑动沿用原行为,必需滑动失败仍返回 RULE_ACTION_FAILED。旧规则 JSON 不回写、不迁移;原任务 ID、历史 attempt、商品与规格快照不变。旧 APK 行为不变,需升级 Agent;本单未改线上规则或执行 CG68 真机采购。
SYB 逐页保存与部分成功(#239)
实现绑定 c6a962d;2026-09-08 已随 d403f3b 部署线上,未手动触发真实同步验收;#240 上游尾页超时尚未修复。每页完整明细在外部请求结束后按页事务保存;页回滚不累计明细/新增/覆盖数,已提交页保留。日期局部读取失败继续下一日期,全局数据库/进度/会话/取消故障停止。当天漂移不在一次运行内重扫;后续运行重新扫描并幂等补齐。
同步状态增加 partial_success(部分成功,15 字符,复用现有 varchar(16),无需迁移)。有错误且 created+updated>0 为部分成功;有错误无已提交明细为 failed;完整且无错误为 succeeded(包括无符合店铺的数据)。中断仍为 interrupted,不把中断追认为成功。所有终态沿用活动槽释放规则。
orderCount 是已验证页的原始列表读取数量;detailCount、created、updated 为已提交明细及其新增/覆盖数量;daysProcessed 是完整通过的日期数,不是已尝试日期数。失败日期/页码/阶段写入现有脱敏限长 errorMessage。部分成功不刷新店铺的完整同步统计。
Web 唯一展示位置为“采集采购 → SYB 同步记录”:列表状态、状态筛选及详情支持部分成功,详情保留已保存数量、错误原因与重新同步补齐提示。定时任务日志只表示异步任务受理,不等于最终业务同步成功。
商品页动态变化下的采购入口恢复(#243)
实现 ec8b14a,Android 0.9.61/versionCode 74;已构建、未安装或真机验收。规格探测和正式采购共用入口函数,面板已打开时不新增点击;仍在同一商品上下文且安全入口存在时,一次重新定位手势恢复不再依赖整页完全静止。手势后仍未打开则报告入口无效果,不循环点击。恢复不能用于地址、创建订单、支付或未知面板,不修改面板分类器及正式下单边界。CG82/CG85 原首次点击未生效的底层原因尚待新日志和授权真机验证。
同一颜色卡片重复选中节点(#244)
实现 93aab6a,Android 0.9.62/versionCode 75;已构建并授权覆盖安装,真实采购效果待验收。仅在颜色维度完整精确目标已选中、但存在非目标已选候选时,识别同一卡片重复表达:卡片必须是滚动容器直接子级的可点击非滚动 android.view.ViewGroup,节点父链明确、可见启用且边界包含;其他冲突节点仅可为该卡片自身或其中的 ImageView。另一文字选项、另一张卡片、多个精确目标、目标未选中、父链/边界不明均不适用例外。额外核对内存源节点以拒绝被解析器按同名去重隐藏的跨卡片目标;不保存原始树。
不删除规格数字、不模糊匹配、不改变通用解析器、尺码确认、摘要兜底、入口/滚动/地址/价格/创建订单。没有非目标选中冲突时继续原判断;仅把同卡片容器/图片的重复选中表达从冲突中排除,不新增点击。
精确规格不可用与入口恢复诊断(#245)
实现 ca815c3,Android 0.9.63/versionCode 76;已通过单元测试并构建,未安装、未进行真实采购验收。入口恢复沿用 #243 条件,拒绝时通过 entryRecovery=rejected;reason=<固定原因码> 区分页面身份、商品上下文、面板/支付区域、数量/摘要、标题、入口来源/文案、歧义、规则别名及可用性;不放宽条件,不新增点击。
在规格面板识别出唯一完整精确候选且 available=false 时,立即返回既有 PURCHASE_SPEC_SAFE_TARGET_MISSING,提示目标颜色/尺码已售罄或当前不可选,未创建订单;已选中目标同样不能绕过不可用检查。只记录 dimension 和 exact_target_unavailable 固定结构证据,不记录规格原文或原始树。原有纵向与横向定位在此条件下本就停止,不能将本改动描述为修复“已识别售罄仍继续搜索”。未识别精确候选时继续既有有界搜索,不推断售罄,不替换规格;解析器、匹配规则、滚动预算、地址与下单流程不变。
改地址返回后的动态提交按钮(#248)
实现绑定 c80c746,Android 0.9.66 / versionCode 79;已通过 353 项 Android 单元测试并构建,尚未安装或进行真实采购验收。
- 地址回读与最终提交按钮定位分开判断。旧“提交订单”“现在买,仅”“确认购买”识别继续优先;存在旧文案候选但歧义时不使用结构补充选择其中一个。地址确实缺失时保留既有有限恢复;地址及采购面板上下文已确认后,不因底部按钮文字变化而滚动规格列表。按钮缺失或不唯一使用
PURCHASE_SUBMIT_TARGET_AMBIGUOUS提示按钮问题,不误报地址保存超时。 - 结构补充只属于当前执行器中已完成地址修改后的返回流程,不能由其他页面或旧执行的地址证明启用。当前须为 PDD、地址后缀按既有规则回读唯一、地址入口唯一,并存在唯一数量输入或已选摘要;通过地址入口与该证据的最近共同祖先确定整个采购弹层,不把颜色/尺码滚动区域当成弹层。排除全屏大祖先、地址编辑、已知支付 Activity 及订单结果/支付页面,后续定位要求 Activity 与地址返回时一致。
- 旧文案无候选时,只接受弹层底部固定区域内一个独立、可见启用、非滚动的可点击容器;不在规格滚动区内选择按钮,不取控件树末项,不使用固定屏幕点击坐标。文字与人民币金额子节点合并为一个按钮;支持如“复购价,”及非支付展示文字变化,但单独价格、多个操作按钮或支付/付款/地址/返回等非提交动作均不放行。
- 地址返回检查、最终复核和提交共用目标定位。结构路径保留原文字节点为重新定位锚点,由已有无障碍点击重新查找其可点击父级;不新增下单手势兜底。最终复核成功后才允许该结构路径提交;提交前再次检查路径、类别、文字与边界,发生变化即停止;复核失败清除本地结构提交锚点。
- 既有规格、数量、价格和地址复核,任务租约、服务端/本地不可逆边界及单次提交规则不变。结构识别不支持支付,不增加采购员操作、配置或审批;不改变 Admin、接口、数据库、规则 JSON、通用解析器及滑动执行器。原始控件树、整屏截图、地址全文和凭据不得落盘或上传。
临时采集连续模式(#250)
当前实现绑定 37e8b56,Agent 0.9.72 / versionCode 85。2026-09-09 用户批准 v5:按配置次数返回后切回 Agent,替代此前“识别并停留 PDD 首页”的方案;不保证 PDD 最终停在首页。代码、376 项 Android 单测及 Debug 构建通过,新版设置与完整真机闭环待验收。
- 连续采集默认关闭,本机即时保存,失败恢复原值;开启后显示返回次数选择,1~5 次、默认 3,取消不改,写入失败恢复旧值。任务忙碌时开关和次数均禁用,选择提交时再次检查;无新增权限。只用于本次人工新建普通临时采集(source=agent_current_page、attemptNumber=1、无替换来源),Admin 下发、重试、替代与采购不参与。
- 单任务执行开始固定返回次数。完整 completed、服务端提交确认且既有图片上传流程结束后,执行有限 Back,每次后等待 500ms;不要求识别商品/搜索/相机/首页,也不要求画面发生变化。图片上传仍沿用既有非致命行为,不因收尾更改结果。
- 每次 Back 前检查前台仍为 PDD,读取页面后再次检查;离开 PDD 则停止余下 Back。次数完成、离开 PDD 或 Back 动作失败后,尝试打开 Agent 保持原 Tab,等待 500ms 并验证前台包名。动作失败不重试,不把请求启动成功直接当作切回成功。
- 沿用风险页安全边界:登录/验证码/风控、地址编辑、订单详情或支付等证据时保留现场,不发送 Back 或强行切回;Activity 缺失、读取异常明确停止。以上例外不引入首页门禁。
- 导航在原任务互斥和唤醒锁内完成,不变更租约/调度。返回失败只显示人工处理提示,不把成功采集改为失败或自动重采。
- 失败、部分成功、提交未确认保留现场,不运行返回步骤,也不触发旧空闲返回倒计时。关闭开关保持原流程,采集间隔不变。
- 不自动拍照、搜索或创建下一任务,不涉及采购/订单/付款;不使用深链、浏览器、OCR/VLM 或坐标兜底。
SYB 存疑规格候选核对(#251)
实现绑定 64b4205,基线 main fdd26af;2026-09-09 代码与本地测试/构建通过,未部署、未重跑生产历史数据。
- 原 Parse 的成功与失败行为不变,仅 uncertain 明细增加既有蝦皮规格候选核对。比较完整原文,沿用【备注】清理,允许全角逗号、逗号两侧空白及连续空白归一;颜色尺码可正序或倒序,使用逗号或空白分隔,只有唯一完整组合才改为 success。返回既有候选标签,不改写标签,不删除加号、不截断体重说明、不做近似匹配。
- 单规格只有在候选确实仅包含该角色时通过;有两个角色时不能用单值补猜另一个角色。空/损坏候选、校验不通过、同角色多维、未知有值维度、多种组合或归一化碰撞,均保留原结果。候选必须已存在,不能用本次待确认输入生成候选再自我证明。
- 同步入库 ApplyDetail、手动 Reparse 共用;成功核对不再次合并规格,因此不新增重复维度、不覆盖已有映射。人工确认仍优先,默认 Reparse 跳过人工与 AI 已确认值;原文保留。
- #198 批处理原本先 Reparse,所以可直接复用本优化:能确定的不用调用 AI;仍不确定的按原 AI 流程处理。没有新增调度、调用额度或同步等待,不自动开启已有任务。
- 不取消 uncertain/failed 状态,不改变采购可信度/可采购规则,不实现一键关联 PDD。部署后新同步或显式重新解析会使用新逻辑;本次没有执行生产批量更新。
蝦皮详情匹配等待与回读(#254)
实现绑定 9088e6b(2026-09-10,分支 fix/254-match-loading);已通过合成数据测试,尚未合并 main 或发布线上。
- AI 设置中的 timeoutSeconds=T 仍是单次 Provider 请求的上限。详情一键匹配的整次预算为 2T+10 秒,浏览器 POST 等待上限为 2T+20 秒;例如 T=60 时130/140秒,T=180时370/380秒。只保留现有一个 AI 设置入口,不新增时间配置框,也不自动改变管理员已保存的 T。
- 超时上限不是固定等待。颜色/尺码串行执行且共用整次预算;正常部分匹配仍按原事务保存合格结果,AI异常在保存前返回时不提交本轮新映射。既有置信度、候选、人工确认映射保护和采购资格不变。
- 前端超时、关闭或切换详情不代表后端已取消、未保存或已回滚;必须以回读结果为准,无法回读显示结果未确认,不自动重复匹配、不自动创建采购。
- 单商品详情的成功/失败/超时/关闭重开都必须结束失效的等待状态;旧请求不得覆盖新商品或新操作。匹配进行期间本抽屉不能人工改映射,已有未保存草稿仍按原确认流程处理。
- UI匹配提示的等待上限仅指POST,不含提交前GET及结果核对GET;结果核对也有限时,不能让失败提示再次陷入无限转圈。
SYB 行内一键关联最近采集(#253)
实现绑定 b1594dc,2026-09-10;分支 feat/253-one-click-link,包含 #254 依赖。已完成合成数据测试及构建,未合并 main、未部署,不代表当前线上已具备此能力。
- 未关联 PDD 且既有处理阶段提供“去关联”的 SYB 行可用一键关联;原人工入口不删除。首次点击选择采集手机后继续当前行,后续使用记忆手机;小箭头查看/切换手机,保存只修改全行共用偏好。取消不改变偏好、不执行关联。与批量采购设备选择互不影响。
- 以所选手机的临时采集 source=agent_current_page 为范围,从 completed、completed_partial 中按 finished_at DESC、id DESC 取最新一条;失败/待执行/执行中不参与。最新为部分成功或商品停用、无可用规格时明确停止,不回退更旧商品,不切换其他手机。离线手机允许使用已有成功结果,停用或已删除手机需要重新选择。
- 主动作开始冻结行、蝦皮商品和设备;服务端关联事务固定来源采集任务、PDD商品与规格版本。仅未关联时自动写入,已有或被其他操作改变的关联不覆盖。关联作用于蝦皮商品,因此共用该蝦皮档案的其他 SYB 明细也受影响;切换手机不会重绑已有商品,也不会改变在途操作。
- 先保存关联,再复用现有颜色/尺码自动匹配及保存。有效已确认映射保留;普通部分匹配保存合格结果,AI故障不提交本轮新映射,但已保存关联保留。后续可从“去匹配”或详情人工继续。failed 且无人工/AI确认时不能自动跳过人工解析;uncertain 不统一拦截,仍以原采购准备规则为准。
- 操作完成不保证立即可采购,必须刷新现有处理阶段;缺规格、缺映射、解析需确认或其他原资格不满足时继续显示真实待处理阶段。不自动创建采购任务、不下单、不支付。
- 请求超时/网络中断只做有限回读,不重复提交;读回失败明确结果未确认,避免无限转圈。离开页面不代表后端停止或回滚。普通用户沿用现有采购员权限,无新管理员专属开关。
SYB 已关联商品的一键替换(#258)
实现绑定 2b01974;部署与验收见 #258 发布证据。
- 复用一键关联及小箭头的位置,保留原查看 PDD 商品。PDD 待采集、采集失败、停用或缺价格的对应处理阶段可替换;采集中、已创建/运行采购、成功或结果未知不开放。服务端提交时再次检查,不能只相信按钮。
- 复用每用户/浏览器/API环境的手机偏好;首次选择继续当前行,小箭头仅切换偏好。预览仅选所选手机最新 completed/completed_partial 临时采集,部分成功或不可用不回退旧商品。确认后固定来源任务和目标,不改用新采集;来源状态、设备、目标规格或旧关联改变时拒绝。
- 不同商品显示一次确认,包含旧/新商品、手机和共享蝦皮档案影响;取消不写入。同商品不弹替换确认且不重写关联,只继续匹配。共享该蝦皮档案的 SYB 明细使用新关联,历史采购任务快照不改。
- 沿用既有更换关联和有效映射检查,再复用自动匹配保存。部分匹配、AI失败或解析需人工处理时保留已保存关联,显示真实处理阶段,不保证立即可采购、不自动创建采购。
- 网络异常只有限回读,区分目标商品、仍为原商品和其他关联,不把“已有某个关联”误报为本次替换成功;不自动重发写请求。没有新增后台作业、订单或付款操作。
辅助信息缺失的采集关联(#259)
实现绑定 e467706,仅 Server;部署/验收见 #259。替代 #253/#258 中“部分完成一律拒绝”的限制,不改变 completed 原有路径。
- completed_partial 的 missing 必须是非空合法列表且仅包含 salesText、shopName、reviewCount,才进入辅助信息兼容检查;title、规格/价格缺失、遍历截断、SKU数量上限及未知原因仍拒绝。
shopeeproduct/partial_collection.go核对本次 task 的维度和值、可售SKU的完整标记/规格引用/非负价格、本次颜色价格,以及当前档案可选值由本次有效SKU覆盖,不能借旧档案合并残留的规格或价格通过。真实单维度允许,不虚构另一维度;本次明确报告缺少规格仍拒绝。- 一键关联、替换预览及确认提交共用验证。失败沿用409 LATEST_COLLECTION_UNAVAILABLE及现有提示,不回退更早采集、不换手机。状态 completed_partial 和 missing 原样保留;辅助字段缺失仍可在任务详情查看。
- 无接口字段、数据库迁移、Android/Web或权限变更;普通人工关联与采购/AI资格不变。不将“允许关联”视为“已匹配或已采购”。
采购单标题面板与地址就绪等待(#260、#261)
实现绑定 #260 3c1ffa4(执行器回归测试 7de4318)、#261 5ea07f1,Android 0.9.74 / versionCode87,基于0.9.73。安装及真实采购验收以工单证据为准;不代表 main 的 Android 已整合这些分支。
- 采购仅在安全规格入口点击返回SUCCESS后,记录本次页面包名/Activity作为内存上下文;开始新执行或页面身份改变时清除。
PddScreenParser的新增 purchaseEntryContext 默认关闭,仅该采购执行器传入;普通解析和采集原判定保留。 - 当前仍为同一PDD Activity、商品ID非空、没有页面风险、没有选中摘要,且唯一有标题规格滚动区、一个维度有值,同时具有关闭、数量、支付展示区域与下单操作证据时,单标题可识别为NORMAL_SCROLLABLE。只是允许进入既有精确规格探测/选择,不执行下单或付款,不全局认可UNKNOWN,不增加入口重复点击或滑动。
- 地址入口点击原有1000ms保留;地址列表等待增加唯一修改目标要求。点击修改和保存由500ms改为1000ms,其他通用动作间隔不变,无新配置项。
- 修改后不再只见“详细地址”文字就立即写入。最多50次、每次间隔200ms读取(不含读取耗时),检查PDD页面风险;唯一可见启用有内容的详细地址EditText,连续两次路径、边界、内容及Activity相同才继续原输入流程。始终零个/多个或不稳定时失败,不取第一个候选。
- 输入内容生成、输入后回读、保存后退出及返回规格面板、最终复核和单次下单边界不变。新增本机脱敏诊断 addressEditorCandidates / addressEditorPolls 两个整数,与task/attempt/device/ruleHash关联;不记录地址内容、原始树或整屏截图。
- 仅Android;无Server/Web、共享API字段、数据库迁移或权限变化。真实采购、地址写入及订单创建不作为自动安装验证,不执行付款。
v2 商品入口补点与地址返回等待(#260、#261)
2026-09-10 实现绑定 #260 713111d、#261 d0a82f3,Android 0.9.75 / versionCode88;真实采购效果以工单验收为准,非 main 合并声明。
- 入口恢复不再把全页面支付方式展示文案单独视为支付页。当前包名/Activity、商品标题和安全入口必须与点击前一致,入口唯一且可用;已打开面板、关闭控件、数量、选中摘要、订单操作、风险/评价页面仍拒绝恢复。支付 Activity 或明确支付、订单、地址文本继续阻止补点。仅允许既有一次重新定位后的规格入口中心手势,随后仍验证面板,不循环、不扩展到地址保存或下单。
- 保存地址后的确认读取、必要时一次返回后的确认读取,增加最多50次、间隔200ms的有界就绪检查,页面捕获耗时另计。连续两次同一Activity满足原地址回读与确认面板条件后继续;完整信息不要求滚动区域。已明确到地址列表时保留原返回路径,不等待列表出现下单按钮;返回后增加1000ms缓冲。
- 就绪检查不修改原地址回读和结构下单入口规则;超时后只对既有识别的面板、唯一可用滚动区域执行原有有限滚动。零/多个区域仍失败,不凭地址入口或未知底部节点授权下单。最终精确规格、数量、价格、地址与单次下单边界不变。
- 私有采购诊断新增布尔 savedAddressMatched、savedPanelMatched;整数 savedLegacySubmitCandidates、savedAddressCards、savedAddressTargets、savedScrollCandidates、savedConfirmationPolls。只记录标量并绑定task/attempt/device/ruleHash,不保存地址、原始树或整屏图。
- CG109 v1现场读取未达到空闲状态,不能确认原失败具体缺哪项证据;v2覆盖迟到确认节点及可观测性,不将合成测试通过冒充真机修复验收。无Server/Web/API/迁移/权限变化,不需要服务器重启。
探测到正式采购的单次面板交接(#262)
2026-09-10 实现绑定 2ea32fd,Android0.9.76/code89;基于#260/#261,未声明合并main或真实采购验收通过。
- AgentForegroundService通过PurchaseProbeHandoff只在成功spec_probe且结束后新快照仍识别PDD规格面板时保留一次性内存交接。仅taskId/goodsId/ruleHash/deviceId、Activity、前台revision和单调时钟时间,不保留控件节点、地址或选中状态,不落盘;有效期180秒。
- 正式阶段消费时检查同任务/商品/规则/设备、前台revision及时间,消费后即清除。失配/超时/无任务或采集任务调度/结果异常/进程重启均不能沿用;普通手动再试不会继承已消费交接。现有服务端租约、互斥和匹配等待策略不变。
- 有交接时,执行器恢复限定的purchaseEntryContext,最多10次、间隔200ms新读取(捕获耗时另计);连续两次相同PDD Activity且具备既有商品/面板证据才跳过openProduct。空树可有限等待,其他应用/Activity改变/页面风险立即拒绝复用。没有交接时保留原一次判断路径;不把UNKNOWN当成功,不跳过正式精确规格/数量/价格/地址或下单验证。
- 私有诊断新增handoffPresent、productReused布尔值,reusePolls整数及reuseReason固定枚举legacy_evidence/page_problem/page_changed/handoff_ready/evidence_timeout。仍绑定task/attempt/device/ruleHash,无敏感文本。
- 无Server/Web、共享API或数据库变化,不需重启服务器。只有合成测试验证;原CG107/108日志证实两阶段,但未记录旧版重开判断,不把上下文丢失假设宣称为唯一现场根因。
PDD 订单实付价格(#306)
实现绑定 8c01329(2026-09-18),待验收,尚未部署。人工“我的订单”回填除订单号和下单时间外,可提交唯一、合法的“实付”价格。它是订单展示总额,人民币分,独立存为 purchase_task.pdd_order_amount_cent;actual_unit_price_cent 仍是下单前观察的商品单价,二者不互相推算。
不判断是否付款,不改变人工支付复核状态。没看到实付、格式异常或多个不同实付值时,仅跳过金额,订单号和时间照常按原规则回填。采购员可稍后再点既有“回填”,为空金额补写;已有相同值幂等,不同值保留旧值并返回金额冲突提示,不撤销正确订单事实。只允许当前设备自己的、原有允许状态的任务;不新增 attempt 或采购动作。
金额仅保存 Admin;#305 订单号回写 SYB 的数据流不得使用该字段或将其映射为 cost,金额缺失/冲突不得成为订单号回写的前置条件。本单不代表 #305 已实现。Admin 现有订单详情卡片增加“实付价格”,缺失显示“尚未获取”,不新增列表列、入口或支付动作。安全点击集合及不保存原始控件树/个人信息的规则不变。
PDD 订单号自动回填 SYB(#305)
实现绑定 e89de1a(2026-09-18),代码与隔离测试已完成,真实迁移/发布/SYB写入尚未验证。以下补充 #306 的单号后续流程,不改变其金额规则。
正式 SYB 订单采购取得 PDD 单号(普通结果或人工遍历回填)后,在订单事实的同一个数据库事务中保存独立回填记录,后台异步写入对应 stock_id + detail_id。已人工回填相同单号也幂等确保记录存在;不重新采购,不等待支付复核。备货、演练、未取得单号或关联失效不回填;不自动扫描历史单据,历史补偿由采购管理勾选发起。
写前精确回读唯一目标明细:同单号且 purchasePlatform=pdd 直接成功;非空不同单号/不兼容平台标记 conflict,不覆盖。远端为空才允许一次写请求,写后回读确认才成功。未知结果不得自动重复写;重启恢复的 running 只回读,不能因租约过期盲重发。失败/unknown 可人工补偿,仍先回读,且在途租约未到期时不能再发起。
订单回填状态独立于采购成功、支付复核及物流 writeback_status。实付金额只存 Admin,SYB cost=0 为接口固定参数,不以金额推断付款。SYB 接口会同时更新采购状态/平台/时间,不能视作纯展示修改。
采购管理增加独立状态列、批量回填和详情补偿;复用既有访问权限,不增支付确认或审批。批量受理与最终成功分开展示;重试采购和回填分别筛选勾选项。远端无原子CAS,对系统外人工并发修改/超长延迟请求不能承诺绝对互斥;有冲突应人工核对,禁止强制覆盖。
SYB 会话类失败的有界自动重试(#330)
实现 01510a8/08b7095(2026-09-21,已合并 main,未部署、未生产验证)。回填 worker 从缓存会话恢复客户端后调用 SYB 会话校验;会话缺失/过期、串号失效、校验网络错误等均记为 SYB_SESSION_UNAVAILABLE,error_message 只记录类别和“将自动重试;如持续失败请恢复登录后重试”,不含原始错误。该类失败发生在任何写入之前,最多自动重试 6 次,退避 5/10/15/30/30 分钟(约 90 分钟,大于一个整点同步周期),达上限保持 failed 等人工。会话仍只由每小时 SYB 同步刷新;回填不登录、不 OCR、不删除或写入会话。其他失败码仍不自动重试。退避期内可手工重新回填,手工提交重置尝试次数。历史失败记录不会被自动领取。
Agent 回填订单入口兼容(#307)
- 打开我的订单后最多采样8次,每次间隔1秒,连续两次订单导航结构一致才继续;登录/风控仍立即停止,超时给出明确原因。
- 保留全部标签selected=true的原路径。PDD不提供selected属性时,要求订单标题、唯一全部标签以及同排至少两个订单状态标签;仅该安全导航标签允许一次中心手势,不扩大到订单卡片、地址、支付或其他操作。
- 本轮主动点击全部后复核订单导航结构;本轮上下文不能跨扫描复用,出现其他已选中订单状态时停止。卡片识别与支付禁令保持不变。
- 回填结束/失败通过现有通知与Toast显示脱敏原因;详细结果仍在Agent采购页。本变更不调整服务端回填接口、采集或采购流程。
下单后待付款核单与应付金额(#325)
实现分支 fix/325-order-result,2026-09-19;未部署、未真机验收。下单点击及不可逆边界不改。已知 PayActivity 允许一次原有 Back,随后从3次放宽为25次200ms采样(约5秒等待,不含页面捕获耗时),持续无证据仍为 PURCHASE_ORDER_PAYMENT_REPEATED。微信恢复、系统选择器、空窗口和陌生应用的既有边界保留。
过渡阶段最多60次采样。首次识别到待付款证据后单独分配30次采样预算,不被之前绕路消耗,不因文字反复出现重置;核单总采样上限90次。缺少唯一订单号或时间时立即向上滑动读取下方内容,最多4次、手势400ms、每次后等500ms;读全立即停止,已有完整字段不滑动。该待付款读取分支不点击任何控件,也不点击付款。纯支付页不使用该滑动分支;出现可读待付款证据优先于复用的 Activity 名称。按采样间隔约18秒加有限手势/额外等待,实际耗时还含capture等调用;未改变2分钟任务租约或5分钟唤醒锁,也不宣称新增了执行器总体墙钟超时机制。
应付金额从同一订单的可见标签集合中读取,兼容“应付:,13元”等标点;不跨无关联节点拼接,不读拼单价、优惠或实付。父子重复同金额去重,多值/缺失/无效/溢出省略,不因金额失败丢弃订单号与时间。仅存Admin,不推断支付、不改SYB金额、不修改地址行为。历史回填及界面语义未在本单统一,详见API契约#325补充。
采购订单资料完整性及简化单号回填(#326)
用户2026-09-19确认内部系统简化流程,原型v1通过。实现3a2472d,尚未发布或真实SYB验收。
采购任务保存 PDD 订单号、下单时间和订单金额即为资料完整,不检查是否已付款;金额0元有效。复用 pddOrderNo/orderSubmittedAt/pddOrderAmountCent,金额以人民币分存储。order_created 不改义,仍是已创建订单事实;缺金额展示“订单信息待补全”,不能当作采购失败再次下单。页面统一称“订单金额”,其来源可能是#325应付或既有回填实付,不能将历史值统一称已付金额。
Admin 复用未知结果处理弹窗增加金额输入,并为 live 已创建且缺资料任务提供“补全订单信息”;已有字段只读、缺项可填。保存中禁用提交,失败保留输入;沿用既有权限,不增加审批。非执行中的未知结果人工确认与已有订单资料补全都会事务内保证单号回填记录,不修改支付复核或触发设备操作。
SYB 回填与资料完整性独立:正式SYB任务已有单号且仍关联有效明细即可入队,不要求 order_created 状态、时间、金额、付款确认或地址后缀。只有订单号上传SYB;沿用同号成功、异号冲突不覆盖及既有在途防重复规则,不倒扫历史任务。历史补偿仍手动勾选,已成功或在途任务不可重复发起。
自动下单读取和Admin补录是后续目标来源;本单尚未删除插件或Agent我的订单回填,不能宣称上游地址后缀已取消或历史错误归属已修复。金额缺失不得自动采购,订单号唯一归属保护和永久不付款规则不变。
采购管理已回填 SYB 筛选(#327)
实现368f2c2,2026-09-19,尚未发布。采购管理现有“状态”下拉框增加“已回填 SYB”,用户选择后点击原查询按钮,按PDD单号回填队列成功记录筛选;不是新的采购任务状态,也不表示物流回填成功或已付款。
筛选后仍展示原采购状态与独立SYB单号回填状态,已成功任务不因查询而允许重复回填。清空或重置恢复原列表,查询回到第一页,其他条件继续叠加。沿用既有下拉框、空/加载/失败状态及权限,不新增页面、审批、数据字段或外部动作。
规格面板识别与选项去重(#331/#332)
实现 0edc78a(#332)、d8382e6(#331),2026-09-22 已合并 main 并发布 Server(Android 0.9.60 仅安装到设备 8);真机采购效果未验证。
- 规格面板识别在原有判定之后新增回退类型
REQUIRED_EVIDENCE:必须同时存在收货地址入口(打码手机号所在可点击行)、支付方式修改入口(支付别名所在可点击行)和唯一可用的数量输入框,三者须位于同一规格面板容器内;另需至少一项辅助证据(规格选项、已选/请选择摘要、关闭、加减数量、提交订单)。加减按钮不再是必备条件。原有已识别的面板分类不变。 - 地址入口只判断存在与否,不读取、不记录、不上传地址内容;诊断只输出布尔值与计数。
- 点击规格入口后、保存地址返回后,若面板仅靠回退类型识别,须连续两次采样结构一致才继续,上限 5 秒;等待期间不按返回键,超时明确失败。稳定且明显不是采购面板的页面(如地址列表)沿用原返回路径。
- 提交订单点击保持严格并进一步收紧:必须唯一、可点击、文字匹配,且文字节点及其可点击容器尺寸非零。
- 规格选项解析:同一选项块(外层可点击块与其内部文字)只计一个值,文字优先取外层块;不做“零差评/快要抢光”等标签清洗。选中确认失败时诊断列出该维度解析值(截断)、选中状态和目标值。
- 缺少必备证据时,失败信息附带可读提示,例如“未找到支付入口:请确认 PDD 默认支付方式为微信支付”“未找到收货地址入口:请确认 PDD 已设置默认收货地址”“未找到购买数量输入框”。
采购手机环境前提
执行采购的 Android 手机必须:PDD App 已登录、微信已登录、PDD 已设置默认收货地址、PDD 默认支付方式为微信支付。规格面板的地址与支付证据依赖该前提;不为支付宝等其他支付方式补充识别别名(有意决定)。条件不满足时 Agent 明确失败,不自动登录、不切换支付方式、不填写地址。