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

350 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# gitlink-stale — 白名单豁免规则
> 本文档详述"哪些 Issue/PR 永不被 stale skill 处理"的完整规则。
> 豁免规则在 Stage B 执行,先于 AI 判断(节省 API 调用)。
## 1. 豁免原则
**核心思想**:宁可放过,不可误关。
任何满足"长期重要"或"主动声明保留"信号的 Issue 都应被豁免。
| 原则 | 说明 |
|------|------|
| **保守** | 不确定时,豁免(不处理) |
| **多信号** | 任一豁免信号触发即可 |
| **可追溯** | 豁免原因必须记录在报告中 |
| **可配置** | 用户可自定义豁免规则 |
---
## 2. 豁免信号全集
### 2.1 标签豁免(最强信号)
| 标签名(中/英) | 豁免原因 | 默认权重 |
|---------------|---------|---------|
| `pinned` / `置顶` | 显式标记永久保留 | 必豁免 |
| `security` / `安全` | 安全相关,永不自动关闭 | 必豁免 |
| `roadmap` / `路线图` | 长期规划 | 必豁免 |
| `epic` / `里程碑` | 大型任务父节点 | 必豁免 |
| `keep-open` / `保留` | 显式声明 | 必豁免 |
| `in-progress` / `进行中` | 正在处理 | 必豁免 |
| `under-review` / `审查中` | 等待审查 | 必豁免 |
| `help-wanted` | 等社区认领 | 必豁免 |
| `good-first-issue` | 等新手认领 | 必豁免 |
| `p0` / `p1` | 高优先级 | 必豁免 |
### 2.2 Tracker 类型豁免
GitLink 的 tracker_id 映射(参考 issue-triage skill
| tracker_id | 名称 | 默认豁免 |
|-----------|------|---------|
| 1 | bug | ❌ 不豁免(仍可能 stale |
| 2 | feature | ❌ 不豁免 |
| 3 | support | ❌ 不豁免(最易 stale |
| 4 | doc | ❌ 不豁免 |
| 5 | test | ❌ 不豁免 |
| 6 | duplicate | ✅ 直接关闭(特殊处理) |
| 7 | question | ❌ 不豁免 |
| 自定义 | roadmap | ✅ 豁免 |
| 自定义 | epic | ✅ 豁免 |
### 2.3 优先级豁免
| priority_id | 等级 | 默认豁免 |
|------------|------|---------|
| 1 | low | ❌ 不豁免 |
| 2 | normal | ❌ 不豁免 |
| 3 | high | ⚠️ 仅在 confidence >= 0.9 时处理 |
| 4 | urgent | ✅ 豁免 |
### 2.4 标题模式豁免
匹配以下正则的标题豁免:
```yaml
keep_open_title_patterns:
- "\\[WIP\\]"
- "\\[Pinned\\]"
- "\\[Keep.?Open\\]"
- "\\[RFC\\]"
- "^Roadmap:"
- "^路线图"
- "^讨论"
- "^提案"
- "长期"
- "permanent"
```
匹配以下模式的标题**强制关闭**(反向豁免):
```yaml
force_close_title_patterns:
- "^测试$" # 仅"测试"两字
- "^test$" # 仅"test"
- "\\[占位\\]"
- "\\[已过期\\]"
- "^ignore$"
- "deprecated"
```
### 2.5 作者豁免
| 作者类型 | 豁免规则 |
|---------|---------|
| 仓库 owner | ✅ 豁免(信任 owner 会跟进) |
| 仓库 member | ✅ 豁免 |
| 资深贡献者(≥ 10 PR merged | ⚠️ confidence >= 0.85 才处理 |
| 普通用户 | ❌ 不豁免 |
| 路过用户(仅 1 Issue | ❌ 不豁免(更倾向清理) |
### 2.6 时间豁免
| 时间条件 | 豁免规则 |
|---------|---------|
| 创建时间 < 7 | 豁免给新 Issue 缓冲期 |
| 最后活动 < 60 | 豁免未达 stale 阈值 |
| milestone 锁定 | 豁免 |
### 2.7 关联豁免
| 关联条件 | 豁免规则 |
|---------|---------|
| linked PR标题含"fixed in #N" | 豁免 PR 合并 |
| 有子任务 epic 引用 | 豁免 |
| duplicate of closed | 直接关闭特殊处理 |
---
## 3. 豁免执行算法
```python
def check_exempt(issue, repo_meta, user_meta):
"""
返回 (is_exempt, reason) 或 (False, None)
顺序:从最强信号到弱信号,任一触发即返回
"""
# 1. 标签豁免(最强)
EXEMPT_LABELS = {
"pinned", "置顶",
"security", "安全",
"roadmap", "路线图",
"epic", "里程碑",
"keep-open", "保留",
"in-progress", "进行中",
"under-review", "审查中",
"help-wanted",
"good-first-issue",
"p0", "p1",
}
for label in get_labels(issue):
if label.lower() in EXEMPT_LABELS:
return True, f"含豁免标签: {label}"
# 2. 标题强信号
import re
for pattern in KEEP_OPEN_TITLE_PATTERNS:
if re.search(pattern, issue.subject, re.IGNORECASE):
return True, f"标题匹配保留模式: {pattern}"
# 3. 优先级豁免
if issue.priority_id == 4: # urgent
return True, "urgent 优先级"
# 4. tracker 豁免
if issue.tracker_id in [ROADMAP, EPIC]:
return True, "tracker 是 roadmap/epic"
# 5. 作者豁免
if issue.author.login == repo_meta.owner:
return True, "作者是仓库 owner"
if issue.author.login in repo_meta.members:
return True, "作者是仓库 member"
# 6. 时间豁免(创建 < 7 天)
days_since_created = (now() - parse(issue.created_at)).days
if days_since_created < 7:
return True, f"创建仅 {days_since_created} 天,在缓冲期内"
# 7. 高优先级的特殊处理
if issue.priority_id == 3: # high
# 不直接豁免,但需要 confidence >= 0.9
return False, None # 走正常流程
return False, None
def check_force_close(issue):
"""
反向豁免:强制关闭
"""
import re
for pattern in FORCE_CLOSE_TITLE_PATTERNS:
if re.search(pattern, issue.subject, re.IGNORECASE):
return True, f"标题匹配强制关闭模式: {pattern}"
return False, None
```
---
## 4. 豁免决策流程图
```
┌─────────────────────────────┐
│ Issue 候选(已通过时间过滤) │
└────────────┬────────────────┘
┌─────────────────────────────┐
│ 1. 强制关闭模式匹配? │─── 是 ──→ force_close
└────────────┬────────────────┘
│ 否
┌─────────────────────────────┐
│ 2. 含豁免标签? │─── 是 ──→ exempt
└────────────┬────────────────┘
│ 否
┌─────────────────────────────┐
│ 3. 标题匹配保留模式? │─── 是 ──→ exempt
└────────────┬────────────────┘
│ 否
┌─────────────────────────────┐
│ 4. priority == urgent │─── 是 ──→ exempt
└────────────┬────────────────┘
│ 否
┌─────────────────────────────┐
│ 5. tracker == roadmap/epic │─── 是 ──→ exempt
└────────────┬────────────────┘
│ 否
┌─────────────────────────────┐
│ 6. 作者是 owner/member │─── 是 ──→ exempt
└────────────┬────────────────┘
│ 否
┌─────────────────────────────┐
│ 7. 创建 < 7 天? │─── 是 ──→ exempt
└────────────┬────────────────┘
│ 否
进入 AI 判断
```
---
## 5. 自定义豁免规则
用户可在仓库根目录创建 `.gitlink-stale.yml` 自定义
```yaml
# .gitlink-stale.yml
version: 1.0
# 阈值
thresholds:
stale_days: 60
close_days: 74
grace_days: 14
# 豁免标签(追加到默认列表)
exempt_labels:
- "客户合同"
- "VIP 用户反馈"
# 豁免标题模式(追加)
exempt_title_patterns:
- "^\\[长期讨论\\]"
# 强制关闭模式(追加)
force_close_title_patterns:
- "^spam"
# 豁免用户
exempt_authors:
- "trusted-contributor"
# 自定义 priority 豁免
exempt_priorities:
- 4 # urgent
- 3 # high比默认更严格
# 自定义 tracker 豁免
exempt_trackers:
- 8 # 自定义的"内部任务"
```
> 💡 Skill 在执行前自动加载此文件(如果存在),与默认规则合并。详见 [SKILL.md §4.3](../SKILL.md)。
---
## 6. 豁免审计
报告中必须列出所有被豁免的 Issue便于人工复核
```json
{
"summary": {
"exempt": 15,
"exempt_breakdown": {
"label_pinned": 3,
"label_security": 2,
"label_roadmap": 5,
"priority_urgent": 2,
"author_owner": 2,
"title_pattern": 1
}
},
"exempt_items": [
{
"number": 88,
"title": "[Pinned] 项目长期路线图",
"exempt_reason": "含豁免标签: pinned",
"exempt_signal": "label_pinned"
},
{
"number": 92,
"title": "线上数据库故障",
"exempt_reason": "urgent 优先级",
"exempt_signal": "priority_urgent"
}
]
}
```
---
## 7. 边界情况
| 情况 | 处理 |
|------|------|
| 同一 Issue 含豁免标签和强制关闭模式 | 豁免优先保守原则 |
| 标签名大小写不同`Pinned` vs `pinned` | 大小写不敏感 |
| 标签名含空格`keep open` | 标准化去空格转小写后比较 |
| 标签是 emoji(📌) | 当前不支持建议搭配文字标签 |
| 作者 ID 已注销`login == null` | 不豁免可能就是僵尸 |
| 用户自定义规则与默认冲突 | 用户规则优先追加而非覆盖 |
---
## 8. 推荐的标签配置
为了让 Skill 发挥最佳效果**强烈推荐**仓库具备以下标签
| 标签名 | 用途 |
|-------|------|
| `pinned` | 显式标记永久保留的 Issue |
| `security` | 安全相关 |
| `roadmap` | 路线图 |
| `stale` | 已被本 Skill 标记 |
| `duplicate` | 重复 Issue |
| `wontfix` | 决定不修复但保留记录 |
如果仓库缺少这些标签Skill 在执行前会提示用户创建不会自动创建避免越权)。