# gitlink-issue-triage — 分析算法详解

> 本文档面向 **AI Agent 开发者** 和 **想理解决策细节的工程师**。
> 普通使用者只需阅读 [SKILL.md](../SKILL.md) 即可。

## 1. 输入数据

### 1.1 Issue 字段（来自 `issue +view --format json`）

```json
{
  "number": 142,                    // project_issues_index，网页 URL 中的序号
  "subject": "登录页面点击登录无反应",
  "description": "线上环境用户反馈...",
  "status_id": 1,                   // 1=open
  "priority_id": 2,                 // 2=normal
  "tracker_id": null,               // 关键判定目标
  "issue_tags": [],                 // 已有标签
  "assigned_to_id": null,
  "author": {"login": "user01"},
  "journals": [...]                 // 评论历史
}
```

### 1.2 仓库元数据

| API | 用途 |
|-----|------|
| `GET /v1/:owner/:repo/issue_tags.json` | 仓库可用标签 name→id 映射 |
| `GET /v1/:owner/:repo/issue_assigners.json` | 可指派用户列表 |
| `GET /v1/:owner/:repo/issues.json?state=all&limit=100` | 历史 Issue 标题（用于关联推荐） |

---

## 2. 决策流水线

```
Issue JSON
    │
    ▼
┌─────────────────────────────┐
│ Stage A: 文本预处理           │
│ - 拼接 subject + description │
│ - 全角转半角                  │
│ - 大小写归一化                │
└────────────┬────────────────┘
             ▼
┌─────────────────────────────┐
│ Stage B: tracker 决策         │
│ - 标题规则集（高优先级）       │
│ - 正文规则集（低优先级）       │
│ - 多命中按优先级排序           │
└────────────┬────────────────┘
             ▼
┌─────────────────────────────┐
│ Stage C: priority 决策        │
│ - 严重度信号扫描              │
│ - 默认 normal                 │
└────────────┬────────────────┘
             ▼
┌─────────────────────────────┐
│ Stage D: 标签建议             │
│ - 仓库标签语义匹配            │
│ - 缺失则跳过                  │
└────────────┬────────────────┘
             ▼
┌─────────────────────────────┐
│ Stage E: assignee 建议        │
│ - @mention 解析              │
│ - 否则 null                   │
└────────────┬────────────────┘
             ▼
┌─────────────────────────────┐
│ Stage F: related_issues 推荐  │
│ - 关键词 Jaccard 相似度       │
│ - Top-3 + duplicate 检测     │
└────────────┬────────────────┘
             ▼
┌─────────────────────────────┐
│ Stage G: confidence 计算      │
│ - 规则命中数 / 总信号数       │
│ - < 0.5 标记需人工复核        │
└─────────────────────────────┘
```

---

## 3. 完整关键词规则表

### 3.1 Tracker 规则（按优先级降序）

```yaml
# bug（tracker_id: 1）
bug:
  title_patterns:
    - "bug"
    - "错误"
    - "失败"
    - "崩溃"
    - "异常"
    - "报错"
    - "不能"
    - "无法"
    - "crash"
    - "error"
    - "exception"
    - "broken"
    - "不工作"
    - "无反应"
  body_patterns:
    - "复现步骤"
    - "重现"
    - "stack trace"
    - "回归"

# duplicate（tracker_id: 6，优先级仅次于 bug）
duplicate:
  title_patterns:
    - "重复"
    - "duplicate"
    - "same as"
    - "已经提过"
  body_patterns:
    - "和 #\\d+ 一样"
    - "同 #\\d+"

# feature（tracker_id: 2）
feature:
  title_patterns:
    - "feature"
    - "希望"
    - "建议"
    - "新增"
    - "支持.*吗"
    - "能否添加"
    - "enhancement"
    - "proposal"
    - "想要"
    - "如果可以"
  body_patterns:
    - "use case"
    - "use-case"
    - "应用场景"

# question（tracker_id: 7）
question:
  title_patterns:
    - "怎么"
    - "如何"
    - "哪里"
    - "？"
    - "?"
    - "请问"
    - "question"
    - "help"
  body_patterns:
    - "我刚开始用"
    - "新手"
    - "文档没写"

# doc（tracker_id: 4）
doc:
  title_patterns:
    - "文档"
    - "README"
    - "教程"
    - "doc"
    - "typo"
    - "拼写"
    - "错别字"
  body_patterns:
    - "文档不全"
    - "示例无法运行"

# support（tracker_id: 3）
support:
  title_patterns:
    - "支持"
    - "求助"
    - "support"
    - "咨询"
    - "如何配置"
```

### 3.2 Priority 规则

```yaml
urgent:
  patterns:
    - "紧急"
    - "urgent"
    - "ASAP"
    - "线上"
    - "production"
    - "数据丢失"
    - "数据泄露"
    - "安全"
    - "security"
    - "CVE"
    - "RCE"
    - "越权"

high:
  patterns:
    - "重要"
    - "阻塞"
    - "block"
    - "无法工作"
    - "完全不能用"
    - "high"
    - "所有用户"
    - "全员受影响"

low:
  patterns:
    - "minor"
    - "小问题"
    - "nice to have"
    - "低优"
    - "不急"
    - "建议"
    - "锦上添花"

# 默认 normal（无任何上述信号）
```

---

## 4. 置信度计算

```python
confidence = 0.0
signals = 0

# tracker 决策信号
if title_match:
    confidence += 0.4
    signals += 1
if body_match:
    confidence += 0.2
    signals += 1
if multiple_match_conflict:
    confidence -= 0.15

# priority 决策信号
if urgent_or_high_signal:
    confidence += 0.2
    signals += 1

# 关联 Issue 强信号
if duplicate_score >= 0.7:
    confidence += 0.15
    signals += 1

# 描述长度（信息量）
if len(description) < 20:
    confidence -= 0.2  # 信息不足

# AI 语义判断的额外加权
if ai_semantic_decision:
    confidence += 0.1

# 归一化到 [0, 1]
confidence = max(0, min(1, confidence))
```

**阈值**：
- `confidence >= 0.7` → 直接应用
- `0.5 <= confidence < 0.7` → 应用但标记"建议复核"
- `confidence < 0.5` → **不应用**，仅放入"待人工"队列

---

## 5. 关联 Issue 算法

### 5.1 文本预处理

```python
def tokenize(text):
    # 中文：2-gram 字符切片
    # 英文：小写化 + 词形还原
    # 去停用词（"的", "了", "the", "a", "an", ...）
    tokens = set()
    # ... implementation
    return tokens
```

### 5.2 Jaccard 相似度

```python
def jaccard(a: set, b: set) -> float:
    if not a or not b:
        return 0.0
    return len(a & b) / len(a | b)
```

### 5.3 关联决策

| 相似度 | 决策 |
|--------|------|
| ≥ 0.7 且一方已关闭 | 推荐 mark as duplicate |
| ≥ 0.7 双方都开 | 评论"可能与 #X 相关" |
| 0.4 - 0.7 | 列入"可能相关"，由人工判断 |
| < 0.4 | 不关联 |

---

## 6. 输出 Schema

完整分析报告遵循以下 JSON Schema（简化版）：

```json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["repository", "analyzed_at", "total", "items"],
  "properties": {
    "repository": {"type": "string", "pattern": "^[^/]+/[^/]+$"},
    "analyzed_at": {"type": "string", "format": "date-time"},
    "total": {"type": "integer", "minimum": 0},
    "by_tracker": {
      "type": "object",
      "additionalProperties": {"type": "integer"}
    },
    "by_priority": {
      "type": "object",
      "additionalProperties": {"type": "integer"}
    },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["number", "title", "decisions", "confidence"],
        "properties": {
          "number": {"type": "integer"},
          "title": {"type": "string"},
          "current_tracker": {"type": ["string", "null"]},
          "current_labels": {"type": "array", "items": {"type": "string"}},
          "decisions": {
            "type": "object",
            "required": ["tracker", "priority"],
            "properties": {
              "tracker": {"type": "string", "enum": ["bug", "feature", "support", "doc", "test", "duplicate", "question"]},
              "priority": {"type": "string", "enum": ["low", "normal", "high", "urgent"]},
              "labels": {"type": "array", "items": {"type": "string"}},
              "assignee": {"type": ["string", "null"]},
              "related_issues": {"type": "array", "items": {"type": "integer"}},
              "mark_duplicate": {"type": ["integer", "null"]}
            }
          },
          "confidence": {"type": "number", "minimum": 0, "maximum": 1},
          "reasoning": {"type": "string"},
          "matched_rules": {"type": "array", "items": {"type": "string"}},
          "needs_review": {"type": "boolean"}
        }
      }
    }
  }
}
```

---

## 7. 边界情况处理

| 情况 | 处理 |
|------|------|
| Issue 无正文 | confidence 上限 0.5；强制 needs_review=true |
| 标题过长（> 100 字） | 截取前 50 字做匹配 |
| 标题全英文 | 跳过中文规则，仅用英文规则 |
| 仓库无任何标签 | 跳过 Stage D，在报告中提示 |
| @mention 用户不在 assigners 列表 | 不指派，提示"权限不足" |
| 历史 Issue < 5 个 | 跳过关联推荐 |
| 已有 tracker 的 Issue | 默认不覆盖，除非用户加 `--force` |

---

## 8. 性能建议

| 规模 | 建议 |
|------|------|
| ≤ 20 个 Issue | 单次分析，内存缓存元数据 |
| 20-100 个 | 分批 20/批，每批后用户确认 |
| > 100 个 | 强制分批，每批 20，建议夜间运行 |

API 调用次数估算：`N * 1 (view) + 3 (元数据) + N * 0.3 (平均关联)` ≈ `1.3N + 3`。

---

## 9. 参考实现

伪代码（Python-like）：

```python
def triage_issue(issue, repo_meta, history):
    text = normalize(issue.subject + " " + issue.description)
    
    # Stage B: tracker
    tracker, tracker_rules = decide_tracker(text)
    
    # Stage C: priority
    priority, priority_rules = decide_priority(text)
    
    # Stage D: labels
    labels = match_labels(tracker, priority, repo_meta.tags)
    
    # Stage E: assignee
    assignee = parse_mention(issue.description, repo_meta.assigners)
    
    # Stage F: related
    related, duplicate = find_related(issue, history)
    
    # Stage G: confidence
    confidence = compute_confidence(
        tracker_rules, priority_rules, duplicate, len(issue.description)
    )
    
    return {
        "number": issue.number,
        "decisions": {
            "tracker": tracker,
            "priority": priority,
            "labels": labels,
            "assignee": assignee,
            "related_issues": related,
            "mark_duplicate": duplicate,
        },
        "confidence": confidence,
        "matched_rules": tracker_rules + priority_rules,
        "needs_review": confidence < 0.7,
    }
```

完整可运行实现请参考 [examples/triage-batch-workflow.md](../examples/triage-batch-workflow.md) 中的 AI Agent 提示词。
