Files
cmroubao/docs/05-coding-rules.md
T

170 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 编码规则
> 每次写代码前完整读取。需求决定“该不该做”,架构和 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 个候选;扩大范围必须先改需求。
- 候选卡必须满足视口可见比例、单列尺寸、图片、价格和语义文本约束;根不可点击时
只允许唯一的大面积覆盖点击目标,禁止点击卡内小按钮。
- 候选和滚动预算在发出动作前消耗,并跨 workflow retry 保持;返回 `false` 或取消
也不能恢复预算。
- 详情截图只保存在 App 内部目录,文件名匿名;manifest 不保存标题/页面原文,并
校验文件 SHA-256、尺寸和字节数。
- 前台服务通知要展示任务编号和当前步骤,并提供安全停止入口。
- 验证码、风控、登录、支付、未知页面统一进入安全失败。
- MVP 不得实现最终提交订单或支付动作,包括“先写好但不调用”的隐藏代码。
## 5. AI 规则
- 输入明确区分原始事实、用户硬约束、页面观察和待推断字段。
- 输出只接受结构化 schema;解析失败不能回退到自由文本猜测。
- SKU、数量、预算、允许平台和停止边界由确定性代码覆盖模型输出;数量和预算不进入
需求提取 prompt。
- 提示词、schema、模型名和阈值版本化并记录到 execution。
- 不向模型发送密码、token、支付信息或与候选判断无关的个人信息。
- 模型低置信度或前后结果冲突时转人工,不自动增加动作权限。
- 需求提取一次用户操作最多发出一次付费调用;重试必须由上层人员显式触发并另计预算。
- GUI-Owl、MAI-UI 等动作模型不能复用为需求提取 provider。
- 需求提取 provider 的远程端点必须使用 HTTPS;HTTP 只允许不携带 API Key 的本机
回环地址,且禁止 userinfo、query、fragment 和重定向。
- 结构化 VLM 调用必须禁用底层自动重试,协程取消必须取消 HTTP call;非成功响应
不读取正文,成功响应最多读取 64 KiB。
- 需求提取标题和 SKU 分别限制为 2048、512 个 UTF-8 字节,超过上限不得截断后发送。
- 图片进入 VLM 前必须校验媒体类型、字节上限、JPEG 魔数、SHA-256 和可解码尺寸,并
按声明长度一次分配精确读取、有界缩放;prompt、Base64 和原始响应不得写普通日志。
- 候选评估按 ordinal 串行执行,每个候选最多调用一次、整批最多 5 次;失败、取消或
无效输出立即停止后续调用,不保留部分结果作为自动建议。
- 候选证据只能通过当前 session 的 metadata allowlist 读取;复核固定文件名、规范
路径、PNG/IHDR、字节数、尺寸和 SHA-256,VLM adapter 不得遍历 cache。
- 候选 session 必须绑定完整需求快照和精确搜索词;旧需求、其他关键词或失败
workflow 的截图不得进入评估。
- 模型不能设置建议 ordinal、人工确认状态或 `order_submitted`;预算缺失时价格或
预算匹配声明无效。
## 6. 后端与 API 规则
- 请求在边界完成类型、大小、媒体类型和业务规则校验。
- 领取任务必须使用事务;不得先 GET 再由客户端自行标记占用。
- 状态变化校验当前状态、设备归属、claim token、版本和租约。
- App 必须在 claim 请求前生成并安全保存独立的 256 bit claim token 与幂等 key;
后端只存 token SHA-256,响应、事件和日志不得返回原值或 hash。
- claim/start/release/cancel-ack 和后续完成/证据上传的重试路径必须幂等;`NO_TASK`
也必须是稳定幂等结果。
- 设备/任务 heartbeat 使用服务端时钟且不写高频事件;过期 RUNNING 不得自动回到
队列。管理取消执行中任务必须等 App 安全确认,不能提前伪装为终态。
- 不向客户端返回 `password_hash`、`token_hash`、存储绝对路径或供应商密钥。
- 管理 Cookie 与 BUYER 设备 Bearer token 使用独立 middleware,不得互相替代;
每次鉴权都重新检查用户/设备启用、绑定、撤销和过期状态。
- 密码使用 bcrypt;session、设备 secret 和 access token 使用至少 256 bit 随机值,
持久化层只保存 SHA-256。账号和设备只由 `authctl` 显式预置。
- 管理 Web POST 校验双提交 CSRF;Cookie 管理 API 的非安全方法额外校验
`X-CSRF-Token`。登录成功同时轮换 session 和 CSRF。
- 管理/App 登录必须在 bcrypt 前按服务端 `RemoteAddr` 独立限流;不得信任未配置的
转发头。限流器必须并发安全、内存有界,超限返回通用 `429` 和 `Retry-After`。
- 创建和取消任务必须从认证上下文传入真实 ADMIN actor 并写入只追加事件;共享
`local-admin` 只用于 MVP 资源可见范围,不能冒充操作者。
- 通用错误使用稳定 code 和可读 message;内部堆栈只进受控日志。
- 文件访问通过鉴权接口,防止路径遍历和猜测 URL;App 参考图读取必须重新校验当前
task/user/device/generation/token/租约,不能只凭 asset UUID 授权。
- T-208 候选数据必须分离 observation、model prediction、deterministic
recommendation 和 human label;模型理由不得预填或复制为人工标签。
- 人工结论使用版本化结构化 reason code;接受/拒绝至少一个理由,`OTHER` 才要求
受限备注。人工修正只追加并引用被替代版本,不能覆盖历史。
- 第三方商品/图片 URL 只作为长度受限的不可执行观测字段;后端不得根据客户端 URL
发起任意网络请求。候选图片使用鉴权、解码、大小/像素/哈希和脱敏受控上传。
- Go 命令固定 `GOTOOLCHAIN=local`;`go.mod` 不得出现更高 Go 版本或未固定的
`@latest` 依赖。
- 后端不得自动加载 `.env`、默认开启 CORS、使用包级数据库单例,或在库、handler、
健康检查中调用 `log.Fatal`/`os.Exit`。
- `http.Server` 必须配置 read-header/read/write/idle/header 上限和有界关闭;
recovery 不得把 Authorization、Cookie、panic 或请求正文写普通日志。
- SQLite 数据文件必须位于被忽略目录,启用 foreign keys、有限 busy timeout 和
WAL;连接由进程入口显式关闭,migration 使用固定版本和受控 SQL 文件。
## 7. 安全与隐私
- 后端密钥只来自环境变量或被忽略的本地配置;管理后端不保存、下发或代理 VLM
provider Key。
- App provider Key 使用 Android Keystore 包装的加密存储;每台采购设备使用独立、
可撤销、有限额度的 Key。Key、Authorization 和完整敏感 endpoint 不得进入任务、
结果、日志、崩溃报告或普通 SharedPreferences。
- App provider HTTP client 必须禁用自动重试和重定向;Release 远程目标只允许
HTTPS,HTTP 仅允许 Debug 下无 Key 的 loopback mock。后台任务不能覆盖端点。
- 管理后端不得根据 App 提交的 provider 或商品 URL 发起第三方网络请求。
- 真实蝦皮订单文本、参考图及其规范化生成物只能位于仓库外或 `.local/`、
`private-fixtures/` 等被忽略目录;测试使用脱敏 fixture。
- 普通日志不得输出完整蝦皮订单号、店铺名或本机原图绝对路径。
- 日志默认脱敏,不记录 Authorization、Cookie、密码、设备令牌或完整地址。
- 上传文件限制媒体类型、大小和解码结果,随机化服务端文件名。
- 不绕过第三方平台限制、验证码、风控或系统权限。
- 不可逆动作必须由明确需求、服务端授权、App 确认和幂等保护共同允许。
- 发现需求与平台条款冲突时停止实现并记录 blocker。
## 8. 测试
每个任务按风险选择测试:
- 领域状态机、硬约束、错误码:单元测试。
- API 权限、事务、幂等、文件校验:集成测试。
- VLM adapter:固定 fixture/契约测试,不让普通测试依赖真实付费 API。
- VLM 隐私测试必须用 sentinel 断言订单号、店铺名、路径和数量不进入 provider
prompt,并断言一次 extractor 调用只调用 gateway 一次。
- 蝦皮文件导入:覆盖同名配对、缺图、重复图片、未知格式、非法数量和敏感日志检查。
- 私有 ProbeTask 只允许通过 `-PprobeFixturesDir` 注入 Debug APK;验证后必须再做
一次不带属性的普通构建,并确认 APK 不含 `assets/probe-fixtures/`。
- Android workflow:用 fake automation/AI client 测状态和安全停止。
- 拼多多真实流程:指定版本测试机手工 smoke,保存脱敏截图和步骤证据。
- UI:覆盖默认、加载、空、错误、权限和中断状态。
不得用删除断言、放宽预算、安全停止或候选上限来让测试通过。
## 9. 完成定义
- [ ] 修改在任务 `write_paths` 内。
- [ ] 构建、相关测试和格式检查通过。
- [ ] 关联需求、US 和 IX 的验收通过。
- [ ] 安全停止路径至少验证一次。
- [ ] 没有真实密钥或敏感证据进入仓库。
- [ ] 接口、数据模型或命令变化已同步文档。
- [ ] 当前任务文件记录命令、结果、环境和未验证项。
- [ ] `current-state.md` 与真实目录、命令和 blocker 一致。
项目标准验证命令是根目录 `.\init.ps1`;它执行 Android Gradle `test` 和
`assembleDebug`,再以 `GOTOOLCHAIN=local` 执行后端 `go test ./...`、
`go vet ./...`、`gofmt` 检查和 API/migration/authctl 三个入口构建。设置
`RUN_START_COMMAND=1` 时使用
SDK 内新版 ADB 安装并启动 Android App。