> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# Task Pipeline 设计 Brief

> **Historical design brief（2026-07-23 校准）**：这是 2026-05 的设计任务书，不是当前 implementation specification。保留用于理解历史问题；当前 Task V2 parity 和 Task V2+ 路线见 [工程审计与实施基线](/product-design/v2/tasks-feature/task-v2-plus-engineering-audit.md)，Task V3 设计仍待评估。
>
> **这是什么**: 给新 session 的设计任务。不是 session 总结,不是 bug 修复清单。
> **日期**: 2026-05-30
> **前序工作**: 2026-05-29 做了 task 生命周期调研(代码 + Neon 数据 + 业界对比),产出了 gap 分析文档和场景覆盖度。细节在材料里,这份 brief 只给方向。

***

## 你要做什么

**设计 retaintive task pipeline 的架构:代码层和 prompt 层各自负责什么、怎么配合。**

这是一个 **system design** 任务,不是修 bug 或补字段。你的角色:一个精通 AI 技术的 Principal Engineer / AI Engineer——选最贴合这个任务的角色来思考。

***

## Expected Output

新 session 完成后应该交付这些:

1. **代码 vs prompt 职责矩阵** — 每个决策点(触发/分类/关闭/没打通/playbook)标清楚谁负责 + 为什么
2. **现状 vs 设计后 workflow 图** — 围绕职责划分画,不是围绕数据存储
3. **architecture recommendation** — 基于上下游理解 + 业界校准,给出推荐的 pipeline 设计方案
4. **gap 分析文档更新** — 把职责划分设计写回 `task-lifecycle-gap-analysis.md` 最上面
5. **需要改的代码/prompt 清单** — 具体到文件和改动方向(不是行号级,是设计级)
6. **API-first / AI-agent-readable 视角** — 反向从未来 API / CLI / OAuth / AI agent 调用方需要什么数据来验证 schema 和 workflow 设计,说明 task / progress / timeline 应该怎么被外部读取和写入

> 不是写代码。是设计 + Max review 后才执行。
>
> **呈现要求**: 产出必须让不在这个 session 里的人(Vivian / Oliver / Peter)也能10分钟看懂核心结论。具体:每个交付物先用一句话说结论,再展开细节;用表格和图而不是长段落;技术细节不省略但要有层次(先 what + why,想看 how 再往下读)。不要 over-simplify(丢掉关键 nuance),也不要绕来绕去(读完不知道在说什么)。

### Design Acceptance Criteria

设计合格的标准(不满足就不算完成):

- 必须回答:**task 到底只是待办清单(还没做的事),还是也兼做业绩记录(当场做成的事也要记),还是一个统一的事项对象(两者都能表达)**。不能含糊
- 每个"谁负责"的 recommendation 必须说明:**为什么不是放在另一层做**
- 必须覆盖至少这些关键场景:lead no answer / intro booked / cancel saved / complaint resolved / DNC / inbound 当场成交 / SMS meaningful reply / 跨门店同号码
- 必须区分**Phase 1 必做**和 **future-compatible 设计**(现在不做但架构要兼容的),不要混在一起

### Non-goals (这次设计明确不做的)

- ❌ 不设计完整 SMS pipeline — 只定义 task pipeline 预留给 SMS 的接口和触发点
- ❌ 不重做 dashboard 指标体系 — 只定义 task lifecycle 对 metrics 的影响
- ❌ 不设计 AI voice agent 产品 — 只确保 executorType / actor / confidence 等字段能兼容未来 AI 接管
- ❌ 不做 production rollout 方案
- ❌ 不改代码、不跑写入型 DB 操作、不 push、不 PR

### 必须显式回答的冲突问题

brief 里有几组方向天然有张力。**不要默认调和,每个都逐一给出明确结论 + 理由:**

1. "每个当场办成的事都是 task" vs "业界通常 conversion funnel 不是 completed task" — 兼有可行吗?怎么兼有?
2. "只提醒一次" vs "没打通还要回头再试" — 提醒一次是指"不重复建 task"还是"真的只打一次"?
3. "AI 判断更灵活 / long term scale" vs "代码状态机必须 deterministic" — 哪些判断给 AI 哪些给代码,边界在哪?
4. "SMS 不想触发 AI" vs "有意义 SMS 可能需要即时跟进" — 怎么定义"有意义"?
5. "task 是待办" vs "task 是业绩记录" — 一个对象能同时承担两个语义吗?会不会污染其中一个?
6. activity(打了电话) vs task progress(联系到了) vs business outcome(签约了) — 这三层是不是不同的概念,该不该压在同一个 task 对象上?

***

## 怎么做

### Step 1: 先理解整个系统的上下游

**不要直接看 task。** 先读 architecture 文档,理解:

- 一通电话从进来到最终产生业务结果,整条链怎么走
- 数据从 RingCentral → 转录 → AI 分析 → 写入各表 → 前端展示,每一步谁做的
- task 在这条链里处于什么位置,它的上游(谁触发它)和下游(谁消费它)是什么
- **环境区分**: test 环境和 prod 环境不同。test 环境做了全面改造 (DynamoDB → Neon 等),prod 很多功能还没有。**以 test 环境为准**。

所有代码都在本地 `/Users/maxwsy/workspace/retaintive.code-workspace`,先读代码再读文档。参考:

- `docs/architecture/0-system-overview.md` — 系统全景
- `docs/architecture/2-backend.md` — 后端数据管道(含通话分析)
- `docs/team-ops/repo-overview.md` — 所有 repo 职责 + 技术栈
- `callytics-infrastructure/lambda/ai-analysis-processor/src/core/stages/pipeline.ts` — per-call AI pipeline 编排(Pre-triage → Triage → Classify → Coaching)
- `callytics-infrastructure/lambda/contacts-analyzer/src/core/prompt-builder.ts` — contact analysis prompt(1040 行,SECTION 4 是 task 决策逻辑)

### Step 2: 从全局判断 task 的角色

理解了上下游之后,回答:

- task 在这个系统里到底是什么?是”待办清单”还是”业绩记录”还是两者兼有?Max 的初步构思:两者兼有——既是待办清单,也能直接 mark 成完成(比如一通电话当场完成就直接标 closed)成为业绩记录。**这个想法不一定对,建议 web search 看 competitors 怎么做,验证后再定。**
- 现在 task 的生成/关闭逻辑,放在系统的哪个环节是合理的?当前放置的位置对不对,还是应该重新设计?**从正确性出发,不要因为现在是这样就继续这样走。** 都在 test 环境,什么都可以改,有 AI 辅助改起来快。
- prompt 和代码各自的能力边界在哪——哪些判断只有 AI 能做(需要理解通话内容),哪些是确定性的规则(代码就能做)?**设计要 long term 能 scale**:硬编码确定性规则以后改起来复杂。AI 时代要考虑 AI 的 capability(可以搜最新的),未来可能用 AI agent。design 要能 long term scale,不要设计成只适合当下。

### Step 3: 设计代码 vs prompt 的职责划分

这是核心交付。要回答的具体问题:

| 决策                                 | 该谁负责 | 为什么 | 现状怎么做的 |
| ---------------------------------- | ---- | --- | ------ |
| 要不要触发 task 流程                      | ?    |     |        |
| 建什么类型的 task                        | ?    |     |        |
| 当场完成建不建 task                       | ?    |     |        |
| 没打通怎么处理                            | ?    |     |        |
| task 的 priority / suggestedActions | ?    |     |        |
| 什么时候关闭 task                        | ?    |     |        |
| Playbook (员工执行指南)                  | ?    |     |        |

现状的问题:代码和 prompt 的职责混在一起。比如 `close.ts:199` 用代码硬编码了"没打通 → 关掉重建",但这个判断可能该由 AI 做;prompt 又硬规则禁止了"当场完成建 task",但这可能是产品规则该在代码层控制。**这条线要重新划。**

### Step 4: 画 pipeline workflow 图

画出来的图应该围绕**代码 vs prompt 的职责划分**,不是围绕"数据存哪个表"。每个节点标清楚:这一步是代码控制还是 prompt 控制。

画两张:现状(代码和 prompt 混着来)vs 设计后(职责清晰)。

### Step 5: 从 API / AI agent 视角反推数据模型

除了给前端页面用,task pipeline 最终也要能被外部系统和 AI agent 可靠调用。设计时要从 API contract 反向验证数据模型:

- 未来可能会有 OAuth API、CLI、第三方集成、AI agent(Codex / Claude Code / customer-owned agent)读取或操作 task。
- 不要只问"数据库怎么存",还要问"外部调用方怎么一眼读懂这个 task 现在是什么状态、尝试过几次、下一步该做什么、最终结果是什么"。
- 需要明确 `tasks` / `task progress` / `contact_timeline` 各自的职责:
  - `tasks`: 当前业务事项对象和最终 outcome
  - task progress / attempt: 每次执行进展(no answer / voicemail / text sent / callback requested 等)
  - `contact_timeline`: contact 维度统一时间线和审计
- 如果建议新增 `task_progress_events` 或类似结构,必须说明它和 `contact_timeline` 的关系:谁是 source of truth,谁是 projection / audit feed,发生一次 progress update 时两边怎么写。
- 需要草拟 high-level API shape,例如:
  - `GET /tasks/:taskId` 返回 task snapshot
  - `GET /tasks/:taskId/progress` 返回 task progress history
  - `POST /tasks/:taskId/progress` 记录 no-answer / voicemail / text-sent / callback 等进展
  - `POST /tasks/:taskId/close` 只记录 business outcome
  - `GET /contacts/:contactId/timeline` 返回跨实体时间线
  - `GET /contacts/:contactId/work-objects` 给 AI agent 一次性读取 open/closed objectives + recent progress + next action context
- 对比竞品 API / object model 时,要查官方 API 文档或产品文档,看 HubSpot / Salesforce / Salesloft / Outreach / Mindbody / ABC 等怎么表达 task、activity、call disposition、timeline、outcome。
- 竞品只是校准,不是答案。很多旧 CRM/API 设计来自 AI 不成熟、人工录入、LLM 成本高的时代。要识别他们的历史包袱,再决定 retaintive 在 2026 AI-native 场景下应该怎么做得更清晰。

### Step 6: 更新 gap 分析文档

把设计结论写回 `docs/product-design/v2/tasks-feature/task-lifecycle-gap-analysis.md`。这份文档已有 schema 对照、场景覆盖度、业界对比——需要在最上面加上"代码 vs prompt 职责"这个维度的设计。

***

## 思考方式

**像一个懂 AI 的 principal engineer 那样思考。** 不是在修一个现有系统的 bug,是在设计一个 AI + 代码混合的架构。要考虑:

- **AI 和代码各自擅长什么**:AI 擅长理解语义/判断意图/处理模糊情况;代码擅长执行确定性规则/保证幂等/控制状态机。把对的事交给对的层。
- **上下游协调**:改了 task pipeline 的某个环节,对上游(per-call AI / lead-tracking)和下游(前端展示 / dashboard 指标 / 未来 AI 化)有什么影响?
- **成本**:每次调 AI 有 LLM 成本。什么时候值得花钱调 AI 判断,什么时候用代码规则就够了?
- **未来 AI 化**:现在前台手动做的事(打电话/选 close result/写 note),以后可能 AI voice agent 来做。现在的架构要给这个过渡留空间,不要设计成只有人能用。
- **API-first / agent-readable**:未来不只是前端读这些数据,第三方系统、CLI、OAuth API、AI agent 也会读写 task。schema 和 workflow 要能被 API 稳定表达,而不是只适合当前页面或某个 prompt。
- **场景 robust**:不是技术上的健壮,是**符合真实前台使用场景的健壮**——系统行为要对得上前台脑子里"我手头有几件事、办完了没"的心智模型。

***

## 已知的核心问题(前序调研发现的)

不展开,只列要点。细节在材料里。**不要逐个解决这些小问题——做好顶层设计,这些问题会同时被解决。以面破题,不以点破题。**

1. **当场完成 = 零 task**: prompt 禁止当场建 task,但产品需要每个办成的事都记为 task
2. **没打通 = 关掉重建**: 代码硬编码的,前台心智不对齐,task 数虚增
3. **disposition 和 outcome 混在一个字段**: close\_result 18 值混了"打通没"和"办成没",业界全部分开。disposition 其实已经在 calls.callState 里有了
4. **前端 close dropdown 缺 2 个值**: booked/cancelled schema 有但 UI 没有,Neon 里 AI 已写入 29 条
5. **Core Productivity metric 有 bug**: denominator 让 rate 恒≈100%

***

## Max 在前序 session 表达的方向

**这些是他的想法和倾向,不是 finalized spec:**

- 每个当场办成的事都是一个 task(签约/book intro/cancel save/resolve/reschedule)
- 一个任务只提醒一次,不要关掉重建
- 只管打电话 + SMS,不管走进店里的。SMS 还没想好
- 没打通要分情况:lead 更重要
- 店长战绩 = 完成多少 task (superset) → 其中多少签约/挽留 (subset)
- 未来要 AI 化:人做的操作以后 AI 做
- **代码和 prompt 的职责要想清楚再动手**
- 整个 flow 对比应该围绕"代码 vs prompt 职责划分"画,不是围绕"数据存哪"
- **要先从 high level 理解整个系统上下游,再看 task 这一块怎么设计**

***

## 材料清单

> **只有代码是 source of truth。其余都是不同人在不同时间的想法,不一定对。**

### A. 代码 (✅ Source of Truth)

| 文件                                                       | 看什么                                                             |
| -------------------------------------------------------- | --------------------------------------------------------------- |
| `callytics-common/src/db/schema/tasks.ts`                | task 表 27 字段 + close\_result 18 值 + CHECK 约束                    |
| `callytics-common/src/db/schema/task-ui.ts`              | CLOSE\_RESULT\_OPTIONS 16 项 + TYPE\_CATEGORY\_OPTIONS 9 项       |
| `callytics-common/src/db/schema/calls.ts`                | callState (disposition) + primaryOutcomeResult + followUpNeeded |
| `callytics-common/src/db/schema/contacts.ts`             | lifecycleStage / leadStatus / doNotContact / actionNeeded       |
| `callytics-common/src/db/schema/contact-timeline.ts`     | 16 种事件,多态 actor,AI forensic 字段                                  |
| `callytics-common/src/db/schema/playbook-feedback.ts`    | helpful / not\_relevant                                         |
| `callytics-infrastructure/.../prompt-builder.ts`         | contact analysis prompt (1040 行) — SECTION 4 是 task 决策逻辑        |
| `callytics-infrastructure/.../models.ts:155-184`         | AI 决策 Zod: create / close / update (无 create-as-closed)         |
| `callytics-infrastructure/.../neon-repository.ts:702`    | create 硬编码 status='pending'                                     |
| `callytics-infrastructure/.../stages/pipeline.ts`        | per-call AI pipeline 编排                                         |
| `callytics-infrastructure/.../stages/prompts.ts`         | per-call 3 个 system prompt                                      |
| `lead-tracking/src/neon-repository.ts:180-204`           | lead\_outreach 建 task 逻辑                                        |
| `studio-website-monorepo/.../tasks/close.ts:199-218`     | 员工关闭 + no\_answer/left\_voicemail 自动重建                          |
| `studio-website-monorepo/.../dashboard-staff.ts:113-172` | Core Productivity SQL + denominator bug                         |

### B. 架构文档 (读了再开始设计)

| 文件                                       | 看什么              |
| ---------------------------------------- | ---------------- |
| `docs/architecture/0-system-overview.md` | 系统全景             |
| `docs/architecture/2-backend.md`         | 后端数据管道(含通话分析上下游) |
| `docs/team-ops/repo-overview.md`         | 所有 repo 职责       |

### C. V1 Task Feature 设计文档 (⚠️ 初版设计,不一定错但不够全,现在要改进)

V1 是最初怎么设计 task feature 的思路。**不一定错,可能只是不够完整,现在要做更全面的改进。** 读它可以理解最初的设计意图。

| 文件                    | 看什么                        | 路径                                                              |
| --------------------- | -------------------------- | --------------------------------------------------------------- |
| Tasks Overview        | 功能总览 + 定位                  | `docs/product-design/v1/tasks-feature/tasks-overview.md`        |
| Tasks Spec            | 完整规格                       | `docs/product-design/v1/tasks-feature/tasks-spec.md`            |
| Task 字段设计             | 字段定义 + 设计决策                | `docs/product-design/v1/tasks-feature/tasks-field-design.md`    |
| Task 生命周期             | 生成/更新/关闭机制                 | `docs/product-design/v1/tasks-feature/task-lifecycle.md`        |
| Task 生命周期 (Prompt 视角) | prompt 怎么控制 task           | `docs/product-design/v1/tasks-feature/prompt-task-lifecycle.md` |
| Task 与营收归因            | close\_result → revenue 映射 | `docs/product-design/v1/tasks-feature/revenue-attribution.md`   |

### D. V2 Task Feature 设计文档 (⚠️ 现版本,schema 对齐后的)

| 文件        | 看什么                                     | 路径                                                            |
| --------- | --------------------------------------- | ------------------------------------------------------------- |
| Task 字段字典 | 27 字段定义 (对齐 schema)                     | `docs/product-design/v2/tasks-feature/tasks-fields.md`        |
| Task 枚举清单 | close\_result 18 值 / typeCategory 9 值 等 | `docs/product-design/v2/tasks-feature/task-enums.md`          |
| Task 业务规则 | SLA / 优先级窗口 / 营收归因                      | `docs/product-design/v2/tasks-feature/task-business-rules.md` |
| Task 计算配置 | 状态计算 / dueAt 公式 / playbook 数据源          | `docs/product-design/v2/tasks-feature/tasks-calculations.md`  |
| Task 页面展示 | 前端 UI 设计 + schema 支持状态                  | `docs/product-design/v2/tasks-feature/tasks-display.md`       |

### E. 调研产出 (⚠️ AI 产出,Max review 中)

| 文件                                                                    | 看什么                                          |
| --------------------------------------------------------------------- | -------------------------------------------- |
| `docs/product-design/v2/tasks-feature/task-lifecycle-gap-analysis.md` | 现状 vs ideal 对比 + schema 对照 + 16 场景覆盖度 + 业界对比 |

### F. 参考材料 (⚠️ 不一定对,当参考不当结论)

| 文件                                                                                    | 来源                      | 说明                                                 |
| ------------------------------------------------------------------------------------- | ----------------------- | -------------------------------------------------- |
| `~/Downloads/retaintive-contact-task-workflow.html`                                   | **来源未确认**(可能是 AI 或队友)   | task workflow 设计图,9 section。**Max 明确说这是别人写的,不一定对** |
| `~/Downloads/05-task-playbook-system-prompt.txt`                                      | Oliver V1 草稿            | 第 5 个 prompt,13 scenario。初稿,需和最终设计对齐               |
| `~/Downloads/retaintive-mvp-v31-prototype.html`                                       | Oliver                  | UI 原型,讨论用                                          |
| `~/Downloads/ui-prototype-mvp-v3(1).html`                                             | Vivian                  | 旧版原型                                               |
| `prompt-eval/expected_results.json`                                                   | 团队测试                    | 13 TC,全无 taskDecisions 预期                          |
| 飞书会议纪要 [link](https://ljprwpnmsg2d.jp.larksuite.com/docx/TuwWdaSAnobk1oxsZsvjvpjypVb) | Max+Vivian+Oliver+Peter | 2026-05-27/28 两场会议共识,不是 spec                       |

### G. Neon Test 环境 (✅ 可查真实数据)

- Project: `callytics-test` (restless-boat-70724564, us-west-2)
- 用 Neon MCP 跑 SELECT 验证假设,不写入

### H. AWS (✅ 已登录)

- Account: 237206024479, AdminAccess role
- 可看 Lambda / CloudWatch,用于验证 prompt 实际输出

***

### I. 前序调研成果 — 分三类: Facts / Hypotheses / Calibration

前一个 session 做了大量调研。**这些是校准用的,不是替代你自己思考的答案。** 按可信度分成三类:

#### Facts (已用代码/数据验证,可直接信)

| 事实                                                                                                  | 验证方式                                         |
| --------------------------------------------------------------------------------------------------- | -------------------------------------------- |
| task 创建只能产 `status='pending'`,没有 create-as-closed 路径                                                | 读 `neon-repository.ts:702` + `models.ts:180` |
| close\_result 18 值里混了 3 个 disposition (`no_answer`/`left_voicemail`/`callback_later`)               | 读 `tasks.ts:38-54`                           |
| disposition 已经在 `calls.callState` 里有了 (human\_conversation/voicemail/no\_answer/busy\_signal)       | 读 `calls.ts:154`                             |
| `CLOSE_RESULT_OPTIONS` (UI) 只有 16 项,缺 `booked`/`cancelled`                                          | 读 `task-ui.ts:20-37`                         |
| Neon test: `booked` 已写入 25 条、`cancelled` 4 条,AI 在用但前端选不到                                            | Neon SELECT                                  |
| Neon test: 616 closed task 全是 `auto_closed`, `manual_closed`=0, `closedByStaffName` 全是 "system"     | Neon SELECT                                  |
| prompt-eval 13 TC 全不包含 `taskDecisions` 预期——task AI 行为尚无测试覆盖                                         | 读 `expected_results.json`                    |
| `close.ts:199` 硬编码 no\_answer → 关旧 task + INSERT 新 task (due 1天后)                                   | 读 `close.ts:199-218`                         |
| `dashboard-staff.ts:121` 的 `WHERE closed_by_staff_name IS NOT NULL` 吞掉所有 pending task → rate 恒≈100% | 读代码 + Neon 验证                                |
| lead-tracking 建 task: 固定 pending/high/5min SLA, `onConflictDoNothing` 幂等                            | 读 `lead-tracking/neon-repository.ts:180-204` |

#### Hypotheses (前序 session 的推断,需要你验证后才能采纳)

| 假设                                                                 | 来源             | 需要验证什么                                                  |
| ------------------------------------------------------------------ | -------------- | ------------------------------------------------------- |
| task 表只需新增 3 个字段 (attemptCount / executorType / closeResultReason) | AI 调研结论        | 新 system design 可能发现需要更多或更少                             |
| close\_result 应移出 3 个 disposition,加 `rescheduled`                  | AI 调研 + Max 倾向 | 取决于职责划分设计——如果 prompt 管 disposition,可能不需要改 close\_result |
| closeType 应加 `create_closed`,models.ts 应加 `create-as-closed` 决策类型  | AI 调研结论        | 取决于"当场完成"的设计——可能有更好的方案                                  |
| 没打通应改成"同 task + attempt 计数",不关闭                                    | 业界对比推断         | 取决于代码 vs prompt 职责划分——也许 prompt 判断比代码规则更灵活              |

#### Calibration (业界校准,不是答案,是参考坐标系)

> **web search 是校准用的,不替代系统设计结论。最终判断必须回到 retaintive 的前台心智、数据模型和 pipeline 成本。**

| 校准点                    | 业界怎么做                                                             | 来源                    |
| ---------------------- | ----------------------------------------------------------------- | --------------------- |
| disposition vs outcome | Salesforce / Salesloft 分成两个独立字段                                   | PhoneIQ · Salesloft   |
| 没打通怎么处理                | 呼叫中心用 Task ID 更新原 task,不关闭重建                                      | Sprinklr · Outreach   |
| 当场成交怎么计                | 计入 conversion funnel,不是 completed task (但 retaintive 想兼有,需要验证可行性) | Convoso · Mariana Tek |
| 短通话省 AI 成本             | Gong 的 minimum duration gate                                      | Gong                  |
| AI + 代码混合架构            | Temporal 状态机 + LangGraph agentic workflow + human-in-the-loop 模式  | arXiv · Google Cloud  |
| 健身房 CRM 怎么做            | Mindbody / ABC / Glofox / PushPress 的 task/follow-up 定义           | 各官网                   |

\| SMS 触发 AI 的成本控制 | 业界三层 gate: content gate (regex) → batch gate (debounce) → token-tier gate (小 classifier)。但**注意:业界 2024 年的做法基于当时 LLM 贵 + 慢的限制,2026 年成本降了 10-50x、小模型 classifier 成熟了(NVIDIA LLM Router 1.75B)。限制变了,解法可能也该变。** 设计时要重新思考:SMS 中什么样的内容值得触发分析,而不是照搬"SMS 一律不触发" | Twilio CI · NVIDIA LLM Router · MindStudio |
\| SMS vs Call 合流分析 | 业界写到同一条 contact record,但触发时机不同。**同样要考虑:这个做法可能只是当时技术限制下的妥协,不是最优解。** 设计时问:如果成本不是问题,理想的 SMS 分析策略是什么?然后再把成本约束加回来做 trade-off | Twilio · Aloware · RingCentral |
\| SMS debounce | AWS 原生 `MaximumBatchingWindowInSeconds` (最长 300 秒),SQS 上设就行 | AWS Lambda batching · n8n |

详细内容在 gap 分析文档的"业界怎么做"段。

***

## 前序 session 发现的关键事实(设计时要知道的)

这些不是"要修的 bug 清单",而是你做 system design 时的**输入事实**——你需要知道系统实际上怎么运作的,才能设计对。

**现有 prompt pipeline 怎么触发 task:**

- per-call AI (Layer 1) 分析每通电话,产出 `fu=yes/no` (follow-up needed) + `out=success/attempted/...` (outcome)
- contact analysis (Layer 2, daily batch) 消费 Layer 1 的输出,做跨通话的 contact 级别分析,产出 `taskDecisions[]` (create/close/update)
- `fu=no` + `out=success` 的组合在当前 prompt 里 = 不建 task (prompt-builder.ts:812, 611-617)
- 这个 `fu=` 信号是 AI 对 AI 的传递——Layer 1 的 AI 告诉 Layer 2 的 AI "要不要跟进"

> 2026-05-31 note: 这里的 Layer 1 / Layer 2 是旧 task 讨论里对 AI signal chain 的叫法，不等同于 [Unified Pipeline Architecture 设计 Brief](/product-design/v2/unified-pipeline/research/unified-pipeline-design-brief.md) 里的 Layer 1 Shared Mutation / Layer 2 Processing Capability。

**task 创建只有 3 条路径:**

1. lead-tracking 直接建 (lead\_outreach, 不经 AI)
2. contact analysis AI 建 (taskDecisions\[].create)
3. 员工手动建 (studio-api)

- 所有路径都只产 status='pending'。没有"一步建成 closed"的路径

**task 关闭有 2 条路径:**

1. AI auto-close (contact analysis 的 taskDecisions\[].close,必须引用已有 taskId)
2. 员工 manual-close (studio-api close.ts)

- 但 Neon 实测: manual-close 在 test 环境从未被使用过 (0 条)

**没打通的硬编码逻辑 (close.ts:199-218):**

- 这段代码不在 prompt 里,是纯代码逻辑
- 员工在前端选 no\_answer → 代码关掉旧 task + 自动 INSERT 一个新 pending task (due 明天)
- left\_voicemail → 同上,due 2 天后
- 用了 `ON CONFLICT DO NOTHING` 防重复

**前台实际怎么看 task:**

- tasks 页面 3 段式 flow: Why (为什么有这个 task) → Playbook (怎么做) → Action (Update / Close)
- Update (no answer / voicemail / text sent) 和 Close (converted / not interested / ...) 在 UI 上想分开,但当前后端没有真正的 "status update" 动作——只有 close
- playbook-panel.vue (223 行) 前端已有,但后端 playbook prompt 没接入

**disposition 数据已经在 calls 表里:**

- `calls.callState` = human\_conversation / voicemail / no\_answer / busy\_signal / system\_error
- `calls.result` = Accepted / Missed / No Answer / Busy / Voicemail (RingCentral 原始值)
- `calls.primaryOutcomeResult` = success / attempted / retained / pending\_follow\_up / cancelled / na
- `calls.followUpNeeded` + `calls.followUpReasons` = AI 判断的 follow-up 信号
- 这些都是 per-call 的,已经有了,不需要在 task 表重复存

**contact\_timeline 的设计:**

- 16 种事件类型,覆盖 task 全生命周期 (task.created / task.status\_changed / task.updated / task.due\_at\_changed / task.note\_updated)
- 多态 actor (system / call\_analysis / contact\_analysis / staff / lead\_webhook)
- AI forensic 字段 (aiRunId / aiModelUsed / aiConfidence) — 可追溯 AI 为什么做了这个决策
- 有 entityType + entityId 索引,查某个 task 的事件历史很快

***

## 补充维度(设计时别漏)

### 多门店 / store 级隔离

task 的幂等约束 `uq_tasks_pending_contact_category` 按 `(contactPhone, storeId, typeCategory)` 做——同一个客人在不同门店可以有独立的 pending task。contacts 表主键也是 `(phone, storeId)`。设计 pipeline 时必须考虑:同一个电话号码跨门店的 task 是独立的,不能共享。

### 前台一天的实际操作流程(场景 robust 的基础)

设计必须对得上前台真实的工作方式,不能只看代码:

1. **早上开工**: 打开系统看待办清单——"今天有哪些客人要跟进"(新 lead 要联系、有人要取消会籍要挽留、有人试课完没签约要追)。每件事有紧迫度(dueAt)。
2. **白天逐个处理**: 挑一件 → 打电话/发短信 → 几种结果:
   - 打通了,当场办成了(签约/约到试课/挽留住/解决了投诉)→ 一件事了结
   - 打通了,没当场办成(客人要考虑/要改时间再打)→ 还没完,记下进展回头来
   - 没打通(没人接/留语音信箱)→ 也没完,回头再试
   - 客人说别再打了(DNC)→ 结束(但不是办成)
3. **当场来的**: 客户直接打进来或走进店里,当场就把事办了(当场签约)——这没经过"待办清单"但是实打实的业绩
4. **一天结束 / 店长视角**: 想知道"今天战绩如何"——完成了几件事、其中几个签约/挽留(superset/subset)

### 未来 AI agent 的操作流程(设计要兼容)

现在人做的操作以后 AI voice agent 来做。设计时要考虑:

- AI agent 自动外呼 → 自动判断对话结果 → 自动关闭/更新 task
- 需要区分"人做的"和"AI 做的"(executorType)
- 低置信度的 AI 决策需要人工复核(human-in-the-loop)
- 现在人选的 close\_result / 写的 note 是未来训练 AI 的 ground truth

### SMS 处理方式

**现状**: message-processor Lambda 只做存储(RC webhook → Neon),**不触发 AI 分析**。SMS 消息存入后,等 contacts-analyzer 的下一次 batch run(daily cron 06:00 UTC 或 per-call 触发)才被读到(作为 `RECENT MESSAGES` 注入 prompt)。

**Max 的顾虑**: 不想让 SMS 不停 trigger AI scan——一条 "thanks" 不值得花 LLM 成本分析。当前设计通过"不直接触发"解决了成本问题,但引入了 delay(SMS 到了要等 batch run 才分析)。

**设计时要思考**:

- 当前"被动等 batch"的方式够不够?还是需要"有意义的 SMS 才触发即时分析"?
- 如果要即时分析:怎么区分"有意义"(客户回复了有实质内容)vs"无价值"(thanks / ok / emoji / 自动回复)?
- 有没有 debounce 机制(5 分钟内多条合并)?
- 业界 2026 怎么做?small model 做前置过滤?

**更深层的设计问题**: 当前 SMS 和 Call 都汇入同一个 contact analysis(Layer 2)再统一决定 task。这个"先合流再决策"的模式对不对?Call 和 SMS 的信号密度完全不同(一通 5 分钟的电话 vs 一条 "thanks"),但现在走同一个 1040 行的 prompt + 同样的 LLM 成本。是不是应该 call 和 SMS 各自有不同的判断路径/不同的触发条件?competitors 怎么处理多渠道合流?

> **注意**: SMS 还没有完全想清楚,先 focus 电话。但 pipeline 设计要给 SMS 留位置,不能设计成只支持电话。

### API / CLI / AI agent 可读性

这次设计还必须考虑未来对外或内部 API 的形状。Retaintive 以后可能让第三方系统、CLI、客户自己的 AI agent、或 Codex / Claude Code 这样的 agent 通过 OAuth/API 读取和操作 task。

设计时要显式回答:

- 一个外部调用方如何区分:
  - task 当前生命周期状态(`pending` / `closed`)
  - task 执行进展(`no_answer` / `left_voicemail` / `text_sent` / `callback_requested`)
  - 最终业务结果(`converted` / `booked` / `cancel_saved` / `issue_resolved` / `do_not_contact`)
- 如果有 task progress / attempt 事件,它们和 `contact_timeline` 怎么同步:
  - 是否需要独立 source-of-truth 表(如 `task_progress_events`)
  - `contact_timeline` 是否作为 projection / audit feed
  - 同一次 progress update 是否应在一个 transaction 里同时写 progress event、timeline event、task snapshot
- API 返回应该是给机器可读的结构化对象,而不是要求调用方解析 timeline JSONB 或 prompt 文本。
- 竞品 API 的做法只能作为校准:旧 CRM 常把 activity/task/call disposition 混在一起,那可能是历史限制,不一定是 AI-native 系统的最佳设计。

***

## 设计时要考虑到(high-level,不需要写具体实现)

- **AI 判断失败时的 fallback 策略** — prompt 返回无法解析的结果 / Lambda timeout / Zod 校验不过,代码怎么兜底?这是代码层的核心职责之一
- **contacts-analyzer 有 6 个触发路径** — EventBridge cron / on-demand / P1 followUp / Task close / T5 showed / T6 trialed。设计 pipeline 时要覆盖所有入口,不能只改一条路径
- **业界做法是参考不是圣经** — 2026 年的技术限制和 2024 年不同(LLM 成本降 10-50x、小模型 classifier 成熟、边缘推理变快)。不要因为"Twilio 这么做"就照搬,要思考他们当时的限制是什么、现在还在不在、有没有更好的方式
- **并发 / 幂等 / race condition** — 这个系统有多条触发路径同时跑:daily batch 和 per-call 可能同时分析同一个 contact;lead-tracking 建 task 的同时 AI 也想建;员工在前端 close 的同时 AI batch 也在 auto-close。设计要说明这些并发场景怎么处理
- **API contract / data access pattern** — 设计要说明核心读写路径:task list 怎么快读当前状态、task detail 怎么读 progress history、contact detail 怎么读 timeline、manager metrics 怎么聚合 attempts vs completed objectives、external API/AI agent 怎么读懂同一个事项。
- **设计边界:如果需要改,什么都可以改** — per-call pipeline / contact analysis / schema / prompt / 前端,都在 scope 内。这是 test 环境,没有"不能碰"的东西

## 约束

- **先理解全局再看局部** — 不要直接钻进 task 字段,先把系统上下游走通
- **先设计再写代码** — 画图、确认逻辑、Max review 之后才动手
- **Code as source of truth** — 每个结论先读代码验证,不信文档 narrative
- **不自动 push/PR** — 改完先给 Max review
- **不要以点破题,以面破题** — 不要逐个修小问题,要做好顶层设计让问题自然消解
- **从正确性出发** — 不要因为现在是这样就继续这样走,test 环境什么都可以改
- **保持 high-level** — 这是 system design,不是 code review。提"要考虑 error handling / logging",不写具体加在哪行
