finding-deleted-feature-flags

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Finding recently deleted feature flags

查找最近被删除的Feature Flag

This skill produces a list of feature flags that were soft-deleted in the active project within a user-specified time window, along with who deleted each one and when.
本技能会生成当前项目中在用户指定时间段内被软删除的Feature Flag列表,同时显示每个标志的删除人和删除时间。

When to use this skill

何时使用此技能

  • The user asks "what flags got deleted last week / in the last N days?"
  • The user wants an audit of recent flag deletions (who, when, what was removed)
  • The user wants to find when a specific flag was deleted, or by whom
  • Any "recently deleted feature flags" framing
Don't use this for active stale-flag cleanup — that's
cleaning-up-stale-feature-flags
. This skill is for flags that have already been removed.
  • 用户询问“上周/过去N天删除了哪些标志?”
  • 用户需要最近标志删除记录的审核信息(删除人、删除时间、删除内容)
  • 用户想查找某个特定标志的删除时间或删除人
  • 任何涉及“最近删除的Feature Flag”的场景
不要将此技能用于活跃的过期标志清理——那是
cleaning-up-stale-feature-flags
的用途。本技能仅适用于已被删除的标志。

The gotcha that makes this non-trivial

这项任务的棘手之处

system.feature_flags
exposes
deleted
as a boolean but does not expose
deleted_at
,
updated_at
, or
last_modified_at
. There's no way to filter soft-deleted flags by deletion time in a single SQL query — trying to use those columns will return
Unable to resolve field
.
The actual deletion timestamp lives in the per-flag activity log, reachable only via
posthog:feature-flags-activity-retrieve
(one call per flag id). There is no bulk activity endpoint.
So the workflow is two-stage: SQL to enumerate candidates, then parallel activity-log lookups to find each deletion event.
system.feature_flags
表暴露了
deleted
布尔字段,但并未暴露
deleted_at
updated_at
last_modified_at
字段。无法通过单次SQL查询按删除时间过滤软删除的标志——尝试使用这些字段会返回
Unable to resolve field
错误。
实际的删除时间存储在每个标志的活动日志中,只能通过
posthog:feature-flags-activity-retrieve
接口获取(每个标志ID需调用一次)。目前没有批量获取活动日志的接口。
因此,整个流程分为两个阶段:先用SQL枚举候选标志,再并行查询活动日志以找到每个标志的删除事件。

Workflow

流程

1. Clarify the window if ambiguous

1. 若时间范围模糊则进行确认

"Last week" is ambiguous — it can mean rolling 7 days from now, or the previous calendar week (Mon–Sun). If the user wasn't explicit, ask, or surface both interpretations in the final report.
Always compute the cutoff in UTC and keep the user's local interpretation in your head separately.
“上周”的表述模糊——它可以指从现在起往前推7天的滚动周期,也可以指上一个日历周(周一至周日)。如果用户没有明确说明,需进行询问,或在最终报告中同时呈现两种解读方式。
始终以UTC时间计算截止点,同时在脑中保留用户的本地时间解读。

2. Enumerate soft-deleted flags via SQL

2. 通过SQL枚举软删除的标志

Query
system.feature_flags
for
deleted = true
in the active project, ordered by
created_at DESC
:
sql
SELECT id, key, created_at
FROM system.feature_flags
WHERE team_id = <team_id> AND deleted = true
ORDER BY created_at DESC
LIMIT 100
Order by
created_at DESC
because deletions empirically cluster near creation — most flags get deleted within a few days of being created — so walking the most-recently-created candidates first finds recent deletions fastest. But this is a heuristic, not a guarantee: an older flag deleted recently won't be at the top of this list. Be explicit about that limitation when you report.
team_id
defaults to the active project, but include it explicitly for clarity.
查询
system.feature_flags
表,获取当前项目中
deleted = true
的标志,按
created_at
降序排列:
sql
SELECT id, key, created_at
FROM system.feature_flags
WHERE team_id = <team_id> AND deleted = true
ORDER BY created_at DESC
LIMIT 100
created_at
降序排列是因为删除操作通常集中在创建后不久——大多数标志会在创建后的几天内被删除——因此优先查看最近创建的候选标志能最快找到最近的删除记录。这只是一种经验法则,并非绝对保证:一个创建较早但最近才被删除的标志不会出现在列表顶部。在报告中需明确说明这一局限性。
team_id
默认是当前项目,但为了清晰起见需显式指定。

3. Fan out activity-log lookups in parallel

3. 并行发起活动日志查询

For each candidate id, call
posthog:feature-flags-activity-retrieve
with
limit: 5, page: 1
. Issue all calls in one message so they run concurrently — sequential calls are dramatically slower.
text
call feature-flags-activity-retrieve {"id": <flag_id>, "limit": 5, "page": 1}
Reasonable batch sizes:
  • "last 7 days" → top 20–25 candidates
  • "last 30 days" → top 50
  • "last 90 days" → walk the full ~100
If you sample fewer than the full set, say so in the report and offer to walk the rest as a follow-up.
针对每个候选标志ID,调用
posthog:feature-flags-activity-retrieve
接口,参数设置为
limit: 5, page: 1
将所有调用放在一条消息中并发执行——顺序调用会慢得多。
text
call feature-flags-activity-retrieve {"id": <flag_id>, "limit": 5, "page": 1}
合理的批量大小:
  • “过去7天” → 前20–25个候选标志
  • “过去30天” → 前50个候选标志
  • “过去90天” → 遍历全部约100个候选标志
如果只采样了部分候选标志,需在报告中说明,并提出可以后续遍历剩余标志。

4. Extract the deletion event from each response

4. 从每个响应中提取删除事件

In each response, find the entry where
activity == "deleted"
. That entry's
created_at
is the actual deletion time, and
user.email
/
user.first_name
identify the deleter.
The deletion event's
detail.changes
array typically contains:
  • {field: "deleted", before: false, after: true}
    — the actual delete
  • {field: "key", before: "<original>", after: "<original>:deleted:<id>"}
    — Django renames the key on delete to free up the unique constraint
  • {field: "name", ...}
    — the name sometimes gets reset
For most flags there's exactly one delete event. If a flag has been deleted-and-restored multiple times, take the most recent
activity: deleted
event within the window.
在每个响应中,找到
activity == "deleted"
的条目。该条目的
created_at
即为实际删除时间,
user.email
/
user.first_name
则标识了删除人。
删除事件的
detail.changes
数组通常包含:
  • {field: "deleted", before: false, after: true}
    —— 实际的删除操作
  • {field: "key", before: "<original>", after: "<original>:deleted:<id>"}
    —— Django会在删除时重命名标志的key,以释放唯一约束
  • {field: "name", ...}
    —— 标志名称有时会被重置
大多数标志只有一次删除事件。如果某个标志被多次删除并恢复,取时间范围内最近的
activity: deleted
事件。

5. Filter and report

5. 过滤并生成报告

Filter the collected deletion events to those whose
created_at
falls inside the requested window. Present as a table:
| Flag ID | Key | Deleted at (UTC) | Deleted by |
State your methodology in the report (how many candidates you walked vs. how many soft-deleted flags exist total), so the user knows what was and wasn't checked.
将收集到的删除事件过滤到符合请求时间范围的条目,以表格形式呈现:
| 标志ID | Key | 删除时间(UTC) | 删除人 |
在报告中说明你的方法(遍历了多少候选标志,以及项目中总共有多少软删除的标志),让用户清楚哪些内容已检查,哪些未检查。

Watch-outs

注意事项

  • Borderline cases: if a deletion is within ~1 hour of the window cutoff, surface it as borderline rather than silently dropping it.
  • Don't trust
    created_at
    as a proxy for deletion time
    : a flag created in 2024 can still have been deleted last week. The activity log is the only authority.
  • Renamed keys are normal: a flag with key
    foo:deleted:12345
    was the flag originally keyed
    foo
    . The original key/name appears in the delete event's
    detail.changes
    array — surface that to the user, not the renamed form.
  • Walking all candidates is possible but slow: ~100 parallel activity-log calls is doable. Offer it as a follow-up rather than the default for short windows.
  • 边界情况:如果删除事件发生在时间范围截止点前后约1小时内,需将其标记为边界情况,而非直接忽略。
  • 不要将
    created_at
    作为删除时间的替代
    :2024年创建的标志仍可能在最近一周被删除。活动日志是唯一可靠的来源。
  • 重命名Key是正常现象:Key为
    foo:deleted:12345
    的标志原本的Key是
    foo
    。原始的Key/名称会出现在删除事件的
    detail.changes
    数组中——需向用户展示原始信息,而非重命名后的形式。
  • 遍历所有候选标志可行但较慢:约100次并行活动日志调用是可行的。对于短时间范围,可将其作为后续操作而非默认选项。

Example interaction

交互示例

User: "what flags got deleted in the last week?"
  1. Clarify if needed, or note both interpretations: "rolling 7 days ending now (UTC), in the active project"
  2. Run the SQL enumeration to get up to 100 soft-deleted candidates ordered by
    created_at DESC
  3. Fan out activity-log lookups in parallel across the top ~25 candidates
  4. Extract
    activity: deleted
    entries; filter to those whose
    created_at >= now - 7 days
  5. Report:
    text
    Found 2 feature flags deleted in the last 7 days (rolling, ending 2026-05-22 19:04 UTC):
    
    | Flag ID | Key                                       | Deleted at (UTC)     | Deleted by  |
    |---------|-------------------------------------------|----------------------|-------------|
    | 687432  | high_frequency_alerts                     | 2026-05-22 17:23     | Matt P.     |
    | 676665  | tasks-sendblue-prewarmed-sandbox-pool     | 2026-05-15 13:45     | Alessandro  |
    
    Methodology: walked the activity log for the 25 most-recently-created soft-deleted
    flags. Team 2 has ~100 soft-deleted flags total; the remaining ~75 were created
    before mid-March 2026 and were not checked. Want me to walk the rest?
用户:“过去一周删除了哪些标志?”
  1. 若需要则进行确认,或说明两种解读方式:“从现在起往前推7天的滚动周期(UTC时间),针对当前项目”
  2. 执行SQL枚举,获取最多100个按
    created_at
    降序排列的软删除候选标志
  3. 并行发起前约25个候选标志的活动日志查询
  4. 提取
    activity: deleted
    条目;过滤出
    created_at >= 当前时间 - 7天
    的条目
  5. 生成报告:
    text
    找到2个在过去7天内被删除的Feature Flag(滚动周期,截止到2026-05-22 19:04 UTC):
    
    | 标志ID | Key                                       | 删除时间(UTC)     | 删除人  |
    |---------|-------------------------------------------|----------------------|-------------|
    | 687432  | high_frequency_alerts                     | 2026-05-22 17:23     | Matt P.     |
    | 676665  | tasks-sendblue-prewarmed-sandbox-pool     | 2026-05-15 13:45     | Alessandro  |
    
    方法说明:遍历了25个最近创建的软删除标志的活动日志。团队2共有约100个软删除标志;剩余约75个创建于2026年3月中旬之前,未被检查。需要我遍历剩余标志吗?

Related tools

相关工具

  • posthog:execute-sql
    : Used in step 2 to enumerate soft-deleted candidates against
    system.feature_flags
  • posthog:feature-flags-activity-retrieve
    : Used in step 3 to find the actual deletion event for each candidate
  • posthog:feature-flag-get-definition
    : Useful if the user then wants to inspect what the deleted flag looked like
  • posthog:execute-sql
    :步骤2中用于枚举
    system.feature_flags
    表中的软删除候选标志
  • posthog:feature-flags-activity-retrieve
    :步骤3中用于查找每个候选标志的实际删除事件
  • posthog:feature-flag-get-definition
    :如果用户想查看已删除标志的具体定义,此工具会很有用