# POST /api/v1/trace/finalize + /trace/epilogue — 比价 trace 收尾族

> 所属:透传端点（前缀 `/api/v1`，外卖比价） | 鉴权:软鉴权 OptionalUser | [← 返回 API 索引](../README.md)

## POST /api/v1/trace/finalize — 收尾上云(+夭折落库)

透传到 pricebot-backend。用户终止 / Phase 1 未识别没走到 done 帧时，pricebot 没上云也没回传 `trace_url`。客户端收尾时打这个，pricebot 按 `trace_id` 一致性 hash 落到处理这条 trace 的同一进程（dir_cache 在那才能算对 trace 目录），打包上云返回 `{trace_url}`。

**顺手夭折落库(2026-07 起)**:app-server 把该 trace 的 [comparison_record](../../database/comparison_record.md) `running` 行更新成夭折终态(`harvest_abort`,**不降级已 success**)。body 可带 `status`(`cancelled`/`failed`)+ `reason`;老客户端只带 `trace_id` → 默认 `cancelled`,其后续 `/compare/record` 上报再补精确态。

## 入参

透传 pricebot，客户端按 pricebot 协议组装。关键字段：

| 字段 | 类型 | 说明 |
|---|---|---|
| `device_id` | string | 设备 ID |
| `trace_id` | string | 比价 trace 标识 |
| *(透传)* | | 其余字段由 pricebot 定义，本端点不做校验 |

Mock 入参:
```json
{
  "device_id": "android_abc123def456",
  "trace_id": "tr_20260703_m3n4o5p6",
  "reason": "user_cancelled"
}
```

## 出参

透传 pricebot 原始响应，通常包含 `trace_url`。

Mock 出参:
```json
{
  "trace_url": "https://trace.shaguabijia.com/tr_20260703_m3n4o5p6",
  "ok": true
}
```

## 错误码
- `502` pricebot 不可达或返回 5xx
- `400` 请求体不是合法 JSON

## 说明
- 一致性 hash 按 `trace_id` 路由到同一 pricebot 实例（确保 dir_cache 命中）
- 软鉴权（OptionalUser,同比价透传族）
- 与 `/intent/recognize`、`/price/step` 等同属外卖比价透传族

---

## POST /api/v1/trace/epilogue — 结果页尾声帧(#112)

App 收到 done、渲染完**结果页**后,把自己页面的截图(base64,body ~几百 KB)传给 pricebot 存进 trace 目录并触发重传——trace 里补上「用户实际看到的汇总页」(步骤帧只有目标 App 画面)。

- **纯透传壳**:不建行、不落库(该 trace 的比价记录已由 done / finalize 落终态)。
- 入参:`{device_id, trace_id, screenshot(base64), ...}`(pricebot 协议);出参:pricebot 原样响应。
- 错误码同 finalize(`400` / `502`)。
