18 KiB
| name | version | description | metadata | |||||||
|---|---|---|---|---|---|---|---|---|---|---|
| gitlink-stale | 1.0.0 | Stale Issue/PR 自动处理:识别长期未活动的 Issue/PR,标记 stale 标签、通知相关者、过期自动关闭。当用户需要清理堆积 Issue/PR、定期巡检仓库、或想仿照 GitHub stale-bot 行为时触发。 |
|
gitlink-stale(Stale Issue/PR 自动处理)
CRITICAL — 开始前必须先阅读 ../gitlink-shared/SKILL.md,其中包含认证、权限处理和 API 注意事项。
CRITICAL — 所有"标记/评论/关闭"动作默认 dry-run;只有用户明确确认后才执行写入。
CRITICAL — GitLink 操作只能用 gitlink-cli。禁止用 gh(GitHub 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_at(Issue 最后活动时间,包括评论、状态变更、字段修改)
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
# 动作 C:PR 催办(不打标签,仅评论)
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. 参考文档
- 扫描算法详解 — 时间计算、字段降级、批量策略
- AI 判断规则详解 — 真假僵尸判断的完整信号集
- 动作执行手册 — 写操作命令清单、评论模板、回滚策略
- 白名单豁免规则 — 哪些 Issue 永不处理
- 每周清理工作流示例 — 端到端定期巡检
- PR 催办示例 — PR 维度的处理流程
- AI 判断演示 — 复杂 Issue 的判断示例
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 标签。所有"非规则决策"会在报告中高亮,便于人工复核。