gitlink-cli/skills/gitlink-stale/references/gitlink-stale-actions.md

13 KiB
Raw Blame History

gitlink-stale — 动作执行手册

本文档说明如何把分析报告中的推荐动作安全地应用到 GitLink Issue/PR。 所有命令默认 dry-run确认后再去掉 --dry-run 实际执行。

1. 应用前置检查

1.1 备份当前状态

# 导出当前所有目标 Issue/PR 的原始字段(用于回滚)
gitlink-cli issue +list --owner <owner> --repo <repo> --state open --format json \
    > /tmp/before-stale-$(date +%s).json

1.2 确认权限

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

permissions.push !== true,所有写操作会失败,应停止并提示用户。

1.3 确认仓库有 stale 标签

# 检查仓库标签是否存在 stale
gitlink-cli api GET /v1/<owner>/<repo>/issue_tags.json --format json \
    | jq '.data.issue_tags[] | select(.name == "stale")'

# 如果不存在,提示用户手动创建(或通过 Raw API 创建)
# 强烈建议由人工创建,避免 Skill 越权

2. 三种推荐动作

2.1 动作 Amark_stale标记 stale

触发条件

  • days_inactive >= 60stale 阈值)
  • ai_analysis.truly_stale == true
  • confidence >= 0.6

执行命令

# 1. 打 stale 标签
gitlink-cli issue +label-add \
    --owner <owner> --repo <repo> \
    --number <N> \
    --labels "stale"

# 2. 评论催办(友好版,非警告)
gitlink-cli issue +comment \
    --owner <owner> --repo <repo> \
    --number <N> \
    --body "⏰ **长期未活动提醒**

本 Issue 已 60 天未收到新回复,暂时标记为 \`stale\`。

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

> 🤖 由 gitlink-stale skill 自动生成。"

2.2 动作 Bauto_close自动关闭

触发条件

  • days_inactive >= 74close 阈值)
  • ai_analysis.truly_stale == true
  • confidence >= 0.8

执行命令

# 1. 确保 stale 标签存在(如果之前没打,先打)
gitlink-cli issue +label-add \
    --owner <owner> --repo <repo> \
    --number <N> \
    --labels "stale"

# 2. 评论关闭说明
gitlink-cli issue +comment \
    --owner <owner> --repo <repo> \
    --number <N> \
    --body "🔒 **自动关闭(长期未活动)**

本 Issue 已 74 天无活动,自动关闭。

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

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

# 3. 关闭 Issue
gitlink-cli issue +close \
    --owner <owner> --repo <repo> \
    --number <N>

2.3 动作 CPR 催办PR stale

⚠️ PR 端点暂不支持 label 操作,仅评论催办。

执行命令

gitlink-cli pr +comment \
    --owner <owner> --repo <repo> \
    --id <N> \
    --body "⏰ **PR 长期未活动**

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

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

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

> 🤖 由 gitlink-stale skill 自动生成。"

如果 PR 也超过 close 阈值74 天):

gitlink-cli pr +comment \
    --owner <owner> --repo <repo> \
    --id <N> \
    --body "🔒 **PR 自动关闭(长期未活动)**

本 PR 已 74 天无活动,自动关闭。

- 如仍需合并,请 rebase 后重新打开
- 如有冲突,可重新发起 PR

> 🤖 由 gitlink-stale skill 自动关闭。"

gitlink-cli pr +close \
    --owner <owner> --repo <repo> \
    --id <N>

3. 用户回复后移除 stale 标签

默认情况下,本 Skill 是按需触发(如每周巡检),不会自动监听回复事件。

但如果用户希望"用户回复后立刻移除 stale 标签",可以单独触发:

# 检查某 Issue 是否有新回复
CURRENT=$(gitlink-cli issue +view --owner <owner> --repo <repo> \
    --number <N> --format json)

HAS_STALE=$(echo "$CURRENT" | jq '[.data.issue_tags[] | select(.name == "stale")] | length > 0')
LAST_JOURNAL_USER=$(echo "$CURRENT" | jq -r '.data.journals[-1].user.login')
AUTHOR=$(echo "$CURRENT" | jq -r '.data.author.login')

if [ "$HAS_STALE" = "true" ] && [ "$LAST_JOURNAL_USER" = "$AUTHOR" ]; then
    # 作者回复了 → 移除 stale
    gitlink-cli issue +label-remove \
        --owner <owner> --repo <repo> \
        --number <N> \
        --label "stale"
    
    gitlink-cli issue +comment \
        --owner <owner> --repo <repo> \
        --number <N> \
        --body "✅ 检测到作者回复,已移除 stale 标签。"
fi

💡 推荐做法:用 webhook 监听 Issue 评论事件,触发本段脚本,实现"自动响应回复"。详见 ../gitlink-webhook/SKILL.md


4. 批量应用模板

4.1 Shell 脚本(推荐)

#!/usr/bin/env bash
# apply-stale.sh — 从 report.json 应用 stale 动作
set -euo pipefail

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

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

# 备份
gitlink-cli issue +list --owner "$OWNER" --repo "$REPO" --state open --format json \
    > "/tmp/before-stale-$(date +%s).json"

# 逐条应用
jq -c '.items[]' "$REPORT" | while read -r item; do
    TYPE=$(echo "$item" | jq -r '.type')
    NUM=$(echo "$item" | jq '.number')
    ACTION=$(echo "$item" | jq -r '.recommended_action')
    CONF=$(echo "$item" | jq '.ai_analysis.confidence')
    
    echo "→ #$NUM ($TYPE): $ACTION (conf=$CONF)"
    
    # 跳过低置信度
    if (( $(echo "$CONF < 0.6" | bc -l) )); then
        echo "  skipped (low confidence)"
        continue
    fi
    
    # 按动作执行
    case "$ACTION" in
        mark_stale)
            apply_mark_stale "$OWNER" "$REPO" "$TYPE" "$NUM"
            ;;
        auto_close)
            apply_auto_close "$OWNER" "$REPO" "$TYPE" "$NUM"
            ;;
        *)
            echo "  skipped (action=$ACTION)"
            ;;
    esac
    
    sleep 0.5  # 避免限流
done

echo "✓ Batch applied"

4.2 AI Agent 执行模板

向 Claude Code 发送:

请按以下步骤应用 /tmp/stale-report.json 中的动作:

1. 读取报告,过滤 confidence < 0.6 的项
2. 对每个剩余项:
   a. 若 action == mark_stale
      - issue +label-add --labels stale
      - issue +comment --body <模板>
   b. 若 action == auto_close
      - 上述步骤 + issue +close
   c. 若 type == pr
      - 仅 pr +comment不打标签
3. 每应用 10 个后暂停,问我是否继续
4. 完成后输出统计:成功数、失败数、跳过数

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

5. 评论模板库

5.1 友好催办mark_stale

通用版(推荐):

**长期未活动提醒**

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

> 🤖 由 gitlink-stale skill 自动生成。

bug 类专用

**这个 bug 还能复现吗?**

本 Issue 已 60 天未活动,可能:

- 问题已经在最新版本中修复?欢迎确认
- 问题不再复现?欢迎手动关闭
- 仍然存在?请回复最新版本号和复现步骤

如果 **14 天内**没有新活动,将默认视为已解决,自动关闭。

feature 类专用

**这个需求还在期待吗?**

本 feature 请求已 60 天未活动。可能:

- 不再需要?欢迎手动关闭
- 仍然想要?欢迎回复说明用例
- 想自己实现?欢迎提交 PR

如果 **14 天内**没有新活动,将默认视为不再需要,自动关闭。

5.2 自动关闭auto_close

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

本 Issue 已 74 天无活动,自动关闭。

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

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

5.3 PR 催办

**PR 长期未活动**

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

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

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

5.4 误标道歉(回滚用)

🙏 **抱歉,刚刚的 stale 标记是误判**

经过人工复核,本 Issue 不应被标记为 stale已移除标签。

如带来困扰,敬请谅解。

> 🤖 由 gitlink-stale skill 回滚。

6. 回滚策略

6.1 误标的 Issue仅打了 stale 标签)

# 移除 stale 标签
gitlink-cli issue +label-remove \
    --owner <owner> --repo <repo> \
    --number <N> \
    --label "stale"

# 道歉评论
gitlink-cli issue +comment \
    --owner <owner> --repo <repo> \
    --number <N> \
    --body "🙏 **抱歉,刚刚的 stale 标记是误判**..."

6.2 误关闭的 Issue被自动关闭

# 重新打开(用 Raw API因 +update 需要状态参数)
CURRENT=$(gitlink-cli issue +view \
    --owner <owner> --repo <repo> \
    --number <N> --format json)
SUBJECT=$(echo "$CURRENT" | jq -r '.data.subject')
DESC=$(echo "$CURRENT" | jq -r '.data.description // ""')

PAYLOAD=$(jq -n \
    --arg s "$SUBJECT" \
    --arg d "$DESC" \
    '{subject:$s, description:$d, status_id:1}')

gitlink-cli api PATCH "/v1/<owner>/<repo>/issues/<N>" --body "$PAYLOAD"

# 移除 stale 标签
gitlink-cli issue +label-remove \
    --owner <owner> --repo <repo> \
    --number <N> \
    --label "stale"

# 道歉评论
gitlink-cli issue +comment \
    --owner <owner> --repo <repo> \
    --number <N> \
    --body "🙏 **已重新打开**,刚才的自动关闭是误判,抱歉。原始讨论继续。"

6.3 批量回滚

#!/usr/bin/env bash
# rollback-stale.sh — 从备份文件批量恢复
BACKUP="${1:?usage: rollback-stale.sh <backup.json>}"

jq -c '.data.issues[]' "$BACKUP" | while read -r issue; do
    NUM=$(echo "$issue" | jq '.number')
    SUBJECT=$(echo "$issue" | jq -r '.subject')
    DESC=$(echo "$issue" | jq -r '.description // ""')
    
    # 重新打开
    PAYLOAD=$(jq -n --arg s "$SUBJECT" --arg d "$DESC" \
        '{subject:$s, description:$d, status_id:1}')
    gitlink-cli api PATCH "/v1/<owner>/<repo>/issues/$NUM" --body "$PAYLOAD" > /dev/null
    
    # 移除 stale 标签
    gitlink-cli issue +label-remove --number "$NUM" --label "stale" 2>/dev/null || true
    
    sleep 0.3
done

echo "✓ Rollback complete"

7. 错误处理

错误 原因 处理
HTTP 401 Token 失效 gitlink-cli auth login
HTTP 403 无写权限 联系仓库 owner
HTTP 404 Issue 已被删除 跳过,记录到 errors
HTTP 422 subject/description 被清空 必须先 GET 再 PATCH
label not found 仓库无 stale 标签 提示用户先创建标签
state: -1 参数错 检查 issue +close 的 number

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


8. 审计日志

每次应用后记录:

{
  "applied_at": "2026-06-23T10:30:00Z",
  "operator": "ai-agent + human-confirm",
  "batch_id": "stale-20260623-1",
  "repository": "owner/repo",
  "thresholds": {
    "stale_days": 60,
    "close_days": 74
  },
  "summary": {
    "total_scanned": 85,
    "total_applied": 18,
    "skipped_low_confidence": 4,
    "exempt": 15,
    "actions": {
      "mark_stale": 12,
      "auto_close": 6
    }
  },
  "items_applied": [
    {
      "type": "issue",
      "number": 142,
      "action": "mark_stale",
      "confidence": 0.85,
      "success": true,
      "changes": {
        "labels_added": ["stale"],
        "comment_added": true
      }
    }
  ],
  "backup_file": "/tmp/before-stale-1719139200.json"
}

保存到 /tmp/stale-audit-<timestamp>.json,便于追溯。


9. 最佳实践

  • 小批量试水:先对 3-5 个候选执行 mark_stale观察结果再扩大
  • urgent 谨慎:对 confidence < 0.85 的 urgent/feature 类 Issue 额外人工复核
  • 避开高峰:大批量执行安排在用户活跃低谷时段
  • 通知 owner:执行前在仓库管理员沟通渠道同步"本次将清理 N 个 Issue"
  • 保留备份:所有备份文件至少保留 30 天
  • 禁止:跳过 dry-run 直接批量执行
  • 禁止:对 archived 或 read-only 仓库执行
  • 禁止:批量关闭超过 50 个 Issue 而不分批