fix(server): 图搜采集只缺评价数、销量、店铺名时也自动关联商品 #368

Open
opened 2026-10-08 14:01:13 +08:00 by ila · 6 comments
Owner

基本信息

  • 类型:缺陷修复 / 业务规则调整(服务端图搜自动关联条件)。
  • 状态:已在工单分支实施、提交及推送,待人工验收;未合并 main、未发布。
  • 本次变更:2026-10-08 用户在 Codex 会话明确授权实施 #368 并提交、推送工单分支;范围沿用已确认方案 A,不包含合并 main、发布或历史数据修复。
  • 来源:2026-10-08 用户反馈:「分析 26100710GREHBK 的 50012262039 图搜采集成功了,只是没有非必要的点赞数等,被判定失败,什么原因」。Claude Code 只读分析后,用户确认「缺少 shopName 不影响采购,建工单」。

已核验事实

原调查基线为 origin/main 7622795;2026-10-08 双方在main e450ac2 复核关联与提交代码。以下线上样例和统计为Claude此前2026-10-08只读调查记录,本次整合未重新查询生产数据,不代表实时状态。

样例

  • SYB 明细 26378(订单 26100710GREHBK),虾皮商品 17985(shopee_item_id=50012262039)。当前仍关联原 PDD 商品 1153,image_search_linked=0。
  • 图搜采集任务 2554(设备 9,10-08 12:01):找到 PDD 商品 9310(goods_id 1010062320398),状态 completed_partial,missing_json=["reviewCount"];规格和价格均已采集。
  • 图搜采集任务 2529(设备 7,10-08 11:24):找到另一个 PDD 商品 9927(goods_id 763676222053),状态 completed_partial,missing_json=["color","reviewCount"]。
  • 09-27 的图搜任务 1486 也找到了 1010062320398(missing_json=["salesText","reviewCount"])。

原因

  • server/app/goauto/task/image_search_link.go:35:autoLinkImageSearch 只在 task.Status == completed 时写入关联,否则直接返回、不报错;调用方为 result_service.go:126。
  • Android CollectionAssembler.kt:38-40:缺 shopName、salesText、reviewCount 时都会加入 missing,按 AGENTS.md「SKU 数据不完整仍须提交……记为 completed_partial」,任务状态为 completed_partial。
  • 结果:只缺评价数、销量、店铺名这类不影响采购的字段时,图搜已找到商品,但不会自动关联,也不会触发后续 AI 规格匹配(#287),表现为「图搜失败」。

影响面(image_search 来源,未删除)

  • 最近 7 天:completed 316,completed_partial 129,failed 117,cancelled 44,pending 8。
  • completed_partial 按 missing_json 分组(7 天内 / 历史累计):["reviewCount"] 51/143;["salesText"] 21/70;["shopName","reviewCount"] 2/10;["salesText","reviewCount"] 0/4。以上合计 7 天内约 74 条,历史约 227 条,只缺非必要字段。
  • 其余 partial 缺 color、size、spec_dimension_invalid:*、price:*、unsupportedDimension:* 等,影响规格或价格,不在本单放宽范围内。

目标与已确认决策

采用评论8991方案A:只放宽图搜自动关联资格。符合白名单的部分完成结果可以关联并进入原后续规格匹配流程;任务仍为 completed_partial,界面仍显示「部分完成」,missing_json 正常保留,不承诺AI一定匹配成功。

不采用方案B,不改 result_service.go 的状态判定,不把非必要字段缺失的任务改记为 completed。

非目标

  • 不放宽缺规格(color/size/规格维度)、缺价格或不支持维度的情况。
  • 不改 Android 采集逻辑和 completed_partial 的状态定义;不改手动关联、价格守卫和乐观并发判断。
  • 不自动创建采购任务(创建采购仍由人工点击,见 #287 说明)。
  • 不实现历史批量补关联、补偿扫描或回填脚本;历史修复另行定向确认范围和授权。本单不主动重新提交已结束任务。

实施方案(工单分支已实现,未发布)

  1. 仅修改自动关联资格:
    • status == completed 沿用原行为,包括正常 missing_json=[] 的任务。
    • 对 status == completed_partial,要求 missing_json 是可解析、非空的字符串数组,且每一项精确属于白名单 {reviewCount, salesText, shopName}。
    • 以下拒绝规则仅作用于completed_partial新增分支:空值、JSON null、空数组、非数组/非字符串项、解析失败、空项、未知项,或混入color/size/规格维度/价格/unsupportedDimension等任一白名单外字段,均不关联。不得把空数组拒绝规则应用到正常completed。
    • 其他任务状态不放宽。采用固定白名单/常量及注释,不引入可配置规则或前缀模糊匹配。
  2. 保留原边界:来源必须为image_search,PDDProductID及图搜快照有效、目标PDD active,沿用 OriginalPDDProductID 乐观比较。只有实际关联写入并返回Linked时才设置/保留图搜关联语义并进入原 #287 规格匹配;比较失败或目标停用不触发。
  3. 只进入原匹配流程,不保证匹配成功:不改变普通采集、手动当前页采集、状态统计、手动关联、价格保护、映射算法或置信度规则。AI不可用或无匹配结果时按原流程处理,不因此伪造完整采集或自动创建采购。
  4. 同图多结果:实时结果继续按原提交顺序及乐观比较处理;不新增“挑最新合格结果”的补偿逻辑。不得先过滤合格历史任务再取最新,从而跳过更新失败/不完整任务回退到旧商品。
  5. 幂等和耗时范围:现有SubmitResult后置hook的同步耗时、请求重放机制不在本单重构。回归确认新增partial分支未造成额外重复写入/错误关联或改变原异常处理;发现独立既有问题单独记录,不扩大本单。

子项目影响、依赖与并行

  • Server:task/image_search_link.go 及测试;不涉及数据库结构、接口、Android、Web。
  • 无新的前置功能依赖;历史补关联不在本单范围。
  • 与 #367 无直接依赖,可先实施本单;与Android独立修改可并行,最终按已合并main基线回归。

设计证据

非 UI 改动,无需原型;以本正文为准。

验收标准

  • completed原行为不变,特别覆盖missing_json为空数组的正常完成图搜任务。
  • completed_partial只包含reviewCount/salesText/shopName的非空任意组合时允许关联、写入image_search_linked,并进入原规格匹配流程。
  • partial的null/空字符串/[]/错误JSON/非字符串项/空项/未知项,以及混入color、size、spec_dimension_invalid:、price:、unsupportedDimension:*均拒绝。
  • PDD非active、快照或关联条件不满足、OriginalPDDProductID比较失败时不关联、不触发匹配。
  • 补SubmitResult完整提交链路回归,不只测helper:提交落库仍为partial且missing保留,正确建立关联并进入原匹配路径;普通采集与手动当前页采集状态/关联逻辑不变。
  • 使用模拟依赖验证匹配失败或无结果的原处理,不以关联成功宣称AI匹配成功;没有自动创建采购。
  • 回归请求重放、同图多任务提交、人工改关联及后置匹配耗时/异常边界;不顺手重构现有hook。
  • 单元/受影响集成测试和Server构建通过并如实记录;无Android/Web改动、无数据库迁移。
  • 不执行历史补关联、生产补偿脚本或真实AI/采购验证;线上发布和真实验证另行授权。

风险与回退

  • 只放宽不影响采购的字段,规格和价格的完整性要求不变。
  • 自动关联仍标记为「图搜关联」,在虾皮商品页、批量采购预览和采购任务列表上可见,供人工核对。
  • 代码回退:恢复只接受completed的资格条件,无结构迁移。
  • 数据回退与代码回退分开:不能只按image_search_linked=true筛选撤销,因为既有图搜关联也使用该标记。已落库关联如需修正,须按精确任务及商品范围、核实关联后未再修改,再单独确认执行;不批量覆盖人工或既有正常关联。

文档影响

实施完成后更新Wiki Business-Rules-and-Glossary的自动关联白名单及任务仍为部分完成的规则;先在线更新并回读revision,再执行一次sync与sync --check。已更新业务规则 Wiki(revision 2a897541f264a12eee8a455b99da0f5c556972d7),并使用 harness 的 --config 将同步及一致性检查限定到本单业务规则页,各一次;未混入其他工单运维镜像更新。历史补关联仍排除。

备注

  • 本单由 Claude Code 依据代码阅读和线上只读查询起草;工单不含个人信息。

正文整合记录

2026-10-08 经用户在Codex会话明确授权,整合评论8991/9011、SynapBus #101/#103及Codex补充意见。方案方向已审核;本单仍未实施,不把正文确认当作代码实施或线上发布授权。

分支交付(2026-10-08)

  • 基线 e450ac2;代码与测试 15ccab3,业务规则镜像 fcd6426;已推送 fix/368-image-search-partial-link,远端 HEAD fcd6426f8034cc965bbeedd0a1566c9a4bc850de。
  • 自动化验收项已完成,不代表用户已验收。工单保持 open/待验收;未合并、未发布、未修改历史业务数据。
  • 工作区 D:/OPC/goauto-worktrees/issue-368 干净。分支尚未合并,因此按规则保留 worktree。
  • 详细验证和限制见本轮完成评论;仓库 check --strict 仍存在 main 已有的未登记证据 Markdown 问题,不在本单扩大修复。
## 基本信息 - 类型:缺陷修复 / 业务规则调整(服务端图搜自动关联条件)。 - 状态:**已在工单分支实施、提交及推送,待人工验收;未合并 main、未发布**。 - 本次变更:2026-10-08 用户在 Codex 会话明确授权实施 #368 并提交、推送工单分支;范围沿用已确认方案 A,不包含合并 main、发布或历史数据修复。 - 来源:2026-10-08 用户反馈:「分析 26100710GREHBK 的 50012262039 图搜采集成功了,只是没有非必要的点赞数等,被判定失败,什么原因」。Claude Code 只读分析后,用户确认「缺少 shopName 不影响采购,建工单」。 ## 已核验事实 原调查基线为 origin/main `7622795`;2026-10-08 双方在main `e450ac2` 复核关联与提交代码。以下线上样例和统计为Claude此前2026-10-08只读调查记录,本次整合未重新查询生产数据,不代表实时状态。 ### 样例 - SYB 明细 26378(订单 `26100710GREHBK`),虾皮商品 17985(`shopee_item_id=50012262039`)。当前仍关联原 PDD 商品 1153,`image_search_linked=0`。 - 图搜采集任务 2554(设备 9,10-08 12:01):找到 PDD 商品 9310(goods_id 1010062320398),状态 `completed_partial`,`missing_json=["reviewCount"]`;规格和价格均已采集。 - 图搜采集任务 2529(设备 7,10-08 11:24):找到另一个 PDD 商品 9927(goods_id 763676222053),状态 `completed_partial`,`missing_json=["color","reviewCount"]`。 - 09-27 的图搜任务 1486 也找到了 1010062320398(`missing_json=["salesText","reviewCount"]`)。 ### 原因 - `server/app/goauto/task/image_search_link.go:35`:`autoLinkImageSearch` 只在 `task.Status == completed` 时写入关联,否则直接返回、不报错;调用方为 `result_service.go:126`。 - Android `CollectionAssembler.kt:38-40`:缺 `shopName`、`salesText`、`reviewCount` 时都会加入 `missing`,按 AGENTS.md「SKU 数据不完整仍须提交……记为 completed_partial」,任务状态为 `completed_partial`。 - 结果:只缺评价数、销量、店铺名这类不影响采购的字段时,图搜已找到商品,但不会自动关联,也不会触发后续 AI 规格匹配(#287),表现为「图搜失败」。 ### 影响面(image_search 来源,未删除) - 最近 7 天:completed 316,completed_partial 129,failed 117,cancelled 44,pending 8。 - completed_partial 按 missing_json 分组(7 天内 / 历史累计):`["reviewCount"]` 51/143;`["salesText"]` 21/70;`["shopName","reviewCount"]` 2/10;`["salesText","reviewCount"]` 0/4。以上合计 7 天内约 74 条,历史约 227 条,只缺非必要字段。 - 其余 partial 缺 `color`、`size`、`spec_dimension_invalid:*`、`price:*`、`unsupportedDimension:*` 等,影响规格或价格,不在本单放宽范围内。 ## 目标与已确认决策 采用评论8991方案A:只放宽图搜自动关联资格。符合白名单的部分完成结果可以关联并进入原后续规格匹配流程;任务仍为 `completed_partial`,界面仍显示「部分完成」,`missing_json` 正常保留,不承诺AI一定匹配成功。 不采用方案B,不改 `result_service.go` 的状态判定,不把非必要字段缺失的任务改记为 `completed`。 ## 非目标 - 不放宽缺规格(color/size/规格维度)、缺价格或不支持维度的情况。 - 不改 Android 采集逻辑和 `completed_partial` 的状态定义;不改手动关联、价格守卫和乐观并发判断。 - 不自动创建采购任务(创建采购仍由人工点击,见 #287 说明)。 - 不实现历史批量补关联、补偿扫描或回填脚本;历史修复另行定向确认范围和授权。本单不主动重新提交已结束任务。 ## 实施方案(工单分支已实现,未发布) 1. **仅修改自动关联资格**: - `status == completed` 沿用原行为,包括正常 `missing_json=[]` 的任务。 - 对 `status == completed_partial`,要求 `missing_json` 是可解析、非空的字符串数组,且每一项精确属于白名单 `{reviewCount, salesText, shopName}`。 - **以下拒绝规则仅作用于completed_partial新增分支**:空值、JSON null、空数组、非数组/非字符串项、解析失败、空项、未知项,或混入color/size/规格维度/价格/unsupportedDimension等任一白名单外字段,均不关联。不得把空数组拒绝规则应用到正常completed。 - 其他任务状态不放宽。采用固定白名单/常量及注释,不引入可配置规则或前缀模糊匹配。 2. **保留原边界**:来源必须为image_search,PDDProductID及图搜快照有效、目标PDD active,沿用 `OriginalPDDProductID` 乐观比较。只有实际关联写入并返回Linked时才设置/保留图搜关联语义并进入原 #287 规格匹配;比较失败或目标停用不触发。 3. **只进入原匹配流程,不保证匹配成功**:不改变普通采集、手动当前页采集、状态统计、手动关联、价格保护、映射算法或置信度规则。AI不可用或无匹配结果时按原流程处理,不因此伪造完整采集或自动创建采购。 4. **同图多结果**:实时结果继续按原提交顺序及乐观比较处理;不新增“挑最新合格结果”的补偿逻辑。不得先过滤合格历史任务再取最新,从而跳过更新失败/不完整任务回退到旧商品。 5. **幂等和耗时范围**:现有SubmitResult后置hook的同步耗时、请求重放机制不在本单重构。回归确认新增partial分支未造成额外重复写入/错误关联或改变原异常处理;发现独立既有问题单独记录,不扩大本单。 ## 子项目影响、依赖与并行 - Server:`task/image_search_link.go` 及测试;不涉及数据库结构、接口、Android、Web。 - 无新的前置功能依赖;历史补关联不在本单范围。 - 与 #367 无直接依赖,可先实施本单;与Android独立修改可并行,最终按已合并main基线回归。 ## 设计证据 非 UI 改动,无需原型;以本正文为准。 ## 验收标准 - [x] completed原行为不变,特别覆盖missing_json为空数组的正常完成图搜任务。 - [x] completed_partial只包含reviewCount/salesText/shopName的非空任意组合时允许关联、写入image_search_linked,并进入原规格匹配流程。 - [x] partial的null/空字符串/[]/错误JSON/非字符串项/空项/未知项,以及混入color、size、spec_dimension_invalid:*、price:*、unsupportedDimension:*均拒绝。 - [x] PDD非active、快照或关联条件不满足、OriginalPDDProductID比较失败时不关联、不触发匹配。 - [x] 补SubmitResult完整提交链路回归,不只测helper:提交落库仍为partial且missing保留,正确建立关联并进入原匹配路径;普通采集与手动当前页采集状态/关联逻辑不变。 - [x] 使用模拟依赖验证匹配失败或无结果的原处理,不以关联成功宣称AI匹配成功;没有自动创建采购。 - [x] 回归请求重放、同图多任务提交、人工改关联及后置匹配耗时/异常边界;不顺手重构现有hook。 - [x] 单元/受影响集成测试和Server构建通过并如实记录;无Android/Web改动、无数据库迁移。 - [x] 不执行历史补关联、生产补偿脚本或真实AI/采购验证;线上发布和真实验证另行授权。 ## 风险与回退 - 只放宽不影响采购的字段,规格和价格的完整性要求不变。 - 自动关联仍标记为「图搜关联」,在虾皮商品页、批量采购预览和采购任务列表上可见,供人工核对。 - 代码回退:恢复只接受completed的资格条件,无结构迁移。 - 数据回退与代码回退分开:不能只按image_search_linked=true筛选撤销,因为既有图搜关联也使用该标记。已落库关联如需修正,须按精确任务及商品范围、核实关联后未再修改,再单独确认执行;不批量覆盖人工或既有正常关联。 ## 文档影响 实施完成后更新Wiki Business-Rules-and-Glossary的自动关联白名单及任务仍为部分完成的规则;先在线更新并回读revision,再执行一次sync与sync --check。已更新业务规则 Wiki(revision `2a897541f264a12eee8a455b99da0f5c556972d7`),并使用 harness 的 --config 将同步及一致性检查限定到本单业务规则页,各一次;未混入其他工单运维镜像更新。历史补关联仍排除。 ## 备注 - 本单由 Claude Code 依据代码阅读和线上只读查询起草;工单不含个人信息。 ## 正文整合记录 2026-10-08 经用户在Codex会话明确授权,整合评论8991/9011、SynapBus #101/#103及Codex补充意见。方案方向已审核;本单仍未实施,不把正文确认当作代码实施或线上发布授权。 ## 分支交付(2026-10-08) - 基线 `e450ac2`;代码与测试 `15ccab3`,业务规则镜像 `fcd6426`;已推送 `fix/368-image-search-partial-link`,远端 HEAD `fcd6426f8034cc965bbeedd0a1566c9a4bc850de`。 - 自动化验收项已完成,不代表用户已验收。工单保持 open/待验收;未合并、未发布、未修改历史业务数据。 - 工作区 `D:/OPC/goauto-worktrees/issue-368` 干净。分支尚未合并,因此按规则保留 worktree。 - 详细验证和限制见本轮完成评论;仓库 check --strict 仍存在 main 已有的未登记证据 Markdown 问题,不在本单扩大修复。
Author
Owner

方案决定:只改自动关联,不改任务状态(2026-10-08,Claude Code 记录用户决定)

讨论过两种做法:

  • A:只放宽 autoLinkImageSearch 的条件(本单正文方案);
  • B:服务端判定状态时,缺失项全为 reviewCount、salesText、shopName 就记为 completed。

用户选择 A。 因此本单明确:

  • 只缺这三项的采集任务,状态仍为 completed_partial,界面仍显示「部分完成」,missing_json 照常记录;
  • 只放宽图搜自动关联:符合白名单的部分完成任务照常关联,并触发规格匹配;
  • 不改 result_service.go:181-183 的状态判定,不影响普通采集和手动当前页采集的状态及统计。

背景(已核对 origin/main 7622795):AI 规格匹配资格(ai_match_eligibility.go:88)、替代商品(replacement/service.go:287)、颜色图片(color_image_service.go:147)、当前页关联(latest_collection.go:145)已经把 completed_partial 视为可用结果;image_search_link.go:35 是唯一只认 completed 的地方。

## 方案决定:只改自动关联,不改任务状态(2026-10-08,Claude Code 记录用户决定) 讨论过两种做法: - A:只放宽 `autoLinkImageSearch` 的条件(本单正文方案); - B:服务端判定状态时,缺失项全为 `reviewCount`、`salesText`、`shopName` 就记为 `completed`。 **用户选择 A。** 因此本单明确: - 只缺这三项的采集任务,状态**仍为 `completed_partial`**,界面仍显示「部分完成」,`missing_json` 照常记录; - 只放宽图搜自动关联:符合白名单的部分完成任务照常关联,并触发规格匹配; - 不改 `result_service.go:181-183` 的状态判定,不影响普通采集和手动当前页采集的状态及统计。 背景(已核对 origin/main `7622795`):AI 规格匹配资格(`ai_match_eligibility.go:88`)、替代商品(`replacement/service.go:287`)、颜色图片(`color_image_service.go:147`)、当前页关联(`latest_collection.go:145`)已经把 `completed_partial` 视为可用结果;`image_search_link.go:35` 是唯一只认 `completed` 的地方。
Author
Owner

方案讨论共识(2026-10-08,Claude Code,回复 SynapBus #99/#100)

依据 Codex 审核意见(核对基线 main e450ac2)。Claude Code 已独立核对,4 点全部采纳。本评论不修改正文;整合进正文需用户授权。

  1. 范围:按评论 8991 方案 A,只修改 autoLinkImageSearch 的资格判断;completed_partial 和 missing_json 保持不变;不改普通采集、手动关联、Android,也不放行缺价格或缺规格的情况。
    • 白名单精确为 reviewCount、salesText、shopName。
    • 以下情况一律拒绝:missing_json 为 null、为 []、JSON 无效、存在空项、存在白名单外的项、与规格或价格缺失混合。
  2. 保留的判断与测试:保留 source=image_search、PDD 为 active、OriginalPDDProductID 乐观比较,以及只有 Linked 时才触发 #287 匹配。补 SubmitResult 全链路回归,而不只测 helper:
    • 落库状态仍为 partial;
    • 关联生效并进入原匹配流程;
    • CAS 失败或 PDD 停用时不触发;
    • 普通采集和 completed 行为不变。
      注意:关联成功不等于 AI 匹配一定成功。现有 hook 的同步耗时和重放特性本单不重构,但需回归,确认不恶化。
  3. 去掉历史补关联:本单只覆盖今后的结果路径;历史数据另行定向授权。
    • 原正文「取最新符合条件的一条」有缺陷:它会跳过更新的失败或不完整任务,回退到更旧的商品。
    • 以后如果要做:先确定范围内最新的有效任务,再判断它是否符合资格;不能先过滤出合格任务再取最新。
  4. 回退:不能只按 image_search_linked=true 筛选,因为既有的图搜关联也使用这个标记。代码可以直接回退;已落库的关联需按精确的任务和商品范围,并确认关联之后未再改动,另行处理。

建议正文据此更新:删除方案第 4 点「历史数据(可选)」的实施范围,并修正「风险与回退」中按标记回退的表述。可以先于 #367 实施。

## 方案讨论共识(2026-10-08,Claude Code,回复 SynapBus #99/#100) 依据 Codex 审核意见(核对基线 main `e450ac2`)。Claude Code 已独立核对,4 点全部采纳。本评论不修改正文;整合进正文需用户授权。 1. **范围**:按评论 8991 方案 A,只修改 `autoLinkImageSearch` 的资格判断;`completed_partial` 和 `missing_json` 保持不变;不改普通采集、手动关联、Android,也不放行缺价格或缺规格的情况。 - 白名单精确为 `reviewCount`、`salesText`、`shopName`。 - 以下情况一律拒绝:`missing_json` 为 null、为 `[]`、JSON 无效、存在空项、存在白名单外的项、与规格或价格缺失混合。 2. **保留的判断与测试**:保留 `source=image_search`、PDD 为 active、`OriginalPDDProductID` 乐观比较,以及只有 Linked 时才触发 #287 匹配。补 SubmitResult 全链路回归,而不只测 helper: - 落库状态仍为 partial; - 关联生效并进入原匹配流程; - CAS 失败或 PDD 停用时不触发; - 普通采集和 `completed` 行为不变。 注意:关联成功不等于 AI 匹配一定成功。现有 hook 的同步耗时和重放特性本单不重构,但需回归,确认不恶化。 3. **去掉历史补关联**:本单只覆盖今后的结果路径;历史数据另行定向授权。 - 原正文「取最新符合条件的一条」有缺陷:它会跳过更新的失败或不完整任务,回退到更旧的商品。 - 以后如果要做:先确定范围内最新的有效任务,再判断它是否符合资格;不能先过滤出合格任务再取最新。 4. **回退**:不能只按 `image_search_linked=true` 筛选,因为既有的图搜关联也使用这个标记。代码可以直接回退;已落库的关联需按精确的任务和商品范围,并确认关联之后未再改动,另行处理。 建议正文据此更新:删除方案第 4 点「历史数据(可选)」的实施范围,并修正「风险与回退」中按标记回退的表述。可以先于 #367 实施。
Author
Owner

开始实施(2026-10-08)

用户在Codex会话明确授权实施并提交、推送工单分支;不合并main、不发布线上。基线最新origin/main e450ac28989de6827328b411e4bdc050dded9ab3;独立worktree D:/OPC/goauto-worktrees/issue-368,分支fix/368-image-search-partial-link。

实施计划:

  1. 检查已有task测试基线;在image_search_link相关测试补partial白名单/非法输入/原completed保护及SubmitResult链路测试,先观察缺少实现导致的失败。
  2. 仅在server/app/goauto/task/image_search_link.go增加严格资格判断:completed原行为不变;partial必须非空字符串数组且每项属于reviewCount/salesText/shopName;保留原source/PDD active/CAS及匹配调用。
  3. 跑受影响task及依赖回归和Server构建;验证无状态判定、接口、迁移、Android/Web或历史补关联改动。
  4. 更新Business-Rules-and-Glossary为分支实现/未发布事实,回读revision,再一次sync和sync --check;提交推送本工单分支并通知Claude审核。未执行的线上/真机行为如实列出,保持待验收。
### 开始实施(2026-10-08) 用户在Codex会话明确授权实施并提交、推送工单分支;不合并main、不发布线上。基线最新origin/main e450ac28989de6827328b411e4bdc050dded9ab3;独立worktree D:/OPC/goauto-worktrees/issue-368,分支fix/368-image-search-partial-link。 实施计划: 1. 检查已有task测试基线;在image_search_link相关测试补partial白名单/非法输入/原completed保护及SubmitResult链路测试,先观察缺少实现导致的失败。 2. 仅在server/app/goauto/task/image_search_link.go增加严格资格判断:completed原行为不变;partial必须非空字符串数组且每项属于reviewCount/salesText/shopName;保留原source/PDD active/CAS及匹配调用。 3. 跑受影响task及依赖回归和Server构建;验证无状态判定、接口、迁移、Android/Web或历史补关联改动。 4. 更新Business-Rules-and-Glossary为分支实现/未发布事实,回读revision,再一次sync和sync --check;提交推送本工单分支并通知Claude审核。未执行的线上/真机行为如实列出,保持待验收。
Author
Owner

实施完成,待验收(2026-10-08)

交付

  • 基线 origin/main e450ac28989de6827328b411e4bdc050dded9ab3。
  • 分支 fix/368-image-search-partial-link 已非强制推送;远端回读 HEAD fcd6426f8034cc965bbeedd0a1566c9a4bc850de。
  • 代码/测试提交 15ccab3,Wiki 镜像提交 fcd6426。
  • 仅 3 个文件:server/app/goauto/task/image_search_link.go、新增 image_search_partial_test.go、docs/03-business-rules-and-glossary.md。
  • 原 completed 行为保持;新增 partial 非空精确白名单。原 source/目标 active/快照/CAS/Linked 后匹配流程未修改,任务状态和 missing 不改。

测试证据

Windows,Go 1.26.5;仅测试进程启用 CGO=1 与已安装 GCC。测试用隔离 SQLite 内存库和本地 httptest ERP,不读取/写入本地 MySQL 或生产数据。

  • 先补测试并观察旧实现失败:白名单组合及实际 SubmitResult partial 关联被拒;原 completed 和拒绝用例通过。随后最小实现后转绿。
  • 最终 go test ./app/goauto/task ./app/goauto/purchase ./app/goauto/shopeeproduct ./app/goauto/shopeespec -count=1:4 包均通过(8.078s / 13.179s / 11.050s / 0.055s)。
  • go build ./...:退出 0。
  • git diff --check:通过;提交后工作区干净。

覆盖:

  1. 3 项可选字段全部 7 种非空组合、重复合法项、正常 completed 空数组/nil;partial nil/null/空串/空数组/错 JSON/非数组/非字符串/空项/未知/大小写空白差异/颜色/尺码/价格/price:/unsupportedDimension:/非法维度拒绝。
  2. 实际 SubmitResult 持久化 → 自动关联 → 原规格同步和匹配 → confirmed 映射落库,partial/missing 保留。
  3. 普通 admin、agent_current_page、PDD 停用、人工改关联、缺快照不关联/不触发匹配。
  4. 结果重放不重复子记录/匹配;同图同原关联快照第二个结果不覆盖先落库关联;不自动创建采购。
  5. ERP 模拟 503、无精确候选且 AI 未配置时保留成功提交和关联,不制造映射。
  6. 实际匹配启动后取消入站 context,映射仍持久化;原 Detail(ctx) 读取取消错误保持不变,另用新 context 回读核验已提交状态,再验证重放。不宣称断开的客户端收到成功响应,不重构同步耗时/重放机制。

审核与文档

  • 按 requesting-code-review 技能完成只读审核;补齐审核指出的实际提交链路取消场景后复核无遗留问题。
  • 线上 Business-Rules-and-Glossary 已更新、回读内容一致,revision 2a897541f264a12eee8a455b99da0f5c556972d7。
  • 一次 harness.py sync --config <本单临时映射> 和一次 sync --check --config <同映射> 通过。限定本单业务规则页以避免混入其他工单运维镜像更新;临时无凭据映射已删除。
  • harness.py check --strict 未通过:main 已存在 docs/evidence/pdd-home-35727-summary.md 未登记为 Wiki 镜像;文件在 origin/main 中,#368 未修改该文件、检查脚本或映射配置。未顺手修复。

未覆盖/未执行

  • 没有 MySQL 8 集成、真实 AI、真机或线上验证;SQLite 测试不冒充 MySQL 验证。
  • 无 Android/Web/API/schema/迁移变化;未合并 main、未重启任何服务、未发布、未补关联历史数据。
  • worktree 保留:尚未合并,暂不满足删除条件。工单保持 open/待人工验收。
## 实施完成,待验收(2026-10-08) ### 交付 - 基线 origin/main `e450ac28989de6827328b411e4bdc050dded9ab3`。 - 分支 `fix/368-image-search-partial-link` 已非强制推送;远端回读 HEAD `fcd6426f8034cc965bbeedd0a1566c9a4bc850de`。 - 代码/测试提交 `15ccab3`,Wiki 镜像提交 `fcd6426`。 - 仅 3 个文件:`server/app/goauto/task/image_search_link.go`、新增 `image_search_partial_test.go`、`docs/03-business-rules-and-glossary.md`。 - 原 completed 行为保持;新增 partial 非空精确白名单。原 source/目标 active/快照/CAS/Linked 后匹配流程未修改,任务状态和 missing 不改。 ### 测试证据 Windows,Go 1.26.5;仅测试进程启用 CGO=1 与已安装 GCC。测试用隔离 SQLite 内存库和本地 httptest ERP,不读取/写入本地 MySQL 或生产数据。 - 先补测试并观察旧实现失败:白名单组合及实际 SubmitResult partial 关联被拒;原 completed 和拒绝用例通过。随后最小实现后转绿。 - 最终 `go test ./app/goauto/task ./app/goauto/purchase ./app/goauto/shopeeproduct ./app/goauto/shopeespec -count=1`:4 包均通过(8.078s / 13.179s / 11.050s / 0.055s)。 - `go build ./...`:退出 0。 - `git diff --check`:通过;提交后工作区干净。 覆盖: 1. 3 项可选字段全部 7 种非空组合、重复合法项、正常 completed 空数组/nil;partial nil/null/空串/空数组/错 JSON/非数组/非字符串/空项/未知/大小写空白差异/颜色/尺码/价格/price:*/unsupportedDimension:*/非法维度拒绝。 2. 实际 SubmitResult 持久化 → 自动关联 → 原规格同步和匹配 → confirmed 映射落库,partial/missing 保留。 3. 普通 admin、agent_current_page、PDD 停用、人工改关联、缺快照不关联/不触发匹配。 4. 结果重放不重复子记录/匹配;同图同原关联快照第二个结果不覆盖先落库关联;不自动创建采购。 5. ERP 模拟 503、无精确候选且 AI 未配置时保留成功提交和关联,不制造映射。 6. 实际匹配启动后取消入站 context,映射仍持久化;原 Detail(ctx) 读取取消错误保持不变,另用新 context 回读核验已提交状态,再验证重放。不宣称断开的客户端收到成功响应,不重构同步耗时/重放机制。 ### 审核与文档 - 按 requesting-code-review 技能完成只读审核;补齐审核指出的实际提交链路取消场景后复核无遗留问题。 - 线上 Business-Rules-and-Glossary 已更新、回读内容一致,revision `2a897541f264a12eee8a455b99da0f5c556972d7`。 - 一次 `harness.py sync --config <本单临时映射>` 和一次 `sync --check --config <同映射>` 通过。限定本单业务规则页以避免混入其他工单运维镜像更新;临时无凭据映射已删除。 - `harness.py check --strict` **未通过**:main 已存在 `docs/evidence/pdd-home-35727-summary.md` 未登记为 Wiki 镜像;文件在 origin/main 中,#368 未修改该文件、检查脚本或映射配置。未顺手修复。 ### 未覆盖/未执行 - 没有 MySQL 8 集成、真实 AI、真机或线上验证;SQLite 测试不冒充 MySQL 验证。 - 无 Android/Web/API/schema/迁移变化;未合并 main、未重启任何服务、未发布、未补关联历史数据。 - worktree 保留:尚未合并,暂不满足删除条件。工单保持 open/待人工验收。
Author
Owner

实施审核(2026-10-08,Claude Code,回复 SynapBus #109~#112)

审核对象:分支 fix/368-image-search-partial-link,base e450ac2,代码与测试 15ccab3,文档 fcd6426。只读审核。

结论

达标,没有阻塞项;满足工单的实施范围。 合并 main 和发布需用户另行确认。

已核对

  1. 范围:只改 server/app/goauto/task/image_search_link.go(+32/-5),新增 image_search_partial_test.go,更新业务规则镜像。没有改 Android、Web、API、迁移,也没有做历史补关联。
  2. 资格判断 imageSearchResultAllowsAutoLink(约 98~121 行):
    • completed 直接放行,原行为不变,包括 missing_json 为 nil 或 [] 的情况;
    • completed_partial 要求 MissingJSON 非空、能解析为 []string、长度大于 0,且每一项都精确等于 reviewCount、salesText 或 shopName;
    • 不修剪空白,不忽略大小写,不按前缀匹配;
    • 数组中的 null 元素会解析成空字符串并被拒绝,数字元素会解析失败。以上与正文一致。
  3. 资格判断与现有 missing 来源的配合:result_service.go 中维度值无效时会写入 spec_dimension_invalid:<key>,并因此把状态置为 partial;这一项不在白名单内,会被拒绝。因此「SKU 被剔除但 missing 只有可选字段」的漏放情况不存在。
  4. 保留的边界:source=image_search、PDDProductID 与快照非空、PDD 为 active、OriginalPDDProductID 的 CAS 比较、只有实际写入(Linked)才触发后续匹配。这些代码都没有改动,只是把原来的 Status != completed 换成了资格函数。
  5. 测试:
    • TestAutoLinkImageSearchPartialMissingWhitelist 共 32 个用例,覆盖 completed 加 []/nil、nil、空串、null、[]、格式错误、对象、标量、数字项、null 项、空项、未知字段、大小写、空白、color/size/price、price:*、不支持维度、无效维度、pending/failed、重复的可选项,以及三项可选字段的 7 种组合;
    • TestSubmitImageSearchPartialLinkAndMatch 走真实 SubmitResult 链路。
  6. Wiki:Business-Rules 新增的小节与实现一致,并写明任务仍为 partial、关联成功不等于 AI 匹配成功、不自动采购,以及验证边界。

非阻塞建议

  • 资格函数的注释说「三项均为可选描述信息」。以后 Android 新增 missing 字段时,白名单默认拒绝,这样安全;但需要在新增字段的工单里明确评估是否加入白名单。Wiki 已有相应表述,无需本单处理。

未验证

  • 没有独立运行测试:本机 Go 版本为 1.24.0,go.mod 要求 >= 1.26.5(GOTOOLCHAIN=local),4 个包的测试和 go build 都以 Codex 报告为准。
  • 测试使用 SQLite 加本地 mock ERP,没有验证 MySQL、真实 AI 和线上环境。
## 实施审核(2026-10-08,Claude Code,回复 SynapBus #109~#112) 审核对象:分支 `fix/368-image-search-partial-link`,base `e450ac2`,代码与测试 `15ccab3`,文档 `fcd6426`。只读审核。 ### 结论 **达标,没有阻塞项;满足工单的实施范围。** 合并 main 和发布需用户另行确认。 ### 已核对 1. **范围**:只改 `server/app/goauto/task/image_search_link.go`(+32/-5),新增 `image_search_partial_test.go`,更新业务规则镜像。没有改 Android、Web、API、迁移,也没有做历史补关联。 2. **资格判断** `imageSearchResultAllowsAutoLink`(约 98~121 行): - `completed` 直接放行,原行为不变,包括 `missing_json` 为 nil 或 `[]` 的情况; - `completed_partial` 要求 `MissingJSON` 非空、能解析为 `[]string`、长度大于 0,且每一项都精确等于 `reviewCount`、`salesText` 或 `shopName`; - 不修剪空白,不忽略大小写,不按前缀匹配; - 数组中的 `null` 元素会解析成空字符串并被拒绝,数字元素会解析失败。以上与正文一致。 3. **资格判断与现有 missing 来源的配合**:`result_service.go` 中维度值无效时会写入 `spec_dimension_invalid:<key>`,并因此把状态置为 partial;这一项不在白名单内,会被拒绝。因此「SKU 被剔除但 missing 只有可选字段」的漏放情况不存在。 4. **保留的边界**:`source=image_search`、`PDDProductID` 与快照非空、PDD 为 active、`OriginalPDDProductID` 的 CAS 比较、只有实际写入(Linked)才触发后续匹配。这些代码都没有改动,只是把原来的 `Status != completed` 换成了资格函数。 5. **测试**: - `TestAutoLinkImageSearchPartialMissingWhitelist` 共 32 个用例,覆盖 completed 加 `[]`/nil、nil、空串、null、`[]`、格式错误、对象、标量、数字项、null 项、空项、未知字段、大小写、空白、color/size/price、`price:*`、不支持维度、无效维度、pending/failed、重复的可选项,以及三项可选字段的 7 种组合; - `TestSubmitImageSearchPartialLinkAndMatch` 走真实 SubmitResult 链路。 6. **Wiki**:Business-Rules 新增的小节与实现一致,并写明任务仍为 partial、关联成功不等于 AI 匹配成功、不自动采购,以及验证边界。 ### 非阻塞建议 - 资格函数的注释说「三项均为可选描述信息」。以后 Android 新增 missing 字段时,白名单默认拒绝,这样安全;但需要在新增字段的工单里明确评估是否加入白名单。Wiki 已有相应表述,无需本单处理。 ### 未验证 - **没有独立运行测试**:本机 Go 版本为 1.24.0,`go.mod` 要求 >= 1.26.5(GOTOOLCHAIN=local),4 个包的测试和 `go build` 都以 Codex 报告为准。 - 测试使用 SQLite 加本地 mock ERP,没有验证 MySQL、真实 AI 和线上环境。
Author
Owner

审核补充:独立运行测试(2026-10-08,Claude Code)

补充评论 9026 中「未独立运行测试」一项。

  • 代码:fcd6426,在临时 detached worktree 中检出,运行后已删除。
  • 工具链:直接使用本机模块缓存中的 golang.org/toolchain@v0.0.1-go1.26.5.windows-amd64 的 go.exe,未改系统 Go。
  • 环境:CGO_ENABLED=1。本机全局 go env 为 CGO_ENABLED=0,在此设置下 go-sqlite3 测试会以「requires cgo」失败,这是环境原因,与本单无关。

结果:

  • go test ./app/goauto/task/ ./app/goauto/purchase/ ./app/goauto/shopeeproduct/ ./app/goauto/shopeespec/ -count=1:4 个包全部 ok。
  • go test ./app/goauto/task/ -run 'ImageSearchPartial|SubmitImageSearchPartial' -v:43 个 PASS(含子测试),0 FAIL。
  • go build:成功。

结论不变:达标,无阻塞项。仍未验证 MySQL、真实 AI 和线上环境。

## 审核补充:独立运行测试(2026-10-08,Claude Code) 补充评论 9026 中「未独立运行测试」一项。 - 代码:`fcd6426`,在临时 detached worktree 中检出,运行后已删除。 - 工具链:直接使用本机模块缓存中的 `golang.org/toolchain@v0.0.1-go1.26.5.windows-amd64` 的 `go.exe`,未改系统 Go。 - 环境:`CGO_ENABLED=1`。本机全局 go env 为 `CGO_ENABLED=0`,在此设置下 go-sqlite3 测试会以「requires cgo」失败,这是环境原因,与本单无关。 结果: - `go test ./app/goauto/task/ ./app/goauto/purchase/ ./app/goauto/shopeeproduct/ ./app/goauto/shopeespec/ -count=1`:4 个包全部 ok。 - `go test ./app/goauto/task/ -run 'ImageSearchPartial|SubmitImageSearchPartial' -v`:43 个 PASS(含子测试),0 FAIL。 - `go build`:成功。 结论不变:达标,无阻塞项。仍未验证 MySQL、真实 AI 和线上环境。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#368