Skip to content

feat(openfeature): DatadogOfflineOpenFeatureProvider [PR3] (FFL-2689, FFL-2690) - #1332

Merged
btthomas merged 14 commits into
blake.thomas/FFL-2666from
blake.thomas/FFL-2666-PR3
Jul 22, 2026
Merged

feat(openfeature): DatadogOfflineOpenFeatureProvider [PR3] (FFL-2689, FFL-2690)#1332
btthomas merged 14 commits into
blake.thomas/FFL-2666from
blake.thomas/FFL-2666-PR3

Conversation

@btthomas

@btthomas btthomas commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Offline feature flags — related PRs


Summary

Adds DatadogOfflineOpenFeatureProvider — a never-fetch OpenFeature provider for offline initialization — and the public exports for the offline API.

The offline provider evaluates flags and reports exposures/RUM exactly like DatadogOpenFeatureProvider, but never fetches configuration from the network: initialize/onContextChange set the evaluation context without a request, and the configuration is supplied via setConfiguration. A precomputed configuration carries the context it was computed for, so no separate OpenFeature.setContext call is needed.

  • Both providers share an internal DatadogCoreOpenFeatureProvider base that owns the flag client, event emitter, and flag evaluation; only the context-sourcing (initialize/onContextChange) differs.
  • Public exports — core: configurationFromString, configurationToString, ParsedFlagsConfiguration. OpenFeature: DatadogOfflineOpenFeatureProvider and a re-exported configurationFromString. The README documents offline usage.

No native changes: the offline path uses the existing native enable + exposure tracking and skips the native fetch; evaluation is all JS.

const provider = new DatadogOfflineOpenFeatureProvider();
provider.setConfiguration(configurationFromString(wire)); // no network
await OpenFeature.setProviderAndWait(provider);

const enabled = OpenFeature.getClient().getBooleanValue('new-feature', false);

Context handling: a mismatch is an error state

A precomputed configuration is a single-subject snapshot served against the context it was computed for. A runtime context that does not match that embedded context (compared after normalization) cannot be served, so the provider enters the OpenFeature ERROR state and evaluations fall back to the app's coded defaults (this replaces the earlier "ignore the mismatch and keep serving" behavior). See #1331 for the core model and error codes.

  • Lifecycle (context path): onContextChange is synchronous and throws the precise OpenFeature error (InvalidContextError / ProviderNotReadyError / GeneralError) on a non-servable context, so the Web SDK transitions straight to ERROR with no async race (a resolving handler would be unconditionally set back to READY). A matching context — or a cleared/empty one — returns normally and the SDK recovers to READY. initialize likewise throws unless the provider can serve, so registering before any configuration starts in ERROR and recovers when a valid config loads.
  • setConfiguration (outside the lifecycle): emits PROVIDER_ERROR (with the spec's top-level errorCode) when the configuration cannot be served, and emits PROVIDER_READY then PROVIDER_CONFIGURATION_CHANGED when recovering from an error; a healthy (re)load emits only PROVIDER_CONFIGURATION_CHANGED.
  • Empty context = no external override: clearContext() / setContext({}) re-adopt the embedded context (order-independent), so they recover rather than error — subject to the effective-context caveat below.
  • Requires @openfeature/web-sdk ^1.8.0, whose static-context lifecycle it relies on: the SDK owns the PROVIDER_RECONCILING / PROVIDER_CONTEXT_CHANGED events, and (a documented SDK limitation) drops the error code from the lifecycle-generated PROVIDER_ERROR event — the thrown error type is still correct for direct callers.

Recommended setup (documented in the README): bind the offline provider to a dedicated OpenFeature domain, give that domain an explicit empty context, and use a unique Datadog clientName (separate domains otherwise share DdFlags.getClient('default')). Note that clearContext(domain) falls back to the global context (which may be non-empty and mismatching, keeping the provider in ERROR), and the context split: OpenFeature hooks see the OpenFeature context ({} when unset) while Datadog exposure tracking uses the embedded context.

Intentional limitation: the offline configuration is applied only in the JS layer and is not propagated to the native SDKs. Native propagation is out of scope for this iteration, so hybrid apps that also read flags natively will have inconsistent configuration between JS and native. The example app therefore does not call OpenFeature.setContext, and its online/offline toggle uses distinct clientNames so the two providers don't share a FlagsClient.

Tests

react-native-openfeature (27 tests) covers both providers — the offline provider never fetches, serves against the configuration's embedded context, throws synchronously to enter ERROR on a mismatch (recovering on a matching/cleared context), and emits PROVIDER_ERROR with a top-level error code and PROVIDER_READY + PROVIDER_CONFIGURATION_CHANGED on recovery; the online provider still fetches on context. A real-FlagsClient, OpenFeature-bound integration test asserts the SDK provider status through ERROR/READY transitions (mismatch, clearContext, provider-first, setConfiguration recovery) plus domain/global-context isolation. The core flags/ suite passes. Lint and tsc are clean on both packages.

Example App

iOS

Screenshot 2026-07-07 at 9 34 43 PM

Android

Screenshot 2026-07-07 at 9 44 29 PM

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds an offline OpenFeature provider for the React Native Datadog SDK, enabling feature-flag evaluation from a precomputed configuration supplied by the app (no network fetch), while keeping evaluation + exposure/RUM tracking aligned with the existing online provider.

Changes:

  • Introduces DatadogOfflineOpenFeatureProvider and refactors shared logic into DatadogCoreOpenFeatureProvider.
  • Adds offline configuration plumbing/events (context set without fetch; emit ConfigurationChanged / Error / Ready as appropriate).
  • Publicly exports offline configuration helpers/types from core (configurationFromString, configurationToString, ParsedFlagsConfiguration) and re-exports configurationFromString from the OpenFeature package; updates docs + adds tests.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/react-native-openfeature/src/provider.ts Refactors online provider to extend shared core provider; keeps fetch-on-context behavior.
packages/react-native-openfeature/src/offlineProvider.ts Adds offline provider that never fetches; supports setConfiguration + event mapping.
packages/react-native-openfeature/src/mappers.ts Extracts OF → Datadog context conversion + empty-context detection helper.
packages/react-native-openfeature/src/index.ts Exports offline provider and re-exports configurationFromString.
packages/react-native-openfeature/src/coreProvider.ts Adds shared base provider owning FlagsClient, event emitter, and evaluations.
packages/react-native-openfeature/src/tests/provider.test.ts Adds unit coverage for online provider behavior after refactor.
packages/react-native-openfeature/src/tests/offlineProvider.test.ts Adds unit coverage for offline provider no-fetch behavior + events.
packages/react-native-openfeature/src/tests/offlineProvider.integration.test.ts Adds integration coverage using real FlagsClient for offline flow edge cases.
packages/react-native-openfeature/README.md Documents offline initialization flow and usage.
packages/core/src/index.tsx Exposes configuration parse/serialize utilities and parsed config type publicly.
packages/core/src/flags/FlagsClient.ts Returns configuration outcome status from offline context/config APIs for provider event mapping.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +51 to +59
constructor(options: DatadogOpenFeatureProviderOptions = {}) {
if (!options.clientName) {
options.clientName = 'default';
}

this.options = options;

this.flagsClient = DdFlags.getClient(this.options.clientName);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is a good point, we should not mutate the user provided options parameter.

Comment on lines +34 to +40
* Whether an OpenFeature evaluation context carries no information (no targeting key and no
* attributes). Used by the offline provider to avoid overwriting a configuration's embedded
* context with an empty context stamped by the OpenFeature lifecycle.
*/
export const isEmptyContext = (context: OFEvaluationContext): boolean => {
return Object.keys(context).length === 0;
};
@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR2 branch from 8cce4b5 to 3bd5e6e Compare July 8, 2026 14:51
@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR3 branch from 38a7e7a to a754c6c Compare July 8, 2026 14:52
@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR2 branch from 3bd5e6e to 752c7a6 Compare July 16, 2026 17:45
@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR3 branch from a754c6c to 04ce353 Compare July 16, 2026 17:45
@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR2 branch from 752c7a6 to 22ebc03 Compare July 16, 2026 18:34
@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR3 branch from 04ce353 to a9abc3c Compare July 16, 2026 18:35
@datadog-datadog-us1-prod

This comment has been minimized.

@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR3 branch from a9abc3c to d143bd4 Compare July 17, 2026 01:52
@btthomas
btthomas marked this pull request as ready for review July 17, 2026 12:20
@btthomas
btthomas requested review from a team as code owners July 17, 2026 12:20
@btthomas
btthomas requested review from leoromanovsky and typotter and removed request for a team July 17, 2026 12:20
@leoromanovsky
leoromanovsky requested a review from sameerank July 17, 2026 12:21
// Set the provider after loading the configuration so it is ready with real flag values.
await OpenFeature.setProviderAndWait(provider);

// Evaluate flags — no network request is made.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: no network request is expected here, that was going to be at setProviderAndAwait


The configuration carries the evaluation context it was computed for, so you do not need to call
`OpenFeature.setContext` for the offline precomputed flow. If you do set a context, it must match
the configuration's context; otherwise the provider reports an error and serves default values.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

good note

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I actually decided this doesn't make sense in the OfflineProvider when setConfiguration is called with precomputed variants. So instead, if the customer calls setContext with a mismatch, we'll keep serving the precomputed but emit a warning.

this.emitConfigurationOutcome(outcome);
}

private emitConfigurationOutcome(outcome: ConfigurationOutcome): void {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In the readme below you mention an error is thrown if the user provides their own context; is that modeled here or elsewhere?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

We changed the design: a mismatched context is no longer an error. The README has been updated.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

And now I need to walk all of that back from yesterday's conversation.

@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR3 branch 2 times, most recently from c94cd7d to c1d7a77 Compare July 17, 2026 14:16

@evazorro evazorro left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

One nit, but approving from now!

Comment thread packages/react-native-openfeature/README.md
@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR2 branch from 6133947 to c63c75e Compare July 17, 2026 14:40
@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR3 branch 2 times, most recently from c3f46ee to e0175eb Compare July 17, 2026 18:59
);
await OpenFeature.setProviderAndWait(provider);
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Perhaps replacing the return with an else would look a bit cleaner.

Comment on lines +112 to +135
private emitConfigurationOutcome(outcome: ConfigurationOutcome): void {
if (outcome === 'ready') {
if (this.hasEmittedError) {
// Recover from a prior error state: emit READY to clear the provider status
// (a bare CONFIGURATION_CHANGED would not clear it).
this.hasEmittedError = false;
this.events.emit(ProviderEvents.Ready);
} else {
// The provider is already READY from initialize; a (re)loaded configuration is
// signalled as a configuration change.
this.events.emit(ProviderEvents.ConfigurationChanged);
}
} else if (outcome === 'invalid') {
this.hasEmittedError = true;
this.events.emit(ProviderEvents.Error, {
message:
'The Datadog offline provider cannot serve the loaded configuration (invalid).'
});
}
// 'none' — no configuration engaged yet; nothing to signal. A runtime context that
// does not match a precomputed snapshot is not an error: the client ignores it
// (serving the snapshot for its embedded context) and warns.
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
private emitConfigurationOutcome(outcome: ConfigurationOutcome): void {
if (outcome === 'ready') {
if (this.hasEmittedError) {
// Recover from a prior error state: emit READY to clear the provider status
// (a bare CONFIGURATION_CHANGED would not clear it).
this.hasEmittedError = false;
this.events.emit(ProviderEvents.Ready);
} else {
// The provider is already READY from initialize; a (re)loaded configuration is
// signalled as a configuration change.
this.events.emit(ProviderEvents.ConfigurationChanged);
}
} else if (outcome === 'invalid') {
this.hasEmittedError = true;
this.events.emit(ProviderEvents.Error, {
message:
'The Datadog offline provider cannot serve the loaded configuration (invalid).'
});
}
// 'none' — no configuration engaged yet; nothing to signal. A runtime context that
// does not match a precomputed snapshot is not an error: the client ignores it
// (serving the snapshot for its embedded context) and warns.
}
}
private emitConfigurationOutcome(outcome: ConfigurationOutcome): void {
if (outcome === 'none') return;
if (outcome === 'invalid') {
this.hasEmittedError = true;
this.events.emit(ProviderEvents.Error, {
message: 'The Datadog offline provider cannot serve the loaded configuration (invalid).'
});
return;
}
// outcome === 'ready'
if (this.hasEmittedError) {
// Recover from a prior error: emit READY to clear provider status
// (a bare CONFIGURATION_CHANGED would not clear it).
this.hasEmittedError = false;
this.events.emit(ProviderEvents.Ready);
} else {
this.events.emit(ProviderEvents.ConfigurationChanged);
}
}

@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR2 branch from c63c75e to c5831d8 Compare July 20, 2026 21:28
@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR3 branch 2 times, most recently from a8387e3 to fb2419c Compare July 21, 2026 21:43
@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR3 branch from fb2419c to 0778e4c Compare July 22, 2026 14:19
@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR2 branch from 320d49f to f7e019f Compare July 22, 2026 14:31
btthomas and others added 14 commits July 22, 2026 10:31
…FL-2690)

A never-fetch OpenFeature provider for offline initialization. It behaves like
DatadogOpenFeatureProvider — same evaluation and exposure/RUM tracking — except
initialize/onContextChange use FlagsClient.setEvaluationContextWithoutFetching
instead of the fetching setEvaluationContext, so it never hits the CDN. It
exposes setConfiguration (delegating to the FlagsClient) and emits provider
events from the configuration outcome: first config -> READY, subsequent ->
CONFIGURATION_CHANGED, mismatch/invalid -> ERROR.

- Core: setConfiguration and setEvaluationContextWithoutFetching now return a
  ConfigurationStatus so the provider can map outcome -> event; export
  configurationFromString/configurationToString, ParsedFlagsConfiguration, and
  ConfigurationStatus.
- react-native-openfeature: make flagsClient protected and export toDdContext so
  the offline provider can reuse the base; export DatadogOfflineOpenFeatureProvider
  and re-export configurationFromString; README offline-init section.

No native changes — the offline path uses existing native enable + trackEvaluation
and skips native setEvaluationContext; evaluation is all JS.

Tests: provider never calls the fetching path, delegates setConfiguration, emits
the right events, and resolves through the client.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both the online and offline providers now extend a shared, internal (un-exported)
DatadogCoreOpenFeatureProvider that owns the FlagsClient, event emitter, and
resolveX evaluation. DatadogOpenFeatureProvider keeps its fetch-on-context
initialize/onContextChange, and DatadogOfflineOpenFeatureProvider extends the
base directly instead of the online provider, so it no longer inherits the
online fetch/promise-chain machinery. Public API and online behavior are
unchanged and the base is not exported. Matches the Portable RFC's CoreProvider.

Adds a provider test locking the online provider's fetch-on-initialize behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… exports)

Two-agent review follow-ups on the offline provider:
- C1 (critical): the offline provider no longer stamps an empty OpenFeature
  context in initialize/onContextChange, so OpenFeature's initialize({}) on
  setProviderAndWait can't defeat the configuration's embedded context (which
  previously caused a spurious mismatch -> PROVIDER_ERROR for every real config).
- H1/M1 (events): the provider now emits CONFIGURATION_CHANGED on a successful
  load (OpenFeature already emits READY when initialize resolves) and emits READY
  only to clear a prior error state, removing the premature/duplicate READY and
  fixing error recovery.
- M2/L5: keep ConfigurationStatus internal (dropped from the public core export;
  the provider derives it via ReturnType) and document it may widen for rules.
- L4: move toDdContext (and a new isEmptyContext) into mappers.ts so the base
  module no longer carries an exported free helper.
- L3: fix the offline provider's stale TSDoc link.

Tests: add a real-FlagsClient integration test that would have caught C1
(initialize({}) then setConfiguration serves; explicit mismatch errors), and
update the unit tests for the empty-context and event behavior. Also lock the
online provider's fetch-on-initialize behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…2690)

Demonstrate DatadogOfflineOpenFeatureProvider in both example apps alongside the online provider, with a runtime 'Flags source' toggle. Loads a bundled ConfigurationWire (no network) and evaluates rn-sdk-test-boolean-flag.

- example/: flags helpers + FlagsSourceToggle, wired into App.tsx/MainScreen. - example-new-architecture/: same helpers. App.tsx renders the boolean flag via useBooleanFlagDetails (react-sdk 1.1.0 has no FeatureFlag component) and aligns setContext to the wire's embedded context.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…+ example (PR3)

Follows the PR2 change: an offline precomputed configuration no longer reports a context mismatch, so the provider no longer emits PROVIDER_ERROR for a differing runtime context — a differing context is ignored (the client warns and serves the snapshot for its embedded context). emitConfigurationOutcome now only errors on an 'invalid' configuration.

example-new-architecture no longer calls OpenFeature.setContext: the bundled precomputed snapshot is served against its embedded context, so setting a runtime context is unnecessary (and would just be ignored with a warning). Tests updated accordingly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ty-context, examples)

README and the new-arch example now describe the correct behavior. A differing runtime context for a precomputed snapshot is ignored with a warning, not a PROVIDER_ERROR that serves defaults.

offlineProvider.applyContext no longer emits PROVIDER_CONFIGURATION_CHANGED on a context change. A precomputed snapshot is context-independent, so a context change is not a config change and config events come from setConfiguration.

isEmptyContext now treats a context whose values are all undefined as empty, so it cannot defeat the empty-context guard. The two example config helpers are unified on DEFAULT_OFFLINE_CONTEXT and drop the favoriteFruit the deleted setContext needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… invalid (PR3 review)

In the documented order (setConfiguration then setProviderAndWait), setConfiguration emits its PROVIDER_ERROR before OpenFeature has subscribed, so an invalid configuration was dropped and initialize resolved anyway, leaving the provider misleadingly READY while serving only default values. initialize now rejects when a loaded configuration is invalid, so OpenFeature starts the provider in ERROR. Setting a provider first and configuring later still works (initialize resolves with no config, and a later invalid setConfiguration emits PROVIDER_ERROR with listeners present).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…(PR3)

Switch the offline provider from "ignore a mismatched runtime context"
to surfacing the correct OpenFeature error state, tracking the widened
ConfigurationResult the core now returns.

- onContextChange is now synchronous and throws the precise OpenFeature
  error (InvalidContextError / ProviderNotReadyError / GeneralError) so
  the Web SDK transitions the provider to ERROR with no async race; a
  matching/cleared context returns normally and the SDK recovers to
  READY. initialize likewise throws unless the provider can serve.
- An empty context ({}, clearContext) means "no external override" and
  re-adopts the configuration's embedded context everywhere (order-
  independent), via resetEvaluationContextWithoutFetching.
- setConfiguration emits PROVIDER_ERROR with the spec's top-level
  errorCode on failure, and emits PROVIDER_READY then
  PROVIDER_CONFIGURATION_CHANGED when recovering from an error.
- Registering the provider before any configuration now initializes to
  ERROR (nothing to serve) and recovers when a valid config loads.
- README: warn against setting a different context (errors + serves
  coded defaults), recommend a dedicated domain + explicit empty domain
  context + unique clientName, document the hooks/exposure context split,
  and target Web SDK 1.8.0 semantics.
- Tests: unit tests for the synchronous throw + recovery + top-level
  event errorCode; an OpenFeature-bound integration test asserting real
  ERROR/READY status transitions (mismatch, clearContext, provider-first,
  setConfiguration recovery).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…viders

The flags-source toggle created both providers with the default clientName,
so they shared one FlagsClient. Switching from offline to online then ran an
online fetch on the client that held the offline configuration — unsupported,
and the source of the stale-overlay edge case. Give each provider its own
clientName so the demo models correct usage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- README: "clearing context recovers" only when the effective context is
  empty or matching; clearContext(domain) falls back to the (possibly
  mismatching) global context. A domain with no context of its own inherits
  the global context, so bind to a dedicated domain AND give it an explicit
  empty context.
- README: warn against the non-awaiting setProvider() + immediate
  setConfiguration ordering (it races); configure first or await
  setProviderAndWait.
- README/comments: "deep-equal" -> matches after normalization; align the
  compat note to the actual peer range (^1.7.3, verified against 1.8.0).
- core: the configuration barrel comment no longer claims the helpers are
  unexported — configurationFromString/configurationToString and
  ParsedFlagsConfiguration are now part of the public entry point.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Unit tests assert the concrete thrown error classes (InvalidContextError /
  ProviderNotReadyError / GeneralError) instead of a bare toThrow().
- Integration test asserts the INVALID_CONTEXT evaluation error code and that
  recovery serves the retained value (stubbing the native TurboModule so a
  ready-state evaluation can track without throwing).
- Add domain/global-context isolation cases: a domain with no context inherits
  a mismatching global context (ERROR); an explicit empty domain context
  isolates it from later global changes; clearing the domain context falls back
  to the (mismatching) global context (ERROR).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Raise the `@openfeature/web-sdk` peer (and dev) dependency to `^1.8.0`, the
  version the offline lifecycle behavior is developed and verified against, so
  the supported minimum matches what is tested.
- Class JSDoc: apply the effective-context caveat (clearContext(domain) can fall
  back to a non-empty, mismatching global context and keep the provider ERROR),
  rather than implying clearing always recovers.
- README: the non-awaiting setProvider + setConfiguration race settles (rejects)
  after recovery — reword "resolve" accordingly — and state the ^1.8.0 requirement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add an integration test for the recommended sequence — a mismatching global
context already set, an explicit empty domain context, then provider
registration — asserting the domain provider isolates itself and stays READY.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@btthomas
btthomas force-pushed the blake.thomas/FFL-2666-PR3 branch from 0778e4c to a316444 Compare July 22, 2026 14:32
Base automatically changed from blake.thomas/FFL-2666-PR2 to blake.thomas/FFL-2666 July 22, 2026 14:50
@btthomas
btthomas merged commit 2f3c59e into blake.thomas/FFL-2666 Jul 22, 2026
1 of 8 checks passed
@btthomas
btthomas deleted the blake.thomas/FFL-2666-PR3 branch July 22, 2026 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants