缺陷:PDD 链接失效被弹回首页时无法与通用「未进入商品详情页」失败区分 #165

Open
opened 2026-08-31 11:05:59 +08:00 by ila · 0 comments
Owner

Gitea MCP 未向当前会话暴露,按仓库规则回退项目根目录安全配置与 Gitea API 创建本工单;凭据未写入工单、代码或日志。

原始需求摘要

来源:用户于 2026-08-31 提问「Agent 通过浏览器打开 PDD 链接跳转商品页时,如果链接失效被跳到 PDD App 首页,失败提示文字是什么」,在只读核验后明确要求建单区分该失败场景与提示文案。

目的:把「链接已失效、被弹回 PDD 首页」从通用的「未进入商品详情页」兜底中分离出来,使运维能区分「换链接」与「重试/改规则」,并避免对必然失败的链接继续重试。

基线与已核实事实

代码基线:4e05048(2026-08-31)。核验日期 2026-08-31,范围为 Android 入口导航与错误码回传路径。

  • PddPageClassifier.classify(PddNavigation.kt:12-27)只在页面出现 商品已下架 / 商品不存在 / 链接已失效 / 页面不存在 时返回 PDD_LINK_INVALID。被弹回 PDD 首页时页面通常不含这些文字,分类器返回 null。
  • 因此当前实际落到兜底分支,采集路径为 PDD_DETAIL_ENTRY_FAILED / 未进入 PDD 商品详情页(PddProductDetailCollector.kt:628、PddNavigation.kt:80),采购路径为 PDD_DETAIL_ENTRY_FAILED / 没有进入拼多多商品页面(PurchaseRehearsalExecutor.kt:201、:213)。
  • 同一错误码同时覆盖三类性质不同的失败:链接失效被弹回首页、页面加载超时、页面证据规则与当前 PDD 版本不匹配。三者处置方式完全不同,但对外表现一致。
  • navigationRecovery.reopenBrowser 对 PDD_DETAIL_ENTRY_FAILED 会触发重开浏览器重试(PddNavigation.kt:66-79,maxAttempts 规则限制为 1)。链接已失效时该重试必然失败,浪费设备占用与 attempt 次数。
  • 服务端与 Web 均未对 PDD_DETAIL_ENTRY_FAILED 做二次映射(全仓检索无匹配),任务详情展示的即 Agent 上报原文。
  • ActivityEvidenceTracker 已提供经 Android 确认、按包名隔离的当前 Activity(GoAutoAccessibilityService.kt:96),RuleExecutor.kt:64 已按 step.activityName 精确校验;v2 规则 pageEvidence 已声明 packageName + activityName + selector(RuleContract.kt:204-212)。判定「停在 PDD 首页形态」无需新增机制。
  • 未确认:PDD 8.22.0 首页的精确 Activity 类名当前没有可复核证据,不得在本单中凭记忆写死。

目标

  1. 商品页证据等待超时后,若已确认当前停留在规则声明的 PDD 首页形态,报独立错误码与明确文案,不再混入通用兜底。
  2. 采集与采购两条入口路径复用同一判定与同一错误码,不各写一套。
  3. 该错误码不参与 reopenBrowser 重试,直接失败。
  4. 判定不成立时完全保持现有 PDD_DETAIL_ENTRY_FAILED 语义与文案不变。

非目标

  • 不进一步细分「加载超时」与「页面证据规则不匹配」;当前证据不足,另行评估。
  • 不修改 v2 页面证据规则的商品页判定逻辑、超时值或 transientSoldOutRecovery。
  • 不修改 #164 涉及的规格选择、复核与探测资格路径。
  • 不在 Android 代码中写死首页 Activity 或首页文案;判定依据只能来自服务端下发的规则。
  • 不保存控件树、整屏截图、账号、地址、订单或支付数据。
  • 不修改任何历史任务、结果或规则快照。

前置依赖与并行性

  • 代码区域与 #164(规格选择/复核)不重叠,实现可并行。
  • 但本单新增共享错误码,需更新 docs/08-agent-api-contract.md 与 Wiki Android-Agent-API-Contract;为避免与 #164 的契约改动冲突,契约文档与 Wiki 更新排在 #164 之后,或由两单协商合并为一次更新。
  • 依赖一次 CG30 现场取证以确认 PDD 首页 Activity 类名,取证前不得写入规则默认值。

固定实施方案

第 1 步:取证(先于编码)

在 CG30 / PDD 8.22.0 上,使用一个已失效的 PDD 链接执行安全采集,记录被弹回首页时 ActivityEvidenceTracker 给出的精确 Activity 类名。只记录包名与 Activity 类名,不记录页面文字、坐标、控件树或截图。取证结果写回本工单。

第 2 步:规则契约

v2 规则新增可选对象 linkExpiredEvidence:

  • 字段限定为 packageName、activityName(必填,精确相等)、可选 selector;沿用 rejectUnknown 严格校验,未知字段拒绝。
  • packageName 只允许 PDD 包名。
  • 未配置时行为与当前完全一致,不改变既有规则的执行结果。

第 3 步:Android 判定

  • 仅在商品页证据等待已经超时、即将返回 PDD_DETAIL_ENTRY_FAILED 的那一刻做一次判定。
  • 判定条件:当前包名为 PDD,且经 Android 确认的当前 Activity 与 linkExpiredEvidence.activityName 精确相等(配置了 selector 时该 selector 需唯一命中)。
  • 命中则返回新错误码 PDD_LINK_EXPIRED_TO_HOME,文案:商品链接已失效,被跳转到拼多多首页。
  • 任一条件不满足、Activity 未确认或规则未配置该证据,一律回落现有 PDD_DETAIL_ENTRY_FAILED 与原文案。不做包含匹配、前缀匹配或文字猜测。
  • 采集与采购共用同一判定函数,两条路径返回同一错误码与同一文案。

第 4 步:重试边界

PddDetailEntryRunner 只对 PDD_DETAIL_ENTRY_FAILED 触发 reopenBrowser 重试;PDD_LINK_EXPIRED_TO_HOME 立即返回,不重试。

第 5 步:契约与文档

在 docs/08-agent-api-contract.md 与 Wiki Android-Agent-API-Contract 记录 linkExpiredEvidence 规则字段、PDD_LINK_EXPIRED_TO_HOME 错误码语义及其不参与重试的约定。

验收标准

  • 规则配置 linkExpiredEvidence 且现场确认停在 PDD 首页时,采集与采购均报 PDD_LINK_EXPIRED_TO_HOME / 商品链接已失效,被跳转到拼多多首页。
  • 该错误码不触发 reopenBrowser 重试,任务一次失败。
  • 规则未配置 linkExpiredEvidence 时,行为、错误码与文案与基线 4e05048 完全一致。
  • Activity 不精确相等、包名不匹配或 Activity 未确认时回落 PDD_DETAIL_ENTRY_FAILED,不发生误判。
  • linkExpiredEvidence 含未知字段、非 PDD 包名或缺 activityName 时规则解析失败。
  • 采集与采购复用同一判定实现,不存在两份判定逻辑。
  • 诊断与错误信息不包含控件树、截图、坐标、账号、地址、订单或支付数据。
  • Android 单元测试与 APK 构建通过;受影响的服务端契约测试通过。
  • CG30 安全验证仅使用 executionMode=rehearsal 或采集任务;未修改地址、未创建订单、未支付。
  • 契约文档与 Wiki Android-Agent-API-Contract 已更新,在线回读 revision 后完成一次 sync 和一次 sync --check,revision 回写本工单。

必测场景

  • 停在 PDD 首页且规则已配置该证据 → PDD_LINK_EXPIRED_TO_HOME,无重试。
  • 停在 PDD 首页但规则未配置 → 维持 PDD_DETAIL_ENTRY_FAILED 及原文案与原重试行为。
  • 停在 PDD 登录页 / 验证码页 → 仍由 PddPageClassifier 优先返回原有登录、验证码、风控错误码,不被新判定抢占。
  • 页面出现「商品已下架 / 链接已失效」文字 → 仍返回 PDD_LINK_INVALID,不受影响。
  • 商品页加载慢但最终成功 → 不触发新错误码。
  • Activity 类名相近但不精确相等 → 不命中。
  • 规则解析:未知字段、非 PDD 包名、缺 activityName 分别拒绝。
  • 采购 rehearsal 路径与采集路径返回一致的错误码与文案。

风险与安全门禁

  • 属共享错误码契约变更,需与 #164 的契约改动协调更新顺序,避免同一文档并发冲突。
  • 首页 Activity 类名未经现场确认前不得写入规则或代码;取证缺失时停止实施。
  • 判定必须保持保守:证据不足一律回落原错误码,不得为提高识别率放宽为包含或前缀匹配。
  • 真机验证限定为采集任务或 rehearsal,不修改地址、不创建订单、不支付。

文档影响

有长期文档影响。 新增规则字段 linkExpiredEvidence 与错误码 PDD_LINK_EXPIRED_TO_HOME,须更新 docs/08-agent-api-contract.md 与 Wiki Android-Agent-API-Contract;在线回读 revision 后执行一次 python dev_scripts/harness.py sync 和一次 sync --check,revision 回写工单。

相邻问题(不在本单范围)

  • 「加载超时」与「页面证据规则不匹配」的进一步区分,证据不足,需要时另建工单。
  • #164 的规格选择失败阶段细分与本单同属「真实根因被通用错误码覆盖」,但代码路径独立,不合并。

状态

待确认(2026-08-31 创建,等待用户确认方案后方可实施)。

> Gitea MCP 未向当前会话暴露,按仓库规则回退项目根目录安全配置与 Gitea API 创建本工单;凭据未写入工单、代码或日志。 ## 原始需求摘要 来源:用户于 2026-08-31 提问「Agent 通过浏览器打开 PDD 链接跳转商品页时,如果链接失效被跳到 PDD App 首页,失败提示文字是什么」,在只读核验后明确要求建单区分该失败场景与提示文案。 目的:把「链接已失效、被弹回 PDD 首页」从通用的「未进入商品详情页」兜底中分离出来,使运维能区分「换链接」与「重试/改规则」,并避免对必然失败的链接继续重试。 ## 基线与已核实事实 代码基线:`4e05048`(2026-08-31)。核验日期 2026-08-31,范围为 Android 入口导航与错误码回传路径。 - `PddPageClassifier.classify`(`PddNavigation.kt:12-27`)只在页面出现 `商品已下架 / 商品不存在 / 链接已失效 / 页面不存在` 时返回 `PDD_LINK_INVALID`。被弹回 PDD 首页时页面通常不含这些文字,分类器返回 `null`。 - 因此当前实际落到兜底分支,采集路径为 `PDD_DETAIL_ENTRY_FAILED / 未进入 PDD 商品详情页`(`PddProductDetailCollector.kt:628`、`PddNavigation.kt:80`),采购路径为 `PDD_DETAIL_ENTRY_FAILED / 没有进入拼多多商品页面`(`PurchaseRehearsalExecutor.kt:201`、`:213`)。 - 同一错误码同时覆盖三类性质不同的失败:链接失效被弹回首页、页面加载超时、页面证据规则与当前 PDD 版本不匹配。三者处置方式完全不同,但对外表现一致。 - `navigationRecovery.reopenBrowser` 对 `PDD_DETAIL_ENTRY_FAILED` 会触发重开浏览器重试(`PddNavigation.kt:66-79`,`maxAttempts` 规则限制为 1)。链接已失效时该重试必然失败,浪费设备占用与 attempt 次数。 - 服务端与 Web 均未对 `PDD_DETAIL_ENTRY_FAILED` 做二次映射(全仓检索无匹配),任务详情展示的即 Agent 上报原文。 - `ActivityEvidenceTracker` 已提供经 Android 确认、按包名隔离的当前 Activity(`GoAutoAccessibilityService.kt:96`),`RuleExecutor.kt:64` 已按 `step.activityName` 精确校验;v2 规则 `pageEvidence` 已声明 `packageName + activityName + selector`(`RuleContract.kt:204-212`)。判定「停在 PDD 首页形态」无需新增机制。 - **未确认**:PDD 8.22.0 首页的精确 Activity 类名当前没有可复核证据,不得在本单中凭记忆写死。 ## 目标 1. 商品页证据等待超时后,若已确认当前停留在规则声明的 PDD 首页形态,报独立错误码与明确文案,不再混入通用兜底。 2. 采集与采购两条入口路径复用同一判定与同一错误码,不各写一套。 3. 该错误码不参与 `reopenBrowser` 重试,直接失败。 4. 判定不成立时完全保持现有 `PDD_DETAIL_ENTRY_FAILED` 语义与文案不变。 ## 非目标 - 不进一步细分「加载超时」与「页面证据规则不匹配」;当前证据不足,另行评估。 - 不修改 v2 页面证据规则的商品页判定逻辑、超时值或 `transientSoldOutRecovery`。 - 不修改 #164 涉及的规格选择、复核与探测资格路径。 - 不在 Android 代码中写死首页 Activity 或首页文案;判定依据只能来自服务端下发的规则。 - 不保存控件树、整屏截图、账号、地址、订单或支付数据。 - 不修改任何历史任务、结果或规则快照。 ## 前置依赖与并行性 - 代码区域与 #164(规格选择/复核)不重叠,实现可并行。 - 但本单新增共享错误码,需更新 `docs/08-agent-api-contract.md` 与 Wiki `Android-Agent-API-Contract`;为避免与 #164 的契约改动冲突,**契约文档与 Wiki 更新排在 #164 之后**,或由两单协商合并为一次更新。 - 依赖一次 CG30 现场取证以确认 PDD 首页 Activity 类名,取证前不得写入规则默认值。 ## 固定实施方案 ### 第 1 步:取证(先于编码) 在 CG30 / PDD 8.22.0 上,使用一个已失效的 PDD 链接执行安全采集,记录被弹回首页时 `ActivityEvidenceTracker` 给出的精确 Activity 类名。只记录包名与 Activity 类名,不记录页面文字、坐标、控件树或截图。取证结果写回本工单。 ### 第 2 步:规则契约 v2 规则新增可选对象 `linkExpiredEvidence`: - 字段限定为 `packageName`、`activityName`(必填,精确相等)、可选 `selector`;沿用 `rejectUnknown` 严格校验,未知字段拒绝。 - `packageName` 只允许 PDD 包名。 - 未配置时行为与当前完全一致,不改变既有规则的执行结果。 ### 第 3 步:Android 判定 - 仅在商品页证据等待已经超时、即将返回 `PDD_DETAIL_ENTRY_FAILED` 的那一刻做一次判定。 - 判定条件:当前包名为 PDD,且经 Android 确认的当前 Activity 与 `linkExpiredEvidence.activityName` 精确相等(配置了 `selector` 时该 selector 需唯一命中)。 - 命中则返回新错误码 `PDD_LINK_EXPIRED_TO_HOME`,文案:**商品链接已失效,被跳转到拼多多首页**。 - 任一条件不满足、Activity 未确认或规则未配置该证据,一律回落现有 `PDD_DETAIL_ENTRY_FAILED` 与原文案。不做包含匹配、前缀匹配或文字猜测。 - 采集与采购共用同一判定函数,两条路径返回同一错误码与同一文案。 ### 第 4 步:重试边界 `PddDetailEntryRunner` 只对 `PDD_DETAIL_ENTRY_FAILED` 触发 `reopenBrowser` 重试;`PDD_LINK_EXPIRED_TO_HOME` 立即返回,不重试。 ### 第 5 步:契约与文档 在 `docs/08-agent-api-contract.md` 与 Wiki `Android-Agent-API-Contract` 记录 `linkExpiredEvidence` 规则字段、`PDD_LINK_EXPIRED_TO_HOME` 错误码语义及其不参与重试的约定。 ## 验收标准 - [ ] 规则配置 `linkExpiredEvidence` 且现场确认停在 PDD 首页时,采集与采购均报 `PDD_LINK_EXPIRED_TO_HOME / 商品链接已失效,被跳转到拼多多首页`。 - [ ] 该错误码不触发 `reopenBrowser` 重试,任务一次失败。 - [ ] 规则未配置 `linkExpiredEvidence` 时,行为、错误码与文案与基线 `4e05048` 完全一致。 - [ ] Activity 不精确相等、包名不匹配或 Activity 未确认时回落 `PDD_DETAIL_ENTRY_FAILED`,不发生误判。 - [ ] `linkExpiredEvidence` 含未知字段、非 PDD 包名或缺 `activityName` 时规则解析失败。 - [ ] 采集与采购复用同一判定实现,不存在两份判定逻辑。 - [ ] 诊断与错误信息不包含控件树、截图、坐标、账号、地址、订单或支付数据。 - [ ] Android 单元测试与 APK 构建通过;受影响的服务端契约测试通过。 - [ ] CG30 安全验证仅使用 `executionMode=rehearsal` 或采集任务;未修改地址、未创建订单、未支付。 - [ ] 契约文档与 Wiki `Android-Agent-API-Contract` 已更新,在线回读 revision 后完成一次 `sync` 和一次 `sync --check`,revision 回写本工单。 ## 必测场景 - 停在 PDD 首页且规则已配置该证据 → `PDD_LINK_EXPIRED_TO_HOME`,无重试。 - 停在 PDD 首页但规则未配置 → 维持 `PDD_DETAIL_ENTRY_FAILED` 及原文案与原重试行为。 - 停在 PDD 登录页 / 验证码页 → 仍由 `PddPageClassifier` 优先返回原有登录、验证码、风控错误码,不被新判定抢占。 - 页面出现「商品已下架 / 链接已失效」文字 → 仍返回 `PDD_LINK_INVALID`,不受影响。 - 商品页加载慢但最终成功 → 不触发新错误码。 - Activity 类名相近但不精确相等 → 不命中。 - 规则解析:未知字段、非 PDD 包名、缺 `activityName` 分别拒绝。 - 采购 rehearsal 路径与采集路径返回一致的错误码与文案。 ## 风险与安全门禁 - 属共享错误码契约变更,需与 #164 的契约改动协调更新顺序,避免同一文档并发冲突。 - 首页 Activity 类名未经现场确认前不得写入规则或代码;取证缺失时停止实施。 - 判定必须保持保守:证据不足一律回落原错误码,不得为提高识别率放宽为包含或前缀匹配。 - 真机验证限定为采集任务或 `rehearsal`,不修改地址、不创建订单、不支付。 ## 文档影响 **有长期文档影响。** 新增规则字段 `linkExpiredEvidence` 与错误码 `PDD_LINK_EXPIRED_TO_HOME`,须更新 `docs/08-agent-api-contract.md` 与 Wiki `Android-Agent-API-Contract`;在线回读 revision 后执行一次 `python dev_scripts/harness.py sync` 和一次 `sync --check`,revision 回写工单。 ## 相邻问题(不在本单范围) - 「加载超时」与「页面证据规则不匹配」的进一步区分,证据不足,需要时另建工单。 - #164 的规格选择失败阶段细分与本单同属「真实根因被通用错误码覆盖」,但代码路径独立,不合并。 ## 状态 待确认(2026-08-31 创建,等待用户确认方案后方可实施)。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#165