## 修复记录

- 22:59：记录 bug 修复：AI 工作台重复保存请求会创建多张申请草稿和多条事件。
  - Git 提交检查：已执行 `git fetch --all --prune`，未发现 upstream 新提交；本地 ahead 4 个既有提交，分别为 `22669a90 feat(expenses): show unified expense event timeline`（真实费用事件时间线）、`a616b30c fix(expenses): unify AI application submission transaction`（AI 申请提交事务）、`653eda05 feat(auth): add opaque bearer sessions`（不透明 Bearer 会话）和 `661990b2 feat(expenses): add transactional expense case events`（Expense Case 事务事件基础）。
  - 修改：新增 `expense_application_draft_events.py`，以租户、操作人、run ID 和稳定草稿快照生成固定长度幂等键及 UUID5 聚合 ID；`user_agent_application.py` 在新建前复用已完成动作，并在并发主键竞争后回滚、重查已提交事件。持久化兜底的当前时间不参与指纹，原始申请时间仍通过申请详情快照区分。
  - 操作：先在容器中分别复现“带日期相同请求”和“缺日期半成品相同请求”均生成两个不同 `claim_id`，再补动作级幂等和数据库并发仲裁路径；业务单号继续使用既有随机格式，没有修改数据库结构或执行迁移。
  - 验证：相同 HTTP 保存请求连续执行两次返回同一 `claim_id` 和 `claim_no`，数据库只有一张申请草稿与一条 `claim_draft_created`；同一 run 的不同快照仍分别留痕，事件失败时草稿、Case、Link 和事件整体回滚。容器内受影响后端定向回归 36 项、前端时间线兼容测试 9 项及 Python `ruff --select F,I` 通过。
  - 影响：网络重试、用户重复点击或客户端重放不会制造重复申请草稿；并发请求由稳定聚合主键仲裁。真实 PostgreSQL 双会话并发集成测试仍是后续可补的非阻断验证，不影响当前顺序重放与事务契约。
