agents/skills/feature-flag-removal/SKILL.md
Your task is to clean up a base::Feature flag and its associated code.
Determine flag's default state:
BASE_FEATURE that defines the flag's default state
(either ENABLED_BY_DEFAULT or DISABLED_BY_DEFAULT).#if BUILDFLAG()),
ask the user to clarify which should be considered the final state.//third_party/blink/renderer/platform/runtime_enabled_features.json5,
which is a config that generates base::Features at build time. Treat the
"stable" status as ENABLED_BY_DEFAULT and all other statuses as
DISABLED_BY_DEFAULT.Remove C++ flag enablement checks:
base::FeatureList::IsEnabled(kFeature) calls or a free
Is<X>Enabled() helper function that wraps the former.true or false literals. Any
true or false in a larger boolean expression should be simplified as
much as possible.Remove obsolete base::FeatureParams:
BASE_FEATURE_PARAMs that are linked to the obsolete feature
flag.FunctionCall(/*param=*/67)).Remove obsolete C++ test coverage:
base::test::ScopedFeatureLists that explicitly set the feature in
the default state.Clean up Java code:
base::Feature is used in Java code by searching for the
constant case version of the base::Feature name (e.g., FOO_BAR for
kFooBar).Clean up WebUI frontend code:
base::Feature state was formerly sent to a WebUI frontend (e.g.,
with AddBoolean("isFooEnabled", base::FeatureList::IsEnabled(kFoo))),
clean up isFooEnabled flags from WebUI frontend files
(TypeScript/HTML/CSS) in the same way as the C++ case.Simplify APIs and expressions:
Suppose a method takes a std::optional<T> that's std::nullopt with
the feature disabled, and T with the feature enabled. If the
feature-disabled case is being removed, then the parameter can just
become a value of type T.
Inline trivial local variable assignments. For example,
const auto x = base::FeatureList::IsEnabled(kFoo) ? Enum::A : Enum::B;
Bar(x);
... will become:
const auto x = Enum::A;
Bar(x);
... if one naively removes an ENABLED_BY_DEFAULT flag kFoo, but this
can be simplified further as:
Bar(Enum::A);
... since the assignment to x is adding unnecessary indirection.
Remove dead code:
Delete unused imports and build deps:
#includes, #imports, and forward declarations that are no
longer needed.BUILD.gn deps that are no longer needed.BUILD.gn.Delete flag-metadata.json entry:
//chrome/browser/about_flags.cc or
//ios/chrome/browser/flags/about_flags.mm, remove the corresponding
entry from //chrome/browser/flag-metadata.json. By convention, a
base::Feature declared as kFooBar has foo-bar as its about:flags
name.Clean up //testing/variations/fieldtrial_testing_config.json:
Delete unused strings or resources:
.grd and .grdp files generate identifiers starting with
IDR_ and IDS_ for resources and localized strings, respectively. In
Java, these are static members on an R class (e.g., R.string.foo
corresponds to IDS_FOO)..grd(p) file.IDS_FOO, delete its corresponding
IDS_FOO.png.sha1 file, which references a screenshot to help
translators.Update metrics:
enums.xml file under //tools/metrics/histograms/
and prepend (Obsolete) to the <int label=...>.histograms.xml file under //tools/metrics/histograms/.<int> values.//tools/metrics/histograms/enums.xml. The
entries are still needed for decoding data in future Chrome versions.Update comments:
Verify the build is not broken:
autoninja -C <dir>.Verify all tests still pass:
git diff to determine modified test files.tools/autotest.py -C <dir> <test-file> to
confirm the tests still pass.Format the code:
git cl format.