docs: 更新协议文档,删除废弃计划文档
- 更新 http-error-codes, user-points-chat-data-protocol - 更新 divination-run-protocol, profile-protocol - 删除废弃的后端和前端设计计划文档
This commit is contained in:
@@ -1,241 +0,0 @@
|
||||
# Eryao 解卦历史与个人档案后端单一数据源改造计划
|
||||
|
||||
日期:2026-04-05
|
||||
状态:评审中(未开始编码)
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
当前移动端存在两类不符合目标架构的问题:
|
||||
|
||||
1. 个人档案(昵称、简介、头像)仍有前端本地状态路径,非后端权威数据源。
|
||||
2. 首页历史解卦无法稳定由后端快照直接重建结果页,前端被迫做本地兜底。
|
||||
|
||||
本计划目标:
|
||||
|
||||
- 实现“后端为唯一数据源,前端仅缓存”。
|
||||
- 将 `DIVINATION_DERIVED` 的完整结构进入消息 `metadata.agent_output` 并持久化。
|
||||
- 历史接口返回可被前端直接解析的结构化 assistant 输出(不再依赖 `ui_schema`)。
|
||||
- 个人档案全链路后端化,头像使用 `avatars` bucket。
|
||||
|
||||
非目标:
|
||||
|
||||
- 本计划不直接提交代码实现。
|
||||
- 本计划不包含 UI 视觉细节改稿。
|
||||
|
||||
## 2. 现状核对(基于仓库代码)
|
||||
|
||||
### 2.1 历史接口与消息转换
|
||||
|
||||
- 历史接口:`GET /api/v1/agent/history`,定义于 `backend/src/v1/agent/router.py`。
|
||||
- 当前转换逻辑在 `backend/src/v1/agent/utils.py`:
|
||||
- `user` 消息主要输出 `content` 与 `attachments`。
|
||||
- `assistant` 消息默认走 `ui_hints -> ui_schema` 编译路径。
|
||||
- 历史响应结构 `HistoryMessage` 当前包含 `ui_schema`,不直接暴露结构化 `agent_output`。
|
||||
|
||||
### 2.2 DIVINATION_DERIVED 与落库断点
|
||||
|
||||
- 运行时会发出 `DIVINATION_DERIVED`(见 `backend/src/core/agentscope/runtime/runner.py`)。
|
||||
- 消息落库由 `backend/src/core/agentscope/events/store.py` 负责。
|
||||
- 当前 `TEXT_MESSAGE_END` 持久化字段包含 `sign_level/summary/.../ui_hints`,未包含 `divination` 结构。
|
||||
- 结果:历史快照难以完整重建结果页结构。
|
||||
|
||||
### 2.3 Profile 与头像
|
||||
|
||||
- 后端配置已有 `storage.avatar.bucket`,默认 `avatars`(`backend/src/core/config/settings.py`)。
|
||||
- 当前 `v1` 仅挂载 `auth/agent/points` 路由(`backend/src/v1/router.py`),尚无 profile 专用路由。
|
||||
|
||||
## 3. 核心设计决策
|
||||
|
||||
### 决策 A:把 `divination_derived` 放入 `metadata.agent_output`
|
||||
|
||||
- 在 `AgentOutput` 增加字段 `divination_derived`(强类型,禁止裸 `dict`)。
|
||||
- 事件落库时把 `DIVINATION_DERIVED` 内容并入 assistant 的 `metadata.agent_output.divination_derived`。
|
||||
- 与 `sign_level/summary/advice/...` 同时持久化,形成一条可回放的 assistant 结构化输出。
|
||||
|
||||
理由:
|
||||
|
||||
- 最小改动复用现有消息表,不新增历史结果表即可满足回放需求。
|
||||
- 前端可直接从历史响应解析结果页,避免本地拼装。
|
||||
|
||||
### 决策 B:历史接口返回 `assistant.agent_output`,移除 `ui_schema`
|
||||
|
||||
- `HistoryMessage` 改为:
|
||||
- `user`: `content + attachments`
|
||||
- `assistant`: `content + agent_output`
|
||||
- `ui_schema` 从接口协议中移除(迁移自通用模块的历史遗留,不在本项目范围)。
|
||||
|
||||
理由:
|
||||
|
||||
- 减少中间编译层,契约更稳定、语义更清晰。
|
||||
- 前端直接消费业务数据,不依赖通用 UI 编译器。
|
||||
|
||||
### 决策 C:Profile 全后端化 + 头像对象存储
|
||||
|
||||
- 新增 users/profile API,前端只保留缓存层。
|
||||
- 头像上传走预签名 URL,bucket 固定 `avatars`,路径按用户隔离。
|
||||
|
||||
## 4. 协议与接口计划(先文档,后实现)
|
||||
|
||||
## 4.1 新增/修改协议文档
|
||||
|
||||
按“协议先行”更新以下文档:
|
||||
|
||||
1. `docs/protocols/divination/divination-run-protocol.md`
|
||||
- 增补:历史回放时 assistant `agent_output.divination_derived` 的字段契约。
|
||||
- 标记:`ui_schema` 已废弃并移除。
|
||||
2. 新增:`docs/protocols/profile/profile-protocol.md`
|
||||
- 定义 profile 读写与头像上传签名协议。
|
||||
3. 如涉及错误码新增,更新:
|
||||
- `docs/protocols/common/http-error-codes.md`
|
||||
|
||||
### 4.2 后端 API 契约(目标)
|
||||
|
||||
#### A. 历史快照(改造)
|
||||
|
||||
- `GET /api/v1/agent/history`
|
||||
- 响应中 assistant 消息新增(或替换为)`agent_output`:
|
||||
- `sign_level`
|
||||
- `summary`
|
||||
- `conclusion`
|
||||
- `focus_points`
|
||||
- `advice`
|
||||
- `keywords`
|
||||
- `answer`
|
||||
- `divination_derived`(完整卦象结构)
|
||||
|
||||
#### B. Profile(新增)
|
||||
|
||||
- `GET /api/v1/users/me/profile`
|
||||
- `PATCH /api/v1/users/me/profile`
|
||||
- `POST /api/v1/users/me/avatar/upload-url`
|
||||
- (可选)`GET /api/v1/users/me/avatar/signed-url`
|
||||
|
||||
#### C. 头像上传约束
|
||||
|
||||
- bucket 固定:`config.storage.avatar.bucket`
|
||||
- 路径前缀建议:`avatars/{user_id}/...`
|
||||
- 文件类型:`image/png|image/jpeg|image/webp`
|
||||
- 体积上限:`config.storage.avatar.max_size_mb`
|
||||
|
||||
## 5. 数据模型改造计划
|
||||
|
||||
### 5.1 Runtime 模型
|
||||
|
||||
- 文件:`backend/src/schemas/agent/runtime_models.py`
|
||||
- 变更:`AgentOutput` 增加 `divination_derived` 字段(类型复用 `schemas/domain/divination.py`)。
|
||||
- 规则:保持 `extra="forbid"`,禁止无类型漂移。
|
||||
|
||||
### 5.2 事件到落库链路
|
||||
|
||||
- 文件:`backend/src/core/agentscope/runtime/stage_emitter.py`
|
||||
- `TEXT_MESSAGE_END` payload 带上 `divination_derived`。
|
||||
- 文件:`backend/src/core/agentscope/events/store.py`
|
||||
- `worker_output_fields` 纳入 `divination_derived` 并写入 `metadata.agent_output`。
|
||||
|
||||
### 5.3 历史响应转换
|
||||
|
||||
- 文件:`backend/src/v1/agent/utils.py`
|
||||
- 删除 `ui_hints -> ui_schema` 编译路径。
|
||||
- assistant 消息改为抽取并返回受控 `agent_output`。
|
||||
- 文件:`backend/src/v1/agent/schemas.py`
|
||||
- `HistoryMessage` 改字段定义(去 `ui_schema`,加 `agent_output`)。
|
||||
|
||||
## 6. 前端消费与缓存策略
|
||||
|
||||
### 6.1 历史与结果页
|
||||
|
||||
- 历史列表数据源改为后端 `agent/history`。
|
||||
- 点开历史项时:
|
||||
- 直接解析 `assistant.agent_output.divination_derived` + 解释文本字段。
|
||||
- 本地仅做缓存,不做真源 fallback。
|
||||
|
||||
### 6.2 Profile
|
||||
|
||||
- 设置页资料读取改为 `GET /users/me/profile`。
|
||||
- 编辑资料写入 `PATCH /users/me/profile`。
|
||||
- 头像更新走 upload-url + 上传 + profile 更新引用路径。
|
||||
|
||||
### 6.3 点数
|
||||
|
||||
- 保持后端余额接口作为权威数据源(现有已接)。
|
||||
- 前端只做短期缓存,解卦完成后强制 refresh。
|
||||
|
||||
## 7. 代码清理边界(你关心的“删除通用遗留”)
|
||||
|
||||
原则:先去引用,再删定义,最后删文件,避免误删。
|
||||
|
||||
分三步:
|
||||
|
||||
1. 第一阶段(本次改造内)
|
||||
- 删除 `agent/history` 对 `ui_schema` 的输出与依赖。
|
||||
- 删除前端对 `ui_schema` 的消费路径(若存在)。
|
||||
2. 第二阶段(安全清理)
|
||||
- 搜索 `schemas/domain` 与 `schemas/agent/ui_hints` 的实际引用。
|
||||
- 对“零引用 + 非协议字段”进行清理。
|
||||
3. 第三阶段(文档与测试补齐)
|
||||
- 更新协议文档、错误码、回归测试。
|
||||
|
||||
备注:
|
||||
|
||||
- 不建议在同一 PR 里“功能改造 + 大规模 schema 删除”,建议拆成两个 PR,降低回归风险。
|
||||
|
||||
## 8. 测试计划(必须项)
|
||||
|
||||
### 8.1 后端单元/集成
|
||||
|
||||
1. `TEXT_MESSAGE_END` 持久化:`metadata.agent_output.divination_derived` 落库断言。
|
||||
2. `GET /api/v1/agent/history`:assistant 返回 `agent_output`,且不再返回 `ui_schema`。
|
||||
3. 历史分页与 owner 校验不回退。
|
||||
4. profile API:读写、权限、字段约束、头像路径安全性。
|
||||
5. 头像签名 URL:bucket/path/mime/size 约束。
|
||||
|
||||
### 8.2 前端
|
||||
|
||||
1. 历史列表从后端数据渲染。
|
||||
2. 点击历史项成功进入结果页,字段一致性校验。
|
||||
3. profile 页面读写闭环(昵称/简介/头像)。
|
||||
4. 点数刷新与缓存失效策略验证。
|
||||
|
||||
## 9. 风险与回滚
|
||||
|
||||
主要风险:
|
||||
|
||||
- 历史消息中旧数据可能没有 `divination_derived`,前端需兼容空值。
|
||||
- `ui_schema` 下线后,若有隐藏调用方会断。
|
||||
|
||||
回滚策略:
|
||||
|
||||
- 协议层采用短期双读兼容窗口(仅过渡期):
|
||||
- 新字段优先;旧字段仅用于读,不再写。
|
||||
- 若线上异常,先回滚 history 响应变更,再保持落库新增字段不删。
|
||||
|
||||
## 10. 实施顺序(最小风险)
|
||||
|
||||
1. 协议文档更新并评审通过。
|
||||
2. 后端:`AgentOutput` + 事件落库 + history 响应新增 `agent_output`(先加后切)。
|
||||
3. 前端:改消费到 `agent_output`,移除本地真源。
|
||||
4. 后端:移除 `ui_schema` 输出。
|
||||
5. profile API + 前端接入头像上传。
|
||||
6. 清理无用 schema(独立 PR)。
|
||||
|
||||
## 11. 验收标准(DoD)
|
||||
|
||||
全部满足才算完成:
|
||||
|
||||
1. 解卦后写入的 assistant 消息在 DB 中可见 `metadata.agent_output.divination_derived`。
|
||||
2. 首页历史完全来自后端,清空本地缓存后仍可正确展示。
|
||||
3. 历史详情可完整还原结果页,不依赖 `ui_schema`。
|
||||
4. profile 读写走后端,头像实际落 `avatars` bucket。
|
||||
5. 前端不再把 profile/history 作为本地权威数据源。
|
||||
6. 协议文档与实现一致,相关测试通过。
|
||||
|
||||
## 12. GSTACK REVIEW REPORT
|
||||
|
||||
| Review | Trigger | Why | Runs | Status | Findings |
|
||||
|--------|---------|-----|------|--------|----------|
|
||||
| Eng Review | `/plan-eng-review` | 锁定架构、契约、测试闭环 | 1 | Done | 确认后端单一数据源方向;建议分阶段移除 `ui_schema` 并将 schema 清理拆分独立 PR |
|
||||
| CEO Review | `/plan-ceo-review` | 范围与优先级 | 0 | — | — |
|
||||
| Design Review | `/plan-design-review` | UI/UX 风险 | 0 | — | — |
|
||||
| DX Review | `/plan-devex-review` | 开发体验风险 | 0 | — | — |
|
||||
|
||||
VERDICT:可以进入实现阶段,但必须先完成协议文档更新并冻结字段契约。
|
||||
@@ -1,403 +0,0 @@
|
||||
# Eryao 工程计划:历史解卦与个人档案后端化(单一数据源)
|
||||
|
||||
日期:2026-04-05
|
||||
状态:规划中(Planning Only)
|
||||
|
||||
## 0. 约束与决策前提
|
||||
|
||||
本计划基于已确认前提:
|
||||
|
||||
1. 当前无生产兼容压力,旧字段可直接不兼容。
|
||||
2. 前端只做缓存层,不做权威数据源。
|
||||
3. `ui_schema` 属于通用迁移遗留,不在本项目范围,目标是移除。
|
||||
4. 头像存储必须使用 `avatars` bucket(`config.storage.avatar.bucket`)。
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标
|
||||
|
||||
在不引入额外业务表的前提下,完成以下工程目标:
|
||||
|
||||
1. assistant 消息落库时,`metadata.agent_output` 持久化完整 `divination_derived`。
|
||||
2. `GET /api/v1/agent/history` 返回前端可直接消费的 `assistant.agent_output`(移除 `ui_schema`)。
|
||||
3. 新增 profile 后端 API,前端设置页改为后端读写。
|
||||
4. 头像上传改为预签名 + `avatars` bucket,后端校验路径和类型。
|
||||
|
||||
---
|
||||
|
||||
## 2. 系统边界与职责
|
||||
|
||||
### 2.1 边界图
|
||||
|
||||
```text
|
||||
[Flutter App]
|
||||
| Auth Token
|
||||
v
|
||||
[API Router v1]
|
||||
|---- /agent/runs + /agent/history
|
||||
|---- /users/me/profile + /users/me/avatar/upload-url
|
||||
v
|
||||
[Service Layer]
|
||||
|---- AgentService: 会话、历史、消息转换
|
||||
|---- UserProfileService: 档案读写、头像签名
|
||||
v
|
||||
[Repository Layer]
|
||||
|---- sessions/messages/profiles CRUD
|
||||
v
|
||||
[Postgres + Supabase Storage]
|
||||
|---- messages.metadata_json
|
||||
|---- profiles
|
||||
|---- bucket: avatars
|
||||
```
|
||||
|
||||
### 2.2 分层职责
|
||||
|
||||
- Router:参数校验、鉴权入口、RFC7807 错误转换。
|
||||
- Service:业务规则与信任边界控制。
|
||||
- Repository:纯查询和写入,不做鉴权决策。
|
||||
- Schema:协议强类型、禁止松散 dict 漂移。
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据流设计
|
||||
|
||||
## 3.1 解卦写入链路(新增 `divination_derived`)
|
||||
|
||||
```text
|
||||
POST /agent/runs
|
||||
-> Runner emit DIVINATION_DERIVED(divination)
|
||||
-> StageEmitter merge into TEXT_MESSAGE_END payload
|
||||
-> EventStore picks worker_output_fields
|
||||
-> metadata.agent_output.divination_derived persisted
|
||||
-> messages.metadata_json
|
||||
```
|
||||
|
||||
### 关键点
|
||||
|
||||
1. `AgentOutput` 增加 `divination_derived` 强类型字段。
|
||||
2. `EventStore` 字段白名单纳入 `divination_derived`。
|
||||
3. `extra="forbid"` 保留,防止脏字段入库。
|
||||
|
||||
## 3.2 历史读取链路(移除 `ui_schema`)
|
||||
|
||||
```text
|
||||
GET /agent/history
|
||||
-> AgentService.get_history_snapshot
|
||||
-> convert_message_to_history
|
||||
user -> content + attachments
|
||||
assistant -> content + agent_output
|
||||
-> HistoryMessage response
|
||||
```
|
||||
|
||||
### 关键点
|
||||
|
||||
1. 停止 `ui_hints -> ui_schema` 编译。
|
||||
2. assistant 返回受控 `agent_output` 子集,不透传任意 metadata。
|
||||
3. 前端结果页以 `agent_output.divination_derived` 为主数据源。
|
||||
|
||||
## 3.3 Profile 与头像链路
|
||||
|
||||
```text
|
||||
GET /users/me/profile
|
||||
-> read profiles
|
||||
|
||||
PATCH /users/me/profile
|
||||
-> validate payload
|
||||
-> update profiles
|
||||
|
||||
POST /users/me/avatar/upload-url
|
||||
-> validate mime/size/path
|
||||
-> create signed upload url (bucket=avatars)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. API 契约(冻结版)
|
||||
|
||||
## 4.1 History 响应(目标结构)
|
||||
|
||||
```json
|
||||
{
|
||||
"scope": "history_day",
|
||||
"threadId": "uuid",
|
||||
"day": "2026-04-05",
|
||||
"hasMore": false,
|
||||
"messages": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"seq": 12,
|
||||
"role": "assistant",
|
||||
"content": "...",
|
||||
"timestamp": "2026-04-05T12:34:56Z",
|
||||
"agent_output": {
|
||||
"sign_level": "中上签",
|
||||
"summary": "...",
|
||||
"conclusion": ["..."],
|
||||
"focus_points": ["..."],
|
||||
"advice": ["..."],
|
||||
"keywords": ["..."],
|
||||
"answer": "...",
|
||||
"divination_derived": {
|
||||
"binaryCode": "101001",
|
||||
"changedBinaryCode": "100001",
|
||||
"guaName": "...",
|
||||
"targetGuaName": "...",
|
||||
"ganzhi": {},
|
||||
"yaoInfoList": []
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- 本接口不再返回 `ui_schema`。
|
||||
- user 消息仍可返回 `attachments`。
|
||||
|
||||
## 4.2 Profile API
|
||||
|
||||
### `GET /api/v1/users/me/profile`
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": "uuid",
|
||||
"display_name": "string",
|
||||
"bio": "string",
|
||||
"avatar_path": "avatars/{user_id}/...",
|
||||
"avatar_url": "https://...",
|
||||
"updated_at": "..."
|
||||
}
|
||||
```
|
||||
|
||||
### `PATCH /api/v1/users/me/profile`
|
||||
|
||||
请求:
|
||||
|
||||
```json
|
||||
{
|
||||
"display_name": "string<=30",
|
||||
"bio": "string<=200",
|
||||
"avatar_path": "avatars/{user_id}/..."
|
||||
}
|
||||
```
|
||||
|
||||
### `POST /api/v1/users/me/avatar/upload-url`
|
||||
|
||||
请求:
|
||||
|
||||
```json
|
||||
{
|
||||
"mime_type": "image/png",
|
||||
"file_size": 123456,
|
||||
"ext": "png"
|
||||
}
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"bucket": "avatars",
|
||||
"path": "avatars/{user_id}/{uuid}.png",
|
||||
"upload_url": "https://...",
|
||||
"expires_in": 600
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 信任边界与安全规则
|
||||
|
||||
1. `user_id` 只能取 JWT `sub`,禁止客户端传 owner。
|
||||
2. 头像 path 必须前缀匹配:`avatars/{current_user.id}/`。
|
||||
3. bucket 必须等于 `config.storage.avatar.bucket`。
|
||||
4. mime 白名单:`image/png|image/jpeg|image/webp`。
|
||||
5. size 上限:`config.storage.avatar.max_size_mb`。
|
||||
6. history 读取严格校验 session owner。
|
||||
7. 错误统一 RFC7807 + `code`。
|
||||
|
||||
---
|
||||
|
||||
## 6. 失败模式与处理
|
||||
|
||||
## 6.1 消息落库阶段
|
||||
|
||||
1. `divination_derived` 校验失败
|
||||
- 行为:拒绝写入该字段并记录结构化日志。
|
||||
- 错误码:`AGENT_OUTPUT_DIVINATION_INVALID`(新)。
|
||||
2. TEXT_MESSAGE_END 缺失关键字段
|
||||
- 行为:整条 assistant 消息按失败路径处理,不写半残对象。
|
||||
|
||||
## 6.2 history 读取阶段
|
||||
|
||||
1. `agent_output` 缺失或损坏
|
||||
- 行为:assistant 消息返回 `content`,并标记 `agent_output=null`。
|
||||
- 前端:展示“历史记录不完整”提示,不崩溃。
|
||||
2. 非 owner 访问
|
||||
- 行为:403,`code=AGENT_SESSION_FORBIDDEN`。
|
||||
|
||||
## 6.3 头像上传阶段
|
||||
|
||||
1. bucket/path 越权
|
||||
- 422,`AVATAR_PATH_SCOPE_INVALID`。
|
||||
2. mime/size 非法
|
||||
- 422,`AVATAR_FILE_INVALID`。
|
||||
3. storage 签名失败
|
||||
- 502,`AVATAR_SIGNED_URL_FAILED`。
|
||||
|
||||
---
|
||||
|
||||
## 7. 关键边缘场景
|
||||
|
||||
1. 用户连续点击“保存资料”两次:
|
||||
- 以后端最后一次写入为准,前端按钮防抖。
|
||||
2. 上传头像成功但 profile 更新失败:
|
||||
- 前端重试 profile PATCH,不重复上传。
|
||||
3. history 返回空列表:
|
||||
- 前端展示空态,不触发本地假数据。
|
||||
4. 助手消息存在但缺 `divination_derived`:
|
||||
- 卡片可展示摘要,不允许进入完整结果页。
|
||||
5. 解卦完成后 history 立即读取:
|
||||
- 允许短暂读到旧快照,前端做一次重拉。
|
||||
|
||||
---
|
||||
|
||||
## 8. 技术取舍
|
||||
|
||||
### 方案 A(推荐):在现有 messages.metadata 扩展
|
||||
|
||||
- 优点:
|
||||
- 最小变更,不新增表。
|
||||
- 复用当前会话与历史体系。
|
||||
- 缺点:
|
||||
- metadata 体积增大,需要关注单条消息大小。
|
||||
|
||||
### 方案 B:新增 `divination_results` 独立表
|
||||
|
||||
- 优点:
|
||||
- 结构更纯,查询更明确。
|
||||
- 缺点:
|
||||
- 迁移、回写、关联复杂度明显增加。
|
||||
|
||||
结论:
|
||||
|
||||
- 当前阶段选 A,满足速度与复杂度平衡。
|
||||
|
||||
---
|
||||
|
||||
## 9. 实施切片(按风险顺序)
|
||||
|
||||
### Slice 1:协议与 schema
|
||||
|
||||
1. 更新协议文档:history + profile + 错误码。
|
||||
2. 更新 `AgentOutput` 模型字段。
|
||||
|
||||
### Slice 2:写链路改造
|
||||
|
||||
1. runner/emitter/store 打通 `divination_derived` 落库。
|
||||
2. 增加单元测试与集成测试。
|
||||
|
||||
### Slice 3:读链路改造
|
||||
|
||||
1. history 转换改为返回 `agent_output`。
|
||||
2. 移除 `ui_schema` 响应字段。
|
||||
|
||||
### Slice 4:profile API + 头像
|
||||
|
||||
1. users 路由、service、schema。
|
||||
2. 头像 upload-url 接口。
|
||||
|
||||
### Slice 5:前端切换
|
||||
|
||||
1. 历史列表/详情改消费后端 `agent_output`。
|
||||
2. 设置页改 profile 接口。
|
||||
3. 清理本地真源。
|
||||
|
||||
---
|
||||
|
||||
## 10. 测试覆盖计划
|
||||
|
||||
## 10.1 后端测试矩阵
|
||||
|
||||
### A. AgentOutput 落库
|
||||
|
||||
1. `divination_derived` 正常写入。
|
||||
2. `divination_derived` 非法结构拒绝写入。
|
||||
|
||||
### B. history 接口
|
||||
|
||||
1. assistant 返回 `agent_output`。
|
||||
2. 响应不含 `ui_schema`。
|
||||
3. 非 owner 403。
|
||||
4. 空历史返回空数组。
|
||||
|
||||
### C. profile 接口
|
||||
|
||||
1. GET 返回当前用户档案。
|
||||
2. PATCH 字段边界(空、超长、非法字符)。
|
||||
3. 并发 PATCH 最终一致性。
|
||||
|
||||
### D. avatar upload-url
|
||||
|
||||
1. 合法 mime/size/path 成功签名。
|
||||
2. bucket/path 越权失败。
|
||||
3. mime/size 超限失败。
|
||||
4. storage 异常返回 502 问题体。
|
||||
|
||||
## 10.2 前端测试矩阵
|
||||
|
||||
1. history 列表从接口渲染。
|
||||
2. 点击历史项进入结果页并解析 `divination_derived`。
|
||||
3. profile 读写回显。
|
||||
4. 头像上传后刷新显示。
|
||||
5. 异常提示(网络失败、数据缺失)不崩溃。
|
||||
|
||||
---
|
||||
|
||||
## 11. 可观测性
|
||||
|
||||
新增日志字段建议:
|
||||
|
||||
1. history 响应统计:`thread_id`, `message_count`, `assistant_with_agent_output_count`。
|
||||
2. profile 更新:`user_id`, `updated_fields`。
|
||||
3. avatar 签名:`user_id`, `mime_type`, `file_size`, `success/failure_code`。
|
||||
|
||||
指标建议:
|
||||
|
||||
1. `history_agent_output_missing_rate`。
|
||||
2. `avatar_upload_url_failure_rate`。
|
||||
3. `profile_patch_error_rate`。
|
||||
|
||||
---
|
||||
|
||||
## 12. 风险与回滚
|
||||
|
||||
### 风险
|
||||
|
||||
1. 单条 metadata 变大,可能影响查询性能。
|
||||
2. 前端解析新结构时存在字段名误配风险。
|
||||
|
||||
### 回滚
|
||||
|
||||
1. 若读链路异常,先回滚 history 输出层(保持落库不回滚)。
|
||||
2. profile 接口异常时,可临时只读禁写,保护账户信息。
|
||||
|
||||
---
|
||||
|
||||
## 13. 验收标准(Done)
|
||||
|
||||
1. 新产生 assistant 消息均含 `metadata.agent_output.divination_derived`。
|
||||
2. history 接口返回 `agent_output`,且不再返回 `ui_schema`。
|
||||
3. 前端历史页与结果页不依赖本地真源。
|
||||
4. profile 读写和头像上传全走后端。
|
||||
5. 测试矩阵项全部落地并通过。
|
||||
|
||||
---
|
||||
|
||||
## 14. NOT in Scope
|
||||
|
||||
1. 大规模清理 `backend/src/schemas/domain/**`。
|
||||
2. 历史数据回填脚本。
|
||||
3. 新增独立 `divination_results` 表。
|
||||
Reference in New Issue
Block a user