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

# Task Pipeline Architecture Addendum

> **Historical design input（2026-07-23 校准）**：本文保留 2026-05 的问题发现和 Task Orchestrator 思路，但不是现行 implementation specification。当前 Task V2 parity 和 Task V2+ 工程路线见 [工程审计与实施基线](/product-design/v2/tasks-feature/task-v2-plus-engineering-audit.md)；V3 proposal 不能自动覆盖本文记录的 V2 行为。
>
> **日期**: 2026-05-31\
> **用途**: 对 [Task Pipeline 设计产出](/product-design/v2/tasks-feature/design/task-pipeline-deliverable-codex.md) 的补充说明。\
> **背景**: 2026-05-30 的 task pipeline 设计方向基本成立；2026-05-31 做了全系统 pipeline 调研后，需要把 task 放回 `contacts / calls / messages / leads / contact_timeline / future AI tools` 的整体架构里看。

***

## 结论

Task V2 的主方向没有问题，但它不能作为一个孤立 feature 落地。

应该保留的核心判断：

- Task 是 actual work object。
- Task lifecycle 应该是 `open / closed`，当前 DB `pending / closed` 可作为 implementation mapping。
- `no_answer`、`left_voicemail`、`callback_later` 这类值是 progress，不是 final outcome。
- AI 可以提出 task action proposal，但状态转换、幂等、权限、DNC、audit 必须由 code 执行。
- Task Orchestrator 是必要的。

需要补强的地方：

**Task Orchestrator 不是 task feature 内部的小 helper，而是 unified pipeline architecture 里的 shared mutation module。**

也就是说，它应该服务：

- `contacts-analyzer`
- `lead-processor`
- `studio-api`
- SMS meaningful reply flow
- retry / reprocess / onboarding backfill
- future AI agent / tool calling

***

## Task V2 和 Unified Pipeline 的关系

### 旧理解

```text
Task Pipeline Design
  -> Task Orchestrator
  -> tasks / task_progress_events / contact_timeline
```

### 现在应该升级为

```text
Unified Pipeline Architecture
  -> Shared Mutation Layer
      -> Task Orchestrator
      -> Contact Writer
      -> Timeline Writer
      -> Policy Guard
```

Task Orchestrator 是 shared mutation layer 的一部分，不是单独为 Tasks 页面服务的后端逻辑。

***

## Task V2 需要修正/强调的点

### 1. `task_progress_events` 和 `contact_timeline` 的关系

Task deliverable 里说 `task_progress_events` 是 progress source of truth，这个判断仍然成立。

需要更明确：

| 表                      | 职责                                  |
| ---------------------- | ----------------------------------- |
| `task_progress_events` | task-level progress source of truth |
| `contact_timeline`     | contact-level audit/feed projection |

它们可以同时写，但不能互相替代。

原因：

- `contact_timeline` 是用户可见的 contact feed。
- task detail / attempt count / retry history 更适合从 task-level events 重建。
- 现在 `tasks/list.ts` 用 closed sibling tasks 推 `attempt_count`，这是当前 schema 不足的表现。

### 2. `closeResult` 的 current state 和 target state 要分开写

当前代码事实：

`TASK_CLOSE_RESULT` 有 18 个值，其中包括 progress-like 值：

- `attempted`
- `no_answer`
- `left_voicemail`
- `callback_later`

Target architecture：

- 这些值不应该继续作为 final outcome 使用。
- 新 API 应该用 `record_progress` 表达。
- 旧 API / 旧数据可以 compatibility 保留一段时间。

因此 `task-enums.md` 应继续记录 current code truth；task design doc 负责说明 target semantics。

### 3. `contacts.actionNeeded` 和 `tasks.actionNeeded` 要定义 source of truth

调研后更明确：

```text
tasks = actual work object source of truth
contacts.actionNeeded / suggestedActions = contact-level summary or compatibility projection
```

否则 contacts-analyzer prompt 会同时生成 contact-level action 和 task-level action，长期会让 UI/API 不知道谁说了算。

Task V2 应该显式要求：

- 任何需要前台执行的 human work 都必须变成 task。
- contact-level action 只用于 summary / ranking / legacy compatibility。
- 后续设计要决定是否 deprecate contact-level action fields。

### 4. Task Orchestrator 应该接受 code-only action

不要把 Task Orchestrator 理解成“AI taskDecisions 的执行器”。

它也应该处理 deterministic action：

| 来源              | 示例                                                    |
| --------------- | ----------------------------------------------------- |
| lead-processor  | create `lead_outreach` task                           |
| studio-api      | staff close / record progress                         |
| SMS STOP        | DNC cascade close                                     |
| retry/backfill  | idempotent re-application                             |
| future tool API | `create_task` / `record_task_progress` / `close_task` |

也就是说：

```text
AI proposal is one caller.
Code/system/manual actions are also callers.
```

### 5. Studio API close behavior 是 Phase 1 必查点

当前 `PATCH /v2/tasks/close` 在 `closeResult = no_answer / left_voicemail` 时：

1. close 当前 task。
2. 自动创建一个 follow-up task。

这和 Task V2 target model 冲突。

Target:

```text
No Answer / Left Voicemail -> record_progress
Task remains open
dueAt may be updated
attemptCount increments from progress events
```

这个不一定第一步就改代码，但 Phase 1 design 必须把 API contract 改清楚。

### 6. Lead retry / backfill 必须走同一个 task contract

lead happy path 通过 `LeadCreated` event 创建 contact/task/timeline 是合理的。

但 retry/backfill path 不能只补 `leads`，漏掉 downstream task。

Task Orchestrator 的价值之一就是让这些入口可以 idempotently 调同一套 task creation contract。

***

## Phase 1 推荐顺序

### Phase 1A: Task Orchestrator contract

先不急着改所有代码，先把 contract 写清楚：

```ts
applyTaskAction({
  action: 'create' | 'update' | 'close' | 'record_progress',
  identity,
  actor,
  payload,
  idempotencyKey,
})
```

必须定义：

- `identity`: `contactPhone + storeId + franchiseId + accountId`
- `actor`: `staff | contact_analysis | lead_webhook | system | ai_agent`
- `action`: mutation type
- `payload`: typed per action
- `idempotencyKey`: retry/backfill/tool safety
- side effects: `tasks` + `task_progress_events` + `contact_timeline`

### Phase 1B: Progress vs close API

定义两个不同 API：

```text
POST /tasks/{taskId}/progress
POST /tasks/{taskId}/close
```

不要再用 close API 承担 progress update。

### Phase 1C: contacts-analyzer prompt output cleanup

当前 `taskDecisions[]` 只有：

- `create`
- `update`
- `close`

Target 应该补：

- `record_progress`
- `create_closed` 或等价 outcome action

但这个要在 Orchestrator contract 定下来之后再改 prompt。

### Phase 1D: timeline projection

每个 task action 都应该生成 contact-level timeline projection，但 source of truth 不一定是 `contact_timeline`。

建议：

```text
task_progress_events -> task detail / attempt count
contact_timeline -> contact feed / audit
```

***

## 文档处理建议

### 保留

| 文档                                      | 处理                           |
| --------------------------------------- | ---------------------------- |
| `../task-pipeline-deliverable-codex.md` | 保留为 task target architecture |
| `task-pipeline-design-brief.md`         | 保留为 task 设计思路来源              |
| `task-enums.md`                         | 保留为 current code enum truth  |

### 新增/使用

| 文档                                                                           | 处理                                       |
| ---------------------------------------------------------------------------- | ---------------------------------------- |
| `task-pipeline-architecture-addendum.md`                                     | 本文件，解释 task V2 如何接入 unified architecture |
| `../../../unified-pipeline/research/unified-pipeline-reference-checklist.md` | 下一轮调研/执行入口                               |
| `../../../unified-pipeline/research/unified-pipeline-research-appendix.md`   | 代码调研结论和 Phase 1 判断                       |

### 不建议现在做

不要直接把 `task-enums.md` 改成 future enum。

原因：

- 它是 current code source-of-truth doc。
- 当前 DB 仍然允许 18 个 `closeResult`。
- 如果在这里直接删/改 progress-like close results，会让工程读者误以为代码已经改了。

正确做法：

```text
Current docs record current code.
Design docs describe target semantics.
Implementation plan tracks migration.
```
