# gitlink-issue-triage — 应用变更手册

> 本文档说明如何把分析报告中的决策**安全地**应用到 GitLink Issue。
> 所有命令默认 dry-run，确认后再去掉 `--dry-run` 实际执行。

## 1. 应用前置检查

### 1.1 备份当前状态

```bash
# 导出当前所有目标 Issue 的原始字段（用于回滚）
gitlink-cli issue +list --state open --format json > /tmp/before-triage.json
```

### 1.2 确认权限

```bash
# 检查当前用户对该仓库的写权限
gitlink-cli user +me --format json
gitlink-cli api GET /:owner/:repo --format json | jq '.data.permissions'
```

若 `permissions.push !== true`，应用变更会失败，应停止并提示用户。

---

## 2. 单 Issue 应用流程

针对报告中的每个 item：

### 2.1 应用 tracker（类型）

```bash
# 注意：GitLink v1 API 通过 tracker_id 字段更新
gitlink-cli issue +update \
    --owner <owner> \
    --repo <repo> \
    --number <N> \
    --state in-progress    # 顺带把状态从 new 改为 in-progress
```

> ⚠️ **当前 gitlink-cli 的 `+update` 不直接支持改 tracker**。
> 如需改 tracker，使用 Raw API：
>
> ```bash
> # tracker_id: 1=bug, 2=feature, 3=support, 4=doc, 5=test, 6=duplicate, 7=question
> gitlink-cli api PATCH /v1/<owner>/<repo>/issues/<N> \
>     --body '{"subject":"<原 subject>","description":"<原 description>","tracker_id":1}'
> ```
>
> **必须**先 GET 当前 Issue 拿到 `subject` 和 `description`，否则会被清空。

### 2.2 应用 priority（优先级）

```bash
# priority_id: 1=low, 2=normal, 3=high, 4=urgent
gitlink-cli api PATCH /v1/<owner>/<repo>/issues/<N> \
    --body '{"subject":"<原>","description":"<原>","priority_id":3}'
```

### 2.3 应用 labels（标签）

```bash
# 方法 A：用 +label-add（推荐，自动处理 name→id）
gitlink-cli issue +label-add \
    --owner <owner> --repo <repo> \
    --number <N> \
    --labels "缺陷,紧急"

# 方法 B：Raw API（需要预先查标签 ID）
LABEL_IDS=$(echo "缺陷,紧急" | tr ',' '\n' | while read name; do
    gitlink-cli api GET /v1/<owner>/<repo>/issue_tags.json --format json \
      | jq -r --arg n "$name" '.data.issue_tags[] | select(.name==$argn) | .id'
done | paste -sd, -)

gitlink-cli api POST /v1/<owner>/<repo>/issues/<N>/labels \
    --body "{\"labels\":\"$LABEL_IDS\"}"
```

### 2.4 应用 assignee（指派人）

> ⚠️ **默认不自动指派个人**，除非用户明确同意。
> 推荐做法：在评论中 @mention 建议由 PM 分配。

```bash
# 若用户明确要求指派：
gitlink-cli issue +update \
    --owner <owner> --repo <repo> \
    --number <N> \
    --body "<原 description>"   # 占位，update 至少要改一个字段
# 或通过 Raw API（更可控）
USER_ID=$(gitlink-cli api GET /users/<login> --format json | jq '.data.id')
gitlink-cli api PATCH /v1/<owner>/<repo>/issues/<N> \
    --body "{\"subject\":\"<原>\",\"description\":\"<原>\",\"assigned_to_id\":$USER_ID}"
```

### 2.5 应用 comment（评论 + 关联 Issue）

```bash
# 生成评论内容（Markdown）
COMMENT_BODY=$(cat <<'EOF'
🤖 **自动分类报告**

| 字段 | 决策 | 依据 |
|------|------|------|
| 类型 | bug | 标题含"无反应" |
| 优先级 | high | 正文提"线上" |
| 标签 | 缺陷, 紧急 | 仓库标签匹配 |

**关联 Issue**：可能与 #138（"登录页加载失败"）相关。

如分类有误请回复 `/triage incorrect`，我会重新分析。
EOF
)

gitlink-cli issue +comment \
    --owner <owner> --repo <repo> \
    --number <N> \
    --body "$COMMENT_BODY"
```

### 2.6 标记 duplicate（可选）

```bash
# 仅评论建议，不主动关闭
gitlink-cli issue +comment \
    --number <N> \
    --body "检测到本 Issue 与 #138 高度相似（相似度 0.82），建议维护者判断是否标记为重复。"
```

---

## 3. 批量应用模板

### 3.1 Shell 脚本（推荐）

```bash
#!/usr/bin/env bash
# apply-triage.sh — 从 report.json 应用分类决策
set -euo pipefail

OWNER="${1:?usage: apply-triage.sh <owner>/<repo> <report.json>}"
REPO="${2:?missing repo}"
REPORT="${3:?missing report.json}"

# 读取报告
TOTAL=$(jq '.total' "$REPORT")
echo "Will apply triage decisions to $TOTAL issues in $OWNER/$REPO"
read -rp "Proceed? (yes/no) " CONFIRM
[ "$CONFIRM" = "yes" ] || { echo "aborted"; exit 1; }

# 逐条应用
jq -c '.items[]' "$REPORT" | while read -r item; do
    NUM=$(echo "$item" | jq '.number')
    TRACKER=$(echo "$item" | jq -r '.decisions.tracker')
    PRIORITY=$(echo "$item" | jq -r '.decisions.priority')
    CONF=$(echo "$item" | jq '.confidence')
    
    echo "→ Issue #$NUM (tracker=$TRACKER, priority=$PRIORITY, conf=$CONF)"
    
    # 跳过低置信度
    if (( $(echo "$CONF < 0.5" | bc -l) )); then
        echo "  skipped (low confidence)"
        continue
    fi
    
    # ... 调用上面的应用命令
    
    # 避免限流
    sleep 0.5
done

echo "Done. Summary written to /tmp/after-triage.json"
```

### 3.2 AI Agent 执行模板

向 Claude Code 发送：

```
请按以下步骤应用 /tmp/triage-report.json 中的决策：

1. 读取报告，过滤 confidence < 0.5 的项
2. 对每个剩余项：
   a. 用 Raw API PATCH 更新 tracker_id 和 priority_id（注意保留 subject/description）
   b. 用 issue +label-add 添加 labels
   c. 用 issue +comment 评论分析摘要
3. 每应用 5 个后暂停，问我是否继续
4. 完成后输出统计：成功数、失败数、跳过数

任何步骤失败都不要继续，停下来问我。
```

---

## 4. 回滚策略

### 4.1 自动备份

应用前已执行：

```bash
gitlink-cli issue +list --state all --format json > /tmp/before-triage-$(date +%s).json
```

### 4.2 回滚单 Issue

```bash
# 从备份恢复原始字段
ORIGINAL=$(jq '.data.issues[] | select(.number==142)' /tmp/before-triage.json)
gitlink-cli api PATCH /v1/<owner>/<repo>/issues/142 \
    --body "$(echo "$ORIGINAL" | jq '{subject, description, tracker_id, priority_id, status_id}')"

# 移除新加的标签
gitlink-cli issue +label-remove --number 142 --label "缺陷"
gitlink-cli issue +label-remove --number 142 --label "紧急"
```

### 4.3 批量回滚

```bash
# 反向应用 before-triage.json，把每个 Issue 恢复到原始状态
# 谨慎：会丢失 triage 之后的人工修改
./apply-triage-rollback.sh <owner>/<repo> /tmp/before-triage.json
```

---

## 5. 错误处理

| 错误 | 原因 | 处理 |
|------|------|------|
| `HTTP 401` | Token 失效 | `gitlink-cli auth login` |
| `HTTP 403` | 无写权限 | 联系仓库 owner |
| `HTTP 404` | Issue 编号错或已删除 | 跳过，记录到 errors |
| `HTTP 422` | subject/description 被清空 | 必须先 GET 再 PATCH |
| `status: -1` | 参数错 | 检查 tracker_id/priority_id 数值 |

应用失败时**不要重试**，记录到错误日志，整体应用结束后人工排查。

---

## 6. 审计日志

每次应用后记录：

```json
{
  "applied_at": "2026-06-16T10:30:00Z",
  "operator": "ai-agent + human-confirm",
  "batch_id": "triage-20260616-1",
  "items_applied": [
    {
      "number": 142,
      "changes": {
        "tracker_id": {"from": null, "to": 1},
        "priority_id": {"from": 2, "to": 3},
        "labels_added": ["缺陷", "紧急"]
      },
      "success": true
    }
  ]
}
```

保存到 `/tmp/triage-audit-<timestamp>.json`，便于追溯。

---

## 7. 最佳实践

- ✅ **小批量试水**：先对 3-5 个 Issue 应用，观察结果再扩大
- ✅ **敏感词过滤**：对 urgent 决策额外人工复核
- ✅ **避开高峰**：大批量应用安排在用户活跃低谷时段
- ✅ **通知 owner**：通过 `issue +comment` 在首个 Issue 中说明"本批为自动分类"
- ❌ **禁止**：跳过 dry-run 直接批量应用
- ❌ **禁止**：对 archived 或 read-only 仓库执行
