Start with one job and grow from there.
Free to start · No credit card required
# Read the durable ledger first — known flags, their last-seen rollout state,
# what's already been removed, and what's already flagged for human review.
cat .singulacomp/memory/flag-cleanup-log.md 2>/dev/null || echo "(no ledger yet — first run)"
# Check any open cleanup PRs from a prior run.
gh pr list --repo {{target_repo}} --state open \
--search 'in:title "chore(flags)" OR label:feature-flags' \
--json number,title,headRefName,statusCheckRollup,url
DEFAULT_BRANCH=$(gh repo view {{target_repo}} --json defaultBranchRef -q .defaultBranchRef.name)
if [ -d /workspace/repo/.git ]; then
cd /workspace/repo && git fetch origin && git checkout "$DEFAULT_BRANCH" && git reset --hard "origin/$DEFAULT_BRANCH"
else
git clone --filter=blob:none https://github.com/{{target_repo}}.git /workspace/repo
cd /workspace/repo
git checkout "$DEFAULT_BRANCH"
fi
cd /workspace/repo
# Flag definitions/registry — adapt the path to this repo's convention
# (e.g. flags.ts, feature-flags.json, a flags/ directory).
grep -rnE "(defineFlag|registerFlag|FEATURE_FLAGS|flags\.(json|ya?ml))" --include="*.ts" --include="*.tsx" --include="*.json" . 2>/dev/null
# Call sites — every place a flag is actually read.
grep -rnE "(isEnabled|useFeatureFlag|getFlag|flags\.[a-zA-Z_]+)\(" --include="*.ts" --include="*.tsx" . 2>/dev/null
git log -1 --format=%ai -- <flag file or last touched call site> for the flag's last-touched date.| Classification | Criteria | Action |
|---|---|---|
| Fully rolled out | Rollout is 100% / hardcoded true with no variant left, or explicitly marked GA | Remove — inline the "on" branch, delete the "off" branch |
| Long dead | No call site found anywhere in the repo, or unchanged (declaration and all call sites) for more than {{min_flag_age_days}} days with a rollout that was already at 0% or 100% | Remove entirely, including the dead declaration |
| Partial rollout | Rollout between 0% and 100% exclusive, percentage-based, or user/cohort-targeted | Do not touch. Log in the ledger for human review |
| Active experiment | Tied to an A/B test, gradual ramp still in progress, or flag age under {{min_flag_age_days}} days with no clear rollout signal | Do not touch. Log in the ledger for human review |
cd /workspace/repo
BRANCH="chore/flag-cleanup-$(date +%Y-%m-%d)"
git checkout -b "$BRANCH" "origin/$DEFAULT_BRANCH" # or check out an existing branch from this run
if (flags.x), useFeatureFlag('x'), etc.).cd /workspace/repo
pnpm install 2>&1 | tee /tmp/flag-install.log
pnpm typecheck 2>&1 | tee /tmp/flag-typecheck.log
pnpm lint 2>&1 | tee /tmp/flag-lint.log
pnpm build 2>&1 | tee /tmp/flag-build.log
pnpm test 2>&1 | tee /tmp/flag-unit.log
pnpm test:integration 2>&1 | tee /tmp/flag-integration.log # if < ~10 min
| Failure | Action |
|---|---|
| Typecheck/build error from a removed branch's dependency | Fix the mechanical fallout (unused import, dangling type); if non-mechanical, revert that one flag's removal and log it |
| Test failure for the removed flag | Expected if the test only covered the dead branch — delete it; if it covered the surviving branch, fix the test |
| Test failure in an UNRELATED area | File it as a note (likely pre-existing); don't revert unless you can prove causation |
| Any failure you can't resolve in a few lines | Revert that flag's removal, log it as deferred with the reason, keep the rest of the batch |
cd /workspace/repo
git add -A
git commit -m "chore(flags): remove stale feature flags $(date +%Y-%m-%d)
Removed: <flag-a> (fully rolled out), <flag-b> (long dead)
Verification: typecheck ✓ lint ✓ build ✓ unit ✓ integration ✓"
cd /workspace/repo
git push origin "$BRANCH"
gh pr create --repo {{target_repo}} --base "$DEFAULT_BRANCH" --head "$BRANCH" \
--title "chore(flags): remove stale feature flags ($(date +%Y-%m-%d))" \
--label feature-flags \
--body "Generated by the flag-cleanup agent. The full suite passed in the
sandbox before this PR was opened.
**Removed (fully rolled out or long dead):**
- <flag-a> — fully rolled out, last touched <date>
- <flag-b> — long dead, no live call site found
**Left untouched (flagged for human review):**
- <flag-c> — partial rollout at <percentage>%
- <flag-d> — active experiment
A human owns the merge."
.singulacomp/memory/flag-cleanup-log.md (see
<ledger-format>), then open + self-merge a scoped change request for the
ledger update only.