Skip to content

Remove FlagRegistry; make FeatureFlagsDebugScreen UI-agnostic#199

Merged
kirich1409 merged 4 commits into
developfrom
refactor/ui-agnostic-debug-screen
May 19, 2026
Merged

Remove FlagRegistry; make FeatureFlagsDebugScreen UI-agnostic#199
kirich1409 merged 4 commits into
developfrom
refactor/ui-agnostic-debug-screen

Conversation

@kirich1409
Copy link
Copy Markdown
Contributor

@kirich1409 kirich1409 commented May 19, 2026

Summary

Completes the 4-PR redesign of Featured's flag registry (PR C of 4).
PR A (#197) added per-module featured-manifest.json producer; PR B (#198)
added the dev.androidbroadcast.featured.application aggregator plugin +
GeneratedFeaturedRegistry. This PR removes the legacy FlagRegistry runtime
singleton and the generateFlagRegistrar Gradle codegen pipeline, and makes
FeatureFlagsDebugScreen UI-agnostic.

What changed

FeatureFlagsDebugScreen signature (breaking):

fun FeatureFlagsDebugScreen(
    configValues: ConfigValues,
    registry: List<ConfigParam<*>>,
    modifier: Modifier = Modifier,
)

Pass GeneratedFeaturedRegistry.all (recommended for multi-module apps using the
aggregator plugin) or build the list inline. Each ConfigParam.key must be unique
within the list; the screen documents that the LaunchedEffect keys via equals
(structural) and asks callers for a stable reference.

Removed:

  • featured-registry module — FlagRegistry global singleton + expect/actual FlagRegistryDelegate.
  • featured-gradle-plugingenerateFlagRegistrar task, FlagRegistrarGenerator, GenerateFlagRegistrarTask. Per-module GeneratedFlagRegistrar.kt is no longer generated.
  • LocalFlagEntry.kotlinReference — became dead with the registrar generator.
  • registerSampleFlags() from the sample.

Sample wiring:

  • New SampleFeatureFlags.all: List<ConfigParam<*>> — single source of truth.
  • MainActivity passes registry = SampleFeatureFlags.all to the debug UI.

Docs:

  • CHANGELOG.md### Removed + ### Changed entries in [Unreleased].
  • GitHub Wiki (Debug-UI, Multi-Module-Setup, Installation, Home, Best-Practices, Configuration-Cache) — committed locally to .wiki/; will be pushed after this PR merges.
  • featured-debug-ui/README.md and featured-gradle-plugin/CLAUDE.md updated.

CI:

  • Removed the now-stale :featured-registry:koverVerify Gradle invocation from .github/workflows/ci.yml.

Why

The previous design coupled the Debug UI to a runtime singleton populated via a
generated GeneratedFlagRegistrar per module. With the new aggregator plugin
(PR B), the consumer-side flow is declarative — featuredAggregation(project(...))
produces a typed GeneratedFeaturedRegistry.all. The singleton becomes redundant,
and the Debug UI can take the list as an explicit parameter, removing the global
state and making the screen testable / reusable.

Featured does not keep API compatibility — direct removal, no @Deprecated shims.

Status

Phase Result
Plan + execute (4-PR sequence) PASS — all 28 files of PR C landed, 3 commits + 1 finalize cleanup
Code review (initial) PASS — KDoc stability + alias inline fixes applied
/simplify PASS — dead val params = registry alias inlined
/finalize round 1 PASS — 1 P0 (CI cleanup) + 3 P1 fixes applied; 1 risk acknowledged (stability contract documented rather than absorbed)
CI 8/8 SUCCESS on 0da39c0 (Tests & Coverage, Analyze Kotlin, dependency-review, submit-gradle, Build Android, Lint, Build iOS, CodeQL)

How to test

Automated (all PASS locally before push):

  • ./gradlew spotlessCheck
  • ./gradlew :featured-gradle-plugin:check
  • ./gradlew :core:jvmTest + :featured-debug-ui:jvmTest + :featured-compose:jvmTest
  • ./gradlew :sample:android-app:assembleDebug
  • ./gradlew :sample:shared:jvmJar
  • Negative-grep: 0 hits for FlagRegistry|GeneratedFlagRegistrar|featured-registry|registerSampleFlags in *.kt/*.kts. Only intentional [Unreleased] CHANGELOG entries + historical fixture-report remain in *.md.

Manual smoke (recommended pre-merge):

  • Install :sample:android-app:assembleDebug on device/emulator, open the «Debug flags» entry, verify all 5 flags appear and toggling main_button_red persists.

Release notes

### Removed
- `featured-registry` module — `FlagRegistry` singleton and `FlagRegistryDelegate` expect/actual removed. Use `GeneratedFeaturedRegistry.all` (from `dev.androidbroadcast.featured.application` plugin) or an explicit `List<ConfigParam<*>>` instead.
- `generateFlagRegistrar` Gradle task and `GeneratedFlagRegistrar.kt` codegen.

### Changed
- **Breaking:** `FeatureFlagsDebugScreen` signature now `(configValues, registry, modifier)`. Pass `GeneratedFeaturedRegistry.all` from the new application plugin, or build the list inline.

Artifacts

Checklist

  • CI green (8/8 SUCCESS)
  • /finalize PASS — review fixes applied
  • Manual smoke (Android sample) confirms all 5 flags visible and togglable
  • Reviewer-confirmed: wiki push deferred until this PR is merged

🤖 Generated with Claude Code

FeatureFlagsDebugScreen now takes an explicit registry: List<ConfigParam<*>>
parameter instead of reading the global FlagRegistry singleton. Pass
GeneratedFeaturedRegistry.all (from the new dev.androidbroadcast.featured
.application plugin) or build the list inline.

Removed:
- featured-registry module (FlagRegistry + expect/actual FlagRegistryDelegate)
- generateFlagRegistrar task + FlagRegistrarGenerator + GenerateFlagRegistrarTask
- LocalFlagEntry.kotlinReference (dead with the registrar generator)
- registerSampleFlags() from sample

Sample wires the debug UI via SampleFeatureFlags.all.

Featured does not keep API compatibility; this is a direct breaking change
with no @deprecated shims.
@kirich1409 kirich1409 added gradle-plugin featured-gradle-plugin work debug-ui featured-debug-ui work registry featured-registry work docs Documentation sample Sample app labels May 19, 2026
LaunchedEffect uses identity equality on the registry parameter. A caller
passing a freshly-allocated list each recomposition would restart the
effect every frame. Spell out the stable-reference requirement in the
KDoc so callers do not stumble into a silent recomposition loop.
After the FlagRegistry removal, `val params = registry` became a pure
rename with no semantic value. Reference the registry parameter directly
in the LaunchedEffect body.
- Drop stale :featured-registry:koverVerify from CI workflow; the module
  no longer exists and Gradle would error on missing project at job start.
- Correct FeatureFlagsDebugScreen KDoc: LaunchedEffect compares keys via
  Any.equals (structural), not identity. Practical guidance unchanged.
- Document the key-uniqueness invariant on the registry parameter so
  callers know a duplicate ConfigParam.key trips LazyColumn at runtime.
- Replace "No feature flags registered." empty-state copy with
  "No feature flags to display." — the global FlagRegistry that the old
  phrasing referenced no longer exists.
@kirich1409 kirich1409 marked this pull request as ready for review May 19, 2026 16:45
Copilot AI review requested due to automatic review settings May 19, 2026 16:45
@qodo-code-review
Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

PR C of a 4-PR redesign that removes the legacy global FlagRegistry runtime singleton and its Gradle-side generateFlagRegistrar codegen, and makes FeatureFlagsDebugScreen take an explicit List<ConfigParam<*>> registry parameter instead of pulling from the singleton. The sample app is updated to pass SampleFeatureFlags.all directly.

Changes:

  • Deletes the featured-registry module (singleton + expect/actual delegate + tests) and unwires it from featured-bom, featured-debug-ui, sample/shared, and settings.gradle.kts.
  • Removes GenerateFlagRegistrarTask, FlagRegistrarGenerator, the generateFlagRegistrar plugin wiring, the now-dead LocalFlagEntry.kotlinReference property, and the corresponding tests; CI no longer runs :featured-registry:koverVerify.
  • Adds registry: List<ConfigParam<*>> parameter to FeatureFlagsDebugScreen (breaking) with stability/uniqueness KDoc, and adds SampleFeatureFlags.all as the single source of truth for the sample.

Reviewed changes

Copilot reviewed 29 out of 29 changed files in this pull request and generated no comments.

Show a summary per file
File Description
settings.gradle.kts Drops :featured-registry from the build.
sample/shared/.../SampleFeatureFlags.kt Adds all: List<ConfigParam<*>> aggregate.
sample/shared/.../SampleApp.kt Removes registerSampleFlags() helper that populated the singleton.
sample/shared/build.gradle.kts Drops dependency on :featured-registry.
sample/android-app/.../MainActivity.kt Passes SampleFeatureFlags.all to the debug screen.
featured-registry/** Module deleted (sources, tests, README, CLAUDE.md, build.gradle.kts).
featured-gradle-plugin/.../FeaturedPlugin.kt Removes generateFlagRegistrar registration and constant.
featured-gradle-plugin/.../GenerateFlagRegistrarTask.kt, FlagRegistrarGenerator.kt Deleted.
featured-gradle-plugin/.../LocalFlagEntry.kt Drops dead kotlinReference getter.
featured-gradle-plugin/.../ResolveFlagsTask.kt KDoc updated to drop reference to the removed task.
featured-gradle-plugin/src/test/.../LocalFlagEntryTest.kt New trimmed test covering remaining isLocal behavior.
featured-gradle-plugin/src/test/.../LocalFlagEntryKotlinReferenceTest.kt, FlagRegistrarGeneratorTest.kt, GenerateFlagRegistrarTaskRegistrationTest.kt Deleted along with the code they covered.
featured-gradle-plugin/CLAUDE.md Drops the row for the removed task.
featured-debug-ui/.../FeatureFlagsDebugScreen.kt New registry parameter, updated LaunchedEffect keys, empty-state copy reworded.
featured-debug-ui/README.md Documents both aggregator and inline-list registry sources.
featured-debug-ui/build.gradle.kts Drops dependency on :featured-registry.
featured-bom/build.gradle.kts Drops :featured-registry from the BOM.
CHANGELOG.md Adds Removed + Changed (breaking) entries under Unreleased.
.github/workflows/ci.yml Removes the stale :featured-registry:koverVerify invocation.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 29 files

Re-trigger cubic

@kirich1409 kirich1409 merged commit e3fe2bb into develop May 19, 2026
13 checks passed
@kirich1409 kirich1409 deleted the refactor/ui-agnostic-debug-screen branch May 19, 2026 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

debug-ui featured-debug-ui work docs Documentation gradle-plugin featured-gradle-plugin work registry featured-registry work sample Sample app

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants