功能切换管理器
管理代码库中功能标志和切换的整个生命周期。该技能教会 AI 代理发现所有切换用法,检测应删除的过时或孤立标志,规划安全的清理操作,并评估整体切换债务。支持 LaunchDarkly、Unleash、环境变量和自定义内码实现。
使用时: "审计功能标志"、"查找过时切换"、"清理功能标志"、"切换债务"、"功能标志生命周期"、"孤立标志"、"标志推出计划"
命令
发现代码库中每个功能标志的引用,按类型和状态对其进行分类,并生成过时报告。
步骤 1:确定切换实现模式
通过扫描已知的 SDK 导入和常见模式来确定使用的切换系统。
# 检查 LaunchDarkly SDK
rg -l "launchdarkly|ldclient|LDClient|useFlags|withLDConsumer" --type-add 'code:
.{js,ts,tsx,py,go,java,rb,cs}' -t code .
# 检查 Unleash SDK
rg -l "unleash-client|Unleash|isEnabled|unleash_client" --type-add 'code:.{js,ts,tsx,py,go,java,rb}' -t code .
# 检查环境变量标志
rg "FEATURE_|ENABLE_|FF_|TOGGLE_|FLAG_" --type-add 'code:
.{js,ts,py,go,java,env,yaml,yml,toml}' -t code .
# 检查自定义切换文件(JSON/YAML 配置)
rg -l "featureFlags|feature_flags|toggles|feature.toggles" . -g '.{json,yaml,yml,toml}'
步骤 2:提取完整的标志库存
构建每个distinct标志名称及其出现位置的结构化列表。
# 从 LaunchDarkly 变化调用中提取标志名称
rg -o "variation\(
'\"['\"]" -r '$1' --no-filename . | sort -u
# 从 Unleash isEnabled 调用中提取标志名称
rg -o "isEnabled\(
'\"['\"]" -r '$1' --no-filename . | sort -u
# 提取环境变量标志
rg -o "(FEATURE_[A-Z_]+|ENABLE_[A-Z_]+|FF_[A-Z_]+)" --no-filename . | sort -u
# 对于每个标志,计算其被引用的次数以衡量其被嵌入程度
for flag in $(rg -o "variation\(
'\"['\"]" -r '$1' --no-filename . | sort -u); do
count=$(rg -c "$flag" -l . 2>/dev/null | wc -l)
echo "$count files -- $flag"
done | sort -rn
步骤 3:使用 Git 历史记录评估过时性
如果标志的最后一次有意义的更改时间很久以前,并且它一直返回一个值,则该标志可能过时。
# 对于每个标志,找到它最后一次被修改的日期
flag="my-feature-flag"
git log -1 --format="%ai" -S "$flag" -- '
.ts' '.js' '
.py' '.go'
# 批量过时检查:90 天以上未被触及的标志
threshold=$(date -d '90 days ago' +%s)
for flag in $(rg -o "variation\(
'\"['\"]" -r '$1' --no-filename . | sort -u); do
last_date=$(git log -1 --format="%at" -S "$flag" 2>/dev/null)
if [ -n "$last_date" ] && [ "$last_date" -lt "$threshold" ]; then
human_date=$(date -d "@$last_date" +%Y-%m-%d)
echo "STALE ($human_date) -- $flag"
fi
done
步骤 4:与切换服务进行交叉引用(如果可访问)
# LaunchDarkly API:列出标志及其当前状态
curl -s -H "Authorization: $LD_API_KEY" \
"https://app.launchdarkly.com/api/v2/flags/$LD_PROJECT_KEY" | \
python3 -c " import sys, json
data = json.load(sys.stdin)
for f in data.get('items', []):
status = 'ON' if f['on'] else 'OFF'
age_days = (json.loads('{\"now\":0}')['now']) # 占位符
print(f\"{status:>3} {f['key']} (envs: {len(f.get('environments', {}))})\" ) "
# Unleash API:列出所有切换
curl -s -H "Authorization: $UNLEASH_API_TOKEN" \
"$UNLEASH_URL/api/admin/features" | python3 -c " import sys, json
data = json.load(sys.stdin)
for f in data.get('features', []):
stale = 'STALE' if f.get('stale') else 'active'
print(f\"{stale:>6} {f['name']} type={f.get('type','unknown')}\") "
报告模板
功能切换审计报告
日期: YYYY-MM-DD
仓库: repo-name
切换系统: LaunchDarkly / Unleash / 环境变量 / 自定义
摘要
- 总共找到 N 个唯一标志
- 活动(最近 90 天内被触及):N
- 过时(90 天以上未被触及):N
- 孤立(在代码中但不在服务中):N
- 幽灵(在服务中但不在代码中):N
标志库存
| 标志名称 | 文件 | 最后修改 | 服务状态 | 推荐操作 |
|-----------|-------|---------------|----------------|----------------|
| flag-name | 12 | 2025-11-03 | ON (100%) | REMOVE (完全推出) |
切换债务评分
- 债务评分:N/10(过时计数 2 + 孤立计数 3,最高 10)
- 推荐操作:[清理冲刺 / 紧急删除 / 可接受]
- 清理 -- 确定可移除标志并生成移除计划
对于每个过时或完全推出的标志,跟踪每个代码路径并生成安全移除计划。
步骤 1:映射单个标志的爆炸半径
flag="old-feature-flag"
# 找到每个引用此标志的文件
rg -l "$flag" .
# 显示实际使用上下文(每个匹配项周围 5 行)
rg -C 5 "$flag" .
# 确定将折叠的条件分支
rg -n "if.*$flag|