关于 launchdarkly-flag-cleanup
用于移除 LaunchDarkly 功能标记代码并保留生产行为的技能。它指导 Agent 检查代码引用、依据 LaunchDarkly 配置确定替代值、评估安全性并验证清理结果。
主要功能
- 01搜索代码中的标记引用
- 02检查移除准备情况与阻碍
- 03根据配置确定替代值
- 04移除标记分支及相关代码
- 05验证构建、测试和残留引用
适用场景
- 01发布完成后清理功能标记
- 02用配置的变体替换标记评估
- 03准备经过审查的标记移除拉取请求
- 04移除标记前识别阻碍因素
MCP 相关
需要配置远程托管的 LaunchDarkly MCP 服务,以检查移除准备情况并获取标记配置。代码清理后,可选用相关工具归档或删除标记。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ launchdarkly/ ai-tooling --skill launchdarkly-flag-cleanup安装后在 Claude Code 中输入/launchdarkly-flag-cleanup确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
marketplace.jsonREADME.mdreferences/pr-template.mdsdk-patterns.md详细介绍
LaunchDarkly 功能标志清理
你正在使用一项技能,它会指导你安全地从代码库中移除功能标志,同时保持生产行为不变。你的任务是探索代码库以了解该标志的使用方式,查询 LaunchDarkly 以确定正确的前向值,干净地移除标志代码,并验证结果。
如果你尚未确定要清理哪个标志,请先使用 标志发现技能 审查整体情况并找出候选标志。
前提条件
此技能要求在你的环境中配置远程托管的 LaunchDarkly MCP 服务。
必需的 MCP 工具:
check-removal-readiness:详细的安全检查(并行编排标志配置、跨环境状态、依赖项、代码引用和即将过期的目标)get-flag:获取特定环境的标志配置
可选的 MCP 工具:
archive-flag:在代码移除后归档 LaunchDarkly 中的标志delete-flag:永久删除标志(不可逆,优先选择归档)
核心原则
- 安全第一:始终保留当前生产行为。
- 以 LaunchDarkly 为唯一可信来源:绝不猜测前向值。查询实际配置。
- 遵循约定:尊重现有代码风格和结构。
- 最小改动:仅移除与标志相关的代码。不做无关的重构。
工作流
第 1 步:探索代码库
在改动 LaunchDarkly 或移除代码之前,先了解该标志在代码库中的使用方式。
-
查找标志键的所有引用。 在代码库中搜索标志键字符串(例如
new-checkout-flow)。检查:- 直接的 SDK 求值调用(
variation()、boolVariation()、useFlags()等) - 引用该键的常量/枚举
- 抽象 SDK 的包装器/服务模式
- 配置文件、测试和文档
- 按语言划分的完整模式列表见 SDK 模式
- 直接的 SDK 求值调用(
-
理解分支。 对于每个引用,确定:
- 当标志为
true(或变体 A)时运行什么代码? - 当标志为
false(或变体 B)时运行什么代码? - 是否存在副作用、提前返回或嵌套条件?
- 当标志为
-
记录范围。 该标志涉及多少个文件、组件或模块?只在一个
if块中使用的标志比贯穿多个层的标志更简单。
第 2 步:运行移除就绪检查
使用 check-removal-readiness 获取详细的安全评估。这单次工具调用会并行编排多项检查:
- 标志配置和定向状态
- 跨环境状态
- 依赖标志(前置条件)
- 即将过期的目标
- 代码引用统计
该工具会返回就绪判定:
safe:没有阻碍或警告。继续移除。
caution:没有硬性阻碍,但存在警告(例如,其他仓库中的代码引用、已安排即将过期的目标、标志被标记为永久)。呈现警告并让用户决定。
blocked:硬性阻碍阻止安全移除(例如,依赖标志、正在接收请求、定向已开启且规则处于活动状态)。呈现阻碍项:用户必须先解决它们。
第 3 步:确定前向值
使用 get-flag 获取每个关键环境中的标志配置。前向值是在代码中替换该标志的变体。
| 场景 | 前向值 |
|---|---|
| 所有关键环境为 ON,相同的 fallthrough,无规则/目标 | 使用 fallthrough.variation |
| 所有关键环境为 OFF,相同的 offVariation | 使用 offVariation |
| 关键环境的 ON/OFF 状态不同 | 不安全:停止并告知用户 |
| 关键环境提供不同的变体 | 不安全:停止并告知用户 |
步骤 4:提交清理方案
在修改任何代码之前,先向用户提交一份摘要并等待确认:
- 前向值 — 将硬编码哪个变体以及原因(基于该 flag 的当前状态)。
- 找到的所有代码引用 — 来自步骤 1 的文件路径和行号。
- 计划中的更改 — 对每个引用,说明将删除什么、保留什么。
- 就绪性判定 —
check-removal-readiness的结果(安全、谨慎或阻止)以及任何警告。 - LaunchDarkly 操作 — 确认在代码更改完成后将归档该 flag。
在用户明确确认之前,不要进行代码更改。
步骤 5:从代码中移除 Flag
现在使用你在步骤 1 中了解到的信息执行移除。
-
用前向值替换 flag 求值。
- 保留与前向值匹配的代码分支
- 完全删除死分支
- 如果 flag 值被赋值给某个变量,用字面值替换该变量或将其内联
-
清理死代码。
- 删除仅为该 flag 而存在的导入、常量和类型定义
- 删除仅为该死分支而存在的函数、组件或文件
- 检查孤立的导出、hook、helper、样式和测试文件
- 如果仓库使用了未使用导出检查工具(Knip、ts-prune、lint 规则),运行它并删除任何与 flag 相关的孤立项
-
不要过度清理。
- 只删除与该 flag 直接相关的代码
- 不要重构、优化或“改进”周围的代码
- 不要更改未触及代码的格式或风格
转换示例(布尔 flag,前向值 = true):
// Before
const showNewCheckout = await ldClient.variation('new-checkout-flow', user, false);
if (showNewCheckout) {
return renderNewCheckout();
} else {
return renderOldCheckout();
}
// After
return renderNewCheckout();
步骤 6:创建 Pull Request
使用 references/pr-template.md 中的模板编写结构化的 PR 描述。PR 应清楚地传达:
- 移除了哪个 flag 以及原因
- 前向值是什么以及为什么它正确
- 就绪性评估结果(来自
check-removal-readiness) - 删除了哪些代码、保留了哪些行为
- 其他仓库是否仍引用该 flag
步骤 7:验证
在认为任务完成之前:
- 代码可编译且通过 lint。 运行项目的构建和 lint 步骤。
- 测试通过。 如果该 flag 在测试中被使用,应更新测试以反映硬编码后的行为。
- 没有残留引用。 再在代码库中搜索一次该 flag key,确保没有遗漏。
- PR 完整。 描述涵盖就绪性评估、前向值依据以及任何需要的跨仓库协调。
边界情况
| 情况 | 操作 |
|---|---|
| 在 LaunchDarkly 中找不到该 flag | 告知用户,检查 key 是否有拼写错误 |
| 该 flag 已归档 | 询问是否仍需要代码清理(flag 已从 LD 中移除,但代码可能仍引用它) |
| 代码库中有多种 SDK 模式 | 搜索所有模式:variation()、boolVariation()、variationDetail()、allFlags()、useFlags(),以及任何封装 |
动态 flag key(flag-${id}) | 警告自动移除可能不完整:需要人工审查 |
| 代码与 LD 中的默认值不同 | 在 PR 描述中将其标记为不一致 |
| 移除后仍有孤立的导出/文件 | 运行未使用导出检查并删除死文件 |
不要做什么
- 不要更改与 flag 清理无关的代码。
- 不要在 flag 移除之外进行重构或优化。
- 不要移除仍在积极灰度发布的 flag。
- 不要猜测前向值:始终查询 LaunchDarkly。
清理之后
一旦 PR 被合并并部署:
- 使用
archive-flag在 LaunchDarkly 中归档该 flag。 归档可逆;删除不可逆。始终先归档。 - 通知其他团队,如果
check-removal-readiness报告在其他仓库中有代码引用。 - 如果该 flag 有待处理的定向更改, 可以忽略:该 flag 正在被移除。