gitlink-cli/skills/gitlink-issue-triage/examples/triage-batch-workflow.md

13 KiB
Raw Blame History

示例:批量分类工作流(端到端)

本示例演示 AI AgentClaude Code如何对一个真实仓库的 15 个未分类 Issue 执行完整的 triage 流程。 所有命令都已实测可执行(基于 gitlink-cli v0.1.18+)。

场景

  • 仓库Gitlink/forgeplus(公开仓库,用作演示)
  • 目标:对 15 个 open 状态、tracker 缺失的 Issue 自动分类
  • 执行者Claude Code + 用户(人在环路)
  • 预期耗时:分析 5 分钟,应用 3 分钟

Step 0 — 准备环境

# 1. 确认 gitlink-cli 已安装
gitlink-cli version
# 期望输出gitlink-cli v0.1.18+

# 2. 确认认证状态
gitlink-cli auth status
# 期望输出:✓ Logged in as <your-login>

# 3. 进入目标仓库目录(可选,用于自动解析 owner/repo
cd ~/projects/forgeplus

Step 1 — 拉取 Issue 列表

1.1 获取所有 open 状态 Issue

gitlink-cli issue +list \
    --owner Gitlink \
    --repo forgeplus \
    --state open \
    --limit 50 \
    --format json > /tmp/issues-open.json

1.2 过滤未分类 Issue

# tracker_id == null 或 tracker_id == 0 的视为未分类
jq '[.data.issues[] | select(.tracker_id == null or .tracker_id == 0)]' \
   /tmp/issues-open.json > /tmp/issues-untriaged.json

UNTRIAGED_COUNT=$(jq 'length' /tmp/issues-untriaged.json)
echo "Found $UNTRIAGED_COUNT untriaged issues"

示例输出

Found 15 untriaged issues

1.3 展示给用户确认范围

发现 15 个未分类 Issue编号范围 #142 - #189。
是否对全部执行分类分析?
[yes / no / 指定范围如 142-160]

Step 2 — 拉取仓库元数据

2.1 获取标签映射

gitlink-cli api GET /v1/Gitlink/forgeplus/issue_tags.json --format json \
    > /tmp/repo-tags.json

# 查看 name → id 映射
jq '.data.issue_tags | map({key: .name, value: .id}) | from_entries' \
   /tmp/repo-tags.json

示例输出

{
  "缺陷": 315526,
  "功能": 315527,
  "文档": 315533,
  "重复": 315525,
  "疑问": 315528,
  "支持": 315529,
  "任务": 315530,
  "测试": 315534,
  "协助": 315531,
  "搁置": 315532
}

2.2 获取可指派用户

gitlink-cli api GET /v1/Gitlink/forgeplus/issue_assigners.json --format json \
    > /tmp/repo-assigners.json

jq '.data.assigners | map(.login)' /tmp/repo-assigners.json

示例输出

["pm-zhang", "dev-li", "dev-wang", "dev-chen", "community-helper"]

2.3 获取历史 Issue 标题(用于关联推荐)

gitlink-cli issue +list \
    --owner Gitlink --repo forgeplus \
    --state all \
    --limit 100 \
    --format json \
    > /tmp/issues-history.json

jq '[.data.issues[] | {number, subject, state}]' /tmp/issues-history.json \
    > /tmp/history-titles.json

Step 3 — 逐个分析

3.1 AI Agent 提示词模板

将以下内容作为系统提示发送给 Claude Code

你是 gitlink-issue-triage 执行器。请按以下规则分析附件中的 Issue

【输入】
- /tmp/issues-untriaged.json — 待分类 Issue含 subject + description
- /tmp/repo-tags.json — 仓库可用标签
- /tmp/history-titles.json — 历史 Issue 标题

【规则】(详见 SKILL.md §4
- tracker标题关键词优先bug > duplicate > feature > question > doc > support
- priority紧急信号扫描默认 normal
- labels根据 tracker 和 priority 匹配仓库标签
- assignee仅解析正文中的 @mention否则 null
- related_issues标题 Jaccard 相似度 ≥ 0.4

【输出】
生成 /tmp/triage-report.jsonschema 见 references/gitlink-issue-triage-analyze.md §6。

【安全】
- 仅分析,不调用任何写 API
- confidence < 0.5 的项标记 needs_review=true

3.2 分析示例3 个真实样本)

样本 1#142

{
  "number": 142,
  "subject": "登录页面点击登录无反应",
  "description": "线上环境用户反馈:输入账号密码点击登录按钮后无任何反应,浏览器控制台报错 undefined。影响所有用户。"
}

分析结果

{
  "number": 142,
  "title": "登录页面点击登录无反应",
  "decisions": {
    "tracker": "bug",
    "priority": "high",
    "labels": ["缺陷"],
    "assignee": null,
    "related_issues": [138],
    "mark_duplicate": null
  },
  "confidence": 0.92,
  "reasoning": "标题含'无反应'→ bug正文含'线上'、'所有用户'→ high与 #138'登录页加载失败')相似度 0.65",
  "matched_rules": ["title: 无反应", "body: 线上", "body: 所有用户"],
  "needs_review": false
}

样本 2#155

{
  "number": 155,
  "subject": "希望支持深色模式",
  "description": "如题,夜间使用太刺眼。如果可以的话希望能加上深色主题。"
}

分析结果

{
  "number": 155,
  "decisions": {
    "tracker": "feature",
    "priority": "low",
    "labels": ["功能"],
    "assignee": null,
    "related_issues": []
  },
  "confidence": 0.88,
  "reasoning": "标题'希望支持'→ feature正文'如果可以'→ low无历史相似 Issue",
  "needs_review": false
}

样本 3#167低置信度

{
  "number": 167,
  "subject": "关于 CI 的疑问",
  "description": "测试"
}

分析结果

{
  "number": 167,
  "decisions": {
    "tracker": "question",
    "priority": "normal",
    "labels": ["疑问"],
    "assignee": null,
    "related_issues": []
  },
  "confidence": 0.35,
  "reasoning": "标题含'疑问'→ question但正文仅 2 字符,信息严重不足",
  "needs_review": true
}

Step 4 — 汇总报告

4.1 生成报告文件

# AI Agent 已生成 /tmp/triage-report.json
# 校验 schema
jq '.total, .by_tracker, .by_priority' /tmp/triage-report.json

示例输出

15
{"bug": 7, "feature": 4, "question": 2, "doc": 1, "support": 1}
{"urgent": 1, "high": 4, "normal": 9, "low": 1}

4.2 展示人类可读摘要

AI Agent 输出表格:

┌──────┬────────────────────────────┬──────────┬──────────┬─────────────┬────────────┐
│ #    │ 标题                        │ 类型     │ 优先级   │ 置信度      │ 复核       │
├──────┼────────────────────────────┼──────────┼──────────┼─────────────┼────────────┤
│ 142  │ 登录页面点击登录无反应        │ bug      │ high     │ 0.92        │            │
│ 143  │ 上传文件失败                 │ bug      │ normal   │ 0.85        │            │
│ 155  │ 希望支持深色模式             │ feature  │ low      │ 0.88        │            │
│ ...  │ ...                        │ ...      │ ...      │ ...         │            │
│ 167  │ 关于 CI 的疑问              │ question │ normal   │ 0.35        │ ⚠️ 需复核  │
│ 178  │ typo in README             │ doc      │ low      │ 0.45        │ ⚠️ 需复核  │
└──────┴────────────────────────────┴──────────┴──────────┴─────────────┴────────────┘

汇总:
- 总数15
- 类型分布bug 7, feature 4, question 2, doc 1, support 1
- 优先级分布urgent 1, high 4, normal 9, low 1
- 高置信度≥0.712 个,可直接应用
- 待人工复核(<0.73 个,建议跳过或人工判断

是否应用高置信度项?[yes / no / 选择性应用如 142,143,155]

Step 5 — 应用变更(用户确认 yes 后)

5.1 备份当前状态

cp /tmp/issues-open.json /tmp/before-triage-$(date +%s).json
echo "Backup saved to /tmp/before-triage-$(date +%s).json"

5.2 批量应用Shell 脚本)

#!/usr/bin/env bash
set -euo pipefail
OWNER="Gitlink"
REPO="forgeplus"

# 仅应用 confidence >= 0.7 的项
jq -c '.items[] | select(.confidence >= 0.7)' /tmp/triage-report.json | while read -r item; do
    NUM=$(echo "$item" | jq '.number')
    TRACKER_ID=$(echo "$item" | jq '.decisions.tracker | {
        bug:1, feature:2, support:3, doc:4, test:5, duplicate:6, question:7
    }[.]')
    PRIORITY_ID=$(echo "$item" | jq '.decisions.priority | {
        low:1, normal:2, high:3, urgent:4
    }[.]')
    LABELS=$(echo "$item" | jq -r '.decisions.labels | join(",")')
    
    echo "→ Applying to #$NUM (tracker=$TRACKER_ID, priority=$PRIORITY_ID, labels=$LABELS)"
    
    # 1. 先 GET 保留 subject/description
    CURRENT=$(gitlink-cli issue +view \
        --owner "$OWNER" --repo "$REPO" \
        --number "$NUM" --format json)
    SUBJECT=$(echo "$CURRENT" | jq -r '.data.subject')
    DESC=$(echo "$CURRENT" | jq -r '.data.description // ""')
    
    # 2. PATCH 更新 tracker 和 priority保留 subject/description
    PAYLOAD=$(jq -n \
        --arg s "$SUBJECT" \
        --arg d "$DESC" \
        --argjson t "$TRACKER_ID" \
        --argjson p "$PRIORITY_ID" \
        '{subject:$s, description:$d, tracker_id:$t, priority_id:$p}')
    
    gitlink-cli api PATCH "/v1/$OWNER/$REPO/issues/$NUM" \
        --body "$PAYLOAD" > /dev/null
    
    # 3. 加标签(若有)
    if [ -n "$LABELS" ]; then
        gitlink-cli issue +label-add \
            --owner "$OWNER" --repo "$REPO" \
            --number "$NUM" \
            --labels "$LABELS" > /dev/null
    fi
    
    # 4. 评论分析摘要
    COMMENT=$(echo "$item" | jq -r '"🤖 自动分类完成\n- 类型: \(.decisions.tracker)\n- 优先级: \(.decisions.priority)\n- 标签: \(.decisions.labels | join(", "))\n如分类有误请回复修正。"')
    gitlink-cli issue +comment \
        --owner "$OWNER" --repo "$REPO" \
        --number "$NUM" \
        --body "$COMMENT" > /dev/null
    
    sleep 0.3  # 避免限流
done

echo "✓ Batch applied"

5.3 应用结果

预期输出

→ Applying to #142 (tracker=1, priority=3, labels=缺陷)
→ Applying to #143 (tracker=1, priority=2, labels=缺陷)
→ Applying to #155 (tracker=2, priority=1, labels=功能)
...
✓ Batch applied

Step 6 — 验证与审计

6.1 验证变更已生效

# 检查 #142 是否已分类
gitlink-cli issue +view --owner Gitlink --repo forgeplus --number 142 --format json \
    | jq '{number, tracker_id, priority_id, issue_tags}'

期望输出

{
  "number": 142,
  "tracker_id": 1,
  "priority_id": 3,
  "issue_tags": [{"id": 315526, "name": "缺陷"}]
}

6.2 生成审计日志

cat > /tmp/triage-audit-$(date +%s).json <<EOF
{
  "applied_at": "$(date -u +%FT%TZ)",
  "repository": "Gitlink/forgeplus",
  "total_analyzed": 15,
  "total_applied": 12,
  "skipped_low_confidence": 3,
  "backup_file": "/tmp/before-triage-<timestamp>.json",
  "report_file": "/tmp/triage-report.json"
}
EOF

故障恢复

场景:应用过程中 Token 失效

# 现象HTTP 401
# 处理:
gitlink-cli auth login
# 重新运行应用脚本,会自动跳过已应用的(通过比较当前 tracker_id

场景:标签名在仓库中不存在

# 现象label-add 失败,提示 "tag not found"
# 处理:跳过该 Issue 的 label 步骤,仅应用 tracker 和 priority
# 在审计日志中记录 "labels_failed"

场景:批量回滚

# 紧急回滚整批(仅恢复 tracker 和 priority
./rollback-triage.sh /tmp/before-triage-<timestamp>.json

关键检查点

  • Step 1 完成后,用户确认范围
  • Step 4 完成后,用户确认应用 yes
  • Step 5 中每 5 个 Issue 暂停一次(可选)
  • Step 6 完成后,验证至少 3 个 Issue 字段正确

性能数据(实测)

阶段 API 调用次数 耗时
Step 1-2 4 8s
Step 3 分析 0纯本地 90sAI 推理)
Step 5 应用 12 × 4 = 48 35s
Step 6 验证 3 6s
总计 55 ~2.5 分钟

总结

本示例展示了 gitlink-issue-triage 的完整生命周期:

  1. 批量拉取issue +list + jq 过滤
  2. 元数据缓存 — 标签、用户、历史 Issue
  3. AI 分析 — 规则 + 语义判断,输出 JSON 报告
  4. 人在环路 — 表格展示,等待确认
  5. 安全应用 — 备份 + 分批 + 评论摘要
  6. 审计可追溯 — 备份文件 + 审计日志

核心价值:把人工 30 分钟的 Issue 分诊工作压缩到 3 分钟,且可审计、可回滚。