Files
AI-Secretary/docs/contracts/状态流转约定.md
2026-06-22 17:30:59 +08:00

322 lines
9.6 KiB
Markdown

# 状态流转约定
本文件是状态枚举、允许流转、触发人和日志要求的唯一事实源。代码枚举、接口返回和测试用例应与本文件一致。
## 1. 通用原则
1. 状态统一使用英文枚举。
2. 状态变化必须通过 service 层完成。
3. 关键状态变化必须写 `operation_logs`
4. 非法状态跳转必须返回 `state_conflict`
5. 通知、回调、调度相关状态变化必须幂等。
## 2. AI 草稿状态
| 状态 | 含义 |
| --- | --- |
| `pending_confirmation` | 草稿已整理完成,等待老板确认、修改、取消或补充/重说 |
| `awaiting_follow_up` | 老板已点击补充/重说,等待 30 分钟内下一条补充消息 |
| `confirmed` | 已人工确认,等待转换为事项或提醒 |
| `converted` | 已转换为事项或提醒;复杂事项已创建 `pending_manager_confirm` 事项壳也视为已转换 |
| `cancelled` | 已取消 |
| `answered` | 已直接回复或留痕,不进入事项、提醒或通知闭环 |
| `superseded` | 已被补充/重说生成的新草稿替代 |
| `expired` | 补充/重说等待超时,旧确认卡片不可继续使用 |
| `parse_failed` | AI 解析或草稿处理失败,仅用于调试追踪 |
允许流转:
```text
pending_confirmation -> confirmed
pending_confirmation -> awaiting_follow_up
pending_confirmation -> cancelled
pending_confirmation -> parse_failed
awaiting_follow_up -> superseded
awaiting_follow_up -> expired
awaiting_follow_up -> cancelled
confirmed -> converted
confirmed -> parse_failed
```
约束:
1. `parse_failed``cancelled``converted``answered``superseded``expired` 为终态。
2. 未进入 `confirmed` 的草稿不得转换。
3. `note``unknown``qa``realtime_qa``need_more_info``unsupported` 不进入事项、提醒或通知闭环;如需留痕,只能使用 `answered``parse_failed`
4. 老板点击补充/重说后,原草稿进入 `awaiting_follow_up`,并使原确认卡片失效。
5. 30 分钟内收到补充消息后,新草稿 `parent_draft_id` 指向原草稿,原草稿进入 `superseded`
6. 超过 30 分钟后,原草稿进入 `expired`,老板下一条消息按新输入处理。
7. 飞书回调确认、取消、补充/重说前,必须校验回调来自 `active_card_notification_id` 对应的当前有效卡片。
8. 复杂事项不使用草稿状态等待程经理确认;老板确认后应创建 `tasks.status=pending_manager_confirm` 的事项壳。
9. `answered``parse_failed` 可以作为最小留痕草稿的初始终态,不参与确认和转换。
## 3. 事项状态
| 状态 | 含义 |
| --- | --- |
| `pending_manager_confirm` | 等待程经理确认 |
| `pending_notify` | 待通知 |
| `notified` | 已通知 |
| `notify_failed` | 通知失败 |
| `feedback_received` | 已收到反馈 |
| `completed` | 已完成 |
| `problem` | 有问题 |
| `cancelled` | 已取消 |
允许流转:
```text
pending_manager_confirm -> pending_notify
pending_manager_confirm -> cancelled
pending_notify -> notified
pending_notify -> notify_failed
notify_failed -> pending_notify
notified -> feedback_received
notified -> completed
notified -> problem
feedback_received -> completed
feedback_received -> problem
problem -> pending_notify
```
约束:
1. `cancelled` 为终态。
2. 未通知事项不得接收飞书反馈。
3. `problem` 必须有问题原因。
4. 通知失败不得标记为 `notified`
## 4. 事项用户可见反馈状态
| 状态 | 含义 |
| --- | --- |
| `received` | 已收到 |
| `in_progress` | 处理中 |
| `completed` | 已完成 |
| `problem` | 有问题 |
约束:
1. `problem` 必须填写 `problem_reason`
2. 反馈人必须是事项接收人。
3. `received``in_progress` 反馈写入 `feedbacks.status`,并将 `tasks.status` 置为 `feedback_received``tasks.visible_feedback_status` 置为对应值。
4. `completed` 反馈将 `tasks.status``tasks.visible_feedback_status` 都置为 `completed`
5. `problem` 反馈将 `tasks.status``tasks.visible_feedback_status` 都置为 `problem`,并写入 `problem_reason`
## 5. 提醒状态
| 状态 | 含义 |
| --- | --- |
| `active` | 生效中 |
| `paused` | 已暂停 |
| `triggered` | 一次性提醒已触发 |
| `trigger_failed` | 触发失败 |
| `cancelled` | 已取消 |
| `expired` | 已过期 |
允许流转:
```text
active -> paused
paused -> active
active -> triggered
active -> trigger_failed
trigger_failed -> active
active -> cancelled
paused -> cancelled
trigger_failed -> cancelled
triggered -> expired
```
约束:
1. 只有 `active` 可以被 scheduler 触发。
2. `cancelled` 为终态。
3. `paused` 不触发通知。
4. `trigger_failed` 必须写失败记录。
5. 一次性提醒成功触发后,状态从 `active` 变为 `triggered`,并可在后续清理或展示时变为 `expired`
6. `daily``weekly``monthly` 周期提醒成功触发后状态保持 `active`,只更新 `last_triggered_at` 和下一次 `next_trigger_at`
7. 提醒反馈不改变提醒调度状态;反馈结果保存在 `feedbacks`,提醒是否继续触发只由 `status``repeat_rule``next_trigger_at` 决定。
## 6. 重复规则
| 值 | 含义 |
| --- | --- |
| `none` | 一次性 |
| `daily` | 每天 |
| `weekly` | 每周 |
| `monthly` | 每月 |
第一版不支持 cron 表达式和自定义复杂周期。
## 7. 通知状态
| 状态 | 含义 |
| --- | --- |
| `pending` | 待发送 |
| `sending` | 发送中 |
| `sent` | 已发送 |
| `failed` | 发送失败 |
| `retrying` | 补发中 |
| `cancelled` | 已取消 |
| `expired` | 卡片或通知操作已过期 |
允许流转:
```text
pending -> sending
pending -> sent
pending -> failed
sending -> sent
sending -> failed
failed -> retrying
retrying -> sent
retrying -> failed
pending -> cancelled
failed -> cancelled
pending -> expired
sent -> expired
```
约束:
1. `sent` 不得重复发送同一通知。
2. 补发必须保留原失败记录和新发送结果。
3. 飞书通知必须使用幂等键。
4. `expired``cancelled` 通知不得继续处理卡片确认、反馈或补充/重说。
5. 被新卡片替代或业务取消时,必须写 `invalidated_at`
通知幂等键建议:
```text
target_type + target_id + receiver_id + channel + trigger_time
```
提醒触发幂等键建议:
```text
reminder_id + trigger_time + receiver_id + notification_channel
```
## 8. 反馈状态
| 状态 | 含义 |
| --- | --- |
| `received` | 已收到 |
| `in_progress` | 处理中 |
| `completed` | 已完成 |
| `problem` | 有问题 |
约束:
1. 反馈目标只能是 `task``reminder`
2. 反馈人必须是接收人。
3. `problem` 必须填写一句原因。
4. 重复点击卡片不得重复创建相同反馈。
## 9. 失败记录状态
| 状态 | 含义 |
| --- | --- |
| `pending` | 待处理 |
| `processing` | 处理中 |
| `resolved` | 已处理 |
| `cancelled` | 已取消 |
允许流转:
```text
pending -> processing
pending -> resolved
pending -> cancelled
processing -> resolved
processing -> cancelled
```
约束:
1. `resolved` 必须填写处理结果。
2. 状态变化必须写操作日志。
## 10. 失败类型
| 类型 | 含义 |
| --- | --- |
| `ai_parse_failed` | AI 输出解析失败 |
| `ai_model_failed` | 百炼或模型网关超时、网络失败、服务异常,重试后仍失败 |
| `bot_message_failed` | 入口消息结构缺失、无法解析文本或 sender 信息 |
| `missing_person_mapping` | 缺少人员映射 |
| `memory_store_failed` | PostgreSQL AI 记忆表、上下文或快照保存/读取失败 |
| `draft_convert_failed` | 老板或程经理确认后,转换任务/提醒失败 |
| `feishu_auth_failed` | 飞书登录失败 |
| `feishu_send_failed` | 飞书通知失败 |
| `feishu_callback_failed` | 飞书回调处理失败 |
| `feishu_signature_invalid` | 飞书验签失败 |
| `reminder_trigger_failed` | 定时提醒触发失败 |
| `bot_unauthorized` | 非老板使用机器人入口 |
| `follow_up_expired` | 补充/重说上下文过期 |
| `user_feedback_problem` | 用户反馈有问题 |
| `permission_error` | 权限拒绝 |
| `system_error` | 未归类系统异常 |
## 11. 飞书事件处理状态
| 状态 | 含义 |
| --- | --- |
| `pending` | 已接收待处理 |
| `processed` | 已处理 |
| `failed` | 处理失败 |
| `ignored` | 已忽略 |
约束:
1. 同一 `event_id` 只处理一次。
2. 如果飞书某类回调没有稳定 `event_id`,必须使用 `idempotency_key` 做事件幂等。
3. 验签失败不得执行业务动作。
4. 旧卡片、失效卡片、已替代草稿和已过期通知的回调只记录事件并标记 `ignored`,不得写业务对象。
5. 处理失败必须写失败记录。
## 12. 用户和配置状态
用户状态:
| 状态 | 含义 |
| --- | --- |
| `active` | 启用 |
| `disabled` | 停用 |
人员映射状态:
| 状态 | 含义 |
| --- | --- |
| `pending` | 待解析 |
| `resolved` | 已解析 |
| `failed` | 解析失败 |
Prompt 上下文状态:
| 状态 | 含义 |
| --- | --- |
| `draft` | 草稿 |
| `active` | 启用 |
| `archived` | 已归档 |
飞书登录会话状态:
| 状态 | 含义 |
| --- | --- |
| `pending` | 登录处理中 |
| `success` | 登录成功 |
| `failed` | 登录失败 |
机器人上下文状态:
| 状态 | 含义 |
| --- | --- |
| `empty` | 当前没有可补充或可确认的草稿 |
| `awaiting_more_info` | AI 已追问,等待老板补充 |
| `awaiting_confirm` | 草稿已整理完成,等待老板确认、修改、取消或转经理 |
| `awaiting_follow_up` | 老板点击补充/重说后,等待下一条消息修订上一版草稿 |
| `expired` | 已过期 |
| `cleared` | 草稿已确认、取消或转换完成,上下文已清空 |