From 50a6d8ee5b86a45faefb57dd642aadf3cbc85c1d Mon Sep 17 00:00:00 2001 From: QiuSW <105186638@qq.com> Date: Sat, 25 Jul 2026 16:59:06 +0800 Subject: [PATCH] docs: establish project harness baseline --- .gitattributes | 7 + .gitignore | 38 +++ AGENTS.md | 88 +++++++ CLAUDE.md | 7 + README.md | 57 +++++ deepseek总结.txt | 100 ++++++++ docs/00-ai-start-here.md | 93 +++++++ docs/01-vision.md | 46 ++++ docs/02-requirements.md | 111 +++++++++ docs/03-tech-stack.md | 159 ++++++++++++ docs/04-architecture.md | 312 ++++++++++++++++++++++++ docs/05-coding-rules.md | 94 +++++++ docs/06-tasks.md | 75 ++++++ docs/07-user-stories.md | 161 ++++++++++++ docs/08-interaction-checklist.md | 242 ++++++++++++++++++ docs/README.md | 46 ++++ docs/agent-context.json | 88 +++++++ docs/agent-context.md | 35 +++ docs/agent-context.schema.json | 94 +++++++ docs/api.md | 406 +++++++++++++++++++++++++++++++ docs/clean-state-checklist.md | 16 ++ docs/current-state.md | 67 +++++ docs/design/README.md | 35 +++ docs/routes.md | 52 ++++ docs/tasks/README.md | 73 ++++++ docs/tasks/T-001.md | 105 ++++++++ docs/tasks/_template.md | 42 ++++ init.ps1 | 33 +++ init.sh | 28 +++ progress.md | 32 +++ 30 files changed, 2742 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 README.md create mode 100644 deepseek总结.txt create mode 100644 docs/00-ai-start-here.md create mode 100644 docs/01-vision.md create mode 100644 docs/02-requirements.md create mode 100644 docs/03-tech-stack.md create mode 100644 docs/04-architecture.md create mode 100644 docs/05-coding-rules.md create mode 100644 docs/06-tasks.md create mode 100644 docs/07-user-stories.md create mode 100644 docs/08-interaction-checklist.md create mode 100644 docs/README.md create mode 100644 docs/agent-context.json create mode 100644 docs/agent-context.md create mode 100644 docs/agent-context.schema.json create mode 100644 docs/api.md create mode 100644 docs/clean-state-checklist.md create mode 100644 docs/current-state.md create mode 100644 docs/design/README.md create mode 100644 docs/routes.md create mode 100644 docs/tasks/README.md create mode 100644 docs/tasks/T-001.md create mode 100644 docs/tasks/_template.md create mode 100644 init.ps1 create mode 100644 init.sh create mode 100644 progress.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..f8e512d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +* text=auto + +*.sh text eol=lf +*.ps1 text eol=crlf +*.md text eol=lf +*.json text eol=lf +*.txt text eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1731f3b --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# OS and editors +.DS_Store +Thumbs.db +.idea/ +.vscode/ +*.iml + +# Local configuration and secrets +.env +.env.* +!.env.example +local.properties +google-services.json +secrets.properties +api_keys.properties +*.jks +*.keystore +*.pem +*.key + +# Android and Gradle outputs +.gradle/ +**/build/ +*.apk +*.aab +*.aar + +# Go and local runtime outputs +bin/ +dist/ +tmp/ +var/ +*.exe +*.test +coverage.out + +# Logs +*.log diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..bb461e6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,88 @@ +# AGENTS.md + +> 本仓库的 AI coding agent 权威入口。进入仓库后先读本文,再进入 +> [`docs/00-ai-start-here.md`](docs/00-ai-start-here.md)。 + +## 项目定位 + +本项目用于验证并逐步实现“采购任务 -> Android App 领取 -> AI 理解图片和文字 +-> 拼多多检索与候选判断 -> 人工确认 -> 结果回传”的采购闭环。 + +当前处于文档和技术验证准备阶段。首版不是生产级无人值守采购系统,不允许自动 +提交订单或自动支付。 + +## 必读顺序 + +首次接入按顺序读取: + +1. `docs/00-ai-start-here.md` +2. `docs/01-vision.md` +3. `docs/02-requirements.md` +4. `docs/03-tech-stack.md` +5. `docs/04-architecture.md` +6. `docs/05-coding-rules.md` +7. `docs/06-tasks.md` +8. `docs/tasks/README.md` +9. `docs/current-state.md` + +日常任务读取 `docs/agent-context.json` 指定的最小文件、本轮任务文件和命中的任务 +类型路由。 + +## Codebase Knowledge Graph + +本项目使用 codebase-memory-mcp 维护代码知识图谱。代码发现按以下优先级执行: + +1. `search_graph`:按模式定位函数、类、路由和变量。 +2. `trace_path`:追踪调用方或被调用方。 +3. `get_code_snippet`:读取指定函数或类的源码。 +4. `query_graph`:复杂关系使用 Cypher 查询。 +5. `get_architecture`:获取项目级架构概览。 + +以下情况才回退到 `rg`、文件列表或直接读取: + +- 查字符串字面量、错误消息和配置值。 +- 查 Markdown、Dockerfile、Shell、JSON 等非代码文件。 +- 图谱尚未建立、不可用或结果不足。 + +## 任务规则 + +- 真实任务一任务一文件,存放于 `docs/tasks/T-<编号>.md`。 +- 每个 agent 同时只做一个 `TODO` 且依赖已完成的任务。 +- 开始时将任务状态改为 `DOING`;只有验收证据齐全时才能改为 `DONE`。 +- 任务的修改路径必须在 `write_paths` 中,不能顺手扩大范围。 +- 路线图 `docs/06-tasks.md` 不跟踪单任务状态。 +- 当前目录、命令或 blocker 变化时同步 `docs/current-state.md`。 +- 执行记录和验证证据写入当前任务文件,不逐任务追加 `progress.md`。 + +## 业务硬边界 + +- MVP 只允许操作拼多多,包名和页面结构必须在测试设备上验证后记录。 +- MVP 由采购人员点击“获取任务”并开始,后台不强推后立即执行。 +- 自动化到达候选商品或订单确认页后必须停止,不能点击最终提交订单或支付。 +- 不绕过验证码、登录验证、平台风控、权限校验或生物识别。 +- 遇到验证码、账号失效、风控提示、页面结构未知或价格超预算时停止并回报。 +- 用户输入的数量和最高预算是权威约束,模型输出不能覆盖。 +- 不记录拼多多密码、支付密码、Cookie、会话令牌或完整个人敏感信息。 + +## 工作规则 + +- 需求、接口、状态机或数据模型有变化时,先更新对应文档再改代码。 +- 优先沿用接入后的 Roubao 代码结构和既有依赖,不并存第二套自动化框架。 +- Android 自动化优先使用可访问性节点和稳定语义;截图/VLM 是辅助判断,不把 + 裸坐标当成唯一定位方式。 +- VLM 输出必须经过结构校验、范围校验和确定性规则复核,不能直接触发不可逆动作。 +- 所有外部调用设置超时;重试必须有上限;任务领取和结果上报必须幂等。 +- 不提交真实密钥。配置只保存环境变量名、占位值或本地忽略文件。 +- 不删除或重置用户已有改动。 + +## 验证 + +当前尚无生产代码和可运行构建命令。完成 `T-001` 后,必须把真实命令同步到: + +- `init.ps1` / `init.sh` +- `docs/00-ai-start-here.md` +- `docs/03-tech-stack.md` +- `docs/05-coding-rules.md` +- `docs/current-state.md` + +结束任务前按 `docs/clean-state-checklist.md` 收尾。 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..c754398 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,7 @@ +# CLAUDE.md + +> Claude Code 的仓库级薄入口。 + +本仓库的权威规则统一维护在 [`AGENTS.md`](AGENTS.md)。先读取 `AGENTS.md`,再按其 +要求进入 [`docs/00-ai-start-here.md`](docs/00-ai-start-here.md)。不要在本文复制 +任务流程、编码规则或业务边界。 diff --git a/README.md b/README.md new file mode 100644 index 0000000..8c9645c --- /dev/null +++ b/README.md @@ -0,0 +1,57 @@ +# 采购自动化验证系统 + +本项目面向采购管理人员和采购执行人员,目标是将后台采集的商品标题、描述、图片、 +数量和预算转成 Android 端可执行的采购任务,并验证 AI 辅助拼多多检索和候选商品 +判断是否可靠。 + +第一版只验证: + +```text +后台创建任务 + -> Android App 手动领取 + -> VLM 解析图片与文字 + -> 拼多多搜索和候选比较 + -> 停在人工确认位置 + -> 回传结果、截图和失败原因 +``` + +MVP 不自动提交订单、不支付、不绕过验证码或平台风控。 + +## 目标结构 + +```text +cmroubao/ +├── android-buyer/ # 基于 Roubao 二次开发的采购 App,待接入 +├── backend-api/ # Go-Gin API、管理页面和任务数据,待创建 +├── docs/ # Harness Coding 项目事实和执行约束 +├── AGENTS.md # AI coding agent 权威入口 +├── init.ps1 # Windows 标准验证入口,待 T-001 配置 +└── init.sh # Unix/WSL 等价入口,待 T-001 配置 +``` + +管理人员使用 Web 管理端,采购人员使用 Android App;二者共享同一后端、任务数据 +和权限体系。验证版先使用单管理账号和设备身份,完整 RBAC 放到验证通过后。 + +后端已确定采用 Go 1.23.0 + Gin 1.11.0,并用 Go Blueprint v0.10.11 生成最小 +Gin + SQLite 骨架后按领域边界二次开发。 + +Android 端已核实的 Roubao 上游环境为 Kotlin 1.9.20、JDK 17、Gradle 8.2、 +AGP 8.2.0、Android SDK 34,以及 Jetpack Compose Compiler 1.5.5。最低支持 +Android 8.0(API 26),目标为 Android 14(API 34)。具体版本和本机环境状态见 +[`docs/03-tech-stack.md`](docs/03-tech-stack.md) 与 +[`docs/current-state.md`](docs/current-state.md)。 + +## 文档入口 + +- [AI 开发入口](docs/00-ai-start-here.md) +- [项目愿景](docs/01-vision.md) +- [需求与 MVP 验收](docs/02-requirements.md) +- [技术栈](docs/03-tech-stack.md) +- [架构设计](docs/04-architecture.md) +- [API 合约](docs/api.md) +- [任务路线图](docs/06-tasks.md) +- [当前实现状态](docs/current-state.md) +- [完整文档导航](docs/README.md) + +当前仓库只有文档,还没有接入 Roubao、后端代码或可构建 APK。真实状态以 +[`docs/current-state.md`](docs/current-state.md) 为准。 diff --git a/deepseek总结.txt b/deepseek总结.txt new file mode 100644 index 0000000..aae992e --- /dev/null +++ b/deepseek总结.txt @@ -0,0 +1,100 @@ +好的,以下是针对你需求的完整总结,格式适合传递给其他 AI Agent 继续执行或迭代。 + +--- + +## Project: 采购以图搜图自动下单系统 + +### 1. 用户原始需求 + +> 制作一个 Android APK,提供给采购人员使用。采购人员可以用自然语言描述 + 上传商品图片,系统通过 LLM/VLM 理解需求后,自动在拼多多(PDD)上搜索匹配的商品,并完成下单流程。 + +### 2. 核心功能流程 + +``` +[采购人员] 上传商品图片 + 输入需求描述(如"类似的黑色款,预算200以内") + ↓ +[VLM 视觉语言模型] 理解图片内容 + 自然语言描述,提取商品特征关键词 + ↓ +[手机端 APK] 自动打开拼多多 APP,搜索匹配商品 + ↓ +[VLM] 对比搜索结果与用户需求,选出最合适的商品 + ↓ +[手机端 APK] 自动进入商品详情页 → 下单 → 提交订单 + ↓ +[系统] 返回订单结果给采购人员 +``` + +### 3. 推荐技术方案 + +| 层级 | 方案 | 说明 | +|------|------|------| +| **基础框架** | **Roubao(肉包)** | GitHub: Turbo1123/roubao,MIT 开源,Kotlin 原生 Android APK | +| **系统权限** | AccessibilityService + Shizuku | 无需 root,无需电脑连接 | +| **AI 模型** | VLM(视觉语言模型) | 如 GPT-4o、DeepSeek-V2、GLM-4V、Doubao-vision-pro 等 | +| **远程控制** | fork 后自加 HTTP/WebSocket Server | 可选,用于后台管理或多人提交需求 | +| **自动化操作** | Roubao 已有 Skill/Tools 架构 | 新增一个 PDD_Skill 即可 | + +### 4. Roubao 已具备的能力(无需重复开发) + +- ✅ 基于 VLM 的屏幕截图理解与操作决策 +- ✅ AccessibilityService 控制其他 APP(点击、滑动、输入) +- ✅ Shizuku 获取系统级权限(截图、模拟操作) +- ✅ Skill/Tools 双层架构(易于扩展业务逻辑) +- ✅ 原生 Kotlin APK,可独立打包发布 +- ✅ 支持自定义 API Base URL 接入多种 VLM + +### 5. 需要二次开发的内容 + +``` +1. PDD_Skill(新增) + ├─ 关键词搜索商品 + ├─ 以图搜图(调用拼多多内部以图搜图功能) + ├─ 遍历商品列表 + AI 匹配判断 + └─ 自动下单流程 + +2. 采购专用 UI(改造) + ├─ 拍照 / 从相册选取图片 + ├─ 自然语言输入框 + ├─ 搜索结果预览与确认 + └─ 订单历史记录 + +3. 可选:HTTP Server(新增) + ├─ 接收远程采购需求 + └─ 返回订单状态 + +4. 可选:多平台扩展 + ├─ 1688 / 淘宝 / 京东 + └─ 多个电商平台并行比价 +``` + +### 6. 技术栈总览 + +``` +开发语言: Kotlin(Android 原生) +底层 API: AccessibilityService(无障碍服务) +AI 模型: VLM(GPT-4o / Qwen-VL / GLM-4V / DeepSeek-V2 等) +权限方案: Shizuku(替代 ADB) +通信方式: HTTP / WebSocket(可选) +输出产物: 独立 APK,可直接安装使用 +开源协议: MIT(可商用,可二次开发) +``` + +### 7. 推荐执行路线 + +``` +Phase 1(1-2周):fork Roubao,跑通 PDD 基础操作 Skill +Phase 2(2-3周):集成 VLM,实现"图片+文字 → 搜索关键词"流程 +Phase 3(1-2周):加上远程控制和采购 UI +Phase 4(持续):优化匹配精度、异常处理、多平台支持 +``` + +### 8. 关键约束与注意事项 + +- 需要用户开启**无障碍服务权限**(Shizuku 一次授权后可保持) +- 拼多多有**反自动化风控**,需控制操作频率 + 随机延迟 +- VLM 调用有**API 成本**(推荐 DeepSeek-V2 或 GLM-4V,性价比高) +- 该方案适用于 Android 8.0+ 设备 + +--- + +以上内容可以直接作为 Prompt 传递给其他 AI Agent(如 Claude、GPT、DeepSeek 等),让它们理解上下文并继续执行后续开发任务。 \ No newline at end of file diff --git a/docs/00-ai-start-here.md b/docs/00-ai-start-here.md new file mode 100644 index 0000000..4468910 --- /dev/null +++ b/docs/00-ai-start-here.md @@ -0,0 +1,93 @@ +# AI 开发入口 + +## 一句话定位 + +本项目验证管理后台创建的图片和文字采购任务,能否由 Android App 领取并借助 VLM +在拼多多中找到合理候选商品,同时安全地停在人工确认位置并回传证据。 + +## 当前 MVP + +只做: + +- 管理 Web 创建和查看采购任务。 +- 一台 Android 设备由采购人员手动领取下一条任务。 +- AI 把图片和文字解析为结构化检索条件。 +- App 在拼多多搜索、检查少量结果并选择候选。 +- App 停在候选确认或订单确认页,由人判断是否通过。 +- 回传任务状态、候选摘要、截图和失败原因。 + +不做: + +- 推送到达后无人确认地立即执行。 +- 最终提交订单、自动付款或处理退款。 +- 绕过验证码、风控或登录校验。 +- 多电商平台、多设备并发调度和生产级 RBAC。 + +## 首次读取顺序 + +1. `../AGENTS.md` +2. `01-vision.md` +3. `02-requirements.md` +4. `03-tech-stack.md` +5. `04-architecture.md` +6. `05-coding-rules.md` +7. `06-tasks.md` +8. `tasks/README.md` +9. `current-state.md` + +有界面任务时再读 `07-user-stories.md`、`08-interaction-checklist.md`、`routes.md` +和关联原型;API 任务读 `api.md`。 + +## 固定开工流程 + +1. 确认工作目录是仓库根目录。 +2. 读取 `agent-context.json`、`current-state.md` 和当前任务文件。 +3. 仓库已启用 Git 时查看最近五条提交;当前未启用时,以 `current-state.md` 为准。 +4. 运行 `./init.ps1`(Windows)或 `./init.sh`(WSL/Linux)。 +5. 如果脚本因 `T-001` 尚未完成而主动失败,只能领取 `T-001`;不要宣称基线可运行。 +6. 有真实基线后先跑 smoke;基线失败时先修基线。 +7. 领取编号最小、依赖已完成的一个 `TODO` 任务并改成 `DOING`。 +8. 完成实现、验证、任务执行记录和当前状态同步后再结束。 + +## 当前阶段与优先路径 + +当前处于“文档基线完成、最高风险验证尚未开始”阶段。 + +严格按以下顺序推进: + +1. 接入并构建 Roubao Android 基线。 +2. 用 App 内固定任务验证拼多多搜索和页面操作。 +3. 接入 VLM,验证结构化需求提取和候选判断。 +4. 建立最小后端和管理页面。 +5. 接入手动领取、租约、状态和结果回传。 +6. 用真实样本完成 20 条任务试验。 + +不允许先建设完整后台、消息推送或多设备调度来代替第 2 步的高风险验证。 + +## 事实来源 + +- 产品范围:`02-requirements.md` +- 角色目标:`07-user-stories.md` +- 交互行为:`08-interaction-checklist.md` +- 技术和模块边界:`03-tech-stack.md`、`04-architecture.md` +- API:`api.md` +- 当前现实:`current-state.md`、当前代码和实际命令输出 +- 任务:`docs/tasks/T-<编号>.md` +- 原始讨论摘要:`../deepseek总结.txt`,仅作背景;与正式文档冲突时不作为权威 + +Roubao、拼多多页面、Android 包名、上游分支和依赖版本必须从接入的源码和测试设备 +核实,不能仅凭讨论摘要推断。 + +## 常见任务路由 + +- Android 自动化:需求 -> 架构“自动化边界” -> 编码规则 -> 当前任务。 +- VLM:需求约束 -> 架构“AI 决策边界” -> API/模块合约 -> 当前任务。 +- 管理 Web:用户故事 -> 交互清单 -> 路由 -> API -> 架构。 +- 后端/数据:API -> 架构数据模型和状态机 -> 编码规则。 +- 安全相关:需求风险 -> 架构安全边界 -> 编码规则,无法满足时停止。 + +## 当前验证命令 + +当前没有生产代码,`init.ps1` 和 `init.sh` 会主动报错。`T-001` 完成后必须用真实 +命令替换本文,例如 Android 至少应有可复现的 Gradle 构建命令;后端建立后再追加 +后端测试和启动命令。 diff --git a/docs/01-vision.md b/docs/01-vision.md new file mode 100644 index 0000000..93b33c5 --- /dev/null +++ b/docs/01-vision.md @@ -0,0 +1,46 @@ +# 项目愿景 + +## 核心目标 + +让采购团队能够把商品图片、标题、描述、数量和预算形成标准采购任务,由专用 Android +设备辅助完成拼多多检索和候选比较,减少重复搜索时间,并为每次自动化执行留下可审计 +的结果。 + +本项目不是绕过电商平台规则的爬虫或支付机器人。首要目标是验证 AI 与 Android UI +自动化能否在真实采购场景中可靠协助人员,而不是追求无人值守。 + +## 目标用户 + +- **采购管理员**:创建任务、设置硬性约束、查看进度和结果。 +- **采购执行员**:在 Android App 上领取任务、监控执行、人工确认候选和处理异常。 +- **系统管理员(后续)**:管理人员、角色、设备、模型配置和审计策略。 +- **审核员(后续)**:审核高金额或异常任务,不直接操作采购流程。 + +## 核心价值 + +| 价值 | 说明 | +| --- | --- | +| 减少重复操作 | 自动把图片和描述转为检索条件,减少人工输入和逐条翻找。 | +| 提高匹配一致性 | 用结构化约束和可解释的候选比较代替完全凭经验浏览。 | +| 保持人工控制 | 对不可逆操作设置明确停止点,人员随时知道当前状态并可接管。 | +| 留下执行证据 | 任务、候选、截图、失败原因和耗时可以追溯。 | + +## 产品原则 + +- **先证伪最高风险**:先证明拼多多页面自动化可运行,再建设完整后台。 +- **硬约束优先于模型**:数量、最高预算和人工输入不能被模型修改。 +- **人工确认不可省略**:验证版的订单提交和支付必须由人控制。 +- **失败要可诊断**:不能只返回“失败”,必须记录步骤、错误码和必要截图。 +- **最小权限**:后台、人员、设备和第三方 App 权限各自隔离。 +- **可替换模型**:业务流程不能绑定单一 VLM 厂商。 + +## 非目标 + +- MVP 不自动提交订单或支付。 +- MVP 不支持淘宝、1688、京东等其他平台。 +- MVP 不做后台推送后立即执行;只做 App 手动领取。 +- MVP 不做多设备负载均衡、复杂审批、财务对账和退款。 +- 不绕过验证码、风控、登录验证、平台限流或权限校验。 +- 不承诺对所有拼多多版本和所有商品类目通用。 + +具体范围与验收见[需求](02-requirements.md)。 diff --git a/docs/02-requirements.md b/docs/02-requirements.md new file mode 100644 index 0000000..525735c --- /dev/null +++ b/docs/02-requirements.md @@ -0,0 +1,111 @@ +# 需求 + +> 本文描述“要什么”和“怎么算达成”,不规定框架或代码实现。 + +## 一、业务现状 + +| 项 | 当前事实 | +| --- | --- | +| 任务来源 | 其他管理后台或本项目管理 Web 采集商品标题、描述、图片、数量和预算。 | +| 执行方式 | 采购人员使用 Android App 操作拼多多;当前没有可运行实现。 | +| 核心痛点 | 人工把图片和描述转成搜索词、逐条比较商品并记录结果,耗时且不一致。 | +| 验证范围 | 一台设备、一个管理身份、一个采购执行人员、拼多多单平台。 | +| 资金边界 | MVP 不提交订单、不支付,只验证到人工确认位置。 | + +## 二、用户角色 + +- **采购管理员**:创建、查看、取消尚未执行的任务并查看执行结果。 +- **采购执行员**:在 App 上检查设备状态、手动领取、执行和人工确认任务。 +- **设备身份**:代表一台获得授权的 Android 设备领取任务和上报状态。 +- **系统管理员/审核员**:目标架构角色,MVP 不提供完整管理界面。 +- **未登录用户**:不能访问任务、图片、执行证据或设备接口。 + +## 三、MVP 功能 + +| ID | 功能 | 用户结果 | 优先级 | 用户故事 | +| --- | --- | --- | --- | --- | +| F-001 | 创建采购任务 | 管理员提交标题、描述、图片、数量和可选预算,获得任务编号。 | P0 | US-001 | +| F-002 | 查看任务状态 | 管理员看到任务阶段、候选摘要、截图和失败原因。 | P0 | US-002 | +| F-003 | 手动领取任务 | 空闲且就绪的 App 点击后只领取一条待处理任务。 | P0 | US-003 | +| F-004 | 解析采购需求 | 系统从图片和文字提取搜索词、属性及约束,并保留原始输入。 | P0 | US-004 | +| F-005 | 拼多多搜索与候选判断 | App 搜索并检查少量结果,得到一个候选或明确无匹配。 | P0 | US-004 | +| F-006 | 人工确认停止点 | 自动化停在候选/订单确认位置,采购员确认结果或拒绝候选。 | P0 | US-005 | +| F-007 | 结果与异常回传 | 管理员和采购员看到成功、失败、取消及可恢复建议。 | P0 | US-002、US-006 | + +## 四、后续迭代 + +| 功能 | 说明 | 阶段 | +| --- | --- | --- | +| 完整 RBAC | 采购管理员、执行员、审核员和系统管理员的细粒度权限。 | V2 | +| 多设备调度 | 设备心跳、任务队列、租约回收和容量调度。 | V2 | +| 后台通知 | WebSocket/厂商推送只通知有任务,App 仍通过 claim 领取。 | V2 | +| 订单提交审批 | 在金额、店铺和品类规则内,经人工审批后允许提交订单。 | V2,需单独安全评审 | +| 多平台比价 | 淘宝、1688、京东等平台。 | V3 | +| 支付自动化 | 不在当前规划内,除非另行完成资金和合规评审。 | 未规划 | + +## 五、业务规则 + +1. 标题、描述和图片至少满足“标题或描述不为空,且图片存在”。 +2. 数量必须是正整数;最高预算如填写,必须大于零。 +3. 数量和最高预算以管理员输入为准,模型不得更改。 +4. 一台设备同一时间最多有一条 `CLAIMED` 或 `RUNNING` 任务。 +5. 一条任务同一时间只能被一台设备持有;重复点击不能产生重复领取。 +6. App 未就绪时不能开始:无障碍未授权、拼多多未安装、设备离线或已有运行任务都 + 必须说明原因。 +7. 遇到验证码、登录失效、风控提示、页面未知、预算不满足或模型低置信度时停止, + 不猜测点击。 +8. MVP 的“成功”表示完成验证闭环并得到人工确认的候选结果, + `order_submitted` 必须为 `false`。 +9. 取消和失败不得自动转成新任务;是否重试由人员显式决定。 + +## 六、MVP 验收标准 + +### 单任务验收 + +- F-001/US-001/IX-001:合法输入创建后出现唯一任务编号和 `PENDING` 状态;非法 + 数量、预算或缺失图片时在原表单显示可修复错误。 +- F-002/US-002/IX-002:状态变化后管理页面能看到最新阶段、时间、设备、候选摘要 + 或结构化错误;无权限用户不可访问。 +- F-003/US-003/IX-004:App 点击“获取任务”后原子领取一条任务;重复点击或多请求 + 不得领取第二条或把同一任务分配两次。 +- F-004/US-004/IX-006:解析结果包含搜索词、识别属性、预算、数量、置信度和警告; + 原始输入保留,硬约束与输入一致。 +- F-005/US-004/IX-006:在已验证的拼多多版本上,App 能从任务进入搜索结果并检查 + 最多 5 个候选;无合理候选时明确结束而不是随意选择。 +- F-006/US-005/IX-007:流程到达人工确认点后停止;MVP 任意路径都不能触发最终 + 提交订单或支付。 +- F-007/US-006/IX-008:失败包含稳定错误码、失败步骤、可读说明和必要截图;重新 + 打开任务后证据仍可查看。 + +### 试验验收 + +使用至少 20 条经采购人员确认的代表性任务: + +- 至少 80% 能自动到达合理候选商品页或给出正确的“无匹配/需人工”结论。 +- 至少 70% 的首选候选被采购人员判定可接受。 +- 不发生重复领取、重复执行导致的不可逆操作或订单提交。 +- 每条失败任务都能定位到具体步骤和错误类别。 +- 记录每条任务的耗时、人工介入点和候选接受结果,用于决定是否进入 V2。 + +这些比例是进入下一阶段的验证门槛,不是正式生产 SLA。 + +## 七、范围决策 + +| 问题 | 当前决策 | +| --- | --- | +| 客户端形态 | 管理人员用 Web,采购人员用 Android App,共享统一后端。 | +| 任务到达 | MVP 由 App 手动领取;后续通知只作唤醒/提示。 | +| 搜索方式 | 先验证关键词搜索;拼多多原生以图搜图作为后续可选路径。 | +| 搜索结果 | 最多检查前 5 个可见候选,避免无界遍历。 | +| 下单边界 | MVP 停在候选或订单确认页,不提交订单、不支付。 | +| 账号边界 | 验证版为单管理身份 + 设备身份;完整人员 RBAC 后置。 | + +## 八、待确认与风险 + +- Roubao 上游源码、许可证、可构建分支和 Android 版本支持仍需在 `T-001` 核实。 +- 拼多多版本、页面结构、账号登录状态和测试设备尚未形成可复现基线。 +- VLM 厂商、模型、成本上限、数据留存地区和图片隐私规则待确认。 +- 拼多多平台条款、自动化允许范围和账号风控需要业务方确认;项目不实现绕过措施。 +- 后续若允许提交订单,必须先明确 SKU、收货地址、运费、优惠、发票、金额审批、 + 幂等和人工确认规则,并单独更新需求。 +- “最终产品是否自动支付”没有定案,当前明确排除。 diff --git a/docs/03-tech-stack.md b/docs/03-tech-stack.md new file mode 100644 index 0000000..7a1e4dc --- /dev/null +++ b/docs/03-tech-stack.md @@ -0,0 +1,159 @@ +# 技术栈 + +> “用什么”的权威速查表。状态为“待验证”的项不能在代码中当作既成事实。 + +## 技术栈一览 + +| 维度 | 选型 | 状态 | 说明 | +| --- | --- | --- | --- | +| Android 基础 | Roubao `main` 的 Kotlin 原生 Android 代码,应用版本 1.4.2 | 上游已核实,待接入 | 上游为 `Turbo1123/roubao`,MIT;接入时固定具体 commit。 | +| Android IDE/JDK | Android Studio Hedgehog 2023.1.1 或更高;JDK 17 | 上游已核实 | 首次导入不接受 IDE 自动升级 AGP、Gradle 或 Kotlin。 | +| Android 构建链 | Gradle 8.2;AGP 8.2.0;Kotlin 1.9.20;JVM target 17 | 上游已核实 | 使用仓库内 Gradle Wrapper,不依赖全局 Gradle。 | +| Android SDK | compileSdk/targetSdk 34;minSdk 26;SDK Build Tools 34.0.0 | 上游已核实 | 支持 Android 8.0+;真机自动化优先 Android 11+。 | +| Android UI | Jetpack Compose + Material 3;Compose Compiler 1.5.5 | 上游已核实 | Compose BOM 为 2023.10.01。 | +| Android 自动化 | 项目目标以 `AccessibilityService` 为主,Shizuku 为兼容/增强路径 | 目标已定,待实现 | 上游 `main` 使用 Shizuku 13.1.5;无障碍实现位于独立开发分支,不能把它误认为主分支现状。 | +| Android 长任务 | 前台服务 + 持续通知 | 计划采用 | 降低执行中被系统挂起的风险,仍需处理进程死亡恢复。 | +| 后端语言 | Go 1.23.0 | MVP 已定 | 与现有本机工具链一致;构建测试必须设置 `GOTOOLCHAIN=local` 防止静默升级。 | +| 后端骨架 | Go Blueprint v0.10.11 生成的最小 Gin + SQLite 工程 | MVP 已定 | 只作为一次性脚手架输入;生成后立即重写版本约束。 | +| 后端框架 | Gin v1.11.0 | MVP 已定 | 这是 `go.mod` 明确支持 Go 1.23.0 的最高已核实 Gin 版本。 | +| 数据访问 | 标准库 `database/sql` | MVP 已定 | 领域层通过仓储接口访问,避免先引入 ORM 和代码生成复杂度。 | +| 数据迁移 | Goose v3,使用 SQL migration | MVP 已定 | 迁移可审核、可排序并支持 SQLite;版本在 T-201 建立 `go.mod` 时锁定。 | +| 管理 Web | Gin + `html/template` + `embed` + 少量原生 JS/CSS | MVP 已定 | 不单独引入 SPA 工程,模板和静态资源随服务构建。 | +| 数据库 | SQLite | MVP 已定 | 单服务、单设备验证足够;多实例或并发提升前迁移 PostgreSQL。 | +| 图片/截图 | 后端受控本地文件目录,数据库存元数据 | MVP 已定 | 禁止把二进制直接塞入日志;生产再评估对象存储。 | +| 管理鉴权 | 单个种子管理账号 + 服务端会话 Cookie | MVP 已定 | 密码只保存哈希;完整 RBAC 为 V2。 | +| App 鉴权 | 采购员登录态 + 设备绑定令牌 | 目标已定,细节待实现 | 人员身份与设备身份分离;令牌只保存哈希。 | +| VLM 接入 | 应用内统一适配器,优先兼容 OpenAI 风格多模态接口 | 接口已定,供应商待定 | 模型输出必须符合本项目 JSON Schema。 | +| 通知 | MVP 不使用推送 | 已定 | 点击“获取任务”调用原子 claim API;V2 再评估厂商推送/WebSocket。 | +| 后端测试 | 标准库 `testing` + `httptest` | MVP 已定 | 覆盖状态机、权限、幂等、SQLite 事务和输入校验。 | +| Android 测试 | JUnit + 现有上游测试工具;真实设备 smoke | 待源码核实 | UI 自动化核心必须在目标设备验证。 | +| 部署 | 单机局域网 Go 服务;容器化后置 | MVP 已定 | Android 测试机必须能通过 HTTPS 或受控测试网络访问。 | + +## Roubao 上游版本基线 + +核实日期:2026-07-25。 + +| 项目 | 已核实值 | +| --- | --- | +| 上游仓库 | [`Turbo1123/roubao`](https://github.com/Turbo1123/roubao) | +| 许可证 | MIT | +| 默认分支 | `main` | +| 核实时 `main` commit | `c8a6d7f03422eb01744b01f3ee77bf7757741f7e` | +| `main` 应用版本 | 1.4.2(`versionCode 7`) | +| 开发 IDE | Android Studio Hedgehog 2023.1.1 或更高 | +| JDK / JVM target | 17 / 17 | +| Android SDK | compileSdk 34、targetSdk 34、minSdk 26 | +| SDK Build Tools | 34.0.0(AGP 8.2 官方兼容基线) | +| Gradle / AGP | 8.2 / 8.2.0 | +| Kotlin | 1.9.20 | +| Compose | Compose BOM 2023.10.01、Compiler 1.5.5、Material 3 | +| 自动化依赖 | Shizuku API/Provider 13.1.5 | +| 无障碍开发分支 | `roubao2.0+AccessibilityService`,核实时 commit `5b114c0a9476c359b27cfe994743fc7beb0a3554` | + +上述值来自上游 README、`build.gradle.kts`、`app/build.gradle.kts` 和 +`gradle/wrapper/gradle-wrapper.properties`。它们是接入前的远端核实结果,不代表 +本仓库已经构建通过。`T-001` 接入时必须再次确认远端 commit,并把最终采用的 commit +作为可复现基线。 + +上游启用了 Google Services 4.4.2、Firebase Crashlytics Gradle Plugin 3.0.2 和 +Firebase BOM 33.7.0,但 `google-services.json` 被 `.gitignore` 排除。干净构建必须 +提供本项目自己的 Firebase 配置,或者在不需要遥测时移除相关插件和依赖;不得提交 +真实 Firebase 配置。 + +## 关键决策 + +- 统一后端同时服务管理 Web 与 Android App;不是两套业务后端。 +- 首版管理页面使用服务端渲染,避免在验证阶段维护独立前端构建链。 +- Go Blueprint 只生成起始目录;正式代码必须删除演示逻辑,并按 + `04-architecture.md` 的领域边界重组。 +- SQLite 只服务单实例验证;出现多服务实例、并发写或正式备份要求时迁移 PostgreSQL。 +- VLM 厂商可替换,领域层只接收结构化请求和结果,不传播供应商 SDK 类型。 +- 拼多多自动化是独立工作流模块,不能耦合后端数据库实现或管理页面。 + +## 骨架选择记录 + +- 来源:[`Melkeydev/go-blueprint`](https://github.com/Melkeydev/go-blueprint) +- 固定版本:`v0.10.11`(MIT) +- 生成目标:`Gin + SQLite` +- 不启用:React、HTMX、WebSocket、Redis、Docker 等高级特性 + +计划生成命令: + +```powershell +go install github.com/melkeydev/go-blueprint@v0.10.11 +go-blueprint create --name backend-api --framework gin --driver sqlite --git skip +``` + +Go Blueprint v0.10.11 当前生成的是 `Go 1.25.0 + Gin 1.12.0`,不能直接作为本项目 +的 `go.mod`。2026-07-25 已在临时目录将生成结果调整为以下版本,并在 +`GOTOOLCHAIN=local` 下完成 `go mod tidy` 和 `go test ./...`: + +```text +go 1.23.0 +github.com/gin-gonic/gin v1.11.0 +github.com/gin-contrib/cors v1.7.6 +github.com/joho/godotenv v1.5.1 +github.com/mattn/go-sqlite3 v1.14.48 +``` + +Gin v1.12.0 的 `go.mod` 要求 Go 1.25.0,因此本项目禁止升级到 Gin 1.12.x,除非先 +单独批准升级 Go 工具链。正式接入还必须修正: + +- 健康检查不得调用 `log.Fatal` 终止进程。 +- 删除包级数据库单例和包加载阶段读取环境变量的写法。 +- 关闭不需要的默认 CORS,不提交生成的 `.env`。 +- 正确关闭数据库和 HTTP Server,注入 config/repository 以便测试。 +- `mattn/go-sqlite3` 需要 CGO 和 GCC;构建环境必须显式验证。 + +不选择 `go-admin-team/go-admin`:Vue、多租户、Casbin RBAC、代码生成和定时任务 +超出 MVP。不选择 `evrone/go-clean-template`:当前模板以 Fiber、PostgreSQL、 +RabbitMQ、NATS 和 gRPC 为主,不符合最小 Gin + SQLite 边界。 + +## 计划目录 + +```text +android-buyer/ # Kotlin Android App +backend-api/ + cmd/api/ # 进程入口,只负责装配和生命周期 + internal/domain/ # 实体、状态机和确定性规则 + internal/usecase/ # 创建、领取、执行和结果归档 + internal/transport/http/ # Gin handler、中间件和页面 + internal/repository/sqlite/ # database/sql 仓储 + internal/platform/ # 配置、日志、文件和 VLM 适配器 + migrations/ # Goose SQL migration + web/templates/ # html/template + web/static/ # 少量 CSS/JS + var/ # 本地运行数据,必须忽略 +docs/ +``` + +目录在真实骨架建立后以代码为准并同步本文。 + +## 构建与运行命令 + +当前没有源码,以下是计划形状而非可运行证据: + +| 用途 | 计划命令 | 当前状态 | +| --- | --- | --- | +| Android 构建 | `android-buyer\gradlew.bat assembleDebug` | 待 `T-001` | +| Android 单元测试 | `android-buyer\gradlew.bat test` | 待 `T-001` | +| 后端依赖 | `go mod download`(在 `backend-api/`) | 待 `T-201` | +| 后端测试 | `go test ./...`(在 `backend-api/`) | 待 `T-201` | +| 后端构建 | `go build -o bin/cmroubao-api.exe ./cmd/api` | 待 `T-201` | +| 后端启动 | `go run ./cmd/api` | 待 `T-201` | +| 数据迁移 | `goose -dir migrations sqlite3 ./var/cmroubao.db up` | 待 `T-201` | + +任何命令只有实际执行成功后才能写入 `init.ps1`、`init.sh` 和 +`current-state.md` 的“当前可运行内容”。 + +## 依赖纪律 + +- 接入 Roubao 后优先使用其已有 HTTP、序列化、依赖注入和 UI 方案。 +- 扩大 Shizuku 使用范围,或新增 OCR、浏览器自动化和第二套网络库前必须证明已有 + 能力不足。 +- 后端新增库要说明用途;验证版不引入 ORM、消息队列、Redis、微服务或 SPA 框架。 +- Go 依赖必须固定到 `go.mod`/`go.sum`;构建和 CI 不使用未固定的 `@latest`。 +- `go.mod` 必须声明 `go 1.23.0`;验证使用 `GOTOOLCHAIN=local go test ./...` 或 + PowerShell 等价环境变量,确保依赖没有暗中要求更高 Go 版本。 +- handler 不直接写 SQL,repository 不依赖 Gin,domain/usecase 不导入具体数据库驱动。 +- 密钥和设备令牌通过环境变量或本地忽略配置注入,不进入 Git。 diff --git a/docs/04-architecture.md b/docs/04-architecture.md new file mode 100644 index 0000000..d8b55b5 --- /dev/null +++ b/docs/04-architecture.md @@ -0,0 +1,312 @@ +# 架构设计 + +## 一、系统结构 + +目标架构是一套后端服务、两个面向不同角色的客户端: + +```text +采购管理员 + | + v +管理 Web(服务端渲染) + | + v +统一 Backend API ---------------------+ + | | + +--> SQLite / 文件存储 +--> VLM Provider + ^ + | +Android 采购 App + | + +--> AccessibilityService + | + v + 拼多多 App +``` + +- 管理 Web 与 API 同属 `backend-api/`,但页面层不能直接访问数据库。 +- Android App 位于 `android-buyer/`,通过 API 领取任务、调用 AI 能力和回传证据。 +- 拼多多是第三方受控边界,只能由 Android 设备在已登录会话中操作。 +- VLM 密钥的正式路径保留在后端;技术探针如需端上临时调用,只能使用本地忽略配置。 + +## 二、模块职责 + +### 2.1 Backend API + +建议分层: + +```text +cmd/api/ # 进程入口、依赖装配、信号和优雅关闭 +internal/transport/http/ # Gin 路由、中间件、页面和请求/响应 DTO +internal/usecase/ # 创建、领取、状态迁移和结果归档 +internal/domain/ # 实体、状态机、权限和确定性约束 +internal/repository/sqlite/ # database/sql 仓储实现 +internal/platform/ # 配置、日志、文件存储和 VLM 适配器 +``` + +职责: + +- 验证管理会话、采购人员和设备身份。 +- 创建任务并保存原始输入,不让模型结果覆盖原始事实。 +- 原子领取下一条任务,签发有期限的 claim lease。 +- 校验任务状态迁移、幂等键和设备归属。 +- 代理 VLM 调用并把供应商响应转换为领域结构。 +- 保存候选、事件、截图元数据和结果。 +- 为管理 Web 提供任务列表、详情和取消能力。 + +不得: + +- 根据 Web 按钮直接驱动某台手机点击。 +- 在 Gin handler 中写任务状态机、SQL 或仓储业务逻辑。 +- 保存拼多多密码、支付凭证或支付验证码。 + +### 2.2 Android App + +建议模块: + +```text +ui/ # 登录、任务列表、执行状态、设置 +taskclient/ # 后端 API、认证、幂等和重试 +workflow/ # ProcurementWorkflow 状态机 +automation/ # Accessibility 节点、截图、点击、输入、滑动 +ai/ # 结构化 AI 请求/响应,不含供应商业务类型 +evidence/ # 截图、步骤日志、脱敏和上传 +``` + +职责: + +- 检查无障碍、拼多多安装/登录可用性、网络和当前任务状态。 +- 由用户点击后领取任务;一台设备一次只运行一条。 +- 执行有界步骤:解析 -> 搜索 -> 浏览不超过 5 个候选 -> 判断 -> 停止确认。 +- 显示当前步骤、停止原因和人工接管入口。 +- 用前台服务承载执行中任务,进程重启后从服务端状态恢复或安全失败。 +- 回传步骤事件、候选、截图和最终结果。 + +不得: + +- 接收到通知就无条件开始采购。 +- 只用固定屏幕坐标定位关键控件。 +- 在验证码、登录、风险提示或未知页面上继续猜测操作。 +- 在 MVP 点击最终“提交订单”或支付相关控件。 + +### 2.3 VLM Gateway + +只负责两类能力: + +1. **需求提取**:图片 + 标题 + 描述 -> 搜索词、属性、置信度、警告。 +2. **候选评估**:候选截图/文本 + 原始约束 -> 匹配项、缺失项、拒绝原因、建议分。 + +模型输出是不可信建议,必须通过 schema 和确定性校验: + +- `quantity` 和 `max_budget` 使用原始任务值。 +- 价格未知、超预算或关键属性无法确认时不能判为可接受。 +- 置信度低于配置阈值时进入人工处理,不自动扩大浏览范围。 +- 模型不能返回点击坐标、状态迁移或“允许提交订单”等执行授权。 + +## 三、核心数据流 + +### 3.1 技术探针 + +```text +App 内固定任务 + -> 校验设备就绪 + -> 解析为固定/模型搜索词 + -> 打开拼多多并搜索 + -> 检查最多 5 个候选 + -> 到达候选详情或确认页 + -> 停止并记录结论 +``` + +该阶段不依赖后台,用于尽早判断 Android 自动化是否可行。 + +### 3.2 MVP 业务闭环 + +```text +管理员创建 PENDING 任务 + -> 采购员在 App 点击“获取任务” + -> 后端事务内选取并置为 CLAIMED + -> App 确认后置为 RUNNING + -> 定期 heartbeat 续租并上报步骤 + -> 需求提取和拼多多自动化 + -> WAITING_CONFIRMATION + -> 采购员接受/拒绝候选 + -> SUCCEEDED 或 FAILED/CANCELED + -> 管理端展示结果 +``` + +## 四、状态机 + +### 4.1 任务状态 + +```text +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 分钟,运行时每 30 秒心跳续租;数值进入配置。 +- 只有当前设备和有效 claim token 能启动、续租、上报或结束任务。 +- 终态不可回退;重试创建新的 execution attempt,不篡改历史证据。 +- 取消正在自动化的任务时,App 应在下一个安全检查点停止。 + +### 4.2 Android 工作流状态 + +```text +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 版本 | +| `pdd_version` | nullable | 已验证拼多多版本 | +| `last_seen_at` | nullable | 最近心跳 | +| `is_enabled` | NOT NULL | 后端开关 | + +### `purchase_tasks` + +| 字段 | 约束 | 说明 | +| --- | --- | --- | +| `id` | PK | 任务 ID | +| `title` | NOT NULL | 原始标题 | +| `description` | NOT NULL | 原始说明,可为空字符串 | +| `image_asset_id` | FK, NOT NULL | 原始参考图 | +| `quantity` | `> 0` | 权威数量 | +| `max_budget` | `> 0`, nullable | 权威最高预算,币种为 CNY | +| `status` | NOT NULL | 任务状态枚举 | +| `created_by` | FK | 创建人 | +| `claimed_by_device_id` | FK, nullable | 当前设备 | +| `claim_expires_at` | nullable | 租约到期时间 | +| `version` | NOT NULL | 乐观锁/状态并发控制 | +| `created_at/updated_at` | NOT NULL | 审计时间 | + +### `task_executions` + +| 字段 | 约束 | 说明 | +| --- | --- | --- | +| `id` | PK | 一次执行尝试 | +| `task_id` | FK | 所属任务 | +| `attempt_no` | UNIQUE(task, no) | 尝试序号 | +| `device_id/user_id` | FK | 执行设备和人员 | +| `extracted_requirements` | JSON | 已校验的模型结果 | +| `candidate_result` | JSON, nullable | 候选及匹配理由 | +| `outcome` | nullable | `CANDIDATE_ACCEPTED`、`CANDIDATE_REJECTED`、`NO_MATCH` 或 `MANUAL_REQUIRED` | +| `order_submitted` | NOT NULL, false | MVP 数据库约束必须为 false | +| `error_code/error_message` | nullable | 结构化失败 | +| `started_at/finished_at` | nullable | 执行耗时 | + +### `execution_events` 与 `assets` + +- `execution_events` 只追加,记录 step、事件类型、可读消息和时间;不保存密码或 token。 +- `assets` 保存文件相对路径、媒体类型、大小、哈希、创建者和保留时间。 +- 原图和截图必须通过鉴权接口读取,文件名不能直接作为公开 URL。 + +## 六、API 和并发边界 + +- 合约以 [`api.md`](api.md) 为准。 +- `claim-next` 必须由 usecase 调用 repository,在一个数据库事务内完成 + “选取 + 校验设备空闲 + 更新状态”。 +- 创建、领取和完成接口支持 `Idempotency-Key`。 +- App 对网络超时不能假定失败;必须用任务详情确认服务端最终状态。 +- 后端拒绝非法状态迁移,即使客户端 UI 隐藏了对应按钮。 +- SQLite MVP 使用单后端进程;切换多实例前先迁移 PostgreSQL 并验证领取竞争。 +- Gin handler 只做鉴权上下文、binding、调用 usecase 和响应映射。 + +## 七、自动化与安全边界 + +- 只允许目标拼多多包处于前台时发送动作。 +- 关键动作前后都校验包名、页面特征和任务取消标志。 +- 节点选择优先资源 ID、可访问性文本和稳定层级;文本版本变化要集中配置。 +- 截图发送给模型前裁剪无关区域并按配置脱敏。 +- 每个动作记录抽象步骤,不默认记录完整输入文本。 +- 发现验证码、风险控制、支付、生物识别或系统权限页面立即停止。 +- MVP 用代码级 allowlist 禁止所有已知“提交订单/支付”动作;不能仅靠提示词约束模型。 + +## 八、错误分类 + +| 错误码前缀 | 示例 | 处理 | +| --- | --- | --- | +| `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 范围执行 | diff --git a/docs/05-coding-rules.md b/docs/05-coding-rules.md new file mode 100644 index 0000000..c7db615 --- /dev/null +++ b/docs/05-coding-rules.md @@ -0,0 +1,94 @@ +# 编码规则 + +> 每次写代码前完整读取。需求决定“该不该做”,架构和 API 决定“如何接入”。 + +## 1. 黄金法则 + +1. 不臆造源码结构、拼多多页面、字段、接口或依赖。 +2. 一次只完成当前任务,不夹带后续功能。 +3. 高风险自动化先做可停止、可观察的最小探针。 +4. 代码完成不等于任务完成;必须有可运行验证证据。 +5. 安全规则不能只写在提示词或 UI 中,服务端和工作流都要强制执行。 + +## 2. 动手前 + +- 读取当前任务关联的需求、US、IX、架构、API 和页面路由。 +- 使用 codebase-memory 图谱优先发现代码;非代码和字符串搜索可用 `rg`。 +- 先核实上游 Roubao 的真实模块和测试,再决定修改位置。 +- 检查任务 `write_paths` 与用户已有改动,不覆盖无关内容。 +- 不确定的业务决策标为 blocker,不让实现自行发明。 + +## 3. 领域边界 + +- 原始任务输入是不可变事实;AI 派生字段单独保存。 +- 任务状态只能由领域状态机转换,HTTP 路由和 UI 不直接写状态。 +- Android 工作流只通过 task client、automation adapter 和 AI client 访问外部边界。 +- 管理页面调用 usecase,不直接执行 SQL。 +- 供应商 VLM SDK 类型停留在 infrastructure adapter。 +- 拼多多 UI 文本、资源标识和版本差异集中维护,不散落在工作流。 + +## 4. Android 自动化规则 + +- 动作前确认目标 App 包名和预期页面,动作后确认状态确实变化。 +- 优先使用资源 ID、可访问性语义和稳定文本;坐标只能作为被验证的局部降级。 +- 每个步骤定义 timeout、有限 retry、成功条件和停止条件。 +- 禁止无界循环、无限滑动、无限候选遍历和随机点击。 +- 默认最多检查 5 个候选;扩大范围必须先改需求。 +- 前台服务通知要展示任务编号和当前步骤,并提供安全停止入口。 +- 验证码、风控、登录、支付、未知页面统一进入安全失败。 +- MVP 不得实现最终提交订单或支付动作,包括“先写好但不调用”的隐藏代码。 + +## 5. AI 规则 + +- 输入明确区分原始事实、用户硬约束、页面观察和待推断字段。 +- 输出只接受结构化 schema;解析失败不能回退到自由文本猜测。 +- 数量、预算、允许平台和停止边界由确定性代码覆盖模型输出。 +- 提示词、schema、模型名和阈值版本化并记录到 execution。 +- 不向模型发送密码、token、支付信息或与候选判断无关的个人信息。 +- 模型低置信度或前后结果冲突时转人工,不自动增加动作权限。 + +## 6. 后端与 API 规则 + +- 请求在边界完成类型、大小、媒体类型和业务规则校验。 +- 领取任务必须使用事务;不得先 GET 再由客户端自行标记占用。 +- 状态变化校验当前状态、设备归属、claim token、版本和租约。 +- 创建、领取、完成和证据上传的重试路径必须幂等。 +- 不向客户端返回 `password_hash`、`token_hash`、存储绝对路径或供应商密钥。 +- 通用错误使用稳定 code 和可读 message;内部堆栈只进受控日志。 +- 文件访问通过鉴权接口,防止路径遍历和猜测 URL。 + +## 7. 安全与隐私 + +- 密钥只来自环境变量或被忽略的本地配置。 +- 日志默认脱敏,不记录 Authorization、Cookie、密码、设备令牌或完整地址。 +- 上传文件限制媒体类型、大小和解码结果,随机化服务端文件名。 +- 不绕过第三方平台限制、验证码、风控或系统权限。 +- 不可逆动作必须由明确需求、服务端授权、App 确认和幂等保护共同允许。 +- 发现需求与平台条款冲突时停止实现并记录 blocker。 + +## 8. 测试 + +每个任务按风险选择测试: + +- 领域状态机、硬约束、错误码:单元测试。 +- API 权限、事务、幂等、文件校验:集成测试。 +- VLM adapter:固定 fixture/契约测试,不让普通测试依赖真实付费 API。 +- Android workflow:用 fake automation/AI client 测状态和安全停止。 +- 拼多多真实流程:指定版本测试机手工 smoke,保存脱敏截图和步骤证据。 +- UI:覆盖默认、加载、空、错误、权限和中断状态。 + +不得用删除断言、放宽预算、安全停止或候选上限来让测试通过。 + +## 9. 完成定义 + +- [ ] 修改在任务 `write_paths` 内。 +- [ ] 构建、相关测试和格式检查通过。 +- [ ] 关联需求、US 和 IX 的验收通过。 +- [ ] 安全停止路径至少验证一次。 +- [ ] 没有真实密钥或敏感证据进入仓库。 +- [ ] 接口、数据模型或命令变化已同步文档。 +- [ ] 当前任务文件记录命令、结果、环境和未验证项。 +- [ ] `current-state.md` 与真实目录、命令和 blocker 一致。 + +当前尚无真实命令。`T-001` 后必须在这里列出 Android 构建和测试命令;后端建立后 +再列出后端命令。不能把 `docs/03-tech-stack.md` 中的计划命令当作已通过证据。 diff --git a/docs/06-tasks.md b/docs/06-tasks.md new file mode 100644 index 0000000..caacf8e --- /dev/null +++ b/docs/06-tasks.md @@ -0,0 +1,75 @@ +# 任务路线图 + +> 本文只维护阶段、里程碑和建议拆分。真实状态和执行证据在 +> [`tasks/T-<编号>.md`](tasks/README.md)。 + +## 使用规则 + +1. 从建议清单落成一任务一文件,沿用编号。 +2. 每个 agent 同时只做一项依赖已完成的任务。 +3. 高风险验证失败时先记录结论和 blocker,不继续堆后端功能。 +4. `DONE` 必须绑定可复现命令、设备环境或截图等证据。 +5. 本文只在路线图变化时修改,不因单任务状态变化而修改。 + +## Phase 0:可运行基线 + +| ID | 任务 | 依赖 | 验收要点 | +| --- | --- | --- | --- | +| T-001 | 初始化 Git 并接入 Roubao Android 基线 | - | 记录上游 URL/commit/许可证;Debug APK 构建通过;真实命令同步文档;不含密钥 | +| T-002 | 建立测试设备基线和就绪检查 | T-001 | 记录 Android/拼多多/App 版本;检测安装、无障碍、前台 App 和登录阻塞 | +| T-003 | 建立 Android workflow 测试骨架 | T-001 | fake automation 下可测状态迁移、timeout、retry 和安全停止 | + +## Phase 1:最高风险技术探针 + +| ID | 任务 | 依赖 | 验收要点 | +| --- | --- | --- | --- | +| T-101 | 固定任务跑通拼多多关键词搜索 | T-002、T-003 | 用固定搜索词进入结果页;未知页、验证码和登录页安全停止 | +| T-102 | 浏览并采集最多 5 个候选 | T-101 | 可进入候选详情、返回并记录证据;无界滑动被禁止 | +| T-103 | 接入 VLM 需求提取 | T-101 | 图片+文字输出符合 schema;数量和预算保持原值;低置信度转人工 | +| T-104 | 接入候选评估并停在人工确认点 | T-102、T-103 | 给出匹配/缺失理由;不得提交订单或支付 | + +## Phase 2:最小后台闭环 + +| ID | 任务 | 依赖 | 验收要点 | +| --- | --- | --- | --- | +| T-201 | 生成并收敛 Go-Gin、SQLite 和迁移骨架 | T-104 | 固定 Go Blueprint v0.10.11 生成后改为 Go 1.23.0、Gin 1.11.0;移除演示逻辑和危险默认;`GOTOOLCHAIN=local` 下服务、健康检查、迁移和 `go test ./...` 通过;数据目录被忽略 | +| T-202 | 生成并确认 P0 Web/App 低保真原型 | T-104 | 覆盖 routes 中 P0 页面;人工确认控件集合;IX 与原型一致 | +| T-203 | 实现任务创建 API 与管理 Web | T-201、T-202 | 合法任务进入 PENDING;校验、列表和详情状态可见 | +| T-204 | 实现用户/设备最小鉴权 | T-201、T-202 | 管理会话和设备令牌隔离;未授权访问被拒绝;无明文凭证 | +| T-205 | 实现原子 claim、租约和状态机 | T-203、T-204 | 并发领取不重复;非法迁移、过期租约和错误设备被拒绝 | +| T-206 | App 接入手动领取和执行进度 | T-202、T-205 | 用户点击后领取一条;前台服务显示步骤;取消安全停止 | +| T-207 | 接入候选、事件和截图回传 | T-206 | 幂等回传;管理详情可查看;资源访问受鉴权保护 | + +## Phase 3:端到端验证 + +| ID | 任务 | 依赖 | 验收要点 | +| --- | --- | --- | --- | +| T-301 | 完成 P0 UI 实现和交互验收 | T-203、T-206 | Web 和 App 的 IX 默认/加载/错误/中断状态均有验证证据 | +| T-302 | 建立脱敏、清理和审计策略 | T-207 | 日志/截图不泄密;文件保留和清理可配置;事件可追溯 | +| T-303 | 运行 20 条真实采购任务试验 | T-301、T-302 | 指标按需求统计;失败分类完整;无订单提交 | +| T-304 | 可行性评审和 V2 决策 | T-303 | 对照 80%/70% 门槛给出继续、修正或停止结论 | + +## Phase 4:交付验证版 + +| ID | 任务 | 依赖 | 验收要点 | +| --- | --- | --- | --- | +| T-401 | 打包 Android 验证 APK | T-304 | 干净环境可构建安装;版本和配置说明完整 | +| T-402 | 部署单机后台和备份说明 | T-304 | 新环境可启动;数据库/文件备份恢复完成一次演练 | +| T-403 | 完整 P0 回归与交付记录 | T-401、T-402 | 所有 P0 验收有证据;已知限制和 blocker 明确 | + +## 里程碑 + +- M1:Android 与测试设备基线可复现。 +- M2:固定任务 + VLM 在拼多多到达人工确认点。 +- M3:管理 Web、手动领取和结果回传闭环完成。 +- M4:20 条真实任务达到或未达到门槛,结论可审计。 +- M5:验证版 APK 和单机后台可交付。 + +## Backlog + +- 完整 RBAC 和人员管理。 +- 多设备调度、通知和租约回收运营页面。 +- 经单独安全评审后的订单提交审批。 +- PostgreSQL、对象存储和正式部署。 +- 原生以图搜图。 +- 淘宝、1688、京东并行比价。 diff --git a/docs/07-user-stories.md b/docs/07-user-stories.md new file mode 100644 index 0000000..e8cf140 --- /dev/null +++ b/docs/07-user-stories.md @@ -0,0 +1,161 @@ +# 用户故事清单 + +> 本文描述角色、目标和业务结果。具体按钮、加载和错误反馈见 +> [交互清单](08-interaction-checklist.md)。 + +## 用户故事总表 + +| ID | 标题 | 优先级 | 角色 | 要达成的结果 | 关联功能 | 关联交互 | 状态 | +| --- | --- | --- | --- | --- | --- | --- | --- | +| US-001 | 创建清晰的采购任务 | P0 | 采购管理员 | 把商品资料和硬约束变成可执行任务 | F-001 | IX-002 | 已定 | +| US-002 | 跟踪任务和查看证据 | P0 | 采购管理员 | 判断任务正在做什么、结果是否可信 | F-002、F-007 | IX-003 | 已定 | +| US-003 | 安全领取下一条任务 | P0 | 采购执行员 | 在设备就绪时领取且只领取一条任务 | F-003 | IX-005 | 已定 | +| US-004 | 自动检索并得到候选 | P0 | 采购执行员 | 减少手工提词和逐条比较 | F-004、F-005 | IX-006 | 已定 | +| US-005 | 在不可逆操作前人工判断 | P0 | 采购执行员 | 接受、拒绝候选或转人工,不被自动下单 | F-006 | IX-007 | 已定 | +| US-006 | 看懂失败并安全恢复 | P0 | 采购执行员、采购管理员 | 知道失败位置和下一步,避免重复操作 | F-007 | IX-008 | 已定 | +| US-007 | 建立受控会话和设备身份 | P0 | 采购管理员、采购执行员 | 未授权人员和设备不能接触任务 | F-001、F-003 | IX-001、IX-004 | 已定 | + +## US-001 创建清晰的采购任务 + +- 关联页面:管理 Web `/tasks/new` +- 前置条件:管理员已登录;参考图片可读取。 + +作为采购管理员,我想提交商品标题、描述、参考图、数量和预算,从而让采购设备拿到 +没有歧义的原始采购要求。 + +**范围** + +- 包含:输入校验、图片上传、任务编号、`PENDING` 状态。 +- 不包含:批量导入、任务模板、审批流。 + +**验收场景** + +1. 合法输入提交后,任务列表出现唯一编号、摘要和 `PENDING` 状态。 +2. 数量、预算、图片或文本不满足规则时,保留已填内容并指出修复位置。 +3. 网络超时后重复提交同一幂等请求,不产生重复任务。 + +## US-002 跟踪任务和查看证据 + +- 关联页面:管理 Web `/tasks`、`/tasks/{id}` +- 前置条件:管理员有任务查看权限。 + +作为采购管理员,我想查看任务状态、执行设备、候选和失败证据,从而判断自动化是否 +完成、是否需要人工介入。 + +**范围** + +- 包含:列表、详情、状态时间线、候选摘要、截图、错误。 +- 不包含:生产级报表、财务对账、实时视频。 + +**验收场景** + +1. 任务被领取和执行后,刷新详情能看到服务端最新状态和时间线。 +2. 任务完成后能看到候选匹配理由、人员判断和 `order_submitted=false`。 +3. 失败后能看到错误码、失败步骤、说明和有权限的证据图片。 +4. 无权限访问任务或证据时,明确拒绝且不泄露摘要。 + +## US-003 安全领取下一条任务 + +- 关联页面:Android“任务”页 +- 前置条件:采购员已登录、设备已绑定、没有活跃任务。 + +作为采购执行员,我想在设备就绪时点击获取下一条任务,从而自主控制何时开始采购, +并避免一台设备同时处理多条任务。 + +**范围** + +- 包含:就绪检查、手动领取、任务预览、无任务反馈。 +- 不包含:后台推送后自动执行、抢单优先级配置。 + +**验收场景** + +1. 设备就绪且有待处理任务时,点击后只出现一条已领取任务。 +2. 没有任务时显示空状态,不把空队列当作错误。 +3. 无障碍缺失、拼多多不可用、设备禁用或已有活跃任务时,说明原因并禁止领取。 +4. 网络超时或重复点击后,刷新服务端状态不会产生重复领取。 + +## US-004 自动检索并得到候选 + +- 关联页面:Android“任务执行”页、拼多多 App +- 前置条件:任务已领取;用户确认开始;拼多多处于可操作状态。 + +作为采购执行员,我想让系统从图片和文字提取搜索条件并检查少量商品,从而减少人工 +输入和逐条浏览。 + +**范围** + +- 包含:结构化解析、关键词搜索、最多 5 个候选、匹配解释。 +- 不包含:全站爬取、无限翻页、跨平台比价。 + +**验收场景** + +1. 解析结果保留原始数量和预算,并展示搜索词、属性、置信度和警告。 +2. App 能在已验证拼多多版本进入搜索结果并按有界流程检查候选。 +3. 找到候选时给出匹配项、缺失项、价格和判断依据。 +4. 无合理候选、模型低置信度或页面不确定时停止并转人工。 + +## US-005 在不可逆操作前人工判断 + +- 关联页面:Android“候选确认”页或拼多多候选/订单确认页 +- 前置条件:自动化已产生候选或“无匹配”结论。 + +作为采购执行员,我想在订单提交前检查候选并明确接受、拒绝或转人工,从而保持对 +资金和商品选择的控制。 + +**范围** + +- 包含:候选摘要、匹配理由、确认结果、停止自动化。 +- 不包含:提交订单、支付、修改收货地址、自动使用优惠。 + +**验收场景** + +1. 到达人工确认点后自动化不再点击,页面清楚显示等待人员处理。 +2. 接受候选只完成验证任务,结果明确记录 `order_submitted=false`。 +3. 拒绝、无匹配或转人工时记录原因,不偷偷改搜索条件继续尝试。 +4. 任意 MVP 路径都不能到达支付动作。 + +## US-006 看懂失败并安全恢复 + +- 关联页面:Android“任务执行/结果”页、管理 Web 任务详情 +- 前置条件:执行期间发生可恢复或不可恢复问题。 + +作为采购人员,我想知道自动化在哪一步因为什么停止,从而可以修复环境、人工接管或 +决定是否重试,而不是重复下单或丢失证据。 + +**范围** + +- 包含:结构化错误、步骤、必要截图、恢复建议、取消。 +- 不包含:无限自动重试、自动绕过平台提示。 + +**验收场景** + +1. 验证码、风控、登录失效、未知页面和安全边界分别产生可区分错误。 +2. 网络中断时保留本地待上传证据,恢复后用幂等方式补报。 +3. 用户取消时工作流在安全检查点停止,任务不会继续在后台点击。 +4. 重新打开终态任务可以看到相同结果和证据。 + +## US-007 建立受控会话和设备身份 + +- 关联页面:管理 Web `/login`、Android“登录/设备绑定”页 +- 前置条件:系统已有种子账号和授权设备。 + +作为授权用户,我想使用自己的账号和设备身份访问系统,从而让任务创建与执行可追溯, +并阻止未授权访问。 + +**范围** + +- 包含:登录、退出、设备绑定、会话过期处理。 +- 不包含:自助注册、找回密码、完整用户管理和 SSO。 + +**验收场景** + +1. 正确凭证建立会话,错误凭证不说明具体哪一项错误。 +2. 禁用账号或设备不能建立新会话或领取任务。 +3. 会话过期时保留非敏感界面上下文并要求重新登录。 +4. 管理员会话不能替代设备令牌,设备令牌也不能访问管理页面。 + +## 待确认 + +- 管理账号和采购账号的初始化、重置流程。 +- 谁负责确认测试任务、如何标注“候选可接受”的统一口径。 +- 拒绝候选是否允许创建新任务,当前默认只记录结果。 diff --git a/docs/08-interaction-checklist.md b/docs/08-interaction-checklist.md new file mode 100644 index 0000000..21d7cd4 --- /dev/null +++ b/docs/08-interaction-checklist.md @@ -0,0 +1,242 @@ +# 交互清单 + +> 本文把 P0 用户故事转换成可实现、可测试的 Web 和 Android 行为。页面入口见 +> [路由](routes.md),接口字段见 [API](api.md)。 + +## 交互总表 + +| ID | 用户故事 | 页面/组件 | 触发 | 预期结果 | 优先级 | 状态 | +| --- | --- | --- | --- | --- | --- | --- | +| IX-001 | US-007 | 管理 Web 登录 | 提交账号密码 | 建立管理会话或显示通用错误 | P0 | 已定 | +| IX-002 | US-001 | 新建任务表单 | 填写并提交 | 创建 `PENDING` 任务 | P0 | 已定 | +| IX-003 | US-002 | 任务列表/详情 | 打开、刷新、取消 | 查看最新状态、证据和允许动作 | P0 | 已定 | +| IX-004 | US-007 | App 登录/设备绑定 | 登录或会话恢复 | 建立人员+设备身份 | P0 | 已定 | +| IX-005 | US-003 | App 任务页 | 点击“获取任务” | 就绪检查后领取一条任务或显示原因 | P0 | 已定 | +| IX-006 | US-004 | App 执行页 | 确认开始/自动步骤 | 显示步骤并有界执行搜索与候选判断 | P0 | 已定 | +| IX-007 | US-005 | App 候选确认 | 接受/拒绝/转人工 | 停止自动化并回传人员结论 | P0 | 已定 | +| IX-008 | US-006 | App/管理端错误状态 | 自动失败、取消、重试上传 | 显示结构化原因和恢复动作 | P0 | 已定 | + +## IX-001 管理 Web 登录 + +- 页面:`/login` +- 角色:采购管理员 +- 前置条件:种子管理账号已建立。 +- 服务依赖:管理会话创建。 +- 关联原型:待 `T-301` 创建。 + +**正常路径** + +1. 用户输入账号和密码并提交。 +2. 提交期间按钮禁用并显示进度,密码不回显。 +3. 成功后进入原目标页或 `/tasks`。 + +**状态与异常** + +- 默认:账号框自动聚焦;密码可切换显示但默认隐藏。 +- 校验:空字段在字段附近提示;服务端仍执行完整校验。 +- 失败:统一显示“账号或密码不正确”,不暴露账号是否存在。 +- 网络错误:保留账号,清空密码,允许重试。 +- 会话过期:跳转登录并保留安全的返回路径。 + +**可访问性** + +- 标签与输入框显式关联;错误摘要可被读屏感知。 +- Enter 提交;焦点移到首个错误字段。 + +## IX-002 创建采购任务 + +- 页面:`/tasks/new` +- 角色:采购管理员 +- 服务依赖:`POST /api/v1/assets`、`POST /api/v1/tasks` +- 关联原型:待 `T-301` 创建。 + +**正常路径** + +1. 输入标题、描述、数量、可选预算并选择一张图片。 +2. 浏览器展示图片预览、文件名和大小。 +3. 提交期间锁定重复提交并显示“正在创建”。 +4. 成功后进入任务详情,显示编号和 `PENDING`。 + +**状态与异常** + +- 数量默认 1,只接受正整数;预算为空表示不设置上限。 +- 图片类型、大小或解码失败时在图片控件旁提示。 +- 上传成功但创建失败时重用已上传 asset,不重复上传。 +- 网络状态不确定时使用幂等键查询结果,不直接再创建。 +- 离开含未提交内容的表单时提示确认。 + +**可访问性与小屏** + +- 字段错误使用文本说明,不只使用颜色。 +- 图片选择有可访问名称;预览提供来源文件名。 +- 小屏下表单单列,提交按钮不遮挡最后一个字段。 + +## IX-003 查看任务与证据 + +- 页面:`/tasks`、`/tasks/{id}` +- 角色:采购管理员 +- 服务依赖:任务列表、详情、取消和资产读取 API。 +- 关联原型:待 `T-301` 创建。 + +**正常路径** + +1. 列表按最近创建时间展示编号、标题、状态、设备和更新时间。 +2. 进入详情查看原始输入、状态时间线、AI 派生结果、候选和证据。 +3. 仅 `PENDING`/允许状态展示取消命令,取消前二次确认。 + +**状态与异常** + +- 加载:保留页面框架和筛选条件,显示明确进度。 +- 空状态:说明还没有任务并提供“新建任务”入口。 +- 失败:保留上一次内容但标明可能过期,提供重试。 +- 权限不足/不存在:分别处理,但都不泄露任务内容。 +- 截图加载失败:显示占位和重试,不影响其他证据查看。 +- `SUCCEEDED` 详情必须醒目展示“验证完成,未提交订单”。 + +**可访问性** + +- 状态同时使用文字,不只用颜色。 +- 时间线使用有序列表语义;图片有描述性替代文本。 +- 列表在窄屏转换为可扫描行,不使用水平溢出遮挡操作。 + +## IX-004 App 登录与设备绑定 + +- 页面:Android“登录/设备绑定” +- 角色:采购执行员 +- 服务依赖:`POST /api/v1/auth/token`、设备心跳。 +- 关联原型:待 `T-301` 创建。 + +**正常路径** + +1. 用户输入采购账号并选择/确认设备身份。 +2. 成功后令牌存入 Android 安全存储,进入任务页。 +3. App 上报版本和就绪能力,不上传敏感设备内容。 + +**状态与异常** + +- 账号或设备被禁用:解释联系管理员,不反复重试。 +- 网络错误:保留非敏感账号字段,密码清空。 +- 会话恢复失败:退出到登录页;活跃任务先查询服务端再决定状态。 +- 退出登录:有运行任务时禁止直接退出,先安全停止。 + +**可访问性** + +- 支持系统字体缩放;输入与错误不重叠。 +- 软键盘不遮挡提交按钮,返回键不会静默丢失运行状态。 + +## IX-005 手动获取任务 + +- 页面:Android“任务” +- 角色:采购执行员 +- 服务依赖:设备预检、`POST /api/v1/tasks/claim-next` +- 关联原型:待 `T-301` 创建。 + +**正常路径** + +1. 页面显示无障碍、拼多多、网络和当前任务的就绪状态。 +2. 全部就绪时“获取任务”可用;点击后立即禁用防重复。 +3. 成功后展示任务预览和“开始采购”,此时状态为 `CLAIMED`。 + +**状态与异常** + +- 无任务:显示安静的空状态和手动刷新,不循环弹错。 +- 权限缺失:提供打开对应系统设置的命令。 +- 已有任务:显示“继续任务”,不再领取。 +- 请求超时:先查询当前设备活跃任务,再允许重试。 +- 租约到期:预览页提示任务已释放,返回任务页。 + +**可访问性** + +- 就绪状态使用图标加文字;系统设置命令有明确名称。 +- 主要控件满足 Android 最小触控区域,加载不改变控件尺寸。 + +## IX-006 执行采购任务 + +- 页面:Android“任务执行”及拼多多前台 +- 角色:采购执行员 +- 服务依赖:start、heartbeat、AI、event API 和 Android 自动化。 +- 关联原型:待 `T-301` 创建。 + +**正常路径** + +1. 用户检查原始需求并点击“开始采购”。 +2. App 启动前台服务,进入预检并显示当前步骤。 +3. 解析需求,打开拼多多,搜索并检查最多 5 个候选。 +4. 每一步上报事件;找到结果后进入 `WAITING_CONFIRMATION`。 + +**状态与异常** + +- 运行中禁止第二次开始;持续通知提供“返回任务”和“停止”。 +- App 切换到拼多多时,通知是回到执行页的稳定入口。 +- 用户请求停止后进入“正在安全停止”,不立即在动作中间销毁状态。 +- 进程重启时查询任务和 execution;无法证明可安全恢复则标记失败。 +- 验证码、风控、登录、支付和未知页面立即停止,不展示“自动继续”。 +- AI 超时最多按配置重试;输出无效或低置信度转人工。 +- 任意候选达到预算上限校验失败时不能进入接受状态。 + +**可访问性与反馈** + +- 当前步骤使用文字和进度列表,不显示虚假百分比。 +- 错误、暂停和等待人工使用不同语义,不只依赖颜色。 +- 通知操作名称明确;动态更新通过适度的 live region/无障碍播报。 + +## IX-007 人工确认候选 + +- 页面:Android“候选确认” +- 角色:采购执行员 +- 服务依赖:`POST /api/v1/tasks/{id}/complete` +- 关联原型:待 `T-301` 创建。 + +**正常路径** + +1. 展示原始需求、候选标题/价格、匹配项、缺失项和证据截图。 +2. 用户选择“接受候选”“拒绝候选”或“需人工处理”。 +3. 每种选择要求确认,必要时填写简短原因。 +4. 结果幂等回传,页面显示“验证完成,未提交订单”。 + +**状态与异常** + +- 没有候选时只允许确认“无匹配”或“需人工处理”。 +- 存在超预算或关键属性未知时禁用“接受候选”并说明原因。 +- 回传超时:保留选择和原因,查询最终状态后再重试。 +- 返回键不能恢复自动点击;等待确认一旦到达就是硬停止点。 +- 所有结果都写入 `order_submitted=false`。 + +**可访问性** + +- 候选信息按标题、价格、匹配和风险分组。 +- 确认对话框默认焦点在取消;破坏性/拒绝动作不能与接受动作混淆。 + +## IX-008 失败、取消和恢复 + +- 页面:Android“任务执行/结果”、Web 任务详情 +- 角色:采购执行员、采购管理员 +- 服务依赖:fail、event、asset API。 +- 关联原型:待 `T-301` 创建。 + +**正常路径** + +1. 系统停止动作,保存失败步骤和错误类别。 +2. App 显示发生了什么、是否已停止和建议下一步。 +3. 证据上传成功后,管理详情显示相同结论。 + +**状态与异常** + +- 上传失败:本地加密/受控保留待传证据,显示“结果待同步”。 +- 取消:说明不会自动恢复;服务端终态后清理前台服务。 +- 可恢复设备问题:只提供“修复后重新领取/新建尝试”,不原地猜测继续。 +- 安全错误 `SAFETY_*` 不允许自动重试。 +- 清理本地证据仅在服务端确认接收或超过明确保留策略后发生。 + +**验收证据** + +- 每类错误至少有一个自动化或 fake 测试。 +- 验证码/未知页/支付边界至少在受控环境各验证一次安全停止。 + +## 通用交互约束 + +- Web 和 App 的所有提交都防重复,网络超时后以服务端状态为准。 +- 状态名称使用用户可理解中文,同时保留稳定机器状态码。 +- 不在 UI 暴露模型密钥、设备令牌、内部堆栈或文件绝对路径。 +- 字体放大、窄屏、软键盘和系统返回操作下,主要命令和错误不能被遮挡。 +- P0 页面实现前按 [`design/README.md`](design/README.md) 生成低保真原型并人工确认。 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..2d7226e --- /dev/null +++ b/docs/README.md @@ -0,0 +1,46 @@ +# 项目文档导航 + +## 一句话定位 + +采购自动化验证系统是一个由管理 Web 端创建任务、Android 采购端领取任务,并通过 +AI 辅助完成拼多多检索和候选判断的系统;第一版先验证“创建 -> 领取 -> 搜索 -> +人工确认 -> 回传”的最小闭环。 + +## 核心文档 + +- [`../AGENTS.md`](../AGENTS.md):AI coding agent 的仓库级权威规则。 +- [`00-ai-start-here.md`](00-ai-start-here.md):每次开发的入口和开工流程。 +- [`01-vision.md`](01-vision.md):目标用户、价值、产品原则和非目标。 +- [`02-requirements.md`](02-requirements.md):MVP 范围、验收标准和待确认事项。 +- [`07-user-stories.md`](07-user-stories.md):角色目标和业务验收场景。 +- [`08-interaction-checklist.md`](08-interaction-checklist.md):Web 与 Android 的界面行为。 +- [`03-tech-stack.md`](03-tech-stack.md):已定技术选型、待验证项和计划命令。 +- [`04-architecture.md`](04-architecture.md):系统边界、数据流、状态机和数据模型。 +- [`api.md`](api.md):管理端和 App 共用的 API 合约。 +- [`routes.md`](routes.md):管理 Web 路由和 Android 页面结构。 +- [`05-coding-rules.md`](05-coding-rules.md):编码、安全和验证硬规则。 +- [`06-tasks.md`](06-tasks.md):只读路线图和建议任务拆分。 +- [`tasks/README.md`](tasks/README.md):一任务一文件的默认执行协议。 +- [`current-state.md`](current-state.md):当前仓库现实和 blocker。 + +## Harness 辅助文档 + +- [`agent-context.json`](agent-context.json):机器可读的按任务类型文档路由。 +- [`agent-context.md`](agent-context.md):上下文清单的使用方式。 +- [`clean-state-checklist.md`](clean-state-checklist.md):每轮结束前检查项。 +- [`design/README.md`](design/README.md):P0 页面低保真原型约定。 +- [`../progress.md`](../progress.md):可选的项目级大事记。 +- [`../init.ps1`](../init.ps1) / [`../init.sh`](../init.sh):标准验证入口;当前等待 + `T-001` 写入真实命令。 + +## 文档职责 + +- “做不做、怎么算完成”以 `02-requirements.md` 为准。 +- “谁要获得什么结果”以 `07-user-stories.md` 为准。 +- “界面如何反馈”以 `08-interaction-checklist.md` 为准。 +- “系统如何分层、状态如何变化”以 `04-architecture.md` 为准。 +- “接口字段和错误”以 `api.md` 为准。 +- “当前代码是否存在、什么命令能跑”以 `current-state.md` 和真实验证结果为准。 +- 任务规格、状态和证据以 `docs/tasks/T-<编号>.md` 为准。 + +需求或架构变化时同步所有受影响的文档,不允许代码独自形成另一套事实。 diff --git a/docs/agent-context.json b/docs/agent-context.json new file mode 100644 index 0000000..5c14c55 --- /dev/null +++ b/docs/agent-context.json @@ -0,0 +1,88 @@ +{ + "schema": "docs/agent-context.schema.json", + "schema_version": 1, + "authority": { + "bootstrap": "local_checkout", + "framework_templates": "project_harness_docs", + "project_facts": "current_project_repository", + "coordination": "local_docs_task_files" + }, + "bootstrap": { + "always_read": [ + "AGENTS.md", + "docs/00-ai-start-here.md", + "docs/05-coding-rules.md", + "docs/current-state.md" + ] + }, + "routes": { + "documentation": [ + "README.md", + "docs/README.md", + "docs/01-vision.md", + "docs/02-requirements.md" + ], + "android": [ + "docs/02-requirements.md", + "docs/03-tech-stack.md", + "docs/04-architecture.md", + "docs/07-user-stories.md", + "docs/08-interaction-checklist.md", + "docs/routes.md" + ], + "automation": [ + "docs/02-requirements.md", + "docs/04-architecture.md", + "docs/05-coding-rules.md", + "docs/api.md" + ], + "ai": [ + "docs/02-requirements.md", + "docs/04-architecture.md", + "docs/05-coding-rules.md", + "docs/api.md" + ], + "backend": [ + "docs/03-tech-stack.md", + "docs/04-architecture.md", + "docs/api.md" + ], + "ui": [ + "docs/02-requirements.md", + "docs/07-user-stories.md", + "docs/08-interaction-checklist.md", + "docs/routes.md", + "docs/design/README.md" + ], + "data": [ + "docs/04-architecture.md", + "docs/api.md" + ], + "security": [ + "docs/02-requirements.md", + "docs/04-architecture.md", + "docs/05-coding-rules.md", + "docs/api.md" + ], + "deploy": [ + "docs/03-tech-stack.md", + "docs/current-state.md" + ] + }, + "tasks": { + "roadmap": "docs/06-tasks.md", + "directory": "docs/tasks/", + "template": "docs/tasks/_template.md" + }, + "refresh": { + "context_ref": "default_branch_head_sha", + "cache_key": "file_sha", + "unchanged_file": "reuse_within_current_session", + "changed_ref": "reread_manifest_and_routed_documents" + }, + "degraded_mode": { + "continue_claimed_task": true, + "claim_new_task": false, + "write_remote_state": false + } +} diff --git a/docs/agent-context.md b/docs/agent-context.md new file mode 100644 index 0000000..c0d71b4 --- /dev/null +++ b/docs/agent-context.md @@ -0,0 +1,35 @@ +# Agent 上下文清单 + +[`agent-context.json`](agent-context.json) 用于按任务类型读取最小上下文, +[`agent-context.schema.json`](agent-context.schema.json) 约束其结构。 + +## 使用流程 + +```text +AGENTS.md + -> agent-context.json + -> bootstrap.always_read + -> 当前任务文件 + -> 一个或多个 routes + -> 代码发现、实现、验证 +``` + +- 同一文件命中多个 route 时只读一次。 +- 首次接入、清单缺失或校验失败时,按 `00-ai-start-here.md` 完整顺序读取。 +- 仓库未启用 Git 时不能假装存在 `context_ref`;任务 frontmatter 保持 `null`。 +- Git 启用后,领取时记录默认分支头 SHA;同一会话文件内容未变可复用。 +- 当前代码和真实命令结果高于历史讨论、计划命令和旧截图。 +- 远端协调不可用时可以继续已领取任务,但不领取新任务,也不猜测其他执行者状态。 + +## 权威来源 + +| 信息 | 权威来源 | +| --- | --- | +| 仓库硬规则 | 最近作用域的 `AGENTS.md` | +| 产品范围 | `02-requirements.md` | +| 架构和状态机 | `04-architecture.md` | +| API 字段 | `api.md` | +| 任务规格、状态和证据 | `docs/tasks/T-<编号>.md` | +| 当前现实 | `current-state.md`、代码和实际验证 | + +修改清单引用的路径时,必须验证 JSON 可解析且所有仓库相对路径存在。 diff --git a/docs/agent-context.schema.json b/docs/agent-context.schema.json new file mode 100644 index 0000000..cb44000 --- /dev/null +++ b/docs/agent-context.schema.json @@ -0,0 +1,94 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.invalid/cmroubao/agent-context.schema.json", + "title": "cmroubao agent context manifest", + "type": "object", + "additionalProperties": false, + "required": [ + "schema", + "schema_version", + "authority", + "bootstrap", + "routes", + "tasks", + "refresh", + "degraded_mode" + ], + "properties": { + "schema": { + "const": "docs/agent-context.schema.json" + }, + "schema_version": { + "const": 1 + }, + "authority": { + "type": "object", + "minProperties": 1, + "additionalProperties": { + "type": "string", + "minLength": 1 + } + }, + "bootstrap": { + "type": "object", + "additionalProperties": false, + "required": ["always_read"], + "properties": { + "always_read": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": {"$ref": "#/$defs/repositoryPath"} + } + } + }, + "routes": { + "type": "object", + "minProperties": 1, + "additionalProperties": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": {"$ref": "#/$defs/repositoryPath"} + } + }, + "tasks": { + "type": "object", + "additionalProperties": false, + "required": ["roadmap", "directory", "template"], + "properties": { + "roadmap": {"$ref": "#/$defs/repositoryPath"}, + "directory": {"$ref": "#/$defs/repositoryPath"}, + "template": {"$ref": "#/$defs/repositoryPath"} + } + }, + "refresh": { + "type": "object", + "additionalProperties": false, + "required": ["context_ref", "cache_key", "unchanged_file", "changed_ref"], + "properties": { + "context_ref": {"const": "default_branch_head_sha"}, + "cache_key": {"const": "file_sha"}, + "unchanged_file": {"const": "reuse_within_current_session"}, + "changed_ref": {"const": "reread_manifest_and_routed_documents"} + } + }, + "degraded_mode": { + "type": "object", + "additionalProperties": false, + "required": ["continue_claimed_task", "claim_new_task", "write_remote_state"], + "properties": { + "continue_claimed_task": {"type": "boolean"}, + "claim_new_task": {"type": "boolean"}, + "write_remote_state": {"type": "boolean"} + } + } + }, + "$defs": { + "repositoryPath": { + "type": "string", + "minLength": 1, + "pattern": "^(?!/)(?!.*\\\\\\\\)(?!.*(^|/)\\.\\.(/|$))(?![A-Za-z][A-Za-z0-9+.-]*:).+$" + } + } +} diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..1adcd3d --- /dev/null +++ b/docs/api.md @@ -0,0 +1,406 @@ +# API 合约 + +> MVP 使用 `/api/v1`、UTF-8 JSON over HTTPS。文件上传使用 `multipart/form-data`。 +> Web 页面可以直接调用同一 usecase,但不能形成不同的业务规则。 + +## 通用约定 + +- 所有 ID 为 UUID 字符串。 +- 时间为 UTC ISO 8601,例如 `2026-07-25T08:30:00Z`。 +- 金额使用十进制定点字符串,例如 `"199.00"`,币种固定 `CNY`;不使用浮点数。 +- 写接口在合约标注处接收 `Idempotency-Key` 请求头。 +- App 的任务执行接口同时需要用户 Bearer Token、设备身份和 `X-Claim-Token`。 +- 分页使用 `limit` 和不透明 `cursor`;MVP `limit` 最大 100。 +- 客户端不得根据 HTTP 超时判断操作失败,必须查询资源最终状态。 + +通用错误: + +```json +{ + "error": { + "code": "TASK_STATE_CONFLICT", + "message": "任务当前状态不允许此操作", + "retryable": false, + "details": {} + }, + "request_id": "f2cf02e9-57e0-4fca-817b-c85228acfc81" +} +``` + +HTTP 语义: + +- `400` 请求格式或业务校验失败 +- `401` 未建立有效身份 +- `403` 身份有效但无权限、设备禁用或 claim 不属于当前设备 +- `404` 资源不存在,外部响应不泄露其他人的资源存在性 +- `409` 幂等冲突、状态冲突或设备已有活跃任务 +- `413` 文件过大 +- `415` 不支持的媒体类型 +- `422` 结构可解析但字段不满足 schema +- `429` 频率限制 +- `503` 依赖暂不可用 + +## 认证 + +### 管理 Web 会话 + +`POST /login` 接受表单账号密码,成功后设置 `HttpOnly`、`Secure`、`SameSite=Lax` +会话 Cookie。`POST /logout` 清除会话。Web 会话不能调用设备执行接口。 + +### `POST /api/v1/auth/token` + +采购 App 建立用户和设备联合会话。 + +```json +{ + "username": "buyer01", + "password": "local-input-only", + "device_id": "f0c3d438-1c44-4f80-b898-c645afe7eaa8", + "device_token": "local-input-only", + "app_version": "0.1.0", + "android_version": "待设备填写" +} +``` + +成功: + +```json +{ + "access_token": "opaque-or-jwt-token", + "token_type": "Bearer", + "expires_in": 3600, + "user": { + "id": "d950db90-cf58-4f21-86fd-067e1a91a3a6", + "username": "buyer01", + "role": "BUYER" + }, + "device": { + "id": "f0c3d438-1c44-4f80-b898-c645afe7eaa8", + "enabled": true + } +} +``` + +密码和设备 token 不得出现在响应、日志或 execution event 中。 + +## 资产 + +### `POST /api/v1/assets` + +管理会话上传任务参考图片;App 也可用设备会话上传执行截图。请求必须带 +`Idempotency-Key`。 + +表单字段: + +- `file`:必填,MVP 允许 JPEG/PNG/WebP;实际大小上限在配置中固定。 +- `purpose`:`TASK_REFERENCE` 或 `EXECUTION_EVIDENCE`。 +- `task_id`:证据图片必填;参考图创建时为空。 + +成功: + +```json +{ + "id": "2bbc1bf2-30f7-497e-a52b-bcb4c61d57c3", + "media_type": "image/jpeg", + "size_bytes": 183245, + "sha256": "hex-value", + "created_at": "2026-07-25T08:30:00Z" +} +``` + +### `GET /api/v1/assets/{asset_id}/content` + +受鉴权的文件流。只能读取用户有权查看的任务资产;不返回服务端文件路径。 + +## 采购任务 + +### `POST /api/v1/tasks` + +采购管理员或授权的外部管理系统创建任务。必须带 `Idempotency-Key`。 + +```json +{ + "source_ref": "external-admin-task-10001", + "title": "黑色双肩包", + "description": "容量约20L,外观接近参考图", + "image_asset_id": "2bbc1bf2-30f7-497e-a52b-bcb4c61d57c3", + "quantity": 2, + "max_budget": "200.00" +} +``` + +规则: + +- `title` 或 `description` 至少一个非空,`image_asset_id` 必填。 +- `quantity` 是正整数。 +- `max_budget` 可为空,否则为大于零、最多两位小数的 CNY 金额。 +- 同一调用方的 `source_ref` 如填写必须唯一。 + +成功返回 `201`: + +```json +{ + "id": "37c9c715-9b51-4ed5-984e-66dad2710c71", + "status": "PENDING", + "title": "黑色双肩包", + "quantity": 2, + "max_budget": "200.00", + "created_at": "2026-07-25T08:30:00Z" +} +``` + +### `GET /api/v1/tasks` + +管理端列表。可选参数:`status`、`created_from`、`created_to`、`limit`、`cursor`。 + +```json +{ + "items": [ + { + "id": "37c9c715-9b51-4ed5-984e-66dad2710c71", + "title": "黑色双肩包", + "status": "RUNNING", + "quantity": 2, + "device_name": "pdd-phone-01", + "updated_at": "2026-07-25T08:35:00Z" + } + ], + "next_cursor": null +} +``` + +### `GET /api/v1/tasks/{task_id}` + +管理会话返回完整任务、当前 execution、时间线、候选和资产元数据。App 只能读取 +当前设备已领取的任务。响应必须同时包含: + +- `original_requirement`:不可变原始输入。 +- `derived_requirement`:模型输出,可能为空。 +- `claim`:管理端可见设备和到期时间;claim token 永不返回。 +- `execution`:step、outcome、错误、`order_submitted`。 +- `events` 和 `assets`:有权限的摘要。 + +### `POST /api/v1/tasks/{task_id}/cancel` + +管理端取消任务。`PENDING` 可立即取消;执行中只设置取消请求,App 在安全检查点确认 +后进入 `CANCELED`。终态返回 `409`。 + +```json +{ + "reason": "需求已撤销" +} +``` + +## 设备与领取 + +### `POST /api/v1/devices/heartbeat` + +App 空闲或运行时上报设备状态;运行时任务续租使用任务专用 heartbeat。 + +```json +{ + "device_id": "f0c3d438-1c44-4f80-b898-c645afe7eaa8", + "app_version": "0.1.0", + "pdd_version": "device-observed-value", + "readiness": { + "accessibility_enabled": true, + "pdd_installed": true, + "active_task_id": null + } +} +``` + +### `POST /api/v1/tasks/claim-next` + +由用户点击触发,在单个数据库事务中领取下一条任务。必须带 `Idempotency-Key`。 + +```json +{ + "device_id": "f0c3d438-1c44-4f80-b898-c645afe7eaa8" +} +``` + +有任务时: + +```json +{ + "task": { + "id": "37c9c715-9b51-4ed5-984e-66dad2710c71", + "status": "CLAIMED", + "title": "黑色双肩包", + "description": "容量约20L,外观接近参考图", + "image_asset_id": "2bbc1bf2-30f7-497e-a52b-bcb4c61d57c3", + "quantity": 2, + "max_budget": "200.00" + }, + "claim_token": "returned-once", + "claim_expires_at": "2026-07-25T08:40:00Z" +} +``` + +没有任务返回 `204`。设备未就绪或已有活跃任务返回 `409`。幂等重放返回同一领取 +结果;claim token 的安全重放形式在实现前通过测试固定。 + +### `POST /api/v1/tasks/{task_id}/start` + +把当前设备持有的 `CLAIMED` 任务改为 `RUNNING` 并创建 execution。请求带 +`X-Claim-Token` 和 `Idempotency-Key`。 + +### `POST /api/v1/tasks/{task_id}/heartbeat` + +运行时续租并返回是否请求取消: + +```json +{ + "execution_id": "e3190742-a24b-441e-b5c1-c7ed10ed342f", + "step": "SCAN_RESULTS", + "client_time": "2026-07-25T08:33:30Z" +} +``` + +```json +{ + "claim_expires_at": "2026-07-25T08:43:30Z", + "cancel_requested": false +} +``` + +### `POST /api/v1/tasks/{task_id}/release` + +只允许尚未开始的 `CLAIMED` 任务释放回 `PENDING`。运行中使用取消/失败流程。 + +## AI 合约 + +### `POST /api/v1/tasks/{task_id}/ai/extract-requirements` + +只允许当前 execution 调用。后端从任务读取原始图片和文字,客户端不能替换硬约束。 + +```json +{ + "execution_id": "e3190742-a24b-441e-b5c1-c7ed10ed342f" +} +``` + +响应: + +```json +{ + "schema_version": 1, + "search_query": "黑色 20L 双肩包", + "category": "双肩包", + "attributes": [ + {"name": "color", "value": "black", "source": "text"}, + {"name": "capacity", "value": "about 20L", "source": "text"} + ], + "quantity": 2, + "max_budget": "200.00", + "confidence": 0.86, + "warnings": [] +} +``` + +### `POST /api/v1/tasks/{task_id}/ai/evaluate-candidate` + +```json +{ + "execution_id": "e3190742-a24b-441e-b5c1-c7ed10ed342f", + "candidate_index": 1, + "screenshot_asset_id": "7b733922-f90f-4bc4-a9ad-3e8ec4769122", + "observed": { + "title": "页面可见标题", + "price": "189.00" + } +} +``` + +响应: + +```json +{ + "schema_version": 1, + "decision": "REVIEW", + "score": 0.82, + "matched": ["颜色接近", "价格未超预算"], + "missing_or_uncertain": ["容量无法从当前页面确认"], + "rejection_reasons": [], + "confidence": 0.78 +} +``` + +`decision` 只允许 `REVIEW`、`REJECT`、`MANUAL_REQUIRED`。模型没有“提交订单”权限。 + +## 执行事件与结果 + +### `POST /api/v1/tasks/{task_id}/events` + +批量追加事件,必须带 `Idempotency-Key`: + +```json +{ + "execution_id": "e3190742-a24b-441e-b5c1-c7ed10ed342f", + "events": [ + { + "event_id": "client-generated-uuid", + "step": "SEARCH", + "type": "STEP_COMPLETED", + "message": "已进入搜索结果页", + "occurred_at": "2026-07-25T08:34:00Z" + } + ] +} +``` + +`message` 不能包含凭证或完整个人敏感信息;同一 `event_id` 重放不重复插入。 + +### `POST /api/v1/tasks/{task_id}/complete` + +人员完成确认后调用,必须带 `Idempotency-Key`: + +```json +{ + "execution_id": "e3190742-a24b-441e-b5c1-c7ed10ed342f", + "outcome": "CANDIDATE_ACCEPTED", + "operator_reason": "款式和预算符合验证要求", + "candidate": { + "title": "页面可见标题", + "price": "189.00", + "evidence_asset_ids": ["7b733922-f90f-4bc4-a9ad-3e8ec4769122"] + }, + "order_submitted": false +} +``` + +`outcome` 允许: + +- `CANDIDATE_ACCEPTED` +- `CANDIDATE_REJECTED` +- `NO_MATCH` +- `MANUAL_REQUIRED` + +后端对 MVP 强制 `order_submitted=false`,成功后任务进入 `SUCCEEDED`;这里的成功表示 +验证工作流正常结束,业务结果由 `outcome` 表达。 + +### `POST /api/v1/tasks/{task_id}/fail` + +```json +{ + "execution_id": "e3190742-a24b-441e-b5c1-c7ed10ed342f", + "error": { + "code": "PDD_RISK_CONTROL", + "message": "检测到平台风险提示,已停止自动化", + "step": "SCAN_RESULTS", + "retryable": false + }, + "evidence_asset_ids": ["7b733922-f90f-4bc4-a9ad-3e8ec4769122"] +} +``` + +后端只接受文档登记的错误码族和合法状态迁移。 + +## 待实现前固定 + +- 上传大小、像素和保留期限的具体数值。 +- access token、管理会话和 claim lease 的最终时长。 +- claim token 幂等重放与轮换细节。 +- VLM `confidence` 阈值、模型和提示词版本记录格式。 +- 外部管理后台的服务账号认证方式和调用频率。 diff --git a/docs/clean-state-checklist.md b/docs/clean-state-checklist.md new file mode 100644 index 0000000..aaa69ee --- /dev/null +++ b/docs/clean-state-checklist.md @@ -0,0 +1,16 @@ +# 干净收尾检查清单 + +每轮结束前确认: + +- [ ] 只处理了一个已领取任务,修改没有超出 `write_paths`。 +- [ ] 当前任务状态真实;没有验证证据时未标 `DONE`。 +- [ ] 构建、测试、smoke 或不能运行的原因已写入任务执行记录。 +- [ ] 关联需求、架构、API、US、IX 和路由已同步。 +- [ ] `current-state.md` 的目录、命令、下一任务和 blocker 与现实一致。 +- [ ] Android 自动化的 timeout、有限 retry 和安全停止已验证。 +- [ ] 没有订单提交/支付动作、验证码绕过或未知页面猜测。 +- [ ] 没有真实密码、token、Cookie、私有 URL 或敏感截图进入仓库。 +- [ ] 文件和 API 的幂等/超时路径没有被忽略。 +- [ ] 用户已有修改没有被重置、删除或混入本任务提交。 +- [ ] Git 已启用时工作树状态和提交边界清晰;未启用时明确记录。 +- [ ] 新 agent 可以从 `AGENTS.md`、当前任务和 `current-state.md` 继续。 diff --git a/docs/current-state.md b/docs/current-state.md new file mode 100644 index 0000000..32c05da --- /dev/null +++ b/docs/current-state.md @@ -0,0 +1,67 @@ +# 当前实现状态 + +> 可覆盖的项目级快照。任务执行日志写入对应任务文件。 + +## 当前快照 + +- 日期:2026-07-25 +- 阶段:Harness 文档基线完成,T-001 已开始,Android 源码尚未接入 +- Git:已初始化,当前分支为 `main`,文档和初始化脚本纳入首个基线提交 +- 生产代码:无 +- Android:Roubao 源码尚未接入;上游仓库、MIT 许可证、分支和构建版本已远端核实 +- 后端:已决定使用 Go 1.23.0 + Gin 1.11.0;Go Blueprint v0.10.11 骨架尚未接入 +- 本机 Android 工具:JDK 17.0.13 和 ADB 已有;Android Studio、Android SDK 34 + 未检测到,`ANDROID_HOME`/`ANDROID_SDK_ROOT` 未设置 +- 测试:无 +- 数据:只有 `deepseek总结.txt` 背景摘要和本套项目文档 +- 标准启动路径:未配置;`init.ps1`/`init.sh` 会主动失败 +- 标准验证路径:文档结构和链接检查;无代码构建 +- 当前 blocker:Roubao 尚未导入,`main` 与无障碍开发分支尚未完成代码差异评估; + Android Studio/SDK 34 未安装或未被检测到,测试设备状态未知;拼多多测试版本/账号 + 未建立基线;VLM 供应商和测试凭证未确认 + +## 当前目录 + +| 路径 | 状态 | 说明 | +| --- | --- | --- | +| `AGENTS.md` | 已有 | agent 权威入口 | +| `docs/` | 已有 | Harness Coding 文档 | +| `docs/tasks/T-001.md` | TODO | 当前第一个可领取任务 | +| `deepseek总结.txt` | 已有 | 历史讨论摘要,不是正式需求权威 | +| `android-buyer/` | 待建 | Roubao Android 代码目标目录 | +| `backend-api/` | 待建 | Go-Gin、管理 Web 和数据目标目录 | +| `init.ps1` / `init.sh` | 占位 | T-001 后写入真实命令 | + +## 任务摘要 + +- 已完成:Harness 文档初始化(本次文档工作,不作为产品开发任务编号)。 +- 正在进行:`T-001 初始化 Git 并接入 Roubao Android 基线`;已完成 Git 初始化和 + 上游远端核实,源码导入及构建尚未完成。 +- 下一个可领取任务:无;完成 T-001 后才能领取依赖它的任务。 + +## 当前可运行内容 + +没有生产代码或已验证构建命令。以下检查仅验证文档文件: + +```powershell +Get-ChildItem -Recurse -File +Get-Content docs/agent-context.json -Raw | ConvertFrom-Json | Out-Null +``` + +`docs/03-tech-stack.md` 中的 Gradle、Go 构建和启动命令是计划形状,尚不能作为 +当前可运行内容。 + +已核实的 Roubao 远端版本事实记录在 `docs/03-tech-stack.md`;“已核实”只表示查看了 +上游配置,不表示本机已经具备 Android SDK 或完成过 APK 构建。 + +## 维护规则 + +发生以下变化时覆盖更新本文: + +- 初始化 Git 或接入上游代码。 +- 获得首个可复现 Android 构建、安装或启动命令。 +- 建立后端和真实测试命令。 +- 设备、拼多多和 VLM 基线确定。 +- 项目阶段、目录或 blocker 变化。 + +任务的详细状态、验证和决策写入 `docs/tasks/T-<编号>.md`,本文只保留快照。 diff --git a/docs/design/README.md b/docs/design/README.md new file mode 100644 index 0000000..7591a4c --- /dev/null +++ b/docs/design/README.md @@ -0,0 +1,35 @@ +# 设计原型输入约定 + +本目录用于 P0 管理 Web 和 Android 页面开工前的低保真原型。原型只回答“页面上有 +什么”,行为权威是 [`../08-interaction-checklist.md`](../08-interaction-checklist.md)。 + +## 形态 + +- 一页面一个可独立打开的 HTML 文件,CSS/JS 内联,零构建依赖。 +- Android 页面也用手机尺寸 HTML 表达控件和信息结构,不伪装成生产代码。 +- 页面顶部固定标记:`PROTOTYPE - 仅供确认布局和交互,不是生产实现`。 +- 使用假数据,不放真实账号、商品图、订单、地址、token 或生产 URL。 +- 使用语义化 `button`、`form`、`table`、`dialog` 等元素。 + +建议文件: + +```text +admin-login.html +admin-task-list.html +admin-task-create.html +admin-task-detail.html +android-login.html +android-task-home.html +android-task-running.html +android-candidate-confirm.html +``` + +## 工作流 + +1. 根据需求、US 和 routes 生成对应 P0 页面原型。 +2. 人工确认页面区块、控件集合、文案和主要动作。 +3. 对照原型更新 IX 总表和 P0 详情。 +4. 再落正式 UI 任务;实现时按真实框架重写,禁止复制原型代码。 + +原型实现后即视为过期,不要求持续同步。显著改变布局或控件集合时重新生成整页; +小文案或字段变化只更新需求/IX。原型与需求冲突时,以需求和已确认 IX 为准。 diff --git a/docs/routes.md b/docs/routes.md new file mode 100644 index 0000000..1874bee --- /dev/null +++ b/docs/routes.md @@ -0,0 +1,52 @@ +# 路由与页面结构 + +## 管理 Web + +| 路由 | 页面 | 职责 | 用户故事 | 交互 | +| --- | --- | --- | --- | --- | +| `/login` | 管理登录 | 建立服务端管理会话 | US-007 | IX-001 | +| `/tasks` | 任务列表 | 查看状态、筛选并进入详情 | US-002 | IX-003 | +| `/tasks/new` | 新建任务 | 提交图片和采购约束 | US-001 | IX-002 | +| `/tasks/{id}` | 任务详情 | 查看原始输入、时间线、候选和证据 | US-002、US-006 | IX-003、IX-008 | + +MVP 登录后默认进入 `/tasks`。未登录访问受保护页面时跳转 `/login` 并携带安全的 +站内返回路径。不存在和无权限必须使用不同内部原因,但页面均不得泄露任务内容。 + +## Android 页面 + +Android 导航名称是逻辑目的地,具体 Compose/Fragment 形式待接入 Roubao 源码后确定。 + +| 目的地 | 页面 | 职责 | 用户故事 | 交互 | +| --- | --- | --- | --- | --- | +| `login` | 登录/设备绑定 | 建立人员与设备身份 | US-007 | IX-004 | +| `tasks` | 任务主页 | 就绪检查、获取或继续任务 | US-003 | IX-005 | +| `task/{id}/preview` | 任务预览 | 检查原始要求并开始 | US-003、US-004 | IX-005、IX-006 | +| `task/{id}/running` | 任务执行 | 显示步骤、返回拼多多、安全停止 | US-004、US-006 | IX-006、IX-008 | +| `task/{id}/confirm` | 候选确认 | 接受、拒绝、无匹配或转人工 | US-005 | IX-007 | +| `task/{id}/result` | 任务结果 | 查看终态和同步状态 | US-002、US-006 | IX-007、IX-008 | +| `settings` | 设备设置 | 查看权限、版本、后端和模型连接状态 | US-003、US-007 | IX-004、IX-005 | + +## 导航规则 + +- App 有活跃任务时启动后优先恢复该任务,不允许直接领取下一条。 +- `CLAIMED` 进入预览;`RUNNING` 进入执行;`WAITING_CONFIRMATION` 进入候选确认; + 终态进入结果。 +- 从执行页切换拼多多后,使用前台服务通知返回执行页。 +- 候选确认页返回不能恢复自动化。 +- 登录过期时先保存非敏感本地状态,再跳转登录;重新登录后查询服务端状态。 +- 设备设置不是首屏,任务主页是采购人员的工作入口。 + +## 页面组件边界 + +| 组件 | 归属 | 说明 | +| --- | --- | --- | +| `TaskForm` | 管理 Web | 只管理表单状态和可访问反馈,创建逻辑在 usecase | +| `TaskStatusBadge` | 管理 Web | 统一状态中文和语义,不内置状态迁移 | +| `ExecutionTimeline` | 管理 Web/App | 展示只追加事件 | +| `ReadinessPanel` | Android | 汇总权限、安装、网络和活跃任务 | +| `TaskRequirementSummary` | Android/Web | 展示原始输入和 AI 派生信息,视觉上明确区分 | +| `CandidateReview` | Android/Web | 展示候选与硬约束校验,不执行自动化动作 | +| `ExecutionController` | Android | UI 命令入口,委托 workflow,不直接调用 Accessibility | + +具体状态反馈以[交互清单](08-interaction-checklist.md)为准,组件命名可在接入真实框架后 +调整并同步本文。 diff --git a/docs/tasks/README.md b/docs/tasks/README.md new file mode 100644 index 0000000..bd35d8a --- /dev/null +++ b/docs/tasks/README.md @@ -0,0 +1,73 @@ +# 任务文件 + +> 默认一任务一文件:`docs/tasks/T-<编号>.md`。路线图只负责建议拆分,不跟踪状态。 + +## 命名和状态 + +- 文件名:`T-001.md`;细分任务可使用 `T-001a.md`。 +- 状态:`TODO`、`DOING`、`DONE`、`BLOCKED`。 +- 路线图已有编号时沿用;新编号不能覆盖已存在文件。 +- `_template.md` 不是任务。 + +## 领取规则 + +1. 每个 agent 同时最多一个 `DOING` 任务。 +2. 领取编号最小、状态为 `TODO`、依赖全部 `DONE` 的任务。 +3. 开工前写清 `write_paths`;和其他活跃任务有路径重叠时不得并行。 +4. 仓库启用 Git 后记录默认分支头 `context_ref` 和工作分支;未启用时保持 `null`。 +5. 状态改为 `DOING` 后再修改生产代码。 +6. 验收全部有证据后改为 `DONE`;无法继续时标 `BLOCKED` 并写清所需外部输入。 + +## 任务文件结构 + +```yaml +--- +id: T-101 +title: 一句话任务名 +phase: 1 +deps: [T-001] +status: TODO +created: 2026-07-25 +context_ref: null +work_branch: null +write_paths: + - docs/tasks/T-101.md + - android-buyer/path/** +--- +``` + +正文必须包含: + +- 问题/背景 +- 关联需求与交互 +- 方案 +- 验收要点 +- 边界 +- 执行记录 + +## 验证证据 + +执行记录至少写: + +- 修改的文件。 +- 实际运行的完整命令。 +- 结果是成功、失败还是未运行。 +- Android smoke 的设备、Android、App 和拼多多版本。 +- 未验证范围和 blocker。 +- 涉及自动化时的安全停止证据。 + +“代码写完”“看起来可以”不能作为 `DONE` 证据。 + +## UI 和高风险任务 + +- P0 UI 首次实现前应有 `docs/design/` 原型并对齐 US/IX。 +- 拼多多真实自动化任务必须在受控测试账号和设备进行。 +- 验证码、风控、支付或未知页面只验证“能够识别并停止”,不验证绕过。 +- 任何扩大候选数量、提交订单或支付的任务,必须先更新需求并完成单独评审。 + +## 共享文档 + +- 单任务执行记录只改自己的任务文件。 +- 启动命令、目录或 blocker 变化时可以同步 `current-state.md`。 +- 需求、架构或 API 事实变化时,任务 `write_paths` 必须提前列出对应文档。 +- `progress.md` 只记录项目级大事记。 diff --git a/docs/tasks/T-001.md b/docs/tasks/T-001.md new file mode 100644 index 0000000..3ab6f32 --- /dev/null +++ b/docs/tasks/T-001.md @@ -0,0 +1,105 @@ +--- +id: T-001 +title: 初始化 Git 并接入 Roubao Android 基线 +phase: 0 +deps: [] +status: DOING +created: 2026-07-25 +context_ref: null +work_branch: main +write_paths: + - docs/tasks/T-001.md + - android-buyer/** + - .gitignore + - README.md + - init.ps1 + - init.sh + - docs/00-ai-start-here.md + - docs/03-tech-stack.md + - docs/04-architecture.md + - docs/05-coding-rules.md + - docs/current-state.md +--- + +## 问题 / 背景 + +当前仓库只有 Harness 文档,不是 Git 仓库,也没有 Roubao 源码、Gradle Wrapper 或 +可验证的 Android 命令。所有自动化、VLM 和后台任务都依赖一个可复现的 Android +基线;在基线完成前不能开始拼多多业务修改。 + +预期上游已经从真实仓库完成远端核实: + +- 仓库:`https://github.com/Turbo1123/roubao` +- 许可证:MIT +- 默认分支:`main` +- 核实时 `main` commit:`c8a6d7f03422eb01744b01f3ee77bf7757741f7e` +- 独立无障碍开发分支:`roubao2.0+AccessibilityService`,核实时 commit + `5b114c0a9476c359b27cfe994743fc7beb0a3554` +- 构建基线:Android Studio Hedgehog+、JDK 17、SDK 34、Gradle 8.2、AGP 8.2.0、 + Kotlin 1.9.20 + +这些是接入前核实结果,源码仍未导入、本机仍未构建。上游 `main` 使用 Shizuku, +AccessibilityService 位于独立开发分支;接入前要先比较分支,不能只按分支名称选型。 + +## 关联需求与交互 + +- 功能:为 F-003 至 F-007 提供实现基线,本任务不实现业务功能。 +- 用户故事:不适用。 +- 交互:不适用。 +- 架构:`04-architecture.md` 的 Android 模块。 + +## 方案 + +1. 确认当前目录应作为新仓库后初始化 Git;远端地址未知时不擅自创建远端。 +2. 重新读取远端分支头,比较 `main` 与无障碍开发分支;确定以哪个 commit 为导入 + 基线,并记录采用或移植无障碍实现的理由。 +3. 将需要二次开发的 Android 源码接入 `android-buyer/`,保留许可证和上游来源说明。 +4. 不做拼多多 Skill、VLM 业务和采购 UI 修改,只处理可构建所需的最小兼容问题。 +5. 运行 Gradle Wrapper 的真实构建和已有测试;有测试设备时安装并启动原始 App。 +6. 把真实目录、最终依赖版本、构建命令、上游 commit 和 blocker 同步到允许修改的 + 文档;若接入后的配置与已核实远端版本不同,要记录差异原因。 +7. 用真实安装、验证和启动命令替换 `init.ps1`/`init.sh` 占位;如果无法提供设备 + 启动命令,保留主动失败并把原因记录为 blocker,不能伪造命令。 + +## 验收要点 + +- [x] 当前目录已成为可正常查看状态和提交的 Git 仓库。 +- [ ] `android-buyer/` 包含可追溯到明确 URL 和 commit 的 Roubao 源码。 +- [ ] 上游许可证文件已保留,并确认允许当前预期的二次开发方式。 +- [ ] Windows 上使用仓库内 Gradle Wrapper 成功构建 Debug APK。 +- [ ] 上游已有 Android 单元测试已执行;没有测试时明确记录。 +- [ ] 有测试设备时完成安装和启动 smoke,并记录设备/Android 版本;无设备时任务 + 不能把设备 smoke 写成已通过。 +- [ ] 未加入真实 API key、签名密码、设备 token 或本地 SDK 绝对路径。 +- [ ] 已处理缺失的 `google-services.json`:提供本地忽略配置,或明确移除不需要的 + Firebase 插件和依赖。 +- [ ] `03-tech-stack.md` 和 `current-state.md` 不再把已核实信息标为待定。 +- [ ] `init.ps1`/`init.sh` 与文档中的当前命令一致,或因明确 blocker 保持主动失败。 + +建议验证命令形状,最终以接入工程为准: + +```powershell +git status --short +Set-Location android-buyer +.\gradlew.bat tasks +.\gradlew.bat test +.\gradlew.bat assembleDebug +``` + +## 边界 + +- 不实现拼多多搜索、点击、候选比较或订单流程。 +- 不接入 VLM、后台 API、任务领取和管理页面。 +- 不升级与构建无关的依赖,不重构上游项目。 +- 不配置生产签名,不提交本机 `local.properties` 或密钥。 + +## 执行记录 + +### 2026-07-25:Git 和文档基线 + +- 当前目录已初始化为 Git 仓库,工作分支为 `main`,远端名为 `origin`。 +- 新增根目录 `.gitignore`,忽略本地 SDK 配置、Firebase 配置、密钥、构建产物、 + 运行数据和日志。 +- 已核实 Roubao 上游版本并更新技术栈、当前状态及本任务,但 Android 源码尚未导入。 +- 本次只建立文档与脚本提交;Gradle 构建、测试、APK 安装和设备 smoke 均未运行。 +- T-001 保持 `DOING`,剩余 blocker 见 `docs/current-state.md`。 diff --git a/docs/tasks/_template.md b/docs/tasks/_template.md new file mode 100644 index 0000000..99bdc45 --- /dev/null +++ b/docs/tasks/_template.md @@ -0,0 +1,42 @@ +--- +id: T-XXX +title: 一句话任务名 +phase: 1 +deps: [] +status: TODO +created: YYYY-MM-DD +context_ref: null +work_branch: null +write_paths: + - docs/tasks/T-XXX.md + - path/to/allowed/module/** +--- + +## 问题 / 背景 + +说明当前事实、为什么要做,以及不做会阻塞什么。 + +## 关联需求与交互 + +- 功能:F-XXX +- 用户故事:US-XXX +- 交互:IX-XXX;无 UI 时写不适用 +- 架构/API:对应章节 + +## 方案 + +按文件和模块写清怎么实现、如何处理失败和安全边界。 + +## 验收要点 + +- 写明可观察结果。 +- 写明实际验证命令或设备 smoke 环境。 +- 高风险任务写明安全停止证据。 + +## 边界 + +明确不修改的模块和不实现的后续功能。 + +## 执行记录 + +开工后记录修改、命令、结果、环境、决策和 blocker。 diff --git a/init.ps1 b/init.ps1 new file mode 100644 index 0000000..8c43757 --- /dev/null +++ b/init.ps1 @@ -0,0 +1,33 @@ +#!/usr/bin/env pwsh + +$ErrorActionPreference = "Stop" +Set-Location -Path $PSScriptRoot + +# T-001 接入真实工程后替换。未配置时主动失败,防止把占位命令当成有效基线。 +$InstallCmd = "__REPLACE_AFTER_T001__" +$VerifyCmd = "__REPLACE_AFTER_T001__" +$StartCmd = "__REPLACE_AFTER_T001__" + +foreach ($entry in @{ + InstallCmd = $InstallCmd + VerifyCmd = $VerifyCmd + StartCmd = $StartCmd +}.GetEnumerator()) { + if ($entry.Value -like "__REPLACE_*") { + [Console]::Error.WriteLine( + "项目尚未完成 T-001;请配置 $($entry.Key),并同步 docs/03-tech-stack.md 和 docs/current-state.md。" + ) + exit 2 + } +} + +Write-Host "==> 当前目录: $($PWD.Path)" +Write-Host "==> 同步依赖" +Invoke-Expression $InstallCmd +Write-Host "==> 运行基础验证" +Invoke-Expression $VerifyCmd +Write-Host "==> 启动命令: $StartCmd" + +if ($env:RUN_START_COMMAND -eq "1") { + Invoke-Expression $StartCmd +} diff --git a/init.sh b/init.sh new file mode 100644 index 0000000..5ca019f --- /dev/null +++ b/init.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$ROOT_DIR" + +# T-001 接入真实工程后替换。 +INSTALL_CMD=(__REPLACE_AFTER_T001__) +VERIFY_CMD=(__REPLACE_AFTER_T001__) +START_CMD=(__REPLACE_AFTER_T001__) + +for value in "${INSTALL_CMD[0]}" "${VERIFY_CMD[0]}" "${START_CMD[0]}"; do + if [[ "$value" == __REPLACE_* ]]; then + echo "ERROR: 项目尚未完成 T-001,请配置 init.sh 并同步技术栈和当前状态文档。" + exit 2 + fi +done + +"${INSTALL_CMD[@]}" +"${VERIFY_CMD[@]}" +printf '启动命令:' +printf ' %q' "${START_CMD[@]}" +printf '\n' + +if [[ "${RUN_START_COMMAND:-0}" == "1" ]]; then + exec "${START_CMD[@]}" +fi diff --git a/progress.md b/progress.md new file mode 100644 index 0000000..09e753b --- /dev/null +++ b/progress.md @@ -0,0 +1,32 @@ +# 项目级大事记 + +> 本文件只记录阶段切换、重大决策和事故复盘。单任务执行记录写入 +> `docs/tasks/T-<编号>.md`。 + +## 2026-07-25 文档基线建立 + +- 类型:重大决策 +- 内容:确定统一后端、Web 管理端和 Android 采购端的目标架构。 +- 影响:首轮优先验证 Android 拼多多自动化,不先建设完整账号、推送和多设备调度。 + +## 2026-07-25 MVP 安全边界 + +- 类型:重大决策 +- 内容:MVP 由 App 手动领取任务,自动化停在候选确认或订单确认页。 +- 影响:MVP 禁止最终提交订单和自动支付;生产自动下单需单独评审和任务。 + +## 2026-07-25 后端切换为 Go-Gin + +- 类型:重大决策 +- 内容:后端调整为 Go 1.23.0 + Gin 1.11.0,使用 Go Blueprint v0.10.11 生成最小 + Gin + SQLite 骨架;生成器默认的 Go 1.25/Gin 1.12 版本必须降级。 +- 影响:骨架只作一次性输入;T-201 必须删除演示逻辑、修复危险默认并按 + domain/usecase/repository/transport 边界重组,且在 `GOTOOLCHAIN=local` 下验证。 + +## 2026-07-25 Roubao 与 Git 基线 + +- 类型:阶段切换 +- 内容:核实 Roubao 上游、MIT 许可证和 Android 构建版本;初始化 Git,并把 Harness + 文档和占位初始化脚本纳入基线提交。 +- 影响:T-001 进入 `DOING`;下一步比较 `main` 与无障碍开发分支、导入固定 commit, + 安装 Android SDK 34 后取得首个可复现 APK 构建证据。