# 审批阻塞精确识别方法论（2026-07-10 实战教训）

## 问题：`actual_blockers` 列表具有误导性

`mcp_pipeline.py` 的阻塞检测逻辑是：取 `get_node_detail` 返回的所有节点中 `status='in_progress'/'doing'` 的节点作为 `actual_blockers`。但这个列表**包含了已经到达但尚未完成的节点，不能直接等同于"谁在阻塞"**。

## 案例：42条阻塞中18条显示"销售大区审核(刘新元)"

初次分析结论：18条阻塞在刘新元处，需要刘新元审批。

用户指出："并不是真实的卡在我这里，而是我在流程这个节点上，请仔细识别是否具体的销售没有审批导致阻塞。"

## 正确分析方法：查看完整节点链的所有状态

**关键工具**：`get_node_detail` 返回的是**全部节点**（包括 finished/not_started），不只是 in_progress 的。

```python
detail = mcp("get_node_detail", {"project_key": pk, "work_item_id": wid})
for node in detail['list']:
    basic = node['basic']
    status = basic['status']  # 'done'/'finished'/'in_progress'/'doing'/'not_started'
    node_name = basic['name']
    owners = node.get('assignees', {}).get('owners', [])
```

### 节点状态解读

| 状态 | 含义 | 是否阻塞 |
|------|------|---------|
| `finished` / `done` | 已完成 | ❌ 不是阻塞 |
| `in_progress` / `doing` | 当前正在进行的节点 | ✅ **真正的阻塞** |
| `not_started` | 尚未开始 | ❌ 不是当前阻塞（但可能是下游节点被上游阻塞了） |
| `rejected` | 被拒绝/回退 | ❌（流程需重新提交） |

## 三类阻塞场景

### 场景1：简单3节点流程（客户项目管理）

```
开始(finished) → 销售大区审核(doing) → 结束(not_started)
```

**结论**：真的阻塞在销售大区审核节点 → 需要该节点负责人审批。

### 场景2：复杂8节点流程（售后管理客诉）

```
开始(finished) → QA初步判断(finished) → 退货信息反馈(finished)
  → 实收数量反馈(doing) ← 真正阻塞！
  → 销售员审核(doing) ← 真正阻塞！
  → 大区/部门经理审核(not_started) ← 尚未到达
  → 结束(not_started)
```

**结论**：阻塞在实收数量反馈和销售员审核 → 彭冠华、销售员需要处理。
大区审核虽然也 assigned to 刘新元，但状态是 not_started → 不是当前阻塞。

### 场景3：回退后重复节点

客诉流程中常见：同一个节点名出现两次（如"大区/部门经理审核"出现两次）：
- 第一次：`finished` → 已审批通过
- 第二次：`not_started` 或 `in_progress` → 回退后重新走

分析时要区分同一节点名的多个实例。

## 跨空间阻塞分布（2026-07-10 实测）

| 空间 | 阻塞数 | 真实阻塞节点 | 说明 |
|------|--------|-------------|------|
| **售后管理** | 24条 | 销售员审核(16)、实收数量反馈(12)、退货(6)、技术支持(5)、大区审核(3，owner为空) | 阻塞在前端环节，非刘新元 |
| **客户项目管理** | 18条 | 销售大区审核(18) | 简单3节点流程，真的需要刘新元审批 |

### 售后管理阻塞节点明细（24条）

| 阻塞节点 | 次数 | 关键负责人 |
|---------|------|-----------|
| 销售员审核 | 16次 | 王星茗/刘虹晶/冯贤平/宋学伟/杜建/赵云浩/黄明月 |
| 实收数量反馈 | 12次 | 彭冠华（主力）、陈晓洁 |
| 退货信息反馈 | 6次 | 王昕伟/杜建/刘虹晶/路要峰 |
| 技术支持信息补充 | 5次 | 饶欣悦/李锋 |
| 大区/部门经理审核 | 3次 | ⚠️ owner为空（未分配），非刘新元 |

### 客户项目管理阻塞（18条）

全部为3节点简单流程：开始(finished) → 销售大区审核(doing, 刘新元) → 结束(not_started)。需刘新元审批，最长积压391天（MRD-RNA单管）。

## 正确的阻塞分析流程

1. **拉取待办列表** → `list_todo` 获取基础信息
2. **按 project_key 分组** → 不同空间有不同的审批流复杂度
3. **对每条阻塞调 get_node_detail** → 获取完整节点链
4. **遍历所有节点**，标记每个节点的 status：
   - `in_progress`/`doing` → 当前阻塞点
   - `not_started` → 下游被阻塞的节点（列出但不作为"谁在阻塞"的结论）
   - `finished` → 已完成的节点
5. **区分"谁的名字在阻塞节点上" vs "谁真正在阻塞"**：
   - 阻塞节点上的人 = 需要行动的人
   - not_started 节点上的人 = 工作流尚未到达，不是他们的问题

## mcp_pipeline.py 的修正方向

当前 `mcp_pipeline.py` 的 `actual_blockers` 字段只列出了 in_progress 节点，但没有区分：
- 哪些是"当前阻塞"（需要立即行动）
- 哪些是"下游节点"（被上游阻塞，尚未到达）

建议在输出JSON中增加：
```json
{
  "actual_blockers": [...],   // 所有 in_progress 节点
  "true_blocker": {...},      // 第一个/最前面的 in_progress 节点
  "downstream_blocked": [...], // not_started 但 assigned 的节点
  "completed_nodes": [...]    // finished 的节点
}
```
