# TriagePilot Manual Issue 回归和诊断 Skill 分层设计

> Status: Draft  
> Date: 2026-05-18  
> Audience: Investibook / TriagePilot / Replay maintainers  
> Scope: manual ISS 分类、诊断 skill 分层、harness 回归策略

## 1. 背景

TriagePilot 现在已经能把用户反馈、postmortem 结果和 autofix 修复串成一个基本闭环。UX 类问题因为复现率高、边界清晰，已经比较适合由 autofix 消化：如果没有修好，用户或人工复盘很容易用同一个 case 再次触发相同反馈。

真正需要强化 harness 的，是当前被标记为 `manual` 的诊断质量问题。这类问题通常不是一个按钮、一个展示状态、一个 API 边界能修完的，而是发生在诊断链路中间：

- 数据源没有拿到，或者拿到的是错误数据。
- Agent 拿到了数据，但理解错了数据语义。
- Agent 太早形成先验，后续证据无法纠正它。
- 大 skill 中规则过多，Agent 读取后无法稳定关注所有 guard。
- 最终结论看起来合理，但缺少必要证据、反例排除或 workaround。

因此，manual issue 不能只靠“写一个更长的规则”来修。它需要同时改进三件事：

1. 用更贴近诊断链路的分类替代笼统的 `FLOW` / `REASONING` / `TOOLING` / `KNOWLEDGE`。
2. 把大诊断 skill 拆成更小、更有触发条件的分层 skill。
3. 用 harness 固定每类失败的回归检查点，证明同类问题真的不再复发。

## 2. 目标

这套设计的目标不是让 Agent 自动修复所有 manual issue，而是让 manual issue 变成可以回归、可以排期、可以验证的工程对象。

核心目标：

| 目标 | 说明 |
|---|---|
| 重新分类 | 让每个 ISS 对应到诊断链路中的失败阶段，而不是只记录表象类型 |
| 指导 skill 分层 | 每类失败都能指向应该拆出来或强化的 skill 层 |
| 支撑 harness | 每类失败都有可检查的 replay/evaluation 信号 |
| 降低惰性推断 | 在 Agent 形成根因判断前，先强制完成异常分类和证据 inventory |
| 保护改动质量 | skill/tool 改动必须通过相关 case 回归，避免只修单个样本 |

## 3. 建议的 Issue Stage 分类

当前建议保留 `UX` 和 `Template`，因为它们不是诊断推理阶段的问题；同时用更贴近诊断链路的 stage 替换原来的 `FLOW` / `REASONING` / `TOOLING` / `KNOWLEDGE` / `CROSS-REF`。

| Stage | 用途 | 典型问题 | 主要修复方向 | Harness 检查点 |
|---|---|---|---|---|
| `ux` | 产品交互和可见反馈 | 按钮无反馈、消息状态错误、输入体验差 | frontend / backend UX 修复，适合 autofix | UI 行为或 API contract 检查 |
| `template` | 输出模板和表达格式 | 报告结构缺失、字段命名不清、结论表达不稳定 | report template / prompt output schema | final answer 是否包含 required sections |
| `intake_context` | 入口信息和上下文归一 | Jira ID、cluster、tenant、时间窗口、ticket comment 使用方式错误 | intake skill / source normalization | 是否正确识别诊断对象、时间范围和可用数据 |
| `data_retrieval` | 数据源和 tool call 可达性 | Loki 404、Clinic URL 缺失、TopSQL 查询失败、API 分页/权限问题 | tool adapter / data source skill / fallback | tool 是否成功返回，失败时是否明确降级 |
| `data_correctness` | 数据源返回的数据本身错误 | 时间窗口错、cluster ID 错、实例映射错、metric 查询条件错 | tool contract / query builder / source validation | 原始返回值是否匹配 case metadata |
| `data_semantics` | Agent 对数据语义理解错误 | 把 modify IOPS event 理解成扩缩容，把 thread CPU 含义解释错 | data semantics guard / evidence glossary | 是否正确解释 event、metric、unit、维度含义 |
| `classification` | 异常类型和诊断路由 | 没先判断 read hotspot / ingest / GC / SQL plan，就直接猜根因 | abnormality classifier / route selector | 是否先列出异常 inventory 并选择合理诊断路径 |
| `specialized_diagnosis` | 专项根因诊断 | read hotspot、ingest stall、TiDB CPU、etcd stall 等细分场景分析不充分 | subskill / action / guard | 是否满足该场景的必要证据链和反例排除 |
| `recommendation` | workaround 和行动建议 | 建议不可执行、优先级错误、风险说明缺失 | recommendation guard / runbook mapping | 是否给出可执行、低风险、有依据的 next step |

这里最关键的新增分类是 `data_correctness` 和 `data_semantics`：

- `data_correctness` 表示工具或数据源返回值本身有问题。例如查询时间错了、cluster ID 用错了、实例映射错了。这类问题应该优先修 tool 或数据源 contract，而不是修诊断 prompt。
- `data_semantics` 表示数据本身拿到了，但 Agent 理解错了。例如把 `modifyiopsevent` 解释成扩缩容，把 read path 线程误当成 write bottleneck。这类问题应该修语义 guard、metric glossary 或专项 skill。

这两个分类必须拆开。否则我们会把“数据错了”和“读懂数据错了”混在一起，导致 skill 修复和 tool 修复互相甩锅。

## 4. 为什么要按 Stage 分类

原来的 `FLOW`、`REASONING`、`TOOLING`、`KNOWLEDGE` 更像复盘时的人类解释标签，适合粗略统计，但不适合作为回归和修复入口。

例如：

- “没有验证跨数据源时间关联”可以叫 `FLOW`，但真正失败点可能是 `classification`，也可能是 `specialized_diagnosis`。
- “错误理解 modify IOPS event”可以叫 `KNOWLEDGE`，但修复目标不是增加一条泛知识，而是补 `data_semantics` guard。
- “Loki 查询 404”可以叫 `TOOLING`，但它应该进入 `data_retrieval`，并用工具 contract test 回归。

Stage 分类的好处是：每个 issue 都能回答三个问题：

1. 诊断链路在哪一步坏了？
2. 应该修 skill、tool、template、还是 UI？
3. 修完以后 harness 应该检查什么？

## 5. 诊断 Skill 分层建议

当前 `tidb-clinic-diagnosis` 可以类比成代码里的 `main()`。问题在于它承载了太多单条规则、例子和 guard。Agent 读取一个过长 skill 时，很难稳定关注所有规则；更糟的是，Agent 在收集证据过程中一旦形成先验，后续很难再回到更早状态重新分类。

建议把诊断 skill 拆成三层。

### 5.1 第一层：入口和通用证据收集

第一层只做通用 intake，不直接判断根因。

职责：

- 识别诊断对象：Jira ID、workspace、cluster、tenant、时间窗口、alert 类型。
- 列出可用数据源：Jira、Clinic metrics、slow query、TopSQL、logs、activity events、diagnostic files。
- 收集轻量 summary：各组件 CPU、latency、关键 error、慢查询摘要、事件时间线。
- 明确缺失数据：哪些工具失败、哪些数据源不可达、哪些时间范围不可信。

禁止：

- 在这一层直接给最终根因。
- 因为看到某个 comment 或某个异常指标就跳到结论。
- 把单个 metric 当作 root cause proof。

产物应该是一个 evidence inventory，而不是 diagnosis。

### 5.2 第二层：异常分类和诊断路由

第二层根据 evidence inventory 做异常分类，决定进入哪个专项诊断路径。

职责：

- 判断主要异常形态：read hotspot、write/ingest bottleneck、TiDB CPU、SQL plan、GC、etcd/disk stall、network、internal operation 等。
- 对每个候选异常列出必要证据和反证。
- 对不满足条件的候选显式降级为 low confidence 或 unknown。
- 选择后续要读取的专项 skill。

例子：

| 候选类型 | 必要证据示例 |
|---|---|
| read hotspot | TiKV 某节点 CPU 异常、read path 线程高、gRPC/cop latency 异常、TopSQL/slow query 指向集中 scan |
| ingest/write bottleneck | write/ingest 线程高、raftstore/apply 相关压力、磁盘或 RocksDB 指标异常、写入量或 compaction 证据 |
| TiDB CPU | TiDB CPU 持续高、TopSQL CPU 占比、session/statement 证据、GC 指标检查 |
| etcd/disk stall | PD/etcd latency、disk I/O wait 或 stall 事件、对应时间线影响 |
| data source failure | tool exit 非 0、404/permission/empty result、缺少 fallback 或 warning |

第二层的重点是抑制 Agent 的“先猜根因”。只有当分类条件满足，才进入对应专项诊断；条件不满足时，必须承认证据不足。

### 5.3 第三层：专项诊断和 workaround

第三层才负责具体根因分析和建议。

职责：

- 读取对应专项 skill，例如 read hotspot、query tuning、ingest、GC、etcd、log/OOM 等。
- 按专项 skill 的证据链要求完成 root cause analysis。
- 给出置信度、缺失证据和反例排除。
- 输出 workaround、长期修复建议和验证方式。

禁止：

- 用专项 skill 反向证明第二层没有满足的分类。
- 忽略不支持当前结论的证据。
- 给出没有风险说明或验证方式的操作建议。

## 6. Harness 如何回归 Manual Issue

UX 问题的 harness 可以比较轻，因为复现路径清晰。manual 诊断问题需要更强的分层检查，否则只看最终文本很容易误判。

建议每个 manual issue 至少补齐以下字段：

| 字段 | 说明 |
|---|---|
| `issue_stage` | 上文定义的诊断阶段 |
| `case_id` / `workspace_id` | 复现该问题的原始 case |
| `expected_behavior` | 修复后应该稳定做到什么 |
| `must_collect` | 必须收集或引用的证据 |
| `must_not_claim` | 没有证据时不能声称的结论 |
| `acceptance_check` | replay/evaluation 中可判断的通过条件 |
| `fix_owner` | skill / tool / template / UI / data source |

### 6.1 分层回归信号

不要只问“最终根因是否正确”。更可靠的做法是让 harness 检查中间状态。

| Stage | 回归信号 |
|---|---|
| `intake_context` | 是否选对 cluster、时间窗口、ticket/comment 使用边界 |
| `data_retrieval` | 关键工具是否成功；失败时是否有 fallback 和用户可见说明 |
| `data_correctness` | 工具返回的 cluster/time/instance/dimension 是否匹配 case metadata |
| `data_semantics` | 是否正确解释 event/metric/thread/unit，而不是只复述名字 |
| `classification` | 是否先生成异常 inventory，再选择诊断路径 |
| `specialized_diagnosis` | 是否满足专项证据链，例如 read hotspot 的 CPU/thread/latency/query 关联 |
| `recommendation` | 建议是否和根因一致，是否有验证方法和风险说明 |
| `template` | 最终输出是否包含 required sections |

### 6.2 对不同问题使用不同 harness

不同 stage 应该使用不同粒度的 harness：

| 问题类型 | 推荐 harness |
|---|---|
| 工具不可达 | tool contract test + replay 中的 fallback 检查 |
| 数据返回错误 | deterministic fixture / query validator |
| 数据语义错误 | evidence snippet classification test |
| 诊断分类错误 | replay 后检查 abnormality inventory 和 route selection |
| 专项诊断错误 | case-specific expected rubric |
| 建议错误 | recommendation rubric + must-not-claim |
| 模板错误 | snapshot/schema check |

这意味着 TriagePilot 的 harness 不应该只有一种 pass/fail。它应该把失败定位到 stage，帮助我们判断下一步应该修 tool、修 skill，还是补 template。

## 7. Manual Issue 的处理流程

建议后续处理 manual open issue 时按下面流程走：

```text
Open manual ISS
  -> 重新打 issue_stage
  -> 确认 source case / workspace
  -> 写 expected_behavior / must_collect / must_not_claim
  -> 判断 fix_owner
  -> 选择 harness 类型
  -> 修 tool / skill / template
  -> 用相同 case 在 dev workspace 重跑
  -> 将新 workspace 和证据写回 ISS
  -> 通过后标记 fixed，否则保留 open 并记录 residual gap
```

关键原则：

- 不能因为 skill 文档改了就直接关闭 issue。
- 不能只看 Agent 最终回答“像是对了”就关闭 issue。
- 对 `data_retrieval` / `data_correctness` 问题，必须优先验证工具输出。
- 对 `data_semantics` / `classification` / `specialized_diagnosis` 问题，必须看中间证据链。
- 对同一类反复出现的问题，应该沉淀为 subskill 或 guard，而不是继续给大 skill 加单条规则。

## 8. 和 TriagePilot Board 的关系

TriagePilot Board 可以把当前 `Type distribution` 替换为 `Issue stage distribution`，用于展示 manual issue 主要堆在哪个诊断阶段。

建议看板上保留两组维度：

| 维度 | 用途 |
|---|---|
| `issue_stage` | 表示诊断链路失败阶段，用于修复和回归 |
| `diagnosis_track` | 表示大方向：skill quality 还是 data/tooling |

其中 `issue_stage` 应该作为主要筛选维度，`diagnosis_track` 作为更粗的运营视角。

例如：

- `data_retrieval` + `data_tooling`：优先排查 tool/API/权限/查询语句。
- `data_semantics` + `skill_quality`：优先补 metric/event semantics guard。
- `classification` + `skill_quality`：优先设计第二层异常分类。
- `specialized_diagnosis` + `skill_quality`：优先拆专项 subskill 和 case rubric。

## 9. 与现有 Skill Orchestration 设计的衔接

这份文档和 `Diagnosis Knowledge Orchestration` 的方向一致，但更偏向当前 manual issue 的落地治理。

对应关系：

| 本文概念 | Orchestration 概念 |
|---|---|
| 第一层 intake 和通用证据收集 | `intake` frame + evidence protocol |
| 第二层异常分类 | `entry-triage` frame + classify actions |
| 第三层专项诊断 | component/specialized actions + guards |
| `data_semantics` | guard + KB fact/glossary |
| `classification` | route selector / action precondition |
| `specialized_diagnosis` | action card + case-specific guard |
| harness 中间检查点 | runtime state + validation |

短期可以先用 Markdown 和 YAML 字段落地；中长期再把 stage、action、guard、rubric 结构化成可生成、可校验的资产。

## 10. 下一步建议

建议按以下顺序推进：

1. 给现有 open ISS 补 `issue_stage`，先不强制修改所有历史字段。
2. 对 P1 manual issue 补 `expected_behavior`、`must_collect`、`must_not_claim`。
3. 在 TriagePilot Board 上用 `issue_stage` 替换旧 type 分布。
4. 选择 3-5 个 P1 case 做试点：一个 `data_retrieval`、一个 `data_semantics`、一个 `classification`、一个 `specialized_diagnosis`。
5. 为试点 case 建立 replay/evaluation acceptance check。
6. 再根据失败聚类拆第一批 subskill 或 guard。

这条路径的核心是：先让 manual issue 能被稳定回归，再谈自动修复或自动改 skill。否则 skill 只会越写越长，Agent 仍然会在复杂诊断里丢掉关键规则。

