--- id: T-004 title: 导入本机蝦皮订单验证样本 phase: 0 deps: [T-001] status: DONE created: 2026-07-25 context_ref: d57c4ae2d42c6e48a2d0ad0e9f295cd354dc911a work_branch: main write_paths: - docs/tasks/T-004.md - android-buyer/build.gradle.kts - android-buyer/settings.gradle.kts - android-buyer/task-contract/** - android-buyer/tools/** - android-buyer/app/build.gradle.kts - android-buyer/app/src/main/java/com/roubao/autopilot/workflow/** - android-buyer/app/src/debug/** - android-buyer/app/src/test/** - .gitignore - README.md - docs/00-ai-start-here.md - docs/02-requirements.md - docs/03-tech-stack.md - docs/04-architecture.md - docs/05-coding-rules.md - docs/current-state.md - progress.md --- ## 问题 / 背景 第一层技术探针需要使用用户已有的蝦皮订单资料,而不是在 Android 代码里硬编码虚构 需求。本机目录中一份文本和一份参考图以蝦皮订单号同名;文本包含自己的店铺名、 待采集商品标题、SKU 和数量。Android 设备不能直接读取 Windows 绝对路径,需要一个 Debug/测试专用导入边界。 首份同名样例已在 2026-07-25 完成非业务内容核实:文本是可按 UTF-8 解码的无 BOM 四行格式,标签为 `店铺名:`、`商品标题:`、`SKU:`、`数量:`;参考图是可解码的 JPEG。正式私有目录、额外图片类型和一单多 SKU 规则仍未固定。 ## 关联需求与交互 - 功能:为 F-004 提供第一层原始输入,不改变正式 F-001 创建任务流程。 - 用户故事:US-004。 - 交互:无生产 UI;导入失败通过开发命令和测试报告返回。 - 架构/API:`04-architecture.md` 3.1;不调用正式后台 API。 ## 方案 1. 正式私有目录约定为仓库根目录 `private-fixtures/shopee/`,工具仍要求显式 `--input`;当前根目录样例保持原位并继续通过本地 exclude 隔离。 2. 以已核实的 UTF-8 四行标签和 JPEG 内容为首版契约;允许 `.jpg`/`.jpeg` 扩展名, 一张订单只允许一行 SKU 和一张参考图。 3. 实现开发机导入工具,按文件主名精确配对文本和唯一参考图。 4. 校验订单号、店铺名、标题、SKU、正整数数量、图片存在且可解码。 5. 生成与未来 HTTP `TaskSource` 同构的 `ProbeTask`,输出到被 Git 忽略的 `.local/` 目录,供 Debug 构建和测试装载。 6. 为有效样本、缺图、多图、重复订单号、未知编码/格式、非法数量和敏感日志编写测试。 ## 验收要点 - [x] 一组合法脱敏文本和参考图能稳定生成一个 `ProbeTask`。 - [x] `source_order_no` 来自文件主名;标题、SKU 和数量与原文完全一致。 - [x] 缺失或匹配到多张参考图、必填字段缺失、数量非法时导入明确失败。 - [x] Android workflow 通过 `TaskSource` 消费结果,不依赖 Windows 路径或导入器类型。 - [x] 真实订单文件、图片、生成物和本机绝对路径均未进入 Git。 - [x] 日志不包含完整订单号、店铺名或原图绝对路径。 - [x] 普通自动化测试不调用真实付费 VLM。 ## 边界 - 不实现 Go-Gin、SQLite、任务领取、鉴权或管理 Web。 - 不实现拼多多自动化和 VLM 供应商调用。 - 不把模糊文本解析结果当成成功,不静默选择重名图片。 - 不处理未经确认的一单多 SKU 格式。 ## 执行记录 ### 2026-07-25:任务开始 - 基于 T-003 提交 `d57c4ae` 开始,依赖 T-001 已满足。 - 前置检查确认一组同名文本/JPEG 存在,文本字段结构和图片解码有效;未记录或提交 实际订单号、店铺名、商品内容及图片。 - 固定首版规则:推荐私有目录为 `private-fixtures/shopee/`;只接收实际内容为 JPEG 的 `.jpg`/`.jpeg`;一张订单只有一个 SKU 和一张参考图,多 SKU 必须先扩展契约。 ### 2026-07-25:实现和验证完成 - 新增纯 Kotlin `task-contract` 模块,统一定义 `ProbeTask`、`ProbeReferenceImage`、 `TaskSource` 和版本化 JSON codec;Android 与开发机工具使用同一模型。 - 新增 `tools:shopee-importer` CLI。它要求显式输入/输出目录,严格解析 UTF-8 无 BOM 四行标签,只接受唯一且可解码的 JPEG,限制文本 64 KiB、图片 20 MiB,并为错误 返回稳定 code。 - 生成物使用匿名 `probe_id` 和匿名图片文件名,但私有 JSON 内保留权威 `source_order_no`、店铺名、标题、SKU、数量;参考图保存大小和 SHA-256。 - 输出目录必须为空或带工具 marker,避免清理任意目录;CLI 普通输出只有导入数量, 不打印完整订单号、店铺名或源路径。 - 新增 Debug `FixtureTaskSource` 和 `ProbeWorkflowCoordinator`。workflow 只依赖 `TaskSource`,不知道任务来自文件还是未来 HTTP。 - `syncProbeFixtures` 仅在显式传入 `-PprobeFixturesDir` 时把私有生成物放入 Debug 构建资产;不带属性的普通构建会清空先前生成资产。 - 脱敏测试覆盖 JSON round-trip、合法导入、缺图、多图、未知图片类型、非法 UTF-8、 缺字段、非法数量、损坏 JPEG、大小写重复订单号、敏感 CLI 输出和 Android TaskSource/workflow 边界。 - 真实本地样本运行成功并生成 1 个任务;自动比较确认订单号、店铺名、标题、SKU、 数量逐字段相等,参考图复制前后 SHA-256 相等。比较结果只记录布尔值,未输出内容。 - 带私有属性的 Debug APK 包含 1 个任务文档和 1 张匿名 JPEG;随后默认重建确认 APK 中 `probe-fixtures` 条目为 0,生成资产也已清除。 - 全量 `lintDebug test assembleDebug` 成功;三个模块共 38 次测试执行, 0 failure、0 error、0 skipped。