refactor(arch): 信息架构升级 — 三层四角色控制面板 + 跨平台 task 交接协议

核心变化:
- dashboard.md 替代 DASHBOARD + ROADMAP,人类+Arch AI 唯一入口
- DECISIONS.md 人类决策入口,≤3 条待决策
- .ai/tasks/ 14 个独立 task 文件(Coder 8 + Tester 6),弱模型自包含可独立执行
- 旧 today/queue 归档,每个角色启动 ≤2 个文件
- ADR-012 跨平台「高模型指挥小模型」协作架构落地
- 知识库补全:L-002~005、P-004~005、ADR-011~012
- Arch AI 上下文资源管理硬约束写入 principles.md

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
tupingr
2026-05-26 15:17:06 +08:00
parent 5b428d0810
commit 6992f59cd2
38 changed files with 1630 additions and 105 deletions
+52
View File
@@ -0,0 +1,52 @@
# Task CROSS-001: 共享工具库日期格式 bug 修复
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P0 |
| 依赖 | 无 |
| 分配给 | Coder AI (Trae CN + GLM-4.6) |
## 输入
**要读的文件**:
- `shared/utils/date.ts` — 日期格式化工具函数
**参考的 ADR**:
-
**上游依赖产出**:
-
## 输出
**要生成/修改的文件**:
- `shared/utils/date.ts` — 修复日期格式输出
**问题描述**:
当前工具库日期格式化函数输出格式与预期不一致(具体格式差异需按实际 bug 修复)。
## 验收方法
```bash
# 运行日期格式化测试
node -e "const {formatDate} = require('./shared/utils/date'); console.log(formatDate(new Date('2026-01-15')));"
# 预期: "2026-01-15"
```
## 约束
- 不碰: `projects/app/` 目录
- 技术栈: Node.js 原生 Date API
- 遵循: ISO 8601 日期格式
## 完成报告
> Coder 完成后填写。Commit message 以 `[READY_FOR_TEST]` 结尾。
- [ ] 输出文件已生成
- [ ] 验收命令通过
- [ ] Commit: `{hash}`
- [ ] Commit message: `fix(CROSS-001): 共享工具库日期格式 bug 修复 [READY_FOR_TEST]`
+69
View File
@@ -0,0 +1,69 @@
# Task P01-001: 数据库 Schema 实现 + 迁移脚本
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P0 |
| 依赖 | 无 |
| 分配给 | Coder AI (Trae CN + GLM-4.6) |
## 输入
**要读的文件**:
- `docs/02_系统架构/数据模型.md` — 所有表定义、字段、索引、Drizzle Schema 示例
- `docs/02_系统架构/技术选型.md` — PostgreSQL + Drizzle ORM 版本
**参考的 ADR**:
- ADR-009: verification_status 状态机 + ai_confidence JSONB 字段
- ADR-010: questions 表 source + external_id 字段(题库适配器路由)
**上游依赖产出**:
- 无(这是所有模块的前置依赖)
## 输出
**要生成/修改的文件**:
- `projects/app/src/db/schema/*.ts` — 全部表定义(Drizzle ORM
- `projects/app/src/db/migrations/` — 迁移脚本
**涉及的表**:
users, user_relations, error_items, error_item_images, correction_logs, knowledge_points, question_knowledge_map, questions, print_tasks, recommendation_logs
**关键字段提醒**:
- users 表: `role VARCHAR` + `invitation_code VARCHAR`
- knowledge_points 表: `code VARCHAR`(业务编码如 G5-MATH-0201
- questions 表: `question_type VARCHAR`6 种题型), `difficulty SMALLINT`1-5, `cognitive_level SMALLINT`Bloom 1-6 预留), `source VARCHAR`self_built / zuoyebang, `external_id VARCHAR`(第三方 ID
- error_items 表: `verification_status VARCHAR`raw/reviewed/corrected/stale, `ai_confidence JSONB`, `subject VARCHAR`math/english
- correction_logs 表: `ai_value JSONB` + `user_value JSONB` + `ai_confidence NUMERIC`
- print_tasks 表: `status, file_url, expires_at, created_at`
- user_relations 表: `parent_user_id, child_user_id, level`(支持递归 CTE 邀请链查询)
## 验收方法
```bash
# 生成迁移脚本
npm run db:generate
# 执行迁移(本地 dev 数据库)
npm run db:migrate
# 验证所有表存在
psql $DATABASE_URL -c "\dt"
```
## 约束
- 不碰: `projects/app/src/modules/`(业务模块)、`projects/app/tests/`
- 技术栈: PostgreSQL + Drizzle ORM
- 遵循: 数据模型 v0.4.0 字段定义,不做自行裁剪
## 完成报告
> Coder 完成后填写。Commit message 以 `[READY_FOR_TEST]` 结尾。
- [ ] 输出文件已生成
- [ ] 验收命令通过
- [ ] Commit: `{hash}`
- [ ] Commit message: `feat(P01-001): 数据库 Schema 实现 + 迁移脚本 [READY_FOR_TEST]`
+64
View File
@@ -0,0 +1,64 @@
# Task P01-002: Auth 模块(微信登录 + JWT
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P0 |
| 依赖 | P01-001DB Schema |
| 分配给 | Coder AI (Trae CN + GLM-4.6) |
## 输入
**要读的文件**:
- `docs/02_系统架构/模块设计.md` — 3.1 Auth 模块 API 接口定义
- `docs/02_系统架构/数据模型.md` — users 表结构(role + invitation_code 字段)
- `projects/app/src/db/schema/*.ts` — P01-001 产出的 Drizzle Schema
**参考的 ADR**:
- ADR-009: 用户相关数据访问权限
**上游依赖产出**:
- P01-001: users 表 Drizzle Schemauser 类型定义)
## 输出
**要生成/修改的文件**:
- `projects/app/src/modules/auth/auth.module.ts`
- `projects/app/src/modules/auth/auth.controller.ts` — POST /auth/logincode2session + JWT 签发)
- `projects/app/src/modules/auth/auth.service.ts` — 微信 code2session → 查/建用户 → 签发 JWT
- `projects/app/src/modules/auth/auth.guard.ts` — AuthGuardJWT 验证中间件)
- `projects/app/src/modules/auth/dto/login.dto.ts`
**API**:
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /auth/login | code → JWT(新用户自动注册) |
| GET | /auth/me | 当前用户信息 |
## 验收方法
```bash
# 编译检查
npx tsc --noEmit
# 手动测试(需要微信小程序 code)
curl -X POST http://localhost:3000/auth/login -d '{"code":"test_code"}'
# 预期: 返回 { access_token, user }
```
## 约束
- 不碰: `projects/app/tests/`、其他 modules/ 目录
- 技术栈: NestJS + JWT + axios(调用微信接口)
- 遵循: `.ai/prompts/coding/code-style.md`
## 完成报告
> Coder 完成后填写。Commit message 以 `[READY_FOR_TEST]` 结尾。
- [ ] 输出文件已生成
- [ ] 验收命令通过
- [ ] Commit: `{hash}`
- [ ] Commit message: `feat(P01-002): Auth 模块(微信登录+JWT [READY_FOR_TEST]`
+69
View File
@@ -0,0 +1,69 @@
# Task P01-003: User 模块(个人资料 CRUD + 邀请链)
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P1 |
| 依赖 | P01-002Auth 模块,需要 JWT AuthGuard |
| 分配给 | Coder AI (Trae CN + GLM-4.6) |
## 输入
**要读的文件**:
- `docs/02_系统架构/模块设计.md` — 3.3 User 模块
- `docs/02_系统架构/数据模型.md` — users 表 + user_relations 表
- `projects/app/src/db/schema/*.ts` — P01-001 产出的 Drizzle Schema
- `projects/app/src/modules/auth/auth.guard.ts` — P01-002 产出的 AuthGuard
**参考的 ADR**:
- 无特殊 ADR
**上游依赖产出**:
- P01-002: AuthGuard(本模块所有接口需要 JWT 验证)
## 输出
**要生成/修改的文件**:
- `projects/app/src/modules/user/user.module.ts`
- `projects/app/src/modules/user/user.controller.ts`
- `projects/app/src/modules/user/user.service.ts`
**API**:
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /user/profile | 获取个人信息 |
| PATCH | /user/profile | 更新个人信息(昵称、头像、年级) |
| POST | /user/invite | 生成邀请码 |
| GET | /user/invite/tree | 查询邀请链(递归 CTE |
**关键逻辑**:
- 邀请码生成: 6 位字母数字随机码,唯一
- 邀请链查询: `WITH RECURSIVE` CTE 查 user_relations 表,返回被邀请人列表+层级
## 验收方法
```bash
# 编译检查
npx tsc --noEmit
# 测试邀请链查询
curl -H "Authorization: Bearer {token}" http://localhost:3000/user/invite/tree
# 预期: { tree: [{ userId, nickname, level, invitedAt }] }
```
## 约束
- 不碰: `projects/app/tests/`、其他 modules/ 目录
- 技术栈: NestJS + Drizzle ORM(嵌套查询)
- 遵循: `.ai/prompts/coding/code-style.md`
## 完成报告
> Coder 完成后填写。Commit message 以 `[READY_FOR_TEST]` 结尾。
- [ ] 输出文件已生成
- [ ] 验收命令通过
- [ ] Commit: `{hash}`
- [ ] Commit message: `feat(P01-003): User 模块(CRUD+邀请链) [READY_FOR_TEST]`
+68
View File
@@ -0,0 +1,68 @@
# Task P01-004: Upload 模块(图片上传 + S3
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P1 |
| 依赖 | P01-001DB Schema |
| 分配给 | Coder AI (Trae CN + GLM-4.6) |
## 输入
**要读的文件**:
- `docs/02_系统架构/模块设计.md` — 3.5 Upload 模块(或相关 API 定义)
- `docs/02_系统架构/数据模型.md` — error_item_images 表结构
- `docs/02_系统架构/技术选型.md` — S3 SDK + Sharp 版本
- `projects/app/src/db/schema/*.ts` — P01-001 产出的 Drizzle Schema
**参考的 ADR**:
- 无特殊 ADR
**上游依赖产出**:
- P01-001: error_item_images 表 Drizzle Schema
## 输出
**要生成/修改的文件**:
- `projects/app/src/modules/upload/upload.module.ts`
- `projects/app/src/modules/upload/upload.controller.ts` — POST /upload/image
- `projects/app/src/modules/upload/upload.service.ts` — 接收文件 → 上传 S3 → 生成缩略图 → 写 DB
**API**:
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /upload/image | multipart 上传图片 → S3 URL + 缩略图 URL |
**关键逻辑**:
- 原图上传 S3bucket: errlens-originals
- Sharp 生成缩略图(max 300x300)→ 上传 S3bucket: errlens-thumbnails
- 写入 error_item_images 表(关联 error_item_id 可选,拍照时先上传图片再创建错题记录)
## 验收方法
```bash
# 编译检查
npx tsc --noEmit
# 上传测试图片
curl -X POST http://localhost:3000/upload/image \
-F "image=@test.jpg"
# 预期: { id, originalUrl, thumbnailUrl, width, height }
```
## 约束
- 不碰: `projects/app/tests/`、Image 模块目录、Print 模块目录
- 技术栈: NestJS + Sharp + @aws-sdk/client-s3(或 Minio SDK
- 遵循: `.ai/prompts/coding/code-style.md`
## 完成报告
> Coder 完成后填写。Commit message 以 `[READY_FOR_TEST]` 结尾。
- [ ] 输出文件已生成
- [ ] 验收命令通过
- [ ] Commit: `{hash}`
- [ ] Commit message: `feat(P01-004): Upload 模块(图片上传+S3+缩略图) [READY_FOR_TEST]`
+64
View File
@@ -0,0 +1,64 @@
# Task P01-005: Image 模块(图像预处理管线)
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P0 |
| 依赖 | P01-004Upload 模块,需要图片 URL 做输入) |
| 分配给 | Coder AI (Trae CN + GLM-4.6) |
## 输入
**要读的文件**:
- `docs/02_系统架构/模块设计.md` — 3.6 Image 模块(图像预处理),含 CLAHE 参数和降级策略
- `docs/02_系统架构/总体架构.md` — 3.1 数据流中的图像预处理位置(OCR 之前)
- `projects/app/src/modules/upload/` — P01-004 产出的 Upload 模块(获取图片 URL
**参考的 ADR**:
- 无特殊 ADR(图像预处理管线来自旧架构已验证方案)
**上游依赖产出**:
- P01-004: Upload 模块(图片 URL 来源)
## 输出
**要生成/修改的文件**:
- `projects/app/src/modules/image/image.module.ts`
- `projects/app/src/modules/image/image.service.ts` — 图像预处理管线
**处理管线(按顺序)**:
1. 透视校正(检测文档边缘 → 透视变换拉正)
2. CLAHE 增强(对比度受限的自适应直方图均衡化)
3. 笔迹去除(红色笔迹 HSV 自动去除,蓝色同,黑色手动标记)
**关键参数**:
- CLAHE: clipLimit=2.0, tileGridSize=(8,8)
- 输出格式: PNG(保留质量)
- 降级策略: 任一步骤失败 → 跳过该步骤 → 用原图继续。不阻塞整体流程
## 验收方法
```bash
# 编译检查
npx tsc --noEmit
# 功能测试(用一张含红笔批改的错题照片)
# 预期: 输出图中红色笔迹明显减弱,对比度提升
```
## 约束
- 不碰: `projects/app/tests/`、OCR 相关模块(不属于当前 scope)
- 技术栈: NestJS + Sharp
- 遵循: 降级策略——不因预处理失败而阻塞
## 完成报告
> Coder 完成后填写。Commit message 以 `[READY_FOR_TEST]` 结尾。
- [ ] 输出文件已生成
- [ ] 验收命令通过
- [ ] Commit: `{hash}`
- [ ] Commit message: `feat(P01-005): Image 模块(图像预处理管线) [READY_FOR_TEST]`
+78
View File
@@ -0,0 +1,78 @@
# Task P01-006: Print 模块(PDF 生成 + S3 + 过期清理)
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P0 |
| 依赖 | P01-001DB Schema,需要 print_tasks 表) |
| 分配给 | Coder AI (Trae CN + GLM-4.6) |
## 输入
**要读的文件**:
- `docs/02_系统架构/模块设计.md` — 3.7 Print 模块(PDF 输出)
- `docs/02_系统架构/数据模型.md` — 2.11 print_tasks 表
- `docs/02_系统架构/总体架构.md` — 3.3 打印/PDF 输出数据流
- `projects/app/src/db/schema/*.ts` — P01-001 产出的 Drizzle Schema
**参考的 ADR**:
- 无特殊 ADR
**上游依赖产出**:
- P01-001: print_tasks 表 Drizzle Schema
## 输出
**要生成/修改的文件**:
- `projects/app/src/modules/print/print.module.ts`
- `projects/app/src/modules/print/print.controller.ts`
- `projects/app/src/modules/print/print.service.ts`
**API**:
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /print/generate | 提交错题 ID 列表 → 生成 PDF → 上传 S3 |
| GET | /print/task/:id | 查询生成进度 |
| GET | /print/download/:id | 获取下载链接(24h 有效) |
**关键逻辑**:
- PDF 生成: PDFKit, A4 纸张, 300 DPI
- 错题图片嵌入 PDF,每页一道题
- 上传 S3bucket: errlens-prints
- 24 小时过期: 数据库 expires_at 字段 + 定时任务清理(node-cron
- 下载链接一次性签名 URL
## 验收方法
```bash
# 编译检查
npx tsc --noEmit
# 提交生成任务
curl -X POST http://localhost:3000/print/generate \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"errorItemIds": ["uuid-1", "uuid-2"]}'
# 预期: { taskId, status: "processing" }
# 查询进度
curl http://localhost:3000/print/task/{taskId}
# 预期: { status: "completed", downloadUrl: "..." }
```
## 约束
- 不碰: `projects/app/tests/`、其他 modules/ 目录
- 技术栈: NestJS + PDFKit + @aws-sdk/client-s3 + node-cron
- 遵循: 下载链接 24h 过期,S3 文件同步过期清理
## 完成报告
> Coder 完成后填写。Commit message 以 `[READY_FOR_TEST]` 结尾。
- [ ] 输出文件已生成
- [ ] 验收命令通过
- [ ] Commit: `{hash}`
- [ ] Commit message: `feat(P01-006): Print 模块(PDF+S3+24h过期清理) [READY_FOR_TEST]`
+67
View File
@@ -0,0 +1,67 @@
# Task P01-007: 页面路由 + 基础页面骨架
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P1 |
| 依赖 | P01-003User 模块 API 稳定后) |
| 分配给 | Coder AI (Trae CN + GLM-4.6) |
## 输入
**要读的文件**:
- `docs/02_系统架构/模块设计.md` — 3.8 Pages 路由(各页面模块)
- `docs/02_系统架构/总体架构.md` — 前端技术栈 Taro 4 + React 18
- `docs/01_产品需求/PRD.md` — 页面功能需求
**参考的 ADR**:
- 无特殊 ADR
**上游依赖产出**:
- P01-003: User 模块 API(各页面需要用户数据)
## 输出
**要生成/修改的文件**:
- `projects/app/src/app.config.ts` — Taro 页面路由配置(9 个页面)
- `projects/app/src/pages/index/index.tsx` — 首页(错题列表)
- `projects/app/src/pages/capture/index.tsx` — 拍照录入页
- `projects/app/src/pages/detail/index.tsx` — 错题详情页
- `projects/app/src/pages/analysis/index.tsx` — AI 分析结果页
- `projects/app/src/pages/recommend/index.tsx` — 推荐练习页(暂为占位)
- `projects/app/src/pages/print/index.tsx` — 打印选择页
- `projects/app/src/pages/print/preview.tsx` — 打印预览页
- `projects/app/src/pages/profile/index.tsx` — 个人中心页
- `projects/app/src/pages/invite/index.tsx` — 邀请页
**页面要求**:
- 每个页面有基础布局(标题栏 + 内容区)
- 打印预览页显示错题列表 + 生成 PDF 按钮
- 其他页面可为功能占位(显示「开发中」即可),不需要完整交互
## 验收方法
```bash
# 编译检查
npx tsc --noEmit
# 小程序开发工具预览
# 预期: 9 个页面可导航,无白屏/报错
```
## 约束
- 不碰: `projects/app/tests/`、后端 modules/ 目录
- 技术栈: Taro 4 + React 18
- 遵循: 页面基础布局即可,不需要完整交互逻辑
## 完成报告
> Coder 完成后填写。Commit message 以 `[READY_FOR_TEST]` 结尾。
- [ ] 输出文件已生成
- [ ] 验收命令通过
- [ ] Commit: `{hash}`
- [ ] Commit message: `feat(P01-007): 页面路由+9个基础页面骨架 [READY_FOR_TEST]`
+63
View File
@@ -0,0 +1,63 @@
# Task T01-001: 数据库 Schema 验证
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P0 |
| 对应 Coder task | P01-001 |
| 分配给 | Tester AI (Coze CN) |
## 测试目标
验证 Drizzle 迁移脚本是否正确创建了所有表、字段类型、索引、外键。
## 被测对象
**Coder 产出的 commit**:
- 从 git log 查找 commit message 包含 `[READY_FOR_TEST]` 且 task 编号为 `P01-001` 的最新 commit
**Coder task 文件**:
- [P01-001](P01-001.md) — 理解该 task 的输出和约束
## 测试内容
**关键路径**:
- [ ] 所有 10 张表已创建(users, user_relations, error_items, error_item_images, correction_logs, knowledge_points, question_knowledge_map, questions, print_tasks, recommendation_logs
- [ ] users 表 role 字段为 VARCHARinvitation_code 字段存在
- [ ] knowledge_points 表 code 字段存在(VARCHAR
- [ ] questions 表 question_type6 种)、difficultySMALLINT 1-5)、source 字段存在
- [ ] error_items 表 verification_status 字段 + ai_confidence JSONB 字段存在
- [ ] correction_logs 表 ai_value + user_value JSONB 字段存在
- [ ] print_tasks 表 status + file_url + expires_at 字段存在
- [ ] user_relations 表支持递归 CTEparent_user_id + child_user_id + level
- [ ] 所有索引已创建(按数据模型文档核对)
**不应发生的**:
- [ ] 无 missing table
- [ ] 无字段类型错误(如 JSONB 写成 TEXT
- [ ] 无 missing index
## 执行方式
```
1. git pull → 拉取最新代码
2. 在 Coze 沙盒中执行迁移
3. 查询 information_schema 对比数据模型文档
4. 生成测试报告
```
## 报告格式
输出 `reports/T01-001-{日期}.json`
## 完成报告
> Tester 完成后填写。
- [ ] 测试已执行
- [ ] 报告已生成 → `reports/T01-001-{日期}.json`
- [ ] Commit: `{hash}`
- [ ] Commit message: `test(T01-001): {结论}`
- [ ] 结论: PASS / FAIL / RETRY
+61
View File
@@ -0,0 +1,61 @@
# Task T01-002: Auth 模块测试
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P0 |
| 对应 Coder task | P01-002 |
| 分配给 | Tester AI (Coze CN) |
## 测试目标
验证微信登录 code2session → JWT 签发 → AuthGuard 保护链路完整可用。
## 被测对象
**Coder 产出的 commit**:
- 从 git log 查找 commit message 包含 `[READY_FOR_TEST]` 且 task 编号为 `P01-002` 的最新 commit
**Coder task 文件**:
- [P01-002](P01-002.md) — 理解该 task 的 API 定义
## 测试内容
**关键路径**:
- [ ] POST /auth/login 使用有效 code → 返回 access_token + user
- [ ] POST /auth/login 使用无效 code → 返回 401
- [ ] POST /auth/login 新用户首次登录 → 自动注册成功(users 表有记录)
- [ ] POST /auth/login 已注册用户再次登录 → 返回已有用户信息(不重复创建)
- [ ] GET /auth/me 携带有效 token → 返回当前用户信息
- [ ] GET /auth/me 无 token → 返回 401
- [ ] GET /auth/me 携带过期 token → 返回 401
**不应发生的**:
- [ ] 无效 code 不返回 500(应优雅处理)
- [ ] JWT payload 不泄露敏感信息(不应有手机号、密码等)
## 执行方式
```
1. git pull → 拉取最新代码
2. 在 Coze 沙盒中启动服务
3. 用测试 code 调用 /auth/login
4. 用返回的 token 调用 /auth/me
5. 生成测试报告
```
## 报告格式
输出 `reports/T01-002-{日期}.json`
## 完成报告
> Tester 完成后填写。
- [ ] 测试已执行
- [ ] 报告已生成 → `reports/T01-002-{日期}.json`
- [ ] Commit: `{hash}`
- [ ] Commit message: `test(T01-002): {结论}`
- [ ] 结论: PASS / FAIL / RETRY
+64
View File
@@ -0,0 +1,64 @@
# Task T01-003: Image + Upload 模块联测
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P0 |
| 对应 Coder task | P01-005 (Image) + P01-004 (Upload) |
| 分配给 | Tester AI (Coze CN) |
## 测试目标
验证「图片上传 → 缩略图生成 → 图像预处理管线(透视校正+CLAHE+笔迹去除)」完整链路。
## 被测对象
**Coder 产出的 commit**:
- P01-004: commit message 包含 `[READY_FOR_TEST]` 且 task 编号为 `P01-004`
- P01-005: commit message 包含 `[READY_FOR_TEST]` 且 task 编号为 `P01-005`
**Coder task 文件**:
- [P01-004](P01-004.md) — Upload 模块 API
- [P01-005](P01-005.md) — Image 模块处理管线
## 测试内容
**关键路径**:
- [ ] POST /upload/image 上传 JPEG 图片 → 返回 originalUrl + thumbnailUrl
- [ ] 缩略图尺寸 ≤ 300x300
- [ ] 图像预处理:透视校正后图片无明显梯形畸变
- [ ] 图像预处理:CLAHE 增强后对比度有可观测提升
- [ ] 图像预处理:红色笔迹去除效果可观测(用含红笔批改的测试图)
- [ ] 图像预处理:蓝色笔迹去除效果可观测(用含蓝笔批改的测试图)
- [ ] 降级策略:任一步骤失败不阻塞整体(用损坏的图片测试)
- [ ] error_item_images 表记录正确写入
**不应发生的**:
- [ ] 预处理管线崩溃时不应返回 500(降级返回原始图片即可)
- [ ] 缩略图不应丢失宽高比
## 执行方式
```
1. git pull → 拉取最新代码
2. 在 Coze 沙盒中启动服务
3. 准备测试图片(含红/蓝笔批改的错题照片 + 一张损坏图)
4. 上传 → 检查 S3 → 检查预处理结果
5. 生成测试报告
```
## 报告格式
输出 `reports/T01-003-{日期}.json`
## 完成报告
> Tester 完成后填写。
- [ ] 测试已执行
- [ ] 报告已生成 → `reports/T01-003-{日期}.json`
- [ ] Commit: `{hash}`
- [ ] Commit message: `test(T01-003): {结论}`
- [ ] 结论: PASS / FAIL / RETRY
+64
View File
@@ -0,0 +1,64 @@
# Task T01-004: Print 模块测试
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P0 |
| 对应 Coder task | P01-006 |
| 分配给 | Tester AI (Coze CN) |
## 测试目标
验证 PDF 生成、S3 上传、24h 过期清理完整流程。
## 被测对象
**Coder 产出的 commit**:
- 从 git log 查找 commit message 包含 `[READY_FOR_TEST]` 且 task 编号为 `P01-006` 的最新 commit
**Coder task 文件**:
- [P01-006](P01-006.md) — Print 模块 API
## 测试内容
**关键路径**:
- [ ] POST /print/generate 提交错题 ID 列表 → 返回 taskId + status: "processing"
- [ ] GET /print/task/:id → 查询进度,最终返回 status: "completed" + downloadUrl
- [ ] GET /print/download/:id → 返回 PDF 文件下载
- [ ] PDF 文件可正常打开,内容为错题图片(每页一道题)
- [ ] PDF 为 A4 纸张规格
- [ ] downloadUrl 为 S3 签名 URL
- [ ] expires_at 字段设置为创建时间 + 24h
- [ ] 过期清理: 模拟 expires_at 已过 → 下载链接失效
**不应发生的**:
- [ ] 空错题列表不应崩溃(返回明确错误信息)
- [ ] 不存在的 task id 不应返回 500
- [ ] 已过期的下载链接不应仍可访问
## 执行方式
```
1. git pull → 拉取最新代码
2. 在 Coze 沙盒中启动服务
3. 提交打印任务 → 等待完成 → 下载 PDF
4. 验证 PDF 格式和内容
5. 模拟过期场景
6. 生成测试报告
```
## 报告格式
输出 `reports/T01-004-{日期}.json`
## 完成报告
> Tester 完成后填写。
- [ ] 测试已执行
- [ ] 报告已生成 → `reports/T01-004-{日期}.json`
- [ ] Commit: `{hash}`
- [ ] Commit message: `test(T01-004): {结论}`
- [ ] 结论: PASS / FAIL / RETRY
+68
View File
@@ -0,0 +1,68 @@
# Task T01-005: User 模块 + 日期修复验证
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P1 |
| 对应 Coder task | P01-003 (User) + CROSS-001 (日期修复) |
| 分配给 | Tester AI (Coze CN) |
## 测试目标
验证用户个人信息 CRUD、邀请码生成、邀请链递归 CTE 查询,以及日期格式 bug 修复。
## 被测对象
**Coder 产出的 commit**:
- P01-003: commit message 包含 `[READY_FOR_TEST]` 且 task 编号为 `P01-003`
- CROSS-001: commit message 包含 `[READY_FOR_TEST]` 且 task 编号为 `CROSS-001`
**Coder task 文件**:
- [P01-003](P01-003.md) — User 模块 API
- [CROSS-001](CROSS-001.md) — 日期格式修复
## 测试内容
**关键路径 (User 模块)**:
- [ ] GET /user/profile → 返回当前用户信息
- [ ] PATCH /user/profile → 更新昵称/头像/年级,返回更新后信息
- [ ] POST /user/invite → 生成 6 位唯一邀请码
- [ ] POST /user/invite → 同一用户重复调用不重复生成(已有时返回已有码)
- [ ] GET /user/invite/tree → 返回邀请树(含被邀请人+层级)
- [ ] GET /user/invite/tree → 无邀请记录时返回空树
**关键路径 (日期修复)**:
- [ ] `shared/utils/date.ts` formatDate 输出为 ISO 8601 格式(YYYY-MM-DD
- [ ] 所有使用日期格式的接口返回正确格式
**不应发生的**:
- [ ] 邀请码不应重复(并发场景)
- [ ] 邀请链查询不应超时(数据量大时 CTE 性能)
## 执行方式
```
1. git pull → 拉取最新代码
2. 在 Coze 沙盒中启动服务
3. 注册/登录两个测试用户
4. 用户 A 生成邀请码 → 用户 B 用邀请码注册
5. 验证邀请链查询结果
6. 验证日期格式
7. 生成测试报告
```
## 报告格式
输出 `reports/T01-005-{日期}.json`
## 完成报告
> Tester 完成后填写。
- [ ] 测试已执行
- [ ] 报告已生成 → `reports/T01-005-{日期}.json`
- [ ] Commit: `{hash}`
- [ ] Commit message: `test(T01-005): {结论}`
- [ ] 结论: PASS / FAIL / RETRY
+66
View File
@@ -0,0 +1,66 @@
# Task T01-006: 页面骨架 + API 集成测试
## 元信息
| 字段 | 值 |
|------|-----|
| 状态 | `todo` |
| 优先级 | P1 |
| 对应 Coder task | P01-007 |
| 分配给 | Tester AI (Coze CN) |
## 测试目标
验证 9 个页面路由可访问、页面骨架渲染正常、各页面 API 调用连通。
## 被测对象
**Coder 产出的 commit**:
- 从 git log 查找 commit message 包含 `[READY_FOR_TEST]` 且 task 编号为 `P01-007` 的最新 commit
**Coder task 文件**:
- [P01-007](P01-007.md) — 页面路由 + 骨架
## 测试内容
**关键路径**:
- [ ] 所有 9 个页面可正常导航(无白屏/报错)
- [ ] 首页(index)— 错题列表骨架渲染
- [ ] 拍照录入页(capture)— 调用相机/相册
- [ ] 错题详情页(detail)— 展示错题信息
- [ ] AI 分析结果页(analysis)— 展示分析数据
- [ ] 推荐练习页(recommend)— 占位内容正常
- [ ] 打印选择页(print/index)— 错题列表可勾选
- [ ] 打印预览页(print/preview)— 显示已选错题 + PDF 生成按钮
- [ ] 个人中心页(profile)— 调用 /user/profile API
- [ ] 邀请页(invite)— 调用 /user/invite API
- [ ] Taro 路由配置正确(app.config.ts 包含所有页面路径)
**不应发生的**:
- [ ] 页面切换不白屏
- [ ] 无 JS 报错(console 无红色)
- [ ] 无 API 调用 404
## 执行方式
```
1. git pull → 拉取最新代码
2. 在 Coze 沙盒或微信开发者工具中编译运行
3. 遍历所有页面 → 检查渲染 + console
4. 验证各页面 API 调用连通性
5. 生成测试报告
```
## 报告格式
输出 `reports/T01-006-{日期}.json`
## 完成报告
> Tester 完成后填写。
- [ ] 测试已执行
- [ ] 报告已生成 → `reports/T01-006-{日期}.json`
- [ ] Commit: `{hash}`
- [ ] Commit message: `test(T01-006): {结论}`
- [ ] 结论: PASS / FAIL / RETRY