gitlink-cli/skills/gitlink-stale/SKILL.md

18 KiB
Raw Blame History

name version description metadata
gitlink-stale 1.0.0 Stale Issue/PR 自动处理:识别长期未活动的 Issue/PR标记 stale 标签、通知相关者、过期自动关闭。当用户需要清理堆积 Issue/PR、定期巡检仓库、或想仿照 GitHub stale-bot 行为时触发。
requires cliHelp
bins
gitlink-cli
gitlink-cli issue --help

gitlink-staleStale Issue/PR 自动处理)

CRITICAL — 开始前必须先阅读 ../gitlink-shared/SKILL.md,其中包含认证、权限处理和 API 注意事项。 CRITICAL — 所有"标记/评论/关闭"动作默认 dry-run只有用户明确确认后才执行写入。 CRITICAL — GitLink 操作只能用 gitlink-cli。禁止用 ghGitHub CLI操作 GitLink 资源。

前置依赖: 先阅读 ../gitlink-issue/SKILL.md 了解 Issue 基础操作和字段映射,../gitlink-pr/SKILL.md 了解 PR 基础操作。


1. 这个 Skill 做什么?

gitlink-stale 是一个 AI Agent 驱动的长期未活动 Issue/PR 处理工作流,解决开源/协作项目中常见的"Issue/PR 堆积无人理"问题:

  • 🔍 扫描识别:找出 N 天未活动的 Issue/PR默认 60 天)
  • 🧠 AI 智能判断:区分"真僵尸"和"等维护者回复"(不是简单按时间一刀切)
  • 🏷️ 自动打 stale 标签:通知作者/相关者
  • 💬 友好催办评论:避免简单粗暴的"过期警告"
  • 🔒 过期自动关闭:超过宽限期(默认 14 天)仍未响应才关闭
  • 🛡️ 白名单豁免pinned/security/roadmap 等关键 Issue 永不处理
  • Dry-run 优先:所有写入操作默认预览,确认后才落地

适合所有 Issue/PR 长期堆积的开源项目或团队仓库,承担类似 GitHub stale bot 的角色,但通过 AI Agent 实现"人在环路"和"智能判断"。


2. 工作流总览

                 ┌─────────────────────────────────┐
                 │ Step 1: 扫描候选列表              │
                 │   issue +list --state open       │
                 │   pr +list --state open          │
                 └────────────┬────────────────────┘
                              ▼
       ┌──────────────────────────────────────────────┐
       │ Step 2: 时间过滤                              │
       │   now - updated_at > stale_days (默认 60)    │
       │   排除白名单pinned/security/roadmap/...  │
       └────────────┬─────────────────────────────────┘
                    ▼
       ┌──────────────────────────────────────────────┐
       │ Step 3: AI 智能分类(核心差异化)             │
       │   - 是否仍在等维护者回复?                    │
       │   - 是否是关键功能/路线图?                   │
       │   - 是否历史活跃度高?                       │
       │   - 输出 confidence + recommendation         │
       └────────────┬─────────────────────────────────┘
                    ▼
       ┌──────────────────────────────────────────────┐
       │ Step 4: 生成处理计划dry-run               │
       │   {                                          │
       │     issue_id: 142,                           │
       │     action: "mark_stale",                    │
       │     reason: "60 天未活动",                   │
       │     confidence: 0.85                         │
       │   }                                          │
       └────────────┬─────────────────────────────────┘
                    ▼
       ┌──────────────────────────────────────────────┐
       │ Step 5: 用户确认 → 执行                       │
       │   issue +label-add --label stale             │
       │   issue +comment --body "..."                │
       │   过宽限期: issue +close                     │
       └──────────────────────────────────────────────┘

3. Shortcuts 与 Raw API 速查

本 Skill 复用 gitlink-cli 已有命令,不新增 shortcut,确保单一可信源。

3.1 读操作(只读,可放心使用)

命令 用途
issue +list --state open --format json 获取 open Issue 列表
issue +view --number <N> --format json 获取 Issue 详情(含 journals 评论历史)
issue +label-list --number <N> --format json 查看 Issue 当前标签
pr +list --state open --format json 获取 open PR 列表(注意需客户端按 pull_request_status: 0 二次过滤)
pr +view --id <N> --format json 获取 PR 详情
api GET /v1/:owner/:repo/issue_tags.json 获取仓库标签name→id 映射)

3.2 写操作(默认 dry-run确认后执行

命令 用途
issue +label-add --number <N> --labels "stale" 给 Issue 打 stale 标签
issue +label-remove --number <N> --label "stale" 移除 stale 标签(用户回复后恢复)
issue +comment --number <N> --body "<text>" 评论催办/关闭说明
issue +close --number <N> 关闭 Issue
issue +batch-close --numbers <csv> --dry-run 批量关闭预览
pr +comment --id <N> --body "<text>" 给 PR 评论

⚠️ PR 标签GitLink PR 端点暂不支持 PR 维度的 label 操作,对 PR 只评论、不打标签;若需要"PR stale 标签",在评论正文中显式写"⚠️ Stale"。


4. 核心算法AI 智能判断)

这是本 Skill 与"简单按时间一刀切"工具的核心差异。 AI Agent 应优先遵循以下规则,对规则无法覆盖的情况使用语义判断。

4.1 三阶段判断流水线

Issue/PR JSON
    │
    ▼
┌─────────────────────────────────┐
│ Stage A: 时间扫描                │
│ - days_inactive = now - updated │
│ - 默认阈值: 60 天                │
└────────────┬────────────────────┘
             ▼
┌─────────────────────────────────┐
│ Stage B: 白名单豁免              │
│ - 含 pinned/security 等标签 → 跳过│
│ - tracker 是 roadmap/epic → 跳过 │
└────────────┬────────────────────┘
             ▼
┌─────────────────────────────────┐
│ Stage C: AI 真假僵尸判断         │
│ - 评论历史分析                   │
│ - 等维护者回复?等用户回复?      │
│ - 输出 truly_stale + confidence  │
└─────────────────────────────────┘

4.2 时间计算

关键字段updated_atIssue 最后活动时间,包括评论、状态变更、字段修改)

days_inactive = (now_utc - parse(issue.updated_at)).days

# 阈值(可通过参数自定义)
if days_inactive >= close_threshold:    # 默认 74 天60 + 14 宽限期)
    candidate_action = "auto_close"
elif days_inactive >= stale_threshold:  # 默认 60 天
    candidate_action = "mark_stale"
else:
    candidate_action = None  # 不处理

⚠️ GitLink API 已知行为updated_at 字段在某些 Issue 上可能缺失或时区异常。降级策略:取 journals 数组最后一条的 created_at 作为最后活动时间。

4.3 白名单豁免规则

满足任一条件即跳过处理:

信号 说明
pinned/置顶 标签 重要 Issue
security/安全 标签 安全相关
roadmap/路线图 标签 长期规划
epic/里程碑 标签 大任务
tracker_id 是 roadmap 类型 路线图类
priority_id == 4 (urgent) 紧急任务
标题含 [Keep Open]/[Pinned] 显式标记
作者仍是仓库活跃成员 信任作者会跟进

4.4 AI 真假僵尸判断Stage C 核心)

关键差异化:不是简单的"时间到了就标记",而是 AI 判断是否真的应该处理。

判断信号

信号类型 僵尸(应处理) 活跃(应跳过)
评论历史 维护者 0 回复,或仅"已知问题"占位 维护者最近 30 天内回复过
Issue 类型 bug/feature/小需求,需要明确动作 question/讨论类,已自然结束
标签 无标签或仅 stale in-progress/under-review
评论数 0 评论,长期无人理 ≥5 评论,有讨论
作者活跃度 0 issue 历史,可能是路过用户 资深贡献者,会跟进
关键词 "测试"、"占位"、"无复现" "正在处理"、"待 v2"、"等待上游"

AI 决策输出

{
  "issue_number": 142,
  "title": "...",
  "last_activity": "2026-04-15T10:30:00Z",
  "days_inactive": 62,
  "ai_analysis": {
    "truly_stale": true,
    "confidence": 0.85,
    "reason": "用户最后回复 60 天前维护者无回复0 评论,作者仅此 1 个 Issue",
    "exempt": false
  },
  "recommended_action": "mark_stale",
  "next_review_date": "2026-06-30"
}

4.5 置信度阈值

confidence 建议动作
≥ 0.8 直接列入"建议执行"清单
0.6 - 0.8 列入"建议执行",但报告中标记"建议人工复核"
< 0.6 不自动处理,仅列入"待人工判断"队列

5. 标准工作流AI Agent 执行模板)

AI Agent 看这里:以下是你被请求"清理 stale Issue/PR"时应遵循的标准流程。

Step 1 — 确认范围与参数

# 默认参数(可被用户覆盖)
# - stale_threshold: 60 天
# - close_threshold: 74 天60 + 14 宽限期)
# - batch_size: 20 个/批

# 确认 owner/repo
gitlink-cli issue +list --state open --limit 5 --format json

向用户确认:"要扫描哪个仓库阈值用默认60 天标记/74 天关闭)还是自定义?想一批处理多少个?"

Step 2 — 拉取候选列表

# Issue 候选
gitlink-cli issue +list \
    --owner <owner> --repo <repo> \
    --state open \
    --limit 100 \
    --format json > /tmp/issues-open.json

# PR 候选
gitlink-cli pr +list \
    --owner <owner> --repo <repo> \
    --state open \
    --format json > /tmp/prs-open.json

Step 3 — 拉取仓库标签(用于白名单判断)

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

Step 4 — 逐个分析

对每个候选项:

# Issue 详情(含 journals
gitlink-cli issue +view --number <N> --format json

# PR 详情
gitlink-cli pr +view --id <N> --format json

应用第 4 节判断规则,生成分析结果。

Step 5 — 汇总报告

把所有候选项的分析结果合并:

{
  "repository": "owner/repo",
  "scanned_at": "2026-06-23T10:00:00Z",
  "thresholds": {
    "stale_days": 60,
    "close_days": 74
  },
  "summary": {
    "total_open_issues": 85,
    "total_open_prs": 12,
    "stale_candidates": 23,
    "close_candidates": 8,
    "exempt": 15,
    "needs_review": 4
  },
  "items": [
    /* 每个候选项的详细分析 */
  ]
}

用表格形式向用户展示摘要(人类可读),等待用户确认。

Step 6 — 应用动作(用户确认后)

按推荐动作执行:

# 动作 A标记 stale
gitlink-cli issue +label-add --number 142 --labels "stale"
gitlink-cli issue +comment --number 142 --body "⏰ 本 Issue 已 60 天无活动..."

# 动作 B自动关闭超过宽限期
gitlink-cli issue +label-add --number 142 --labels "stale"
gitlink-cli issue +comment --number 142 --body "🔒 本 Issue 已 74 天无活动,自动关闭..."
gitlink-cli issue +close --number 142

# 动作 CPR 催办(不打标签,仅评论)
gitlink-cli pr +comment --id 8 --body "⏰ 本 PR 已 60 天无活动..."

6. 催办评论模板

6.1 标记 stale友好版非警告

**长期未活动提醒**

本 Issue 已 60 天未收到新回复,暂时标记为 `stale`- 如果**仍然相关**,请回复任意内容,会自动移除 stale 标签
- 如果**已经过时**,欢迎手动关闭
- 如果在 **14 天内**没有新活动,将自动关闭以保持 Issue 列表清爽

> 🤖 由 gitlink-stale skill 自动生成。如有疑问请联系 @维护者。

6.2 自动关闭(礼貌版)

🔒 **自动关闭(长期未活动)**

本 Issue 自标记 stale 后 14 天内仍未收到新回复,自动关闭。

- 如问题仍然存在,请**重新打开**并补充最新信息
- 如需长期保留,可打上 `pinned` 标签豁免巡检

> 🤖 由 gitlink-stale skill 自动关闭。原始讨论保留在历史中。

6.3 PR 催办

**PR 长期未活动**

本 PR 已 60 天未更新,可能存在以下情况:

- 合并遇到冲突?请 rebase 后重新推送
- 等待 review@mention 相关维护者
- 不再需要?欢迎手动关闭

如果 **14 天内**没有新活动,将默认关闭。

7. 安全规则

规则 说明
Dry-run 优先 分析阶段只读,不调用任何写 API
用户确认 应用变更前必须展示报告并征得同意
白名单豁免 pinned/security/roadmap 永不动
AI 双重判断 不仅看时间,还要 AI 判断"真僵尸"
小批量 一批不超过 20 个,超 50 强制分批
低置信度跳过 confidence < 0.6 不自动处理
可回滚 记录原始标签和状态,便于撤销
禁止 批量关闭超过 50 个 Issue 而不分批确认
禁止 跳过 dry-run 直接执行

8. 回滚策略

8.1 备份原始状态

# 应用前导出当前 Issue 状态
gitlink-cli issue +list --state open --format json > /tmp/before-stale-$(date +%s).json

8.2 单 Issue 回滚

# 误标的 Issue移除 stale 标签 + 道歉评论
gitlink-cli issue +label-remove --number 142 --label "stale"
gitlink-cli issue +comment --number 142 --body "抱歉,刚刚的 stale 标记是误判,已恢复。"

8.3 误关闭的 Issue 恢复

# 重新打开(用 Raw API因 gitlink-cli +update 需要状态参数)
gitlink-cli api PATCH /v1/<owner>/<repo>/issues/142 \
    --body '{"subject":"<原>","description":"<原>","status_id":1}'  # 1=open
gitlink-cli issue +label-remove --number 142 --label "stale"

9. 与现有 Skills 的关系

Skill 关系
gitlink-shared 前置必读:认证、错误处理、安全规则
gitlink-issue 基础命令来源:所有写操作通过这里的 shortcut
gitlink-pr PR 操作来源
gitlink-issue-triage 互补triage 处理"未分类"stale 处理"未活动"

10. 参考文档


11. 常见问题

Q: 为什么不用一个固定的 stale-bot 配置文件? A: 因为不同 Issue 的"重要程度"差异巨大。AI Agent 可以读取评论历史判断"是否还在等维护者",比规则引擎更准。

Q: 用户回复后会自动去掉 stale 标签吗? A: 默认不会自动响应。本 Skill 是按需触发(如每周巡检),下次扫描时会看到新活动并自动跳过;如果要立刻移除,可手动调用 issue +label-remove。详见 references/gitlink-stale-actions.md §3。

Q: 一次处理多少 Issue 合适? A: 建议 10-20 个/批。超过 50 个时强制分批,每批之间用户确认。

Q: 误关了重要 Issue 怎么办? A: 见 §8.3 回滚策略。所有动作都保留原始字段快照,可重新打开。强烈建议 urgent/roadmap 类 Issue 打上对应标签加入白名单。

Q: PR 没有 label 接口怎么办? A: GitLink PR 端点暂不支持 PR 维度的标签。对 PR 只做评论催办,不打 stale 标签;如需"PR 已 stale"的视觉提示,在评论标题中显式写""或"Stale"。

Q: AI 判断和简单时间过滤冲突时怎么办? A: AI 判断优先。如果 AI 认为"仍在等维护者回复",即使超过 60 天也不打 stale 标签。所有"非规则决策"会在报告中高亮,便于人工复核。