@wireai/activation 0.13.0 → 0.13.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +7 -4
- package/CHANGELOG.md +341 -4
- package/README.md +98 -2
- package/dist/analytics/index.d.mts +4 -4
- package/dist/analytics/index.d.ts +4 -4
- package/dist/analytics/index.js +164 -471
- package/dist/analytics/index.js.map +1 -1
- package/dist/analytics/index.mjs +162 -469
- package/dist/analytics/index.mjs.map +1 -1
- package/dist/coachmarks/index.d.mts +14 -1
- package/dist/coachmarks/index.d.ts +14 -1
- package/dist/coachmarks/index.js +58 -14
- package/dist/coachmarks/index.js.map +1 -1
- package/dist/coachmarks/index.mjs +58 -14
- package/dist/coachmarks/index.mjs.map +1 -1
- package/dist/{currentSession-_GynvhzT.d.mts → currentSession-BoWtr3Jp.d.mts} +299 -14
- package/dist/{currentSession-D7zabMXK.d.ts → currentSession-CCOMlaQ2.d.ts} +299 -14
- package/dist/{decision-Bl_M2y3r.d.mts → decision-Cjw0jbEj.d.mts} +1 -1
- package/dist/{decision-Cau5KmP6.d.ts → decision-GfpXAsk_.d.ts} +1 -1
- package/dist/index.d.mts +218 -4
- package/dist/index.d.ts +218 -4
- package/dist/index.js +1104 -888
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +887 -692
- package/dist/index.mjs.map +1 -1
- package/dist/questionnaire/index.d.mts +42 -10
- package/dist/questionnaire/index.d.ts +42 -10
- package/dist/questionnaire/index.js +45 -13
- package/dist/questionnaire/index.js.map +1 -1
- package/dist/questionnaire/index.mjs +45 -13
- package/dist/questionnaire/index.mjs.map +1 -1
- package/dist/reviews/index.d.mts +4 -4
- package/dist/reviews/index.d.ts +4 -4
- package/dist/reviews/index.js +39 -8
- package/dist/reviews/index.js.map +1 -1
- package/dist/reviews/index.mjs +39 -8
- package/dist/reviews/index.mjs.map +1 -1
- package/dist/showcase/index.js +7 -2
- package/dist/showcase/index.js.map +1 -1
- package/dist/showcase/index.mjs +7 -2
- package/dist/showcase/index.mjs.map +1 -1
- package/dist/{transport-DsRe4epC.d.ts → transport-CefdERPs.d.mts} +44 -5
- package/dist/{transport-CF_eHwzC.d.mts → transport-DFuPyCoJ.d.ts} +44 -5
- package/dist/{types-Buj9Lw9t.d.ts → types-UVYt9BJe.d.ts} +41 -1
- package/dist/{types-CNUqMK0D.d.mts → types-l2tfg23P.d.mts} +41 -1
- package/package.json +4 -1
- package/src/OnboardingFlow.tsx +175 -15
- package/src/WireOnboarding.tsx +70 -8
- package/src/activation/wireActivation.ts +3 -3
- package/src/analytics/analyticsEvent.ts +16 -1
- package/src/analytics/analyticsFacade.ts +2 -2
- package/src/analytics/eventQueue.ts +85 -20
- package/src/analytics/reportClientEvent.ts +68 -12
- package/src/cards/CardGridSelectCard.tsx +1 -1
- package/src/cards/ChipSelectCard.tsx +2 -2
- package/src/cards/PermissionCard.tsx +438 -0
- package/src/cards/SelectionCard.tsx +1 -1
- package/src/cards/index.ts +7 -0
- package/src/coachmarks/runtime.ts +62 -2
- package/src/coachmarks/useCoachmarkTour.ts +62 -14
- package/src/context/deviceId.ts +4 -4
- package/src/features/WireFeaturesProvider.tsx +4 -1
- package/src/identity/userIdentity.ts +1 -1
- package/src/illustrations/defaultIllustrations.tsx +44 -3
- package/src/index.ts +38 -0
- package/src/permissions/index.ts +64 -0
- package/src/permissions/permissionCopy.ts +87 -0
- package/src/permissions/permissionEvents.ts +76 -0
- package/src/permissions/permissionMemory.ts +88 -0
- package/src/permissions/placement.ts +88 -0
- package/src/permissions/types.ts +131 -0
- package/src/questionnaire/QuestionnaireGate.tsx +90 -10
- package/src/questionnaire/index.ts +9 -1
- package/src/questionnaire/transport.ts +46 -11
- package/src/reviews/ReviewGate.tsx +61 -6
- package/src/reviews/index.ts +10 -1
- package/src/reviews/transport.ts +58 -12
- package/src/session/persistedSession.ts +10 -3
- package/src/session-analytics/useLifecycleEvents.ts +1 -1
- package/src/theme/ThemeContext.tsx +42 -1
- package/src/types.ts +66 -4
- package/src/utils/submitResult.ts +39 -0
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/expo-modules-core/src/errors/CodedError.ts","../node_modules/expo-modules-core/src/NativeModulesProxy.ts","../node_modules/expo-modules-core/src/TurboModuleToExpoModuleProxy.ts","../node_modules/expo-modules-core/src/ensureNativeModulesAreInstalled.ts","../node_modules/expo-modules-core/src/requireNativeModule.ts","../node_modules/expo-modules-core/src/sweet/setUpJsLogger.fx.ts","../node_modules/expo-modules-core/src/registerWebModule.ts","../node_modules/expo-modules-core/src/TypedArrays.types.ts","../node_modules/expo-modules-core/src/PermissionsInterface.ts","../node_modules/expo-modules-core/src/PermissionsHook.ts","../node_modules/expo-modules-core/src/Refs.ts","../node_modules/expo-modules-core/src/hooks/useReleasingSharedObject.ts","../node_modules/expo-modules-core/src/reload.ts","../node_modules/expo-modules-core/src/index.ts","../node_modules/expo-constants/src/Constants.types.ts","../node_modules/expo-constants/src/ExponentConstants.ts","../node_modules/expo-constants/src/Constants.ts","../src/theme/defaultTheme.ts","../src/theme/ThemeContext.tsx","../src/components/Illustration.tsx","../src/illustrations/defaultIllustrations.tsx","../src/icons/IconRegistry.tsx","../src/theme/typography.ts","../src/motion/motionSpec.ts","../src/motion/useReducedMotion.ts","../src/components/AnimatedSparkle.tsx","../src/components/LoadingBlock.tsx","../src/components/LoadingScreen.tsx","../src/components/StepProgress.tsx","../src/components/OnboardingScaffold.tsx","../src/components/Button.tsx","../src/components/ErrorBlock.tsx","../src/components/CardLayout.tsx","../src/components/CompletionView.tsx","../src/components/CardHandoff.tsx","../src/utils/deriveAnswers.ts","../src/utils/readProgress.ts","../src/analytics/reportClientEvent.ts","../src/analytics/sendPreview.ts","../src/OnboardingFlow.tsx","../src/cards/ChipSelectCard.tsx","../src/cards/TextInputCard.tsx","../src/icons/expoIcons.ts","../src/icons/vocabulary.ts","../src/icons/WireIcon.tsx","../src/cards/optionSchema.ts","../src/cards/SelectionCard.tsx","../src/cards/CardGridSelectCard.tsx","../src/cards/StatusCard.tsx","../src/cards/NumberStepperCard.tsx","../src/cards/InterstitialCard.tsx","../src/cards/index.ts","../src/device/appVersion.ts","../src/device/deviceModel.ts","../src/device/deviceContext.ts","../src/identity/identityRecord.ts","../src/context/deviceId.ts","../src/utils/warnInDev.ts","../src/analytics/currentSession.ts","../src/session/persistedSession.ts","../src/identity/userIdentity.ts","../src/context/userContext.ts","../src/WireOnboarding.tsx","../src/DemoOnboarding.tsx","../src/theme/themeFromBrand.ts","../src/motion/centeredModalMotion.ts","../src/components/CenteredModal.tsx","../src/features/defaults.ts","../src/features/cache.ts","../src/features/fetchWireFeatures.ts","../src/features/useWireFeatures.ts","../src/features/WireFeaturesProvider.tsx","../src/config/wireConfigFromEnv.ts","../src/config/onboardingFlag.ts","../src/analytics/analyticsEvent.ts","../src/attribution/attribution.ts","../src/activation/revalidation.ts","../src/activation/wireActivation.ts","../src/activation/useWireActivation.ts","../src/revenuecat/purchaseEvents.ts","../src/revenuecat/revenueCatBridge.ts","../src/session-analytics/reportSessionStart.ts","../src/session-analytics/useSessionStart.ts","../src/session-analytics/lifecycle.ts","../src/analytics/eventQueue.ts","../src/session-analytics/useLifecycleEvents.ts"],"names":["name","_a","AppOwnership","ExecutionEnvironment","UserInterfaceIdiom","createContext","useMemo","jsx","useContext","EMPTY_REGISTRY","useEffect","styles","Text","React","StyleSheet","useRef","Animated","Easing","View","useState","jsxs","SafeAreaView","makeStyles","easeWire","useCallback","_b","_c","_d","step","_e","_f","validators","Fragment","Pressable","schema","z","runtimeRequire","interop","constants","safeInterop","Platform","Modal","READ_TIMEOUT_MS","withTimeout","cached","globalSlot","parsePersisted","AppState"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * A general error class that should be used for all errors in Expo modules.\n * Guarantees a `code` field that can be used to differentiate between different\n * types of errors without further subclassing Error.\n */\nexport class CodedError extends Error {\n code: string;\n info?: any;\n\n constructor(code: string, message: string) {\n super(message);\n this.code = code;\n }\n}\n","import type { ProxyNativeModule } from './NativeModulesProxy.types';\n\n// We default to an empty object shim wherever we don't have an environment-specific implementation\n\n/**\n * @deprecated `NativeModulesProxy` is deprecated and might be removed in the future releases.\n * Use `requireNativeModule` or `requireOptionalNativeModule` instead.\n */\nexport default {} as Record<string, ProxyNativeModule>;\n","// Copyright © 2024 650 Industries.\nimport type { TurboModule } from 'react-native';\n\nexport function createTurboModuleToExpoProxy(turboModule: TurboModule | null, name: string) {\n return null;\n}\n","// Installs the expo global on web\nimport './polyfill';\n\n/**\n * Ensures that the native modules are installed in the current runtime.\n * Otherwise, it synchronously calls a native function that installs them.\n */\nexport function ensureNativeModulesAreInstalled(): void {\n // No-op on web\n}\n","import { TurboModuleRegistry } from 'react-native';\n\nimport NativeModulesProxy from './NativeModulesProxy';\nimport { createTurboModuleToExpoProxy } from './TurboModuleToExpoModuleProxy';\nimport { ensureNativeModulesAreInstalled } from './ensureNativeModulesAreInstalled';\n\n/**\n * Imports the native module registered with given name. In the first place it tries to load\n * the module installed through the JSI host object and then falls back to the bridge proxy module.\n * Notice that the modules loaded from the proxy may not support some features like synchronous functions.\n *\n * @param moduleName Name of the requested native module.\n * @returns Object representing the native module.\n * @throws Error when there is no native module with given name.\n */\nexport function requireNativeModule<ModuleType = any>(moduleName: string): ModuleType {\n const nativeModule = requireOptionalNativeModule<ModuleType>(moduleName);\n\n if (!nativeModule) {\n throw new Error(`Cannot find native module '${moduleName}'`);\n }\n return nativeModule;\n}\n\n/**\n * Imports the native module registered with the given name. The same as `requireNativeModule`,\n * but returns `null` when the module cannot be found instead of throwing an error.\n *\n * @param moduleName Name of the requested native module.\n * @returns Object representing the native module or `null` when it cannot be found.\n */\nexport function requireOptionalNativeModule<ModuleType = any>(\n moduleName: string\n): ModuleType | null {\n ensureNativeModulesAreInstalled();\n\n try {\n return (\n globalThis.expo?.modules?.[moduleName] ??\n NativeModulesProxy[moduleName] ??\n createTurboModuleToExpoProxy(TurboModuleRegistry.get(moduleName), moduleName) ??\n null\n );\n } catch (e) {\n const error = e as Error;\n console.warn(`An error occurred while requiring the '${moduleName}' module: ${error.message}`);\n return null;\n }\n}\n","import { CodedError } from '../errors/CodedError';\nimport { requireOptionalNativeModule } from '../requireNativeModule';\n\ntype LogListener = {\n action: (...data: any[]) => void;\n eventName: string;\n};\n\nif (\n __DEV__ &&\n typeof window !== 'undefined' &&\n (process.env.EXPO_OS === 'android' || process.env.EXPO_OS === 'ios')\n) {\n const NativeJSLogger = requireOptionalNativeModule('ExpoModulesCoreJSLogger');\n if (NativeJSLogger) {\n const onNewException: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewError',\n action: console.error,\n };\n\n const onNewWarning: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewWarning',\n action: console.warn,\n };\n\n const onNewDebug: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewDebug',\n action: console.debug,\n };\n\n const onNewInfo: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewInfo',\n action: console.info,\n };\n\n const onNewTrace: LogListener = {\n eventName: 'ExpoModulesCoreJSLogger.onNewTrace',\n action: console.trace,\n };\n\n const listeners: LogListener[] = [\n onNewException,\n onNewWarning,\n onNewDebug,\n onNewInfo,\n onNewTrace,\n ];\n\n for (const listener of listeners) {\n NativeJSLogger.addListener(listener.eventName, ({ message }: { message: string }) => {\n listener.action(message);\n });\n }\n }\n}\n\ndeclare namespace globalThis {\n let ExpoModulesCore_CodedError: undefined | typeof CodedError;\n}\n\n// We have to export `CodedError` via global object to use in later in the C++ code.\nglobalThis.ExpoModulesCore_CodedError = CodedError;\n","import { ensureNativeModulesAreInstalled } from './ensureNativeModulesAreInstalled';\nimport type { NativeModule } from './ts-declarations/NativeModule';\n\n/**\n * Registers a web module.\n * @param moduleImplementation A class that extends `NativeModule`. The class is registered under `globalThis.expo.modules[className]`.\n * @param moduleName A name to register the module under `globalThis.expo.modules[className]`.\n * @returns A singleton instance of the class passed into arguments.\n */\n\nexport function registerWebModule<\n EventsMap extends Record<never, never>,\n ModuleType extends typeof NativeModule<EventsMap>,\n>(moduleImplementation: ModuleType, moduleName: string): ModuleType {\n ensureNativeModulesAreInstalled();\n\n moduleName = moduleName ?? moduleImplementation.name;\n if (!moduleName) {\n throw new Error(\n 'Web module implementation is missing a name - it is either not a class or has been minified. Pass the name as a second argument to the `registerWebModule` function.'\n );\n }\n if (!globalThis?.expo?.modules) {\n globalThis.expo.modules = {};\n }\n if (globalThis.expo.modules[moduleName]) {\n return globalThis.expo.modules[moduleName];\n }\n globalThis.expo.modules[moduleName] = new moduleImplementation();\n return globalThis.expo.modules[moduleName];\n}\n","/** A union type for all integer based [`TypedArray` objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects). */\nexport type IntBasedTypedArray = Int8Array | Int16Array | Int32Array;\n\n/** A union type for all unsigned integer based [`TypedArray` objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects). */\nexport type UintBasedTypedArray = Uint8Array | Uint8ClampedArray | Uint16Array | Uint32Array;\n\n/** A union type for all floating point based [`TypedArray` objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#typedarray_objects). */\nexport type FloatBasedTypedArray = Float32Array | Float64Array;\n\n/** A [`TypedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) describes an array-like view of an underlying binary data buffer. */\nexport type TypedArray = IntBasedTypedArray | UintBasedTypedArray | FloatBasedTypedArray;\n","export enum PermissionStatus {\n /**\n * User has granted the permission.\n */\n GRANTED = 'granted',\n /**\n * User hasn't granted or denied the permission yet.\n */\n UNDETERMINED = 'undetermined',\n /**\n * User has denied the permission.\n */\n DENIED = 'denied',\n}\n\n/**\n * Permission expiration time. Currently, all permissions are granted permanently.\n */\nexport type PermissionExpiration = 'never' | number;\n\n/**\n * An object obtained by permissions get and request functions.\n */\nexport type PermissionResponse = {\n /**\n * Determines the status of the permission.\n */\n status: PermissionStatus;\n /**\n * Determines time when the permission expires.\n */\n expires: PermissionExpiration;\n /**\n * A convenience boolean that indicates if the permission is granted.\n */\n granted: boolean;\n /**\n * Indicates if user can be asked again for specific permission.\n * If not, one should be directed to the Settings app\n * in order to enable/disable the permission.\n */\n canAskAgain: boolean;\n};\n","// Copyright © 2024 650 Industries.\n\n'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport type { PermissionResponse } from './PermissionsInterface';\n\n// These types are identical, but improves the readability for suggestions in editors\ntype RequestPermissionMethod<Permission extends PermissionResponse> = () => Promise<Permission>;\ntype GetPermissionMethod<Permission extends PermissionResponse> = () => Promise<Permission>;\n\ntype PermissionHookMethods<Permission extends PermissionResponse, Options = never> = {\n /** The permission method that requests the user to grant permission. */\n requestMethod: (options?: Options) => Promise<Permission>;\n /** The permission method that only fetches the current permission status. */\n getMethod: (options?: Options) => Promise<Permission>;\n};\n\ntype PermissionHookBehavior = {\n /** If the hook should automatically fetch the current permission status, without asking the user. */\n get?: boolean;\n /** If the hook should automatically request the user to grant permission. */\n request?: boolean;\n};\n\nexport type PermissionHookOptions<Options extends object> = PermissionHookBehavior & Options;\n\n/**\n * Get or request permission for protected functionality within the app.\n * It uses separate permission requesters to interact with a single permission.\n * By default, the hook will only retrieve the permission status.\n */\nfunction usePermission<Permission extends PermissionResponse, Options extends object>(\n methods: PermissionHookMethods<Permission, Options>,\n options?: PermissionHookOptions<Options>\n): [Permission | null, RequestPermissionMethod<Permission>, GetPermissionMethod<Permission>] {\n const isMounted = useRef(true);\n const [status, setStatus] = useState<Permission | null>(null);\n const { get = true, request = false, ...permissionOptions } = options || {};\n\n const getPermission = useCallback(async () => {\n let response: Permission;\n if (Object.keys(permissionOptions).length > 0) {\n response = await methods.getMethod(permissionOptions as Options);\n } else {\n response = await methods.getMethod();\n }\n if (isMounted.current) setStatus(response);\n return response;\n }, [methods.getMethod]);\n\n const requestPermission = useCallback(async () => {\n let response: Permission;\n if (Object.keys(permissionOptions).length > 0) {\n response = await methods.requestMethod(permissionOptions as Options);\n } else {\n response = await methods.requestMethod();\n }\n if (isMounted.current) setStatus(response);\n return response;\n }, [methods.requestMethod]);\n\n useEffect(\n function runMethods() {\n if (request) requestPermission();\n if (!request && get) getPermission();\n },\n [get, request, requestPermission, getPermission]\n );\n\n // Workaround for unmounting components receiving state updates\n useEffect(function didMount() {\n isMounted.current = true;\n return () => {\n isMounted.current = false;\n };\n }, []);\n\n return [status, requestPermission, getPermission];\n}\n\n/**\n * Create a new permission hook with the permission methods built-in.\n * This can be used to quickly create specific permission hooks in every module.\n */\nexport function createPermissionHook<Permission extends PermissionResponse, Options extends object>(\n methods: PermissionHookMethods<Permission, Options>\n) {\n return (options?: PermissionHookOptions<Options>) =>\n usePermission<Permission, Options>(methods, options);\n}\n","import { createRef, type RefObject } from 'react';\n\n/**\n * Create a React ref object that is friendly for snapshots.\n * It will be represented as `[React.ref]` in snapshots.\n * @returns A React ref object.\n */\nexport function createSnapshotFriendlyRef<T>(): RefObject<T | null> {\n return createRef<T>();\n}\n","'use client';\n\nimport type { DependencyList } from 'react';\nimport { useEffect, useMemo, useRef } from 'react';\n\nimport type { SharedObject } from '../ts-declarations/SharedObject';\n\n/**\n * Returns a shared object, which is automatically cleaned up when the component is unmounted.\n */\nexport function useReleasingSharedObject<TSharedObject extends SharedObject>(\n factory: () => TSharedObject,\n dependencies: DependencyList\n): TSharedObject {\n const objectRef = useRef<TSharedObject | null>(null);\n const objectRefToRelease = useRef<TSharedObject | null>(null);\n const isFastRefresh = useRef(false);\n const previousDependencies = useRef<DependencyList>(dependencies);\n\n if (objectRef.current == null) {\n objectRef.current = factory();\n }\n\n const object = useMemo(() => {\n let newObject = objectRef.current;\n const dependenciesAreEqual =\n previousDependencies.current?.length === dependencies.length &&\n dependencies.every((value, index) => value === previousDependencies.current[index]);\n\n // If the dependencies have changed, schedule the previous object for release and create a new one,\n // otherwise this has been called because of an unrelated fast refresh, and we don't want to release the object.\n if (!newObject || !dependenciesAreEqual) {\n objectRefToRelease.current = objectRef.current;\n newObject = factory();\n objectRef.current = newObject;\n previousDependencies.current = dependencies;\n }\n return newObject;\n }, dependencies);\n\n useEffect(() => {\n // When the object changes, release the previous one - it is important to do this in a useEffect, so that we don't release\n // the object during render.\n if (objectRefToRelease.current) {\n objectRefToRelease.current.release();\n objectRefToRelease.current = null;\n }\n }, [object]);\n\n useMemo(() => {\n isFastRefresh.current = true;\n }, []);\n\n useEffect(() => {\n isFastRefresh.current = false;\n\n return () => {\n // This will be called on every fast refresh and on unmount, but we only want to release the object on unmount.\n if (!isFastRefresh.current && objectRef.current) {\n objectRef.current.release();\n }\n };\n }, []);\n\n return object;\n}\n","/**\n * Reloads the app. This method works for both release and debug builds.\n *\n * Unlike [`Updates.reloadAsync()`](/versions/latest/sdk/updates/#updatesreloadasync),\n * this function does not use a new update even if one is available. It only reloads the app using the same JavaScript bundle that is currently running.\n *\n * @param reason The reason for reloading the app. This is used only for some platforms.\n */\nexport async function reloadAppAsync(reason: string = 'Reloaded from JS call'): Promise<void> {\n await globalThis.expo?.reloadAppAsync(reason);\n}\n","import './ts-declarations/global';\nimport './sweet/setUpJsLogger.fx';\nimport './polyfill';\n\nexport type * from './ts-declarations/global';\n\nexport { EventEmitter, type EventSubscription } from './EventEmitter';\nexport { NativeModule } from './NativeModule';\nexport { SharedObject } from './SharedObject';\nexport { SharedRef } from './SharedRef';\n\nexport { default as Platform } from './Platform';\nexport { default as uuid } from './uuid';\n\nexport type { ProxyNativeModule } from './NativeModulesProxy.types';\nexport { requireNativeViewManager } from './NativeViewManagerAdapter';\n\nexport * from './requireNativeModule';\nexport * from './registerWebModule';\nexport * from './TypedArrays.types';\n\nexport * from './PermissionsInterface';\nexport * from './PermissionsHook';\n\nexport * from './Refs';\n\nexport * from './hooks/useReleasingSharedObject';\nexport * from './reload';\n\n// Errors\nexport { CodedError } from './errors/CodedError';\nexport { UnavailabilityError } from './errors/UnavailabilityError';\n\n// Deprecated\nexport { LegacyEventEmitter } from './LegacyEventEmitter';\nexport { default as NativeModulesProxy } from './NativeModulesProxy';\n\nexport { installOnUIRuntime } from './worklets';\n","import type { ExpoConfig } from 'expo/config';\nimport type {\n EASConfig as ManifestsEASConfig,\n ExpoGoConfig as ManifestsExpoGoConfig,\n ExpoUpdatesManifest,\n EmbeddedManifest,\n ManifestAsset as ManifestAssetForReExport,\n ManifestExtra as ManifestExtraForReExport,\n ClientScopingConfig as ClientScopingConfigForReExport,\n ExpoGoPackagerOpts as ExpoGoPackagerOptsForReExport,\n // @ts-ignore -- optional interface, will gracefully degrade to `any` not installed\n} from 'expo-manifests';\n\nexport enum AppOwnership {\n /**\n * The experience is running inside the Expo Go app.\n * @deprecated Use [`Constants.executionEnvironment`](#executionenvironment) instead.\n */\n Expo = 'expo',\n}\n\n/**\n * Identifies where the app's JavaScript bundle is currently running.\n */\nexport enum ExecutionEnvironment {\n /** A project that includes native project directories that you maintain directly in your\n * [existing React Native project](/bare/overview/).\n */\n Bare = 'bare',\n /** Production/release build created with or without EAS Build. */\n Standalone = 'standalone',\n /** Expo Go or a development build built with `expo-dev-client`. */\n StoreClient = 'storeClient',\n}\n\n// @needsAudit\n/**\n * Current supported values are `handset`, `tablet`, `desktop` and `tv`. CarPlay will show up\n * as `unsupported`.\n */\nexport enum UserInterfaceIdiom {\n Handset = 'handset',\n Tablet = 'tablet',\n Desktop = 'desktop',\n TV = 'tv',\n Unsupported = 'unsupported',\n}\n\n// @needsAudit\n/**\n * @platform ios\n */\nexport type IOSManifest = {\n /**\n * The build number specified in the embedded **Info.plist** value for `CFBundleVersion` in this app.\n * In a standalone app, you can set this with the `ios.buildNumber` value in **app.json**. This\n * may differ from the value in `Constants.expoConfig.ios.buildNumber` because the manifest\n * can be updated, whereas this value will never change for a given native binary.\n * The value is set to `null` in case you run your app in Expo Go.\n */\n buildNumber: string | null;\n /**\n * The Apple internal model identifier for this device.\n * @example\n * `iPhone1,1`\n * @deprecated Use `expo-device`'s [`Device.modelId`](./device/#devicemodelid).\n */\n platform: string;\n /**\n * The human-readable model name of this device. For example, `\"iPhone 7 Plus\"` if it can be determined,\n * otherwise will be `null`.\n * @deprecated Moved to `expo-device` as [`Device.modelName`](./device/#devicemodelname).\n */\n model: string | null;\n /**\n * The user interface idiom of the current device, such as whether the app is running on an iPhone, iPad, Mac or Apple TV.\n * @deprecated Use `expo-device`'s [`Device.getDeviceTypeAsync()`](./device/#devicegetdevicetypeasync).\n */\n userInterfaceIdiom: UserInterfaceIdiom;\n /**\n * The version of iOS running on this device.\n * @example\n * `10.3`\n * @deprecated Use `expo-device`'s [`Device.osVersion`](./device/#deviceosversion).\n */\n systemVersion: string;\n} & Record<string, any>;\n\n// @needsAudit\n/**\n * @platform android\n */\nexport type AndroidManifest = {\n /**\n * The version code set by `android.versionCode` in app.json.\n * The value is set to `null` in case you run your app in Expo Go.\n * @deprecated Use `expo-application`'s [`Application.nativeBuildVersion`](./application/#applicationnativebuildversion).\n */\n versionCode: number;\n} & Record<string, any>;\n\n/**\n * @platform web\n */\nexport type WebManifest = Record<string, any>;\n\n// type re-exports to prevent breaking change\n\nexport type ManifestAsset = ManifestAssetForReExport;\nexport type Manifest = ExpoUpdatesManifest;\nexport type ManifestExtra = ManifestExtraForReExport;\nexport type EASConfig = ManifestsEASConfig;\nexport type ClientScopingConfig = ClientScopingConfigForReExport;\nexport type ExpoGoConfig = ManifestsExpoGoConfig;\nexport type ExpoGoPackagerOpts = ExpoGoPackagerOptsForReExport;\n\n// @needsAudit @docsMissing\nexport type PlatformManifest = {\n ios?: IOSManifest;\n android?: AndroidManifest;\n web?: WebManifest;\n detach?: {\n scheme?: string;\n [key: string]: any;\n };\n scheme?: string;\n hostUri?: string;\n developer?: string;\n} & Record<string, any>;\n\n// @needsAudit @docsMissing\nexport type NativeConstants = {\n /**\n * @hidden\n */\n name: 'ExponentConstants';\n /**\n * Returns `expo` when running in Expo Go, otherwise `null`.\n * @deprecated Use [`Constants.executionEnvironment`](#executionenvironment) instead.\n */\n appOwnership: AppOwnership | null;\n /**\n * Returns `true` when the app is running in debug mode (`__DEV__`). Otherwise, returns `false`.\n */\n debugMode: boolean;\n /**\n * A human-readable name for the device type.\n */\n deviceName?: string;\n /**\n * The [device year class](https://github.com/facebook/device-year-class) of this device.\n * @deprecated Moved to `expo-device` as [`Device.deviceYearClass`](./device/#deviceyearclass).\n */\n deviceYearClass: number | null;\n /**\n * Returns the current execution environment.\n */\n executionEnvironment: ExecutionEnvironment;\n experienceUrl: string;\n /**\n * Nullable only on the web.\n */\n expoRuntimeVersion: string | null;\n /**\n * The version string of the Expo Go app currently running.\n * Returns `null` in existing React Native projects and on web.\n */\n expoVersion: string | null;\n isDetached?: boolean;\n intentUri?: string;\n /**\n * Returns `true` if the app is running in headless mode. Otherwise, returns `false`.\n */\n isHeadless: boolean;\n linkingUri: string;\n\n /**\n * @hidden\n * Manifest embedded in the build. Returns `null` when `manifest2` is non-null.\n * @deprecated Use `Constants.expoConfig` instead, which behaves more consistently across EAS Build\n * and EAS Update.\n */\n manifest: EmbeddedManifest | null;\n /**\n * Manifest for Expo apps using modern Expo Updates from a remote source, such as apps that\n * use EAS Update. `Constants.expoConfig` should be used for accessing the Expo config object.\n */\n manifest2: ExpoUpdatesManifest | null;\n /**\n * The standard Expo config object defined in **app.json** and **app.config.js** files. For both\n * classic and modern manifests, whether they are embedded or remote.\n */\n expoConfig:\n | (ExpoConfig & {\n /**\n * Only present during development using @expo/cli.\n */\n hostUri?: string;\n })\n | null;\n /**\n * The standard Expo Go config object populated when running in Expo Go.\n */\n expoGoConfig: ManifestsExpoGoConfig | null;\n /**\n * The standard EAS config object populated when using EAS.\n */\n easConfig: ManifestsEASConfig | null;\n /**\n * A string that is unique to the current session of your app. It is different across apps and\n * across multiple launches of the same app.\n */\n sessionId: string;\n /**\n * The default status bar height for the device. Does not factor in changes when location tracking\n * is in use or a phone call is active.\n */\n statusBarHeight: number;\n /**\n * A list of the system font names available on the current device.\n */\n systemFonts: string[];\n systemVersion?: number;\n /**\n * @hidden\n */\n supportedExpoSdks?: string[];\n /**\n * Returns the specific platform manifest object.\n *\n * > **Note**: This is distinct from the `manifest` and `manifest2`.\n */\n platform?: PlatformManifest;\n /**\n * Gets the user agent string which would be included in requests sent by a web view running on\n * this device. This is probably not the same user agent you might be providing in your JS `fetch`\n * requests.\n */\n getWebViewUserAgentAsync: () => Promise<string | null>;\n} & Record<string, any>;\n\n/**\n * @hidden\n */\nexport type Constants = NativeConstants & {\n /**\n * > **Warning**: Do not use this property. Use `manifest` by default.\n *\n * In certain cases accessing manifest via this property\n * suppresses important warning about missing manifest.\n */\n __unsafeNoWarnManifest?: EmbeddedManifest;\n /**\n * > **Warning**: Do not use this property. Use `manifest2` by default.\n *\n * In certain cases accessing manifest via this property\n * suppresses important warning about missing manifest.\n */\n __unsafeNoWarnManifest2?: ExpoUpdatesManifest;\n};\n","import { requireOptionalNativeModule } from 'expo-modules-core';\n\nexport default requireOptionalNativeModule('ExponentConstants');\n","// TODO(@kitten): Add missing optional peers\n\nimport type { ExpoConfig } from 'expo/config';\n// @ts-ignore -- optional interface, will gracefully degrade to `any` if not installed\nimport type {\n EmbeddedManifest,\n EASConfig,\n ExpoGoConfig,\n ExpoUpdatesManifest,\n // @ts-ignore -- optional interface, will gracefully degrade to `any` if not installed\n} from 'expo-manifests';\nimport { CodedError, requireOptionalNativeModule } from 'expo-modules-core';\n// @ts-ignore -- optional interface, will gracefully degrade to `any` if not installed\nimport type { Manifest as UpdatesManifest, ExpoUpdatesModule } from 'expo-updates';\nimport { Platform, NativeModules } from 'react-native';\n\nimport { type Constants, ExecutionEnvironment } from './Constants.types';\nimport ExponentConstants from './ExponentConstants';\ntype DevLauncherManifest = ExpoUpdatesManifest;\n\nexport {\n type AndroidManifest,\n AppOwnership,\n type Constants,\n ExecutionEnvironment,\n type IOSManifest,\n type NativeConstants,\n type PlatformManifest,\n UserInterfaceIdiom,\n type WebManifest,\n} from './Constants.types';\n\nif (!ExponentConstants) {\n console.warn(\n \"No native ExponentConstants module found, are you sure the expo-constants's module is linked properly?\"\n );\n}\n\nconst ExpoUpdates = requireOptionalNativeModule<ExpoUpdatesModule>('ExpoUpdates');\n\nlet rawUpdatesManifest: UpdatesManifest | null = null;\n// If expo-updates defines a non-empty manifest, prefer that one\nif (ExpoUpdates) {\n let updatesManifest: object | undefined;\n if (ExpoUpdates.manifest) {\n updatesManifest = ExpoUpdates.manifest;\n } else if (ExpoUpdates.manifestString) {\n updatesManifest = JSON.parse(ExpoUpdates.manifestString);\n }\n if (updatesManifest && Object.keys(updatesManifest).length > 0) {\n rawUpdatesManifest = updatesManifest as any;\n }\n}\n\n// If dev-launcher defines a non-empty manifest, prefer that one\nlet rawDevLauncherManifest: DevLauncherManifest | null = null;\nif (NativeModules.EXDevLauncher) {\n let devLauncherManifest;\n if (NativeModules.EXDevLauncher.manifestString) {\n devLauncherManifest = JSON.parse(NativeModules.EXDevLauncher.manifestString);\n }\n\n if (devLauncherManifest && Object.keys(devLauncherManifest).length > 0) {\n rawDevLauncherManifest = devLauncherManifest as any;\n }\n}\n\n// Fall back to ExponentConstants.manifest if we don't have one from Updates\nlet rawAppConfig: ExpoConfig | null = null;\nif (ExponentConstants && ExponentConstants.manifest) {\n const appConfig: object | string = ExponentConstants.manifest;\n\n // On Android we pass the manifest in JSON form so this step is necessary\n if (typeof appConfig === 'string') {\n rawAppConfig = JSON.parse(appConfig);\n } else {\n rawAppConfig = appConfig as any;\n }\n}\n\ntype RawManifest = UpdatesManifest | DevLauncherManifest | ExpoConfig;\nlet rawManifest: RawManifest | null = rawUpdatesManifest ?? rawDevLauncherManifest ?? rawAppConfig;\n\nconst { name, appOwnership, ...nativeConstants } = (ExponentConstants || {}) as any;\n\nconst constants: Constants = {\n ...nativeConstants,\n // Ensure this is null in bare workflow\n appOwnership: appOwnership ?? null,\n};\n\nObject.defineProperties(constants, {\n /**\n * Use `manifest` property by default.\n * This property is only used for internal purposes.\n * It behaves similarly to the original one, but suppresses warning upon no manifest available.\n * `expo-asset` uses it to prevent users from seeing mentioned warning.\n */\n __unsafeNoWarnManifest: {\n get(): EmbeddedManifest | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest || !isEmbeddedManifest(maybeManifest)) {\n return null;\n }\n return maybeManifest;\n },\n enumerable: false,\n },\n __unsafeNoWarnManifest2: {\n get(): ExpoUpdatesManifest | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest || !isExpoUpdatesManifest(maybeManifest)) {\n return null;\n }\n return maybeManifest;\n },\n enumerable: false,\n },\n manifest: {\n get(): EmbeddedManifest | null {\n const maybeManifest = getManifest();\n if (!maybeManifest || !isEmbeddedManifest(maybeManifest)) {\n return null;\n }\n return maybeManifest;\n },\n enumerable: true,\n },\n manifest2: {\n get(): ExpoUpdatesManifest | null {\n const maybeManifest = getManifest();\n if (!maybeManifest || !isExpoUpdatesManifest(maybeManifest)) {\n return null;\n }\n return maybeManifest;\n },\n enumerable: true,\n },\n expoConfig: {\n get():\n | (ExpoConfig & {\n /**\n * Only present during development using @expo/cli.\n */\n hostUri?: string;\n })\n | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest) {\n return null;\n }\n\n // if running an embedded update, maybeManifest is a EmbeddedManifest which doesn't have\n // the expo config. Instead, the embedded expo-constants app.config should be used.\n if (ExpoUpdates && ExpoUpdates.isEmbeddedLaunch) {\n return rawAppConfig;\n }\n\n if (isExpoUpdatesManifest(maybeManifest)) {\n return maybeManifest.extra?.expoClient ?? null;\n } else if (isEmbeddedManifest(maybeManifest)) {\n return maybeManifest as any;\n }\n\n return null;\n },\n enumerable: true,\n },\n expoGoConfig: {\n get(): ExpoGoConfig | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest) {\n return null;\n }\n\n if (isExpoUpdatesManifest(maybeManifest)) {\n return maybeManifest.extra?.expoGo ?? null;\n } else if (isEmbeddedManifest(maybeManifest)) {\n return maybeManifest as any;\n }\n\n return null;\n },\n enumerable: true,\n },\n easConfig: {\n get(): EASConfig | null {\n const maybeManifest = getManifest(true);\n if (!maybeManifest) {\n return null;\n }\n\n if (isExpoUpdatesManifest(maybeManifest)) {\n return maybeManifest.extra?.eas ?? null;\n } else if (isEmbeddedManifest(maybeManifest)) {\n return maybeManifest as any;\n }\n\n return null;\n },\n enumerable: true,\n },\n __rawManifest_TEST: {\n get(): RawManifest | null {\n return rawManifest;\n },\n set(value: RawManifest | null) {\n rawManifest = value;\n },\n enumerable: false,\n },\n});\n\nfunction isEmbeddedManifest(manifest: RawManifest): manifest is EmbeddedManifest {\n return !isExpoUpdatesManifest(manifest);\n}\n\nfunction isExpoUpdatesManifest(manifest: RawManifest): manifest is ExpoUpdatesManifest {\n return 'metadata' in manifest;\n}\n\nfunction getManifest(suppressWarning = false): RawManifest | null {\n if (!rawManifest) {\n const invalidManifestType = rawManifest === null ? 'null' : 'undefined';\n if (\n nativeConstants.executionEnvironment === ExecutionEnvironment.Bare &&\n Platform.OS !== 'web'\n ) {\n if (!suppressWarning) {\n console.warn(\n `Constants.manifest is ${invalidManifestType} because the embedded app.config could not be read. Ensure that you have installed the expo-constants build scripts if you need to read from Constants.manifest.`\n );\n }\n } else if (\n nativeConstants.executionEnvironment === ExecutionEnvironment.StoreClient ||\n nativeConstants.executionEnvironment === ExecutionEnvironment.Standalone\n ) {\n // If we somehow get here, this is a truly exceptional state to be in.\n // Constants.manifest should *always* be defined in those contexts.\n throw new CodedError(\n 'ERR_CONSTANTS_MANIFEST_UNAVAILABLE',\n `Constants.manifest is ${invalidManifestType}, must be an object.`\n );\n }\n }\n return rawManifest;\n}\n\nexport default constants as Constants;\n","/**\n * defaultOnboardingTheme — a neutral, light, brand-agnostic baseline. Consumers\n * pass a `Partial<OnboardingTheme>` that is deep-merged over this (see\n * `mergeTheme`), so they only override what differs from neutral.\n */\nimport type { OnboardingTheme } from \"./types\";\n\nexport const defaultOnboardingTheme: OnboardingTheme = {\n colors: {\n background: \"#FFFFFF\",\n surface: \"#F7F7F8\",\n text: \"#101114\",\n textMuted: \"#6B7280\",\n primary: \"#111111\",\n onPrimary: \"#FFFFFF\",\n primarySoft: \"rgba(17,17,17,0.06)\",\n border: \"#E4E4E7\",\n borderStrong: \"#C7C7CC\",\n disabled: \"#EBEBEB\",\n success: \"#16A34A\",\n warning: \"#D97706\",\n error: \"#DC2626\",\n info: \"#2563EB\",\n },\n fonts: {\n regular: undefined,\n medium: undefined,\n bold: undefined,\n baseSize: 16,\n scale: 1,\n },\n radius: {\n sm: 8,\n md: 12,\n lg: 16,\n full: 9999,\n },\n spacing: {\n xs: 4,\n sm: 8,\n md: 16,\n lg: 24,\n xl: 32,\n },\n // Circled (pill) CTA by default; an app can pass `button: { radius: 12 }` for\n // a rounded rectangle, or override height/paddingX to match its design system.\n button: {\n radius: 9999,\n height: 52,\n paddingX: 24,\n },\n};\n\n/**\n * Deep-merge a partial theme over the default. Two levels deep is enough — the\n * theme is intentionally shallow (colors/fonts/radius/spacing), so we merge each\n * known sub-object and leave scalars to overwrite.\n */\nexport const mergeTheme = (\n override?: Partial<OnboardingTheme>,\n): OnboardingTheme => {\n if (!override) return defaultOnboardingTheme;\n return {\n colors: { ...defaultOnboardingTheme.colors, ...override.colors },\n fonts: { ...defaultOnboardingTheme.fonts, ...override.fonts },\n radius: { ...defaultOnboardingTheme.radius, ...override.radius },\n spacing: { ...defaultOnboardingTheme.spacing, ...override.spacing },\n button: { ...defaultOnboardingTheme.button, ...override.button },\n };\n};\n","/**\n * ThemeContext — provides the resolved OnboardingTheme to every shell element and\n * themed card via `useOnboardingTheme()`. WHY a context rather than prop-drilling:\n * the cards are mounted by the SDK's ComponentRenderer (not by us), so we can't\n * pass them props directly — they must read the theme from context.\n */\nimport React, { createContext, useContext, useMemo } from \"react\";\nimport { mergeTheme } from \"./defaultTheme\";\nimport type { OnboardingTheme } from \"./types\";\n\nconst OnboardingThemeContext = createContext<OnboardingTheme | null>(null);\n\nexport type OnboardingThemeProviderProps = {\n /** Partial overrides merged over the neutral default theme. */\n theme?: Partial<OnboardingTheme>;\n children: React.ReactNode;\n};\n\nexport const OnboardingThemeProvider: React.FC<OnboardingThemeProviderProps> = ({\n theme,\n children,\n}) => {\n const resolved = useMemo(() => mergeTheme(theme), [theme]);\n return (\n <OnboardingThemeContext.Provider value={resolved}>\n {children}\n </OnboardingThemeContext.Provider>\n );\n};\n\n/**\n * Read the active theme. Falls back to the default theme when used outside a\n * provider so a stray card never crashes — it just renders neutral.\n */\nexport const useOnboardingTheme = (): OnboardingTheme => {\n const ctx = useContext(OnboardingThemeContext);\n return ctx ?? mergeTheme();\n};\n","/**\n * Illustration registry — lets the host app supply brand artwork (SVG / Lottie /\n * Image nodes) keyed by name, which the backend references from an InterstitialCard\n * by `illustration`. Keeping the registry in React context (rather than as a card\n * prop) is what keeps the kit dependency-free: the kit never imports react-native-svg\n * or Lottie — the app brings its own nodes and the kit just slots the matching one.\n *\n * <WireOnboarding illustrations={{ \"before-after\": <BeforeAfter/> }} ... />\n *\n * When the backend names an illustration the registry doesn't have, the\n * InterstitialCard falls back to its `imageUrl` (a plain RN <Image>).\n */\nimport React, { createContext, useContext, useMemo } from \"react\";\n\nexport type IllustrationRegistry = Record<string, React.ReactNode>;\n\n/** One shared empty registry so an unconfigured provider never allocates a fresh {} per render. */\nconst EMPTY_REGISTRY: IllustrationRegistry = {};\n\nconst IllustrationContext = createContext<IllustrationRegistry>(EMPTY_REGISTRY);\n\nexport type IllustrationProviderProps = {\n registry?: IllustrationRegistry;\n children: React.ReactNode;\n};\n\nexport const IllustrationProvider: React.FC<IllustrationProviderProps> = ({\n registry,\n children,\n}) => {\n const value = useMemo(() => registry ?? EMPTY_REGISTRY, [registry]);\n return <IllustrationContext.Provider value={value}>{children}</IllustrationContext.Provider>;\n};\n\n/** Look up an app-supplied illustration node by name. Returns undefined if absent. */\nexport const useIllustration = (name?: string): React.ReactNode | undefined => {\n const registry = useContext(IllustrationContext);\n if (!name) return undefined;\n return registry[name];\n};\n","/**\n * defaultIllustrations — a tiny, dependency-free fallback registry so an app can\n * render `InterstitialCard` with ZERO illustration code. These are plain\n * <View>/<Text> glyphs (NO react-native-svg, NO Lottie, NO image assets) themed\n * from the active OnboardingTheme, covering the common backend-emitted names.\n *\n * Spread it under your own artwork — your named nodes win:\n *\n * illustrations={{ ...defaultIllustrations, ...myIllustrations }}\n *\n * Names match what the onboarding backend commonly emits via an InterstitialCard's\n * `illustration`: `momentum` (forward-motion arc) and `before-after` (two states).\n * Add more by spreading your own — these are only sensible defaults.\n */\nimport React from \"react\";\nimport { StyleSheet, Text, View } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\n\n/** A soft tinted disc with a centered glyph — the shared frame for every default. */\nconst Glyph: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const t = useOnboardingTheme();\n return (\n <View\n style={[\n styles.disc,\n { backgroundColor: t.colors.primarySoft, borderRadius: t.radius.full },\n ]}\n >\n <Text style={[styles.glyphText, { color: t.colors.primary }]} allowFontScaling={false}>\n {children}\n </Text>\n </View>\n );\n};\n\n/** Forward-motion / momentum: an upward arrow. */\nconst MomentumGlyph: React.FC = () => <Glyph>{\"↗\"}</Glyph>;\n\n/** Before → after: two states with an arrow between. */\nconst BeforeAfterGlyph: React.FC = () => {\n const t = useOnboardingTheme();\n return (\n <View style={styles.row}>\n <View\n style={[\n styles.chip,\n { borderColor: t.colors.border, borderRadius: t.radius.md },\n ]}\n />\n <Text style={[styles.arrow, { color: t.colors.primary }]} allowFontScaling={false}>\n {\"→\"}\n </Text>\n <View\n style={[\n styles.chip,\n { backgroundColor: t.colors.primarySoft, borderColor: t.colors.primary, borderRadius: t.radius.md },\n ]}\n />\n </View>\n );\n};\n\n/**\n * The default registry. `WireOnboarding`'s `illustrations` prop is\n * `Record<string, ReactNode>`, so these are concrete element nodes.\n */\nexport const defaultIllustrations: Record<string, React.ReactNode> = {\n momentum: <MomentumGlyph />,\n \"before-after\": <BeforeAfterGlyph />,\n};\n\nconst styles = StyleSheet.create({\n disc: {\n width: 96,\n height: 96,\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n glyphText: {\n fontSize: 44,\n fontWeight: \"700\",\n lineHeight: 52,\n },\n row: {\n flexDirection: \"row\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 12,\n },\n chip: {\n width: 56,\n height: 56,\n borderWidth: 2,\n },\n arrow: {\n fontSize: 28,\n fontWeight: \"700\",\n },\n});\n","/**\n * Icon registry — the host's escape hatch, and the FIRST step of icon resolution.\n *\n * Deliberately the same shape and philosophy as the `illustrations` registry\n * (components/Illustration.tsx): name → ReactNode, held in context, so an app can ship brand\n * SVG / Lottie / Image nodes the kit never imports. Here it means a host can:\n *\n * • override any vocabulary name with its own brand mark (`{ instagram: <MyIgGlyph/> }`), or\n * • supply icons WITHOUT installing `@expo/vector-icons` at all, or\n * • extend the vocabulary with names of its own — the AI emits `\"my-thing\"`, the host renders\n * it, and the kit needs no release.\n *\n * <WireOnboarding icons={{ instagram: <BrandIg/> }} ... />\n *\n * A name the registry doesn't have falls through to `@expo/vector-icons`, then to no icon at\n * all. See `WireIcon`.\n */\nimport React, { createContext, useContext, useMemo } from \"react\";\n\nexport type WireIconRegistry = Record<string, React.ReactNode>;\n\n/** One shared empty registry so an unconfigured provider never allocates a fresh {} per render. */\nconst EMPTY_REGISTRY: WireIconRegistry = {};\n\nconst IconContext = createContext<WireIconRegistry>(EMPTY_REGISTRY);\n\nexport type IconRegistryProviderProps = {\n registry?: WireIconRegistry;\n children: React.ReactNode;\n};\n\nexport const IconRegistryProvider: React.FC<IconRegistryProviderProps> = ({\n registry,\n children,\n}) => {\n const value = useMemo(() => registry ?? EMPTY_REGISTRY, [registry]);\n return <IconContext.Provider value={value}>{children}</IconContext.Provider>;\n};\n\n/**\n * Look up a host-supplied icon node by name. Returns undefined if absent.\n *\n * The OWN-property check matters here for the same reason it does in `vocabulary.ts`: the name\n * is LLM-authored, and a bare `registry[name]` answers `\"toString\"` with an inherited function\n * — which is truthy, so it would be handed to React as a child and blow up the card. An icon\n * name must never be able to do that.\n */\nexport const useHostIcon = (name?: string): React.ReactNode | undefined => {\n const registry = useContext(IconContext);\n if (!name) return undefined;\n if (!Object.prototype.hasOwnProperty.call(registry, name)) return undefined;\n return registry[name];\n};\n","/**\n * typography — derive concrete RN text styles from the theme's font config, so\n * every label/title/caption in the kit scales from one `baseSize` + `scale` and\n * picks the right family. Cards call these instead of hardcoding fontSize/weight.\n */\nimport type { TextStyle } from \"react-native\";\nimport type { OnboardingFonts } from \"./types\";\n\nconst round = (n: number) => Math.round(n);\n\n/** Body text — the reference size. */\nexport const bodyStyle = (f: OnboardingFonts): TextStyle => ({\n fontFamily: f.regular,\n fontSize: round(f.baseSize * f.scale),\n lineHeight: round(f.baseSize * f.scale * 1.5),\n});\n\n/** Slightly smaller secondary/hint text. */\nexport const captionStyle = (f: OnboardingFonts): TextStyle => ({\n fontFamily: f.regular,\n fontSize: round(f.baseSize * 0.8125 * f.scale),\n lineHeight: round(f.baseSize * 0.8125 * f.scale * 1.5),\n});\n\n/** Emphasised label (e.g. a card question). */\nexport const labelStyle = (f: OnboardingFonts): TextStyle => ({\n fontFamily: f.medium ?? f.bold,\n fontSize: round(f.baseSize * f.scale),\n lineHeight: round(f.baseSize * f.scale * 1.4),\n fontWeight: f.medium ? undefined : (\"600\" as const),\n});\n\n/** Heading (status title, done block). */\nexport const headingStyle = (f: OnboardingFonts): TextStyle => ({\n fontFamily: f.bold,\n fontSize: round(f.baseSize * 1.25 * f.scale),\n lineHeight: round(f.baseSize * 1.25 * f.scale * 1.3),\n fontWeight: f.bold ? undefined : (\"700\" as const),\n});\n\n/** Button label. */\nexport const buttonLabelStyle = (f: OnboardingFonts): TextStyle => ({\n fontFamily: f.bold ?? f.medium,\n fontSize: round(f.baseSize * f.scale),\n fontWeight: f.bold ? undefined : (\"600\" as const),\n});\n","/**\n * motionSpec — the single source of truth for every animation value in the kit,\n * extracted 1:1 from the Wire Activation card-interactions design canvas\n * (see design-refs/EXTRACTED-SPEC.md for the row-by-row mapping).\n *\n * Pure constants + pure helpers only — NO react-native import — so the spec is\n * unit-testable under node:test and components can't drift from the design\n * without a red test.\n */\n\n/** The design system's \"ease-wire\" curve: cubic-bezier(0.16, 1, 0.3, 1). */\nexport const WIRE_BEZIER = [0.16, 1, 0.3, 1] as const;\n\n/** Design-system duration tokens (colors_and_type.css --duration-*). */\nexport const DURATION_FAST_MS = 150;\nexport const DURATION_BASE_MS = 300;\nexport const DURATION_SLOW_MS = 500;\n\n/** Reduce-motion fallback: a short fade to the final frame, never a frozen mid-state. */\nexport const REDUCED_FADE_MS = 120;\n\n// ── Press feedback (spec rows 1, 4, 20) ─────────────────────────────────────\nexport const ROW_PRESS_SCALE = 0.975;\nexport const CHIP_PRESS_SCALE = 0.94;\nexport const BUTTON_PRESS_SCALE = 0.975;\n/** Reduce-motion press feedback: opacity dip instead of scale. */\nexport const REDUCED_PRESS_OPACITY = 0.85;\nexport const PRESS_SPRING = { friction: 8, tension: 220 } as const;\nexport const BUTTON_PRESS_SPRING = { friction: 8, tension: 240 } as const;\n\n// ── Selection state changes (spec rows 2, 3, 5, 6) ──────────────────────────\nexport const SELECT_FILL_MS = 180;\nexport const CHIP_FILL_MS = 160;\nexport const CHECK_SPRING = { friction: 6, tension: 180 } as const;\nexport const CHECK_SCALE_FROM = 0.6;\n\n// ── Card-to-card handoff (spec rows 7-10) ───────────────────────────────────\nexport const CARD_ENTER_MS = 220;\nexport const CARD_EXIT_MS = 180;\n/** The exit starts this long BEFORE the enter (enter is delayed by this). */\nexport const CARD_EXIT_LEAD_MS = 80;\nexport const CARD_SLIDE_PX = 26;\nexport const CARD_ENTER_SCALE_FROM = 0.96;\n/** The interstitial keeps the shell's springier value-beat (AnimatedCard idiom). */\nexport const CARD_SPRING = { damping: 14, stiffness: 180, mass: 1 } as const;\n/** Loader-to-card handoff: the loader just fades out. */\nexport const LOADER_HANDOFF_FADE_MS = 120;\n\n// ── InterstitialCard reveal (spec rows 11-13) ───────────────────────────────\nexport const INTERSTITIAL_HEAD_MS = 500;\nexport const INTERSTITIAL_HEAD_STAGGER_MS = 100;\nexport const INTERSTITIAL_ITEM_MS = 300;\nexport const INTERSTITIAL_ITEM_STAGGER_MS = 90;\nexport const INTERSTITIAL_ITEM_BASE_DELAY_MS = 200;\nexport const INTERSTITIAL_CHECK_DELAY_MS = 200;\nexport const INTERSTITIAL_CHECK_SCALE_FROM = 0.4;\n\n/** Delay before work item `index` begins its reveal (row lands after the head). */\nexport const interstitialItemDelay = (index: number): number =>\n INTERSTITIAL_ITEM_BASE_DELAY_MS + index * INTERSTITIAL_ITEM_STAGGER_MS;\n\n/** Delay before work item `index`'s check pops (200ms after its row starts). */\nexport const interstitialCheckDelay = (index: number): number =>\n interstitialItemDelay(index) + INTERSTITIAL_CHECK_DELAY_MS;\n\n// ── Status / completion payoff (spec rows 14-16) ────────────────────────────\nexport const STATUS_POP_SPRING = { friction: 6, tension: 200 } as const;\nexport const STATUS_POP_SCALE_FROM = 0.4;\nexport const STATUS_BURST_MS = 500;\nexport const STATUS_BURST_SCALE_FROM = 0.4;\nexport const STATUS_BURST_SCALE_TO = 1.5;\nexport const STATUS_BURST_OPACITY_FROM = 0.5;\nexport const STATUS_COPY_MS = 300;\nexport const STATUS_COPY_STAGGER_MS = 80;\n/** Copy starts settling once the badge pop is visibly underway. */\nexport const STATUS_COPY_BASE_DELAY_MS = 200;\n\n/** Delay before payoff copy line `index` fades up. */\nexport const statusCopyDelay = (index: number): number =>\n STATUS_COPY_BASE_DELAY_MS + index * STATUS_COPY_STAGGER_MS;\n\n// ── Loading treatment (spec rows 17-19) ─────────────────────────────────────\nexport const LOADER_PULSE_MS = 1600;\nexport const LOADER_PULSE_MIN_OPACITY = 0.35;\nexport const LOADER_ORBIT_MS = 2400;\n/** Skeleton lines appear only when the fetch runs past this. */\nexport const SKELETON_DELAY_MS = 300;\nexport const SKELETON_PULSE_MS = 1500;\nexport const SKELETON_MIN_OPACITY = 0.45;\n\n// ── Progress bar (spec row 21) ──────────────────────────────────────────────\nexport const PROGRESS_MS = 400;\n\n// ── Dev/QA duration scale (slow-mo for judging motion) ──────────────────────\n// A module-level multiplier applied to every timing DURATION (and stagger\n// delay) at animation start. 1 = design speed; 2 = half-speed slow-mo. Springs\n// are physics-based (friction/tension) and do NOT scale. This is a dev/QA tool\n// (the playground's tweak panel drives it) — production code never calls the\n// setter, so the default 1 keeps shipped motion exactly on spec.\n\nlet durationScale = 1;\n\n/** Set the global duration multiplier (clamped to 0.1-10; invalid resets to 1). */\nexport const setMotionDurationScale = (scale: number): void => {\n durationScale = Number.isFinite(scale) && scale > 0 ? Math.min(10, Math.max(0.1, scale)) : 1;\n};\n\nexport const getMotionDurationScale = (): number => durationScale;\n\n/** Apply the current duration scale to a spec duration/delay (rounded ms). */\nexport const scaledMs = (ms: number): number => Math.round(ms * durationScale);\n\n// ── Reduce-motion helpers (pure, shared by every animated component) ────────\n\nexport type EntranceSpec = {\n /** Duration to animate with (falls back to the short fade under reduce motion). */\n duration: number;\n /** Whether transforms (translate/scale) may move; false = opacity-only fade. */\n useTransform: boolean;\n};\n\n/** Entrances: full motion normally; a 120ms opacity-only fade under reduce motion. */\nexport const entranceSpec = (reduced: boolean, durationMs: number): EntranceSpec =>\n reduced\n ? { duration: REDUCED_FADE_MS, useTransform: false }\n : { duration: durationMs, useTransform: true };\n\n/** State changes (select fills etc.): snap instantly under reduce motion. */\nexport const stateChangeDuration = (reduced: boolean, durationMs: number): number =>\n reduced ? 0 : durationMs;\n\n/** Looping/ambient animations run only when motion is allowed. */\nexport const loopEnabled = (reduced: boolean): boolean => !reduced;\n","/**\n * useReducedMotion — the kit's ONE reduce-motion gate. Reads the OS setting via\n * AccessibilityInfo and stays subscribed to `reduceMotionChanged`, so every\n * animated component lands on its final frame (or a ~120ms fade) the moment the\n * user flips the setting — no restart needed.\n *\n * This closes the gap documented in ai_rules/rules/performance.md §3: every\n * animation in the kit must consume this hook (usually through the pure helpers\n * in motionSpec.ts: `entranceSpec` / `stateChangeDuration` / `loopEnabled`).\n */\nimport { useEffect, useState } from \"react\";\nimport { AccessibilityInfo } from \"react-native\";\n\n// Last-known value, module-level: cards remount every turn (keyed on message id),\n// and a `useState(false)` default would flash one animated frame per turn for a\n// reduce-motion user before the async read resolves.\nlet lastKnown = false;\n\nexport const useReducedMotion = (): boolean => {\n const [reduced, setReduced] = useState(lastKnown);\n\n useEffect(() => {\n let mounted = true;\n AccessibilityInfo.isReduceMotionEnabled()\n .then((value) => {\n lastKnown = value;\n if (mounted) setReduced(value);\n })\n .catch(() => {\n // Unavailable (e.g. some test envs): keep the last-known value.\n });\n const sub = AccessibilityInfo.addEventListener(\"reduceMotionChanged\", (value) => {\n lastKnown = value;\n setReduced(value);\n });\n return () => {\n mounted = false;\n sub?.remove();\n };\n }, []);\n\n return reduced;\n};\n","/**\n * AnimatedSparkle — the themed \"AI is thinking\" glyph (✦), animated with RN's\n * built-in `Animated` (native driver) so the kit needs neither reanimated nor a\n * vector-icon dependency.\n *\n * Variants:\n * - \"spin\" (default, unchanged): continuous rotation — the original loader.\n * - \"pulse\": the Wire Activation loading treatment — the mark breathes\n * (opacity 0.35 ↔ 1, 1600ms loop) instead of rotating.\n *\n * Reduce motion: no loop at all — the glyph renders static at full opacity\n * (final frame), per design-refs/EXTRACTED-SPEC.md row 17.\n */\nimport React, { useEffect, useRef } from \"react\";\nimport { Animated, Easing, StyleSheet, Text } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { LOADER_PULSE_MIN_OPACITY, LOADER_PULSE_MS, loopEnabled, scaledMs } from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst ROTATION_MS = 1800;\n\nexport type AnimatedSparkleProps = {\n /** Glyph size in px. */\n size?: number;\n /** Override color; defaults to the theme primary. */\n color?: string;\n /** \"spin\" rotates (default, the original), \"pulse\" breathes (the loader treatment). */\n variant?: \"spin\" | \"pulse\";\n};\n\nconst _AnimatedSparkle: React.FC<AnimatedSparkleProps> = ({ size = 30, color, variant = \"spin\" }) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const progress = useRef(new Animated.Value(0)).current;\n\n useEffect(() => {\n if (!loopEnabled(reduced)) {\n // Static final frame: no rotation, full opacity.\n progress.setValue(0);\n return;\n }\n const loop =\n variant === \"pulse\"\n ? Animated.loop(\n Animated.sequence([\n Animated.timing(progress, {\n toValue: 1,\n duration: scaledMs(LOADER_PULSE_MS / 2),\n easing: Easing.inOut(Easing.ease),\n useNativeDriver: true,\n }),\n Animated.timing(progress, {\n toValue: 0,\n duration: scaledMs(LOADER_PULSE_MS / 2),\n easing: Easing.inOut(Easing.ease),\n useNativeDriver: true,\n }),\n ]),\n )\n : Animated.loop(\n Animated.timing(progress, {\n toValue: 1,\n duration: scaledMs(ROTATION_MS),\n easing: Easing.linear,\n useNativeDriver: true,\n }),\n );\n loop.start();\n return () => loop.stop();\n }, [progress, variant, reduced]);\n\n const rotate = progress.interpolate({ inputRange: [0, 1], outputRange: [\"0deg\", \"360deg\"] });\n const pulse = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [1, LOADER_PULSE_MIN_OPACITY],\n });\n\n const animatedStyle = reduced\n ? undefined\n : variant === \"pulse\"\n ? { opacity: pulse }\n : { transform: [{ rotate }] };\n\n // The glyph lives in a fixed size×size box (alignItems/justifyContent:center) so the\n // font's side-bearing and Android includeFontPadding can't shove the visible mark off\n // center. The box carries the transform too, so a spinning box still rotates around its\n // own center → the ✦ spins in place, optically centered on both axes.\n return (\n <Animated.View style={[styles.box, { width: size, height: size }, animatedStyle]}>\n <Text\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n style={[\n styles.glyph,\n {\n width: size,\n fontSize: size,\n lineHeight: size,\n color: color ?? t.colors.primary,\n },\n ]}\n >\n ✦\n </Text>\n </Animated.View>\n );\n};\n\nexport const AnimatedSparkle = React.memo(_AnimatedSparkle);\n\nconst styles = StyleSheet.create({\n box: { alignItems: \"center\", justifyContent: \"center\" },\n glyph: {\n textAlign: \"center\",\n textAlignVertical: \"center\",\n includeFontPadding: false,\n },\n});\n","/**\n * LoadingBlock — the \"AI is thinking\" indicator, shown before the first card and\n * between every turn (each round-trip to the backend). The Wire Activation\n * loading treatment: no generic spinner — the brand mark breathes inside a\n * dashed ring while an accent dot orbits it, and skeleton lines appear (softly\n * pulsing) only when the fetch runs past 300ms so a fast turn never flashes\n * placeholder chrome (design-refs/EXTRACTED-SPEC.md rows 17-19).\n *\n * Reduce motion: static mark + copy, no orbit, no pulse.\n */\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, StyleSheet, Text, View } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { bodyStyle, headingStyle } from \"../theme/typography\";\nimport { AnimatedSparkle } from \"./AnimatedSparkle\";\nimport {\n LOADER_ORBIT_MS,\n SKELETON_DELAY_MS,\n SKELETON_MIN_OPACITY,\n SKELETON_PULSE_MS,\n loopEnabled,\n scaledMs,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst STAGE_SIZE = 96;\nconst ORBIT_DOT = 9;\n\nexport type LoadingBlockProps = {\n /** Primary line, e.g. \"Thinking…\". */\n title?: string;\n /** Supporting line under the title. */\n hint?: string;\n};\n\n/** The orbiting accent dot: a full-stage rotating layer with the dot at 12 o'clock. */\nconst OrbitDot: React.FC<{ color: string; reduced: boolean }> = ({ color, reduced }) => {\n const spin = useRef(new Animated.Value(0)).current;\n useEffect(() => {\n if (!loopEnabled(reduced)) return;\n const loop = Animated.loop(\n Animated.timing(spin, {\n toValue: 1,\n duration: scaledMs(LOADER_ORBIT_MS),\n easing: Easing.linear,\n useNativeDriver: true,\n }),\n );\n loop.start();\n return () => loop.stop();\n }, [spin, reduced]);\n\n if (reduced) return null;\n const rotate = spin.interpolate({ inputRange: [0, 1], outputRange: [\"0deg\", \"360deg\"] });\n return (\n <Animated.View pointerEvents=\"none\" style={[StyleSheet.absoluteFill, { transform: [{ rotate }] }]}>\n <View style={[styles.orbitDot, { backgroundColor: color }]} />\n </Animated.View>\n );\n};\n\n/** A skeleton line that softly pulses (static under reduce motion). */\nconst SkeletonLine: React.FC<{ width: `${number}%`; delay: number; color: string; reduced: boolean }> = ({\n width,\n delay,\n color,\n reduced,\n}) => {\n const pulse = useRef(new Animated.Value(1)).current;\n useEffect(() => {\n if (!loopEnabled(reduced)) return;\n const loop = Animated.loop(\n Animated.sequence([\n Animated.delay(delay),\n Animated.timing(pulse, {\n toValue: SKELETON_MIN_OPACITY,\n duration: scaledMs(SKELETON_PULSE_MS / 2),\n easing: Easing.inOut(Easing.ease),\n useNativeDriver: true,\n }),\n Animated.timing(pulse, {\n toValue: 1,\n duration: scaledMs(SKELETON_PULSE_MS / 2),\n easing: Easing.inOut(Easing.ease),\n useNativeDriver: true,\n }),\n ]),\n );\n loop.start();\n return () => loop.stop();\n }, [pulse, delay, reduced]);\n\n return (\n <Animated.View\n style={[styles.skeletonLine, { width, backgroundColor: color, opacity: reduced ? 1 : pulse }]}\n />\n );\n};\n\nconst _LoadingBlock: React.FC<LoadingBlockProps> = ({\n title = \"Thinking…\",\n hint = \"Personalizing your experience\",\n}) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n // The loader fills its parent (flex:1) and centers in it. In the flow that parent is the\n // scaffold BODY (the same content region the cards render into), so the loader lands at the\n // content-area center — visually consistent with the cards it hands off to. Standalone\n // (LoadingScreen / a playground CardFrame) it centers in whatever bounds it. No screen-inset\n // math and no transform: it inherits the content area it is dropped into, so it is centered\n // in every context by construction.\n\n // Skeleton lines are gated behind the 300ms window: a fast fetch never shows them.\n const [showSkeleton, setShowSkeleton] = useState(false);\n useEffect(() => {\n const timer = setTimeout(() => setShowSkeleton(true), SKELETON_DELAY_MS);\n return () => clearTimeout(timer);\n }, []);\n\n return (\n <View style={[styles.center, { padding: t.spacing.lg }]}>\n {/*\n * The stage is the ANCHOR: it's the only in-flow child, so `justifyContent:\n * center` lands the icon at the true center of the flow area. Title, hint and\n * the (300ms-gated) skeleton hang BELOW it in an absolutely-positioned column,\n * so they never displace the icon — previously they lived in the same centered\n * column, which re-balanced (and jumped the icon UP ~½ its height) the moment\n * the skeleton lines mounted at 300ms.\n */}\n <View style={styles.stage}>\n <View style={[styles.ring, { borderColor: t.colors.border, borderRadius: t.radius.full }]} />\n <OrbitDot color={t.colors.primary} reduced={reduced} />\n <AnimatedSparkle size={40} variant=\"pulse\" />\n </View>\n <View\n style={[\n styles.labels,\n { marginTop: STAGE_SIZE / 2 + t.spacing.lg, gap: t.spacing.md, paddingHorizontal: t.spacing.lg },\n ]}\n pointerEvents=\"none\"\n >\n {title ? (\n <Text style={[headingStyle(t.fonts), { color: t.colors.text, textAlign: \"center\" }]}>\n {title}\n </Text>\n ) : null}\n {hint ? (\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: \"center\" }]}>\n {hint}\n </Text>\n ) : null}\n {showSkeleton ? (\n <View style={[styles.skeleton, { gap: t.spacing.sm, marginTop: t.spacing.sm }]}>\n <SkeletonLine width=\"80%\" delay={0} color={t.colors.surface} reduced={reduced} />\n <SkeletonLine width=\"60%\" delay={200} color={t.colors.surface} reduced={reduced} />\n </View>\n ) : null}\n </View>\n </View>\n );\n};\n\nexport const LoadingBlock = React.memo(_LoadingBlock);\n\nconst styles = StyleSheet.create({\n center: { flex: 1, alignItems: \"center\", justifyContent: \"center\" },\n // Absolutely-positioned label column, pinned just under the centered stage: its top\n // edge starts at the flow center (top: 50%) and the inline marginTop (STAGE_SIZE/2 +\n // a gap) drops it below the stage. Out of flow → it never moves the stage, so the\n // 300ms skeleton reveal grows DOWNWARD only and the icon stays centered.\n labels: { position: \"absolute\", top: \"50%\", left: 0, right: 0, alignItems: \"center\" },\n stage: {\n width: STAGE_SIZE,\n height: STAGE_SIZE,\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n ring: {\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n borderWidth: 1.5,\n borderStyle: \"dashed\",\n },\n orbitDot: {\n position: \"absolute\",\n top: -ORBIT_DOT / 2 + 1,\n left: STAGE_SIZE / 2 - ORBIT_DOT / 2,\n width: ORBIT_DOT,\n height: ORBIT_DOT,\n borderRadius: ORBIT_DOT / 2,\n },\n skeleton: { width: \"100%\", alignItems: \"center\" },\n skeletonLine: { height: 12, borderRadius: 6 },\n});\n","/**\n * LoadingScreen — the STANDALONE loader surface: a full-area safe frame that centers a\n * LoadingBlock dead in the middle of the screen. Used for the loader slots that render on\n * their own (no OnboardingScaffold around them): the cold-start \"getting started\" wait, the\n * resumed-session \"restoring\" wait, and the transient error/timeout retry beat.\n *\n * WHY a dedicated frame: those slots used to return a bare <LoadingBlock/>, whose flex:1 only\n * fills whatever the host happened to give it — with no safe area and, if the host didn't\n * bound it, no height at all (top-anchored). This wraps them in the same SafeAreaView the flow\n * uses, so the standalone loaders center exactly like the between-turns loader (both fill their\n * parent flex:1 region and center in it — here the SafeAreaView, in the flow the scaffold body).\n * One consistent centered look.\n */\nimport React from \"react\";\nimport { StyleSheet } from \"react-native\";\nimport { SafeAreaView } from \"react-native-safe-area-context\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { LoadingBlock, type LoadingBlockProps } from \"./LoadingBlock\";\n\nconst _LoadingScreen: React.FC<LoadingBlockProps> = ({ title, hint }) => {\n const t = useOnboardingTheme();\n return (\n <SafeAreaView\n edges={[\"top\", \"bottom\"]}\n style={[styles.flex, { backgroundColor: t.colors.background }]}\n >\n <LoadingBlock title={title} hint={hint} />\n </SafeAreaView>\n );\n};\n\nexport const LoadingScreen = React.memo(_LoadingScreen);\n\nconst styles = StyleSheet.create({\n flex: { flex: 1 },\n});\n","/**\n * StepProgress — a single themed progress bar that conveys forward motion. It never\n * shows a \"Step X of N\" number (the count would read as a promise the model may not\n * keep), but it can be *paced* two ways:\n *\n * - Default (no `approxScreens`): an asymptotic curve of the step index — always\n * advances, never reaches the end until the flow actually completes.\n * - With `approxScreens`: when the host knows roughly how many screens the flow\n * runs (e.g. the backend's screen budget), the fill tracks `step / approxScreens`\n * (capped below 100% until `complete`). More truthful pacing, still no number.\n */\nimport React, { useEffect, useRef } from \"react\";\nimport { Animated, Easing, StyleSheet, View } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { PROGRESS_MS, WIRE_BEZIER, scaledMs, stateChangeDuration } from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\n\nexport type StepProgressProps = {\n /** 1-based index of the current step. Drives the fill. */\n step: number;\n /** When true, fill to 100% (flow finished). */\n complete?: boolean;\n /**\n * Approximate total number of screens, if known (e.g. the backend screen budget).\n * Paces the bar as `step / approxScreens` instead of the asymptotic curve. Never\n * shown as a number — it only shapes the fill. Omit for the asymptotic default.\n */\n approxScreens?: number;\n};\n\n// Asymptotic default: each step closes ~38% of the remaining gap, so the bar always\n// moves but never hits the end on its own: step1≈38%, step2≈62%, step3≈76%…\nconst DECAY = 0.62;\nconst MIN_FILL = 0.08;\n// When pacing by an approximate total, never look finished until `complete`.\nconst APPROX_CAP = 0.95;\n\nconst targetFor = (step: number, complete?: boolean, approxScreens?: number): number => {\n if (complete) return 1;\n const s = Number.isFinite(step) && step > 0 ? Math.floor(step) : 1;\n if (approxScreens && approxScreens > 0) {\n return Math.max(MIN_FILL, Math.min(APPROX_CAP, s / approxScreens));\n }\n return Math.max(MIN_FILL, 1 - DECAY ** s);\n};\n\nconst _StepProgress: React.FC<StepProgressProps> = ({ step, complete, approxScreens }) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const fill = useRef(new Animated.Value(targetFor(step, complete, approxScreens))).current;\n\n // 400ms ease-wire per the design spec (design-refs/EXTRACTED-SPEC.md row 21).\n // A growing total re-targets the same value, so the fill eases forward and never\n // snaps back. Reduce motion: jump straight to the ratio.\n useEffect(() => {\n Animated.timing(fill, {\n toValue: targetFor(step, complete, approxScreens),\n duration: scaledMs(stateChangeDuration(reduced, PROGRESS_MS)),\n easing: easeWire,\n useNativeDriver: false, // animating width %\n }).start();\n }, [fill, step, complete, approxScreens, reduced]);\n\n const width = fill.interpolate({ inputRange: [0, 1], outputRange: [\"0%\", \"100%\"] });\n\n return (\n <View style={[styles.track, { backgroundColor: t.colors.border, borderRadius: t.radius.full }]}>\n <Animated.View\n style={[\n styles.fill,\n { width, backgroundColor: t.colors.primary, borderRadius: t.radius.full },\n ]}\n />\n </View>\n );\n};\n\nexport const StepProgress = React.memo(_StepProgress);\n\nconst styles = StyleSheet.create({\n track: { height: 6, width: \"100%\", overflow: \"hidden\" },\n fill: { height: 6 },\n});\n","/**\n * OnboardingScaffold — the themed shell that wraps every step:\n * [ safe area ]\n * header -> StepProgress (a numberless fill — never \"Step X of N\") + optional Skip\n * body -> the rendered card (children), full-screen (flex: 1)\n * footer -> optional Back link\n *\n * WHY a single scaffold: the body content changes every turn (it's an\n * SDK-rendered card), but the chrome — progress, skip, back, padding, safe area —\n * stays constant. Keeping it here means cards never re-implement the frame.\n *\n * The body no longer centers/scrolls the card: each card fills the body via the\n * shared CardLayout, which owns its own scroll + bottom-pinned CTA (Cal-AI style).\n * The safe area uses `react-native-safe-area-context` (top + bottom edges) — the\n * RN core SafeAreaView is deprecated and iOS-only, so the kit takes the standard\n * Expo/RN peer instead of shipping cropped layouts on Android + notched devices.\n */\nimport React, { useMemo } from \"react\";\nimport { StyleSheet, Text, TouchableOpacity, View } from \"react-native\";\nimport { SafeAreaView } from \"react-native-safe-area-context\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport type { OnboardingTheme } from \"../theme/types\";\nimport { bodyStyle } from \"../theme/typography\";\nimport { StepProgress } from \"./StepProgress\";\n\nexport type OnboardingScaffoldProps = {\n /** 1-based index of the current step; drives the (countless) progress bar. */\n step: number;\n /** When true, the progress bar fills to 100% (flow finished). */\n complete?: boolean;\n /** Approximate total screens, if known — paces the bar (never shown). */\n approxScreens?: number;\n /** Optional Back action — hidden when omitted (e.g. on the first step). */\n onBack?: () => void;\n /** Optional Skip action — hidden when omitted. */\n onSkip?: () => void;\n skipLabel?: string;\n backLabel?: string;\n children: React.ReactNode;\n};\n\nconst _OnboardingScaffold: React.FC<OnboardingScaffoldProps> = ({\n step,\n complete,\n approxScreens,\n onBack,\n onSkip,\n skipLabel = \"Skip\",\n backLabel = \"Back\",\n children,\n}) => {\n const t = useOnboardingTheme();\n const styles = useMemo(() => makeStyles(t), [t]);\n const hit = { top: 12, bottom: 12, left: 12, right: 12 };\n\n return (\n <SafeAreaView\n edges={[\"top\", \"bottom\"]}\n style={[styles.flex, { backgroundColor: t.colors.background }]}\n >\n <View style={[styles.header, { paddingHorizontal: t.spacing.md, paddingTop: t.spacing.md }]}>\n <View style={styles.progressWrap}>\n <StepProgress step={step} complete={complete} approxScreens={approxScreens} />\n </View>\n {onSkip ? (\n <TouchableOpacity onPress={onSkip} hitSlop={hit} style={styles.skip}>\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted }]}>{skipLabel}</Text>\n </TouchableOpacity>\n ) : null}\n </View>\n\n {/* Full-screen body (flex:1): the card (via CardLayout) fills this and pins its own CTA,\n and the between-turns LoadingBlock fills+centers in this SAME region — so the loader\n lands at the content-area center, consistent with the cards, not the full-screen center. */}\n <View\n style={[styles.body, { paddingHorizontal: t.spacing.md, paddingTop: t.spacing.md }]}\n >\n {children}\n </View>\n\n {onBack ? (\n <View style={[styles.footer, { paddingHorizontal: t.spacing.md, paddingBottom: t.spacing.sm }]}>\n <TouchableOpacity onPress={onBack} hitSlop={hit}>\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted }]}>{backLabel}</Text>\n </TouchableOpacity>\n </View>\n ) : null}\n </SafeAreaView>\n );\n};\n\nexport const OnboardingScaffold = React.memo(_OnboardingScaffold);\n\nfunction makeStyles(t: OnboardingTheme) {\n return StyleSheet.create({\n flex: { flex: 1 },\n header: { flexDirection: \"row\", alignItems: \"center\" },\n progressWrap: { flex: 1 },\n body: { flex: 1 },\n footer: { flexDirection: \"row\", justifyContent: \"flex-start\" },\n skip: { marginLeft: t.spacing.md },\n });\n}\n","/**\n * Button — the kit's themed primary/outline button, replacing the SDK's hardcoded\n * `Btn`. Every color/radius/font comes from the active theme.\n *\n * Motion (design-refs/EXTRACTED-SPEC.md row 20): \"a footer button that answers\n * the tap\" — scale 1→0.975 spring on press-in, back on release, native driver.\n * Reduce motion: an opacity dip to 0.85 while pressed, no scale. Disabled keeps\n * the `disabled` token fill with no press handler (unchanged).\n */\nimport React, { useCallback, useRef } from \"react\";\nimport { Animated, Pressable, StyleSheet, Text } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { buttonLabelStyle } from \"../theme/typography\";\nimport {\n BUTTON_PRESS_SCALE,\n BUTTON_PRESS_SPRING,\n REDUCED_FADE_MS,\n REDUCED_PRESS_OPACITY,\n scaledMs,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\ntype Variant = \"primary\" | \"outline\";\n\ntype ButtonProps = {\n title: string;\n onPress?: () => void;\n variant?: Variant;\n disabled?: boolean;\n /** Stretch to the container width — for form-style CTAs (e.g. the review form's\n * \"Send feedback\"). Default false keeps the content-width pill used by cards. */\n fullWidth?: boolean;\n};\n\nconst _Button: React.FC<ButtonProps> = ({\n title,\n onPress,\n variant = \"primary\",\n disabled = false,\n fullWidth = false,\n}) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const isPrimary = variant === \"primary\";\n\n // 0 = at rest, 1 = pressed. Scale normally; opacity dip under reduce motion.\n const pressT = useRef(new Animated.Value(0)).current;\n const pressTo = useCallback(\n (to: number) => {\n if (reduced) {\n Animated.timing(pressT, {\n toValue: to,\n duration: scaledMs(REDUCED_FADE_MS),\n useNativeDriver: true,\n }).start();\n return;\n }\n Animated.spring(pressT, {\n toValue: to,\n friction: BUTTON_PRESS_SPRING.friction,\n tension: BUTTON_PRESS_SPRING.tension,\n useNativeDriver: true,\n }).start();\n },\n [pressT, reduced],\n );\n const lastPress = useRef<number>(0);\n const handlePress = useCallback(() => {\n if (!onPress) return;\n const now = Date.now();\n if (now - lastPress.current < 500) return;\n lastPress.current = now;\n onPress();\n }, [onPress]);\n\n const handlePressIn = useCallback(() => pressTo(1), [pressTo]);\n const handlePressOut = useCallback(() => pressTo(0), [pressTo]);\n\n const scale = pressT.interpolate({\n inputRange: [0, 1],\n outputRange: [1, reduced ? 1 : BUTTON_PRESS_SCALE],\n });\n const opacity = pressT.interpolate({\n inputRange: [0, 1],\n outputRange: [1, reduced ? REDUCED_PRESS_OPACITY : 1],\n });\n\n return (\n <Pressable\n onPress={disabled ? undefined : handlePress}\n onPressIn={disabled ? undefined : handlePressIn}\n onPressOut={disabled ? undefined : handlePressOut}\n disabled={disabled}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled }}\n style={fullWidth ? styles.fill : undefined}\n >\n <Animated.View\n style={[\n styles.base,\n fullWidth && styles.fill,\n {\n borderRadius: t.button.radius,\n minHeight: t.button.height,\n paddingHorizontal: t.button.paddingX,\n opacity,\n transform: [{ scale }],\n },\n isPrimary\n ? { backgroundColor: disabled ? t.colors.disabled : t.colors.primary }\n : { borderWidth: 1.5, borderColor: disabled ? t.colors.border : t.colors.primary },\n ]}\n >\n <Text\n style={[\n buttonLabelStyle(t.fonts),\n {\n color: disabled\n ? t.colors.textMuted\n : isPrimary\n ? t.colors.onPrimary\n : t.colors.primary,\n },\n ]}\n >\n {title}\n </Text>\n </Animated.View>\n </Pressable>\n );\n};\n\nexport const Button = React.memo(_Button);\n\nconst styles = StyleSheet.create({\n base: { alignItems: \"center\", justifyContent: \"center\" },\n fill: { width: \"100%\" },\n});\n","/**\n * ErrorBlock — shown on backend error/timeout. Carries a retry action so the flow\n * never dead-ends. The host decides what retry does (re-send start, or fall back).\n */\nimport React from \"react\";\nimport { StyleSheet, Text, View } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { bodyStyle, headingStyle } from \"../theme/typography\";\nimport { Button } from \"./Button\";\n\nexport type ErrorBlockProps = {\n title?: string;\n message?: string;\n retryLabel?: string;\n onRetry?: () => void;\n};\n\nconst _ErrorBlock: React.FC<ErrorBlockProps> = ({\n title = \"Something went wrong\",\n message = \"We couldn't load this step. You can try again.\",\n retryLabel = \"Try again\",\n onRetry,\n}) => {\n const t = useOnboardingTheme();\n return (\n <View style={[styles.center, { gap: t.spacing.md, padding: t.spacing.lg }]}>\n <Text style={[headingStyle(t.fonts), { color: t.colors.text, textAlign: \"center\" }]}>\n {title}\n </Text>\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: \"center\" }]}>\n {message}\n </Text>\n {onRetry ? <Button title={retryLabel} onPress={onRetry} variant=\"outline\" /> : null}\n </View>\n );\n};\n\nexport const ErrorBlock = React.memo(_ErrorBlock);\n\nconst styles = StyleSheet.create({\n center: { flex: 1, alignItems: \"center\", justifyContent: \"center\" },\n});\n","/**\n * CardLayout — the shared full-screen card body every card renders into. It owns\n * the Cal-AI style vertical rhythm so no card re-implements layout:\n *\n * [ title ] ← fixed at top (small gap → subtitle)\n * [ subtitle / hint ]\n * [ ─ scrollable content ─ ]← options / chips / input; a flex:1 ScrollView that\n * fills the gap, so it scrolls only when tall and\n * otherwise just pushes the footer down\n * [ footer / CTA ] ← the submit button, ANCHORED to the bottom\n *\n * The middle ScrollView (flex:1) IS the flexible spacer: when the content is short\n * it grows to fill, pinning the footer to the bottom of the screen; when the\n * content is many/tall options it scrolls while the CTA stays put. Everything\n * reads from the theme tokens — no hardcoded spacing or color.\n *\n * `align=\"center\"` vertically centers the content (used by the value/status beats:\n * InterstitialCard / StatusCard), keeping the same pinned-CTA footer.\n *\n * The whole column sits in a KeyboardAvoidingView (behavior=\"padding\") so the pinned\n * footer rides above the soft keyboard on text questions (TextInputCard). On hosts\n * whose window already resizes for the keyboard the computed overlap is ~0, so the\n * padding is a no-op — safe on both iOS and Android, edge-to-edge or not.\n */\nimport React, { useMemo } from \"react\";\nimport { KeyboardAvoidingView, ScrollView, StyleSheet, Text, View } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport type { OnboardingTheme } from \"../theme/types\";\nimport { bodyStyle, labelStyle } from \"../theme/typography\";\n\nexport type CardLayoutProps = {\n /** Fixed question/label shown at the top. Omit for a header-less centered beat. */\n title?: string;\n /** Optional supporting line under the title (small gap between them). */\n subtitle?: string;\n /** The options / chips / input area — the scrollable middle. */\n children: React.ReactNode;\n /** The pinned bottom CTA (usually a <Button/>). Omitted → no footer. */\n footer?: React.ReactNode;\n /** Vertical alignment of the middle content. \"top\" (questions) | \"center\" (beats). */\n align?: \"top\" | \"center\";\n /** Custom title node (e.g. StatusCard's icon+title row) rendered in place of `title`. */\n titleNode?: React.ReactNode;\n};\n\nconst _CardLayout: React.FC<CardLayoutProps> = ({\n title,\n subtitle,\n children,\n footer,\n align = \"top\",\n titleNode,\n}) => {\n const t = useOnboardingTheme();\n const styles = useMemo(() => makeStyles(t), [t]);\n const hasHeader = !!title || !!subtitle || !!titleNode;\n\n return (\n <KeyboardAvoidingView style={styles.fill} behavior=\"padding\">\n {hasHeader ? (\n <View style={styles.header}>\n {titleNode ??\n (title ? (\n <Text style={[labelStyle(t.fonts), { color: t.colors.text }]}>{title}</Text>\n ) : null)}\n {subtitle ? (\n <Text\n style={[\n bodyStyle(t.fonts),\n { color: t.colors.textMuted, marginTop: t.spacing.xs },\n ]}\n >\n {subtitle}\n </Text>\n ) : null}\n </View>\n ) : null}\n\n <ScrollView\n style={styles.fill}\n contentContainerStyle={[\n styles.scrollContent,\n align === \"center\" && styles.center,\n ]}\n keyboardShouldPersistTaps=\"handled\"\n keyboardDismissMode=\"on-drag\"\n showsVerticalScrollIndicator={false}\n >\n {children}\n </ScrollView>\n\n {footer ? <View style={styles.footer}>{footer}</View> : null}\n </KeyboardAvoidingView>\n );\n};\n\nexport const CardLayout = React.memo(_CardLayout);\n\nfunction makeStyles(t: OnboardingTheme) {\n return StyleSheet.create({\n fill: { flex: 1 },\n header: { marginBottom: t.spacing.lg },\n footer: { paddingTop: t.spacing.lg },\n // flexGrow lets a short content block grow to fill (pinning the footer) while a\n // tall one scrolls past the visible area.\n scrollContent: { flexGrow: 1 },\n center: { justifyContent: \"center\" },\n });\n}\n","/**\n * CompletionView — the terminal \"you're all set\" screen, shown when the flow\n * reaches its final StatusCard. It surfaces the backend's recap (what the app\n * will do for the user, derived from their answers) and a single clear CTA.\n *\n * WHY a dedicated screen (not an instant hand-off): the backend spends the last\n * turn summarizing the user's tastes and what their experience will now look\n * like. The user should actually SEE that payoff and tap to continue — so\n * `onContinue` fires only on the button press, never automatically.\n *\n * Motion (design-refs/EXTRACTED-SPEC.md rows 14-16, the peak-end beat): the\n * badge pops in with a spring (scale 0.4→1, slight overshoot), ONE soft accent\n * burst radiates once behind it (scale 0.4→1.5, opacity 0.5→0, 500ms) —\n * celebratory without confetti — and the copy fades up 80ms apart. Everything\n * settles well under a second. Reduce motion: final frame, no burst.\n */\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, StyleSheet, Text, View } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { bodyStyle, headingStyle } from \"../theme/typography\";\nimport { Button } from \"./Button\";\nimport { CardLayout } from \"./CardLayout\";\nimport {\n STATUS_BURST_MS,\n STATUS_BURST_OPACITY_FROM,\n STATUS_BURST_SCALE_FROM,\n STATUS_BURST_SCALE_TO,\n STATUS_COPY_MS,\n STATUS_POP_SCALE_FROM,\n STATUS_POP_SPRING,\n WIRE_BEZIER,\n scaledMs,\n statusCopyDelay,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\nconst BADGE_SIZE = 64;\nconst BURST_SIZE = 104;\n\nexport type CompletionViewProps = {\n title: string;\n message?: string;\n ctaLabel?: string;\n onContinue: () => void;\n};\n\nconst _CompletionView: React.FC<CompletionViewProps> = ({\n title,\n message,\n ctaLabel = \"Let's go\",\n onContinue,\n}) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const [submitted, setSubmitted] = useState(false);\n\n const pop = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const burst = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const titleT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const messageT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n\n useEffect(() => {\n if (reduced) {\n // Final frame: badge + copy settled, burst already faded out.\n pop.setValue(1);\n burst.setValue(1);\n titleT.setValue(1);\n messageT.setValue(1);\n return;\n }\n const rise = (value: Animated.Value, delay: number) =>\n Animated.timing(value, {\n toValue: 1,\n duration: scaledMs(STATUS_COPY_MS),\n delay,\n easing: easeWire,\n useNativeDriver: true,\n });\n const anims = [\n Animated.spring(pop, {\n toValue: 1,\n friction: STATUS_POP_SPRING.friction,\n tension: STATUS_POP_SPRING.tension,\n useNativeDriver: true,\n }),\n // One-shot celebratory burst: fires once, never loops.\n Animated.timing(burst, {\n toValue: 1,\n duration: scaledMs(STATUS_BURST_MS),\n easing: Easing.out(Easing.ease),\n useNativeDriver: true,\n }),\n rise(titleT, scaledMs(statusCopyDelay(0))),\n rise(messageT, scaledMs(statusCopyDelay(1))),\n ];\n anims.forEach((a) => a.start());\n return () => anims.forEach((a) => a.stop());\n }, [reduced, pop, burst, titleT, messageT]);\n\n const handlePress = useCallback(() => {\n if (submitted) return;\n setSubmitted(true);\n onContinue();\n }, [submitted, onContinue]);\n\n const scale = pop.interpolate({ inputRange: [0, 1], outputRange: [STATUS_POP_SCALE_FROM, 1] });\n const burstScale = burst.interpolate({\n inputRange: [0, 1],\n outputRange: [STATUS_BURST_SCALE_FROM, STATUS_BURST_SCALE_TO],\n });\n const burstOpacity = burst.interpolate({\n inputRange: [0, 1],\n outputRange: [STATUS_BURST_OPACITY_FROM, 0],\n });\n const riseStyle = (value: Animated.Value) => ({\n opacity: value,\n transform: [{ translateY: value.interpolate({ inputRange: [0, 1], outputRange: [10, 0] }) }],\n });\n\n return (\n <CardLayout\n align=\"center\"\n footer={<Button title={ctaLabel} onPress={handlePress} variant=\"primary\" disabled={submitted} />}\n >\n <View style={[styles.center, { gap: t.spacing.md }]}>\n <View style={styles.badgeStage}>\n {/* Soft accent burst behind the badge: primarySoft keeps the tint calm. */}\n <Animated.View\n pointerEvents=\"none\"\n style={[\n styles.burst,\n {\n backgroundColor: t.colors.primarySoft,\n borderRadius: t.radius.full,\n opacity: burstOpacity,\n transform: [{ scale: burstScale }],\n },\n ]}\n />\n <Animated.View\n style={[\n styles.badge,\n {\n backgroundColor: t.colors.primarySoft,\n borderRadius: t.radius.full,\n transform: [{ scale }],\n opacity: pop,\n },\n ]}\n >\n <Text style={[styles.check, { color: t.colors.primary }]}>✓</Text>\n </Animated.View>\n </View>\n\n <Animated.View style={riseStyle(titleT)}>\n <Text style={[headingStyle(t.fonts), { color: t.colors.text, textAlign: \"center\" }]}>\n {title}\n </Text>\n </Animated.View>\n {message ? (\n <Animated.View style={riseStyle(messageT)}>\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: \"center\" }]}>\n {message}\n </Text>\n </Animated.View>\n ) : null}\n </View>\n </CardLayout>\n );\n};\n\nexport const CompletionView = React.memo(_CompletionView);\n\nconst styles = StyleSheet.create({\n center: { width: \"100%\", alignItems: \"center\", justifyContent: \"center\" },\n badgeStage: {\n width: BURST_SIZE,\n height: BURST_SIZE,\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n burst: { position: \"absolute\", width: BURST_SIZE, height: BURST_SIZE },\n badge: { width: BADGE_SIZE, height: BADGE_SIZE, alignItems: \"center\", justifyContent: \"center\" },\n check: { fontSize: 34, fontWeight: \"800\" },\n});\n","/**\n * CardHandoff — the card-to-card transition from the Wire Activation design:\n * \"cards hand off, they don't cut\". When `transitionKey` changes, the outgoing\n * child leaves left (translateX 0→-26, fade, 180ms) in an absolute layer while\n * the incoming child arrives from the right (translateX +26→0, fade, 220ms)\n * delayed by the 80ms exit lead — one moving surface, ~300ms total.\n *\n * Variants (per child):\n * - \"slide\": questions — the directional stepper motion above.\n * - \"spring\": the InterstitialCard value beat — scale 0.96→1 spring pop\n * (the shell's springier variant, kept from AnimatedCard).\n * - \"fade\": loaders — enter/exit as a plain 120ms fade so the \"thinking\"\n * state hands off to the first card without a hard cut.\n *\n * `direction` mirrors the whole slide for BACK navigation, so a step the user\n * returns to comes back from the side it left toward. Spatial consistency: if\n * \"next\" pushes left, \"back\" must pull right, or the stack loses its geography.\n *\n * `layout` picks how the moving surface is sized. \"fill\" (default) is the\n * full-screen flow, where the pane owns the viewport. \"auto\" is for a pane\n * inside an auto-height container (the CenteredModal card): `flex: 1` there\n * resolves to a ZERO-height child under Yoga — flex-basis 0 with no free space\n * to grow into — so the in-flow layer must size to its own content instead.\n *\n * Reduce motion: every handoff becomes a 120ms crossfade, no translate/scale.\n * All values run on the native driver (transform/opacity only); in-flight\n * animations are stopped when superseded and on unmount.\n *\n * This SUPERSEDES the enter-only AnimatedCard: same keyed-remount contract from\n * OnboardingFlow (the child renderer stays keyed on the message id), plus the\n * paired exit layer the design calls for.\n */\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, StyleSheet } from \"react-native\";\nimport {\n CARD_ENTER_MS,\n CARD_ENTER_SCALE_FROM,\n CARD_EXIT_LEAD_MS,\n CARD_EXIT_MS,\n CARD_SLIDE_PX,\n CARD_SPRING,\n LOADER_HANDOFF_FADE_MS,\n REDUCED_FADE_MS,\n WIRE_BEZIER,\n scaledMs,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\n\nexport type CardHandoffVariant = \"slide\" | \"spring\" | \"fade\";\n\n/** Which way the stack is moving. \"backward\" mirrors the slide (see the header note). */\nexport type CardHandoffDirection = \"forward\" | \"backward\";\n\n/** How the moving surface is sized. \"auto\" = a pane in an auto-height container. */\nexport type CardHandoffLayout = \"fill\" | \"auto\";\n\nexport type CardHandoffProps = {\n /** Identity of the current child (e.g. the message id). A change runs the handoff. */\n transitionKey: string;\n /** How the CURRENT child enters (and, snapshotted, how it will later exit). */\n variant?: CardHandoffVariant;\n /** Travel direction of THIS transition. Default \"forward\". */\n direction?: CardHandoffDirection;\n /** Sizing mode. Default \"fill\" (the full-screen flow). */\n layout?: CardHandoffLayout;\n children: React.ReactNode;\n};\n\ntype Snapshot = { key: string; node: React.ReactNode; variant: CardHandoffVariant };\n\nconst _CardHandoff: React.FC<CardHandoffProps> = ({\n transitionKey,\n variant = \"slide\",\n direction = \"forward\",\n layout = \"fill\",\n children,\n}) => {\n const reduced = useReducedMotion();\n const [leaving, setLeaving] = useState<Snapshot | null>(null);\n\n const enterT = useRef(new Animated.Value(0)).current;\n const exitT = useRef(new Animated.Value(0)).current;\n // The previous render's child, snapshotted so it can play the exit layer.\n const prev = useRef<Snapshot>({ key: transitionKey, node: children, variant });\n const running = useRef<{ enter?: Animated.CompositeAnimation; exit?: Animated.CompositeAnimation }>({});\n const mounted = useRef(false);\n\n // One orchestration effect, run every render: refresh the snapshot while the key\n // is stable; on a key change, snapshot the old child into the exit layer and run\n // the paired exit+enter. (No deps array on purpose — `children` is a fresh node\n // every parent render and must keep the snapshot current.)\n useEffect(() => {\n const last = prev.current;\n prev.current = { key: transitionKey, node: children, variant };\n\n // First mount: enter only (the design's initial reveal), nothing exits.\n if (!mounted.current) {\n mounted.current = true;\n running.current.enter = startEnter(enterT, variant, reduced, 0);\n return;\n }\n if (last.key === transitionKey) return;\n\n running.current.enter?.stop();\n running.current.exit?.stop();\n setLeaving(last);\n enterT.setValue(0);\n exitT.setValue(0);\n\n const exitDuration = reduced\n ? REDUCED_FADE_MS\n : last.variant === \"fade\"\n ? LOADER_HANDOFF_FADE_MS\n : CARD_EXIT_MS;\n const exit = Animated.timing(exitT, {\n toValue: 1,\n duration: scaledMs(exitDuration),\n easing: easeWire,\n useNativeDriver: true,\n });\n running.current.exit = exit;\n exit.start();\n\n const enter = startEnter(enterT, variant, reduced, reduced ? 0 : CARD_EXIT_LEAD_MS, () =>\n setLeaving(null),\n );\n running.current.enter = enter;\n });\n\n // Stop anything in flight on unmount (leaked animations drain the JS thread).\n useEffect(\n () => () => {\n running.current.enter?.stop();\n running.current.exit?.stop();\n },\n [],\n );\n\n const enterStyle = {\n opacity: enterT,\n transform: transformFor(variant, enterT, reduced, \"enter\", direction),\n };\n\n return (\n <>\n {leaving ? (\n <Animated.View\n pointerEvents=\"none\"\n style={[\n StyleSheet.absoluteFill,\n {\n opacity: exitT.interpolate({ inputRange: [0, 1], outputRange: [1, 0] }),\n // The CURRENT direction drives BOTH layers: one transition, one geography.\n transform: transformFor(leaving.variant, exitT, reduced, \"exit\", direction),\n },\n ]}\n >\n {leaving.node}\n </Animated.View>\n ) : null}\n <Animated.View key={variant} style={[layout === \"fill\" ? styles.fill : null, enterStyle]}>\n {children}\n </Animated.View>\n </>\n );\n};\n\n/** Kick off the enter animation for a variant (spring for the value beat, timing otherwise). */\nconst startEnter = (\n value: Animated.Value,\n variant: CardHandoffVariant,\n reduced: boolean,\n delay: number,\n onDone?: () => void,\n): Animated.CompositeAnimation => {\n value.setValue(0);\n const anim =\n !reduced && variant === \"spring\"\n ? Animated.spring(value, {\n toValue: 1,\n delay: scaledMs(delay),\n damping: CARD_SPRING.damping,\n stiffness: CARD_SPRING.stiffness,\n mass: CARD_SPRING.mass,\n useNativeDriver: true,\n })\n : Animated.timing(value, {\n toValue: 1,\n delay: scaledMs(delay),\n duration: scaledMs(\n reduced\n ? REDUCED_FADE_MS\n : variant === \"fade\"\n ? LOADER_HANDOFF_FADE_MS\n : CARD_ENTER_MS,\n ),\n easing: easeWire,\n useNativeDriver: true,\n });\n anim.start(({ finished }) => {\n if (finished) onDone?.();\n });\n return anim;\n};\n\n/**\n * Transform track per variant/layer; reduce motion = opacity-only crossfade.\n *\n * `travel` mirrors the X axis: forward pushes the stack left (new arrives from the\n * right), backward pulls it right (new arrives from the left).\n */\nconst transformFor = (\n variant: CardHandoffVariant,\n t: Animated.Value,\n reduced: boolean,\n layer: \"enter\" | \"exit\",\n travel: CardHandoffDirection,\n) => {\n if (reduced || variant === \"fade\") return [];\n if (variant === \"spring\" && layer === \"enter\") {\n return [{ scale: t.interpolate({ inputRange: [0, 1], outputRange: [CARD_ENTER_SCALE_FROM, 1] }) }];\n }\n const slide = travel === \"forward\" ? CARD_SLIDE_PX : -CARD_SLIDE_PX;\n return [\n {\n translateX: t.interpolate({\n inputRange: [0, 1],\n outputRange: layer === \"enter\" ? [slide, 0] : [0, -slide],\n }),\n },\n ];\n};\n\nexport const CardHandoff = React.memo(_CardHandoff);\n\nconst styles = StyleSheet.create({\n fill: { flex: 1 },\n});\n","/**\n * deriveAnswers — read the user's structured choices off the thread.\n *\n * The cards send answers back as natural-language strings (the SDK's\n * useWireAIAction wraps them, e.g. `I selected: [\"Food\",\"Travel\"]`,\n * `My answer is: \"Casablanca\"`). We pair each rendered question with the reply\n * that followed it and key the answer by the backend's progress `key` when\n * present (so `username`/`interests`/`city` come back under their real keys),\n * else by the question text. No second LLM call — the values ARE the data.\n */\nimport type { Message } from \"wireai-rn\";\n\nconst stripPrefix = (s: string): string =>\n s.replace(/^(I selected:|My answer is:|I tapped:)\\s*/i, \"\").trim();\n\nconst tryParse = (s: string): unknown => {\n try {\n return JSON.parse(s);\n } catch {\n return s;\n }\n};\n\nexport const deriveAnswers = (messages: Message[]): Record<string, unknown> => {\n const out: Record<string, unknown> = {};\n for (let i = 0; i < messages.length; i++) {\n const m = messages[i];\n const r = m?.response;\n if (!m || m.role !== \"assistant\" || !r || r.action !== \"render\") continue;\n\n const props = (r.props ?? {}) as Record<string, unknown>;\n const progress = props.progress as { key?: string; slot_id?: string } | undefined;\n const questionText =\n (props.title as string) ?? (props.label as string) ?? (props.question as string);\n // slot_id > key > question text, decided PER CARD. A thread that mixes slotted and unslotted\n // cards is the real shape during a server rollout, so caching a \"this backend does slots\" verdict\n // off the first card would mis-key every later one. Against a backend that sends no `slot_id`\n // this is byte-identical to 0.12.2.\n const key = progress?.slot_id || progress?.key || questionText;\n\n const reply = messages[i + 1];\n if (key && reply?.role === \"user\") {\n out[key] = tryParse(stripPrefix(reply.content));\n }\n }\n return out;\n};\n","/**\n * readProgress — pull the backend's progress metadata off a render response.\n *\n * The managed backend rides `{ step, total, key }` inside the Wire envelope's\n * `props.progress`. That's the only field that survives the SDK's strict client\n * validation (extra top-level keys get folded into props; the card's own schema\n * silently strips `progress` from its render props, but it stays readable on\n * `response.props`). All fields are optional so an older backend just falls back\n * to the local counter.\n */\nimport type { WireAIResponse } from \"wireai-rn\";\nimport type { OnboardingProgress } from \"../types\";\n\ntype PartialProgress = {\n step?: number;\n total?: number;\n key?: string;\n /** The stable per-slot identity, when the backend sends one. See `OnboardingProgress.slot_id`. */\n slot_id?: string;\n skippable?: boolean;\n};\n\nexport const readProgress = (response?: WireAIResponse): PartialProgress => {\n if (!response || response.action !== \"render\") return {};\n const props = (response.props ?? {}) as Record<string, unknown>;\n const raw = props.progress;\n if (!raw || typeof raw !== \"object\") return {};\n const p = raw as Partial<OnboardingProgress>;\n return {\n step: typeof p.step === \"number\" ? p.step : undefined,\n total: typeof p.total === \"number\" ? p.total : undefined,\n key: typeof p.key === \"string\" ? p.key : undefined,\n // Whitelisted the same way as every other field: an old backend simply omits it.\n slot_id: typeof p.slot_id === \"string\" ? p.slot_id : undefined,\n skippable: typeof p.skippable === \"boolean\" ? p.skippable : undefined,\n };\n};\n","/**\n * reportClientEvent — forward DEVICE-ONLY onboarding events to the Wire AI analytics\n * backend (`POST {serverUrl}/v1/events`), completing the funnel for events the server\n * can't observe on its own.\n *\n * The backend already records the server-observable funnel during the A2A flow\n * (`session_started`, `screen_shown`, `answer_submitted`, `completed`, `llm_fallback`,\n * and even `screen_skipped` — it derives that from the kit's skip sentinel). The one\n * event no server request can capture is `dropped`: the user closing the app / unmounting\n * the flow without finishing. That's what this reporter is for.\n *\n * Contract (server: routers/onboarding.py → analytics/events.py):\n * POST {serverUrl}/v1/events\n * Authorization: Bearer {apiKey}\n * { \"events\": [ { event_type, session_id, screen_index?, component?, question_key?,\n * latency_ms?, meta?, device?, user_context? } ] }\n * The server fills `app_id` + `environment` from the resolving key (never send app_id),\n * and silently skips malformed events — one bad payload never fails the batch.\n *\n * ⚠️ Correlation: `session_id` MUST equal the A2A `contextId` the server uses to key the\n * server-side events, or the funnel report (which groups by `session_id`) treats this as a\n * phantom session. See `makeSessionId` + WireOnboarding for how the kit seeds it.\n *\n * Fire-and-forget: this never throws into the UI and never awaits — analytics must never\n * be able to break onboarding.\n */\nimport type { DeviceContext } from \"../device/deviceContext\";\n\n/** Event types a CLIENT may report. The rest of the funnel is server-side; sending those\n * here would double-count. `screen_skipped` is included for completeness, but the kit does\n * NOT emit it — the backend already derives it from the skip sentinel (see OnboardingFlow).\n * `client_fallback` is emitted by the kit when the AI flow degrades to the static fallback,\n * so the dashboard's fallback-rate counts the whole-flow case (distinct from the server's\n * per-turn `llm_fallback`). The server back-fills a `session_started` for it if unseen.\n * This is the SINGLE fallback signal — hosts must NOT also report their own.\n * `identify` binds the host's opaque `user_id` to this `session_id` (late binding — the user\n * registered during/after onboarding). It carries no funnel weight; the server maps the\n * session to the user and back-fills a `session_started` if it never saw the session.\n * `app_event` is the host's own in-app event (the `createAnalytics` façade's `track`/`screen`\n * route through the offline queue as first-class `ClientEvent`s). The server already ingests\n * it — `reportAppEvent` (reviews/transport) has fired `event_type='app_event'` all along; this\n * widening just lets the same shape flow through the durable queue instead of a blind POST. */\nexport type ClientEventType =\n | \"screen_skipped\"\n | \"dropped\"\n | \"client_fallback\"\n | \"identify\"\n | \"app_event\";\n\n/** One client-reported event. Mirrors the server's `OnboardingEvent` (client-settable fields). */\nexport type ClientEvent = {\n event_type: ClientEventType;\n /** Must match the server-side A2A contextId for this onboarding (see makeSessionId). */\n session_id: string;\n /** 0-based index of the screen the event refers to (matches server `screen_shown`). */\n screen_index?: number;\n component?: string;\n question_key?: string;\n latency_ms?: number;\n /** JSON-stringified extras; the server stores it verbatim. */\n meta?: string;\n /**\n * Privacy-label-neutral device snapshot (platform / form factor / locale / host appVersion).\n * Sent as an object; the server sanitizes + persists it and derives a coarse country. Old\n * servers ignore this unknown field — fully backward compatible. See device/deviceContext.ts.\n */\n device?: DeviceContext;\n /**\n * Host-injected, non-PII context (signup method, referral, plan, hashed user id). Old servers\n * ignore it. MUST NOT contain PII like raw emails — see the README `userContext` section.\n */\n user_context?: Record<string, string | number | boolean>;\n /**\n * The host's OPAQUE PSEUDONYMOUS user id (their internal id, NOT an email/name). Required on\n * `identify`, optional (rides along) on other events. Trimmed + capped at 128 chars host-side.\n * Lets the backend reconcile onboarding sessions to real users. Old servers ignore it.\n */\n user_id?: string;\n /**\n * Client-stamped epoch-ms timestamp of when the event was ENQUEUED on the device. Optional and\n * ADDITIVE: the offline queue stamps it at enqueue time (see `createEventQueue`) so two otherwise\n * byte-identical events fired seconds apart (a genuine repeat, e.g. the user taps \"share\" twice)\n * are NOT collapsed by the queue's identical-JSON de-dup — while two truly simultaneous\n * re-enqueues of the same instant (a redundant re-render) still share a `ts` and collapse. A raw\n * `Date.now()`, never a wall-clock the server trusts (the server derives its own receive time);\n * an old/strict server that does not model it simply ignores the unknown field.\n */\n ts?: number;\n};\n\n/** Where to POST. Derived from `WireOnboardingConfig` (`serverUrl` + `apiKey`). */\nexport type ClientEventTarget = {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/v1/events` is appended. */\n serverUrl: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey: string;\n};\n\n/**\n * A unique-per-onboarding session id. Used both as the client event `session_id` AND as the\n * seed the kit forwards to the backend so the SERVER adopts it as the A2A `contextId` — making\n * client and server agree (see WireOnboarding + the SDK-correlation note in the kit docs).\n * No crypto dependency: timestamp + random is collision-safe for a single device's onboarding.\n */\nexport const makeSessionId = (): string =>\n `wire_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n\n/**\n * The ONE place the `/v1/events` POST is described (url + method + headers + body). Both the\n * fire-and-forget {@link reportClientEvents} and the awaitable {@link reportClientEventsAwait}\n * build their request here so there is a SINGLE definition of the events transport — no second\n * copy of the endpoint path, headers, or envelope shape to drift. Returns `null` when there is\n * nothing to send (no target / no events) or serialization throws, so callers just bail.\n */\nexport const buildEventsRequest = (\n target: { serverUrl: string; apiKey?: string } | undefined,\n events: ClientEvent[],\n): { url: string; init: RequestInit } | null => {\n if (!target?.serverUrl || events.length === 0) return null;\n try {\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/v1/events`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n return { url, init: { method: \"POST\", headers, body: JSON.stringify({ events }) } };\n } catch {\n // URL construction or JSON serialization failed — nothing to send.\n return null;\n }\n};\n\n/** What the `/v1/events` endpoint says in its 200 body. `errors` is the server's planned per-event\n * reason list; it is read defensively because no deployed server sends it yet. */\ntype EventsAck = { written?: number; skipped: number; reasons: string[] };\n\n/**\n * Read the `/v1/events` ACK body. Resolves `undefined` when there is nothing readable — no `.json`\n * (an old server, a bare test mock), an already-consumed body, or a hostile response object. NEVER\n * throws, and NEVER dev-gated: the `skipped` count is a RETURN VALUE for the awaitable path, not only\n * a warning, so it has to be read in production too.\n *\n * ⚠️ The body can be read exactly once, so a caller that both decides on `skipped` AND warns must do\n * both from ONE call to this.\n */\nconst readEventsAck = async (res: unknown): Promise<EventsAck | undefined> => {\n try {\n const json = (res as { json?: () => Promise<unknown> } | null | undefined)?.json;\n if (typeof json !== \"function\") return undefined;\n const body = (await Promise.resolve(json.call(res))) as\n | { written?: unknown; skipped?: unknown; errors?: unknown }\n | null\n | undefined;\n const skipped = body?.skipped;\n if (typeof skipped !== \"number\" || !Number.isFinite(skipped)) return undefined;\n const reasons = Array.isArray(body?.errors)\n ? body.errors\n .map((e) => (e as { reason?: unknown } | null)?.reason)\n .filter((r): r is string => typeof r === \"string\")\n : [];\n return { written: typeof body?.written === \"number\" ? body.written : undefined, skipped, reasons };\n } catch {\n // Unreadable / already-consumed body / hostile object — best-effort, treat as \"no ack\".\n return undefined;\n }\n};\n\n/**\n * The DISCARDED warning text, built from what the server ACTUALLY said.\n *\n * It used to staple a cause onto a bare integer — \"the usual cause is a missing or empty session_id\".\n * Since `ensureCurrentSessionId` shipped, no kit path can emit an event without a `session_id`, so\n * that is now the LEAST likely explanation, and naming it sent every reader looking in the one place\n * the problem is not. The endpoint folds four real failures and two idempotent no-ops into one\n * integer, so unless the server volunteers reasons, the honest thing to report is the count and where\n * the reason lives.\n */\nconst describeDiscarded = (ack: EventsAck): string =>\n `[wireai] the server ACCEPTED the /v1/events POST but DISCARDED ${ack.skipped} event(s) ` +\n \"(skipped in the response body) — they are gone, not retried. The server reported: \" +\n `skipped=${ack.skipped}${ack.written !== undefined ? `, written=${ack.written}` : \"\"}` +\n (ack.reasons.length > 0\n ? `, reasons: ${ack.reasons.join(\", \")}.`\n : \". It gave no reason (the endpoint folds every rejection into one count), so check the \" +\n \"server's ingest log for this request rather than guessing.\");\n\n/** RN sets this global; absent under node/SSR. Read defensively inside {@link warnOnSkippedEvents}. */\ndeclare const __DEV__: boolean | undefined;\n\n/**\n * Read the `/v1/events` ACK body and warn (dev builds only) when the server DISCARDED events.\n *\n * The endpoint answers HTTP **200** with `{ ok, written, skipped }` — an event it refuses is counted\n * in `skipped`, never surfaced in the status code. Every send path here reads `res.ok` alone, so a\n * whole batch can evaporate behind a green response. As of 0.13.0 ALL FOUR send paths consume the ack:\n * the offline queue, session-start, the fire-and-forget POST, and the awaitable one (which also acts\n * on it — see {@link reportClientEventsAwait}).\n *\n * LOG ONLY: returns immediately, never throws, and never influences retry / dequeue / return values.\n * A response with no usable `.json` (an old server, a test mock) is silently ignored.\n *\n * DEV-GATED FIRST: the `__DEV__` check is the FIRST statement, before the body is even looked at.\n * The check used to sit inside the `.then`, so a release build parsed the JSON of every\n * persistent-path POST to build a warning no one would ever read. Nothing here runs in production.\n */\nexport const warnOnSkippedEvents = (res: unknown): void => {\n if (typeof __DEV__ === \"undefined\" || !__DEV__) return;\n if (typeof console === \"undefined\" || !console.warn) return;\n void readEventsAck(res).then((ack) => {\n if (!ack || ack.skipped <= 0) return;\n console.warn(describeDiscarded(ack));\n });\n};\n\n/**\n * POST one or more client events, fire-and-forget. A missing/invalid target, a build error,\n * a missing `fetch`, or a network failure is swallowed — the call returns immediately and the\n * request (if any) runs in the background.\n */\nexport const reportClientEvents = (\n target: ClientEventTarget | undefined,\n events: ClientEvent[],\n): void => {\n try {\n const req = buildEventsRequest(target, events);\n if (!req) return;\n void fetch(req.url, req.init)\n .then((res) => {\n // Still fire-and-forget — nothing is retried, nothing is returned. But a batch that\n // evaporated behind a 200 is exactly what this path used to make invisible, so in dev it\n // now says so, like the queue and session-start paths already did.\n warnOnSkippedEvents(res);\n })\n .catch(() => {\n // Network/transport error — analytics is best-effort, swallow.\n });\n } catch {\n // A missing `fetch` — swallow.\n }\n};\n\n/** Convenience single-event wrapper around {@link reportClientEvents}. */\nexport const reportClientEvent = (\n target: ClientEventTarget | undefined,\n event: ClientEvent,\n): void => reportClientEvents(target, [event]);\n\n/**\n * AWAITABLE sibling of {@link reportClientEvents}: POST one or more client events through the SAME\n * `/v1/events` path, but resolve only once the server has RESPONDED — so a decision re-fetch fired\n * immediately after is guaranteed to see the event in the session stream (this is the guarantee\n * `wire.track` needs before it triggers decision revalidation). Never throws: a missing/invalid\n * target, a missing `fetch`, a network error, or a non-2xx status all resolve to `false`.\n *\n * ⚠️ 0.13.0: a 2xx is NO LONGER SUFFICIENT. The endpoint answers HTTP 200 with `{ ok, written,\n * skipped }` and counts an event it refuses in `skipped`, so this used to resolve `true` for an event\n * the server had thrown away — and `wire.track` then bumped decision revalidation, making every\n * subscribed gate re-fetch against a stream the action never entered. It now reads the ack and\n * resolves `false` when the server reports a positive `skipped`.\n *\n * BACKWARD COMPATIBLE BY CONSTRUCTION: only an explicit positive `skipped` demotes a 200. An old\n * server that sends no such field, a body that cannot be parsed, or a response with no `.json` at all\n * resolves `true` exactly as before — the change can produce no false negatives.\n */\nexport const reportClientEventsAwait = async (\n target: ClientEventTarget | undefined,\n events: ClientEvent[],\n): Promise<boolean> => {\n try {\n const req = buildEventsRequest(target, events);\n if (!req) return false;\n const res = await fetch(req.url, req.init);\n if (!res || !res.ok) return false;\n // ONE body read, used for both the verdict and the dev warning — it can only be read once.\n const ack = await readEventsAck(res);\n if (!ack || ack.skipped <= 0) return true;\n if (typeof __DEV__ !== \"undefined\" && __DEV__ && typeof console !== \"undefined\" && console.warn) {\n console.warn(describeDiscarded(ack));\n }\n return false;\n } catch {\n // Unreachable / missing-fetch / network — best-effort, report failure.\n return false;\n }\n};\n\n/** Convenience single-event wrapper around {@link reportClientEventsAwait}. */\nexport const reportClientEventAwait = (\n target: ClientEventTarget | undefined,\n event: ClientEvent,\n): Promise<boolean> => reportClientEventsAwait(target, [event]);\n","/**\n * sendPreview — fire-and-forget PREFETCH of the next A2A turn, so the backend can warm\n * its generation cache during a moment the user isn't waiting.\n *\n * Two callers, both firing the SAME text the real commit will send (the backend keys the\n * preview cache on the raw message string, so a mismatch just misses harmlessly):\n * 1. InterstitialCard — its answer is always \"continue\" (SDK-wrapped `My answer is: \"continue\"`),\n * warmed while the user reads the momentum screen.\n * 2. Choice cards (Selection/ChipSelect) — warmed on selection-change with the exact\n * `I selected: ${JSON.stringify(value)}` the Continue tap will send, so the perceptibly-slow\n * first LLM question returns from cache. See OnboardingFlow.previewOnSelect.\n *\n * Contract (mirrors the A2A `message/send` shape, but a distinct `method`):\n * POST {serverUrl}/a2a\n * Authorization: Bearer {apiKey}\n * { jsonrpc:\"2.0\", id:<rand>, method:\"message/preview\",\n * params:{ message:{ role:\"user\", parts:[{ text }] }, contextId:<sessionId>,\n * metadata:{ sessionId } } }\n *\n * Fire-and-forget, exactly like reportClientEvent: never awaits, never throws into the UI —\n * a prefetch that fails just means the real turn generates normally.\n */\n\n/** Where to POST the preview. Same tenant creds as the flow (`serverUrl` + `apiKey`). */\nexport type PreviewTarget = {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/a2a` is appended. */\n serverUrl: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey: string;\n};\n\n/** What to preview: the session to warm and the message the user is about to send. */\nexport type PreviewArgs = {\n /** A2A contextId for this onboarding (the kit session id). */\n sessionId: string;\n /** The message that will be committed next (for interstitials, always \"continue\"). */\n userMessage: string;\n};\n\n/**\n * Warm the next turn's cache, fire-and-forget. A missing/invalid target, a build error,\n * a missing `fetch`, or a network failure is swallowed — the call returns immediately and\n * the request (if any) runs in the background.\n */\nexport const sendPreview = (\n target: PreviewTarget | undefined,\n { sessionId, userMessage }: PreviewArgs,\n): void => {\n if (!target?.serverUrl) return;\n try {\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/a2a`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n void fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: Math.floor(Math.random() * 1e9),\n method: \"message/preview\",\n params: {\n message: { role: \"user\", parts: [{ text: userMessage }] },\n contextId: sessionId,\n metadata: { sessionId },\n },\n }),\n }).catch(() => {\n // Network/transport error — prefetch is best-effort, swallow.\n });\n } catch {\n // URL construction, JSON serialization, or a missing fetch — swallow.\n }\n};\n","/**\n * OnboardingFlow — the inner engine. Mirrors the proven production-app usage of the SDK\n * (useWireAIThread + useWireAIAction + ComponentRenderer) and layers on the kit's\n * shell, progress, and per-step validators.\n *\n * Lifecycle per turn:\n * 1. Auto-send `startMessage` once → backend returns the first card.\n * 2. Show LoadingBlock until the first card arrives AND between every turn\n * (while `isLoading`); on error/timeout, auto-retry up to `maxRetries`, then\n * degrade to the host's static `fallbackFlow` (preferred), else `onError`, else\n * an inline ErrorBlock — so a generation failure never breaks onboarding.\n * 3. Render the latest card inside OnboardingScaffold. The progress bar follows\n * an asymptotic curve of the step index — it never reveals a total.\n * 4. Before any answer is sent, if the current screen's question key has a\n * validator, run it; on failure show the error inline and DON'T advance.\n * 5. On the terminal StatusCard, show CompletionView (the recap of what the app\n * will do for the user) and fire onComplete only when they tap its CTA.\n *\n * Lifecycle events (started / per-turn / error) are surfaced via `onEvent` so a\n * host can keep its analytics even though the kit owns the thread loop.\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n ComponentRenderer,\n useWireAIAction,\n useWireAIThread,\n type Message,\n} from \"wireai-rn\";\nimport { OnboardingScaffold } from \"./components/OnboardingScaffold\";\nimport { LoadingBlock } from \"./components/LoadingBlock\";\nimport { LoadingScreen } from \"./components/LoadingScreen\";\nimport { ErrorBlock } from \"./components/ErrorBlock\";\nimport { CompletionView } from \"./components/CompletionView\";\nimport { CardHandoff } from \"./components/CardHandoff\";\nimport { deriveAnswers } from \"./utils/deriveAnswers\";\nimport { readProgress } from \"./utils/readProgress\";\nimport { reportClientEvent, type ClientEventTarget } from \"./analytics/reportClientEvent\";\nimport { sendPreview } from \"./analytics/sendPreview\";\nimport type { DeviceContext } from \"./device/deviceContext\";\nimport type { OnboardingCopy, OnboardingEvent, OnboardingResult, StepValidator } from \"./types\";\n\ntype OnboardingFlowProps = {\n validators?: Record<string, StepValidator>;\n onComplete: (result: OnboardingResult) => void;\n onSkip?: () => void;\n onError?: (err: unknown) => void;\n onEvent?: (event: OnboardingEvent) => void;\n copy?: Partial<OnboardingCopy>;\n approxScreens?: number;\n startMessage: string;\n startTimeoutMs: number;\n /** Static onboarding rendered when the AI flow fails and retries are exhausted. */\n fallbackFlow?: React.ReactNode;\n /** Consecutive failures to auto-retry before degrading. */\n maxRetries: number;\n /** Where to POST device-only client events (`dropped`). Omit to disable reporting. */\n reportTarget?: ClientEventTarget;\n /** Session id shared with the backend (A2A contextId), so `dropped` correlates. */\n sessionId: string;\n /**\n * Device snapshot + host-injected user context, attached to every client event so the\n * backend can segment the funnel by device. Old servers ignore the extra fields.\n */\n clientContext?: {\n device?: DeviceContext;\n userContext?: Record<string, string | number | boolean>;\n /** The host's opaque user id (see WireOnboarding `userId`), rides `dropped`/`client_fallback`. */\n userId?: string;\n };\n /**\n * True when `sessionId` was restored from persisted storage (app killed mid-flow).\n * The kickoff then sends the skip sentinel instead of `startMessage` — the server\n * would record the literal start text as the ANSWER to the pending question, while\n * the sentinel advances one card recording nothing — and fires `resumed` instead of\n * `started` so host funnels don't double-count the session.\n */\n resumed?: boolean;\n};\n\n// The kit's per-question Skip sends this sentinel; the backend skips ONE question\n// (advances one card, no answer recorded). Must match the backend's SKIP_ONE_SENTINEL.\nconst SKIP_ONE_SENTINEL = \"__wireai_skip__\";\n\n// Callbacks that carry the user's ANSWER (and so must pass validation first).\nconst ANSWER_CALLBACKS = [\"onSubmit\", \"onSelect\", \"onConfirm\", \"onPress\"] as const;\n\nexport const DEFAULT_COPY: OnboardingCopy = {\n startingTitle: \"Getting started…\",\n startingHint: \"Setting up your onboarding\",\n restoringTitle: \"Picking up where you left off…\",\n restoringHint: \"Restoring your session\",\n thinkingTitle: \"Personalizing…\",\n thinkingHint: \"Tailoring your next question\",\n checkingTitle: \"Checking…\",\n checkingHint: \"One moment\",\n completeTitle: \"You're all set\",\n completeCta: \"Let's go\",\n};\n\nexport const OnboardingFlow: React.FC<OnboardingFlowProps> = ({\n validators,\n onComplete,\n onError,\n onEvent,\n copy,\n approxScreens,\n startMessage,\n startTimeoutMs,\n fallbackFlow,\n maxRetries,\n reportTarget,\n sessionId,\n resumed = false,\n clientContext,\n}) => {\n const { messages, error, isLoading, sendMessage, reset } = useWireAIThread();\n const makeActions = useWireAIAction(sendMessage);\n\n const c = useMemo<OnboardingCopy>(() => ({ ...DEFAULT_COPY, ...copy }), [copy]);\n\n // Hold the latest event/error callbacks in refs so the lifecycle effects below\n // stay stable (and fire exactly once) regardless of the host re-passing closures.\n const onEventRef = useRef(onEvent);\n onEventRef.current = onEvent;\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n const onCompleteRef = useRef(onComplete);\n onCompleteRef.current = onComplete;\n const validatorsRef = useRef(validators);\n validatorsRef.current = validators;\n\n // Client-event reporting refs, captured so the unmount cleanup (which runs once, with a\n // stale closure) reads current values.\n const reportTargetRef = useRef(reportTarget);\n reportTargetRef.current = reportTarget;\n const sessionIdRef = useRef(sessionId);\n sessionIdRef.current = sessionId;\n // Device + user context, held in a ref so the mount-once unmount cleanup (the `dropped`\n // reporter, which runs with a stale closure) reads the current snapshot.\n const clientContextRef = useRef(clientContext);\n clientContextRef.current = clientContext;\n // Last 0-based screen index we showed the user (matches the server's `screen_shown`\n // index). Used as the `dropped` event's screen_index. -1 = nothing shown yet.\n const lastScreenIndexRef = useRef(-1);\n // Trailing-edge debounce timer for prefetch-on-select (see previewOnSelect below).\n const previewTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const started = useRef(false);\n const finished = useRef(false);\n const errored = useRef(false);\n const attempts = useRef(0);\n // Mirror of the `degraded` state for the unmount cleanup: a degrade to the static\n // fallback is NOT a drop, so `dropped` must not fire after it.\n const degradedRef = useRef(false);\n const [degraded, setDegraded] = useState(false);\n const [timedOut, setTimedOut] = useState(false);\n const [validationError, setValidationError] = useState<string | undefined>();\n const [validating, setValidating] = useState(false);\n\n const lastCard = useMemo<Message | undefined>(\n () => [...messages].reverse().find((m) => m.role === \"assistant\" && m.response?.action === \"render\"),\n [messages],\n );\n\n // Local fallback counter — how many distinct rendered cards we've seen.\n const renderedCount = useMemo(\n () => messages.filter((m) => m.role === \"assistant\" && m.response?.action === \"render\").length,\n [messages],\n );\n\n const progress = useMemo(() => readProgress(lastCard?.response), [lastCard]);\n\n // 1. Auto-start: the backend treats the first inbound message as \"begin\".\n // On a RESUMED session (persisted id restored after an app kill) the kickoff is\n // the skip sentinel instead: the server has this session mid-flow with a pending\n // question, and would record `startMessage`'s literal text as its ANSWER — the\n // sentinel advances one card recording nothing (a `screen_skipped`). On a session\n // the server no longer knows (restart/expiry), the sentinel degrades cleanly to a\n // normal kickoff under the same id. Retries re-send the same kickoff.\n useEffect(() => {\n if (started.current) return;\n started.current = true;\n sendMessage(resumed ? SKIP_ONE_SENTINEL : startMessage);\n // Surface the session id (the A2A contextId) on the start event so a host can capture it\n // and bind a user AFTER the flow via `identifyOnboarding({ contextId })` — completion clears\n // the persisted session, so the in-flight event is the reliable post-flow handle. sessionId\n // is stable for the whole session (minted before this subtree mounts), so this stays mount-once.\n onEventRef.current?.(\n resumed\n ? { type: \"resumed\", contextId: sessionId }\n : { type: \"started\", contextId: sessionId },\n );\n }, [sendMessage, startMessage, resumed, sessionId]);\n\n // 2. Startup watchdog.\n useEffect(() => {\n if (lastCard) return;\n const timer = setTimeout(() => setTimedOut(true), startTimeoutMs);\n return () => clearTimeout(timer);\n }, [lastCard, startTimeoutMs]);\n\n // A new card arrived → clear any prior inline validation error + emit a turn event.\n useEffect(() => {\n setValidationError(undefined);\n if (!lastCard?.id) return;\n const step = progress.step ?? renderedCount;\n // Remember the latest screen we showed (0-based) for a possible `dropped` event.\n lastScreenIndexRef.current = Math.max(0, step - 1);\n onEventRef.current?.({\n type: \"turn\",\n step,\n component: lastCard.response?.component,\n });\n // Prefetch: an InterstitialCard's answer is always \"continue\", so we can warm the next\n // turn's cache during the momentum window — by the time the user taps Continue the following\n // card is already generated. The preview MUST use the exact text the real Continue tap sends,\n // or the backend's message-keyed preview cache misses. The card's onSubmit(\"continue\") is\n // wrapped by the SDK as `My answer is: ${JSON.stringify(value)}`, so mirror that here.\n // Fire-and-forget; a failed/missed preview just means the real turn generates normally.\n if (lastCard.response?.component === \"InterstitialCard\") {\n sendPreview(reportTargetRef.current, {\n sessionId: sessionIdRef.current,\n userMessage: `My answer is: ${JSON.stringify(\"continue\")}`,\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [lastCard?.id]);\n\n // `dropped`: the user abandoned onboarding. No backend request fires on unmount, so the\n // server can't see this — the client must report it. Fire ONLY on a true unmount that\n // did NOT complete (`onComplete` never ran) and did NOT degrade to the static fallback\n // (a degrade is a reliability fallback, not a user drop). Refs keep this effect mount-once.\n useEffect(() => {\n return () => {\n if (finished.current || degradedRef.current) return;\n reportClientEvent(reportTargetRef.current, {\n event_type: \"dropped\",\n session_id: sessionIdRef.current,\n screen_index: lastScreenIndexRef.current >= 0 ? lastScreenIndexRef.current : undefined,\n device: clientContextRef.current?.device,\n user_context: clientContextRef.current?.userContext,\n user_id: clientContextRef.current?.userId,\n });\n };\n }, []);\n\n // Silently restart the thread from turn one (shared by auto-retry + manual retry).\n // Does NOT clear the attempt counter or the degraded flag — the caller decides that.\n const restartThread = useCallback(() => {\n setTimedOut(false);\n started.current = false;\n errored.current = false;\n reset();\n }, [reset]);\n\n // 3. Error/timeout → auto-retry a transient blip, then degrade to the static flow.\n // Each failure: log `error`; if we have retries left, restart the thread silently\n // (`retry`); once exhausted, mark `degraded` so the render falls through to the\n // host's `fallbackFlow`/`onError` (`fallback`). Counter is a ref → survives the\n // reset()-driven re-renders. This is the \"AI fails → static onboarding, never a\n // broken screen\" guarantee.\n useEffect(() => {\n if (errored.current) return;\n if (!error && !timedOut) return;\n errored.current = true;\n const reason: \"backend\" | \"timeout\" = error ? \"backend\" : \"timeout\";\n onEventRef.current?.({ type: \"error\", reason });\n attempts.current += 1;\n if (attempts.current <= maxRetries) {\n onEventRef.current?.({ type: \"retry\", reason, attempt: attempts.current });\n restartThread();\n } else {\n onEventRef.current?.({ type: \"fallback\", reason });\n // Report the degrade to the backend so the dashboard's fallback-rate reflects it.\n // Server-side `llm_fallback` fires per single degraded turn; this `client_fallback`\n // captures the whole-flow case (AI gave up, the user got static onboarding). The server\n // ingests it idempotently and back-fills a `session_started` if it never saw the session,\n // so even a device that dropped straight to its static manifest shows as a counted\n // fallback session. This is the ONE fallback signal — hosts must NOT also report it.\n reportClientEvent(reportTargetRef.current, {\n event_type: \"client_fallback\",\n session_id: sessionIdRef.current,\n screen_index: lastScreenIndexRef.current >= 0 ? lastScreenIndexRef.current : undefined,\n meta: JSON.stringify({ reason }),\n device: clientContextRef.current?.device,\n user_context: clientContextRef.current?.userContext,\n user_id: clientContextRef.current?.userId,\n });\n degradedRef.current = true;\n setDegraded(true);\n onErrorRef.current?.(error ?? new Error(\"Onboarding timed out\"));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [error, timedOut, maxRetries]);\n\n // 5. Completion: the terminal StatusCard is rendered as CompletionView; we fire\n // onComplete only when the user taps its CTA (guarded so it fires once).\n const handleFinish = useCallback(() => {\n if (finished.current) return;\n finished.current = true;\n onCompleteRef.current({ answers: deriveAnswers(messages), raw: messages });\n }, [messages]);\n\n // Manual retry (the no-fallback ErrorBlock button): clear the degrade + counter so\n // the user gets a fresh set of attempts.\n const handleRetry = useCallback(() => {\n attempts.current = 0;\n degradedRef.current = false;\n setDegraded(false);\n restartThread();\n }, [restartThread]);\n\n // Per-question Skip: tell the backend to skip THIS question only and advance to the\n // next card (no answer recorded) — distinct from finishing the flow. Rendered only\n // when the current card is `skippable` (see the scaffold below).\n //\n // NOTE: we deliberately do NOT report a client `screen_skipped` here. The backend already\n // emits `screen_skipped` (correctly correlated by its own contextId, with screen_index +\n // question_key) when it processes this SKIP_ONE_SENTINEL — see the server engine. A client\n // emission would double-count. The reporter supports `screen_skipped` for clients whose skip\n // never reaches the server, which is not the case for this kit.\n const skipQuestion = useCallback(() => {\n if (isLoading) return;\n sendMessage(SKIP_ONE_SENTINEL);\n }, [isLoading, sendMessage]);\n\n // Prefetch on SELECT — the fix for \"the first AI question is always the slowest\". Q1 is a\n // deterministic base card (instant); Q2 is the first LLM turn, and neither cache protects it\n // (flow-cache misses a novel answer combo, the provider prompt-cache is cold on the first\n // call). Choice cards hold their selection LOCALLY and only commit on Continue, so there's a\n // real gap we can use: as the user picks, fire a debounced `message/preview` keyed on the\n // EXACT text the Continue tap will send (`I selected: ${JSON.stringify(value)}`), so the\n // backend generates Q2 during the pick→Continue window. By the time they tap Continue it's\n // already cached → the slow question returns instantly. Fire-and-forget: if they change the\n // selection after the last preview, the real turn just generates normally (never worse than\n // today). Trailing-edge debounced so rapid multi-select toggles warm at most once.\n const previewOnSelect = useCallback((value: string | string[]) => {\n const target = reportTargetRef.current;\n if (!target?.serverUrl) return;\n if (Array.isArray(value) ? value.length === 0 : !value) return;\n if (previewTimer.current) clearTimeout(previewTimer.current);\n previewTimer.current = setTimeout(() => {\n sendPreview(target, {\n sessionId: sessionIdRef.current,\n userMessage: `I selected: ${JSON.stringify(value)}`,\n });\n }, 300);\n }, []);\n\n // Cancel any pending preview on unmount so a fired-but-unsent warm can't outlive the flow.\n useEffect(() => () => {\n if (previewTimer.current) clearTimeout(previewTimer.current);\n }, []);\n\n // 4. Wrap the SDK's action callbacks so an answer is validated before it's sent.\n const wrappedActions = useCallback(\n (messageId: string) => {\n const base = makeActions(messageId);\n // ⚠️ HOST VALIDATORS LIVE IN THE SAME KEY NAMESPACE `deriveAnswers` files answers under, so\n // moving the answer key to `slot_id` without moving this lookup would silently UNBIND every\n // host validator — no error, no warning, values just stop being checked. Try the slot first\n // (matching the answer key), then fall back to the question key, so a host that has not yet\n // renamed its validator map keeps working while a server rolls slots out.\n const validators = validatorsRef.current;\n const validator =\n (progress.slot_id ? validators?.[progress.slot_id] : undefined) ??\n (progress.key ? validators?.[progress.key] : undefined);\n if (!validator) return base;\n\n const out: Record<string, (...args: unknown[]) => void> = { ...base };\n for (const name of ANSWER_CALLBACKS) {\n const original = base[name];\n if (!original) continue;\n out[name] = (...args: unknown[]) => {\n const value = args[0];\n // Only string answers are validatable (e.g. username). Pass others through.\n if (typeof value !== \"string\") return original(...args);\n setValidating(true);\n validator(value)\n .then((res) => {\n if (res.ok) {\n setValidationError(undefined);\n original(...args);\n } else {\n setValidationError(res.error ?? \"That value isn't available.\");\n }\n })\n .catch(() => {\n // A validator failure must never block the user — let them proceed.\n original(...args);\n })\n .finally(() => setValidating(false));\n };\n }\n return out;\n },\n [makeActions, progress.key, progress.slot_id],\n );\n\n // ── Render ────────────────────────────────────────────────────────────────\n // Degraded (retries exhausted): render the host's static onboarding in place —\n // the \"AI failed → your static flow, never a broken screen\" guarantee. If no\n // static flow was supplied, hand off to onError (host navigates away), else the\n // inline retry screen as a last resort.\n if (degraded) {\n if (fallbackFlow !== undefined) return <>{fallbackFlow}</>;\n if (onError) {\n return <LoadingScreen title={c.startingTitle} hint={c.startingHint} />;\n }\n return (\n <ErrorBlock\n onRetry={handleRetry}\n message={\n timedOut\n ? \"This is taking longer than expected. Try again?\"\n : \"We couldn't reach the onboarding service. Try again?\"\n }\n />\n );\n }\n\n // Errored but not yet degraded → an auto-retry is in flight. Show a neutral loader\n // so a transient blip never flashes an error screen.\n if (error || timedOut) {\n return <LoadingScreen title={c.startingTitle} hint={c.startingHint} />;\n }\n\n const response = lastCard?.response;\n\n // No card yet → the first \"thinking\" screen.\n if (!lastCard || !response) {\n return <LoadingScreen title={c.startingTitle} hint={c.startingHint} />;\n }\n\n // Step index drives the progress bar. A total (never shown) only paces the fill:\n // prefer a backend-supplied total, else the host's approximate prop, else asymptotic.\n const step = progress.step ?? renderedCount;\n const total = progress.total ?? approxScreens;\n const isTerminal = response.action === \"render\" && response.component === \"StatusCard\";\n\n // Terminal recap: show what the app will now do for the user (backend-authored),\n // and finish only when they tap the CTA.\n if (isTerminal) {\n const props = (response.props ?? {}) as {\n title?: string;\n message?: string;\n ctaLabel?: string;\n };\n return (\n <OnboardingScaffold step={step} complete approxScreens={total}>\n <CompletionView\n title={props.title ?? c.completeTitle}\n message={props.message}\n ctaLabel={props.ctaLabel ?? c.completeCta}\n onContinue={handleFinish}\n />\n </OnboardingScaffold>\n );\n }\n\n const overrides: Record<string, unknown> = {\n ...wrappedActions(lastCard.id),\n // Inject the inline error onto whichever card supports it (TextInputCard).\n validationError,\n // Choice cards (Selection/ChipSelect) call this as the live selection changes, so the flow\n // can prefetch the next turn before Continue. Non-committing; ignored by cards that don't use it.\n onSelectionChange: previewOnSelect,\n };\n\n return (\n <OnboardingScaffold\n step={step}\n onSkip={progress.skippable ? skipQuestion : undefined}\n approxScreens={total}\n >\n {/* CardHandoff pairs the exit with the enter (the design's \"cards hand off,\n they don't cut\"): the answered card leaves left while the next arrives\n from the right; loader states enter/exit as a short fade. transitionKey\n identifies WHAT is on screen — loader states get a stable key per state,\n cards key on the message id. */}\n <CardHandoff\n transitionKey={validating ? \"loader:checking\" : isLoading ? \"loader:thinking\" : lastCard.id}\n variant={\n validating || isLoading\n ? \"fade\"\n : lastCard.response?.component === \"InterstitialCard\"\n ? \"spring\"\n : \"slide\"\n }\n >\n {validating ? (\n <LoadingBlock title={c.checkingTitle} hint={c.checkingHint} />\n ) : isLoading ? (\n // Between turns: the answer was sent and we're waiting on the next card.\n // Show the \"thinking\" loader instead of leaving the old card on screen.\n <LoadingBlock title={c.thinkingTitle} hint={c.thinkingHint} />\n ) : (\n // key={lastCard.id} is load-bearing: cards (SelectionCard/ChipSelectCard)\n // hold internal `selected`/`submitted` state, and React reuses a component\n // instance across turns when the rendered type is identical (e.g. two\n // SelectionCards in a row). Without a per-turn key the second card inherits\n // the first's `submitted=true` and silently rejects all taps. Keying on the\n // message id forces a fresh mount every turn. (CardHandoff's transitionKey\n // shares the id, but this renderer key stays the state-isolation guarantee.)\n <ComponentRenderer\n key={lastCard.id}\n messageId={lastCard.id}\n response={response}\n callbackOverrides={overrides as never}\n />\n )}\n </CardHandoff>\n </OnboardingScaffold>\n );\n};\n","/**\n * Themed ChipSelectCard — drop-in replacement for the OSS SDK's ChipSelectCard.\n * Identical `name`, `propsSchema`, `defaultProps`, and `onSelect` callback contract\n * so the SDK's ComponentRenderer drives it transparently. Only the look is themed.\n *\n * Motion (design-refs/EXTRACTED-SPEC.md rows 4-6): chips tick on press (scale\n * 0.94 spring), the selected accent fill crossfades in over 160ms (native-driver\n * opacity overlay) with the label flipping to `onPrimary` and a check popping in.\n * Deselect reverses. Reduce motion: color swap only, check shown instantly.\n */\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, Pressable, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { captionStyle } from \"../theme/typography\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\nimport {\n CHECK_SCALE_FROM,\n CHECK_SPRING,\n CHIP_FILL_MS,\n CHIP_PRESS_SCALE,\n PRESS_SPRING,\n WIRE_BEZIER,\n scaledMs,\n stateChangeDuration,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\n\n// Mirror of the SDK schema — must stay identical so the registry + validator agree.\nconst schema = z.object({\n title: z.string().describe(\"Question or section header, e.g. 'Which season?'\"),\n chips: z\n .array(z.string())\n .min(1)\n .describe(\"List of option labels shown as chips, e.g. ['Spring','Summer','Autumn','Winter']\"),\n multiSelect: z.boolean().optional().describe(\"Allow multiple chips selected at once, default true\"),\n submitLabel: z.string().optional().describe(\"Confirm button label, default: Continue\"),\n maxSelections: z.number().optional().describe(\"Maximum number of chips the user can select at once\"),\n});\n\ntype Props = z.infer<typeof schema> &\n InjectedProps & {\n onSelect?: (selected: string | string[]) => void;\n /** Fires as the live selection changes (before Continue), so the flow can prefetch the\n * next turn. Same value shape as onSelect. Optional — injected by OnboardingFlow. */\n onSelectionChange?: (selected: string | string[]) => void;\n };\n\ntype ChipItemProps = {\n chip: string;\n isSelected: boolean;\n multiSelect: boolean;\n onToggle: (chip: string) => void;\n};\n\nconst _ChipItem: React.FC<ChipItemProps> = ({ chip, isSelected, multiSelect, onToggle }) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const handlePress = useCallback(() => onToggle(chip), [chip, onToggle]);\n\n // Press tick: scale 1→0.94, spring, native driver. Skipped under reduce motion.\n const pressScale = useRef(new Animated.Value(1)).current;\n const pressTo = useCallback(\n (to: number) => {\n if (reduced) return;\n Animated.spring(pressScale, {\n toValue: to,\n friction: PRESS_SPRING.friction,\n tension: PRESS_SPRING.tension,\n useNativeDriver: true,\n }).start();\n },\n [pressScale, reduced],\n );\n const handlePressIn = useCallback(() => pressTo(CHIP_PRESS_SCALE), [pressTo]);\n const handlePressOut = useCallback(() => pressTo(1), [pressTo]);\n\n // Selected fill: full accent pill, crossfaded in over 160ms on a native-driver\n // opacity overlay (EXTRACTED-SPEC.md D7). Reduce motion: instant swap.\n const fillT = useRef(new Animated.Value(isSelected ? 1 : 0)).current;\n useEffect(() => {\n const anim = Animated.timing(fillT, {\n toValue: isSelected ? 1 : 0,\n duration: scaledMs(stateChangeDuration(reduced, CHIP_FILL_MS)),\n easing: easeWire,\n useNativeDriver: true,\n });\n anim.start();\n return () => anim.stop();\n }, [isSelected, reduced, fillT]);\n\n // Check pop on select (the width-slide of the canvas is a layout animation the\n // native driver can't express — see EXTRACTED-SPEC.md D4).\n const checkT = useRef(new Animated.Value(isSelected ? 1 : 0)).current;\n useEffect(() => {\n if (!isSelected) {\n checkT.setValue(0);\n return;\n }\n if (reduced) {\n checkT.setValue(1);\n return;\n }\n checkT.setValue(0);\n const anim = Animated.spring(checkT, {\n toValue: 1,\n friction: CHECK_SPRING.friction,\n tension: CHECK_SPRING.tension,\n useNativeDriver: true,\n });\n anim.start();\n return () => anim.stop();\n }, [isSelected, reduced, checkT]);\n\n const checkScale = checkT.interpolate({ inputRange: [0, 1], outputRange: [CHECK_SCALE_FROM, 1] });\n\n return (\n <Pressable\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n accessibilityRole={multiSelect ? \"checkbox\" : \"radio\"}\n accessibilityState={multiSelect ? { checked: isSelected } : { selected: isSelected }}\n accessibilityLabel={chip}\n >\n <Animated.View\n style={[\n styles.chip,\n {\n borderRadius: t.radius.full,\n paddingHorizontal: t.spacing.md,\n paddingVertical: t.spacing.sm,\n borderColor: t.colors.border,\n backgroundColor: t.colors.background,\n transform: [{ scale: pressScale }],\n },\n ]}\n >\n <Animated.View\n pointerEvents=\"none\"\n style={[\n StyleSheet.absoluteFill,\n styles.fillOverlay,\n {\n borderRadius: t.radius.full,\n borderColor: t.colors.primary,\n backgroundColor: t.colors.primary,\n opacity: fillT,\n },\n ]}\n />\n {isSelected ? (\n <Animated.Text\n style={[\n styles.check,\n { color: t.colors.onPrimary, opacity: checkT, transform: [{ scale: checkScale }] },\n ]}\n >\n ✓\n </Animated.Text>\n ) : null}\n <Text\n style={[\n captionStyle(t.fonts),\n styles.chipLabel,\n { color: isSelected ? t.colors.onPrimary : t.colors.textMuted },\n ]}\n >\n {chip}\n </Text>\n </Animated.View>\n </Pressable>\n );\n};\nconst ChipItem = React.memo(_ChipItem);\n\nconst _ChipSelectCard: React.FC<Props> = ({\n title,\n chips,\n multiSelect = true,\n submitLabel = \"Continue\",\n maxSelections,\n onSelect,\n onSelectionChange,\n}) => {\n const t = useOnboardingTheme();\n const [selected, setSelected] = useState<string[]>([]);\n const [submitted, setSubmitted] = useState(false);\n\n // Report the settled selection upward (before Continue) so the flow can prefetch the next\n // turn. Debouncing lives in the flow; here we just emit on every change once something's picked.\n useEffect(() => {\n if (!submitted && selected.length) onSelectionChange?.(multiSelect ? selected : selected[0]!);\n }, [selected, submitted, multiSelect, onSelectionChange]);\n\n const toggle = useCallback(\n (chip: string) => {\n if (submitted) return;\n if (multiSelect) {\n setSelected((prev) => {\n if (prev.includes(chip)) return prev.filter((c) => c !== chip);\n if (maxSelections && prev.length >= maxSelections) return prev;\n return [...prev, chip];\n });\n } else {\n setSelected([chip]);\n }\n },\n [submitted, multiSelect, maxSelections],\n );\n\n const handleSubmit = useCallback(() => {\n if (!selected.length || !onSelect || submitted) return;\n setSubmitted(true);\n onSelect(multiSelect ? selected : selected[0]!);\n }, [selected, onSelect, submitted, multiSelect]);\n\n return (\n <CardLayout\n title={title}\n subtitle={maxSelections ? `Select up to ${maxSelections}` : undefined}\n footer={\n <Button\n title={submitLabel}\n onPress={handleSubmit}\n variant=\"primary\"\n disabled={selected.length === 0 || submitted}\n />\n }\n >\n <View style={[styles.chipsRow, { gap: t.spacing.sm + t.spacing.xs }]}>\n {chips.map((chip) => (\n <ChipItem\n key={chip}\n chip={chip}\n isSelected={selected.includes(chip)}\n multiSelect={multiSelect}\n onToggle={toggle}\n />\n ))}\n </View>\n </CardLayout>\n );\n};\n\nexport const ChipSelectCard: WireAIComponent = {\n name: \"ChipSelectCard\",\n description:\n \"Use for compact short labels: seasons, activities, travel styles, moods, categories. Ideal for 4–12 single-word or two-word options. Use SelectionCard instead when options need descriptions; use CardGridSelectCard for a smaller set (2–6) of visual choices that each deserve an icon.\",\n component: React.memo(_ChipSelectCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n defaultProps: { multiSelect: true, submitLabel: \"Continue\" },\n};\n\nconst styles = StyleSheet.create({\n chipsRow: { flexDirection: \"row\", flexWrap: \"wrap\" },\n chip: { borderWidth: 1.5, flexDirection: \"row\", alignItems: \"center\", gap: 6, overflow: \"hidden\" },\n fillOverlay: { borderWidth: 1.5 },\n chipLabel: { fontWeight: \"600\" },\n check: { fontSize: 13, fontWeight: \"800\", lineHeight: 15 },\n});\n","/**\n * Themed TextInputCard — drop-in for the OSS SDK's TextInputCard. Same `name`,\n * `propsSchema`, `defaultProps`, and `onSubmit(value: string)` contract. The input\n * is themed and supports an optional inline error string (used by the kit's\n * per-step validators — e.g. \"username taken\"), set via the `validationError` prop\n * which the OnboardingFlow injects through callbackOverrides.\n *\n * Open-ended answers (goals, notes, \"what would make this better\") render a tall\n * multi-line box by default so the user has room to actually write. Short fields\n * (a name, a username) set `multiline: false` for the compact single-line height.\n */\nimport React, { useCallback, useMemo, useState } from \"react\";\nimport { StyleSheet, Text, TextInput, View, useWindowDimensions } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport type { OnboardingTheme } from \"../theme/types\";\nimport { bodyStyle, captionStyle } from \"../theme/typography\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\n\nconst schema = z.object({\n label: z.string().describe(\"Input field label / the question being asked\"),\n hint: z\n .string()\n .optional()\n .describe(\n \"One short line under the question giving context: what the answer is used for or why you ask. Add it whenever the question alone might be unclear.\"\n ),\n placeholder: z\n .string()\n .optional()\n .describe(\n 'A concrete example answer shown inside the box, phrased like a real user wrote it and starting with \"e.g. \". ALWAYS provide one for open-ended questions: it shows the expected answer shape and inspires the user.'\n ),\n submitLabel: z.string().optional().describe(\"Submit button label, default: Submit\"),\n multiline: z\n .boolean()\n .optional()\n .describe(\n \"Tall multi-line box for open-ended answers (goals, notes, feedback). Default true. Set false for a single-line field like a name or username.\"\n ),\n lines: z\n .number()\n .optional()\n .describe(\"Approx visible rows when multiline (default 6). Height is capped at 40% of the screen.\"),\n});\n\ntype Props = z.infer<typeof schema> &\n InjectedProps & {\n onSubmit?: (value: string) => void;\n /**\n * Inline error injected by OnboardingFlow when a validator rejects the value\n * (e.g. username already taken). Re-enables the input so the user can edit.\n */\n validationError?: string;\n };\n\nconst _TextInputCard: React.FC<Props> = ({\n label,\n hint,\n placeholder,\n submitLabel = \"Submit\",\n onSubmit,\n validationError,\n multiline = true,\n lines = 6,\n}) => {\n const t = useOnboardingTheme();\n const styles = useMemo(() => makeStyles(t), [t]);\n const { height: screenHeight } = useWindowDimensions();\n const [value, setValue] = useState(\"\");\n const [submitted, setSubmitted] = useState(false);\n\n // A validator rejection arrives as `validationError`; reopen the field so the\n // user can fix their answer instead of being stuck on a submitted state.\n const locked = submitted && !validationError;\n\n // Multi-line free-text gets a generous box (~`lines` rows), capped at 40% of\n // screen height so it stays comfortable on small devices. Single-line fields\n // keep the compact 52pt height.\n const APPROX_ROW_HEIGHT = 26;\n const minHeight = multiline\n ? Math.min(Math.max(lines, 4) * APPROX_ROW_HEIGHT + t.spacing.md * 2, screenHeight * 0.4)\n : 52;\n\n const handleSubmit = useCallback(() => {\n if (value.trim() && onSubmit && !locked) {\n setSubmitted(true);\n onSubmit(value.trim());\n }\n }, [value, onSubmit, locked]);\n\n return (\n <CardLayout\n title={label}\n subtitle={hint}\n footer={\n <Button\n title={submitLabel}\n onPress={handleSubmit}\n variant=\"primary\"\n disabled={!value.trim() || locked}\n />\n }\n >\n <View style={styles.row}>\n <TextInput\n value={value}\n onChangeText={setValue}\n placeholder={placeholder ?? \"\"}\n placeholderTextColor={t.colors.textMuted}\n editable={!locked}\n multiline={multiline}\n numberOfLines={multiline ? lines : 1}\n textAlignVertical={multiline ? \"top\" : \"center\"}\n style={[\n bodyStyle(t.fonts),\n styles.input,\n {\n color: t.colors.text,\n backgroundColor: t.colors.surface,\n borderRadius: t.radius.md,\n borderColor: validationError ? t.colors.error : t.colors.border,\n padding: t.spacing.md,\n minHeight,\n },\n ]}\n />\n {validationError ? (\n <Text style={[captionStyle(t.fonts), { color: t.colors.error }]}>{validationError}</Text>\n ) : null}\n </View>\n </CardLayout>\n );\n};\n\nexport const TextInputCard: WireAIComponent = {\n name: \"TextInputCard\",\n description:\n \"Use when the user needs to type a free-text answer: an open-ended goal, notes, feedback, a name, a destination, a search query. Multi-line by default (great for open-ended goals); set multiline:false for a short single-line field like a name. Use NumberStepperCard for numeric ranges with known bounds.\",\n component: React.memo(_TextInputCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n defaultProps: { submitLabel: \"Submit\", multiline: true, lines: 6 },\n};\n\nfunction makeStyles(t: OnboardingTheme) {\n return StyleSheet.create({\n row: { gap: t.spacing.sm },\n input: { borderWidth: 1 },\n });\n}\n","/**\n * expoIcons — resolve an `@expo/vector-icons` family, lazily and optionally.\n *\n * ── WHY THIS DOES NOT BREAK THE NO-NATIVE-DEPENDENCY POLICY ──────────────────────────────\n *\n * The policy (see `questionnaire/QuestionnaireGate.tsx`'s back-chevron note, `AnimatedSparkle`,\n * `coachmarks/GestureHint`, `cards/StatusCard`'s Unicode STATUS_ICONS) says: no vector library\n * is worth FORCING EVERY HOST INTO A NATIVE REBUILD. Read it precisely — what it forbids is\n * forcing hosts, not the existence of an icon.\n *\n * `@expo/vector-icons` is an OPTIONAL peer:\n *\n * • A host WITHOUT it installs the kit fine (optional peer → npm never fetches it) and renders\n * fine (icon → null, layout unchanged). To BUNDLE fine it must let Metro know the module is\n * allowed to be missing — see \"OPTIONALITY IS A BUILD-TIME CONTRACT\" below.\n * • A host WITH it gets real brand icons. Both live host apps already ship it\n * (`@expo/vector-icons ^15.0.3`), so neither needs a rebuild — which matters because\n * neither can be force-updated: both ship new store builds only and never OTA.\n * • A host that wants neither can override every name with its own artwork through the\n * `icons` registry, so the library is never on the critical path at all.\n *\n * ── THE SPECIFIER MUST BE A STRING LITERAL — THIS IS THE WHOLE BUG ───────────────────────\n *\n * DO NOT \"restore\" the old `const req = require; req(moduleName)` shape. It could never work,\n * and it shipped broken in 0.8.0. What that shape actually did, proven in a real `expo export`\n * bundle and in Expo SDK 55's runtime:\n *\n * 1. Metro collects dependencies STATICALLY, by matching a call whose callee is literally the\n * identifier `require` and whose argument is a STRING LITERAL. Aliasing `require` to a local\n * hid the call from the collector, so this module's dependencyMap was emitted EMPTY (`[]`)\n * and `@expo/vector-icons` was never put in the bundle at all.\n * 2. At runtime the alias did NOT point at Node's `require`. Metro renames the free `require`\n * identifier to the module factory's require param, so `req` WAS `metroRequire`, whose\n * module registry is keyed by NUMERIC module ids. Handing it the string \"@expo/vector-icons\"\n * could never match a key, so it threw `Requiring unknown module \"@expo/vector-icons\"` —\n * even in a bundle that contained the module.\n * 3. That throw never reached the `catch` below. Metro's own `guardedLoadModule` wraps the\n * load, catches the error FIRST, and routes it to `global.ErrorUtils.reportFatalError(e)`\n * instead of rethrowing (Expo SDK 55: `@expo/cli/build/metro-require/require.js:151-165`).\n * So the call returned `undefined` — icon silently null — AND logged a red fatal error. A\n * try/catch cannot guard a require that Metro never lets throw.\n *\n * A LITERAL `require(\"@expo/vector-icons\")` is collected, is bundled, and resolves SYNCHRONOUSLY\n * through the numeric dependencyMap — the same reason `reviews/storeReview.ts`'s literal\n * `await import(\"expo-store-review\")` has always worked. (The old comment here claimed the alias\n * worked \"exactly like expo-store-review\". It was the opposite: storeReview's specifier is a\n * literal, and that is precisely why it resolves and this one did not.)\n *\n * ── OPTIONALITY IS A BUILD-TIME CONTRACT, AND THE TRY/CATCH IS LOAD-BEARING ──────────────\n *\n * Metro has NO runtime resolution: every specifier is resolved when the bundle is built. It does\n * have a real optional-dependency mechanism, and it needs BOTH halves of what is written below:\n * a LITERAL specifier (so the dep is collected at all) AND the call inside a TRY/CATCH — that is\n * literally how Metro marks a dependency `isOptional`. When the peer is absent, Metro then puts\n * `null` in this module's dependencyMap and `metroRequire(null, \"@expo/vector-icons\")` throws\n * \"Cannot find module\" from its own `moduleId === null` branch, BEFORE `guardedLoadModule` — so\n * unlike the string-id path in the autopsy above, that throw really does land in the catch below.\n * So do NOT \"simplify\" the try/catch away: it is what keeps the peer optional, not just tidy.\n *\n * That mechanism rides on the transformer's `allowOptionalDependencies`, which Expo enables by\n * default but bare `metro-config` defaults to FALSE. For hosts in the second camp, the kit ships\n * a safety net: `withWireOnboarding` (metro/index.js) installs a `resolveRequest` that maps an\n * absent optional peer to an EMPTY module, landing on exactly the degradation path below (no\n * families on the namespace → `undefined` → icon renders null).\n */\nimport type { WireIconFamily } from \"./vocabulary\";\n\n// Metro injects a module-scoped `require`; it is ABSENT in a pure-ESM runtime (the kit's own\n// tests run under `node --test` as ESM). Declared locally so this type-checks without ambient\n// Node types; the `typeof` guard keeps the reference ESM-safe.\ndeclare const require: ((id: string) => unknown) | undefined;\n\n/** A `require`-like resolver. Injectable in tests; production uses the guarded literal require. */\nexport type OptionalRequire = (moduleName: string) => unknown;\n\n/**\n * The minimal shape the kit uses from a vector-icons family. A COMPONENT TYPE, not a plain\n * function: these are real React components (createIconSet output) and must be mounted via\n * JSX/createElement, never invoked directly — calling one bypasses the reconciler and breaks\n * the moment the family uses hooks or is a class.\n */\nexport type IconComponent = import(\"react\").ComponentType<{\n name: string;\n size?: number;\n color?: string;\n allowFontScaling?: boolean;\n}>;\n\n/**\n * The production resolver. The specifier is a LITERAL so Metro collects it (see the header); the\n * `moduleName` parameter exists only to keep the `OptionalRequire` seam shape, so anything other\n * than the one module this file owns resolves to undefined.\n */\nconst runtimeRequire: OptionalRequire = (moduleName) => {\n if (moduleName !== \"@expo/vector-icons\") return undefined;\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"@expo/vector-icons\");\n } catch {\n return undefined;\n }\n};\n\n/** Read a module's `default` (Expo modules are consumed as default exports) or the namespace. */\nconst interop = (mod: unknown): Record<string, unknown> | undefined => {\n if (!mod || typeof mod !== \"object\") return undefined;\n const def = (mod as { default?: unknown }).default;\n // `@expo/vector-icons` exposes the families as NAMED exports; prefer the namespace when it\n // already carries them, and only fall back to `default` for a CJS-interop wrapper.\n const ns = mod as Record<string, unknown>;\n if (ns.MaterialCommunityIcons || ns.Ionicons) return ns;\n if (def && typeof def === \"object\") return def as Record<string, unknown>;\n return ns;\n};\n\n/**\n * Narrow an unknown export to something mountable. A vector-icons family is either a function\n * component or a class (`createIconSet` has returned both across versions), and React.memo /\n * forwardRef wrappers are objects — so accept an object carrying a `$$typeof` too, and reject\n * anything else rather than handing the reconciler a non-component.\n */\nconst asComponent = (value: unknown): IconComponent | undefined => {\n if (typeof value === \"function\") return value as IconComponent;\n if (value && typeof value === \"object\" && \"$$typeof\" in (value as object)) {\n return value as IconComponent;\n }\n return undefined;\n};\n\n/**\n * Module-level memo. `null` = \"we looked and it is not there\" (distinct from \"not looked yet\"),\n * so an absent peer costs exactly one failed require per process, not one per rendered icon.\n */\nlet cached: Record<string, unknown> | null | undefined;\n\n/** Reset the memo. TEST-ONLY seam — production never calls it. */\nexport const resetIconModuleCache = (): void => {\n cached = undefined;\n};\n\n/**\n * Resolve one icon family component, or undefined when the peer is absent/unresolvable.\n * Never throws: an icon is decorative, so it must never be able to break a card.\n *\n * `requireModule` is injectable so tests can exercise BOTH the found and absent paths without\n * installing the native peer (same convention as `detectAppVersion`).\n */\nexport const resolveIconFamily = (\n family: WireIconFamily,\n requireModule: OptionalRequire = runtimeRequire,\n): IconComponent | undefined => {\n try {\n if (cached === undefined || requireModule !== runtimeRequire) {\n const resolved = interop(requireModule(\"@expo/vector-icons\"));\n // Don't poison the module memo from an injected test require.\n if (requireModule === runtimeRequire) cached = resolved ?? null;\n if (!resolved) return undefined;\n return asComponent(resolved[family]);\n }\n if (cached === null) return undefined;\n return asComponent(cached[family]);\n } catch {\n return undefined;\n }\n};\n","/**\n * The Wire icon VOCABULARY — the stable, semantic contract between the AI and the kit.\n *\n * The model emits a plain semantic string (`\"instagram\"`, `\"friend\"`, `\"wedding\"`), never a\n * raw icon-library glyph name. That indirection is the whole point:\n *\n * • The model is never coupled to a library version. `@expo/vector-icons` renaming a glyph,\n * or a host swapping the library out for brand SVGs, changes THIS map — not the prompt,\n * not the server, and not a single stored answer.\n * • A host can override any name with its own artwork (see `IconRegistry`), so brand icons\n * need no kit change.\n * • An unknown name degrades to no icon (see `WireIcon`), which is why the vocabulary can\n * grow without a coordinated kit+server release.\n *\n * `WIRE_ICON_NAMES` is exported so the server/AI side can be taught the list verbatim — paste\n * it into the prompt as the allowed `icon` values. Keep names SEMANTIC (what the option means)\n * rather than visual (what the glyph looks like): the model reasons about meaning.\n *\n * Every glyph below was verified to exist in the `@expo/vector-icons` 15.0.3 glyphmaps that\n * both live host apps already ship. MaterialCommunityIcons is the default family (the broadest\n * single set); Ionicons covers the few brand logos MCI lacks (TikTok, Discord).\n */\n\n/** The icon families this kit resolves out of `@expo/vector-icons`. Both are root exports. */\nexport type WireIconFamily = \"MaterialCommunityIcons\" | \"Ionicons\";\n\n/** One vocabulary entry: the concrete glyph a semantic name resolves to. */\nexport interface WireIconGlyph {\n family: WireIconFamily;\n /** The library's own glyph name — an INTERNAL detail. The AI never sees or emits this. */\n name: string;\n}\n\n/**\n * The semantic name → concrete glyph map. Grouped by the onboarding questions these actually\n * serve: acquisition channels (\"where did you hear about us\"), intent/occasion (\"what brings\n * you here\"), and a general-purpose set for everything else.\n */\nexport const WIRE_ICON_GLYPHS = {\n // ── Acquisition channels (\"where did you hear about us?\") ──────────────────\n instagram: { family: \"MaterialCommunityIcons\", name: \"instagram\" },\n tiktok: { family: \"Ionicons\", name: \"logo-tiktok\" },\n youtube: { family: \"MaterialCommunityIcons\", name: \"youtube\" },\n facebook: { family: \"MaterialCommunityIcons\", name: \"facebook\" },\n twitter: { family: \"MaterialCommunityIcons\", name: \"twitter\" },\n reddit: { family: \"MaterialCommunityIcons\", name: \"reddit\" },\n linkedin: { family: \"MaterialCommunityIcons\", name: \"linkedin\" },\n discord: { family: \"Ionicons\", name: \"logo-discord\" },\n whatsapp: { family: \"MaterialCommunityIcons\", name: \"whatsapp\" },\n twitch: { family: \"MaterialCommunityIcons\", name: \"twitch\" },\n snapchat: { family: \"MaterialCommunityIcons\", name: \"snapchat\" },\n pinterest: { family: \"MaterialCommunityIcons\", name: \"pinterest\" },\n google: { family: \"MaterialCommunityIcons\", name: \"google\" },\n search: { family: \"MaterialCommunityIcons\", name: \"magnify\" },\n friend: { family: \"MaterialCommunityIcons\", name: \"account-heart\" },\n podcast: { family: \"MaterialCommunityIcons\", name: \"podcast\" },\n blog: { family: \"MaterialCommunityIcons\", name: \"post\" },\n newsletter: { family: \"MaterialCommunityIcons\", name: \"email-outline\" },\n news: { family: \"MaterialCommunityIcons\", name: \"newspaper\" },\n \"app-store\": { family: \"MaterialCommunityIcons\", name: \"apple\" },\n ad: { family: \"MaterialCommunityIcons\", name: \"bullhorn\" },\n\n // ── Intent / occasion (\"what brings you here?\") ────────────────────────────\n wedding: { family: \"MaterialCommunityIcons\", name: \"ring\" },\n birthday: { family: \"MaterialCommunityIcons\", name: \"cake-variant\" },\n baby: { family: \"MaterialCommunityIcons\", name: \"baby-carriage\" },\n travel: { family: \"MaterialCommunityIcons\", name: \"airplane\" },\n work: { family: \"MaterialCommunityIcons\", name: \"briefcase\" },\n celebration: { family: \"MaterialCommunityIcons\", name: \"party-popper\" },\n store: { family: \"MaterialCommunityIcons\", name: \"storefront\" },\n school: { family: \"MaterialCommunityIcons\", name: \"school\" },\n team: { family: \"MaterialCommunityIcons\", name: \"account-multiple\" },\n growth: { family: \"MaterialCommunityIcons\", name: \"trending-up\" },\n\n // ── General purpose ────────────────────────────────────────────────────────\n sparkle: { family: \"MaterialCommunityIcons\", name: \"star-four-points\" },\n heart: { family: \"MaterialCommunityIcons\", name: \"heart\" },\n star: { family: \"MaterialCommunityIcons\", name: \"star\" },\n fire: { family: \"MaterialCommunityIcons\", name: \"fire\" },\n target: { family: \"MaterialCommunityIcons\", name: \"target\" },\n trophy: { family: \"MaterialCommunityIcons\", name: \"trophy\" },\n rocket: { family: \"MaterialCommunityIcons\", name: \"rocket-launch\" },\n clock: { family: \"MaterialCommunityIcons\", name: \"clock-outline\" },\n calendar: { family: \"MaterialCommunityIcons\", name: \"calendar-star\" },\n camera: { family: \"MaterialCommunityIcons\", name: \"camera\" },\n image: { family: \"MaterialCommunityIcons\", name: \"image\" },\n video: { family: \"MaterialCommunityIcons\", name: \"video\" },\n mic: { family: \"MaterialCommunityIcons\", name: \"microphone\" },\n music: { family: \"MaterialCommunityIcons\", name: \"music\" },\n book: { family: \"MaterialCommunityIcons\", name: \"book-open-variant\" },\n food: { family: \"MaterialCommunityIcons\", name: \"silverware-fork-knife\" },\n coffee: { family: \"MaterialCommunityIcons\", name: \"coffee\" },\n fitness: { family: \"MaterialCommunityIcons\", name: \"dumbbell\" },\n health: { family: \"MaterialCommunityIcons\", name: \"heart-pulse\" },\n meditation: { family: \"MaterialCommunityIcons\", name: \"meditation\" },\n sleep: { family: \"MaterialCommunityIcons\", name: \"sleep\" },\n brain: { family: \"MaterialCommunityIcons\", name: \"brain\" },\n idea: { family: \"MaterialCommunityIcons\", name: \"lightbulb-on\" },\n money: { family: \"MaterialCommunityIcons\", name: \"cash\" },\n shopping: { family: \"MaterialCommunityIcons\", name: \"cart\" },\n gift: { family: \"MaterialCommunityIcons\", name: \"gift\" },\n home: { family: \"MaterialCommunityIcons\", name: \"home\" },\n car: { family: \"MaterialCommunityIcons\", name: \"car\" },\n pet: { family: \"MaterialCommunityIcons\", name: \"paw\" },\n plant: { family: \"MaterialCommunityIcons\", name: \"sprout\" },\n sun: { family: \"MaterialCommunityIcons\", name: \"white-balance-sunny\" },\n moon: { family: \"MaterialCommunityIcons\", name: \"weather-night\" },\n globe: { family: \"MaterialCommunityIcons\", name: \"earth\" },\n \"map-pin\": { family: \"MaterialCommunityIcons\", name: \"map-marker\" },\n compass: { family: \"MaterialCommunityIcons\", name: \"compass\" },\n flag: { family: \"MaterialCommunityIcons\", name: \"flag\" },\n bookmark: { family: \"MaterialCommunityIcons\", name: \"bookmark\" },\n bell: { family: \"MaterialCommunityIcons\", name: \"bell\" },\n mail: { family: \"MaterialCommunityIcons\", name: \"email\" },\n phone: { family: \"MaterialCommunityIcons\", name: \"phone\" },\n chat: { family: \"MaterialCommunityIcons\", name: \"chat\" },\n user: { family: \"MaterialCommunityIcons\", name: \"account\" },\n users: { family: \"MaterialCommunityIcons\", name: \"account-group\" },\n settings: { family: \"MaterialCommunityIcons\", name: \"cog\" },\n tools: { family: \"MaterialCommunityIcons\", name: \"tools\" },\n puzzle: { family: \"MaterialCommunityIcons\", name: \"puzzle\" },\n chart: { family: \"MaterialCommunityIcons\", name: \"chart-line\" },\n shield: { family: \"MaterialCommunityIcons\", name: \"shield-check\" },\n lock: { family: \"MaterialCommunityIcons\", name: \"lock\" },\n cloud: { family: \"MaterialCommunityIcons\", name: \"cloud\" },\n pencil: { family: \"MaterialCommunityIcons\", name: \"pencil\" },\n check: { family: \"MaterialCommunityIcons\", name: \"check-circle\" },\n plus: { family: \"MaterialCommunityIcons\", name: \"plus-circle\" },\n question: { family: \"MaterialCommunityIcons\", name: \"help-circle\" },\n other: { family: \"MaterialCommunityIcons\", name: \"dots-horizontal-circle\" },\n} as const satisfies Record<string, WireIconGlyph>;\n\n/** A name in the vocabulary. The card schemas accept any string and degrade — see `WireIcon`. */\nexport type WireIconName = keyof typeof WIRE_ICON_GLYPHS;\n\n/**\n * Every semantic name, as a plain array — the list to paste into the server/AI prompt as the\n * allowed `icon` values. Sorted for a stable, diffable prompt.\n */\nexport const WIRE_ICON_NAMES: readonly string[] = Object.keys(WIRE_ICON_GLYPHS).sort();\n\n/**\n * Look up a semantic name. Returns undefined for anything outside the vocabulary.\n *\n * The OWN-property check is load-bearing, not defensive noise: the name comes from an LLM, and\n * a plain object lookup answers `\"toString\"` / `\"constructor\"` / `\"valueOf\"` with an inherited\n * `Object.prototype` member. That would hand back a function where a `{family, name}` is\n * expected — a non-glyph masquerading as one. Caught by the vocabulary canary.\n */\nexport const lookupIconGlyph = (name: string | undefined): WireIconGlyph | undefined => {\n if (!name) return undefined;\n if (!Object.prototype.hasOwnProperty.call(WIRE_ICON_GLYPHS, name)) return undefined;\n return (WIRE_ICON_GLYPHS as Record<string, WireIconGlyph>)[name];\n};\n","/**\n * WireIcon — render one semantic icon name, or nothing at all.\n *\n * RESOLUTION ORDER (each step falls through to the next, never throws):\n * 1. the host `icons` registry — brand artwork, zero kit deps (IconRegistry.tsx)\n * 2. `@expo/vector-icons` — if the optional peer resolves (expoIcons.ts)\n * 3. NOTHING — render null\n *\n * Step 3 is a FEATURE, not a failure mode. The AI emits icon names from a vocabulary that will\n * keep growing, against production apps that ship on their own schedule (new store builds only,\n * never OTA, so they cannot be force-updated). So an unknown, misspelled, hallucinated, or\n * simply newer-than-this-client name MUST be a no-op: no crash, no broken-glyph tofu box, and\n * no layout shift. Returning `null` (rather than a spacer or a placeholder) is what gives the\n * last property — a row with an unresolvable icon lays out EXACTLY like a row with no icon,\n * because the parent's flex `gap` adds no space for a null child.\n *\n * An icon is always DECORATIVE: the label carries the meaning, so the icon is hidden from\n * assistive tech and never becomes the accessible name of its option.\n */\nimport React from \"react\";\nimport { StyleSheet, View } from \"react-native\";\n\nimport { resolveIconFamily, type OptionalRequire } from \"./expoIcons\";\nimport { useHostIcon } from \"./IconRegistry\";\nimport { lookupIconGlyph } from \"./vocabulary\";\n\nexport type WireIconProps = {\n /** A semantic name from the vocabulary (see vocabulary.ts). Unknown → renders nothing. */\n name?: string;\n /** Glyph size in px. */\n size?: number;\n /** Glyph color. Callers pass a THEME token — never a raw hex. */\n color?: string;\n /** Injectable resolver. TEST-ONLY seam; production uses the guarded runtime require. */\n requireModule?: OptionalRequire;\n};\n\nconst _WireIcon: React.FC<WireIconProps> = ({ name, size = 20, color, requireModule }) => {\n // 1) Host artwork wins — it can also cover names outside the vocabulary entirely.\n const hostIcon = useHostIcon(name);\n if (hostIcon) {\n return (\n <View\n style={styles.decorative}\n accessible={false}\n importantForAccessibility=\"no-hide-descendants\"\n >\n {hostIcon}\n </View>\n );\n }\n\n // 2) The vocabulary → a concrete glyph, then the optional peer. Both may miss; both degrade.\n const glyph = lookupIconGlyph(name);\n if (!glyph) return null;\n\n const Family = resolveIconFamily(glyph.family, requireModule);\n if (!Family) return null;\n\n return (\n <View\n style={styles.decorative}\n accessible={false}\n importantForAccessibility=\"no-hide-descendants\"\n >\n <Family\n name={glyph.name}\n size={size}\n color={color}\n // Icons are sized by the layout, not the text scale — a large accessibility font must\n // not blow up a card grid. The LABEL still scales, which is what carries the meaning.\n allowFontScaling={false}\n />\n </View>\n );\n};\n\nexport const WireIcon = React.memo(_WireIcon);\nWireIcon.displayName = \"WireIcon\";\n\nconst styles = StyleSheet.create({\n // No size/margin of its own: the glyph decides its footprint, so an absent icon and a\n // present one differ by exactly the glyph — never by a wrapper.\n decorative: {},\n});\n","/**\n * The shared option shape for the choice cards (SelectionCard, CardGridSelectCard).\n *\n * ── BACK-COMPAT, IN BOTH DIRECTIONS (the hard gate) ──────────────────────────────────────\n *\n * NEW option → OLD kit: `z.object` STRIPS unknown keys, and the SDK renderer mounts\n * `parsed.data` (not the raw props — see wireai-rn `renderer/ComponentRenderer.tsx`). So a\n * client on kit 0.7.x that receives `{value, label, icon}` silently drops `icon` and renders\n * the plain row it always did. No throw, no fallback card. This is what makes it safe to teach\n * the server `icon` before every host has re-pinned — and it MUST stay true, so never make\n * this schema `.strict()`.\n *\n * OLD option → NEW kit: the `preprocess` still coerces a bare `\"Spring\"` into\n * `{value:\"Spring\", label:\"Spring\"}`, exactly as before. A bare string and a bare\n * `{value,label}` both keep working untouched.\n *\n * `icon` is a plain `z.string()`, NOT a z.enum of the vocabulary. Deliberate: an unknown name\n * must degrade to no icon (WireIcon does that), never fail validation. If it were an enum, one\n * hallucinated or newer-than-this-client icon name would turn the whole card into a\n * LLM_SCHEMA_ERROR and cost the user their question — a catastrophic trade for a decoration.\n */\nimport { z } from \"zod\";\n\nimport { WIRE_ICON_NAMES } from \"../icons/vocabulary\";\n\n/**\n * The icon `.describe()` — an LLM ROUTING INSTRUCTION, not a type label (frequent_rules #4).\n * The vocabulary is inlined so the model reads the allowed values right where it fills the\n * field, and the list stays generated from the SSOT rather than drifting in a hand-typed copy.\n */\nexport const ICON_FIELD_DESCRIPTION =\n \"Optional icon for this option, making the choice scannable at a glance. Pick the ONE name \" +\n \"whose meaning matches the option (e.g. 'instagram' for an Instagram answer, 'friend' for \" +\n \"'A friend told me', 'wedding' for a wedding). Omit it when no name fits — a wrong icon is \" +\n `worse than none. Allowed values: ${WIRE_ICON_NAMES.join(\", \")}.`;\n\nexport const optionObjectSchema = z.object({\n value: z.string().describe(\"Option value\"),\n label: z.string().describe(\"Option display label\"),\n icon: z.string().optional().describe(ICON_FIELD_DESCRIPTION),\n});\n\nexport type CardOption = z.infer<typeof optionObjectSchema>;\n\n/** A bare string stays a valid option: coerce it to `{value, label}` before validating. */\nconst coerceOptions = (arr: unknown) =>\n Array.isArray(arr)\n ? arr.map((item) => (typeof item === \"string\" ? { value: item, label: item } : item))\n : arr;\n\n/** The `options` field, with its card-specific routing description. */\nexport const optionsField = (description: string) =>\n z.preprocess(coerceOptions, z.array(optionObjectSchema).min(1)).describe(description);\n\n/**\n * Component-level tolerance for the SAME coercion the schema does.\n *\n * WHY BOTH: in production the SDK renderer re-parses props and hands the card `parsed.data`, so\n * options arrive normalized. But a card is a plain exported component — the canary suite and any\n * host composing it directly mount it with raw props, where a bare string would otherwise read\n * `opt.value === undefined` and render an empty, unkeyed row. Cheap, total, and keeps the\n * component honest on its own contract instead of relying on a caller that may not exist.\n */\nexport const normalizeOptions = (options: ReadonlyArray<string | CardOption>): CardOption[] =>\n options.map((opt) => (typeof opt === \"string\" ? { value: opt, label: opt } : opt));\n","/**\n * Themed SelectionCard — drop-in for the OSS SDK's SelectionCard. Same `name`,\n * `propsSchema` (including the string|object option preprocess), `defaultProps`,\n * and `onSelect(string | string[])` contract. Radio/checkbox styling is themed.\n *\n * Motion (design-refs/EXTRACTED-SPEC.md rows 1-3): rows tick on press (scale\n * 0.975 spring), the selected fill/border eases in over 180ms ease-wire (a\n * native-driver opacity crossfade of a selected-style overlay), and the check\n * dot pops with a spring. All gated by useReducedMotion (snap, no spring).\n */\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, Pressable, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { labelStyle } from \"../theme/typography\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\nimport { WireIcon } from \"../icons/WireIcon\";\nimport { normalizeOptions, optionsField, type CardOption } from \"./optionSchema\";\nimport {\n CHECK_SCALE_FROM,\n CHECK_SPRING,\n PRESS_SPRING,\n ROW_PRESS_SCALE,\n SELECT_FILL_MS,\n WIRE_BEZIER,\n scaledMs,\n stateChangeDuration,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\n\nconst schema = z.object({\n title: z.string().describe(\"Question or prompt for the user\"),\n options: optionsField(\"List of choices\"),\n submitLabel: z.string().optional().describe(\"Submit button label, default: Continue\"),\n multiSelect: z.boolean().optional().describe(\"Allow multiple selections\"),\n});\n\ntype Props = Omit<z.infer<typeof schema>, \"options\"> &\n InjectedProps & {\n /** Bare strings stay valid (normalized on the way in) — see optionSchema.ts. */\n options: ReadonlyArray<string | CardOption>;\n onSelect?: (selected: string | string[]) => void;\n /** Fires as the live selection changes (before Continue), so the flow can prefetch the\n * next turn. Same value shape as onSelect. Optional — injected by OnboardingFlow. */\n onSelectionChange?: (selected: string | string[]) => void;\n };\n\ntype OptionRowProps = {\n opt: CardOption;\n isSelected: boolean;\n multiSelect: boolean;\n onToggle: (value: string) => void;\n};\n\nconst _OptionRow: React.FC<OptionRowProps> = ({ opt, isSelected, multiSelect, onToggle }) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const handlePress = useCallback(() => onToggle(opt.value), [opt.value, onToggle]);\n\n // Press tick: scale 1→0.975, spring, native driver. Skipped under reduce motion.\n const pressScale = useRef(new Animated.Value(1)).current;\n const pressTo = useCallback(\n (to: number) => {\n if (reduced) return;\n Animated.spring(pressScale, {\n toValue: to,\n friction: PRESS_SPRING.friction,\n tension: PRESS_SPRING.tension,\n useNativeDriver: true,\n }).start();\n },\n [pressScale, reduced],\n );\n const handlePressIn = useCallback(() => pressTo(ROW_PRESS_SCALE), [pressTo]);\n const handlePressOut = useCallback(() => pressTo(1), [pressTo]);\n\n // Selected fill: the selected border+bg live on an absolute overlay whose opacity\n // crossfades in 180ms ease-wire — same visual as a color interpolation, but it\n // stays on the native driver (see EXTRACTED-SPEC.md D7). Reduce motion: snap.\n const selectT = useRef(new Animated.Value(isSelected ? 1 : 0)).current;\n useEffect(() => {\n const anim = Animated.timing(selectT, {\n toValue: isSelected ? 1 : 0,\n duration: scaledMs(stateChangeDuration(reduced, SELECT_FILL_MS)),\n easing: easeWire,\n useNativeDriver: true,\n });\n anim.start();\n return () => anim.stop();\n }, [isSelected, reduced, selectT]);\n\n // Check pop: scale 0.6→1 + fade, springy. Reduce motion: shown at scale 1 instantly.\n const checkT = useRef(new Animated.Value(isSelected ? 1 : 0)).current;\n useEffect(() => {\n if (!isSelected) {\n checkT.setValue(0);\n return;\n }\n if (reduced) {\n checkT.setValue(1);\n return;\n }\n checkT.setValue(0);\n const anim = Animated.spring(checkT, {\n toValue: 1,\n friction: CHECK_SPRING.friction,\n tension: CHECK_SPRING.tension,\n useNativeDriver: true,\n });\n anim.start();\n return () => anim.stop();\n }, [isSelected, reduced, checkT]);\n\n const checkScale = checkT.interpolate({ inputRange: [0, 1], outputRange: [CHECK_SCALE_FROM, 1] });\n\n return (\n <Pressable\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n accessibilityRole={multiSelect ? \"checkbox\" : \"radio\"}\n accessibilityState={multiSelect ? { checked: isSelected } : { selected: isSelected }}\n accessibilityLabel={opt.label}\n >\n <Animated.View\n style={[\n styles.option,\n {\n padding: t.spacing.md,\n borderRadius: t.radius.md,\n gap: t.spacing.sm,\n borderColor: t.colors.border,\n backgroundColor: t.colors.background,\n transform: [{ scale: pressScale }],\n },\n ]}\n >\n <Animated.View\n pointerEvents=\"none\"\n style={[\n StyleSheet.absoluteFill,\n styles.selectedOverlay,\n {\n borderRadius: t.radius.md,\n borderColor: t.colors.primary,\n backgroundColor: t.colors.primarySoft,\n opacity: selectT,\n },\n ]}\n />\n <View\n style={[\n styles.indicator,\n { borderRadius: t.radius.full },\n isSelected\n ? { borderColor: t.colors.primary, backgroundColor: t.colors.primary }\n : { borderColor: t.colors.borderStrong, backgroundColor: \"transparent\" },\n ]}\n >\n {isSelected ? (\n <Animated.Text\n style={[\n styles.check,\n { color: t.colors.onPrimary, opacity: checkT, transform: [{ scale: checkScale }] },\n ]}\n >\n ✓\n </Animated.Text>\n ) : null}\n </View>\n {/* Accent discipline: the label keeps the text color in both states; the\n accent lives on the border, fill, and dot only. The icon obeys the same rule —\n it holds `text` in BOTH states rather than flipping to the accent, because an\n icon is not an excuse to invent a second accent. Decorative + unresolvable-safe:\n an unknown name renders null, so the row lays out exactly as an icon-less one. */}\n <WireIcon name={opt.icon} size={20} color={t.colors.text} />\n <Text style={[labelStyle(t.fonts), { color: t.colors.text }]}>{opt.label}</Text>\n </Animated.View>\n </Pressable>\n );\n};\nconst OptionRow = React.memo(_OptionRow);\n\nconst _SelectionCard: React.FC<Props> = ({\n title,\n options,\n submitLabel = \"Continue\",\n multiSelect = false,\n onSelect,\n onSelectionChange,\n}) => {\n const t = useOnboardingTheme();\n const opts = React.useMemo(() => normalizeOptions(options), [options]);\n const [selected, setSelected] = useState<string[]>([]);\n const [submitted, setSubmitted] = useState(false);\n\n // Report the settled selection upward (before Continue) so the flow can prefetch the next\n // turn. Debouncing lives in the flow; here we just emit on every change once something's picked.\n useEffect(() => {\n if (!submitted && selected.length) onSelectionChange?.(multiSelect ? selected : selected[0]!);\n }, [selected, submitted, multiSelect, onSelectionChange]);\n\n const toggle = useCallback(\n (value: string) => {\n if (submitted) return;\n if (multiSelect) {\n setSelected((prev) => (prev.includes(value) ? prev.filter((v) => v !== value) : [...prev, value]));\n } else {\n setSelected([value]);\n }\n },\n [submitted, multiSelect],\n );\n\n const handleSubmit = useCallback(() => {\n if (!selected.length || !onSelect || submitted) return;\n setSubmitted(true);\n onSelect(multiSelect ? selected : selected[0]!);\n }, [selected, onSelect, submitted, multiSelect]);\n\n return (\n <CardLayout\n title={title}\n footer={\n <Button\n title={submitLabel}\n onPress={handleSubmit}\n variant=\"primary\"\n disabled={selected.length === 0 || submitted}\n />\n }\n >\n <View style={{ gap: t.spacing.sm + t.spacing.xs }}>\n {opts.map((opt) => (\n <OptionRow\n key={opt.value}\n opt={opt}\n isSelected={selected.includes(opt.value)}\n multiSelect={multiSelect}\n onToggle={toggle}\n />\n ))}\n </View>\n </CardLayout>\n );\n};\n\nexport const SelectionCard: WireAIComponent = {\n name: \"SelectionCard\",\n description:\n \"Use for mutually exclusive (radio) or multi-select (checkbox) choices from 2–8 options, as a vertical list of rows. Best when options are wordy or need reading. Options may carry an optional `icon` from the vocabulary to make the list scannable. Use ChipSelectCard instead when options are short single words; use CardGridSelectCard when the options are visual and each has an obvious icon (occasions, channels, categories).\",\n component: React.memo(_SelectionCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n defaultProps: { submitLabel: \"Continue\", multiSelect: false },\n};\n\nconst styles = StyleSheet.create({\n option: { borderWidth: 1.5, flexDirection: \"row\", alignItems: \"center\", overflow: \"hidden\" },\n selectedOverlay: { borderWidth: 1.5 },\n indicator: { width: 24, height: 24, borderWidth: 2, alignItems: \"center\", justifyContent: \"center\" },\n check: { fontSize: 13, fontWeight: \"800\", lineHeight: 15 },\n});\n","/**\n * CardGridSelectCard — icon-led choices as a two-column grid of small cards.\n *\n * The shape Malik asked for (2026-07-16): \"the multi select needs to be a small card like this\n * one, with an icon on top, it is much better.\" Icon top-left, short label beneath, the whole\n * card is the tap target, selection lives on the card itself.\n *\n * ┌──────────────┐ ┌──────────────┐\n * │ ◇ │ │ ▣ │ ← icon on top\n * │ Wedding day │ │ Birthday │ ← label beneath\n * └──────────────┘ └──────────────┘\n *\n * WHY A NEW CARD RATHER THAN A `display` MODE ON SelectionCard: the card's `description` IS the\n * router — it is the only thing the model reads when choosing (frequent_rules #4). SelectionCard\n * already carries two modes behind one description; a third (\"a list, but sometimes a grid, and\n * then the icons matter\") cannot be stated honestly in one string, and a muddy description makes\n * the model pick the wrong card. The kit already has the precedent: ChipSelectCard exists ONLY\n * because \"compact vs. descriptive\" is a presentation difference worth its own name, over the\n * very same pick-from-options job. Back-compat costs nothing here — `supportedComponents`\n * (WireOnboarding.tsx) means an already-shipped client never advertises this name, so the server\n * intersects it away and can never emit it to the apps already in the stores. See the CHANGELOG.\n *\n * Layout is percentage flex, never a measured width: `flexBasis` ~47% + `flexGrow` makes exactly\n * two per row that fill the width, with no Dimensions read, no onLayout, and no re-render on\n * rotation. An odd last card stretches the row — deliberate, and the same thing every native\n * grid does.\n *\n * Motion mirrors SelectionCard's OptionRow exactly (press tick spring + a native-driver opacity\n * crossfade of the selected overlay), so the two cards feel like one system.\n */\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, Pressable, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { labelStyle } from \"../theme/typography\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\nimport { WireIcon } from \"../icons/WireIcon\";\nimport { normalizeOptions, optionsField, type CardOption } from \"./optionSchema\";\nimport {\n PRESS_SPRING,\n ROW_PRESS_SCALE,\n SELECT_FILL_MS,\n WIRE_BEZIER,\n scaledMs,\n stateChangeDuration,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\n\nconst schema = z.object({\n title: z.string().describe(\"Question or prompt for the user, e.g. 'What brings you here?'\"),\n options: optionsField(\n \"The choices, 2-6 of them. Give EVERY option an `icon` from the vocabulary — the icon is \" +\n \"the point of this card, and an option without one renders as a bare label next to \" +\n \"icon-bearing neighbours. Keep labels short (1-3 words) so they fit a half-width card.\",\n ),\n submitLabel: z.string().optional().describe(\"Submit button label, default: Continue\"),\n multiSelect: z\n .boolean()\n .optional()\n .describe(\"Allow multiple cards selected at once, default true\"),\n});\n\ntype Props = Omit<z.infer<typeof schema>, \"options\"> &\n InjectedProps & {\n /** Bare strings stay valid (normalized on the way in) — see optionSchema.ts. */\n options: ReadonlyArray<string | CardOption>;\n onSelect?: (selected: string | string[]) => void;\n /** Fires as the live selection changes (before Continue), so the flow can prefetch the\n * next turn. Same value shape as onSelect. Optional — injected by OnboardingFlow. */\n onSelectionChange?: (selected: string | string[]) => void;\n };\n\ntype OptionCardProps = {\n opt: CardOption;\n isSelected: boolean;\n multiSelect: boolean;\n onToggle: (value: string) => void;\n};\n\nconst _OptionCard: React.FC<OptionCardProps> = ({ opt, isSelected, multiSelect, onToggle }) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const handlePress = useCallback(() => onToggle(opt.value), [opt.value, onToggle]);\n\n // Press tick: scale 1→0.975, spring, native driver. Skipped under reduce motion.\n const pressScale = useRef(new Animated.Value(1)).current;\n const pressTo = useCallback(\n (to: number) => {\n if (reduced) return;\n Animated.spring(pressScale, {\n toValue: to,\n friction: PRESS_SPRING.friction,\n tension: PRESS_SPRING.tension,\n useNativeDriver: true,\n }).start();\n },\n [pressScale, reduced],\n );\n const handlePressIn = useCallback(() => pressTo(ROW_PRESS_SCALE), [pressTo]);\n const handlePressOut = useCallback(() => pressTo(1), [pressTo]);\n\n // Selected fill: accent border + tinted wash on an absolute overlay whose opacity crossfades\n // (native driver — see EXTRACTED-SPEC.md D7). Reduce motion: snap.\n const selectT = useRef(new Animated.Value(isSelected ? 1 : 0)).current;\n useEffect(() => {\n const anim = Animated.timing(selectT, {\n toValue: isSelected ? 1 : 0,\n duration: scaledMs(stateChangeDuration(reduced, SELECT_FILL_MS)),\n easing: easeWire,\n useNativeDriver: true,\n });\n anim.start();\n return () => anim.stop();\n }, [isSelected, reduced, selectT]);\n\n return (\n <Pressable\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n accessibilityRole={multiSelect ? \"checkbox\" : \"radio\"}\n accessibilityState={multiSelect ? { checked: isSelected } : { selected: isSelected }}\n accessibilityLabel={opt.label}\n style={styles.cell}\n >\n <Animated.View\n style={[\n styles.card,\n {\n padding: t.spacing.md,\n borderRadius: t.radius.lg,\n gap: t.spacing.sm,\n borderColor: t.colors.border,\n backgroundColor: t.colors.surface,\n transform: [{ scale: pressScale }],\n },\n ]}\n >\n <Animated.View\n pointerEvents=\"none\"\n style={[\n StyleSheet.absoluteFill,\n styles.selectedOverlay,\n {\n borderRadius: t.radius.lg,\n borderColor: t.colors.primary,\n backgroundColor: t.colors.primarySoft,\n opacity: selectT,\n },\n ]}\n />\n {/* Accent discipline (same rule as SelectionCard's rows): label AND icon keep the text\n color in both states; the accent lives on the border and fill only. An unresolvable\n icon renders null, so a card with a bad name lays out like one with no icon. */}\n <WireIcon name={opt.icon} size={24} color={t.colors.text} />\n <Text style={[labelStyle(t.fonts), { color: t.colors.text }]}>{opt.label}</Text>\n </Animated.View>\n </Pressable>\n );\n};\nconst OptionCard = React.memo(_OptionCard);\n\nconst _CardGridSelectCard: React.FC<Props> = ({\n title,\n options,\n submitLabel = \"Continue\",\n multiSelect = true,\n onSelect,\n onSelectionChange,\n}) => {\n const t = useOnboardingTheme();\n const opts = React.useMemo(() => normalizeOptions(options), [options]);\n const [selected, setSelected] = useState<string[]>([]);\n const [submitted, setSubmitted] = useState(false);\n\n // Report the settled selection upward (before Continue) so the flow can prefetch the next\n // turn. Debouncing lives in the flow; here we just emit on every change once something's picked.\n useEffect(() => {\n if (!submitted && selected.length) onSelectionChange?.(multiSelect ? selected : selected[0]!);\n }, [selected, submitted, multiSelect, onSelectionChange]);\n\n const toggle = useCallback(\n (value: string) => {\n if (submitted) return;\n if (multiSelect) {\n setSelected((prev) =>\n prev.includes(value) ? prev.filter((v) => v !== value) : [...prev, value],\n );\n } else {\n setSelected([value]);\n }\n },\n [submitted, multiSelect],\n );\n\n const handleSubmit = useCallback(() => {\n if (!selected.length || !onSelect || submitted) return;\n setSubmitted(true);\n onSelect(multiSelect ? selected : selected[0]!);\n }, [selected, onSelect, submitted, multiSelect]);\n\n return (\n <CardLayout\n title={title}\n footer={\n <Button\n title={submitLabel}\n onPress={handleSubmit}\n variant=\"primary\"\n disabled={selected.length === 0 || submitted}\n />\n }\n >\n <View style={[styles.grid, { gap: t.spacing.sm }]}>\n {opts.map((opt) => (\n <OptionCard\n key={opt.value}\n opt={opt}\n isSelected={selected.includes(opt.value)}\n multiSelect={multiSelect}\n onToggle={toggle}\n />\n ))}\n </View>\n </CardLayout>\n );\n};\n\nexport const CardGridSelectCard: WireAIComponent = {\n name: \"CardGridSelectCard\",\n description:\n \"Use for VISUAL, icon-led choices shown as a 2-column grid of tappable cards (icon on top, \" +\n \"short label beneath). Ideal for 2–6 concrete options that each have an obvious icon — \" +\n \"occasions, channels, goals, categories — e.g. 'What brings you here?' or 'Where did you \" +\n \"hear about us?'. Multi-select by default. Every option should carry an `icon`. Use \" +\n \"SelectionCard instead when options need descriptions or have no natural icon; use \" +\n \"ChipSelectCard for many short word-like tags.\",\n component: React.memo(_CardGridSelectCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n defaultProps: { submitLabel: \"Continue\", multiSelect: true },\n};\n\nconst styles = StyleSheet.create({\n grid: { flexDirection: \"row\", flexWrap: \"wrap\" },\n // Two per row: ~47% basis leaves room for the gap, flexGrow fills the remainder exactly.\n cell: { flexBasis: \"47%\", flexGrow: 1 },\n card: { borderWidth: 1.5, alignItems: \"flex-start\", overflow: \"hidden\" },\n selectedOverlay: { borderWidth: 1.5 },\n});\n","/**\n * Themed StatusCard — drop-in for the OSS SDK's StatusCard. Same `name`,\n * `propsSchema`, and the onContinue/onPress/onSubmit callback fallback chain.\n * The terminal StatusCard is what OnboardingFlow treats as \"flow complete\".\n * Status colors read from the theme's semantic palette.\n *\n * Motion (design-refs/EXTRACTED-SPEC.md rows 14, 16): the status glyph pops in\n * with a spring (scale 0.4→1, overshoot) and the copy fades up 80ms behind it.\n * Reduce motion: final frame instantly. (The terminal payoff with the burst is\n * CompletionView; this card is the inline status treatment.)\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { Animated, Easing, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { bodyStyle, headingStyle } from \"../theme/typography\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\nimport {\n STATUS_COPY_MS,\n STATUS_COPY_STAGGER_MS,\n STATUS_POP_SCALE_FROM,\n STATUS_POP_SPRING,\n WIRE_BEZIER,\n scaledMs,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\n\nconst schema = z.object({\n status: z.enum([\"success\", \"warning\", \"error\", \"info\"]).describe(\"Status type\"),\n title: z.string().describe(\"Status title\"),\n message: z.string().optional().describe(\"Supporting message\"),\n ctaLabel: z\n .string()\n .optional()\n .describe(\n \"Optional call-to-action button label. Always include this on success status to keep the conversation going.\",\n ),\n});\n\ntype Props = z.infer<typeof schema> &\n InjectedProps & {\n onContinue?: () => void;\n onPress?: (label: string) => void;\n onSubmit?: (value: string) => void;\n };\n\nconst STATUS_ICONS: Record<string, string> = {\n success: \"✓\",\n warning: \"⚠\",\n error: \"✗\",\n info: \"ℹ\",\n};\n\nconst _StatusCard: React.FC<Props> = ({ status, title, message, ctaLabel, onContinue, onPress, onSubmit }) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const [submitted, setSubmitted] = useState(false);\n\n const color = useMemo(() => {\n switch (status) {\n case \"success\":\n return t.colors.success;\n case \"warning\":\n return t.colors.warning;\n case \"error\":\n return t.colors.error;\n default:\n return t.colors.info;\n }\n }, [status, t.colors]);\n\n // Glyph pop + copy fade-up (final frame under reduce motion).\n const popT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const copyT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n useEffect(() => {\n if (reduced) {\n popT.setValue(1);\n copyT.setValue(1);\n return;\n }\n const anims = [\n Animated.spring(popT, {\n toValue: 1,\n friction: STATUS_POP_SPRING.friction,\n tension: STATUS_POP_SPRING.tension,\n useNativeDriver: true,\n }),\n Animated.timing(copyT, {\n toValue: 1,\n duration: scaledMs(STATUS_COPY_MS),\n delay: scaledMs(STATUS_COPY_STAGGER_MS),\n easing: easeWire,\n useNativeDriver: true,\n }),\n ];\n anims.forEach((a) => a.start());\n return () => anims.forEach((a) => a.stop());\n }, [reduced, popT, copyT]);\n\n const popScale = popT.interpolate({ inputRange: [0, 1], outputRange: [STATUS_POP_SCALE_FROM, 1] });\n const copyRise = copyT.interpolate({ inputRange: [0, 1], outputRange: [10, 0] });\n\n const handleContinue = useCallback(() => {\n if (!submitted) {\n setSubmitted(true);\n if (onContinue) onContinue();\n else if (onPress && ctaLabel) onPress(ctaLabel);\n else if (onSubmit) onSubmit(\"continue\");\n }\n }, [submitted, onContinue, onPress, onSubmit, ctaLabel]);\n\n return (\n <CardLayout\n align=\"center\"\n footer={\n ctaLabel ? (\n <Button title={ctaLabel} onPress={handleContinue} variant=\"primary\" disabled={submitted} />\n ) : undefined\n }\n >\n <View style={[styles.center, { gap: t.spacing.sm }]}>\n <View style={[styles.titleRow, { gap: t.spacing.sm }]}>\n <Animated.Text\n style={[\n headingStyle(t.fonts),\n { color, opacity: popT, transform: [{ scale: popScale }] },\n ]}\n >\n {STATUS_ICONS[status] ?? \"·\"}\n </Animated.Text>\n <Animated.Text\n style={[\n headingStyle(t.fonts),\n { color, textAlign: \"center\", opacity: copyT, transform: [{ translateY: copyRise }] },\n ]}\n >\n {title}\n </Animated.Text>\n </View>\n {message ? (\n <Animated.Text\n style={[\n bodyStyle(t.fonts),\n {\n color: t.colors.textMuted,\n textAlign: \"center\",\n opacity: copyT,\n transform: [{ translateY: copyRise }],\n },\n ]}\n >\n {message}\n </Animated.Text>\n ) : null}\n </View>\n </CardLayout>\n );\n};\n\nexport const StatusCard: WireAIComponent = {\n name: \"StatusCard\",\n description:\n \"Use ONLY for real outcomes: booking confirmed, data saved, action completed. NEVER for 'you just viewed X' acknowledgments. Always include ctaLabel so the user can continue after seeing the status.\",\n component: React.memo(_StatusCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n};\n\nconst styles = StyleSheet.create({\n center: { width: \"100%\", alignItems: \"center\", justifyContent: \"center\" },\n titleRow: { flexDirection: \"row\", alignItems: \"center\", justifyContent: \"center\" },\n});\n","/**\n * Themed NumberStepperCard — drop-in for the OSS SDK's NumberStepperCard. Same\n * `name`, `propsSchema`, `defaultProps`, and `onSubmit(value: number)` contract.\n * Keeps the SDK's defensive numeric coercion so a malformed LLM payload can never\n * feed NaN/Infinity into layout math.\n */\nimport React, { useCallback, useMemo, useState } from \"react\";\nimport { Pressable, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport type { OnboardingTheme } from \"../theme/types\";\nimport { captionStyle, headingStyle } from \"../theme/typography\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\n\nconst schema = z.object({\n label: z.string().describe(\"What is being counted, e.g. 'Number of days' or 'Travellers'\"),\n min: z.number().optional().describe(\"Minimum value, default 1\"),\n max: z.number().optional().describe(\"Maximum value, default 30\"),\n defaultValue: z.number().optional().describe(\"Starting value\"),\n step: z.number().optional().describe(\"Increment per tap, default 1\"),\n unit: z.string().optional().describe(\"Unit label shown next to value, e.g. 'days' or 'people'\"),\n submitLabel: z.string().optional().describe(\"Confirm button label, default: Confirm\"),\n});\n\ntype Props = z.infer<typeof schema> &\n InjectedProps & {\n onSubmit?: (value: number) => void;\n };\n\nconst safeNum = (n: unknown, fallback: number): number =>\n typeof n === \"number\" && Number.isFinite(n) ? n : fallback;\n\nconst _NumberStepperCard: React.FC<Props> = ({\n label,\n min,\n max,\n defaultValue,\n step,\n unit,\n submitLabel = \"Confirm\",\n onSubmit,\n}) => {\n const t = useOnboardingTheme();\n const styles = useMemo(() => makeStyles(t), [t]);\n\n const safeMin = safeNum(min, 1);\n const safeMaxRaw = safeNum(max, 30);\n const safeMax = safeMaxRaw < safeMin ? safeMin : safeMaxRaw;\n const safeStepRaw = safeNum(step, 1);\n const safeStep = safeStepRaw > 0 ? safeStepRaw : 1;\n const safeDefault = safeNum(defaultValue, safeMin);\n\n const [value, setValue] = useState(Math.min(Math.max(safeDefault, safeMin), safeMax));\n const [submitted, setSubmitted] = useState(false);\n\n const handleDecrement = useCallback(() => {\n if (!submitted) setValue((v) => Math.max(v - safeStep, safeMin));\n }, [submitted, safeStep, safeMin]);\n\n const handleIncrement = useCallback(() => {\n if (!submitted) setValue((v) => Math.min(v + safeStep, safeMax));\n }, [submitted, safeStep, safeMax]);\n\n const handleSubmit = useCallback(() => {\n if (!submitted) {\n setSubmitted(true);\n onSubmit?.(value);\n }\n }, [submitted, onSubmit, value]);\n\n const atMin = value <= safeMin;\n const atMax = value >= safeMax;\n\n const stepBtnStyle = (disabled: boolean) => [\n styles.stepBtn,\n { borderRadius: t.radius.full, backgroundColor: t.colors.background, borderColor: disabled ? t.colors.border : t.colors.primary },\n ];\n\n return (\n <CardLayout\n title={label}\n align=\"center\"\n footer={\n <Button title={submitLabel} onPress={handleSubmit} variant=\"primary\" disabled={submitted} />\n }\n >\n <View style={styles.wrap}>\n <View style={[styles.stepper, { gap: t.spacing.lg }]}>\n <Pressable onPress={atMin || submitted ? undefined : handleDecrement} disabled={atMin || submitted} style={stepBtnStyle(atMin)}>\n <Text style={[headingStyle(t.fonts), { color: atMin ? t.colors.textMuted : t.colors.primary }]}>{\"−\"}</Text>\n </Pressable>\n <View style={styles.valueBox}>\n <Text style={[headingStyle(t.fonts), { color: t.colors.primary }]}>{String(value)}</Text>\n {unit ? <Text style={[captionStyle(t.fonts), { color: t.colors.textMuted }]}>{unit}</Text> : null}\n </View>\n <Pressable onPress={atMax || submitted ? undefined : handleIncrement} disabled={atMax || submitted} style={stepBtnStyle(atMax)}>\n <Text style={[headingStyle(t.fonts), { color: atMax ? t.colors.textMuted : t.colors.primary }]}>{\"+\"}</Text>\n </Pressable>\n </View>\n <Text style={[captionStyle(t.fonts), { color: t.colors.textMuted, textAlign: \"center\" }]}>\n {`${safeMin} – ${safeMax}${unit ? ` ${unit}` : \"\"}`}\n </Text>\n </View>\n </CardLayout>\n );\n};\n\nexport const NumberStepperCard: WireAIComponent = {\n name: \"NumberStepperCard\",\n description:\n \"Use for any bounded numeric input: days, people, portions, budget tiers, ratings. Best for ranges 1–99. Set unit (e.g. 'days', 'people') for clarity.\",\n component: React.memo(_NumberStepperCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n defaultProps: { min: 1, max: 30, defaultValue: 1, step: 1, submitLabel: \"Confirm\" },\n};\n\nfunction makeStyles(t: OnboardingTheme) {\n return StyleSheet.create({\n wrap: { gap: t.spacing.md, alignItems: \"center\" },\n stepper: { flexDirection: \"row\", alignItems: \"center\", justifyContent: \"center\" },\n stepBtn: { width: 44, height: 44, borderWidth: 2, alignItems: \"center\", justifyContent: \"center\" },\n valueBox: { alignItems: \"center\", minWidth: 80 },\n });\n}\n","/**\n * InterstitialCard — a mid-flow \"value\" screen (the Duolingo / Cal-AI beat): an\n * illustration + a short motivational line + a single Continue button. It is NOT a\n * question — it builds momentum and reinforces what the user is committing to,\n * which is one of the biggest retention levers in great onboarding.\n *\n * Artwork resolves in order so the screen is NEVER a blank box: the host's named\n * `illustration` (brand SVG/Lottie, keeping the kit dependency-free) → a\n * backend-supplied `imageUrl` via RN <Image> (which self-heals to art on load\n * error) → a named `illustrationFallback` (defaults to \"momentum\", always present\n * in the kit's default registry).\n *\n * A minimum display window keeps the momentum beat from flashing past when the next\n * card is already cached: Continue is disabled for MIN_DISPLAY_MS after mount.\n *\n * Motion (design-refs/EXTRACTED-SPEC.md rows 11-13): art and title fade-up in\n * sequence (500ms ease-wire, 100ms stagger); the optional `items` (short lines\n * referencing what the user already said) tick on one by one (90ms stagger),\n * each check popping 200ms after its row — \"work being done\", not a slideshow.\n * Reduce motion: everything rendered at its final frame at once.\n *\n * On Continue it sends \"continue\" back to the backend so the flow advances; the\n * submitted-state guard makes the tap idempotent.\n */\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, Image, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { bodyStyle, headingStyle } from \"../theme/typography\";\nimport { useIllustration } from \"../components/Illustration\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\nimport {\n CHECK_SPRING,\n INTERSTITIAL_CHECK_SCALE_FROM,\n INTERSTITIAL_HEAD_MS,\n INTERSTITIAL_HEAD_STAGGER_MS,\n INTERSTITIAL_ITEM_MS,\n WIRE_BEZIER,\n interstitialCheckDelay,\n scaledMs,\n interstitialItemDelay,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\nconst RISE_PX = 10;\n\nconst schema = z.object({\n title: z.string().describe(\"Short, warm headline for the value/momentum moment\"),\n body: z\n .string()\n .optional()\n .describe(\"One or two supporting lines that reflect the user's answers back and build momentum\"),\n items: z\n .array(z.string())\n .max(4)\n .optional()\n .describe(\n \"2-3 very short 'work being done' lines that each reference something the user already answered (e.g. 'Sized for a small team'). Shown as ticked items appearing in sequence. Prefer these over `body` when you have concrete answers to reflect back.\",\n ),\n illustration: z\n .string()\n .optional()\n .describe(\n \"Name of an app-provided illustration to show (the app's registry decides the artwork). Prefer this over imageUrl.\",\n ),\n imageUrl: z\n .string()\n .url()\n .refine((v) => v.startsWith(\"https://\"), \"imageUrl must be an https URL\")\n .optional()\n .describe(\n \"Fallback remote HTTPS image URL, used only when no named illustration is registered. A non-https or malformed value is rejected and degrades to the named-illustration fallback.\",\n ),\n illustrationFallback: z\n .string()\n .optional()\n .describe(\n \"Named illustration to show when neither `illustration` nor `imageUrl` resolves (or the image fails to load). Defaults to the kit's always-present 'momentum' art so the screen is never blank.\",\n ),\n ctaLabel: z.string().optional().describe(\"Continue button label, default: Continue\"),\n});\n\n// Minimum time the momentum screen stays interactive-locked, so it never flashes past\n// when the next card is already prefetched/cached.\nconst MIN_DISPLAY_MS = 500;\n\ntype Props = z.infer<typeof schema> &\n InjectedProps & {\n onSubmit?: (value: string) => void;\n onPress?: (label: string) => void;\n };\n\n/** One ticked \"work\" row: fades up on its stagger slot, then the check pops. */\nconst _WorkItem: React.FC<{ text: string; index: number; reduced: boolean }> = ({\n text,\n index,\n reduced,\n}) => {\n const t = useOnboardingTheme();\n const rowT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const checkT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n\n useEffect(() => {\n if (reduced) {\n rowT.setValue(1);\n checkT.setValue(1);\n return;\n }\n const anims = [\n Animated.timing(rowT, {\n toValue: 1,\n duration: scaledMs(INTERSTITIAL_ITEM_MS),\n delay: scaledMs(interstitialItemDelay(index)),\n easing: easeWire,\n useNativeDriver: true,\n }),\n Animated.spring(checkT, {\n toValue: 1,\n delay: scaledMs(interstitialCheckDelay(index)),\n friction: CHECK_SPRING.friction,\n tension: CHECK_SPRING.tension,\n useNativeDriver: true,\n }),\n ];\n anims.forEach((a) => a.start());\n return () => anims.forEach((a) => a.stop());\n }, [reduced, index, rowT, checkT]);\n\n const rise = rowT.interpolate({ inputRange: [0, 1], outputRange: [RISE_PX, 0] });\n const checkScale = checkT.interpolate({\n inputRange: [0, 1],\n outputRange: [INTERSTITIAL_CHECK_SCALE_FROM, 1],\n });\n\n return (\n <Animated.View\n style={[styles.itemRow, { gap: t.spacing.sm + t.spacing.xs, opacity: rowT, transform: [{ translateY: rise }] }]}\n >\n <View\n style={[\n styles.itemBadge,\n { backgroundColor: t.colors.primarySoft, borderRadius: t.radius.full },\n ]}\n >\n <Animated.Text\n style={[\n styles.itemCheck,\n { color: t.colors.primary, opacity: checkT, transform: [{ scale: checkScale }] },\n ]}\n >\n ✓\n </Animated.Text>\n </View>\n <Text style={[bodyStyle(t.fonts), styles.itemText, { color: t.colors.text }]}>{text}</Text>\n </Animated.View>\n );\n};\nconst WorkItem = React.memo(_WorkItem);\n\nconst _InterstitialCard: React.FC<Props> = ({\n title,\n body,\n items,\n illustration,\n imageUrl,\n illustrationFallback,\n ctaLabel = \"Continue\",\n onSubmit,\n onPress,\n}) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const node = useIllustration(illustration);\n const fallbackNode = useIllustration(illustrationFallback);\n const [submitted, setSubmitted] = useState(false);\n const [imgFailed, setImgFailed] = useState(false);\n // Keep the momentum beat on screen for at least MIN_DISPLAY_MS before Continue is tappable.\n const [canAdvance, setCanAdvance] = useState(false);\n\n useEffect(() => {\n const timer = setTimeout(() => setCanAdvance(true), MIN_DISPLAY_MS);\n return () => clearTimeout(timer);\n }, []);\n\n // Head reveal: art then title (then body) fade-up, 500ms ease-wire, 100ms stagger.\n // Reduce motion: final frame immediately (the shell handoff supplies the short fade).\n const artT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const titleT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const bodyT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n useEffect(() => {\n if (reduced) {\n artT.setValue(1);\n titleT.setValue(1);\n bodyT.setValue(1);\n return;\n }\n const rise = (value: Animated.Value, delay: number) =>\n Animated.timing(value, {\n toValue: 1,\n duration: scaledMs(INTERSTITIAL_HEAD_MS),\n delay,\n easing: easeWire,\n useNativeDriver: true,\n });\n const anims = [\n rise(artT, 0),\n rise(titleT, scaledMs(INTERSTITIAL_HEAD_STAGGER_MS)),\n rise(bodyT, scaledMs(INTERSTITIAL_HEAD_STAGGER_MS * 2)),\n ];\n anims.forEach((a) => a.start());\n return () => anims.forEach((a) => a.stop());\n }, [reduced, artT, titleT, bodyT]);\n\n const riseStyle = (value: Animated.Value) => ({\n opacity: value,\n transform: [{ translateY: value.interpolate({ inputRange: [0, 1], outputRange: [RISE_PX, 0] }) }],\n });\n\n const handleContinue = useCallback(() => {\n if (submitted || !canAdvance) return;\n setSubmitted(true);\n if (onSubmit) onSubmit(\"continue\");\n else if (onPress) onPress(ctaLabel);\n }, [submitted, canAdvance, onSubmit, onPress, ctaLabel]);\n\n // Resolution order — a broken/missing image must never leave a blank box:\n // named illustration → remote image (until it errors) → named fallback art.\n const showImage = !node && !!imageUrl && !imgFailed;\n const art = node ?? (showImage ? undefined : fallbackNode);\n\n return (\n <CardLayout\n align=\"center\"\n footer={\n <Button\n title={ctaLabel}\n onPress={handleContinue}\n variant=\"primary\"\n disabled={submitted || !canAdvance}\n />\n }\n >\n <View style={[styles.center, { gap: t.spacing.md }]}>\n <Animated.View style={[styles.fullWidth, riseStyle(artT)]}>\n {showImage ? (\n <Image\n source={{ uri: imageUrl }}\n style={styles.image}\n resizeMode=\"contain\"\n onError={() => setImgFailed(true)}\n />\n ) : art ? (\n <View style={styles.art}>{art}</View>\n ) : null}\n </Animated.View>\n\n <Animated.View style={riseStyle(titleT)}>\n <Text style={[headingStyle(t.fonts), { color: t.colors.text, textAlign: \"center\" }]}>{title}</Text>\n </Animated.View>\n\n {items?.length ? (\n <View style={[styles.items, { gap: t.spacing.md, marginTop: t.spacing.sm }]}>\n {items.map((item, i) => (\n <WorkItem key={`${item}-${i}`} text={item} index={i} reduced={reduced} />\n ))}\n </View>\n ) : body ? (\n <Animated.View style={riseStyle(bodyT)}>\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: \"center\" }]}>{body}</Text>\n </Animated.View>\n ) : null}\n </View>\n </CardLayout>\n );\n};\n\nexport const InterstitialCard: WireAIComponent = {\n name: \"InterstitialCard\",\n description:\n \"Use ONCE mid-flow (never first, never last) as a momentum/value screen between questions — an illustration + a warm line that reflects answers back, like Duolingo/Cal-AI. NOT a question; the user just taps Continue. Set `illustration` to an app-registered artwork name. Prefer `items` (2-3 short ticked lines, each reflecting a real answer) when you have the signal. Skip it if you don't have enough signal to make the line specific.\",\n component: React.memo(_InterstitialCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n defaultProps: { ctaLabel: \"Continue\", illustrationFallback: \"momentum\" },\n};\n\nconst styles = StyleSheet.create({\n center: { width: \"100%\", alignItems: \"center\", justifyContent: \"center\" },\n fullWidth: { width: \"100%\", alignItems: \"center\" },\n art: { alignItems: \"center\", justifyContent: \"center\" },\n image: { width: \"100%\", height: 200 },\n items: { width: \"100%\", alignSelf: \"stretch\" },\n itemRow: { flexDirection: \"row\", alignItems: \"center\" },\n itemBadge: { width: 24, height: 24, alignItems: \"center\", justifyContent: \"center\" },\n itemCheck: { fontSize: 13, fontWeight: \"800\", lineHeight: 15 },\n itemText: { flex: 1 },\n});\n","/**\n * onboardingComponents — the constrained set of themed cards the kit registers\n * with the SDK. The backend's `allowed_components` must be a subset of these\n * names so every card the agent asks for has a themed renderer.\n */\nimport type { WireAIComponent } from \"wireai-rn\";\nimport { ChipSelectCard } from \"./ChipSelectCard\";\nimport { TextInputCard } from \"./TextInputCard\";\nimport { SelectionCard } from \"./SelectionCard\";\nimport { CardGridSelectCard } from \"./CardGridSelectCard\";\nimport { StatusCard } from \"./StatusCard\";\nimport { NumberStepperCard } from \"./NumberStepperCard\";\nimport { InterstitialCard } from \"./InterstitialCard\";\n\nexport {\n ChipSelectCard,\n TextInputCard,\n SelectionCard,\n CardGridSelectCard,\n StatusCard,\n NumberStepperCard,\n InterstitialCard,\n};\nexport { normalizeOptions, optionsField, optionObjectSchema } from \"./optionSchema\";\nexport type { CardOption } from \"./optionSchema\";\n\nexport const onboardingComponents: WireAIComponent[] = [\n ChipSelectCard,\n TextInputCard,\n SelectionCard,\n CardGridSelectCard,\n StatusCard,\n NumberStepperCard,\n InterstitialCard,\n];\n","/**\n * appVersion — best-effort, DEPENDENCY-FREE auto-detection of the host app's version string.\n *\n * WHY this exists: analytics segments the funnel `by_app_version`, but that breakdown is only\n * populated when a `device.appVersion` rides the event. `config.appVersion` (see types.ts) has\n * always been the way to supply it — but it is easy for a host to forget, and then the release\n * breakdown is silently empty. This module fills that gap: when the host does NOT pass a version,\n * the kit makes a best-effort read of the app version the host already ships in its Expo config,\n * so the breakdown works out of the box. An explicit `config.appVersion` always WINS over this.\n *\n * WHY it adds NO dependency (the kit's hard rule): `expo-constants` / `expo-application` are read\n * through a GUARDED require with a STRING-LITERAL specifier, inside a try/catch. Both halves are\n * required: the literal is what lets Metro COLLECT the dep, and the try/catch is what marks it\n * OPTIONAL, so an absent module becomes a `null` dependencyMap entry whose require throws \"Cannot\n * find module\" straight into the catch. (`withWireOnboarding` in metro/index.js adds a stub-to-\n * empty-module safety net for hosts that disable Metro's `allowOptionalDependencies`.) Nothing is\n * added to `package.json`; nothing is forced on the host.\n *\n * The specifier MUST stay a literal. A variable specifier (`const req = require; req(name)`) is not\n * \"lazier\" — it is broken: Metro collects dependencies statically, so a variable collects NOTHING,\n * the module never enters the bundle, and the aliased `require` is Metro's own numeric-id-keyed\n * `metroRequire`, which can never resolve a package-name string. That shape is why this function\n * returned `undefined` on every host despite `expo-constants` being installed, which silently\n * emptied the `by_app_version` breakdown this module exists to fill. See icons/expoIcons.ts for\n * the full autopsy, and reviews/storeReview.ts for the literal-specifier counter-example.\n *\n * PRIVACY: an app version string is not PII and identifies no user or device, so surfacing it\n * changes no App Privacy / Data Safety declaration (same guarantee as the rest of deviceContext).\n *\n * NEVER THROWS: every read is guarded; a missing/odd value yields `undefined`, never an exception.\n * Analytics must never be able to break onboarding.\n */\n\n// Metro injects a module-scoped `require`; it is ABSENT in a pure-ESM runtime. Declared locally so\n// this type-checks without ambient Node types; the `typeof` guard keeps the reference ESM-safe.\ndeclare const require: ((id: string) => unknown) | undefined;\n\n/** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */\nexport type OptionalRequire = (moduleName: string) => unknown;\n\n/** Trim + reject non-strings/empties so we only ever emit a real version string. */\nexport const coerceVersion = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\n/**\n * Guarded runtime require.\n *\n * Every specifier below is a STRING LITERAL, because that is the only shape Metro's dependency\n * collector matches (callee literally `require`, argument literally a string). The `moduleName`\n * parameter exists only to keep the `OptionalRequire` seam shape for tests; an unrecognised name\n * resolves to undefined. See the header for why the old variable-specifier shape could not work.\n */\nconst runtimeRequire: OptionalRequire = (moduleName) => {\n if (typeof require !== \"function\") return undefined;\n try {\n switch (moduleName) {\n case \"expo-constants\":\n return require(\"expo-constants\");\n case \"expo-application\":\n return require(\"expo-application\");\n default:\n return undefined;\n }\n } catch {\n return undefined;\n }\n};\n\n/** Read a module's `default` (Expo modules are consumed as default exports) or the namespace. */\nconst interop = (mod: unknown): Record<string, unknown> | undefined => {\n if (!mod || typeof mod !== \"object\") return undefined;\n const def = (mod as { default?: unknown }).default;\n if (def && typeof def === \"object\") return def as Record<string, unknown>;\n return mod as Record<string, unknown>;\n};\n\n/** Resolve a module namespace, swallowing a throwing require (an uninstalled module throws). */\nconst safeInterop = (\n requireModule: OptionalRequire,\n moduleName: string,\n): Record<string, unknown> | undefined => {\n try {\n return interop(requireModule(moduleName));\n } catch {\n return undefined;\n }\n};\n\n/**\n * Detect the host app version, preferring `expo-constants` (`expoConfig.version`, then\n * `nativeAppVersion`) and finally `expo-application` (`nativeApplicationVersion`). Returns the\n * first real string, or `undefined` when none of those are available. Pure and never throws.\n *\n * `requireModule` is injectable so tests can exercise the \"found\" path without the native modules;\n * production defaults to the guarded runtime require above.\n */\nexport const detectAppVersion = (\n requireModule: OptionalRequire = runtimeRequire,\n): string | undefined => {\n try {\n const constants = safeInterop(requireModule, \"expo-constants\");\n if (constants) {\n const expoConfig = constants.expoConfig;\n if (expoConfig && typeof expoConfig === \"object\") {\n const fromExpoConfig = coerceVersion((expoConfig as { version?: unknown }).version);\n if (fromExpoConfig) return fromExpoConfig;\n }\n const fromNative = coerceVersion(constants.nativeAppVersion);\n if (fromNative) return fromNative;\n }\n\n const application = safeInterop(requireModule, \"expo-application\");\n if (application) {\n const fromApplication = coerceVersion(application.nativeApplicationVersion);\n if (fromApplication) return fromApplication;\n }\n } catch {\n // Any unexpected read error → \"unknown\"; analytics must never crash onboarding.\n }\n return undefined;\n};\n","/**\n * deviceModel — best-effort, DEPENDENCY-FREE detection of the device MODEL on iOS.\n *\n * WHY this exists (the asymmetry it closes): `collectDeviceContext` already reports `device.model`\n * on Android straight from `Platform.constants.Model` (e.g. \"SM-G991B\"), but iOS `Platform.constants`\n * exposes NO model — only `osVersion` / `interfaceIdiom`. So the analytics `by_model` breakdown was\n * Android-only. This module fills the iOS gap with the SAME zero-dependency technique the kit already\n * uses for `appVersion` (see device/appVersion.ts): a GUARDED, STRING-LITERAL `require` of the common\n * Expo `expo-device` module, inside a try/catch — the literal is what lets Metro COLLECT the dep and\n * the try/catch is what marks it OPTIONAL, so an absent module degrades instead of failing the build.\n * (`withWireOnboarding` in metro/index.js adds a stub-to-empty-module safety net for hosts that\n * disable Metro's `allowOptionalDependencies`.) If the host has it, iOS gets a model out of the box;\n * if not, the read yields `undefined` and iOS `model` stays omitted — nothing is forced, and nothing\n * is added to `package.json`.\n *\n * The specifier MUST stay a literal. A variable specifier (`const req = require; req(name)`) collects\n * NOTHING under Metro's static dependency collector, so the module never enters the bundle and the\n * aliased `require` — really Metro's numeric-id-keyed `metroRequire` — can never resolve a package\n * name. See icons/expoIcons.ts for the full autopsy.\n *\n * WHY it is NOT PII: `expo-device`'s `modelName` (\"iPhone 14 Pro\") and `modelId` (\"iPhone15,2\") are a\n * device CLASS shared by millions of units — the same privacy category as the Android `Model` the kit\n * already sends. It is NOT a unique device id / IDFA / fingerprint, so surfacing it changes no App\n * Privacy / Data Safety declaration (identical guarantee to the rest of deviceContext). It deliberately\n * does NOT read `expo-device`'s `deviceName` (that is the user-set name, e.g. \"Malik's iPhone\", and IS\n * personal data).\n *\n * NEVER THROWS: every read is guarded; a missing/odd value yields `undefined`, never an exception.\n */\n\n// Metro injects a module-scoped `require`; it is ABSENT in a pure-ESM runtime. Declared locally so\n// this type-checks without ambient Node types; the `typeof` guard keeps the reference ESM-safe.\ndeclare const require: ((id: string) => unknown) | undefined;\n\n/** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */\nexport type OptionalRequire = (moduleName: string) => unknown;\n\n/** Trim + reject non-strings/empties so we only ever emit a real model string. */\nconst coerceModel = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\n/**\n * Guarded runtime require.\n *\n * The specifier is a STRING LITERAL, because that is the only shape Metro's dependency collector\n * matches (callee literally `require`, argument literally a string). The `moduleName` parameter\n * exists only to keep the `OptionalRequire` seam shape for tests; an unrecognised name resolves to\n * undefined. (See the twin guard in ./appVersion.ts.)\n */\nconst runtimeRequire: OptionalRequire = (moduleName) => {\n if (moduleName !== \"expo-device\") return undefined;\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"expo-device\");\n } catch {\n return undefined;\n }\n};\n\n/** Read a module's `default` (Expo modules are often consumed as default exports) or the namespace. */\nconst interop = (mod: unknown): Record<string, unknown> | undefined => {\n if (!mod || typeof mod !== \"object\") return undefined;\n const def = (mod as { default?: unknown }).default;\n if (def && typeof def === \"object\") return def as Record<string, unknown>;\n return mod as Record<string, unknown>;\n};\n\n/** Resolve a module namespace, swallowing a throwing require (an uninstalled module throws). */\nconst safeInterop = (\n requireModule: OptionalRequire,\n moduleName: string,\n): Record<string, unknown> | undefined => {\n try {\n return interop(requireModule(moduleName));\n } catch {\n return undefined;\n }\n};\n\n/**\n * Detect the device model via `expo-device`, preferring the human-readable `modelName`\n * (\"iPhone 14 Pro\") and falling back to the identifier `modelId` (\"iPhone15,2\"). Returns the first\n * real string, or `undefined` when `expo-device` is absent. Pure and never throws.\n *\n * `requireModule` is injectable so tests can exercise the \"found\" path without the native module;\n * production defaults to the guarded runtime require above.\n */\nexport const detectNativeModel = (\n requireModule: OptionalRequire = runtimeRequire,\n): string | undefined => {\n try {\n const device = safeInterop(requireModule, \"expo-device\");\n if (device) {\n const modelName = coerceModel(device.modelName);\n if (modelName) return modelName;\n const modelId = coerceModel(device.modelId);\n if (modelId) return modelId;\n }\n } catch {\n // Any unexpected read error → undefined; analytics must never crash onboarding.\n }\n return undefined;\n};\n","/**\n * deviceContext — collect a small, privacy-label-neutral snapshot of the device so\n * onboarding analytics can segment the funnel (platform / form factor / locale) WITHOUT\n * adding a single dependency to the kit or changing a host app's App Privacy / Data Safety\n * declarations.\n *\n * HARD RULE (why this file adds no dependency):\n * The kit stays dependency-free. Everything here comes from `Platform`, `Dimensions`,\n * `I18nManager`, and the standard `Intl` global — plus a best-effort `appVersion` read via\n * `detectAppVersion()`, which itself adds NO dependency (it reaches for `expo-constants` /\n * `expo-application` through a guarded, variable-specifier require that a host without them\n * simply never resolves — see device/appVersion.ts). There are NO advertising IDs, NO\n * `getUniqueId`/IDFA/GAID/fingerprinting APIs, and nothing that would require a new\n * privacy-label entry. A host can adopt this without touching its store declarations.\n *\n * DEFENSIVE BY DESIGN: `collectDeviceContext()` never throws. Every read is guarded and\n * a missing/unavailable field is simply omitted (Hermes may ship without full `Intl`,\n * `Platform.constants` differs per OS and RN version, etc.). Analytics must never be able\n * to break onboarding.\n */\nimport { Dimensions, I18nManager, Platform } from \"react-native\";\n\nimport { detectAppVersion } from \"./appVersion\";\nimport { detectNativeModel } from \"./deviceModel\";\n\n/** Coarse device class. iOS uses the reported interface idiom; else a screen-size heuristic. */\nexport type DeviceFormFactor = \"phone\" | \"tablet\";\n\n/**\n * A privacy-label-neutral device snapshot. ALL fields except `platform` are optional and are\n * omitted when unavailable. Nothing here identifies a user or device uniquely.\n */\nexport type DeviceContext = {\n /** `Platform.OS` — \"ios\" | \"android\" | \"windows\" | \"macos\" | \"web\". Always present. */\n platform: typeof Platform.OS;\n /** OS version string (iOS `osVersion`/`Platform.Version`, Android `Release`). */\n osVersion?: string;\n /** Android device brand (e.g. \"samsung\"). Android only. */\n brand?: string;\n /**\n * Device model. On Android it is read directly from `Platform.constants.Model` (e.g. \"SM-G991B\").\n * iOS `Platform.constants` exposes NO model, so on iOS it is a BEST-EFFORT read of `expo-device`'s\n * `modelName` (\"iPhone 14 Pro\"), falling back to `modelId` (\"iPhone15,2\") — dependency-free via a\n * guarded require (see device/deviceModel.ts). ASYMMETRY: without `expo-device` installed, iOS\n * `model` is omitted (there is no dependency-free iOS model in the already-used RN surface, and the\n * kit will not add a native dep for it); Android needs no extra module. Not PII (a device class,\n * not a unique id), so it changes no privacy-label declaration.\n */\n model?: string;\n /** iOS interface idiom (\"phone\" | \"pad\" | …), when reported. iOS only. */\n interfaceIdiom?: string;\n /** Derived device class. */\n formFactor?: DeviceFormFactor;\n /** `Dimensions.get('screen')` width in dp. */\n screenWidth?: number;\n /** `Dimensions.get('screen')` height in dp. */\n screenHeight?: number;\n /** Screen pixel density (`scale`). */\n screenScale?: number;\n /** Right-to-left layout (`I18nManager.isRTL`). */\n isRTL?: boolean;\n /** Resolved locale (e.g. \"en-US\"), from `Intl` when available. */\n locale?: string;\n /** IANA time zone (e.g. \"Europe/Berlin\"), from `Intl` when available. */\n timeZone?: string;\n /**\n * Host app version (e.g. \"1.4.2\"). BEST-EFFORT auto-detected here via `detectAppVersion()`\n * (reads `expo-constants` / `expo-application` when present; adds no dependency — see\n * device/appVersion.ts). An explicit host-injected `config.appVersion` always WINS: the merge\n * sites (`WireOnboarding`, the session-analytics hooks, the context envelope) overwrite this\n * with the host value when one is supplied. Omitted when neither source yields a version.\n */\n appVersion?: string;\n};\n\n/** iOS idiom wins; otherwise the shortest side in dp (>= 600 → tablet) picks the class. */\nconst deriveFormFactor = (\n iosIdiom: string | undefined,\n width: number | undefined,\n height: number | undefined,\n): DeviceFormFactor | undefined => {\n if (iosIdiom === \"pad\") return \"tablet\";\n if (iosIdiom === \"phone\") return \"phone\";\n if (typeof width === \"number\" && typeof height === \"number\") {\n return Math.min(width, height) >= 600 ? \"tablet\" : \"phone\";\n }\n return undefined;\n};\n\n/**\n * Collect the device snapshot. Pure, synchronous, and never throws — call it once per\n * onboarding session. Missing fields are omitted rather than sent as null/undefined so the\n * payload (and the server's stored dict) stays compact.\n */\nexport const collectDeviceContext = (): DeviceContext => {\n const ctx: DeviceContext = { platform: Platform.OS };\n\n // OS version (fallback; per-OS constants below may refine it).\n try {\n const version = Platform.Version;\n if (version !== undefined && version !== null && String(version)) {\n ctx.osVersion = String(version);\n }\n } catch {\n // ignore\n }\n\n // `Platform.constants` shape differs by OS and RN version — read every field defensively.\n let constants: Record<string, unknown> = {};\n try {\n constants = (Platform.constants ?? {}) as Record<string, unknown>;\n } catch {\n constants = {};\n }\n\n let iosIdiom: string | undefined;\n try {\n if (Platform.OS === \"android\") {\n const brand = constants.Brand;\n const model = constants.Model;\n const release = constants.Release;\n if (typeof brand === \"string\" && brand) ctx.brand = brand;\n if (typeof model === \"string\" && model) ctx.model = model;\n if (release !== undefined && release !== null && String(release)) {\n ctx.osVersion = String(release);\n }\n } else if (Platform.OS === \"ios\") {\n const osVersion = constants.osVersion;\n const idiom = constants.interfaceIdiom;\n if (osVersion !== undefined && osVersion !== null && String(osVersion)) {\n ctx.osVersion = String(osVersion);\n }\n if (typeof idiom === \"string\" && idiom) {\n ctx.interfaceIdiom = idiom;\n iosIdiom = idiom;\n }\n // iOS has no model in `Platform.constants`; best-effort via `expo-device` (adds no dep,\n // omitted when the module is absent — see device/deviceModel.ts).\n const iosModel = detectNativeModel();\n if (iosModel) ctx.model = iosModel;\n }\n } catch {\n // ignore per-OS constant reads\n }\n\n // Screen dimensions + derived form factor.\n try {\n const screen = Dimensions.get(\"screen\");\n if (screen) {\n if (typeof screen.width === \"number\") ctx.screenWidth = screen.width;\n if (typeof screen.height === \"number\") ctx.screenHeight = screen.height;\n if (typeof screen.scale === \"number\") ctx.screenScale = screen.scale;\n const formFactor = deriveFormFactor(iosIdiom, screen.width, screen.height);\n if (formFactor) ctx.formFactor = formFactor;\n }\n } catch {\n // ignore\n }\n\n // Layout direction.\n try {\n ctx.isRTL = I18nManager.isRTL;\n } catch {\n // ignore\n }\n\n // Locale + time zone via the standard Intl global. Hermes may ship without full Intl,\n // so referencing it can throw ReferenceError — the try/catch covers that too.\n try {\n const resolved = Intl.DateTimeFormat().resolvedOptions();\n if (resolved.locale) ctx.locale = resolved.locale;\n if (resolved.timeZone) ctx.timeZone = resolved.timeZone;\n } catch {\n // Intl unavailable — omit locale/timeZone.\n }\n\n // Best-effort host app version (adds no dependency; omitted when unavailable). An explicit\n // `config.appVersion` overrides this downstream at the merge sites.\n const appVersion = detectAppVersion();\n if (appVersion) ctx.appVersion = appVersion;\n\n return ctx;\n};\n","/**\n * identityRecord — the ONE provenance-carrying shape for an id the kit puts on the wire.\n *\n * WHY IT EXISTS. `session_id` and `device_key` are bare `string`s minted independently by four\n * subsystems, and nothing anywhere recorded WHERE a given id came from. Every id-layer defect this\n * release fixes is a direct consequence of that one omission:\n *\n * • a rejecting storage adapter's in-memory id was indistinguishable from a persisted one, so the\n * kit injected a fresh per-launch join key on every launch — nothing carried `durable`.\n * • an app-OPEN session id could be posted into a field that means the ONBOARDING session, and the\n * caller was told `true` — nothing carried `space`.\n * • an auto-minted `wdev_*` could be injected beside a device id the host demonstrably owns on\n * another surface, silently — nothing carried `source`.\n *\n * WHAT THIS IS, AND WHAT IT DELIBERATELY IS NOT. It is a small record plus a process-wide registry of\n * the ids a HOST supplied. It is NOT a branded-type refactor (`OnboardingSessionId` / `AppSessionId` /\n * `DeviceKey` across every signature) — that is real value and it is deferred, because it touches\n * every file and is not what makes a number correct this week. Nothing here changes the wire.\n *\n * WHY A `Symbol.for` REGISTRY. Same reason as `analytics/currentSession` and `context/deviceId`: tsup\n * inlines a separate copy of a module into each bundle (`.` and `./analytics`), so a plain module\n * `let` would give every bundle its own registry and the cross-surface question this exists to answer\n * (\"did ANY surface in this process get a host-supplied device key?\") would read `no` from the wrong\n * copy. `Symbol.for` resolves to one slot on `globalThis` no matter how many copies exist.\n */\n\n/**\n * Which id space a value belongs to. These are NOT interchangeable, and the whole point of naming\n * them is that a value from one space must never be posted into a field that means another:\n * • `onboarding-session` — the A2A `contextId` for ONE onboarding run.\n * • `app-session` — the per-app-open session id (`app.session_started`).\n * • `device` — the per-install `device_key`; the only cross-family join key.\n */\nexport type IdentitySpace = \"onboarding-session\" | \"app-session\" | \"device\";\n\n/** Where the value came from: the host handed it over, or the kit minted it. */\nexport type IdentitySource = \"host\" | \"auto\";\n\n/** An id plus everything a consumer needs to decide whether it may use it. */\nexport type IdentityRecord = {\n /** The id itself, trimmed. Never empty (a blank input yields no record at all). */\n value: string;\n /** Which id space {@link value} belongs to. */\n space: IdentitySpace;\n /** `host` = the integrator supplied it; `auto` = the kit minted it. */\n source: IdentitySource;\n /**\n * Whether the value was actually PERSISTED (or adopted from persistence), as opposed to living\n * only in this process's memory. A non-durable auto id is a DIFFERENT id on the next launch, which\n * for a `device` value is worse than no value at all: the server counts `min_sessions` by distinct\n * opens grouped on `device_key`, so a per-launch key corrupts the counter rather than leaving it\n * empty. A host-supplied value is durable by definition — the host owns its lifetime.\n */\n durable: boolean;\n};\n\n/** Input to {@link resolveIdentity}. `value` is `unknown` so callers can pass a raw prop through. */\nexport type ResolveIdentityInput = {\n value: unknown;\n space: IdentitySpace;\n source: IdentitySource;\n /** Defaults to `true` for a host value (the host owns its lifetime) and `false` otherwise. */\n durable?: boolean;\n /** Tenant/app id — two tenants in one process never share a provenance entry. */\n scope?: string;\n};\n\n/** Well-known key into the runtime-global symbol registry — one provenance registry per process. */\nconst IDENTITY_PROVENANCE_SLOT: unique symbol = Symbol.for(\"@wireai/activation:identityProvenance\");\n\n/** `\"<space>:<scope>\"` → the HOST-supplied value seen for it. Auto values are never recorded. */\ntype ProvenanceRegistry = { host: Map<string, string> };\n\ntype GlobalWithProvenance = typeof globalThis & {\n [IDENTITY_PROVENANCE_SLOT]?: ProvenanceRegistry;\n};\n\nconst provenanceGlobal = globalThis as GlobalWithProvenance;\n\nconst provenanceRegistry = (): ProvenanceRegistry => {\n const existing = provenanceGlobal[IDENTITY_PROVENANCE_SLOT];\n if (existing) return existing;\n const created: ProvenanceRegistry = { host: new Map() };\n provenanceGlobal[IDENTITY_PROVENANCE_SLOT] = created;\n return created;\n};\n\nconst provenanceKey = (space: IdentitySpace, scope?: string): string =>\n `${space}:${scope ?? \"default\"}`;\n\n/**\n * Build an {@link IdentityRecord} from a candidate value, or `undefined` when there is nothing usable\n * (a non-string, or blank after trimming) — so a caller can `if (record)`-gate instead of guessing\n * whether an empty string means \"none\" or \"not yet\".\n *\n * SIDE EFFECT, deliberate and the reason this is a function and not an object literal: a `host`-sourced\n * record is RECORDED on the process registry, so a later surface can ask {@link hostIdentity} whether\n * this process demonstrably owns a host id in that space. That is what turns \"the kit injected its own\n * key\" from a silent third id space into a warnable condition. Never throws.\n */\nexport const resolveIdentity = (input: ResolveIdentityInput): IdentityRecord | undefined => {\n if (typeof input.value !== \"string\") return undefined;\n const value = input.value.trim();\n if (!value) return undefined;\n const durable = input.durable ?? input.source === \"host\";\n if (input.source === \"host\") {\n provenanceRegistry().host.set(provenanceKey(input.space, input.scope), value);\n }\n return { value, space: input.space, source: input.source, durable };\n};\n\n/**\n * The HOST-supplied id this process has seen for a space, or `undefined` when every surface so far\n * let the kit mint its own. Answers the cross-surface question no single mount can answer alone:\n * \"does this app own a device id that this particular mount was not given?\"\n */\nexport const hostIdentity = (space: IdentitySpace, scope?: string): string | undefined =>\n provenanceRegistry().host.get(provenanceKey(space, scope));\n\n/** Test-only: forget every recorded host identity so a unit test starts from a clean registry. */\nexport const resetIdentityProvenance = (): void => {\n provenanceRegistry().host.clear();\n};\n","/**\n * deviceId — mint a stable, NON-PII, per-install device id the kit owns when the host supplies\n * none. This is the headline of \"device fully automatic\": the analytics façade auto-mints ONE id,\n * persists it via the host's `storage` abstraction, and reuses it on every subsequent open — so\n * `user_context.device_key` is ALWAYS present and the server's review/questionnaire gating +\n * A/B stickiness (both key on `device_key`) work out of the box, with zero host wiring.\n *\n * WHY it is NOT PII and adds NO dependency (the kit's hard rules):\n * The id is a random token generated from `Date.now()` + `Math.random()` — it carries NO hardware\n * identifier, NO IDFA/GAID, NO fingerprint. It is a first-party per-install correlation key, the\n * same privacy category as a first-party cookie: it groups a single install's sessions and cannot\n * identify a person or be joined across apps. There is NO `uuid` (or any) dependency — a\n * time+random scheme is sufficient because the id is minted ONCE and then persisted, so global\n * uniqueness across the fleet is not required (a per-install collision is astronomically unlikely\n * and inconsequential — worst case two installs share a bucket).\n *\n * A host that wants its OWN device id still wins: pass `WireUserContext.deviceKey` and the kit uses\n * that verbatim and never mints/persists an auto id.\n */\n\nimport { resolveIdentity, type IdentityRecord } from \"../identity/identityRecord\";\n\n/** Prefix so an auto-minted id is visibly the kit's (distinguishable from a host-supplied `deviceKey`). */\nexport const AUTO_DEVICE_ID_PREFIX = \"wdev_\";\n\n/** The storage key the façade persists the auto-minted id under (namespaced per `appId`). */\nexport const deviceIdStorageKey = (appId?: string): string =>\n `wireai:analytics:deviceKey:${appId ?? \"default\"}`;\n\n/** One 32-bit base-36 chunk of randomness. Two chunks are concatenated for a wider token. */\nconst randomChunk = (): string =>\n Math.floor(Math.random() * 0x100000000)\n .toString(36)\n .padStart(6, \"0\");\n\n/**\n * Mint a fresh per-install device id. Dependency-free (`Date.now()` + `Math.random()`), never\n * throws, and returns a NEW value on every call — the façade mints ONCE and persists, so this is\n * called at most once per install (then the persisted value is reused). Two random chunks plus the\n * timestamp keep the token wide enough that a per-install collision is not a practical concern.\n */\nexport const mintDeviceId = (): string => {\n const time = Date.now().toString(36);\n return `${AUTO_DEVICE_ID_PREFIX}${time}_${randomChunk()}${randomChunk()}`;\n};\n\n// ── The ONE auto device key per install ──────────────────────────────────────────────────────\n//\n// WHY A REGISTRY AND NOT A `let` PER FACTORY: `createAnalytics` and `createWireActivation` each\n// used to mint their OWN id synchronously and then race a storage read to overwrite it. A host that\n// creates BOTH (the documented wiring: a façade for `track`/`screen`, an activation instance for the\n// gate-firing `wire.track`) therefore had TWO auto ids for ONE install. Every event carried whichever\n// id its own surface minted, so the `device_key` the server groups a device's sessions under — the\n// key `min_sessions`, A/B arm stickiness, and the purchase↔onboarding join all read — SPLIT in two.\n// On a first run both also wrote their own id to the same storage slot, so which one survived was a\n// coin flip. Same failure class as joining two event families on disjoint id spaces: no error, just\n// halved counts and a join that misses.\n//\n// The fix is the pattern this repo already uses for `currentSession` and `activation revalidation`:\n// ONE value in a `globalThis` slot keyed by `Symbol.for(...)`, so every inlined copy of this module\n// (tsup duplicates modules across the `.` / `./analytics` bundles) addresses the SAME registry.\n// Keyed by `appId` so two tenants in one process never share an id.\n//\n// RESIDUAL WINDOW: the storage read is async, so an event emitted in the milliseconds before\n// hydration completes carries the freshly minted id rather than the persisted one. The registry makes\n// every surface agree on WHICH id that is; it does not make the read sync. A caller that can afford to\n// wait (the lifecycle hook's mount effect — see `hydrateAutoDeviceKey`) should await instead: its two\n// events are the ONLY ones the server counts `min_sessions` from, so a per-launch id there is not a\n// millisecond of noise, it is a counter that can never exceed 1.\n\n/** Well-known key into the runtime-global symbol registry — one auto-id registry across every bundle. */\nconst AUTO_DEVICE_KEY_SLOT: unique symbol = Symbol.for(\"@wireai/activation:autoDeviceKeys\");\n\n/** What a hydration settled on: the id, and whether persistence actually CONFIRMED it.\n *\n * `durable: false` means the id lives only in this process's memory — the adapter rejected, threw,\n * or there was no adapter at all. That distinction is the whole of K1: a string is a string, so\n * before 0.13.0 a caller could not tell a persisted id from a per-launch mint, and the auto-join\n * gate (`Boolean(storage)`) was reading the PRESENCE of the prop rather than the SUCCESS of the\n * write. See {@link hydrateDeviceIdentity}. */\ntype HydrationOutcome = { value: string; durable: boolean };\n\n/** The shared registry: the live id per `appId`, the set of appIds whose hydration already started,\n * and the in-flight (or settled) hydration promise per `appId` so a waiter can join it. */\ntype AutoDeviceKeyRegistry = {\n keys: Map<string, string>;\n hydrating: Set<string>;\n pending?: Map<string, Promise<HydrationOutcome>>;\n};\n\ntype GlobalWithDeviceKeys = typeof globalThis & {\n [AUTO_DEVICE_KEY_SLOT]?: AutoDeviceKeyRegistry;\n};\n\nconst deviceKeyGlobal = globalThis as GlobalWithDeviceKeys;\n\nconst autoDeviceKeyRegistry = (): AutoDeviceKeyRegistry => {\n const existing = deviceKeyGlobal[AUTO_DEVICE_KEY_SLOT];\n if (existing) return existing;\n const created: AutoDeviceKeyRegistry = { keys: new Map(), hydrating: new Set() };\n deviceKeyGlobal[AUTO_DEVICE_KEY_SLOT] = created;\n return created;\n};\n\n/** The persistence subset {@link resolveAutoDeviceKey} needs (a strict subset of `WireOnboardingStorage`). */\nexport type DeviceKeyStorage = {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n};\n\n/** Options for {@link resolveAutoDeviceKey}. Omitting `storage` gives a PROCESS-scoped id, not a\n * per-install one — see the caller notes: a caller with no persistence must decide whether a\n * per-launch id is better or worse than no id for its metric. */\nexport interface ResolveAutoDeviceKeyOptions {\n /** Tenant/app id — namespaces both the registry entry and the storage slot. */\n appId?: string;\n /** Host persistence. Present → the id survives launches. Absent → process-scoped only. */\n storage?: DeviceKeyStorage;\n}\n\n/**\n * Start (or join) the SINGLE-FLIGHT storage read for `appId` and resolve to the {@link HydrationOutcome}\n * it settles on. The promise is parked on the registry so a later `hydrateAutoDeviceKey` awaits the\n * SAME read instead of starting a second one. Never rejects: any storage failure resolves to the live\n * id with `durable: false`.\n *\n * TWO OUTCOMES, NOT ONE STRING:\n * • ADOPTED (`durable: true`) — a persisted id was read back, or the freshly minted one was\n * written successfully. The next launch will see the same id.\n * • DEGRADED (`durable: false`) — the adapter rejected, threw, or returned nothing and then failed\n * the write. The id is real but PROCESS-scoped, so anything that\n * counts a device across launches must refuse it.\n *\n * A DEGRADED outcome also drops the registry latches so the NEXT caller starts a fresh read (K8). A\n * cold-boot storage lock is transient; caching it as a verdict for the process lifetime turned a\n * one-second problem into a whole-launch one, and nothing ever retried.\n */\nconst startHydration = (\n registry: AutoDeviceKeyRegistry,\n appId: string,\n storage: DeviceKeyStorage,\n minted: string,\n): Promise<HydrationOutcome> => {\n if (!registry.pending) registry.pending = new Map();\n const existing = registry.pending.get(appId);\n if (existing) return existing;\n\n const slot = deviceIdStorageKey(appId);\n const degraded = (): HydrationOutcome => ({ value: registry.keys.get(appId) ?? minted, durable: false });\n const adopted = (value: string): HydrationOutcome => ({ value, durable: true });\n let run: Promise<HydrationOutcome>;\n try {\n run = Promise.resolve(storage.getItem(slot))\n .then((saved) => {\n const persisted = typeof saved === \"string\" && saved.trim() ? saved.trim() : undefined;\n if (persisted) {\n registry.keys.set(appId, persisted);\n return adopted(persisted);\n }\n // First run on this install: persist the id we just minted so the next launch adopts it.\n // ONLY a resolved write earns `durable` — a rejected one leaves the id in memory alone.\n return Promise.resolve(storage.setItem(slot, minted)).then(\n () => adopted(registry.keys.get(appId) ?? minted),\n degraded,\n );\n })\n .catch(degraded);\n } catch {\n // A storage adapter that throws synchronously — degrade to the in-memory id.\n run = Promise.resolve(degraded());\n }\n registry.pending.set(appId, run);\n // Retry-on-failure (K8): release the latches once a degraded outcome settles, so a later caller\n // is not permanently bound to one bad read. Registered AFTER the `set` above, so the clean-up can\n // never race ahead of the entry it is clearing.\n void run.then((outcome) => {\n if (outcome.durable) return;\n registry.pending?.delete(appId);\n registry.hydrating.delete(appId);\n });\n return run;\n};\n\n/**\n * The ONE auto-minted `device_key` for an install, shared by every kit surface.\n *\n * SYNCHRONOUS by contract (a fire-and-forget event path cannot await): returns the current live id\n * immediately, minting one on first call. When `storage` is supplied it also kicks off a SINGLE\n * hydration per `appId` that adopts the persisted id (or persists the freshly minted one). Callers\n * should call this per EVENT rather than caching the return value, so an event built after hydration\n * carries the persisted id.\n *\n * A host-supplied `deviceKey` always wins — callers must short-circuit before reaching this.\n * Never throws: a missing, hung, or rejecting storage adapter degrades to the in-memory id.\n */\nexport const resolveAutoDeviceKey = (opts: ResolveAutoDeviceKeyOptions = {}): string => {\n const registry = autoDeviceKeyRegistry();\n const appId = opts.appId ?? \"default\";\n\n let id = registry.keys.get(appId);\n if (!id) {\n id = mintDeviceId();\n registry.keys.set(appId, id);\n }\n\n const storage = opts.storage;\n // Single-flight: the FIRST caller with storage owns hydration for this appId; later callers just\n // read whatever the registry currently holds.\n if (storage && !registry.hydrating.has(appId)) {\n registry.hydrating.add(appId);\n void startHydration(registry, appId, storage, id);\n }\n\n return registry.keys.get(appId) ?? id;\n};\n\n/**\n * The AWAITABLE sibling of {@link resolveAutoDeviceKey}: resolve to the auto `device_key` AFTER the\n * persisted id has been read back (or written, on a first run), so the caller stamps the id this\n * install will keep rather than the one that was minted a millisecond ago.\n *\n * WHY IT EXISTS: `resolveAutoDeviceKey` is synchronous by contract, so a caller firing at mount got\n * the freshly minted id and the persisted one landed milliseconds later. For most events that is\n * noise. For `app.session_started` it is the whole metric: the server computes `min_sessions` by\n * counting distinct opens grouped by `device_key`, so a per-launch key there makes the counter\n * structurally incapable of exceeding 1, and it splits `first_open` off from every event that\n * follows it. Only a caller that can afford one storage read should use this; the fire-and-forget\n * event paths must stay on the sync function.\n *\n * Never throws or rejects: a missing, hung, or rejecting adapter resolves to the in-memory id, and\n * with no `storage` it resolves immediately (there is nothing to hydrate from).\n */\nexport const hydrateAutoDeviceKey = async (\n opts: ResolveAutoDeviceKeyOptions = {},\n): Promise<string> => (await hydrateDeviceIdentity(opts))?.value ?? resolveAutoDeviceKey(opts);\n\n/**\n * The PROVENANCE-CARRYING sibling of {@link hydrateAutoDeviceKey}: the same awaited read, but it\n * answers \"is this id one this install will KEEP?\" instead of only \"what is the id?\".\n *\n * WHY IT EXISTS (K1). `<WireOnboarding>` gated auto-injection on `Boolean(storage)` — the presence of\n * the prop — because a string carries no provenance and there was nothing better to gate on. A\n * REJECTING adapter therefore injected a fresh `wdev_*` on every launch: strictly worse than\n * injecting nothing, since the server counts `min_sessions` by distinct opens grouped on `device_key`,\n * so a per-launch key corrupts that counter AND inflates distinct-device counts. Callers that write a\n * key onto the wire as a cross-launch join must read `durable` and refuse a `false`.\n *\n * Resolves `undefined` only when there is no usable id at all. With no `storage` it resolves\n * immediately with `durable: false` — a process-scoped id is exactly what \"no persistence\" means.\n * Never throws or rejects.\n */\nexport const hydrateDeviceIdentity = async (\n opts: ResolveAutoDeviceKeyOptions = {},\n): Promise<IdentityRecord | undefined> => {\n // Mint + register synchronously first, so a waiter and a concurrent sync caller share ONE id.\n const id = resolveAutoDeviceKey(opts);\n const appId = opts.appId ?? \"default\";\n const record = (value: string, durable: boolean): IdentityRecord | undefined =>\n resolveIdentity({ value, space: \"device\", source: \"auto\", durable, scope: appId });\n\n if (!opts.storage) return record(id, false);\n const registry = autoDeviceKeyRegistry();\n const pending = registry.pending?.get(appId);\n // No pending entry means a previous hydration already settled DEGRADED and released its latches\n // (see `startHydration`), so the live id is the in-memory one — real, but not durable.\n if (!pending) return record(registry.keys.get(appId) ?? id, false);\n const outcome = await pending;\n return record(outcome.value, outcome.durable);\n};\n\n/** Test-only: forget every auto id + hydration flag so a unit test starts from a clean registry. */\nexport const resetAutoDeviceKeys = (): void => {\n const registry = autoDeviceKeyRegistry();\n registry.keys.clear();\n registry.hydrating.clear();\n registry.pending?.clear();\n};\n","/**\n * warnInDev — the ONE developer-warning primitive.\n *\n * The kit warns a developer in four places (the onboarding host, the env-config helper, the analytics\n * façade, the current-session registry) and until 0.13.0 each carried its own copy of the same five\n * lines. Three were byte-identical; the fourth differed only by returning whether it actually warned.\n * Four copies of a guard is four chances for one of them to drift out of the `__DEV__` gate, which is\n * the failure that matters: a warning that runs in production is a string built for nobody.\n *\n * ON THE TREE-SHAKING NOTE THIS REPLACES: `analytics/currentSession` used to justify its copy as\n * keeping the module import-free for the tree-shaken `./analytics` bundle. That rationale had already\n * lapsed — the module imports `makeSessionId` from `./reportClientEvent` — and this module has no\n * imports of its own, so it adds one leaf to the graph and nothing to the bundle. The `treeShake`\n * canary still holds the real guarantee (the analytics graph reaches no UI module).\n */\n\n/** RN sets this global; absent under node/SSR. Read defensively, never assumed. */\ndeclare const __DEV__: boolean | undefined;\n\n/**\n * Emit a one-line developer warning, but ONLY in a dev build (RN `__DEV__`). No-op in prod/tests.\n *\n * Returns whether it ACTUALLY warned, which a caller holding a once-flag must honour: marking\n * \"already warned\" after a no-op would burn the single warning in production, and the one dev build\n * that needed it would then run silent.\n */\nexport const warnInDev = (message: string): boolean => {\n if (typeof __DEV__ !== \"undefined\" && __DEV__ && typeof console !== \"undefined\" && console.warn) {\n console.warn(message);\n return true;\n }\n return false;\n};\n","/**\n * currentSession — a tiny registry of the CURRENT per-open `session_id`.\n *\n * WHY it exists (kills the phantom-session): the per-open emitters (`reportSessionStart` and the\n * `useSessionStart` / `useLifecycleEvents` hooks) mint a fresh `session_id` for each app-open and\n * post `app.session_started` with it — so the SERVER knows that id. But other client paths\n * (`identify`, host `app_event`s through the analytics façade) used to reference a DIFFERENT id\n * (a frozen per-instance id), which the server had never seen, so it back-filled a synthetic\n * `session_started` — inflating session counts (the \"phantom-session\" bug).\n *\n * This registry is the single seam that lets those paths reuse the LIVE per-open session id the\n * server already ingested. `reportSessionStart` writes the current id here on every open; the façade\n * reads it so `identify`/app-events correlate to the real session instead of minting a phantom.\n *\n * ── WHY A globalThis SLOT, NOT A PLAIN MODULE VARIABLE ────────────────────────────────────────\n * This module is exported from TWO package entry points — the main `.` bundle (`src/index.ts`) and\n * the `./analytics` subpath (`src/analytics/index.ts`). Under `dist` resolution (node `import`/\n * `require`, which is how tests, SSR and some tooling load the kit) tsup inlines a SEPARATE copy of\n * this module into each bundle, so a plain `let` would give the SETTER (reached via `.` →\n * `reportSessionStart`) and the READER (reached via `./analytics` → façade / `userIdentity`) TWO\n * different variables: the reader would see `undefined` even after an open set the id, and gating\n * would fire under a null session id. On-device this was masked only because Metro's `react-native`\n * export condition resolves both subpaths back to this one `src/` file (a single instance) — a\n * bundler accident, not a guarantee.\n *\n * The bundler-agnostic fix: keep the ONE live value in a well-known `globalThis` slot keyed by a\n * `Symbol.for(...)`. `Symbol.for` uses the runtime-global symbol registry, so every inlined copy of\n * this module resolves the SAME symbol and reads/writes the SAME slot — one identity no matter how\n * many times the module is duplicated across bundles. `globalThis` is present and identical in\n * Hermes/React Native, Node and SSR (we never touch `window`), so this is safe on every host.\n *\n * PROCESS-LOCAL, NOT PERSISTED: the slot lives on the runtime global, so it tracks the CURRENT\n * process's open and a fresh open overwrites it. There is no cross-launch state.\n * `resetCurrentSessionId` clears the slot so a unit test starts from a clean registry.\n *\n * ── WHY `ensureCurrentSessionId` EXISTS (the silent-drop contract) ─────────────────────────────\n * The server's event model declares `session_id: str = Field(min_length=1)` — REQUIRED, non-empty.\n * `POST /v1/events` validates each event inside a try/except that increments a `skipped` counter and\n * still returns HTTP 200. So an event posted without a `session_id` is accepted by the wire and\n * DISCARDED by the server, and a fire-and-forget client can never learn it happened. That is the\n * worst of both: no error, no data. Screen tracking in a host that never mounted the lifecycle hook\n * fell into exactly that hole — every screen view posted, 200'd, and dropped.\n *\n * `ensureCurrentSessionId` closes it: it returns the registered id when an open HAS been registered\n * (unchanged behaviour for every host that fires `reportSessionStart` first), and otherwise mints one,\n * REGISTERS it, and returns it — so every later event in the process correlates to that same id\n * instead of each emitting its own orphan. A minted id is a fallback, not a substitute for a real\n * app-open: it warns once in dev, naming the fix.\n */\nimport { makeSessionId } from \"./reportClientEvent\";\n// The shared primitive returns whether it ACTUALLY warned, which the once-flag below depends on:\n// marking \"already warned\" after a prod no-op would burn the single warning and leave the one dev\n// build that needed it silent. (The old local copy justified itself as keeping this module\n// import-free for the tree-shaken analytics bundle; that had already lapsed — it imports\n// `makeSessionId` right here — and `utils/warnInDev` has no imports of its own.)\nimport { warnInDev } from \"../utils/warnInDev\";\n\n/**\n * Well-known key into the runtime-global symbol registry. `Symbol.for` (NOT a plain `Symbol()`) is\n * what makes this cross-bundle: it returns the SAME symbol for the same string across every copy of\n * this module, so duplicated inlined copies all address one slot.\n */\nconst CURRENT_SESSION_ID_SLOT: unique symbol = Symbol.for(\n \"@wireai/activation:currentSessionId\",\n);\n\ntype GlobalWithSlot = typeof globalThis & {\n [CURRENT_SESSION_ID_SLOT]?: string | undefined;\n};\n\nconst globalSlot = globalThis as GlobalWithSlot;\n\n/**\n * Record the current per-open `session_id`. Called by `reportSessionStart` when it emits an\n * app-open. A blank / non-string id is ignored (the previous id stays current). Idempotent.\n */\nexport const setCurrentSessionId = (id: string | undefined): void => {\n if (typeof id === \"string\" && id.length > 0) {\n globalSlot[CURRENT_SESSION_ID_SLOT] = id;\n }\n};\n\n/** The current per-open `session_id`, or `undefined` when no app-open has been registered yet. */\nexport const getCurrentSessionId = (): string | undefined =>\n globalSlot[CURRENT_SESSION_ID_SLOT];\n\n/** Test-only: forget the current session id so a unit test starts from a clean registry. */\nexport const resetCurrentSessionId = (): void => {\n globalSlot[CURRENT_SESSION_ID_SLOT] = undefined;\n};\n\n/** The one-time message. Hoisted so a prod mint does not rebuild a string nobody will read. */\nconst MINT_WARNING =\n \"[wireai] No app-open session was registered, so a session id was minted for this event \" +\n \"(the server drops an event that has no session_id, and still answers 200). Mount \" +\n \"useLifecycleEvents at your app root so events correlate to a real app-open.\";\n\n/**\n * \"Have we already warned about a minted session id?\" — its OWN `Symbol.for` slot, for the same\n * cross-bundle reason as the id itself: a plain module `let` would warn once per inlined copy, i.e.\n * once per bundle, not once per process. NOT cleared by `resetCurrentSessionId`: \"warn once\" is a\n * process-lifetime promise, and a test that resets the id between mints is still one process.\n */\nconst MINT_WARNED_SLOT: unique symbol = Symbol.for(\n \"@wireai/activation:currentSessionIdMintWarned\",\n);\n\ntype GlobalWithWarnSlot = typeof globalThis & { [MINT_WARNED_SLOT]?: boolean };\n\nconst warnSlot = globalThis as GlobalWithWarnSlot;\n\n/**\n * The current per-open `session_id`, MINTING and registering one when no app-open has been\n * registered yet. Always returns a non-empty string. Idempotent (a second call returns the same id)\n * and never throws.\n *\n * Use this on every path that puts a `session_id` on the wire. The server REQUIRES a non-empty\n * `session_id` and drops the event otherwise while still answering 200 (see the module header), so\n * \"no id yet\" must never mean \"send it without one\".\n *\n * BACKWARD-COMPATIBLE BY CONSTRUCTION: when `reportSessionStart` / `useLifecycleEvents` has already\n * registered the real per-open id, this is `getCurrentSessionId()` and nothing changes. It only ever\n * mints in the case that used to produce a silently discarded event.\n *\n * A mint means the host never registered an app-open, so the minted id is one the server has not\n * seen a `session_started` for — the events land, but the session is thinner than a real open.\n * Hence the one-time dev warning naming the fix (mount `useLifecycleEvents` at the app root).\n */\nexport const ensureCurrentSessionId = (): string => {\n const existing = globalSlot[CURRENT_SESSION_ID_SLOT];\n if (typeof existing === \"string\" && existing.length > 0) return existing;\n const minted = makeSessionId();\n globalSlot[CURRENT_SESSION_ID_SLOT] = minted;\n if (!warnSlot[MINT_WARNED_SLOT] && warnInDev(MINT_WARNING)) {\n warnSlot[MINT_WARNED_SLOT] = true;\n }\n return minted;\n};\n","/**\n * Session-id persistence — the kit caching its OWN correlation seed across app kills.\n *\n * WHY: the session id is minted per mount and forwarded to the backend as the A2A\n * `contextId` (see WireOnboarding). Without persistence, an app KILL mid-onboarding\n * mints a NEW id on relaunch — the server counts a second `session_started` and the\n * orphaned first session reads as a phantom \"drop\", inflating the funnel's `started`\n * denominator. Persisting `{ id, ts }` and reusing a still-fresh id keeps a\n * kill-and-relaunch a SINGLE session in analytics.\n *\n * SCOPE: this persists the correlation seed ONLY — never answers. Answer persistence\n * stays a host concern via `onComplete` (the kit/host boundary is unchanged).\n *\n * The host injects the storage via the `storage` prop (an AsyncStorage-compatible\n * subset), keeping the kit dependency-free: an MMKV wrapper and AsyncStorage itself\n * both fit. Every operation is best-effort — a broken or hung storage must NEVER\n * break (or indefinitely gate) onboarding: reads race a short timeout, writes and\n * removes swallow all errors.\n */\nimport { makeSessionId } from \"../analytics/reportClientEvent\";\n\n/**\n * The storage the host injects. Deliberately the AsyncStorage-compatible subset so\n * `@react-native-async-storage/async-storage` can be passed as-is, and an MMKV (or\n * any other) wrapper is three one-line methods.\n */\nexport type WireOnboardingStorage = {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n};\n\n/**\n * Matches the backend's session TTL (SESSION_TTL_SECONDS = 3600): an id older than\n * this can't be resumed server-side anyway, so the client mints fresh past it.\n */\nexport const DEFAULT_SESSION_TTL_MS = 3_600_000;\n\n/** Ceiling on the storage read — a hung adapter degrades to a fresh mint, never a stuck gate. */\nconst READ_TIMEOUT_MS = 1_500;\n\n/** Storage key for an app's cached session, e.g. `wireai:session:acme`. */\nexport const sessionStorageKey = (appId: string): string => `wireai:session:${appId}`;\n\ntype PersistedSession = { id: string; ts: number };\n\n/** Resolved session for a mount: the id to use + whether it was restored from storage. */\nexport type LoadedSession = {\n id: string;\n /** True when a stored, still-fresh id was reused — the flow resumes instead of starting. */\n resumed: boolean;\n};\n\nconst withTimeout = <T>(p: Promise<T>, ms: number): Promise<T | undefined> => {\n let timer: ReturnType<typeof setTimeout>;\n const timeout = new Promise<undefined>((resolve) => {\n timer = setTimeout(() => resolve(undefined), ms);\n });\n // Clear the timer once the race settles, so a won read doesn't leave a ≤ms no-op\n // timer holding the closure alive.\n return Promise.race([p, timeout]).finally(() => clearTimeout(timer));\n};\n\nconst parsePersisted = (raw: string | null | undefined): PersistedSession | undefined => {\n if (!raw) return undefined;\n try {\n const parsed: unknown = JSON.parse(raw);\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n typeof (parsed as PersistedSession).id === \"string\" &&\n typeof (parsed as PersistedSession).ts === \"number\"\n ) {\n return parsed as PersistedSession;\n }\n } catch {\n // Corrupt entry → treat as absent; the caller mints fresh and overwrites it.\n }\n return undefined;\n};\n\n/**\n * Resolve the session id for this mount: reuse the stored one while it's fresh\n * (→ `resumed: true`), else mint via `makeSessionId`, persist it, and start clean.\n * Never throws; never hangs past the read timeout.\n */\nexport const loadPersistedSession = async (\n storage: WireOnboardingStorage,\n key: string,\n ttlMs: number = DEFAULT_SESSION_TTL_MS,\n): Promise<LoadedSession> => {\n let stored: PersistedSession | undefined;\n try {\n stored = parsePersisted(await withTimeout(storage.getItem(key), READ_TIMEOUT_MS));\n } catch {\n stored = undefined;\n }\n if (stored && Date.now() - stored.ts < ttlMs) {\n return { id: stored.id, resumed: true };\n }\n const id = makeSessionId();\n savePersistedSession(storage, key, id);\n return { id, resumed: false };\n};\n\n/**\n * Read the persisted session WITHOUT minting a fresh one (unlike `loadPersistedSession`).\n * Returns the stored `{ id, ts }` or `undefined` when absent/corrupt/timed-out. Used by the\n * post-onboarding `identifyOnboarding` helper to recover the contextId to bind a user to.\n * Never throws; never hangs past the read timeout.\n */\nexport const peekPersistedSession = async (\n storage: WireOnboardingStorage,\n key: string,\n): Promise<{ id: string; ts: number } | undefined> => {\n try {\n return parsePersisted(await withTimeout(storage.getItem(key), READ_TIMEOUT_MS));\n } catch {\n return undefined;\n }\n};\n\n/** Persist `{ id, ts }` under `key` — fire-and-forget, all errors swallowed. */\nexport const savePersistedSession = (\n storage: WireOnboardingStorage,\n key: string,\n id: string,\n): void => {\n try {\n void storage.setItem(key, JSON.stringify({ id, ts: Date.now() })).catch(() => {});\n } catch {\n // Best-effort: a failed write just means the next launch starts a fresh session.\n }\n};\n\n/** Remove the cached id (fired on completion) — fire-and-forget, all errors swallowed. */\nexport const clearPersistedSession = (storage: WireOnboardingStorage, key: string): void => {\n try {\n void storage.removeItem(key).catch(() => {});\n } catch {\n // Best-effort.\n }\n};\n\n/**\n * The opt-in decision for `WireOnboarding.handleComplete`: given the host's\n * `retainSessionOnComplete` opt-in, whether a completion should CLEAR the persisted seed.\n * (The caller still gates on `storage` being present — this only encodes the opt-in axis, so the\n * legacy `if (storage) clearPersistedSession(...)` guard stays byte-for-byte for a host that does\n * not opt in.)\n *\n * - undefined / false (the default) → `true`: clear on completion, so the NEXT onboarding on this\n * device mints a fresh session. This is the legacy single-stage behavior (e.g. Myelino).\n * - true → `false`: LEAVE the seed in place so a same-signup re-entry/remount within the TTL\n * resumes the SAME session (one funnel start) instead of minting a phantom second `started`.\n * Freshness for a genuinely new run is then governed by the TTL (past `sessionTtlMs` → fresh\n * mint) and an explicit new-run signal (a changed `persistKey`).\n */\nexport const shouldClearOnComplete = (retainSessionOnComplete: boolean | undefined): boolean =>\n !retainSessionOnComplete;\n","/**\n * User identity — bind an onboarding session to the HOST's own user id so the funnel can\n * be reconciled to real users later (console sessions ↔ your user table / GA4 users).\n *\n * The id is an OPAQUE PSEUDONYMOUS STRING the host owns — its internal user id, NOT an\n * email/name/phone. Same host-injection philosophy as `storage` and `userContext`: the kit\n * mints nothing and reads nothing; the host passes what it wants. Dependency-free.\n *\n * Three binding moments (see WireOnboarding + the README \"User identity\" section):\n * 1. MOUNT — pass `userId` and it rides the A2A session-start metadata; the server\n * binds it when it creates the session.\n * 2. MID-SESSION— the user registers DURING onboarding: change the `userId` prop and the\n * kit emits an `identify` client event that attaches the id to the live\n * session (late binding — the key scenario).\n * 3. POST-FLOW — the user registers AFTER onboarding: call `identifyOnboarding(...)` with\n * the same host storage (it recovers the persisted contextId, before completion\n * clears it) or, more reliably, the `contextId` you captured from the\n * `started`/`resumed` `onEvent` (both events carry a `contextId` field).\n *\n * ⚠️ NO PII. Pass an opaque id (or a hash), never a raw email/name/phone. The id is capped at\n * {@link USER_ID_MAX_LENGTH} chars (longer ids are truncated, not rejected).\n */\nimport { getCurrentSessionId } from \"../analytics/currentSession\";\nimport { reportClientEvent } from \"../analytics/reportClientEvent\";\nimport {\n peekPersistedSession,\n sessionStorageKey,\n type WireOnboardingStorage,\n} from \"../session/persistedSession\";\n\n/** Max accepted user-id length. Longer strings are truncated (never rejected). Keep in sync\n * with the server's `USER_ID_MAX_LENGTH` (analytics/events.py). */\nexport const USER_ID_MAX_LENGTH = 128;\n\n/**\n * Normalize a host-supplied user id: trim, drop empty, and cap at {@link USER_ID_MAX_LENGTH}.\n * Returns `undefined` for a missing/blank/non-string value so callers can `if (id)`-gate.\n * PII is a host concern — this only bounds length, it does not (and cannot) detect an email.\n */\nexport const sanitizeUserId = (raw: unknown): string | undefined => {\n if (typeof raw !== \"string\") return undefined;\n const trimmed = raw.trim();\n if (!trimmed) return undefined;\n return trimmed.length > USER_ID_MAX_LENGTH ? trimmed.slice(0, USER_ID_MAX_LENGTH) : trimmed;\n};\n\n/**\n * A permissive email-SHAPE test (`local@domain.tld`) — NOT an RFC validator. Its ONE job is to\n * catch the common integration mistake of binding a RAW EMAIL as the opaque `user_id`: that leaks\n * PII into the top-level id (which the server treats as an opaque key and may surface), when the\n * email belongs in the opt-in `user_context.user_email` field instead. `identify()` uses this to\n * refuse an email-shaped id (with a dev warning) unless the host opts in explicitly. Trims first.\n */\nexport const looksLikeEmail = (value: unknown): boolean =>\n typeof value === \"string\" && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value.trim());\n\n/** Options for {@link identifyOnboarding}. */\nexport type IdentifyOnboardingOptions = {\n /** Tenant transport, same shape as `WireOnboardingConfig` (only these two fields are used). */\n config: { serverUrl: string; apiKey: string };\n /** The host's opaque user id to bind. Trimmed + capped; NO PII. */\n userId: string;\n /**\n * The onboarding session id to bind to (the A2A contextId) — the `contextId` field carried on\n * the `started`/`resumed` `onEvent`. Pass this when you captured it there. Required after the\n * flow COMPLETED, since completion clears the persisted session. Wins over the storage lookup.\n */\n contextId?: string;\n /**\n * The SAME host storage you passed to `<WireOnboarding storage={…} />`. When `contextId` is\n * omitted, the helper reads the persisted contextId from it (works while the session is still\n * persisted — i.e. dropped or mid-flow, before completion clears it).\n */\n storage?: WireOnboardingStorage;\n /** App id, to derive the default storage key `wireai:session:<appId>` when reading from storage. */\n appId?: string;\n /** Storage key override — pass the same `persistKey` you gave `<WireOnboarding>`, if any. */\n persistKey?: string;\n /**\n * OPT-IN LAST RESORT, default `false`. When no ONBOARDING session can be resolved (no `contextId`,\n * nothing in `storage`), bind the user to the LIVE PER-OPEN app session instead and return\n * `\"app_session\"`.\n *\n * ⚠️ These are two different id spaces sharing one wire field. An onboarding session id is the A2A\n * `contextId`; a per-open id is what `app.session_started` registers. The server's onboarding funnel\n * groups by `session_id`, so a per-open id posted here does not attach the user to their onboarding\n * — it writes a row nothing in that funnel can join. Until 0.13.0 this happened SILENTLY and\n * returned `true`, in exactly the documented post-completion case (completion clears the persisted\n * session), so the funnel stayed unattributed while the host was told it had worked.\n *\n * Turn it on only if binding the id to *some* session the server saw is genuinely worth more to you\n * than knowing the onboarding bind failed — and read the return value, which now says which it was.\n */\n allowAppSessionFallback?: boolean;\n};\n\n/**\n * What {@link identifyOnboarding} bound, and to WHICH id space — because `true` could not say.\n *\n * • `\"onboarding\"` — bound to the A2A `contextId`. This is the one that attributes the funnel.\n * • `\"app_session\"` — bound to the live per-open app session, via `allowAppSessionFallback`. The\n * server saw that session, but it is not this user's onboarding.\n * • `false` — nothing was dispatched (no user id, no server url, no resolvable session).\n *\n * ⚠️ 0.13.0 widened this from `boolean`. `\"onboarding\"` is truthy, so an `if (await identify…)` still\n * behaves identically; only an explicit `: boolean` annotation needs updating.\n */\nexport type IdentifyOnboardingBinding = \"onboarding\" | \"app_session\" | false;\n\n/**\n * Attach a host user id to an onboarding session AFTER the fact (post-registration), by sending\n * an `identify` client event to `/v1/events`. Resolves the contextId from an explicit\n * `contextId` or, failing that, from the persisted session in the host `storage`.\n *\n * Fire-and-forget under the hood (never throws, never blocks onboarding). Resolves to the\n * {@link IdentifyOnboardingBinding} that says WHICH id space was bound, or `false` when nothing could\n * be (no user id, no server url, or no resolvable session).\n */\nexport const identifyOnboarding = async (\n opts: IdentifyOnboardingOptions,\n): Promise<IdentifyOnboardingBinding> => {\n const userId = sanitizeUserId(opts.userId);\n if (!userId || !opts.config?.serverUrl) return false;\n\n let contextId = opts.contextId?.trim() || undefined;\n if (!contextId && opts.storage) {\n const key = opts.persistKey ?? (opts.appId ? sessionStorageKey(opts.appId) : undefined);\n if (key) {\n const stored = await peekPersistedSession(opts.storage, key);\n contextId = stored?.id;\n }\n }\n let space: Exclude<IdentifyOnboardingBinding, false> = \"onboarding\";\n // The OPT-IN last resort (K3). Until 0.13.0 this ran unconditionally: with no captured contextId\n // it posted the LIVE PER-OPEN session id in the `session_id` field — which on this endpoint means\n // the ONBOARDING session — and then returned `true`. Two disjoint id spaces share that field, so\n // the row it wrote could never join the onboarding funnel, and the host got a success signal for a\n // bind that had not happened. It is now off unless the caller asks, and when it does fire it says\n // so in the return value instead of impersonating an onboarding bind.\n if (!contextId && opts.allowAppSessionFallback) {\n contextId = getCurrentSessionId();\n space = \"app_session\";\n }\n if (!contextId) return false;\n\n reportClientEvent(\n { serverUrl: opts.config.serverUrl, apiKey: opts.config.apiKey },\n { event_type: \"identify\", session_id: contextId, user_id: userId },\n );\n return space;\n};\n","/**\n * userContext — the ONE extensible object a host passes once and the kit flows into every\n * analytics event's `user_context` (plus the top-level opaque `user_id`).\n *\n * WHY it exists: hosts already hand the kit fragments of \"who this user is\" — `config.appVersion`,\n * `useSessionStart({ deviceKey, userId })`, `<WireOnboarding userContext={…} />` — but there was no\n * single object that carries app version + device key + user id + (opt-in) email + arbitrary extras\n * together, with one precedence rule, into every event. `WireUserContext` is that object;\n * `resolveUserContext` is the pure merge that turns it into the wire shape.\n *\n * PRECEDENCE (the one rule): an explicit `WireUserContext` field WINS over the #42 auto-detected\n * `device`/`appVersion`. A missing field is OMITTED, never sent empty.\n *\n * WHERE EACH FIELD LANDS (deliberate separation so nothing leaks across buckets):\n * • `userId` → the event's TOP-LEVEL opaque `user_id` (via `sanitizeUserId`). NEVER the bucket.\n * • `userEmail` → its OWN key `user_context.user_email`. NEVER merged into `userId`. OPT-IN PII.\n * • `deviceKey` → `user_context.device_key` (the server's `_event_device_key` reads it there).\n * • `appVersion`→ `user_context.app_version` (and returned as `appVersion` for `device.appVersion`).\n * • `extra` → NAMESPACED under a `custom.` key prefix, coerced to scalars, so a host extra can\n * never collide with a reserved `user_context` key.\n *\n * DEPENDENCY-FREE: the only import is the kit's own `sanitizeUserId`. The optional email hash is a\n * dependency-free FNV-1a fold (see {@link hashEmailFnv1a}) — no crypto library, no async.\n */\nimport { sanitizeUserId } from \"../identity/userIdentity\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\n\n/**\n * The single, extensible user-context object. A host passes it ONCE (at analytics init) and may\n * update it post-mount (e.g. attach `userId`/`userEmail` at login) via `setUserContext(partial)`.\n * Every field is optional; missing fields are omitted from the wire payload.\n */\nexport interface WireUserContext {\n /**\n * Host app version, e.g. \"1.4.2\". EXPLICIT — wins over the #42 auto-detected `device.appVersion`.\n * Lands in `user_context.app_version`. Omitted when neither this nor auto-detect yields a version.\n */\n appVersion?: string;\n /**\n * A stable, non-PII device id the host owns. Lands in `user_context.device_key` (NOT `session_id`),\n * where the server groups a device's sessions. Host-supplied; the kit never mints or reads one.\n */\n deviceKey?: string;\n /**\n * The host's OPAQUE PSEUDONYMOUS user id (their internal id — NOT an email/name/phone). Sanitized +\n * capped (see `sanitizeUserId`) and placed on the event's top-level `user_id`. NEVER the bucket.\n */\n userId?: string;\n /**\n * OPT-IN PII. The user's email, its OWN field (`user_context.user_email`) — NEVER merged into\n * `userId`. The kit NEVER auto-collects this; a host passes it only WITH the user's consent (EU\n * users: treat as personal data). For a non-reversible form, set {@link hashEmail} `true` (the kit\n * folds it with a dependency-free hash and stamps `user_context.user_email_hashed: true`), OR\n * pre-hash host-side with a cryptographic digest and pass that here with `hashEmail` falsy.\n */\n userEmail?: string;\n /**\n * When `true`, {@link userEmail} is folded with the kit's dependency-free {@link hashEmailFnv1a}\n * before it leaves the device, and `user_context.user_email_hashed` is set `true`. NOTE: FNV-1a is\n * a lightweight NON-cryptographic fold (obfuscation, not a secure digest). For a cryptographic\n * hash, compute it host-side (e.g. SHA-256 via `expo-crypto`) and pass the digest as `userEmail`\n * with `hashEmail` falsy. Default: raw email is sent as-is (opt-in already gated it upstream).\n */\n hashEmail?: boolean;\n /**\n * Arbitrary host context (signup method, referral, plan tier…). Each value is coerced to a scalar\n * (`string | number | boolean`; non-scalars and non-finite numbers are DROPPED) and NAMESPACED\n * under a `custom.` key prefix in `user_context` (e.g. `user_context[\"custom.referral\"]`) so it can\n * never collide with a reserved key. No raw PII — use {@link userEmail} for email.\n */\n extra?: Record<string, string | number | boolean>;\n}\n\n/**\n * The wire-shaped result of {@link resolveUserContext}. `userContext` is the non-PII/opt-in-PII\n * bucket stamped onto the event; `userId` is the top-level opaque id; `appVersion`/`deviceKey` are\n * echoed for callers that also place them elsewhere (e.g. `device.appVersion`). Absent fields are\n * omitted so a caller can spread this without sending empties.\n */\nexport interface ResolvedUserContext {\n /** The opaque, sanitized user id → the event's top-level `user_id`. Omitted when unset/blank. */\n userId?: string;\n /** The stable device id → `user_context.device_key`. Omitted when unset. */\n deviceKey?: string;\n /** The effective app version (explicit > auto-detected) → `user_context.app_version`. */\n appVersion?: string;\n /** The `user_context` bucket (device_key, app_version, user_email[+ _hashed], custom.*). */\n userContext?: Record<string, string | number | boolean>;\n}\n\n/** The prefix applied to every host `extra` key so it can never collide with a reserved key. */\nexport const EXTRA_KEY_PREFIX = \"custom.\" as const;\n\n/** A finite scalar the wire accepts. Non-finite numbers (NaN/Infinity) are NOT scalars here. */\nexport const isWireScalar = (value: unknown): value is string | number | boolean => {\n const t = typeof value;\n if (t === \"string\" || t === \"boolean\") return true;\n if (t === \"number\") return Number.isFinite(value as number);\n return false;\n};\n\n/**\n * Fold an email to a stable, dependency-free 32-bit FNV-1a hex token (lowercased + trimmed first so\n * the same address always folds identically). This is OBFUSCATION, not a cryptographic digest — it\n * is not collision-resistant. For a real hash, pre-hash host-side and pass the digest as `userEmail`.\n */\nexport const hashEmailFnv1a = (email: string): string => {\n const normalized = email.trim().toLowerCase();\n let hash = 0x811c9dc5; // FNV offset basis (32-bit)\n for (let i = 0; i < normalized.length; i++) {\n hash ^= normalized.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193); // FNV prime (32-bit), kept in 32-bit via imul\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n};\n\n/** Trim a candidate string; return `undefined` for a non-string / blank so callers can `if`-gate.\n * Shared with `activation/wireActivation`, which carried a byte-identical private copy named `clean`.\n * Not re-exported from the package barrel — this is an internal helper, not public surface. */\nexport const cleanString = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\n/**\n * Coerce a host `extra` map into the namespaced, scalar-only bucket shape. Every kept value is\n * placed under `custom.<key>`; non-scalar values (objects, arrays, null, functions, NaN/Infinity)\n * are DROPPED. Returns an object (possibly empty).\n */\nexport const namespaceExtra = (\n extra: Record<string, unknown> | undefined,\n): Record<string, string | number | boolean> => {\n const out: Record<string, string | number | boolean> = {};\n if (!extra || typeof extra !== \"object\") return out;\n for (const [key, value] of Object.entries(extra)) {\n const cleanKey = cleanString(key);\n if (!cleanKey) continue;\n if (!isWireScalar(value)) continue; // drop anything that isn't a finite scalar\n out[`${EXTRA_KEY_PREFIX}${cleanKey}`] = value;\n }\n return out;\n};\n\n/**\n * The storage key the analytics façade persists the bound opaque `user_id` under (namespaced per\n * `appId`, mirroring {@link deviceIdStorageKey}). Exported so a logout path can target it directly.\n */\nexport const analyticsUserIdStorageKey = (appId?: string): string =>\n `wireai:analytics:userId:${appId ?? \"default\"}`;\n\n/**\n * Return a COPY of a {@link WireUserContext} with every USER-scoped (PII / pseudonymous) field\n * removed — `userId`, `userEmail`, `hashEmail`, and `extra` — while KEEPING the non-PII device-scope\n * fields (`appVersion`, `deviceKey`). This is the in-memory half of logout: after it, the same\n * analytics instance keeps its stable `device_key` (which groups a DEVICE, not a user) but no longer\n * stamps the previous user's id/email onto events. Pure; never mutates the input.\n */\nexport const clearPiiFromContext = (ctx: WireUserContext = {}): WireUserContext => {\n const rest: WireUserContext = {};\n if (typeof ctx.appVersion === \"string\") rest.appVersion = ctx.appVersion;\n if (typeof ctx.deviceKey === \"string\") rest.deviceKey = ctx.deviceKey;\n return rest;\n};\n\n/** Options for {@link clearUserContext}. */\nexport interface ClearUserContextOptions {\n /** Host persistence (AsyncStorage subset) — the persisted bound `user_id` is removed from here. */\n storage?: WireOnboardingStorage;\n /** Tenant/app id — namespaces the persisted key (`wireai:analytics:userId:<appId>`). */\n appId?: string;\n}\n\n/**\n * LOGOUT primitive: purge the persisted, bound opaque `user_id` for an app so the NEXT user on a\n * shared device is not silently attributed to the previous one. Removes the\n * `wireai:analytics:userId:<appId>` key that the analytics façade persists and reuses across\n * launches. Fire-and-forget: a missing storage or a failing adapter resolves quietly.\n *\n * COVERAGE. The stateful `createAnalytics(...)` instance also exposes {@link Analytics.reset}, which\n * does this AND clears the in-memory binding + PII in one call — prefer it when you hold the\n * instance. This standalone helper covers the `createWireActivation` / `wire` path (whose config is\n * captured immutably, so it has no `reset`): call `clearUserContext({ storage, appId })` on logout,\n * and RECREATE the `wire` / analytics instance without the user's `userContext` (userId/userEmail)\n * so no further events carry the previous user's identity. The non-PII per-install `device_key`\n * (`wireai:analytics:deviceKey:<appId>`) is intentionally left in place — it groups a device, not a\n * person, and stays stable across users of the same install.\n */\nexport const clearUserContext = async (opts: ClearUserContextOptions = {}): Promise<void> => {\n const storage = opts.storage;\n if (!storage) return;\n try {\n await storage.removeItem(analyticsUserIdStorageKey(opts.appId));\n } catch {\n /* best-effort, swallow — logout must never throw into the UI */\n }\n};\n\n/**\n * The `userContext` value to hand `<WireOnboarding userContext={...} />` so an onboarding session\n * and the app's later events (purchases, actions, screens) share ONE join key.\n *\n * WHY it exists as a named function instead of an inline object literal: the wire key is\n * `device_key`, the prop-facing name is `deviceKey`, and the analytics surfaces auto-mint the value\n * for you. A host that hand-writes `userContext={{ deviceKey }}` produces a bucket the server's\n * device lookup does not read, and the resulting funnel is silently EMPTY rather than wrong. This is\n * the one place that spelling is decided.\n *\n * Pass the SAME `deviceKey` you gave `createAnalytics` / `createWireActivation`. `session_id` is not\n * a join key across those two families: an onboarding session id is the A2A `contextId` and an\n * app-event session id is the per-open id, so intersecting them returns nothing.\n */\nexport const activationJoinContext = (\n deviceKey: string,\n): Record<string, string | number | boolean> => resolveUserContext({ deviceKey }).userContext ?? {};\n\n/** Options for {@link resolveUserContext}. */\nexport interface ResolveUserContextOptions {\n /**\n * The kit's best-effort auto-detected app version (#42; from `detectAppVersion()`/the device\n * snapshot). Used ONLY when the explicit `WireUserContext.appVersion` is absent — explicit wins.\n */\n autoAppVersion?: string;\n}\n\n/**\n * Merge a {@link WireUserContext} into the wire shape with the precedence rule (explicit field >\n * auto-detected). Pure, never throws. Missing fields are omitted so the result can be spread onto an\n * event without sending empties.\n */\nexport const resolveUserContext = (\n ctx: WireUserContext = {},\n opts: ResolveUserContextOptions = {},\n): ResolvedUserContext => {\n const result: ResolvedUserContext = {};\n const bucket: Record<string, string | number | boolean> = {};\n\n // userId → top-level opaque id (NEVER the bucket). Sanitized + capped host-side.\n const userId = sanitizeUserId(ctx.userId);\n if (userId) result.userId = userId;\n\n // deviceKey → user_context.device_key (NOT session_id).\n const deviceKey = cleanString(ctx.deviceKey);\n if (deviceKey) {\n result.deviceKey = deviceKey;\n bucket.device_key = deviceKey;\n }\n\n // appVersion → explicit wins over auto-detected (#42); echoed for device.appVersion callers.\n const appVersion = cleanString(ctx.appVersion) ?? cleanString(opts.autoAppVersion);\n if (appVersion) {\n result.appVersion = appVersion;\n bucket.app_version = appVersion;\n }\n\n // userEmail → its OWN key. OPT-IN PII, optionally folded. NEVER touches userId.\n const email = cleanString(ctx.userEmail);\n if (email) {\n if (ctx.hashEmail) {\n bucket.user_email = hashEmailFnv1a(email);\n bucket.user_email_hashed = true;\n } else {\n bucket.user_email = email;\n }\n }\n\n // extra → namespaced + scalar-coerced.\n Object.assign(bucket, namespaceExtra(ctx.extra));\n\n if (Object.keys(bucket).length > 0) result.userContext = bucket;\n return result;\n};\n","/**\n * WireOnboarding — the public host component. Drop it into a screen and it runs\n * the whole AI onboarding: builds the A2A transport from `config`, wires the SDK\n * provider with the themed cards, applies the theme, and renders the flow.\n *\n * <WireOnboarding\n * config={{ apiKey, serverUrl, appId }}\n * theme={myBrandTheme}\n * validators={{ username: checkUsernameAvailable }}\n * onComplete={persist}\n * onSkip={skip}\n * />\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { WireAIProvider, type LocalLLMConfig } from \"wireai-rn\";\nimport { OnboardingThemeProvider } from \"./theme/ThemeContext\";\nimport { IllustrationProvider } from \"./components/Illustration\";\nimport { defaultIllustrations } from \"./illustrations/defaultIllustrations\";\nimport { IconRegistryProvider } from \"./icons/IconRegistry\";\nimport { LoadingScreen } from \"./components/LoadingScreen\";\nimport { OnboardingFlow, DEFAULT_COPY } from \"./OnboardingFlow\";\nimport { onboardingComponents } from \"./cards\";\nimport { makeSessionId, reportClientEvent, type ClientEventTarget } from \"./analytics/reportClientEvent\";\nimport { collectDeviceContext, type DeviceContext } from \"./device/deviceContext\";\nimport { hydrateDeviceIdentity } from \"./context/deviceId\";\nimport { activationJoinContext } from \"./context/userContext\";\nimport { hostIdentity, resolveIdentity } from \"./identity/identityRecord\";\nimport { sanitizeUserId } from \"./identity/userIdentity\";\nimport {\n clearPersistedSession,\n loadPersistedSession,\n sessionStorageKey,\n shouldClearOnComplete,\n DEFAULT_SESSION_TTL_MS,\n type LoadedSession,\n} from \"./session/persistedSession\";\nimport type { OnboardingResult, WireOnboardingProps } from \"./types\";\nimport { warnInDev } from \"./utils/warnInDev\";\n\n/** Ceiling on the auto-join-key storage read — a hung adapter degrades to no key, never a stuck\n * loader. Matches the persisted-session read's own ceiling. */\nconst AUTO_JOIN_HYDRATION_TIMEOUT_MS = 1_500;\n\n/** The settled result of the auto-join read: a key to inject, or `null` plus WHY the kit declined.\n * `timeout` = the adapter never answered; `not-durable` = it answered but did not persist the id,\n * so injecting it would mean a different key on every launch. */\ntype AutoJoinOutcome = { key: string } | { key: null; reason: \"timeout\" | \"not-durable\" };\n\nexport const WireOnboarding: React.FC<WireOnboardingProps> = ({\n config,\n theme,\n components,\n illustrations,\n icons,\n validators,\n onComplete,\n onSkip,\n onError,\n onEvent,\n copy,\n approxScreens,\n startMessage = \"start\",\n startTimeoutMs = 15_000,\n fallbackFlow,\n maxRetries = 1,\n storage,\n sessionTtlMs = DEFAULT_SESSION_TTL_MS,\n persistKey,\n retainSessionOnComplete,\n userContext,\n userId,\n autoJoinKey = true,\n}) => {\n // The host's own opaque user id (trimmed + capped, NO PII) so onboarding sessions can be\n // reconciled to real users later. `sanitizeUserId` is a pure string transform → the memoized\n // result is a stable primitive, safe to feed the `llm` / `clientContext` memos directly (unlike\n // the raw object props). Bound at three moments: session-start metadata (mount), an `identify`\n // event on a mid-session change (late binding), and the `identifyOnboarding` helper post-flow.\n const boundUserId = useMemo(() => sanitizeUserId(userId), [userId]);\n\n // Privacy-label-neutral device snapshot, collected once per mount (no advertising IDs, no\n // fingerprinting — see device/deviceContext.ts). `collectDeviceContext` already carries a\n // best-effort auto-detected `appVersion`; an explicit host `config.appVersion` overrides it.\n // Attached to BOTH the A2A session metadata and every client event so the backend can segment\n // the funnel by device (and by app version).\n const device = useMemo<DeviceContext>(() => {\n const collected = collectDeviceContext();\n return config.appVersion ? { ...collected, appVersion: config.appVersion } : collected;\n }, [config.appVersion]);\n\n // Stable serialization of `userContext`. Hosts pass it INLINE (`userContext={{ … }}`, the\n // documented usage), so the raw object identity changes every render. Feeding that raw object\n // into the `llm` / `clientContext` memos below would make them unstable, and wireai-rn recreates\n // its A2A adapter whenever the llmConfig identity changes — the adapter ctor resets `contextId`\n // (node_modules/wireai-rn: `this.contextId = void 0`), so the server-learned session id is\n // dropped and correlation breaks. We key both memos on the JSON string (compared by value) and\n // reuse ONE normalized reference in the metadata + client-event paths.\n const userContextKey = userContext ? JSON.stringify(userContext) : \"\";\n const userContextStable = useMemo<Record<string, string | number | boolean> | undefined>(\n () => (userContextKey ? (JSON.parse(userContextKey) as Record<string, string | number | boolean>) : undefined),\n [userContextKey],\n );\n\n // THE JOIN KEY, or the absence of it. `user_context.device_key` is the ONLY thing that stitches an\n // onboarding session to everything the app reports later, and the prop that carries it is optional\n // and named `userContext` — so forgetting it is the default, and the failure is a silent zero in the\n // `activated` funnel rather than an error. Two real consumers shipped without it.\n //\n // A host-supplied key is also RECORDED on the process-wide provenance registry, so a sibling\n // surface can later ask \"does this app own a device id?\" — see the K9 warning below. The registry\n // write is idempotent (same key, same value), so running it from a memo is safe under StrictMode's\n // double-invoke; it lives here rather than in an effect so the answer is already true for any\n // surface constructed later in the same tick.\n const hostJoinIdentity = useMemo(\n () =>\n resolveIdentity({\n value: userContextStable?.device_key,\n space: \"device\",\n source: \"host\",\n scope: config.appId,\n }),\n [userContextStable, config.appId],\n );\n const missingJoinKey = !hostJoinIdentity;\n\n // AUTO-JOIN (0.12.2). When the host supplied no join key, the kit supplies its OWN — the same\n // per-install `device_key` the analytics surfaces auto-mint and persist — so the default wiring\n // produces a joined funnel instead of a silent zero. Three conditions, all necessary:\n //\n // • `missingJoinKey` — a host-supplied key ALWAYS wins, verbatim, and is never touched.\n // • `autoJoinKey !== false` — the documented opt-out for a host that genuinely wants an\n // unlinked onboarding session; opting out restores the pre-0.12.2 behavior exactly.\n // • `storage` that actually WORKS — without persistence the auto id is process-scoped, so every\n // launch would carry a DIFFERENT key. That is worse than no key: the server counts\n // `min_sessions` by distinct opens grouped on `device_key`, so a per-launch key corrupts the\n // counter rather than leaving it empty, and it inflates distinct-device counts on top. Same\n // reason `useLifecycleEvents` gates its own fallback on storage.\n //\n // ⚠️ 0.13.0 (K1): the third condition used to be `Boolean(storage)` — the PRESENCE of the prop,\n // never the SUCCESS of the write. A REJECTING adapter (a locked / full / permission-denied\n // AsyncStorage, the most common real breakage) therefore walked the per-launch key in through the\n // front door: `hydrateAutoDeviceKey` resolves to the in-memory mint on every failure branch, and a\n // string is a string. The gate now reads `IdentityRecord.durable`, which is `true` ONLY when the id\n // was adopted from storage or written to it successfully — so a broken adapter lands on exactly the\n // same \"declined, and here is why\" path as no adapter at all.\n //\n // It resolves through `hydrateDeviceIdentity`, never the sync `resolveAutoDeviceKey`: the sync\n // contract returns the freshly minted id and adopts the persisted one milliseconds later, which\n // is exactly the 0.12.1 H1 defect — the key stamped here must be the one the analytics side\n // stamps, not a fresh mint per launch. The value is therefore awaited BEHIND THE LOADER GATE\n // below (the same gate the persisted-session read already holds, and it is only ever open when\n // `storage` is present anyway), because `userContext` feeds the `llm` memo: swapping it after the\n // provider mounted would recreate the A2A adapter and drop the server-learned `contextId`.\n const autoJoinPossible = Boolean(storage) && autoJoinKey !== false;\n const wantsAutoJoin = missingJoinKey && autoJoinPossible;\n // `undefined` = the hydration is still in flight (the gate below holds). Otherwise a settled\n // outcome: a `key` to inject, or `null` plus the reason the kit declined, which the warning names.\n const [autoJoinOutcome, setAutoJoinOutcome] = useState<AutoJoinOutcome | undefined>(undefined);\n\n useEffect(() => {\n if (!wantsAutoJoin || autoJoinOutcome !== undefined || !storage) return;\n let cancelled = false;\n // Ceiling on the read, the same discipline as `loadPersistedSession`: a hung storage adapter\n // must degrade to \"no auto key\", never to a stuck loader over the host's onboarding. Giving up\n // is deliberately NOT \"fall back to the synchronous mint\" — that key is per-launch, which is\n // the corruption this feature is gated on `storage` to avoid.\n const timer = setTimeout(() => {\n if (!cancelled) setAutoJoinOutcome({ key: null, reason: \"timeout\" });\n }, AUTO_JOIN_HYDRATION_TIMEOUT_MS);\n void hydrateDeviceIdentity({ appId: config.appId, storage }).then((identity) => {\n if (cancelled) return;\n clearTimeout(timer);\n setAutoJoinOutcome(\n identity?.durable ? { key: identity.value } : { key: null, reason: \"not-durable\" },\n );\n });\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n }, [wantsAutoJoin, autoJoinOutcome, config.appId, storage]);\n\n const injectedJoinKey = wantsAutoJoin ? (autoJoinOutcome?.key ?? undefined) : undefined;\n const autoJoinPending = wantsAutoJoin && autoJoinOutcome === undefined;\n\n // What actually goes on the wire: the host's context, with the auto join key merged in ONLY when\n // the host left the slot empty. Every other key the host passed survives untouched, and a host\n // that passed a valid `device_key` gets a byte-identical payload to 0.12.1.\n const effectiveUserContext = useMemo<Record<string, string | number | boolean> | undefined>(\n () =>\n injectedJoinKey\n ? { ...userContextStable, ...activationJoinContext(injectedJoinKey) }\n : userContextStable,\n [userContextStable, injectedJoinKey],\n );\n\n // THE JOIN DECISION IS FROZEN AT THE MOMENT THE GATE OPENS (K5), exactly as `startupUserIdRef`\n // below freezes the user id, and for the identical reason: `userContext` feeds the `llm` memo, and\n // wireai-rn recreates its A2A adapter whenever the `llm` identity changes — the adapter ctor resets\n // `contextId` (`this.contextId = void 0`), so the server-learned session id is dropped.\n //\n // THE TEARDOWN THIS PREVENTS: a host that resolves its device key ASYNCHRONOUSLY renders once\n // without it → auto-join injects `wdev_*` → the host key lands a tick later → `effectiveUserContext`\n // flips → the memo rebuilds → the adapter is recreated → the user restarts onboarding mid-flow and\n // the server is left holding an orphaned session. It is not a hypothetical shape: it is the default\n // shape of any host that reads its device id out of async storage.\n //\n // Frozen at gate-open rather than at first render because the auto-join key itself arrives\n // asynchronously — freezing earlier would freeze `undefined`. The value is carried as a JSON STRING\n // so it can sit in a dependency array by value; a ref alone would not re-run the memo when it fills.\n // Client events deliberately keep reading the LIVE `effectiveUserContext`: they are posted one at a\n // time and carry no adapter, so late host context enriches them at no risk — the same split the\n // user id already uses (frozen in session-start metadata, live via the `identify` event).\n const frozenWireContextRef = useRef<string | null>(null);\n if (!autoJoinPending && frozenWireContextRef.current === null) {\n frozenWireContextRef.current = effectiveUserContext ? JSON.stringify(effectiveUserContext) : \"\";\n }\n const startupUserContextKey = frozenWireContextRef.current ?? \"\";\n const startupUserContext = useMemo<Record<string, string | number | boolean> | undefined>(\n () =>\n startupUserContextKey\n ? (JSON.parse(startupUserContextKey) as Record<string, string | number | boolean>)\n : undefined,\n [startupUserContextKey],\n );\n\n // Dev-only warning (never a throw, never a wire change), once per mount, naming the exact fix.\n // Reconciled with auto-join: it fires only when the gap is still OPEN — injection was impossible\n // (no `storage`), the host opted out, or the read gave up. When auto-join covered the gap the\n // session IS joined, so there is nothing to warn about; while it is still in flight, nothing is\n // decided yet, so it stays quiet.\n const warnMissingJoinKey = missingJoinKey && !injectedJoinKey && !autoJoinPending;\n const autoJoinReason =\n autoJoinKey === false\n ? \"you passed autoJoinKey={false}.\"\n : !storage\n ? \"it got no `storage` prop, and without persistence its key would be different on every \" +\n \"launch, which corrupts min_sessions instead of merely leaving the join empty.\"\n : autoJoinOutcome?.key === null && autoJoinOutcome.reason === \"not-durable\"\n ? \"your `storage` adapter answered but could not persist the key (the read or the write \" +\n \"failed), so the key would be different on every launch, which corrupts min_sessions \" +\n \"instead of merely leaving the join empty. Check the adapter you passed as `storage`.\"\n : \"your `storage` adapter did not answer in time.\";\n useEffect(() => {\n if (!warnMissingJoinKey) return;\n warnInDev(\n \"[wireai] <WireOnboarding> got no user_context.device_key, so this onboarding session can \" +\n \"never be joined to the app's later events and the `activated` funnel will read zero. Pass \" +\n \"userContext={activationJoinContext(deviceKey)} — and if your app owns no device id, \" +\n \"userContext={activationJoinContext(resolveAutoDeviceKey({ appId, storage }))} returns the \" +\n \"SAME id the analytics side stamps. Never hand-write userContext={{ deviceKey }}. \" +\n \"The kit did NOT auto-inject its own key here because \" +\n autoJoinReason,\n );\n }, [warnMissingJoinKey, autoJoinReason]);\n\n // THE SECOND CASE AUTO-JOIN WOULD OTHERWISE SILENCE (K9). 0.12.2 suppressed the missing-join-key\n // warning whenever injection succeeded, which is right when the host genuinely owns no device id —\n // and wrong when it owns one and simply forgot it HERE. That host used to get a loud warning and\n // now gets a silent third id space: its app events under its own key, this onboarding session under\n // `wdev_*`, and `activated` still zero. Nothing a single mount can see distinguishes the two cases,\n // which is why the provenance registry exists: any surface constructed with a HOST-supplied device\n // key records it, so this mount can ask whether the process demonstrably owns one.\n //\n // It WARNS rather than declining to inject: declining would leave the onboarding side with no key\n // at all, which is strictly worse than a self-consistent one. It also does not silently ADOPT the\n // other surface's key — that would be the kit guessing which of two ids a host meant, on the\n // strength of construction order, and quietly changing what lands on the wire.\n const hostKeyElsewhere = missingJoinKey ? hostIdentity(\"device\", config.appId) : undefined;\n const warnHostKeyElsewhere = Boolean(hostKeyElsewhere) && Boolean(injectedJoinKey);\n useEffect(() => {\n if (!warnHostKeyElsewhere) return;\n warnInDev(\n \"[wireai] <WireOnboarding> got no user_context.device_key, so the kit injected its own — but \" +\n \"another surface in this app was constructed WITH a host-supplied device key \" +\n `(\"${hostKeyElsewhere}\"). Your app events carry that id and this onboarding session carries ` +\n \"the kit's, so the two land in disjoint id spaces and the `activated` funnel still reads \" +\n \"zero. Pass the SAME id here: userContext={activationJoinContext(deviceKey)}.\",\n );\n }, [warnHostKeyElsewhere, hostKeyElsewhere]);\n\n // The one case auto-join would otherwise SILENCE and must not: the host hand-wrote\n // `userContext={{ deviceKey }}`. That bucket is not the wire key, so the kit injects its own —\n // but the host demonstrably owns an id, and their app-side events carry THAT one, so the two\n // families still land in disjoint id spaces. Injection makes the onboarding side self-consistent;\n // only the host can make it join.\n const misspelledJoinKey =\n missingJoinKey &&\n typeof userContextStable?.deviceKey === \"string\" &&\n Boolean(userContextStable.deviceKey.trim());\n useEffect(() => {\n if (!misspelledJoinKey || !injectedJoinKey) return;\n warnInDev(\n \"[wireai] <WireOnboarding> got userContext={{ deviceKey }}, which is NOT the wire key — the \" +\n \"server's device lookup reads `device_key`. The kit auto-injected its own device_key so this \" +\n \"session is at least self-consistent, but your app's own events carry YOUR id, so the two \" +\n \"still will not join and the `activated` funnel stays zero. Pass \" +\n \"userContext={activationJoinContext(deviceKey)} instead.\",\n );\n }, [misspelledJoinKey, injectedJoinKey]);\n\n // The context payload shared by the A2A metadata + client-event paths. `userContext` +\n // `userId` are host-injected and forwarded verbatim (the server sanitizes them). Omitted keys\n // stay absent, so `dropped`/`client_fallback` events carry the user id when it's known.\n const clientContext = useMemo(\n () => ({ device, userContext: effectiveUserContext, userId: boundUserId }),\n [device, effectiveUserContext, boundUserId],\n );\n // One stable session id per onboarding SESSION (not per mount). It's used as the\n // client event `session_id` AND forwarded to the backend as `metadata.sessionId` so\n // the server can adopt it as the A2A `contextId` — making client-reported events\n // (`dropped`) correlate to the same session the server keys its own events by. See\n // the SDK-correlation note in analytics/reportClientEvent.ts.\n //\n // Without `storage`: minted synchronously per mount (the original behavior).\n // With `storage`: hydrated from the host-injected storage BEFORE the provider mounts\n // (loader-gate below), so an app KILL mid-onboarding resumes the SAME backend session\n // instead of minting a new one — which would count a phantom second `started` + a\n // false \"drop\" in the analytics funnel. See session/persistedSession.ts.\n const [session, setSession] = useState<LoadedSession | null>(() =>\n storage ? null : { id: makeSessionId(), resumed: false },\n );\n const storageKey = persistKey ?? sessionStorageKey(config.appId);\n\n useEffect(() => {\n if (!storage || session) return;\n // StrictMode/dev double-effect safe: the cancel flag drops the stale resolution.\n // Dev-only caveat: on a brand-new first mint, StrictMode's double-invoke can persist\n // then read the id back, surfacing a spurious `resumed: true`. Production is unaffected\n // (double-invoke is dev-only) and it self-heals on the next mount.\n let cancelled = false;\n void loadPersistedSession(storage, storageKey, sessionTtlMs).then((loaded) => {\n if (!cancelled) setSession(loaded);\n });\n return () => {\n cancelled = true;\n };\n }, [storage, storageKey, sessionTtlMs, session]);\n\n // By DEFAULT, clear the cached id the moment the flow completes, so the next onboarding on\n // this device starts a fresh session. Dropped/degraded paths deliberately do NOT clear —\n // a dropped session must stay resumable within the TTL.\n //\n // OPT-IN (`retainSessionOnComplete`): a multi-stage / replay-after-complete signup re-enters\n // (often via a `key=` remount) WITHIN one signup. If we cleared, that re-entry would find no\n // seed and mint a fresh `metadata.sessionId` → a phantom second `session_started` on the same\n // funnel. When the host opts in, we LEAVE the seed in place so the re-entry resumes the SAME\n // session (one funnel start); freshness for a genuinely new run then rides the TTL (past\n // `sessionTtlMs` → fresh mint) and an explicit new-run signal (a changed `persistKey`).\n // `shouldClearOnComplete` is the pure, unit-tested seam; the `storage` guard is unchanged, so a\n // host that does not opt in lands on the byte-for-byte legacy clear-on-complete path.\n const handleComplete = useCallback(\n (result: OnboardingResult) => {\n if (storage && shouldClearOnComplete(retainSessionOnComplete)) clearPersistedSession(storage, storageKey);\n onComplete(result);\n },\n [storage, storageKey, retainSessionOnComplete, onComplete],\n );\n\n const sessionId = session?.id ?? \"\";\n\n // Session-start snapshot of the bound user id. It seeds the A2A `metadata.userId` so the\n // adapter is built ONCE with whatever id was known at session start. A mid-session userId\n // change must NOT flow through this memo — recreating `llm` recreates the A2A adapter,\n // whose ctor resets `contextId` (see the userContext note above) and drops the server-\n // learned session id. Later changes ride EXCLUSIVELY on the `identify` effect below, which\n // mutates the live session in place. `useRef` captures the first-render value once.\n const startupUserIdRef = useRef<string | undefined>(boundUserId);\n\n // Build the A2A LocalLLMConfig from the friendlier kit config. The backend\n // resolves the app from the API key, so `model` (appId) is informational.\n const metadataKey = config.metadata ? JSON.stringify(config.metadata) : \"\";\n const metadataStable = useMemo(() => (metadataKey ? JSON.parse(metadataKey) : undefined), [metadataKey]);\n const componentNamesKey = (components ?? onboardingComponents).map((c) => c.name).join(\",\");\n const componentsStable = useMemo(() => components ?? onboardingComponents, [componentNamesKey]);\n\n const llm = useMemo<LocalLLMConfig>(() => {\n const baseUrl = config.serverUrl.replace(/\\/$/, \"\");\n return {\n provider: \"a2a\",\n baseUrl: `${baseUrl}/a2a`,\n model: config.appId,\n apiKey: config.apiKey,\n // Carry the kit session id alongside any host attribution so it reaches the A2A\n // request's `params.metadata` (the correlation seed; see note above), plus the\n // names of the components this device can actually render — so the backend only\n // emits cards the kit knows how to draw.\n metadata: {\n ...metadataStable,\n sessionId,\n supportedComponents: componentsStable.map((c) => c.name),\n // Device snapshot + host-injected user context ride the session-start metadata so the\n // backend can segment the funnel. Old servers ignore these unknown keys (backward compat).\n device,\n // The FROZEN wire context, never the live one — see the freeze note above. A change here\n // recreates the A2A adapter and drops `contextId`.\n ...(startupUserContext ? { userContext: startupUserContext } : {}),\n // The session-start user id (from the ref) rides the session-start metadata so the\n // server binds the session to a real user at creation. Reading the ref — not\n // `boundUserId` — keeps this memo off the userId dependency, so a mid-session change\n // does NOT recreate the adapter; it's bound by the `identify` effect below instead.\n ...(startupUserIdRef.current ? { userId: startupUserIdRef.current } : {}),\n },\n timeoutMs: 60_000,\n };\n }, [config.serverUrl, config.appId, config.apiKey, metadataStable, sessionId, componentsStable, device, startupUserContext]);\n\n // Where client-reported events are POSTed (`/v1/events`). Same tenant creds as the flow.\n const reportTarget = useMemo<ClientEventTarget>(\n () => ({ serverUrl: config.serverUrl, apiKey: config.apiKey }),\n [config.serverUrl, config.apiKey],\n );\n\n // LATE BINDING (mid-session): the user often registers DURING onboarding. When `userId`\n // becomes known (or changes) after the session already started, emit an `identify` client\n // event that attaches the id to the LIVE session, so the backend can map this in-flight\n // session to the real user. On a FRESH mount the initial id already rode the session-start\n // metadata, so we seed the \"already bound\" ref with it and only react to later CHANGES. On a\n // RESUMED session the server-side record predates this mount and won't re-read start metadata,\n // so we leave the seed empty to force an identify when a userId is present. Fire-and-forget.\n const identifiedRef = useRef<string | undefined>(undefined);\n const identifySeededRef = useRef(false);\n useEffect(() => {\n if (!session || !sessionId) return;\n if (!identifySeededRef.current) {\n identifySeededRef.current = true;\n identifiedRef.current = session.resumed ? undefined : boundUserId;\n }\n if (!boundUserId || boundUserId === identifiedRef.current) return;\n identifiedRef.current = boundUserId;\n reportClientEvent(reportTarget, {\n event_type: \"identify\",\n session_id: sessionId,\n user_id: boundUserId,\n });\n }, [session, sessionId, boundUserId, reportTarget]);\n\n const cards = components ?? onboardingComponents;\n\n // Loader-gate (hydration approach A): hold the entire provider subtree until the\n // stored id resolves. `sessionId` is a dependency of the `llm` memo above, so mounting\n // the provider with a throwaway id and swapping later would re-init it mid-flight.\n // The read is timeout-capped in loadPersistedSession, so this gate is one storage\n // read (~a frame), never an indefinite hold.\n //\n // The auto join key rides the SAME gate for the same reason (`effectiveUserContext` is also an\n // `llm` dependency). It costs no extra hold in practice: auto-join requires `storage`, and with\n // `storage` this gate is already closed on the persisted-session read.\n if (!session || autoJoinPending) {\n return (\n <OnboardingThemeProvider theme={theme}>\n <LoadingScreen\n title={copy?.restoringTitle ?? DEFAULT_COPY.restoringTitle}\n hint={copy?.restoringHint ?? DEFAULT_COPY.restoringHint}\n />\n </OnboardingThemeProvider>\n );\n }\n\n return (\n <OnboardingThemeProvider theme={theme}>\n <IllustrationProvider registry={{ ...defaultIllustrations, ...illustrations }}>\n <IconRegistryProvider registry={icons}>\n <WireAIProvider llm={llm} components={cards}>\n <OnboardingFlow\n validators={validators}\n onComplete={handleComplete}\n onSkip={onSkip}\n onError={onError}\n onEvent={onEvent}\n copy={copy}\n approxScreens={approxScreens}\n startMessage={startMessage}\n startTimeoutMs={startTimeoutMs}\n fallbackFlow={fallbackFlow}\n maxRetries={maxRetries}\n reportTarget={reportTarget}\n sessionId={sessionId}\n resumed={session.resumed}\n clientContext={clientContext}\n />\n </WireAIProvider>\n </IconRegistryProvider>\n </IllustrationProvider>\n </OnboardingThemeProvider>\n );\n};\n","/**\n * DemoOnboarding — a drop-in dev/QA trigger that runs the onboarding flow ON\n * DEMAND in a modal, then closes. No loop, no account, no navigation side-effects:\n * re-runnable infinitely with the same logged-in user. Place it anywhere a host\n * wants (e.g. a __DEV__ row in Settings). If `config` is null (the app hasn't\n * integrated Wire AI yet), it shows a hint instead of the flow.\n *\n * {__DEV__ && (\n * <DemoOnboarding config={wireConfigFromEnv({ appId: \"my-app\" })} theme={myTheme} />\n * )}\n *\n * It does NOT persist by default (a demo, not a real run) — pass `onComplete` if\n * you want to observe the captured answers.\n */\nimport { useCallback, useMemo, useState, type ReactNode } from \"react\";\nimport { Modal, Pressable, StyleSheet, Text, View } from \"react-native\";\n\nimport { WireOnboarding } from \"./WireOnboarding\";\nimport { mergeTheme } from \"./theme/defaultTheme\";\nimport type { OnboardingTheme } from \"./theme/types\";\nimport type { OnboardingResult, WireOnboardingConfig, WireOnboardingProps } from \"./types\";\n\nexport type DemoOnboardingProps = {\n /** The Wire AI config, or `null` when the app hasn't integrated Wire AI yet. */\n config: WireOnboardingConfig | null;\n theme?: WireOnboardingProps[\"theme\"];\n illustrations?: WireOnboardingProps[\"illustrations\"];\n validators?: WireOnboardingProps[\"validators\"];\n copy?: WireOnboardingProps[\"copy\"];\n /** Trigger button label. Default \"Demo onboarding\". */\n label?: string;\n /** Observe the demo result. By default the demo just closes (no persistence). */\n onComplete?: (result: OnboardingResult) => void;\n /** Render your own trigger instead of the default button: `(open) => <YourButton onPress={open} />`. */\n renderTrigger?: (open: () => void) => ReactNode;\n};\n\nexport function DemoOnboarding({\n config,\n theme,\n illustrations,\n validators,\n copy,\n label = \"Demo onboarding\",\n onComplete,\n renderTrigger,\n}: DemoOnboardingProps) {\n const [open, setOpen] = useState(false);\n const [runId, setRunId] = useState(0);\n const t = useMemo(() => mergeTheme(theme ?? {}), [theme]);\n const styles = useMemo(() => makeStyles(t), [t]);\n\n const openDemo = useCallback(() => {\n setRunId((n) => n + 1); // remount WireOnboarding → a fresh A2A session each open\n setOpen(true);\n }, []);\n const close = useCallback(() => setOpen(false), []);\n const finish = useCallback(\n (result: OnboardingResult) => {\n onComplete?.(result);\n setOpen(false);\n },\n [onComplete],\n );\n\n return (\n <>\n {renderTrigger ? (\n renderTrigger(openDemo)\n ) : (\n <Pressable onPress={openDemo} style={styles.trigger} accessibilityRole=\"button\">\n <Text style={styles.triggerText}>{label}</Text>\n </Pressable>\n )}\n\n <Modal\n visible={open}\n animationType=\"slide\"\n presentationStyle=\"fullScreen\"\n onRequestClose={close}\n >\n <View style={styles.modal}>\n {config ? (\n <WireOnboarding\n key={runId}\n config={config}\n theme={theme}\n illustrations={illustrations}\n validators={validators}\n copy={copy}\n onComplete={finish}\n onSkip={close}\n onError={close}\n />\n ) : (\n <View style={styles.notice}>\n <Text style={styles.noticeTitle}>Wire AI not configured</Text>\n <Text style={styles.noticeBody}>\n Set the Wire AI key + server URL (e.g. via wireConfigFromEnv) to demo the AI\n onboarding here.\n </Text>\n <Pressable onPress={close} style={styles.trigger} accessibilityRole=\"button\">\n <Text style={styles.triggerText}>Close</Text>\n </Pressable>\n </View>\n )}\n </View>\n </Modal>\n </>\n );\n}\n\nfunction makeStyles(t: OnboardingTheme) {\n return StyleSheet.create({\n trigger: {\n backgroundColor: t.colors.primary,\n borderRadius: t.button.radius,\n paddingVertical: 14,\n paddingHorizontal: 20,\n alignItems: \"center\",\n },\n triggerText: { color: t.colors.onPrimary, fontFamily: t.fonts.medium, fontSize: 16 },\n modal: { flex: 1, backgroundColor: t.colors.background },\n notice: { flex: 1, alignItems: \"center\", justifyContent: \"center\", padding: 24, gap: 12 },\n noticeTitle: { color: t.colors.text, fontFamily: t.fonts.bold, fontSize: 20 },\n noticeBody: {\n color: t.colors.textMuted,\n fontFamily: t.fonts.regular,\n fontSize: 15,\n textAlign: \"center\",\n },\n });\n}\n","/**\n * themeFromBrand — the fastest path to a branded flow. Give it a primary brand\n * color (and optionally a background + a font), and it derives a sensible full\n * `Partial<OnboardingTheme>` over the neutral `defaultOnboardingTheme` (via\n * `mergeTheme`): a tinted soft wash for selected states, a readable on-primary\n * label, and matching success/info accents left at the neutral default.\n *\n * theme={themeFromBrand({ primary: \"#15B0B0\" })}\n *\n * It stays intentionally small: it only touches the values that flow from a brand\n * color. Anything else (radius, spacing, button shape) keeps the default; pass\n * `extra` to override those without re-authoring the palette.\n */\nimport { defaultOnboardingTheme, mergeTheme } from \"./defaultTheme\";\nimport type { OnboardingTheme } from \"./types\";\n\nexport type ThemeFromBrandInput = {\n /** Brand / accent color — drives selected states, primary buttons, progress fill. */\n primary: string;\n /** App background behind the whole flow. Default: the neutral light background. */\n background?: string;\n /** Card / elevated surface background. Default: the neutral surface. */\n surface?: string;\n /** Primary body text color. Default: the neutral near-black. */\n text?: string;\n /** Text/icon color on top of `primary`. Default: white. */\n onPrimary?: string;\n /**\n * A single font family applied to regular/medium/bold (the kit derives weight\n * from size when a family isn't weight-split). Pass `fonts` in `extra` for\n * per-weight families.\n */\n font?: string;\n /** Any further theme overrides, deep-merged last (radius/spacing/button/fonts/colors). */\n extra?: Partial<OnboardingTheme>;\n};\n\n/** Parse a #RGB or #RRGGBB hex into [r,g,b]; returns null for anything else (e.g. rgba()). */\nconst hexToRgb = (hex: string): [number, number, number] | null => {\n const m = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());\n if (!m) return null;\n let h = m[1] as string;\n if (h.length === 3) h = h[0]! + h[0]! + h[1]! + h[1]! + h[2]! + h[2]!;\n const int = parseInt(h, 16);\n return [(int >> 16) & 255, (int >> 8) & 255, int & 255];\n};\n\n/** A low-alpha wash of the primary for selected backgrounds, falling back gracefully. */\nconst softFromPrimary = (primary: string): string => {\n const rgb = hexToRgb(primary);\n if (!rgb) return defaultOnboardingTheme.colors.primarySoft;\n const [r, g, b] = rgb;\n return `rgba(${r},${g},${b},0.10)`;\n};\n\nexport const themeFromBrand = (input: ThemeFromBrandInput): Partial<OnboardingTheme> => {\n const { primary, background, surface, text, onPrimary, font, extra } = input;\n\n const derived: Partial<OnboardingTheme> = {\n colors: {\n ...defaultOnboardingTheme.colors,\n primary,\n primarySoft: softFromPrimary(primary),\n onPrimary: onPrimary ?? defaultOnboardingTheme.colors.onPrimary,\n ...(background ? { background } : {}),\n ...(surface ? { surface } : {}),\n ...(text ? { text } : {}),\n },\n ...(font\n ? {\n fonts: {\n ...defaultOnboardingTheme.fonts,\n regular: font,\n medium: font,\n bold: font,\n },\n }\n : {}),\n };\n\n // mergeTheme resolves the derived palette over the neutral default into a full\n // theme. Then deep-merge `extra` per sub-object so callers can override\n // radius/spacing/button/fonts/colors without re-authoring the palette.\n const base = mergeTheme(derived);\n if (!extra) return base;\n return {\n colors: { ...base.colors, ...extra.colors },\n fonts: { ...base.fonts, ...extra.fonts },\n radius: { ...base.radius, ...extra.radius },\n spacing: { ...base.spacing, ...extra.spacing },\n button: { ...base.button, ...extra.button },\n };\n};\n","/**\n * centeredModalMotion - the pure entrance spec for the content-agnostic CenteredModal shell.\n *\n * WHY split out: the shell UI (CenteredModal) is RN and cannot run under the kit's node:test\n * runner, but the entrance math is pure and worth pinning. Keep the animation spec here so both\n * the component and the tests read one source, and so any module (reviews, questionnaire) can\n * reuse the shell without depending on another feature module.\n *\n * The centered popup uses RN's built-in `Animated` (native driver), the same idiom as\n * CompletionView/CardHandoff, so the shell stays dependency-free (no reanimated).\n *\n * NOTE: `reviews/presentation.ts` re-exports these under their original names\n * (`REVIEW_MODAL_ANIM`, `entranceFrame`) for back-compat with the reviews public API.\n */\n\n/**\n * The entrance spec for the centered popup. Values chosen to match the boilerplate's\n * `animated-modal` feel (a springy zoom-in) with the kit's own native-driver idiom:\n * • backdrop fades 0 -> `backdropOpacity`\n * • card springs from `scaleFrom` -> 1 and fades 0 -> 1\n */\nexport const CENTERED_MODAL_ANIM = {\n /** Spring config for the card scale/opacity entrance (mirrors CompletionView's pop). */\n enterSpring: { friction: 7, tension: 80 },\n /** Exit timing in ms (fade + shrink back out before unmount). */\n exitMs: 160,\n /** Card scale at rest (progress 0); grows to 1 at progress 1. */\n scaleFrom: 0.9,\n /** Peak dim of the backdrop at progress 1. */\n backdropOpacity: 0.55,\n} as const;\n\n/** A single frame of the entrance, for a progress value in [0..1] (clamped). Pure, testable. */\nexport const centeredModalFrame = (\n progress: number,\n backdropMax: number = CENTERED_MODAL_ANIM.backdropOpacity,\n): { cardOpacity: number; cardScale: number; backdropOpacity: number } => {\n const p = progress < 0 ? 0 : progress > 1 ? 1 : progress;\n const { scaleFrom } = CENTERED_MODAL_ANIM;\n return {\n cardOpacity: p,\n cardScale: scaleFrom + (1 - scaleFrom) * p,\n backdropOpacity: backdropMax * p,\n };\n};\n","/**\n * CenteredModal - the content-agnostic centered-popup shell.\n *\n * Renders its children as an alert-style card in the MIDDLE of the screen, over a dimmed\n * backdrop, with a spring/fade entrance. It knows nothing about what it presents: the reviews\n * gate uses it (via the `ReviewModal` back-compat re-export) and the questionnaire module reuses\n * the same shell, neither depends on the other.\n *\n * Adapted from the mobile-launcher boilerplate's `animated-modal` (transparent RN Modal +\n * centered container + backdrop-tap dismiss + content stop-propagation + springy zoom-in), but\n * reimplemented on RN's built-in `Animated` (native driver) so the shell stays dependency-free:\n * the boilerplate uses react-native-reanimated, which the kit does not.\n *\n * Dismissal (backdrop tap / Android back / the imperative `close()` handle) animates the card\n * out, then fires `onDismiss`. It never auto-closes on resolve: the host keeps the card showing\n * whatever payoff it wants (a thank-you, a summary) until the user taps the backdrop to close,\n * exactly like CompletionView.\n */\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { Animated, BackHandler, Easing, Modal, Pressable, StyleSheet } from \"react-native\";\nimport { SafeAreaView } from \"react-native-safe-area-context\";\n\nimport type { OnboardingTheme } from \"../theme/types\";\nimport { REDUCED_FADE_MS } from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\nimport { CENTERED_MODAL_ANIM } from \"../motion/centeredModalMotion\";\n\n/** Imperative handle so an in-card \"Not now\"/\"Skip\" link can trigger the exit animation. */\nexport type CenteredModalHandle = { close: () => void };\n\nexport type CenteredModalProps = {\n /** The (already merged) active theme - card surface/radius/spacing come from here. */\n theme: OnboardingTheme;\n /** Whether a backdrop tap / back press dismisses. Default true (never a dead end). */\n dismissible?: boolean;\n /** Fired once, AFTER the exit animation, on any dismiss. Wire to the host's resolve. */\n onDismiss: () => void;\n children: React.ReactNode;\n};\n\nconst _CenteredModal = forwardRef<CenteredModalHandle, CenteredModalProps>(\n ({ theme, dismissible = true, onDismiss, children }, ref) => {\n const progress = useRef(new Animated.Value(0)).current;\n const [open, setOpen] = useState(true);\n const closingRef = useRef(false);\n const reduced = useReducedMotion();\n\n // Entrance: spring the card in (scale + fade); the backdrop fades up in lock-step.\n // Reduce motion: a short fade to the settled card, no spring/scale.\n useEffect(() => {\n const anim = reduced\n ? Animated.timing(progress, {\n toValue: 1,\n duration: REDUCED_FADE_MS,\n useNativeDriver: true,\n })\n : Animated.spring(progress, {\n toValue: 1,\n useNativeDriver: true,\n friction: CENTERED_MODAL_ANIM.enterSpring.friction,\n tension: CENTERED_MODAL_ANIM.enterSpring.tension,\n });\n anim.start();\n return () => anim.stop();\n }, [progress, reduced]);\n\n const close = useCallback(() => {\n if (closingRef.current) return;\n closingRef.current = true;\n Animated.timing(progress, {\n toValue: 0,\n duration: reduced ? REDUCED_FADE_MS : CENTERED_MODAL_ANIM.exitMs,\n easing: Easing.in(Easing.cubic),\n useNativeDriver: true,\n }).start(() => {\n setOpen(false);\n onDismiss();\n });\n }, [progress, onDismiss, reduced]);\n\n useImperativeHandle(ref, () => ({ close }), [close]);\n\n // Android hardware back -> dismiss (when allowed). Always consume so it never pops a route.\n useEffect(() => {\n const sub = BackHandler.addEventListener(\"hardwareBackPress\", () => {\n if (dismissible) close();\n return true;\n });\n return () => sub.remove();\n }, [dismissible, close]);\n\n const onBackdrop = useCallback(() => {\n if (dismissible) close();\n }, [dismissible, close]);\n\n const backdropOpacity = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [0, CENTERED_MODAL_ANIM.backdropOpacity],\n });\n // Reduce motion: the card fades in already settled (no zoom).\n const cardScale = reduced\n ? 1\n : progress.interpolate({\n inputRange: [0, 1],\n outputRange: [CENTERED_MODAL_ANIM.scaleFrom, 1],\n });\n\n return (\n <Modal\n visible={open}\n transparent\n animationType=\"none\"\n statusBarTranslucent\n onRequestClose={dismissible ? close : undefined}\n >\n {/* Dimmed backdrop (fades with the entrance). */}\n <Animated.View\n style={[styles.backdrop, { opacity: backdropOpacity }]}\n pointerEvents=\"none\"\n />\n\n {/* Full-screen tap target: a tap outside the card dismisses. */}\n <Pressable\n style={styles.fill}\n onPress={onBackdrop}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Dismiss\"\n >\n <SafeAreaView style={styles.center} pointerEvents=\"box-none\">\n {/* Inner Pressable swallows taps so the card itself never dismisses. */}\n <Pressable onPress={() => {}} style={styles.cardWrap}>\n <Animated.View\n accessibilityViewIsModal\n accessibilityRole=\"alert\"\n style={[\n styles.card,\n {\n backgroundColor: theme.colors.surface,\n borderRadius: theme.radius.lg,\n padding: theme.spacing.lg,\n gap: theme.spacing.md,\n opacity: progress,\n transform: [{ scale: cardScale }],\n },\n ]}\n >\n {children}\n </Animated.View>\n </Pressable>\n </SafeAreaView>\n </Pressable>\n </Modal>\n );\n },\n);\n\n_CenteredModal.displayName = \"CenteredModal\";\n\nexport const CenteredModal = React.memo(_CenteredModal);\n\nconst styles = StyleSheet.create({\n fill: { flex: 1 },\n backdrop: { position: \"absolute\", top: 0, left: 0, right: 0, bottom: 0, backgroundColor: \"#000\" },\n center: { flex: 1, alignItems: \"center\", justifyContent: \"center\", padding: 24 },\n cardWrap: { width: \"100%\", maxWidth: 420 },\n card: {\n width: \"100%\",\n // Soft elevation so the popup reads as lifted above the app in both themes.\n shadowColor: \"#000\",\n shadowOffset: { width: 0, height: 8 },\n shadowOpacity: 0.28,\n shadowRadius: 24,\n elevation: 12,\n },\n});\n\nexport default CenteredModal;\n","/**\n * The fail-open defaults + a tolerant parser for the server's flags payload.\n *\n * THE CONTRACT: fail-open, never fail-dark. An absent server object, a missing module key, a\n * malformed value, or an unreachable endpoint must resolve to the MOST PERMISSIVE state — every\n * module ON, onboarding `ai` — so a control-plane outage can only ever be more permissive than\n * the dashboard intends. It can never dark a tenant's activation. Matches the server's own\n * documented fail-open default (FEATURES.md: \"local defaults — every module on, onboarding ai\").\n */\nimport type { OnboardingMode, WireFeatures } from \"./types\";\n\n/**\n * ALL ON, onboarding `ai`. Frozen + module-level so its reference is stable across every call\n * (consumers that list resolved flags in an effect dep array never loop on a fresh identity).\n */\nexport const defaultWireFeatures: WireFeatures = Object.freeze({\n coachmarks: Object.freeze({ enabled: true }),\n showcase: Object.freeze({ enabled: true }),\n onboarding: Object.freeze({ mode: \"ai\" as OnboardingMode }),\n review: Object.freeze({ enabled: true }),\n questionnaire: Object.freeze({ enabled: true }),\n announcements: Object.freeze({ enabled: true }),\n}) as WireFeatures;\n\nconst VALID_MODES: readonly OnboardingMode[] = [\"ai\", \"static\", \"off\"];\n\n/** Read a `{ enabled: boolean }` module, defaulting to ON when absent/malformed (fail-open). */\nconst readEnabled = (raw: unknown): { enabled: boolean } => {\n if (raw && typeof raw === \"object\" && typeof (raw as { enabled?: unknown }).enabled === \"boolean\") {\n return { enabled: (raw as { enabled: boolean }).enabled };\n }\n return { enabled: true };\n};\n\n/**\n * Narrow the server's (untrusted) JSON to a complete `WireFeatures`. Every field is filled with\n * its fail-open default when the server omits it or sends the wrong type, so a partial or\n * malformed payload degrades PERMISSIVELY rather than throwing. A non-object input (null, array,\n * string) → the full defaults. Never throws.\n */\nexport const parseWireFeatures = (raw: unknown): WireFeatures => {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return defaultWireFeatures;\n const src = raw as Record<string, unknown>;\n const modeRaw = (src.onboarding as { mode?: unknown } | undefined)?.mode;\n const mode: OnboardingMode =\n typeof modeRaw === \"string\" && VALID_MODES.includes(modeRaw as OnboardingMode)\n ? (modeRaw as OnboardingMode)\n : \"ai\";\n return {\n coachmarks: readEnabled(src.coachmarks),\n showcase: readEnabled(src.showcase),\n onboarding: { mode },\n review: readEnabled(src.review),\n questionnaire: readEnabled(src.questionnaire),\n announcements: readEnabled(src.announcements),\n };\n};\n\n/** Value-equality of two resolved flags — lets the hook hold a stable reference across churn. */\nexport const featuresEqual = (a: WireFeatures, b: WireFeatures): boolean =>\n a === b ||\n (a.coachmarks.enabled === b.coachmarks.enabled &&\n a.showcase.enabled === b.showcase.enabled &&\n a.onboarding.mode === b.onboarding.mode &&\n a.review.enabled === b.review.enabled &&\n a.questionnaire.enabled === b.questionnaire.enabled &&\n a.announcements.enabled === b.announcements.enabled);\n","/**\n * The last-known-flags cache — persisted through the host's optional `storage`.\n *\n * WHY: the fetch is best-effort and fail-open. When the control plane is unreachable we serve the\n * LAST value we saw rather than snapping to defaults, so a tenant that intentionally disabled a\n * module during an incident keeps it disabled across an outage instead of flapping back on. That\n * is \"stale-while-error\": a fresh cache (< TTL) is trusted, and on a fetch error even a STALE\n * cache is served (any age beats a guess). Every operation is best-effort — a broken/hung storage\n * degrades to defaults, never a throw and never a stuck gate (mirrors persistedSession).\n */\nimport { parseWireFeatures } from \"./defaults\";\nimport type { WireFeatures } from \"./types\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\n\n/**\n * TTL for a cached flags entry, aligned to the server's `Cache-Control: private, max-age=300`.\n * A cache younger than this is \"fresh\"; older is \"stale\" (still served on a fetch error).\n */\nexport const DEFAULT_FEATURES_TTL_MS = 300_000;\n\n/** Ceiling on the storage read so a hung adapter degrades to defaults, never a stuck resolve. */\nconst READ_TIMEOUT_MS = 1_500;\n\n/** Storage key for a tenant's cached flags, e.g. `wireai:features:acme`. */\nexport const featuresCacheKey = (appId?: string): string =>\n `wireai:features:${appId && appId.length > 0 ? appId : \"default\"}`;\n\n/** A cached flags entry: the resolved flags + the epoch-ms they were fetched. */\nexport interface CachedFeatures {\n features: WireFeatures;\n /** Age of the entry in ms at read time. */\n ageMs: number;\n}\n\nconst withTimeout = <T>(p: Promise<T>, ms: number): Promise<T | undefined> => {\n let timer: ReturnType<typeof setTimeout>;\n const timeout = new Promise<undefined>((resolve) => {\n timer = setTimeout(() => resolve(undefined), ms);\n });\n return Promise.race([p, timeout]).finally(() => clearTimeout(timer));\n};\n\n/** Whether a cache entry is still within the TTL (server max-age aligned). */\nexport const isFeaturesFresh = (ageMs: number, ttlMs: number = DEFAULT_FEATURES_TTL_MS): boolean =>\n ageMs >= 0 && ageMs < ttlMs;\n\n/**\n * Read the cached flags for `key`, or `undefined` when absent/corrupt/timed-out. Returns the\n * value AND its age so a caller can apply a TTL (fresh) or ignore it (stale-while-error). Never\n * throws; never hangs past the read timeout. The stored value is re-parsed through\n * `parseWireFeatures`, so a partially-corrupt entry still degrades fail-open.\n */\nexport const readCachedFeatures = async (\n storage: WireOnboardingStorage,\n key: string,\n): Promise<CachedFeatures | undefined> => {\n let raw: string | null | undefined;\n try {\n raw = await withTimeout(storage.getItem(key), READ_TIMEOUT_MS);\n } catch {\n return undefined;\n }\n if (!raw) return undefined;\n try {\n const parsed: unknown = JSON.parse(raw);\n if (parsed && typeof parsed === \"object\" && typeof (parsed as { ts?: unknown }).ts === \"number\") {\n const ts = (parsed as { ts: number }).ts;\n return {\n features: parseWireFeatures((parsed as { features?: unknown }).features),\n ageMs: Date.now() - ts,\n };\n }\n } catch {\n // Corrupt entry → treat as absent; the caller falls back to defaults / a fresh fetch.\n }\n return undefined;\n};\n\n/** Persist `{ features, ts }` under `key` — fire-and-forget, all errors swallowed. */\nexport const writeCachedFeatures = (\n storage: WireOnboardingStorage,\n key: string,\n features: WireFeatures,\n): void => {\n try {\n void storage\n .setItem(key, JSON.stringify({ features, ts: Date.now() }))\n .catch(() => {});\n } catch {\n // Best-effort: a failed write just means the next launch has no cache to fall back to.\n }\n};\n","/**\n * fetchWireFeatures — read the per-module kill switches from `GET {serverUrl}/v1/features`.\n *\n * Contract (server: chohra-med/wireai-onboarding-server, routers/onboarding.py):\n * GET {serverUrl}/v1/features\n * Authorization: Bearer {apiKey}\n * 200 → { coachmarks:{enabled}, showcase:{enabled}, onboarding:{mode}, review:{enabled},\n * announcements:{enabled} } (Cache-Control: private, max-age=300)\n *\n * THE CONTRACT — fail-open, never fail-dark. Unreachable, timed-out, unauthorized (401),\n * server-error (5xx), or malformed JSON all resolve to the LAST CACHED value, else the\n * all-on defaults. No throw ever reaches the host: this is timeout-capped and swallows every\n * error, exactly like the session's best-effort reads. A control-plane outage can only ever be\n * MORE permissive than the dashboard intends — it can never dark a tenant's activation.\n */\nimport { readCachedFeatures, featuresCacheKey, writeCachedFeatures } from \"./cache\";\nimport { defaultWireFeatures, parseWireFeatures } from \"./defaults\";\nimport type { WireFeatures, WireFeaturesConfig } from \"./types\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\n\nconst DEFAULT_TIMEOUT_MS = 4_000;\n\n/** The fail-open fallback: last cached value (any age — stale-while-error), else defaults. */\nconst failOpen = async (\n storage: WireOnboardingStorage | undefined,\n key: string,\n): Promise<WireFeatures> => {\n if (!storage) return defaultWireFeatures;\n const cached = await readCachedFeatures(storage, key);\n return cached?.features ?? defaultWireFeatures;\n};\n\n/** GET with a hard timeout via AbortController (falls back to no-abort where unsupported). */\nconst fetchWithTimeout = async (\n url: string,\n apiKey: string,\n timeoutMs: number,\n): Promise<Response> => {\n const controller =\n typeof AbortController !== \"undefined\" ? new AbortController() : undefined;\n const timer = setTimeout(() => controller?.abort(), timeoutMs);\n try {\n return await fetch(url, {\n method: \"GET\",\n headers: { Accept: \"application/json\", Authorization: `Bearer ${apiKey}` },\n signal: controller?.signal,\n });\n } finally {\n clearTimeout(timer);\n }\n};\n\n/**\n * Resolve the tenant's feature flags. Attempts the network once; on ANY failure returns the\n * cached value (any age), else the all-on defaults. On success, persists the fresh value to the\n * cache (fire-and-forget) and returns it. Never throws.\n *\n * const flags = await fetchWireFeatures({ serverUrl, apiKey, appId, storage });\n * if (!flags.coachmarks.enabled) { /* skip the tour * / }\n */\nexport const fetchWireFeatures = async (\n config?: WireFeaturesConfig,\n): Promise<WireFeatures> => {\n const key = featuresCacheKey(config?.appId);\n const storage = config?.storage;\n\n // Nothing to fetch (no creds) → cache, else defaults. Lets a host mount the provider before\n // its config is ready without ever darking.\n if (!config?.serverUrl || !config?.apiKey) return failOpen(storage, key);\n\n const url = `${config.serverUrl.replace(/\\/$/, \"\")}/v1/features`;\n const timeoutMs = config.timeoutMs && config.timeoutMs > 0 ? config.timeoutMs : DEFAULT_TIMEOUT_MS;\n\n try {\n const res = await fetchWithTimeout(url, config.apiKey, timeoutMs);\n // 401 (bad/rotated key), 5xx, any non-2xx → last-known, never dark.\n if (!res || !res.ok) return failOpen(storage, key);\n const json: unknown = await res.json(); // throws on malformed body → caught below\n const features = parseWireFeatures(json);\n if (storage) writeCachedFeatures(storage, key, features);\n return features;\n } catch {\n // Timeout/abort, network error, missing fetch, or malformed JSON — all fail open.\n return failOpen(storage, key);\n }\n};\n","/**\n * useWireFeatures — resolve the tenant's feature flags for a component tree, once per mount.\n *\n * Returns the all-on defaults immediately (fail-open), then swaps to the fetched value when the\n * network resolves. When no `serverUrl`+`apiKey` is supplied it never fetches and just returns\n * defaults, so a host that never adopts flags sees ZERO behavior change and ZERO network calls.\n *\n * frequent_rules #11 (unstable inline props): the config is idiomatically passed inline\n * (`config={{ serverUrl, apiKey }}`), a fresh identity every render. We stabilize the fetch key\n * by VALUE so the effect fires once per real credential change, and we only swap the returned\n * flags object when its VALUES change — so a host that lists the returned flags in an effect dep\n * array settles in a bounded number of commits instead of looping (enforced by the canary suite).\n */\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { defaultWireFeatures, featuresEqual } from \"./defaults\";\nimport { fetchWireFeatures } from \"./fetchWireFeatures\";\nimport type { WireFeatures, WireFeaturesConfig } from \"./types\";\n\n/** Hold a stable reference for a value while its CONTENT is unchanged (see reviews/equality.ts). */\nconst useStableValue = <T,>(value: T, isEqual: (a: T, b: T) => boolean): T => {\n const ref = useRef(value);\n if (!isEqual(ref.current, value)) ref.current = value;\n return ref.current;\n};\n\n/** The credential slice that actually drives a refetch — stabilized by value. */\nconst sameFetchKey = (a: WireFeaturesConfig | undefined, b: WireFeaturesConfig | undefined): boolean =>\n a?.serverUrl === b?.serverUrl && a?.apiKey === b?.apiKey && a?.appId === b?.appId;\n\nexport const useWireFeatures = (config?: WireFeaturesConfig): WireFeatures => {\n const stableConfig = useStableValue(config, sameFetchKey);\n const [flags, setFlags] = useState<WireFeatures>(defaultWireFeatures);\n\n const canFetch = !!stableConfig?.serverUrl && !!stableConfig?.apiKey;\n\n useEffect(() => {\n if (!canFetch) {\n // No creds → stay on the all-on defaults (and reset if creds were removed).\n setFlags((prev) => (featuresEqual(prev, defaultWireFeatures) ? prev : defaultWireFeatures));\n return;\n }\n let alive = true;\n // fetchWireFeatures never throws — the .then always runs with a fail-open value.\n void fetchWireFeatures(stableConfig).then((next) => {\n if (!alive) return;\n // Only adopt a NEW reference on a real value change, so a host effect keyed on the\n // returned flags doesn't loop (frequent_rules #11).\n setFlags((prev) => (featuresEqual(prev, next) ? prev : next));\n });\n return () => {\n alive = false;\n };\n }, [canFetch, stableConfig]);\n\n return flags;\n};\n","/**\n * WireFeaturesProvider + useResolvedFeatures — the OPTIONAL one-fetch-serves-all-modules layer.\n *\n * Mount `WireFeaturesProvider` once near your app root with the tenant `config` and it fetches the\n * flags ONCE; every gated surface below it (coachmarks / showcase / reviews) reads the same\n * resolved value from context instead of each fetching its own. It is entirely optional: with no\n * provider, every surface falls back to its own lazy fetch (when given a config) or to the all-on\n * defaults, so modules work with zero setup and a host that never adopts flags is unchanged.\n *\n * NOTE on the built npm subpaths: React context is shared across the kit's subpath entries in the\n * SOURCE-consumption path (the monorepo apps) and in this test suite — one module instance, one\n * context. If you consume the built `@wireai/activation/*` subpaths as separate bundles, pass the\n * resolved flags (or a `featuresConfig`) to each surface explicitly instead of relying on context.\n */\nimport React, { createContext, useContext, useMemo } from \"react\";\n\nimport { defaultWireFeatures } from \"./defaults\";\nimport { useWireFeatures } from \"./useWireFeatures\";\nimport type { WireFeatures, WireFeaturesConfig } from \"./types\";\n\nconst CONTEXT_SYMBOL = Symbol.for(\"wireai.features.context\");\nconst globalObj = global as any;\n\nif (!globalObj[CONTEXT_SYMBOL]) {\n globalObj[CONTEXT_SYMBOL] = createContext<WireFeatures | null>(null);\n}\nconst WireFeaturesContext = globalObj[CONTEXT_SYMBOL];\n\nexport interface WireFeaturesProviderProps {\n /** Tenant creds (+ optional storage) to fetch the flags once for the whole tree. */\n config?: WireFeaturesConfig;\n /**\n * Pre-resolved flags to provide directly instead of fetching (e.g. you already have them, or\n * you drive them from your own remote-config). Takes precedence over `config`.\n */\n flags?: WireFeatures;\n children: React.ReactNode;\n}\n\n/**\n * Fetch (or accept) the flags once and broadcast them to descendants. The provider VALUE is\n * memoized (performance rule #6) so a fresh object each render doesn't re-render every consumer.\n */\nexport const WireFeaturesProvider: React.FC<WireFeaturesProviderProps> = ({\n config,\n flags,\n children,\n}) => {\n // Always call the hook (rules of hooks); when `flags` is supplied we pass no config so it\n // never fetches and the explicit flags win below.\n const fetched = useWireFeatures(flags ? undefined : config);\n const value = flags ?? fetched;\n const stable = useMemo(() => value, [value]);\n return <WireFeaturesContext.Provider value={stable}>{children}</WireFeaturesContext.Provider>;\n};\n\nWireFeaturesProvider.displayName = \"WireFeaturesProvider\";\n\n/** Raw context read — `null` when no `WireFeaturesProvider` is mounted above. */\nexport const useWireFeaturesContext = (): WireFeatures | null =>\n useContext(WireFeaturesContext);\n\n/** Options for `useResolvedFeatures`: an explicit override and/or a lazy-fetch config. */\nexport interface ResolveFeaturesOptions {\n /** Explicit flags — win over everything (a surface's own `features` prop). */\n flags?: WireFeatures;\n /** Lazy-fetch config, used ONLY when there is no explicit `flags` and no provider above. */\n config?: WireFeaturesConfig;\n}\n\n/**\n * The resolution every gated surface uses. Precedence:\n * 1. explicit `options.flags` (a surface's own prop) →\n * 2. the nearest `WireFeaturesProvider` (context) →\n * 3. a lazy fetch from `options.config` (serverUrl + apiKey) →\n * 4. the all-on defaults.\n * Always fail-open, always a stable reference for a given value (so it's safe in effect deps).\n */\nexport const useResolvedFeatures = (options?: ResolveFeaturesOptions): WireFeatures => {\n const ctx = useWireFeaturesContext();\n // Only lazily fetch when nothing else provides the flags — otherwise pass no config so the\n // hook stays inert (defaults, no network). The hook is always called (rules of hooks).\n const shouldFetch = !options?.flags && ctx == null;\n const fetched = useWireFeatures(shouldFetch ? options?.config : undefined);\n return options?.flags ?? ctx ?? fetched ?? defaultWireFeatures;\n};\n","/**\n * wireConfigFromEnv — stop re-authoring env gating in every app. Reads the Wire AI\n * tenant key + server URL from the standard Expo public env vars and returns a\n * ready `WireOnboardingConfig`, or `null` when the key/URL are missing (so a host\n * can fall through to a static onboarding without writing the `if (!key)` itself).\n *\n * EXPO_PUBLIC_WIREAI_API_KEY=... (required)\n * EXPO_PUBLIC_WIREAI_SERVER_URL=... (required)\n *\n * const config = wireConfigFromEnv({ appId: \"morrow\" });\n * if (!config) return <StaticOnboarding />;\n * return <WireOnboarding config={config} ... />;\n *\n * `appId` defaults to `EXPO_PUBLIC_WIREAI_APP_ID` (or \"default\"); pass overrides to\n * set `appId`/`metadata` or to substitute the key/URL programmatically. `appVersion`\n * defaults to `detectAppVersion()` so every surface built from this config carries it.\n */\nimport { detectAppVersion } from \"../device/appVersion\";\nimport type { WireOnboardingConfig } from \"../types\";\nimport { warnInDev } from \"../utils/warnInDev\";\n\nexport type WireConfigOverrides = Partial<WireOnboardingConfig>;\n\n/** The env vars this helper reads. Exported so a host preflight can assert them itself. */\nexport const WIRE_ENV_VARS = [\n \"EXPO_PUBLIC_WIREAI_API_KEY\",\n \"EXPO_PUBLIC_WIREAI_SERVER_URL\",\n \"EXPO_PUBLIC_WIREAI_APP_ID\",\n] as const;\n\n/**\n * Minimal `process.env` declaration so the kit stays RN-pure (no `@types/node`).\n * In RN/Expo, `process.env.EXPO_PUBLIC_*` is provided/inlined by Metro at build\n * time; we only read string env vars here.\n *\n * IMPORTANT: read each var via STATIC member access (`process.env.EXPO_PUBLIC_FOO`).\n * Expo's `babel-preset-expo` `inline-env-vars` plugin ONLY inlines static\n * `process.env.EXPO_PUBLIC_*` member expressions. Aliasing (`const env = process.env`)\n * or computed access (`process.env[name]`) is left `undefined` in the Metro bundle, so\n * the value reads fine in Jest (Node) but is null on a real device. Do not refactor\n * these to an alias.\n */\ndeclare const process: { env: Record<string, string | undefined> };\n\nexport const wireConfigFromEnv = (\n overrides?: WireConfigOverrides,\n): WireOnboardingConfig | null => {\n const apiKey = overrides?.apiKey ?? process.env.EXPO_PUBLIC_WIREAI_API_KEY;\n const serverUrl = overrides?.serverUrl ?? process.env.EXPO_PUBLIC_WIREAI_SERVER_URL;\n const appId =\n overrides?.appId ?? process.env.EXPO_PUBLIC_WIREAI_APP_ID ?? \"default\";\n\n // Missing transport → null, so the host gates on one falsy check.\n //\n // The `null` return is the CORRECT contract and hosts rely on it — but it is also the quietest\n // failure the kit has: a missing EAS env var makes this return null, and then the facade never\n // constructs, `useLifecycleEvents` no-ops on `!cfg?.serverUrl`, and every gate returns null. Wire\n // is 100% off, with no error anywhere. Name it once in dev, and name WHICH var is missing.\n if (!apiKey || !serverUrl) {\n const missing = [\n apiKey ? undefined : \"EXPO_PUBLIC_WIREAI_API_KEY\",\n serverUrl ? undefined : \"EXPO_PUBLIC_WIREAI_SERVER_URL\",\n ].filter(Boolean);\n warnInDev(\n `[wireai] wireConfigFromEnv() returned null: ${missing.join(\" and \")} ${\n missing.length > 1 ? \"are\" : \"is\"\n } missing. The kit is now FULLY DISABLED (no onboarding, no analytics, no gates) and nothing ` +\n \"else will report an error. Set the var(s) in your env / EAS secrets.\",\n );\n return null;\n }\n\n // `appVersion` is part of `WireOnboardingConfig`, but this helper could not carry it — so a host\n // that built its config here forwarded `config.appVersion === undefined` to every surface. The\n // facade and the lifecycle path each auto-detect their own fallback; `createWireActivation` does\n // not, so every `wire.track` event shipped with no `app_version` at all. Detect once here (an\n // explicit override still wins) and the whole config carries it.\n const appVersion = overrides?.appVersion ?? detectAppVersion();\n\n return {\n apiKey,\n serverUrl,\n appId,\n ...(appVersion ? { appVersion } : {}),\n ...(overrides?.metadata ? { metadata: overrides.metadata } : {}),\n };\n};\n","/**\n * isOnboardingEnabled — the ONE standard gate for AI onboarding, so every app stops\n * re-authoring `flag && hasConfig` (one app had `isAiOnboardingEnabled`, another had\n * `isWireBackendConfigured` — same idea, two shapes).\n *\n * The gate is **transport presence**: `wireConfigFromEnv()` is non-null (the key + URL are\n * set), and that is it. There is no separate on/off env flag — a missing key already means\n * \"off\", so a second `EXPO_PUBLIC_AI_ONBOARDING_ENABLED` flag was redundant (and, read via\n * computed access, it didn't even inline on device). An optional `remote` kill-switch lets an\n * app turn it off without a release; the kit stays dependency-free (the app owns the remote\n * read and hands us the boolean).\n *\n * Enabled ⇔ transport present AND `(remote ?? true)`.\n *\n * if (!isOnboardingEnabled()) return goToStaticOnboarding();\n * // or, with a remote kill-switch the app already read:\n * if (!isOnboardingEnabled({ remote: remoteKillSwitchOn })) return goToStaticOnboarding();\n */\nimport { wireConfigFromEnv } from \"./wireConfigFromEnv\";\nimport type { WireConfigOverrides } from \"./wireConfigFromEnv\";\n\nexport type OnboardingFlagOptions = {\n /**\n * Optional remote kill-switch the app already read (Firebase/LD/etc.). When `false`, it\n * disables onboarding even though transport is present. Omit (or `true`) to leave it on.\n */\n remote?: boolean;\n /**\n * Config overrides forwarded to `wireConfigFromEnv` for the transport-present check\n * (e.g. a programmatic `apiKey`/`serverUrl`). Usually omitted.\n */\n config?: WireConfigOverrides;\n};\n\nexport const isOnboardingEnabled = (opts?: OnboardingFlagOptions): boolean => {\n const transportPresent = wireConfigFromEnv(opts?.config) !== null;\n if (!transportPresent) return false;\n return opts?.remote ?? true;\n};\n","/**\n * Canonical analytics names for the onboarding funnel. The kit already emits a typed\n * `OnboardingEvent` (`started | turn | error | retry | fallback`) — but one app logged them as\n * `onboarding_*` and another as `AI_ONBOARDING_*`, so the same funnel reads differently per app.\n * This maps the kit event to ONE canonical `wire_onboarding_*` name + params, and the app logs\n * it through whatever transport it already has (Firebase, Amplitude, console). The app still\n * owns the logger; only the NAMES are standardized.\n *\n * <WireOnboarding\n * onEvent={(e) => { const a = toAnalyticsEvent(e); logEvent(a.name, a.params); }}\n * onComplete={(r) => { logEvent(WIRE_ONBOARDING_EVENTS.completed, { answers: Object.keys(r.answers).length }); persist(r); }}\n * />\n *\n * `completed` has no kit `OnboardingEvent` (the kit signals completion via `onComplete`, not\n * `onEvent`) — the app logs it explicitly on `onComplete` using the constant below, so the\n * funnel name stays canonical.\n */\nimport type { OnboardingEvent } from \"../types\";\n\nexport const WIRE_ONBOARDING_EVENTS = {\n started: \"wire_onboarding_started\",\n /** A persisted session was restored after an app kill (fires instead of `started`). */\n resumed: \"wire_onboarding_resumed\",\n turn: \"wire_onboarding_turn\",\n error: \"wire_onboarding_error\",\n retry: \"wire_onboarding_retry\",\n fallback: \"wire_onboarding_fallback\",\n /** Logged by the host on `onComplete` (no matching kit `OnboardingEvent`). */\n completed: \"wire_onboarding_completed\",\n} as const;\n\nexport type WireOnboardingEventName =\n (typeof WIRE_ONBOARDING_EVENTS)[keyof typeof WIRE_ONBOARDING_EVENTS];\n\nexport type AnalyticsEvent = {\n name: WireOnboardingEventName;\n params?: Record<string, unknown>;\n};\n\n/**\n * Map a kit `OnboardingEvent` to its canonical `{ name, params }`. Exhaustive over the union\n * (the `never` default makes a new event type a compile error here — intentional).\n */\nexport const toAnalyticsEvent = (event: OnboardingEvent): AnalyticsEvent => {\n switch (event.type) {\n case \"started\":\n return { name: WIRE_ONBOARDING_EVENTS.started };\n case \"resumed\":\n return { name: WIRE_ONBOARDING_EVENTS.resumed };\n case \"turn\":\n return {\n name: WIRE_ONBOARDING_EVENTS.turn,\n params: { step: event.step, component: event.component },\n };\n case \"error\":\n return { name: WIRE_ONBOARDING_EVENTS.error, params: { reason: event.reason } };\n case \"retry\":\n return {\n name: WIRE_ONBOARDING_EVENTS.retry,\n params: { reason: event.reason, attempt: event.attempt },\n };\n case \"fallback\":\n return { name: WIRE_ONBOARDING_EVENTS.fallback, params: { reason: event.reason } };\n default: {\n const _exhaustive: never = event;\n return _exhaustive;\n }\n }\n};\n","/**\n * attribution — forward install/ad attribution to the onboarding agent so it can tailor the\n * first question by acquisition source (e.g. a paid-campaign install vs an organic one). The\n * channel already exists: `WireOnboardingConfig.metadata` is merged into every A2A request by\n * `WireOnboarding`. No production app populated it before; this gives every app a standard shape.\n *\n * The app reads its raw attribution (AppsFlyer / Branch / deferred deep link — an app concern,\n * not the kit's) and passes the normalized result as `metadata`:\n *\n * const config = wireConfigFromEnv({\n * appId: \"morrow-self\",\n * metadata: attributionMetadata({ source: conv.mediaSource, campaign: conv.campaign, isOrganic: conv.isOrganic }),\n * });\n *\n * The backend sees `metadata.attribution = { source, campaign, ... }`.\n */\n\n/** Normalized acquisition attribution. All fields optional — pass what the SDK gives you. */\nexport type OnboardingAttribution = {\n /** Media source / network, e.g. \"appsflyer\", \"branch\", \"organic\". */\n source?: string;\n campaign?: string;\n adset?: string;\n ad?: string;\n /** Deferred deep-link slug / path that routed the install. */\n deepLink?: string;\n isFirstLaunch?: boolean;\n isOrganic?: boolean;\n /** Escape hatch for SDK-specific fields not covered above. */\n raw?: Record<string, unknown>;\n};\n\n/**\n * Wrap attribution into the `{ attribution: {...} }` metadata the agent reads. Drops `undefined`\n * fields so the request payload stays compact. Returns `{ attribution: {} }` for empty input\n * (still a valid, harmless metadata object).\n */\nexport const attributionMetadata = (\n a: OnboardingAttribution,\n): { attribution: Record<string, unknown> } => {\n const attribution: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(a)) {\n if (value !== undefined) attribution[key] = value;\n }\n return { attribution };\n};\n","/**\n * activation revalidation — a tiny kit-owned pub/sub the review / questionnaire decision fetches\n * subscribe to, so they RE-FETCH their server decision AFTER a trigger action, not only on mount.\n *\n * WHY THIS EXISTS (subsumes Morrow's hand-rolled `activation-revalidation.ts`): a host mounts the\n * review / questionnaire gate on the home screen and fetches its `/decision` verdict once, in a\n * mount-scoped effect. But the screen stays mounted while the user goes elsewhere to perform the\n * triggering action (journal a win, complete a task); the server's firing rule is trigger-based AND\n * session-scoped, so the mount fetch ran BEFORE the trigger event existed and never re-runs. Bumping\n * this store after the action POSTs re-runs the gate's decision fetch (it lists the version in its\n * deps) → the server now sees the trigger → `{fire:true}`.\n *\n * `wire.track()` bumps this automatically on a successful POST, so a consumer no longer hand-rolls\n * an await-then-bump: it subscribes (via {@link useActivationRevalidation} in `useWireActivation`)\n * and re-fetches when the version changes.\n *\n * ── WHY A globalThis SLOT, NOT MODULE-LOCAL STATE (same reasoning as currentSession) ─────────────\n * This module can be reached from more than one package entry (the main `.` barrel exposes the\n * revalidation surface; the gates live under the `./reviews` / `./questionnaire` subpaths). Under\n * `dist` resolution tsup inlines a SEPARATE copy of a module into each bundle, so plain module-local\n * `version` + `listeners` would give the BUMPER (main entry, via `wire.track`) and a SUBSCRIBER a\n * different store — the bump would never reach the listener, exactly the defect-B failure mode. So\n * the ONE store lives in a `globalThis` slot keyed by `Symbol.for(...)`: every inlined copy resolves\n * the same symbol and shares one store, on Hermes/RN, Node and SSR alike.\n */\n\n/** Well-known key into the runtime-global symbol registry — one shared store across every bundle. */\nconst REVALIDATION_SLOT: unique symbol = Symbol.for(\n \"@wireai/activation:activationRevalidation\",\n);\n\n/** The shared store: a monotonic version + the set of subscriber callbacks. */\ntype RevalidationStore = { version: number; listeners: Set<() => void> };\n\ntype GlobalWithSlot = typeof globalThis & {\n [REVALIDATION_SLOT]?: RevalidationStore;\n};\n\nconst globalSlot = globalThis as GlobalWithSlot;\n\n/** The one shared store, lazily created on the runtime global (never a second copy per bundle). */\nconst store = (): RevalidationStore => {\n const existing = globalSlot[REVALIDATION_SLOT];\n if (existing) return existing;\n const created: RevalidationStore = { version: 0, listeners: new Set() };\n globalSlot[REVALIDATION_SLOT] = created;\n return created;\n};\n\n/**\n * Signal every activation subscriber to re-fetch its server decision. `wire.track()` calls this on a\n * successful POST (await the post first so the re-fetch sees the event). A throwing subscriber never\n * breaks the notify loop — each listener is isolated.\n */\nexport const bumpActivationRevalidation = (): void => {\n const s = store();\n s.version += 1;\n // Iterate a snapshot so a listener that (un)subscribes during notify never corrupts the walk.\n for (const listener of Array.from(s.listeners)) {\n try {\n listener();\n } catch {\n // A subscriber that throws must not stop the others (fail-safe).\n }\n }\n};\n\n/**\n * Subscribe to revalidation. Returns an unsubscribe fn. Shaped for `useSyncExternalStore`\n * (see {@link useActivationRevalidation} in `useWireActivation`).\n */\nexport const subscribeActivationRevalidation = (listener: () => void): (() => void) => {\n const s = store();\n s.listeners.add(listener);\n return () => {\n s.listeners.delete(listener);\n };\n};\n\n/** The current revalidation version — include it in a decision-fetch effect's deps to re-fetch on bump. */\nexport const getActivationRevalidationVersion = (): number => store().version;\n\n/** Test-only: reset the shared store between cases (clears version + listeners). */\nexport const resetActivationRevalidation = (): void => {\n const s = store();\n s.version = 0;\n s.listeners.clear();\n};\n","/**\n * wireActivation — the kit-owned `wire.track()` + session accessor + revalidation surface.\n *\n * WHAT IT CONSOLIDATES (subsumes Morrow's workarounds): a consumer used to hand-roll three things\n * because the kit didn't own them — an awaitable action POST (`wireTrackActionAwait`), its OWN\n * per-open session id (`getWireSessionId`, minted because the kit's `getCurrentSessionId` desynced\n * cross-bundle — defect B), and an await-then-bump revalidation dance (`bumpActivationDecision`).\n * Defect B is fixed (PR #48: `getCurrentSessionId` is a `globalThis` singleton, reliable under\n * `dist`), so the kit can now own all three behind one thin surface:\n *\n * const wire = createWireActivation({ serverUrl, apiKey }); // or useWireActivation(...)\n * await wire.track(\"journal_done\"); // awaitable POST + auto-revalidate\n *\n * `track` POSTs `event_type='app_event'`, `question_key=<name>` (the EXACT string a review /\n * questionnaire firing TRIGGER matches on) under the CURRENT `ensureCurrentSessionId()` — the same id\n * the gates pass to their `/decision` fetch, so the server's session-scoped trigger rule agrees —\n * with `user_context.device_key` for the min-sessions / arm-assignment lookups. On a successful POST\n * it bumps decision revalidation so a subscribed gate re-fetches and can fire.\n *\n * ADDITIVE + built on existing primitives: it reuses the events transport\n * (`reportClientEventAwait`, the awaitable sibling of `reportClientEvents` — ONE `/v1/events` path)\n * and `getCurrentSessionId` — it introduces NO second session concept and duplicates no POST path.\n * React-free (the optional React glue is the thin `useWireActivation` hook).\n */\nimport { ensureCurrentSessionId, getCurrentSessionId } from \"../analytics/currentSession\";\nimport {\n reportClientEventAwait,\n type ClientEvent,\n type ClientEventTarget,\n} from \"../analytics/reportClientEvent\";\nimport { resolveAutoDeviceKey, type ResolveAutoDeviceKeyOptions } from \"../context/deviceId\";\nimport { cleanString, resolveUserContext, type WireUserContext } from \"../context/userContext\";\nimport { resolveIdentity } from \"../identity/identityRecord\";\nimport { detectAppVersion } from \"../device/appVersion\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\nimport {\n bumpActivationRevalidation,\n getActivationRevalidationVersion,\n subscribeActivationRevalidation,\n} from \"./revalidation\";\n\n/** The shared trim helper (was a byte-identical private copy named `clean` in this file). */\nconst clean = cleanString;\n\n/**\n * Tenant transport + context inputs for {@link createWireActivation}. `serverUrl`/`apiKey` are the\n * SAME creds as onboarding (never a second key); everything else is optional.\n */\nexport type WireActivationConfig = {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/v1/events` is appended. */\n serverUrl: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey: string;\n /**\n * A stable, non-PII device id → `user_context.device_key` (the server's review/questionnaire\n * gating + A/B stickiness key on it). When omitted, the kit auto-mints ONE per-install id, persists\n * it via `storage` when given, and reuses it — so `device_key` is ALWAYS present. Host-supplied wins.\n */\n deviceKey?: string;\n /**\n * Optional rich context stamped onto every tracked event's `user_context` (opaque `userId` →\n * top-level `user_id`, opt-in `userEmail`, namespaced `extra`). `deviceKey` here is equivalent to\n * the top-level one (top-level wins). Same shape the analytics façade accepts.\n */\n userContext?: WireUserContext;\n /** Tenant/app id — namespaces the auto-minted device-key storage slot. */\n appId?: string;\n /** Host app version → `user_context.app_version` when no explicit `userContext.appVersion` is set. */\n appVersion?: string;\n /** Host persistence (AsyncStorage-compatible subset) so the auto-minted device key survives launches. */\n storage?: WireOnboardingStorage;\n};\n\n/** The kit-owned activation surface. `sessionId` is a live getter (reads `getCurrentSessionId()`). */\nexport type WireActivation = {\n /**\n * Awaitable action report: POST `event_type='app_event'`, `question_key=<name>`, optional `meta`,\n * under the CURRENT session id + `user_context.device_key`. Resolves `true` once the server has\n * stored it (2xx) and THEN bumps decision revalidation; resolves `false` (no bump) for a blank\n * name or a failed POST. Never throws.\n *\n * It no longer refuses when no app-open has been registered: the session id is resolved through\n * `ensureCurrentSessionId()`, which mints and registers one in that case (the server requires a\n * non-empty `session_id` and silently drops an event without one, so bailing lost the action\n * entirely). A host that fires `reportSessionStart` / `useLifecycleEvents` first is unaffected —\n * the real per-open id is already registered and gets used exactly as before.\n */\n track(name: string, meta?: Record<string, unknown>): Promise<boolean>;\n /** The CURRENT per-open session id (the kit's canonical `getCurrentSessionId()`), or `undefined`. */\n readonly sessionId: string | undefined;\n /** Subscribe to decision revalidation (bumped by a successful `track`). Returns an unsubscribe fn. */\n subscribeRevalidation(listener: () => void): () => void;\n /** The current revalidation version — include in a decision-fetch effect's deps to re-fetch on bump. */\n getRevalidationVersion(): number;\n};\n\n/**\n * Create a bound activation instance for a tenant transport. Resolves the device key once (explicit >\n * `userContext.deviceKey` > auto-minted + persisted). Pure + React-free.\n */\nexport const createWireActivation = (config: WireActivationConfig): WireActivation => {\n const target: ClientEventTarget = { serverUrl: config.serverUrl, apiKey: config.apiKey };\n\n // Device key: an explicit id (top-level or in userContext) wins and is never overwritten; otherwise\n // read the ONE process-wide auto id (`resolveAutoDeviceKey`) so this instance and a sibling\n // `createAnalytics` instance carry the SAME `device_key` for the same install. Minting locally here\n // gave one install two auto ids — see the registry note in context/deviceId.ts.\n const explicitDeviceKey = clean(config.deviceKey) ?? clean(config.userContext?.deviceKey);\n // Record a HOST-supplied key on the process provenance registry, so a `<WireOnboarding>` mount that\n // was NOT given one can tell \"this app owns no device id\" (fine, inject) from \"this app owns one\n // and forgot it here\" (the silent third id space — K9). Recording only; nothing reads it on this path.\n resolveIdentity({\n value: explicitDeviceKey,\n space: \"device\",\n source: \"host\",\n scope: config.appId,\n });\n const autoDeviceKeyOptions: ResolveAutoDeviceKeyOptions = {\n appId: config.appId,\n // An explicit key opts out of minting AND persisting (unchanged contract).\n storage: explicitDeviceKey ? undefined : config.storage,\n };\n // Start hydration AT CONSTRUCTION (not at the first `track`) so the persisted id is adopted as early\n // as it used to be. The return value is deliberately discarded — every event re-resolves.\n if (!explicitDeviceKey) resolveAutoDeviceKey(autoDeviceKeyOptions);\n\n // The auto-detected host app version, read ONCE (cheap, sync, never throws) — same as the facade.\n // Without it this path had NO `app_version` fallback at all, so every `wire.track` event from a host\n // that passed no `config.appVersion` (which `wireConfigFromEnv` could not even carry) shipped\n // without one, while the facade and lifecycle families both had theirs.\n const detectedAppVersion = detectAppVersion();\n\n // Stamp the resolved rich context onto the event: `user_context` bucket (device_key always, plus any\n // app_version / opt-in user_email / namespaced extra) and the top-level opaque `user_id`.\n const applyContext = (event: ClientEvent): void => {\n const resolved = resolveUserContext(\n // `??` is lazy on purpose: an explicit key must never even touch the auto registry.\n {\n ...(config.userContext ?? {}),\n deviceKey: explicitDeviceKey ?? resolveAutoDeviceKey(autoDeviceKeyOptions),\n },\n { autoAppVersion: config.appVersion ?? detectedAppVersion },\n );\n if (resolved.userContext) {\n event.user_context = { ...resolved.userContext, ...(event.user_context ?? {}) };\n }\n if (resolved.userId && !event.user_id) event.user_id = resolved.userId;\n };\n\n const track = async (name: string, meta?: Record<string, unknown>): Promise<boolean> => {\n // A blank name is the only thing left to refuse on: there is no `question_key` to match a\n // firing trigger against, so bail WITHOUT bumping (a bump with no posted event would only make\n // the gate re-fetch for nothing).\n if (!clean(name)) return false;\n // No app-open registered is NOT a reason to drop the action. `ensureCurrentSessionId` returns\n // the registered per-open id when there is one (the unchanged path) and otherwise mints +\n // registers one, so the POST always carries the non-empty `session_id` the server requires\n // instead of being accepted with a 200 and discarded.\n const sessionId = ensureCurrentSessionId();\n const event: ClientEvent = {\n event_type: \"app_event\",\n session_id: sessionId,\n question_key: name,\n };\n if (meta && Object.keys(meta).length > 0) event.meta = JSON.stringify(meta);\n applyContext(event);\n const ok = await reportClientEventAwait(target, event);\n // Only revalidate once the event is actually in the stream — a failed POST leaves the gate as-is.\n if (ok) bumpActivationRevalidation();\n return ok;\n };\n\n return {\n track,\n get sessionId() {\n return getCurrentSessionId();\n },\n subscribeRevalidation: subscribeActivationRevalidation,\n getRevalidationVersion: getActivationRevalidationVersion,\n };\n};\n","/**\n * useWireActivation — a THIN optional React hook over {@link createWireActivation}.\n *\n * One import gives a consumer everything the activation consolidation owns: `track` (awaitable POST\n * that auto-revalidates), the CURRENT `sessionId`, and a `revalidation` counter that ticks whenever\n * a `track()` (from anywhere) succeeds — subscribe to re-render, then re-fetch your gate decision.\n *\n * const { track, sessionId, revalidation } = useWireActivation({ serverUrl, apiKey });\n * // fetch the gate decision on mount AND whenever revalidation ticks:\n * useEffect(() => { fetchReviewDecision(target, { sessionId, deviceKey }).then(setDecision); },\n * [revalidation]);\n * // on the trigger action:\n * await track(\"journal_done\");\n *\n * Mirrors the existing `createAnalytics` / `useAnalytics` (and `createScreenTracker` /\n * `useScreenTracking`) split: the factory stays React-free; this is the glue. The instance is built\n * once per mount and held in a ref, so re-renders never rebuild it or re-resolve the device key.\n */\nimport { useRef, useSyncExternalStore } from \"react\";\n\nimport {\n getActivationRevalidationVersion,\n subscribeActivationRevalidation,\n} from \"./revalidation\";\nimport {\n createWireActivation,\n type WireActivation,\n type WireActivationConfig,\n} from \"./wireActivation\";\n\n/**\n * Subscribe a component to decision revalidation. Returns the current version; list it in a\n * decision-fetch effect's deps so a `bumpActivationRevalidation()` (which a successful `track` does)\n * re-runs the fetch. The kit-owned replacement for a host's hand-rolled `useActivationRevalidation`.\n */\nexport const useActivationRevalidation = (): number =>\n useSyncExternalStore(\n subscribeActivationRevalidation,\n getActivationRevalidationVersion,\n getActivationRevalidationVersion,\n );\n\n/** What {@link useWireActivation} returns: the awaitable `track`, the live `sessionId`, and the tick. */\nexport type UseWireActivation = {\n /** Awaitable action report that auto-revalidates on success (see {@link WireActivation.track}). */\n track: WireActivation[\"track\"];\n /** The CURRENT per-open session id (read fresh each render), or `undefined`. */\n sessionId: string | undefined;\n /** Monotonic counter that increments on every successful `track()` — a re-fetch trigger. */\n revalidation: number;\n};\n\n/**\n * Build a per-mount activation instance. `config` is read once at first render (the instance is\n * stable for the component's lifetime, keyed on the transport creds + device key); the returned\n * `revalidation` re-renders the component whenever any `track()` succeeds.\n */\nexport const useWireActivation = (config: WireActivationConfig): UseWireActivation => {\n const ref = useRef<WireActivation | undefined>(undefined);\n const prevKeys = useRef<string>(\"\");\n\n // The identity of the built instance. `userContext.deviceKey` MUST be in here: `createWireActivation`\n // honors it as an explicit device key (`config.deviceKey ?? config.userContext?.deviceKey`), so a host\n // that hydrates its device id asynchronously and passes it only inside `userContext` would otherwise\n // keep an instance frozen on the first render's `undefined` — the stale-static-ref failure this repo\n // has already been bitten by (see .memory/70-knowledge.md, \"Stale Option Closures in Static Refs\").\n const currentKeys = [\n config.serverUrl,\n config.apiKey,\n config.appId,\n config.deviceKey,\n config.userContext?.deviceKey,\n ].join(\"|\");\n if (!ref.current || prevKeys.current !== currentKeys) {\n prevKeys.current = currentKeys;\n ref.current = createWireActivation(config);\n }\n\n const revalidation = useActivationRevalidation();\n return { track: ref.current.track, sessionId: ref.current.sessionId, revalidation };\n};\n","/**\n * purchaseEvents - the canonical Wire names for a subscription funnel, plus the PURE mappers that\n * turn a RevenueCat snapshot into small, non-PII event props.\n *\n * Same job `analyticsEvent.ts` does for the onboarding funnel: every app was naming these events\n * itself (`PURCHASE`, `purchase_success`, `AI_PAYWALL_VIEW`), so the same funnel read differently\n * per tenant and no cross-app report was possible. These are the ONE set of names; the mappers are\n * the ONE definition of which RevenueCat fields are safe to send.\n *\n * PURE + dependency-free: no React, no React Native, no `react-native-purchases`, no transport.\n * Every function tolerates a malformed or absent snapshot and returns a defined value instead of\n * throwing, because a paywall must never break on an analytics mapping.\n */\nimport type {\n RevenueCatCustomerInfoLike,\n RevenueCatEntitlementLike,\n RevenueCatPackageLike,\n} from \"./types\";\n\n/**\n * The canonical purchase-funnel event names. These are `app_event` `question_key` values on the\n * wire, so they are ALSO the exact strings a review / questionnaire firing trigger matches on.\n * Never rename one: a rename silently unfires every trigger configured against the old string.\n */\nexport const WIRE_PURCHASE_EVENTS = {\n /** The paywall became visible (offerings loaded). */\n paywallShown: \"wire_paywall_shown\",\n /** The user tapped buy; the store sheet is about to open. */\n checkoutStarted: \"wire_checkout_started\",\n /** The store confirmed the purchase AND the entitlement is now active. */\n purchased: \"wire_purchase_completed\",\n /** The purchase did not land: a user cancel or a real store/network error (see `reason`). */\n purchaseFailed: \"wire_purchase_failed\",\n /** A restore ran (whether or not it produced an entitlement; see `plan_tier`). */\n restored: \"wire_purchase_restored\",\n} as const;\n\nexport type WirePurchaseEventName =\n (typeof WIRE_PURCHASE_EVENTS)[keyof typeof WIRE_PURCHASE_EVENTS];\n\n/**\n * The user-context key the bridge writes the tier to. It lands NAMESPACED as\n * `user_context[\"custom.plan_tier\"]` (host extras are always prefixed), which is the flattened\n * dimension the server report can break the funnel down by.\n */\nexport const PLAN_TIER_CONTEXT_KEY = \"plan_tier\";\n\n/** The three tiers the kit models. Anything richer belongs in the host's own analytics. */\nexport type PlanTier = \"paid\" | \"trial\" | \"free\";\n\n/** Read a plain record field defensively (the snapshot comes from a native bridge). */\nconst asRecord = (value: unknown): Record<string, unknown> | undefined =>\n typeof value === \"object\" && value !== null ? (value as Record<string, unknown>) : undefined;\n\n/**\n * The ACTIVE entitlement matching `entitlementId`, or `undefined`. Returns `undefined` for a\n * missing key, an explicitly inactive entry, and any malformed snapshot.\n */\nexport const activeEntitlement = (\n info: RevenueCatCustomerInfoLike | undefined,\n entitlementId: string,\n): RevenueCatEntitlementLike | undefined => {\n const active = asRecord(asRecord(asRecord(info)?.entitlements)?.active);\n const found = active?.[entitlementId];\n const entitlement = asRecord(found) as RevenueCatEntitlementLike | undefined;\n if (!entitlement) return undefined;\n // `isActive` is always present on the real type; treat an explicit `false` as not entitled and a\n // missing value as entitled, because the key only appears in `entitlements.active` at all when\n // RevenueCat considers it granted.\n return entitlement.isActive === false ? undefined : entitlement;\n};\n\n/** True when RevenueCat says this entitlement is a free trial rather than a paid period. */\nconst isTrial = (entitlement: RevenueCatEntitlementLike): boolean =>\n typeof entitlement.periodType === \"string\" && entitlement.periodType.toUpperCase() === \"TRIAL\";\n\n/** `paid` / `trial` / `free` for the configured entitlement. Never throws. */\nexport const resolvePlanTier = (\n info: RevenueCatCustomerInfoLike | undefined,\n entitlementId: string,\n): PlanTier => {\n const entitlement = activeEntitlement(info, entitlementId);\n if (!entitlement) return \"free\";\n return isTrial(entitlement) ? \"trial\" : \"paid\";\n};\n\n/**\n * Non-PII props for an offering package: which package, which product, what it costs. Every field\n * is optional on the wire, so a missing one is OMITTED rather than sent empty or invented.\n */\nexport const describePackage = (\n pkg: RevenueCatPackageLike | undefined,\n): Record<string, string | number> => {\n const props: Record<string, string | number> = {};\n if (!pkg) return props;\n if (typeof pkg.identifier === \"string\") props.package_id = pkg.identifier;\n if (typeof pkg.packageType === \"string\") props.package_type = pkg.packageType;\n if (typeof pkg.offeringIdentifier === \"string\") props.offering_id = pkg.offeringIdentifier;\n const product = asRecord(pkg.product) as RevenueCatProductFields | undefined;\n if (product) {\n if (typeof product.identifier === \"string\") props.product_id = product.identifier;\n if (typeof product.price === \"number\" && Number.isFinite(product.price)) {\n props.price = product.price;\n }\n if (typeof product.currencyCode === \"string\") props.currency = product.currencyCode;\n }\n return props;\n};\n\n/** The product fields `describePackage` reads, narrowed after the defensive record check. */\ntype RevenueCatProductFields = {\n identifier?: unknown;\n price?: unknown;\n currencyCode?: unknown;\n};\n\n/**\n * Non-PII props for the entitlement state after a purchase or a restore. Always carries\n * `entitlement` + `plan_tier` so a \"restore that granted nothing\" is still a queryable row; the\n * rest of the fields only appear when the entitlement is actually active.\n */\nexport const describeEntitlement = (\n info: RevenueCatCustomerInfoLike | undefined,\n entitlementId: string,\n): Record<string, string | number | boolean> => {\n const entitlement = activeEntitlement(info, entitlementId);\n const props: Record<string, string | number | boolean> = {\n entitlement: entitlementId,\n plan_tier: entitlement ? (isTrial(entitlement) ? \"trial\" : \"paid\") : \"free\",\n };\n if (!entitlement) return props;\n if (typeof entitlement.periodType === \"string\") props.period_type = entitlement.periodType;\n props.is_trial = isTrial(entitlement);\n if (typeof entitlement.willRenew === \"boolean\") props.will_renew = entitlement.willRenew;\n if (typeof entitlement.store === \"string\") props.store = entitlement.store;\n if (typeof entitlement.productIdentifier === \"string\") {\n props.product_id = entitlement.productIdentifier;\n }\n if (typeof entitlement.isSandbox === \"boolean\") props.is_sandbox = entitlement.isSandbox;\n return props;\n};\n\n/** RevenueCat's `PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR`. A STRING enum, value `\"1\"`. */\nconst PURCHASE_CANCELLED_CODE = \"1\";\n\n/**\n * True when the rejection is the user backing out of the store sheet rather than a real failure.\n * Reads BOTH signals the SDK exposes: the current `code` and the deprecated-but-still-populated\n * `userCancelled` flag. Anything else (including a plain `Error`) is a genuine failure.\n */\nexport const isUserCancelled = (error: unknown): boolean => {\n const record = asRecord(error);\n if (!record) return false;\n if (record.userCancelled === true) return true;\n return record.code === PURCHASE_CANCELLED_CODE;\n};\n\n/**\n * A short, stable, non-PII failure descriptor. The store's `message` is DELIBERATELY dropped: it is\n * localized, unbounded, and occasionally echoes the account it failed for, so it is not something\n * the kit forwards to a shared analytics backend. The RevenueCat `code` is the stable handle.\n */\nexport const describeFailure = (error: unknown): { reason: string; code: string } => {\n const record = asRecord(error);\n const code = typeof record?.code === \"string\" ? record.code : \"unknown\";\n return { reason: isUserCancelled(error) ? \"cancelled\" : \"error\", code };\n};\n","/**\n * revenueCatBridge - the short, first-class path from RevenueCat to Wire activation.\n *\n * const revenuecat = createRevenueCatBridge({ analytics, entitlementId: \"pro\" });\n * revenuecat.paywallShown(offering, { source: variant });\n * revenuecat.checkoutStarted(pkg, { source: variant });\n * const entitled = revenuecat.purchaseCompleted(customerInfo, pkg, { source: variant });\n *\n * WHAT IT REPLACES: every consumer was hand-rolling the same four things around its paywall,\n * differently: its own event names, its own idea of which RevenueCat fields are safe to send, its\n * own entitlement check duplicated at the purchase and the restore site, and its own plan-tier\n * user property. This owns all four, so adopting the purchase funnel is a constructor plus five\n * call sites.\n *\n * ── THE JOIN KEY (read this before you wire it) ───────────────────────────────────────────────\n * A purchase event is only worth anything if it can be joined to the SAME user's onboarding. The\n * key that does that is `user_context.device_key`, NOT `session_id`:\n *\n * • Purchase side: this bridge reports through a kit sink (`createAnalytics` or\n * `createWireActivation`). Both auto-mint a stable, persisted, per-install `device_key` and\n * stamp it on every event (see `context/deviceId.ts`).\n * • Onboarding side: `<WireOnboarding userContext={activationJoinContext(deviceKey)} />`. The kit\n * forwards `userContext` verbatim into the A2A session-start metadata, and the server records\n * it on the session's `session_started` event, where the SAME `device_key` lookup reads it.\n *\n * Pass the SAME `deviceKey` to both. `session_id` is NOT a join key across these two families: the\n * onboarding session id is the A2A `contextId`, the app-event session id is the per-open id, and\n * they live in disjoint spaces on purpose. Intersecting them yields zero rows, every time.\n *\n * PURE + dependency-free: no React, no React Native, no `react-native-purchases`. Fire-and-forget\n * throughout, so an analytics failure can never take the paywall down with it.\n */\nimport type { Analytics } from \"../analytics/analyticsFacade\";\nimport type { WireActivation } from \"../activation/wireActivation\";\nimport {\n PLAN_TIER_CONTEXT_KEY,\n WIRE_PURCHASE_EVENTS,\n describeEntitlement,\n describeFailure,\n describePackage,\n resolvePlanTier,\n type PlanTier,\n} from \"./purchaseEvents\";\nimport type {\n RevenueCatCustomerInfoLike,\n RevenueCatOfferingLike,\n RevenueCatPackageLike,\n RevenueCatSink,\n} from \"./types\";\n\n/**\n * COMPILE-TIME PROOF that both kit sinks satisfy {@link RevenueCatSink}, so a host can pass the\n * analytics instance it already holds with no adapter of its own. Type-only (erased at build), and\n * `tsc --noEmit` fails here the day either surface drifts. This lives in source, not the test file,\n * because `tsconfig.json` excludes tests from the typecheck.\n */\ntype AssertIsSink<T extends RevenueCatSink> = T;\ntype _AnalyticsIsASink = AssertIsSink<Analytics>;\ntype _WireActivationIsASink = AssertIsSink<WireActivation>;\n\n/** Small, non-PII extras a host merges onto a purchase event (paywall variant, entry point, ...). */\nexport type PurchaseProps = Record<string, string | number | boolean>;\n\n/** Inputs for {@link createRevenueCatBridge}. */\nexport interface RevenueCatBridgeConfig {\n /**\n * Where events go: the `createAnalytics(...)` instance (offline-first queue) or the\n * `createWireActivation(...)` instance (awaitable POST). Both already carry the `device_key` this\n * funnel joins on, so pass the one the app already holds rather than creating a second.\n */\n analytics: RevenueCatSink;\n /**\n * The entitlement identifier that means \"paid\" in THIS app, exactly as configured in the\n * RevenueCat dashboard (e.g. `\"pro\"`). The bridge reads `customerInfo.entitlements.active[id]`.\n */\n entitlementId: string;\n /** Non-PII props merged into EVERY event from this bridge. A per-call prop of the same name wins. */\n commonProps?: PurchaseProps;\n /**\n * Whether entitlement changes also update the bound user context with `plan_tier`\n * (`user_context[\"custom.plan_tier\"]`), so the whole funnel can be sliced paid vs trial vs free.\n * Default `true`. Requires a sink with `setUserContext` (`createAnalytics`); a no-op otherwise.\n */\n writePlanTier?: boolean;\n}\n\n/** The bridge surface. Every method is fire-and-forget and never throws. */\nexport interface RevenueCatBridge {\n /**\n * The paywall became visible. Pass the RevenueCat offering you just loaded and the bridge derives\n * `offering_id` + `packages_count`. Fires even with no offering, because a paywall that reached\n * the user with nothing to sell is exactly the failure you want in the funnel.\n */\n paywallShown(offering?: RevenueCatOfferingLike, props?: PurchaseProps): void;\n /** The user tapped buy and the store sheet is opening. */\n checkoutStarted(pkg: RevenueCatPackageLike, props?: PurchaseProps): void;\n /**\n * The store returned from a purchase. Fires `wire_purchase_completed` when the configured\n * entitlement is now active, and `wire_purchase_failed` with `reason: \"not_entitled\"` when the\n * store confirmed but nothing was granted (the case hosts usually drop on the floor). Syncs\n * `plan_tier` either way. Returns whether the user is entitled now, so the caller can navigate.\n */\n purchaseCompleted(\n customerInfo: RevenueCatCustomerInfoLike | undefined,\n pkg?: RevenueCatPackageLike,\n props?: PurchaseProps,\n ): boolean;\n /** The purchase call rejected. Separates a user cancel from a real store error via `reason`. */\n purchaseFailed(error: unknown, pkg?: RevenueCatPackageLike, props?: PurchaseProps): void;\n /** A restore finished. Reports the resulting tier and returns whether the user is entitled now. */\n purchasesRestored(\n customerInfo: RevenueCatCustomerInfoLike | undefined,\n props?: PurchaseProps,\n ): boolean;\n /**\n * Write the current tier to the bound user context WITHOUT emitting an event. Call it once at\n * launch with a `getCustomerInfo()` snapshot so returning subscribers are segmented correctly\n * from their first event of the session. Returns the tier it resolved.\n */\n syncPlanTier(customerInfo: RevenueCatCustomerInfoLike | undefined): PlanTier;\n}\n\n/**\n * Create a bridge bound to one sink and one entitlement. Pure, React-free, and safe to create at\n * module scope next to the paywall.\n */\nexport const createRevenueCatBridge = (config: RevenueCatBridgeConfig): RevenueCatBridge => {\n const { analytics, entitlementId } = config;\n const writeTier = config.writePlanTier !== false;\n\n /**\n * Send one event. Swallows a throwing sink AND a rejected promise from an awaitable one, so an\n * analytics failure is never visible at the paywall and never becomes an unhandled rejection.\n */\n const emit = (event: string, props: Record<string, unknown>): void => {\n try {\n const result = analytics.track(event, { ...config.commonProps, ...props });\n if (result && typeof (result as Promise<boolean>).catch === \"function\") {\n void (result as Promise<boolean>).catch(() => {});\n }\n } catch {\n /* analytics must never break a purchase */\n }\n };\n\n const syncPlanTier = (customerInfo: RevenueCatCustomerInfoLike | undefined): PlanTier => {\n const tier = resolvePlanTier(customerInfo, entitlementId);\n if (!writeTier) return tier;\n try {\n analytics.setUserContext?.({ extra: { [PLAN_TIER_CONTEXT_KEY]: tier } });\n } catch {\n /* a sink without a usable context writer is not a purchase failure */\n }\n return tier;\n };\n\n const paywallShown = (offering?: RevenueCatOfferingLike, props?: PurchaseProps): void => {\n const shown: Record<string, unknown> = {\n packages_count: offering?.availablePackages?.length ?? 0,\n };\n if (typeof offering?.identifier === \"string\") shown.offering_id = offering.identifier;\n emit(WIRE_PURCHASE_EVENTS.paywallShown, { ...shown, ...props });\n };\n\n const checkoutStarted = (pkg: RevenueCatPackageLike, props?: PurchaseProps): void => {\n emit(WIRE_PURCHASE_EVENTS.checkoutStarted, { ...describePackage(pkg), ...props });\n };\n\n const purchaseCompleted = (\n customerInfo: RevenueCatCustomerInfoLike | undefined,\n pkg?: RevenueCatPackageLike,\n props?: PurchaseProps,\n ): boolean => {\n const tier = syncPlanTier(customerInfo);\n const entitled = tier !== \"free\";\n if (entitled) {\n emit(WIRE_PURCHASE_EVENTS.purchased, {\n ...describePackage(pkg),\n ...describeEntitlement(customerInfo, entitlementId),\n ...props,\n });\n return true;\n }\n // The store said yes but the entitlement is not active: a product/entitlement mapping problem,\n // the single most common silent paywall defect. Report it rather than returning quietly.\n emit(WIRE_PURCHASE_EVENTS.purchaseFailed, {\n ...describePackage(pkg),\n reason: \"not_entitled\",\n code: \"unknown\",\n entitlement: entitlementId,\n ...props,\n });\n return false;\n };\n\n const purchaseFailed = (\n error: unknown,\n pkg?: RevenueCatPackageLike,\n props?: PurchaseProps,\n ): void => {\n emit(WIRE_PURCHASE_EVENTS.purchaseFailed, {\n ...describePackage(pkg),\n ...describeFailure(error),\n ...props,\n });\n };\n\n const purchasesRestored = (\n customerInfo: RevenueCatCustomerInfoLike | undefined,\n props?: PurchaseProps,\n ): boolean => {\n const tier = syncPlanTier(customerInfo);\n emit(WIRE_PURCHASE_EVENTS.restored, {\n ...describeEntitlement(customerInfo, entitlementId),\n ...props,\n });\n return tier !== \"free\";\n };\n\n return { paywallShown, checkoutStarted, purchaseCompleted, purchaseFailed, purchasesRestored, syncPlanTier };\n};\n","/**\n * reportSessionStart — the ONE standard emitter for \"the user opened the app again\".\n *\n * Every app-open posts a single `app.session_started` event to the Wire analytics backend\n * (`POST {serverUrl}/v1/events`). That event does two jobs at once, with ZERO server changes:\n *\n * 1. SESSION MAPPING. It carries the host's opaque `userId` + a stable `deviceKey`, so the\n * backend can group a user's (or a pre-auth device's) opens over time — \"when did this\n * user last use the app, and how many times\". The device_key links the pre-auth opens to\n * the user once `userId` arrives (here or via `identifyOnboarding`).\n * 2. QUESTIONNAIRE / RETENTION FIRING. It flows into the SAME event stream the server's\n * decision engines read, so a questionnaire trigger `{event:\"app.session_started\", min_count:N}`\n * (matched within a session) or a questionnaire `min_sessions:N` (distinct device sessions)\n * fires on the user's Nth open with no new server endpoint.\n *\n * WIRE CONTRACT (server: analytics/events.py + routers/onboarding.py `POST /v1/events`):\n * The event is stored as `event_type='app_event'`, `question_key='app.session_started'` — the\n * generic app.* namespace the reviews wave shipped. The server's `_event_name(ev)` returns the\n * `question_key` for an `app_event`, which is what a trigger's `event` string matches. We do NOT\n * send `event_type:'app.session_started'` — that name is not in the server's EVENT_TYPES and\n * would be rejected. `device_key` rides in the non-PII `user_context` bucket, where the server's\n * `_event_device_key(ev)` reads it to group a device's sessions. `app_id` + `environment` are\n * filled server-side from the resolving key (never sent here).\n *\n * SESSION ID DISTINCTION (important): the `session_id` on this event is a PER-OPEN id (a fresh\n * `makeSessionId()` each app-open) — it is NOT the onboarding A2A `contextId`. Onboarding runs\n * ONCE (first launch) and owns its own context id; session-start fires on EVERY open, so it needs\n * its own per-open id. Grouping over time is done by `device_key`/`user_id`, not by session_id.\n *\n * Fire-and-forget: like every analytics path in the kit, this never throws into the UI, never\n * awaits, and swallows a missing target / bad URL / missing fetch / network error. Analytics must\n * never be able to break the app.\n */\nimport { setCurrentSessionId } from \"../analytics/currentSession\";\nimport {\n makeSessionId,\n warnOnSkippedEvents,\n type ClientEvent,\n type ClientEventTarget,\n} from \"../analytics/reportClientEvent\";\nimport type { DeviceContext } from \"../device/deviceContext\";\nimport { sanitizeUserId } from \"../identity/userIdentity\";\n\n/** The canonical event name for an app-open. A trigger keys off this exact string. */\nexport const SESSION_STARTED_EVENT = \"app.session_started\" as const;\n\n/** Options for {@link reportSessionStart}. Everything except `target` is optional so a pre-auth\n * open (no user yet) is a valid, device-only session. */\nexport interface ReportSessionStartOptions {\n /** Where to POST — the tenant transport (`serverUrl` + `apiKey`), same as `WireOnboardingConfig`. */\n target: ClientEventTarget | undefined;\n /**\n * The per-open session id. Defaults to a fresh `makeSessionId()`. Pass your own ONLY to\n * dedupe re-renders of the same open (the {@link useSessionStart} hook does exactly that).\n * This is NOT the onboarding contextId — see the file header.\n */\n sessionId?: string;\n /** The host's OPAQUE pseudonymous user id (their internal id, NOT an email/PII). Sanitized +\n * capped here; omitted on a pre-auth open (device-only session). */\n userId?: string;\n /** A stable, non-PII device id the host owns. Rides in `user_context.device_key` so the server\n * groups this device's sessions (the min_sessions signal). Host-supplied, same as reviews. */\n deviceKey?: string;\n /** The host's own local open-counter value for this open (1 on the first ever open). Drives the\n * `returning` flag and lets analytics read \"Nth session\" without server-side counting. */\n sessionCount?: number;\n /** Host app version (e.g. \"1.4.2\"), if cheaply available. Segments retention by release. */\n appVersion?: string;\n /** Platform string (e.g. \"ios\"), if cheaply available. */\n platform?: string;\n /** An optional richer device snapshot (from `collectDeviceContext()`); the hook fills this. */\n device?: DeviceContext;\n /** Small non-PII extras, stored as a JSON string in the event `meta`. */\n meta?: Record<string, unknown>;\n /** Set `false` to bypass the once-per-open guard (default on). See {@link resetSessionStartGuard}. */\n once?: boolean;\n /**\n * OPTIONAL transport sink. When provided, the built `app.session_started` event is routed HERE\n * (e.g. the offline-first event queue's `enqueue`) INSTEAD of this emitter's own direct `fetch`,\n * while KEEPING the once-per-open guard above. This is how the lifecycle wiring\n * (`useLifecycleEvents` / `wireLifecycleEvents`) offline-buffers session-start WITHOUT adding a\n * second session emitter: one emitter, one guard, now durable. Omit it for the direct-POST path.\n * A throwing sink is swallowed — analytics must never surface into the UI.\n */\n sink?: (event: ClientEvent) => void;\n}\n\n// ── Once-per-open guard ──────────────────────────────────────────────────────\n// A re-render (or a host that lists the emitter in an effect) must never double-fire the SAME\n// open. We remember the session ids already emitted; a repeat call with a seen id is a no-op.\n// Bounded so a long-lived app never grows this unboundedly — a fresh open always mints a fresh\n// id, so evicting old ids can never cause a real re-fire.\nconst _emitted = new Set<string>();\nconst _GUARD_MAX = 128;\n\n/** Test-only: forget every emitted session id so a unit test starts from a clean guard. */\nexport const resetSessionStartGuard = (): void => {\n _emitted.clear();\n};\n\n/**\n * Emit one `app.session_started` event for this app-open. Fire-and-forget; returns immediately.\n * Idempotent per `sessionId` (unless `once:false`) so a re-render can never double-fire.\n */\nexport const reportSessionStart = (opts: ReportSessionStartOptions): void => {\n const target = opts.target;\n // A wired sink is a valid transport on its own — it owns the target (the queue's serverUrl), so\n // this emitter needs its own `target` ONLY for the direct-fetch fallback.\n if (!opts.sink && !target?.serverUrl) return;\n\n const sessionId = opts.sessionId ?? makeSessionId();\n\n // Register this open as the CURRENT per-open session so the analytics façade's `identify` /\n // app-events reuse the id the server sees here (via `app.session_started`) instead of minting a\n // fresh one it would back-fill into a phantom session. Idempotent; set before the once-guard so\n // even a guard-deduped repeat keeps the current id pointing at this open.\n setCurrentSessionId(sessionId);\n\n // Once-per-open guard: skip a repeat emit for a session id we already sent.\n if (opts.once !== false) {\n if (_emitted.has(sessionId)) return;\n if (_emitted.size >= _GUARD_MAX) {\n // Evict the oldest insertion (Set preserves insertion order).\n const oldest = _emitted.values().next().value;\n if (oldest !== undefined) _emitted.delete(oldest);\n }\n _emitted.add(sessionId);\n }\n\n try {\n // Non-PII correlation bucket. device_key is read by the server to group a device's sessions;\n // session_count / returning / app_version / platform feed per-user retention analytics.\n const userContext: Record<string, string | number | boolean> = {};\n if (opts.deviceKey) userContext.device_key = opts.deviceKey;\n if (typeof opts.sessionCount === \"number\" && Number.isFinite(opts.sessionCount)) {\n userContext.session_count = opts.sessionCount;\n userContext.returning = opts.sessionCount > 1;\n }\n if (opts.appVersion) userContext.app_version = opts.appVersion;\n if (opts.platform) userContext.platform = opts.platform;\n\n const event: Record<string, unknown> = {\n event_type: \"app_event\",\n question_key: SESSION_STARTED_EVENT,\n session_id: sessionId,\n };\n const userId = sanitizeUserId(opts.userId);\n if (userId) event.user_id = userId;\n if (Object.keys(userContext).length > 0) event.user_context = userContext;\n if (opts.device) event.device = opts.device;\n if (opts.meta && Object.keys(opts.meta).length > 0) event.meta = JSON.stringify(opts.meta);\n\n // Preferred transport: an injected sink (the offline-first event queue's `enqueue`), which\n // buffers + persists + retries. The once-guard above already ran, so this stays the single\n // session emitter with a single guard — now durable.\n if (opts.sink) {\n opts.sink(event as ClientEvent);\n return;\n }\n\n // Fallback: this emitter's own direct POST when no sink is wired.\n if (!target?.serverUrl) return;\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/v1/events`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n void fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ events: [event] }),\n })\n .then((res) => {\n // A 200 can still carry `skipped:N` — the server took the request and threw the event away.\n // Log-only; this path has nothing to retry either way.\n warnOnSkippedEvents(res);\n })\n .catch(() => {\n // Network/transport error — analytics is best-effort, swallow.\n });\n } catch {\n // URL construction, JSON serialization, a throwing sink, or a missing fetch — swallow.\n }\n};\n","/**\n * useSessionStart — the optional convenience hook that fires {@link reportSessionStart} for you.\n *\n * Two firing moments, mirroring the reference apps' session-counter semantics:\n * • ON MOUNT — the app opened (cold start or the provider first rendered).\n * • ON FOREGROUND after a real background — when AppState returns to `active` having been\n * backgrounded for at least {@link BACKGROUND_SESSION_MS} (30 min), that's a NEW open, so a\n * fresh session fires. A quick app-switch (under the threshold) does NOT count as a new open.\n *\n * Each firing mints its OWN per-open `session_id` (held in a ref so a re-render never re-fires),\n * so grouping over time is by `deviceKey`/`userId`, never by session_id (see reportSessionStart).\n *\n * NOT THE DEFAULT WIRING. `useLifecycleEvents` is: this hook emits `app.session_started` ONLY, so a\n * host on this path has a permanently empty `app.first_open` and no top of funnel. Use it when you\n * already own an open counter and deliberately want session starts alone; otherwise mount\n * `useLifecycleEvents(config, { deviceKey?, sessionCount?, userId? })` once at the app root.\n *\n * The hook is OPTIONAL. A host that already owns a session counter (most hosts do) can skip\n * the hook and call `reportSessionStart(...)` directly from its own \"app opened\" path — BOTH\n * paths are first-class. This hook is the batteries-included option for a host that has none.\n *\n * Dependency policy: `AppState` + `Platform` are React Native built-ins (no new dep); the device\n * snapshot comes from the kit's own dependency-free `collectDeviceContext()`.\n */\nimport { useEffect, useRef } from \"react\";\nimport { AppState, Platform, type AppStateStatus } from \"react-native\";\n\nimport type { ClientEventTarget } from \"../analytics/reportClientEvent\";\nimport { resolveAutoDeviceKey } from \"../context/deviceId\";\nimport { collectDeviceContext } from \"../device/deviceContext\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\nimport { reportSessionStart } from \"./reportSessionStart\";\n\n/** A foreground after at least this long in the background counts as a NEW app-open (30 min). */\nexport const BACKGROUND_SESSION_MS = 30 * 60 * 1000;\n\n/** Tenant transport + optional host app version. Same creds as `WireOnboardingConfig`. */\nexport interface SessionStartConfig {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/v1/events` is appended. */\n serverUrl?: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey?: string;\n /** Host app version (e.g. \"1.4.2\"), forwarded for release segmentation. Optional. */\n appVersion?: string;\n /** Tenant/app id — namespaces the auto `device_key` fallback below. */\n appId?: string;\n /** Host storage (AsyncStorage subset). Present → `app.session_started` falls back to the kit's\n * persisted auto `device_key` when the host passes none. Absent → no fallback (see below). */\n storage?: WireOnboardingStorage;\n}\n\n/** Per-open identity the host supplies. All optional: a pre-auth open is device-only. */\nexport interface UseSessionStartOptions {\n /** The host's opaque pseudonymous user id (NOT PII). Omitted before the user authenticates. */\n userId?: string;\n /** The host's local open-counter value for this open. Drives `returning` + \"Nth session\". */\n sessionCount?: number;\n /** A stable, non-PII device id the host owns. Groups this device's sessions server-side. */\n deviceKey?: string;\n /** Small non-PII extras forwarded on the event `meta`. */\n meta?: Record<string, unknown>;\n /** Set `false` to disable firing (e.g. behind a consent gate). Default enabled. */\n enabled?: boolean;\n}\n\n/**\n * Fire `app.session_started` on mount and on every real foreground-after-background. Returns\n * nothing — it is a side-effecting hook. Safe to call with inline options (values are read\n * through a ref, so changing `userId`/`sessionCount` never re-fires a session).\n */\nexport const useSessionStart = (\n config: SessionStartConfig | undefined,\n options: UseSessionStartOptions = {},\n): void => {\n // Latest options/config through a ref so the mount/resume fires read fresh values without\n // listing them as effect deps (which would re-fire a session on every prop change).\n const latest = useRef({ config, options });\n latest.current = { config, options };\n\n useEffect(() => {\n /**\n * The `device_key` this open rides under. A host-supplied id always wins.\n *\n * BACKPORTED FROM `useLifecycleEvents` (which had this and this hook did not): `min_sessions` is\n * computed server-side by counting distinct `app.session_started` grouped by\n * `user_context.device_key`, so a host that passed no `deviceKey` emitted the counted event with\n * NO key while its facade / activation events carried an auto-minted one — two disjoint identity\n * spaces, and a counter that could never increase. The two session-start paths must not diverge\n * on the thing the firing rule reads.\n *\n * ONLY WITH `storage`, for the same reason as the sibling hook: without persistence the auto id\n * is per-LAUNCH, and a per-launch key makes every open look like a new device, corrupting\n * `min_sessions` in the other direction.\n */\n const resolveDeviceKey = (\n cfg: SessionStartConfig | undefined,\n opts: UseSessionStartOptions,\n ): string | undefined => {\n const host = typeof opts.deviceKey === \"string\" && opts.deviceKey.trim() ? opts.deviceKey : undefined;\n if (host) return host;\n if (!cfg?.storage) return undefined;\n return resolveAutoDeviceKey({ appId: cfg.appId, storage: cfg.storage });\n };\n\n const fire = () => {\n const { config: cfg, options: opts } = latest.current;\n if (!cfg?.serverUrl) return;\n if (opts.enabled === false) return;\n const target: ClientEventTarget = { serverUrl: cfg.serverUrl, apiKey: cfg.apiKey ?? \"\" };\n const device = collectDeviceContext();\n // `device.appVersion` is auto-detected best-effort; an explicit host version always wins.\n if (cfg.appVersion) device.appVersion = cfg.appVersion;\n reportSessionStart({\n target,\n // A fresh per-open id each fire; the emitter's once-guard dedupes within the open.\n userId: opts.userId,\n deviceKey: resolveDeviceKey(cfg, opts),\n sessionCount: opts.sessionCount,\n appVersion: cfg.appVersion ?? device.appVersion,\n platform: Platform.OS,\n device,\n meta: opts.meta,\n });\n };\n\n // 1) Mount = an app-open.\n fire();\n\n // 2) Foreground after a real background = a new app-open.\n let backgroundedAt: number | null = null;\n const onChange = (state: AppStateStatus) => {\n if (state === \"background\" || state === \"inactive\") {\n // Record the first moment we left the foreground (don't overwrite inactive→background).\n if (backgroundedAt == null) backgroundedAt = Date.now();\n return;\n }\n if (state === \"active\") {\n const since = backgroundedAt;\n backgroundedAt = null;\n if (since != null && Date.now() - since >= BACKGROUND_SESSION_MS) fire();\n }\n };\n const sub = AppState.addEventListener(\"change\", onChange);\n return () => {\n // RN >= 0.65 returns a subscription with remove(); guard for older shims.\n if (sub && typeof (sub as { remove?: () => void }).remove === \"function\") sub.remove();\n };\n // Mount-only effect: firing reads fresh values via `latest`, so no reactive deps.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n};\n","/**\n * lifecycle — the TOP-OF-FUNNEL app lifecycle events that sit ABOVE onboarding: `app.first_open`\n * (once ever per install) and `app.session_started` (per app-open). They compose with, and never\n * duplicate, the events the funnel already records.\n *\n * WHERE THIS FITS (one funnel, no double counting):\n * • `app.first_open` → THIS module, once ever (persisted flag). The in-app \"install\" proxy.\n * • `app.session_started` → the EXISTING {@link reportSessionStart} emitter (per app-open). This\n * module REUSES it (routed through the offline queue), never re-emits.\n * • onboarding started / completed / activated → ALREADY recorded: the server writes\n * `session_started` + `completed` during the A2A flow, and the client reports `dropped` /\n * `client_fallback` / `identify` via `reportClientEvent`. This module does NOT touch them —\n * emitting them here would double-count. It only ADDS the two lifecycle events above them.\n *\n * WIRE CONTRACT (identical to `app.session_started`): both lifecycle events are stored as\n * `event_type='app_event'` with the name in `question_key` (the server's `_event_name` returns\n * `question_key` for an `app_event`, which a trigger matches). `app.first_open` uses the SAME\n * `app.*` namespace + the SAME event shape as `app.session_started` — no bespoke `event_type`,\n * no invented contract. `device_key` rides in the non-PII `user_context` bucket; `app_id` +\n * `environment` are filled server-side.\n *\n * TWO FIRST-CLASS ENTRY POINTS (mirrors reportSessionStart vs useSessionStart):\n * • `reportFirstOpen(...)` / `wireLifecycleEvents(...)` — pure, React-free, for a host that owns\n * its own app-open path.\n * • `useLifecycleEvents(...)` — the batteries-included React hook (in `useLifecycleEvents.ts`).\n *\n * OFFLINE-FIRST: pass the Brief-01 event queue's `enqueue` as the `sink` and every lifecycle event\n * is buffered + persisted + retried instead of a blind fetch. Without a sink they degrade to a\n * direct fire-and-forget POST.\n *\n * PRIVACY (hard rule, same as the rest of the kit): NO GPS/location, NO advertising id. Nothing\n * here carries a coordinate or an ad id — a host adopting it changes no store privacy declaration.\n *\n * FIRE-AND-FORGET: like every analytics path in the kit, nothing here throws into the UI, awaits\n * in the caller, or hangs the app — storage reads race a short timeout, writes swallow errors.\n */\nimport { buildEventsRequest, makeSessionId, type ClientEvent, type ClientEventTarget } from \"../analytics/reportClientEvent\";\nimport type { DeviceContext } from \"../device/deviceContext\";\nimport { sanitizeUserId } from \"../identity/userIdentity\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\nimport { reportSessionStart, SESSION_STARTED_EVENT } from \"./reportSessionStart\";\n\n/** The canonical event name for the first-ever app open. Same `app.*` namespace as\n * {@link SESSION_STARTED_EVENT}; a trigger keys off this exact string. */\nexport const FIRST_OPEN_EVENT = \"app.first_open\" as const;\n\n/** Storage key for the once-ever first-open flag, e.g. `wireai:first_open:acme`. Mirrors the\n * `wireai:<concern>:<appId>` namespacing of {@link sessionStorageKey}. */\nexport const firstOpenStorageKey = (appId: string): string => `wireai:first_open:${appId}`;\n\n/** Ceiling on the flag read — a hung adapter degrades to the in-memory latch, never a stuck gate. */\nconst READ_TIMEOUT_MS = 1_500;\n\nconst withTimeout = <T>(p: Promise<T>, ms: number): Promise<T | undefined> => {\n let timer: ReturnType<typeof setTimeout>;\n const timeout = new Promise<undefined>((resolve) => {\n timer = setTimeout(() => resolve(undefined), ms);\n });\n return Promise.race([p, timeout]).finally(() => clearTimeout(timer));\n};\n\n// ── First-open in-memory latch ───────────────────────────────────────────────\n// Covers TWO cases the persisted flag can't: (1) two near-simultaneous calls in one process (the\n// flag read is async, so a synchronous latch is what guarantees at-most-one before any await), and\n// (2) the documented DEGRADED no-storage mode (fires once per process). Keyed by appId.\nconst _firstOpenLatched = new Set<string>();\n\n/** Test-only: forget the first-open latch so a unit test starts from a clean process state. */\nexport const resetFirstOpenLatch = (): void => {\n _firstOpenLatched.clear();\n};\n\n/** Shared inputs for a lifecycle event. Everything is optional except a transport (`target` for the\n * direct-POST fallback, or a `sink`). A pre-auth open (no user yet) is a valid device-only event. */\nexport interface LifecycleEventInput {\n /** Where to POST if no `sink` is wired (the tenant transport, same as `WireOnboardingConfig`). */\n target?: ClientEventTarget;\n /** Preferred transport: route the built event HERE (the offline queue's `enqueue`). */\n sink?: (event: ClientEvent) => void;\n /** The per-open session id. Defaults to a fresh `makeSessionId()`. */\n sessionId?: string;\n /** The host's OPAQUE pseudonymous user id (NOT PII). Sanitized + capped; omitted pre-auth. */\n userId?: string;\n /** A stable, non-PII device id the host owns. Rides in `user_context.device_key`. */\n deviceKey?: string;\n /** The host's local open-counter value. Drives `returning` + \"Nth session\". */\n sessionCount?: number;\n /** Host app version (e.g. \"1.4.2\"), if cheaply available. */\n appVersion?: string;\n /** Platform string (e.g. \"ios\"), if cheaply available. */\n platform?: string;\n /** An optional richer device snapshot (from `collectDeviceContext()`); the hook fills this. */\n device?: DeviceContext;\n /** Small non-PII extras, stored as a JSON string in the event `meta`. */\n meta?: Record<string, unknown>;\n}\n\n/** Options for {@link reportFirstOpen}. Adds the once-ever persistence inputs on top of the shared\n * lifecycle inputs. Without `storage` it degrades to the in-memory latch (once per process). */\nexport interface ReportFirstOpenOptions extends LifecycleEventInput {\n /** Host persistence (AsyncStorage subset). The once-ever flag lives here — it is what survives an\n * app kill. Omit it for the documented degraded (in-memory, once-per-process) mode. */\n storage?: WireOnboardingStorage;\n /** Tenant/app id — namespaces the persisted flag (`wireai:first_open:<appId>`). */\n appId?: string;\n}\n\n/**\n * Build the `app_event` payload shared by `app.first_open` and `app.session_started`. This is a\n * BYTE-FOR-BYTE mirror of the field logic in {@link reportSessionStart} — same `event_type`, same\n * `question_key`-as-name contract, same `user_context` bucket, same optional fields — so the two\n * lifecycle events are one contract with two names. Do NOT let these diverge (see lifecycle.test).\n */\nconst buildLifecycleEvent = (questionKey: string, opts: LifecycleEventInput): Record<string, unknown> => {\n const userContext: Record<string, string | number | boolean> = {};\n if (opts.deviceKey) userContext.device_key = opts.deviceKey;\n if (typeof opts.sessionCount === \"number\" && Number.isFinite(opts.sessionCount)) {\n userContext.session_count = opts.sessionCount;\n userContext.returning = opts.sessionCount > 1;\n }\n if (opts.appVersion) userContext.app_version = opts.appVersion;\n if (opts.platform) userContext.platform = opts.platform;\n\n const event: Record<string, unknown> = {\n event_type: \"app_event\",\n question_key: questionKey,\n session_id: opts.sessionId ?? makeSessionId(),\n };\n const userId = sanitizeUserId(opts.userId);\n if (userId) event.user_id = userId;\n if (Object.keys(userContext).length > 0) event.user_context = userContext;\n if (opts.device) event.device = opts.device;\n if (opts.meta && Object.keys(opts.meta).length > 0) event.meta = JSON.stringify(opts.meta);\n return event;\n};\n\n/** Route a built event to the wired sink, else a direct fire-and-forget POST. Never throws. */\nconst routeLifecycleEvent = (event: Record<string, unknown>, opts: LifecycleEventInput): void => {\n try {\n if (opts.sink) {\n opts.sink(event as ClientEvent);\n return;\n }\n // Route the direct-POST fallback through the ONE canonical /v1/events builder (url + headers +\n // body) instead of re-describing the endpoint here; still fire-and-forget.\n const req = buildEventsRequest(opts.target, [event as unknown as ClientEvent]);\n if (!req) return;\n void fetch(req.url, req.init).catch(() => {\n // Network/transport error — analytics is best-effort, swallow.\n });\n } catch {\n // A throwing sink, URL/JSON error, or a missing fetch — swallow.\n }\n};\n\nconst emitFirstOpen = (opts: ReportFirstOpenOptions): void => {\n routeLifecycleEvent(buildLifecycleEvent(FIRST_OPEN_EVENT, opts), opts);\n};\n\n/**\n * Emit `app.first_open` EXACTLY ONCE EVER per install. Fire-and-forget; returns immediately.\n *\n * • With `storage`: reads the persisted flag (`wireai:first_open:<appId>`). Absent → emit, then\n * write the flag (survives app kills, so a second launch is a no-op). Present → no-op.\n * • Race guard: an in-memory latch is set SYNCHRONOUSLY before the async read, so two\n * near-simultaneous calls fire at most once.\n * • Without `storage`: degraded mode — fires once per PROCESS via the latch only (documented).\n */\nexport const reportFirstOpen = (opts: ReportFirstOpenOptions): void => {\n const appId = opts.appId ?? \"default\";\n\n // Synchronous latch FIRST: guarantees at-most-one before any await (same-process race guard) and\n // is the sole guard in the no-storage degraded mode.\n if (_firstOpenLatched.has(appId)) return;\n _firstOpenLatched.add(appId);\n\n const storage = opts.storage;\n if (!storage) {\n // Degraded: no persistence to survive a kill → the latch fires it once per process.\n emitFirstOpen(opts);\n return;\n }\n\n const key = firstOpenStorageKey(appId);\n void (async () => {\n try {\n const seen = await withTimeout(storage.getItem(key), READ_TIMEOUT_MS);\n // A prior launch already fired + wrote the flag → once-ever satisfied, no-op.\n if (seen) return;\n emitFirstOpen(opts);\n try {\n // Best-effort persist: a failed write just means the next launch may re-fire once.\n void storage.setItem(key, JSON.stringify({ ts: Date.now() })).catch(() => {});\n } catch {\n // Missing/broken storage write — swallow.\n }\n } catch {\n // Unreadable flag → the in-memory latch still caps us at one fire this process.\n emitFirstOpen(opts);\n }\n })();\n};\n\n/** Options for {@link wireLifecycleEvents}: the shared lifecycle inputs + first-open persistence. */\nexport interface WireLifecycleOptions extends ReportFirstOpenOptions {}\n\n/**\n * Wire BOTH lifecycle events in one call for a host that owns its own app-open path (the non-hook\n * counterpart to {@link useLifecycleEvents}). Fires `app.first_open` (once ever) and one\n * `app.session_started` for THIS open through the EXISTING {@link reportSessionStart} emitter (so\n * the once-per-open guard still applies — pass the same `sessionId` and it never double-fires).\n * Route both through the same `sink` (the offline queue) to buffer them. Fire-and-forget.\n */\nexport const wireLifecycleEvents = (opts: WireLifecycleOptions): void => {\n // ONE per-open id for BOTH events when the caller supplies none. Without this, `reportFirstOpen`\n // fell through to `buildLifecycleEvent`'s own `makeSessionId()` while `reportSessionStart` minted a\n // DIFFERENT one — so `app.first_open` carried a session id the server never saw a `session_started`\n // for and back-filled into a phantom session, inflating session counts. `useLifecycleEvents` already\n // pinned this (it mints `mountOpenSessionId`); the React-free entry point did not, so the identical\n // bug was still reachable from the documented non-hook path.\n const sessionId = opts.sessionId ?? makeSessionId();\n reportFirstOpen({ ...opts, sessionId });\n reportSessionStart({\n target: opts.target,\n sink: opts.sink,\n sessionId,\n userId: opts.userId,\n deviceKey: opts.deviceKey,\n sessionCount: opts.sessionCount,\n appVersion: opts.appVersion,\n platform: opts.platform,\n device: opts.device,\n meta: opts.meta,\n });\n};\n\n// Re-exported so callers wiring lifecycle events have the session name alongside the first-open one.\nexport { SESSION_STARTED_EVENT };\n","/**\n * eventQueue — the OFFLINE-FIRST, persistent transport buffer for client analytics events.\n *\n * The existing `reportClientEvents` is a blind fire-and-forget POST: it returns `void`, has no\n * success signal, and drops events when the network is down. The analytics data story depends on\n * NEVER losing an event offline, so this queue adds the missing durability layer on top of the\n * same `POST {serverUrl}/v1/events` contract:\n *\n * • Persists pending events to the host-injected `WireOnboardingStorage` (survives app kills).\n * • Batches them into one request body `{ events: [...] }`.\n * • Owns its OWN awaited `fetch` that reads `res.ok` — the only way to drive retry + dequeue,\n * since `reportClientEvents` cannot ack. A 2xx dequeues the batch; a non-ok / rejected / thrown\n * response keeps it and schedules an exponential backoff retry.\n * • Flushes on `enqueue`, on an explicit `flush()`, and on `notifyOnline()` (host reconnect).\n * • Caps the buffer (drop-OLDEST under pressure) and de-dups identical pending events.\n * • Stamps the current context envelope (device + host scalars) onto every event before send.\n *\n * FIRE-AND-FORGET (load-bearing): `enqueue` returns immediately and NEVER throws into the UI. A\n * missing `fetch`, a hung/broken storage, a rejecting network, or a JSON error is swallowed and\n * degrades gracefully — analytics must never be able to break the app. In-memory fallback covers\n * the no-storage case (survives re-renders, not app kills).\n *\n * DEPENDENCY-FREE: no network-detection or persistence library. Connectivity is host-driven via\n * `notifyOnline()`; persistence is the host-injected AsyncStorage-compatible subset.\n */\nimport type { ContextEnvelope } from \"./contextEnvelope\";\nimport {\n buildEventsRequest,\n warnOnSkippedEvents,\n type ClientEvent,\n type ClientEventTarget,\n} from \"./reportClientEvent\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\nimport { warnInDev } from \"../utils/warnInDev\";\n\n/** Envelope source: a fixed envelope or a provider evaluated at enqueue time (fresh network type). */\nexport type EnvelopeSource = ContextEnvelope | (() => ContextEnvelope | undefined);\n\n/** Options for {@link createEventQueue}. Only `target` is conceptually required to actually send. */\nexport type EventQueueOptions = {\n /** Where to POST — the tenant transport (`serverUrl` + `apiKey`), same as `WireOnboardingConfig`. */\n target: ClientEventTarget | undefined;\n /**\n * Host persistence (AsyncStorage-compatible subset). When omitted, the queue runs in the\n * documented DEGRADED in-memory mode — it survives re-renders but not an app kill.\n */\n storage?: WireOnboardingStorage;\n /** Tenant/app id used to namespace the default storage key (`wireai:evtq:<appId>`). */\n appId?: string;\n /** Explicit storage key override (wins over the `appId`-derived default). */\n storageKey?: string;\n /** The context envelope stamped onto every event before send (device + host scalars). */\n envelope?: EnvelopeSource;\n /** Max pending events; enqueuing past this DROPS THE OLDEST first (default 200). */\n maxSize?: number;\n /** Events per POST batch (default 20). */\n batchSize?: number;\n /** First retry delay in ms; doubles each failed attempt (default 1000). */\n baseBackoffMs?: number;\n /** Backoff ceiling in ms (default 30000). */\n maxBackoffMs?: number;\n /** Max AUTOMATIC backoff retries before pausing (default 6); `notifyOnline()`/`flush()` re-arm it. */\n maxRetries?: number;\n};\n\n/** The queue's public surface. `enqueue` is fire-and-forget (returns immediately, never throws). */\nexport type EventQueue = {\n /** Buffer one event (envelope-stamped), persist, and schedule a flush. Never throws. */\n enqueue(event: ClientEvent): void;\n /** Attempt an immediate drain of the pending buffer. Fire-and-forget. */\n flush(): void;\n /** Host reconnect signal: reset backoff and drain immediately. Fire-and-forget. */\n notifyOnline(): void;\n /** Current pending (in-memory) count. */\n size(): number;\n};\n\nconst DEFAULTS = {\n maxSize: 200,\n batchSize: 20,\n baseBackoffMs: 1000,\n maxBackoffMs: 30000,\n maxRetries: 6,\n} as const;\n\n/** Ceiling on the persisted-backlog read — a hung adapter degrades to an empty start, never a stall. */\nconst READ_TIMEOUT_MS = 1500;\n\n// ── One storage slot per QUEUE, not per appId (K4) ───────────────────────────────────────────────\n//\n// The default key was derived from `appId` alone, so two `createAnalytics` instances for one tenant —\n// the documented double-wiring, a façade for `track`/`screen` plus an activation instance — shared ONE\n// persisted backlog while keeping SEPARATE in-memory buffers. Every symptom of that is silent:\n// each `persist()` overwrites the other's blob with its own view of \"pending\"; a queue that drains to\n// empty calls `removeItem` and DELETES a sibling's still-pending events; and on relaunch whatever\n// survived is loaded by both instances and sent twice. `useLifecycleEvents` already avoided all of it\n// by handing its queue a dedicated explicit key — this generalizes that.\n//\n// A `Symbol.for` slot for the same reason as every other registry here: tsup inlines a copy of this\n// module into each bundle, and a plain module `let` would let the `.` and `./analytics` copies each\n// think they were the first claimant of the same key.\nconst QUEUE_KEY_SLOT: unique symbol = Symbol.for(\"@wireai/activation:eventQueueKeys\");\n\ntype GlobalWithQueueKeys = typeof globalThis & { [QUEUE_KEY_SLOT]?: Set<string> };\n\nconst queueKeyGlobal = globalThis as GlobalWithQueueKeys;\n\nconst claimedQueueKeys = (): Set<string> => {\n const existing = queueKeyGlobal[QUEUE_KEY_SLOT];\n if (existing) return existing;\n const created = new Set<string>();\n queueKeyGlobal[QUEUE_KEY_SLOT] = created;\n return created;\n};\n\n/**\n * Claim `preferred` for this queue, or the next free `preferred#N` when a live queue already holds it.\n *\n * ONLY the appId-derived DEFAULT is ever rotated. An EXPLICIT `storageKey` is the host (or\n * `useLifecycleEvents`) declaring which slot a queue owns, and that hook re-creates its queue on every\n * remount — rotating there would silently walk it off its own backlog once per remount, which is a\n * worse bug than the one being fixed.\n */\nconst claimQueueKey = (preferred: string, explicit: boolean): string => {\n const claimed = claimedQueueKeys();\n if (explicit || !claimed.has(preferred)) {\n claimed.add(preferred);\n return preferred;\n }\n let ordinal = 2;\n while (claimed.has(`${preferred}#${ordinal}`)) ordinal++;\n const key = `${preferred}#${ordinal}`;\n claimed.add(key);\n warnInDev(\n `[wireai] a second event queue was created for the same appId, and \"${preferred}\" is already ` +\n \"claimed by a live one. Two queues sharing one storage slot overwrite each other's backlog, \" +\n \"delete each other's pending events when one drains to empty, and double-send on relaunch, so \" +\n `this queue was given \"${key}\" instead. Prefer ONE analytics instance per app; if you really ` +\n \"need two, pass an explicit `storageKey` to each so the slots are yours to reason about.\",\n );\n return key;\n};\n\n/** Test-only: forget every claimed queue key. A real RELAUNCH is a new process, so a test that\n * simulates one in-process must call this or its second queue reads as a concurrent sibling.\n * Exported from `@wireai/activation/analytics`, matching `resetAutoDeviceKeys` / `resetCurrentSessionId`. */\nexport const resetEventQueueKeys = (): void => claimedQueueKeys().clear();\n\n/** Internal buffered item. `id` is a local monotonic handle for deterministic dequeue-after-ack;\n * it is NEVER sent to the server. `sig` is the de-dup signature (serialized stamped event). */\ntype QueuedItem = { id: number; event: ClientEvent; sig: string };\n\n/** Persisted shape — the local id + the (already envelope-stamped) event. `sig` is recomputed on load. */\ntype PersistedItem = { id: number; event: ClientEvent };\n\nconst withTimeout = <T>(p: Promise<T>, ms: number): Promise<T | undefined> => {\n let timer: ReturnType<typeof setTimeout>;\n const timeout = new Promise<undefined>((resolve) => {\n timer = setTimeout(() => resolve(undefined), ms);\n });\n return Promise.race([p, timeout]).finally(() => clearTimeout(timer));\n};\n\n/** Detach a timer from the event loop where the runtime supports it (Node test process / some RNs). */\nconst unrefTimer = (timer: ReturnType<typeof setTimeout>): void => {\n const t = timer as unknown as { unref?: () => void };\n if (typeof t.unref === \"function\") t.unref();\n};\n\nconst parsePersisted = (raw: string | null | undefined): PersistedItem[] => {\n if (!raw) return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const items: PersistedItem[] = [];\n for (const entry of parsed) {\n if (\n entry &&\n typeof entry === \"object\" &&\n typeof (entry as PersistedItem).id === \"number\" &&\n (entry as PersistedItem).event &&\n typeof (entry as PersistedItem).event === \"object\"\n ) {\n items.push(entry as PersistedItem);\n }\n }\n return items;\n } catch {\n // Corrupt backlog → start empty; the next persist overwrites it.\n return [];\n }\n};\n\n/**\n * Create an offline-first event queue. Loads any persisted backlog on creation so a\n * killed-and-relaunched app resumes where it left off. Returns the {@link EventQueue} surface.\n */\nexport const createEventQueue = (options: EventQueueOptions): EventQueue => {\n const target = options.target;\n const storage = options.storage;\n // One slot per QUEUE (K4): an explicit key is taken verbatim; the appId-derived default is rotated\n // to `…#2` when a live queue already holds it, so two instances can never share one backlog.\n //\n // Only claimed when there IS storage. The defect is entirely about the persisted slot, and a\n // storage-less queue (the documented degraded in-memory mode) never reads or writes the key — so\n // claiming there would warn about a collision that cannot happen.\n const defaultKey = options.storageKey ?? `wireai:evtq:${options.appId ?? \"default\"}`;\n const key = storage ? claimQueueKey(defaultKey, options.storageKey !== undefined) : defaultKey;\n const maxSize = options.maxSize ?? DEFAULTS.maxSize;\n const batchSize = options.batchSize ?? DEFAULTS.batchSize;\n const baseBackoffMs = options.baseBackoffMs ?? DEFAULTS.baseBackoffMs;\n const maxBackoffMs = options.maxBackoffMs ?? DEFAULTS.maxBackoffMs;\n const maxRetries = options.maxRetries ?? DEFAULTS.maxRetries;\n\n let pending: QueuedItem[] = [];\n let nextId = 0;\n let flushing = false;\n let attempt = 0;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n\n const resolveEnvelope = (): ContextEnvelope | undefined => {\n try {\n return typeof options.envelope === \"function\" ? options.envelope() : options.envelope;\n } catch {\n return undefined;\n }\n };\n\n // Stamp the current envelope onto a COPY of the event (never mutate the caller's object):\n // device → event.device (when the event has none)\n // sessionId → event.session_id (when the event has none)\n // appVersion / appBuild / networkType → event.user_context (the non-PII bucket the server\n // sanitizes), never overwriting a key the caller already set.\n const stamp = (event: ClientEvent): ClientEvent => {\n const env = resolveEnvelope();\n const stamped: ClientEvent = { ...event };\n // Client enqueue timestamp: distinguishes a GENUINE repeat (same event fired seconds apart)\n // from a REDUNDANT re-enqueue of the same instant. The de-dup signature below includes it, so\n // two identical events enqueued in the same millisecond still collapse (a re-render), while the\n // same action repeated later carries a fresh `ts` and survives. A caller-set `ts` is preserved.\n if (stamped.ts === undefined) stamped.ts = Date.now();\n if (!env) return stamped;\n if (!stamped.device && env.device) stamped.device = env.device;\n if (!stamped.session_id && env.sessionId) stamped.session_id = env.sessionId;\n const uc: Record<string, string | number | boolean> = { ...(stamped.user_context ?? {}) };\n if (env.appVersion && uc.app_version === undefined) uc.app_version = env.appVersion;\n if (env.appBuild && uc.app_build === undefined) uc.app_build = env.appBuild;\n if (env.networkType && uc.network_type === undefined) uc.network_type = env.networkType;\n if (Object.keys(uc).length > 0) stamped.user_context = uc;\n return stamped;\n };\n\n const persist = (): void => {\n if (!storage) return;\n try {\n if (pending.length === 0) {\n void storage.removeItem(key).catch(() => {});\n return;\n }\n const payload: PersistedItem[] = pending.map((item) => ({ id: item.id, event: item.event }));\n void storage.setItem(key, JSON.stringify(payload)).catch(() => {});\n } catch {\n // Best-effort: a failed write just means the backlog is not durable this launch.\n }\n };\n\n const enforceSizeCap = (): void => {\n // Drop the OLDEST first so the newest events are never the ones lost under pressure.\n if (pending.length > maxSize) pending.splice(0, pending.length - maxSize);\n };\n\n const safeSig = (event: ClientEvent): string => {\n try {\n return JSON.stringify(event);\n } catch {\n // Non-serializable event → give it a unique signature so it is never wrongly de-duped.\n return `__nosig_${nextId}_${Math.random()}`;\n }\n };\n\n // Load any persisted backlog. Anything enqueued before this settles stays in memory; we merge\n // persisted (older) ahead of it and reassign monotonic ids so dequeue-after-ack is deterministic.\n const loadPromise: Promise<void> = (async () => {\n if (!storage) return;\n try {\n const persistedItems = parsePersisted(await withTimeout(storage.getItem(key), READ_TIMEOUT_MS));\n if (persistedItems.length === 0) return;\n const events = [...persistedItems.map((p) => p.event), ...pending.map((p) => p.event)];\n pending = [];\n nextId = 0;\n const seen = new Set<string>();\n for (const event of events) {\n const sig = safeSig(event);\n if (seen.has(sig)) continue; // collapse duplicates carried across the merge\n seen.add(sig);\n pending.push({ id: nextId++, event, sig });\n }\n enforceSizeCap();\n persist();\n } catch {\n // Unreadable backlog → start empty; nothing enqueued in-memory is lost.\n }\n })();\n\n // The queue's OWN awaited POST. Reads `res.ok` to drive retry/dequeue. NEVER throws — a missing\n // fetch, a rejecting network, or a JSON error resolves to `false` (batch stays, retry schedules).\n const postBatch = async (events: ClientEvent[]): Promise<boolean> => {\n // Build the /v1/events request through the ONE canonical builder (url + headers + body) so this\n // queue never re-describes the endpoint. The abort-timeout stays: the queue owns retry/dequeue,\n // so a hung request must be cut loose to schedule a backoff rather than block the drain forever.\n const req = buildEventsRequest(target, events);\n if (!req) return false;\n const controller = typeof AbortController !== \"undefined\" ? new AbortController() : undefined;\n const timer = setTimeout(() => controller?.abort(), 15_000);\n try {\n const res = await fetch(req.url, { ...req.init, signal: controller?.signal });\n // A 200 can still carry `skipped:N` — events the server threw away. Log-only: the ack below\n // stays `res.ok`, so retry/dequeue behaviour is unchanged.\n warnOnSkippedEvents(res);\n return !!(res && (res as { ok?: boolean }).ok);\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n }\n };\n\n const clearRetry = (): void => {\n if (retryTimer !== undefined) {\n clearTimeout(retryTimer);\n retryTimer = undefined;\n }\n };\n\n const scheduleRetry = (): void => {\n // Bounded automatic retry. Past the cap the backlog simply waits for the next\n // `notifyOnline()` / `flush()` (both re-arm attempt), so events are paused, never dropped.\n if (attempt >= maxRetries) return;\n const delay = Math.min(baseBackoffMs * 2 ** attempt, maxBackoffMs);\n attempt++;\n clearRetry();\n retryTimer = setTimeout(() => {\n retryTimer = undefined;\n void drain();\n }, delay);\n unrefTimer(retryTimer);\n };\n\n const drain = async (): Promise<void> => {\n try {\n await loadPromise;\n } catch {\n // load already swallows; guard the await defensively.\n }\n if (flushing) return;\n flushing = true;\n try {\n while (pending.length > 0) {\n const batch = pending.slice(0, batchSize);\n const ok = await postBatch(batch.map((item) => item.event));\n if (!ok) {\n scheduleRetry();\n return;\n }\n // Dequeue exactly the acked batch by id (pending may have grown while in flight).\n const acked = new Set(batch.map((item) => item.id));\n pending = pending.filter((item) => !acked.has(item.id));\n persist();\n attempt = 0;\n clearRetry();\n }\n } finally {\n flushing = false;\n }\n };\n\n const flush = (): void => {\n try {\n void drain();\n } catch {\n // drain never throws synchronously, but guard the kick anyway.\n }\n };\n\n const enqueue = (event: ClientEvent): void => {\n try {\n const stamped = stamp(event);\n const sig = safeSig(stamped);\n // Collapse a redundant re-enqueue of an identical pending event.\n for (const item of pending) {\n if (item.sig === sig) return;\n }\n pending.push({ id: nextId++, event: stamped, sig });\n enforceSizeCap();\n persist();\n // Only kick a drain when no retry is already pending — avoids hammering fetch while offline.\n if (retryTimer === undefined) flush();\n } catch {\n // Fire-and-forget: nothing in enqueue may surface to the UI.\n }\n };\n\n const notifyOnline = (): void => {\n // Host reconnected: reset the backoff and drain now.\n attempt = 0;\n clearRetry();\n flush();\n };\n\n const size = (): number => pending.length;\n\n return { enqueue, flush, notifyOnline, size };\n};\n","/**\n * useLifecycleEvents — the batteries-included React hook that wires the TOP-OF-FUNNEL lifecycle\n * events in ONE place: `app.first_open` (once ever) on mount, and `app.session_started` on every\n * real app-open, both offline-buffered through the Brief-01 event queue.\n *\n * ONE emitter, one guard, no double-emit: session-start goes through the EXISTING\n * {@link reportSessionStart} emitter (routed via a `sink`), NOT a second session emitter — so a\n * host must use EITHER this hook OR `useSessionStart`, never both (both would fire an app-open).\n * The once-per-open guard dedupes re-renders within this hook.\n *\n * Firing moments mirror {@link useSessionStart} exactly:\n * • ON MOUNT — the app opened (cold start / provider first render). `app.first_open` fires here\n * too (once ever, gated by the persisted flag in `reportFirstOpen`). When the kit's AUTO device\n * key is the one in play (no host `deviceKey`, `config.storage` present) the mount fire waits on\n * one storage read so both events carry the PERSISTED key, not a freshly minted one — see the\n * `hydrateAutoDeviceKey` note below.\n * • ON FOREGROUND after a real background of at least {@link BACKGROUND_SESSION_MS} (30 min) — a\n * new app-open, so a fresh `app.session_started` fires. A quick app-switch does NOT count.\n *\n * OFFLINE-FIRST by default: pass your shared {@link EventQueue}'s `enqueue` as `options.sink` to\n * route both events through your one queue. If you pass no sink, the hook lazily creates its OWN\n * offline queue (dedicated storage key, so it never collides with your main queue) from the config\n * + storage. Either way lifecycle events are buffered + persisted + retried, never lost offline.\n *\n * Dependency policy: `AppState` + `Platform` are RN built-ins (no new dep); the device snapshot is\n * the kit's own dependency-free `collectDeviceContext()`; the queue is the dependency-free Brief-01\n * `createEventQueue`. The pure `reportFirstOpen` / `wireLifecycleEvents` (in lifecycle.ts) import no\n * React — this hook is the only React surface.\n */\nimport { useEffect, useRef } from \"react\";\nimport { AppState, Platform, type AppStateStatus } from \"react-native\";\n\nimport { createEventQueue, type EnvelopeSource, type EventQueue } from \"../analytics/eventQueue\";\nimport { makeSessionId, type ClientEvent, type ClientEventTarget } from \"../analytics/reportClientEvent\";\nimport { hydrateAutoDeviceKey, resolveAutoDeviceKey } from \"../context/deviceId\";\nimport { resolveIdentity } from \"../identity/identityRecord\";\nimport { collectDeviceContext } from \"../device/deviceContext\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\nimport { reportFirstOpen } from \"./lifecycle\";\nimport { reportSessionStart } from \"./reportSessionStart\";\nimport { BACKGROUND_SESSION_MS } from \"./useSessionStart\";\n\n/** Tenant transport + host persistence for the lifecycle wiring. Same creds as `WireOnboardingConfig`. */\nexport interface LifecycleConfig {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/v1/events` is appended. */\n serverUrl?: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey?: string;\n /** Host app version (e.g. \"1.4.2\"), forwarded for release segmentation. Optional. */\n appVersion?: string;\n /** Tenant/app id — namespaces the first-open flag AND the hook's internal queue storage key. */\n appId?: string;\n /** Host storage (AsyncStorage subset). Enables the persisted once-ever first-open flag AND the\n * offline durability of the hook's internal queue. Omit it and both degrade to in-memory. */\n storage?: WireOnboardingStorage;\n}\n\n/** Per-open identity + wiring the host supplies. All optional: a pre-auth open is device-only. */\nexport interface UseLifecycleEventsOptions {\n /** The host's opaque pseudonymous user id (NOT PII). Omitted before the user authenticates. */\n userId?: string;\n /** The host's local open-counter value for this open. Drives `returning` + \"Nth session\". */\n sessionCount?: number;\n /** A stable, non-PII device id the host owns. Groups this device's sessions server-side. */\n deviceKey?: string;\n /** Small non-PII extras forwarded on the event `meta`. */\n meta?: Record<string, unknown>;\n /** Set `false` to disable firing (e.g. behind a consent gate). Default enabled. */\n enabled?: boolean;\n /**\n * Explicit transport sink (e.g. an existing shared `EventQueue.enqueue`). When provided, BOTH\n * lifecycle events route here and the hook does NOT create its own queue — pass this to share ONE\n * offline queue across the kit's analytics (screen tracking + lifecycle).\n */\n sink?: (event: ClientEvent) => void;\n /**\n * Context envelope (or provider) for the hook's internally-created queue. Ignored when `sink` is\n * supplied (the host's queue owns envelope stamping).\n */\n envelope?: EnvelopeSource;\n}\n\n/**\n * Fire `app.first_open` (once ever) + `app.session_started` (per open), offline-buffered. Returns\n * nothing — a side-effecting hook. Safe to call with inline options (read through a ref, so\n * changing `userId`/`sessionCount` never re-fires a session).\n */\nexport const useLifecycleEvents = (\n config: LifecycleConfig | undefined,\n options: UseLifecycleEventsOptions = {},\n): void => {\n // Latest options/config through a ref so the mount/resume fires read fresh values without listing\n // them as effect deps (which would re-fire a session on every prop change).\n const latest = useRef({ config, options });\n latest.current = { config, options };\n\n // The resolved sink is created at most once and reused for every fire this mount.\n const queueRef = useRef<EventQueue | undefined>(undefined);\n\n useEffect(() => {\n const resolveSink = (): ((event: ClientEvent) => void) | undefined => {\n const { config: cfg, options: opts } = latest.current;\n // Host-owned shared queue wins — one queue across the whole kit.\n if (opts.sink) return opts.sink;\n // No transport → no sink (events no-op rather than buffer forever against a dead target).\n if (!cfg?.serverUrl) return undefined;\n if (!queueRef.current) {\n queueRef.current = createEventQueue({\n target: { serverUrl: cfg.serverUrl, apiKey: cfg.apiKey ?? \"\" },\n storage: cfg.storage,\n // Dedicated key so the hook's internal queue never collides with a host's main queue.\n storageKey: `wireai:evtq:lifecycle:${cfg.appId ?? \"default\"}`,\n envelope: opts.envelope,\n });\n }\n return queueRef.current.enqueue;\n };\n\n const targetOf = (cfg: LifecycleConfig | undefined): ClientEventTarget | undefined =>\n cfg?.serverUrl ? { serverUrl: cfg.serverUrl, apiKey: cfg.apiKey ?? \"\" } : undefined;\n\n /**\n * The `device_key` these lifecycle events ride under. A host-supplied id always wins.\n *\n * WHY THE FALLBACK EXISTS: `min_sessions` (the review / questionnaire firing rule, and the\n * \"fire on the user's Nth session\" recipe in the README) is computed SERVER-SIDE by counting\n * distinct `app.session_started` events grouped by `user_context.device_key`. A host that took\n * the batteries-included path and passed no `deviceKey` emitted those events with NO device key\n * at all — while its `createAnalytics` / `createWireActivation` events carried an auto-minted\n * one. Two disjoint identity spaces again: the counter the rule reads could never increase, so\n * `min_sessions` was structurally unsatisfiable and the gate never fired from the server side.\n *\n * ONLY WITH `storage`: the auto id is per-INSTALL only when it can be persisted. With no\n * storage it would be per-LAUNCH, which would make every open look like a brand-new device and\n * corrupt `min_sessions` in the other direction. So no storage → no fallback, same as before.\n */\n const resolveDeviceKey = (\n cfg: LifecycleConfig | undefined,\n opts: UseLifecycleEventsOptions,\n ): string | undefined => {\n // A HOST-supplied key is recorded on the process provenance registry, so a `<WireOnboarding>`\n // mount that was not given one can tell \"this app owns no device id\" from \"this app owns one\n // and forgot it there\" — the silent third id space (K9). Recording only; nothing reads it here.\n const host = resolveIdentity({\n value: opts.deviceKey,\n space: \"device\",\n source: \"host\",\n scope: cfg?.appId,\n })?.value;\n if (host) return host;\n if (!cfg?.storage) return undefined;\n return resolveAutoDeviceKey({ appId: cfg.appId, storage: cfg.storage });\n };\n\n // ONE per-open session id for the MOUNT open, shared by first_open AND session_started below.\n // WHY: `first_open` used to default to its OWN fresh `makeSessionId()` (via `buildLifecycleEvent`)\n // while `session_started` minted a different one — so every install's `first_open` carried a\n // session id the server never got a `session_started` for (a PHANTOM session the server\n // back-filled). Minting one id here and handing it to both makes them agree, so the server sees\n // `first_open` under the same session it saw `session_started` for. A later foreground open\n // (below) mints its OWN fresh id — a new open is a new session.\n const mountOpenSessionId = makeSessionId();\n\n // session_start — the EXISTING emitter routed through the sink (offline-buffered, one guard).\n // Accepts the per-open id so the mount open reuses `mountOpenSessionId`; omit it and the emitter\n // mints a fresh id (a genuinely new open). Either way the once-guard dedupes within the open.\n const fireSession = (sessionId?: string) => {\n const { config: cfg, options: opts } = latest.current;\n if (opts.enabled === false) return;\n if (!cfg?.serverUrl && !opts.sink) return;\n const device = collectDeviceContext();\n // `device.appVersion` is auto-detected best-effort; an explicit host version always wins.\n if (cfg?.appVersion) device.appVersion = cfg.appVersion;\n reportSessionStart({\n target: targetOf(cfg),\n sink: resolveSink(),\n sessionId,\n userId: opts.userId,\n deviceKey: resolveDeviceKey(cfg, opts),\n sessionCount: opts.sessionCount,\n appVersion: cfg?.appVersion ?? device.appVersion,\n platform: Platform.OS,\n device,\n meta: opts.meta,\n });\n };\n\n // The mount open: session_start FIRST (mount = an app-open), so the server has ingested\n // `session_started` for `mountOpenSessionId` before first_open references the same id; then\n // first_open — once ever (persisted flag + in-memory latch inside reportFirstOpen), pinned to the\n // SAME per-open id so it is never a phantom session.\n const fireMountOpen = () => {\n fireSession(mountOpenSessionId);\n\n const { config: cfg, options: opts } = latest.current;\n if (opts.enabled === false) return;\n const device = collectDeviceContext();\n // `device.appVersion` is auto-detected best-effort; an explicit host version always wins.\n if (cfg?.appVersion) device.appVersion = cfg.appVersion;\n reportFirstOpen({\n target: targetOf(cfg),\n sink: resolveSink(),\n sessionId: mountOpenSessionId,\n storage: cfg?.storage,\n appId: cfg?.appId,\n userId: opts.userId,\n deviceKey: resolveDeviceKey(cfg, opts),\n sessionCount: opts.sessionCount,\n appVersion: cfg?.appVersion ?? device.appVersion,\n platform: Platform.OS,\n device,\n meta: opts.meta,\n });\n };\n\n // WAIT FOR THE PERSISTED DEVICE KEY, but ONLY when the auto fallback is the one in play.\n //\n // `resolveAutoDeviceKey` is synchronous by contract: it returns a freshly minted id and adopts the\n // PERSISTED one a storage read later. Firing at mount therefore stamped a brand-new `wdev_*` on\n // BOTH lifecycle events on every launch, while every other surface adopted the persisted id\n // milliseconds afterwards. Those two events are exactly the ones the server counts `min_sessions`\n // from (distinct `app.session_started` grouped by `device_key`), so the counter could never exceed\n // 1 — and `first_open`, fired once ever, ended up under a key no later event shares, which breaks\n // `first_open` → `activated` cohorting too. One storage read at mount buys both back.\n //\n // A host-supplied `deviceKey` needs no read, and with no `storage` there is nothing to read (and\n // `resolveDeviceKey` deliberately does not fall back), so both keep firing synchronously at mount.\n let cancelled = false;\n const { config: mountCfg, options: mountOpts } = latest.current;\n const hostKey =\n typeof mountOpts.deviceKey === \"string\" && mountOpts.deviceKey.trim()\n ? mountOpts.deviceKey\n : undefined;\n if (!hostKey && mountCfg?.storage) {\n void hydrateAutoDeviceKey({ appId: mountCfg.appId, storage: mountCfg.storage }).then(() => {\n if (!cancelled) fireMountOpen();\n });\n } else {\n fireMountOpen();\n }\n\n // Foreground after a real background = a new app-open.\n let backgroundedAt: number | null = null;\n const onChange = (state: AppStateStatus) => {\n if (state === \"background\" || state === \"inactive\") {\n if (backgroundedAt == null) backgroundedAt = Date.now();\n return;\n }\n if (state === \"active\") {\n const since = backgroundedAt;\n backgroundedAt = null;\n if (since != null && Date.now() - since >= BACKGROUND_SESSION_MS) fireSession();\n }\n };\n const sub = AppState.addEventListener(\"change\", onChange);\n return () => {\n // A pending hydration must not fire an app-open for a mount that is already gone.\n cancelled = true;\n // RN >= 0.65 returns a subscription with remove(); guard for older shims.\n if (sub && typeof (sub as { remove?: () => void }).remove === \"function\") sub.remove();\n };\n // Mount-only effect: firing reads fresh values via `latest`, so no reactive deps.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/theme/defaultTheme.ts","../src/theme/ThemeContext.tsx","../src/components/Illustration.tsx","../src/illustrations/defaultIllustrations.tsx","../src/icons/IconRegistry.tsx","../src/theme/typography.ts","../src/motion/motionSpec.ts","../src/motion/useReducedMotion.ts","../src/components/AnimatedSparkle.tsx","../src/components/LoadingBlock.tsx","../src/components/LoadingScreen.tsx","../src/components/StepProgress.tsx","../src/components/OnboardingScaffold.tsx","../src/components/Button.tsx","../src/components/ErrorBlock.tsx","../src/components/CardLayout.tsx","../src/components/CompletionView.tsx","../src/components/CardHandoff.tsx","../src/utils/deriveAnswers.ts","../src/utils/readProgress.ts","../src/analytics/reportClientEvent.ts","../src/analytics/sendPreview.ts","../src/permissions/permissionEvents.ts","../src/haptics/haptics.ts","../src/utils/warnInDev.ts","../src/cards/PermissionCard.tsx","../src/permissions/placement.ts","../src/permissions/permissionCopy.ts","../src/OnboardingFlow.tsx","../src/cards/ChipSelectCard.tsx","../src/cards/TextInputCard.tsx","../src/icons/expoIcons.ts","../src/icons/vocabulary.ts","../src/icons/WireIcon.tsx","../src/cards/optionSchema.ts","../src/cards/SelectionCard.tsx","../src/cards/CardGridSelectCard.tsx","../src/cards/StatusCard.tsx","../src/cards/NumberStepperCard.tsx","../src/cards/InterstitialCard.tsx","../src/cards/index.ts","../src/device/appVersion.ts","../src/device/deviceModel.ts","../src/device/deviceContext.ts","../src/identity/identityRecord.ts","../src/context/deviceId.ts","../src/analytics/currentSession.ts","../src/session/persistedSession.ts","../src/identity/userIdentity.ts","../src/context/userContext.ts","../src/permissions/permissionMemory.ts","../src/WireOnboarding.tsx","../src/DemoOnboarding.tsx","../src/theme/themeFromBrand.ts","../src/motion/centeredModalMotion.ts","../src/components/CenteredModal.tsx","../src/features/defaults.ts","../src/features/cache.ts","../src/features/fetchWireFeatures.ts","../src/features/useWireFeatures.ts","../src/features/WireFeaturesProvider.tsx","../src/config/wireConfigFromEnv.ts","../src/config/onboardingFlag.ts","../src/analytics/analyticsEvent.ts","../src/attribution/attribution.ts","../src/activation/revalidation.ts","../src/activation/wireActivation.ts","../src/activation/useWireActivation.ts","../src/revenuecat/purchaseEvents.ts","../src/revenuecat/revenueCatBridge.ts","../src/session-analytics/reportSessionStart.ts","../src/session-analytics/useSessionStart.ts","../src/session-analytics/lifecycle.ts","../src/analytics/eventQueue.ts","../src/session-analytics/useLifecycleEvents.ts"],"names":["createContext","useMemo","jsx","useContext","EMPTY_REGISTRY","useEffect","styles","Text","React","StyleSheet","useRef","Animated","Easing","View","useState","jsxs","SafeAreaView","makeStyles","easeWire","useCallback","_a","_b","_c","_d","step","_e","_f","validators","Fragment","copy","schema","z","Pressable","RISE_PX","runtimeRequire","interop","safeInterop","Modal","READ_TIMEOUT_MS","withTimeout","cached","globalSlot","Platform","parsePersisted","AppState"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * defaultOnboardingTheme — a neutral, light, brand-agnostic baseline. Consumers\n * pass a `Partial<OnboardingTheme>` that is deep-merged over this (see\n * `mergeTheme`), so they only override what differs from neutral.\n */\nimport type { OnboardingTheme } from \"./types\";\n\nexport const defaultOnboardingTheme: OnboardingTheme = {\n colors: {\n background: \"#FFFFFF\",\n surface: \"#F7F7F8\",\n text: \"#101114\",\n textMuted: \"#6B7280\",\n primary: \"#111111\",\n onPrimary: \"#FFFFFF\",\n primarySoft: \"rgba(17,17,17,0.06)\",\n border: \"#E4E4E7\",\n borderStrong: \"#C7C7CC\",\n disabled: \"#EBEBEB\",\n success: \"#16A34A\",\n warning: \"#D97706\",\n error: \"#DC2626\",\n info: \"#2563EB\",\n },\n fonts: {\n regular: undefined,\n medium: undefined,\n bold: undefined,\n baseSize: 16,\n scale: 1,\n },\n radius: {\n sm: 8,\n md: 12,\n lg: 16,\n full: 9999,\n },\n spacing: {\n xs: 4,\n sm: 8,\n md: 16,\n lg: 24,\n xl: 32,\n },\n // Circled (pill) CTA by default; an app can pass `button: { radius: 12 }` for\n // a rounded rectangle, or override height/paddingX to match its design system.\n button: {\n radius: 9999,\n height: 52,\n paddingX: 24,\n },\n};\n\n/**\n * Deep-merge a partial theme over the default. Two levels deep is enough — the\n * theme is intentionally shallow (colors/fonts/radius/spacing), so we merge each\n * known sub-object and leave scalars to overwrite.\n */\nexport const mergeTheme = (\n override?: Partial<OnboardingTheme>,\n): OnboardingTheme => {\n if (!override) return defaultOnboardingTheme;\n return {\n colors: { ...defaultOnboardingTheme.colors, ...override.colors },\n fonts: { ...defaultOnboardingTheme.fonts, ...override.fonts },\n radius: { ...defaultOnboardingTheme.radius, ...override.radius },\n spacing: { ...defaultOnboardingTheme.spacing, ...override.spacing },\n button: { ...defaultOnboardingTheme.button, ...override.button },\n };\n};\n","/**\n * ThemeContext — provides the resolved OnboardingTheme to every shell element and\n * themed card via `useOnboardingTheme()`. WHY a context rather than prop-drilling:\n * the cards are mounted by the SDK's ComponentRenderer (not by us), so we can't\n * pass them props directly — they must read the theme from context.\n *\n * ── WHY THE CONTEXT LIVES ON A `Symbol.for` SLOT ───────────────────────────────────────────────\n *\n * It was a plain `createContext(...)`, and tsup inlines this module into FIVE dist bundles\n * (`.`, `./reviews`, `./questionnaire`, `./coachmarks`, `./showcase`) — so each one carried its own\n * context instance. `OnboardingThemeProvider` is exported ONLY from the root barrel, so on any\n * `dist` resolution path (plain RN CLI, `unstable_enablePackageExports: false`, node, jest, SSR) a\n * host that wrapped its tree in `<OnboardingThemeProvider>` and rendered `<ReviewGate>` from\n * `@wireai/activation/reviews` was writing one context and reading another. Nothing crashed and\n * nothing warned: `useOnboardingTheme`'s `ctx ?? mergeTheme()` fallback quietly served the NEUTRAL\n * default theme, so the tenant's brand simply did not apply to the gate. On-device this was masked\n * only because Metro's `react-native` export condition collapses every subpath back to this one\n * `src/` file — the same \"bundler accident, not a guarantee\" the `currentSession` header names, and\n * the same root cause as the optional-peers bug 0.13.3 fixed.\n *\n * The bundler-agnostic fix, exactly as `coachmarks/runtime`, `analytics/currentSession`,\n * `context/deviceId` and `features/WireFeaturesProvider` already do it: park the ONE context on a\n * well-known `globalThis` slot keyed by `Symbol.for(...)`. `Symbol.for` uses the runtime-global\n * symbol registry, so every inlined copy of this module resolves the SAME symbol, finds the slot\n * already filled, and reuses that instance — one context identity however many copies exist.\n * `globalThis` is present and identical in Hermes/React Native, Node and SSR (we never touch\n * `window`), so this is safe on every host. `test/canary/themeContextIdentity.test.tsx` measures it\n * in the BUILT artifact, because the defect is invisible in source.\n */\nimport React, { createContext, useContext, useMemo } from \"react\";\nimport { mergeTheme } from \"./defaultTheme\";\nimport type { OnboardingTheme } from \"./types\";\n\n/**\n * Well-known key into the runtime-global symbol registry. `Symbol.for` (NOT a plain `Symbol()`) is\n * what makes this cross-bundle: it returns the SAME symbol for the same string across every copy of\n * this module, so duplicated inlined copies all address one slot.\n */\nconst THEME_CONTEXT_SLOT: unique symbol = Symbol.for(\"@wireai/activation:themeContext\");\n\ntype GlobalWithThemeContext = typeof globalThis & {\n [THEME_CONTEXT_SLOT]?: React.Context<OnboardingTheme | null>;\n};\n\nconst themeGlobal = globalThis as GlobalWithThemeContext;\n\n// First copy to load creates the context; every later copy adopts it. Never overwrite an existing\n// slot — a second `createContext` here would re-split the identity this guard exists to keep whole.\nif (!themeGlobal[THEME_CONTEXT_SLOT]) {\n themeGlobal[THEME_CONTEXT_SLOT] = createContext<OnboardingTheme | null>(null);\n}\nconst OnboardingThemeContext = themeGlobal[THEME_CONTEXT_SLOT] as React.Context<OnboardingTheme | null>;\n\nexport type OnboardingThemeProviderProps = {\n /** Partial overrides merged over the neutral default theme. */\n theme?: Partial<OnboardingTheme>;\n children: React.ReactNode;\n};\n\nexport const OnboardingThemeProvider: React.FC<OnboardingThemeProviderProps> = ({\n theme,\n children,\n}) => {\n const resolved = useMemo(() => mergeTheme(theme), [theme]);\n return (\n <OnboardingThemeContext.Provider value={resolved}>\n {children}\n </OnboardingThemeContext.Provider>\n );\n};\n\n/**\n * Read the active theme. Falls back to the default theme when used outside a\n * provider so a stray card never crashes — it just renders neutral.\n */\nexport const useOnboardingTheme = (): OnboardingTheme => {\n const ctx = useContext(OnboardingThemeContext);\n return ctx ?? mergeTheme();\n};\n","/**\n * Illustration registry — lets the host app supply brand artwork (SVG / Lottie /\n * Image nodes) keyed by name, which the backend references from an InterstitialCard\n * by `illustration`. Keeping the registry in React context (rather than as a card\n * prop) is what keeps the kit dependency-free: the kit never imports react-native-svg\n * or Lottie — the app brings its own nodes and the kit just slots the matching one.\n *\n * <WireOnboarding illustrations={{ \"before-after\": <BeforeAfter/> }} ... />\n *\n * When the backend names an illustration the registry doesn't have, the\n * InterstitialCard falls back to its `imageUrl` (a plain RN <Image>).\n */\nimport React, { createContext, useContext, useMemo } from \"react\";\n\nexport type IllustrationRegistry = Record<string, React.ReactNode>;\n\n/** One shared empty registry so an unconfigured provider never allocates a fresh {} per render. */\nconst EMPTY_REGISTRY: IllustrationRegistry = {};\n\nconst IllustrationContext = createContext<IllustrationRegistry>(EMPTY_REGISTRY);\n\nexport type IllustrationProviderProps = {\n registry?: IllustrationRegistry;\n children: React.ReactNode;\n};\n\nexport const IllustrationProvider: React.FC<IllustrationProviderProps> = ({\n registry,\n children,\n}) => {\n const value = useMemo(() => registry ?? EMPTY_REGISTRY, [registry]);\n return <IllustrationContext.Provider value={value}>{children}</IllustrationContext.Provider>;\n};\n\n/** Look up an app-supplied illustration node by name. Returns undefined if absent. */\nexport const useIllustration = (name?: string): React.ReactNode | undefined => {\n const registry = useContext(IllustrationContext);\n if (!name) return undefined;\n return registry[name];\n};\n","/**\n * defaultIllustrations — a tiny, dependency-free fallback registry so an app can\n * render `InterstitialCard` with ZERO illustration code. These are plain\n * <View>/<Text> glyphs (NO react-native-svg, NO Lottie, NO image assets) themed\n * from the active OnboardingTheme, covering the common backend-emitted names.\n *\n * Spread it under your own artwork — your named nodes win:\n *\n * illustrations={{ ...defaultIllustrations, ...myIllustrations }}\n *\n * Names match what the onboarding backend commonly emits via an InterstitialCard's\n * `illustration`: `momentum` (forward-motion arc) and `before-after` (two states).\n * Add more by spreading your own — these are only sensible defaults.\n */\nimport React from \"react\";\nimport { StyleSheet, Text, View } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\n\n/** The soft tinted disc every default sits in, whether its content is a glyph or a shape. */\nconst Disc: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const t = useOnboardingTheme();\n return (\n <View\n style={[\n styles.disc,\n { backgroundColor: t.colors.primarySoft, borderRadius: t.radius.full },\n ]}\n >\n {children}\n </View>\n );\n};\n\n/** A soft tinted disc with a centered glyph: the shared frame for every text-glyph default. */\nconst Glyph: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const t = useOnboardingTheme();\n return (\n <Disc>\n <Text style={[styles.glyphText, { color: t.colors.primary }]} allowFontScaling={false}>\n {children}\n </Text>\n </Disc>\n );\n};\n\n/** Forward-motion / momentum: an upward arrow. */\nconst MomentumGlyph: React.FC = () => <Glyph>{\"↗\"}</Glyph>;\n\n/**\n * Notification priming: a bell, DRAWN FROM VIEWS rather than written as an emoji.\n *\n * A color emoji carries its own palette and ignores the `color` its container sets, so a \"🔔\" here\n * would be the one default illustration that refuses to repaint with the host's theme, sitting\n * next to siblings that do. Three plain Views (a domed body, a rim, a clapper) take\n * `t.colors.primary` directly, and they depend on no glyph being present in the platform font and\n * on no guess about whether it renders as text or as emoji.\n *\n * Keyed by the PERMISSION name, which is what PermissionCard looks up by default, so a\n * notification screen is never a blank box with no host wiring.\n */\nconst NotificationsGlyph: React.FC = () => {\n const t = useOnboardingTheme();\n return (\n <Disc>\n <View style={styles.bell}>\n <View style={[styles.bellBody, { backgroundColor: t.colors.primary }]} />\n <View style={[styles.bellRim, { backgroundColor: t.colors.primary }]} />\n <View style={[styles.bellClapper, { backgroundColor: t.colors.primary }]} />\n </View>\n </Disc>\n );\n};\n\n/** Before → after: two states with an arrow between. */\nconst BeforeAfterGlyph: React.FC = () => {\n const t = useOnboardingTheme();\n return (\n <View style={styles.row}>\n <View\n style={[\n styles.chip,\n { borderColor: t.colors.border, borderRadius: t.radius.md },\n ]}\n />\n <Text style={[styles.arrow, { color: t.colors.primary }]} allowFontScaling={false}>\n {\"→\"}\n </Text>\n <View\n style={[\n styles.chip,\n { backgroundColor: t.colors.primarySoft, borderColor: t.colors.primary, borderRadius: t.radius.md },\n ]}\n />\n </View>\n );\n};\n\n/**\n * The default registry. `WireOnboarding`'s `illustrations` prop is\n * `Record<string, ReactNode>`, so these are concrete element nodes.\n */\nexport const defaultIllustrations: Record<string, React.ReactNode> = {\n momentum: <MomentumGlyph />,\n \"before-after\": <BeforeAfterGlyph />,\n notifications: <NotificationsGlyph />,\n};\n\nconst styles = StyleSheet.create({\n disc: {\n width: 96,\n height: 96,\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n glyphText: {\n fontSize: 44,\n fontWeight: \"700\",\n lineHeight: 52,\n },\n row: {\n flexDirection: \"row\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 12,\n },\n chip: {\n width: 56,\n height: 56,\n borderWidth: 2,\n },\n arrow: {\n fontSize: 28,\n fontWeight: \"700\",\n },\n // The bell: a domed body over a wider rim, with the clapper hanging below it.\n bell: { alignItems: \"center\", justifyContent: \"center\" },\n bellBody: { width: 34, height: 30, borderTopLeftRadius: 17, borderTopRightRadius: 17 },\n bellRim: { width: 44, height: 5, borderRadius: 3, marginTop: 2 },\n bellClapper: { width: 9, height: 9, borderRadius: 5, marginTop: 3 },\n});\n","/**\n * Icon registry — the host's escape hatch, and the FIRST step of icon resolution.\n *\n * Deliberately the same shape and philosophy as the `illustrations` registry\n * (components/Illustration.tsx): name → ReactNode, held in context, so an app can ship brand\n * SVG / Lottie / Image nodes the kit never imports. Here it means a host can:\n *\n * • override any vocabulary name with its own brand mark (`{ instagram: <MyIgGlyph/> }`), or\n * • supply icons WITHOUT installing `@expo/vector-icons` at all, or\n * • extend the vocabulary with names of its own — the AI emits `\"my-thing\"`, the host renders\n * it, and the kit needs no release.\n *\n * <WireOnboarding icons={{ instagram: <BrandIg/> }} ... />\n *\n * A name the registry doesn't have falls through to `@expo/vector-icons`, then to no icon at\n * all. See `WireIcon`.\n */\nimport React, { createContext, useContext, useMemo } from \"react\";\n\nexport type WireIconRegistry = Record<string, React.ReactNode>;\n\n/** One shared empty registry so an unconfigured provider never allocates a fresh {} per render. */\nconst EMPTY_REGISTRY: WireIconRegistry = {};\n\nconst IconContext = createContext<WireIconRegistry>(EMPTY_REGISTRY);\n\nexport type IconRegistryProviderProps = {\n registry?: WireIconRegistry;\n children: React.ReactNode;\n};\n\nexport const IconRegistryProvider: React.FC<IconRegistryProviderProps> = ({\n registry,\n children,\n}) => {\n const value = useMemo(() => registry ?? EMPTY_REGISTRY, [registry]);\n return <IconContext.Provider value={value}>{children}</IconContext.Provider>;\n};\n\n/**\n * Look up a host-supplied icon node by name. Returns undefined if absent.\n *\n * The OWN-property check matters here for the same reason it does in `vocabulary.ts`: the name\n * is LLM-authored, and a bare `registry[name]` answers `\"toString\"` with an inherited function\n * — which is truthy, so it would be handed to React as a child and blow up the card. An icon\n * name must never be able to do that.\n */\nexport const useHostIcon = (name?: string): React.ReactNode | undefined => {\n const registry = useContext(IconContext);\n if (!name) return undefined;\n if (!Object.prototype.hasOwnProperty.call(registry, name)) return undefined;\n return registry[name];\n};\n","/**\n * typography — derive concrete RN text styles from the theme's font config, so\n * every label/title/caption in the kit scales from one `baseSize` + `scale` and\n * picks the right family. Cards call these instead of hardcoding fontSize/weight.\n */\nimport type { TextStyle } from \"react-native\";\nimport type { OnboardingFonts } from \"./types\";\n\nconst round = (n: number) => Math.round(n);\n\n/** Body text — the reference size. */\nexport const bodyStyle = (f: OnboardingFonts): TextStyle => ({\n fontFamily: f.regular,\n fontSize: round(f.baseSize * f.scale),\n lineHeight: round(f.baseSize * f.scale * 1.5),\n});\n\n/** Slightly smaller secondary/hint text. */\nexport const captionStyle = (f: OnboardingFonts): TextStyle => ({\n fontFamily: f.regular,\n fontSize: round(f.baseSize * 0.8125 * f.scale),\n lineHeight: round(f.baseSize * 0.8125 * f.scale * 1.5),\n});\n\n/** Emphasised label (e.g. a card question). */\nexport const labelStyle = (f: OnboardingFonts): TextStyle => ({\n fontFamily: f.medium ?? f.bold,\n fontSize: round(f.baseSize * f.scale),\n lineHeight: round(f.baseSize * f.scale * 1.4),\n fontWeight: f.medium ? undefined : (\"600\" as const),\n});\n\n/** Heading (status title, done block). */\nexport const headingStyle = (f: OnboardingFonts): TextStyle => ({\n fontFamily: f.bold,\n fontSize: round(f.baseSize * 1.25 * f.scale),\n lineHeight: round(f.baseSize * 1.25 * f.scale * 1.3),\n fontWeight: f.bold ? undefined : (\"700\" as const),\n});\n\n/** Button label. */\nexport const buttonLabelStyle = (f: OnboardingFonts): TextStyle => ({\n fontFamily: f.bold ?? f.medium,\n fontSize: round(f.baseSize * f.scale),\n fontWeight: f.bold ? undefined : (\"600\" as const),\n});\n","/**\n * motionSpec — the single source of truth for every animation value in the kit,\n * extracted 1:1 from the Wire Activation card-interactions design canvas\n * (see design-refs/EXTRACTED-SPEC.md for the row-by-row mapping).\n *\n * Pure constants + pure helpers only — NO react-native import — so the spec is\n * unit-testable under node:test and components can't drift from the design\n * without a red test.\n */\n\n/** The design system's \"ease-wire\" curve: cubic-bezier(0.16, 1, 0.3, 1). */\nexport const WIRE_BEZIER = [0.16, 1, 0.3, 1] as const;\n\n/** Design-system duration tokens (colors_and_type.css --duration-*). */\nexport const DURATION_FAST_MS = 150;\nexport const DURATION_BASE_MS = 300;\nexport const DURATION_SLOW_MS = 500;\n\n/** Reduce-motion fallback: a short fade to the final frame, never a frozen mid-state. */\nexport const REDUCED_FADE_MS = 120;\n\n// ── Press feedback (spec rows 1, 4, 20) ─────────────────────────────────────\nexport const ROW_PRESS_SCALE = 0.975;\nexport const CHIP_PRESS_SCALE = 0.94;\nexport const BUTTON_PRESS_SCALE = 0.975;\n/** Reduce-motion press feedback: opacity dip instead of scale. */\nexport const REDUCED_PRESS_OPACITY = 0.85;\nexport const PRESS_SPRING = { friction: 8, tension: 220 } as const;\nexport const BUTTON_PRESS_SPRING = { friction: 8, tension: 240 } as const;\n\n// ── Selection state changes (spec rows 2, 3, 5, 6) ──────────────────────────\nexport const SELECT_FILL_MS = 180;\nexport const CHIP_FILL_MS = 160;\nexport const CHECK_SPRING = { friction: 6, tension: 180 } as const;\nexport const CHECK_SCALE_FROM = 0.6;\n\n// ── Card-to-card handoff (spec rows 7-10) ───────────────────────────────────\nexport const CARD_ENTER_MS = 220;\nexport const CARD_EXIT_MS = 180;\n/** The exit starts this long BEFORE the enter (enter is delayed by this). */\nexport const CARD_EXIT_LEAD_MS = 80;\nexport const CARD_SLIDE_PX = 26;\nexport const CARD_ENTER_SCALE_FROM = 0.96;\n/** The interstitial keeps the shell's springier value-beat (AnimatedCard idiom). */\nexport const CARD_SPRING = { damping: 14, stiffness: 180, mass: 1 } as const;\n/** Loader-to-card handoff: the loader just fades out. */\nexport const LOADER_HANDOFF_FADE_MS = 120;\n\n// ── InterstitialCard reveal (spec rows 11-13) ───────────────────────────────\nexport const INTERSTITIAL_HEAD_MS = 500;\nexport const INTERSTITIAL_HEAD_STAGGER_MS = 100;\nexport const INTERSTITIAL_ITEM_MS = 300;\nexport const INTERSTITIAL_ITEM_STAGGER_MS = 90;\nexport const INTERSTITIAL_ITEM_BASE_DELAY_MS = 200;\nexport const INTERSTITIAL_CHECK_DELAY_MS = 200;\nexport const INTERSTITIAL_CHECK_SCALE_FROM = 0.4;\n\n/** Delay before work item `index` begins its reveal (row lands after the head). */\nexport const interstitialItemDelay = (index: number): number =>\n INTERSTITIAL_ITEM_BASE_DELAY_MS + index * INTERSTITIAL_ITEM_STAGGER_MS;\n\n/** Delay before work item `index`'s check pops (200ms after its row starts). */\nexport const interstitialCheckDelay = (index: number): number =>\n interstitialItemDelay(index) + INTERSTITIAL_CHECK_DELAY_MS;\n\n// ── Status / completion payoff (spec rows 14-16) ────────────────────────────\nexport const STATUS_POP_SPRING = { friction: 6, tension: 200 } as const;\nexport const STATUS_POP_SCALE_FROM = 0.4;\nexport const STATUS_BURST_MS = 500;\nexport const STATUS_BURST_SCALE_FROM = 0.4;\nexport const STATUS_BURST_SCALE_TO = 1.5;\nexport const STATUS_BURST_OPACITY_FROM = 0.5;\nexport const STATUS_COPY_MS = 300;\nexport const STATUS_COPY_STAGGER_MS = 80;\n/** Copy starts settling once the badge pop is visibly underway. */\nexport const STATUS_COPY_BASE_DELAY_MS = 200;\n\n/** Delay before payoff copy line `index` fades up. */\nexport const statusCopyDelay = (index: number): number =>\n STATUS_COPY_BASE_DELAY_MS + index * STATUS_COPY_STAGGER_MS;\n\n// ── Loading treatment (spec rows 17-19) ─────────────────────────────────────\nexport const LOADER_PULSE_MS = 1600;\nexport const LOADER_PULSE_MIN_OPACITY = 0.35;\nexport const LOADER_ORBIT_MS = 2400;\n/** Skeleton lines appear only when the fetch runs past this. */\nexport const SKELETON_DELAY_MS = 300;\nexport const SKELETON_PULSE_MS = 1500;\nexport const SKELETON_MIN_OPACITY = 0.45;\n\n// ── Progress bar (spec row 21) ──────────────────────────────────────────────\nexport const PROGRESS_MS = 400;\n\n// ── Dev/QA duration scale (slow-mo for judging motion) ──────────────────────\n// A module-level multiplier applied to every timing DURATION (and stagger\n// delay) at animation start. 1 = design speed; 2 = half-speed slow-mo. Springs\n// are physics-based (friction/tension) and do NOT scale. This is a dev/QA tool\n// (the playground's tweak panel drives it) — production code never calls the\n// setter, so the default 1 keeps shipped motion exactly on spec.\n\nlet durationScale = 1;\n\n/** Set the global duration multiplier (clamped to 0.1-10; invalid resets to 1). */\nexport const setMotionDurationScale = (scale: number): void => {\n durationScale = Number.isFinite(scale) && scale > 0 ? Math.min(10, Math.max(0.1, scale)) : 1;\n};\n\nexport const getMotionDurationScale = (): number => durationScale;\n\n/** Apply the current duration scale to a spec duration/delay (rounded ms). */\nexport const scaledMs = (ms: number): number => Math.round(ms * durationScale);\n\n// ── Reduce-motion helpers (pure, shared by every animated component) ────────\n\nexport type EntranceSpec = {\n /** Duration to animate with (falls back to the short fade under reduce motion). */\n duration: number;\n /** Whether transforms (translate/scale) may move; false = opacity-only fade. */\n useTransform: boolean;\n};\n\n/** Entrances: full motion normally; a 120ms opacity-only fade under reduce motion. */\nexport const entranceSpec = (reduced: boolean, durationMs: number): EntranceSpec =>\n reduced\n ? { duration: REDUCED_FADE_MS, useTransform: false }\n : { duration: durationMs, useTransform: true };\n\n/** State changes (select fills etc.): snap instantly under reduce motion. */\nexport const stateChangeDuration = (reduced: boolean, durationMs: number): number =>\n reduced ? 0 : durationMs;\n\n/** Looping/ambient animations run only when motion is allowed. */\nexport const loopEnabled = (reduced: boolean): boolean => !reduced;\n","/**\n * useReducedMotion — the kit's ONE reduce-motion gate. Reads the OS setting via\n * AccessibilityInfo and stays subscribed to `reduceMotionChanged`, so every\n * animated component lands on its final frame (or a ~120ms fade) the moment the\n * user flips the setting — no restart needed.\n *\n * This closes the gap documented in ai_rules/rules/performance.md §3: every\n * animation in the kit must consume this hook (usually through the pure helpers\n * in motionSpec.ts: `entranceSpec` / `stateChangeDuration` / `loopEnabled`).\n */\nimport { useEffect, useState } from \"react\";\nimport { AccessibilityInfo } from \"react-native\";\n\n// Last-known value, module-level: cards remount every turn (keyed on message id),\n// and a `useState(false)` default would flash one animated frame per turn for a\n// reduce-motion user before the async read resolves.\nlet lastKnown = false;\n\nexport const useReducedMotion = (): boolean => {\n const [reduced, setReduced] = useState(lastKnown);\n\n useEffect(() => {\n let mounted = true;\n AccessibilityInfo.isReduceMotionEnabled()\n .then((value) => {\n lastKnown = value;\n if (mounted) setReduced(value);\n })\n .catch(() => {\n // Unavailable (e.g. some test envs): keep the last-known value.\n });\n const sub = AccessibilityInfo.addEventListener(\"reduceMotionChanged\", (value) => {\n lastKnown = value;\n setReduced(value);\n });\n return () => {\n mounted = false;\n sub?.remove();\n };\n }, []);\n\n return reduced;\n};\n","/**\n * AnimatedSparkle — the themed \"AI is thinking\" glyph (✦), animated with RN's\n * built-in `Animated` (native driver) so the kit needs neither reanimated nor a\n * vector-icon dependency.\n *\n * Variants:\n * - \"spin\" (default, unchanged): continuous rotation — the original loader.\n * - \"pulse\": the Wire Activation loading treatment — the mark breathes\n * (opacity 0.35 ↔ 1, 1600ms loop) instead of rotating.\n *\n * Reduce motion: no loop at all — the glyph renders static at full opacity\n * (final frame), per design-refs/EXTRACTED-SPEC.md row 17.\n */\nimport React, { useEffect, useRef } from \"react\";\nimport { Animated, Easing, StyleSheet, Text } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { LOADER_PULSE_MIN_OPACITY, LOADER_PULSE_MS, loopEnabled, scaledMs } from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst ROTATION_MS = 1800;\n\nexport type AnimatedSparkleProps = {\n /** Glyph size in px. */\n size?: number;\n /** Override color; defaults to the theme primary. */\n color?: string;\n /** \"spin\" rotates (default, the original), \"pulse\" breathes (the loader treatment). */\n variant?: \"spin\" | \"pulse\";\n};\n\nconst _AnimatedSparkle: React.FC<AnimatedSparkleProps> = ({ size = 30, color, variant = \"spin\" }) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const progress = useRef(new Animated.Value(0)).current;\n\n useEffect(() => {\n if (!loopEnabled(reduced)) {\n // Static final frame: no rotation, full opacity.\n progress.setValue(0);\n return;\n }\n const loop =\n variant === \"pulse\"\n ? Animated.loop(\n Animated.sequence([\n Animated.timing(progress, {\n toValue: 1,\n duration: scaledMs(LOADER_PULSE_MS / 2),\n easing: Easing.inOut(Easing.ease),\n useNativeDriver: true,\n }),\n Animated.timing(progress, {\n toValue: 0,\n duration: scaledMs(LOADER_PULSE_MS / 2),\n easing: Easing.inOut(Easing.ease),\n useNativeDriver: true,\n }),\n ]),\n )\n : Animated.loop(\n Animated.timing(progress, {\n toValue: 1,\n duration: scaledMs(ROTATION_MS),\n easing: Easing.linear,\n useNativeDriver: true,\n }),\n );\n loop.start();\n return () => loop.stop();\n }, [progress, variant, reduced]);\n\n const rotate = progress.interpolate({ inputRange: [0, 1], outputRange: [\"0deg\", \"360deg\"] });\n const pulse = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [1, LOADER_PULSE_MIN_OPACITY],\n });\n\n const animatedStyle = reduced\n ? undefined\n : variant === \"pulse\"\n ? { opacity: pulse }\n : { transform: [{ rotate }] };\n\n // The glyph lives in a fixed size×size box (alignItems/justifyContent:center) so the\n // font's side-bearing and Android includeFontPadding can't shove the visible mark off\n // center. The box carries the transform too, so a spinning box still rotates around its\n // own center → the ✦ spins in place, optically centered on both axes.\n return (\n <Animated.View style={[styles.box, { width: size, height: size }, animatedStyle]}>\n <Text\n accessibilityElementsHidden\n importantForAccessibility=\"no\"\n style={[\n styles.glyph,\n {\n width: size,\n fontSize: size,\n lineHeight: size,\n color: color ?? t.colors.primary,\n },\n ]}\n >\n ✦\n </Text>\n </Animated.View>\n );\n};\n\nexport const AnimatedSparkle = React.memo(_AnimatedSparkle);\n\nconst styles = StyleSheet.create({\n box: { alignItems: \"center\", justifyContent: \"center\" },\n glyph: {\n textAlign: \"center\",\n textAlignVertical: \"center\",\n includeFontPadding: false,\n },\n});\n","/**\n * LoadingBlock — the \"AI is thinking\" indicator, shown before the first card and\n * between every turn (each round-trip to the backend). The Wire Activation\n * loading treatment: no generic spinner — the brand mark breathes inside a\n * dashed ring while an accent dot orbits it, and skeleton lines appear (softly\n * pulsing) only when the fetch runs past 300ms so a fast turn never flashes\n * placeholder chrome (design-refs/EXTRACTED-SPEC.md rows 17-19).\n *\n * Reduce motion: static mark + copy, no orbit, no pulse.\n */\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, StyleSheet, Text, View } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { bodyStyle, headingStyle } from \"../theme/typography\";\nimport { AnimatedSparkle } from \"./AnimatedSparkle\";\nimport {\n LOADER_ORBIT_MS,\n SKELETON_DELAY_MS,\n SKELETON_MIN_OPACITY,\n SKELETON_PULSE_MS,\n loopEnabled,\n scaledMs,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst STAGE_SIZE = 96;\nconst ORBIT_DOT = 9;\n\nexport type LoadingBlockProps = {\n /** Primary line, e.g. \"Thinking…\". */\n title?: string;\n /** Supporting line under the title. */\n hint?: string;\n};\n\n/** The orbiting accent dot: a full-stage rotating layer with the dot at 12 o'clock. */\nconst OrbitDot: React.FC<{ color: string; reduced: boolean }> = ({ color, reduced }) => {\n const spin = useRef(new Animated.Value(0)).current;\n useEffect(() => {\n if (!loopEnabled(reduced)) return;\n const loop = Animated.loop(\n Animated.timing(spin, {\n toValue: 1,\n duration: scaledMs(LOADER_ORBIT_MS),\n easing: Easing.linear,\n useNativeDriver: true,\n }),\n );\n loop.start();\n return () => loop.stop();\n }, [spin, reduced]);\n\n if (reduced) return null;\n const rotate = spin.interpolate({ inputRange: [0, 1], outputRange: [\"0deg\", \"360deg\"] });\n return (\n <Animated.View pointerEvents=\"none\" style={[StyleSheet.absoluteFill, { transform: [{ rotate }] }]}>\n <View style={[styles.orbitDot, { backgroundColor: color }]} />\n </Animated.View>\n );\n};\n\n/** A skeleton line that softly pulses (static under reduce motion). */\nconst SkeletonLine: React.FC<{ width: `${number}%`; delay: number; color: string; reduced: boolean }> = ({\n width,\n delay,\n color,\n reduced,\n}) => {\n const pulse = useRef(new Animated.Value(1)).current;\n useEffect(() => {\n if (!loopEnabled(reduced)) return;\n const loop = Animated.loop(\n Animated.sequence([\n Animated.delay(delay),\n Animated.timing(pulse, {\n toValue: SKELETON_MIN_OPACITY,\n duration: scaledMs(SKELETON_PULSE_MS / 2),\n easing: Easing.inOut(Easing.ease),\n useNativeDriver: true,\n }),\n Animated.timing(pulse, {\n toValue: 1,\n duration: scaledMs(SKELETON_PULSE_MS / 2),\n easing: Easing.inOut(Easing.ease),\n useNativeDriver: true,\n }),\n ]),\n );\n loop.start();\n return () => loop.stop();\n }, [pulse, delay, reduced]);\n\n return (\n <Animated.View\n style={[styles.skeletonLine, { width, backgroundColor: color, opacity: reduced ? 1 : pulse }]}\n />\n );\n};\n\nconst _LoadingBlock: React.FC<LoadingBlockProps> = ({\n title = \"Thinking…\",\n hint = \"Personalizing your experience\",\n}) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n // The loader fills its parent (flex:1) and centers in it. In the flow that parent is the\n // scaffold BODY (the same content region the cards render into), so the loader lands at the\n // content-area center — visually consistent with the cards it hands off to. Standalone\n // (LoadingScreen / a playground CardFrame) it centers in whatever bounds it. No screen-inset\n // math and no transform: it inherits the content area it is dropped into, so it is centered\n // in every context by construction.\n\n // Skeleton lines are gated behind the 300ms window: a fast fetch never shows them.\n const [showSkeleton, setShowSkeleton] = useState(false);\n useEffect(() => {\n const timer = setTimeout(() => setShowSkeleton(true), SKELETON_DELAY_MS);\n return () => clearTimeout(timer);\n }, []);\n\n return (\n <View style={[styles.center, { padding: t.spacing.lg }]}>\n {/*\n * The stage is the ANCHOR: it's the only in-flow child, so `justifyContent:\n * center` lands the icon at the true center of the flow area. Title, hint and\n * the (300ms-gated) skeleton hang BELOW it in an absolutely-positioned column,\n * so they never displace the icon — previously they lived in the same centered\n * column, which re-balanced (and jumped the icon UP ~½ its height) the moment\n * the skeleton lines mounted at 300ms.\n */}\n <View style={styles.stage}>\n <View style={[styles.ring, { borderColor: t.colors.border, borderRadius: t.radius.full }]} />\n <OrbitDot color={t.colors.primary} reduced={reduced} />\n <AnimatedSparkle size={40} variant=\"pulse\" />\n </View>\n <View\n style={[\n styles.labels,\n { marginTop: STAGE_SIZE / 2 + t.spacing.lg, gap: t.spacing.md, paddingHorizontal: t.spacing.lg },\n ]}\n pointerEvents=\"none\"\n >\n {title ? (\n <Text style={[headingStyle(t.fonts), { color: t.colors.text, textAlign: \"center\" }]}>\n {title}\n </Text>\n ) : null}\n {hint ? (\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: \"center\" }]}>\n {hint}\n </Text>\n ) : null}\n {showSkeleton ? (\n <View style={[styles.skeleton, { gap: t.spacing.sm, marginTop: t.spacing.sm }]}>\n <SkeletonLine width=\"80%\" delay={0} color={t.colors.surface} reduced={reduced} />\n <SkeletonLine width=\"60%\" delay={200} color={t.colors.surface} reduced={reduced} />\n </View>\n ) : null}\n </View>\n </View>\n );\n};\n\nexport const LoadingBlock = React.memo(_LoadingBlock);\n\nconst styles = StyleSheet.create({\n center: { flex: 1, alignItems: \"center\", justifyContent: \"center\" },\n // Absolutely-positioned label column, pinned just under the centered stage: its top\n // edge starts at the flow center (top: 50%) and the inline marginTop (STAGE_SIZE/2 +\n // a gap) drops it below the stage. Out of flow → it never moves the stage, so the\n // 300ms skeleton reveal grows DOWNWARD only and the icon stays centered.\n labels: { position: \"absolute\", top: \"50%\", left: 0, right: 0, alignItems: \"center\" },\n stage: {\n width: STAGE_SIZE,\n height: STAGE_SIZE,\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n ring: {\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n borderWidth: 1.5,\n borderStyle: \"dashed\",\n },\n orbitDot: {\n position: \"absolute\",\n top: -ORBIT_DOT / 2 + 1,\n left: STAGE_SIZE / 2 - ORBIT_DOT / 2,\n width: ORBIT_DOT,\n height: ORBIT_DOT,\n borderRadius: ORBIT_DOT / 2,\n },\n skeleton: { width: \"100%\", alignItems: \"center\" },\n skeletonLine: { height: 12, borderRadius: 6 },\n});\n","/**\n * LoadingScreen — the STANDALONE loader surface: a full-area safe frame that centers a\n * LoadingBlock dead in the middle of the screen. Used for the loader slots that render on\n * their own (no OnboardingScaffold around them): the cold-start \"getting started\" wait, the\n * resumed-session \"restoring\" wait, and the transient error/timeout retry beat.\n *\n * WHY a dedicated frame: those slots used to return a bare <LoadingBlock/>, whose flex:1 only\n * fills whatever the host happened to give it — with no safe area and, if the host didn't\n * bound it, no height at all (top-anchored). This wraps them in the same SafeAreaView the flow\n * uses, so the standalone loaders center exactly like the between-turns loader (both fill their\n * parent flex:1 region and center in it — here the SafeAreaView, in the flow the scaffold body).\n * One consistent centered look.\n */\nimport React from \"react\";\nimport { StyleSheet } from \"react-native\";\nimport { SafeAreaView } from \"react-native-safe-area-context\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { LoadingBlock, type LoadingBlockProps } from \"./LoadingBlock\";\n\nconst _LoadingScreen: React.FC<LoadingBlockProps> = ({ title, hint }) => {\n const t = useOnboardingTheme();\n return (\n <SafeAreaView\n edges={[\"top\", \"bottom\"]}\n style={[styles.flex, { backgroundColor: t.colors.background }]}\n >\n <LoadingBlock title={title} hint={hint} />\n </SafeAreaView>\n );\n};\n\nexport const LoadingScreen = React.memo(_LoadingScreen);\n\nconst styles = StyleSheet.create({\n flex: { flex: 1 },\n});\n","/**\n * StepProgress — a single themed progress bar that conveys forward motion. It never\n * shows a \"Step X of N\" number (the count would read as a promise the model may not\n * keep), but it can be *paced* two ways:\n *\n * - Default (no `approxScreens`): an asymptotic curve of the step index — always\n * advances, never reaches the end until the flow actually completes.\n * - With `approxScreens`: when the host knows roughly how many screens the flow\n * runs (e.g. the backend's screen budget), the fill tracks `step / approxScreens`\n * (capped below 100% until `complete`). More truthful pacing, still no number.\n */\nimport React, { useEffect, useRef } from \"react\";\nimport { Animated, Easing, StyleSheet, View } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { PROGRESS_MS, WIRE_BEZIER, scaledMs, stateChangeDuration } from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\n\nexport type StepProgressProps = {\n /** 1-based index of the current step. Drives the fill. */\n step: number;\n /** When true, fill to 100% (flow finished). */\n complete?: boolean;\n /**\n * Approximate total number of screens, if known (e.g. the backend screen budget).\n * Paces the bar as `step / approxScreens` instead of the asymptotic curve. Never\n * shown as a number — it only shapes the fill. Omit for the asymptotic default.\n */\n approxScreens?: number;\n};\n\n// Asymptotic default: each step closes ~38% of the remaining gap, so the bar always\n// moves but never hits the end on its own: step1≈38%, step2≈62%, step3≈76%…\nconst DECAY = 0.62;\nconst MIN_FILL = 0.08;\n// When pacing by an approximate total, never look finished until `complete`.\nconst APPROX_CAP = 0.95;\n\nconst targetFor = (step: number, complete?: boolean, approxScreens?: number): number => {\n if (complete) return 1;\n const s = Number.isFinite(step) && step > 0 ? Math.floor(step) : 1;\n if (approxScreens && approxScreens > 0) {\n return Math.max(MIN_FILL, Math.min(APPROX_CAP, s / approxScreens));\n }\n return Math.max(MIN_FILL, 1 - DECAY ** s);\n};\n\nconst _StepProgress: React.FC<StepProgressProps> = ({ step, complete, approxScreens }) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const fill = useRef(new Animated.Value(targetFor(step, complete, approxScreens))).current;\n\n // 400ms ease-wire per the design spec (design-refs/EXTRACTED-SPEC.md row 21).\n // A growing total re-targets the same value, so the fill eases forward and never\n // snaps back. Reduce motion: jump straight to the ratio.\n useEffect(() => {\n Animated.timing(fill, {\n toValue: targetFor(step, complete, approxScreens),\n duration: scaledMs(stateChangeDuration(reduced, PROGRESS_MS)),\n easing: easeWire,\n useNativeDriver: false, // animating width %\n }).start();\n }, [fill, step, complete, approxScreens, reduced]);\n\n const width = fill.interpolate({ inputRange: [0, 1], outputRange: [\"0%\", \"100%\"] });\n\n return (\n <View style={[styles.track, { backgroundColor: t.colors.border, borderRadius: t.radius.full }]}>\n <Animated.View\n style={[\n styles.fill,\n { width, backgroundColor: t.colors.primary, borderRadius: t.radius.full },\n ]}\n />\n </View>\n );\n};\n\nexport const StepProgress = React.memo(_StepProgress);\n\nconst styles = StyleSheet.create({\n track: { height: 6, width: \"100%\", overflow: \"hidden\" },\n fill: { height: 6 },\n});\n","/**\n * OnboardingScaffold — the themed shell that wraps every step:\n * [ safe area ]\n * header -> StepProgress (a numberless fill — never \"Step X of N\") + optional Skip\n * body -> the rendered card (children), full-screen (flex: 1)\n * footer -> optional Back link\n *\n * WHY a single scaffold: the body content changes every turn (it's an\n * SDK-rendered card), but the chrome — progress, skip, back, padding, safe area —\n * stays constant. Keeping it here means cards never re-implement the frame.\n *\n * The body no longer centers/scrolls the card: each card fills the body via the\n * shared CardLayout, which owns its own scroll + bottom-pinned CTA (Cal-AI style).\n * The safe area uses `react-native-safe-area-context` (top + bottom edges) — the\n * RN core SafeAreaView is deprecated and iOS-only, so the kit takes the standard\n * Expo/RN peer instead of shipping cropped layouts on Android + notched devices.\n */\nimport React, { useMemo } from \"react\";\nimport { StyleSheet, Text, TouchableOpacity, View } from \"react-native\";\nimport { SafeAreaView } from \"react-native-safe-area-context\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport type { OnboardingTheme } from \"../theme/types\";\nimport { bodyStyle } from \"../theme/typography\";\nimport { StepProgress } from \"./StepProgress\";\n\nexport type OnboardingScaffoldProps = {\n /** 1-based index of the current step; drives the (countless) progress bar. */\n step: number;\n /** When true, the progress bar fills to 100% (flow finished). */\n complete?: boolean;\n /** Approximate total screens, if known — paces the bar (never shown). */\n approxScreens?: number;\n /** Optional Back action — hidden when omitted (e.g. on the first step). */\n onBack?: () => void;\n /** Optional Skip action — hidden when omitted. */\n onSkip?: () => void;\n skipLabel?: string;\n backLabel?: string;\n children: React.ReactNode;\n};\n\nconst _OnboardingScaffold: React.FC<OnboardingScaffoldProps> = ({\n step,\n complete,\n approxScreens,\n onBack,\n onSkip,\n skipLabel = \"Skip\",\n backLabel = \"Back\",\n children,\n}) => {\n const t = useOnboardingTheme();\n const styles = useMemo(() => makeStyles(t), [t]);\n const hit = { top: 12, bottom: 12, left: 12, right: 12 };\n\n return (\n <SafeAreaView\n edges={[\"top\", \"bottom\"]}\n style={[styles.flex, { backgroundColor: t.colors.background }]}\n >\n <View style={[styles.header, { paddingHorizontal: t.spacing.md, paddingTop: t.spacing.md }]}>\n <View style={styles.progressWrap}>\n <StepProgress step={step} complete={complete} approxScreens={approxScreens} />\n </View>\n {onSkip ? (\n <TouchableOpacity onPress={onSkip} hitSlop={hit} style={styles.skip}>\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted }]}>{skipLabel}</Text>\n </TouchableOpacity>\n ) : null}\n </View>\n\n {/* Full-screen body (flex:1): the card (via CardLayout) fills this and pins its own CTA,\n and the between-turns LoadingBlock fills+centers in this SAME region — so the loader\n lands at the content-area center, consistent with the cards, not the full-screen center. */}\n <View\n style={[styles.body, { paddingHorizontal: t.spacing.md, paddingTop: t.spacing.md }]}\n >\n {children}\n </View>\n\n {onBack ? (\n <View style={[styles.footer, { paddingHorizontal: t.spacing.md, paddingBottom: t.spacing.sm }]}>\n <TouchableOpacity onPress={onBack} hitSlop={hit}>\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted }]}>{backLabel}</Text>\n </TouchableOpacity>\n </View>\n ) : null}\n </SafeAreaView>\n );\n};\n\nexport const OnboardingScaffold = React.memo(_OnboardingScaffold);\n\nfunction makeStyles(t: OnboardingTheme) {\n return StyleSheet.create({\n flex: { flex: 1 },\n header: { flexDirection: \"row\", alignItems: \"center\" },\n progressWrap: { flex: 1 },\n body: { flex: 1 },\n footer: { flexDirection: \"row\", justifyContent: \"flex-start\" },\n skip: { marginLeft: t.spacing.md },\n });\n}\n","/**\n * Button — the kit's themed primary/outline button, replacing the SDK's hardcoded\n * `Btn`. Every color/radius/font comes from the active theme.\n *\n * Motion (design-refs/EXTRACTED-SPEC.md row 20): \"a footer button that answers\n * the tap\" — scale 1→0.975 spring on press-in, back on release, native driver.\n * Reduce motion: an opacity dip to 0.85 while pressed, no scale. Disabled keeps\n * the `disabled` token fill with no press handler (unchanged).\n */\nimport React, { useCallback, useRef } from \"react\";\nimport { Animated, Pressable, StyleSheet, Text } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { buttonLabelStyle } from \"../theme/typography\";\nimport {\n BUTTON_PRESS_SCALE,\n BUTTON_PRESS_SPRING,\n REDUCED_FADE_MS,\n REDUCED_PRESS_OPACITY,\n scaledMs,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\ntype Variant = \"primary\" | \"outline\";\n\ntype ButtonProps = {\n title: string;\n onPress?: () => void;\n variant?: Variant;\n disabled?: boolean;\n /** Stretch to the container width — for form-style CTAs (e.g. the review form's\n * \"Send feedback\"). Default false keeps the content-width pill used by cards. */\n fullWidth?: boolean;\n};\n\nconst _Button: React.FC<ButtonProps> = ({\n title,\n onPress,\n variant = \"primary\",\n disabled = false,\n fullWidth = false,\n}) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const isPrimary = variant === \"primary\";\n\n // 0 = at rest, 1 = pressed. Scale normally; opacity dip under reduce motion.\n const pressT = useRef(new Animated.Value(0)).current;\n const pressTo = useCallback(\n (to: number) => {\n if (reduced) {\n Animated.timing(pressT, {\n toValue: to,\n duration: scaledMs(REDUCED_FADE_MS),\n useNativeDriver: true,\n }).start();\n return;\n }\n Animated.spring(pressT, {\n toValue: to,\n friction: BUTTON_PRESS_SPRING.friction,\n tension: BUTTON_PRESS_SPRING.tension,\n useNativeDriver: true,\n }).start();\n },\n [pressT, reduced],\n );\n const lastPress = useRef<number>(0);\n const handlePress = useCallback(() => {\n if (!onPress) return;\n const now = Date.now();\n if (now - lastPress.current < 500) return;\n lastPress.current = now;\n onPress();\n }, [onPress]);\n\n const handlePressIn = useCallback(() => pressTo(1), [pressTo]);\n const handlePressOut = useCallback(() => pressTo(0), [pressTo]);\n\n const scale = pressT.interpolate({\n inputRange: [0, 1],\n outputRange: [1, reduced ? 1 : BUTTON_PRESS_SCALE],\n });\n const opacity = pressT.interpolate({\n inputRange: [0, 1],\n outputRange: [1, reduced ? REDUCED_PRESS_OPACITY : 1],\n });\n\n return (\n <Pressable\n onPress={disabled ? undefined : handlePress}\n onPressIn={disabled ? undefined : handlePressIn}\n onPressOut={disabled ? undefined : handlePressOut}\n disabled={disabled}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled }}\n style={fullWidth ? styles.fill : undefined}\n >\n <Animated.View\n style={[\n styles.base,\n fullWidth && styles.fill,\n {\n borderRadius: t.button.radius,\n minHeight: t.button.height,\n paddingHorizontal: t.button.paddingX,\n opacity,\n transform: [{ scale }],\n },\n isPrimary\n ? { backgroundColor: disabled ? t.colors.disabled : t.colors.primary }\n : { borderWidth: 1.5, borderColor: disabled ? t.colors.border : t.colors.primary },\n ]}\n >\n <Text\n style={[\n buttonLabelStyle(t.fonts),\n {\n color: disabled\n ? t.colors.textMuted\n : isPrimary\n ? t.colors.onPrimary\n : t.colors.primary,\n },\n ]}\n >\n {title}\n </Text>\n </Animated.View>\n </Pressable>\n );\n};\n\nexport const Button = React.memo(_Button);\n\nconst styles = StyleSheet.create({\n base: { alignItems: \"center\", justifyContent: \"center\" },\n fill: { width: \"100%\" },\n});\n","/**\n * ErrorBlock — shown on backend error/timeout. Carries a retry action so the flow\n * never dead-ends. The host decides what retry does (re-send start, or fall back).\n */\nimport React from \"react\";\nimport { StyleSheet, Text, View } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { bodyStyle, headingStyle } from \"../theme/typography\";\nimport { Button } from \"./Button\";\n\nexport type ErrorBlockProps = {\n title?: string;\n message?: string;\n retryLabel?: string;\n onRetry?: () => void;\n};\n\nconst _ErrorBlock: React.FC<ErrorBlockProps> = ({\n title = \"Something went wrong\",\n message = \"We couldn't load this step. You can try again.\",\n retryLabel = \"Try again\",\n onRetry,\n}) => {\n const t = useOnboardingTheme();\n return (\n <View style={[styles.center, { gap: t.spacing.md, padding: t.spacing.lg }]}>\n <Text style={[headingStyle(t.fonts), { color: t.colors.text, textAlign: \"center\" }]}>\n {title}\n </Text>\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: \"center\" }]}>\n {message}\n </Text>\n {onRetry ? <Button title={retryLabel} onPress={onRetry} variant=\"outline\" /> : null}\n </View>\n );\n};\n\nexport const ErrorBlock = React.memo(_ErrorBlock);\n\nconst styles = StyleSheet.create({\n center: { flex: 1, alignItems: \"center\", justifyContent: \"center\" },\n});\n","/**\n * CardLayout — the shared full-screen card body every card renders into. It owns\n * the Cal-AI style vertical rhythm so no card re-implements layout:\n *\n * [ title ] ← fixed at top (small gap → subtitle)\n * [ subtitle / hint ]\n * [ ─ scrollable content ─ ]← options / chips / input; a flex:1 ScrollView that\n * fills the gap, so it scrolls only when tall and\n * otherwise just pushes the footer down\n * [ footer / CTA ] ← the submit button, ANCHORED to the bottom\n *\n * The middle ScrollView (flex:1) IS the flexible spacer: when the content is short\n * it grows to fill, pinning the footer to the bottom of the screen; when the\n * content is many/tall options it scrolls while the CTA stays put. Everything\n * reads from the theme tokens — no hardcoded spacing or color.\n *\n * `align=\"center\"` vertically centers the content (used by the value/status beats:\n * InterstitialCard / StatusCard), keeping the same pinned-CTA footer.\n *\n * The whole column sits in a KeyboardAvoidingView (behavior=\"padding\") so the pinned\n * footer rides above the soft keyboard on text questions (TextInputCard). On hosts\n * whose window already resizes for the keyboard the computed overlap is ~0, so the\n * padding is a no-op — safe on both iOS and Android, edge-to-edge or not.\n */\nimport React, { useMemo } from \"react\";\nimport { KeyboardAvoidingView, ScrollView, StyleSheet, Text, View } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport type { OnboardingTheme } from \"../theme/types\";\nimport { bodyStyle, labelStyle } from \"../theme/typography\";\n\nexport type CardLayoutProps = {\n /** Fixed question/label shown at the top. Omit for a header-less centered beat. */\n title?: string;\n /** Optional supporting line under the title (small gap between them). */\n subtitle?: string;\n /** The options / chips / input area — the scrollable middle. */\n children: React.ReactNode;\n /** The pinned bottom CTA (usually a <Button/>). Omitted → no footer. */\n footer?: React.ReactNode;\n /** Vertical alignment of the middle content. \"top\" (questions) | \"center\" (beats). */\n align?: \"top\" | \"center\";\n /** Custom title node (e.g. StatusCard's icon+title row) rendered in place of `title`. */\n titleNode?: React.ReactNode;\n};\n\nconst _CardLayout: React.FC<CardLayoutProps> = ({\n title,\n subtitle,\n children,\n footer,\n align = \"top\",\n titleNode,\n}) => {\n const t = useOnboardingTheme();\n const styles = useMemo(() => makeStyles(t), [t]);\n const hasHeader = !!title || !!subtitle || !!titleNode;\n\n return (\n <KeyboardAvoidingView style={styles.fill} behavior=\"padding\">\n {hasHeader ? (\n <View style={styles.header}>\n {titleNode ??\n (title ? (\n <Text style={[labelStyle(t.fonts), { color: t.colors.text }]}>{title}</Text>\n ) : null)}\n {subtitle ? (\n <Text\n style={[\n bodyStyle(t.fonts),\n { color: t.colors.textMuted, marginTop: t.spacing.xs },\n ]}\n >\n {subtitle}\n </Text>\n ) : null}\n </View>\n ) : null}\n\n <ScrollView\n style={styles.fill}\n contentContainerStyle={[\n styles.scrollContent,\n align === \"center\" && styles.center,\n ]}\n keyboardShouldPersistTaps=\"handled\"\n keyboardDismissMode=\"on-drag\"\n showsVerticalScrollIndicator={false}\n >\n {children}\n </ScrollView>\n\n {footer ? <View style={styles.footer}>{footer}</View> : null}\n </KeyboardAvoidingView>\n );\n};\n\nexport const CardLayout = React.memo(_CardLayout);\n\nfunction makeStyles(t: OnboardingTheme) {\n return StyleSheet.create({\n fill: { flex: 1 },\n header: { marginBottom: t.spacing.lg },\n footer: { paddingTop: t.spacing.lg },\n // flexGrow lets a short content block grow to fill (pinning the footer) while a\n // tall one scrolls past the visible area.\n scrollContent: { flexGrow: 1 },\n center: { justifyContent: \"center\" },\n });\n}\n","/**\n * CompletionView — the terminal \"you're all set\" screen, shown when the flow\n * reaches its final StatusCard. It surfaces the backend's recap (what the app\n * will do for the user, derived from their answers) and a single clear CTA.\n *\n * WHY a dedicated screen (not an instant hand-off): the backend spends the last\n * turn summarizing the user's tastes and what their experience will now look\n * like. The user should actually SEE that payoff and tap to continue — so\n * `onContinue` fires only on the button press, never automatically.\n *\n * Motion (design-refs/EXTRACTED-SPEC.md rows 14-16, the peak-end beat): the\n * badge pops in with a spring (scale 0.4→1, slight overshoot), ONE soft accent\n * burst radiates once behind it (scale 0.4→1.5, opacity 0.5→0, 500ms) —\n * celebratory without confetti — and the copy fades up 80ms apart. Everything\n * settles well under a second. Reduce motion: final frame, no burst.\n */\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, StyleSheet, Text, View } from \"react-native\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { bodyStyle, headingStyle } from \"../theme/typography\";\nimport { Button } from \"./Button\";\nimport { CardLayout } from \"./CardLayout\";\nimport {\n STATUS_BURST_MS,\n STATUS_BURST_OPACITY_FROM,\n STATUS_BURST_SCALE_FROM,\n STATUS_BURST_SCALE_TO,\n STATUS_COPY_MS,\n STATUS_POP_SCALE_FROM,\n STATUS_POP_SPRING,\n WIRE_BEZIER,\n scaledMs,\n statusCopyDelay,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\nconst BADGE_SIZE = 64;\nconst BURST_SIZE = 104;\n\nexport type CompletionViewProps = {\n title: string;\n message?: string;\n ctaLabel?: string;\n onContinue: () => void;\n};\n\nconst _CompletionView: React.FC<CompletionViewProps> = ({\n title,\n message,\n ctaLabel = \"Let's go\",\n onContinue,\n}) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const [submitted, setSubmitted] = useState(false);\n\n const pop = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const burst = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const titleT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const messageT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n\n useEffect(() => {\n if (reduced) {\n // Final frame: badge + copy settled, burst already faded out.\n pop.setValue(1);\n burst.setValue(1);\n titleT.setValue(1);\n messageT.setValue(1);\n return;\n }\n const rise = (value: Animated.Value, delay: number) =>\n Animated.timing(value, {\n toValue: 1,\n duration: scaledMs(STATUS_COPY_MS),\n delay,\n easing: easeWire,\n useNativeDriver: true,\n });\n const anims = [\n Animated.spring(pop, {\n toValue: 1,\n friction: STATUS_POP_SPRING.friction,\n tension: STATUS_POP_SPRING.tension,\n useNativeDriver: true,\n }),\n // One-shot celebratory burst: fires once, never loops.\n Animated.timing(burst, {\n toValue: 1,\n duration: scaledMs(STATUS_BURST_MS),\n easing: Easing.out(Easing.ease),\n useNativeDriver: true,\n }),\n rise(titleT, scaledMs(statusCopyDelay(0))),\n rise(messageT, scaledMs(statusCopyDelay(1))),\n ];\n anims.forEach((a) => a.start());\n return () => anims.forEach((a) => a.stop());\n }, [reduced, pop, burst, titleT, messageT]);\n\n const handlePress = useCallback(() => {\n if (submitted) return;\n setSubmitted(true);\n onContinue();\n }, [submitted, onContinue]);\n\n const scale = pop.interpolate({ inputRange: [0, 1], outputRange: [STATUS_POP_SCALE_FROM, 1] });\n const burstScale = burst.interpolate({\n inputRange: [0, 1],\n outputRange: [STATUS_BURST_SCALE_FROM, STATUS_BURST_SCALE_TO],\n });\n const burstOpacity = burst.interpolate({\n inputRange: [0, 1],\n outputRange: [STATUS_BURST_OPACITY_FROM, 0],\n });\n const riseStyle = (value: Animated.Value) => ({\n opacity: value,\n transform: [{ translateY: value.interpolate({ inputRange: [0, 1], outputRange: [10, 0] }) }],\n });\n\n return (\n <CardLayout\n align=\"center\"\n footer={<Button title={ctaLabel} onPress={handlePress} variant=\"primary\" disabled={submitted} />}\n >\n <View style={[styles.center, { gap: t.spacing.md }]}>\n <View style={styles.badgeStage}>\n {/* Soft accent burst behind the badge: primarySoft keeps the tint calm. */}\n <Animated.View\n pointerEvents=\"none\"\n style={[\n styles.burst,\n {\n backgroundColor: t.colors.primarySoft,\n borderRadius: t.radius.full,\n opacity: burstOpacity,\n transform: [{ scale: burstScale }],\n },\n ]}\n />\n <Animated.View\n style={[\n styles.badge,\n {\n backgroundColor: t.colors.primarySoft,\n borderRadius: t.radius.full,\n transform: [{ scale }],\n opacity: pop,\n },\n ]}\n >\n <Text style={[styles.check, { color: t.colors.primary }]}>✓</Text>\n </Animated.View>\n </View>\n\n <Animated.View style={riseStyle(titleT)}>\n <Text style={[headingStyle(t.fonts), { color: t.colors.text, textAlign: \"center\" }]}>\n {title}\n </Text>\n </Animated.View>\n {message ? (\n <Animated.View style={riseStyle(messageT)}>\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: \"center\" }]}>\n {message}\n </Text>\n </Animated.View>\n ) : null}\n </View>\n </CardLayout>\n );\n};\n\nexport const CompletionView = React.memo(_CompletionView);\n\nconst styles = StyleSheet.create({\n center: { width: \"100%\", alignItems: \"center\", justifyContent: \"center\" },\n badgeStage: {\n width: BURST_SIZE,\n height: BURST_SIZE,\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n burst: { position: \"absolute\", width: BURST_SIZE, height: BURST_SIZE },\n badge: { width: BADGE_SIZE, height: BADGE_SIZE, alignItems: \"center\", justifyContent: \"center\" },\n check: { fontSize: 34, fontWeight: \"800\" },\n});\n","/**\n * CardHandoff — the card-to-card transition from the Wire Activation design:\n * \"cards hand off, they don't cut\". When `transitionKey` changes, the outgoing\n * child leaves left (translateX 0→-26, fade, 180ms) in an absolute layer while\n * the incoming child arrives from the right (translateX +26→0, fade, 220ms)\n * delayed by the 80ms exit lead — one moving surface, ~300ms total.\n *\n * Variants (per child):\n * - \"slide\": questions — the directional stepper motion above.\n * - \"spring\": the InterstitialCard value beat — scale 0.96→1 spring pop\n * (the shell's springier variant, kept from AnimatedCard).\n * - \"fade\": loaders — enter/exit as a plain 120ms fade so the \"thinking\"\n * state hands off to the first card without a hard cut.\n *\n * `direction` mirrors the whole slide for BACK navigation, so a step the user\n * returns to comes back from the side it left toward. Spatial consistency: if\n * \"next\" pushes left, \"back\" must pull right, or the stack loses its geography.\n *\n * `layout` picks how the moving surface is sized. \"fill\" (default) is the\n * full-screen flow, where the pane owns the viewport. \"auto\" is for a pane\n * inside an auto-height container (the CenteredModal card): `flex: 1` there\n * resolves to a ZERO-height child under Yoga — flex-basis 0 with no free space\n * to grow into — so the in-flow layer must size to its own content instead.\n *\n * Reduce motion: every handoff becomes a 120ms crossfade, no translate/scale.\n * All values run on the native driver (transform/opacity only); in-flight\n * animations are stopped when superseded and on unmount.\n *\n * This SUPERSEDES the enter-only AnimatedCard: same keyed-remount contract from\n * OnboardingFlow (the child renderer stays keyed on the message id), plus the\n * paired exit layer the design calls for.\n */\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, StyleSheet } from \"react-native\";\nimport {\n CARD_ENTER_MS,\n CARD_ENTER_SCALE_FROM,\n CARD_EXIT_LEAD_MS,\n CARD_EXIT_MS,\n CARD_SLIDE_PX,\n CARD_SPRING,\n LOADER_HANDOFF_FADE_MS,\n REDUCED_FADE_MS,\n WIRE_BEZIER,\n scaledMs,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\n\nexport type CardHandoffVariant = \"slide\" | \"spring\" | \"fade\";\n\n/** Which way the stack is moving. \"backward\" mirrors the slide (see the header note). */\nexport type CardHandoffDirection = \"forward\" | \"backward\";\n\n/** How the moving surface is sized. \"auto\" = a pane in an auto-height container. */\nexport type CardHandoffLayout = \"fill\" | \"auto\";\n\nexport type CardHandoffProps = {\n /** Identity of the current child (e.g. the message id). A change runs the handoff. */\n transitionKey: string;\n /** How the CURRENT child enters (and, snapshotted, how it will later exit). */\n variant?: CardHandoffVariant;\n /** Travel direction of THIS transition. Default \"forward\". */\n direction?: CardHandoffDirection;\n /** Sizing mode. Default \"fill\" (the full-screen flow). */\n layout?: CardHandoffLayout;\n children: React.ReactNode;\n};\n\ntype Snapshot = { key: string; node: React.ReactNode; variant: CardHandoffVariant };\n\nconst _CardHandoff: React.FC<CardHandoffProps> = ({\n transitionKey,\n variant = \"slide\",\n direction = \"forward\",\n layout = \"fill\",\n children,\n}) => {\n const reduced = useReducedMotion();\n const [leaving, setLeaving] = useState<Snapshot | null>(null);\n\n const enterT = useRef(new Animated.Value(0)).current;\n const exitT = useRef(new Animated.Value(0)).current;\n // The previous render's child, snapshotted so it can play the exit layer.\n const prev = useRef<Snapshot>({ key: transitionKey, node: children, variant });\n const running = useRef<{ enter?: Animated.CompositeAnimation; exit?: Animated.CompositeAnimation }>({});\n const mounted = useRef(false);\n\n // One orchestration effect, run every render: refresh the snapshot while the key\n // is stable; on a key change, snapshot the old child into the exit layer and run\n // the paired exit+enter. (No deps array on purpose — `children` is a fresh node\n // every parent render and must keep the snapshot current.)\n useEffect(() => {\n const last = prev.current;\n prev.current = { key: transitionKey, node: children, variant };\n\n // First mount: enter only (the design's initial reveal), nothing exits.\n if (!mounted.current) {\n mounted.current = true;\n running.current.enter = startEnter(enterT, variant, reduced, 0);\n return;\n }\n if (last.key === transitionKey) return;\n\n running.current.enter?.stop();\n running.current.exit?.stop();\n setLeaving(last);\n enterT.setValue(0);\n exitT.setValue(0);\n\n const exitDuration = reduced\n ? REDUCED_FADE_MS\n : last.variant === \"fade\"\n ? LOADER_HANDOFF_FADE_MS\n : CARD_EXIT_MS;\n const exit = Animated.timing(exitT, {\n toValue: 1,\n duration: scaledMs(exitDuration),\n easing: easeWire,\n useNativeDriver: true,\n });\n running.current.exit = exit;\n exit.start();\n\n const enter = startEnter(enterT, variant, reduced, reduced ? 0 : CARD_EXIT_LEAD_MS, () =>\n setLeaving(null),\n );\n running.current.enter = enter;\n });\n\n // Stop anything in flight on unmount (leaked animations drain the JS thread).\n useEffect(\n () => () => {\n running.current.enter?.stop();\n running.current.exit?.stop();\n },\n [],\n );\n\n const enterStyle = {\n opacity: enterT,\n transform: transformFor(variant, enterT, reduced, \"enter\", direction),\n };\n\n return (\n <>\n {leaving ? (\n <Animated.View\n pointerEvents=\"none\"\n style={[\n StyleSheet.absoluteFill,\n {\n opacity: exitT.interpolate({ inputRange: [0, 1], outputRange: [1, 0] }),\n // The CURRENT direction drives BOTH layers: one transition, one geography.\n transform: transformFor(leaving.variant, exitT, reduced, \"exit\", direction),\n },\n ]}\n >\n {leaving.node}\n </Animated.View>\n ) : null}\n <Animated.View key={variant} style={[layout === \"fill\" ? styles.fill : null, enterStyle]}>\n {children}\n </Animated.View>\n </>\n );\n};\n\n/** Kick off the enter animation for a variant (spring for the value beat, timing otherwise). */\nconst startEnter = (\n value: Animated.Value,\n variant: CardHandoffVariant,\n reduced: boolean,\n delay: number,\n onDone?: () => void,\n): Animated.CompositeAnimation => {\n value.setValue(0);\n const anim =\n !reduced && variant === \"spring\"\n ? Animated.spring(value, {\n toValue: 1,\n delay: scaledMs(delay),\n damping: CARD_SPRING.damping,\n stiffness: CARD_SPRING.stiffness,\n mass: CARD_SPRING.mass,\n useNativeDriver: true,\n })\n : Animated.timing(value, {\n toValue: 1,\n delay: scaledMs(delay),\n duration: scaledMs(\n reduced\n ? REDUCED_FADE_MS\n : variant === \"fade\"\n ? LOADER_HANDOFF_FADE_MS\n : CARD_ENTER_MS,\n ),\n easing: easeWire,\n useNativeDriver: true,\n });\n anim.start(({ finished }) => {\n if (finished) onDone?.();\n });\n return anim;\n};\n\n/**\n * Transform track per variant/layer; reduce motion = opacity-only crossfade.\n *\n * `travel` mirrors the X axis: forward pushes the stack left (new arrives from the\n * right), backward pulls it right (new arrives from the left).\n */\nconst transformFor = (\n variant: CardHandoffVariant,\n t: Animated.Value,\n reduced: boolean,\n layer: \"enter\" | \"exit\",\n travel: CardHandoffDirection,\n) => {\n if (reduced || variant === \"fade\") return [];\n if (variant === \"spring\" && layer === \"enter\") {\n return [{ scale: t.interpolate({ inputRange: [0, 1], outputRange: [CARD_ENTER_SCALE_FROM, 1] }) }];\n }\n const slide = travel === \"forward\" ? CARD_SLIDE_PX : -CARD_SLIDE_PX;\n return [\n {\n translateX: t.interpolate({\n inputRange: [0, 1],\n outputRange: layer === \"enter\" ? [slide, 0] : [0, -slide],\n }),\n },\n ];\n};\n\nexport const CardHandoff = React.memo(_CardHandoff);\n\nconst styles = StyleSheet.create({\n fill: { flex: 1 },\n});\n","/**\n * deriveAnswers — read the user's structured choices off the thread.\n *\n * The cards send answers back as natural-language strings (the SDK's\n * useWireAIAction wraps them, e.g. `I selected: [\"Food\",\"Travel\"]`,\n * `My answer is: \"Casablanca\"`). We pair each rendered question with the reply\n * that followed it and key the answer by the backend's progress `key` when\n * present (so `username`/`interests`/`city` come back under their real keys),\n * else by the question text. No second LLM call — the values ARE the data.\n */\nimport type { Message } from \"wireai-rn\";\n\nconst stripPrefix = (s: string): string =>\n s.replace(/^(I selected:|My answer is:|I tapped:)\\s*/i, \"\").trim();\n\nconst tryParse = (s: string): unknown => {\n try {\n return JSON.parse(s);\n } catch {\n return s;\n }\n};\n\nexport const deriveAnswers = (messages: Message[]): Record<string, unknown> => {\n const out: Record<string, unknown> = {};\n for (let i = 0; i < messages.length; i++) {\n const m = messages[i];\n const r = m?.response;\n if (!m || m.role !== \"assistant\" || !r || r.action !== \"render\") continue;\n\n const props = (r.props ?? {}) as Record<string, unknown>;\n const progress = props.progress as { key?: string; slot_id?: string } | undefined;\n const questionText =\n (props.title as string) ?? (props.label as string) ?? (props.question as string);\n // slot_id > key > question text, decided PER CARD. A thread that mixes slotted and unslotted\n // cards is the real shape during a server rollout, so caching a \"this backend does slots\" verdict\n // off the first card would mis-key every later one. Against a backend that sends no `slot_id`\n // this is byte-identical to 0.12.2.\n const key = progress?.slot_id || progress?.key || questionText;\n\n const reply = messages[i + 1];\n if (key && reply?.role === \"user\") {\n out[key] = tryParse(stripPrefix(reply.content));\n }\n }\n return out;\n};\n","/**\n * readProgress — pull the backend's progress metadata off a render response.\n *\n * The managed backend rides `{ step, total, key }` inside the Wire envelope's\n * `props.progress`. That's the only field that survives the SDK's strict client\n * validation (extra top-level keys get folded into props; the card's own schema\n * silently strips `progress` from its render props, but it stays readable on\n * `response.props`). All fields are optional so an older backend just falls back\n * to the local counter.\n */\nimport type { WireAIResponse } from \"wireai-rn\";\nimport type { OnboardingProgress } from \"../types\";\n\ntype PartialProgress = {\n step?: number;\n total?: number;\n key?: string;\n /** The stable per-slot identity, when the backend sends one. See `OnboardingProgress.slot_id`. */\n slot_id?: string;\n skippable?: boolean;\n};\n\nexport const readProgress = (response?: WireAIResponse): PartialProgress => {\n if (!response || response.action !== \"render\") return {};\n const props = (response.props ?? {}) as Record<string, unknown>;\n const raw = props.progress;\n if (!raw || typeof raw !== \"object\") return {};\n const p = raw as Partial<OnboardingProgress>;\n return {\n step: typeof p.step === \"number\" ? p.step : undefined,\n total: typeof p.total === \"number\" ? p.total : undefined,\n key: typeof p.key === \"string\" ? p.key : undefined,\n // Whitelisted the same way as every other field: an old backend simply omits it.\n slot_id: typeof p.slot_id === \"string\" ? p.slot_id : undefined,\n skippable: typeof p.skippable === \"boolean\" ? p.skippable : undefined,\n };\n};\n","/**\n * reportClientEvent — forward DEVICE-ONLY onboarding events to the Wire AI analytics\n * backend (`POST {serverUrl}/v1/events`), completing the funnel for events the server\n * can't observe on its own.\n *\n * The backend already records the server-observable funnel during the A2A flow\n * (`session_started`, `screen_shown`, `answer_submitted`, `completed`, `llm_fallback`,\n * and even `screen_skipped` — it derives that from the kit's skip sentinel). The one\n * event no server request can capture is `dropped`: the user closing the app / unmounting\n * the flow without finishing. That's what this reporter is for.\n *\n * Contract (server: routers/onboarding.py → analytics/events.py):\n * POST {serverUrl}/v1/events\n * Authorization: Bearer {apiKey}\n * { \"events\": [ { event_type, session_id, screen_index?, component?, question_key?,\n * latency_ms?, meta?, device?, user_context? } ] }\n * The server fills `app_id` + `environment` from the resolving key (never send app_id),\n * and silently skips malformed events — one bad payload never fails the batch.\n *\n * ⚠️ Correlation: `session_id` MUST equal the A2A `contextId` the server uses to key the\n * server-side events, or the funnel report (which groups by `session_id`) treats this as a\n * phantom session. See `makeSessionId` + WireOnboarding for how the kit seeds it.\n *\n * Fire-and-forget: this never throws into the UI and never awaits — analytics must never\n * be able to break onboarding.\n */\nimport type { DeviceContext } from \"../device/deviceContext\";\n\n/** Event types a CLIENT may report. The rest of the funnel is server-side; sending those\n * here would double-count. `screen_skipped` is included for completeness, but the kit does\n * NOT emit it — the backend already derives it from the skip sentinel (see OnboardingFlow).\n * `client_fallback` is emitted by the kit when the AI flow degrades to the static fallback,\n * so the dashboard's fallback-rate counts the whole-flow case (distinct from the server's\n * per-turn `llm_fallback`). The server back-fills a `session_started` for it if unseen.\n * This is the SINGLE fallback signal — hosts must NOT also report their own.\n * `identify` binds the host's opaque `user_id` to this `session_id` (late binding — the user\n * registered during/after onboarding). It carries no funnel weight; the server maps the\n * session to the user and back-fills a `session_started` if it never saw the session.\n * `app_event` is the host's own in-app event (the `createAnalytics` façade's `track`/`screen`\n * route through the offline queue as first-class `ClientEvent`s). The server already ingests\n * it — `reportAppEvent` (reviews/transport) has fired `event_type='app_event'` all along; this\n * widening just lets the same shape flow through the durable queue instead of a blind POST. */\nexport type ClientEventType =\n | \"screen_skipped\"\n | \"dropped\"\n | \"client_fallback\"\n | \"identify\"\n | \"app_event\";\n\n/** One client-reported event. Mirrors the server's `OnboardingEvent` (client-settable fields). */\nexport type ClientEvent = {\n event_type: ClientEventType;\n /** Must match the server-side A2A contextId for this onboarding (see makeSessionId). */\n session_id: string;\n /** 0-based index of the screen the event refers to (matches server `screen_shown`). */\n screen_index?: number;\n component?: string;\n question_key?: string;\n latency_ms?: number;\n /** JSON-stringified extras; the server stores it verbatim. */\n meta?: string;\n /**\n * Privacy-label-neutral device snapshot (platform / form factor / locale / host appVersion).\n * Sent as an object; the server sanitizes + persists it and derives a coarse country. Old\n * servers ignore this unknown field — fully backward compatible. See device/deviceContext.ts.\n */\n device?: DeviceContext;\n /**\n * Host-injected, non-PII context (signup method, referral, plan, hashed user id). Old servers\n * ignore it. MUST NOT contain PII like raw emails — see the README `userContext` section.\n */\n user_context?: Record<string, string | number | boolean>;\n /**\n * The host's OPAQUE PSEUDONYMOUS user id (their internal id, NOT an email/name). Required on\n * `identify`, optional (rides along) on other events. Trimmed + capped at 128 chars host-side.\n * Lets the backend reconcile onboarding sessions to real users. Old servers ignore it.\n */\n user_id?: string;\n /**\n * Client-stamped timestamp of when the event was ENQUEUED on the device. Optional and ADDITIVE.\n *\n * TWO REPRESENTATIONS, on purpose:\n * - INTERNAL (epoch-ms `number`): what the offline queue stamps at enqueue time (see\n * `createEventQueue`), so two otherwise byte-identical events fired seconds apart (a genuine\n * repeat, e.g. the user taps \"share\" twice) are NOT collapsed by the queue's identical-JSON\n * de-dup — while two truly simultaneous re-enqueues of the same instant (a redundant\n * re-render) still share a `ts` and collapse. The de-dup signature depends on this number.\n * - WIRE (ISO8601 UTC `string`): what actually leaves the device. {@link buildEventsRequest}\n * converts the number on its way out, because the server declares `ts: str | None` and\n * pydantic v2 does NOT coerce a number into it — a numeric `ts` made the server answer HTTP\n * 200 with `{written: 0, skipped: N, errors: [{field: \"ts\", reason: \"validation_error\"}]}`,\n * silently discarding EVERY `app_event` through 0.13.0.\n *\n * A caller-set ISO string is passed through as-is. Never a wall-clock the server trusts (it\n * derives its own receive time); an old/strict server that does not model it ignores the field.\n */\n ts?: number | string;\n};\n\n/** Where to POST. Derived from `WireOnboardingConfig` (`serverUrl` + `apiKey`). */\nexport type ClientEventTarget = {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/v1/events` is appended. */\n serverUrl: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey: string;\n};\n\n/**\n * A unique-per-onboarding session id. Used both as the client event `session_id` AND as the\n * seed the kit forwards to the backend so the SERVER adopts it as the A2A `contextId` — making\n * client and server agree (see WireOnboarding + the SDK-correlation note in the kit docs).\n * No crypto dependency: timestamp + random is collision-safe for a single device's onboarding.\n */\nexport const makeSessionId = (): string =>\n `wire_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;\n\n/**\n * Serialize the internal epoch-ms `ts` to the ISO8601 UTC string the WIRE requires.\n *\n * The server's event model declares `ts: str | None` and pydantic v2 does NOT coerce int → str, so\n * a numeric `ts` fails per-event validation: the endpoint still answers HTTP 200, but with\n * `{written: 0, skipped: N, errors: [{index, reason: \"validation_error\", field: \"ts\"}]}` — every\n * `app_event` from `track()`/`screen()` silently discarded behind a green response.\n *\n * WHY HERE and not at the queue's `stamp()`: this is the single choke point all FOUR send paths go\n * through (offline queue, fire-and-forget, awaitable, session-start). Converting here leaves the\n * queue's numeric `ts` — and therefore its identical-JSON de-dup signature — exactly as it was, and\n * it also converts the persisted 0.13.0 backlogs (which hold a numeric `ts`) on their way out.\n *\n * NEVER mutates the caller's event: an event that needs a change is copied. A string `ts` (a\n * caller-set ISO stamp) and an absent `ts` pass through untouched. A non-finite (`NaN`/`Infinity`)\n * or out-of-range number — the latter makes `toISOString` throw — drops the `ts` field from the\n * copy rather than killing the whole batch.\n */\nconst toWireEvents = (events: ClientEvent[]): ClientEvent[] =>\n events.map((event) => {\n if (typeof event.ts !== \"number\") return event;\n const { ts, ...rest } = event;\n if (!Number.isFinite(ts)) return rest;\n try {\n return { ...rest, ts: new Date(ts).toISOString() };\n } catch {\n // Out-of-range epoch-ms — send the event WITHOUT a ts rather than lose the batch.\n return rest;\n }\n });\n\n/**\n * The ONE place the `/v1/events` POST is described (url + method + headers + body). Both the\n * fire-and-forget {@link reportClientEvents} and the awaitable {@link reportClientEventsAwait}\n * build their request here so there is a SINGLE definition of the events transport — no second\n * copy of the endpoint path, headers, or envelope shape to drift. Returns `null` when there is\n * nothing to send (no target / no events) or serialization throws, so callers just bail.\n *\n * It is also where the internal epoch-ms `ts` becomes the wire's ISO8601 string — see\n * {@link toWireEvents} for why the conversion belongs at this choke point.\n */\nexport const buildEventsRequest = (\n target: { serverUrl: string; apiKey?: string } | undefined,\n events: ClientEvent[],\n): { url: string; init: RequestInit } | null => {\n if (!target?.serverUrl || events.length === 0) return null;\n try {\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/v1/events`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n const body = JSON.stringify({ events: toWireEvents(events) });\n return { url, init: { method: \"POST\", headers, body } };\n } catch {\n // URL construction or JSON serialization failed — nothing to send.\n return null;\n }\n};\n\n/** What the `/v1/events` endpoint says in its 200 body. The deployed server DOES send `errors[]`,\n * each entry carrying `{index, reason, field}` — `field` names the property that failed validation\n * (it is what identified the `ts` rejection), so it is folded into the reason string here. Still\n * read defensively: an older server sends no `errors` at all. */\ntype EventsAck = { written?: number; skipped: number; reasons: string[] };\n\n/**\n * Read the `/v1/events` ACK body. Resolves `undefined` when there is nothing readable — no `.json`\n * (an old server, a bare test mock), an already-consumed body, or a hostile response object. NEVER\n * throws, and NEVER dev-gated: the `skipped` count is a RETURN VALUE for the awaitable path, not only\n * a warning, so it has to be read in production too.\n *\n * ⚠️ The body can be read exactly once, so a caller that both decides on `skipped` AND warns must do\n * both from ONE call to this.\n */\nconst readEventsAck = async (res: unknown): Promise<EventsAck | undefined> => {\n try {\n const json = (res as { json?: () => Promise<unknown> } | null | undefined)?.json;\n if (typeof json !== \"function\") return undefined;\n const body = (await Promise.resolve(json.call(res))) as\n | { written?: unknown; skipped?: unknown; errors?: unknown }\n | null\n | undefined;\n const skipped = body?.skipped;\n if (typeof skipped !== \"number\" || !Number.isFinite(skipped)) return undefined;\n const reasons = Array.isArray(body?.errors)\n ? body.errors\n .map((e) => {\n const entry = e as { reason?: unknown; field?: unknown } | null;\n const reason = entry?.reason;\n if (typeof reason !== \"string\") return undefined;\n // `field` is the whole point of a validation error — a bare \"validation_error\" sends the\n // reader hunting; \"validation_error (field: ts)\" names the property the server refused.\n const field = entry?.field;\n return typeof field === \"string\" && field.length > 0\n ? `${reason} (field: ${field})`\n : reason;\n })\n .filter((r): r is string => typeof r === \"string\")\n : [];\n return { written: typeof body?.written === \"number\" ? body.written : undefined, skipped, reasons };\n } catch {\n // Unreadable / already-consumed body / hostile object — best-effort, treat as \"no ack\".\n return undefined;\n }\n};\n\n/**\n * The DISCARDED warning text, built from what the server ACTUALLY said.\n *\n * It used to staple a cause onto a bare integer — \"the usual cause is a missing or empty session_id\".\n * Since `ensureCurrentSessionId` shipped, no kit path can emit an event without a `session_id`, so\n * that is now the LEAST likely explanation, and naming it sent every reader looking in the one place\n * the problem is not. The endpoint folds four real failures and two idempotent no-ops into one\n * integer, so unless the server volunteers reasons, the honest thing to report is the count and where\n * the reason lives.\n */\nconst describeDiscarded = (ack: EventsAck): string =>\n `[wireai] the server ACCEPTED the /v1/events POST but DISCARDED ${ack.skipped} event(s) ` +\n \"(skipped in the response body) — they are gone, not retried. The server reported: \" +\n `skipped=${ack.skipped}${ack.written !== undefined ? `, written=${ack.written}` : \"\"}` +\n (ack.reasons.length > 0\n ? `, reasons: ${ack.reasons.join(\", \")}.`\n : \". It gave no reason (the endpoint folds every rejection into one count), so check the \" +\n \"server's ingest log for this request rather than guessing.\");\n\n/** RN sets this global; absent under node/SSR. Read defensively inside {@link warnOnSkippedEvents}. */\ndeclare const __DEV__: boolean | undefined;\n\n/**\n * Read the `/v1/events` ACK body and warn (dev builds only) when the server DISCARDED events.\n *\n * The endpoint answers HTTP **200** with `{ ok, written, skipped }` — an event it refuses is counted\n * in `skipped`, never surfaced in the status code. Every send path here reads `res.ok` alone, so a\n * whole batch can evaporate behind a green response. As of 0.13.0 ALL FOUR send paths consume the ack:\n * the offline queue, session-start, the fire-and-forget POST, and the awaitable one (which also acts\n * on it — see {@link reportClientEventsAwait}).\n *\n * LOG ONLY: returns immediately, never throws, and never influences retry / dequeue / return values.\n * A response with no usable `.json` (an old server, a test mock) is silently ignored.\n *\n * DEV-GATED FIRST: the `__DEV__` check is the FIRST statement, before the body is even looked at.\n * The check used to sit inside the `.then`, so a release build parsed the JSON of every\n * persistent-path POST to build a warning no one would ever read. Nothing here runs in production.\n */\nexport const warnOnSkippedEvents = (res: unknown): void => {\n if (typeof __DEV__ === \"undefined\" || !__DEV__) return;\n if (typeof console === \"undefined\" || !console.warn) return;\n void readEventsAck(res).then((ack) => {\n if (!ack || ack.skipped <= 0) return;\n console.warn(describeDiscarded(ack));\n });\n};\n\n/**\n * POST one or more client events, fire-and-forget. A missing/invalid target, a build error,\n * a missing `fetch`, or a network failure is swallowed — the call returns immediately and the\n * request (if any) runs in the background.\n */\nexport const reportClientEvents = (\n target: ClientEventTarget | undefined,\n events: ClientEvent[],\n): void => {\n try {\n const req = buildEventsRequest(target, events);\n if (!req) return;\n void fetch(req.url, req.init)\n .then((res) => {\n // Still fire-and-forget — nothing is retried, nothing is returned. But a batch that\n // evaporated behind a 200 is exactly what this path used to make invisible, so in dev it\n // now says so, like the queue and session-start paths already did.\n warnOnSkippedEvents(res);\n })\n .catch(() => {\n // Network/transport error — analytics is best-effort, swallow.\n });\n } catch {\n // A missing `fetch` — swallow.\n }\n};\n\n/** Convenience single-event wrapper around {@link reportClientEvents}. */\nexport const reportClientEvent = (\n target: ClientEventTarget | undefined,\n event: ClientEvent,\n): void => reportClientEvents(target, [event]);\n\n/**\n * AWAITABLE sibling of {@link reportClientEvents}: POST one or more client events through the SAME\n * `/v1/events` path, but resolve only once the server has RESPONDED — so a decision re-fetch fired\n * immediately after is guaranteed to see the event in the session stream (this is the guarantee\n * `wire.track` needs before it triggers decision revalidation). Never throws: a missing/invalid\n * target, a missing `fetch`, a network error, or a non-2xx status all resolve to `false`.\n *\n * ⚠️ 0.13.0: a 2xx is NO LONGER SUFFICIENT. The endpoint answers HTTP 200 with `{ ok, written,\n * skipped }` and counts an event it refuses in `skipped`, so this used to resolve `true` for an event\n * the server had thrown away — and `wire.track` then bumped decision revalidation, making every\n * subscribed gate re-fetch against a stream the action never entered. It now reads the ack and\n * resolves `false` when the server reports a positive `skipped`.\n *\n * BACKWARD COMPATIBLE BY CONSTRUCTION: only an explicit positive `skipped` demotes a 200. An old\n * server that sends no such field, a body that cannot be parsed, or a response with no `.json` at all\n * resolves `true` exactly as before — the change can produce no false negatives.\n */\nexport const reportClientEventsAwait = async (\n target: ClientEventTarget | undefined,\n events: ClientEvent[],\n): Promise<boolean> => {\n try {\n const req = buildEventsRequest(target, events);\n if (!req) return false;\n const res = await fetch(req.url, req.init);\n if (!res || !res.ok) return false;\n // ONE body read, used for both the verdict and the dev warning — it can only be read once.\n const ack = await readEventsAck(res);\n if (!ack || ack.skipped <= 0) return true;\n if (typeof __DEV__ !== \"undefined\" && __DEV__ && typeof console !== \"undefined\" && console.warn) {\n console.warn(describeDiscarded(ack));\n }\n return false;\n } catch {\n // Unreachable / missing-fetch / network — best-effort, report failure.\n return false;\n }\n};\n\n/** Convenience single-event wrapper around {@link reportClientEventsAwait}. */\nexport const reportClientEventAwait = (\n target: ClientEventTarget | undefined,\n event: ClientEvent,\n): Promise<boolean> => reportClientEventsAwait(target, [event]);\n","/**\n * sendPreview — fire-and-forget PREFETCH of the next A2A turn, so the backend can warm\n * its generation cache during a moment the user isn't waiting.\n *\n * Two callers, both firing the SAME text the real commit will send (the backend keys the\n * preview cache on the raw message string, so a mismatch just misses harmlessly):\n * 1. InterstitialCard — its answer is always \"continue\" (SDK-wrapped `My answer is: \"continue\"`),\n * warmed while the user reads the momentum screen.\n * 2. Choice cards (Selection/ChipSelect) — warmed on selection-change with the exact\n * `I selected: ${JSON.stringify(value)}` the Continue tap will send, so the perceptibly-slow\n * first LLM question returns from cache. See OnboardingFlow.previewOnSelect.\n *\n * Contract (mirrors the A2A `message/send` shape, but a distinct `method`):\n * POST {serverUrl}/a2a\n * Authorization: Bearer {apiKey}\n * { jsonrpc:\"2.0\", id:<rand>, method:\"message/preview\",\n * params:{ message:{ role:\"user\", parts:[{ text }] }, contextId:<sessionId>,\n * metadata:{ sessionId } } }\n *\n * Fire-and-forget, exactly like reportClientEvent: never awaits, never throws into the UI —\n * a prefetch that fails just means the real turn generates normally.\n */\n\n/** Where to POST the preview. Same tenant creds as the flow (`serverUrl` + `apiKey`). */\nexport type PreviewTarget = {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/a2a` is appended. */\n serverUrl: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey: string;\n};\n\n/** What to preview: the session to warm and the message the user is about to send. */\nexport type PreviewArgs = {\n /** A2A contextId for this onboarding (the kit session id). */\n sessionId: string;\n /** The message that will be committed next (for interstitials, always \"continue\"). */\n userMessage: string;\n};\n\n/**\n * Warm the next turn's cache, fire-and-forget. A missing/invalid target, a build error,\n * a missing `fetch`, or a network failure is swallowed — the call returns immediately and\n * the request (if any) runs in the background.\n */\nexport const sendPreview = (\n target: PreviewTarget | undefined,\n { sessionId, userMessage }: PreviewArgs,\n): void => {\n if (!target?.serverUrl) return;\n try {\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/a2a`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n void fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n jsonrpc: \"2.0\",\n id: Math.floor(Math.random() * 1e9),\n method: \"message/preview\",\n params: {\n message: { role: \"user\", parts: [{ text: userMessage }] },\n contextId: sessionId,\n metadata: { sessionId },\n },\n }),\n }).catch(() => {\n // Network/transport error — prefetch is best-effort, swallow.\n });\n } catch {\n // URL construction, JSON serialization, or a missing fetch — swallow.\n }\n};\n","/**\n * permissionEvents - the canonical Wire names for a permission-priming funnel.\n *\n * Same job `purchaseEvents.ts` does for the subscription funnel and `analyticsEvent.ts` does for\n * the onboarding funnel: every app was naming these itself (`push_permission`, `NOTIF_PROMPT`,\n * `notifications_allowed`), so the same funnel read differently per tenant and no cross-app report\n * was possible. These are the ONE set of names.\n *\n * They are `app_event` `question_key` values on the wire, exactly like `WIRE_PURCHASE_EVENTS`, so\n * they are ALSO the exact strings a review / questionnaire firing trigger matches on. Never rename\n * one: a rename silently unfires every trigger configured against the old string.\n *\n * PURE + dependency-free: no React, no React Native, no transport, no imports outside the type\n * declarations - so an analytics-only bundle can carry the names without carrying a screen.\n */\nimport type { PermissionStage, WirePermissionKind, WirePermissionStatus } from \"./types\";\n\nexport const WIRE_PERMISSION_EVENTS = {\n /** The priming screen became visible. The denominator for every rate below. */\n screenShown: \"wire_permission_screen_shown\",\n /** The user tapped the primary, so the OS dialog is about to open. The rationale worked. */\n primerAccepted: \"wire_permission_primer_accepted\",\n /** The OS granted it. */\n granted: \"wire_permission_granted\",\n /** The OS refused it (a permanently blocked answer reports here too, with `status: \"blocked\"`). */\n denied: \"wire_permission_denied\",\n /** The user took the secondary. The one native prompt was NOT spent. */\n skipped: \"wire_permission_skipped\",\n /** A blocked user was redirected to the OS settings page. */\n settingsOpened: \"wire_permission_settings_opened\",\n} as const;\n\nexport type WirePermissionEventName =\n (typeof WIRE_PERMISSION_EVENTS)[keyof typeof WIRE_PERMISSION_EVENTS];\n\n/** The canonical event name for a stage. Exhaustive over the union (a new stage is a compile error). */\nexport const permissionEventName = (stage: PermissionStage): WirePermissionEventName => {\n switch (stage) {\n case \"shown\":\n return WIRE_PERMISSION_EVENTS.screenShown;\n case \"accepted\":\n return WIRE_PERMISSION_EVENTS.primerAccepted;\n case \"granted\":\n return WIRE_PERMISSION_EVENTS.granted;\n case \"denied\":\n return WIRE_PERMISSION_EVENTS.denied;\n case \"skipped\":\n return WIRE_PERMISSION_EVENTS.skipped;\n case \"settings\":\n return WIRE_PERMISSION_EVENTS.settingsOpened;\n default: {\n const _exhaustive: never = stage;\n return _exhaustive;\n }\n }\n};\n\n/**\n * The small, non-PII props that ride a permission event. `permission` is always present so one\n * funnel can be sliced per permission; `status` only appears when the OS actually answered, which\n * is what keeps a `blocked` refusal distinguishable from a plain `denied` without a second event.\n */\nexport const permissionEventProps = (\n permission: WirePermissionKind,\n status?: WirePermissionStatus,\n): Record<string, string> => (status ? { permission, status } : { permission });\n\n/**\n * Normalize whatever the host's `request` / `getStatus` actually returned.\n *\n * A native permission bridge is the host's code, and hosts return `\"undetermined\"`, `true`, or a\n * whole Expo response object. Anything the kit does not recognise is treated as `denied`: it is the\n * only reading that cannot invent a grant, and every outcome continues the flow anyway.\n */\nexport const normalizePermissionStatus = (value: unknown): WirePermissionStatus =>\n value === \"granted\" || value === \"denied\" || value === \"blocked\" ? value : \"denied\";\n","/**\n * haptics.ts — the physical half of the kit's feedback layer: a tap you feel.\n *\n * `expo-haptics` is an OPTIONAL peer, loaded lazily via a guarded dynamic import so the\n * core kit never depends on it — the exact contract `reviews/storeReview.ts` uses for\n * `expo-store-review`. A host that has not installed it (or a platform without a taptic\n * engine) simply feels nothing: every call resolves to `false` and NOTHING throws. A\n * missed haptic must never break a gate.\n *\n * The module is deliberately fire-and-forget. Callers `void play(...)` from a press\n * handler and never await it, so a slow/absent native module can't delay a tap.\n *\n * Tones map to intent, not to a device API:\n * • \"selection\" — a value changed (picking a star).\n * • \"light\" — a light impact (moving to the next question).\n * • \"success\" — a task completed (the submit payoff, under the done check).\n *\n * NOT gated on reduce-motion: `prefers-reduced-motion` is a VESTIBULAR accommodation about\n * on-screen movement. Haptics are a non-visual channel and are often the accessibility\n * affordance a reduce-motion user relies on, so silencing them here would be the wrong\n * trade. Hosts that want no haptics leave `expo-haptics` uninstalled.\n */\n\n/** What a haptic is for, in product terms. Mapped to the native API inside `play`. */\nexport type HapticTone = \"selection\" | \"light\" | \"success\";\n\n/**\n * Play a haptic when the optional peer is available. Resolves `true` when a haptic was\n * actually requested, `false` when the peer is absent or the native call failed. NEVER\n * throws and never rejects — the result is advisory (tests/analytics), not control flow.\n */\nexport const play = async (tone: HapticTone): Promise<boolean> => {\n try {\n const mod = await import(\"expo-haptics\");\n if (!mod) return false;\n if (tone === \"selection\") {\n await mod.selectionAsync();\n return true;\n }\n if (tone === \"light\") {\n await mod.impactAsync(mod.ImpactFeedbackStyle.Light);\n return true;\n }\n await mod.notificationAsync(mod.NotificationFeedbackType.Success);\n return true;\n } catch {\n // Peer not installed, unsupported platform, or the native call failed — stay silent.\n return false;\n }\n};\n\n/**\n * Fire-and-forget `play`. The call site reads as the intent (\"a star was tapped\"), and a\n * rejected/absent native module can never surface as an unhandled rejection.\n */\nexport const playHaptic = (tone: HapticTone): void => {\n void play(tone);\n};\n","/**\n * warnInDev — the ONE developer-warning primitive.\n *\n * The kit warns a developer in four places (the onboarding host, the env-config helper, the analytics\n * façade, the current-session registry) and until 0.13.0 each carried its own copy of the same five\n * lines. Three were byte-identical; the fourth differed only by returning whether it actually warned.\n * Four copies of a guard is four chances for one of them to drift out of the `__DEV__` gate, which is\n * the failure that matters: a warning that runs in production is a string built for nobody.\n *\n * ON THE TREE-SHAKING NOTE THIS REPLACES: `analytics/currentSession` used to justify its copy as\n * keeping the module import-free for the tree-shaken `./analytics` bundle. That rationale had already\n * lapsed — the module imports `makeSessionId` from `./reportClientEvent` — and this module has no\n * imports of its own, so it adds one leaf to the graph and nothing to the bundle. The `treeShake`\n * canary still holds the real guarantee (the analytics graph reaches no UI module).\n */\n\n/** RN sets this global; absent under node/SSR. Read defensively, never assumed. */\ndeclare const __DEV__: boolean | undefined;\n\n/**\n * Emit a one-line developer warning, but ONLY in a dev build (RN `__DEV__`). No-op in prod/tests.\n *\n * Returns whether it ACTUALLY warned, which a caller holding a once-flag must honour: marking\n * \"already warned\" after a no-op would burn the single warning in production, and the one dev build\n * that needed it would then run silent.\n */\nexport const warnInDev = (message: string): boolean => {\n if (typeof __DEV__ !== \"undefined\" && __DEV__ && typeof console !== \"undefined\" && console.warn) {\n console.warn(message);\n return true;\n }\n return false;\n};\n","/**\n * PermissionCard - the priming screen that stands in front of an OS permission dialog.\n *\n * THE PRIMING PATTERN, which is the entire point: the OS dialog opens from the primary press\n * handler and from nowhere else. There is no mount effect, no auto-fire, no timer, and no code path\n * from render to `request()`. iOS grants an app exactly ONE native notification prompt for its\n * whole lifetime, so this cheap in-app screen spends first and only forwards the users who said\n * yes. The secondary (\"Maybe later\") advances the flow with the prompt still unspent.\n *\n * THREE PRIMARY ACTIONS, picked from the non-prompting `getStatus` probe (never from `request`):\n * • ask (the default, and the only branch that can reach `request`)\n * • settings (status `blocked`: the OS would show nothing, so the only route left is Settings)\n * • continue (already granted, or a host that supplied no `request` at all - the kit declines to\n * fabricate a prompt it has no way to open)\n *\n * IT IS NOT A QUESTION. It sends nothing to the backend, appends nothing to the thread, and mints\n * no `key` / `slot_id`, so `deriveAnswers` and every completion semantic are untouched. Every\n * outcome, including a denial, continues the flow.\n *\n * Motion: the same register as the other value beats. The illustration springs in\n * (STATUS_POP_SPRING, the StatusCard glyph pop) and the copy rises behind it on the interstitial\n * head stagger. Reduce motion: final frame at once, like every other card.\n *\n * Registered as a `WireAIComponent` so a later server-emitted placement (AI-chosen timing) renders\n * through the same component with no rewrite. It is deliberately NOT in `onboardingComponents`:\n * that array is what the device ADVERTISES as renderable, and a backend told it may emit this card\n * could emit one for a host that wired no `request`.\n */\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { bodyStyle, headingStyle } from \"../theme/typography\";\nimport { useIllustration } from \"../components/Illustration\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\nimport {\n INTERSTITIAL_HEAD_MS,\n INTERSTITIAL_HEAD_STAGGER_MS,\n STATUS_POP_SCALE_FROM,\n STATUS_POP_SPRING,\n WIRE_BEZIER,\n scaledMs,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\nimport { normalizePermissionStatus } from \"../permissions/permissionEvents\";\nimport type {\n PermissionStage,\n WirePermissionOutcome,\n WirePermissionStatus,\n} from \"../permissions/types\";\nimport { playHaptic } from \"../haptics/haptics\";\nimport { warnInDev } from \"../utils/warnInDev\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\nconst RISE_PX = 10;\n\n/** The name the card is registered under, and the `component` stamped on its events. */\nexport const PERMISSION_CARD_NAME = \"PermissionCard\";\n\n/**\n * How long a host's `request` may stay outstanding before the kit hands the controls back.\n *\n * DELIBERATELY GENEROUS. This is not a race against the user: someone reading an OS permission\n * dialog, switching apps mid-prompt, or hitting a slow native bridge is doing nothing wrong, and a\n * short ceiling would advance the flow underneath a dialog that is still open. It exists for one\n * failure only, a `request` that never settles at all (a swallowed native callback, a promise\n * nobody resolves), which would otherwise leave the user on a screen whose buttons are all\n * disabled. On expiry the kit records NO outcome, because a pending request is not a denial.\n */\nexport const REQUEST_WATCHDOG_MS = 90_000;\n\n/**\n * The COPY half of the card, i.e. everything a server could legitimately author. The capability\n * half (`request` / `getStatus` / `openSettings`) is host-injected and deliberately absent here:\n * a schema field can only ever carry data, never a function, and the kit imports no native module.\n */\nconst schema = z.object({\n permission: z\n .string()\n .describe(\"Which OS permission this screen primes, e.g. 'notifications'\"),\n title: z.string().describe(\"Headline for the ask\"),\n message: z.string().describe(\"Why the app needs it, in the user's terms\"),\n primaryLabel: z.string().describe(\"Primary button, the only control that can open the OS dialog\"),\n secondaryLabel: z.string().describe(\"Secondary button, advances without spending the OS prompt\"),\n blockedTitle: z.string().optional().describe(\"Headline once the permission is permanently refused\"),\n blockedMessage: z.string().optional().describe(\"Rationale for the settings route\"),\n settingsLabel: z.string().optional().describe(\"Primary button label on the blocked route\"),\n continueLabel: z.string().optional().describe(\"Primary button label when there is nothing to ask\"),\n illustration: z\n .string()\n .optional()\n .describe(\"Name of an app-provided illustration (defaults to the permission name)\"),\n});\n\nexport type PermissionCardProps = z.infer<typeof schema> &\n Partial<InjectedProps> & {\n /** THE ONLY function that can open an OS dialog. Called from the primary handler alone. */\n request?: () => Promise<WirePermissionStatus>;\n /** NON-PROMPTING status read. Decides which primary action is offered, nothing else. */\n getStatus?: () => Promise<WirePermissionStatus>;\n /** Open the OS settings page. Only reachable on the `blocked` route. */\n openSettings?: () => void | Promise<void>;\n /** Reports each moment for analytics. Never control flow. */\n onStage?: (stage: PermissionStage, status?: WirePermissionStatus) => void;\n /** Fires exactly once, with the outcome this screen produced. The flow advances on it. */\n onSettled?: (outcome: WirePermissionOutcome) => void;\n };\n\n/** Which action the primary button performs. `ask` is the only one that can reach `request`. */\ntype PrimaryAction = \"ask\" | \"settings\" | \"continue\";\n\nconst _PermissionCard: React.FC<PermissionCardProps> = ({\n permission,\n title,\n message,\n primaryLabel,\n secondaryLabel,\n blockedTitle,\n blockedMessage,\n settingsLabel,\n continueLabel,\n illustration,\n request,\n getStatus,\n openSettings,\n onStage,\n onSettled,\n}) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const art = useIllustration(illustration ?? permission);\n // The probed status. `undefined` means \"not known\", which is the ASK state: the kit never\n // assumes a grant it has not been told about.\n const [status, setStatus] = useState<WirePermissionStatus | undefined>(undefined);\n const [busy, setBusy] = useState(false);\n // One settle per mount. The card is keyed by screen id, so this is one settle per screen. It is\n // also what makes a late `request` settlement a no-op, since `finish` reaches `settle`\n // synchronously (see `handlePrimary`).\n const settledRef = useRef(false);\n // `accepted` is a per-screen boolean, so `accepted / shown` stays a readable rate.\n const acceptedRef = useRef(false);\n const watchdogRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const clearWatchdog = useCallback(() => {\n if (watchdogRef.current) {\n clearTimeout(watchdogRef.current);\n watchdogRef.current = null;\n }\n }, []);\n // A pending watchdog must never outlive the screen (it would setState on an unmounted card).\n useEffect(() => clearWatchdog, [clearWatchdog]);\n\n // Host callbacks held in refs so the mount-once effects below stay mount-once no matter how a\n // host passes them (the documented usage is an INLINE `permissionScreens={[...]}`, which mints a\n // fresh closure for every one of them on every render).\n const onStageRef = useRef(onStage);\n onStageRef.current = onStage;\n const onSettledRef = useRef(onSettled);\n onSettledRef.current = onSettled;\n const getStatusRef = useRef(getStatus);\n getStatusRef.current = getStatus;\n\n // `shown` fires once per mount, ref-guarded so StrictMode's dev double-invoke cannot\n // double-count the denominator every rate in this funnel is measured against.\n const shownRef = useRef(false);\n useEffect(() => {\n if (shownRef.current) return;\n shownRef.current = true;\n onStageRef.current?.(\"shown\");\n }, []);\n\n // The status probe, MOUNT-ONCE. `getPermissionsAsync()` and its equivalents READ, they never\n // prompt - which is exactly why `request` is not called here and why this effect may exist at\n // all. All it decides is which primary action the screen offers.\n useEffect(() => {\n const probe = getStatusRef.current;\n if (!probe) return;\n let cancelled = false;\n try {\n void Promise.resolve(probe())\n .then((value) => {\n if (!cancelled) setStatus(normalizePermissionStatus(value));\n })\n .catch(() => {\n // A host probe that throws just leaves the screen in its ask state.\n });\n } catch {\n // A synchronously-throwing probe, same treatment.\n }\n return () => {\n cancelled = true;\n };\n }, []);\n\n // A host that configured a screen with no `request` gets a screen that cannot ask. The kit says\n // so instead of rendering a button that silently does nothing (dev only, never a throw).\n const requestRef = useRef(request);\n requestRef.current = request;\n useEffect(() => {\n if (requestRef.current) return;\n warnInDev(\n `[wireai] <WireOnboarding> got a permission screen for \"${permission}\" with no \\`request\\` ` +\n \"function, so it cannot open the OS dialog and renders as a plain continue. Pass \" +\n \"request: () => Promise<'granted' | 'denied' | 'blocked'> (5 lines around \" +\n \"expo-notifications, see the README).\",\n );\n }, [permission]);\n\n const settle = useCallback((outcome: WirePermissionOutcome) => {\n if (settledRef.current) return;\n settledRef.current = true;\n clearWatchdog();\n onSettledRef.current?.(outcome);\n }, [clearWatchdog]);\n\n const primaryAction: PrimaryAction =\n status === \"blocked\" ? \"settings\" : status === \"granted\" || !request ? \"continue\" : \"ask\";\n\n const handlePrimary = useCallback(() => {\n if (settledRef.current || busy) return;\n\n if (primaryAction === \"settings\") {\n onStageRef.current?.(\"settings\", \"blocked\");\n try {\n void Promise.resolve(openSettings?.()).catch(() => {});\n } catch {\n // A settings redirect that fails is not a reason to trap the user on this screen.\n }\n settle(\"blocked\");\n return;\n }\n\n if (primaryAction === \"continue\") {\n // Already granted (nothing to ask), or no `request` was supplied. Report the state as it is;\n // never report a grant this screen did not produce as anything other than what it is.\n if (status === \"granted\") {\n onStageRef.current?.(\"granted\", \"granted\");\n settle(\"granted\");\n } else {\n onStageRef.current?.(\"skipped\");\n settle(\"skipped\");\n }\n return;\n }\n\n // THE ONE PATH TO THE OS DIALOG, reachable from this press handler only.\n //\n // `accepted` is a per-screen boolean, not a per-tap counter: the screen is shown once, and\n // `accepted / shown` is the rate that says whether the rationale copy works. A second tap after\n // the watchdog re-armed the UI would push that rate past 100%, so it is emitted once.\n if (!acceptedRef.current) {\n acceptedRef.current = true;\n onStageRef.current?.(\"accepted\");\n }\n setBusy(true);\n // FIRST SETTLEMENT WINS, and `settledRef` is the whole mechanism. The watchdog below can hand\n // the UI back while a `request` is still outstanding, so a second tap can put a SECOND one in\n // flight, and the original can answer late. What decides between them is that this function\n // runs STRAIGHT THROUGH to `settle` with no await in between: the first settlement to arrive\n // has already flipped that ref by the time any later one is invoked, so the later one returns\n // on the line below. The flow advances once and each stage event is emitted once. The same ref\n // is why a settlement landing after the user skipped changes nothing.\n const finish = (value: unknown) => {\n if (settledRef.current) return;\n clearWatchdog();\n const resolved = normalizePermissionStatus(value);\n setBusy(false);\n setStatus(resolved);\n if (resolved === \"granted\") {\n // A light success tap on the grant, through the kit's optional-peer haptics: a host\n // without `expo-haptics` simply feels nothing and nothing throws.\n playHaptic(\"success\");\n onStageRef.current?.(\"granted\", \"granted\");\n } else {\n onStageRef.current?.(\"denied\", resolved);\n }\n settle(resolved);\n };\n\n // THE WATCHDOG, and what it deliberately does NOT do.\n //\n // A host `request` that never settles (a native module that swallows its callback, a promise\n // that is never resolved) would otherwise BRICK the screen: `busy` disables both buttons, the\n // secondary re-guards on it, and nothing upstream rescues a rendered card. Dead end, and\n // `onComplete` never fires.\n //\n // So the ceiling exists to un-brick a HOST BUG, never to race the user. A person can sit on an\n // OS permission dialog for a long time, so a short ceiling that recorded `denied` on expiry\n // would advance the flow underneath a dialog that is still open and log an outcome the user\n // never gave. On expiry this therefore fabricates NOTHING: no outcome, no event, no settle. It\n // only hands the controls back so the user can tap again or skip, and says so in dev.\n clearWatchdog();\n watchdogRef.current = setTimeout(() => {\n watchdogRef.current = null;\n if (settledRef.current) return;\n setBusy(false);\n warnInDev(\n `[wireai] the \\`request\\` for the \"${permission}\" permission screen has not settled after ` +\n `${Math.round(REQUEST_WATCHDOG_MS / 1000)}s, so the kit handed the controls back rather ` +\n \"than leaving the user on a dead-end screen. It recorded NO outcome, because a pending \" +\n \"request is not a denial. Make sure your request resolves to 'granted' | 'denied' | \" +\n \"'blocked' on every branch, including the one where the user dismisses the OS dialog.\",\n );\n }, REQUEST_WATCHDOG_MS);\n\n try {\n void Promise.resolve(request?.()).then(finish, () => finish(\"denied\"));\n } catch {\n // A synchronously-throwing request is a denial, never a stuck screen.\n finish(\"denied\");\n }\n }, [busy, primaryAction, status, request, openSettings, settle, clearWatchdog, permission]);\n\n const handleSecondary = useCallback(() => {\n if (settledRef.current || busy) return;\n onStageRef.current?.(\"skipped\");\n settle(\"skipped\");\n }, [busy, settle]);\n\n // Art springs in, copy rises behind it (final frame at once under reduce motion).\n const popT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const titleT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const bodyT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n useEffect(() => {\n if (reduced) {\n popT.setValue(1);\n titleT.setValue(1);\n bodyT.setValue(1);\n return;\n }\n const rise = (value: Animated.Value, delay: number) =>\n Animated.timing(value, {\n toValue: 1,\n duration: scaledMs(INTERSTITIAL_HEAD_MS),\n delay,\n easing: easeWire,\n useNativeDriver: true,\n });\n const anims = [\n Animated.spring(popT, {\n toValue: 1,\n friction: STATUS_POP_SPRING.friction,\n tension: STATUS_POP_SPRING.tension,\n useNativeDriver: true,\n }),\n rise(titleT, scaledMs(INTERSTITIAL_HEAD_STAGGER_MS)),\n rise(bodyT, scaledMs(INTERSTITIAL_HEAD_STAGGER_MS * 2)),\n ];\n anims.forEach((a) => a.start());\n return () => anims.forEach((a) => a.stop());\n }, [reduced, popT, titleT, bodyT]);\n\n const popScale = popT.interpolate({\n inputRange: [0, 1],\n outputRange: [STATUS_POP_SCALE_FROM, 1],\n });\n const riseStyle = (value: Animated.Value) => ({\n opacity: value,\n transform: [\n { translateY: value.interpolate({ inputRange: [0, 1], outputRange: [RISE_PX, 0] }) },\n ],\n });\n\n const blocked = status === \"blocked\";\n const shownTitle = blocked ? (blockedTitle ?? title) : title;\n const shownMessage = blocked ? (blockedMessage ?? message) : message;\n const primaryTitle =\n primaryAction === \"settings\"\n ? (settingsLabel ?? primaryLabel)\n : primaryAction === \"continue\"\n ? (continueLabel ?? primaryLabel)\n : primaryLabel;\n // Nothing left to decline once the permission is already granted.\n const showSecondary = status !== \"granted\";\n\n return (\n <CardLayout\n align=\"center\"\n footer={\n <View style={[styles.footer, { gap: t.spacing.sm }]}>\n <Button title={primaryTitle} onPress={handlePrimary} variant=\"primary\" disabled={busy} />\n {showSecondary ? (\n <Button\n title={secondaryLabel}\n onPress={handleSecondary}\n variant=\"outline\"\n disabled={busy}\n />\n ) : null}\n </View>\n }\n >\n <View style={[styles.center, { gap: t.spacing.md }]}>\n {art ? (\n <Animated.View\n style={[styles.art, { opacity: popT, transform: [{ scale: popScale }] }]}\n >\n {art}\n </Animated.View>\n ) : null}\n\n <Animated.View style={riseStyle(titleT)}>\n <Text style={[headingStyle(t.fonts), { color: t.colors.text, textAlign: \"center\" }]}>\n {shownTitle}\n </Text>\n </Animated.View>\n\n <Animated.View style={riseStyle(bodyT)}>\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: \"center\" }]}>\n {shownMessage}\n </Text>\n </Animated.View>\n </View>\n </CardLayout>\n );\n};\n\n/** The typed component the flow renders directly (host-injected placement). */\nexport const PermissionCardView = React.memo(_PermissionCard);\n\n/**\n * The SDK registration object, so a server-emitted placement can adopt this exact screen later.\n * Not part of `onboardingComponents` on purpose - see the file header.\n */\nexport const PermissionCard: WireAIComponent = {\n name: PERMISSION_CARD_NAME,\n description:\n \"A priming screen shown BEFORE an OS permission dialog: it explains why the app wants the permission and asks only on the primary tap. Never first, never last. The user is never blocked by it: the secondary advances the flow with the OS prompt unspent.\",\n component: PermissionCardView as WireAIComponent[\"component\"],\n propsSchema: schema,\n};\n\nconst styles = StyleSheet.create({\n center: { width: \"100%\", alignItems: \"center\", justifyContent: \"center\" },\n art: { alignItems: \"center\", justifyContent: \"center\" },\n footer: { width: \"100%\", alignItems: \"center\" },\n});\n","/**\n * placement - WHERE an injected permission screen lands in a stream nobody knows the length of.\n *\n * The card stream is server-driven: the backend decides how many questions this user gets, and the\n * count differs per user and per run. So a placement is never an index into a known list; it is a\n * predicate evaluated against the card the flow is ABOUT to render, on every turn.\n *\n * THE CLAMP is the whole reason this is a function and not a comparison. `{ afterCard: 4 }` against\n * a stream that ended after 3 would simply never fire, and \"the screen silently never showed\" is\n * the exact failure a host cannot see. So an unreached target degrades to `\"beforeEnd\"`: the\n * terminal card is the last position where the screen can still exist, so that is where it goes.\n *\n * PURE, no React, no React Native - the placement math is the part worth unit-testing.\n */\nimport type { PermissionPlacement, PermissionScreenConfig } from \"./types\";\n\n/** Where a screen sits when the host does not say. High intent, and it can never be clamped away. */\nexport const DEFAULT_PERMISSION_PLACEMENT: PermissionPlacement = \"beforeEnd\";\n\n/** The flow position a placement is resolved against. */\nexport type FlowPosition = {\n /** 0-based index of the card about to render. `-1` when no card has arrived yet. */\n cardIndex: number;\n /** Whether that card is the terminal recap, i.e. the flow's last screen. */\n isTerminal: boolean;\n};\n\n/** `afterCard` from a host is arbitrary input: floor it, floor it at 0, and never let NaN through. */\nexport const normalizeAfterCard = (value: number): number =>\n Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;\n\n/** The 0-based card index a placement targets. `\"beforeEnd\"` has none, it rides `isTerminal`. */\nconst targetIndex = (placement: PermissionPlacement): number | undefined => {\n if (placement === \"beforeEnd\") return undefined;\n if (placement === \"start\") return 0;\n return normalizeAfterCard(placement.afterCard);\n};\n\n/**\n * Is a screen with this placement due at this position?\n *\n * `>=` rather than `===` on purpose: due-ness is re-evaluated every render and a screen is settled\n * the moment it is answered, so a target the flow has already passed (because a screen ahead of it\n * in the array was on screen for those turns) still fires instead of being skipped forever.\n */\nexport const isPermissionDue = (\n placement: PermissionPlacement,\n position: FlowPosition,\n): boolean => {\n if (position.cardIndex < 0) return false;\n const target = targetIndex(placement);\n // \"beforeEnd\", or an `afterCard` the stream ended before reaching: the terminal card is the\n // last chance, so this is where the clamp lands.\n if (target === undefined) return position.isTerminal;\n return position.cardIndex >= target || position.isTerminal;\n};\n\n/**\n * The stable id a screen is remembered by across a resume. Defaults to `<permission>:<index>`,\n * which is right until the array is reordered - hence the documented `id` escape hatch.\n */\nexport const permissionScreenId = (screen: PermissionScreenConfig, index: number): string =>\n screen.id ?? `${screen.permission}:${index}`;\n\n/** A due screen and the id it is remembered by. */\nexport type DuePermissionScreen = { screen: PermissionScreenConfig; id: string };\n\n/**\n * The FIRST configured screen that is due here and has not already been settled in this session.\n * One at a time, in array order, so two screens due at the same position queue rather than collide.\n */\nexport const selectDuePermissionScreen = (\n screens: readonly PermissionScreenConfig[] | undefined,\n settled: readonly string[],\n position: FlowPosition,\n): DuePermissionScreen | undefined => {\n if (!screens || screens.length === 0) return undefined;\n for (let index = 0; index < screens.length; index++) {\n const screen = screens[index];\n if (!screen) continue;\n const id = permissionScreenId(screen, index);\n if (settled.includes(id)) continue;\n if (isPermissionDue(screen.placement ?? DEFAULT_PERMISSION_PLACEMENT, position)) {\n return { screen, id };\n }\n }\n return undefined;\n};\n","/**\n * permissionCopy - the rationale a priming screen shows, and the kit-quality defaults behind it.\n *\n * Same job the `copy` prop does for the loaders: the kit ships English that is good enough to\n * ship as-is, and a host overrides any single line without having to restate the rest.\n *\n * PURE, no React, no React Native - so the resolution is unit-testable and the same function can\n * later resolve copy a server sent.\n */\nimport type { WirePermissionKind } from \"./types\";\n\n/** Every string a permission screen can render. Both states (the ask and the blocked route). */\nexport type PermissionScreenCopy = {\n /** Headline for the ask. */\n title: string;\n /** The rationale. The one thing that decides whether the primary gets tapped. */\n message: string;\n /** Primary button. Tapping it is the ONLY thing that can open the OS dialog. */\n primaryLabel: string;\n /** Secondary button. Advances the flow and does NOT spend the one native prompt. */\n secondaryLabel: string;\n /** Headline once the OS says the permission is permanently refused. */\n blockedTitle: string;\n /** Rationale for the blocked state, where the only remaining route is the settings app. */\n blockedMessage: string;\n /** Primary button on the blocked route. */\n settingsLabel: string;\n /** Primary button when there is nothing left to ask for (already granted, or no `request`). */\n continueLabel: string;\n};\n\n/**\n * The notification default. Written to the same bar as the kit's other shipped copy: it names the\n * benefit in the user's terms and promises a limit, because \"we would like to send you\n * notifications\" is exactly the sentence that spends the one iOS prompt on a no.\n */\nexport const NOTIFICATIONS_PERMISSION_COPY: PermissionScreenCopy = {\n title: \"Want a nudge at the right moment?\",\n message:\n \"Turn notifications on and we will remind you when it actually helps. No daily noise, and you can turn them off any time.\",\n primaryLabel: \"Enable notifications\",\n secondaryLabel: \"Maybe later\",\n blockedTitle: \"Notifications are switched off\",\n blockedMessage:\n \"Notifications are turned off for this app, so we cannot ask from here. You can switch them back on in Settings.\",\n settingsLabel: \"Open settings\",\n continueLabel: \"Continue\",\n};\n\n/** The fallback for any permission the kit ships no copy for. A host overriding `copy` replaces it. */\nexport const GENERIC_PERMISSION_COPY: PermissionScreenCopy = {\n title: \"One quick permission\",\n message: \"We need your permission for this part to work. You can change it any time.\",\n primaryLabel: \"Allow\",\n secondaryLabel: \"Maybe later\",\n blockedTitle: \"Permission is switched off\",\n blockedMessage:\n \"This permission is turned off for this app, so we cannot ask from here. You can switch it back on in Settings.\",\n settingsLabel: \"Open settings\",\n continueLabel: \"Continue\",\n};\n\n/** The kit's shipped defaults, by permission. Anything not listed falls back to the generic set. */\nexport const DEFAULT_PERMISSION_COPY: Record<string, PermissionScreenCopy> = {\n notifications: NOTIFICATIONS_PERMISSION_COPY,\n};\n\n/**\n * The kit default for `permission`, with the host's overrides applied on top.\n *\n * An override key whose value is `undefined` is IGNORED rather than allowed to blank the default:\n * hosts build this object from their i18n layer, and a missing translation resolving to `undefined`\n * would otherwise render an empty button.\n */\nexport const resolvePermissionCopy = (\n permission: WirePermissionKind,\n overrides?: Partial<PermissionScreenCopy>,\n): PermissionScreenCopy => {\n const base = DEFAULT_PERMISSION_COPY[permission] ?? GENERIC_PERMISSION_COPY;\n if (!overrides) return base;\n const merged: PermissionScreenCopy = { ...base };\n for (const key of Object.keys(overrides) as Array<keyof PermissionScreenCopy>) {\n const value = overrides[key];\n if (typeof value === \"string\" && value.length > 0) merged[key] = value;\n }\n return merged;\n};\n","/**\n * OnboardingFlow — the inner engine. Mirrors the proven production-app usage of the SDK\n * (useWireAIThread + useWireAIAction + ComponentRenderer) and layers on the kit's\n * shell, progress, and per-step validators.\n *\n * Lifecycle per turn:\n * 1. Auto-send `startMessage` once → backend returns the first card.\n * 2. Show LoadingBlock until the first card arrives AND between every turn\n * (while `isLoading`); on error/timeout, auto-retry up to `maxRetries`, then\n * degrade to the host's static `fallbackFlow` (preferred), else `onError`, else\n * an inline ErrorBlock — so a generation failure never breaks onboarding.\n * 3. Render the latest card inside OnboardingScaffold. The progress bar follows\n * an asymptotic curve of the step index — it never reveals a total.\n * 4. Before any answer is sent, if the current screen's question key has a\n * validator, run it; on failure show the error inline and DON'T advance.\n * 5. On the terminal StatusCard, show CompletionView (the recap of what the app\n * will do for the user) and fire onComplete only when they tap its CTA.\n *\n * Lifecycle events (started / per-turn / error) are surfaced via `onEvent` so a\n * host can keep its analytics even though the kit owns the thread loop.\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n ComponentRenderer,\n useWireAIAction,\n useWireAIThread,\n type Message,\n} from \"wireai-rn\";\nimport { OnboardingScaffold } from \"./components/OnboardingScaffold\";\nimport { LoadingBlock } from \"./components/LoadingBlock\";\nimport { LoadingScreen } from \"./components/LoadingScreen\";\nimport { ErrorBlock } from \"./components/ErrorBlock\";\nimport { CompletionView } from \"./components/CompletionView\";\nimport { CardHandoff } from \"./components/CardHandoff\";\nimport { deriveAnswers } from \"./utils/deriveAnswers\";\nimport { readProgress } from \"./utils/readProgress\";\nimport { reportClientEvent, type ClientEventTarget } from \"./analytics/reportClientEvent\";\nimport { sendPreview } from \"./analytics/sendPreview\";\nimport { PermissionCardView, PERMISSION_CARD_NAME } from \"./cards/PermissionCard\";\nimport { permissionEventName, permissionEventProps } from \"./permissions/permissionEvents\";\nimport { selectDuePermissionScreen } from \"./permissions/placement\";\nimport { resolvePermissionCopy } from \"./permissions/permissionCopy\";\nimport type {\n PermissionScreenConfig,\n PermissionStage,\n WirePermissionKind,\n WirePermissionOutcome,\n WirePermissionStatus,\n} from \"./permissions/types\";\nimport type { DeviceContext } from \"./device/deviceContext\";\nimport type { OnboardingCopy, OnboardingEvent, OnboardingResult, StepValidator } from \"./types\";\n\ntype OnboardingFlowProps = {\n validators?: Record<string, StepValidator>;\n onComplete: (result: OnboardingResult) => void;\n onSkip?: () => void;\n onError?: (err: unknown) => void;\n onEvent?: (event: OnboardingEvent) => void;\n copy?: Partial<OnboardingCopy>;\n approxScreens?: number;\n startMessage: string;\n startTimeoutMs: number;\n /** Static onboarding rendered when the AI flow fails and retries are exhausted. */\n fallbackFlow?: React.ReactNode;\n /** Consecutive failures to auto-retry before degrading. */\n maxRetries: number;\n /** Where to POST device-only client events (`dropped`). Omit to disable reporting. */\n reportTarget?: ClientEventTarget;\n /** Session id shared with the backend (A2A contextId), so `dropped` correlates. */\n sessionId: string;\n /**\n * Device snapshot + host-injected user context, attached to every client event so the\n * backend can segment the funnel by device. Old servers ignore the extra fields.\n */\n clientContext?: {\n device?: DeviceContext;\n userContext?: Record<string, string | number | boolean>;\n /** The host's opaque user id (see WireOnboarding `userId`), rides `dropped`/`client_fallback`. */\n userId?: string;\n };\n /**\n * True when `sessionId` was restored from persisted storage (app killed mid-flow).\n * The kickoff then sends the skip sentinel instead of `startMessage` — the server\n * would record the literal start text as the ANSWER to the pending question, while\n * the sentinel advances one card recording nothing — and fires `resumed` instead of\n * `started` so host funnels don't double-count the session.\n */\n resumed?: boolean;\n /**\n * Host-declared permission screens injected into this server-driven stream. See\n * `permissions/types.ts`: the OS dialog is only ever reached from the primary tap.\n */\n permissionScreens?: PermissionScreenConfig[];\n /**\n * Screen ids already settled in THIS session, restored from `storage` by WireOnboarding so an\n * app kill mid-flow does not re-ask. Empty (the default) means \"nothing settled yet\".\n */\n settledPermissions?: readonly string[];\n /**\n * True while that restore is still in flight. Permission screens are suppressed until it lands,\n * because showing one before the record is read is exactly the re-ask the record prevents. The\n * read is short (one storage get, timeout-capped) and cannot outlive the first card's round trip\n * in practice, so this normally never shows up as a delay.\n */\n permissionsPending?: boolean;\n /** Persist one settled screen id (fire-and-forget; WireOnboarding owns the storage). */\n onPermissionSettled?: (id: string, outcome: WirePermissionOutcome) => void;\n};\n\n// The kit's per-question Skip sends this sentinel; the backend skips ONE question\n// (advances one card, no answer recorded). Must match the backend's SKIP_ONE_SENTINEL.\nconst SKIP_ONE_SENTINEL = \"__wireai_skip__\";\n\n// Callbacks that carry the user's ANSWER (and so must pass validation first).\nconst ANSWER_CALLBACKS = [\"onSubmit\", \"onSelect\", \"onConfirm\", \"onPress\"] as const;\n\nexport const DEFAULT_COPY: OnboardingCopy = {\n startingTitle: \"Getting started…\",\n startingHint: \"Setting up your onboarding\",\n restoringTitle: \"Picking up where you left off…\",\n restoringHint: \"Restoring your session\",\n thinkingTitle: \"Personalizing…\",\n thinkingHint: \"Tailoring your next question\",\n checkingTitle: \"Checking…\",\n checkingHint: \"One moment\",\n completeTitle: \"You're all set\",\n completeCta: \"Let's go\",\n};\n\nexport const OnboardingFlow: React.FC<OnboardingFlowProps> = ({\n validators,\n onComplete,\n onError,\n onEvent,\n copy,\n approxScreens,\n startMessage,\n startTimeoutMs,\n fallbackFlow,\n maxRetries,\n reportTarget,\n sessionId,\n resumed = false,\n clientContext,\n permissionScreens,\n settledPermissions,\n permissionsPending = false,\n onPermissionSettled,\n}) => {\n const { messages, error, isLoading, sendMessage, reset } = useWireAIThread();\n const makeActions = useWireAIAction(sendMessage);\n\n const c = useMemo<OnboardingCopy>(() => ({ ...DEFAULT_COPY, ...copy }), [copy]);\n\n // Hold the latest event/error callbacks in refs so the lifecycle effects below\n // stay stable (and fire exactly once) regardless of the host re-passing closures.\n const onEventRef = useRef(onEvent);\n onEventRef.current = onEvent;\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n const onCompleteRef = useRef(onComplete);\n onCompleteRef.current = onComplete;\n const validatorsRef = useRef(validators);\n validatorsRef.current = validators;\n\n // Client-event reporting refs, captured so the unmount cleanup (which runs once, with a\n // stale closure) reads current values.\n const reportTargetRef = useRef(reportTarget);\n reportTargetRef.current = reportTarget;\n const sessionIdRef = useRef(sessionId);\n sessionIdRef.current = sessionId;\n // Device + user context, held in a ref so the mount-once unmount cleanup (the `dropped`\n // reporter, which runs with a stale closure) reads the current snapshot.\n const clientContextRef = useRef(clientContext);\n clientContextRef.current = clientContext;\n // Last 0-based screen index we showed the user (matches the server's `screen_shown`\n // index). Used as the `dropped` event's screen_index. -1 = nothing shown yet.\n const lastScreenIndexRef = useRef(-1);\n // Trailing-edge debounce timer for prefetch-on-select (see previewOnSelect below).\n const previewTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // The attempt generation. It lives in STATE, not in a ref, and both the auto-start effect and\n // the startup watchdog list it in their deps — a retry has to genuinely RE-ARM both, and a ref\n // cannot re-trigger an effect. Nothing else in those deps moves on a retry: `sendMessage` is\n // memoized in wireai-rn on [registry, provider, model], and `lastCard` is still `undefined`\n // because no card ever arrived. Without the generation the kickoff is never re-sent, `timedOut`\n // can never become true a second time, and the retry budget can never be spent — which leaves a\n // backend that never answers sitting on the loader forever.\n const [runId, setRunId] = useState(0);\n // The generation whose kickoff has already been sent. -1 = nothing sent yet (so the very first\n // run can be told apart from a retry, which must NOT re-fire `started`/`resumed`).\n const startedRunRef = useRef(-1);\n const finished = useRef(false);\n const errored = useRef(false);\n const attempts = useRef(0);\n // Mirror of the `degraded` state for the unmount cleanup: a degrade to the static\n // fallback is NOT a drop, so `dropped` must not fire after it.\n const degradedRef = useRef(false);\n const [degraded, setDegraded] = useState(false);\n const [timedOut, setTimedOut] = useState(false);\n const [validationError, setValidationError] = useState<string | undefined>();\n const [validating, setValidating] = useState(false);\n // Permission screens settled during THIS mount, on top of whatever was restored from storage.\n // A settled screen never comes back, which is the \"shown exactly once\" half of the contract.\n const [locallySettledPermissions, setLocallySettledPermissions] = useState<string[]>([]);\n const onPermissionSettledRef = useRef(onPermissionSettled);\n onPermissionSettledRef.current = onPermissionSettled;\n\n const lastCard = useMemo<Message | undefined>(\n () => [...messages].reverse().find((m) => m.role === \"assistant\" && m.response?.action === \"render\"),\n [messages],\n );\n\n // Local fallback counter — how many distinct rendered cards we've seen.\n const renderedCount = useMemo(\n () => messages.filter((m) => m.role === \"assistant\" && m.response?.action === \"render\").length,\n [messages],\n );\n\n const progress = useMemo(() => readProgress(lastCard?.response), [lastCard]);\n\n // 1. Auto-start: the backend treats the first inbound message as \"begin\".\n // ONLY the very first attempt of a fresh session sends `startMessage`. Every other kickoff\n // — a RESUMED session (persisted id restored after an app kill) and every RETRY — sends the\n // skip sentinel, because both can reach a server that already has a question PENDING on this\n // session, and a non-empty message arriving against a pending question is recorded as that\n // question's ANSWER (server engine dispatch: `if user_message and pending and not\n // _stop_requested(...)` appends `{key, question, answer}` to `session[\"answers\"]`). For a\n // retry that is not hypothetical: the watchdog fires at `startTimeoutMs` while a slow LLM is\n // still generating, so the server can genuinely hold card 1 pending when the retry lands, and\n // the user's first onboarding answer becomes the literal kickoff text — silently.\n // THE COST, stated plainly: when the server DID have card 1 pending, the sentinel SKIPS that\n // card — the user loses one question and the server logs a `screen_skipped`. Deliberate. A\n // skipped question is visible in the funnel and recorded as nothing; a kickoff string stored\n // as the user's first answer is invisible and poisons the data the product is built on.\n // When the server has no pending (restart/expiry, or a retry whose predecessor never landed)\n // the sentinel is zeroed and falls through — it degrades cleanly to a normal kickoff under\n // the same id, which is what makes it safe to send on an attempt that may be either.\n useEffect(() => {\n if (startedRunRef.current === runId) return;\n const isFirstRun = startedRunRef.current < 0;\n startedRunRef.current = runId;\n sendMessage(isFirstRun && !resumed ? startMessage : SKIP_ONE_SENTINEL);\n // Only the FIRST run is a session start. A retry re-kicks the flow (with the sentinel) but\n // must not re-fire `started`/`resumed`, or every host funnel double-counts the session; the\n // retry itself is already surfaced as a `retry` event by the error effect below.\n if (!isFirstRun) return;\n // Surface the session id (the A2A contextId) on the start event so a host can capture it\n // and bind a user AFTER the flow via `identifyOnboarding({ contextId })` — completion clears\n // the persisted session, so the in-flight event is the reliable post-flow handle. sessionId\n // is stable for the whole session (minted before this subtree mounts), so this stays once\n // per session.\n onEventRef.current?.(\n resumed\n ? { type: \"resumed\", contextId: sessionId }\n : { type: \"started\", contextId: sessionId },\n );\n }, [sendMessage, startMessage, resumed, sessionId, runId]);\n\n // 2. Startup watchdog. `runId` is load-bearing in these deps: after a retry there is still no\n // card, so `lastCard` does not change and nothing else would re-arm the timer.\n useEffect(() => {\n if (lastCard) return;\n const timer = setTimeout(() => setTimedOut(true), startTimeoutMs);\n return () => clearTimeout(timer);\n }, [lastCard, startTimeoutMs, runId]);\n\n // A new card arrived → clear any prior inline validation error + emit a turn event.\n useEffect(() => {\n setValidationError(undefined);\n if (!lastCard?.id) return;\n const step = progress.step ?? renderedCount;\n // Remember the latest screen we showed (0-based) for a possible `dropped` event.\n lastScreenIndexRef.current = Math.max(0, step - 1);\n onEventRef.current?.({\n type: \"turn\",\n step,\n component: lastCard.response?.component,\n });\n // Prefetch: an InterstitialCard's answer is always \"continue\", so we can warm the next\n // turn's cache during the momentum window — by the time the user taps Continue the following\n // card is already generated. The preview MUST use the exact text the real Continue tap sends,\n // or the backend's message-keyed preview cache misses. The card's onSubmit(\"continue\") is\n // wrapped by the SDK as `My answer is: ${JSON.stringify(value)}`, so mirror that here.\n // Fire-and-forget; a failed/missed preview just means the real turn generates normally.\n if (lastCard.response?.component === \"InterstitialCard\") {\n sendPreview(reportTargetRef.current, {\n sessionId: sessionIdRef.current,\n userMessage: `My answer is: ${JSON.stringify(\"continue\")}`,\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [lastCard?.id]);\n\n // `dropped`: the user abandoned onboarding. No backend request fires on unmount, so the\n // server can't see this — the client must report it. Fire ONLY on a true unmount that\n // did NOT complete (`onComplete` never ran) and did NOT degrade to the static fallback\n // (a degrade is a reliability fallback, not a user drop). Refs keep this effect mount-once.\n useEffect(() => {\n return () => {\n if (finished.current || degradedRef.current) return;\n reportClientEvent(reportTargetRef.current, {\n event_type: \"dropped\",\n session_id: sessionIdRef.current,\n screen_index: lastScreenIndexRef.current >= 0 ? lastScreenIndexRef.current : undefined,\n device: clientContextRef.current?.device,\n user_context: clientContextRef.current?.userContext,\n user_id: clientContextRef.current?.userId,\n });\n };\n }, []);\n\n // Silently restart the thread from turn one (shared by auto-retry + manual retry).\n // Does NOT clear the attempt counter or the degraded flag — the caller decides that.\n const restartThread = useCallback(() => {\n setTimedOut(false);\n errored.current = false;\n // Bumping the generation IN STATE is what actually re-runs the kickoff effect and re-arms the\n // watchdog. Flipping a ref here would re-trigger neither.\n setRunId((n) => n + 1);\n reset();\n }, [reset]);\n\n // 3. Error/timeout → auto-retry a transient blip, then degrade to the static flow.\n // Each failure: log `error`; if we have retries left, restart the thread silently\n // (`retry`); once exhausted, mark `degraded` so the render falls through to the\n // host's `fallbackFlow`/`onError` (`fallback`). Counter is a ref → survives the\n // reset()-driven re-renders. This is the \"AI fails → static onboarding, never a\n // broken screen\" guarantee.\n useEffect(() => {\n if (errored.current) return;\n if (!error && !timedOut) return;\n errored.current = true;\n const reason: \"backend\" | \"timeout\" = error ? \"backend\" : \"timeout\";\n onEventRef.current?.({ type: \"error\", reason });\n attempts.current += 1;\n if (attempts.current <= maxRetries) {\n onEventRef.current?.({ type: \"retry\", reason, attempt: attempts.current });\n restartThread();\n } else {\n onEventRef.current?.({ type: \"fallback\", reason });\n // Report the degrade to the backend so the dashboard's fallback-rate reflects it.\n // Server-side `llm_fallback` fires per single degraded turn; this `client_fallback`\n // captures the whole-flow case (AI gave up, the user got static onboarding). The server\n // ingests it idempotently and back-fills a `session_started` if it never saw the session,\n // so even a device that dropped straight to its static manifest shows as a counted\n // fallback session. This is the ONE fallback signal — hosts must NOT also report it.\n reportClientEvent(reportTargetRef.current, {\n event_type: \"client_fallback\",\n session_id: sessionIdRef.current,\n screen_index: lastScreenIndexRef.current >= 0 ? lastScreenIndexRef.current : undefined,\n meta: JSON.stringify({ reason }),\n device: clientContextRef.current?.device,\n user_context: clientContextRef.current?.userContext,\n user_id: clientContextRef.current?.userId,\n });\n degradedRef.current = true;\n setDegraded(true);\n onErrorRef.current?.(error ?? new Error(\"Onboarding timed out\"));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [error, timedOut, maxRetries]);\n\n // 5. Completion: the terminal StatusCard is rendered as CompletionView; we fire\n // onComplete only when the user taps its CTA (guarded so it fires once).\n const handleFinish = useCallback(() => {\n if (finished.current) return;\n finished.current = true;\n onCompleteRef.current({ answers: deriveAnswers(messages), raw: messages });\n }, [messages]);\n\n // Manual retry (the no-fallback ErrorBlock button): clear the degrade + counter so\n // the user gets a fresh set of attempts.\n const handleRetry = useCallback(() => {\n attempts.current = 0;\n degradedRef.current = false;\n setDegraded(false);\n restartThread();\n }, [restartThread]);\n\n // Per-question Skip: tell the backend to skip THIS question only and advance to the\n // next card (no answer recorded) — distinct from finishing the flow. Rendered only\n // when the current card is `skippable` (see the scaffold below).\n //\n // NOTE: we deliberately do NOT report a client `screen_skipped` here. The backend already\n // emits `screen_skipped` (correctly correlated by its own contextId, with screen_index +\n // question_key) when it processes this SKIP_ONE_SENTINEL — see the server engine. A client\n // emission would double-count. The reporter supports `screen_skipped` for clients whose skip\n // never reaches the server, which is not the case for this kit.\n const skipQuestion = useCallback(() => {\n if (isLoading) return;\n sendMessage(SKIP_ONE_SENTINEL);\n }, [isLoading, sendMessage]);\n\n // ── Permission screens (host-injected, never server-driven in this release) ─────────────────\n //\n // Analytics for one moment of a permission screen. It rides the SAME plumbing as the rest of the\n // funnel: an `app_event` on `/v1/events` whose `question_key` is the canonical `wire_permission_*`\n // name (exactly how `WIRE_PURCHASE_EVENTS` reach the wire), carrying the same device snapshot and\n // `user_context`, so the `device_key` join that makes every other number real covers these too.\n // It is ALSO surfaced on `onEvent`, so a host keeps its own analytics without a second wiring.\n //\n // `screen_index` is the last card index shown, NOT a new one: a permission screen is not a\n // question, so it must never introduce a screen index the server never emitted a `screen_shown`\n // for. Nothing here can throw into the UI (reportClientEvent is fire-and-forget by contract).\n const emitPermissionStage = useCallback(\n (permission: WirePermissionKind, stage: PermissionStage, status?: WirePermissionStatus) => {\n onEventRef.current?.({ type: \"permission\", permission, stage, status });\n reportClientEvent(reportTargetRef.current, {\n event_type: \"app_event\",\n session_id: sessionIdRef.current,\n question_key: permissionEventName(stage),\n component: PERMISSION_CARD_NAME,\n screen_index: lastScreenIndexRef.current >= 0 ? lastScreenIndexRef.current : undefined,\n meta: JSON.stringify(permissionEventProps(permission, status)),\n device: clientContextRef.current?.device,\n user_context: clientContextRef.current?.userContext,\n user_id: clientContextRef.current?.userId,\n });\n },\n [],\n );\n\n // A screen is DONE: remember it (so it never returns), let the host persist that across a kill,\n // and hand the outcome to `onResult`, the seam a host schedules its first local notification\n // from. A throwing host callback is swallowed: the flow continues on every path, always.\n const settlePermission = useCallback(\n (id: string, screen: PermissionScreenConfig, outcome: WirePermissionOutcome) => {\n setLocallySettledPermissions((prev) => (prev.includes(id) ? prev : [...prev, id]));\n onPermissionSettledRef.current?.(id, outcome);\n try {\n screen.onResult?.(screen.permission, outcome);\n } catch {\n // A host's post-grant work (scheduling a reminder) must never break onboarding.\n }\n },\n [],\n );\n\n // Prefetch on SELECT — the fix for \"the first AI question is always the slowest\". Q1 is a\n // deterministic base card (instant); Q2 is the first LLM turn, and neither cache protects it\n // (flow-cache misses a novel answer combo, the provider prompt-cache is cold on the first\n // call). Choice cards hold their selection LOCALLY and only commit on Continue, so there's a\n // real gap we can use: as the user picks, fire a debounced `message/preview` keyed on the\n // EXACT text the Continue tap will send (`I selected: ${JSON.stringify(value)}`), so the\n // backend generates Q2 during the pick→Continue window. By the time they tap Continue it's\n // already cached → the slow question returns instantly. Fire-and-forget: if they change the\n // selection after the last preview, the real turn just generates normally (never worse than\n // today). Trailing-edge debounced so rapid multi-select toggles warm at most once.\n const previewOnSelect = useCallback((value: string | string[]) => {\n const target = reportTargetRef.current;\n if (!target?.serverUrl) return;\n if (Array.isArray(value) ? value.length === 0 : !value) return;\n if (previewTimer.current) clearTimeout(previewTimer.current);\n previewTimer.current = setTimeout(() => {\n sendPreview(target, {\n sessionId: sessionIdRef.current,\n userMessage: `I selected: ${JSON.stringify(value)}`,\n });\n }, 300);\n }, []);\n\n // Cancel any pending preview on unmount so a fired-but-unsent warm can't outlive the flow.\n useEffect(() => () => {\n if (previewTimer.current) clearTimeout(previewTimer.current);\n }, []);\n\n // 4. Wrap the SDK's action callbacks so an answer is validated before it's sent.\n const wrappedActions = useCallback(\n (messageId: string) => {\n const base = makeActions(messageId);\n // ⚠️ HOST VALIDATORS LIVE IN THE SAME KEY NAMESPACE `deriveAnswers` files answers under, so\n // moving the answer key to `slot_id` without moving this lookup would silently UNBIND every\n // host validator — no error, no warning, values just stop being checked. Try the slot first\n // (matching the answer key), then fall back to the question key, so a host that has not yet\n // renamed its validator map keeps working while a server rolls slots out.\n const validators = validatorsRef.current;\n const validator =\n (progress.slot_id ? validators?.[progress.slot_id] : undefined) ??\n (progress.key ? validators?.[progress.key] : undefined);\n if (!validator) return base;\n\n const out: Record<string, (...args: unknown[]) => void> = { ...base };\n for (const name of ANSWER_CALLBACKS) {\n const original = base[name];\n if (!original) continue;\n out[name] = (...args: unknown[]) => {\n const value = args[0];\n // Only string answers are validatable (e.g. username). Pass others through.\n if (typeof value !== \"string\") return original(...args);\n setValidating(true);\n validator(value)\n .then((res) => {\n if (res.ok) {\n setValidationError(undefined);\n original(...args);\n } else {\n setValidationError(res.error ?? \"That value isn't available.\");\n }\n })\n .catch(() => {\n // A validator failure must never block the user — let them proceed.\n original(...args);\n })\n .finally(() => setValidating(false));\n };\n }\n return out;\n },\n [makeActions, progress.key, progress.slot_id],\n );\n\n // ── Render ────────────────────────────────────────────────────────────────\n // Degraded (retries exhausted): render the host's static onboarding in place —\n // the \"AI failed → your static flow, never a broken screen\" guarantee. If no\n // static flow was supplied, hand off to onError (host navigates away), else the\n // inline retry screen as a last resort.\n if (degraded) {\n if (fallbackFlow !== undefined) return <>{fallbackFlow}</>;\n if (onError) {\n return <LoadingScreen title={c.startingTitle} hint={c.startingHint} />;\n }\n return (\n <ErrorBlock\n onRetry={handleRetry}\n message={\n timedOut\n ? \"This is taking longer than expected. Try again?\"\n : \"We couldn't reach the onboarding service. Try again?\"\n }\n />\n );\n }\n\n // Errored but not yet degraded → an auto-retry is in flight. Show a neutral loader\n // so a transient blip never flashes an error screen.\n if (error || timedOut) {\n return <LoadingScreen title={c.startingTitle} hint={c.startingHint} />;\n }\n\n const response = lastCard?.response;\n\n // No card yet → the first \"thinking\" screen.\n if (!lastCard || !response) {\n return <LoadingScreen title={c.startingTitle} hint={c.startingHint} />;\n }\n\n // Step index drives the progress bar. A total (never shown) only paces the fill:\n // prefer a backend-supplied total, else the host's approximate prop, else asymptotic.\n const step = progress.step ?? renderedCount;\n const total = progress.total ?? approxScreens;\n const isTerminal = response.action === \"render\" && response.component === \"StatusCard\";\n\n // A permission screen sits IN FRONT of the card the flow was about to render (including the\n // terminal recap, which is what `\"beforeEnd\"` means), and hands that card straight back once it\n // settles. Nothing is sent to the backend, nothing is appended to the thread, and `step` is\n // untouched, so the progress bar, the funnel, and `deriveAnswers` cannot tell it happened.\n // Placement is resolved against the card ABOUT to render, because the stream length is\n // server-driven; an `afterCard` the stream never reaches clamps to the terminal position.\n const duePermission = permissionsPending\n ? undefined\n : selectDuePermissionScreen(\n permissionScreens,\n settledPermissions\n ? [...settledPermissions, ...locallySettledPermissions]\n : locallySettledPermissions,\n { cardIndex: renderedCount - 1, isTerminal },\n );\n\n if (duePermission) {\n const { screen, id } = duePermission;\n const copy = resolvePermissionCopy(screen.permission, screen.copy);\n return (\n <OnboardingScaffold step={step} approxScreens={total}>\n {/* The same shell + handoff every card uses; \"spring\" is the value-beat register the\n InterstitialCard already wears, which is what this screen is. */}\n <CardHandoff transitionKey={`permission:${id}`} variant=\"spring\">\n <PermissionCardView\n key={id}\n permission={screen.permission}\n title={copy.title}\n message={copy.message}\n primaryLabel={copy.primaryLabel}\n secondaryLabel={copy.secondaryLabel}\n blockedTitle={copy.blockedTitle}\n blockedMessage={copy.blockedMessage}\n settingsLabel={copy.settingsLabel}\n continueLabel={copy.continueLabel}\n illustration={screen.illustration}\n request={screen.request}\n getStatus={screen.getStatus}\n openSettings={screen.openSettings}\n onStage={(stage, status) => emitPermissionStage(screen.permission, stage, status)}\n onSettled={(outcome) => settlePermission(id, screen, outcome)}\n />\n </CardHandoff>\n </OnboardingScaffold>\n );\n }\n\n // Terminal recap: show what the app will now do for the user (backend-authored),\n // and finish only when they tap the CTA.\n if (isTerminal) {\n const props = (response.props ?? {}) as {\n title?: string;\n message?: string;\n ctaLabel?: string;\n };\n return (\n <OnboardingScaffold step={step} complete approxScreens={total}>\n <CompletionView\n title={props.title ?? c.completeTitle}\n message={props.message}\n ctaLabel={props.ctaLabel ?? c.completeCta}\n onContinue={handleFinish}\n />\n </OnboardingScaffold>\n );\n }\n\n const overrides: Record<string, unknown> = {\n ...wrappedActions(lastCard.id),\n // Inject the inline error onto whichever card supports it (TextInputCard).\n validationError,\n // Choice cards (Selection/ChipSelect) call this as the live selection changes, so the flow\n // can prefetch the next turn before Continue. Non-committing; ignored by cards that don't use it.\n onSelectionChange: previewOnSelect,\n };\n\n return (\n <OnboardingScaffold\n step={step}\n onSkip={progress.skippable ? skipQuestion : undefined}\n approxScreens={total}\n >\n {/* CardHandoff pairs the exit with the enter (the design's \"cards hand off,\n they don't cut\"): the answered card leaves left while the next arrives\n from the right; loader states enter/exit as a short fade. transitionKey\n identifies WHAT is on screen — loader states get a stable key per state,\n cards key on the message id. */}\n <CardHandoff\n transitionKey={validating ? \"loader:checking\" : isLoading ? \"loader:thinking\" : lastCard.id}\n variant={\n validating || isLoading\n ? \"fade\"\n : lastCard.response?.component === \"InterstitialCard\"\n ? \"spring\"\n : \"slide\"\n }\n >\n {validating ? (\n <LoadingBlock title={c.checkingTitle} hint={c.checkingHint} />\n ) : isLoading ? (\n // Between turns: the answer was sent and we're waiting on the next card.\n // Show the \"thinking\" loader instead of leaving the old card on screen.\n <LoadingBlock title={c.thinkingTitle} hint={c.thinkingHint} />\n ) : (\n // key={lastCard.id} is load-bearing: cards (SelectionCard/ChipSelectCard)\n // hold internal `selected`/`submitted` state, and React reuses a component\n // instance across turns when the rendered type is identical (e.g. two\n // SelectionCards in a row). Without a per-turn key the second card inherits\n // the first's `submitted=true` and silently rejects all taps. Keying on the\n // message id forces a fresh mount every turn. (CardHandoff's transitionKey\n // shares the id, but this renderer key stays the state-isolation guarantee.)\n <ComponentRenderer\n key={lastCard.id}\n messageId={lastCard.id}\n response={response}\n callbackOverrides={overrides as never}\n />\n )}\n </CardHandoff>\n </OnboardingScaffold>\n );\n};\n","/**\n * Themed ChipSelectCard — drop-in replacement for the OSS SDK's ChipSelectCard.\n * Identical `name`, `propsSchema`, `defaultProps`, and `onSelect` callback contract\n * so the SDK's ComponentRenderer drives it transparently. Only the look is themed.\n *\n * Motion (design-refs/EXTRACTED-SPEC.md rows 4-6): chips tick on press (scale\n * 0.94 spring), the selected accent fill crossfades in over 160ms (native-driver\n * opacity overlay) with the label flipping to `onPrimary` and a check popping in.\n * Deselect reverses. Reduce motion: color swap only, check shown instantly.\n */\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, Pressable, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { captionStyle } from \"../theme/typography\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\nimport {\n CHECK_SCALE_FROM,\n CHECK_SPRING,\n CHIP_FILL_MS,\n CHIP_PRESS_SCALE,\n PRESS_SPRING,\n WIRE_BEZIER,\n scaledMs,\n stateChangeDuration,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\n\n// Mirror of the SDK schema — must stay identical so the registry + validator agree.\nconst schema = z.object({\n title: z.string().describe(\"Question or section header, e.g. 'Which season?'\"),\n chips: z\n .array(z.string())\n .min(1)\n .describe(\"List of option labels shown as chips, e.g. ['Spring','Summer','Autumn','Winter']\"),\n multiSelect: z.boolean().optional().describe(\"Allow multiple chips selected at once, default true\"),\n submitLabel: z.string().optional().describe(\"Confirm button label, default: Continue\"),\n maxSelections: z.number().optional().describe(\"Maximum number of chips the user can select at once\"),\n});\n\ntype Props = z.infer<typeof schema> &\n InjectedProps & {\n onSelect?: (selected: string | string[]) => void;\n /** Fires as the live selection changes (before Continue), so the flow can prefetch the\n * next turn. Same value shape as onSelect. Optional — injected by OnboardingFlow. */\n onSelectionChange?: (selected: string | string[]) => void;\n };\n\ntype ChipItemProps = {\n chip: string;\n isSelected: boolean;\n multiSelect: boolean;\n onToggle: (chip: string) => void;\n};\n\nconst _ChipItem: React.FC<ChipItemProps> = ({ chip, isSelected, multiSelect, onToggle }) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const handlePress = useCallback(() => onToggle(chip), [chip, onToggle]);\n\n // Press tick: scale 1→0.94, spring, native driver. Skipped under reduce motion.\n const pressScale = useRef(new Animated.Value(1)).current;\n const pressTo = useCallback(\n (to: number) => {\n if (reduced) return;\n Animated.spring(pressScale, {\n toValue: to,\n friction: PRESS_SPRING.friction,\n tension: PRESS_SPRING.tension,\n useNativeDriver: true,\n }).start();\n },\n [pressScale, reduced],\n );\n const handlePressIn = useCallback(() => pressTo(CHIP_PRESS_SCALE), [pressTo]);\n const handlePressOut = useCallback(() => pressTo(1), [pressTo]);\n\n // Selected fill: full accent pill, crossfaded in over 160ms on a native-driver\n // opacity overlay, never a color interpolation. Reduce motion: instant swap.\n const fillT = useRef(new Animated.Value(isSelected ? 1 : 0)).current;\n useEffect(() => {\n const anim = Animated.timing(fillT, {\n toValue: isSelected ? 1 : 0,\n duration: scaledMs(stateChangeDuration(reduced, CHIP_FILL_MS)),\n easing: easeWire,\n useNativeDriver: true,\n });\n anim.start();\n return () => anim.stop();\n }, [isSelected, reduced, fillT]);\n\n // Check pop on select (the width-slide of the canvas is a layout animation the\n // native driver can't express, so it stays on the JS driver deliberately).\n const checkT = useRef(new Animated.Value(isSelected ? 1 : 0)).current;\n useEffect(() => {\n if (!isSelected) {\n checkT.setValue(0);\n return;\n }\n if (reduced) {\n checkT.setValue(1);\n return;\n }\n checkT.setValue(0);\n const anim = Animated.spring(checkT, {\n toValue: 1,\n friction: CHECK_SPRING.friction,\n tension: CHECK_SPRING.tension,\n useNativeDriver: true,\n });\n anim.start();\n return () => anim.stop();\n }, [isSelected, reduced, checkT]);\n\n const checkScale = checkT.interpolate({ inputRange: [0, 1], outputRange: [CHECK_SCALE_FROM, 1] });\n\n return (\n <Pressable\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n accessibilityRole={multiSelect ? \"checkbox\" : \"radio\"}\n accessibilityState={multiSelect ? { checked: isSelected } : { selected: isSelected }}\n accessibilityLabel={chip}\n >\n <Animated.View\n style={[\n styles.chip,\n {\n borderRadius: t.radius.full,\n paddingHorizontal: t.spacing.md,\n paddingVertical: t.spacing.sm,\n borderColor: t.colors.border,\n backgroundColor: t.colors.background,\n transform: [{ scale: pressScale }],\n },\n ]}\n >\n <Animated.View\n pointerEvents=\"none\"\n style={[\n StyleSheet.absoluteFill,\n styles.fillOverlay,\n {\n borderRadius: t.radius.full,\n borderColor: t.colors.primary,\n backgroundColor: t.colors.primary,\n opacity: fillT,\n },\n ]}\n />\n {isSelected ? (\n <Animated.Text\n style={[\n styles.check,\n { color: t.colors.onPrimary, opacity: checkT, transform: [{ scale: checkScale }] },\n ]}\n >\n ✓\n </Animated.Text>\n ) : null}\n <Text\n style={[\n captionStyle(t.fonts),\n styles.chipLabel,\n { color: isSelected ? t.colors.onPrimary : t.colors.textMuted },\n ]}\n >\n {chip}\n </Text>\n </Animated.View>\n </Pressable>\n );\n};\nconst ChipItem = React.memo(_ChipItem);\n\nconst _ChipSelectCard: React.FC<Props> = ({\n title,\n chips,\n multiSelect = true,\n submitLabel = \"Continue\",\n maxSelections,\n onSelect,\n onSelectionChange,\n}) => {\n const t = useOnboardingTheme();\n const [selected, setSelected] = useState<string[]>([]);\n const [submitted, setSubmitted] = useState(false);\n\n // Report the settled selection upward (before Continue) so the flow can prefetch the next\n // turn. Debouncing lives in the flow; here we just emit on every change once something's picked.\n useEffect(() => {\n if (!submitted && selected.length) onSelectionChange?.(multiSelect ? selected : selected[0]!);\n }, [selected, submitted, multiSelect, onSelectionChange]);\n\n const toggle = useCallback(\n (chip: string) => {\n if (submitted) return;\n if (multiSelect) {\n setSelected((prev) => {\n if (prev.includes(chip)) return prev.filter((c) => c !== chip);\n if (maxSelections && prev.length >= maxSelections) return prev;\n return [...prev, chip];\n });\n } else {\n setSelected([chip]);\n }\n },\n [submitted, multiSelect, maxSelections],\n );\n\n const handleSubmit = useCallback(() => {\n if (!selected.length || !onSelect || submitted) return;\n setSubmitted(true);\n onSelect(multiSelect ? selected : selected[0]!);\n }, [selected, onSelect, submitted, multiSelect]);\n\n return (\n <CardLayout\n title={title}\n subtitle={maxSelections ? `Select up to ${maxSelections}` : undefined}\n footer={\n <Button\n title={submitLabel}\n onPress={handleSubmit}\n variant=\"primary\"\n disabled={selected.length === 0 || submitted}\n />\n }\n >\n <View style={[styles.chipsRow, { gap: t.spacing.sm + t.spacing.xs }]}>\n {chips.map((chip) => (\n <ChipItem\n key={chip}\n chip={chip}\n isSelected={selected.includes(chip)}\n multiSelect={multiSelect}\n onToggle={toggle}\n />\n ))}\n </View>\n </CardLayout>\n );\n};\n\nexport const ChipSelectCard: WireAIComponent = {\n name: \"ChipSelectCard\",\n description:\n \"Use for compact short labels: seasons, activities, travel styles, moods, categories. Ideal for 4–12 single-word or two-word options. Use SelectionCard instead when options need descriptions; use CardGridSelectCard for a smaller set (2–6) of visual choices that each deserve an icon.\",\n component: React.memo(_ChipSelectCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n defaultProps: { multiSelect: true, submitLabel: \"Continue\" },\n};\n\nconst styles = StyleSheet.create({\n chipsRow: { flexDirection: \"row\", flexWrap: \"wrap\" },\n chip: { borderWidth: 1.5, flexDirection: \"row\", alignItems: \"center\", gap: 6, overflow: \"hidden\" },\n fillOverlay: { borderWidth: 1.5 },\n chipLabel: { fontWeight: \"600\" },\n check: { fontSize: 13, fontWeight: \"800\", lineHeight: 15 },\n});\n","/**\n * Themed TextInputCard — drop-in for the OSS SDK's TextInputCard. Same `name`,\n * `propsSchema`, `defaultProps`, and `onSubmit(value: string)` contract. The input\n * is themed and supports an optional inline error string (used by the kit's\n * per-step validators — e.g. \"username taken\"), set via the `validationError` prop\n * which the OnboardingFlow injects through callbackOverrides.\n *\n * Open-ended answers (goals, notes, \"what would make this better\") render a tall\n * multi-line box by default so the user has room to actually write. Short fields\n * (a name, a username) set `multiline: false` for the compact single-line height.\n */\nimport React, { useCallback, useMemo, useState } from \"react\";\nimport { StyleSheet, Text, TextInput, View, useWindowDimensions } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport type { OnboardingTheme } from \"../theme/types\";\nimport { bodyStyle, captionStyle } from \"../theme/typography\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\n\nconst schema = z.object({\n label: z.string().describe(\"Input field label / the question being asked\"),\n hint: z\n .string()\n .optional()\n .describe(\n \"One short line under the question giving context: what the answer is used for or why you ask. Add it whenever the question alone might be unclear.\"\n ),\n placeholder: z\n .string()\n .optional()\n .describe(\n 'A concrete example answer shown inside the box, phrased like a real user wrote it and starting with \"e.g. \". ALWAYS provide one for open-ended questions: it shows the expected answer shape and inspires the user.'\n ),\n submitLabel: z.string().optional().describe(\"Submit button label, default: Submit\"),\n multiline: z\n .boolean()\n .optional()\n .describe(\n \"Tall multi-line box for open-ended answers (goals, notes, feedback). Default true. Set false for a single-line field like a name or username.\"\n ),\n lines: z\n .number()\n .optional()\n .describe(\"Approx visible rows when multiline (default 6). Height is capped at 40% of the screen.\"),\n});\n\ntype Props = z.infer<typeof schema> &\n InjectedProps & {\n onSubmit?: (value: string) => void;\n /**\n * Inline error injected by OnboardingFlow when a validator rejects the value\n * (e.g. username already taken). Re-enables the input so the user can edit.\n */\n validationError?: string;\n };\n\nconst _TextInputCard: React.FC<Props> = ({\n label,\n hint,\n placeholder,\n submitLabel = \"Submit\",\n onSubmit,\n validationError,\n multiline = true,\n lines = 6,\n}) => {\n const t = useOnboardingTheme();\n const styles = useMemo(() => makeStyles(t), [t]);\n const { height: screenHeight } = useWindowDimensions();\n const [value, setValue] = useState(\"\");\n const [submitted, setSubmitted] = useState(false);\n\n // A validator rejection arrives as `validationError`; reopen the field so the\n // user can fix their answer instead of being stuck on a submitted state.\n const locked = submitted && !validationError;\n\n // Multi-line free-text gets a generous box (~`lines` rows), capped at 40% of\n // screen height so it stays comfortable on small devices. Single-line fields\n // keep the compact 52pt height.\n const APPROX_ROW_HEIGHT = 26;\n const minHeight = multiline\n ? Math.min(Math.max(lines, 4) * APPROX_ROW_HEIGHT + t.spacing.md * 2, screenHeight * 0.4)\n : 52;\n\n const handleSubmit = useCallback(() => {\n if (value.trim() && onSubmit && !locked) {\n setSubmitted(true);\n onSubmit(value.trim());\n }\n }, [value, onSubmit, locked]);\n\n return (\n <CardLayout\n title={label}\n subtitle={hint}\n footer={\n <Button\n title={submitLabel}\n onPress={handleSubmit}\n variant=\"primary\"\n disabled={!value.trim() || locked}\n />\n }\n >\n <View style={styles.row}>\n <TextInput\n value={value}\n onChangeText={setValue}\n placeholder={placeholder ?? \"\"}\n placeholderTextColor={t.colors.textMuted}\n editable={!locked}\n multiline={multiline}\n numberOfLines={multiline ? lines : 1}\n textAlignVertical={multiline ? \"top\" : \"center\"}\n style={[\n bodyStyle(t.fonts),\n styles.input,\n {\n color: t.colors.text,\n backgroundColor: t.colors.surface,\n borderRadius: t.radius.md,\n borderColor: validationError ? t.colors.error : t.colors.border,\n padding: t.spacing.md,\n minHeight,\n },\n ]}\n />\n {validationError ? (\n <Text style={[captionStyle(t.fonts), { color: t.colors.error }]}>{validationError}</Text>\n ) : null}\n </View>\n </CardLayout>\n );\n};\n\nexport const TextInputCard: WireAIComponent = {\n name: \"TextInputCard\",\n description:\n \"Use when the user needs to type a free-text answer: an open-ended goal, notes, feedback, a name, a destination, a search query. Multi-line by default (great for open-ended goals); set multiline:false for a short single-line field like a name. Use NumberStepperCard for numeric ranges with known bounds.\",\n component: React.memo(_TextInputCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n defaultProps: { submitLabel: \"Submit\", multiline: true, lines: 6 },\n};\n\nfunction makeStyles(t: OnboardingTheme) {\n return StyleSheet.create({\n row: { gap: t.spacing.sm },\n input: { borderWidth: 1 },\n });\n}\n","/**\n * expoIcons — resolve an `@expo/vector-icons` family, lazily and optionally.\n *\n * ── WHY THIS DOES NOT BREAK THE NO-NATIVE-DEPENDENCY POLICY ──────────────────────────────\n *\n * The policy (see `questionnaire/QuestionnaireGate.tsx`'s back-chevron note, `AnimatedSparkle`,\n * `coachmarks/GestureHint`, `cards/StatusCard`'s Unicode STATUS_ICONS) says: no vector library\n * is worth FORCING EVERY HOST INTO A NATIVE REBUILD. Read it precisely — what it forbids is\n * forcing hosts, not the existence of an icon.\n *\n * `@expo/vector-icons` is an OPTIONAL peer:\n *\n * • A host WITHOUT it installs the kit fine (optional peer → npm never fetches it) and renders\n * fine (icon → null, layout unchanged). To BUNDLE fine it must let Metro know the module is\n * allowed to be missing — see \"OPTIONALITY IS A BUILD-TIME CONTRACT\" below.\n * • A host WITH it gets real brand icons. Both live host apps already ship it\n * (`@expo/vector-icons ^15.0.3`), so neither needs a rebuild — which matters because\n * neither can be force-updated: both ship new store builds only and never OTA.\n * • A host that wants neither can override every name with its own artwork through the\n * `icons` registry, so the library is never on the critical path at all.\n *\n * ── THE SPECIFIER MUST BE A STRING LITERAL — THIS IS THE WHOLE BUG ───────────────────────\n *\n * DO NOT \"restore\" the old `const req = require; req(moduleName)` shape. It could never work,\n * and it shipped broken in 0.8.0. What that shape actually did, proven in a real `expo export`\n * bundle and in Expo SDK 55's runtime:\n *\n * 1. Metro collects dependencies STATICALLY, by matching a call whose callee is literally the\n * identifier `require` and whose argument is a STRING LITERAL. Aliasing `require` to a local\n * hid the call from the collector, so this module's dependencyMap was emitted EMPTY (`[]`)\n * and `@expo/vector-icons` was never put in the bundle at all.\n * 2. At runtime the alias did NOT point at Node's `require`. Metro renames the free `require`\n * identifier to the module factory's require param, so `req` WAS `metroRequire`, whose\n * module registry is keyed by NUMERIC module ids. Handing it the string \"@expo/vector-icons\"\n * could never match a key, so it threw `Requiring unknown module \"@expo/vector-icons\"` —\n * even in a bundle that contained the module.\n * 3. That throw never reached the `catch` below. Metro's own `guardedLoadModule` wraps the\n * load, catches the error FIRST, and routes it to `global.ErrorUtils.reportFatalError(e)`\n * instead of rethrowing (Expo SDK 55: `@expo/cli/build/metro-require/require.js:151-165`).\n * So the call returned `undefined` — icon silently null — AND logged a red fatal error. A\n * try/catch cannot guard a require that Metro never lets throw.\n *\n * A LITERAL `require(\"@expo/vector-icons\")` is collected, is bundled, and resolves SYNCHRONOUSLY\n * through the numeric dependencyMap — the same reason `reviews/storeReview.ts`'s literal\n * `await import(\"expo-store-review\")` has always worked. (The old comment here claimed the alias\n * worked \"exactly like expo-store-review\". It was the opposite: storeReview's specifier is a\n * literal, and that is precisely why it resolves and this one did not.)\n *\n * ── OPTIONALITY IS A BUILD-TIME CONTRACT, AND THE TRY/CATCH IS LOAD-BEARING ──────────────\n *\n * Metro has NO runtime resolution: every specifier is resolved when the bundle is built. It does\n * have a real optional-dependency mechanism, and it needs BOTH halves of what is written below:\n * a LITERAL specifier (so the dep is collected at all) AND the call inside a TRY/CATCH — that is\n * literally how Metro marks a dependency `isOptional`. When the peer is absent, Metro then puts\n * `null` in this module's dependencyMap and `metroRequire(null, \"@expo/vector-icons\")` throws\n * \"Cannot find module\" from its own `moduleId === null` branch, BEFORE `guardedLoadModule` — so\n * unlike the string-id path in the autopsy above, that throw really does land in the catch below.\n * So do NOT \"simplify\" the try/catch away: it is what keeps the peer optional, not just tidy.\n *\n * That mechanism rides on the transformer's `allowOptionalDependencies`, which Expo enables by\n * default but bare `metro-config` defaults to FALSE. For hosts in the second camp, the kit ships\n * a safety net: `withWireOnboarding` (metro/index.js) installs a `resolveRequest` that maps an\n * absent optional peer to an EMPTY module, landing on exactly the degradation path below (no\n * families on the namespace → `undefined` → icon renders null).\n */\nimport type { WireIconFamily } from \"./vocabulary\";\n\n// Metro injects a module-scoped `require`; it is ABSENT in a pure-ESM runtime (the kit's own\n// tests run under `node --test` as ESM). Declared locally so this type-checks without ambient\n// Node types; the `typeof` guard keeps the reference ESM-safe.\ndeclare const require: ((id: string) => unknown) | undefined;\n\n/** A `require`-like resolver. Injectable in tests; production uses the guarded literal require. */\nexport type OptionalRequire = (moduleName: string) => unknown;\n\n/**\n * The minimal shape the kit uses from a vector-icons family. A COMPONENT TYPE, not a plain\n * function: these are real React components (createIconSet output) and must be mounted via\n * JSX/createElement, never invoked directly — calling one bypasses the reconciler and breaks\n * the moment the family uses hooks or is a class.\n */\nexport type IconComponent = import(\"react\").ComponentType<{\n name: string;\n size?: number;\n color?: string;\n allowFontScaling?: boolean;\n}>;\n\n/**\n * The production resolver. The specifier is a LITERAL so Metro collects it (see the header); the\n * `moduleName` parameter exists only to keep the `OptionalRequire` seam shape, so anything other\n * than the one module this file owns resolves to undefined.\n */\nconst runtimeRequire: OptionalRequire = (moduleName) => {\n if (moduleName !== \"@expo/vector-icons\") return undefined;\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"@expo/vector-icons\");\n } catch {\n return undefined;\n }\n};\n\n/** Read a module's `default` (Expo modules are consumed as default exports) or the namespace. */\nconst interop = (mod: unknown): Record<string, unknown> | undefined => {\n if (!mod || typeof mod !== \"object\") return undefined;\n const def = (mod as { default?: unknown }).default;\n // `@expo/vector-icons` exposes the families as NAMED exports; prefer the namespace when it\n // already carries them, and only fall back to `default` for a CJS-interop wrapper.\n const ns = mod as Record<string, unknown>;\n if (ns.MaterialCommunityIcons || ns.Ionicons) return ns;\n if (def && typeof def === \"object\") return def as Record<string, unknown>;\n return ns;\n};\n\n/**\n * Narrow an unknown export to something mountable. A vector-icons family is either a function\n * component or a class (`createIconSet` has returned both across versions), and React.memo /\n * forwardRef wrappers are objects — so accept an object carrying a `$$typeof` too, and reject\n * anything else rather than handing the reconciler a non-component.\n */\nconst asComponent = (value: unknown): IconComponent | undefined => {\n if (typeof value === \"function\") return value as IconComponent;\n if (value && typeof value === \"object\" && \"$$typeof\" in (value as object)) {\n return value as IconComponent;\n }\n return undefined;\n};\n\n/**\n * Module-level memo. `null` = \"we looked and it is not there\" (distinct from \"not looked yet\"),\n * so an absent peer costs exactly one failed require per process, not one per rendered icon.\n */\nlet cached: Record<string, unknown> | null | undefined;\n\n/** Reset the memo. TEST-ONLY seam — production never calls it. */\nexport const resetIconModuleCache = (): void => {\n cached = undefined;\n};\n\n/**\n * Resolve one icon family component, or undefined when the peer is absent/unresolvable.\n * Never throws: an icon is decorative, so it must never be able to break a card.\n *\n * `requireModule` is injectable so tests can exercise BOTH the found and absent paths without\n * installing the native peer (same convention as `detectAppVersion`).\n */\nexport const resolveIconFamily = (\n family: WireIconFamily,\n requireModule: OptionalRequire = runtimeRequire,\n): IconComponent | undefined => {\n try {\n if (cached === undefined || requireModule !== runtimeRequire) {\n const resolved = interop(requireModule(\"@expo/vector-icons\"));\n // Don't poison the module memo from an injected test require.\n if (requireModule === runtimeRequire) cached = resolved ?? null;\n if (!resolved) return undefined;\n return asComponent(resolved[family]);\n }\n if (cached === null) return undefined;\n return asComponent(cached[family]);\n } catch {\n return undefined;\n }\n};\n","/**\n * The Wire icon VOCABULARY — the stable, semantic contract between the AI and the kit.\n *\n * The model emits a plain semantic string (`\"instagram\"`, `\"friend\"`, `\"wedding\"`), never a\n * raw icon-library glyph name. That indirection is the whole point:\n *\n * • The model is never coupled to a library version. `@expo/vector-icons` renaming a glyph,\n * or a host swapping the library out for brand SVGs, changes THIS map — not the prompt,\n * not the server, and not a single stored answer.\n * • A host can override any name with its own artwork (see `IconRegistry`), so brand icons\n * need no kit change.\n * • An unknown name degrades to no icon (see `WireIcon`), which is why the vocabulary can\n * grow without a coordinated kit+server release.\n *\n * `WIRE_ICON_NAMES` is exported so the server/AI side can be taught the list verbatim — paste\n * it into the prompt as the allowed `icon` values. Keep names SEMANTIC (what the option means)\n * rather than visual (what the glyph looks like): the model reasons about meaning.\n *\n * Every glyph below was verified to exist in the `@expo/vector-icons` 15.0.3 glyphmaps that\n * both live host apps already ship. MaterialCommunityIcons is the default family (the broadest\n * single set); Ionicons covers the few brand logos MCI lacks (TikTok, Discord).\n */\n\n/** The icon families this kit resolves out of `@expo/vector-icons`. Both are root exports. */\nexport type WireIconFamily = \"MaterialCommunityIcons\" | \"Ionicons\";\n\n/** One vocabulary entry: the concrete glyph a semantic name resolves to. */\nexport interface WireIconGlyph {\n family: WireIconFamily;\n /** The library's own glyph name — an INTERNAL detail. The AI never sees or emits this. */\n name: string;\n}\n\n/**\n * The semantic name → concrete glyph map. Grouped by the onboarding questions these actually\n * serve: acquisition channels (\"where did you hear about us\"), intent/occasion (\"what brings\n * you here\"), and a general-purpose set for everything else.\n */\nexport const WIRE_ICON_GLYPHS = {\n // ── Acquisition channels (\"where did you hear about us?\") ──────────────────\n instagram: { family: \"MaterialCommunityIcons\", name: \"instagram\" },\n tiktok: { family: \"Ionicons\", name: \"logo-tiktok\" },\n youtube: { family: \"MaterialCommunityIcons\", name: \"youtube\" },\n facebook: { family: \"MaterialCommunityIcons\", name: \"facebook\" },\n twitter: { family: \"MaterialCommunityIcons\", name: \"twitter\" },\n reddit: { family: \"MaterialCommunityIcons\", name: \"reddit\" },\n linkedin: { family: \"MaterialCommunityIcons\", name: \"linkedin\" },\n discord: { family: \"Ionicons\", name: \"logo-discord\" },\n whatsapp: { family: \"MaterialCommunityIcons\", name: \"whatsapp\" },\n twitch: { family: \"MaterialCommunityIcons\", name: \"twitch\" },\n snapchat: { family: \"MaterialCommunityIcons\", name: \"snapchat\" },\n pinterest: { family: \"MaterialCommunityIcons\", name: \"pinterest\" },\n google: { family: \"MaterialCommunityIcons\", name: \"google\" },\n search: { family: \"MaterialCommunityIcons\", name: \"magnify\" },\n friend: { family: \"MaterialCommunityIcons\", name: \"account-heart\" },\n podcast: { family: \"MaterialCommunityIcons\", name: \"podcast\" },\n blog: { family: \"MaterialCommunityIcons\", name: \"post\" },\n newsletter: { family: \"MaterialCommunityIcons\", name: \"email-outline\" },\n news: { family: \"MaterialCommunityIcons\", name: \"newspaper\" },\n \"app-store\": { family: \"MaterialCommunityIcons\", name: \"apple\" },\n ad: { family: \"MaterialCommunityIcons\", name: \"bullhorn\" },\n\n // ── Intent / occasion (\"what brings you here?\") ────────────────────────────\n wedding: { family: \"MaterialCommunityIcons\", name: \"ring\" },\n birthday: { family: \"MaterialCommunityIcons\", name: \"cake-variant\" },\n baby: { family: \"MaterialCommunityIcons\", name: \"baby-carriage\" },\n travel: { family: \"MaterialCommunityIcons\", name: \"airplane\" },\n work: { family: \"MaterialCommunityIcons\", name: \"briefcase\" },\n celebration: { family: \"MaterialCommunityIcons\", name: \"party-popper\" },\n store: { family: \"MaterialCommunityIcons\", name: \"storefront\" },\n school: { family: \"MaterialCommunityIcons\", name: \"school\" },\n team: { family: \"MaterialCommunityIcons\", name: \"account-multiple\" },\n growth: { family: \"MaterialCommunityIcons\", name: \"trending-up\" },\n\n // ── General purpose ────────────────────────────────────────────────────────\n sparkle: { family: \"MaterialCommunityIcons\", name: \"star-four-points\" },\n heart: { family: \"MaterialCommunityIcons\", name: \"heart\" },\n star: { family: \"MaterialCommunityIcons\", name: \"star\" },\n fire: { family: \"MaterialCommunityIcons\", name: \"fire\" },\n target: { family: \"MaterialCommunityIcons\", name: \"target\" },\n trophy: { family: \"MaterialCommunityIcons\", name: \"trophy\" },\n rocket: { family: \"MaterialCommunityIcons\", name: \"rocket-launch\" },\n clock: { family: \"MaterialCommunityIcons\", name: \"clock-outline\" },\n calendar: { family: \"MaterialCommunityIcons\", name: \"calendar-star\" },\n camera: { family: \"MaterialCommunityIcons\", name: \"camera\" },\n image: { family: \"MaterialCommunityIcons\", name: \"image\" },\n video: { family: \"MaterialCommunityIcons\", name: \"video\" },\n mic: { family: \"MaterialCommunityIcons\", name: \"microphone\" },\n music: { family: \"MaterialCommunityIcons\", name: \"music\" },\n book: { family: \"MaterialCommunityIcons\", name: \"book-open-variant\" },\n food: { family: \"MaterialCommunityIcons\", name: \"silverware-fork-knife\" },\n coffee: { family: \"MaterialCommunityIcons\", name: \"coffee\" },\n fitness: { family: \"MaterialCommunityIcons\", name: \"dumbbell\" },\n health: { family: \"MaterialCommunityIcons\", name: \"heart-pulse\" },\n meditation: { family: \"MaterialCommunityIcons\", name: \"meditation\" },\n sleep: { family: \"MaterialCommunityIcons\", name: \"sleep\" },\n brain: { family: \"MaterialCommunityIcons\", name: \"brain\" },\n idea: { family: \"MaterialCommunityIcons\", name: \"lightbulb-on\" },\n money: { family: \"MaterialCommunityIcons\", name: \"cash\" },\n shopping: { family: \"MaterialCommunityIcons\", name: \"cart\" },\n gift: { family: \"MaterialCommunityIcons\", name: \"gift\" },\n home: { family: \"MaterialCommunityIcons\", name: \"home\" },\n car: { family: \"MaterialCommunityIcons\", name: \"car\" },\n pet: { family: \"MaterialCommunityIcons\", name: \"paw\" },\n plant: { family: \"MaterialCommunityIcons\", name: \"sprout\" },\n sun: { family: \"MaterialCommunityIcons\", name: \"white-balance-sunny\" },\n moon: { family: \"MaterialCommunityIcons\", name: \"weather-night\" },\n globe: { family: \"MaterialCommunityIcons\", name: \"earth\" },\n \"map-pin\": { family: \"MaterialCommunityIcons\", name: \"map-marker\" },\n compass: { family: \"MaterialCommunityIcons\", name: \"compass\" },\n flag: { family: \"MaterialCommunityIcons\", name: \"flag\" },\n bookmark: { family: \"MaterialCommunityIcons\", name: \"bookmark\" },\n bell: { family: \"MaterialCommunityIcons\", name: \"bell\" },\n mail: { family: \"MaterialCommunityIcons\", name: \"email\" },\n phone: { family: \"MaterialCommunityIcons\", name: \"phone\" },\n chat: { family: \"MaterialCommunityIcons\", name: \"chat\" },\n user: { family: \"MaterialCommunityIcons\", name: \"account\" },\n users: { family: \"MaterialCommunityIcons\", name: \"account-group\" },\n settings: { family: \"MaterialCommunityIcons\", name: \"cog\" },\n tools: { family: \"MaterialCommunityIcons\", name: \"tools\" },\n puzzle: { family: \"MaterialCommunityIcons\", name: \"puzzle\" },\n chart: { family: \"MaterialCommunityIcons\", name: \"chart-line\" },\n shield: { family: \"MaterialCommunityIcons\", name: \"shield-check\" },\n lock: { family: \"MaterialCommunityIcons\", name: \"lock\" },\n cloud: { family: \"MaterialCommunityIcons\", name: \"cloud\" },\n pencil: { family: \"MaterialCommunityIcons\", name: \"pencil\" },\n check: { family: \"MaterialCommunityIcons\", name: \"check-circle\" },\n plus: { family: \"MaterialCommunityIcons\", name: \"plus-circle\" },\n question: { family: \"MaterialCommunityIcons\", name: \"help-circle\" },\n other: { family: \"MaterialCommunityIcons\", name: \"dots-horizontal-circle\" },\n} as const satisfies Record<string, WireIconGlyph>;\n\n/** A name in the vocabulary. The card schemas accept any string and degrade — see `WireIcon`. */\nexport type WireIconName = keyof typeof WIRE_ICON_GLYPHS;\n\n/**\n * Every semantic name, as a plain array — the list to paste into the server/AI prompt as the\n * allowed `icon` values. Sorted for a stable, diffable prompt.\n */\nexport const WIRE_ICON_NAMES: readonly string[] = Object.keys(WIRE_ICON_GLYPHS).sort();\n\n/**\n * Look up a semantic name. Returns undefined for anything outside the vocabulary.\n *\n * The OWN-property check is load-bearing, not defensive noise: the name comes from an LLM, and\n * a plain object lookup answers `\"toString\"` / `\"constructor\"` / `\"valueOf\"` with an inherited\n * `Object.prototype` member. That would hand back a function where a `{family, name}` is\n * expected — a non-glyph masquerading as one. Caught by the vocabulary canary.\n */\nexport const lookupIconGlyph = (name: string | undefined): WireIconGlyph | undefined => {\n if (!name) return undefined;\n if (!Object.prototype.hasOwnProperty.call(WIRE_ICON_GLYPHS, name)) return undefined;\n return (WIRE_ICON_GLYPHS as Record<string, WireIconGlyph>)[name];\n};\n","/**\n * WireIcon — render one semantic icon name, or nothing at all.\n *\n * RESOLUTION ORDER (each step falls through to the next, never throws):\n * 1. the host `icons` registry — brand artwork, zero kit deps (IconRegistry.tsx)\n * 2. `@expo/vector-icons` — if the optional peer resolves (expoIcons.ts)\n * 3. NOTHING — render null\n *\n * Step 3 is a FEATURE, not a failure mode. The AI emits icon names from a vocabulary that will\n * keep growing, against production apps that ship on their own schedule (new store builds only,\n * never OTA, so they cannot be force-updated). So an unknown, misspelled, hallucinated, or\n * simply newer-than-this-client name MUST be a no-op: no crash, no broken-glyph tofu box, and\n * no layout shift. Returning `null` (rather than a spacer or a placeholder) is what gives the\n * last property — a row with an unresolvable icon lays out EXACTLY like a row with no icon,\n * because the parent's flex `gap` adds no space for a null child.\n *\n * An icon is always DECORATIVE: the label carries the meaning, so the icon is hidden from\n * assistive tech and never becomes the accessible name of its option.\n */\nimport React from \"react\";\nimport { StyleSheet, View } from \"react-native\";\n\nimport { resolveIconFamily, type OptionalRequire } from \"./expoIcons\";\nimport { useHostIcon } from \"./IconRegistry\";\nimport { lookupIconGlyph } from \"./vocabulary\";\n\nexport type WireIconProps = {\n /** A semantic name from the vocabulary (see vocabulary.ts). Unknown → renders nothing. */\n name?: string;\n /** Glyph size in px. */\n size?: number;\n /** Glyph color. Callers pass a THEME token — never a raw hex. */\n color?: string;\n /** Injectable resolver. TEST-ONLY seam; production uses the guarded runtime require. */\n requireModule?: OptionalRequire;\n};\n\nconst _WireIcon: React.FC<WireIconProps> = ({ name, size = 20, color, requireModule }) => {\n // 1) Host artwork wins — it can also cover names outside the vocabulary entirely.\n const hostIcon = useHostIcon(name);\n if (hostIcon) {\n return (\n <View\n style={styles.decorative}\n accessible={false}\n importantForAccessibility=\"no-hide-descendants\"\n >\n {hostIcon}\n </View>\n );\n }\n\n // 2) The vocabulary → a concrete glyph, then the optional peer. Both may miss; both degrade.\n const glyph = lookupIconGlyph(name);\n if (!glyph) return null;\n\n const Family = resolveIconFamily(glyph.family, requireModule);\n if (!Family) return null;\n\n return (\n <View\n style={styles.decorative}\n accessible={false}\n importantForAccessibility=\"no-hide-descendants\"\n >\n <Family\n name={glyph.name}\n size={size}\n color={color}\n // Icons are sized by the layout, not the text scale — a large accessibility font must\n // not blow up a card grid. The LABEL still scales, which is what carries the meaning.\n allowFontScaling={false}\n />\n </View>\n );\n};\n\nexport const WireIcon = React.memo(_WireIcon);\nWireIcon.displayName = \"WireIcon\";\n\nconst styles = StyleSheet.create({\n // No size/margin of its own: the glyph decides its footprint, so an absent icon and a\n // present one differ by exactly the glyph — never by a wrapper.\n decorative: {},\n});\n","/**\n * The shared option shape for the choice cards (SelectionCard, CardGridSelectCard).\n *\n * ── BACK-COMPAT, IN BOTH DIRECTIONS (the hard gate) ──────────────────────────────────────\n *\n * NEW option → OLD kit: `z.object` STRIPS unknown keys, and the SDK renderer mounts\n * `parsed.data` (not the raw props — see wireai-rn `renderer/ComponentRenderer.tsx`). So a\n * client on kit 0.7.x that receives `{value, label, icon}` silently drops `icon` and renders\n * the plain row it always did. No throw, no fallback card. This is what makes it safe to teach\n * the server `icon` before every host has re-pinned — and it MUST stay true, so never make\n * this schema `.strict()`.\n *\n * OLD option → NEW kit: the `preprocess` still coerces a bare `\"Spring\"` into\n * `{value:\"Spring\", label:\"Spring\"}`, exactly as before. A bare string and a bare\n * `{value,label}` both keep working untouched.\n *\n * `icon` is a plain `z.string()`, NOT a z.enum of the vocabulary. Deliberate: an unknown name\n * must degrade to no icon (WireIcon does that), never fail validation. If it were an enum, one\n * hallucinated or newer-than-this-client icon name would turn the whole card into a\n * LLM_SCHEMA_ERROR and cost the user their question — a catastrophic trade for a decoration.\n */\nimport { z } from \"zod\";\n\nimport { WIRE_ICON_NAMES } from \"../icons/vocabulary\";\n\n/**\n * The icon `.describe()` — an LLM ROUTING INSTRUCTION, not a type label (frequent_rules #4).\n * The vocabulary is inlined so the model reads the allowed values right where it fills the\n * field, and the list stays generated from the SSOT rather than drifting in a hand-typed copy.\n */\nexport const ICON_FIELD_DESCRIPTION =\n \"Optional icon for this option, making the choice scannable at a glance. Pick the ONE name \" +\n \"whose meaning matches the option (e.g. 'instagram' for an Instagram answer, 'friend' for \" +\n \"'A friend told me', 'wedding' for a wedding). Omit it when no name fits — a wrong icon is \" +\n `worse than none. Allowed values: ${WIRE_ICON_NAMES.join(\", \")}.`;\n\nexport const optionObjectSchema = z.object({\n value: z.string().describe(\"Option value\"),\n label: z.string().describe(\"Option display label\"),\n icon: z.string().optional().describe(ICON_FIELD_DESCRIPTION),\n});\n\nexport type CardOption = z.infer<typeof optionObjectSchema>;\n\n/** A bare string stays a valid option: coerce it to `{value, label}` before validating. */\nconst coerceOptions = (arr: unknown) =>\n Array.isArray(arr)\n ? arr.map((item) => (typeof item === \"string\" ? { value: item, label: item } : item))\n : arr;\n\n/** The `options` field, with its card-specific routing description. */\nexport const optionsField = (description: string) =>\n z.preprocess(coerceOptions, z.array(optionObjectSchema).min(1)).describe(description);\n\n/**\n * Component-level tolerance for the SAME coercion the schema does.\n *\n * WHY BOTH: in production the SDK renderer re-parses props and hands the card `parsed.data`, so\n * options arrive normalized. But a card is a plain exported component — the canary suite and any\n * host composing it directly mount it with raw props, where a bare string would otherwise read\n * `opt.value === undefined` and render an empty, unkeyed row. Cheap, total, and keeps the\n * component honest on its own contract instead of relying on a caller that may not exist.\n */\nexport const normalizeOptions = (options: ReadonlyArray<string | CardOption>): CardOption[] =>\n options.map((opt) => (typeof opt === \"string\" ? { value: opt, label: opt } : opt));\n","/**\n * Themed SelectionCard — drop-in for the OSS SDK's SelectionCard. Same `name`,\n * `propsSchema` (including the string|object option preprocess), `defaultProps`,\n * and `onSelect(string | string[])` contract. Radio/checkbox styling is themed.\n *\n * Motion (design-refs/EXTRACTED-SPEC.md rows 1-3): rows tick on press (scale\n * 0.975 spring), the selected fill/border eases in over 180ms ease-wire (a\n * native-driver opacity crossfade of a selected-style overlay), and the check\n * dot pops with a spring. All gated by useReducedMotion (snap, no spring).\n */\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, Pressable, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { labelStyle } from \"../theme/typography\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\nimport { WireIcon } from \"../icons/WireIcon\";\nimport { normalizeOptions, optionsField, type CardOption } from \"./optionSchema\";\nimport {\n CHECK_SCALE_FROM,\n CHECK_SPRING,\n PRESS_SPRING,\n ROW_PRESS_SCALE,\n SELECT_FILL_MS,\n WIRE_BEZIER,\n scaledMs,\n stateChangeDuration,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\n\nconst schema = z.object({\n title: z.string().describe(\"Question or prompt for the user\"),\n options: optionsField(\"List of choices\"),\n submitLabel: z.string().optional().describe(\"Submit button label, default: Continue\"),\n multiSelect: z.boolean().optional().describe(\"Allow multiple selections\"),\n});\n\ntype Props = Omit<z.infer<typeof schema>, \"options\"> &\n InjectedProps & {\n /** Bare strings stay valid (normalized on the way in) — see optionSchema.ts. */\n options: ReadonlyArray<string | CardOption>;\n onSelect?: (selected: string | string[]) => void;\n /** Fires as the live selection changes (before Continue), so the flow can prefetch the\n * next turn. Same value shape as onSelect. Optional — injected by OnboardingFlow. */\n onSelectionChange?: (selected: string | string[]) => void;\n };\n\ntype OptionRowProps = {\n opt: CardOption;\n isSelected: boolean;\n multiSelect: boolean;\n onToggle: (value: string) => void;\n};\n\nconst _OptionRow: React.FC<OptionRowProps> = ({ opt, isSelected, multiSelect, onToggle }) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const handlePress = useCallback(() => onToggle(opt.value), [opt.value, onToggle]);\n\n // Press tick: scale 1→0.975, spring, native driver. Skipped under reduce motion.\n const pressScale = useRef(new Animated.Value(1)).current;\n const pressTo = useCallback(\n (to: number) => {\n if (reduced) return;\n Animated.spring(pressScale, {\n toValue: to,\n friction: PRESS_SPRING.friction,\n tension: PRESS_SPRING.tension,\n useNativeDriver: true,\n }).start();\n },\n [pressScale, reduced],\n );\n const handlePressIn = useCallback(() => pressTo(ROW_PRESS_SCALE), [pressTo]);\n const handlePressOut = useCallback(() => pressTo(1), [pressTo]);\n\n // Selected fill: the selected border+bg live on an absolute overlay whose opacity\n // crossfades in 180ms ease-wire — same visual as a color interpolation, but it\n // stays on the native driver. Reduce motion: snap.\n const selectT = useRef(new Animated.Value(isSelected ? 1 : 0)).current;\n useEffect(() => {\n const anim = Animated.timing(selectT, {\n toValue: isSelected ? 1 : 0,\n duration: scaledMs(stateChangeDuration(reduced, SELECT_FILL_MS)),\n easing: easeWire,\n useNativeDriver: true,\n });\n anim.start();\n return () => anim.stop();\n }, [isSelected, reduced, selectT]);\n\n // Check pop: scale 0.6→1 + fade, springy. Reduce motion: shown at scale 1 instantly.\n const checkT = useRef(new Animated.Value(isSelected ? 1 : 0)).current;\n useEffect(() => {\n if (!isSelected) {\n checkT.setValue(0);\n return;\n }\n if (reduced) {\n checkT.setValue(1);\n return;\n }\n checkT.setValue(0);\n const anim = Animated.spring(checkT, {\n toValue: 1,\n friction: CHECK_SPRING.friction,\n tension: CHECK_SPRING.tension,\n useNativeDriver: true,\n });\n anim.start();\n return () => anim.stop();\n }, [isSelected, reduced, checkT]);\n\n const checkScale = checkT.interpolate({ inputRange: [0, 1], outputRange: [CHECK_SCALE_FROM, 1] });\n\n return (\n <Pressable\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n accessibilityRole={multiSelect ? \"checkbox\" : \"radio\"}\n accessibilityState={multiSelect ? { checked: isSelected } : { selected: isSelected }}\n accessibilityLabel={opt.label}\n >\n <Animated.View\n style={[\n styles.option,\n {\n padding: t.spacing.md,\n borderRadius: t.radius.md,\n gap: t.spacing.sm,\n borderColor: t.colors.border,\n backgroundColor: t.colors.background,\n transform: [{ scale: pressScale }],\n },\n ]}\n >\n <Animated.View\n pointerEvents=\"none\"\n style={[\n StyleSheet.absoluteFill,\n styles.selectedOverlay,\n {\n borderRadius: t.radius.md,\n borderColor: t.colors.primary,\n backgroundColor: t.colors.primarySoft,\n opacity: selectT,\n },\n ]}\n />\n <View\n style={[\n styles.indicator,\n { borderRadius: t.radius.full },\n isSelected\n ? { borderColor: t.colors.primary, backgroundColor: t.colors.primary }\n : { borderColor: t.colors.borderStrong, backgroundColor: \"transparent\" },\n ]}\n >\n {isSelected ? (\n <Animated.Text\n style={[\n styles.check,\n { color: t.colors.onPrimary, opacity: checkT, transform: [{ scale: checkScale }] },\n ]}\n >\n ✓\n </Animated.Text>\n ) : null}\n </View>\n {/* Accent discipline: the label keeps the text color in both states; the\n accent lives on the border, fill, and dot only. The icon obeys the same rule —\n it holds `text` in BOTH states rather than flipping to the accent, because an\n icon is not an excuse to invent a second accent. Decorative + unresolvable-safe:\n an unknown name renders null, so the row lays out exactly as an icon-less one. */}\n <WireIcon name={opt.icon} size={20} color={t.colors.text} />\n <Text style={[labelStyle(t.fonts), { color: t.colors.text }]}>{opt.label}</Text>\n </Animated.View>\n </Pressable>\n );\n};\nconst OptionRow = React.memo(_OptionRow);\n\nconst _SelectionCard: React.FC<Props> = ({\n title,\n options,\n submitLabel = \"Continue\",\n multiSelect = false,\n onSelect,\n onSelectionChange,\n}) => {\n const t = useOnboardingTheme();\n const opts = React.useMemo(() => normalizeOptions(options), [options]);\n const [selected, setSelected] = useState<string[]>([]);\n const [submitted, setSubmitted] = useState(false);\n\n // Report the settled selection upward (before Continue) so the flow can prefetch the next\n // turn. Debouncing lives in the flow; here we just emit on every change once something's picked.\n useEffect(() => {\n if (!submitted && selected.length) onSelectionChange?.(multiSelect ? selected : selected[0]!);\n }, [selected, submitted, multiSelect, onSelectionChange]);\n\n const toggle = useCallback(\n (value: string) => {\n if (submitted) return;\n if (multiSelect) {\n setSelected((prev) => (prev.includes(value) ? prev.filter((v) => v !== value) : [...prev, value]));\n } else {\n setSelected([value]);\n }\n },\n [submitted, multiSelect],\n );\n\n const handleSubmit = useCallback(() => {\n if (!selected.length || !onSelect || submitted) return;\n setSubmitted(true);\n onSelect(multiSelect ? selected : selected[0]!);\n }, [selected, onSelect, submitted, multiSelect]);\n\n return (\n <CardLayout\n title={title}\n footer={\n <Button\n title={submitLabel}\n onPress={handleSubmit}\n variant=\"primary\"\n disabled={selected.length === 0 || submitted}\n />\n }\n >\n <View style={{ gap: t.spacing.sm + t.spacing.xs }}>\n {opts.map((opt) => (\n <OptionRow\n key={opt.value}\n opt={opt}\n isSelected={selected.includes(opt.value)}\n multiSelect={multiSelect}\n onToggle={toggle}\n />\n ))}\n </View>\n </CardLayout>\n );\n};\n\nexport const SelectionCard: WireAIComponent = {\n name: \"SelectionCard\",\n description:\n \"Use for mutually exclusive (radio) or multi-select (checkbox) choices from 2–8 options, as a vertical list of rows. Best when options are wordy or need reading. Options may carry an optional `icon` from the vocabulary to make the list scannable. Use ChipSelectCard instead when options are short single words; use CardGridSelectCard when the options are visual and each has an obvious icon (occasions, channels, categories).\",\n component: React.memo(_SelectionCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n defaultProps: { submitLabel: \"Continue\", multiSelect: false },\n};\n\nconst styles = StyleSheet.create({\n option: { borderWidth: 1.5, flexDirection: \"row\", alignItems: \"center\", overflow: \"hidden\" },\n selectedOverlay: { borderWidth: 1.5 },\n indicator: { width: 24, height: 24, borderWidth: 2, alignItems: \"center\", justifyContent: \"center\" },\n check: { fontSize: 13, fontWeight: \"800\", lineHeight: 15 },\n});\n","/**\n * CardGridSelectCard — icon-led choices as a two-column grid of small cards.\n *\n * The shape Malik asked for (2026-07-16): \"the multi select needs to be a small card like this\n * one, with an icon on top, it is much better.\" Icon top-left, short label beneath, the whole\n * card is the tap target, selection lives on the card itself.\n *\n * ┌──────────────┐ ┌──────────────┐\n * │ ◇ │ │ ▣ │ ← icon on top\n * │ Wedding day │ │ Birthday │ ← label beneath\n * └──────────────┘ └──────────────┘\n *\n * WHY A NEW CARD RATHER THAN A `display` MODE ON SelectionCard: the card's `description` IS the\n * router — it is the only thing the model reads when choosing (frequent_rules #4). SelectionCard\n * already carries two modes behind one description; a third (\"a list, but sometimes a grid, and\n * then the icons matter\") cannot be stated honestly in one string, and a muddy description makes\n * the model pick the wrong card. The kit already has the precedent: ChipSelectCard exists ONLY\n * because \"compact vs. descriptive\" is a presentation difference worth its own name, over the\n * very same pick-from-options job. Back-compat costs nothing here — `supportedComponents`\n * (WireOnboarding.tsx) means an already-shipped client never advertises this name, so the server\n * intersects it away and can never emit it to the apps already in the stores. See the CHANGELOG.\n *\n * Layout is percentage flex, never a measured width: `flexBasis` ~47% + `flexGrow` makes exactly\n * two per row that fill the width, with no Dimensions read, no onLayout, and no re-render on\n * rotation. An odd last card stretches the row — deliberate, and the same thing every native\n * grid does.\n *\n * Motion mirrors SelectionCard's OptionRow exactly (press tick spring + a native-driver opacity\n * crossfade of the selected overlay), so the two cards feel like one system.\n */\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, Pressable, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { labelStyle } from \"../theme/typography\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\nimport { WireIcon } from \"../icons/WireIcon\";\nimport { normalizeOptions, optionsField, type CardOption } from \"./optionSchema\";\nimport {\n PRESS_SPRING,\n ROW_PRESS_SCALE,\n SELECT_FILL_MS,\n WIRE_BEZIER,\n scaledMs,\n stateChangeDuration,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\n\nconst schema = z.object({\n title: z.string().describe(\"Question or prompt for the user, e.g. 'What brings you here?'\"),\n options: optionsField(\n \"The choices, 2-6 of them. Give EVERY option an `icon` from the vocabulary — the icon is \" +\n \"the point of this card, and an option without one renders as a bare label next to \" +\n \"icon-bearing neighbours. Keep labels short (1-3 words) so they fit a half-width card.\",\n ),\n submitLabel: z.string().optional().describe(\"Submit button label, default: Continue\"),\n multiSelect: z\n .boolean()\n .optional()\n .describe(\"Allow multiple cards selected at once, default true\"),\n});\n\ntype Props = Omit<z.infer<typeof schema>, \"options\"> &\n InjectedProps & {\n /** Bare strings stay valid (normalized on the way in) — see optionSchema.ts. */\n options: ReadonlyArray<string | CardOption>;\n onSelect?: (selected: string | string[]) => void;\n /** Fires as the live selection changes (before Continue), so the flow can prefetch the\n * next turn. Same value shape as onSelect. Optional — injected by OnboardingFlow. */\n onSelectionChange?: (selected: string | string[]) => void;\n };\n\ntype OptionCardProps = {\n opt: CardOption;\n isSelected: boolean;\n multiSelect: boolean;\n onToggle: (value: string) => void;\n};\n\nconst _OptionCard: React.FC<OptionCardProps> = ({ opt, isSelected, multiSelect, onToggle }) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const handlePress = useCallback(() => onToggle(opt.value), [opt.value, onToggle]);\n\n // Press tick: scale 1→0.975, spring, native driver. Skipped under reduce motion.\n const pressScale = useRef(new Animated.Value(1)).current;\n const pressTo = useCallback(\n (to: number) => {\n if (reduced) return;\n Animated.spring(pressScale, {\n toValue: to,\n friction: PRESS_SPRING.friction,\n tension: PRESS_SPRING.tension,\n useNativeDriver: true,\n }).start();\n },\n [pressScale, reduced],\n );\n const handlePressIn = useCallback(() => pressTo(ROW_PRESS_SCALE), [pressTo]);\n const handlePressOut = useCallback(() => pressTo(1), [pressTo]);\n\n // Selected fill: accent border + tinted wash on an absolute overlay whose opacity crossfades\n // (native driver, never a color interpolation). Reduce motion: snap.\n const selectT = useRef(new Animated.Value(isSelected ? 1 : 0)).current;\n useEffect(() => {\n const anim = Animated.timing(selectT, {\n toValue: isSelected ? 1 : 0,\n duration: scaledMs(stateChangeDuration(reduced, SELECT_FILL_MS)),\n easing: easeWire,\n useNativeDriver: true,\n });\n anim.start();\n return () => anim.stop();\n }, [isSelected, reduced, selectT]);\n\n return (\n <Pressable\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n accessibilityRole={multiSelect ? \"checkbox\" : \"radio\"}\n accessibilityState={multiSelect ? { checked: isSelected } : { selected: isSelected }}\n accessibilityLabel={opt.label}\n style={styles.cell}\n >\n <Animated.View\n style={[\n styles.card,\n {\n padding: t.spacing.md,\n borderRadius: t.radius.lg,\n gap: t.spacing.sm,\n borderColor: t.colors.border,\n backgroundColor: t.colors.surface,\n transform: [{ scale: pressScale }],\n },\n ]}\n >\n <Animated.View\n pointerEvents=\"none\"\n style={[\n StyleSheet.absoluteFill,\n styles.selectedOverlay,\n {\n borderRadius: t.radius.lg,\n borderColor: t.colors.primary,\n backgroundColor: t.colors.primarySoft,\n opacity: selectT,\n },\n ]}\n />\n {/* Accent discipline (same rule as SelectionCard's rows): label AND icon keep the text\n color in both states; the accent lives on the border and fill only. An unresolvable\n icon renders null, so a card with a bad name lays out like one with no icon. */}\n <WireIcon name={opt.icon} size={24} color={t.colors.text} />\n <Text style={[labelStyle(t.fonts), { color: t.colors.text }]}>{opt.label}</Text>\n </Animated.View>\n </Pressable>\n );\n};\nconst OptionCard = React.memo(_OptionCard);\n\nconst _CardGridSelectCard: React.FC<Props> = ({\n title,\n options,\n submitLabel = \"Continue\",\n multiSelect = true,\n onSelect,\n onSelectionChange,\n}) => {\n const t = useOnboardingTheme();\n const opts = React.useMemo(() => normalizeOptions(options), [options]);\n const [selected, setSelected] = useState<string[]>([]);\n const [submitted, setSubmitted] = useState(false);\n\n // Report the settled selection upward (before Continue) so the flow can prefetch the next\n // turn. Debouncing lives in the flow; here we just emit on every change once something's picked.\n useEffect(() => {\n if (!submitted && selected.length) onSelectionChange?.(multiSelect ? selected : selected[0]!);\n }, [selected, submitted, multiSelect, onSelectionChange]);\n\n const toggle = useCallback(\n (value: string) => {\n if (submitted) return;\n if (multiSelect) {\n setSelected((prev) =>\n prev.includes(value) ? prev.filter((v) => v !== value) : [...prev, value],\n );\n } else {\n setSelected([value]);\n }\n },\n [submitted, multiSelect],\n );\n\n const handleSubmit = useCallback(() => {\n if (!selected.length || !onSelect || submitted) return;\n setSubmitted(true);\n onSelect(multiSelect ? selected : selected[0]!);\n }, [selected, onSelect, submitted, multiSelect]);\n\n return (\n <CardLayout\n title={title}\n footer={\n <Button\n title={submitLabel}\n onPress={handleSubmit}\n variant=\"primary\"\n disabled={selected.length === 0 || submitted}\n />\n }\n >\n <View style={[styles.grid, { gap: t.spacing.sm }]}>\n {opts.map((opt) => (\n <OptionCard\n key={opt.value}\n opt={opt}\n isSelected={selected.includes(opt.value)}\n multiSelect={multiSelect}\n onToggle={toggle}\n />\n ))}\n </View>\n </CardLayout>\n );\n};\n\nexport const CardGridSelectCard: WireAIComponent = {\n name: \"CardGridSelectCard\",\n description:\n \"Use for VISUAL, icon-led choices shown as a 2-column grid of tappable cards (icon on top, \" +\n \"short label beneath). Ideal for 2–6 concrete options that each have an obvious icon — \" +\n \"occasions, channels, goals, categories — e.g. 'What brings you here?' or 'Where did you \" +\n \"hear about us?'. Multi-select by default. Every option should carry an `icon`. Use \" +\n \"SelectionCard instead when options need descriptions or have no natural icon; use \" +\n \"ChipSelectCard for many short word-like tags.\",\n component: React.memo(_CardGridSelectCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n defaultProps: { submitLabel: \"Continue\", multiSelect: true },\n};\n\nconst styles = StyleSheet.create({\n grid: { flexDirection: \"row\", flexWrap: \"wrap\" },\n // Two per row: ~47% basis leaves room for the gap, flexGrow fills the remainder exactly.\n cell: { flexBasis: \"47%\", flexGrow: 1 },\n card: { borderWidth: 1.5, alignItems: \"flex-start\", overflow: \"hidden\" },\n selectedOverlay: { borderWidth: 1.5 },\n});\n","/**\n * Themed StatusCard — drop-in for the OSS SDK's StatusCard. Same `name`,\n * `propsSchema`, and the onContinue/onPress/onSubmit callback fallback chain.\n * The terminal StatusCard is what OnboardingFlow treats as \"flow complete\".\n * Status colors read from the theme's semantic palette.\n *\n * Motion (design-refs/EXTRACTED-SPEC.md rows 14, 16): the status glyph pops in\n * with a spring (scale 0.4→1, overshoot) and the copy fades up 80ms behind it.\n * Reduce motion: final frame instantly. (The terminal payoff with the burst is\n * CompletionView; this card is the inline status treatment.)\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { Animated, Easing, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { bodyStyle, headingStyle } from \"../theme/typography\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\nimport {\n STATUS_COPY_MS,\n STATUS_COPY_STAGGER_MS,\n STATUS_POP_SCALE_FROM,\n STATUS_POP_SPRING,\n WIRE_BEZIER,\n scaledMs,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\n\nconst schema = z.object({\n status: z.enum([\"success\", \"warning\", \"error\", \"info\"]).describe(\"Status type\"),\n title: z.string().describe(\"Status title\"),\n message: z.string().optional().describe(\"Supporting message\"),\n ctaLabel: z\n .string()\n .optional()\n .describe(\n \"Optional call-to-action button label. Always include this on success status to keep the conversation going.\",\n ),\n});\n\ntype Props = z.infer<typeof schema> &\n InjectedProps & {\n onContinue?: () => void;\n onPress?: (label: string) => void;\n onSubmit?: (value: string) => void;\n };\n\nconst STATUS_ICONS: Record<string, string> = {\n success: \"✓\",\n warning: \"⚠\",\n error: \"✗\",\n info: \"ℹ\",\n};\n\nconst _StatusCard: React.FC<Props> = ({ status, title, message, ctaLabel, onContinue, onPress, onSubmit }) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const [submitted, setSubmitted] = useState(false);\n\n const color = useMemo(() => {\n switch (status) {\n case \"success\":\n return t.colors.success;\n case \"warning\":\n return t.colors.warning;\n case \"error\":\n return t.colors.error;\n default:\n return t.colors.info;\n }\n }, [status, t.colors]);\n\n // Glyph pop + copy fade-up (final frame under reduce motion).\n const popT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const copyT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n useEffect(() => {\n if (reduced) {\n popT.setValue(1);\n copyT.setValue(1);\n return;\n }\n const anims = [\n Animated.spring(popT, {\n toValue: 1,\n friction: STATUS_POP_SPRING.friction,\n tension: STATUS_POP_SPRING.tension,\n useNativeDriver: true,\n }),\n Animated.timing(copyT, {\n toValue: 1,\n duration: scaledMs(STATUS_COPY_MS),\n delay: scaledMs(STATUS_COPY_STAGGER_MS),\n easing: easeWire,\n useNativeDriver: true,\n }),\n ];\n anims.forEach((a) => a.start());\n return () => anims.forEach((a) => a.stop());\n }, [reduced, popT, copyT]);\n\n const popScale = popT.interpolate({ inputRange: [0, 1], outputRange: [STATUS_POP_SCALE_FROM, 1] });\n const copyRise = copyT.interpolate({ inputRange: [0, 1], outputRange: [10, 0] });\n\n const handleContinue = useCallback(() => {\n if (!submitted) {\n setSubmitted(true);\n if (onContinue) onContinue();\n else if (onPress && ctaLabel) onPress(ctaLabel);\n else if (onSubmit) onSubmit(\"continue\");\n }\n }, [submitted, onContinue, onPress, onSubmit, ctaLabel]);\n\n return (\n <CardLayout\n align=\"center\"\n footer={\n ctaLabel ? (\n <Button title={ctaLabel} onPress={handleContinue} variant=\"primary\" disabled={submitted} />\n ) : undefined\n }\n >\n <View style={[styles.center, { gap: t.spacing.sm }]}>\n <View style={[styles.titleRow, { gap: t.spacing.sm }]}>\n <Animated.Text\n style={[\n headingStyle(t.fonts),\n { color, opacity: popT, transform: [{ scale: popScale }] },\n ]}\n >\n {STATUS_ICONS[status] ?? \"·\"}\n </Animated.Text>\n <Animated.Text\n style={[\n headingStyle(t.fonts),\n { color, textAlign: \"center\", opacity: copyT, transform: [{ translateY: copyRise }] },\n ]}\n >\n {title}\n </Animated.Text>\n </View>\n {message ? (\n <Animated.Text\n style={[\n bodyStyle(t.fonts),\n {\n color: t.colors.textMuted,\n textAlign: \"center\",\n opacity: copyT,\n transform: [{ translateY: copyRise }],\n },\n ]}\n >\n {message}\n </Animated.Text>\n ) : null}\n </View>\n </CardLayout>\n );\n};\n\nexport const StatusCard: WireAIComponent = {\n name: \"StatusCard\",\n description:\n \"Use ONLY for real outcomes: booking confirmed, data saved, action completed. NEVER for 'you just viewed X' acknowledgments. Always include ctaLabel so the user can continue after seeing the status.\",\n component: React.memo(_StatusCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n};\n\nconst styles = StyleSheet.create({\n center: { width: \"100%\", alignItems: \"center\", justifyContent: \"center\" },\n titleRow: { flexDirection: \"row\", alignItems: \"center\", justifyContent: \"center\" },\n});\n","/**\n * Themed NumberStepperCard — drop-in for the OSS SDK's NumberStepperCard. Same\n * `name`, `propsSchema`, `defaultProps`, and `onSubmit(value: number)` contract.\n * Keeps the SDK's defensive numeric coercion so a malformed LLM payload can never\n * feed NaN/Infinity into layout math.\n */\nimport React, { useCallback, useMemo, useState } from \"react\";\nimport { Pressable, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport type { OnboardingTheme } from \"../theme/types\";\nimport { captionStyle, headingStyle } from \"../theme/typography\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\n\nconst schema = z.object({\n label: z.string().describe(\"What is being counted, e.g. 'Number of days' or 'Travellers'\"),\n min: z.number().optional().describe(\"Minimum value, default 1\"),\n max: z.number().optional().describe(\"Maximum value, default 30\"),\n defaultValue: z.number().optional().describe(\"Starting value\"),\n step: z.number().optional().describe(\"Increment per tap, default 1\"),\n unit: z.string().optional().describe(\"Unit label shown next to value, e.g. 'days' or 'people'\"),\n submitLabel: z.string().optional().describe(\"Confirm button label, default: Confirm\"),\n});\n\ntype Props = z.infer<typeof schema> &\n InjectedProps & {\n onSubmit?: (value: number) => void;\n };\n\nconst safeNum = (n: unknown, fallback: number): number =>\n typeof n === \"number\" && Number.isFinite(n) ? n : fallback;\n\nconst _NumberStepperCard: React.FC<Props> = ({\n label,\n min,\n max,\n defaultValue,\n step,\n unit,\n submitLabel = \"Confirm\",\n onSubmit,\n}) => {\n const t = useOnboardingTheme();\n const styles = useMemo(() => makeStyles(t), [t]);\n\n const safeMin = safeNum(min, 1);\n const safeMaxRaw = safeNum(max, 30);\n const safeMax = safeMaxRaw < safeMin ? safeMin : safeMaxRaw;\n const safeStepRaw = safeNum(step, 1);\n const safeStep = safeStepRaw > 0 ? safeStepRaw : 1;\n const safeDefault = safeNum(defaultValue, safeMin);\n\n const [value, setValue] = useState(Math.min(Math.max(safeDefault, safeMin), safeMax));\n const [submitted, setSubmitted] = useState(false);\n\n const handleDecrement = useCallback(() => {\n if (!submitted) setValue((v) => Math.max(v - safeStep, safeMin));\n }, [submitted, safeStep, safeMin]);\n\n const handleIncrement = useCallback(() => {\n if (!submitted) setValue((v) => Math.min(v + safeStep, safeMax));\n }, [submitted, safeStep, safeMax]);\n\n const handleSubmit = useCallback(() => {\n if (!submitted) {\n setSubmitted(true);\n onSubmit?.(value);\n }\n }, [submitted, onSubmit, value]);\n\n const atMin = value <= safeMin;\n const atMax = value >= safeMax;\n\n const stepBtnStyle = (disabled: boolean) => [\n styles.stepBtn,\n { borderRadius: t.radius.full, backgroundColor: t.colors.background, borderColor: disabled ? t.colors.border : t.colors.primary },\n ];\n\n return (\n <CardLayout\n title={label}\n align=\"center\"\n footer={\n <Button title={submitLabel} onPress={handleSubmit} variant=\"primary\" disabled={submitted} />\n }\n >\n <View style={styles.wrap}>\n <View style={[styles.stepper, { gap: t.spacing.lg }]}>\n <Pressable onPress={atMin || submitted ? undefined : handleDecrement} disabled={atMin || submitted} style={stepBtnStyle(atMin)}>\n <Text style={[headingStyle(t.fonts), { color: atMin ? t.colors.textMuted : t.colors.primary }]}>{\"−\"}</Text>\n </Pressable>\n <View style={styles.valueBox}>\n <Text style={[headingStyle(t.fonts), { color: t.colors.primary }]}>{String(value)}</Text>\n {unit ? <Text style={[captionStyle(t.fonts), { color: t.colors.textMuted }]}>{unit}</Text> : null}\n </View>\n <Pressable onPress={atMax || submitted ? undefined : handleIncrement} disabled={atMax || submitted} style={stepBtnStyle(atMax)}>\n <Text style={[headingStyle(t.fonts), { color: atMax ? t.colors.textMuted : t.colors.primary }]}>{\"+\"}</Text>\n </Pressable>\n </View>\n <Text style={[captionStyle(t.fonts), { color: t.colors.textMuted, textAlign: \"center\" }]}>\n {`${safeMin} – ${safeMax}${unit ? ` ${unit}` : \"\"}`}\n </Text>\n </View>\n </CardLayout>\n );\n};\n\nexport const NumberStepperCard: WireAIComponent = {\n name: \"NumberStepperCard\",\n description:\n \"Use for any bounded numeric input: days, people, portions, budget tiers, ratings. Best for ranges 1–99. Set unit (e.g. 'days', 'people') for clarity.\",\n component: React.memo(_NumberStepperCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n defaultProps: { min: 1, max: 30, defaultValue: 1, step: 1, submitLabel: \"Confirm\" },\n};\n\nfunction makeStyles(t: OnboardingTheme) {\n return StyleSheet.create({\n wrap: { gap: t.spacing.md, alignItems: \"center\" },\n stepper: { flexDirection: \"row\", alignItems: \"center\", justifyContent: \"center\" },\n stepBtn: { width: 44, height: 44, borderWidth: 2, alignItems: \"center\", justifyContent: \"center\" },\n valueBox: { alignItems: \"center\", minWidth: 80 },\n });\n}\n","/**\n * InterstitialCard — a mid-flow \"value\" screen (the Duolingo / Cal-AI beat): an\n * illustration + a short motivational line + a single Continue button. It is NOT a\n * question — it builds momentum and reinforces what the user is committing to,\n * which is one of the biggest retention levers in great onboarding.\n *\n * Artwork resolves in order so the screen is NEVER a blank box: the host's named\n * `illustration` (brand SVG/Lottie, keeping the kit dependency-free) → a\n * backend-supplied `imageUrl` via RN <Image> (which self-heals to art on load\n * error) → a named `illustrationFallback` (defaults to \"momentum\", always present\n * in the kit's default registry).\n *\n * A minimum display window keeps the momentum beat from flashing past when the next\n * card is already cached: Continue is disabled for MIN_DISPLAY_MS after mount.\n *\n * Motion (design-refs/EXTRACTED-SPEC.md rows 11-13): art and title fade-up in\n * sequence (500ms ease-wire, 100ms stagger); the optional `items` (short lines\n * referencing what the user already said) tick on one by one (90ms stagger),\n * each check popping 200ms after its row — \"work being done\", not a slideshow.\n * Reduce motion: everything rendered at its final frame at once.\n *\n * On Continue it sends \"continue\" back to the backend so the flow advances; the\n * submitted-state guard makes the tap idempotent.\n */\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Animated, Easing, Image, StyleSheet, Text, View } from \"react-native\";\nimport { z } from \"zod\";\nimport type { InjectedProps, WireAIComponent } from \"wireai-rn\";\nimport { useOnboardingTheme } from \"../theme/ThemeContext\";\nimport { bodyStyle, headingStyle } from \"../theme/typography\";\nimport { useIllustration } from \"../components/Illustration\";\nimport { Button } from \"../components/Button\";\nimport { CardLayout } from \"../components/CardLayout\";\nimport {\n CHECK_SPRING,\n INTERSTITIAL_CHECK_SCALE_FROM,\n INTERSTITIAL_HEAD_MS,\n INTERSTITIAL_HEAD_STAGGER_MS,\n INTERSTITIAL_ITEM_MS,\n WIRE_BEZIER,\n interstitialCheckDelay,\n scaledMs,\n interstitialItemDelay,\n} from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\n\nconst easeWire = Easing.bezier(...WIRE_BEZIER);\nconst RISE_PX = 10;\n\nconst schema = z.object({\n title: z.string().describe(\"Short, warm headline for the value/momentum moment\"),\n body: z\n .string()\n .optional()\n .describe(\"One or two supporting lines that reflect the user's answers back and build momentum\"),\n items: z\n .array(z.string())\n .max(4)\n .optional()\n .describe(\n \"2-3 very short 'work being done' lines that each reference something the user already answered (e.g. 'Sized for a small team'). Shown as ticked items appearing in sequence. Prefer these over `body` when you have concrete answers to reflect back.\",\n ),\n illustration: z\n .string()\n .optional()\n .describe(\n \"Name of an app-provided illustration to show (the app's registry decides the artwork). Prefer this over imageUrl.\",\n ),\n imageUrl: z\n .string()\n .url()\n .refine((v) => v.startsWith(\"https://\"), \"imageUrl must be an https URL\")\n .optional()\n .describe(\n \"Fallback remote HTTPS image URL, used only when no named illustration is registered. A non-https or malformed value is rejected and degrades to the named-illustration fallback.\",\n ),\n illustrationFallback: z\n .string()\n .optional()\n .describe(\n \"Named illustration to show when neither `illustration` nor `imageUrl` resolves (or the image fails to load). Defaults to the kit's always-present 'momentum' art so the screen is never blank.\",\n ),\n ctaLabel: z.string().optional().describe(\"Continue button label, default: Continue\"),\n});\n\n// Minimum time the momentum screen stays interactive-locked, so it never flashes past\n// when the next card is already prefetched/cached.\nconst MIN_DISPLAY_MS = 500;\n\ntype Props = z.infer<typeof schema> &\n InjectedProps & {\n onSubmit?: (value: string) => void;\n onPress?: (label: string) => void;\n };\n\n/** One ticked \"work\" row: fades up on its stagger slot, then the check pops. */\nconst _WorkItem: React.FC<{ text: string; index: number; reduced: boolean }> = ({\n text,\n index,\n reduced,\n}) => {\n const t = useOnboardingTheme();\n const rowT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const checkT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n\n useEffect(() => {\n if (reduced) {\n rowT.setValue(1);\n checkT.setValue(1);\n return;\n }\n const anims = [\n Animated.timing(rowT, {\n toValue: 1,\n duration: scaledMs(INTERSTITIAL_ITEM_MS),\n delay: scaledMs(interstitialItemDelay(index)),\n easing: easeWire,\n useNativeDriver: true,\n }),\n Animated.spring(checkT, {\n toValue: 1,\n delay: scaledMs(interstitialCheckDelay(index)),\n friction: CHECK_SPRING.friction,\n tension: CHECK_SPRING.tension,\n useNativeDriver: true,\n }),\n ];\n anims.forEach((a) => a.start());\n return () => anims.forEach((a) => a.stop());\n }, [reduced, index, rowT, checkT]);\n\n const rise = rowT.interpolate({ inputRange: [0, 1], outputRange: [RISE_PX, 0] });\n const checkScale = checkT.interpolate({\n inputRange: [0, 1],\n outputRange: [INTERSTITIAL_CHECK_SCALE_FROM, 1],\n });\n\n return (\n <Animated.View\n style={[styles.itemRow, { gap: t.spacing.sm + t.spacing.xs, opacity: rowT, transform: [{ translateY: rise }] }]}\n >\n <View\n style={[\n styles.itemBadge,\n { backgroundColor: t.colors.primarySoft, borderRadius: t.radius.full },\n ]}\n >\n <Animated.Text\n style={[\n styles.itemCheck,\n { color: t.colors.primary, opacity: checkT, transform: [{ scale: checkScale }] },\n ]}\n >\n ✓\n </Animated.Text>\n </View>\n <Text style={[bodyStyle(t.fonts), styles.itemText, { color: t.colors.text }]}>{text}</Text>\n </Animated.View>\n );\n};\nconst WorkItem = React.memo(_WorkItem);\n\nconst _InterstitialCard: React.FC<Props> = ({\n title,\n body,\n items,\n illustration,\n imageUrl,\n illustrationFallback,\n ctaLabel = \"Continue\",\n onSubmit,\n onPress,\n}) => {\n const t = useOnboardingTheme();\n const reduced = useReducedMotion();\n const node = useIllustration(illustration);\n const fallbackNode = useIllustration(illustrationFallback);\n const [submitted, setSubmitted] = useState(false);\n const [imgFailed, setImgFailed] = useState(false);\n // Keep the momentum beat on screen for at least MIN_DISPLAY_MS before Continue is tappable.\n const [canAdvance, setCanAdvance] = useState(false);\n\n useEffect(() => {\n const timer = setTimeout(() => setCanAdvance(true), MIN_DISPLAY_MS);\n return () => clearTimeout(timer);\n }, []);\n\n // Head reveal: art then title (then body) fade-up, 500ms ease-wire, 100ms stagger.\n // Reduce motion: final frame immediately (the shell handoff supplies the short fade).\n const artT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const titleT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n const bodyT = useRef(new Animated.Value(reduced ? 1 : 0)).current;\n useEffect(() => {\n if (reduced) {\n artT.setValue(1);\n titleT.setValue(1);\n bodyT.setValue(1);\n return;\n }\n const rise = (value: Animated.Value, delay: number) =>\n Animated.timing(value, {\n toValue: 1,\n duration: scaledMs(INTERSTITIAL_HEAD_MS),\n delay,\n easing: easeWire,\n useNativeDriver: true,\n });\n const anims = [\n rise(artT, 0),\n rise(titleT, scaledMs(INTERSTITIAL_HEAD_STAGGER_MS)),\n rise(bodyT, scaledMs(INTERSTITIAL_HEAD_STAGGER_MS * 2)),\n ];\n anims.forEach((a) => a.start());\n return () => anims.forEach((a) => a.stop());\n }, [reduced, artT, titleT, bodyT]);\n\n const riseStyle = (value: Animated.Value) => ({\n opacity: value,\n transform: [{ translateY: value.interpolate({ inputRange: [0, 1], outputRange: [RISE_PX, 0] }) }],\n });\n\n const handleContinue = useCallback(() => {\n if (submitted || !canAdvance) return;\n setSubmitted(true);\n if (onSubmit) onSubmit(\"continue\");\n else if (onPress) onPress(ctaLabel);\n }, [submitted, canAdvance, onSubmit, onPress, ctaLabel]);\n\n // Resolution order — a broken/missing image must never leave a blank box:\n // named illustration → remote image (until it errors) → named fallback art.\n const showImage = !node && !!imageUrl && !imgFailed;\n const art = node ?? (showImage ? undefined : fallbackNode);\n\n return (\n <CardLayout\n align=\"center\"\n footer={\n <Button\n title={ctaLabel}\n onPress={handleContinue}\n variant=\"primary\"\n disabled={submitted || !canAdvance}\n />\n }\n >\n <View style={[styles.center, { gap: t.spacing.md }]}>\n <Animated.View style={[styles.fullWidth, riseStyle(artT)]}>\n {showImage ? (\n <Image\n source={{ uri: imageUrl }}\n style={styles.image}\n resizeMode=\"contain\"\n onError={() => setImgFailed(true)}\n />\n ) : art ? (\n <View style={styles.art}>{art}</View>\n ) : null}\n </Animated.View>\n\n <Animated.View style={riseStyle(titleT)}>\n <Text style={[headingStyle(t.fonts), { color: t.colors.text, textAlign: \"center\" }]}>{title}</Text>\n </Animated.View>\n\n {items?.length ? (\n <View style={[styles.items, { gap: t.spacing.md, marginTop: t.spacing.sm }]}>\n {items.map((item, i) => (\n <WorkItem key={`${item}-${i}`} text={item} index={i} reduced={reduced} />\n ))}\n </View>\n ) : body ? (\n <Animated.View style={riseStyle(bodyT)}>\n <Text style={[bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: \"center\" }]}>{body}</Text>\n </Animated.View>\n ) : null}\n </View>\n </CardLayout>\n );\n};\n\nexport const InterstitialCard: WireAIComponent = {\n name: \"InterstitialCard\",\n description:\n \"Use ONCE mid-flow (never first, never last) as a momentum/value screen between questions — an illustration + a warm line that reflects answers back, like Duolingo/Cal-AI. NOT a question; the user just taps Continue. Set `illustration` to an app-registered artwork name. Prefer `items` (2-3 short ticked lines, each reflecting a real answer) when you have the signal. Skip it if you don't have enough signal to make the line specific.\",\n component: React.memo(_InterstitialCard) as WireAIComponent[\"component\"],\n propsSchema: schema,\n defaultProps: { ctaLabel: \"Continue\", illustrationFallback: \"momentum\" },\n};\n\nconst styles = StyleSheet.create({\n center: { width: \"100%\", alignItems: \"center\", justifyContent: \"center\" },\n fullWidth: { width: \"100%\", alignItems: \"center\" },\n art: { alignItems: \"center\", justifyContent: \"center\" },\n image: { width: \"100%\", height: 200 },\n items: { width: \"100%\", alignSelf: \"stretch\" },\n itemRow: { flexDirection: \"row\", alignItems: \"center\" },\n itemBadge: { width: 24, height: 24, alignItems: \"center\", justifyContent: \"center\" },\n itemCheck: { fontSize: 13, fontWeight: \"800\", lineHeight: 15 },\n itemText: { flex: 1 },\n});\n","/**\n * onboardingComponents — the constrained set of themed cards the kit registers\n * with the SDK. The backend's `allowed_components` must be a subset of these\n * names so every card the agent asks for has a themed renderer.\n */\nimport type { WireAIComponent } from \"wireai-rn\";\nimport { ChipSelectCard } from \"./ChipSelectCard\";\nimport { TextInputCard } from \"./TextInputCard\";\nimport { SelectionCard } from \"./SelectionCard\";\nimport { CardGridSelectCard } from \"./CardGridSelectCard\";\nimport { StatusCard } from \"./StatusCard\";\nimport { NumberStepperCard } from \"./NumberStepperCard\";\nimport { InterstitialCard } from \"./InterstitialCard\";\n\nexport {\n ChipSelectCard,\n TextInputCard,\n SelectionCard,\n CardGridSelectCard,\n StatusCard,\n NumberStepperCard,\n InterstitialCard,\n};\nexport { PermissionCard, PermissionCardView, PERMISSION_CARD_NAME } from \"./PermissionCard\";\nexport type { PermissionCardProps } from \"./PermissionCard\";\nexport { normalizeOptions, optionsField, optionObjectSchema } from \"./optionSchema\";\nexport type { CardOption } from \"./optionSchema\";\n\n// ⚠️ `PermissionCard` is deliberately NOT in this array. The list is what the device ADVERTISES to\n// the backend as renderable (`metadata.supportedComponents`), and a backend told it may emit a\n// permission screen could emit one into a host that injected no `request` function, which the kit\n// has no way to honour. Permission screens are host-declared for now (`permissionScreens`); the\n// card is registered and ready for the day a server-emitted placement lands.\nexport const onboardingComponents: WireAIComponent[] = [\n ChipSelectCard,\n TextInputCard,\n SelectionCard,\n CardGridSelectCard,\n StatusCard,\n NumberStepperCard,\n InterstitialCard,\n];\n","/**\n * appVersion — best-effort, DEPENDENCY-FREE auto-detection of the host app's version string.\n *\n * WHY this exists: analytics segments the funnel `by_app_version`, but that breakdown is only\n * populated when a `device.appVersion` rides the event. `config.appVersion` (see types.ts) has\n * always been the way to supply it — but it is easy for a host to forget, and then the release\n * breakdown is silently empty. This module fills that gap: when the host does NOT pass a version,\n * the kit makes a best-effort read of the app version the host already ships in its Expo config,\n * so the breakdown works out of the box. An explicit `config.appVersion` always WINS over this.\n *\n * WHY it adds NO dependency (the kit's hard rule): `expo-constants` / `expo-application` are read\n * through a GUARDED require with a STRING-LITERAL specifier, inside a try/catch. Both halves are\n * required: the literal is what lets Metro COLLECT the dep, and the try/catch is what marks it\n * OPTIONAL, so an absent module becomes a `null` dependencyMap entry whose require throws \"Cannot\n * find module\" straight into the catch. (`withWireOnboarding` in metro/index.js adds a stub-to-\n * empty-module safety net for hosts that disable Metro's `allowOptionalDependencies`.) Nothing is\n * added to `package.json`; nothing is forced on the host.\n *\n * The specifier MUST stay a literal. A variable specifier (`const req = require; req(name)`) is not\n * \"lazier\" — it is broken: Metro collects dependencies statically, so a variable collects NOTHING,\n * the module never enters the bundle, and the aliased `require` is Metro's own numeric-id-keyed\n * `metroRequire`, which can never resolve a package-name string. That shape is why this function\n * returned `undefined` on every host despite `expo-constants` being installed, which silently\n * emptied the `by_app_version` breakdown this module exists to fill. See icons/expoIcons.ts for\n * the full autopsy, and reviews/storeReview.ts for the literal-specifier counter-example.\n *\n * PRIVACY: an app version string is not PII and identifies no user or device, so surfacing it\n * changes no App Privacy / Data Safety declaration (same guarantee as the rest of deviceContext).\n *\n * NEVER THROWS: every read is guarded; a missing/odd value yields `undefined`, never an exception.\n * Analytics must never be able to break onboarding.\n */\n\n// Metro injects a module-scoped `require`; it is ABSENT in a pure-ESM runtime. Declared locally so\n// this type-checks without ambient Node types; the `typeof` guard keeps the reference ESM-safe.\ndeclare const require: ((id: string) => unknown) | undefined;\n\n/** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */\nexport type OptionalRequire = (moduleName: string) => unknown;\n\n/** Trim + reject non-strings/empties so we only ever emit a real version string. */\nexport const coerceVersion = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\n/**\n * Guarded runtime require.\n *\n * Every specifier below is a STRING LITERAL, because that is the only shape Metro's dependency\n * collector matches (callee literally `require`, argument literally a string). The `moduleName`\n * parameter exists only to keep the `OptionalRequire` seam shape for tests; an unrecognised name\n * resolves to undefined. See the header for why the old variable-specifier shape could not work.\n */\nconst runtimeRequire: OptionalRequire = (moduleName) => {\n if (typeof require !== \"function\") return undefined;\n try {\n switch (moduleName) {\n case \"expo-constants\":\n return require(\"expo-constants\");\n case \"expo-application\":\n return require(\"expo-application\");\n default:\n return undefined;\n }\n } catch {\n return undefined;\n }\n};\n\n/** Read a module's `default` (Expo modules are consumed as default exports) or the namespace. */\nconst interop = (mod: unknown): Record<string, unknown> | undefined => {\n if (!mod || typeof mod !== \"object\") return undefined;\n const def = (mod as { default?: unknown }).default;\n if (def && typeof def === \"object\") return def as Record<string, unknown>;\n return mod as Record<string, unknown>;\n};\n\n/** Resolve a module namespace, swallowing a throwing require (an uninstalled module throws). */\nconst safeInterop = (\n requireModule: OptionalRequire,\n moduleName: string,\n): Record<string, unknown> | undefined => {\n try {\n return interop(requireModule(moduleName));\n } catch {\n return undefined;\n }\n};\n\n/**\n * Detect the host app version, preferring `expo-constants` (`expoConfig.version`, then\n * `nativeAppVersion`) and finally `expo-application` (`nativeApplicationVersion`). Returns the\n * first real string, or `undefined` when none of those are available. Pure and never throws.\n *\n * `requireModule` is injectable so tests can exercise the \"found\" path without the native modules;\n * production defaults to the guarded runtime require above.\n */\nexport const detectAppVersion = (\n requireModule: OptionalRequire = runtimeRequire,\n): string | undefined => {\n try {\n const constants = safeInterop(requireModule, \"expo-constants\");\n if (constants) {\n const expoConfig = constants.expoConfig;\n if (expoConfig && typeof expoConfig === \"object\") {\n const fromExpoConfig = coerceVersion((expoConfig as { version?: unknown }).version);\n if (fromExpoConfig) return fromExpoConfig;\n }\n const fromNative = coerceVersion(constants.nativeAppVersion);\n if (fromNative) return fromNative;\n }\n\n const application = safeInterop(requireModule, \"expo-application\");\n if (application) {\n const fromApplication = coerceVersion(application.nativeApplicationVersion);\n if (fromApplication) return fromApplication;\n }\n } catch {\n // Any unexpected read error → \"unknown\"; analytics must never crash onboarding.\n }\n return undefined;\n};\n","/**\n * deviceModel — best-effort, DEPENDENCY-FREE detection of the device MODEL on iOS.\n *\n * WHY this exists (the asymmetry it closes): `collectDeviceContext` already reports `device.model`\n * on Android straight from `Platform.constants.Model` (e.g. \"SM-G991B\"), but iOS `Platform.constants`\n * exposes NO model — only `osVersion` / `interfaceIdiom`. So the analytics `by_model` breakdown was\n * Android-only. This module fills the iOS gap with the SAME zero-dependency technique the kit already\n * uses for `appVersion` (see device/appVersion.ts): a GUARDED, STRING-LITERAL `require` of the common\n * Expo `expo-device` module, inside a try/catch — the literal is what lets Metro COLLECT the dep and\n * the try/catch is what marks it OPTIONAL, so an absent module degrades instead of failing the build.\n * (`withWireOnboarding` in metro/index.js adds a stub-to-empty-module safety net for hosts that\n * disable Metro's `allowOptionalDependencies`.) If the host has it, iOS gets a model out of the box;\n * if not, the read yields `undefined` and iOS `model` stays omitted — nothing is forced, and nothing\n * is added to `package.json`.\n *\n * The specifier MUST stay a literal. A variable specifier (`const req = require; req(name)`) collects\n * NOTHING under Metro's static dependency collector, so the module never enters the bundle and the\n * aliased `require` — really Metro's numeric-id-keyed `metroRequire` — can never resolve a package\n * name. See icons/expoIcons.ts for the full autopsy.\n *\n * WHY it is NOT PII: `expo-device`'s `modelName` (\"iPhone 14 Pro\") and `modelId` (\"iPhone15,2\") are a\n * device CLASS shared by millions of units — the same privacy category as the Android `Model` the kit\n * already sends. It is NOT a unique device id / IDFA / fingerprint, so surfacing it changes no App\n * Privacy / Data Safety declaration (identical guarantee to the rest of deviceContext). It deliberately\n * does NOT read `expo-device`'s `deviceName` (that is the user-set name, e.g. \"Malik's iPhone\", and IS\n * personal data).\n *\n * NEVER THROWS: every read is guarded; a missing/odd value yields `undefined`, never an exception.\n */\n\n// Metro injects a module-scoped `require`; it is ABSENT in a pure-ESM runtime. Declared locally so\n// this type-checks without ambient Node types; the `typeof` guard keeps the reference ESM-safe.\ndeclare const require: ((id: string) => unknown) | undefined;\n\n/** A `require`-like resolver. Injectable in tests; production uses the guarded runtime require. */\nexport type OptionalRequire = (moduleName: string) => unknown;\n\n/** Trim + reject non-strings/empties so we only ever emit a real model string. */\nconst coerceModel = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\n/**\n * Guarded runtime require.\n *\n * The specifier is a STRING LITERAL, because that is the only shape Metro's dependency collector\n * matches (callee literally `require`, argument literally a string). The `moduleName` parameter\n * exists only to keep the `OptionalRequire` seam shape for tests; an unrecognised name resolves to\n * undefined. (See the twin guard in ./appVersion.ts.)\n */\nconst runtimeRequire: OptionalRequire = (moduleName) => {\n if (moduleName !== \"expo-device\") return undefined;\n if (typeof require !== \"function\") return undefined;\n try {\n return require(\"expo-device\");\n } catch {\n return undefined;\n }\n};\n\n/** Read a module's `default` (Expo modules are often consumed as default exports) or the namespace. */\nconst interop = (mod: unknown): Record<string, unknown> | undefined => {\n if (!mod || typeof mod !== \"object\") return undefined;\n const def = (mod as { default?: unknown }).default;\n if (def && typeof def === \"object\") return def as Record<string, unknown>;\n return mod as Record<string, unknown>;\n};\n\n/** Resolve a module namespace, swallowing a throwing require (an uninstalled module throws). */\nconst safeInterop = (\n requireModule: OptionalRequire,\n moduleName: string,\n): Record<string, unknown> | undefined => {\n try {\n return interop(requireModule(moduleName));\n } catch {\n return undefined;\n }\n};\n\n/**\n * Detect the device model via `expo-device`, preferring the human-readable `modelName`\n * (\"iPhone 14 Pro\") and falling back to the identifier `modelId` (\"iPhone15,2\"). Returns the first\n * real string, or `undefined` when `expo-device` is absent. Pure and never throws.\n *\n * `requireModule` is injectable so tests can exercise the \"found\" path without the native module;\n * production defaults to the guarded runtime require above.\n */\nexport const detectNativeModel = (\n requireModule: OptionalRequire = runtimeRequire,\n): string | undefined => {\n try {\n const device = safeInterop(requireModule, \"expo-device\");\n if (device) {\n const modelName = coerceModel(device.modelName);\n if (modelName) return modelName;\n const modelId = coerceModel(device.modelId);\n if (modelId) return modelId;\n }\n } catch {\n // Any unexpected read error → undefined; analytics must never crash onboarding.\n }\n return undefined;\n};\n","/**\n * deviceContext — collect a small, privacy-label-neutral snapshot of the device so\n * onboarding analytics can segment the funnel (platform / form factor / locale) WITHOUT\n * adding a single dependency to the kit or changing a host app's App Privacy / Data Safety\n * declarations.\n *\n * HARD RULE (why this file adds no dependency):\n * The kit stays dependency-free. Everything here comes from `Platform`, `Dimensions`,\n * `I18nManager`, and the standard `Intl` global — plus a best-effort `appVersion` read via\n * `detectAppVersion()`, which itself adds NO dependency (it reaches for `expo-constants` /\n * `expo-application` through a guarded, variable-specifier require that a host without them\n * simply never resolves — see device/appVersion.ts). There are NO advertising IDs, NO\n * `getUniqueId`/IDFA/GAID/fingerprinting APIs, and nothing that would require a new\n * privacy-label entry. A host can adopt this without touching its store declarations.\n *\n * DEFENSIVE BY DESIGN: `collectDeviceContext()` never throws. Every read is guarded and\n * a missing/unavailable field is simply omitted (Hermes may ship without full `Intl`,\n * `Platform.constants` differs per OS and RN version, etc.). Analytics must never be able\n * to break onboarding.\n */\nimport { Dimensions, I18nManager, Platform } from \"react-native\";\n\nimport { detectAppVersion } from \"./appVersion\";\nimport { detectNativeModel } from \"./deviceModel\";\n\n/** Coarse device class. iOS uses the reported interface idiom; else a screen-size heuristic. */\nexport type DeviceFormFactor = \"phone\" | \"tablet\";\n\n/**\n * A privacy-label-neutral device snapshot. ALL fields except `platform` are optional and are\n * omitted when unavailable. Nothing here identifies a user or device uniquely.\n */\nexport type DeviceContext = {\n /** `Platform.OS` — \"ios\" | \"android\" | \"windows\" | \"macos\" | \"web\". Always present. */\n platform: typeof Platform.OS;\n /** OS version string (iOS `osVersion`/`Platform.Version`, Android `Release`). */\n osVersion?: string;\n /** Android device brand (e.g. \"samsung\"). Android only. */\n brand?: string;\n /**\n * Device model. On Android it is read directly from `Platform.constants.Model` (e.g. \"SM-G991B\").\n * iOS `Platform.constants` exposes NO model, so on iOS it is a BEST-EFFORT read of `expo-device`'s\n * `modelName` (\"iPhone 14 Pro\"), falling back to `modelId` (\"iPhone15,2\") — dependency-free via a\n * guarded require (see device/deviceModel.ts). ASYMMETRY: without `expo-device` installed, iOS\n * `model` is omitted (there is no dependency-free iOS model in the already-used RN surface, and the\n * kit will not add a native dep for it); Android needs no extra module. Not PII (a device class,\n * not a unique id), so it changes no privacy-label declaration.\n */\n model?: string;\n /** iOS interface idiom (\"phone\" | \"pad\" | …), when reported. iOS only. */\n interfaceIdiom?: string;\n /** Derived device class. */\n formFactor?: DeviceFormFactor;\n /** `Dimensions.get('screen')` width in dp. */\n screenWidth?: number;\n /** `Dimensions.get('screen')` height in dp. */\n screenHeight?: number;\n /** Screen pixel density (`scale`). */\n screenScale?: number;\n /** Right-to-left layout (`I18nManager.isRTL`). */\n isRTL?: boolean;\n /** Resolved locale (e.g. \"en-US\"), from `Intl` when available. */\n locale?: string;\n /** IANA time zone (e.g. \"Europe/Berlin\"), from `Intl` when available. */\n timeZone?: string;\n /**\n * Host app version (e.g. \"1.4.2\"). BEST-EFFORT auto-detected here via `detectAppVersion()`\n * (reads `expo-constants` / `expo-application` when present; adds no dependency — see\n * device/appVersion.ts). An explicit host-injected `config.appVersion` always WINS: the merge\n * sites (`WireOnboarding`, the session-analytics hooks, the context envelope) overwrite this\n * with the host value when one is supplied. Omitted when neither source yields a version.\n */\n appVersion?: string;\n};\n\n/** iOS idiom wins; otherwise the shortest side in dp (>= 600 → tablet) picks the class. */\nconst deriveFormFactor = (\n iosIdiom: string | undefined,\n width: number | undefined,\n height: number | undefined,\n): DeviceFormFactor | undefined => {\n if (iosIdiom === \"pad\") return \"tablet\";\n if (iosIdiom === \"phone\") return \"phone\";\n if (typeof width === \"number\" && typeof height === \"number\") {\n return Math.min(width, height) >= 600 ? \"tablet\" : \"phone\";\n }\n return undefined;\n};\n\n/**\n * Collect the device snapshot. Pure, synchronous, and never throws — call it once per\n * onboarding session. Missing fields are omitted rather than sent as null/undefined so the\n * payload (and the server's stored dict) stays compact.\n */\nexport const collectDeviceContext = (): DeviceContext => {\n const ctx: DeviceContext = { platform: Platform.OS };\n\n // OS version (fallback; per-OS constants below may refine it).\n try {\n const version = Platform.Version;\n if (version !== undefined && version !== null && String(version)) {\n ctx.osVersion = String(version);\n }\n } catch {\n // ignore\n }\n\n // `Platform.constants` shape differs by OS and RN version — read every field defensively.\n let constants: Record<string, unknown> = {};\n try {\n constants = (Platform.constants ?? {}) as Record<string, unknown>;\n } catch {\n constants = {};\n }\n\n let iosIdiom: string | undefined;\n try {\n if (Platform.OS === \"android\") {\n const brand = constants.Brand;\n const model = constants.Model;\n const release = constants.Release;\n if (typeof brand === \"string\" && brand) ctx.brand = brand;\n if (typeof model === \"string\" && model) ctx.model = model;\n if (release !== undefined && release !== null && String(release)) {\n ctx.osVersion = String(release);\n }\n } else if (Platform.OS === \"ios\") {\n const osVersion = constants.osVersion;\n const idiom = constants.interfaceIdiom;\n if (osVersion !== undefined && osVersion !== null && String(osVersion)) {\n ctx.osVersion = String(osVersion);\n }\n if (typeof idiom === \"string\" && idiom) {\n ctx.interfaceIdiom = idiom;\n iosIdiom = idiom;\n }\n // iOS has no model in `Platform.constants`; best-effort via `expo-device` (adds no dep,\n // omitted when the module is absent — see device/deviceModel.ts).\n const iosModel = detectNativeModel();\n if (iosModel) ctx.model = iosModel;\n }\n } catch {\n // ignore per-OS constant reads\n }\n\n // Screen dimensions + derived form factor.\n try {\n const screen = Dimensions.get(\"screen\");\n if (screen) {\n if (typeof screen.width === \"number\") ctx.screenWidth = screen.width;\n if (typeof screen.height === \"number\") ctx.screenHeight = screen.height;\n if (typeof screen.scale === \"number\") ctx.screenScale = screen.scale;\n const formFactor = deriveFormFactor(iosIdiom, screen.width, screen.height);\n if (formFactor) ctx.formFactor = formFactor;\n }\n } catch {\n // ignore\n }\n\n // Layout direction.\n try {\n ctx.isRTL = I18nManager.isRTL;\n } catch {\n // ignore\n }\n\n // Locale + time zone via the standard Intl global. Hermes may ship without full Intl,\n // so referencing it can throw ReferenceError — the try/catch covers that too.\n try {\n const resolved = Intl.DateTimeFormat().resolvedOptions();\n if (resolved.locale) ctx.locale = resolved.locale;\n if (resolved.timeZone) ctx.timeZone = resolved.timeZone;\n } catch {\n // Intl unavailable — omit locale/timeZone.\n }\n\n // Best-effort host app version (adds no dependency; omitted when unavailable). An explicit\n // `config.appVersion` overrides this downstream at the merge sites.\n const appVersion = detectAppVersion();\n if (appVersion) ctx.appVersion = appVersion;\n\n return ctx;\n};\n","/**\n * identityRecord — the ONE provenance-carrying shape for an id the kit puts on the wire.\n *\n * WHY IT EXISTS. `session_id` and `device_key` are bare `string`s minted independently by four\n * subsystems, and nothing anywhere recorded WHERE a given id came from. Every id-layer defect this\n * release fixes is a direct consequence of that one omission:\n *\n * • a rejecting storage adapter's in-memory id was indistinguishable from a persisted one, so the\n * kit injected a fresh per-launch join key on every launch — nothing carried `durable`.\n * • an app-OPEN session id could be posted into a field that means the ONBOARDING session, and the\n * caller was told `true` — nothing carried `space`.\n * • an auto-minted `wdev_*` could be injected beside a device id the host demonstrably owns on\n * another surface, silently — nothing carried `source`.\n *\n * WHAT THIS IS, AND WHAT IT DELIBERATELY IS NOT. It is a small record plus a process-wide registry of\n * the ids a HOST supplied. It is NOT a branded-type refactor (`OnboardingSessionId` / `AppSessionId` /\n * `DeviceKey` across every signature) — that is real value and it is deferred, because it touches\n * every file and is not what makes a number correct this week. Nothing here changes the wire.\n *\n * WHY A `Symbol.for` REGISTRY. Same reason as `analytics/currentSession` and `context/deviceId`: tsup\n * inlines a separate copy of a module into each bundle (`.` and `./analytics`), so a plain module\n * `let` would give every bundle its own registry and the cross-surface question this exists to answer\n * (\"did ANY surface in this process get a host-supplied device key?\") would read `no` from the wrong\n * copy. `Symbol.for` resolves to one slot on `globalThis` no matter how many copies exist.\n */\n\n/**\n * Which id space a value belongs to. These are NOT interchangeable, and the whole point of naming\n * them is that a value from one space must never be posted into a field that means another:\n * • `onboarding-session` — the A2A `contextId` for ONE onboarding run.\n * • `app-session` — the per-app-open session id (`app.session_started`).\n * • `device` — the per-install `device_key`; the only cross-family join key.\n */\nexport type IdentitySpace = \"onboarding-session\" | \"app-session\" | \"device\";\n\n/** Where the value came from: the host handed it over, or the kit minted it. */\nexport type IdentitySource = \"host\" | \"auto\";\n\n/** An id plus everything a consumer needs to decide whether it may use it. */\nexport type IdentityRecord = {\n /** The id itself, trimmed. Never empty (a blank input yields no record at all). */\n value: string;\n /** Which id space {@link value} belongs to. */\n space: IdentitySpace;\n /** `host` = the integrator supplied it; `auto` = the kit minted it. */\n source: IdentitySource;\n /**\n * Whether the value was actually PERSISTED (or adopted from persistence), as opposed to living\n * only in this process's memory. A non-durable auto id is a DIFFERENT id on the next launch, which\n * for a `device` value is worse than no value at all: the server counts `min_sessions` by distinct\n * opens grouped on `device_key`, so a per-launch key corrupts the counter rather than leaving it\n * empty. A host-supplied value is durable by definition — the host owns its lifetime.\n */\n durable: boolean;\n};\n\n/** Input to {@link resolveIdentity}. `value` is `unknown` so callers can pass a raw prop through. */\nexport type ResolveIdentityInput = {\n value: unknown;\n space: IdentitySpace;\n source: IdentitySource;\n /** Defaults to `true` for a host value (the host owns its lifetime) and `false` otherwise. */\n durable?: boolean;\n /** Tenant/app id — two tenants in one process never share a provenance entry. */\n scope?: string;\n};\n\n/** Well-known key into the runtime-global symbol registry — one provenance registry per process. */\nconst IDENTITY_PROVENANCE_SLOT: unique symbol = Symbol.for(\"@wireai/activation:identityProvenance\");\n\n/** `\"<space>:<scope>\"` → the HOST-supplied value seen for it. Auto values are never recorded. */\ntype ProvenanceRegistry = { host: Map<string, string> };\n\ntype GlobalWithProvenance = typeof globalThis & {\n [IDENTITY_PROVENANCE_SLOT]?: ProvenanceRegistry;\n};\n\nconst provenanceGlobal = globalThis as GlobalWithProvenance;\n\nconst provenanceRegistry = (): ProvenanceRegistry => {\n const existing = provenanceGlobal[IDENTITY_PROVENANCE_SLOT];\n if (existing) return existing;\n const created: ProvenanceRegistry = { host: new Map() };\n provenanceGlobal[IDENTITY_PROVENANCE_SLOT] = created;\n return created;\n};\n\nconst provenanceKey = (space: IdentitySpace, scope?: string): string =>\n `${space}:${scope ?? \"default\"}`;\n\n/**\n * Build an {@link IdentityRecord} from a candidate value, or `undefined` when there is nothing usable\n * (a non-string, or blank after trimming) — so a caller can `if (record)`-gate instead of guessing\n * whether an empty string means \"none\" or \"not yet\".\n *\n * SIDE EFFECT, deliberate and the reason this is a function and not an object literal: a `host`-sourced\n * record is RECORDED on the process registry, so a later surface can ask {@link hostIdentity} whether\n * this process demonstrably owns a host id in that space. That is what turns \"the kit injected its own\n * key\" from a silent third id space into a warnable condition. Never throws.\n */\nexport const resolveIdentity = (input: ResolveIdentityInput): IdentityRecord | undefined => {\n if (typeof input.value !== \"string\") return undefined;\n const value = input.value.trim();\n if (!value) return undefined;\n const durable = input.durable ?? input.source === \"host\";\n if (input.source === \"host\") {\n provenanceRegistry().host.set(provenanceKey(input.space, input.scope), value);\n }\n return { value, space: input.space, source: input.source, durable };\n};\n\n/**\n * The HOST-supplied id this process has seen for a space, or `undefined` when every surface so far\n * let the kit mint its own. Answers the cross-surface question no single mount can answer alone:\n * \"does this app own a device id that this particular mount was not given?\"\n */\nexport const hostIdentity = (space: IdentitySpace, scope?: string): string | undefined =>\n provenanceRegistry().host.get(provenanceKey(space, scope));\n\n/** Test-only: forget every recorded host identity so a unit test starts from a clean registry. */\nexport const resetIdentityProvenance = (): void => {\n provenanceRegistry().host.clear();\n};\n","/**\n * deviceId — mint a stable, NON-PII, per-install device id the kit owns when the host supplies\n * none. This is the headline of \"device fully automatic\": the analytics façade auto-mints ONE id,\n * persists it via the host's `storage` abstraction, and reuses it on every subsequent open — so\n * `user_context.device_key` is ALWAYS present and the server's review/questionnaire gating +\n * A/B stickiness (both key on `device_key`) work out of the box, with zero host wiring.\n *\n * WHY it is NOT PII and adds NO dependency (the kit's hard rules):\n * The id is a random token generated from `Date.now()` + `Math.random()` — it carries NO hardware\n * identifier, NO IDFA/GAID, NO fingerprint. It is a first-party per-install correlation key, the\n * same privacy category as a first-party cookie: it groups a single install's sessions and cannot\n * identify a person or be joined across apps. There is NO `uuid` (or any) dependency — a\n * time+random scheme is sufficient because the id is minted ONCE and then persisted, so global\n * uniqueness across the fleet is not required (a per-install collision is astronomically unlikely\n * and inconsequential — worst case two installs share a bucket).\n *\n * A host that wants its OWN device id still wins: pass `WireUserContext.deviceKey` and the kit uses\n * that verbatim and never mints/persists an auto id.\n */\n\nimport { resolveIdentity, type IdentityRecord } from \"../identity/identityRecord\";\n\n/** Prefix so an auto-minted id is visibly the kit's (distinguishable from a host-supplied `deviceKey`). */\nexport const AUTO_DEVICE_ID_PREFIX = \"wdev_\";\n\n/** The storage key the façade persists the auto-minted id under (namespaced per `appId`). */\nexport const deviceIdStorageKey = (appId?: string): string =>\n `wireai:analytics:deviceKey:${appId ?? \"default\"}`;\n\n/** One 32-bit base-36 chunk of randomness. Two chunks are concatenated for a wider token. */\nconst randomChunk = (): string =>\n Math.floor(Math.random() * 0x100000000)\n .toString(36)\n .padStart(6, \"0\");\n\n/**\n * Mint a fresh per-install device id. Dependency-free (`Date.now()` + `Math.random()`), never\n * throws, and returns a NEW value on every call — the façade mints ONCE and persists, so this is\n * called at most once per install (then the persisted value is reused). Two random chunks plus the\n * timestamp keep the token wide enough that a per-install collision is not a practical concern.\n */\nexport const mintDeviceId = (): string => {\n const time = Date.now().toString(36);\n return `${AUTO_DEVICE_ID_PREFIX}${time}_${randomChunk()}${randomChunk()}`;\n};\n\n// ── The ONE auto device key per install ──────────────────────────────────────────────────────\n//\n// WHY A REGISTRY AND NOT A `let` PER FACTORY: `createAnalytics` and `createWireActivation` each\n// used to mint their OWN id synchronously and then race a storage read to overwrite it. A host that\n// creates BOTH (the documented wiring: a façade for `track`/`screen`, an activation instance for the\n// gate-firing `wire.track`) therefore had TWO auto ids for ONE install. Every event carried whichever\n// id its own surface minted, so the `device_key` the server groups a device's sessions under — the\n// key `min_sessions`, A/B arm stickiness, and the purchase↔onboarding join all read — SPLIT in two.\n// On a first run both also wrote their own id to the same storage slot, so which one survived was a\n// coin flip. Same failure class as joining two event families on disjoint id spaces: no error, just\n// halved counts and a join that misses.\n//\n// The fix is the pattern this repo already uses for `currentSession` and `activation revalidation`:\n// ONE value in a `globalThis` slot keyed by `Symbol.for(...)`, so every inlined copy of this module\n// (tsup duplicates modules across the `.` / `./analytics` bundles) addresses the SAME registry.\n// Keyed by `appId` so two tenants in one process never share an id.\n//\n// RESIDUAL WINDOW: the storage read is async, so an event emitted in the milliseconds before\n// hydration completes carries the freshly minted id rather than the persisted one. The registry makes\n// every surface agree on WHICH id that is; it does not make the read sync. A caller that can afford to\n// wait (the lifecycle hook's mount effect — see `hydrateAutoDeviceKey`) should await instead: its two\n// events are the ONLY ones the server counts `min_sessions` from, so a per-launch id there is not a\n// millisecond of noise, it is a counter that can never exceed 1.\n\n/** Well-known key into the runtime-global symbol registry — one auto-id registry across every bundle. */\nconst AUTO_DEVICE_KEY_SLOT: unique symbol = Symbol.for(\"@wireai/activation:autoDeviceKeys\");\n\n/** What a hydration settled on: the id, and whether persistence actually CONFIRMED it.\n *\n * `durable: false` means the id lives only in this process's memory — the adapter rejected, threw,\n * or there was no adapter at all. That distinction is the whole point here: a string is a string, so\n * before 0.13.0 a caller could not tell a persisted id from a per-launch mint, and the auto-join\n * gate (`Boolean(storage)`) was reading the PRESENCE of the prop rather than the SUCCESS of the\n * write. See {@link hydrateDeviceIdentity}. */\ntype HydrationOutcome = { value: string; durable: boolean };\n\n/** The shared registry: the live id per `appId`, the set of appIds whose hydration already started,\n * and the in-flight (or settled) hydration promise per `appId` so a waiter can join it. */\ntype AutoDeviceKeyRegistry = {\n keys: Map<string, string>;\n hydrating: Set<string>;\n pending?: Map<string, Promise<HydrationOutcome>>;\n};\n\ntype GlobalWithDeviceKeys = typeof globalThis & {\n [AUTO_DEVICE_KEY_SLOT]?: AutoDeviceKeyRegistry;\n};\n\nconst deviceKeyGlobal = globalThis as GlobalWithDeviceKeys;\n\nconst autoDeviceKeyRegistry = (): AutoDeviceKeyRegistry => {\n const existing = deviceKeyGlobal[AUTO_DEVICE_KEY_SLOT];\n if (existing) return existing;\n const created: AutoDeviceKeyRegistry = { keys: new Map(), hydrating: new Set() };\n deviceKeyGlobal[AUTO_DEVICE_KEY_SLOT] = created;\n return created;\n};\n\n/** The persistence subset {@link resolveAutoDeviceKey} needs (a strict subset of `WireOnboardingStorage`). */\nexport type DeviceKeyStorage = {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n};\n\n/** Options for {@link resolveAutoDeviceKey}. Omitting `storage` gives a PROCESS-scoped id, not a\n * per-install one — see the caller notes: a caller with no persistence must decide whether a\n * per-launch id is better or worse than no id for its metric. */\nexport interface ResolveAutoDeviceKeyOptions {\n /** Tenant/app id — namespaces both the registry entry and the storage slot. */\n appId?: string;\n /** Host persistence. Present → the id survives launches. Absent → process-scoped only. */\n storage?: DeviceKeyStorage;\n}\n\n/**\n * Start (or join) the SINGLE-FLIGHT storage read for `appId` and resolve to the {@link HydrationOutcome}\n * it settles on. The promise is parked on the registry so a later `hydrateAutoDeviceKey` awaits the\n * SAME read instead of starting a second one. Never rejects: any storage failure resolves to the live\n * id with `durable: false`.\n *\n * TWO OUTCOMES, NOT ONE STRING:\n * • ADOPTED (`durable: true`) — a persisted id was read back, or the freshly minted one was\n * written successfully. The next launch will see the same id.\n * • DEGRADED (`durable: false`) — the adapter rejected, threw, or returned nothing and then failed\n * the write. The id is real but PROCESS-scoped, so anything that\n * counts a device across launches must refuse it.\n *\n * A DEGRADED outcome also drops the registry latches so the NEXT caller starts a fresh read. A\n * cold-boot storage lock is transient; caching it as a verdict for the process lifetime turned a\n * one-second problem into a whole-launch one, and nothing ever retried.\n */\nconst startHydration = (\n registry: AutoDeviceKeyRegistry,\n appId: string,\n storage: DeviceKeyStorage,\n minted: string,\n): Promise<HydrationOutcome> => {\n if (!registry.pending) registry.pending = new Map();\n const existing = registry.pending.get(appId);\n if (existing) return existing;\n\n const slot = deviceIdStorageKey(appId);\n const degraded = (): HydrationOutcome => ({ value: registry.keys.get(appId) ?? minted, durable: false });\n const adopted = (value: string): HydrationOutcome => ({ value, durable: true });\n let run: Promise<HydrationOutcome>;\n try {\n run = Promise.resolve(storage.getItem(slot))\n .then((saved) => {\n const persisted = typeof saved === \"string\" && saved.trim() ? saved.trim() : undefined;\n if (persisted) {\n registry.keys.set(appId, persisted);\n return adopted(persisted);\n }\n // First run on this install: persist the id we just minted so the next launch adopts it.\n // ONLY a resolved write earns `durable` — a rejected one leaves the id in memory alone.\n return Promise.resolve(storage.setItem(slot, minted)).then(\n () => adopted(registry.keys.get(appId) ?? minted),\n degraded,\n );\n })\n .catch(degraded);\n } catch {\n // A storage adapter that throws synchronously — degrade to the in-memory id.\n run = Promise.resolve(degraded());\n }\n registry.pending.set(appId, run);\n // Retry-on-failure: release the latches once a degraded outcome settles, so a later caller\n // is not permanently bound to one bad read. Registered AFTER the `set` above, so the clean-up can\n // never race ahead of the entry it is clearing.\n void run.then((outcome) => {\n if (outcome.durable) return;\n registry.pending?.delete(appId);\n registry.hydrating.delete(appId);\n });\n return run;\n};\n\n/**\n * The ONE auto-minted `device_key` for an install, shared by every kit surface.\n *\n * SYNCHRONOUS by contract (a fire-and-forget event path cannot await): returns the current live id\n * immediately, minting one on first call. When `storage` is supplied it also kicks off a SINGLE\n * hydration per `appId` that adopts the persisted id (or persists the freshly minted one). Callers\n * should call this per EVENT rather than caching the return value, so an event built after hydration\n * carries the persisted id.\n *\n * A host-supplied `deviceKey` always wins — callers must short-circuit before reaching this.\n * Never throws: a missing, hung, or rejecting storage adapter degrades to the in-memory id.\n */\nexport const resolveAutoDeviceKey = (opts: ResolveAutoDeviceKeyOptions = {}): string => {\n const registry = autoDeviceKeyRegistry();\n const appId = opts.appId ?? \"default\";\n\n let id = registry.keys.get(appId);\n if (!id) {\n id = mintDeviceId();\n registry.keys.set(appId, id);\n }\n\n const storage = opts.storage;\n // Single-flight: the FIRST caller with storage owns hydration for this appId; later callers just\n // read whatever the registry currently holds.\n if (storage && !registry.hydrating.has(appId)) {\n registry.hydrating.add(appId);\n void startHydration(registry, appId, storage, id);\n }\n\n return registry.keys.get(appId) ?? id;\n};\n\n/**\n * The AWAITABLE sibling of {@link resolveAutoDeviceKey}: resolve to the auto `device_key` AFTER the\n * persisted id has been read back (or written, on a first run), so the caller stamps the id this\n * install will keep rather than the one that was minted a millisecond ago.\n *\n * WHY IT EXISTS: `resolveAutoDeviceKey` is synchronous by contract, so a caller firing at mount got\n * the freshly minted id and the persisted one landed milliseconds later. For most events that is\n * noise. For `app.session_started` it is the whole metric: the server computes `min_sessions` by\n * counting distinct opens grouped by `device_key`, so a per-launch key there makes the counter\n * structurally incapable of exceeding 1, and it splits `first_open` off from every event that\n * follows it. Only a caller that can afford one storage read should use this; the fire-and-forget\n * event paths must stay on the sync function.\n *\n * Never throws or rejects: a missing, hung, or rejecting adapter resolves to the in-memory id, and\n * with no `storage` it resolves immediately (there is nothing to hydrate from).\n */\nexport const hydrateAutoDeviceKey = async (\n opts: ResolveAutoDeviceKeyOptions = {},\n): Promise<string> => (await hydrateDeviceIdentity(opts))?.value ?? resolveAutoDeviceKey(opts);\n\n/**\n * The PROVENANCE-CARRYING sibling of {@link hydrateAutoDeviceKey}: the same awaited read, but it\n * answers \"is this id one this install will KEEP?\" instead of only \"what is the id?\".\n *\n * WHY IT EXISTS. `<WireOnboarding>` gated auto-injection on `Boolean(storage)` — the presence of\n * the prop — because a string carries no provenance and there was nothing better to gate on. A\n * REJECTING adapter therefore injected a fresh `wdev_*` on every launch: strictly worse than\n * injecting nothing, since the server counts `min_sessions` by distinct opens grouped on `device_key`,\n * so a per-launch key corrupts that counter AND inflates distinct-device counts. Callers that write a\n * key onto the wire as a cross-launch join must read `durable` and refuse a `false`.\n *\n * Resolves `undefined` only when there is no usable id at all. With no `storage` it resolves\n * immediately with `durable: false` — a process-scoped id is exactly what \"no persistence\" means.\n * Never throws or rejects.\n */\nexport const hydrateDeviceIdentity = async (\n opts: ResolveAutoDeviceKeyOptions = {},\n): Promise<IdentityRecord | undefined> => {\n // Mint + register synchronously first, so a waiter and a concurrent sync caller share ONE id.\n const id = resolveAutoDeviceKey(opts);\n const appId = opts.appId ?? \"default\";\n const record = (value: string, durable: boolean): IdentityRecord | undefined =>\n resolveIdentity({ value, space: \"device\", source: \"auto\", durable, scope: appId });\n\n if (!opts.storage) return record(id, false);\n const registry = autoDeviceKeyRegistry();\n const pending = registry.pending?.get(appId);\n // No pending entry means a previous hydration already settled DEGRADED and released its latches\n // (see `startHydration`), so the live id is the in-memory one — real, but not durable.\n if (!pending) return record(registry.keys.get(appId) ?? id, false);\n const outcome = await pending;\n return record(outcome.value, outcome.durable);\n};\n\n/** Test-only: forget every auto id + hydration flag so a unit test starts from a clean registry. */\nexport const resetAutoDeviceKeys = (): void => {\n const registry = autoDeviceKeyRegistry();\n registry.keys.clear();\n registry.hydrating.clear();\n registry.pending?.clear();\n};\n","/**\n * currentSession — a tiny registry of the CURRENT per-open `session_id`.\n *\n * WHY it exists (kills the phantom-session): the per-open emitters (`reportSessionStart` and the\n * `useSessionStart` / `useLifecycleEvents` hooks) mint a fresh `session_id` for each app-open and\n * post `app.session_started` with it — so the SERVER knows that id. But other client paths\n * (`identify`, host `app_event`s through the analytics façade) used to reference a DIFFERENT id\n * (a frozen per-instance id), which the server had never seen, so it back-filled a synthetic\n * `session_started` — inflating session counts (the \"phantom-session\" bug).\n *\n * This registry is the single seam that lets those paths reuse the LIVE per-open session id the\n * server already ingested. `reportSessionStart` writes the current id here on every open; the façade\n * reads it so `identify`/app-events correlate to the real session instead of minting a phantom.\n *\n * ── WHY A globalThis SLOT, NOT A PLAIN MODULE VARIABLE ────────────────────────────────────────\n * This module is exported from TWO package entry points — the main `.` bundle (`src/index.ts`) and\n * the `./analytics` subpath (`src/analytics/index.ts`). Under `dist` resolution (node `import`/\n * `require`, which is how tests, SSR and some tooling load the kit) tsup inlines a SEPARATE copy of\n * this module into each bundle, so a plain `let` would give the SETTER (reached via `.` →\n * `reportSessionStart`) and the READER (reached via `./analytics` → façade / `userIdentity`) TWO\n * different variables: the reader would see `undefined` even after an open set the id, and gating\n * would fire under a null session id. On-device this was masked only because Metro's `react-native`\n * export condition resolves both subpaths back to this one `src/` file (a single instance) — a\n * bundler accident, not a guarantee.\n *\n * The bundler-agnostic fix: keep the ONE live value in a well-known `globalThis` slot keyed by a\n * `Symbol.for(...)`. `Symbol.for` uses the runtime-global symbol registry, so every inlined copy of\n * this module resolves the SAME symbol and reads/writes the SAME slot — one identity no matter how\n * many times the module is duplicated across bundles. `globalThis` is present and identical in\n * Hermes/React Native, Node and SSR (we never touch `window`), so this is safe on every host.\n *\n * PROCESS-LOCAL, NOT PERSISTED: the slot lives on the runtime global, so it tracks the CURRENT\n * process's open and a fresh open overwrites it. There is no cross-launch state.\n * `resetCurrentSessionId` clears the slot so a unit test starts from a clean registry.\n *\n * ── WHY `ensureCurrentSessionId` EXISTS (the silent-drop contract) ─────────────────────────────\n * The server's event model declares `session_id: str = Field(min_length=1)` — REQUIRED, non-empty.\n * `POST /v1/events` validates each event inside a try/except that increments a `skipped` counter and\n * still returns HTTP 200. So an event posted without a `session_id` is accepted by the wire and\n * DISCARDED by the server, and a fire-and-forget client can never learn it happened. That is the\n * worst of both: no error, no data. Screen tracking in a host that never mounted the lifecycle hook\n * fell into exactly that hole — every screen view posted, 200'd, and dropped.\n *\n * `ensureCurrentSessionId` closes it: it returns the registered id when an open HAS been registered\n * (unchanged behaviour for every host that fires `reportSessionStart` first), and otherwise mints one,\n * REGISTERS it, and returns it — so every later event in the process correlates to that same id\n * instead of each emitting its own orphan. A minted id is a fallback, not a substitute for a real\n * app-open: it warns once in dev, naming the fix.\n */\nimport { makeSessionId } from \"./reportClientEvent\";\n// The shared primitive returns whether it ACTUALLY warned, which the once-flag below depends on:\n// marking \"already warned\" after a prod no-op would burn the single warning and leave the one dev\n// build that needed it silent. (The old local copy justified itself as keeping this module\n// import-free for the tree-shaken analytics bundle; that had already lapsed — it imports\n// `makeSessionId` right here — and `utils/warnInDev` has no imports of its own.)\nimport { warnInDev } from \"../utils/warnInDev\";\n\n/**\n * Well-known key into the runtime-global symbol registry. `Symbol.for` (NOT a plain `Symbol()`) is\n * what makes this cross-bundle: it returns the SAME symbol for the same string across every copy of\n * this module, so duplicated inlined copies all address one slot.\n */\nconst CURRENT_SESSION_ID_SLOT: unique symbol = Symbol.for(\n \"@wireai/activation:currentSessionId\",\n);\n\ntype GlobalWithSlot = typeof globalThis & {\n [CURRENT_SESSION_ID_SLOT]?: string | undefined;\n};\n\nconst globalSlot = globalThis as GlobalWithSlot;\n\n/**\n * Record the current per-open `session_id`. Called by `reportSessionStart` when it emits an\n * app-open. A blank / non-string id is ignored (the previous id stays current). Idempotent.\n */\nexport const setCurrentSessionId = (id: string | undefined): void => {\n if (typeof id === \"string\" && id.length > 0) {\n globalSlot[CURRENT_SESSION_ID_SLOT] = id;\n }\n};\n\n/** The current per-open `session_id`, or `undefined` when no app-open has been registered yet. */\nexport const getCurrentSessionId = (): string | undefined =>\n globalSlot[CURRENT_SESSION_ID_SLOT];\n\n/** Test-only: forget the current session id so a unit test starts from a clean registry. */\nexport const resetCurrentSessionId = (): void => {\n globalSlot[CURRENT_SESSION_ID_SLOT] = undefined;\n};\n\n/** The one-time message. Hoisted so a prod mint does not rebuild a string nobody will read. */\nconst MINT_WARNING =\n \"[wireai] No app-open session was registered, so a session id was minted for this event \" +\n \"(the server drops an event that has no session_id, and still answers 200). Mount \" +\n \"useLifecycleEvents at your app root so events correlate to a real app-open.\";\n\n/**\n * \"Have we already warned about a minted session id?\" — its OWN `Symbol.for` slot, for the same\n * cross-bundle reason as the id itself: a plain module `let` would warn once per inlined copy, i.e.\n * once per bundle, not once per process. NOT cleared by `resetCurrentSessionId`: \"warn once\" is a\n * process-lifetime promise, and a test that resets the id between mints is still one process.\n */\nconst MINT_WARNED_SLOT: unique symbol = Symbol.for(\n \"@wireai/activation:currentSessionIdMintWarned\",\n);\n\ntype GlobalWithWarnSlot = typeof globalThis & { [MINT_WARNED_SLOT]?: boolean };\n\nconst warnSlot = globalThis as GlobalWithWarnSlot;\n\n/**\n * The current per-open `session_id`, MINTING and registering one when no app-open has been\n * registered yet. Always returns a non-empty string. Idempotent (a second call returns the same id)\n * and never throws.\n *\n * Use this on every path that puts a `session_id` on the wire. The server REQUIRES a non-empty\n * `session_id` and drops the event otherwise while still answering 200 (see the module header), so\n * \"no id yet\" must never mean \"send it without one\".\n *\n * BACKWARD-COMPATIBLE BY CONSTRUCTION: when `reportSessionStart` / `useLifecycleEvents` has already\n * registered the real per-open id, this is `getCurrentSessionId()` and nothing changes. It only ever\n * mints in the case that used to produce a silently discarded event.\n *\n * A mint means the host never registered an app-open, so the minted id is one the server has not\n * seen a `session_started` for — the events land, but the session is thinner than a real open.\n * Hence the one-time dev warning naming the fix (mount `useLifecycleEvents` at the app root).\n */\nexport const ensureCurrentSessionId = (): string => {\n const existing = globalSlot[CURRENT_SESSION_ID_SLOT];\n if (typeof existing === \"string\" && existing.length > 0) return existing;\n const minted = makeSessionId();\n globalSlot[CURRENT_SESSION_ID_SLOT] = minted;\n if (!warnSlot[MINT_WARNED_SLOT] && warnInDev(MINT_WARNING)) {\n warnSlot[MINT_WARNED_SLOT] = true;\n }\n return minted;\n};\n","/**\n * Session-id persistence — the kit caching its OWN correlation seed across app kills.\n *\n * WHY: the session id is minted per mount and forwarded to the backend as the A2A\n * `contextId` (see WireOnboarding). Without persistence, an app KILL mid-onboarding\n * mints a NEW id on relaunch — the server counts a second `session_started` and the\n * orphaned first session reads as a phantom \"drop\", inflating the funnel's `started`\n * denominator. Persisting `{ id, ts }` and reusing a still-fresh id keeps a\n * kill-and-relaunch a SINGLE session in analytics.\n *\n * SCOPE: this persists the correlation seed ONLY — never answers. Answer persistence\n * stays a host concern via `onComplete` (the kit/host boundary is unchanged).\n *\n * The host injects the storage via the `storage` prop (an AsyncStorage-compatible\n * subset), keeping the kit dependency-free: an MMKV wrapper and AsyncStorage itself\n * both fit. Every operation is best-effort — a broken or hung storage must NEVER\n * break (or indefinitely gate) onboarding: reads race a short timeout, writes and\n * removes swallow all errors.\n */\nimport { makeSessionId } from \"../analytics/reportClientEvent\";\n\n/**\n * The storage the host injects. Deliberately the AsyncStorage-compatible subset so\n * `@react-native-async-storage/async-storage` can be passed as-is, and an MMKV (or\n * any other) wrapper is three one-line methods.\n */\nexport type WireOnboardingStorage = {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n};\n\n/**\n * Matches the backend's session TTL (SESSION_TTL_SECONDS = 3600): an id older than\n * this can't be resumed server-side anyway, so the client mints fresh past it.\n */\nexport const DEFAULT_SESSION_TTL_MS = 3_600_000;\n\n/** Ceiling on the storage read — a hung adapter degrades to a fresh mint, never a stuck gate. */\nexport const READ_TIMEOUT_MS = 1_500;\n\n/** Storage key for an app's cached session, e.g. `wireai:session:acme`. */\nexport const sessionStorageKey = (appId: string): string => `wireai:session:${appId}`;\n\ntype PersistedSession = { id: string; ts: number };\n\n/** Resolved session for a mount: the id to use + whether it was restored from storage. */\nexport type LoadedSession = {\n id: string;\n /** True when a stored, still-fresh id was reused — the flow resumes instead of starting. */\n resumed: boolean;\n};\n\n/**\n * Race a storage read against a ceiling, resolving `undefined` when the adapter did not answer.\n * Exported so the permission memory reads through the same ceiling as the session seed rather than\n * carrying a second copy of it. NOT the kit's only such helper: `features/cache.ts`,\n * `session-analytics/lifecycle.ts` and `analytics/eventQueue.ts` each keep their own local timeout\n * for their own transports. Consolidating those is a separate change, not this one.\n */\nexport const withTimeout = <T>(p: Promise<T>, ms: number): Promise<T | undefined> => {\n let timer: ReturnType<typeof setTimeout>;\n const timeout = new Promise<undefined>((resolve) => {\n timer = setTimeout(() => resolve(undefined), ms);\n });\n // Clear the timer once the race settles, so a won read doesn't leave a ≤ms no-op\n // timer holding the closure alive.\n return Promise.race([p, timeout]).finally(() => clearTimeout(timer));\n};\n\nconst parsePersisted = (raw: string | null | undefined): PersistedSession | undefined => {\n if (!raw) return undefined;\n try {\n const parsed: unknown = JSON.parse(raw);\n if (\n typeof parsed === \"object\" &&\n parsed !== null &&\n typeof (parsed as PersistedSession).id === \"string\" &&\n typeof (parsed as PersistedSession).ts === \"number\"\n ) {\n return parsed as PersistedSession;\n }\n } catch {\n // Corrupt entry → treat as absent; the caller mints fresh and overwrites it.\n }\n return undefined;\n};\n\n/**\n * Resolve the session id for this mount: reuse the stored one while it's fresh\n * (→ `resumed: true`), else mint via `makeSessionId`, persist it, and start clean.\n * Never throws; never hangs past the read timeout.\n */\nexport const loadPersistedSession = async (\n storage: WireOnboardingStorage,\n key: string,\n ttlMs: number = DEFAULT_SESSION_TTL_MS,\n): Promise<LoadedSession> => {\n let stored: PersistedSession | undefined;\n try {\n stored = parsePersisted(await withTimeout(storage.getItem(key), READ_TIMEOUT_MS));\n } catch {\n stored = undefined;\n }\n if (stored && Date.now() - stored.ts < ttlMs) {\n return { id: stored.id, resumed: true };\n }\n const id = makeSessionId();\n savePersistedSession(storage, key, id);\n return { id, resumed: false };\n};\n\n/**\n * Read the persisted session WITHOUT minting a fresh one (unlike `loadPersistedSession`).\n * Returns the stored `{ id, ts }` or `undefined` when absent/corrupt/timed-out. Used by the\n * post-onboarding `identifyOnboarding` helper to recover the contextId to bind a user to.\n * Never throws; never hangs past the read timeout.\n */\nexport const peekPersistedSession = async (\n storage: WireOnboardingStorage,\n key: string,\n): Promise<{ id: string; ts: number } | undefined> => {\n try {\n return parsePersisted(await withTimeout(storage.getItem(key), READ_TIMEOUT_MS));\n } catch {\n return undefined;\n }\n};\n\n/** Persist `{ id, ts }` under `key` — fire-and-forget, all errors swallowed. */\nexport const savePersistedSession = (\n storage: WireOnboardingStorage,\n key: string,\n id: string,\n): void => {\n try {\n void storage.setItem(key, JSON.stringify({ id, ts: Date.now() })).catch(() => {});\n } catch {\n // Best-effort: a failed write just means the next launch starts a fresh session.\n }\n};\n\n/** Remove the cached id (fired on completion) — fire-and-forget, all errors swallowed. */\nexport const clearPersistedSession = (storage: WireOnboardingStorage, key: string): void => {\n try {\n void storage.removeItem(key).catch(() => {});\n } catch {\n // Best-effort.\n }\n};\n\n/**\n * The opt-in decision for `WireOnboarding.handleComplete`: given the host's\n * `retainSessionOnComplete` opt-in, whether a completion should CLEAR the persisted seed.\n * (The caller still gates on `storage` being present — this only encodes the opt-in axis, so the\n * legacy `if (storage) clearPersistedSession(...)` guard stays byte-for-byte for a host that does\n * not opt in.)\n *\n * - undefined / false (the default) → `true`: clear on completion, so the NEXT onboarding on this\n * device mints a fresh session. This is the legacy single-stage behavior.\n * - true → `false`: LEAVE the seed in place so a same-signup re-entry/remount within the TTL\n * resumes the SAME session (one funnel start) instead of minting a phantom second `started`.\n * Freshness for a genuinely new run is then governed by the TTL (past `sessionTtlMs` → fresh\n * mint) and an explicit new-run signal (a changed `persistKey`).\n */\nexport const shouldClearOnComplete = (retainSessionOnComplete: boolean | undefined): boolean =>\n !retainSessionOnComplete;\n","/**\n * User identity — bind an onboarding session to the HOST's own user id so the funnel can\n * be reconciled to real users later (console sessions ↔ your user table / GA4 users).\n *\n * The id is an OPAQUE PSEUDONYMOUS STRING the host owns — its internal user id, NOT an\n * email/name/phone. Same host-injection philosophy as `storage` and `userContext`: the kit\n * mints nothing and reads nothing; the host passes what it wants. Dependency-free.\n *\n * Three binding moments (see WireOnboarding + the README \"User identity\" section):\n * 1. MOUNT — pass `userId` and it rides the A2A session-start metadata; the server\n * binds it when it creates the session.\n * 2. MID-SESSION— the user registers DURING onboarding: change the `userId` prop and the\n * kit emits an `identify` client event that attaches the id to the live\n * session (late binding — the key scenario).\n * 3. POST-FLOW — the user registers AFTER onboarding: call `identifyOnboarding(...)` with\n * the same host storage (it recovers the persisted contextId, before completion\n * clears it) or, more reliably, the `contextId` you captured from the\n * `started`/`resumed` `onEvent` (both events carry a `contextId` field).\n *\n * ⚠️ NO PII. Pass an opaque id (or a hash), never a raw email/name/phone. The id is capped at\n * {@link USER_ID_MAX_LENGTH} chars (longer ids are truncated, not rejected).\n */\nimport { getCurrentSessionId } from \"../analytics/currentSession\";\nimport { reportClientEvent } from \"../analytics/reportClientEvent\";\nimport {\n peekPersistedSession,\n sessionStorageKey,\n type WireOnboardingStorage,\n} from \"../session/persistedSession\";\n\n/** Max accepted user-id length. Longer strings are truncated (never rejected). Keep in sync\n * with the server's `USER_ID_MAX_LENGTH` (analytics/events.py). */\nexport const USER_ID_MAX_LENGTH = 128;\n\n/**\n * Normalize a host-supplied user id: trim, drop empty, and cap at {@link USER_ID_MAX_LENGTH}.\n * Returns `undefined` for a missing/blank/non-string value so callers can `if (id)`-gate.\n * PII is a host concern — this only bounds length, it does not (and cannot) detect an email.\n */\nexport const sanitizeUserId = (raw: unknown): string | undefined => {\n if (typeof raw !== \"string\") return undefined;\n const trimmed = raw.trim();\n if (!trimmed) return undefined;\n return trimmed.length > USER_ID_MAX_LENGTH ? trimmed.slice(0, USER_ID_MAX_LENGTH) : trimmed;\n};\n\n/**\n * A permissive email-SHAPE test (`local@domain.tld`) — NOT an RFC validator. Its ONE job is to\n * catch the common integration mistake of binding a RAW EMAIL as the opaque `user_id`: that leaks\n * PII into the top-level id (which the server treats as an opaque key and may surface), when the\n * email belongs in the opt-in `user_context.user_email` field instead. `identify()` uses this to\n * refuse an email-shaped id (with a dev warning) unless the host opts in explicitly. Trims first.\n */\nexport const looksLikeEmail = (value: unknown): boolean =>\n typeof value === \"string\" && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value.trim());\n\n/** Options for {@link identifyOnboarding}. */\nexport type IdentifyOnboardingOptions = {\n /** Tenant transport, same shape as `WireOnboardingConfig` (only these two fields are used). */\n config: { serverUrl: string; apiKey: string };\n /** The host's opaque user id to bind. Trimmed + capped; NO PII. */\n userId: string;\n /**\n * The onboarding session id to bind to (the A2A contextId) — the `contextId` field carried on\n * the `started`/`resumed` `onEvent`. Pass this when you captured it there. Required after the\n * flow COMPLETED, since completion clears the persisted session. Wins over the storage lookup.\n */\n contextId?: string;\n /**\n * The SAME host storage you passed to `<WireOnboarding storage={…} />`. When `contextId` is\n * omitted, the helper reads the persisted contextId from it (works while the session is still\n * persisted — i.e. dropped or mid-flow, before completion clears it).\n */\n storage?: WireOnboardingStorage;\n /** App id, to derive the default storage key `wireai:session:<appId>` when reading from storage. */\n appId?: string;\n /** Storage key override — pass the same `persistKey` you gave `<WireOnboarding>`, if any. */\n persistKey?: string;\n /**\n * OPT-IN LAST RESORT, default `false`. When no ONBOARDING session can be resolved (no `contextId`,\n * nothing in `storage`), bind the user to the LIVE PER-OPEN app session instead and return\n * `\"app_session\"`.\n *\n * ⚠️ These are two different id spaces sharing one wire field. An onboarding session id is the A2A\n * `contextId`; a per-open id is what `app.session_started` registers. The server's onboarding funnel\n * groups by `session_id`, so a per-open id posted here does not attach the user to their onboarding\n * — it writes a row nothing in that funnel can join. Until 0.13.0 this happened SILENTLY and\n * returned `true`, in exactly the documented post-completion case (completion clears the persisted\n * session), so the funnel stayed unattributed while the host was told it had worked.\n *\n * Turn it on only if binding the id to *some* session the server saw is genuinely worth more to you\n * than knowing the onboarding bind failed — and read the return value, which now says which it was.\n */\n allowAppSessionFallback?: boolean;\n};\n\n/**\n * What {@link identifyOnboarding} bound, and to WHICH id space — because `true` could not say.\n *\n * • `\"onboarding\"` — bound to the A2A `contextId`. This is the one that attributes the funnel.\n * • `\"app_session\"` — bound to the live per-open app session, via `allowAppSessionFallback`. The\n * server saw that session, but it is not this user's onboarding.\n * • `false` — nothing was dispatched (no user id, no server url, no resolvable session).\n *\n * ⚠️ 0.13.0 widened this from `boolean`. `\"onboarding\"` is truthy, so an `if (await identify…)` still\n * behaves identically; only an explicit `: boolean` annotation needs updating.\n */\nexport type IdentifyOnboardingBinding = \"onboarding\" | \"app_session\" | false;\n\n/**\n * Attach a host user id to an onboarding session AFTER the fact (post-registration), by sending\n * an `identify` client event to `/v1/events`. Resolves the contextId from an explicit\n * `contextId` or, failing that, from the persisted session in the host `storage`.\n *\n * Fire-and-forget under the hood (never throws, never blocks onboarding). Resolves to the\n * {@link IdentifyOnboardingBinding} that says WHICH id space was bound, or `false` when nothing could\n * be (no user id, no server url, or no resolvable session).\n */\nexport const identifyOnboarding = async (\n opts: IdentifyOnboardingOptions,\n): Promise<IdentifyOnboardingBinding> => {\n const userId = sanitizeUserId(opts.userId);\n if (!userId || !opts.config?.serverUrl) return false;\n\n let contextId = opts.contextId?.trim() || undefined;\n if (!contextId && opts.storage) {\n const key = opts.persistKey ?? (opts.appId ? sessionStorageKey(opts.appId) : undefined);\n if (key) {\n const stored = await peekPersistedSession(opts.storage, key);\n contextId = stored?.id;\n }\n }\n let space: Exclude<IdentifyOnboardingBinding, false> = \"onboarding\";\n // The OPT-IN last resort. Until 0.13.0 this ran unconditionally: with no captured contextId\n // it posted the LIVE PER-OPEN session id in the `session_id` field — which on this endpoint means\n // the ONBOARDING session — and then returned `true`. Two disjoint id spaces share that field, so\n // the row it wrote could never join the onboarding funnel, and the host got a success signal for a\n // bind that had not happened. It is now off unless the caller asks, and when it does fire it says\n // so in the return value instead of impersonating an onboarding bind.\n if (!contextId && opts.allowAppSessionFallback) {\n contextId = getCurrentSessionId();\n space = \"app_session\";\n }\n if (!contextId) return false;\n\n reportClientEvent(\n { serverUrl: opts.config.serverUrl, apiKey: opts.config.apiKey },\n { event_type: \"identify\", session_id: contextId, user_id: userId },\n );\n return space;\n};\n","/**\n * userContext — the ONE extensible object a host passes once and the kit flows into every\n * analytics event's `user_context` (plus the top-level opaque `user_id`).\n *\n * WHY it exists: hosts already hand the kit fragments of \"who this user is\" — `config.appVersion`,\n * `useSessionStart({ deviceKey, userId })`, `<WireOnboarding userContext={…} />` — but there was no\n * single object that carries app version + device key + user id + (opt-in) email + arbitrary extras\n * together, with one precedence rule, into every event. `WireUserContext` is that object;\n * `resolveUserContext` is the pure merge that turns it into the wire shape.\n *\n * PRECEDENCE (the one rule): an explicit `WireUserContext` field WINS over the #42 auto-detected\n * `device`/`appVersion`. A missing field is OMITTED, never sent empty.\n *\n * WHERE EACH FIELD LANDS (deliberate separation so nothing leaks across buckets):\n * • `userId` → the event's TOP-LEVEL opaque `user_id` (via `sanitizeUserId`). NEVER the bucket.\n * • `userEmail` → its OWN key `user_context.user_email`. NEVER merged into `userId`. OPT-IN PII.\n * • `deviceKey` → `user_context.device_key` (the server's `_event_device_key` reads it there).\n * • `appVersion`→ `user_context.app_version` (and returned as `appVersion` for `device.appVersion`).\n * • `extra` → NAMESPACED under a `custom.` key prefix, coerced to scalars, so a host extra can\n * never collide with a reserved `user_context` key.\n *\n * DEPENDENCY-FREE: the only import is the kit's own `sanitizeUserId`. The optional email hash is a\n * dependency-free FNV-1a fold (see {@link hashEmailFnv1a}) — no crypto library, no async.\n */\nimport { sanitizeUserId } from \"../identity/userIdentity\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\n\n/**\n * The single, extensible user-context object. A host passes it ONCE (at analytics init) and may\n * update it post-mount (e.g. attach `userId`/`userEmail` at login) via `setUserContext(partial)`.\n * Every field is optional; missing fields are omitted from the wire payload.\n */\nexport interface WireUserContext {\n /**\n * Host app version, e.g. \"1.4.2\". EXPLICIT — wins over the #42 auto-detected `device.appVersion`.\n * Lands in `user_context.app_version`. Omitted when neither this nor auto-detect yields a version.\n */\n appVersion?: string;\n /**\n * A stable, non-PII device id the host owns. Lands in `user_context.device_key` (NOT `session_id`),\n * where the server groups a device's sessions. Host-supplied; the kit never mints or reads one.\n */\n deviceKey?: string;\n /**\n * The host's OPAQUE PSEUDONYMOUS user id (their internal id — NOT an email/name/phone). Sanitized +\n * capped (see `sanitizeUserId`) and placed on the event's top-level `user_id`. NEVER the bucket.\n */\n userId?: string;\n /**\n * OPT-IN PII. The user's email, its OWN field (`user_context.user_email`) — NEVER merged into\n * `userId`. The kit NEVER auto-collects this; a host passes it only WITH the user's consent (EU\n * users: treat as personal data). For a non-reversible form, set {@link hashEmail} `true` (the kit\n * folds it with a dependency-free hash and stamps `user_context.user_email_hashed: true`), OR\n * pre-hash host-side with a cryptographic digest and pass that here with `hashEmail` falsy.\n */\n userEmail?: string;\n /**\n * When `true`, {@link userEmail} is folded with the kit's dependency-free {@link hashEmailFnv1a}\n * before it leaves the device, and `user_context.user_email_hashed` is set `true`. NOTE: FNV-1a is\n * a lightweight NON-cryptographic fold (obfuscation, not a secure digest). For a cryptographic\n * hash, compute it host-side (e.g. SHA-256 via `expo-crypto`) and pass the digest as `userEmail`\n * with `hashEmail` falsy. Default: raw email is sent as-is (opt-in already gated it upstream).\n */\n hashEmail?: boolean;\n /**\n * Arbitrary host context (signup method, referral, plan tier…). Each value is coerced to a scalar\n * (`string | number | boolean`; non-scalars and non-finite numbers are DROPPED) and NAMESPACED\n * under a `custom.` key prefix in `user_context` (e.g. `user_context[\"custom.referral\"]`) so it can\n * never collide with a reserved key. No raw PII — use {@link userEmail} for email.\n */\n extra?: Record<string, string | number | boolean>;\n}\n\n/**\n * The wire-shaped result of {@link resolveUserContext}. `userContext` is the non-PII/opt-in-PII\n * bucket stamped onto the event; `userId` is the top-level opaque id; `appVersion`/`deviceKey` are\n * echoed for callers that also place them elsewhere (e.g. `device.appVersion`). Absent fields are\n * omitted so a caller can spread this without sending empties.\n */\nexport interface ResolvedUserContext {\n /** The opaque, sanitized user id → the event's top-level `user_id`. Omitted when unset/blank. */\n userId?: string;\n /** The stable device id → `user_context.device_key`. Omitted when unset. */\n deviceKey?: string;\n /** The effective app version (explicit > auto-detected) → `user_context.app_version`. */\n appVersion?: string;\n /** The `user_context` bucket (device_key, app_version, user_email[+ _hashed], custom.*). */\n userContext?: Record<string, string | number | boolean>;\n}\n\n/** The prefix applied to every host `extra` key so it can never collide with a reserved key. */\nexport const EXTRA_KEY_PREFIX = \"custom.\" as const;\n\n/** A finite scalar the wire accepts. Non-finite numbers (NaN/Infinity) are NOT scalars here. */\nexport const isWireScalar = (value: unknown): value is string | number | boolean => {\n const t = typeof value;\n if (t === \"string\" || t === \"boolean\") return true;\n if (t === \"number\") return Number.isFinite(value as number);\n return false;\n};\n\n/**\n * Fold an email to a stable, dependency-free 32-bit FNV-1a hex token (lowercased + trimmed first so\n * the same address always folds identically). This is OBFUSCATION, not a cryptographic digest — it\n * is not collision-resistant. For a real hash, pre-hash host-side and pass the digest as `userEmail`.\n */\nexport const hashEmailFnv1a = (email: string): string => {\n const normalized = email.trim().toLowerCase();\n let hash = 0x811c9dc5; // FNV offset basis (32-bit)\n for (let i = 0; i < normalized.length; i++) {\n hash ^= normalized.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193); // FNV prime (32-bit), kept in 32-bit via imul\n }\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n};\n\n/** Trim a candidate string; return `undefined` for a non-string / blank so callers can `if`-gate.\n * Shared with `activation/wireActivation`, which carried a byte-identical private copy named `clean`.\n * Not re-exported from the package barrel — this is an internal helper, not public surface. */\nexport const cleanString = (value: unknown): string | undefined => {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n};\n\n/**\n * Coerce a host `extra` map into the namespaced, scalar-only bucket shape. Every kept value is\n * placed under `custom.<key>`; non-scalar values (objects, arrays, null, functions, NaN/Infinity)\n * are DROPPED. Returns an object (possibly empty).\n */\nexport const namespaceExtra = (\n extra: Record<string, unknown> | undefined,\n): Record<string, string | number | boolean> => {\n const out: Record<string, string | number | boolean> = {};\n if (!extra || typeof extra !== \"object\") return out;\n for (const [key, value] of Object.entries(extra)) {\n const cleanKey = cleanString(key);\n if (!cleanKey) continue;\n if (!isWireScalar(value)) continue; // drop anything that isn't a finite scalar\n out[`${EXTRA_KEY_PREFIX}${cleanKey}`] = value;\n }\n return out;\n};\n\n/**\n * The storage key the analytics façade persists the bound opaque `user_id` under (namespaced per\n * `appId`, mirroring {@link deviceIdStorageKey}). Exported so a logout path can target it directly.\n */\nexport const analyticsUserIdStorageKey = (appId?: string): string =>\n `wireai:analytics:userId:${appId ?? \"default\"}`;\n\n/**\n * Return a COPY of a {@link WireUserContext} with every USER-scoped (PII / pseudonymous) field\n * removed — `userId`, `userEmail`, `hashEmail`, and `extra` — while KEEPING the non-PII device-scope\n * fields (`appVersion`, `deviceKey`). This is the in-memory half of logout: after it, the same\n * analytics instance keeps its stable `device_key` (which groups a DEVICE, not a user) but no longer\n * stamps the previous user's id/email onto events. Pure; never mutates the input.\n */\nexport const clearPiiFromContext = (ctx: WireUserContext = {}): WireUserContext => {\n const rest: WireUserContext = {};\n if (typeof ctx.appVersion === \"string\") rest.appVersion = ctx.appVersion;\n if (typeof ctx.deviceKey === \"string\") rest.deviceKey = ctx.deviceKey;\n return rest;\n};\n\n/** Options for {@link clearUserContext}. */\nexport interface ClearUserContextOptions {\n /** Host persistence (AsyncStorage subset) — the persisted bound `user_id` is removed from here. */\n storage?: WireOnboardingStorage;\n /** Tenant/app id — namespaces the persisted key (`wireai:analytics:userId:<appId>`). */\n appId?: string;\n}\n\n/**\n * LOGOUT primitive: purge the persisted, bound opaque `user_id` for an app so the NEXT user on a\n * shared device is not silently attributed to the previous one. Removes the\n * `wireai:analytics:userId:<appId>` key that the analytics façade persists and reuses across\n * launches. Fire-and-forget: a missing storage or a failing adapter resolves quietly.\n *\n * COVERAGE. The stateful `createAnalytics(...)` instance also exposes {@link Analytics.reset}, which\n * does this AND clears the in-memory binding + PII in one call — prefer it when you hold the\n * instance. This standalone helper covers the `createWireActivation` / `wire` path (whose config is\n * captured immutably, so it has no `reset`): call `clearUserContext({ storage, appId })` on logout,\n * and RECREATE the `wire` / analytics instance without the user's `userContext` (userId/userEmail)\n * so no further events carry the previous user's identity. The non-PII per-install `device_key`\n * (`wireai:analytics:deviceKey:<appId>`) is intentionally left in place — it groups a device, not a\n * person, and stays stable across users of the same install.\n */\nexport const clearUserContext = async (opts: ClearUserContextOptions = {}): Promise<void> => {\n const storage = opts.storage;\n if (!storage) return;\n try {\n await storage.removeItem(analyticsUserIdStorageKey(opts.appId));\n } catch {\n /* best-effort, swallow — logout must never throw into the UI */\n }\n};\n\n/**\n * The `userContext` value to hand `<WireOnboarding userContext={...} />` so an onboarding session\n * and the app's later events (purchases, actions, screens) share ONE join key.\n *\n * WHY it exists as a named function instead of an inline object literal: the wire key is\n * `device_key`, the prop-facing name is `deviceKey`, and the analytics surfaces auto-mint the value\n * for you. A host that hand-writes `userContext={{ deviceKey }}` produces a bucket the server's\n * device lookup does not read, and the resulting funnel is silently EMPTY rather than wrong. This is\n * the one place that spelling is decided.\n *\n * Pass the SAME `deviceKey` you gave `createAnalytics` / `createWireActivation`. `session_id` is not\n * a join key across those two families: an onboarding session id is the A2A `contextId` and an\n * app-event session id is the per-open id, so intersecting them returns nothing.\n */\nexport const activationJoinContext = (\n deviceKey: string,\n): Record<string, string | number | boolean> => resolveUserContext({ deviceKey }).userContext ?? {};\n\n/** Options for {@link resolveUserContext}. */\nexport interface ResolveUserContextOptions {\n /**\n * The kit's best-effort auto-detected app version (#42; from `detectAppVersion()`/the device\n * snapshot). Used ONLY when the explicit `WireUserContext.appVersion` is absent — explicit wins.\n */\n autoAppVersion?: string;\n}\n\n/**\n * Merge a {@link WireUserContext} into the wire shape with the precedence rule (explicit field >\n * auto-detected). Pure, never throws. Missing fields are omitted so the result can be spread onto an\n * event without sending empties.\n */\nexport const resolveUserContext = (\n ctx: WireUserContext = {},\n opts: ResolveUserContextOptions = {},\n): ResolvedUserContext => {\n const result: ResolvedUserContext = {};\n const bucket: Record<string, string | number | boolean> = {};\n\n // userId → top-level opaque id (NEVER the bucket). Sanitized + capped host-side.\n const userId = sanitizeUserId(ctx.userId);\n if (userId) result.userId = userId;\n\n // deviceKey → user_context.device_key (NOT session_id).\n const deviceKey = cleanString(ctx.deviceKey);\n if (deviceKey) {\n result.deviceKey = deviceKey;\n bucket.device_key = deviceKey;\n }\n\n // appVersion → explicit wins over auto-detected (#42); echoed for device.appVersion callers.\n const appVersion = cleanString(ctx.appVersion) ?? cleanString(opts.autoAppVersion);\n if (appVersion) {\n result.appVersion = appVersion;\n bucket.app_version = appVersion;\n }\n\n // userEmail → its OWN key. OPT-IN PII, optionally folded. NEVER touches userId.\n const email = cleanString(ctx.userEmail);\n if (email) {\n if (ctx.hashEmail) {\n bucket.user_email = hashEmailFnv1a(email);\n bucket.user_email_hashed = true;\n } else {\n bucket.user_email = email;\n }\n }\n\n // extra → namespaced + scalar-coerced.\n Object.assign(bucket, namespaceExtra(ctx.extra));\n\n if (Object.keys(bucket).length > 0) result.userContext = bucket;\n return result;\n};\n","/**\n * permissionMemory - \"shown exactly once per session\", kept true across an app kill.\n *\n * The in-memory guard alone is not enough. The kit already resumes a killed onboarding into the\n * SAME backend session (see `persistedSession.ts`), so without a persisted record the resumed mount\n * would re-show a permission screen the user had already answered - and on the ask path that means\n * a second dialog attempt against an OS that grants exactly one.\n *\n * The record is SCOPED TO THE SESSION ID, one entry, never a growing map: a record whose\n * `sessionId` is not the session being resumed is stale by definition and reads as empty. That is\n * also what makes a genuinely new onboarding start clean without anything having to expire it.\n *\n * Same host-injected `WireOnboardingStorage` and the same best-effort discipline as the session\n * seed: reads race the shared ceiling and degrade to \"nothing remembered\", writes swallow every\n * error. A broken storage adapter must never gate or break onboarding.\n */\nimport {\n READ_TIMEOUT_MS,\n withTimeout,\n type WireOnboardingStorage,\n} from \"../session/persistedSession\";\n\n/** Storage key for an app's settled permission screens, e.g. `wireai:permissions:acme`. */\nexport const permissionStorageKey = (appId: string): string => `wireai:permissions:${appId}`;\n\ntype PermissionRecord = { sessionId: string; ids: string[] };\n\n/**\n * PURE seam: which screen ids a stored blob contributes to THIS session. A corrupt entry, a\n * malformed shape, or a record belonging to a different session all read as \"nothing remembered\",\n * because re-showing a screen is a far cheaper failure than trusting another session's answers.\n */\nexport const readSettledPermissions = (\n raw: string | null | undefined,\n sessionId: string,\n): string[] => {\n if (!raw || !sessionId) return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null) return [];\n const record = parsed as Partial<PermissionRecord>;\n if (record.sessionId !== sessionId || !Array.isArray(record.ids)) return [];\n return record.ids.filter((id): id is string => typeof id === \"string\" && id.length > 0);\n } catch {\n // Corrupt entry: treat as absent. The next write overwrites it.\n return [];\n }\n};\n\n/** Read the settled ids for `sessionId`. Never throws, never hangs past the shared read ceiling. */\nexport const loadSettledPermissions = async (\n storage: WireOnboardingStorage,\n key: string,\n sessionId: string,\n): Promise<string[]> => {\n try {\n return readSettledPermissions(await withTimeout(storage.getItem(key), READ_TIMEOUT_MS), sessionId);\n } catch {\n return [];\n }\n};\n\n/** Persist the settled ids for `sessionId` - fire-and-forget, all errors swallowed. */\nexport const saveSettledPermissions = (\n storage: WireOnboardingStorage,\n key: string,\n sessionId: string,\n ids: readonly string[],\n): void => {\n try {\n const record: PermissionRecord = { sessionId, ids: [...ids] };\n void storage.setItem(key, JSON.stringify(record)).catch(() => {});\n } catch {\n // Best-effort: a failed write only means a resumed session may re-show the screen.\n }\n};\n\n/** Drop the record (fired alongside the session seed on completion) - fire-and-forget. */\nexport const clearSettledPermissions = (\n storage: WireOnboardingStorage,\n key: string,\n): void => {\n try {\n void storage.removeItem(key).catch(() => {});\n } catch {\n // Best-effort.\n }\n};\n","/**\n * WireOnboarding — the public host component. Drop it into a screen and it runs\n * the whole AI onboarding: builds the A2A transport from `config`, wires the SDK\n * provider with the themed cards, applies the theme, and renders the flow.\n *\n * <WireOnboarding\n * config={{ apiKey, serverUrl, appId }}\n * theme={myBrandTheme}\n * validators={{ username: checkUsernameAvailable }}\n * onComplete={persist}\n * onSkip={skip}\n * />\n */\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { WireAIProvider, type LocalLLMConfig } from \"wireai-rn\";\nimport { OnboardingThemeProvider } from \"./theme/ThemeContext\";\nimport { IllustrationProvider } from \"./components/Illustration\";\nimport { defaultIllustrations } from \"./illustrations/defaultIllustrations\";\nimport { IconRegistryProvider } from \"./icons/IconRegistry\";\nimport { LoadingScreen } from \"./components/LoadingScreen\";\nimport { OnboardingFlow, DEFAULT_COPY } from \"./OnboardingFlow\";\nimport { onboardingComponents } from \"./cards\";\nimport { makeSessionId, reportClientEvent, type ClientEventTarget } from \"./analytics/reportClientEvent\";\nimport { collectDeviceContext, type DeviceContext } from \"./device/deviceContext\";\nimport { hydrateDeviceIdentity } from \"./context/deviceId\";\nimport { activationJoinContext } from \"./context/userContext\";\nimport { hostIdentity, resolveIdentity } from \"./identity/identityRecord\";\nimport { sanitizeUserId } from \"./identity/userIdentity\";\nimport {\n clearPersistedSession,\n loadPersistedSession,\n sessionStorageKey,\n shouldClearOnComplete,\n DEFAULT_SESSION_TTL_MS,\n type LoadedSession,\n} from \"./session/persistedSession\";\nimport {\n clearSettledPermissions,\n loadSettledPermissions,\n permissionStorageKey,\n saveSettledPermissions,\n} from \"./permissions/permissionMemory\";\nimport type { OnboardingResult, WireOnboardingProps } from \"./types\";\nimport { warnInDev } from \"./utils/warnInDev\";\n\n/** Ceiling on the auto-join-key storage read — a hung adapter degrades to no key, never a stuck\n * loader. Matches the persisted-session read's own ceiling. */\nconst AUTO_JOIN_HYDRATION_TIMEOUT_MS = 1_500;\n\n/** The settled result of the auto-join read: a key to inject, or `null` plus WHY the kit declined.\n * `timeout` = the adapter never answered; `not-durable` = it answered but did not persist the id,\n * so injecting it would mean a different key on every launch. */\ntype AutoJoinOutcome = { key: string } | { key: null; reason: \"timeout\" | \"not-durable\" };\n\nexport const WireOnboarding: React.FC<WireOnboardingProps> = ({\n config,\n theme,\n components,\n illustrations,\n icons,\n validators,\n onComplete,\n onSkip,\n onError,\n onEvent,\n copy,\n approxScreens,\n startMessage = \"start\",\n startTimeoutMs = 15_000,\n fallbackFlow,\n maxRetries = 1,\n storage,\n sessionTtlMs = DEFAULT_SESSION_TTL_MS,\n persistKey,\n retainSessionOnComplete,\n userContext,\n userId,\n autoJoinKey = true,\n permissionScreens,\n}) => {\n // The host's own opaque user id (trimmed + capped, NO PII) so onboarding sessions can be\n // reconciled to real users later. `sanitizeUserId` is a pure string transform → the memoized\n // result is a stable primitive, safe to feed the `llm` / `clientContext` memos directly (unlike\n // the raw object props). Bound at three moments: session-start metadata (mount), an `identify`\n // event on a mid-session change (late binding), and the `identifyOnboarding` helper post-flow.\n const boundUserId = useMemo(() => sanitizeUserId(userId), [userId]);\n\n // Privacy-label-neutral device snapshot, collected once per mount (no advertising IDs, no\n // fingerprinting — see device/deviceContext.ts). `collectDeviceContext` already carries a\n // best-effort auto-detected `appVersion`; an explicit host `config.appVersion` overrides it.\n // Attached to BOTH the A2A session metadata and every client event so the backend can segment\n // the funnel by device (and by app version).\n const device = useMemo<DeviceContext>(() => {\n const collected = collectDeviceContext();\n return config.appVersion ? { ...collected, appVersion: config.appVersion } : collected;\n }, [config.appVersion]);\n\n // Stable serialization of `userContext`. Hosts pass it INLINE (`userContext={{ … }}`, the\n // documented usage), so the raw object identity changes every render. Feeding that raw object\n // into the `llm` / `clientContext` memos below would make them unstable, and wireai-rn recreates\n // its A2A adapter whenever the llmConfig identity changes — the adapter ctor resets `contextId`\n // (node_modules/wireai-rn: `this.contextId = void 0`), so the server-learned session id is\n // dropped and correlation breaks. We key both memos on the JSON string (compared by value) and\n // reuse ONE normalized reference in the metadata + client-event paths.\n const userContextKey = userContext ? JSON.stringify(userContext) : \"\";\n const userContextStable = useMemo<Record<string, string | number | boolean> | undefined>(\n () => (userContextKey ? (JSON.parse(userContextKey) as Record<string, string | number | boolean>) : undefined),\n [userContextKey],\n );\n\n // THE JOIN KEY, or the absence of it. `user_context.device_key` is the ONLY thing that stitches an\n // onboarding session to everything the app reports later, and the prop that carries it is optional\n // and named `userContext` — so forgetting it is the default, and the failure is a silent zero in the\n // `activated` funnel rather than an error. Two real consumers shipped without it.\n //\n // A host-supplied key is also RECORDED on the process-wide provenance registry, so a sibling\n // surface can later ask \"does this app own a device id?\" — see the third-id-space warning below.\n // The registry\n // write is idempotent (same key, same value), so running it from a memo is safe under StrictMode's\n // double-invoke; it lives here rather than in an effect so the answer is already true for any\n // surface constructed later in the same tick.\n const hostJoinIdentity = useMemo(\n () =>\n resolveIdentity({\n value: userContextStable?.device_key,\n space: \"device\",\n source: \"host\",\n scope: config.appId,\n }),\n [userContextStable, config.appId],\n );\n const missingJoinKey = !hostJoinIdentity;\n\n // AUTO-JOIN (0.12.2). When the host supplied no join key, the kit supplies its OWN — the same\n // per-install `device_key` the analytics surfaces auto-mint and persist — so the default wiring\n // produces a joined funnel instead of a silent zero. Three conditions, all necessary:\n //\n // • `missingJoinKey` — a host-supplied key ALWAYS wins, verbatim, and is never touched.\n // • `autoJoinKey !== false` — the documented opt-out for a host that genuinely wants an\n // unlinked onboarding session; opting out restores the pre-0.12.2 behavior exactly.\n // • `storage` that actually WORKS — without persistence the auto id is process-scoped, so every\n // launch would carry a DIFFERENT key. That is worse than no key: the server counts\n // `min_sessions` by distinct opens grouped on `device_key`, so a per-launch key corrupts the\n // counter rather than leaving it empty, and it inflates distinct-device counts on top. Same\n // reason `useLifecycleEvents` gates its own fallback on storage.\n //\n // ⚠️ 0.13.0: the third condition used to be `Boolean(storage)` — the PRESENCE of the prop,\n // never the SUCCESS of the write. A REJECTING adapter (a locked / full / permission-denied\n // AsyncStorage, the most common real breakage) therefore walked the per-launch key in through the\n // front door: `hydrateAutoDeviceKey` resolves to the in-memory mint on every failure branch, and a\n // string is a string. The gate now reads `IdentityRecord.durable`, which is `true` ONLY when the id\n // was adopted from storage or written to it successfully — so a broken adapter lands on exactly the\n // same \"declined, and here is why\" path as no adapter at all.\n //\n // It resolves through `hydrateDeviceIdentity`, never the sync `resolveAutoDeviceKey`: the sync\n // contract returns the freshly minted id and adopts the persisted one milliseconds later, which\n // is exactly the split-identity defect 0.12.1 shipped — the key stamped here must be the one the\n // analytics side stamps, not a fresh mint per launch. It is therefore awaited BEHIND THE LOADER GATE\n // below (the same gate the persisted-session read already holds, and it is only ever open when\n // `storage` is present anyway), because `userContext` feeds the `llm` memo: swapping it after the\n // provider mounted would recreate the A2A adapter and drop the server-learned `contextId`.\n const autoJoinPossible = Boolean(storage) && autoJoinKey !== false;\n const wantsAutoJoin = missingJoinKey && autoJoinPossible;\n // `undefined` = the hydration is still in flight (the gate below holds). Otherwise a settled\n // outcome: a `key` to inject, or `null` plus the reason the kit declined, which the warning names.\n const [autoJoinOutcome, setAutoJoinOutcome] = useState<AutoJoinOutcome | undefined>(undefined);\n\n useEffect(() => {\n if (!wantsAutoJoin || autoJoinOutcome !== undefined || !storage) return;\n let cancelled = false;\n // Ceiling on the read, the same discipline as `loadPersistedSession`: a hung storage adapter\n // must degrade to \"no auto key\", never to a stuck loader over the host's onboarding. Giving up\n // is deliberately NOT \"fall back to the synchronous mint\" — that key is per-launch, which is\n // the corruption this feature is gated on `storage` to avoid.\n const timer = setTimeout(() => {\n if (!cancelled) setAutoJoinOutcome({ key: null, reason: \"timeout\" });\n }, AUTO_JOIN_HYDRATION_TIMEOUT_MS);\n void hydrateDeviceIdentity({ appId: config.appId, storage }).then((identity) => {\n if (cancelled) return;\n clearTimeout(timer);\n setAutoJoinOutcome(\n identity?.durable ? { key: identity.value } : { key: null, reason: \"not-durable\" },\n );\n });\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n }, [wantsAutoJoin, autoJoinOutcome, config.appId, storage]);\n\n const injectedJoinKey = wantsAutoJoin ? (autoJoinOutcome?.key ?? undefined) : undefined;\n const autoJoinPending = wantsAutoJoin && autoJoinOutcome === undefined;\n\n // What actually goes on the wire: the host's context, with the auto join key merged in ONLY when\n // the host left the slot empty. Every other key the host passed survives untouched, and a host\n // that passed a valid `device_key` gets a byte-identical payload to 0.12.1.\n const effectiveUserContext = useMemo<Record<string, string | number | boolean> | undefined>(\n () =>\n injectedJoinKey\n ? { ...userContextStable, ...activationJoinContext(injectedJoinKey) }\n : userContextStable,\n [userContextStable, injectedJoinKey],\n );\n\n // THE JOIN DECISION IS FROZEN AT THE MOMENT THE GATE OPENS, exactly as `startupUserIdRef`\n // below freezes the user id, and for the identical reason: `userContext` feeds the `llm` memo, and\n // wireai-rn recreates its A2A adapter whenever the `llm` identity changes — the adapter ctor resets\n // `contextId` (`this.contextId = void 0`), so the server-learned session id is dropped.\n //\n // THE TEARDOWN THIS PREVENTS: a host that resolves its device key ASYNCHRONOUSLY renders once\n // without it → auto-join injects `wdev_*` → the host key lands a tick later → `effectiveUserContext`\n // flips → the memo rebuilds → the adapter is recreated → the user restarts onboarding mid-flow and\n // the server is left holding an orphaned session. It is not a hypothetical shape: it is the default\n // shape of any host that reads its device id out of async storage.\n //\n // Frozen at gate-open rather than at first render because the auto-join key itself arrives\n // asynchronously — freezing earlier would freeze `undefined`. The value is carried as a JSON STRING\n // so it can sit in a dependency array by value; a ref alone would not re-run the memo when it fills.\n // Client events deliberately keep reading the LIVE `effectiveUserContext`: they are posted one at a\n // time and carry no adapter, so late host context enriches them at no risk — the same split the\n // user id already uses (frozen in session-start metadata, live via the `identify` event).\n const frozenWireContextRef = useRef<string | null>(null);\n if (!autoJoinPending && frozenWireContextRef.current === null) {\n frozenWireContextRef.current = effectiveUserContext ? JSON.stringify(effectiveUserContext) : \"\";\n }\n const startupUserContextKey = frozenWireContextRef.current ?? \"\";\n const startupUserContext = useMemo<Record<string, string | number | boolean> | undefined>(\n () =>\n startupUserContextKey\n ? (JSON.parse(startupUserContextKey) as Record<string, string | number | boolean>)\n : undefined,\n [startupUserContextKey],\n );\n\n // Dev-only warning (never a throw, never a wire change), once per mount, naming the exact fix.\n // Reconciled with auto-join: it fires only when the gap is still OPEN — injection was impossible\n // (no `storage`), the host opted out, or the read gave up. When auto-join covered the gap the\n // session IS joined, so there is nothing to warn about; while it is still in flight, nothing is\n // decided yet, so it stays quiet.\n const warnMissingJoinKey = missingJoinKey && !injectedJoinKey && !autoJoinPending;\n const autoJoinReason =\n autoJoinKey === false\n ? \"you passed autoJoinKey={false}.\"\n : !storage\n ? \"it got no `storage` prop, and without persistence its key would be different on every \" +\n \"launch, which corrupts min_sessions instead of merely leaving the join empty.\"\n : autoJoinOutcome?.key === null && autoJoinOutcome.reason === \"not-durable\"\n ? \"your `storage` adapter answered but could not persist the key (the read or the write \" +\n \"failed), so the key would be different on every launch, which corrupts min_sessions \" +\n \"instead of merely leaving the join empty. Check the adapter you passed as `storage`.\"\n : \"your `storage` adapter did not answer in time.\";\n useEffect(() => {\n if (!warnMissingJoinKey) return;\n warnInDev(\n \"[wireai] <WireOnboarding> got no user_context.device_key, so this onboarding session can \" +\n \"never be joined to the app's later events and the `activated` funnel will read zero. Pass \" +\n \"userContext={activationJoinContext(deviceKey)} — and if your app owns no device id, \" +\n \"userContext={activationJoinContext(resolveAutoDeviceKey({ appId, storage }))} returns the \" +\n \"SAME id the analytics side stamps. Never hand-write userContext={{ deviceKey }}. \" +\n \"The kit did NOT auto-inject its own key here because \" +\n autoJoinReason,\n );\n }, [warnMissingJoinKey, autoJoinReason]);\n\n // THE SECOND CASE AUTO-JOIN WOULD OTHERWISE SILENCE. 0.12.2 suppressed the missing-join-key\n // warning whenever injection succeeded, which is right when the host genuinely owns no device id —\n // and wrong when it owns one and simply forgot it HERE. That host used to get a loud warning and\n // now gets a silent third id space: its app events under its own key, this onboarding session under\n // `wdev_*`, and `activated` still zero. Nothing a single mount can see distinguishes the two cases,\n // which is why the provenance registry exists: any surface constructed with a HOST-supplied device\n // key records it, so this mount can ask whether the process demonstrably owns one.\n //\n // It WARNS rather than declining to inject: declining would leave the onboarding side with no key\n // at all, which is strictly worse than a self-consistent one. It also does not silently ADOPT the\n // other surface's key — that would be the kit guessing which of two ids a host meant, on the\n // strength of construction order, and quietly changing what lands on the wire.\n const hostKeyElsewhere = missingJoinKey ? hostIdentity(\"device\", config.appId) : undefined;\n const warnHostKeyElsewhere = Boolean(hostKeyElsewhere) && Boolean(injectedJoinKey);\n useEffect(() => {\n if (!warnHostKeyElsewhere) return;\n warnInDev(\n \"[wireai] <WireOnboarding> got no user_context.device_key, so the kit injected its own — but \" +\n \"another surface in this app was constructed WITH a host-supplied device key \" +\n `(\"${hostKeyElsewhere}\"). Your app events carry that id and this onboarding session carries ` +\n \"the kit's, so the two land in disjoint id spaces and the `activated` funnel still reads \" +\n \"zero. Pass the SAME id here: userContext={activationJoinContext(deviceKey)}.\",\n );\n }, [warnHostKeyElsewhere, hostKeyElsewhere]);\n\n // The one case auto-join would otherwise SILENCE and must not: the host hand-wrote\n // `userContext={{ deviceKey }}`. That bucket is not the wire key, so the kit injects its own —\n // but the host demonstrably owns an id, and their app-side events carry THAT one, so the two\n // families still land in disjoint id spaces. Injection makes the onboarding side self-consistent;\n // only the host can make it join.\n const misspelledJoinKey =\n missingJoinKey &&\n typeof userContextStable?.deviceKey === \"string\" &&\n Boolean(userContextStable.deviceKey.trim());\n useEffect(() => {\n if (!misspelledJoinKey || !injectedJoinKey) return;\n warnInDev(\n \"[wireai] <WireOnboarding> got userContext={{ deviceKey }}, which is NOT the wire key — the \" +\n \"server's device lookup reads `device_key`. The kit auto-injected its own device_key so this \" +\n \"session is at least self-consistent, but your app's own events carry YOUR id, so the two \" +\n \"still will not join and the `activated` funnel stays zero. Pass \" +\n \"userContext={activationJoinContext(deviceKey)} instead.\",\n );\n }, [misspelledJoinKey, injectedJoinKey]);\n\n // The context payload shared by the A2A metadata + client-event paths. `userContext` +\n // `userId` are host-injected and forwarded verbatim (the server sanitizes them). Omitted keys\n // stay absent, so `dropped`/`client_fallback` events carry the user id when it's known.\n const clientContext = useMemo(\n () => ({ device, userContext: effectiveUserContext, userId: boundUserId }),\n [device, effectiveUserContext, boundUserId],\n );\n // One stable session id per onboarding SESSION (not per mount). It's used as the\n // client event `session_id` AND forwarded to the backend as `metadata.sessionId` so\n // the server can adopt it as the A2A `contextId` — making client-reported events\n // (`dropped`) correlate to the same session the server keys its own events by. See\n // the SDK-correlation note in analytics/reportClientEvent.ts.\n //\n // Without `storage`: minted synchronously per mount (the original behavior).\n // With `storage`: hydrated from the host-injected storage BEFORE the provider mounts\n // (loader-gate below), so an app KILL mid-onboarding resumes the SAME backend session\n // instead of minting a new one — which would count a phantom second `started` + a\n // false \"drop\" in the analytics funnel. See session/persistedSession.ts.\n const [session, setSession] = useState<LoadedSession | null>(() =>\n storage ? null : { id: makeSessionId(), resumed: false },\n );\n const storageKey = persistKey ?? sessionStorageKey(config.appId);\n const permissionsKey = permissionStorageKey(config.appId);\n\n useEffect(() => {\n if (!storage || session) return;\n // StrictMode/dev double-effect safe: the cancel flag drops the stale resolution.\n // Dev-only caveat: on a brand-new first mint, StrictMode's double-invoke can persist\n // then read the id back, surfacing a spurious `resumed: true`. Production is unaffected\n // (double-invoke is dev-only) and it self-heals on the next mount.\n let cancelled = false;\n void loadPersistedSession(storage, storageKey, sessionTtlMs).then((loaded) => {\n if (!cancelled) setSession(loaded);\n });\n return () => {\n cancelled = true;\n };\n }, [storage, storageKey, sessionTtlMs, session]);\n\n // By DEFAULT, clear the cached id the moment the flow completes, so the next onboarding on\n // this device starts a fresh session. Dropped/degraded paths deliberately do NOT clear —\n // a dropped session must stay resumable within the TTL.\n //\n // OPT-IN (`retainSessionOnComplete`): a multi-stage / replay-after-complete signup re-enters\n // (often via a `key=` remount) WITHIN one signup. If we cleared, that re-entry would find no\n // seed and mint a fresh `metadata.sessionId` → a phantom second `session_started` on the same\n // funnel. When the host opts in, we LEAVE the seed in place so the re-entry resumes the SAME\n // session (one funnel start); freshness for a genuinely new run then rides the TTL (past\n // `sessionTtlMs` → fresh mint) and an explicit new-run signal (a changed `persistKey`).\n // `shouldClearOnComplete` is the pure, unit-tested seam; the `storage` guard is unchanged, so a\n // host that does not opt in lands on the byte-for-byte legacy clear-on-complete path.\n const handleComplete = useCallback(\n (result: OnboardingResult) => {\n if (storage && shouldClearOnComplete(retainSessionOnComplete)) {\n clearPersistedSession(storage, storageKey);\n // The permission record is keyed by session id, so a stale one already reads as empty,\n // this only keeps the adapter from carrying a dead entry forever.\n clearSettledPermissions(storage, permissionsKey);\n }\n onComplete(result);\n },\n [storage, storageKey, permissionsKey, retainSessionOnComplete, onComplete],\n );\n\n const sessionId = session?.id ?? \"\";\n\n // ── Permission-screen memory: \"shown once per session\", kept true across an app KILL ─────────\n //\n // The in-memory guard covers one mount. A resumed session (the whole point of `storage`) is a\n // NEW mount of the SAME session, so without a persisted record it would re-show a screen the user\n // already answered, and on the ask path that is a second attempt at a prompt iOS grants once.\n //\n // Unlike the auto-join key, this does NOT hold the loader gate: it feeds no `llm` dependency, so\n // a late arrival cannot recreate the A2A adapter. The flow simply suppresses permission screens\n // while `permissionsPending` is true, and that window closes long before the first card arrives\n // (one timeout-capped storage read against a backend round trip).\n const wantsPermissionMemory = Boolean(storage) && (permissionScreens?.length ?? 0) > 0;\n const [settledPermissions, setSettledPermissions] = useState<string[] | undefined>(undefined);\n useEffect(() => {\n if (!wantsPermissionMemory || !storage || !sessionId || settledPermissions !== undefined) return;\n let cancelled = false;\n void loadSettledPermissions(storage, permissionsKey, sessionId).then((ids) => {\n if (!cancelled) setSettledPermissions(ids);\n });\n return () => {\n cancelled = true;\n };\n }, [wantsPermissionMemory, storage, permissionsKey, sessionId, settledPermissions]);\n\n // Persist the settled set as it grows. Fire-and-forget: a failed write only costs a re-ask on a\n // resume, never a broken flow. Without `storage` there is nothing to write to and the\n // in-memory guard alone carries the once-only contract for this mount.\n // Mirrored in a ref so the handler can compute the next set WITHOUT doing the storage write\n // inside a state updater (React invokes updaters twice under StrictMode; a write belongs outside).\n const settledPermissionsRef = useRef<string[] | undefined>(undefined);\n settledPermissionsRef.current = settledPermissions;\n const handlePermissionSettled = useCallback(\n (id: string) => {\n const current = settledPermissionsRef.current ?? [];\n if (current.includes(id)) return;\n const next = [...current, id];\n settledPermissionsRef.current = next;\n setSettledPermissions(next);\n if (storage && wantsPermissionMemory && sessionId) {\n saveSettledPermissions(storage, permissionsKey, sessionId, next);\n }\n },\n [storage, wantsPermissionMemory, permissionsKey, sessionId],\n );\n\n // Session-start snapshot of the bound user id. It seeds the A2A `metadata.userId` so the\n // adapter is built ONCE with whatever id was known at session start. A mid-session userId\n // change must NOT flow through this memo — recreating `llm` recreates the A2A adapter,\n // whose ctor resets `contextId` (see the userContext note above) and drops the server-\n // learned session id. Later changes ride EXCLUSIVELY on the `identify` effect below, which\n // mutates the live session in place. `useRef` captures the first-render value once.\n const startupUserIdRef = useRef<string | undefined>(boundUserId);\n\n // Build the A2A LocalLLMConfig from the friendlier kit config. The backend\n // resolves the app from the API key, so `model` (appId) is informational.\n const metadataKey = config.metadata ? JSON.stringify(config.metadata) : \"\";\n const metadataStable = useMemo(() => (metadataKey ? JSON.parse(metadataKey) : undefined), [metadataKey]);\n const componentNamesKey = (components ?? onboardingComponents).map((c) => c.name).join(\",\");\n const componentsStable = useMemo(() => components ?? onboardingComponents, [componentNamesKey]);\n\n const llm = useMemo<LocalLLMConfig>(() => {\n const baseUrl = config.serverUrl.replace(/\\/$/, \"\");\n return {\n provider: \"a2a\",\n baseUrl: `${baseUrl}/a2a`,\n model: config.appId,\n apiKey: config.apiKey,\n // Carry the kit session id alongside any host attribution so it reaches the A2A\n // request's `params.metadata` (the correlation seed; see note above), plus the\n // names of the components this device can actually render — so the backend only\n // emits cards the kit knows how to draw.\n metadata: {\n ...metadataStable,\n sessionId,\n supportedComponents: componentsStable.map((c) => c.name),\n // Device snapshot + host-injected user context ride the session-start metadata so the\n // backend can segment the funnel. Old servers ignore these unknown keys (backward compat).\n device,\n // The FROZEN wire context, never the live one — see the freeze note above. A change here\n // recreates the A2A adapter and drops `contextId`.\n ...(startupUserContext ? { userContext: startupUserContext } : {}),\n // The session-start user id (from the ref) rides the session-start metadata so the\n // server binds the session to a real user at creation. Reading the ref — not\n // `boundUserId` — keeps this memo off the userId dependency, so a mid-session change\n // does NOT recreate the adapter; it's bound by the `identify` effect below instead.\n ...(startupUserIdRef.current ? { userId: startupUserIdRef.current } : {}),\n },\n timeoutMs: 60_000,\n };\n }, [config.serverUrl, config.appId, config.apiKey, metadataStable, sessionId, componentsStable, device, startupUserContext]);\n\n // Where client-reported events are POSTed (`/v1/events`). Same tenant creds as the flow.\n const reportTarget = useMemo<ClientEventTarget>(\n () => ({ serverUrl: config.serverUrl, apiKey: config.apiKey }),\n [config.serverUrl, config.apiKey],\n );\n\n // LATE BINDING (mid-session): the user often registers DURING onboarding. When `userId`\n // becomes known (or changes) after the session already started, emit an `identify` client\n // event that attaches the id to the LIVE session, so the backend can map this in-flight\n // session to the real user. On a FRESH mount the initial id already rode the session-start\n // metadata, so we seed the \"already bound\" ref with it and only react to later CHANGES. On a\n // RESUMED session the server-side record predates this mount and won't re-read start metadata,\n // so we leave the seed empty to force an identify when a userId is present. Fire-and-forget.\n const identifiedRef = useRef<string | undefined>(undefined);\n const identifySeededRef = useRef(false);\n useEffect(() => {\n if (!session || !sessionId) return;\n if (!identifySeededRef.current) {\n identifySeededRef.current = true;\n identifiedRef.current = session.resumed ? undefined : boundUserId;\n }\n if (!boundUserId || boundUserId === identifiedRef.current) return;\n identifiedRef.current = boundUserId;\n reportClientEvent(reportTarget, {\n event_type: \"identify\",\n session_id: sessionId,\n user_id: boundUserId,\n });\n }, [session, sessionId, boundUserId, reportTarget]);\n\n const cards = components ?? onboardingComponents;\n\n // Loader-gate (hydration approach A): hold the entire provider subtree until the\n // stored id resolves. `sessionId` is a dependency of the `llm` memo above, so mounting\n // the provider with a throwaway id and swapping later would re-init it mid-flight.\n // The read is timeout-capped in loadPersistedSession, so this gate is one storage\n // read (~a frame), never an indefinite hold.\n //\n // The auto join key rides the SAME gate for the same reason (`effectiveUserContext` is also an\n // `llm` dependency). It costs no extra hold in practice: auto-join requires `storage`, and with\n // `storage` this gate is already closed on the persisted-session read.\n if (!session || autoJoinPending) {\n return (\n <OnboardingThemeProvider theme={theme}>\n <LoadingScreen\n title={copy?.restoringTitle ?? DEFAULT_COPY.restoringTitle}\n hint={copy?.restoringHint ?? DEFAULT_COPY.restoringHint}\n />\n </OnboardingThemeProvider>\n );\n }\n\n return (\n <OnboardingThemeProvider theme={theme}>\n <IllustrationProvider registry={{ ...defaultIllustrations, ...illustrations }}>\n <IconRegistryProvider registry={icons}>\n <WireAIProvider llm={llm} components={cards}>\n <OnboardingFlow\n validators={validators}\n onComplete={handleComplete}\n onSkip={onSkip}\n onError={onError}\n onEvent={onEvent}\n copy={copy}\n approxScreens={approxScreens}\n startMessage={startMessage}\n startTimeoutMs={startTimeoutMs}\n fallbackFlow={fallbackFlow}\n maxRetries={maxRetries}\n reportTarget={reportTarget}\n sessionId={sessionId}\n resumed={session.resumed}\n clientContext={clientContext}\n permissionScreens={permissionScreens}\n settledPermissions={settledPermissions}\n permissionsPending={wantsPermissionMemory && settledPermissions === undefined}\n onPermissionSettled={handlePermissionSettled}\n />\n </WireAIProvider>\n </IconRegistryProvider>\n </IllustrationProvider>\n </OnboardingThemeProvider>\n );\n};\n","/**\n * DemoOnboarding — a drop-in dev/QA trigger that runs the onboarding flow ON\n * DEMAND in a modal, then closes. No loop, no account, no navigation side-effects:\n * re-runnable infinitely with the same logged-in user. Place it anywhere a host\n * wants (e.g. a __DEV__ row in Settings). If `config` is null (the app hasn't\n * integrated Wire AI yet), it shows a hint instead of the flow.\n *\n * {__DEV__ && (\n * <DemoOnboarding config={wireConfigFromEnv({ appId: \"my-app\" })} theme={myTheme} />\n * )}\n *\n * It does NOT persist by default (a demo, not a real run) — pass `onComplete` if\n * you want to observe the captured answers.\n */\nimport { useCallback, useMemo, useState, type ReactNode } from \"react\";\nimport { Modal, Pressable, StyleSheet, Text, View } from \"react-native\";\n\nimport { WireOnboarding } from \"./WireOnboarding\";\nimport { mergeTheme } from \"./theme/defaultTheme\";\nimport type { OnboardingTheme } from \"./theme/types\";\nimport type { OnboardingResult, WireOnboardingConfig, WireOnboardingProps } from \"./types\";\n\nexport type DemoOnboardingProps = {\n /** The Wire AI config, or `null` when the app hasn't integrated Wire AI yet. */\n config: WireOnboardingConfig | null;\n theme?: WireOnboardingProps[\"theme\"];\n illustrations?: WireOnboardingProps[\"illustrations\"];\n validators?: WireOnboardingProps[\"validators\"];\n copy?: WireOnboardingProps[\"copy\"];\n /** Trigger button label. Default \"Demo onboarding\". */\n label?: string;\n /** Observe the demo result. By default the demo just closes (no persistence). */\n onComplete?: (result: OnboardingResult) => void;\n /** Render your own trigger instead of the default button: `(open) => <YourButton onPress={open} />`. */\n renderTrigger?: (open: () => void) => ReactNode;\n};\n\nexport function DemoOnboarding({\n config,\n theme,\n illustrations,\n validators,\n copy,\n label = \"Demo onboarding\",\n onComplete,\n renderTrigger,\n}: DemoOnboardingProps) {\n const [open, setOpen] = useState(false);\n const [runId, setRunId] = useState(0);\n const t = useMemo(() => mergeTheme(theme ?? {}), [theme]);\n const styles = useMemo(() => makeStyles(t), [t]);\n\n const openDemo = useCallback(() => {\n setRunId((n) => n + 1); // remount WireOnboarding → a fresh A2A session each open\n setOpen(true);\n }, []);\n const close = useCallback(() => setOpen(false), []);\n const finish = useCallback(\n (result: OnboardingResult) => {\n onComplete?.(result);\n setOpen(false);\n },\n [onComplete],\n );\n\n return (\n <>\n {renderTrigger ? (\n renderTrigger(openDemo)\n ) : (\n <Pressable onPress={openDemo} style={styles.trigger} accessibilityRole=\"button\">\n <Text style={styles.triggerText}>{label}</Text>\n </Pressable>\n )}\n\n <Modal\n visible={open}\n animationType=\"slide\"\n presentationStyle=\"fullScreen\"\n onRequestClose={close}\n >\n <View style={styles.modal}>\n {config ? (\n <WireOnboarding\n key={runId}\n config={config}\n theme={theme}\n illustrations={illustrations}\n validators={validators}\n copy={copy}\n onComplete={finish}\n onSkip={close}\n onError={close}\n />\n ) : (\n <View style={styles.notice}>\n <Text style={styles.noticeTitle}>Wire AI not configured</Text>\n <Text style={styles.noticeBody}>\n Set the Wire AI key + server URL (e.g. via wireConfigFromEnv) to demo the AI\n onboarding here.\n </Text>\n <Pressable onPress={close} style={styles.trigger} accessibilityRole=\"button\">\n <Text style={styles.triggerText}>Close</Text>\n </Pressable>\n </View>\n )}\n </View>\n </Modal>\n </>\n );\n}\n\nfunction makeStyles(t: OnboardingTheme) {\n return StyleSheet.create({\n trigger: {\n backgroundColor: t.colors.primary,\n borderRadius: t.button.radius,\n paddingVertical: 14,\n paddingHorizontal: 20,\n alignItems: \"center\",\n },\n triggerText: { color: t.colors.onPrimary, fontFamily: t.fonts.medium, fontSize: 16 },\n modal: { flex: 1, backgroundColor: t.colors.background },\n notice: { flex: 1, alignItems: \"center\", justifyContent: \"center\", padding: 24, gap: 12 },\n noticeTitle: { color: t.colors.text, fontFamily: t.fonts.bold, fontSize: 20 },\n noticeBody: {\n color: t.colors.textMuted,\n fontFamily: t.fonts.regular,\n fontSize: 15,\n textAlign: \"center\",\n },\n });\n}\n","/**\n * themeFromBrand — the fastest path to a branded flow. Give it a primary brand\n * color (and optionally a background + a font), and it derives a sensible full\n * `Partial<OnboardingTheme>` over the neutral `defaultOnboardingTheme` (via\n * `mergeTheme`): a tinted soft wash for selected states, a readable on-primary\n * label, and matching success/info accents left at the neutral default.\n *\n * theme={themeFromBrand({ primary: \"#15B0B0\" })}\n *\n * It stays intentionally small: it only touches the values that flow from a brand\n * color. Anything else (radius, spacing, button shape) keeps the default; pass\n * `extra` to override those without re-authoring the palette.\n */\nimport { defaultOnboardingTheme, mergeTheme } from \"./defaultTheme\";\nimport type { OnboardingTheme } from \"./types\";\n\nexport type ThemeFromBrandInput = {\n /** Brand / accent color — drives selected states, primary buttons, progress fill. */\n primary: string;\n /** App background behind the whole flow. Default: the neutral light background. */\n background?: string;\n /** Card / elevated surface background. Default: the neutral surface. */\n surface?: string;\n /** Primary body text color. Default: the neutral near-black. */\n text?: string;\n /** Text/icon color on top of `primary`. Default: white. */\n onPrimary?: string;\n /**\n * A single font family applied to regular/medium/bold (the kit derives weight\n * from size when a family isn't weight-split). Pass `fonts` in `extra` for\n * per-weight families.\n */\n font?: string;\n /** Any further theme overrides, deep-merged last (radius/spacing/button/fonts/colors). */\n extra?: Partial<OnboardingTheme>;\n};\n\n/** Parse a #RGB or #RRGGBB hex into [r,g,b]; returns null for anything else (e.g. rgba()). */\nconst hexToRgb = (hex: string): [number, number, number] | null => {\n const m = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());\n if (!m) return null;\n let h = m[1] as string;\n if (h.length === 3) h = h[0]! + h[0]! + h[1]! + h[1]! + h[2]! + h[2]!;\n const int = parseInt(h, 16);\n return [(int >> 16) & 255, (int >> 8) & 255, int & 255];\n};\n\n/** A low-alpha wash of the primary for selected backgrounds, falling back gracefully. */\nconst softFromPrimary = (primary: string): string => {\n const rgb = hexToRgb(primary);\n if (!rgb) return defaultOnboardingTheme.colors.primarySoft;\n const [r, g, b] = rgb;\n return `rgba(${r},${g},${b},0.10)`;\n};\n\nexport const themeFromBrand = (input: ThemeFromBrandInput): Partial<OnboardingTheme> => {\n const { primary, background, surface, text, onPrimary, font, extra } = input;\n\n const derived: Partial<OnboardingTheme> = {\n colors: {\n ...defaultOnboardingTheme.colors,\n primary,\n primarySoft: softFromPrimary(primary),\n onPrimary: onPrimary ?? defaultOnboardingTheme.colors.onPrimary,\n ...(background ? { background } : {}),\n ...(surface ? { surface } : {}),\n ...(text ? { text } : {}),\n },\n ...(font\n ? {\n fonts: {\n ...defaultOnboardingTheme.fonts,\n regular: font,\n medium: font,\n bold: font,\n },\n }\n : {}),\n };\n\n // mergeTheme resolves the derived palette over the neutral default into a full\n // theme. Then deep-merge `extra` per sub-object so callers can override\n // radius/spacing/button/fonts/colors without re-authoring the palette.\n const base = mergeTheme(derived);\n if (!extra) return base;\n return {\n colors: { ...base.colors, ...extra.colors },\n fonts: { ...base.fonts, ...extra.fonts },\n radius: { ...base.radius, ...extra.radius },\n spacing: { ...base.spacing, ...extra.spacing },\n button: { ...base.button, ...extra.button },\n };\n};\n","/**\n * centeredModalMotion - the pure entrance spec for the content-agnostic CenteredModal shell.\n *\n * WHY split out: the shell UI (CenteredModal) is RN and cannot run under the kit's node:test\n * runner, but the entrance math is pure and worth pinning. Keep the animation spec here so both\n * the component and the tests read one source, and so any module (reviews, questionnaire) can\n * reuse the shell without depending on another feature module.\n *\n * The centered popup uses RN's built-in `Animated` (native driver), the same idiom as\n * CompletionView/CardHandoff, so the shell stays dependency-free (no reanimated).\n *\n * NOTE: `reviews/presentation.ts` re-exports these under their original names\n * (`REVIEW_MODAL_ANIM`, `entranceFrame`) for back-compat with the reviews public API.\n */\n\n/**\n * The entrance spec for the centered popup. Values chosen to match the boilerplate's\n * `animated-modal` feel (a springy zoom-in) with the kit's own native-driver idiom:\n * • backdrop fades 0 -> `backdropOpacity`\n * • card springs from `scaleFrom` -> 1 and fades 0 -> 1\n */\nexport const CENTERED_MODAL_ANIM = {\n /** Spring config for the card scale/opacity entrance (mirrors CompletionView's pop). */\n enterSpring: { friction: 7, tension: 80 },\n /** Exit timing in ms (fade + shrink back out before unmount). */\n exitMs: 160,\n /** Card scale at rest (progress 0); grows to 1 at progress 1. */\n scaleFrom: 0.9,\n /** Peak dim of the backdrop at progress 1. */\n backdropOpacity: 0.55,\n} as const;\n\n/** A single frame of the entrance, for a progress value in [0..1] (clamped). Pure, testable. */\nexport const centeredModalFrame = (\n progress: number,\n backdropMax: number = CENTERED_MODAL_ANIM.backdropOpacity,\n): { cardOpacity: number; cardScale: number; backdropOpacity: number } => {\n const p = progress < 0 ? 0 : progress > 1 ? 1 : progress;\n const { scaleFrom } = CENTERED_MODAL_ANIM;\n return {\n cardOpacity: p,\n cardScale: scaleFrom + (1 - scaleFrom) * p,\n backdropOpacity: backdropMax * p,\n };\n};\n","/**\n * CenteredModal - the content-agnostic centered-popup shell.\n *\n * Renders its children as an alert-style card in the MIDDLE of the screen, over a dimmed\n * backdrop, with a spring/fade entrance. It knows nothing about what it presents: the reviews\n * gate uses it (via the `ReviewModal` back-compat re-export) and the questionnaire module reuses\n * the same shell, neither depends on the other.\n *\n * Adapted from the mobile-launcher boilerplate's `animated-modal` (transparent RN Modal +\n * centered container + backdrop-tap dismiss + content stop-propagation + springy zoom-in), but\n * reimplemented on RN's built-in `Animated` (native driver) so the shell stays dependency-free:\n * the boilerplate uses react-native-reanimated, which the kit does not.\n *\n * Dismissal (backdrop tap / Android back / the imperative `close()` handle) animates the card\n * out, then fires `onDismiss`. It never auto-closes on resolve: the host keeps the card showing\n * whatever payoff it wants (a thank-you, a summary) until the user taps the backdrop to close,\n * exactly like CompletionView.\n */\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { Animated, BackHandler, Easing, Modal, Pressable, StyleSheet } from \"react-native\";\nimport { SafeAreaView } from \"react-native-safe-area-context\";\n\nimport type { OnboardingTheme } from \"../theme/types\";\nimport { REDUCED_FADE_MS } from \"../motion/motionSpec\";\nimport { useReducedMotion } from \"../motion/useReducedMotion\";\nimport { CENTERED_MODAL_ANIM } from \"../motion/centeredModalMotion\";\n\n/** Imperative handle so an in-card \"Not now\"/\"Skip\" link can trigger the exit animation. */\nexport type CenteredModalHandle = { close: () => void };\n\nexport type CenteredModalProps = {\n /** The (already merged) active theme - card surface/radius/spacing come from here. */\n theme: OnboardingTheme;\n /** Whether a backdrop tap / back press dismisses. Default true (never a dead end). */\n dismissible?: boolean;\n /** Fired once, AFTER the exit animation, on any dismiss. Wire to the host's resolve. */\n onDismiss: () => void;\n children: React.ReactNode;\n};\n\nconst _CenteredModal = forwardRef<CenteredModalHandle, CenteredModalProps>(\n ({ theme, dismissible = true, onDismiss, children }, ref) => {\n const progress = useRef(new Animated.Value(0)).current;\n const [open, setOpen] = useState(true);\n const closingRef = useRef(false);\n const reduced = useReducedMotion();\n\n // Entrance: spring the card in (scale + fade); the backdrop fades up in lock-step.\n // Reduce motion: a short fade to the settled card, no spring/scale.\n useEffect(() => {\n const anim = reduced\n ? Animated.timing(progress, {\n toValue: 1,\n duration: REDUCED_FADE_MS,\n useNativeDriver: true,\n })\n : Animated.spring(progress, {\n toValue: 1,\n useNativeDriver: true,\n friction: CENTERED_MODAL_ANIM.enterSpring.friction,\n tension: CENTERED_MODAL_ANIM.enterSpring.tension,\n });\n anim.start();\n return () => anim.stop();\n }, [progress, reduced]);\n\n const close = useCallback(() => {\n if (closingRef.current) return;\n closingRef.current = true;\n Animated.timing(progress, {\n toValue: 0,\n duration: reduced ? REDUCED_FADE_MS : CENTERED_MODAL_ANIM.exitMs,\n easing: Easing.in(Easing.cubic),\n useNativeDriver: true,\n }).start(() => {\n setOpen(false);\n onDismiss();\n });\n }, [progress, onDismiss, reduced]);\n\n useImperativeHandle(ref, () => ({ close }), [close]);\n\n // Android hardware back -> dismiss (when allowed). Always consume so it never pops a route.\n useEffect(() => {\n const sub = BackHandler.addEventListener(\"hardwareBackPress\", () => {\n if (dismissible) close();\n return true;\n });\n return () => sub.remove();\n }, [dismissible, close]);\n\n const onBackdrop = useCallback(() => {\n if (dismissible) close();\n }, [dismissible, close]);\n\n const backdropOpacity = progress.interpolate({\n inputRange: [0, 1],\n outputRange: [0, CENTERED_MODAL_ANIM.backdropOpacity],\n });\n // Reduce motion: the card fades in already settled (no zoom).\n const cardScale = reduced\n ? 1\n : progress.interpolate({\n inputRange: [0, 1],\n outputRange: [CENTERED_MODAL_ANIM.scaleFrom, 1],\n });\n\n return (\n <Modal\n visible={open}\n transparent\n animationType=\"none\"\n statusBarTranslucent\n onRequestClose={dismissible ? close : undefined}\n >\n {/* Dimmed backdrop (fades with the entrance). */}\n <Animated.View\n style={[styles.backdrop, { opacity: backdropOpacity }]}\n pointerEvents=\"none\"\n />\n\n {/* Full-screen tap target: a tap outside the card dismisses. */}\n <Pressable\n style={styles.fill}\n onPress={onBackdrop}\n accessibilityRole=\"button\"\n accessibilityLabel=\"Dismiss\"\n >\n <SafeAreaView style={styles.center} pointerEvents=\"box-none\">\n {/* Inner Pressable swallows taps so the card itself never dismisses. */}\n <Pressable onPress={() => {}} style={styles.cardWrap}>\n <Animated.View\n accessibilityViewIsModal\n accessibilityRole=\"alert\"\n style={[\n styles.card,\n {\n backgroundColor: theme.colors.surface,\n borderRadius: theme.radius.lg,\n padding: theme.spacing.lg,\n gap: theme.spacing.md,\n opacity: progress,\n transform: [{ scale: cardScale }],\n },\n ]}\n >\n {children}\n </Animated.View>\n </Pressable>\n </SafeAreaView>\n </Pressable>\n </Modal>\n );\n },\n);\n\n_CenteredModal.displayName = \"CenteredModal\";\n\nexport const CenteredModal = React.memo(_CenteredModal);\n\nconst styles = StyleSheet.create({\n fill: { flex: 1 },\n backdrop: { position: \"absolute\", top: 0, left: 0, right: 0, bottom: 0, backgroundColor: \"#000\" },\n center: { flex: 1, alignItems: \"center\", justifyContent: \"center\", padding: 24 },\n cardWrap: { width: \"100%\", maxWidth: 420 },\n card: {\n width: \"100%\",\n // Soft elevation so the popup reads as lifted above the app in both themes.\n shadowColor: \"#000\",\n shadowOffset: { width: 0, height: 8 },\n shadowOpacity: 0.28,\n shadowRadius: 24,\n elevation: 12,\n },\n});\n\nexport default CenteredModal;\n","/**\n * The fail-open defaults + a tolerant parser for the server's flags payload.\n *\n * THE CONTRACT: fail-open, never fail-dark. An absent server object, a missing module key, a\n * malformed value, or an unreachable endpoint must resolve to the MOST PERMISSIVE state — every\n * module ON, onboarding `ai` — so a control-plane outage can only ever be more permissive than\n * the dashboard intends. It can never dark a tenant's activation. Matches the server's own\n * documented fail-open default (FEATURES.md: \"local defaults — every module on, onboarding ai\").\n */\nimport type { OnboardingMode, WireFeatures } from \"./types\";\n\n/**\n * ALL ON, onboarding `ai`. Frozen + module-level so its reference is stable across every call\n * (consumers that list resolved flags in an effect dep array never loop on a fresh identity).\n */\nexport const defaultWireFeatures: WireFeatures = Object.freeze({\n coachmarks: Object.freeze({ enabled: true }),\n showcase: Object.freeze({ enabled: true }),\n onboarding: Object.freeze({ mode: \"ai\" as OnboardingMode }),\n review: Object.freeze({ enabled: true }),\n questionnaire: Object.freeze({ enabled: true }),\n announcements: Object.freeze({ enabled: true }),\n}) as WireFeatures;\n\nconst VALID_MODES: readonly OnboardingMode[] = [\"ai\", \"static\", \"off\"];\n\n/** Read a `{ enabled: boolean }` module, defaulting to ON when absent/malformed (fail-open). */\nconst readEnabled = (raw: unknown): { enabled: boolean } => {\n if (raw && typeof raw === \"object\" && typeof (raw as { enabled?: unknown }).enabled === \"boolean\") {\n return { enabled: (raw as { enabled: boolean }).enabled };\n }\n return { enabled: true };\n};\n\n/**\n * Narrow the server's (untrusted) JSON to a complete `WireFeatures`. Every field is filled with\n * its fail-open default when the server omits it or sends the wrong type, so a partial or\n * malformed payload degrades PERMISSIVELY rather than throwing. A non-object input (null, array,\n * string) → the full defaults. Never throws.\n */\nexport const parseWireFeatures = (raw: unknown): WireFeatures => {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return defaultWireFeatures;\n const src = raw as Record<string, unknown>;\n const modeRaw = (src.onboarding as { mode?: unknown } | undefined)?.mode;\n const mode: OnboardingMode =\n typeof modeRaw === \"string\" && VALID_MODES.includes(modeRaw as OnboardingMode)\n ? (modeRaw as OnboardingMode)\n : \"ai\";\n return {\n coachmarks: readEnabled(src.coachmarks),\n showcase: readEnabled(src.showcase),\n onboarding: { mode },\n review: readEnabled(src.review),\n questionnaire: readEnabled(src.questionnaire),\n announcements: readEnabled(src.announcements),\n };\n};\n\n/** Value-equality of two resolved flags — lets the hook hold a stable reference across churn. */\nexport const featuresEqual = (a: WireFeatures, b: WireFeatures): boolean =>\n a === b ||\n (a.coachmarks.enabled === b.coachmarks.enabled &&\n a.showcase.enabled === b.showcase.enabled &&\n a.onboarding.mode === b.onboarding.mode &&\n a.review.enabled === b.review.enabled &&\n a.questionnaire.enabled === b.questionnaire.enabled &&\n a.announcements.enabled === b.announcements.enabled);\n","/**\n * The last-known-flags cache — persisted through the host's optional `storage`.\n *\n * WHY: the fetch is best-effort and fail-open. When the control plane is unreachable we serve the\n * LAST value we saw rather than snapping to defaults, so a tenant that intentionally disabled a\n * module during an incident keeps it disabled across an outage instead of flapping back on. That\n * is \"stale-while-error\": a fresh cache (< TTL) is trusted, and on a fetch error even a STALE\n * cache is served (any age beats a guess). Every operation is best-effort — a broken/hung storage\n * degrades to defaults, never a throw and never a stuck gate (mirrors persistedSession).\n */\nimport { parseWireFeatures } from \"./defaults\";\nimport type { WireFeatures } from \"./types\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\n\n/**\n * TTL for a cached flags entry, aligned to the server's `Cache-Control: private, max-age=300`.\n * A cache younger than this is \"fresh\"; older is \"stale\" (still served on a fetch error).\n */\nexport const DEFAULT_FEATURES_TTL_MS = 300_000;\n\n/** Ceiling on the storage read so a hung adapter degrades to defaults, never a stuck resolve. */\nconst READ_TIMEOUT_MS = 1_500;\n\n/** Storage key for a tenant's cached flags, e.g. `wireai:features:acme`. */\nexport const featuresCacheKey = (appId?: string): string =>\n `wireai:features:${appId && appId.length > 0 ? appId : \"default\"}`;\n\n/** A cached flags entry: the resolved flags + the epoch-ms they were fetched. */\nexport interface CachedFeatures {\n features: WireFeatures;\n /** Age of the entry in ms at read time. */\n ageMs: number;\n}\n\nconst withTimeout = <T>(p: Promise<T>, ms: number): Promise<T | undefined> => {\n let timer: ReturnType<typeof setTimeout>;\n const timeout = new Promise<undefined>((resolve) => {\n timer = setTimeout(() => resolve(undefined), ms);\n });\n return Promise.race([p, timeout]).finally(() => clearTimeout(timer));\n};\n\n/** Whether a cache entry is still within the TTL (server max-age aligned). */\nexport const isFeaturesFresh = (ageMs: number, ttlMs: number = DEFAULT_FEATURES_TTL_MS): boolean =>\n ageMs >= 0 && ageMs < ttlMs;\n\n/**\n * Read the cached flags for `key`, or `undefined` when absent/corrupt/timed-out. Returns the\n * value AND its age so a caller can apply a TTL (fresh) or ignore it (stale-while-error). Never\n * throws; never hangs past the read timeout. The stored value is re-parsed through\n * `parseWireFeatures`, so a partially-corrupt entry still degrades fail-open.\n */\nexport const readCachedFeatures = async (\n storage: WireOnboardingStorage,\n key: string,\n): Promise<CachedFeatures | undefined> => {\n let raw: string | null | undefined;\n try {\n raw = await withTimeout(storage.getItem(key), READ_TIMEOUT_MS);\n } catch {\n return undefined;\n }\n if (!raw) return undefined;\n try {\n const parsed: unknown = JSON.parse(raw);\n if (parsed && typeof parsed === \"object\" && typeof (parsed as { ts?: unknown }).ts === \"number\") {\n const ts = (parsed as { ts: number }).ts;\n return {\n features: parseWireFeatures((parsed as { features?: unknown }).features),\n ageMs: Date.now() - ts,\n };\n }\n } catch {\n // Corrupt entry → treat as absent; the caller falls back to defaults / a fresh fetch.\n }\n return undefined;\n};\n\n/** Persist `{ features, ts }` under `key` — fire-and-forget, all errors swallowed. */\nexport const writeCachedFeatures = (\n storage: WireOnboardingStorage,\n key: string,\n features: WireFeatures,\n): void => {\n try {\n void storage\n .setItem(key, JSON.stringify({ features, ts: Date.now() }))\n .catch(() => {});\n } catch {\n // Best-effort: a failed write just means the next launch has no cache to fall back to.\n }\n};\n","/**\n * fetchWireFeatures — read the per-module kill switches from `GET {serverUrl}/v1/features`.\n *\n * Contract (server: chohra-med/wireai-onboarding-server, routers/onboarding.py):\n * GET {serverUrl}/v1/features\n * Authorization: Bearer {apiKey}\n * 200 → { coachmarks:{enabled}, showcase:{enabled}, onboarding:{mode}, review:{enabled},\n * announcements:{enabled} } (Cache-Control: private, max-age=300)\n *\n * THE CONTRACT — fail-open, never fail-dark. Unreachable, timed-out, unauthorized (401),\n * server-error (5xx), or malformed JSON all resolve to the LAST CACHED value, else the\n * all-on defaults. No throw ever reaches the host: this is timeout-capped and swallows every\n * error, exactly like the session's best-effort reads. A control-plane outage can only ever be\n * MORE permissive than the dashboard intends — it can never dark a tenant's activation.\n */\nimport { readCachedFeatures, featuresCacheKey, writeCachedFeatures } from \"./cache\";\nimport { defaultWireFeatures, parseWireFeatures } from \"./defaults\";\nimport type { WireFeatures, WireFeaturesConfig } from \"./types\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\n\nconst DEFAULT_TIMEOUT_MS = 4_000;\n\n/** The fail-open fallback: last cached value (any age — stale-while-error), else defaults. */\nconst failOpen = async (\n storage: WireOnboardingStorage | undefined,\n key: string,\n): Promise<WireFeatures> => {\n if (!storage) return defaultWireFeatures;\n const cached = await readCachedFeatures(storage, key);\n return cached?.features ?? defaultWireFeatures;\n};\n\n/** GET with a hard timeout via AbortController (falls back to no-abort where unsupported). */\nconst fetchWithTimeout = async (\n url: string,\n apiKey: string,\n timeoutMs: number,\n): Promise<Response> => {\n const controller =\n typeof AbortController !== \"undefined\" ? new AbortController() : undefined;\n const timer = setTimeout(() => controller?.abort(), timeoutMs);\n try {\n return await fetch(url, {\n method: \"GET\",\n headers: { Accept: \"application/json\", Authorization: `Bearer ${apiKey}` },\n signal: controller?.signal,\n });\n } finally {\n clearTimeout(timer);\n }\n};\n\n/**\n * Resolve the tenant's feature flags. Attempts the network once; on ANY failure returns the\n * cached value (any age), else the all-on defaults. On success, persists the fresh value to the\n * cache (fire-and-forget) and returns it. Never throws.\n *\n * const flags = await fetchWireFeatures({ serverUrl, apiKey, appId, storage });\n * if (!flags.coachmarks.enabled) { /* skip the tour * / }\n */\nexport const fetchWireFeatures = async (\n config?: WireFeaturesConfig,\n): Promise<WireFeatures> => {\n const key = featuresCacheKey(config?.appId);\n const storage = config?.storage;\n\n // Nothing to fetch (no creds) → cache, else defaults. Lets a host mount the provider before\n // its config is ready without ever darking.\n if (!config?.serverUrl || !config?.apiKey) return failOpen(storage, key);\n\n const url = `${config.serverUrl.replace(/\\/$/, \"\")}/v1/features`;\n const timeoutMs = config.timeoutMs && config.timeoutMs > 0 ? config.timeoutMs : DEFAULT_TIMEOUT_MS;\n\n try {\n const res = await fetchWithTimeout(url, config.apiKey, timeoutMs);\n // 401 (bad/rotated key), 5xx, any non-2xx → last-known, never dark.\n if (!res || !res.ok) return failOpen(storage, key);\n const json: unknown = await res.json(); // throws on malformed body → caught below\n const features = parseWireFeatures(json);\n if (storage) writeCachedFeatures(storage, key, features);\n return features;\n } catch {\n // Timeout/abort, network error, missing fetch, or malformed JSON — all fail open.\n return failOpen(storage, key);\n }\n};\n","/**\n * useWireFeatures — resolve the tenant's feature flags for a component tree, once per mount.\n *\n * Returns the all-on defaults immediately (fail-open), then swaps to the fetched value when the\n * network resolves. When no `serverUrl`+`apiKey` is supplied it never fetches and just returns\n * defaults, so a host that never adopts flags sees ZERO behavior change and ZERO network calls.\n *\n * frequent_rules #11 (unstable inline props): the config is idiomatically passed inline\n * (`config={{ serverUrl, apiKey }}`), a fresh identity every render. We stabilize the fetch key\n * by VALUE so the effect fires once per real credential change, and we only swap the returned\n * flags object when its VALUES change — so a host that lists the returned flags in an effect dep\n * array settles in a bounded number of commits instead of looping (enforced by the canary suite).\n */\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { defaultWireFeatures, featuresEqual } from \"./defaults\";\nimport { fetchWireFeatures } from \"./fetchWireFeatures\";\nimport type { WireFeatures, WireFeaturesConfig } from \"./types\";\n\n/** Hold a stable reference for a value while its CONTENT is unchanged (see reviews/equality.ts). */\nconst useStableValue = <T,>(value: T, isEqual: (a: T, b: T) => boolean): T => {\n const ref = useRef(value);\n if (!isEqual(ref.current, value)) ref.current = value;\n return ref.current;\n};\n\n/** The credential slice that actually drives a refetch — stabilized by value. */\nconst sameFetchKey = (a: WireFeaturesConfig | undefined, b: WireFeaturesConfig | undefined): boolean =>\n a?.serverUrl === b?.serverUrl && a?.apiKey === b?.apiKey && a?.appId === b?.appId;\n\nexport const useWireFeatures = (config?: WireFeaturesConfig): WireFeatures => {\n const stableConfig = useStableValue(config, sameFetchKey);\n const [flags, setFlags] = useState<WireFeatures>(defaultWireFeatures);\n\n const canFetch = !!stableConfig?.serverUrl && !!stableConfig?.apiKey;\n\n useEffect(() => {\n if (!canFetch) {\n // No creds → stay on the all-on defaults (and reset if creds were removed).\n setFlags((prev) => (featuresEqual(prev, defaultWireFeatures) ? prev : defaultWireFeatures));\n return;\n }\n let alive = true;\n // fetchWireFeatures never throws — the .then always runs with a fail-open value.\n void fetchWireFeatures(stableConfig).then((next) => {\n if (!alive) return;\n // Only adopt a NEW reference on a real value change, so a host effect keyed on the\n // returned flags doesn't loop (frequent_rules #11).\n setFlags((prev) => (featuresEqual(prev, next) ? prev : next));\n });\n return () => {\n alive = false;\n };\n }, [canFetch, stableConfig]);\n\n return flags;\n};\n","/**\n * WireFeaturesProvider + useResolvedFeatures — the OPTIONAL one-fetch-serves-all-modules layer.\n *\n * Mount `WireFeaturesProvider` once near your app root with the tenant `config` and it fetches the\n * flags ONCE; every gated surface below it (coachmarks / showcase / reviews) reads the same\n * resolved value from context instead of each fetching its own. It is entirely optional: with no\n * provider, every surface falls back to its own lazy fetch (when given a config) or to the all-on\n * defaults, so modules work with zero setup and a host that never adopts flags is unchanged.\n *\n * NOTE on the built npm subpaths: React context is shared across the kit's subpath entries in the\n * SOURCE-consumption path (the monorepo apps) and in this test suite — one module instance, one\n * context. If you consume the built `@wireai/activation/*` subpaths as separate bundles, pass the\n * resolved flags (or a `featuresConfig`) to each surface explicitly instead of relying on context.\n */\nimport React, { createContext, useContext, useMemo } from \"react\";\n\nimport { defaultWireFeatures } from \"./defaults\";\nimport { useWireFeatures } from \"./useWireFeatures\";\nimport type { WireFeatures, WireFeaturesConfig } from \"./types\";\n\nconst CONTEXT_SYMBOL = Symbol.for(\"wireai.features.context\");\n// `globalThis`, not `global`: the other nine `Symbol.for` slots in this kit all use it, and `global`\n// simply does not exist in a plain browser (RN-web / SSR-in-the-browser), where this line would\n// throw a ReferenceError before the provider could render anything.\nconst globalObj = globalThis as any;\n\nif (!globalObj[CONTEXT_SYMBOL]) {\n globalObj[CONTEXT_SYMBOL] = createContext<WireFeatures | null>(null);\n}\nconst WireFeaturesContext = globalObj[CONTEXT_SYMBOL];\n\nexport interface WireFeaturesProviderProps {\n /** Tenant creds (+ optional storage) to fetch the flags once for the whole tree. */\n config?: WireFeaturesConfig;\n /**\n * Pre-resolved flags to provide directly instead of fetching (e.g. you already have them, or\n * you drive them from your own remote-config). Takes precedence over `config`.\n */\n flags?: WireFeatures;\n children: React.ReactNode;\n}\n\n/**\n * Fetch (or accept) the flags once and broadcast them to descendants. The provider VALUE is\n * memoized (performance rule #6) so a fresh object each render doesn't re-render every consumer.\n */\nexport const WireFeaturesProvider: React.FC<WireFeaturesProviderProps> = ({\n config,\n flags,\n children,\n}) => {\n // Always call the hook (rules of hooks); when `flags` is supplied we pass no config so it\n // never fetches and the explicit flags win below.\n const fetched = useWireFeatures(flags ? undefined : config);\n const value = flags ?? fetched;\n const stable = useMemo(() => value, [value]);\n return <WireFeaturesContext.Provider value={stable}>{children}</WireFeaturesContext.Provider>;\n};\n\nWireFeaturesProvider.displayName = \"WireFeaturesProvider\";\n\n/** Raw context read — `null` when no `WireFeaturesProvider` is mounted above. */\nexport const useWireFeaturesContext = (): WireFeatures | null =>\n useContext(WireFeaturesContext);\n\n/** Options for `useResolvedFeatures`: an explicit override and/or a lazy-fetch config. */\nexport interface ResolveFeaturesOptions {\n /** Explicit flags — win over everything (a surface's own `features` prop). */\n flags?: WireFeatures;\n /** Lazy-fetch config, used ONLY when there is no explicit `flags` and no provider above. */\n config?: WireFeaturesConfig;\n}\n\n/**\n * The resolution every gated surface uses. Precedence:\n * 1. explicit `options.flags` (a surface's own prop) →\n * 2. the nearest `WireFeaturesProvider` (context) →\n * 3. a lazy fetch from `options.config` (serverUrl + apiKey) →\n * 4. the all-on defaults.\n * Always fail-open, always a stable reference for a given value (so it's safe in effect deps).\n */\nexport const useResolvedFeatures = (options?: ResolveFeaturesOptions): WireFeatures => {\n const ctx = useWireFeaturesContext();\n // Only lazily fetch when nothing else provides the flags — otherwise pass no config so the\n // hook stays inert (defaults, no network). The hook is always called (rules of hooks).\n const shouldFetch = !options?.flags && ctx == null;\n const fetched = useWireFeatures(shouldFetch ? options?.config : undefined);\n return options?.flags ?? ctx ?? fetched ?? defaultWireFeatures;\n};\n","/**\n * wireConfigFromEnv — stop re-authoring env gating in every app. Reads the Wire AI\n * tenant key + server URL from the standard Expo public env vars and returns a\n * ready `WireOnboardingConfig`, or `null` when the key/URL are missing (so a host\n * can fall through to a static onboarding without writing the `if (!key)` itself).\n *\n * EXPO_PUBLIC_WIREAI_API_KEY=... (required)\n * EXPO_PUBLIC_WIREAI_SERVER_URL=... (required)\n *\n * const config = wireConfigFromEnv({ appId: \"morrow\" });\n * if (!config) return <StaticOnboarding />;\n * return <WireOnboarding config={config} ... />;\n *\n * `appId` defaults to `EXPO_PUBLIC_WIREAI_APP_ID` (or \"default\"); pass overrides to\n * set `appId`/`metadata` or to substitute the key/URL programmatically. `appVersion`\n * defaults to `detectAppVersion()` so every surface built from this config carries it.\n */\nimport { detectAppVersion } from \"../device/appVersion\";\nimport type { WireOnboardingConfig } from \"../types\";\nimport { warnInDev } from \"../utils/warnInDev\";\n\nexport type WireConfigOverrides = Partial<WireOnboardingConfig>;\n\n/** The env vars this helper reads. Exported so a host preflight can assert them itself. */\nexport const WIRE_ENV_VARS = [\n \"EXPO_PUBLIC_WIREAI_API_KEY\",\n \"EXPO_PUBLIC_WIREAI_SERVER_URL\",\n \"EXPO_PUBLIC_WIREAI_APP_ID\",\n] as const;\n\n/**\n * Minimal `process.env` declaration so the kit stays RN-pure (no `@types/node`).\n * In RN/Expo, `process.env.EXPO_PUBLIC_*` is provided/inlined by Metro at build\n * time; we only read string env vars here.\n *\n * IMPORTANT: read each var via STATIC member access (`process.env.EXPO_PUBLIC_FOO`).\n * Expo's `babel-preset-expo` `inline-env-vars` plugin ONLY inlines static\n * `process.env.EXPO_PUBLIC_*` member expressions. Aliasing (`const env = process.env`)\n * or computed access (`process.env[name]`) is left `undefined` in the Metro bundle, so\n * the value reads fine in Jest (Node) but is null on a real device. Do not refactor\n * these to an alias.\n */\ndeclare const process: { env: Record<string, string | undefined> };\n\nexport const wireConfigFromEnv = (\n overrides?: WireConfigOverrides,\n): WireOnboardingConfig | null => {\n const apiKey = overrides?.apiKey ?? process.env.EXPO_PUBLIC_WIREAI_API_KEY;\n const serverUrl = overrides?.serverUrl ?? process.env.EXPO_PUBLIC_WIREAI_SERVER_URL;\n const appId =\n overrides?.appId ?? process.env.EXPO_PUBLIC_WIREAI_APP_ID ?? \"default\";\n\n // Missing transport → null, so the host gates on one falsy check.\n //\n // The `null` return is the CORRECT contract and hosts rely on it — but it is also the quietest\n // failure the kit has: a missing EAS env var makes this return null, and then the facade never\n // constructs, `useLifecycleEvents` no-ops on `!cfg?.serverUrl`, and every gate returns null. Wire\n // is 100% off, with no error anywhere. Name it once in dev, and name WHICH var is missing.\n if (!apiKey || !serverUrl) {\n const missing = [\n apiKey ? undefined : \"EXPO_PUBLIC_WIREAI_API_KEY\",\n serverUrl ? undefined : \"EXPO_PUBLIC_WIREAI_SERVER_URL\",\n ].filter(Boolean);\n warnInDev(\n `[wireai] wireConfigFromEnv() returned null: ${missing.join(\" and \")} ${\n missing.length > 1 ? \"are\" : \"is\"\n } missing. The kit is now FULLY DISABLED (no onboarding, no analytics, no gates) and nothing ` +\n \"else will report an error. Set the var(s) in your env / EAS secrets.\",\n );\n return null;\n }\n\n // `appVersion` is part of `WireOnboardingConfig`, but this helper could not carry it — so a host\n // that built its config here forwarded `config.appVersion === undefined` to every surface. The\n // facade and the lifecycle path each auto-detect their own fallback; `createWireActivation` does\n // not, so every `wire.track` event shipped with no `app_version` at all. Detect once here (an\n // explicit override still wins) and the whole config carries it.\n const appVersion = overrides?.appVersion ?? detectAppVersion();\n\n return {\n apiKey,\n serverUrl,\n appId,\n ...(appVersion ? { appVersion } : {}),\n ...(overrides?.metadata ? { metadata: overrides.metadata } : {}),\n };\n};\n","/**\n * isOnboardingEnabled — the ONE standard gate for AI onboarding, so every app stops\n * re-authoring `flag && hasConfig` (one app had `isAiOnboardingEnabled`, another had\n * `isWireBackendConfigured` — same idea, two shapes).\n *\n * The gate is **transport presence**: `wireConfigFromEnv()` is non-null (the key + URL are\n * set), and that is it. There is no separate on/off env flag — a missing key already means\n * \"off\", so a second `EXPO_PUBLIC_AI_ONBOARDING_ENABLED` flag was redundant (and, read via\n * computed access, it didn't even inline on device). An optional `remote` kill-switch lets an\n * app turn it off without a release; the kit stays dependency-free (the app owns the remote\n * read and hands us the boolean).\n *\n * Enabled ⇔ transport present AND `(remote ?? true)`.\n *\n * if (!isOnboardingEnabled()) return goToStaticOnboarding();\n * // or, with a remote kill-switch the app already read:\n * if (!isOnboardingEnabled({ remote: remoteKillSwitchOn })) return goToStaticOnboarding();\n */\nimport { wireConfigFromEnv } from \"./wireConfigFromEnv\";\nimport type { WireConfigOverrides } from \"./wireConfigFromEnv\";\n\nexport type OnboardingFlagOptions = {\n /**\n * Optional remote kill-switch the app already read (Firebase/LD/etc.). When `false`, it\n * disables onboarding even though transport is present. Omit (or `true`) to leave it on.\n */\n remote?: boolean;\n /**\n * Config overrides forwarded to `wireConfigFromEnv` for the transport-present check\n * (e.g. a programmatic `apiKey`/`serverUrl`). Usually omitted.\n */\n config?: WireConfigOverrides;\n};\n\nexport const isOnboardingEnabled = (opts?: OnboardingFlagOptions): boolean => {\n const transportPresent = wireConfigFromEnv(opts?.config) !== null;\n if (!transportPresent) return false;\n return opts?.remote ?? true;\n};\n","/**\n * Canonical analytics names for the onboarding funnel. The kit already emits a typed\n * `OnboardingEvent` (`started | turn | error | retry | fallback`) — but one app logged them as\n * `onboarding_*` and another as `AI_ONBOARDING_*`, so the same funnel reads differently per app.\n * This maps the kit event to ONE canonical `wire_onboarding_*` name + params, and the app logs\n * it through whatever transport it already has (Firebase, Amplitude, console). The app still\n * owns the logger; only the NAMES are standardized.\n *\n * <WireOnboarding\n * onEvent={(e) => { const a = toAnalyticsEvent(e); logEvent(a.name, a.params); }}\n * onComplete={(r) => { logEvent(WIRE_ONBOARDING_EVENTS.completed, { answers: Object.keys(r.answers).length }); persist(r); }}\n * />\n *\n * `completed` has no kit `OnboardingEvent` (the kit signals completion via `onComplete`, not\n * `onEvent`) — the app logs it explicitly on `onComplete` using the constant below, so the\n * funnel name stays canonical.\n */\nimport {\n permissionEventName,\n permissionEventProps,\n type WirePermissionEventName,\n} from \"../permissions/permissionEvents\";\nimport type { OnboardingEvent } from \"../types\";\n\nexport const WIRE_ONBOARDING_EVENTS = {\n started: \"wire_onboarding_started\",\n /** A persisted session was restored after an app kill (fires instead of `started`). */\n resumed: \"wire_onboarding_resumed\",\n turn: \"wire_onboarding_turn\",\n error: \"wire_onboarding_error\",\n retry: \"wire_onboarding_retry\",\n fallback: \"wire_onboarding_fallback\",\n /** Logged by the host on `onComplete` (no matching kit `OnboardingEvent`). */\n completed: \"wire_onboarding_completed\",\n} as const;\n\nexport type WireOnboardingEventName =\n (typeof WIRE_ONBOARDING_EVENTS)[keyof typeof WIRE_ONBOARDING_EVENTS];\n\nexport type AnalyticsEvent = {\n /**\n * A permission screen maps to its own canonical `wire_permission_*` name rather than to an\n * onboarding one: it is a distinct funnel (see `permissions/permissionEvents.ts`), and folding it\n * into `wire_onboarding_turn` would make every permission rate unreadable.\n */\n name: WireOnboardingEventName | WirePermissionEventName;\n params?: Record<string, unknown>;\n};\n\n/**\n * Map a kit `OnboardingEvent` to its canonical `{ name, params }`. Exhaustive over the union\n * (the `never` default makes a new event type a compile error here — intentional).\n */\nexport const toAnalyticsEvent = (event: OnboardingEvent): AnalyticsEvent => {\n switch (event.type) {\n case \"started\":\n return { name: WIRE_ONBOARDING_EVENTS.started };\n case \"resumed\":\n return { name: WIRE_ONBOARDING_EVENTS.resumed };\n case \"turn\":\n return {\n name: WIRE_ONBOARDING_EVENTS.turn,\n params: { step: event.step, component: event.component },\n };\n case \"error\":\n return { name: WIRE_ONBOARDING_EVENTS.error, params: { reason: event.reason } };\n case \"retry\":\n return {\n name: WIRE_ONBOARDING_EVENTS.retry,\n params: { reason: event.reason, attempt: event.attempt },\n };\n case \"fallback\":\n return { name: WIRE_ONBOARDING_EVENTS.fallback, params: { reason: event.reason } };\n case \"permission\":\n return {\n name: permissionEventName(event.stage),\n params: permissionEventProps(event.permission, event.status),\n };\n default: {\n const _exhaustive: never = event;\n return _exhaustive;\n }\n }\n};\n","/**\n * attribution — forward install/ad attribution to the onboarding agent so it can tailor the\n * first question by acquisition source (e.g. a paid-campaign install vs an organic one). The\n * channel already exists: `WireOnboardingConfig.metadata` is merged into every A2A request by\n * `WireOnboarding`. No production app populated it before; this gives every app a standard shape.\n *\n * The app reads its raw attribution (AppsFlyer / Branch / deferred deep link — an app concern,\n * not the kit's) and passes the normalized result as `metadata`:\n *\n * const config = wireConfigFromEnv({\n * appId: \"morrow-self\",\n * metadata: attributionMetadata({ source: conv.mediaSource, campaign: conv.campaign, isOrganic: conv.isOrganic }),\n * });\n *\n * The backend sees `metadata.attribution = { source, campaign, ... }`.\n */\n\n/** Normalized acquisition attribution. All fields optional — pass what the SDK gives you. */\nexport type OnboardingAttribution = {\n /** Media source / network, e.g. \"appsflyer\", \"branch\", \"organic\". */\n source?: string;\n campaign?: string;\n adset?: string;\n ad?: string;\n /** Deferred deep-link slug / path that routed the install. */\n deepLink?: string;\n isFirstLaunch?: boolean;\n isOrganic?: boolean;\n /** Escape hatch for SDK-specific fields not covered above. */\n raw?: Record<string, unknown>;\n};\n\n/**\n * Wrap attribution into the `{ attribution: {...} }` metadata the agent reads. Drops `undefined`\n * fields so the request payload stays compact. Returns `{ attribution: {} }` for empty input\n * (still a valid, harmless metadata object).\n */\nexport const attributionMetadata = (\n a: OnboardingAttribution,\n): { attribution: Record<string, unknown> } => {\n const attribution: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(a)) {\n if (value !== undefined) attribution[key] = value;\n }\n return { attribution };\n};\n","/**\n * activation revalidation — a tiny kit-owned pub/sub the review / questionnaire decision fetches\n * subscribe to, so they RE-FETCH their server decision AFTER a trigger action, not only on mount.\n *\n * WHY THIS EXISTS (subsumes Morrow's hand-rolled `activation-revalidation.ts`): a host mounts the\n * review / questionnaire gate on the home screen and fetches its `/decision` verdict once, in a\n * mount-scoped effect. But the screen stays mounted while the user goes elsewhere to perform the\n * triggering action (journal a win, complete a task); the server's firing rule is trigger-based AND\n * session-scoped, so the mount fetch ran BEFORE the trigger event existed and never re-runs. Bumping\n * this store after the action POSTs re-runs the gate's decision fetch (it lists the version in its\n * deps) → the server now sees the trigger → `{fire:true}`.\n *\n * `wire.track()` bumps this automatically on a successful POST, so a consumer no longer hand-rolls\n * an await-then-bump: it subscribes (via {@link useActivationRevalidation} in `useWireActivation`)\n * and re-fetches when the version changes.\n *\n * ── WHY A globalThis SLOT, NOT MODULE-LOCAL STATE (same reasoning as currentSession) ─────────────\n * This module can be reached from more than one package entry (the main `.` barrel exposes the\n * revalidation surface; the gates live under the `./reviews` / `./questionnaire` subpaths). Under\n * `dist` resolution tsup inlines a SEPARATE copy of a module into each bundle, so plain module-local\n * `version` + `listeners` would give the BUMPER (main entry, via `wire.track`) and a SUBSCRIBER a\n * different store — the bump would never reach the listener, exactly the defect-B failure mode. So\n * the ONE store lives in a `globalThis` slot keyed by `Symbol.for(...)`: every inlined copy resolves\n * the same symbol and shares one store, on Hermes/RN, Node and SSR alike.\n */\n\n/** Well-known key into the runtime-global symbol registry — one shared store across every bundle. */\nconst REVALIDATION_SLOT: unique symbol = Symbol.for(\n \"@wireai/activation:activationRevalidation\",\n);\n\n/** The shared store: a monotonic version + the set of subscriber callbacks. */\ntype RevalidationStore = { version: number; listeners: Set<() => void> };\n\ntype GlobalWithSlot = typeof globalThis & {\n [REVALIDATION_SLOT]?: RevalidationStore;\n};\n\nconst globalSlot = globalThis as GlobalWithSlot;\n\n/** The one shared store, lazily created on the runtime global (never a second copy per bundle). */\nconst store = (): RevalidationStore => {\n const existing = globalSlot[REVALIDATION_SLOT];\n if (existing) return existing;\n const created: RevalidationStore = { version: 0, listeners: new Set() };\n globalSlot[REVALIDATION_SLOT] = created;\n return created;\n};\n\n/**\n * Signal every activation subscriber to re-fetch its server decision. `wire.track()` calls this on a\n * successful POST (await the post first so the re-fetch sees the event). A throwing subscriber never\n * breaks the notify loop — each listener is isolated.\n */\nexport const bumpActivationRevalidation = (): void => {\n const s = store();\n s.version += 1;\n // Iterate a snapshot so a listener that (un)subscribes during notify never corrupts the walk.\n for (const listener of Array.from(s.listeners)) {\n try {\n listener();\n } catch {\n // A subscriber that throws must not stop the others (fail-safe).\n }\n }\n};\n\n/**\n * Subscribe to revalidation. Returns an unsubscribe fn. Shaped for `useSyncExternalStore`\n * (see {@link useActivationRevalidation} in `useWireActivation`).\n */\nexport const subscribeActivationRevalidation = (listener: () => void): (() => void) => {\n const s = store();\n s.listeners.add(listener);\n return () => {\n s.listeners.delete(listener);\n };\n};\n\n/** The current revalidation version — include it in a decision-fetch effect's deps to re-fetch on bump. */\nexport const getActivationRevalidationVersion = (): number => store().version;\n\n/** Test-only: reset the shared store between cases (clears version + listeners). */\nexport const resetActivationRevalidation = (): void => {\n const s = store();\n s.version = 0;\n s.listeners.clear();\n};\n","/**\n * wireActivation — the kit-owned `wire.track()` + session accessor + revalidation surface.\n *\n * WHAT IT CONSOLIDATES (subsumes Morrow's workarounds): a consumer used to hand-roll three things\n * because the kit didn't own them — an awaitable action POST (`wireTrackActionAwait`), its OWN\n * per-open session id (`getWireSessionId`, minted because the kit's `getCurrentSessionId` desynced\n * cross-bundle — defect B), and an await-then-bump revalidation dance (`bumpActivationDecision`).\n * Defect B is fixed — `getCurrentSessionId` is now a `globalThis` singleton, reliable under\n * `dist` — so the kit can own all three behind one thin surface:\n *\n * const wire = createWireActivation({ serverUrl, apiKey }); // or useWireActivation(...)\n * await wire.track(\"journal_done\"); // awaitable POST + auto-revalidate\n *\n * `track` POSTs `event_type='app_event'`, `question_key=<name>` (the EXACT string a review /\n * questionnaire firing TRIGGER matches on) under the CURRENT `ensureCurrentSessionId()` — the same id\n * the gates pass to their `/decision` fetch, so the server's session-scoped trigger rule agrees —\n * with `user_context.device_key` for the min-sessions / arm-assignment lookups. On a successful POST\n * it bumps decision revalidation so a subscribed gate re-fetches and can fire.\n *\n * ADDITIVE + built on existing primitives: it reuses the events transport\n * (`reportClientEventAwait`, the awaitable sibling of `reportClientEvents` — ONE `/v1/events` path)\n * and `getCurrentSessionId` — it introduces NO second session concept and duplicates no POST path.\n * React-free (the optional React glue is the thin `useWireActivation` hook).\n */\nimport { ensureCurrentSessionId, getCurrentSessionId } from \"../analytics/currentSession\";\nimport {\n reportClientEventAwait,\n type ClientEvent,\n type ClientEventTarget,\n} from \"../analytics/reportClientEvent\";\nimport { resolveAutoDeviceKey, type ResolveAutoDeviceKeyOptions } from \"../context/deviceId\";\nimport { cleanString, resolveUserContext, type WireUserContext } from \"../context/userContext\";\nimport { resolveIdentity } from \"../identity/identityRecord\";\nimport { detectAppVersion } from \"../device/appVersion\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\nimport {\n bumpActivationRevalidation,\n getActivationRevalidationVersion,\n subscribeActivationRevalidation,\n} from \"./revalidation\";\n\n/** The shared trim helper (was a byte-identical private copy named `clean` in this file). */\nconst clean = cleanString;\n\n/**\n * Tenant transport + context inputs for {@link createWireActivation}. `serverUrl`/`apiKey` are the\n * SAME creds as onboarding (never a second key); everything else is optional.\n */\nexport type WireActivationConfig = {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/v1/events` is appended. */\n serverUrl: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey: string;\n /**\n * A stable, non-PII device id → `user_context.device_key` (the server's review/questionnaire\n * gating + A/B stickiness key on it). When omitted, the kit auto-mints ONE per-install id, persists\n * it via `storage` when given, and reuses it — so `device_key` is ALWAYS present. Host-supplied wins.\n */\n deviceKey?: string;\n /**\n * Optional rich context stamped onto every tracked event's `user_context` (opaque `userId` →\n * top-level `user_id`, opt-in `userEmail`, namespaced `extra`). `deviceKey` here is equivalent to\n * the top-level one (top-level wins). Same shape the analytics façade accepts.\n */\n userContext?: WireUserContext;\n /** Tenant/app id — namespaces the auto-minted device-key storage slot. */\n appId?: string;\n /** Host app version → `user_context.app_version` when no explicit `userContext.appVersion` is set. */\n appVersion?: string;\n /** Host persistence (AsyncStorage-compatible subset) so the auto-minted device key survives launches. */\n storage?: WireOnboardingStorage;\n};\n\n/** The kit-owned activation surface. `sessionId` is a live getter (reads `getCurrentSessionId()`). */\nexport type WireActivation = {\n /**\n * Awaitable action report: POST `event_type='app_event'`, `question_key=<name>`, optional `meta`,\n * under the CURRENT session id + `user_context.device_key`. Resolves `true` once the server has\n * stored it (2xx) and THEN bumps decision revalidation; resolves `false` (no bump) for a blank\n * name or a failed POST. Never throws.\n *\n * It no longer refuses when no app-open has been registered: the session id is resolved through\n * `ensureCurrentSessionId()`, which mints and registers one in that case (the server requires a\n * non-empty `session_id` and silently drops an event without one, so bailing lost the action\n * entirely). A host that fires `reportSessionStart` / `useLifecycleEvents` first is unaffected —\n * the real per-open id is already registered and gets used exactly as before.\n */\n track(name: string, meta?: Record<string, unknown>): Promise<boolean>;\n /** The CURRENT per-open session id (the kit's canonical `getCurrentSessionId()`), or `undefined`. */\n readonly sessionId: string | undefined;\n /** Subscribe to decision revalidation (bumped by a successful `track`). Returns an unsubscribe fn. */\n subscribeRevalidation(listener: () => void): () => void;\n /** The current revalidation version — include in a decision-fetch effect's deps to re-fetch on bump. */\n getRevalidationVersion(): number;\n};\n\n/**\n * Create a bound activation instance for a tenant transport. Resolves the device key once (explicit >\n * `userContext.deviceKey` > auto-minted + persisted). Pure + React-free.\n */\nexport const createWireActivation = (config: WireActivationConfig): WireActivation => {\n const target: ClientEventTarget = { serverUrl: config.serverUrl, apiKey: config.apiKey };\n\n // Device key: an explicit id (top-level or in userContext) wins and is never overwritten; otherwise\n // read the ONE process-wide auto id (`resolveAutoDeviceKey`) so this instance and a sibling\n // `createAnalytics` instance carry the SAME `device_key` for the same install. Minting locally here\n // gave one install two auto ids — see the registry note in context/deviceId.ts.\n const explicitDeviceKey = clean(config.deviceKey) ?? clean(config.userContext?.deviceKey);\n // Record a HOST-supplied key on the process provenance registry, so a `<WireOnboarding>` mount that\n // was NOT given one can tell \"this app owns no device id\" (fine, inject) from \"this app owns one\n // and forgot it here\" (the silent third id space). Recording only; nothing reads it on this path.\n resolveIdentity({\n value: explicitDeviceKey,\n space: \"device\",\n source: \"host\",\n scope: config.appId,\n });\n const autoDeviceKeyOptions: ResolveAutoDeviceKeyOptions = {\n appId: config.appId,\n // An explicit key opts out of minting AND persisting (unchanged contract).\n storage: explicitDeviceKey ? undefined : config.storage,\n };\n // Start hydration AT CONSTRUCTION (not at the first `track`) so the persisted id is adopted as early\n // as it used to be. The return value is deliberately discarded — every event re-resolves.\n if (!explicitDeviceKey) resolveAutoDeviceKey(autoDeviceKeyOptions);\n\n // The auto-detected host app version, read ONCE (cheap, sync, never throws) — same as the facade.\n // Without it this path had NO `app_version` fallback at all, so every `wire.track` event from a host\n // that passed no `config.appVersion` (which `wireConfigFromEnv` could not even carry) shipped\n // without one, while the facade and lifecycle families both had theirs.\n const detectedAppVersion = detectAppVersion();\n\n // Stamp the resolved rich context onto the event: `user_context` bucket (device_key always, plus any\n // app_version / opt-in user_email / namespaced extra) and the top-level opaque `user_id`.\n const applyContext = (event: ClientEvent): void => {\n const resolved = resolveUserContext(\n // `??` is lazy on purpose: an explicit key must never even touch the auto registry.\n {\n ...(config.userContext ?? {}),\n deviceKey: explicitDeviceKey ?? resolveAutoDeviceKey(autoDeviceKeyOptions),\n },\n { autoAppVersion: config.appVersion ?? detectedAppVersion },\n );\n if (resolved.userContext) {\n event.user_context = { ...resolved.userContext, ...(event.user_context ?? {}) };\n }\n if (resolved.userId && !event.user_id) event.user_id = resolved.userId;\n };\n\n const track = async (name: string, meta?: Record<string, unknown>): Promise<boolean> => {\n // A blank name is the only thing left to refuse on: there is no `question_key` to match a\n // firing trigger against, so bail WITHOUT bumping (a bump with no posted event would only make\n // the gate re-fetch for nothing).\n if (!clean(name)) return false;\n // No app-open registered is NOT a reason to drop the action. `ensureCurrentSessionId` returns\n // the registered per-open id when there is one (the unchanged path) and otherwise mints +\n // registers one, so the POST always carries the non-empty `session_id` the server requires\n // instead of being accepted with a 200 and discarded.\n const sessionId = ensureCurrentSessionId();\n const event: ClientEvent = {\n event_type: \"app_event\",\n session_id: sessionId,\n question_key: name,\n };\n if (meta && Object.keys(meta).length > 0) event.meta = JSON.stringify(meta);\n applyContext(event);\n const ok = await reportClientEventAwait(target, event);\n // Only revalidate once the event is actually in the stream — a failed POST leaves the gate as-is.\n if (ok) bumpActivationRevalidation();\n return ok;\n };\n\n return {\n track,\n get sessionId() {\n return getCurrentSessionId();\n },\n subscribeRevalidation: subscribeActivationRevalidation,\n getRevalidationVersion: getActivationRevalidationVersion,\n };\n};\n","/**\n * useWireActivation — a THIN optional React hook over {@link createWireActivation}.\n *\n * One import gives a consumer everything the activation consolidation owns: `track` (awaitable POST\n * that auto-revalidates), the CURRENT `sessionId`, and a `revalidation` counter that ticks whenever\n * a `track()` (from anywhere) succeeds — subscribe to re-render, then re-fetch your gate decision.\n *\n * const { track, sessionId, revalidation } = useWireActivation({ serverUrl, apiKey });\n * // fetch the gate decision on mount AND whenever revalidation ticks:\n * useEffect(() => { fetchReviewDecision(target, { sessionId, deviceKey }).then(setDecision); },\n * [revalidation]);\n * // on the trigger action:\n * await track(\"journal_done\");\n *\n * Mirrors the existing `createAnalytics` / `useAnalytics` (and `createScreenTracker` /\n * `useScreenTracking`) split: the factory stays React-free; this is the glue. The instance is built\n * once per mount and held in a ref, so re-renders never rebuild it or re-resolve the device key.\n */\nimport { useRef, useSyncExternalStore } from \"react\";\n\nimport {\n getActivationRevalidationVersion,\n subscribeActivationRevalidation,\n} from \"./revalidation\";\nimport {\n createWireActivation,\n type WireActivation,\n type WireActivationConfig,\n} from \"./wireActivation\";\n\n/**\n * Subscribe a component to decision revalidation. Returns the current version; list it in a\n * decision-fetch effect's deps so a `bumpActivationRevalidation()` (which a successful `track` does)\n * re-runs the fetch. The kit-owned replacement for a host's hand-rolled `useActivationRevalidation`.\n */\nexport const useActivationRevalidation = (): number =>\n useSyncExternalStore(\n subscribeActivationRevalidation,\n getActivationRevalidationVersion,\n getActivationRevalidationVersion,\n );\n\n/** What {@link useWireActivation} returns: the awaitable `track`, the live `sessionId`, and the tick. */\nexport type UseWireActivation = {\n /** Awaitable action report that auto-revalidates on success (see {@link WireActivation.track}). */\n track: WireActivation[\"track\"];\n /** The CURRENT per-open session id (read fresh each render), or `undefined`. */\n sessionId: string | undefined;\n /** Monotonic counter that increments on every successful `track()` — a re-fetch trigger. */\n revalidation: number;\n};\n\n/**\n * Build a per-mount activation instance. `config` is read once at first render (the instance is\n * stable for the component's lifetime, keyed on the transport creds + device key); the returned\n * `revalidation` re-renders the component whenever any `track()` succeeds.\n */\nexport const useWireActivation = (config: WireActivationConfig): UseWireActivation => {\n const ref = useRef<WireActivation | undefined>(undefined);\n const prevKeys = useRef<string>(\"\");\n\n // The identity of the built instance. `userContext.deviceKey` MUST be in here: `createWireActivation`\n // honors it as an explicit device key (`config.deviceKey ?? config.userContext?.deviceKey`), so a host\n // that hydrates its device id asynchronously and passes it only inside `userContext` would otherwise\n // keep an instance frozen on the first render's `undefined` — the stale-static-ref failure this repo\n // has already been bitten by (see .memory/70-knowledge.md, \"Stale Option Closures in Static Refs\").\n const currentKeys = [\n config.serverUrl,\n config.apiKey,\n config.appId,\n config.deviceKey,\n config.userContext?.deviceKey,\n ].join(\"|\");\n if (!ref.current || prevKeys.current !== currentKeys) {\n prevKeys.current = currentKeys;\n ref.current = createWireActivation(config);\n }\n\n const revalidation = useActivationRevalidation();\n return { track: ref.current.track, sessionId: ref.current.sessionId, revalidation };\n};\n","/**\n * purchaseEvents - the canonical Wire names for a subscription funnel, plus the PURE mappers that\n * turn a RevenueCat snapshot into small, non-PII event props.\n *\n * Same job `analyticsEvent.ts` does for the onboarding funnel: every app was naming these events\n * itself (`PURCHASE`, `purchase_success`, `AI_PAYWALL_VIEW`), so the same funnel read differently\n * per tenant and no cross-app report was possible. These are the ONE set of names; the mappers are\n * the ONE definition of which RevenueCat fields are safe to send.\n *\n * PURE + dependency-free: no React, no React Native, no `react-native-purchases`, no transport.\n * Every function tolerates a malformed or absent snapshot and returns a defined value instead of\n * throwing, because a paywall must never break on an analytics mapping.\n */\nimport type {\n RevenueCatCustomerInfoLike,\n RevenueCatEntitlementLike,\n RevenueCatPackageLike,\n} from \"./types\";\n\n/**\n * The canonical purchase-funnel event names. These are `app_event` `question_key` values on the\n * wire, so they are ALSO the exact strings a review / questionnaire firing trigger matches on.\n * Never rename one: a rename silently unfires every trigger configured against the old string.\n */\nexport const WIRE_PURCHASE_EVENTS = {\n /** The paywall became visible (offerings loaded). */\n paywallShown: \"wire_paywall_shown\",\n /** The user tapped buy; the store sheet is about to open. */\n checkoutStarted: \"wire_checkout_started\",\n /** The store confirmed the purchase AND the entitlement is now active. */\n purchased: \"wire_purchase_completed\",\n /** The purchase did not land: a user cancel or a real store/network error (see `reason`). */\n purchaseFailed: \"wire_purchase_failed\",\n /** A restore ran (whether or not it produced an entitlement; see `plan_tier`). */\n restored: \"wire_purchase_restored\",\n} as const;\n\nexport type WirePurchaseEventName =\n (typeof WIRE_PURCHASE_EVENTS)[keyof typeof WIRE_PURCHASE_EVENTS];\n\n/**\n * The user-context key the bridge writes the tier to. It lands NAMESPACED as\n * `user_context[\"custom.plan_tier\"]` (host extras are always prefixed), which is the flattened\n * dimension the server report can break the funnel down by.\n */\nexport const PLAN_TIER_CONTEXT_KEY = \"plan_tier\";\n\n/** The three tiers the kit models. Anything richer belongs in the host's own analytics. */\nexport type PlanTier = \"paid\" | \"trial\" | \"free\";\n\n/** Read a plain record field defensively (the snapshot comes from a native bridge). */\nconst asRecord = (value: unknown): Record<string, unknown> | undefined =>\n typeof value === \"object\" && value !== null ? (value as Record<string, unknown>) : undefined;\n\n/**\n * The ACTIVE entitlement matching `entitlementId`, or `undefined`. Returns `undefined` for a\n * missing key, an explicitly inactive entry, and any malformed snapshot.\n */\nexport const activeEntitlement = (\n info: RevenueCatCustomerInfoLike | undefined,\n entitlementId: string,\n): RevenueCatEntitlementLike | undefined => {\n const active = asRecord(asRecord(asRecord(info)?.entitlements)?.active);\n const found = active?.[entitlementId];\n const entitlement = asRecord(found) as RevenueCatEntitlementLike | undefined;\n if (!entitlement) return undefined;\n // `isActive` is always present on the real type; treat an explicit `false` as not entitled and a\n // missing value as entitled, because the key only appears in `entitlements.active` at all when\n // RevenueCat considers it granted.\n return entitlement.isActive === false ? undefined : entitlement;\n};\n\n/** True when RevenueCat says this entitlement is a free trial rather than a paid period. */\nconst isTrial = (entitlement: RevenueCatEntitlementLike): boolean =>\n typeof entitlement.periodType === \"string\" && entitlement.periodType.toUpperCase() === \"TRIAL\";\n\n/** `paid` / `trial` / `free` for the configured entitlement. Never throws. */\nexport const resolvePlanTier = (\n info: RevenueCatCustomerInfoLike | undefined,\n entitlementId: string,\n): PlanTier => {\n const entitlement = activeEntitlement(info, entitlementId);\n if (!entitlement) return \"free\";\n return isTrial(entitlement) ? \"trial\" : \"paid\";\n};\n\n/**\n * Non-PII props for an offering package: which package, which product, what it costs. Every field\n * is optional on the wire, so a missing one is OMITTED rather than sent empty or invented.\n */\nexport const describePackage = (\n pkg: RevenueCatPackageLike | undefined,\n): Record<string, string | number> => {\n const props: Record<string, string | number> = {};\n if (!pkg) return props;\n if (typeof pkg.identifier === \"string\") props.package_id = pkg.identifier;\n if (typeof pkg.packageType === \"string\") props.package_type = pkg.packageType;\n if (typeof pkg.offeringIdentifier === \"string\") props.offering_id = pkg.offeringIdentifier;\n const product = asRecord(pkg.product) as RevenueCatProductFields | undefined;\n if (product) {\n if (typeof product.identifier === \"string\") props.product_id = product.identifier;\n if (typeof product.price === \"number\" && Number.isFinite(product.price)) {\n props.price = product.price;\n }\n if (typeof product.currencyCode === \"string\") props.currency = product.currencyCode;\n }\n return props;\n};\n\n/** The product fields `describePackage` reads, narrowed after the defensive record check. */\ntype RevenueCatProductFields = {\n identifier?: unknown;\n price?: unknown;\n currencyCode?: unknown;\n};\n\n/**\n * Non-PII props for the entitlement state after a purchase or a restore. Always carries\n * `entitlement` + `plan_tier` so a \"restore that granted nothing\" is still a queryable row; the\n * rest of the fields only appear when the entitlement is actually active.\n */\nexport const describeEntitlement = (\n info: RevenueCatCustomerInfoLike | undefined,\n entitlementId: string,\n): Record<string, string | number | boolean> => {\n const entitlement = activeEntitlement(info, entitlementId);\n const props: Record<string, string | number | boolean> = {\n entitlement: entitlementId,\n plan_tier: entitlement ? (isTrial(entitlement) ? \"trial\" : \"paid\") : \"free\",\n };\n if (!entitlement) return props;\n if (typeof entitlement.periodType === \"string\") props.period_type = entitlement.periodType;\n props.is_trial = isTrial(entitlement);\n if (typeof entitlement.willRenew === \"boolean\") props.will_renew = entitlement.willRenew;\n if (typeof entitlement.store === \"string\") props.store = entitlement.store;\n if (typeof entitlement.productIdentifier === \"string\") {\n props.product_id = entitlement.productIdentifier;\n }\n if (typeof entitlement.isSandbox === \"boolean\") props.is_sandbox = entitlement.isSandbox;\n return props;\n};\n\n/** RevenueCat's `PURCHASES_ERROR_CODE.PURCHASE_CANCELLED_ERROR`. A STRING enum, value `\"1\"`. */\nconst PURCHASE_CANCELLED_CODE = \"1\";\n\n/**\n * True when the rejection is the user backing out of the store sheet rather than a real failure.\n * Reads BOTH signals the SDK exposes: the current `code` and the deprecated-but-still-populated\n * `userCancelled` flag. Anything else (including a plain `Error`) is a genuine failure.\n */\nexport const isUserCancelled = (error: unknown): boolean => {\n const record = asRecord(error);\n if (!record) return false;\n if (record.userCancelled === true) return true;\n return record.code === PURCHASE_CANCELLED_CODE;\n};\n\n/**\n * A short, stable, non-PII failure descriptor. The store's `message` is DELIBERATELY dropped: it is\n * localized, unbounded, and occasionally echoes the account it failed for, so it is not something\n * the kit forwards to a shared analytics backend. The RevenueCat `code` is the stable handle.\n */\nexport const describeFailure = (error: unknown): { reason: string; code: string } => {\n const record = asRecord(error);\n const code = typeof record?.code === \"string\" ? record.code : \"unknown\";\n return { reason: isUserCancelled(error) ? \"cancelled\" : \"error\", code };\n};\n","/**\n * revenueCatBridge - the short, first-class path from RevenueCat to Wire activation.\n *\n * const revenuecat = createRevenueCatBridge({ analytics, entitlementId: \"pro\" });\n * revenuecat.paywallShown(offering, { source: variant });\n * revenuecat.checkoutStarted(pkg, { source: variant });\n * const entitled = revenuecat.purchaseCompleted(customerInfo, pkg, { source: variant });\n *\n * WHAT IT REPLACES: every consumer was hand-rolling the same four things around its paywall,\n * differently: its own event names, its own idea of which RevenueCat fields are safe to send, its\n * own entitlement check duplicated at the purchase and the restore site, and its own plan-tier\n * user property. This owns all four, so adopting the purchase funnel is a constructor plus five\n * call sites.\n *\n * ── THE JOIN KEY (read this before you wire it) ───────────────────────────────────────────────\n * A purchase event is only worth anything if it can be joined to the SAME user's onboarding. The\n * key that does that is `user_context.device_key`, NOT `session_id`:\n *\n * • Purchase side: this bridge reports through a kit sink (`createAnalytics` or\n * `createWireActivation`). Both auto-mint a stable, persisted, per-install `device_key` and\n * stamp it on every event (see `context/deviceId.ts`).\n * • Onboarding side: `<WireOnboarding userContext={activationJoinContext(deviceKey)} />`. The kit\n * forwards `userContext` verbatim into the A2A session-start metadata, and the server records\n * it on the session's `session_started` event, where the SAME `device_key` lookup reads it.\n *\n * Pass the SAME `deviceKey` to both. `session_id` is NOT a join key across these two families: the\n * onboarding session id is the A2A `contextId`, the app-event session id is the per-open id, and\n * they live in disjoint spaces on purpose. Intersecting them yields zero rows, every time.\n *\n * PURE + dependency-free: no React, no React Native, no `react-native-purchases`. Fire-and-forget\n * throughout, so an analytics failure can never take the paywall down with it.\n */\nimport type { Analytics } from \"../analytics/analyticsFacade\";\nimport type { WireActivation } from \"../activation/wireActivation\";\nimport {\n PLAN_TIER_CONTEXT_KEY,\n WIRE_PURCHASE_EVENTS,\n describeEntitlement,\n describeFailure,\n describePackage,\n resolvePlanTier,\n type PlanTier,\n} from \"./purchaseEvents\";\nimport type {\n RevenueCatCustomerInfoLike,\n RevenueCatOfferingLike,\n RevenueCatPackageLike,\n RevenueCatSink,\n} from \"./types\";\n\n/**\n * COMPILE-TIME PROOF that both kit sinks satisfy {@link RevenueCatSink}, so a host can pass the\n * analytics instance it already holds with no adapter of its own. Type-only (erased at build), and\n * `tsc --noEmit` fails here the day either surface drifts. This lives in source, not the test file,\n * because `tsconfig.json` excludes tests from the typecheck.\n */\ntype AssertIsSink<T extends RevenueCatSink> = T;\ntype _AnalyticsIsASink = AssertIsSink<Analytics>;\ntype _WireActivationIsASink = AssertIsSink<WireActivation>;\n\n/** Small, non-PII extras a host merges onto a purchase event (paywall variant, entry point, ...). */\nexport type PurchaseProps = Record<string, string | number | boolean>;\n\n/** Inputs for {@link createRevenueCatBridge}. */\nexport interface RevenueCatBridgeConfig {\n /**\n * Where events go: the `createAnalytics(...)` instance (offline-first queue) or the\n * `createWireActivation(...)` instance (awaitable POST). Both already carry the `device_key` this\n * funnel joins on, so pass the one the app already holds rather than creating a second.\n */\n analytics: RevenueCatSink;\n /**\n * The entitlement identifier that means \"paid\" in THIS app, exactly as configured in the\n * RevenueCat dashboard (e.g. `\"pro\"`). The bridge reads `customerInfo.entitlements.active[id]`.\n */\n entitlementId: string;\n /** Non-PII props merged into EVERY event from this bridge. A per-call prop of the same name wins. */\n commonProps?: PurchaseProps;\n /**\n * Whether entitlement changes also update the bound user context with `plan_tier`\n * (`user_context[\"custom.plan_tier\"]`), so the whole funnel can be sliced paid vs trial vs free.\n * Default `true`. Requires a sink with `setUserContext` (`createAnalytics`); a no-op otherwise.\n */\n writePlanTier?: boolean;\n}\n\n/** The bridge surface. Every method is fire-and-forget and never throws. */\nexport interface RevenueCatBridge {\n /**\n * The paywall became visible. Pass the RevenueCat offering you just loaded and the bridge derives\n * `offering_id` + `packages_count`. Fires even with no offering, because a paywall that reached\n * the user with nothing to sell is exactly the failure you want in the funnel.\n */\n paywallShown(offering?: RevenueCatOfferingLike, props?: PurchaseProps): void;\n /** The user tapped buy and the store sheet is opening. */\n checkoutStarted(pkg: RevenueCatPackageLike, props?: PurchaseProps): void;\n /**\n * The store returned from a purchase. Fires `wire_purchase_completed` when the configured\n * entitlement is now active, and `wire_purchase_failed` with `reason: \"not_entitled\"` when the\n * store confirmed but nothing was granted (the case hosts usually drop on the floor). Syncs\n * `plan_tier` either way. Returns whether the user is entitled now, so the caller can navigate.\n */\n purchaseCompleted(\n customerInfo: RevenueCatCustomerInfoLike | undefined,\n pkg?: RevenueCatPackageLike,\n props?: PurchaseProps,\n ): boolean;\n /** The purchase call rejected. Separates a user cancel from a real store error via `reason`. */\n purchaseFailed(error: unknown, pkg?: RevenueCatPackageLike, props?: PurchaseProps): void;\n /** A restore finished. Reports the resulting tier and returns whether the user is entitled now. */\n purchasesRestored(\n customerInfo: RevenueCatCustomerInfoLike | undefined,\n props?: PurchaseProps,\n ): boolean;\n /**\n * Write the current tier to the bound user context WITHOUT emitting an event. Call it once at\n * launch with a `getCustomerInfo()` snapshot so returning subscribers are segmented correctly\n * from their first event of the session. Returns the tier it resolved.\n */\n syncPlanTier(customerInfo: RevenueCatCustomerInfoLike | undefined): PlanTier;\n}\n\n/**\n * Create a bridge bound to one sink and one entitlement. Pure, React-free, and safe to create at\n * module scope next to the paywall.\n */\nexport const createRevenueCatBridge = (config: RevenueCatBridgeConfig): RevenueCatBridge => {\n const { analytics, entitlementId } = config;\n const writeTier = config.writePlanTier !== false;\n\n /**\n * Send one event. Swallows a throwing sink AND a rejected promise from an awaitable one, so an\n * analytics failure is never visible at the paywall and never becomes an unhandled rejection.\n */\n const emit = (event: string, props: Record<string, unknown>): void => {\n try {\n const result = analytics.track(event, { ...config.commonProps, ...props });\n if (result && typeof (result as Promise<boolean>).catch === \"function\") {\n void (result as Promise<boolean>).catch(() => {});\n }\n } catch {\n /* analytics must never break a purchase */\n }\n };\n\n const syncPlanTier = (customerInfo: RevenueCatCustomerInfoLike | undefined): PlanTier => {\n const tier = resolvePlanTier(customerInfo, entitlementId);\n if (!writeTier) return tier;\n try {\n analytics.setUserContext?.({ extra: { [PLAN_TIER_CONTEXT_KEY]: tier } });\n } catch {\n /* a sink without a usable context writer is not a purchase failure */\n }\n return tier;\n };\n\n const paywallShown = (offering?: RevenueCatOfferingLike, props?: PurchaseProps): void => {\n const shown: Record<string, unknown> = {\n packages_count: offering?.availablePackages?.length ?? 0,\n };\n if (typeof offering?.identifier === \"string\") shown.offering_id = offering.identifier;\n emit(WIRE_PURCHASE_EVENTS.paywallShown, { ...shown, ...props });\n };\n\n const checkoutStarted = (pkg: RevenueCatPackageLike, props?: PurchaseProps): void => {\n emit(WIRE_PURCHASE_EVENTS.checkoutStarted, { ...describePackage(pkg), ...props });\n };\n\n const purchaseCompleted = (\n customerInfo: RevenueCatCustomerInfoLike | undefined,\n pkg?: RevenueCatPackageLike,\n props?: PurchaseProps,\n ): boolean => {\n const tier = syncPlanTier(customerInfo);\n const entitled = tier !== \"free\";\n if (entitled) {\n emit(WIRE_PURCHASE_EVENTS.purchased, {\n ...describePackage(pkg),\n ...describeEntitlement(customerInfo, entitlementId),\n ...props,\n });\n return true;\n }\n // The store said yes but the entitlement is not active: a product/entitlement mapping problem,\n // the single most common silent paywall defect. Report it rather than returning quietly.\n emit(WIRE_PURCHASE_EVENTS.purchaseFailed, {\n ...describePackage(pkg),\n reason: \"not_entitled\",\n code: \"unknown\",\n entitlement: entitlementId,\n ...props,\n });\n return false;\n };\n\n const purchaseFailed = (\n error: unknown,\n pkg?: RevenueCatPackageLike,\n props?: PurchaseProps,\n ): void => {\n emit(WIRE_PURCHASE_EVENTS.purchaseFailed, {\n ...describePackage(pkg),\n ...describeFailure(error),\n ...props,\n });\n };\n\n const purchasesRestored = (\n customerInfo: RevenueCatCustomerInfoLike | undefined,\n props?: PurchaseProps,\n ): boolean => {\n const tier = syncPlanTier(customerInfo);\n emit(WIRE_PURCHASE_EVENTS.restored, {\n ...describeEntitlement(customerInfo, entitlementId),\n ...props,\n });\n return tier !== \"free\";\n };\n\n return { paywallShown, checkoutStarted, purchaseCompleted, purchaseFailed, purchasesRestored, syncPlanTier };\n};\n","/**\n * reportSessionStart — the ONE standard emitter for \"the user opened the app again\".\n *\n * Every app-open posts a single `app.session_started` event to the Wire analytics backend\n * (`POST {serverUrl}/v1/events`). That event does two jobs at once, with ZERO server changes:\n *\n * 1. SESSION MAPPING. It carries the host's opaque `userId` + a stable `deviceKey`, so the\n * backend can group a user's (or a pre-auth device's) opens over time — \"when did this\n * user last use the app, and how many times\". The device_key links the pre-auth opens to\n * the user once `userId` arrives (here or via `identifyOnboarding`).\n * 2. QUESTIONNAIRE / RETENTION FIRING. It flows into the SAME event stream the server's\n * decision engines read, so a questionnaire trigger `{event:\"app.session_started\", min_count:N}`\n * (matched within a session) or a questionnaire `min_sessions:N` (distinct device sessions)\n * fires on the user's Nth open with no new server endpoint.\n *\n * WIRE CONTRACT (server: analytics/events.py + routers/onboarding.py `POST /v1/events`):\n * The event is stored as `event_type='app_event'`, `question_key='app.session_started'` — the\n * generic app.* namespace the reviews wave shipped. The server's `_event_name(ev)` returns the\n * `question_key` for an `app_event`, which is what a trigger's `event` string matches. We do NOT\n * send `event_type:'app.session_started'` — that name is not in the server's EVENT_TYPES and\n * would be rejected. `device_key` rides in the non-PII `user_context` bucket, where the server's\n * `_event_device_key(ev)` reads it to group a device's sessions. `app_id` + `environment` are\n * filled server-side from the resolving key (never sent here).\n *\n * SESSION ID DISTINCTION (important): the `session_id` on this event is a PER-OPEN id (a fresh\n * `makeSessionId()` each app-open) — it is NOT the onboarding A2A `contextId`. Onboarding runs\n * ONCE (first launch) and owns its own context id; session-start fires on EVERY open, so it needs\n * its own per-open id. Grouping over time is done by `device_key`/`user_id`, not by session_id.\n *\n * Fire-and-forget: like every analytics path in the kit, this never throws into the UI, never\n * awaits, and swallows a missing target / bad URL / missing fetch / network error. Analytics must\n * never be able to break the app.\n */\nimport { setCurrentSessionId } from \"../analytics/currentSession\";\nimport {\n makeSessionId,\n warnOnSkippedEvents,\n type ClientEvent,\n type ClientEventTarget,\n} from \"../analytics/reportClientEvent\";\nimport type { DeviceContext } from \"../device/deviceContext\";\nimport { sanitizeUserId } from \"../identity/userIdentity\";\n\n/** The canonical event name for an app-open. A trigger keys off this exact string. */\nexport const SESSION_STARTED_EVENT = \"app.session_started\" as const;\n\n/** Options for {@link reportSessionStart}. Everything except `target` is optional so a pre-auth\n * open (no user yet) is a valid, device-only session. */\nexport interface ReportSessionStartOptions {\n /** Where to POST — the tenant transport (`serverUrl` + `apiKey`), same as `WireOnboardingConfig`. */\n target: ClientEventTarget | undefined;\n /**\n * The per-open session id. Defaults to a fresh `makeSessionId()`. Pass your own ONLY to\n * dedupe re-renders of the same open (the {@link useSessionStart} hook does exactly that).\n * This is NOT the onboarding contextId — see the file header.\n */\n sessionId?: string;\n /** The host's OPAQUE pseudonymous user id (their internal id, NOT an email/PII). Sanitized +\n * capped here; omitted on a pre-auth open (device-only session). */\n userId?: string;\n /** A stable, non-PII device id the host owns. Rides in `user_context.device_key` so the server\n * groups this device's sessions (the min_sessions signal). Host-supplied, same as reviews. */\n deviceKey?: string;\n /** The host's own local open-counter value for this open (1 on the first ever open). Drives the\n * `returning` flag and lets analytics read \"Nth session\" without server-side counting. */\n sessionCount?: number;\n /** Host app version (e.g. \"1.4.2\"), if cheaply available. Segments retention by release. */\n appVersion?: string;\n /** Platform string (e.g. \"ios\"), if cheaply available. */\n platform?: string;\n /** An optional richer device snapshot (from `collectDeviceContext()`); the hook fills this. */\n device?: DeviceContext;\n /** Small non-PII extras, stored as a JSON string in the event `meta`. */\n meta?: Record<string, unknown>;\n /** Set `false` to bypass the once-per-open guard (default on). See {@link resetSessionStartGuard}. */\n once?: boolean;\n /**\n * OPTIONAL transport sink. When provided, the built `app.session_started` event is routed HERE\n * (e.g. the offline-first event queue's `enqueue`) INSTEAD of this emitter's own direct `fetch`,\n * while KEEPING the once-per-open guard above. This is how the lifecycle wiring\n * (`useLifecycleEvents` / `wireLifecycleEvents`) offline-buffers session-start WITHOUT adding a\n * second session emitter: one emitter, one guard, now durable. Omit it for the direct-POST path.\n * A throwing sink is swallowed — analytics must never surface into the UI.\n */\n sink?: (event: ClientEvent) => void;\n}\n\n// ── Once-per-open guard ──────────────────────────────────────────────────────\n// A re-render (or a host that lists the emitter in an effect) must never double-fire the SAME\n// open. We remember the session ids already emitted; a repeat call with a seen id is a no-op.\n// Bounded so a long-lived app never grows this unboundedly — a fresh open always mints a fresh\n// id, so evicting old ids can never cause a real re-fire.\nconst _emitted = new Set<string>();\nconst _GUARD_MAX = 128;\n\n/** Test-only: forget every emitted session id so a unit test starts from a clean guard. */\nexport const resetSessionStartGuard = (): void => {\n _emitted.clear();\n};\n\n/**\n * Emit one `app.session_started` event for this app-open. Fire-and-forget; returns immediately.\n * Idempotent per `sessionId` (unless `once:false`) so a re-render can never double-fire.\n */\nexport const reportSessionStart = (opts: ReportSessionStartOptions): void => {\n const target = opts.target;\n // A wired sink is a valid transport on its own — it owns the target (the queue's serverUrl), so\n // this emitter needs its own `target` ONLY for the direct-fetch fallback.\n if (!opts.sink && !target?.serverUrl) return;\n\n const sessionId = opts.sessionId ?? makeSessionId();\n\n // Register this open as the CURRENT per-open session so the analytics façade's `identify` /\n // app-events reuse the id the server sees here (via `app.session_started`) instead of minting a\n // fresh one it would back-fill into a phantom session. Idempotent; set before the once-guard so\n // even a guard-deduped repeat keeps the current id pointing at this open.\n setCurrentSessionId(sessionId);\n\n // Once-per-open guard: skip a repeat emit for a session id we already sent.\n if (opts.once !== false) {\n if (_emitted.has(sessionId)) return;\n if (_emitted.size >= _GUARD_MAX) {\n // Evict the oldest insertion (Set preserves insertion order).\n const oldest = _emitted.values().next().value;\n if (oldest !== undefined) _emitted.delete(oldest);\n }\n _emitted.add(sessionId);\n }\n\n try {\n // Non-PII correlation bucket. device_key is read by the server to group a device's sessions;\n // session_count / returning / app_version / platform feed per-user retention analytics.\n const userContext: Record<string, string | number | boolean> = {};\n if (opts.deviceKey) userContext.device_key = opts.deviceKey;\n if (typeof opts.sessionCount === \"number\" && Number.isFinite(opts.sessionCount)) {\n userContext.session_count = opts.sessionCount;\n userContext.returning = opts.sessionCount > 1;\n }\n if (opts.appVersion) userContext.app_version = opts.appVersion;\n if (opts.platform) userContext.platform = opts.platform;\n\n const event: Record<string, unknown> = {\n event_type: \"app_event\",\n question_key: SESSION_STARTED_EVENT,\n session_id: sessionId,\n };\n const userId = sanitizeUserId(opts.userId);\n if (userId) event.user_id = userId;\n if (Object.keys(userContext).length > 0) event.user_context = userContext;\n if (opts.device) event.device = opts.device;\n if (opts.meta && Object.keys(opts.meta).length > 0) event.meta = JSON.stringify(opts.meta);\n\n // Preferred transport: an injected sink (the offline-first event queue's `enqueue`), which\n // buffers + persists + retries. The once-guard above already ran, so this stays the single\n // session emitter with a single guard — now durable.\n if (opts.sink) {\n opts.sink(event as ClientEvent);\n return;\n }\n\n // Fallback: this emitter's own direct POST when no sink is wired.\n if (!target?.serverUrl) return;\n const url = `${target.serverUrl.replace(/\\/$/, \"\")}/v1/events`;\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (target.apiKey) headers.Authorization = `Bearer ${target.apiKey}`;\n void fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ events: [event] }),\n })\n .then((res) => {\n // A 200 can still carry `skipped:N` — the server took the request and threw the event away.\n // Log-only; this path has nothing to retry either way.\n warnOnSkippedEvents(res);\n })\n .catch(() => {\n // Network/transport error — analytics is best-effort, swallow.\n });\n } catch {\n // URL construction, JSON serialization, a throwing sink, or a missing fetch — swallow.\n }\n};\n","/**\n * useSessionStart — the optional convenience hook that fires {@link reportSessionStart} for you.\n *\n * Two firing moments, mirroring the reference apps' session-counter semantics:\n * • ON MOUNT — the app opened (cold start or the provider first rendered).\n * • ON FOREGROUND after a real background — when AppState returns to `active` having been\n * backgrounded for at least {@link BACKGROUND_SESSION_MS} (30 min), that's a NEW open, so a\n * fresh session fires. A quick app-switch (under the threshold) does NOT count as a new open.\n *\n * Each firing mints its OWN per-open `session_id` (held in a ref so a re-render never re-fires),\n * so grouping over time is by `deviceKey`/`userId`, never by session_id (see reportSessionStart).\n *\n * NOT THE DEFAULT WIRING. `useLifecycleEvents` is: this hook emits `app.session_started` ONLY, so a\n * host on this path has a permanently empty `app.first_open` and no top of funnel. Use it when you\n * already own an open counter and deliberately want session starts alone; otherwise mount\n * `useLifecycleEvents(config, { deviceKey?, sessionCount?, userId? })` once at the app root.\n *\n * The hook is OPTIONAL. A host that already owns a session counter (most hosts do) can skip\n * the hook and call `reportSessionStart(...)` directly from its own \"app opened\" path — BOTH\n * paths are first-class. This hook is the batteries-included option for a host that has none.\n *\n * Dependency policy: `AppState` + `Platform` are React Native built-ins (no new dep); the device\n * snapshot comes from the kit's own dependency-free `collectDeviceContext()`.\n */\nimport { useEffect, useRef } from \"react\";\nimport { AppState, Platform, type AppStateStatus } from \"react-native\";\n\nimport type { ClientEventTarget } from \"../analytics/reportClientEvent\";\nimport { resolveAutoDeviceKey } from \"../context/deviceId\";\nimport { collectDeviceContext } from \"../device/deviceContext\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\nimport { reportSessionStart } from \"./reportSessionStart\";\n\n/** A foreground after at least this long in the background counts as a NEW app-open (30 min). */\nexport const BACKGROUND_SESSION_MS = 30 * 60 * 1000;\n\n/** Tenant transport + optional host app version. Same creds as `WireOnboardingConfig`. */\nexport interface SessionStartConfig {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/v1/events` is appended. */\n serverUrl?: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey?: string;\n /** Host app version (e.g. \"1.4.2\"), forwarded for release segmentation. Optional. */\n appVersion?: string;\n /** Tenant/app id — namespaces the auto `device_key` fallback below. */\n appId?: string;\n /** Host storage (AsyncStorage subset). Present → `app.session_started` falls back to the kit's\n * persisted auto `device_key` when the host passes none. Absent → no fallback (see below). */\n storage?: WireOnboardingStorage;\n}\n\n/** Per-open identity the host supplies. All optional: a pre-auth open is device-only. */\nexport interface UseSessionStartOptions {\n /** The host's opaque pseudonymous user id (NOT PII). Omitted before the user authenticates. */\n userId?: string;\n /** The host's local open-counter value for this open. Drives `returning` + \"Nth session\". */\n sessionCount?: number;\n /** A stable, non-PII device id the host owns. Groups this device's sessions server-side. */\n deviceKey?: string;\n /** Small non-PII extras forwarded on the event `meta`. */\n meta?: Record<string, unknown>;\n /** Set `false` to disable firing (e.g. behind a consent gate). Default enabled. */\n enabled?: boolean;\n}\n\n/**\n * Fire `app.session_started` on mount and on every real foreground-after-background. Returns\n * nothing — it is a side-effecting hook. Safe to call with inline options (values are read\n * through a ref, so changing `userId`/`sessionCount` never re-fires a session).\n */\nexport const useSessionStart = (\n config: SessionStartConfig | undefined,\n options: UseSessionStartOptions = {},\n): void => {\n // Latest options/config through a ref so the mount/resume fires read fresh values without\n // listing them as effect deps (which would re-fire a session on every prop change).\n const latest = useRef({ config, options });\n latest.current = { config, options };\n\n useEffect(() => {\n /**\n * The `device_key` this open rides under. A host-supplied id always wins.\n *\n * BACKPORTED FROM `useLifecycleEvents` (which had this and this hook did not): `min_sessions` is\n * computed server-side by counting distinct `app.session_started` grouped by\n * `user_context.device_key`, so a host that passed no `deviceKey` emitted the counted event with\n * NO key while its facade / activation events carried an auto-minted one — two disjoint identity\n * spaces, and a counter that could never increase. The two session-start paths must not diverge\n * on the thing the firing rule reads.\n *\n * ONLY WITH `storage`, for the same reason as the sibling hook: without persistence the auto id\n * is per-LAUNCH, and a per-launch key makes every open look like a new device, corrupting\n * `min_sessions` in the other direction.\n */\n const resolveDeviceKey = (\n cfg: SessionStartConfig | undefined,\n opts: UseSessionStartOptions,\n ): string | undefined => {\n const host = typeof opts.deviceKey === \"string\" && opts.deviceKey.trim() ? opts.deviceKey : undefined;\n if (host) return host;\n if (!cfg?.storage) return undefined;\n return resolveAutoDeviceKey({ appId: cfg.appId, storage: cfg.storage });\n };\n\n const fire = () => {\n const { config: cfg, options: opts } = latest.current;\n if (!cfg?.serverUrl) return;\n if (opts.enabled === false) return;\n const target: ClientEventTarget = { serverUrl: cfg.serverUrl, apiKey: cfg.apiKey ?? \"\" };\n const device = collectDeviceContext();\n // `device.appVersion` is auto-detected best-effort; an explicit host version always wins.\n if (cfg.appVersion) device.appVersion = cfg.appVersion;\n reportSessionStart({\n target,\n // A fresh per-open id each fire; the emitter's once-guard dedupes within the open.\n userId: opts.userId,\n deviceKey: resolveDeviceKey(cfg, opts),\n sessionCount: opts.sessionCount,\n appVersion: cfg.appVersion ?? device.appVersion,\n platform: Platform.OS,\n device,\n meta: opts.meta,\n });\n };\n\n // 1) Mount = an app-open.\n fire();\n\n // 2) Foreground after a real background = a new app-open.\n let backgroundedAt: number | null = null;\n const onChange = (state: AppStateStatus) => {\n if (state === \"background\" || state === \"inactive\") {\n // Record the first moment we left the foreground (don't overwrite inactive→background).\n if (backgroundedAt == null) backgroundedAt = Date.now();\n return;\n }\n if (state === \"active\") {\n const since = backgroundedAt;\n backgroundedAt = null;\n if (since != null && Date.now() - since >= BACKGROUND_SESSION_MS) fire();\n }\n };\n const sub = AppState.addEventListener(\"change\", onChange);\n return () => {\n // RN >= 0.65 returns a subscription with remove(); guard for older shims.\n if (sub && typeof (sub as { remove?: () => void }).remove === \"function\") sub.remove();\n };\n // Mount-only effect: firing reads fresh values via `latest`, so no reactive deps.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n};\n","/**\n * lifecycle — the TOP-OF-FUNNEL app lifecycle events that sit ABOVE onboarding: `app.first_open`\n * (once ever per install) and `app.session_started` (per app-open). They compose with, and never\n * duplicate, the events the funnel already records.\n *\n * WHERE THIS FITS (one funnel, no double counting):\n * • `app.first_open` → THIS module, once ever (persisted flag). The in-app \"install\" proxy.\n * • `app.session_started` → the EXISTING {@link reportSessionStart} emitter (per app-open). This\n * module REUSES it (routed through the offline queue), never re-emits.\n * • onboarding started / completed / activated → ALREADY recorded: the server writes\n * `session_started` + `completed` during the A2A flow, and the client reports `dropped` /\n * `client_fallback` / `identify` via `reportClientEvent`. This module does NOT touch them —\n * emitting them here would double-count. It only ADDS the two lifecycle events above them.\n *\n * WIRE CONTRACT (identical to `app.session_started`): both lifecycle events are stored as\n * `event_type='app_event'` with the name in `question_key` (the server's `_event_name` returns\n * `question_key` for an `app_event`, which a trigger matches). `app.first_open` uses the SAME\n * `app.*` namespace + the SAME event shape as `app.session_started` — no bespoke `event_type`,\n * no invented contract. `device_key` rides in the non-PII `user_context` bucket; `app_id` +\n * `environment` are filled server-side.\n *\n * TWO FIRST-CLASS ENTRY POINTS (mirrors reportSessionStart vs useSessionStart):\n * • `reportFirstOpen(...)` / `wireLifecycleEvents(...)` — pure, React-free, for a host that owns\n * its own app-open path.\n * • `useLifecycleEvents(...)` — the batteries-included React hook (in `useLifecycleEvents.ts`).\n *\n * OFFLINE-FIRST: pass the Brief-01 event queue's `enqueue` as the `sink` and every lifecycle event\n * is buffered + persisted + retried instead of a blind fetch. Without a sink they degrade to a\n * direct fire-and-forget POST.\n *\n * PRIVACY (hard rule, same as the rest of the kit): NO GPS/location, NO advertising id. Nothing\n * here carries a coordinate or an ad id — a host adopting it changes no store privacy declaration.\n *\n * FIRE-AND-FORGET: like every analytics path in the kit, nothing here throws into the UI, awaits\n * in the caller, or hangs the app — storage reads race a short timeout, writes swallow errors.\n */\nimport { buildEventsRequest, makeSessionId, type ClientEvent, type ClientEventTarget } from \"../analytics/reportClientEvent\";\nimport type { DeviceContext } from \"../device/deviceContext\";\nimport { sanitizeUserId } from \"../identity/userIdentity\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\nimport { reportSessionStart, SESSION_STARTED_EVENT } from \"./reportSessionStart\";\n\n/** The canonical event name for the first-ever app open. Same `app.*` namespace as\n * {@link SESSION_STARTED_EVENT}; a trigger keys off this exact string. */\nexport const FIRST_OPEN_EVENT = \"app.first_open\" as const;\n\n/** Storage key for the once-ever first-open flag, e.g. `wireai:first_open:acme`. Mirrors the\n * `wireai:<concern>:<appId>` namespacing of {@link sessionStorageKey}. */\nexport const firstOpenStorageKey = (appId: string): string => `wireai:first_open:${appId}`;\n\n/** Ceiling on the flag read — a hung adapter degrades to the in-memory latch, never a stuck gate. */\nconst READ_TIMEOUT_MS = 1_500;\n\nconst withTimeout = <T>(p: Promise<T>, ms: number): Promise<T | undefined> => {\n let timer: ReturnType<typeof setTimeout>;\n const timeout = new Promise<undefined>((resolve) => {\n timer = setTimeout(() => resolve(undefined), ms);\n });\n return Promise.race([p, timeout]).finally(() => clearTimeout(timer));\n};\n\n// ── First-open in-memory latch ───────────────────────────────────────────────\n// Covers TWO cases the persisted flag can't: (1) two near-simultaneous calls in one process (the\n// flag read is async, so a synchronous latch is what guarantees at-most-one before any await), and\n// (2) the documented DEGRADED no-storage mode (fires once per process). Keyed by appId.\nconst _firstOpenLatched = new Set<string>();\n\n/** Test-only: forget the first-open latch so a unit test starts from a clean process state. */\nexport const resetFirstOpenLatch = (): void => {\n _firstOpenLatched.clear();\n};\n\n/** Shared inputs for a lifecycle event. Everything is optional except a transport (`target` for the\n * direct-POST fallback, or a `sink`). A pre-auth open (no user yet) is a valid device-only event. */\nexport interface LifecycleEventInput {\n /** Where to POST if no `sink` is wired (the tenant transport, same as `WireOnboardingConfig`). */\n target?: ClientEventTarget;\n /** Preferred transport: route the built event HERE (the offline queue's `enqueue`). */\n sink?: (event: ClientEvent) => void;\n /** The per-open session id. Defaults to a fresh `makeSessionId()`. */\n sessionId?: string;\n /** The host's OPAQUE pseudonymous user id (NOT PII). Sanitized + capped; omitted pre-auth. */\n userId?: string;\n /** A stable, non-PII device id the host owns. Rides in `user_context.device_key`. */\n deviceKey?: string;\n /** The host's local open-counter value. Drives `returning` + \"Nth session\". */\n sessionCount?: number;\n /** Host app version (e.g. \"1.4.2\"), if cheaply available. */\n appVersion?: string;\n /** Platform string (e.g. \"ios\"), if cheaply available. */\n platform?: string;\n /** An optional richer device snapshot (from `collectDeviceContext()`); the hook fills this. */\n device?: DeviceContext;\n /** Small non-PII extras, stored as a JSON string in the event `meta`. */\n meta?: Record<string, unknown>;\n}\n\n/** Options for {@link reportFirstOpen}. Adds the once-ever persistence inputs on top of the shared\n * lifecycle inputs. Without `storage` it degrades to the in-memory latch (once per process). */\nexport interface ReportFirstOpenOptions extends LifecycleEventInput {\n /** Host persistence (AsyncStorage subset). The once-ever flag lives here — it is what survives an\n * app kill. Omit it for the documented degraded (in-memory, once-per-process) mode. */\n storage?: WireOnboardingStorage;\n /** Tenant/app id — namespaces the persisted flag (`wireai:first_open:<appId>`). */\n appId?: string;\n}\n\n/**\n * Build the `app_event` payload shared by `app.first_open` and `app.session_started`. This is a\n * BYTE-FOR-BYTE mirror of the field logic in {@link reportSessionStart} — same `event_type`, same\n * `question_key`-as-name contract, same `user_context` bucket, same optional fields — so the two\n * lifecycle events are one contract with two names. Do NOT let these diverge (see lifecycle.test).\n */\nconst buildLifecycleEvent = (questionKey: string, opts: LifecycleEventInput): Record<string, unknown> => {\n const userContext: Record<string, string | number | boolean> = {};\n if (opts.deviceKey) userContext.device_key = opts.deviceKey;\n if (typeof opts.sessionCount === \"number\" && Number.isFinite(opts.sessionCount)) {\n userContext.session_count = opts.sessionCount;\n userContext.returning = opts.sessionCount > 1;\n }\n if (opts.appVersion) userContext.app_version = opts.appVersion;\n if (opts.platform) userContext.platform = opts.platform;\n\n const event: Record<string, unknown> = {\n event_type: \"app_event\",\n question_key: questionKey,\n session_id: opts.sessionId ?? makeSessionId(),\n };\n const userId = sanitizeUserId(opts.userId);\n if (userId) event.user_id = userId;\n if (Object.keys(userContext).length > 0) event.user_context = userContext;\n if (opts.device) event.device = opts.device;\n if (opts.meta && Object.keys(opts.meta).length > 0) event.meta = JSON.stringify(opts.meta);\n return event;\n};\n\n/** Route a built event to the wired sink, else a direct fire-and-forget POST. Never throws. */\nconst routeLifecycleEvent = (event: Record<string, unknown>, opts: LifecycleEventInput): void => {\n try {\n if (opts.sink) {\n opts.sink(event as ClientEvent);\n return;\n }\n // Route the direct-POST fallback through the ONE canonical /v1/events builder (url + headers +\n // body) instead of re-describing the endpoint here; still fire-and-forget.\n const req = buildEventsRequest(opts.target, [event as unknown as ClientEvent]);\n if (!req) return;\n void fetch(req.url, req.init).catch(() => {\n // Network/transport error — analytics is best-effort, swallow.\n });\n } catch {\n // A throwing sink, URL/JSON error, or a missing fetch — swallow.\n }\n};\n\nconst emitFirstOpen = (opts: ReportFirstOpenOptions): void => {\n routeLifecycleEvent(buildLifecycleEvent(FIRST_OPEN_EVENT, opts), opts);\n};\n\n/**\n * Emit `app.first_open` EXACTLY ONCE EVER per install. Fire-and-forget; returns immediately.\n *\n * • With `storage`: reads the persisted flag (`wireai:first_open:<appId>`). Absent → emit, then\n * write the flag (survives app kills, so a second launch is a no-op). Present → no-op.\n * • Race guard: an in-memory latch is set SYNCHRONOUSLY before the async read, so two\n * near-simultaneous calls fire at most once.\n * • Without `storage`: degraded mode — fires once per PROCESS via the latch only (documented).\n */\nexport const reportFirstOpen = (opts: ReportFirstOpenOptions): void => {\n const appId = opts.appId ?? \"default\";\n\n // Synchronous latch FIRST: guarantees at-most-one before any await (same-process race guard) and\n // is the sole guard in the no-storage degraded mode.\n if (_firstOpenLatched.has(appId)) return;\n _firstOpenLatched.add(appId);\n\n const storage = opts.storage;\n if (!storage) {\n // Degraded: no persistence to survive a kill → the latch fires it once per process.\n emitFirstOpen(opts);\n return;\n }\n\n const key = firstOpenStorageKey(appId);\n void (async () => {\n try {\n const seen = await withTimeout(storage.getItem(key), READ_TIMEOUT_MS);\n // A prior launch already fired + wrote the flag → once-ever satisfied, no-op.\n if (seen) return;\n emitFirstOpen(opts);\n try {\n // Best-effort persist: a failed write just means the next launch may re-fire once.\n void storage.setItem(key, JSON.stringify({ ts: Date.now() })).catch(() => {});\n } catch {\n // Missing/broken storage write — swallow.\n }\n } catch {\n // Unreadable flag → the in-memory latch still caps us at one fire this process.\n emitFirstOpen(opts);\n }\n })();\n};\n\n/** Options for {@link wireLifecycleEvents}: the shared lifecycle inputs + first-open persistence. */\nexport interface WireLifecycleOptions extends ReportFirstOpenOptions {}\n\n/**\n * Wire BOTH lifecycle events in one call for a host that owns its own app-open path (the non-hook\n * counterpart to {@link useLifecycleEvents}). Fires `app.first_open` (once ever) and one\n * `app.session_started` for THIS open through the EXISTING {@link reportSessionStart} emitter (so\n * the once-per-open guard still applies — pass the same `sessionId` and it never double-fires).\n * Route both through the same `sink` (the offline queue) to buffer them. Fire-and-forget.\n */\nexport const wireLifecycleEvents = (opts: WireLifecycleOptions): void => {\n // ONE per-open id for BOTH events when the caller supplies none. Without this, `reportFirstOpen`\n // fell through to `buildLifecycleEvent`'s own `makeSessionId()` while `reportSessionStart` minted a\n // DIFFERENT one — so `app.first_open` carried a session id the server never saw a `session_started`\n // for and back-filled into a phantom session, inflating session counts. `useLifecycleEvents` already\n // pinned this (it mints `mountOpenSessionId`); the React-free entry point did not, so the identical\n // bug was still reachable from the documented non-hook path.\n const sessionId = opts.sessionId ?? makeSessionId();\n reportFirstOpen({ ...opts, sessionId });\n reportSessionStart({\n target: opts.target,\n sink: opts.sink,\n sessionId,\n userId: opts.userId,\n deviceKey: opts.deviceKey,\n sessionCount: opts.sessionCount,\n appVersion: opts.appVersion,\n platform: opts.platform,\n device: opts.device,\n meta: opts.meta,\n });\n};\n\n// Re-exported so callers wiring lifecycle events have the session name alongside the first-open one.\nexport { SESSION_STARTED_EVENT };\n","/**\n * eventQueue — the OFFLINE-FIRST, persistent transport buffer for client analytics events.\n *\n * The existing `reportClientEvents` is a blind fire-and-forget POST: it returns `void`, has no\n * success signal, and drops events when the network is down. The analytics data story depends on\n * NEVER losing an event offline, so this queue adds the missing durability layer on top of the\n * same `POST {serverUrl}/v1/events` contract:\n *\n * • Persists pending events to the host-injected `WireOnboardingStorage` (survives app kills).\n * • Batches them into one request body `{ events: [...] }`.\n * • Owns its OWN awaited `fetch` that reads `res.ok` — the only way to drive retry + dequeue,\n * since `reportClientEvents` cannot ack. A 2xx dequeues the batch; a non-ok / rejected / thrown\n * response keeps it and schedules an exponential backoff retry.\n * • Flushes on `enqueue`, on an explicit `flush()`, and on `notifyOnline()` (host reconnect).\n * • Caps the buffer (drop-OLDEST under pressure) and de-dups identical pending events.\n * • Stamps the current context envelope (device + host scalars) onto every event before send.\n *\n * FIRE-AND-FORGET (load-bearing): `enqueue` returns immediately and NEVER throws into the UI. A\n * missing `fetch`, a hung/broken storage, a rejecting network, or a JSON error is swallowed and\n * degrades gracefully — analytics must never be able to break the app. In-memory fallback covers\n * the no-storage case (survives re-renders, not app kills).\n *\n * DEPENDENCY-FREE: no network-detection or persistence library. Connectivity is host-driven via\n * `notifyOnline()`; persistence is the host-injected AsyncStorage-compatible subset.\n */\nimport type { ContextEnvelope } from \"./contextEnvelope\";\nimport {\n buildEventsRequest,\n warnOnSkippedEvents,\n type ClientEvent,\n type ClientEventTarget,\n} from \"./reportClientEvent\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\nimport { warnInDev } from \"../utils/warnInDev\";\n\n/** Envelope source: a fixed envelope or a provider evaluated at enqueue time (fresh network type). */\nexport type EnvelopeSource = ContextEnvelope | (() => ContextEnvelope | undefined);\n\n/** Options for {@link createEventQueue}. Only `target` is conceptually required to actually send. */\nexport type EventQueueOptions = {\n /** Where to POST — the tenant transport (`serverUrl` + `apiKey`), same as `WireOnboardingConfig`. */\n target: ClientEventTarget | undefined;\n /**\n * Host persistence (AsyncStorage-compatible subset). When omitted, the queue runs in the\n * documented DEGRADED in-memory mode — it survives re-renders but not an app kill.\n */\n storage?: WireOnboardingStorage;\n /** Tenant/app id used to namespace the default storage key (`wireai:evtq:<appId>`). */\n appId?: string;\n /** Explicit storage key override (wins over the `appId`-derived default). */\n storageKey?: string;\n /** The context envelope stamped onto every event before send (device + host scalars). */\n envelope?: EnvelopeSource;\n /** Max pending events; enqueuing past this DROPS THE OLDEST first (default 200). */\n maxSize?: number;\n /** Events per POST batch (default 20). */\n batchSize?: number;\n /** First retry delay in ms; doubles each failed attempt (default 1000). */\n baseBackoffMs?: number;\n /** Backoff ceiling in ms (default 30000). */\n maxBackoffMs?: number;\n /** Max AUTOMATIC backoff retries before pausing (default 6); `notifyOnline()`/`flush()` re-arm it. */\n maxRetries?: number;\n};\n\n/** The queue's public surface. `enqueue` is fire-and-forget (returns immediately, never throws). */\nexport type EventQueue = {\n /** Buffer one event (envelope-stamped), persist, and schedule a flush. Never throws. */\n enqueue(event: ClientEvent): void;\n /** Attempt an immediate drain of the pending buffer. Fire-and-forget. */\n flush(): void;\n /** Host reconnect signal: reset backoff and drain immediately. Fire-and-forget. */\n notifyOnline(): void;\n /** Current pending (in-memory) count. */\n size(): number;\n};\n\nconst DEFAULTS = {\n maxSize: 200,\n batchSize: 20,\n baseBackoffMs: 1000,\n maxBackoffMs: 30000,\n maxRetries: 6,\n} as const;\n\n/** Ceiling on the persisted-backlog read — a hung adapter degrades to an empty start, never a stall. */\nconst READ_TIMEOUT_MS = 1500;\n\n// ── One storage slot per QUEUE, not per appId ────────────────────────────────────────────────────\n//\n// The default key was derived from `appId` alone, so two `createAnalytics` instances for one tenant —\n// the documented double-wiring, a façade for `track`/`screen` plus an activation instance — shared ONE\n// persisted backlog while keeping SEPARATE in-memory buffers. Every symptom of that is silent:\n// each `persist()` overwrites the other's blob with its own view of \"pending\"; a queue that drains to\n// empty calls `removeItem` and DELETES a sibling's still-pending events; and on relaunch whatever\n// survived is loaded by both instances and sent twice. `useLifecycleEvents` already avoided all of it\n// by handing its queue a dedicated explicit key — this generalizes that.\n//\n// A `Symbol.for` slot for the same reason as every other registry here: tsup inlines a copy of this\n// module into each bundle, and a plain module `let` would let the `.` and `./analytics` copies each\n// think they were the first claimant of the same key.\nconst QUEUE_KEY_SLOT: unique symbol = Symbol.for(\"@wireai/activation:eventQueueKeys\");\n\ntype GlobalWithQueueKeys = typeof globalThis & { [QUEUE_KEY_SLOT]?: Set<string> };\n\nconst queueKeyGlobal = globalThis as GlobalWithQueueKeys;\n\nconst claimedQueueKeys = (): Set<string> => {\n const existing = queueKeyGlobal[QUEUE_KEY_SLOT];\n if (existing) return existing;\n const created = new Set<string>();\n queueKeyGlobal[QUEUE_KEY_SLOT] = created;\n return created;\n};\n\n/**\n * Claim `preferred` for this queue, or the next free `preferred#N` when a live queue already holds it.\n *\n * ONLY the appId-derived DEFAULT is ever rotated. An EXPLICIT `storageKey` is the host (or\n * `useLifecycleEvents`) declaring which slot a queue owns, and that hook re-creates its queue on every\n * remount — rotating there would silently walk it off its own backlog once per remount, which is a\n * worse bug than the one being fixed.\n */\nconst claimQueueKey = (preferred: string, explicit: boolean): string => {\n const claimed = claimedQueueKeys();\n if (explicit || !claimed.has(preferred)) {\n claimed.add(preferred);\n return preferred;\n }\n let ordinal = 2;\n while (claimed.has(`${preferred}#${ordinal}`)) ordinal++;\n const key = `${preferred}#${ordinal}`;\n claimed.add(key);\n warnInDev(\n `[wireai] a second event queue was created for the same appId, and \"${preferred}\" is already ` +\n \"claimed by a live one. Two queues sharing one storage slot overwrite each other's backlog, \" +\n \"delete each other's pending events when one drains to empty, and double-send on relaunch, so \" +\n `this queue was given \"${key}\" instead. Prefer ONE analytics instance per app; if you really ` +\n \"need two, pass an explicit `storageKey` to each so the slots are yours to reason about.\",\n );\n return key;\n};\n\n/** Test-only: forget every claimed queue key. A real RELAUNCH is a new process, so a test that\n * simulates one in-process must call this or its second queue reads as a concurrent sibling.\n * Exported from `@wireai/activation/analytics`, matching `resetAutoDeviceKeys` / `resetCurrentSessionId`. */\nexport const resetEventQueueKeys = (): void => claimedQueueKeys().clear();\n\n/** Internal buffered item. `id` is a local monotonic handle for deterministic dequeue-after-ack;\n * it is NEVER sent to the server. `sig` is the de-dup signature (serialized stamped event). */\ntype QueuedItem = { id: number; event: ClientEvent; sig: string };\n\n/** Persisted shape — the local id + the (already envelope-stamped) event. `sig` is recomputed on load. */\ntype PersistedItem = { id: number; event: ClientEvent };\n\n/**\n * The verdict of a read that ran out of time. A DISTINCT value, and never `undefined` — an\n * `undefined` here is byte-identical to \"the adapter answered, there is no backlog\", and that\n * conflation destroys data silently: `parsePersisted(undefined)` gives `[]`, hydration takes its\n * `length === 0` early return without throwing, and the next `persist()` writes the in-memory\n * pending list over a blob nobody has read — or, with nothing pending, `removeItem`s it outright.\n */\nconst READ_TIMED_OUT: unique symbol = Symbol(\"wireai:storage-read-timeout\");\n\nconst withTimeout = <T>(p: Promise<T>, ms: number): Promise<T | typeof READ_TIMED_OUT> => {\n let timer: ReturnType<typeof setTimeout>;\n const timeout = new Promise<typeof READ_TIMED_OUT>((resolve) => {\n timer = setTimeout(() => resolve(READ_TIMED_OUT), ms);\n });\n return Promise.race([p, timeout]).finally(() => clearTimeout(timer));\n};\n\n/** Detach a timer from the event loop where the runtime supports it (Node test process / some RNs). */\nconst unrefTimer = (timer: ReturnType<typeof setTimeout>): void => {\n const t = timer as unknown as { unref?: () => void };\n if (typeof t.unref === \"function\") t.unref();\n};\n\nconst parsePersisted = (raw: string | null | undefined): PersistedItem[] => {\n if (!raw) return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const items: PersistedItem[] = [];\n for (const entry of parsed) {\n if (\n entry &&\n typeof entry === \"object\" &&\n typeof (entry as PersistedItem).id === \"number\" &&\n (entry as PersistedItem).event &&\n typeof (entry as PersistedItem).event === \"object\"\n ) {\n items.push(entry as PersistedItem);\n }\n }\n return items;\n } catch {\n // Corrupt backlog → start empty; the next persist overwrites it.\n return [];\n }\n};\n\n/**\n * Create an offline-first event queue. Loads any persisted backlog on creation so a\n * killed-and-relaunched app resumes where it left off. Returns the {@link EventQueue} surface.\n */\nexport const createEventQueue = (options: EventQueueOptions): EventQueue => {\n const target = options.target;\n const storage = options.storage;\n // One slot per QUEUE: an explicit key is taken verbatim; the appId-derived default is rotated\n // to `…#2` when a live queue already holds it, so two instances can never share one backlog.\n //\n // Only claimed when there IS storage. The defect is entirely about the persisted slot, and a\n // storage-less queue (the documented degraded in-memory mode) never reads or writes the key — so\n // claiming there would warn about a collision that cannot happen.\n const defaultKey = options.storageKey ?? `wireai:evtq:${options.appId ?? \"default\"}`;\n const key = storage ? claimQueueKey(defaultKey, options.storageKey !== undefined) : defaultKey;\n const maxSize = options.maxSize ?? DEFAULTS.maxSize;\n const batchSize = options.batchSize ?? DEFAULTS.batchSize;\n const baseBackoffMs = options.baseBackoffMs ?? DEFAULTS.baseBackoffMs;\n const maxBackoffMs = options.maxBackoffMs ?? DEFAULTS.maxBackoffMs;\n const maxRetries = options.maxRetries ?? DEFAULTS.maxRetries;\n\n let pending: QueuedItem[] = [];\n let nextId = 0;\n let flushing = false;\n let attempt = 0;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n // The persisted blob exists but has NOT been read yet (the cold-start read blew its deadline and\n // is still in flight). While this is true every write is suppressed: the only thing the queue\n // could write is a view of `pending` that does not include the backlog it has not seen, and\n // `setItem`/`removeItem` would destroy it. Cleared as soon as the slow read settles, whichever\n // way it settles, so a read that ultimately fails resumes normal persistence rather than\n // suppressing it for the life of the process.\n let backlogUnread = false;\n\n const resolveEnvelope = (): ContextEnvelope | undefined => {\n try {\n return typeof options.envelope === \"function\" ? options.envelope() : options.envelope;\n } catch {\n return undefined;\n }\n };\n\n // Stamp the current envelope onto a COPY of the event (never mutate the caller's object):\n // device → event.device (when the event has none)\n // sessionId → event.session_id (when the event has none)\n // appVersion / appBuild / networkType → event.user_context (the non-PII bucket the server\n // sanitizes), never overwriting a key the caller already set.\n const stamp = (event: ClientEvent): ClientEvent => {\n const env = resolveEnvelope();\n const stamped: ClientEvent = { ...event };\n // Client enqueue timestamp: distinguishes a GENUINE repeat (same event fired seconds apart)\n // from a REDUNDANT re-enqueue of the same instant. The de-dup signature below includes it, so\n // two identical events enqueued in the same millisecond still collapse (a re-render), while the\n // same action repeated later carries a fresh `ts` and survives. A caller-set `ts` is preserved.\n // This stays a NUMBER in the queue (the de-dup signature depends on it); `buildEventsRequest`\n // serializes it to the ISO8601 string the server requires at send time.\n if (stamped.ts === undefined) stamped.ts = Date.now();\n if (!env) return stamped;\n if (!stamped.device && env.device) stamped.device = env.device;\n if (!stamped.session_id && env.sessionId) stamped.session_id = env.sessionId;\n const uc: Record<string, string | number | boolean> = { ...(stamped.user_context ?? {}) };\n if (env.appVersion && uc.app_version === undefined) uc.app_version = env.appVersion;\n if (env.appBuild && uc.app_build === undefined) uc.app_build = env.appBuild;\n if (env.networkType && uc.network_type === undefined) uc.network_type = env.networkType;\n if (Object.keys(uc).length > 0) stamped.user_context = uc;\n return stamped;\n };\n\n const persist = (): void => {\n if (!storage) return;\n // NEVER write over a blob that has not been read yet. See `backlogUnread`.\n if (backlogUnread) return;\n try {\n if (pending.length === 0) {\n void storage.removeItem(key).catch(() => {});\n return;\n }\n const payload: PersistedItem[] = pending.map((item) => ({ id: item.id, event: item.event }));\n void storage.setItem(key, JSON.stringify(payload)).catch(() => {});\n } catch {\n // Best-effort: a failed write just means the backlog is not durable this launch.\n }\n };\n\n const enforceSizeCap = (): void => {\n // Drop the OLDEST first so the newest events are never the ones lost under pressure.\n if (pending.length > maxSize) pending.splice(0, pending.length - maxSize);\n };\n\n const safeSig = (event: ClientEvent): string => {\n try {\n return JSON.stringify(event);\n } catch {\n // Non-serializable event → give it a unique signature so it is never wrongly de-duped.\n return `__nosig_${nextId}_${Math.random()}`;\n }\n };\n\n /**\n * Merge a loaded backlog into the in-memory buffer: persisted (older) events go AHEAD of\n * whatever was enqueued while the read was in flight, duplicates collapse, and the size cap\n * applies as usual.\n *\n * Ids are minted FRESH from the running `nextId` rather than reset to 0. A drain may already be\n * in flight holding a batch of ids it will filter out on ack, and re-numbering from 0 would make\n * those ids point at different events — the ack would then dequeue (silently drop) whichever\n * events happened to inherit them. Monotonic ids are never reused, so an in-flight ack stays\n * correct whatever lands in between.\n */\n const mergePersisted = (persistedItems: PersistedItem[]): void => {\n if (persistedItems.length === 0) return;\n const seen = new Set(pending.map((item) => item.sig));\n const restored: QueuedItem[] = [];\n for (const persisted of persistedItems) {\n const sig = safeSig(persisted.event);\n if (seen.has(sig)) continue; // already in memory — collapse the duplicate\n seen.add(sig);\n restored.push({ id: nextId++, event: persisted.event, sig });\n }\n if (restored.length === 0) return;\n pending = [...restored, ...pending];\n enforceSizeCap();\n persist();\n };\n\n // Load any persisted backlog. Anything enqueued before this settles stays in memory; the merge\n // above puts persisted (older) events ahead of it.\n //\n // A read that blows READ_TIMEOUT_MS is NOT treated as \"no backlog\". The race only unblocks the\n // DRAIN — the original read is kept and merged whenever it lands, and until then every write is\n // suppressed so the unread blob survives intact.\n const loadPromise: Promise<void> = (async () => {\n if (!storage) return;\n try {\n const read = Promise.resolve(storage.getItem(key));\n // A rejecting read must not surface as an unhandled rejection when the race is won by the\n // timeout; the recovery path below re-attaches its own handlers.\n read.catch(() => {});\n const raced = await withTimeout(read, READ_TIMEOUT_MS);\n if (raced === READ_TIMED_OUT) {\n backlogUnread = true;\n warnInDev(\n `[wireai] the persisted analytics backlog at \"${key}\" took longer than ${READ_TIMEOUT_MS}ms ` +\n \"to read, so the queue started without it. The stored events are NOT discarded: writes \" +\n \"are held back until the read lands, and the backlog is merged in then. If you see this \" +\n \"on every cold start, your storage adapter is too slow to be on the launch path.\",\n );\n void read\n .then((late) => {\n backlogUnread = false;\n mergePersisted(parsePersisted(late));\n // Send whatever was just recovered; without this it would wait for the next enqueue.\n flush();\n })\n .catch(() => {\n // The slow read ultimately failed → nothing to preserve, resume normal persistence.\n backlogUnread = false;\n persist();\n });\n return;\n }\n mergePersisted(parsePersisted(raced));\n } catch {\n // Unreadable backlog → start empty; nothing enqueued in-memory is lost.\n }\n })();\n\n // The queue's OWN awaited POST. Reads `res.ok` to drive retry/dequeue. NEVER throws — a missing\n // fetch, a rejecting network, or a JSON error resolves to `false` (batch stays, retry schedules).\n const postBatch = async (events: ClientEvent[]): Promise<boolean> => {\n // Build the /v1/events request through the ONE canonical builder (url + headers + body) so this\n // queue never re-describes the endpoint. The abort-timeout stays: the queue owns retry/dequeue,\n // so a hung request must be cut loose to schedule a backoff rather than block the drain forever.\n const req = buildEventsRequest(target, events);\n if (!req) return false;\n const controller = typeof AbortController !== \"undefined\" ? new AbortController() : undefined;\n const timer = setTimeout(() => controller?.abort(), 15_000);\n try {\n const res = await fetch(req.url, { ...req.init, signal: controller?.signal });\n // A 200 can still carry `skipped:N` — events the server threw away. Log-only: the ack below\n // stays `res.ok`, so retry/dequeue behaviour is unchanged.\n warnOnSkippedEvents(res);\n return !!(res && (res as { ok?: boolean }).ok);\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n }\n };\n\n const clearRetry = (): void => {\n if (retryTimer !== undefined) {\n clearTimeout(retryTimer);\n retryTimer = undefined;\n }\n };\n\n const scheduleRetry = (): void => {\n // Bounded automatic retry. Past the cap the backlog simply waits for the next\n // `notifyOnline()` / `flush()` (both re-arm attempt), so events are paused, never dropped.\n if (attempt >= maxRetries) return;\n const delay = Math.min(baseBackoffMs * 2 ** attempt, maxBackoffMs);\n attempt++;\n clearRetry();\n retryTimer = setTimeout(() => {\n retryTimer = undefined;\n void drain();\n }, delay);\n unrefTimer(retryTimer);\n };\n\n const drain = async (): Promise<void> => {\n try {\n await loadPromise;\n } catch {\n // load already swallows; guard the await defensively.\n }\n if (flushing) return;\n flushing = true;\n try {\n while (pending.length > 0) {\n const batch = pending.slice(0, batchSize);\n const ok = await postBatch(batch.map((item) => item.event));\n if (!ok) {\n scheduleRetry();\n return;\n }\n // Dequeue exactly the acked batch by id (pending may have grown while in flight).\n const acked = new Set(batch.map((item) => item.id));\n pending = pending.filter((item) => !acked.has(item.id));\n persist();\n attempt = 0;\n clearRetry();\n }\n } finally {\n flushing = false;\n }\n };\n\n const flush = (): void => {\n try {\n void drain();\n } catch {\n // drain never throws synchronously, but guard the kick anyway.\n }\n };\n\n const enqueue = (event: ClientEvent): void => {\n try {\n const stamped = stamp(event);\n const sig = safeSig(stamped);\n // Collapse a redundant re-enqueue of an identical pending event.\n for (const item of pending) {\n if (item.sig === sig) return;\n }\n pending.push({ id: nextId++, event: stamped, sig });\n enforceSizeCap();\n persist();\n // Only kick a drain when no retry is already pending — avoids hammering fetch while offline.\n if (retryTimer === undefined) flush();\n } catch {\n // Fire-and-forget: nothing in enqueue may surface to the UI.\n }\n };\n\n const notifyOnline = (): void => {\n // Host reconnected: reset the backoff and drain now.\n attempt = 0;\n clearRetry();\n flush();\n };\n\n const size = (): number => pending.length;\n\n return { enqueue, flush, notifyOnline, size };\n};\n","/**\n * useLifecycleEvents — the batteries-included React hook that wires the TOP-OF-FUNNEL lifecycle\n * events in ONE place: `app.first_open` (once ever) on mount, and `app.session_started` on every\n * real app-open, both offline-buffered through the Brief-01 event queue.\n *\n * ONE emitter, one guard, no double-emit: session-start goes through the EXISTING\n * {@link reportSessionStart} emitter (routed via a `sink`), NOT a second session emitter — so a\n * host must use EITHER this hook OR `useSessionStart`, never both (both would fire an app-open).\n * The once-per-open guard dedupes re-renders within this hook.\n *\n * Firing moments mirror {@link useSessionStart} exactly:\n * • ON MOUNT — the app opened (cold start / provider first render). `app.first_open` fires here\n * too (once ever, gated by the persisted flag in `reportFirstOpen`). When the kit's AUTO device\n * key is the one in play (no host `deviceKey`, `config.storage` present) the mount fire waits on\n * one storage read so both events carry the PERSISTED key, not a freshly minted one — see the\n * `hydrateAutoDeviceKey` note below.\n * • ON FOREGROUND after a real background of at least {@link BACKGROUND_SESSION_MS} (30 min) — a\n * new app-open, so a fresh `app.session_started` fires. A quick app-switch does NOT count.\n *\n * OFFLINE-FIRST by default: pass your shared {@link EventQueue}'s `enqueue` as `options.sink` to\n * route both events through your one queue. If you pass no sink, the hook lazily creates its OWN\n * offline queue (dedicated storage key, so it never collides with your main queue) from the config\n * + storage. Either way lifecycle events are buffered + persisted + retried, never lost offline.\n *\n * Dependency policy: `AppState` + `Platform` are RN built-ins (no new dep); the device snapshot is\n * the kit's own dependency-free `collectDeviceContext()`; the queue is the dependency-free Brief-01\n * `createEventQueue`. The pure `reportFirstOpen` / `wireLifecycleEvents` (in lifecycle.ts) import no\n * React — this hook is the only React surface.\n */\nimport { useEffect, useRef } from \"react\";\nimport { AppState, Platform, type AppStateStatus } from \"react-native\";\n\nimport { createEventQueue, type EnvelopeSource, type EventQueue } from \"../analytics/eventQueue\";\nimport { makeSessionId, type ClientEvent, type ClientEventTarget } from \"../analytics/reportClientEvent\";\nimport { hydrateAutoDeviceKey, resolveAutoDeviceKey } from \"../context/deviceId\";\nimport { resolveIdentity } from \"../identity/identityRecord\";\nimport { collectDeviceContext } from \"../device/deviceContext\";\nimport type { WireOnboardingStorage } from \"../session/persistedSession\";\nimport { reportFirstOpen } from \"./lifecycle\";\nimport { reportSessionStart } from \"./reportSessionStart\";\nimport { BACKGROUND_SESSION_MS } from \"./useSessionStart\";\n\n/** Tenant transport + host persistence for the lifecycle wiring. Same creds as `WireOnboardingConfig`. */\nexport interface LifecycleConfig {\n /** Base server URL (same as `WireOnboardingConfig.serverUrl`); `/v1/events` is appended. */\n serverUrl?: string;\n /** Tenant API key; sent as `Authorization: Bearer`. */\n apiKey?: string;\n /** Host app version (e.g. \"1.4.2\"), forwarded for release segmentation. Optional. */\n appVersion?: string;\n /** Tenant/app id — namespaces the first-open flag AND the hook's internal queue storage key. */\n appId?: string;\n /** Host storage (AsyncStorage subset). Enables the persisted once-ever first-open flag AND the\n * offline durability of the hook's internal queue. Omit it and both degrade to in-memory. */\n storage?: WireOnboardingStorage;\n}\n\n/** Per-open identity + wiring the host supplies. All optional: a pre-auth open is device-only. */\nexport interface UseLifecycleEventsOptions {\n /** The host's opaque pseudonymous user id (NOT PII). Omitted before the user authenticates. */\n userId?: string;\n /** The host's local open-counter value for this open. Drives `returning` + \"Nth session\". */\n sessionCount?: number;\n /** A stable, non-PII device id the host owns. Groups this device's sessions server-side. */\n deviceKey?: string;\n /** Small non-PII extras forwarded on the event `meta`. */\n meta?: Record<string, unknown>;\n /** Set `false` to disable firing (e.g. behind a consent gate). Default enabled. */\n enabled?: boolean;\n /**\n * Explicit transport sink (e.g. an existing shared `EventQueue.enqueue`). When provided, BOTH\n * lifecycle events route here and the hook does NOT create its own queue — pass this to share ONE\n * offline queue across the kit's analytics (screen tracking + lifecycle).\n */\n sink?: (event: ClientEvent) => void;\n /**\n * Context envelope (or provider) for the hook's internally-created queue. Ignored when `sink` is\n * supplied (the host's queue owns envelope stamping).\n */\n envelope?: EnvelopeSource;\n}\n\n/**\n * Fire `app.first_open` (once ever) + `app.session_started` (per open), offline-buffered. Returns\n * nothing — a side-effecting hook. Safe to call with inline options (read through a ref, so\n * changing `userId`/`sessionCount` never re-fires a session).\n */\nexport const useLifecycleEvents = (\n config: LifecycleConfig | undefined,\n options: UseLifecycleEventsOptions = {},\n): void => {\n // Latest options/config through a ref so the mount/resume fires read fresh values without listing\n // them as effect deps (which would re-fire a session on every prop change).\n const latest = useRef({ config, options });\n latest.current = { config, options };\n\n // The resolved sink is created at most once and reused for every fire this mount.\n const queueRef = useRef<EventQueue | undefined>(undefined);\n\n useEffect(() => {\n const resolveSink = (): ((event: ClientEvent) => void) | undefined => {\n const { config: cfg, options: opts } = latest.current;\n // Host-owned shared queue wins — one queue across the whole kit.\n if (opts.sink) return opts.sink;\n // No transport → no sink (events no-op rather than buffer forever against a dead target).\n if (!cfg?.serverUrl) return undefined;\n if (!queueRef.current) {\n queueRef.current = createEventQueue({\n target: { serverUrl: cfg.serverUrl, apiKey: cfg.apiKey ?? \"\" },\n storage: cfg.storage,\n // Dedicated key so the hook's internal queue never collides with a host's main queue.\n storageKey: `wireai:evtq:lifecycle:${cfg.appId ?? \"default\"}`,\n envelope: opts.envelope,\n });\n }\n return queueRef.current.enqueue;\n };\n\n const targetOf = (cfg: LifecycleConfig | undefined): ClientEventTarget | undefined =>\n cfg?.serverUrl ? { serverUrl: cfg.serverUrl, apiKey: cfg.apiKey ?? \"\" } : undefined;\n\n /**\n * The `device_key` these lifecycle events ride under. A host-supplied id always wins.\n *\n * WHY THE FALLBACK EXISTS: `min_sessions` (the review / questionnaire firing rule, and the\n * \"fire on the user's Nth session\" recipe in the README) is computed SERVER-SIDE by counting\n * distinct `app.session_started` events grouped by `user_context.device_key`. A host that took\n * the batteries-included path and passed no `deviceKey` emitted those events with NO device key\n * at all — while its `createAnalytics` / `createWireActivation` events carried an auto-minted\n * one. Two disjoint identity spaces again: the counter the rule reads could never increase, so\n * `min_sessions` was structurally unsatisfiable and the gate never fired from the server side.\n *\n * ONLY WITH `storage`: the auto id is per-INSTALL only when it can be persisted. With no\n * storage it would be per-LAUNCH, which would make every open look like a brand-new device and\n * corrupt `min_sessions` in the other direction. So no storage → no fallback, same as before.\n */\n const resolveDeviceKey = (\n cfg: LifecycleConfig | undefined,\n opts: UseLifecycleEventsOptions,\n ): string | undefined => {\n // A HOST-supplied key is recorded on the process provenance registry, so a `<WireOnboarding>`\n // mount that was not given one can tell \"this app owns no device id\" from \"this app owns one\n // and forgot it there\" — the silent third id space. Recording only; nothing reads it here.\n const host = resolveIdentity({\n value: opts.deviceKey,\n space: \"device\",\n source: \"host\",\n scope: cfg?.appId,\n })?.value;\n if (host) return host;\n if (!cfg?.storage) return undefined;\n return resolveAutoDeviceKey({ appId: cfg.appId, storage: cfg.storage });\n };\n\n // ONE per-open session id for the MOUNT open, shared by first_open AND session_started below.\n // WHY: `first_open` used to default to its OWN fresh `makeSessionId()` (via `buildLifecycleEvent`)\n // while `session_started` minted a different one — so every install's `first_open` carried a\n // session id the server never got a `session_started` for (a PHANTOM session the server\n // back-filled). Minting one id here and handing it to both makes them agree, so the server sees\n // `first_open` under the same session it saw `session_started` for. A later foreground open\n // (below) mints its OWN fresh id — a new open is a new session.\n const mountOpenSessionId = makeSessionId();\n\n // session_start — the EXISTING emitter routed through the sink (offline-buffered, one guard).\n // Accepts the per-open id so the mount open reuses `mountOpenSessionId`; omit it and the emitter\n // mints a fresh id (a genuinely new open). Either way the once-guard dedupes within the open.\n const fireSession = (sessionId?: string) => {\n const { config: cfg, options: opts } = latest.current;\n if (opts.enabled === false) return;\n if (!cfg?.serverUrl && !opts.sink) return;\n const device = collectDeviceContext();\n // `device.appVersion` is auto-detected best-effort; an explicit host version always wins.\n if (cfg?.appVersion) device.appVersion = cfg.appVersion;\n reportSessionStart({\n target: targetOf(cfg),\n sink: resolveSink(),\n sessionId,\n userId: opts.userId,\n deviceKey: resolveDeviceKey(cfg, opts),\n sessionCount: opts.sessionCount,\n appVersion: cfg?.appVersion ?? device.appVersion,\n platform: Platform.OS,\n device,\n meta: opts.meta,\n });\n };\n\n // The mount open: session_start FIRST (mount = an app-open), so the server has ingested\n // `session_started` for `mountOpenSessionId` before first_open references the same id; then\n // first_open — once ever (persisted flag + in-memory latch inside reportFirstOpen), pinned to the\n // SAME per-open id so it is never a phantom session.\n const fireMountOpen = () => {\n fireSession(mountOpenSessionId);\n\n const { config: cfg, options: opts } = latest.current;\n if (opts.enabled === false) return;\n const device = collectDeviceContext();\n // `device.appVersion` is auto-detected best-effort; an explicit host version always wins.\n if (cfg?.appVersion) device.appVersion = cfg.appVersion;\n reportFirstOpen({\n target: targetOf(cfg),\n sink: resolveSink(),\n sessionId: mountOpenSessionId,\n storage: cfg?.storage,\n appId: cfg?.appId,\n userId: opts.userId,\n deviceKey: resolveDeviceKey(cfg, opts),\n sessionCount: opts.sessionCount,\n appVersion: cfg?.appVersion ?? device.appVersion,\n platform: Platform.OS,\n device,\n meta: opts.meta,\n });\n };\n\n // WAIT FOR THE PERSISTED DEVICE KEY, but ONLY when the auto fallback is the one in play.\n //\n // `resolveAutoDeviceKey` is synchronous by contract: it returns a freshly minted id and adopts the\n // PERSISTED one a storage read later. Firing at mount therefore stamped a brand-new `wdev_*` on\n // BOTH lifecycle events on every launch, while every other surface adopted the persisted id\n // milliseconds afterwards. Those two events are exactly the ones the server counts `min_sessions`\n // from (distinct `app.session_started` grouped by `device_key`), so the counter could never exceed\n // 1 — and `first_open`, fired once ever, ended up under a key no later event shares, which breaks\n // `first_open` → `activated` cohorting too. One storage read at mount buys both back.\n //\n // A host-supplied `deviceKey` needs no read, and with no `storage` there is nothing to read (and\n // `resolveDeviceKey` deliberately does not fall back), so both keep firing synchronously at mount.\n let cancelled = false;\n const { config: mountCfg, options: mountOpts } = latest.current;\n const hostKey =\n typeof mountOpts.deviceKey === \"string\" && mountOpts.deviceKey.trim()\n ? mountOpts.deviceKey\n : undefined;\n if (!hostKey && mountCfg?.storage) {\n void hydrateAutoDeviceKey({ appId: mountCfg.appId, storage: mountCfg.storage }).then(() => {\n if (!cancelled) fireMountOpen();\n });\n } else {\n fireMountOpen();\n }\n\n // Foreground after a real background = a new app-open.\n let backgroundedAt: number | null = null;\n const onChange = (state: AppStateStatus) => {\n if (state === \"background\" || state === \"inactive\") {\n if (backgroundedAt == null) backgroundedAt = Date.now();\n return;\n }\n if (state === \"active\") {\n const since = backgroundedAt;\n backgroundedAt = null;\n if (since != null && Date.now() - since >= BACKGROUND_SESSION_MS) fireSession();\n }\n };\n const sub = AppState.addEventListener(\"change\", onChange);\n return () => {\n // A pending hydration must not fire an app-open for a mount that is already gone.\n cancelled = true;\n // RN >= 0.65 returns a subscription with remove(); guard for older shims.\n if (sub && typeof (sub as { remove?: () => void }).remove === \"function\") sub.remove();\n };\n // Mount-only effect: firing reads fresh values via `latest`, so no reactive deps.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n};\n"]}
|