# 健康度指标计算

> **前置条件：** 先阅读 [`../../gitlink-shared/SKILL.md`](../../gitlink-shared/SKILL.md) 了解认证、全局参数和安全规则。

基于收集到的数据，计算 Issue 响应时间、PR 合并效率、贡献者活跃度三大指标，并给出综合健康评分。

## 指标 1：Issue 响应时间

### 两种评价方式

Issue 响应时间支持两种计算口径，AI Agent 可根据数据可用性和项目工作流选择：

| 口径 | 计算方式 | 含义 | 适用场景 |
|------|----------|------|----------|
| **响应时间** | `resolved_at - created_at` | 从创建到解决的时间 | 衡量团队对 Issue 的实际响应速度 |
| **全周期时间** | `closed_at - created_at` | 从创建到正式关闭的时间 | 衡量 Issue 的完整生命周期 |

**推荐优先使用响应时间**（新增→已解决），因为它反映真实处理效率。全周期时间受"解决后批量关闭"等工作流影响，可能虚高。

### 计算所需数据

从 `issue +list --state closed` 返回的 Issue 列表中提取：

- `created_at` — 创建时间
- `updated_at` — 最后更新时间（当无独立 `closed_at`/`resolved_at` 时的降级代理字段）
- `status_id` — 状态：1=新增, 2=正在解决, 3=已解决, 5=关闭
- `status_name` — 状态名称（辅助判断）

> **注意**：GitLink API 不直接返回 `closed_at` 或 `resolved_at` 字段。AI Agent 需根据上下文推断：
> - 若 Issue 的 `status_id=5`（关闭）且 `updated_at` 在近期批量操作中突变，则 `updated_at` 反映的是关闭时间而非解决时间，应尝试从历史会话或其他来源获取解决时间
> - 若项目工作流为"解决即关闭"（单步），则 `updated_at` 同时代表解决和关闭时间，可直接使用

### 计算公式

```
# 方式 A：响应时间（推荐）
time_to_resolve = resolved_at - created_at
avg_response = sum(time_to_resolve) / count
median_response = sorted(time_to_resolve)[count / 2]

# 方式 B：全周期时间
time_to_close = closed_at - created_at
avg_close = sum(time_to_close) / count
median_close = sorted(time_to_close)[count / 2]
```

### 阈值

| 指标 | 优秀 | 良好 | 需改进 |
|------|------|------|--------|
| 平均响应/关闭时间 | ≤ 2 天 | ≤ 7 天 | > 7 天 |
| 中位数响应/关闭时间 | ≤ 1 天 | ≤ 5 天 | > 5 天 |
| Issue 积压数 | ≤ 10 | ≤ 20 | > 20 |

### 时间计算注意

- 时间字段为 ISO 8601 格式（如 `"2026-06-04 14:45"`），需解析后求差值
- 无 `closed_at` 的 Issue（open 状态）不计入响应时间，计入积压统计
- 当两种口径结果差异显著时（如响应时间 1.5 天 vs 全周期 15 天），以响应时间为评分依据，在全周期时间处标注"受工作流影响"

## 指标 2：PR 合并效率

### 三段时间计算

PR 合并效率由**三类 PR** 共同决定，需计算**三段时间**：

| 时间编号 | 名称 | 公式 | 适用对象 |
|----------|------|------|----------|
| ① | 已合并 PR 平均合并时长 | `avg(merged_at - created_at)` | status=1（已合并） |
| ② | 开放 PR 平均等待时长 | `avg(now - created_at)` | status=0（开放中） |
| ③ | 加权总平均处理时长 | 见下方公式 | status=1 ∪ status=0 |

### 计算公式

```
# ① 已合并 PR 平均合并时长
time_merged_i = merged_at_i - created_at_i
avg_merged = sum(time_merged_i) / merged_count

# ② 开放 PR 平均等待时长
time_open_i = now - created_at_i
avg_open = sum(time_open_i) / open_count

# ③ 加权总平均处理时长
total_count = merged_count + open_count
weight_merged = merged_count / total_count
weight_open = open_count / total_count
weighted_total = weight_merged * avg_merged + weight_open * avg_open
```

### 状态分类

| 状态 | 含义 | 是否计入 | 计入哪类 |
|------|------|---------|---------|
| `pull_request_status=1` | 已合并 | ✅ | ①已合并 |
| `pull_request_status=0` | 开放中 | ✅ | ②开放等待 |
| `pull_request_status=2` | 已关闭（未合并） | ❌ | 不参与时间计算，但参与合并率分母 |

> **设计依据**：
> - 已合并 PR 已有"完成时间"（merged_at），用真实合并耗时
> - 开放 PR 尚未合并，"等待时长"= 从创建到当前（持续增长中），反映积压压力
> - 加权平均综合体现项目处理 PR 的整体节奏，比单一指标更准确

### 合并率（独立指标）

```
merge_rate = merged_count / (merged_count + closed_count) × 100%
```

仅使用「已合并」与「已关闭未合并」作为分母，开放 PR 不参与。

### 阈值

| 指标 | 优秀 | 良好 | 需改进 |
|------|------|------|--------|
| ① 已合并 PR 平均合并时长 | ≤ 1 小时 | ≤ 1 天 | > 1 天 |
| ② 开放 PR 平均等待时长 | ≤ 1 天 | ≤ 7 天 | > 7 天 |
| **③ 加权总平均处理时长** | **≤ 6 小时** | **≤ 2 天** | **> 2 天** |
| PR 积压数 | ≤ 3 | ≤ 10 | > 10 |
| 合并率 | ≥ 90% | ≥ 70% | < 70% |

> **可调阈值**：此表为默认值。不同项目工作流差异大（如 fork 端预审型 vs 上游社区 PR 型），可在 `health-metrics.md` 中按项目特征调整。

### 数据可用性

| 字段 | 来源命令 | 路径 |
|------|---------|------|
| `created_at` | `pr +list` | `data.issues[].pr_full_time` 或 `pr_created_unix` |
| `merged_at` | `pr +view --id <pull_request_number>` | `data.pull_request.merged_at` |

> **绝对禁止**：用「当前时间 - 创建时间」估算已合并 PR 的合并时间。已合并 PR 必须用真实的 `merged_at`。
> 开放 PR 用「当前时间 - 创建时间」是允许的（且必要），因为它们没有合并时间点，等待时长反映积压。

### 数据可用性

PR 合并时间**只与 PR 自身时间相关**（创建时间 + 合并时间），**与当前时间无关**。

实际数据源：

| 字段 | 来源命令 | 路径 |
|------|---------|------|
| `created_at` | `pr +list --state merged` | `data.issues[].pr_full_time` 或 `pr_created_unix` |
| `merged_at` | `pr +view --id <pull_request_id>` | `data.pull_request.merged_at` |

**注意**：`merged_at` 只在 `pr +view` 单个 PR 详情中暴露，列表接口不返回。需要对每个已合并 PR 调用一次详情接口。

> **绝对禁止**：使用「当前时间 - 创建时间」作为合并时间估算。这种做法会把开放中或近期合并的 PR 误判为"超长合并时间"，与 PR 合并效率的真实含义相悖。

## 指标 3：贡献者活跃度

### 计算所需数据

从 `GET /:owner/:repo/contributors` 返回：

- `authors[].login` — 贡献者登录名
- `authors[].commits` — 提交数
- `authors[].additions / deletions` — 增删行数

### 活跃度分级

| 级别 | 图标 | 条件 |
|------|------|------|
| 高频活跃 | 🔥 | 近 30 天 commits ≥ 5 或 PRs ≥ 2 |
| 正常活跃 | 🟢 | 近 30 天 commits ≥ 1 或 PRs ≥ 1 |
| 低频活跃 | 🟡 | 近 30 天无 commit 但有 Issue 活动 |
| 不活跃 | ⚪ | 近 60 天无任何贡献活动 |

### 贡献者集中度

```
top_contributor_share = max(authors[].commits) / total_commits × 100%
```

集中度 > 70% 视为过度集中（bus factor 低，有单点风险）。

## 综合健康评分（100 分制）

### 计分规则

起始分 **100 分**，逐项扣分。核心三指标（Issue 响应时间、PR 合并效率、贡献者活跃度）占 75 分，辅助指标占 25 分。

### 核心指标（75 分）

| 扣分项 | 扣分 | 触发条件 | 说明 |
|--------|------|----------|------|
| Issue 响应慢 | -25 | `avg_response > 7天`（使用响应时间口径，即新增→已解决） | Issue 平均解决时间超过一周 |
| PR 合并慢 | -25 | `avg_merge > 1天` | PR 平均合并时间超过一天 |
| 贡献者活跃度低 | -25 | `active_contributors < 2` 或 `top_contributor_share > 70%` | 活跃贡献者过少或过度依赖单一贡献者 |

### 辅助指标（25 分）

| 扣分项 | 扣分 | 触发条件 | 说明 |
|--------|------|----------|------|
| Issue 积压 | -10 | `open Issues > 20` | 待处理 Issue 数量过多 |
| PR 积压 | -10 | `open PRs > 10` | 待合并 PR 数量过多 |
| 无近期发布 | -5 | `latest_release > 30天` | 近 30 天无新发布 |

### 评分等级

| 分数 | 等级 | 图标 | 说明 |
|------|------|------|------|
| 90-100 | 优秀 | 🟢 | 项目运转非常健康 |
| 70-89 | 良好 | 🔵 | 整体正常，有小问题 |
| 50-69 | 一般 | 🟡 | 需要关注多项指标 |
| 30-49 | 需关注 | 🟠 | 存在明显瓶颈 |
| 0-29 | 严重 | 🔴 | 需要立即干预 |

### 改进建议生成

根据扣分项自动生成改进建议：

| 扣分项 | 改进建议 |
|--------|----------|
| Issue 积压 | 建议安排 Issue Triage，优先处理高优先级 Issue |
| PR 积压 | 建议增加 Code Review 资源，缩短 PR 等待时间 |
| Issue 响应慢 | 建议建立 Issue 处理 SLA，落实责任人 |
| PR 合并慢 | 建议设 PR 合并时效目标（如 48 小时内） |
| 贡献者集中 | 建议鼓励多人参与核心模块，避免单点风险 |
| 无近期发布 | 建议建立定期发布节奏（如每 2 周发一次） |

## 输出格式

计算完成后，整理为结构化数据供模板填充：

```
综合评分: 70/100（良好 🟡）
  核心扣分: Issue 响应慢 -25 (avg 8天), 贡献者活跃度低 -25 (仅1位活跃)
  辅助扣分: Issue 积压 -10 (当前 25 个)

Issue 响应时间:
  平均 4.2 天, 中位数 2.1 天, 积压 25 个

PR 合并效率:
  平均 1.8 天, 中位数 0.9 天, 积压 12 个, 合并率 85%

贡献者活跃度:
  总贡献者 5, 总 commits 247
  前三: mengcheng(120), zzx-coder(65), wbtiger(40)
  集中度: mengcheng 占 48.6%（正常）
```

## References

- [collect-data](collect-data.md) — 数据收集步骤
- [generate-report](generate-report.md) — 报告生成和输出
- [SKILL.md](../SKILL.md) — 评分规则速查表
