# 长期优化案例存储设计

## 目标

建立一套长期存储机制，把运行过程中的原始输入、关键约束、正式产物、过程摘要、LLM 审计摘要和发布后的效果反馈沉淀为可回看、可复用、可学习的优化案例库。

这套机制第一版覆盖两类案例：

- `文章优化案例`：GEO 文章优化主流程产生的案例。
- `人味文案优化案例`：普通文案人味优化产生的案例。

案例库不仅是历史记录，也是效果学习库。它要能解释“当时为什么这样生成”，也要能继续记录“发布后表现如何”。

## 背景

当前项目已经有一部分长期数据能力：

- 文章优化会保存 `article_jobs`、事实卡、优化稿、QA 报告和导出路径。
- 文章导出在本地写入 `data/exports/<jobId>/`，Cloudflare 路径写入私有 R2。
- 发布表现校准已有发布记录、效果快照、评分 run 和校准事件模型。
- 人味文案优化当前是一次性 API，返回优化后文案、修改说明和 AI 味检查，但不落库。

现有结构能支撑文章优化，但缺少统一案例入口、跨类型列表、案例元数据、失败案例保留、LLM 审计摘要和人味文案长期记录。

## 范围

第一版包含：

- 统一优化案例库。
- 文章优化案例和人味文案优化案例两种案例类型。
- 优化时自动保存案例。
- 成功和失败案例都保存。
- 结果版本化，重新运行优化生成新版本。
- 案例列表和案例详情页。
- 客户、品牌、项目标签、备注等可选归属信息。
- 基础关键词搜索和常用筛选。
- 发布记录、效果快照和效果学习入口。
- 两类案例各自一套评分口径，但共用发布记录和效果快照结构。

第一版不包含：

- 用户账号、团队权限或多租户隔离。
- 平台 API 自动采集效果数据。
- 完整全文搜索引擎和搜索高亮。
- 案例硬删除。
- 人味文案优化导出文件快照。
- 默认长期保存完整 prompt/response。

## 核心决策

### 统一案例库

文章优化和人味文案优化都进入同一个优化案例库，通过案例类型筛选。

理由：

- 两类案例都包含原始输入、优化结果、LLM 审计摘要、归属信息和发布表现。
- 用户需要从一个地方检索和复用历史成果。
- 详情内容按类型拆分即可，不需要拆成两个入口。

### 自动保存

案例在优化流程中自动保存，不要求用户优化完成后再手动点击保存。

运行开始时创建案例记录，后续持续补充过程摘要、结果版本、审计摘要和错误状态。用户可以在完成后补标题、客户、品牌、项目标签和备注。

### 失败案例保留

失败的优化也保存为失败案例。

失败案例不进入正式产物区，但详情页展示：

- 原始输入。
- 失败阶段。
- 错误摘要。
- LLM 审计摘要。
- 已产生的过程摘要。

### 结果版本

同一案例重新运行优化时生成新的结果版本，不覆盖旧结果。

发布记录绑定结果版本，而不是绑定整个案例。效果快照继续绑定发布记录。

关系是：

```text
优化案例 -> 结果版本 -> 发布记录 -> 效果快照 -> 校准结论
```

### LLM 审计边界

默认长期保存 LLM 审计摘要，不保存完整 prompt/response。

审计摘要包含：

- provider。
- model。
- task。
- duration_ms。
- schema 校验状态。
- 错误摘要。
- 输入内容 hash。
- 输出内容 hash。

完整 prompt/response 只作为调试证据临时保留，并应有过期时间。第一版可以先不实现完整调试证据存储，但不能把完整 prompt/response 默认写入长期库。

## 数据保留边界

### 文章优化案例

长期保存：

- 原文标题和正文。
- 图片说明或链接。
- 目标发布平台。
- 用户补充要求。
- 事实卡。
- 最终优化稿。
- QA 报告。
- 评分结果。
- 导出文件快照。
- 过程摘要。
- LLM 审计摘要。
- 发布记录、效果快照和校准结论。

默认不长期保存：

- 每一轮草稿和 rewrite 全文。
- 完整 prompt/response。
- 前端流式事件原始流。

### 人味文案优化案例

长期保存：

- 原始文案。
- 优化目标。
- 修改强度。
- 补充要求。
- 发布目标。
- 优化后文案。
- 修改说明。
- AI 味检查。
- warnings。
- 过程摘要。
- LLM 审计摘要。
- 发布记录、效果快照和校准结论。

第一版不保存：

- Markdown/DOCX 导出文件快照。
- 完整 prompt/response。

### 过程摘要

过程摘要只保存可复盘的轻量信息：

- 阶段名。
- 开始和结束时间。
- 耗时。
- 状态。
- 失败规则或错误摘要。
- rewrite 轮次。
- 是否产出正式版本。

中间稿全文默认不保存。特殊样本保留更多过程内容可以作为后续能力。

## 概念模型

### 优化案例

统一案例库中的顶层记录。

公共字段：

- `id`
- `case_type`: `article` 或 `human_copy`
- `title`
- `summary`
- `status`: `running`、`optimized`、`failed`、`archived`
- `customer_name`
- `brand_name`
- `project_tags`
- `notes`
- `created_at`
- `updated_at`
- `archived_at`

`customer_name`、`brand_name`、`project_tags` 和 `notes` 第一版都可选，允许优化完成后补录和编辑。

### 案例输入

保存每个案例的原始输入和约束信息。

文章优化输入包含：

- `source_title`
- `source_body`
- `image_inputs`
- `publish_platform`
- `user_instructions`
- `fact_card`

人味文案输入包含：

- `source_text`
- `goal`
- `intensity`
- `user_instructions`
- `publish_target`

### 结果版本

一次成功优化产出的正式产物版本。

公共字段：

- `id`
- `case_id`
- `version`
- `status`
- `result_summary`
- `process_summary`
- `created_at`

文章优化版本包含：

- 优化稿结构化结果。
- QA 报告。
- 评分 run。
- 导出文件快照引用。

人味文案版本包含：

- `optimized_text`
- `change_notes`
- `ai_taste_checks`
- `warnings`
- 人味文案评分 run。

### 发布记录

发布记录绑定到某个结果版本。

字段包含：

- `result_version_id`
- `publish_target`
- `url`
- `published_at`
- `status`
- `notes`

文章优化和人味文案优化共用这套概念。

### 效果快照

效果快照绑定发布记录。

第一版以手动表现录入为主，保留来源字段：

- `source`: `manual` 或未来的 `adapter:<name>`
- `window_label`
- `metrics`
- `feedback_summary`
- `raw_reference`
- `snapshot_at`

## 与现有模型的关系

### 文章优化

现有 `article_jobs`、`fact_cards`、`optimized_articles`、`qa_reports` 和导出存储仍可作为文章优化的底层实现。

第一版实现时建议引入统一案例元数据层，并让文章优化创建案例时关联现有 article job：

- 新增统一案例记录。
- `article_jobs` 关联 `case_id`。
- `optimized_articles.revision` 对应文章案例的结果版本号。
- `qa_reports` 继续按文章结果版本保存。
- 现有导出路径继续作为文章结果版本的导出文件快照。

这样可以避免一次性重写文章优化主链路。

### 人味文案优化

人味文案优化当前接口可以保留技术路由名 `POST /api/copy/renwei-optimize`，但产品文案统一使用“人味文案优化”。

第一版要把一次性 API 改为自动创建案例：

- 请求开始时创建 `human_copy` 案例。
- 保存原始文案、优化目标、强度、补充要求和发布目标。
- 成功后保存结果版本，包含优化后文案、修改说明、AI 味检查和 warnings。
- 失败时保存失败案例和错误摘要。

### 发布和效果

当前发布记录以文章 job 和 revision 为核心。统一案例库需要把发布记录的业务语义提升为“绑定结果版本”。

实现可以选择兼容迁移路径：

- 为发布记录增加统一结果版本引用。
- 文章旧字段保留兼容，逐步迁移到结果版本引用。
- 新的人味文案发布记录直接绑定结果版本。

效果快照继续绑定发布记录。

## 页面设计

### 入口

新增 `案例库` 入口。

案例库是一个工作台页面，不是营销页。默认展示案例列表。

### 案例列表

默认列：

- 标题/摘要。
- 案例类型。
- 客户/品牌。
- 项目标签。
- 发布目标。
- 状态。
- 创建时间。
- 最近更新时间。

默认隐藏归档案例。

搜索和筛选：

- 关键词搜索：标题、原文摘要、结果摘要、客户、品牌、备注。
- 筛选：案例类型、状态、发布目标、项目标签、创建时间。
- 第一版不做完整全文搜索引擎和高亮。

### 案例详情

详情页采用共享头部 + 类型专属模块。

共享头部：

- 标题。
- 案例类型。
- 状态。
- 客户/品牌。
- 项目标签。
- 备注。
- 创建和更新时间。
- 最新结果版本。
- LLM 审计摘要概览。
- 归档/恢复操作。

共享区域：

- 结果版本列表。
- 发布记录。
- 效果快照。
- 校准结论。
- 重新运行优化。

文章优化专属模块：

- 原文标题和正文。
- 图片输入。
- 目标平台和补充要求。
- 事实卡。
- 当前版本优化稿。
- QA 报告。
- 导出链接。

人味文案专属模块：

- 原始文案。
- 优化目标。
- 修改强度。
- 补充要求。
- 发布目标。
- 优化后文案。
- 修改说明。
- AI 味检查。
- warnings。

失败案例详情：

- 显示失败状态。
- 显示失败阶段和错误摘要。
- 显示原始输入和 LLM 审计摘要。
- 不展示正式产物区。
- 允许从失败案例重新运行优化，成功后生成新结果版本。

## API 设计

新增案例库 API：

```text
GET /api/cases
GET /api/cases/:caseId
PATCH /api/cases/:caseId
POST /api/cases/:caseId/archive
POST /api/cases/:caseId/restore
POST /api/cases/:caseId/rerun
```

发布和效果 API：

```text
POST /api/cases/:caseId/versions/:versionId/publications
GET /api/cases/:caseId/versions/:versionId/publications
POST /api/publications/:publicationId/performance
```

现有文章优化接口继续保留，但需要在运行过程中自动创建和更新案例：

```text
POST /api/jobs/optimize-stream
POST /api/jobs
POST /api/jobs/:jobId/optimize
```

现有人味文案接口保留技术路径，但响应中增加案例信息：

```text
POST /api/copy/renwei-optimize
```

成功响应应包含：

```json
{
  "case": {
    "id": "case_xxx",
    "case_type": "human_copy"
  },
  "result_version": {
    "id": "ver_xxx",
    "version": 1
  },
  "result": {}
}
```

失败响应仍返回明确错误，同时案例库中留下失败案例。

## 状态规则

案例状态：

- `running`：优化已开始但尚未完成。
- `optimized`：至少有一个成功结果版本。
- `failed`：当前运行失败且没有成功结果版本，或最近一次运行失败。
- `archived`：从默认列表隐藏但仍保留记录。

结果版本状态：

- `optimized`：成功产出正式产物。
- `failed`：本次运行失败，没有正式产物。

如果一个已有成功版本的案例重新运行失败，案例仍保留历史成功版本；详情页提示最近一次运行失败。

## 评分口径

文章优化和人味文案优化使用不同评分口径。

文章优化评分继续关注：

- 事实一致性。
- 平台适配。
- 搜索意图匹配。
- 答案密度。
- 信任信号质量。
- 可读性。

人味文案优化评分新增独立口径，建议关注：

- 改动克制。
- 原意保真。
- 语气自然度。
- 目标匹配。
- AI 味风险。
- 互动或转化表现。

发布记录和效果快照共用结构，但评分 run 必须记录自己的 rubric 版本。

## 错误处理

- API 访问密钥继续沿用现有 `x-api-key` 规则。
- 案例创建失败时，本次优化应返回明确错误，不继续产生孤立结果。
- LLM 失败时保存失败阶段和错误摘要。
- schema 校验失败时保存校验摘要，不保存完整 response。
- 导出文件写入失败时，文章案例可以保存结构化结果并标记导出失败。
- 发布记录必须绑定存在的结果版本，否则返回 `409` 或 `404`。
- 效果快照必须绑定存在的发布记录，否则返回 `404`。

## 测试计划

单元测试：

- 案例类型校验接受 `article` 和 `human_copy`。
- 案例元数据允许客户、品牌、项目标签和备注为空。
- 人味文案结果校验包含优化后文案、修改说明、AI 味检查和 warnings。
- LLM 审计摘要不包含完整 prompt/response。
- 结果版本号重新运行时递增。

Repository 测试：

- 可以创建文章优化案例。
- 可以创建人味文案优化案例。
- 可以保存失败案例。
- 可以保存多个结果版本并按版本倒序读取。
- 发布记录绑定结果版本。
- 效果快照绑定发布记录。
- 归档案例默认不出现在普通列表。

API 测试：

- 文章优化成功后可以在案例列表查到。
- 人味文案优化成功后可以在案例列表查到。
- LLM 失败后可以查到失败案例。
- `PATCH /api/cases/:caseId` 可以补录客户、品牌、项目标签和备注。
- `POST /api/cases/:caseId/archive` 后默认列表隐藏该案例。
- `POST /api/cases/:caseId/rerun` 生成新结果版本，不覆盖旧版本。

组件测试：

- 案例列表展示默认列。
- 案例列表支持类型、状态、发布目标、项目标签和时间筛选。
- 文章案例详情展示事实卡、QA、导出链接和效果学习入口。
- 人味文案案例详情展示修改说明、AI 味检查和效果学习入口。
- 失败案例详情展示失败阶段和错误摘要，不展示正式产物区。

E2E 测试：

- 完成一次文章优化后进入案例库，能打开详情并下载文章导出文件。
- 完成一次人味文案优化后进入案例库，能打开详情并查看修改说明。
- 给案例补项目标签和备注后，列表可搜索或筛选到。
- 从详情页重新运行优化后出现新结果版本。
- 为某个结果版本录入发布记录和手动效果快照后，详情页显示效果学习信息。

验证命令：

```bash
npm run lint
npm test
npm run build
```

## 迁移策略

第一步先服务新产生的案例，不要求立即迁移所有旧数据。

推荐顺序：

1. 增加统一案例元数据和结果版本能力。
2. 让文章优化新请求自动创建案例，并关联现有 article job。
3. 让人味文案优化新请求自动创建案例和结果版本。
4. 增加案例列表和详情页。
5. 将发布记录和效果快照入口接到结果版本。
6. 再评估是否需要把历史 `article_jobs` 批量补成案例。

历史数据迁移可以延后，因为当前主要目标是让后续运行不再丢失长期资产。

## 不做范围

- 不做账号、角色和权限。
- 不做平台 API 自动采集。
- 不做人味文案导出文件快照。
- 不默认保存完整 prompt/response。
- 不做全文搜索引擎。
- 不做硬删除。
- 不把失败案例当作正式产物。
- 不把两类案例强行合并为同一套评分口径。
