diff --git a/CHANGELOG.md b/CHANGELOG.md index da4260b..fbbfb2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [1.0.0] - 2026-05-30 ### Removed @@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `ExtensionFunctionGenerator` emits non-suspend `is*Enabled()` / `get*()` extension functions — they delegate to `getValueCached` and can be called from any context without a coroutine. Callers that previously wrapped them in `runBlocking { … }` or a coroutine scope can drop the wrapper. - `ConfigValues.resetOverride` re-resolves the effective value synchronously through the full provider priority chain; [getValueCached] reflects the updated value immediately after the call returns. - Generated `GeneratedLocalFlagsX` / `GeneratedRemoteFlagsX` objects are now `internal` to their declaring Gradle module — each feature module's flag declarations are an implementation detail and no longer leak across module boundaries. Cross-module flag introspection (e.g. the debug screen) flows exclusively through `GeneratedFeaturedRegistry.all`, which the aggregator plugin builds from per-module manifests. The sample app demonstrates the per-module wiring pattern: one `ConfigValues` per feature module plus a dedicated debug aggregator, all sharing the same `LocalConfigValueProvider`. +- The plugin's ProGuard-rules generation task is renamed from `generateProguardRules` to `generateFeaturedProguardRules` to avoid name collisions with other plugins. (#190) +- User documentation moved from the in-repo MkDocs site to the [GitHub Wiki](https://github.com/AndroidBroadcast/Featured/wiki); the `docs/` site and `mkdocs.yml` are removed from the repository. (#193) ### Added @@ -31,13 +33,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - New `dev.androidbroadcast.featured.application` Gradle plugin: aggregates `featured-manifest.json` artifacts from project dependencies declared via `featuredAggregation(project(...))` and generates `object GeneratedFeaturedRegistry { val all: List> }` in `build/generated/featured/commonMain/`. Apply alongside `dev.androidbroadcast.featured` in the application module; wire the output directory into your source set manually (e.g., `kotlin.sourceSets.commonMain.kotlin.srcDir(...)`). Modules declaring `enum` flags also require a regular `implementation(project(...))` dependency in the consumer so the enum class is on the compile classpath; primitive-only modules need only `featuredAggregation(...)`. - Three KMP sample feature modules — `:sample:feature-checkout`, `:sample:feature-promotions`, `:sample:feature-ui` — each declaring its own flags via the `featured { ... }` DSL. Serves as the canonical multi-module reference. - `EnumDropdown` component in `featured-debug-ui` for overriding `enum`-typed flags in `FeatureFlagsDebugScreen`; `ConfigParam` now carries `enumConstants: List?` populated by codegen so the debug UI can render the dropdown without reflection. -- `featured-gradle-plugin` extracted to a `build-logic/` included build; `pluginManagement { includeBuild("build-logic") }` in the root `settings.gradle.kts` exposes it to all main-build subprojects without a version coordinate. +- `featured-gradle-plugin` lives at the repo root as an included build; `pluginManagement { includeBuild("featured-gradle-plugin") }` in the root `settings.gradle.kts` exposes it to all main-build subprojects without a version coordinate. ### Fixed +- `ConfigValues.observe()` now wraps provider `Flow` collection in `catch` — exceptions thrown by a local or remote provider are routed to `onProviderError` instead of propagating and breaking the observation flow. (#196) - Restored R8 per-function DCE: ProGuard `-assumevalues` rules now target the actual Kotlin-compiled class name (`GeneratedFlagExtensionsXKt`). The rules were silently no-op since `@file:JvmName` was removed in an earlier PR; unused boolean flags are once again eliminated at shrinking time. - iOS framework can now `export(project(":sample:feature-*"))` without the K/N `ObjCExportCodeGenerator` crashing — requires `api(project(...))` linkage in the aggregator module so K/N has access to type adapters for generic `ConfigParam` specializations. +### Platform stability + +- **Android — Stable.** Public API and behavior are covered by SemVer. +- **iOS (SKIE / Swift DCE) — Preview.** Functional, but the Swift-facing API and the SPM packaging may change in minor releases without a major bump. +- **JVM — Preview.** Functional, but the API may change in minor releases without a major bump. + ## [1.0.0-Beta1] - 2026-05-17 ### Added @@ -115,5 +124,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - License mismatch: use MIT in all POM declarations (#174) - Stale artifact IDs in quick-start docs (#179) -[Unreleased]: https://github.com/androidbroadcast/Featured/compare/v1.0.0-Beta1...HEAD +[Unreleased]: https://github.com/androidbroadcast/Featured/compare/v1.0.0...HEAD +[1.0.0]: https://github.com/androidbroadcast/Featured/compare/v1.0.0-Beta1...v1.0.0 [1.0.0-Beta1]: https://github.com/androidbroadcast/Featured/releases/tag/v1.0.0-Beta1 diff --git a/CLAUDE.md b/CLAUDE.md index 1bbdbd0..e787fba 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -106,7 +106,7 @@ For non-reactive reads (logging, eager-conditional paths) use `configValues.getV - **Explicit API mode** is on for every KMP module — all public declarations need explicit visibility. Generated flag objects are deliberately `internal`. - **Version catalog** (`gradle/libs.versions.toml`) is the single source of truth for dependency versions. - **Spotless / ktlint** runs over `**/*.kt` and `**/*.kts` excluding `build/`. CI fails on `spotlessCheck`. -- **Binary Compatibility Validator** enforces public-API stability — a public-surface change without `apiDump` update fails CI. Featured has **no migration window** for breaking changes; breaking changes go in directly, the version number reflects it. +- **Public-API stability is reviewed manually in PRs** — there is no automated Binary Compatibility Validator gate (BCV was removed in #150). Reviewers check public-surface changes by hand. Featured has **no migration window** for breaking changes; breaking changes go in directly, the version number reflects it. - **Branching:** `develop` is the integration branch; PRs go to `develop`, not `main`. `main` is updated only on releases. One logical change per PR — do not bundle. - **Comment language:** English (per `.github/copilot-instructions.md`). - **iOS:** SKIE is applied in `:core`; the XCFramework is named `FeaturedCore`. SKIE config is `skie.toml` at repo root. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 08212cf..669b21a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,16 +63,14 @@ Featured follows [Semantic Versioning](https://semver.org/) (`MAJOR.MINOR.PATCH` - Changing a function signature in a way that requires call-site updates - Changing the behavior of an existing API in a way that requires migration -Binary Compatibility Validator (BCV) enforces this automatically — a CI check will fail if -a public API surface changes without an explicit `apiDump` update. +Public API changes are reviewed manually during code review — there is no automated Binary Compatibility Validator gate. Reviewers verify that any public-surface change is intentional and that the version bump reflects it. -## Deprecation Policy +## API Stability and Breaking Changes -1. An API is marked `@Deprecated` with a `ReplaceWith` suggestion and a `DeprecationLevel.WARNING`. -2. The deprecated API is kept for **at least one minor release** before being promoted to `ERROR` level. -3. APIs at `ERROR` level are removed in the **next major release**. +Featured has **no deprecation or migration window**. Breaking changes are made directly; the version number reflects the impact per the Versioning table above. -Example timeline: deprecated in `1.2.0` → error in `1.3.0` → removed in `2.0.0`. +- **Android (Stable):** a breaking public-API change (removed/renamed symbol, changed signature) requires a `MAJOR` version bump. +- **iOS (Preview) and JVM (Preview):** public API may change in `MINOR` releases without a major bump; no migration window is provided. ## Releasing a New Version diff --git a/README.md b/README.md index 7147969..229d120 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,16 @@ Featured is a type-safe, reactive feature-flag and configuration management libr - **Multiple providers** — DataStore, SharedPreferences, NSUserDefaults, JavaPreferences, Firebase Remote Config, ConfigCat, or a custom one. - **Debug UI** — a ready-made Compose screen for overriding flags at runtime. +## Platform stability + +| Platform | Status | +|---|---| +| Android | **Stable** | +| iOS (SKIE / DCE) | **Preview** | +| JVM | **Preview** | + +*Preview* means the platform is functional but its public API may change in minor releases without a major version bump. *Stable* platforms follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + ## Quick example ```kotlin diff --git a/gradle.properties b/gradle.properties index c4166f5..8baa471 100644 --- a/gradle.properties +++ b/gradle.properties @@ -36,7 +36,7 @@ android.r8.strictInputValidation=true android.proguard.failOnMissingFiles=true # Publishing -VERSION_NAME=1.0.0-Beta1 +VERSION_NAME=1.0.0 # Dokka org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled