---
name: harness-eval
description: "评估功能的真实运行性能。从 Wiki 读取 schema 和 metric 定义，查询 SQLite 日志，对比基线，调用 LLM judge 做语义评估，产出诊断和迭代建议。触发短语: harness eval, 评估性能, 性能评估。"
argument-hint: "[run_id]"
---

# Harness Eval

## Overview

在真实环境中运行程序后，评估性能是否达标，诊断问题，决定是否迭代。

**核心原则：** 不是"通过就停"，而是基于真实指标判断"跑得好不好"。

## 触发方式

1. **自动**：subagent-driven-development Step 10，所有任务完成 + final review 通过后
2. **手动**：`/harness-eval` 或 `/harness-eval <run_id>`

## 前置条件

- `research-wiki/schemas/` 中有至少一个 schema 实体
- `research-wiki/metrics/` 中有至少一个 metric 实体
- `results/harness.db` 存在且包含数据
- `.env` 中有 LLM API key（用于 LlmJudge）

## 长时命令执行约定

对真实样本重跑流水线属于长时操作。超过 30s 的命令建议在 tmux 中后台运行，便于人工随时 attach 检查进度；短命令直接前台执行即可。

## 执行流程

### Phase 1: 准备

1. 列出 `research-wiki/schemas/` 下所有 schema 实体，获取表名和列信息
2. 列出 `research-wiki/metrics/` 下所有 metric 实体，获取基线值和阈值
3. 确认 `results/harness.db` 存在，查询 `_runs` 表获取最新运行状态
4. 如果指定了 run_id，使用该 run_id；否则使用最近一次 status='completed' 的 run

### Phase 2: 运行

#### 2a: 检查已有运行记录

在 subagent-driven-development 流程中，某个子任务可能已经执行过全局运行并将结果写入了 `harness.db`。此时 harness-eval **不应重复运行**，直接复用已有记录即可。

1. 查询 `_runs` 表，查找 `status='completed'` 且 `git_sha` 与当前 `HEAD` 匹配的记录
2. **找到匹配记录** → 使用该记录的 run_id，**跳过运行**，直接进入 Phase 3。在最终报告中注明「复用已有运行: run_id=xxx」
3. **未找到匹配记录 + 自动触发** → 继续 2b
4. **未找到匹配记录 + 手动触发** → 询问用户是否需要执行运行

#### 2b: 重跑流水线（仅无可用记录时）

1. `make deploy-testing` 起服务（api / worker / Postgres / Redis / 对象存储）
2. 对真实样本重跑流水线，结果落 `results/harness.db`；属长时操作，建议按「长时命令执行约定」在 tmux 中运行
3. 轮询检查 `_runs` 表状态，等待完成
4. 确认 `_runs` 表中对应 run 的 status = 'completed'
5. 如果 status = 'failed'，直接进入 Phase 6 诊断

### Phase 3: 硬性指标检查

对 `research-wiki/metrics/` 中每个标记为硬性判定的指标：

1. 从 metric 实体中读取：指标名、基线值、阈值、对应的 schema（表名和列名）
2. 执行 SQL 查询获取当前运行的实际值
3. 对比：实际值 vs 阈值
4. 记录结果：pass / fail + 具体数值

### Phase 4: 语义评估

对 `research-wiki/metrics/` 中每个标记为语义判定的指标：

1. 收集 evidence：相关表的数据、_events 表的事件、配置信息
2. 调用 `LlmJudge.evaluate(EvalRequest)`（请求体封装 criteria、evidence、rubric）
3. 记录结果：Verdict

### Phase 5: 综合判定

- 硬性指标全部 pass **且** 语义评估全部 pass → **通过**
- 任一不通过 → **不通过**，进入 Phase 6

### Phase 6: 诊断与迭代决策（仅不通过时）

1. 收集失败信息：哪些指标不达标、实际值与期望值的差距
2. 查询 `_events` 表获取运行过程中的关键事件
3. 调用 `LlmJudge.diagnose(error_context, log)`
4. 向用户报告：
   - 问题根因分析
   - 修复建议
   - 是否建议再迭代一轮

### Phase 7: 记录到 Wiki

1. 创建 finding 实体：
   ```bash
   conda run -n chs python3 .claude/tools/research_wiki.py add_entity research-wiki/ --type finding --id eval-<run_id> --title "Harness 评估: <run_id>"
   ```
2. 在 finding 中记录完整评估报告（硬性指标表 + 语义评估结果 + 诊断结论）
3. 建立 edge：
   ```bash
   conda run -n chs python3 .claude/tools/research_wiki.py add_edge research-wiki/ --from "finding:eval-<run_id>" --to "metric:<id>" --type evaluates --evidence "..."
   ```
4. 如果通过且用户确认，更新 metric 实体中的基线值为当前值
5. 重建索引

## 输出格式

评估完成后，向用户输出结构化报告：

| 字段 | 内容 |
|------|------|
| 运行信息 | run_id, git_sha, 耗时 |
| 硬性指标表 | 指标名, 基线, 当前, 阈值, 判定 |
| 语义评估表 | 维度, 得分, 判定, 说明 |
| 综合判定 | 通过/不通过 |
| 诊断（如有） | 根因, 建议 |

## 与 subagent-driven-development 集成

在 SKILL.md 的 Step 9（final whole-implementation review）之后追加 Step 10：

```
Step 10: Harness 评估
  调用 /harness-eval skill
  通过 → 进入 finishing-a-development-branch
  不通过 → 根据诊断结果，回到 Step 2 迭代相关 task
```

## 评估范围

本 skill 当前覆盖①工程评估；②提取信度/③诊断效度的全量评估待 `app/` 流水线落地后接入。
