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

# Coaching Schema

> **Source of truth**: `callytics-common/src/db/schema/calls.ts` + `coaching-reviews.ts` + `ai-feedback.ts` (verified 2026-06-15)
> **物理表边界**: AI coaching 内容仍在 `calls` 表；经理处理状态在 `coaching_reviews`；对 AI 内容质量/采纳的反馈在 `ai_feedback(subject_type='coaching')`。
> **Calls 全表**: [../calls-feature/calls-schema.md](/product-design/v2/calls-feature/calls-schema.md)

***

## 1. 表说明

Coaching 有 3 层数据，不要混在一起：

| 层                  | 表 / 字段                                                               | 谁写                                    | 用途                                               |
| ------------------ | -------------------------------------------------------------------- | ------------------------------------- | ------------------------------------------------ |
| AI 内容层             | `calls.practicalCoachingScenario`, `calls.practicalCoachingFeedback` | ai-analysis-processor Coaching prompt | 告诉 manager 这通电话为什么值得辅导、应该怎么教                     |
| Manager workflow 层 | `coaching_reviews`                                                   | studio-api `/v3/coaching-reviews`     | read/unread、active/archived/removed、manager note |
| AI feedback 层      | `ai_feedback(subject_type='coaching')`                               | 前端反馈入口 / studio-api                   | 记录 manager 是否觉得 AI coaching 有用、是否采纳或修正           |

`calls` 内的 4 个 coaching/review 字段拆 2 类:

- **已接线** (AI 真在写,前端真在读): `practicalCoachingScenario` / `practicalCoachingFeedback` — 给前台看的辅导建议
- **已定义未接线** (schema 有列 + 有 index, AI pipeline 零 write, 前端零 read): `reviewCategory` / `reviewReason` — 通话质量评估标签

写入者: **ai (Coaching prompt)** = ai-analysis-processor Stage 3 (Coaching) 调用 AI prompt 后直接写入 calls 表对应 4 列。

Coaching gate (`shouldRunCoaching()`): 必须 `callState === 'human_conversation'` 且 `duration > 30` 秒才跑 AI;否则填占位 sentinel,详见 [coaching-calculations.md](/product-design/v2/coaching-feature/coaching-calculations.md)。

> **覆盖语义 + 反馈叠加**:coaching 是 per-call 一次性产出,仅手动 reprocess 覆盖(罕见)。人工修改不动 calls 原行,而是走统一反应层 `ai_feedback` 的 `corrected` 叠加 —— 设计见 [AI 产出数据架构](/system-design/ai-output-data-architecture.md)。

***

## 2. Schema 全字段

| # | Field                       | Type  | Nullable | Enum / Values                                                                                                                                                   | Writer               | 用途                                                                                       |
| - | --------------------------- | ----- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ---------------------------------------------------------------------------------------- |
| 1 | `practicalCoachingScenario` | text  | NULL     | — (自由文本 + 3 种 sentinel,见 [§6](#6-sentinel-占位值))                                                                                                                 | ai (Coaching prompt) | 一句话标签,命名 AI 识别到的具体辅导场景(如 "Cancellation save attempt missed objection")                   |
| 2 | `practicalCoachingFeedback` | jsonb | NULL     | `{ timestamp, what_was_said, context, what_could_have_been_said, why_recommendation_is_better }` (5 个 string 子字段,见 [§7](#7-practicalcoachingfeedback-jsonb-结构)) | ai (Coaching prompt) | 详细辅导反馈 — 哪个时刻、员工原话、上下文、建议替换话术、为什么更好                                                      |
| 3 | `reviewCategory` ⚠️         | text  | NULL     | `NOT_REQUIRED` \| `EXEMPLARY` \| `FAILURE` \| `CHURN_RISK` \| `MISSED_OPPORTUNITY` \| `ESCALATION` (6 值,见 [§3](#3-reviewcategory-enum-6-values))                | ai (设计意图;**实际未接线**)  | AI 对通话的质量评估标签。schema 已定义 + 有 index `idx_calls_review_category`,但 lambda 零 write、前端零 read |
| 4 | `reviewReason` ⚠️           | text  | NULL     | —                                                                                                                                                               | ai (设计意图;**实际未接线**)  | `reviewCategory ≠ NOT_REQUIRED` 时的说明文本(1-2 句话)                                           |

⚠️ = "schema 占位 + 未接线" — 6 个 reviewCategory 值是设计意图,不是可观察行为。

***

## 3. reviewCategory enum — 6 values

`reviewCategory` 列单独拉出来,每个 value 有含义说明。

| Value                | 含义                                         |
| -------------------- | ------------------------------------------ |
| `NOT_REQUIRED`       | 不需要复盘 — 设计意图 \~90-95% 的通话落在这里(常规通话,无异常无亮点) |
| `EXEMPLARY`          | 标杆通话 — 员工处理得非常好,值得作为培训案例                   |
| `FAILURE`            | 明显失败 — 员工有重大失误(冷漠、错信息、流程错误)                |
| `CHURN_RISK`         | 流失风险 — 客户表达不满 / 取消意图,需经理介入挽留               |
| `MISSED_OPPORTUNITY` | 错失机会 — 客户给了 buying signal 但员工没接住           |
| `ESCALATION`         | 需升级 — 投诉 / 法律风险 / 安全问题,需立刻找经理              |

## 4. `coaching_reviews` workflow 表

`coaching_reviews` 是一通 coaching call 在 manager inbox 里的处理状态。它不存 AI coaching 内容，只用 `(store_id, telephony_session_id)` 对齐 `calls`。

| Field                    | Type        | Nullable | Values                              | 用途                                       |
| ------------------------ | ----------- | -------- | ----------------------------------- | ---------------------------------------- |
| `storeId`                | text        | NOT NULL | —                                   | Store-level isolation key；复合 PK 一半       |
| `telephonySessionId`     | text        | NOT NULL | —                                   | 对应 `calls.telephony_session_id`；复合 PK 一半 |
| `tenantId`               | uuid        | NULL     | —                                   | multitenant V1 预留                        |
| `status`                 | text        | NOT NULL | `active` \| `archived` \| `removed` | Manager inbox 状态                         |
| `statusChangedAt`        | timestamptz | NULL     | —                                   | 状态最后一次变更时间                               |
| `readAt`                 | timestamptz | NULL     | —                                   | NULL 表示 unread                           |
| `note`                   | text        | NULL     | —                                   | 经理复盘备注                                   |
| `updatedBy`              | text        | NULL     | —                                   | 最后操作人 Cognito user id                    |
| `createdAt`, `updatedAt` | timestamptz | NOT NULL | —                                   | 系统时间戳                                    |

## 5. `ai_feedback(subject_type='coaching')`

`ai_feedback` 是产品用户对 AI 内容的反应层。对 coaching 来说，`subject_id = calls.telephony_session_id`。

| Field                                        | Values / 用途                                        |
| -------------------------------------------- | -------------------------------------------------- |
| `subjectType`                                | `coaching`                                         |
| `subjectId`                                  | `telephony_session_id` 文本                          |
| `feedback`                                   | `helpful`, `not_relevant`, `followed`, `corrected` |
| `reason`                                     | 可选原因，尤其适合 `not_relevant`                           |
| `correctedContent`                           | `corrected` 时的人工修正版                                |
| `storeId`, `tenantId`, `userId`, `createdAt` | 隔离、操作人、时间                                          |

***

## 6. Sentinel 占位值

`practicalCoachingScenario` 不只有 AI 自由文本,有 3 种 sentinel 占位,分管道路径:

| Sentinel                                   | 写入路径                                 | 触发条件                                    | 配套 `practicalCoachingFeedback` |
| ------------------------------------------ | ------------------------------------ | --------------------------------------- | ------------------------------ |
| `No coaching — <reason>` (em dash)         | Staged pipeline (`pipeline.ts`,当前活跃) | Gate 没通过 (通话太短 / voicemail / no-answer) | NULL                           |
| `No Coaching Available - <state>` (hyphen) | Legacy path (`models.ts`,历史遗留)       | 同上                                      | NULL                           |
| `No coaching moment identified`            | 两条路径共用                               | Gate 通过 + AI 跑了但判断"这通无值得辅导时刻"           | 5 个子字段全填 `"N/A"`               |

⚠️ 前端 / 运营按字符串识别空 coaching 时要匹配 `No coaching — `(em dash) — 当前活跃路径是 staged pipeline。详细行为见 [coaching-calculations.md](/product-design/v2/coaching-feature/coaching-calculations.md)。

***

## 7. `practicalCoachingFeedback` jsonb 结构

对应 Coaching prompt 输出的 `detailed_feedback_item`:

| 子字段                            | 类型     | 含义                              |
| ------------------------------ | ------ | ------------------------------- |
| `timestamp`                    | string | 辅导时刻的转录时间戳(如 `"01:23"`)         |
| `what_was_said`                | string | 员工当时实际说的话(逐字引用或近似转述)            |
| `context`                      | string | 1-2 句话交代当时情境(客户刚说了什么、利害关系、通话主题) |
| `what_could_have_been_said`    | string | 建议替换话术(写成员工能直接照说的自然句子,不是抽象建议)   |
| `why_recommendation_is_better` | string | 1-2 句话说明为什么这个建议更好(关联销售 / 留存原则)  |

AI 判断无辅导时刻时,5 个子字段全填 `"N/A"`(详见 [§6](#6-sentinel-占位值))。

> V1 `coaching-highlights-spec` 提过的"5 个 SA 维度打分"(Booking Ask / Objection Handling / Retention Technique / Rapport Building / Information Accuracy,各 0-10 分)**当前未实现** — 代码里只有 scenario + feedback(单个最有价值的辅导时刻)。V1 spec 见 [../../v1/coaching-highlights-feature/coaching-highlights-spec.md](/product-design/v1/coaching-highlights-feature/coaching-highlights-spec.md)。

***

## 8. Prompt Output ↔ Schema 字段对照(给 reviewer 用)

Reviewer 用本表验证 prompt 输出 JSON 字段是否落在 calls 表的 coaching 子集内。

| Prompt             | 写入字段                                                      | 备注                                       |
| ------------------ | --------------------------------------------------------- | ---------------------------------------- |
| 01 Triage          | —                                                         | 不写 coaching                              |
| 02 Classify        | —                                                         | 不写 coaching(写 calls 其他字段)                |
| 03 Verify          | —                                                         | 不写 coaching                              |
| **04 Coaching**    | `practicalCoachingScenario` / `practicalCoachingFeedback` | **主要写入 prompt** — reviewer 重点验证输出字段 ∈ §2 |
| 05 Contact Profile | —                                                         | 写 contacts 表                             |
| 06 Task Decision   | —                                                         | 写 tasks + task\_progress\_events         |
| 07 Task Playbook   | —                                                         | read-only                                |

`reviewCategory` / `reviewReason` 没有 prompt 在产出 — 当前 7 个 prompt 中,reviewer 无需验证这两个字段。

***

## 9. Appendix A — Re-verification commands

> 2026-06-15 verified。文档 stale(>30 天)时重跑下方命令并比对。

```bash
# 1. 4 个 coaching 字段是否还在 calls.ts 里
grep -nE "practicalCoaching|reviewCategory|reviewReason" \
  ../../../../../callytics-common/src/db/schema/calls.ts
# 期望: 4 行 column 定义 + 1 行 idx_calls_review_category index

# 1b. manager workflow 表 + AI feedback 表
grep -nE "coachingReviews|COACHING_REVIEW_STATUS|aiFeedback|AI_FEEDBACK_SUBJECT_TYPE|AI_FEEDBACK_TYPE" \
  ../../../../../callytics-common/src/db/schema/coaching-reviews.ts \
  ../../../../../callytics-common/src/db/schema/ai-feedback.ts

# 2. Codex final design 是否动 coaching
grep -i "coaching\|practicalCoaching\|reviewCategory" \
  ../../tasks-feature/design/task-pipeline-deliverable-codex.md
# 期望: 0 行 — codex 完全不提 coaching

# 3. Unified pipeline final 是否动 coaching schema
grep -i "coaching\|practicalCoaching\|reviewCategory" \
  ../../unified-pipeline/unified-pipeline-final.md
# 期望: 只 reference Coaching 是 Stage ⑤ + 写 calls 表,不改 schema

# 4. reviewCategory 真接线了吗
grep -rnE "reviewCategory|review_category" \
  ../../../../../callytics-infrastructure/lambda/ \
  ../../../../../callytics-common/src/ 2>/dev/null | \
  grep -v schema/calls.ts
# 期望: 0 行 write/read — 仍是 schema 占位
```

***

## 10. Cross-References

- Calls 全表 schema(coaching 4 字段所在的物理表): [../calls-feature/calls-schema.md](/product-design/v2/calls-feature/calls-schema.md)
- Coaching gate + sentinel 行为详解: [coaching-calculations.md](/product-design/v2/coaching-feature/coaching-calculations.md)
- Coaching 前端展示: [coaching-display.md](/product-design/v2/coaching-feature/coaching-display.md)
- Tasks 表(下游 Task Decision prompt 写入): [../tasks-feature/tasks-schema.md](/product-design/v2/tasks-feature/tasks-schema.md)
- Unified pipeline (Coaching 是 Stage ⑤): [../unified-pipeline/unified-pipeline-final.md](/product-design/v2/unified-pipeline/unified-pipeline-final.md)
- All 7 prompts: [../unified-pipeline/prompts/](../unified-pipeline/prompts/)
- V1 5 维度打分(规划中,未实现): [../../v1/coaching-highlights-feature/coaching-highlights-spec.md](/product-design/v1/coaching-highlights-feature/coaching-highlights-spec.md)
- Live schema: `callytics-common/src/db/schema/calls.ts` (lines 217, 220, 229, 232 + index line 311)
